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.
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : H. Schulzrinne (Columbia University), A. Rao (Cisco), R. Lanphier, M. Westerlund (Ericsson AB), M. Stiemerling (NEC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF mmusic
Première rédaction de cet article le 28 décembre 2016
Voici la version 2 du protocole bien connu RTSP, protocole servant à accéder à des flux vidéo. Comme c'est ce que j'utilise pour regarder la télévision sur l'écran de mon PC, je suis ravi que l'IETF se préoccupe de l'améliorer.
Comme beaucoup de protocoles dans le monde du multimédia (SIP, par exemple), RTSP est en fait uniquement un protocole de contrôle, permettant de déclencher ou d'arrêter des flux audio ou vidéo. Ces flux peuvent être temps-réel ou bien avoir simplement été stockés sur le disque d'un serveur. Donc, RTSP est une zapette logicielle. RTSP fait le contrôle et plusieurs protocoles peuvent être utilisés pour le transport des données, UDP, TCP, RTP, etc. À noter la taille impressionnante de ce RFC, avec plus de 300 pages. Ce n'est pas que le protocole soit si compliqué que cela, mais il y a beaucoup d'options et de choix.
La section 2 du RFC résume le protocole : RTSP est client/serveur,
le client RTSP se connecte au serveur, un certain nombre de choix
techniques sont faits et ensuite l'envoi des données
commence. Physiquement, les messages sont du texte (la syntaxe de RTSP
ressemble beaucoup à celle d'HTTP) bien que du
binaire soit parfois possible. La ressource convoitée est identifiée
par un URI de plan rtsp
(ou rtsps
pour TLS) et cet URI contient le nom de la
machine qui sera utilisée comme serveur. Par exemple, si je dis à mon logiciel
RTSP d'utiliser
rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=658&flavour=ld
,
la connexion RTSP sur TCP (ou TCP avec TLS) se fera avec
mafreebox.freebox.fr
. La requête RTSP inclus un
certain nombre d'en-têtes comme dans HTTP, et parfois un corps
(toujours comme en HTTP). Voici un exemple avec le client
VLC. Je le lance avec vlc
'rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=897'
et on voit (tcpdump ne sait pas
apparemment décoder le RTSP mais Wireshark y
arrive très bien) :
Internet Protocol Version 4, Src: 192.168.2.1 (192.168.2.1), Dst: 212.27.38.253 (212.27.38.253) Transmission Control Protocol, Src Port: 45854 (45854), Dst Port: rtsp (554), Seq: 563, Ack: 873, Len: 204 Real Time Streaming Protocol Request: PLAY rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=897 RTSP/1.0\r\n CSeq: 5\r\n User-Agent: LibVLC/2.0.3 (LIVE555 Streaming Media v2012.05.17)\r\n Session: pokf6CQWbA8CUyC Range: npt=0.000-\r\n \r\n
Dans l'exemple ci-dessus, le protocole était RTSP version 1.0
(rappelez-vous que ce RFC décrit la version 2), la requête était
PLAY
(dont le nom dit bien ce qu'elle fait et
vous ne serez pas surpris d'apprendre qu'il existe une commande PAUSE
) et
l'un des en-têtes, User-Agent:
montre que
j'utilise bien vlc.
Quand au trafic lui-même, on voit (ici avec tcpdump) d'abord du RTSP sur TCP puis un gros flux UDP :
21:34:36.179830 IP (tos 0x10, ttl 64, id 20888, offset 0, flags [DF], proto UDP (17), length 1356) 212.27.38.253.46099 > 192.168.2.1.34324: [udp sum ok] UDP, length 1328 21:34:36.180040 IP (tos 0x10, ttl 64, id 20889, offset 0, flags [DF], proto UDP (17), length 1356) 212.27.38.253.46099 > 192.168.2.1.34324: [udp sum ok] UDP, length 1328 21:34:36.180738 IP (tos 0x10, ttl 64, id 20890, offset 0, flags [DF], proto UDP (17), length 1356) 212.27.38.253.46099 > 192.168.2.1.34324: [udp sum ok] UDP, length 1328
Les contenus auxquels on accède avec RTSP peuvent être de type très variés. Il faut donc une description formalisée des caractéristiques de ce contenu. RTSP peut utiliser plusieurs formats pour cela, le plus répandu étant sans doute SDP (RFC 4566). C'est en tout cas celui utilisé entre mon VLC et ma Freebox. La description peut inclure le nombre de flux (souvent un flux vidéo et plusieurs audios), le protocole de délivrance (RTP - RFC 3550 - dans l'exemple ci-dessous), le format (MPEG-2 ici), etc :
Session Description Protocol Session Description Protocol Version (v): 0 Owner/Creator, Session Id (o): leCDN 1395332443 1395332443 IN IP4 kapoueh.proxad.net ... Media Description, name and address (m): video 0 RTP/AVP 33 Media Type: video Media Port: 0 Media Protocol: RTP/AVP Media Format: MPEG-II transport streams Media Attribute (a): control:rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=658&flavour=ld Media Attribute Fieldname: control Media Attribute Value: rtsp://mafreebox.freebox.fr/fbxtv_pub/stream?namespace=1&service=658&flavour=ld
Quels sont les changements par rapport à RTSP version 1, la version
du RFC 2326 ? Les deux
versions, quoique identiques dans leurs principes, ne sont pas
compatibles (par exemple, la commande PLAY
n'a
plus le même comportement, des en-têtes ont changé de syntaxe sans
changer de nom, etc). C'est toujours un choix difficile que de casser la
compatibilité d'un protocole mais, là, c'était nécessaire vu le nombre
de modifications. En outre, RTSP 1 ne
permettait pas de déployer facilement des extensions (en-têtes à la
syntaxe trop rigide) et le modèle d'extension a changé. L'annexe I de
notre RFC résume ce qu'il faut savoir sur ces différences :
suppression des requêtes RECORD
et
ANNOUNCE
, suppression de l'option qui permettait
de faire passer RTSP (le contrôle, pas les données) sur UDP, gestion
complète d'IPv6 (qui manquait en version 1),
refactorisation du RFC (les en-têtes qui sont proches de ceux de HTTP
sont désormais décrits par un texte spécifique, sans renvoyer au RFC
HTTP), etc.
Il y a apparemment au moins une mise en œuvre de RTSP qui a la version 2, et plusieurs des nouveautés de la version 2 ont été mises en œuvre de manière séparée.
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : P. Hoffman (ICANN)
Pour information
Première rédaction de cet article le 16 décembre 2016
Contrairement à beaucoup de SDO, l'IETF n'avait pas de format standard pour l'écriture de ses documents. Désormais, avec le nouveau cadre décrit dans le RFC 7990, c'est fait. XML, avec le vocabulaire décrit dans ce nouveau RFC, est le format canonique des RFC.
Vous voulez écrire un RFC ? Il est fortement recommandé d'utiliser dès le début le format standard XML, fondé sur un vocabulaire spécifique aux RFC, et mis en œuvre dans la future version de l'outil xml2rfc. Voici donc le vocabulaire « XML2RFC version 3 », succédant à deux versions qui n'étaient pas officiellement standard (les changements depuis la v2, spécifiée dans le RFC 7749, ne sont pas énormes). Notez que le vocabulaire XML et les outils continuent à évoluer, donc ce RFC n'est pas éternel. Et que la version 2 restera sans doute en service pendant encore des années : cela prend du temps de changer les habitudes !
Voici le squelette d'un Internet-Draft écrit avec ce XML :
<?xml version="1.0" encoding="utf-8"?> <rfc docName="draft-ietf-dnsop-qname-minimisation-09" submissionType="IETF" ipr="trust200902"> <front> <title abbrev="Qname minimisation">DNS query name minimisation to improve privacy</title> ... <middle> <section anchor="intro" title="Introduction and background"> <t>The problem statement is described in <xref target="RFC7626"/>. [...] ... </back> </rfc>
Sur ce squelette simple, on voit l'élément racine
(<rfc>
), l'utilisation des attributs
(comme submissionType
qui indique la voie
prise par le document, ici, l'IETF,
cf. RFC 7841), la séparation en trois parties,
<front>
, qui regroupe les
métadonnées,
<middle>
, qui est le texte principal,
et <back>
, où se trouvent la
bibliographie, les annexes, etc.
Parmi les attributs de cet élément racine
<rfc>
, notez ipr
,
qui indique les conditions légales d'utilisation de ce RFC. Dans
cet example, la valeur est la plus couramment utilisée :
trust200902
(cf. l'annexe A.1) indique les règles de
l'IETF Trust datant de 2009 (qui disent en
gros que le texte du RFC peut être librement copié, reproduit,
distribué et mis en œuvre dans des programmes). L'annexe A de
notre RFC détaille ce qu'on appelle le
boilerplate, ces textes juridiques obligatoires
qui sont ajoutés automatiquement par le logiciel xml2rfc. Ainsi,
si on met ipr="trust200902"
dans l'élément
<rfc>
, xml2rfc va automatiquement
ajouter « Copyright (c) 2015 IETF Trust and the persons identified as the
document authors. All rights reserved. \ This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents [...] »...
Le gros morceau du RFC est la section 2, qui donne la liste des éléments XML acceptés. Je ne vais pas reproduire ici cette liste, juste parler de quelques éléments qui me semblent rigolos.
<section>
contient une partie du
RFC. Cet élément est hiérarchique : on crée des sous-sections en
les mettant sous les sections existantes, et ainsi de suite,
récursivement. (Contrairement à ce qui se passe avec
HTML, où on indique explicitement le niveau
de la section, <h1>
,
<h2>
, etc.) On a aussi
<abstract>
, qui indique le résumé au
début du RFC.
<t>
contient un paragraphe et est
donc l'équivalent du <p>
de HTML.
<artwork>
permet de spécifier du texte qui sera représenté comme tel,
sans aucune justification, mise à la ligne, etc. (Les
tabulations sont interdites, ce qui règle
le vieux débat « tabs
vs. spaces ».) <artwork>
permet
de mettre de l'art ASCII dans un RFC, mais la
méthode préférée pour les images est désormais
SVG, voir le RFC 7996. Le SVG peut être mis directement dans le source
XML ou bien inclus par différentes méthodes, dont l'attribut
src
. Cet attribut
src
permet de spécifier un fichier externe,
l'art ASCII ne servant alors que de solution de secours, pour le
format en texte seul. Un attribut type
permet
d'indiquer le type du dessin (par exemple
svg
pour les images en SVG). La liste des types
possibles sera en ligne.
Voici un exemple d'art ASCII :
<artwork type="ascii-art"> +--------------+ +----------------+ | Alice |------------------------------------| Bob | | 2001:db8::1 | | 2001:db8::2 | +--------------+ +----------------+ </artwork>
Le code source, lui, se fait avec
l'élément <sourcecode>
, un attribut
type
permettant d'indiquer le langage utilisé
(une liste des valeurs possibles sera en ligne). Voici un exemple :
<sourcecode type="python"> print("Hello, world") </sourcecode>
Comme le langage utilisé peut utiliser des caractères qui sont spéciaux pour XML (comme < ou &), il est souvent préférable de mettre le code source dans une section CDATA.
<eref>
permet de faire un lien
hypertexte vers l'extérieur :
<t>More text and a <eref target="http://www.rfc-editor.org/">lien vers le site du RFC Editor</eref>.</t>
<ul>
permet de représenter les
traditionnelles listes à puces :
<t>There are three sorts of DNS requests being issued:</t> <ul> <li>Primary request: [...]</li> <li>Secondary requests: [...]</li> <li>Tertiary requests: [...]</li> </ul>
<references>
permet d'indiquer une
bibliographie. Il y en a typiquement deux
dans un RFC (cf. la section 4.8.6 du RFC 7322), la bibliographie normative (ce qu'il faut absolument
avoir lu et compris car le RFC en dépend) et l'informative (ce
qu'on peut sauter si on est pressé). Pour aider, le RFC
Editor distribue des fichiers XML contenant les
références aux RFC publiés, comme http://www.rfc-editor.org/refs/bibxml/reference.RFC.7626.xml
.
Le nom d'un auteur de RFC se met avec l'attribut
<author>
. Comme il peut être en
caractères non-ASCII, des attributs permettent d'indiquer une
variante en ASCII seul. Par exemple :
<author fullname="Patrik Fältström" asciiFullname="Patrik Faltstrom"> <organization>Netnod</organization> </author>
Ce format de RFC s'appuie sur XML et il faut donc suivre les règles de XML, notamment sur les caractères spéciaux. Ainsi, le chevron ouvrant doit être remplacé par une séquence d'échappement (< au lieu de <). Si cette contrainte est trop forte, on peut aussi enclore les parties à « échapper » dans une section CDATA.
Le format des RFC permet d'autres caractères que ceux du jeu ASCII, mais avec certaines restrictions (voir RFC 7997).
Le format actuel permet l'inclusion d'autres documents, via des
attributs comme l'attribut src
pour le code
source :
<sourcecode type="python" src="hello.py"/>
On peut aussi utiliser les mécanismes génériques d'inclusion de XML, comme XInclude (cf. annexe B.1) ou les entités, et c'est souvent utilisé pour la bibliographie :
<!DOCTYPE rfc [ <!ENTITY rfc7830 PUBLIC "http://xml.resource.org/public/rfc/bibxml/reference.RFC.7830.xml"> ]> [...] <references> &rfc7830; </references>
À noter qu'il existe un type
MIME pour les sources XML de RFC,
application/rfc+xml
(section 8 de notre RFC).
Si vous voulez voir le schéma XML complet, il est en annexe
C (j'en ai exporté une version utilisable telle quelle, sans les
sauts de page des RFC, en rfc-v3.rnc
). Comme il est
écrit en Relax NG, il
permet l'utilisation de tous les outils Relax NG, comme le mode
emacs nxml-mode et comme
rnv. Ainsi, une fois le fichier
rfc-v3.rnc
chargé dans emacs (menus XML puis
Set schema puis File), on
dispose de fonctions d'édition bien pratiques (par exemple, on
tape un < puis une tabulation et emacs propose de compléter
uniquement avec les éléments autorisés à cet endroit). Cela évite
bien des erreurs.
À noter que ce RFC ne décrit que les éléments et attributs XML, pas de processing instructions (PI), qui ne sont plus acceptées.
Avec un logiciel comme rnv, on peut tester la syntaxe (uniquement la syntaxe : certaines contraintes dans le RFC ne sont pas exprimables dans le schéma, il a fallu les formuler en langue naturelle dans le texte du RFC) :
% rnv rfc-v3.rnc rfc-v3-sample.xml rfc-v3-sample.xml
Parfait, ici, tout est bon. S'il y avait eu une erreur :
% rnv rfc-v3.rnc rfc-v3-sample-wrong.xml rfc-v3-sample-wrong.xml rfc-v3-sample-wrong.xml:9:6: error: element ^t not allowed required: element ^section rfc-v3-sample-wrong.xml:11:2: error: unfinished content of element ^middle required: element ^section error: some documents are invalid
Si le RFC contient des références externes (que rnv ne sait pas traiter), on peut utiliser xmllint pour les remplacer :
% xmllint --dropdtd --noent draft-dupont-my-protocol.xml | rnv rfc-v3.rnc
On peut aussi utiliser Jing (annexe C.1). Mode d'emploi très court, on télécharge :
% wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jing-trang/jing-20091111.zip % unzip jing-20091111.zip % java -jar ./jing-20091111/bin/jing.jar -c rfc-v3.rnc draft-dupont-my-protocol.xml %
Les changements depuis le texte précédent, le RFC 7749, qui décrivait la version 2 (notre RFC est la version 3), sont décrits dans l'annexe D et résumés en section 1.3. L'idée était notamment d'avoir un vocabulaire plus facile à utiliser, sans pour autant trop changer par rapport au format v2, qui était bien connu des auteurs.
Le changement le plus spectaculaire concerne les listes, qui
sont désormais faites, comme en HTML, avec
des <dl>
,
<ul>
et
<ol>
. Dans une liste, le contenu est
marqué par <li>
et plus
<t>
. Autre inspiration HTML,
l'apparition des tables, avec <table>
(et éléments associés comme <tr>
et
<td>
). D'autre part, de nouveaux éléments
apparaissent pour marquer du texte, par exemple s'il est
important (<em>
,
qui n'avait pas d'équivalent en v2, dont le seul format de sortie
était le texte brut). Il y a aussi un
<blockquote>
pour les citations. Bien que l'IETF se
vante souvent de pratiquer le culte du « running
code », il n'y avait pas d'élément XML particulier pour
indiquer du code source dans un RFC (on se contentait
d'<artwork>
). C'est désormais fait avec
<sourcecode>
. Quelques autres éléments
XML nouveaux (je ne les cite pas tous, le RFC fait 159 pages !) :
<displayreference>
pour associer un
chouette texte aux références, <link>
pour les liens externes (contrairement à
<eref>
, qui existait déjà,
<link>
est spécifique à certains types
de documents, par exemple les Internet-Drafts) ou encore
<br>
pour forcer des sauts de ligne
(mauvaise idée que de mettre des éléments de présentation, si vous
voulez mon avis).
Il y a aussi de nouveaux attributs XML aux éléments
existants. Pour remplacer les PI (processing
instructions comme <?rfc
toc="yes"?>
), on a tocInclude
et tocDepth
dans l'élément
<rfc>
, afin de contrôler la
table des matières. De même, pour gérer
l'internationalisation, il y a désormais un attribut
ascii
pour les éléments qui acceptent du
contenu non-ASCII, afin de fournir une
alternative pour les anglophones. Il y a aussi des attributs plus
orientés présentation comme keepWithNext
ou
keepWithPrevious
, attributs de
<t>
, qui expriment un souhait de garder
ce paragraphe avec le suivant ou le précédent, pour mieux
contrôler la pagination.
En revanche, certains éléments et attributs sont retirés de la
circulation. Ils seront encore acceptés par les outils, mais
temporairement. <list>
subit ce trist sort
(remplacé par les éléments HTMLisant comme
<ul>
et
<ol>
). <facsimile>
disparait également, victime des évolutions technologiques. Parmi
les attributs, title
disparait (il était
utilisé dans des éléments comme
<section>
) au profit de
name
(changement assez gratuit, je
trouve).
Les autres changements sont bien sûr l'acceptation de caractères non-ASCII, et plein de modifications de détail.
Question mise en œuvre, il faudra patienter. S'il y a déjà eu des mises en œuvre expérimentales et partielles, les vrais logiciels officiels ne sont pas encore, en octobre 2016, développés.
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : H. Flanagan (RFC Editor)
Pour information
Première rédaction de cet article le 16 décembre 2016
Voici enfin la série de RFC décrivant le nouveau format des RFC. Ce projet a commencé il y a plusieurs années, mais les discussions ont été longues. Ce nouveau RFC et les huit autres qui l'accompagnent, marquent un changement important dans ces « textes sacrés » de l'Internet : l'ancien format « texte brut » n'est plus le format de référence. Désormais, tout RFC sera fait en XML, format d'où seront produits automatiquement des versions texte brut, HTML, PDF, etc.
Les RFC sont des documents cruciaux pour l'Internet. C'est sous forme de RFC que sont publiées les normes techniques de la famille de protocoles TCP/IP. Et il y a bien d'autres RFC qui ne sont pas forcément des normes (cf. RFC 1796). Librement disponibles en ligne (contrairement aux normes techniques des organisations traditionnelles du mésozoïque), dans un format ouvert, la disponibilité des RFC est l'une des raisons du succès de l'Internet.
Parlons de format, justement. Les RFC, jusqu'à maintenant, étaient sous forme de texte brut, et en ASCII seul. (Certes, des versions PDF et HTML non-officielles étaient diffusées mais on voyait bien qu'elles avaient été produites à partir du texte brut... Certes, il était possible depuis dix ans d'écrire les RFC en XML, cf. RFC 2629, mais ce n'était pas le format de référence.) Pourquoi donc se limiter à ce format ? Il y avait plusieurs bonnes (et d'autres moins bonnes) raisons mais il ne faut pas de cacher qu'une des raisons les plus importantes était qu'il est difficile de faire changer un processus de production bien établi, même s'il comprend des archaïsmes, comme l'utilisation de troff pour traiter des documents. L'actuelle éditrice des RFC, Heather Flanagan, a donc eu bien du mérite à faire aboutir ce projet de changement. Il a fallu beaucoup de discussions, dans une communauté souvent divisée. (Que les informaticiens pensent aux grands débats du genre « vi ou emacs ? »)
Le projet de réforme des RFC avait sérieusement commencé en 2013 avec le RFC 6949, le véritable cahier des charges du nouveau format. La décision formelle de migrer vers le nouveau format, et donc de décider que le format de référence serait désormais le XML et non plus le texte brut a été prise en mai 2013. Avant et pendant cette décision, d'innombrables messages ont été échangés sur la liste de diffusion rfc-interest.
Il est important de noter que cette discussion portait sur le processus de publication des RFC terminés. L'élaboration des Internet-Drafts, la décision de les publier ou pas (qui dépend de chaque voie, cf. RFC 8729) ne sont pas concernées.
La section 2 de notre RFC résume le problème que veut résoudre le nouveau format. Le monde a bien changé depuis que seuls une poignée de Californiens anglophones venait aux réunions IETF. Les participants viennent aujourd'hui de 45 pays, situés dans le monde entier, les lecteurs des RFC sont plus divers que jamais, utilisent des engins très variés, et il est toujours aussi crucial que les RFC soient largement disponibles et accessibles, et sur une très longue période (mon favori est le RFC 768, publié en 1980 et toujours d'actualité). Le format de référence en texte ASCII brut ne permettait clairement pas cela.
Mais choisir un successeur n'était pas facile : notre RFC insiste sur le fait qu'il y a aujourd'hui plusieurs groupes qui utilisent les RFC (pas seulement des techniciens, juristes et chefs accèdent aujourd'hui à des RFC), et sur le fait qu'il fallait un compromis entre les besoins actuels et l'importance d'une disponibilité à long terme (par exemple, adopter le format à la mode du moment pourrait se payer cher plus tard lorsque ce format n'intéressera plus personne).
Un peu de terminologie (section 3) est nécessaire pour bien comprendre le choix effectué :
Et aussi un terme important : texte réagencable (ou réajustable, reflowable text). C'est du texte qui s'ajuste automatiquement à la largeur du dispositif de lecture. C'est banal dans le monde HTML, où c'est fait automatiquement depuis toujours. Mais c'était un des principaux inconvénients de l'ancien format des RFC : le texte avait une largeur fixe.
Quel sera donc exactement le format canonique ? La section 6 répond à cette question :
<sourcecode
src="[un URI externe]"...
(RFC 7991, section 2.48), le code en question sera inclus
dans la version canonique. Idem si l'auteur a utilisé XInclude.Notez donc que les images (en SVG) seront désormais possibles (voir le RFC 7996).
Le guide du style des RFC (RFC 7322) avait été révisé pour tenir compte de ce nouveau format. Notamment, il se concentre désormais sur le contenu du texte, ne demandant plus aux auteurs des efforts de présentation. (La section 5 résume les changements importants pour les auteurs.)
Enfin, la section 7 décrit les formats de publication. À partir du source XML, seront automatiquement produits HTML, PDF, texte brut et peut-être plus tard d'autres. Le HTML est évidemment la cible évidente. Son utilisation pour les RFC est décrite dans le RFC 7992. Le résultat sera certainement bien meilleur que les versions HTML non-officielles actuelles, qui sont produites à partir du texte brut, qui ne contient pas assez de structure pour faire du bon HTML. La mise en page sera évidemment assurée par CSS (RFC 7993), il y aura une feuille de style standard, que chacun sera bien sûr libre de remplacer. Le SVG sera inclus dans l'HTML (il faudra donc un navigateur qui gère bien SVG). Il y aura même du JavaScript mais avec de sévères restrictions. Notamment, le code JavaScript ne devra pas changer le texte, ou supprimer du texte.
PDF, quant à lui, est spécifié dans le RFC 7995. Il devra suivre le profil PDF/A-3, spécialement prévu pour de l'archivage à long terme, et pour pouvoir être relu par des logiciels PDF n'ayant pas tous les derniers gadgets.
Naturellement, le texte brut n'est pas abandonné. Comme indiqué dans le RFC 7994, il y aura une version en texte brut produite automatiquement à partir du XML, même si elle ne sera plus la version canonique. Parmi les nouveautés par rapport à l'ancien format, UTF-8 sera désormais autorisé, même si c'est de façon limitée (voir les limitations dans le RFC 7997). Il pourra y avoir une variante non découpée en pages.
Dans le futur, il est possible que le format EPUB soit ajouté à cette liste.
Au passage, comment a été décidé cet important changement dans le format des RFC ? La section 4 résume cette histoire. Comme indiqué plus haut, cela a pris très longtemps et nécessité beaucoup de discussions, qui ont notamment eu lieu sur la liste de diffusion rfc-interest, et au cours des réunions physiques de l'IETF. Le cahier des charges a été formalisé en 2013 dans le RFC 6949. Une fois le cahier des charges décidé, une équipe spécialisée a été désignée par le RFC Editor pour mettre au point les détails, notamment en adaptant le langage XML utilisé, partant de la dernière version (RFC 7749), pour arriver au futur langage, RFC 7991. Des éditeurs professionnels ont également été consultés, ainsi d'autres SDO et même des juristes (oui, car aux États-Unis, rien n'est désormais à l'abri d'actions en justice, même pas les RFC, le choix du format de sortie PDF/A-3 venait en partie de la nécessité de répondre aux subpoenas). Le tout était bien sûr fait sous la supervision du RFC Series Oversight Committee. Certaines décisions furent consensuelles, les autres tranchées par le RFC Editor (cf. RFC 8728). Le tout a été approuvé par l'IAB en août 2016.
Après ce tour du passé, le futur. Comment se fera la transition vers le nouveau système (section 10) ? C'est qu'il va falloir créer de nouveaux outils (cf. RFC 7998). L'appel d'offres pour leur développement a été fait en septembre 2016. La description des outils est une très intéressante lecture (l'appel d'offres formel est sur la page des Request For Proposal). L'appel d'offres a été gagné par les sociétés SeanTek et Elf Tools.
Pendant une période intermédiaire, le texte seul sera toujours utilisé comme format canonique, mais les nouveaux RFC passeront également par le nouveau workflow, pour vérifier que tout se passe bien et que le résultat est correct. Double travail, donc, mais nécessaire pour s'assurer que tout est en place.
Notez que, même une fois la transition finie, les auteurs ne seront pas forcés de soumettre leur document sous forme d'un fichier XML (ils seront simplement très fortement encouragés à le faire). S'ils envoient le texte seul comme avant, le RFC Editor devra produire le XML lui-même, et c'est ce XML qui sera la version canonique. Rappelez-vous que beaucoup de RFC sont des documents normatifs et que chaque mot, voire chaque virgule peut compter ! Voici pourquoi il faudra s'assurer que tout est parfait, même si, au début, cela entrainera certainement des retards dans la publication.
Dans le cas où l'auteur envoie du XML suivant le RFC 7991, il y aura moins de travail pour le RFC Editor, juste convertir ce XML au XML canonique (résoudre les références extérieures, par exemple) et passer ce XML canonique dans les nouveaux outils.
Notez que le RFC Editor maintient une FAQ très utile sur toutes les questions que pose le nouveau format. Et la RFC Editor avait fait un très drôle Pecha Kucha à Séoul en novembre 2016, sur le cahier des charges du nouveau format.
Le premier RFC au nouveau format a été le RFC 8651, sorti en octobre 2019.
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : J. Hildebrand (Cisco
Systems), P. Hoffman (ICANN)
Pour information
Première rédaction de cet article le 16 décembre 2016
Depuis la sortie du RFC 7990 et ses copains, le format canonique (le format de référence) des RFC n'est plus le texte seul mais un langage XML, normalisé dans le RFC 7991. Les formats « de publication » seront produits automatiquement à partir de ce XML. C'est ainsi que notre RFC 7992 décrit la sortie HTML, qui permettra de publier des beaux RFC sur le Web.
HTML, trop riche et trop mouvant, est en effet mal adapté à l'écriture et à la maintenance de documents. Il n'était donc pas envisageable de le choisir comme format canonique. En revanche, il est incontournable comme format de publication. C'est en effet le langage du Web, et il y a donc logiquement une forte demande pour pouvoir lire les RFC en HTML. Avant, lorsque le format canonique était le texte brut, des versions non officielles étaient publiées en HTML (voir un exemple) mais, le texte brut n'ayant pas de formatage précis, ces versions n'avaient pas vraiment l'air de vraies pages Web...
(Notez que ce blog que vous êtes en train de lire est produit par un mécanisme analogue à celui que les RFC suivront désormais : tapé en XML, avec le HTML produit automatiquement.)
La section 1 de notre RFC résume les principes de l'HTML utilisé. D'abord, ce sera un sous-ensemble de HTML (HTML a bien trop de fonctions). Ensuite, la présentation sera largement délégué à une feuille de style CSS, dont les caractéristiques sont mentionnées dans le RFC 7993.
La section 2, elle, est le « cahier des charges » du HTML des RFC. Elle précise les exigences du RFC 6949. Elle concerne les auteurs du ou des logiciels de production des RFC (pour ces logiciels, voir le RFC 7998). Les auteurs de RFC, eux, n'ont pas à s'en soucier, ils écrivent du XML, et le HTML sera produit par les outils.
Le but principal est que l'HTML produit soit parfaitement lisible sur la grande majorité des navigateurs utilisés. Pas question bien sûr d'ajouter une de des ridicules mentions « optimisé pour Internet Explorer » qui étaient si communes sur les sites Web d'amateurs, dans les années 2000. Notre RFC mentionne explicitement l'exigence que les textes soient lisibles avec au moins un navigateur « texte », comme Lynx, certaines personnes accédant au Web ainsi (par obligation ou par goût). C'est l'une des raisons de la décision de ne pas accepter la totalité de HTML.
Le fichier HTML devra être autonome (ne pas dépendre de fichiers extérieurs), de manière à pouvoir être transmis facilement par des mécanismes tels que rsync ou le courrier électronique.
Le JavaScript est accepté mais à condition qu'il ne modifie en aucun cas le texte du RFC. (Il peut, par exemple, ajouter des éléments de navigation, ou afficher des métadonnées.)
On l'a dit, CSS sera utilisé pour la présentation, mais le cahier des charges exige qu'on puisse facilement remplacer la feuille de style par une de son choix, pour s'adapter aux goûts locaux.
Le Web étant fondé sur la notion de lien hypertexte, il y aura évidemment des liens, aussi bien ceux mis explicitement par l'auteur (« ce point est développé en section N »), que ceux ajoutés automatiquement (de la table des matières vers les différentes sections, par exemple).
Un point crucial est évidemment l'accessibilité. Comme le savent tous ceux et toutes celles qui vont régulièrement à Paris Web, c'est un point essentiel mais souvent oublié. Notre RFC note donc que les publications en HTML des futurs RFC devront être accessibles aux malvoyants, aux daltoniens, et aux utilisateurs de petits écrans, par exemple les smartphones. (Note personnelle : ce dernier point ne devrait pas être dans une section sur l'accessibilité. Le Web est prévu - contrairement aux formats du monde du papier, comme PDF - pour être visible sur tous les périphériques.)
Au fait, quelle version de HTML sera utilisée (section 3 de notre RFC) ? Ce sera HTML5 (et pas, et je le déplore, XHTML ; l'inconvénient, souvent cité contre XHTML, de la difficulté à l'écrire n'a pas de sens ici, puisque le HTML sera produit automatiquement).
La section 4 précise la syntaxe utilisée (rappelez-vous qu'on n'accepte pas la totalité de HTML5) : encodage en UTF-8, sauts de ligne en style Unix (un U+000A et rien d'autre), pas de caractères de contrôle comme la tabulation (U+0009). Les éventuels commentaires du source XML ne seront pas mis dans le HTML (l'idée est qu'ils sont pour les auteurs, pas pour les lecteurs).
Il y a des objets divers qu'on retrouve souvent dans le source
XML. Ils sont rassemblés dans la section 5. Par exemple, on
trouve les identificateurs qui seront mis comme valeur des
attributs id
dans le HTML produit. Ce sont
parfois des identificateurs mis explicitement par l'auteur, et
parfois des identificateurs produits par le logiciel, par exemple
pour que les entrées de la table des matières pointent vers la
section correspondante.
Autre objet récurrent, la marque de paragraphe (pilcrow pied-de-mouche, caractère Unicode U+00B6, celui-ci : ¶), qui sera mise automatiquement derrière chaque paragraphe, mais pas affiché par défaut (il faudra promener le pointeur dessus pour le voir).
Maintenant, attaquons les différentes parties du RFC rendu en
HTML. D'abord (section 6), les premiers objets HTML qu'on
rencontrera, notamment les métadonnées du
RFC. Il y aura évidemment un
DOCTYPE
identifiant le document comme du HTML5. L'élément racine sera <html>
,
avec une étiquette de langue qui sera bien
sûr en
,
l'anglais. L'élément
<head>
qui suivra contiendra une
déclaration de jeu de caractère, un titre,
et diverses métadonnées :
<meta charset="utf-8"> <title>The Mother of all RFCs</title> <meta name="author" content="Joe Hildebrand"> <meta name="author" content="Heather Flanagan"> <meta name="description" content="This document defines..."> <meta name="generator" content="xmljade v0.2.4"> <meta name="keywords" content="html,css,rfc">
(Rappelez-vous que le HTML produit n'est hélas pas du
XHTML donc il est normal que les
<meta>
ne soient pas explicitement
fermés.)
Il y aura aussi un lien vers la licence des RFC, en utilisant le
cadre général des liens (RFC 8288) :
<link rel="license" href="https://www.rfc-editor.org/copyright/">
Cette première partie du RFC produit contiendra aussi une feuille de style, ainsi qu'un lien vers une éventuelle feuille locale, au cas où un lecteur souhaiterait lire le RFC selon un style différent :
<style> body {} ... </style> <link rel="stylesheet" type="text/css" href="rfc-local.css">
Le début de la partie visible du RFC sera composée d'une
<dl>
pour les métadonnées affichées, et
d'une table des matières. Les métadonnées seront donc du genre :
<dl id="identifiers"> <dt>Workgroup:</dt> <dd class="workgroup">rfc-interest</dd> <dt>Series:</dt> <dd class="series">Internet-Draft</dd> <dt>Status:</dt> <dd class="status">Informational</dd> <dt>Published:</dt> <dd><time datetime="2014-10-25" class="published">2014-10-25</time></dd> ...
La partie principale du RFC sera, elle, rendue selon les principes décrits en section 9 pour chacun des éléments XML qui composent le source.
La dernière partie du RFC incluera un index (si le source XML
avait un attribut indexInclude
dans l'élément
<rfc>
), les adresses des auteurs
(formatées en hCard), et les métadonnées
considérées comme les moins importantes (les autres ayant été
mises au début).
La section 9 de notre RFC est particulièrement longue car elle
décrit le rendu en HTML de tous les éléments du vocabulaire XML du
RFC 7991. Je ne vais pas tout décrire ici,
juste donner quelques exemples. Ainsi,
<artwork>
sera rendu dans un élément
HTML <pre>
, si le schéma était en
art ASCII, sera inclus tel quel dans le
HTML si le schéma était en SVG (RFC 7996), et sera mis sous forme d'un
<img>
(avec contenu de plan
data:
) dans les autres
cas. <sourcecode>
, lui, est toujours
restitué sous forme d'un <pre>
HTML.
La traduction de certains éléments en HTML est plus
directe. Par exemple,
<em>
est simplement rendu par le même
élément HTML.
Et, pour finir, un petit mot sur la sécurité (section 11) : comme les RFC en HTML ne sont pas forcément téléchargés depuis le Web mais peuvent être lus depuis un fichier local (après, par exemple, synchronisation via rsync), on ne bénéficie pas forcément des protections du navigateur. Donc, prudence.
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : H. Flanagan (RFC Editor)
Pour information
Première rédaction de cet article le 16 décembre 2016
Les RFC sont forcément écrits en anglais, qui restera la langue officielle (cf. RFC 7322). L'anglais peut s'écrire avec uniquement les caractères ASCII (avec quelques exceptions : resume et résumé ne sont pas le même mot). Mais on pourra désormais inclure des caractères non-ASCII, par exemple pour le nom des auteurs (chic, je pourrais écrire correctement mon prénom dans les RFC). Cette possibilité permettra aussi aux exemples de protocoles Internet utilisant Unicode (la grande majorité) d'être plus lisibles.
Cette nouvelle possibilité fait partie de celles qu'offre le nouveau format des RFC, décrit dans le RFC 7990. Il n'y a quand même pas d'autorisation générale d'inclure n'importe quel caractère Unicode dans les RFC, à n'importe quel endroit. Le RFC Editor pourra toujours refuser tel ou tel caractère, par exemple parce qu'il n'existe pas de police permettant de l'afficher. Et le « non-ASCII » n'est autorisé que dans certains cas, décrits plus loin. La grande majorité du texte sera donc du pur ASCII (RFC 20).
Il ne suffit pas de proclamer « on a droit à Unicode ». Il faut aussi adapter les outils. Par exemple, notre RFC impose (section 2) que les outils de recherche dans les RFC gèrent correctement la recherche Unicode. (C'est pour traiter le cas des outils imparfaits que le RFC demande aussi que les noms d'auteurs en Unicode soient accompagnés d'une version en ASCII.) Et que le RFC soit affichable correctement sur un bon nombre de plate-formes (d'où la possibilité de rejeter les caractères les plus rares).
Ce problème du repli (vers une version en ACSII pur) est souvent cité dans le RFC. Ainsi, lorsqu'on veut mentionner un caractère Unicode (mettons le thorn islandais), le RFC permet désormais de l'afficher proprement, mais il demande qu'on l'accompagne du numéro du point de code, et, si possible, de son nom Unicode. Cela donnerait, par exemple « For instance, U+00FE, "LATIN SMALL LETTER THORN", þ, is interesting because... ». Notez que cette façon de désigner des caractères Unicode que tout le monde n'arrivera pas forcément à afficher n'est pas vraiment standardisée. Dans les RFC actuels, on trouve des variantes (voir cette discussion). Le RFC contient plusieurs exemples sur la façon d'écrire la phrase « Temperature changes in the Temperature Control Protocol are indicated by the U+2206 character (∆, "INCREMENT") », tous acceptés (le nom Unicode n'est pas obligatoire, il peut être placé avant ou après le caractère lui-même, etc.) Autre cas, ce texte du RFC 8264, « For example, the characters U+13DA U+13A2 U+13B5 U+13AC U+13A2 U+13AC U+13D2 from the Cherokee block look similar to the ASCII characters "STPETER" » deviendrait « For example, the characters U+13DA U+13A2 U+13B5 U+13AC U+13A2 U+13AC U+13D2 (ᏚᎢᎵᎬᎢᎬᏒ) from the Cherokee block look similar to the ASCII characters "STPETER" ». Des tables comme celles des identificateurs et mots de passe Unicode légaux (RFC 8265) seraient ainsi bien plus lisibles.
Pour les noms, par exemple ceux des auteurs. On aurait du « non-ASCII » et un texte de repli, comme (en utilisant le vocabulaire XML du RFC 7991) :
<author fullname="רוני אבן" asciiFullname="R. Even"/> <author fullname="吴钦" asciiFullname="Q. Wu"/> <author fullname="J. Smith" asciiFullname="J. Smith"/> <!-- Oui, dans ce cas, il faut le dire deux fois -->
Cela permettra enfin d'écrire correctement les noms des auteurs de RFC.
La bibliographie d'un RFC est également un bon endroit où mettre des caractères Unicode, par exemple lorsqu'on cite des textes non-anglo-saxons. Ainsi, la bibliographie du RFC 5933 pourrait inclure :
[GOST3410] "Information technology. Cryptographic data security. Signature and verification processes of [electronic] digital signature.", GOST R 34.10-2001, Gosudarstvennyi Standard of Russian Federation, Government Committee of Russia for Standards, 2001. (In Russian) "Информационная технология. Криптографическая защита информации. Процессы формирования и проверки электронной цифровой подписи", GOST R 34.10-2001, Государственный стандарт Российской Федерации, 2001.
Le second texte étant l'original russe.
Les règles exactes figurent dans la section 3. D'abord, on peut mettre du « non-ASCII » comme on veut quand il fait partie d'un exemple. Ainsi, la communication XMPP pourrait être décrite de manière plus naturelle. Au lieu de cet exemple de communication en tchèque (RFC 6121) :
<message from='juliet@example.com/balcony' id='z94nb37h' to='romeo@example.net' type='chat' xml:lang='en'> <body>Wherefore art thou, Romeo?</body> <body xml:lang='cs'> PročeŽ jsi ty, Romeo? </body> </message>
On pourra écrire la forme lisible :
<message from='juliet@example.com/balcony' id='z94nb37h' to='romeo@example.net' type='chat' xml:lang='en'> <body>Wherefore art thou, Romeo?</body> <body xml:lang='cs'> PročeŽ jsi ty, Romeo? </body> </message>
Ensuite, on peut utiliser le « non-ASCII » pour les cas cités plus haut (noms d'auteurs, textes non-anglophones dans la bibliographie, etc). Pour les exemples utilisant un langage de programmation, notre RFC spécifie qu'il faut suivre les règles du langage en question. Ainsi, Python 3 autorisant l'Unicode même dans les noms de variables, on peut écrire :
a = "chocolat" b = "café" # Accentué ç = "lait" print(a+b+ç)
Enfin, un petit mot sur la normalisation Unicode, pour rappeler que le format des RFC ne garantit rien à ce sujet (on aurait pu décider que NFC serait systématiquement utilisée...) et que les auteurs de RFC ne doivent donc pas compter dessus.
Le premier RFC publié avec des caractères Unicode a été le RFC 8187, en septembre 2017.
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : T. Hansen (AT&T
Laboratories), L. Masinter, M. Hardy
(Adobe)
Pour information
Première rédaction de cet article le 16 décembre 2016
Parmi les nombreux formats de publication des RFC prévus suite à l'adoption du nouveau format (RFC 7990), ce RFC décrit l'utilisation de PDF. On pourra donc, en suivant ces règles, avoir une jolie version papier des RFC.
Actuellement, les RFC peuvent bien sûr être imprimés mais c'est un peu tristoune (cf. annexe A). Avec le nouveau cadre de gestion des RFC, le format canonique du RFC sera du XML (RFC 7991), à partir duquel seront produits automatiquement (par des outils qui ne sont pas encore développés) divers formats. HTML sera sans doute le principal pour une publication en ligne (RFC 7992), mais il y a des partisans de PDF, surtout pour l'impression sur le bon vieux papier. Ce RFC 7995 décrit donc l'utilisation de PDF comme format de sortie pour les RFC. À noter que ce format, créé et piloté par une entreprise privée n'est pas à proprement parler un « format Internet » et est sans doute moins connu des participants à l'IETF que ne l'est HTML.
La norme PDF est déposée à l'ISO (ISO 32000-1) mais l'archaïque ISO ne distribue toujours pas librement ces documents. Si on veut apprendre PDF, il faut donc le télécharger sur le site d'Adobe.
Première question (section 2 de notre RFC), quelle version de PDF choisir ? PDF a évolué dans le temps, chaque version ajoutant de nouvelles fonctions. C'est aujourd'hui un format très complexe, difficile à mettre en œuvre complètement. C'est pour cela qu'il existe des profils de PDF, restreignant ce format pour des usages spécifiques. Ainsi, PDF/X est conçu pour l'échange de fichiers avec l'imprimeur. Pour les RFC, documents souvent normatifs, et à longue durée de vie, les exigences principales sont l'accessibilité et la stabilité. C'est ce que fournissent les profils PDF/UA (accessibilité) et PDF/A-3 (archivage à long terme).
Pour les RFC, les profils choisis sont la version 1.7 de PDF, suffisamment ancienne pour être gérée par la plupart des logiciels, le profil PDF/A-3 pour limiter le nombre de fonctions à gérer, et PDF/UA pour l'accessibilité.
La section 3 de notre RFC détaille ensuite toutes les exigences particulières des RFC, pour le format de sortie PDF. Je ne les commente pas toutes ici, seulement celles qui me semblent importantes. Par exemple, la délicate question des polices. PDF permet d'inclure une police dans le document, ou bien de se référer simplement à une police par son nom. Dans ce dernier cas, si le logiciel qui lit le PDF ne trouve pas exactement cette police, il se rabat sur une police « proche », avec un résultat qui n'est pas forcément satisfaisant. De toute façon, PDF/A, le profil « archivage » impose d'inclure la police utilisée, pour éviter de dépendre de logiciels futurs. À noter que cela peut impliquer de payer : peu de polices sont gratuites pour l'auteur. L'annexe C.4 discute des polices acceptables. Il y a les gratuites, mais sans support Unicode complet, comme Source Sans Pro, Source Serif Pro ou Source Code Pro. Bien meilleure du point de vue de la couverture Unicode, mais payante, est Skolar. L'idéal sera peut-être la nouvelle police Noto. Les RFC ayant maintenant le droit d'utiliser des caractères non-ASCII, mais avec des restrictions (cf. RFC 7997), il est possible que des caractères soient refusés par le RFC Editor uniquement parce qu'ils ne sont pas présents dans les polices utilisées.
Le choix des caractéristiques des polices (chasse fixe ou variable, empattement ou pas) devra suivre les mêmes règles que pour HTML et CSS, règles qui figurent dans le RFC 7993. À propos de HTML, notons d'ailleurs que notre RFC sur PDF demande que le PDF ressemble visuellement autant que possible au document HTML. Si vous écrivez un logiciel qui produit le PDF pour un RFC et que vous hésitez sur tel ou tel aspect graphique, consultez le RFC 7992 sur la sortie HTML.
Parmi les autres exigences pour la production de PDF, notre RFC demande qu'on évite les césures.
PDF permet de mettre des liens hypertextes. L'intérêt est faible puisque PDF est surtout utilisé pour le papier (si on regarde sur un écran PDF n'a aucun avantage par rapport au format bien plus ouvert qu'est HTML), mais le RFC prévoit quand même cette possibilité. Il y aura donc des liens, à la fois externes (vers des URL, y compris vers d'autres RFC et, dans ce cas, le RFC 7322 requiert que cela soit vers la page d'information officielle du RFC Editor) et internes (une section du RFC référençant une autre). Les liens internes sont parfois produits automatiquement (par exemple depuis la table des matières vers les sections du texte).
Un problème délicat est celui de la façon dont le texte est stocké dans le document PDF. PDF permet en effet plusieurs façons de réaliser ce stockage. Elles donnent le même résultat visuel mais se comportent différemment pour des fonctions comme la recherche de texte. Ainsi, le mot « IETF » peut être stocké comme une image, comme quatre lettres positionnées indépendamment, ou comme un mot unique. Le stockage en image posera évidemment des problèmes aux outils comme pdftotext (mais ce n'est pas forcément grave pour les RFC, on a toujours le source XML) ou aux outils de synthèse vocale, nécessaires aux malvoyants. Pour la recherche de texte, la solution du mot unique est certainement meilleure, même si elle ne permet pas une typographie aussi subtile. Mais il y a aussi le placement des phrases. La phrase « The IETF supports the Internet » peut être stockée comme cinq mots différents stockés indépendamment (y compris dans un ordre différent de celui de la phrase) et positionnés ensuite, ou bien comme un objet unique.
Notre RFC recommande d'au moins garder les mots dans l'ordre du texte (PDF/UA l'impose).
Pour les images, si le source XML contenait à la fois de
l'art ASCII et du
SVG, notre RFC impose bien sûr qu'on
utilise le SVG pour produire le PDF. Le texte alternatif aux
images, indispensable
pour l'accessibilité, doit être mis dans le PDF (dans la
propriété /Alt
).
Les métadonnées (noms des auteurs, date, etc) sont très utiles pour l'indexation et la recherche et doivent donc être mises dans le PDF. PDF a plusieurs façons d'embarquer des métadonnées, et la recommandation est d'utiliser XMP.
Parmi les zillions de fonctions de PDF, il peut agir en
container d'autres fichiers (oui, comme tar
ou AVI). Tous les logiciels PDF ne savent
pas extraire ces fichiers embarqués dans le PDF mais c'est une
fonction utile, au cas où. Le RFC recommande donc que des fichiers
utiles soient ainsi embarqués : le source XML du RFC, les codes
sources (dans les éléments <sourcecode>
du RFC), les images (dont les sources
SVG)...
Dernier point, les éventuelles signatures. Pour l'instant, il n'y a pas de mécanisme standard pour signer les RFC et en garantir l'authenticité mais, lorsque ce sera le cas, PDF permettra d'inclure une signature dans le fichier produit. (Cette fonction existe dans PDF depuis longtemps.)
Le RFC contient aussi trois annexes intéressantes. L'annexe A
est un historique de la relation compliquée entre les RFC et
PDF. Depuis longtemps, une version
PostScript du RFC était acceptée par le
RFC Editor et publiée, même si très peu
d'auteurs en ont profité. Cela concernait surtout les RFC ayant
des images ou des formules mathématiques comme les RFC 1119 ou RFC 1142. Le PDF produit
par le RFC Editor pour tous les RFC (ou par
) n'était,
lui, qu'une simple « impression » du RFC en texte brut.https://tools.ietf.org/
L'annexe B rappelle ce que doit faire un bon logiciel de production de contenu imprimé, avec découpage en pages. C'est plus dur que cela n'en a l'air, car il faut gérer les veuves et les orphelines, ne pas couper juste après le titre d'une section, ne pas couper les dessins en art ASCII, placer les tableaux intelligemment, etc.
Enfin, l'annexe C décrit une partie des outils disponibles pour le producteur de documents PDF. Si les logiciels de visualisation sont nombreux, il faut noter que tous n'ont pas la totalité des fonctions qu'utilise le format de sortie des RFC (par exemple les liens hypertexte). Du côté des imprimantes (le papier étant le but final de la plupart des documents PDF), certaines savent même gérer le PDF directement (dans les autres cas, ce sera au logiciel de visualisation de produire le format attendu par l'imprimante, souvent PostScript).
Et pour produire le PDF à partir du XML des RFC ? Une solution possible, puisqu'il existe une feuille de style XSLT (disponible en ligne) est de produire du FO qui sera ensuite transformé en PDF, par exemple avec FOP (je n'ai personnellement eu que des expériences décevantes avec FO). Mais il existe plein de bibliothèques qui produisent du PDF, et qui pourraient être utilisées.
Comme notre RFC impose l'utilisation de profils de PDF comme PDF/A, un outil important est le logiciel de vérification qui s'assure que le résultat est bien conforme aux exigences de ce profil. Pour l'instant, il semble qu'il n'existe pas grand'chose dans ce domaine. Il faudra donc compter sur l'outil de production de PDF pour qu'il fasse un travail correct.
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : P. Hoffman (ICANN), J. Hildebrand (Cisco)
Pour information
Première rédaction de cet article le 16 décembre 2016
Depuis la sortie du RFC 7990, le format canonique des RFC est le format XML. C'est un texte écrit en XML, selon le vocabulaire du RFC 7991 qui sera la version de référence, archivée et faisant autorité, pour tous les RFC. Comme les auteurs enverront souvent un XML imparfait, un outil de préparation sera nécessaire, pour compléter ce XML imparfait et permettre au RFC Editor de travailler sur une base sérieuse. Ce nouveau RFC décrit ce futur outil de préparation.
Ainsi, les outils qui travailleront sur le format canonique des RFC (par exemple les outils qui produiront le PDF, le HTML, etc) pourront compter sur un document complet et n'auront pas à gérer les écarts des auteurs : seul l'outil de préparation devra s'en soucier.
Cet outil de préparation servira aux RFC une fois qu'ils seront soumis au RFC production center (cf. RFC 8728) mais aussi aux Internet-Drafts pendant leur élaboration.
Dans le second cas (section 3 de notre RFC), le futur outil de préparation prendra un Internet-Draft en entrée et produira un document complet (par exemple avec addition des boilerplates).
Et ce sera à peu près la même chose lorsque le RFC sera presque fini. On passera la version finale dans l'outil de préparation, qui résoudra les références externes et ajoutera les éléments obligatoires manquants.
Bon, et en quoi vont consister exactement ces modifications ? Elle sont décrites dans la section 5, qui forme le gros de ce RFC. Contrairement à l'outil actuel idnits qui se contente de vérifier les Internet-Drafts, le nouvel outil va également corriger le texte, ajoutant des éléments, et changeant les valeurs erronées.
C'est ainsi que l'outil de préparation va traiter les éléments
XInclude, les remplaçant par la valeur
incluse. Il va traiter les DTD pour les
supprimer ensuite (donc, remplacer les entités par leur valeur, et
inclure les fichiers inclus par ce mécanisme). Ces deux actions
peuvent aujourd'hui être faites par l'outil
xmllint, avec xmllint --xinclude
--noent --dropdtd NOMDUFICHIER.xml
.
Outre ces mécanismes d'inclusion de XML, l'outil de préparation
va aussi traiter les inclusions spécifiques au vocabulaire du RFC 7991. Ainsi,
<artwork>
a un attribut
src
indiquant la source du graphique, et
l'outil de préparation va donc inclure ce graphique. (Idem avec
<sourcecode>
pour inclure le code source.)
Les instructions XML (PI, Processing Instructions) seront supprimées (ça, je ne sais pas le faire avec xmllint).
L'outil va valider le résultat produit, en utilisant la grammaire Relax NG du RFC 7991. Ça peut aujourd'hui se faire avec xmllint mais aussi avec rnv :
% rnv rfc-v3.rnc rfc-v3-sample.xml rfc-v3-sample.xml
ou bien avec jing :
% java -jar ./jing-20091111/bin/jing.jar -c rfc-v3.rnc rfc-v3-sample.xml
Parmi les nombreuses transformations possibles, citons l'ajout
(s'il n'était pas déjà présent) de l'élément
<seriesInfo>
qui indique s'il s'agit
d'un Internet-Draft ou d'un RFC, l'ajout d'un
élément <date>
s'il manque (sa valeur
étant la date du traitement), changement de l'ancien attribut
title
en name
, le
retrait des
commentaires XML...
Il est fréquent dans les Internet-Drafts de
voir des paragraphes qui ne devront pas être inclus dans le futur
RFC. C'est le cas s'ils contiennent des exemples réels qui
risquent de ne pas être éternels (les RFC peuvent durer longtemps
et ne sont jamais modifiés). C'est également le cas s'il s'agit de
l'état actuel des mises en œuvre d'un RFC, comme décrit dans le
RFC 7942. Dans le système actuel, ces
paragraphes sont marqués par un texte en langue naturelle. Dans le
nouveau vocabulaire du RFC 7991, ce sera
fait avec un attribut removeInRFC
. L'outil de
préparation pourra enlever automatiquement ce paragraphe quand il
préparera un RFC.
L'outil de prépartion devra également arranger le XML. Cela peut se
faire aujourd'hui avec xmllint (ses options
--format
ou bien
--pretty
). Par contre, il n'est pas prévu de
mettre le XML sous sa forme canonique.
Il y aura d'autres opérations faites par l'outil de préparation, voir le RFC pour les détails.
L'outil n'est pas encore développé, un appel d'offres a été lancé et les gagnants ont été les sociétés SeanTek et Elf Tools.
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : N. Brownlee (University of Auckland)
Pour information
Première rédaction de cet article le 16 décembre 2016
Dans la longue liste de RFC décrivant le nouveau format des RFC (commencez par le RFC 7990), ce document décrit l'utilisation de SVG pour faire (enfin) des graphiques dans les RFC.
Traditionnellement, en effet, seul le texte était possible dans
les RFC. (On pouvait toutefois faire des
graphiques en art ASCII, dont on imagine
bien que ce n'était ni très pratique à écrire - malgré l'excellent
mode Emacs picture-mode
,
ni très facile à lire.) Il y avait de bonnes raisons à cet état de
fait, notamment le manque d'un format d'images ouvert et largement
répandu. Je parle bien sûr d'images
vectorielles car, a priori, dans un RFC, il
y aura beaucoup plus de schémas que de photos.
Le processus de décision a été long et compliqué. En 2013, le RFC 6949 notait déjà la décision de permettre des images, en indiquant « Graphics may include ASCII art and a more complex form to be defined, such as SVG line art ». C'est désormais possible. Au fait, c'est quoi, SVG ? Il s'agit d'une norme d'un format d'images vectoriel, gérée par le W3C, et fondée sur XML. Voici un exemple d'un simple dessin en SVG :
<svg xmlns="http://www.w3.org/2000/svg" version="1.2"> <rect x="25" y="25" width="200" height="200" fill="white" stroke-width="4" stroke="black" /> <circle cx="125" cy="125" r="75" fill="black" /> <polyline points="50,150 50,200 200,200 200,100" stroke="black" stroke-width="4" fill="none" /> <line x1="50" y1="50" x2="200" y2="200" stroke="white" stroke-width="4" /> </svg>
Et voici son rendu :
Les RFC n'utiliseront qu'un sous-ensemble de SVG, spécifié ici. Il existe d'autres sous-ensembles de SVG comme SVG Tiny, prévu pour des équipements contraints, genre smartphones. Ce SVG Tiny a servi de base au SVG des RFC, sous-ensemble limité car on n'attend pas de dessins artistiques et compliqués dans les RFC.
SVG RFC est donc SVG Tiny moins les éléments permettant le multimédia et l'animation (pas de vidéos dans les RFC), l'interaction (pas d'interface utilisateur active dans un RFC), l'utilisation de langages de programmation (pas de JavaScript actif dans un RFC). Plusieurs autres restrictions ont été apportées : pas de couleur (RFC 6949, section 3.2), pas d'IRI, seulement des URI, et pas de choix arbitraire de police.
Comment on écrit du SVG ? S'il est évidemment possible de le faire entièrement à la main avec un éditeur ordinaire, gageons que peu de gens le tenteront. Notre RFC cite des éditeurs graphiques, produisant du SVG, comme les logiciels libres Inkscape et Dia. (Et, si on aime programmer en Python, il y a svgwrite, que je présente plus en détail à la fin.) Attention, Inkscape et Dia produisent du SVG généraliste, pas du SVG RFC, qui est plus restreint. (Je ne connais personnellement pas d'outil pour produire du SVG RFC, ou pour « réduire » un fichier SVG généraliste en enlevant tout ce qui n'appartient pas à SVG RFC. Un tel outil était prévu mais je ne sais pas où il en est. C'était une des fonctions attendues du futur svgcheck.)
Et l'accessibilité (section 4) ? Il est crucial que les RFC soient accessibles à tou·te·s, non seulement que que soit le matériel utilisé, mais également quels que soient les handicaps dont souffre leur propriétaire. C'est bien joli de vouloir ajouter des tas de choses dans les RFC mais encore faut-il ne pas creuser ainsi davantage le fossé entre les utilisateurs. Ainsi, accepter de la couleur (le RFC 6949 limite les futurs RFC au noir et blanc) fait courir le risque que les daltoniens ne puissent pas comprendre un RFC. De même, les graphiques, qui ont l'air comme ça d'être une bonne idée, peuvent aggraver la situation des malvoyants. Le texte seul peut toujours être lu à voix haute par un synthétiseur de parole mais pas le graphique. Comme le note le RFC avec humour, « lire le source SVG à voix haute ne va pas le faire ».
Le texte « Tips for Creating Accessible SVG » donne des bons conseils pour faire du SVG accessible. Et il y a bien sûr la norme ARIA, dont il existe une introduction et de bons exemples. (Désolé, je n'ai pas suivi ces excellents principes dans les exemples ci-dessous, mais j'accepte les patches.)
Si vous voulez voir des exemples concrets, regardez https://www.cs.auckland.ac.nz/~nevil/SVG_RFC_1.2/
. Ainsi,
l'exemple de schéma d'un en-tête TCP
donnera :
Et le schéma de la communication SIP du
RFC 4321 fera
L'annexe A de notre RFC donne un schéma complet (formulé en
Relax
NG) du SVG des RFC. Il est extrait ici dans le fichier
svg-rfc.rnc
, que vous pouvez utiliser pour tester
la conformité de vos SVG. Par exemple, avec
rnv :
% rnv files/svg-rfc.rnc files/tcp-header.svg files/tcp-header.svg
En revanche, avec du SVG trop « riche » (ici, utilisant les couleurs), on aurait :
% rnv files/svg-rfc.rnc /tmp/test1.svg ... /tmp/test1.svg:2:267: error: attribute ^fill with invalid value "red" required: value ^token "none" value ^token "black" value ^token "white" value ^token "#000000" value ^token "#FFFFFF" value ^token "#ffffff" value ^token "inherit"
Une alternative, pour tester la validité des SVG conformes à ce profil, sera svgcheck quand il sera développé.
Avec Inkscape, il faut veiller à sauver le
fichier en Plain SVG (autrement, on a des
ennuis avec les éléments spécifiques d'Inkscape,
ex-Sodipodi). Mais il reste malgré cela deux ou trois trucs à
corriger manuellement, avant que le document produit par Inkscape
soit accepté. Pour Dia, il faut utiliser
l'action Export (par défaut, Dia n'enregistre
pas en SVG), mais Dia produit alors un document avec une
DTD. Si on la retire (manuellement, ou bien
avec xmllint --dropdtd
), tout se passe bien,
le document SVG est alors conforme au profil demandé pour les
RFC.
Autre solution que j'aime bien pour faire du SVG, dès qu'on a des éléménts répétitifs et qu'on veut donc automatiser (en Python), svgwrite. Ce schéma en art ASCII :
+--------------+ +----------------+ | Alice |------------------------------------| Bob | | 2001:db8::1 | | 2001:db8::2 | +--------------+ +----------------+
aurait pu être créé avec svgwrite avec network-schema-svgwrite.py
, qui donne
Bien sûr, pour un schéma aussi simple, le gain n'est pas évident, mais il le devient pour les schémas comportant beaucoup d'éléments récurrents. Mais notez que svgwrite ne connait pas le profil « SVG pour RFC » et, par défaut, peut donc produire des SVG invalides (par exemple avec de la couleur). Le programmeur doit donc faire attention.
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC : H. Flanagan (RFC Editor)
Pour information
Première rédaction de cet article le 16 décembre 2016
Le nouveau format des RFC, décrit dans le RFC 7990, prévoit un format canonique, XML, à partir duquel seront automatiquement produits des versions texte brut, PDF, etc. Il y aura évidemment la possibilité de produire une version HTML (RFC 7992) et celle-ci sera bien sûr « stylée » avec CSS. Ce RFC décrit donc le cahier des charges de la feuille de style CSS à développer, avec tous les mots-clés du moment (comme responsive design).
Cette future feuille de style sera le style par défaut (le lecteur pourra toujours la redéfinir). Son but (section 2 du RFC) est de respecter le contenu du RFC (ceux-ci sont parfois des normes : pas question de toucher au texte !) tout en permettant une accessibilité maximale, pour tous les lecteurs, quelle que soit la machine qu'ils utilisent pour accéder au Web.
Plus précisément, la section 3 exige de :
La section 4 donne ensuite les principes de présentation à suivre. Je ne vais pas les reprendre ici dans leur intégralité mais on y trouve :
Il y aura également une feuille de style pour l'impression (comme pour le blog que vous êtes en train de lire, d'ailleurs.) La police par défaut sera cette fois avec empattement.
Enfin, la section 7 et l'annexe A de notre RFC font la liste des classes CSS
employées. Par exemple, .pilcrow
sera utilisé
pour les marques de paragraphe, qui ne seront affichées que
lorsque le pointeur passera dessus. .url
servira à marquer les URL de manière
visuellement distinctive. La classe .cref
ne
servira que dans les
Internet-Drafts, pour
afficher les commentaires, mais pas dans les RFC (où les
commentaires des auteurs sont supprimés).
La merveilleuse feuille de style qui met en œuvre ces exigences n'est pas encore finie. Un appel d'offres a eu lieu (après relecture). Et on peut voir la feuille temporaire en ligne (pour le développement et les commentaires, c'est sur Github).
Date de publication du RFC : Décembre 2016
Auteur(s) du RFC :
H. Flanagan (RFC Editor)
Pour information
Première rédaction de cet article le 16 décembre 2016
Dans la grande série des nombreux RFC spécifiant le nouveau format de ces documents (avec XML étant désormais la référence), ce court RFC décrit le format de publication « texte brut » des RFC.
En effet, si le format « texte brut » n'est plus la référence des RFC, ce format reste toujours utile. Dans le nouveau mécanisme (RFC 7990), il y a désormais plusieurs formats de publication, obtenus à partir du format canonique (celui qui est en XML). Le texte brut est l'un d'eux. Ce format, historiquement le seul utilisé par les RFC, ne disparait pas, mais perd de son importance. Il n'est plus qu'un des formats de publication parmi d'autres (comme HTML, voir le RFC 7992). Le RFC 6949 expliquait ce choix.
À noter que les RFC produits avant ce changement ne sont pas affectés : leur format de référence reste le texte brut (et en ASCII seul).
Bon, désormais, on aura un format de sortie (parmi d'autres) en « texte seul » ou « texte brut ». Mais c'est quoi, le texte brut ? Notre RFC reprend la définition du consortium Unicode : « du texte encodé pour les ordinateurs composé uniquement de points de code d'une norme donnée, sans instructions de format ou de structure ». Bref, les caractères indiqués ne valent que pour eux-mêmes, ils n'indiquent jamais de formatage ou de style. Selon cette définition, HTML, LaTeX et Markdown (RFC 7763) ne sont donc pas du texte brut. (La définition n'est pas 100 % parfaite. La norme Unicode, par exemple, inclut des caractères qui influencent le format.) Le texte brut est donc ce qui est le plus portable : tous les acteurs qui connaissent la norme de jeu de caractères sous-jacente (aujourd'hui, quasiment toujours Unicode) peuvent lire et écrire du texte brut. C'est d'ailleurs une des raisons pour lesquelles les RFC ont si longtemps gardé ce format comme format canonique.
Mais si le texte brut n'est pas idéal comme format de référence, il reste un format de sortie très utile, notamment pour son interopérabilité, ou en raison de l'existence de nombreux outils qui peuvent le traiter (à commencer par grep...) Désormais, donc, le format canonique est le XML décrit dans le RFC 7991 et le texte brut sera produit automatiquement par les nouveaux outils. Mais ce texte brut a des règles qui sont légèrement différentes du texte brut original (« RFC canal historique ») et notre RFC 7994 les décrit. Il est très court, car le format « texte brut » est un format simple.
D'abord, le jeu de caractères (section 2). Ce sera
bien sûr Unicode, mais avec les
restrictions indiquées dans le RFC 7997. En pratique, là où les caractères non-ASCII ne
sont pas autorisés, il faudra utiliser l'ASCII équivalent, donné
dans les attributs XML prévus à cet effet
(ascii
, RFC 7991 en section 2.23.1,
asciiFullname
en 2.7.1, etc). L'encodage sera obligatoirement
UTF-8 (RFC 3629). Curieusement, il est prévu de mettre
une BOM au début du document.
Que faire avec les graphiques, désormais autorisés par le RFC 7990, et écrits en
SVG (RFC 7996) ? Ces graphiques sont, dans le source XML, à
l'intérieur d'un élément
<artwork>
. Comment les rendre dans du
texte brut (section 3 de notre RFC) ? D'abord, si le graphique
n'est pas en SVG mais dans le traditionnel art
ASCII (indiqué par
type=ascii-art
), on utilise cet art ASCII.
Autrement, notre RFC ne propose pas de solution générale. Il est
recommandé aux auteurs de diagrammes et schémas de prévoir une
alternative en art ASCII, même quand ils font du SVG.
Enfin, la section 4 du RFC couvre le problème de la « mise en page ». Un caractère de fin de page (U+000C) sera inclus automatiquement toutes les 58 lignes (les outils auront probablement une option pour ne pas inclure de telles marques). L'outil devra gérer le délicat problème des veuves et des orphelines. Les lignes feront 72 caractères, suivies de deux caractères marquant la fin (U+000D U+000A).
Les textes de début du RFC (RFC 5741) seront automatiquement mis comme avant, mais les en-têtes et pieds de page disparaissent. Autre disparition, il n'y aura plus, dans le format de sortie en texte brut, de numéros de pages dans la table des matières (dommage, je trouve, mais c'est au nom de la cohérence avec les autres formats de sortie).
Première rédaction de cet article le 7 décembre 2016
Qu'est-ce que ça peut bien être, « BCP 38 » ? Ce terme désigne un ensemble de documents de bonnes pratiques pour les acteurs de l'Internet, plus spécialement les opérateurs réseaux : il ne faut pas laisser sortir de son réseau des paquets ayant une adresse source usurpée. Le respect de ce principe permettrait de lutter contre certaines attaques par déni de service sur l'Internet. Ce principe est formalisé dans deux RFC, les RFC 2827 et RFC 3704.
« BCP » veut dire « Best Current Practice ». Le but de cet étiquetage est de pointer vers le ou les RFC qui décrivent la pratique en question. En effet, un RFC, une fois publié, n'est jamais modifié, alors que le monde, lui, change. C'est ainsi que le RFC 7525, parlant de TLS est décrit par l'étiquette BCP 195 : les bonnes pratiques, en matière de cryptographie, changent vite. Une étiquette BCP peut pointer plusieurs RFC. Un bon exemple est le BCP 47, sur les étiquettes de langue, qui pointe vers les RFC 5646 et RFC 4647.
Le problème que vise à résoudre ce BCP est celui de l'usurpation d'adresse IP par un
attaquant qui voudrait faire du déni de
service sans révéler son adresse, ou bien en faisant une
attaque par réflexion. Par défaut, dans
l'Internet, il est trivial d'émettre des datagrammes avec une
adresse source mensongère. BCP 38 dit que les opérateurs réseaux
devraient interdire cette pratique, en configurant leurs routeurs à
cette fin. Par exemple, si un FAI a deux
préfixes IP, 192.0.2.0/24
et
2001:db8::/32
, il n'y a aucune raison valable
de laisser sortir du réseau du FAI des paquets ayant comme adresse IP
source, mettons, 203.0.113.65
.
Notons qu'un déploiement systématique de BCP 38 résoudrait un certain nombre de problèmes de sécurité sur l'Internet, mais pas tous. Ainsi, si l'attaquant dispose d'un botnet, et fait une attaque directe (pas par réflexion), il n'a pas vraiment besoin de mentir sur ses adresses IP source, ce ne sont pas les siennes, de toute façon (usurper l'adresse source aurait quand même quelques avantages, ça dépend des cas).
Aujourd'hui, le déploiement de BCP 38 dans l'Internet n'est pas inexistant mais il est très inégal. Par exemple, la situation est bien meilleure en Europe qu'en Asie. Un attaquant qui veut faire de l'usurpation d'adresses IP a donc encore pas mal de réseaux à sa disposition.
Pourquoi est-ce que tout le monde n'a pas déployé BCP 38, malgré le très large consensus qui existe parmi les professionnels ? La principale raison est économique. Un opérateur qui déploie BCP 38 (tous les routeurs permettent de le faire, soit en n'autorisant que ses propres préfixes, soit par des astuces comme RPF) aide les autres. Imaginez l'ingénieur allant voir le directeur financier et lui disant « on va dépenser de l'argent, et le ROI ira entièrement à nos concurrents »... Comme en écologie, c'est donc un cas typique où le sacro-saint marché ne peut pas aboutir à une bonne solution.
Notez que tester si un FAI donné met en œuvre ou pas BCP 38 est
un peu plus compliqué que cela peut sembler au premier abord. Je
connais par exemple une
box très utilisée en
France qui bloque les paquets IPv4 ayant
une adresse IP source usurpée (par effet de bord du
NAT) mais qui ne le fait que pour des
flots existants ou pour des paquets de
début d'un flot. Si on envoie un paquet TCP
sans bit SYN
, il passe malgré son adresse usurpée...
Quelques lectures pour approfondir :
Auteur(s) du livre : Andreas Antonopoulos
Éditeur : Merkle Bloom
9781537000459
Publié en 2016
Première rédaction de cet article le 5 décembre 2016
Ce petit livre rassemble le texte de plusieurs conférences d'Andreas Antonopoulos au sujet de Bitcoin. Les textes ont été édités, les erreurs corrigées, mais le ton reste celui des conférences de l'auteur, passionnantes et brillantes. Sa thèse principale est que le Bitcoin n'est pas juste une monnaie, c'est un mécanisme sur lequel on va pouvoir bâtir plein de nouvelles relations économiques, c'est l'Internet of money. Et les vieux dinosaures du monde actuel peuvent toujours critiquer, et prétendre que le Bitcoin n'a pas d'avenir, Antonopoulos démonte tous leurs arguments. (Les conférences elles-mêmes sont visibles en ligne.)
C'est donc vraiment le bouquin à faire lire aux gens qui expliquent doctement que le Bitcoin n'est pas une monnaie réelle, ou bien que ce n'est qu'une expérience d'une poignée de gusses dans leur garage. Antonopoulos est très pédagogue... et très militant.
Il n'a pas de mal à rappeler que les arguments contre le Bitcoin sont à peu près les mêmes que ceux employés par les messieurs sérieux et les experts médiatiques contre l'Internet (ou, puis-je ajouter, contre Unix et contre le logiciel libre) : c'est juste une expérience, ce n'est pas sérieux, c'est un truc de hippies libertariens, cela ne durera pas. Pourquoi croirait-on aujourd'hui ces mêmes experts ? D'où le titre du livre, qui fait allusion au fait que l'auteur prédit au Bitcoin le même succès que l'Internet : déranger les systèmes en place, permettre de nouvelles possibilités, reposer les questions. « Dire que le Bitcoin est une monnaie numérique, c'est aussi réducteur que dire que l'Internet est un téléphone amélioré. »
Un concept intéressant dans une des conférences est celui d'inversion de l'infrastructure. Au début, la nouvelle technologie utilise une infrastructure conçue pour la technologie précédente, et a donc bien du mal. Les premières voitures roulaient sur des routes prévues pour les chevaux. Ceux-ci ont quatre pattes et un bon équilibre, les trous ne les dérangeaient donc pas trop, alors qu'ils étaient redoutables pour les voitures. Petit à petit, les choses ont changé, l'infrastructure s'est inversée, et ce sont aujourd'hui les chevaux qui marchent sur une route goudronnée conçue pour les voitures. De même, l'Internet à ses débuts devait emprunter une infrastructure conçue pour le téléphone (et on avait besoin de modems, pour faire passer IP pour de la voix) alors qu'aujourd'hui, l'infrastructure s'est inversée, c'est la voix qui n'est plus qu'une des nombreuses applications qui utilisent l'infrastructure de l'Internet.
De la même façon, estime Antonopoulos, les services bancaires traditionnels continueront à exister, mais seront simplement des applications au-dessus de Bitcoin.
L'auteur est bien conscient que les adversaires du Bitcoin ne vont pas se contenter de le ridiculiser ou de le critiquer. Ils vont activement tenter de l'interdire. Il est très optimiste sur les chances du Bitcoin de résister à cette censure (dans le pire des cas, les transactions seront encodées en smileys dans les discussions des articles Wikipédia et ne pourront donc pas être stoppées...) Après tout, Bitcoin a déjà été testé au feu, d'innombrables attaques ont déjà visé cette monnaie, et le Bitcoin a toujours survécu. (Voir à ce sujet l'hilarant site « Bitcoin Obituaries » et l'amusante vidéo « Not this time ».)
Antonopoulos insiste sur le caractère « sans permission » du Bitcoin. Il n'y a pas de Président du Bitcoin, chacun avec une idée peut la mettre en œuvre sur la chaîne de blocs tout de suite, sans demander de permission. En tant que « programmable money », Bitcoin n'a pas seulement un usage (payer) mais tous les usages qu'on peut imaginer. (Le Bitcoin est neutre, au sens de « neutralité du réseau ».)
Antonopoulos fait remarquer que toutes les innovations ont été la cible d'innombrables critiques à leur début. (Il oublie de dire que certaines critiques étaient justifiées. Par exemple, il cite des déclarations anti-voiture des débuts de l'automobile, pointant les dangers mortels de cette technologie, dangers qui existent toujours.) Ces critiques semblent bien ridicules avec le recul, comme celles contre le Bitcoin sonneront moyenâgeuses dans le futur. Antonopoulos remarque avec justesse que ces critiques portaient souvent sur des points de détail, qui allaient évoluer avec le temps. Ainsi, les premières critiques des automobiles portaient sur la difficulté à les faire démarrer, problème réel mais qui a été vite résolu avec l'invention du démarreur. (Personnellement, je me souviens bien des premières démonstrations de l'Internet que je faisais au début des années 1990, où la plupart des remarques des gens portaient sur le caractère « peu convivial » des logiciels utilisés. Peu de gens étaient capables de voir l'intérêt de cette technologie, au-delà de problèmes ergonomiques temporaires.)
Dans une autre conférence, Antonopoulos revient sur la monnaie : de quand date t-elle ? Et, d'ailleurs, qu'est-ce qu'on appelle « monnaie » ? (Beaucoup de messieurs experts refusent de considérer le Bitcoin comme une monnaie car ils donnent de la monnaie une définition arbitraire et anti-historique du genre « la monnaie est le moyen de paiement décidé par un État, et régulé ».)
L'auteur insiste aussi sur l'importance pour les acteurs du monde Bitcoin de ne pas copier bêtement le vocabulaire du passé. Ainsi, il s'énerve (à juste titre) contre les articles mentionnant le Bitcoin et qui sont illustrés par... des pièces de monnaie. Il reconnait que c'est d'ailleurs en partie la faute du terme « bitcoin » qui est trompeur. De même, le terme de « portefeuille », souvent utilisé pour les logiciels de gestion de ses bitcoins, est erroné : on ne peut pas copier un portefeuille traditionnel, alors qu'il n'y a aucun problème à le faire avec un portefeuille Bitcoin (il ne stocke pas d'argent, mais des clés).
Autre exemple de l'erreur qu'il y a à copier aveuglément les anciennes techniques, les places de marché Bitcoin. Ces places n'ont rien de Bitcoin, ce sont des établissements financiers traditionnels et, notamment, leur modèle de sécurité n'est pas du tout celui de Bitcoin.
Compte-tenu de la marée médiatique anti-Bitcoin (et anti-cryptomonnaies en général), on a bien besoin d'un livre comme celui-ci, qui redresse la barre. Par contre, il ne faut pas y chercher une analyse balancée. On ne voit aucune critique sur les aspects problématiques du Bitcoin. Il faudra un autre livre pour cela. Un volontaire pour écrire une critique sérieuse du Bitcoin ? (Qui ne se limite pas à des points de détail spectaculaires comme l'identité de Nakamoto, ou à du simple conservatisme du genre « les banques n'en veulent pas » ?) En attendant, lisez le livre, et écoutez les conférences d'Andreas Antonopoulos, vous ne le regretterez pas.
Date de publication du RFC : Novembre 2016
Auteur(s) du RFC : W. Hardaker
(USC/ISI), O. Gudmundsson
(CloudFlare), S. Krishnaswamy
(Parsons)
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 4 décembre 2016
Normalement, en 2016, tous les résolveurs DNS sérieux devraient valider avec DNSSEC. Mais ce n'est pas le cas. Il y a plusieurs raisons à cela, mais ce nouveau RFC se focalise sur un problème précis : le cas d'un résolveur connecté via un réseau pourri, non-neutre, et qui se permet d'interférer avec le transport des paquets IP, menant le résolveur à de sérieuses difficultés. Comment détecter ces réseaux pourris ? Et que faire pour valider quand même ?
Si le résolveur est une grosse machine dans un centre de données, connectée directement à des opérateurs neutres, il n'y a pas trop de problème. C'est le cas des résolveurs des FAI, par exemple. Mais la situation est bien moins favorable à M. Michu. Si celui-ci veut, à juste titre, avoir son propre résolveur DNS sur sa machine, il dépend des réseaux où on laisse M. Michu se connecter, et ceux-ci sont rarement neutres. (Le RFC couvre le cas où ce résolveur local fait suivre - forwarde - les requêtes à un autre résolveur, et celui où il parle directement aux serveurs faisant autorité.)
La section 1.2 du RFC décrit les cas où la validation DNSSEC va être difficile ou impossible :
Bien des outils ont été développés pour contourner ces problèmes, comme dnssec-trigger.
Pour faire des tests des résolveurs et de tous les équipements
intermédiaires qui peuvent poser des problèmes de validation
DNSSEC dans certains cas, le RFC parle d'une zone de test nommée
test.example.com
. Elle n'existe pas en vrai
mais, aujourd'hui, la zone
test.dnssec-tools.org
fait la même chose
(elle est par exemple utilisée pour les travaux pratiques lors de
la formation DNSSEC chez HSC). Cette zone
est délibérement peuplée avec des noms mal signés. Ainsi, le nom
badsign-aaaa.test.dnssec-tools.org
a un
enregistrement AAAA dont la signature a été modifiée, la rendant
invalide. Testons (pour tous les tests, comme le but était de voir
le comportement DNSSEC, j'ai utilisé un fichier de configuration
~/.digrc
contenant +dnssec
+multiline
, merci à Landry Minoza de l'avoir remarqué) :
% dig AAAA badsign-aaaa.test.dnssec-tools.org ; <<>> DiG 9.9.5-9+deb8u8-Debian <<>> AAAA badsign-aaaa.test.dnssec-tools.org ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 60910 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;badsign-aaaa.test.dnssec-tools.org. IN AAAA ;; Query time: 3759 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sun Dec 04 17:12:28 CET 2016 ;; MSG SIZE rcvd: 63 % dig +cd AAAA badsign-aaaa.test.dnssec-tools.org ; <<>> DiG 9.9.5-9+deb8u8-Debian <<>> +cd AAAA badsign-aaaa.test.dnssec-tools.org ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29404 ;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 5 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;badsign-aaaa.test.dnssec-tools.org. IN AAAA ;; ANSWER SECTION: badsign-aaaa.test.dnssec-tools.org. 86400 IN AAAA 2001:470:1f00:ffff::1 badsign-aaaa.test.dnssec-tools.org. 86400 IN RRSIG AAAA 5 4 86400 ( 20170101064820 20161202054820 19442 test.dnssec-tools.org. nZ8bPLBleW/sW6x135+Iz4IhO6Lr04V8C9fC1bMVfCVY 3rKqbOoBk1i+wnnGDCTWQ5iCicWTKLIpbDmCSW9C33pj P2j7C/ensspbdwpD/7Ia8zN+XUSN+ThLU6lgYGKFuoVL QmIG/vr1lOn6xdjXY2E4mStAjaGuertvKKDYy/I= ) ;; AUTHORITY SECTION: test.dnssec-tools.org. 280 IN NS dns1.test.dnssec-tools.org. test.dnssec-tools.org. 280 IN NS dns2.test.dnssec-tools.org. test.dnssec-tools.org. 280 IN RRSIG NS 5 3 86400 ( 20170101064820 20161202054820 19442 test.dnssec-tools.org. AK95JOAuvfZ1ZwEsrKiR8DP1zluoBvBkXHRXa78rrK5U UuZdLnZwnYlnNplrZZOrQNuUaPyb4zI0TGfw/+aa/ZTU qyx8uQODSHuBTPQTlcmCFAfTIyd1Q+tSTEs2TuGUhjKe H9Hk+w6yOjI/o52c2OcTMTJ4Jmt2GlIssrrDlxY= ) ;; ADDITIONAL SECTION: dns1.test.dnssec-tools.org. 280 IN A 168.150.236.43 dns2.test.dnssec-tools.org. 280 IN A 75.101.48.145 dns1.test.dnssec-tools.org. 86400 IN RRSIG A 5 4 86400 ( 20170101064820 20161202054820 19442 test.dnssec-tools.org. zoa0V/Hwa4QM0spG6RlhGM6hK3rQVALpDve1rtF6NvUS Sb6/HBzQOP6YXTFQMzPEFUza8/tchYp5eQaPBf2AqsBl i4TqSjkIEklHohUmdhK7xcfFjHILUMcT/5AXkEStJg7I 6AqZE1ibcOh7Mfmt/2f0vj2opIkz6uK740W7qjg= ) dns2.test.dnssec-tools.org. 86400 IN RRSIG A 5 4 86400 ( 20170101064820 20161202054820 19442 test.dnssec-tools.org. hGq7iAtbHrtjCYJGMPQ3fxijhu4Izk8Ly+xZOa0Ag24R lqpFgdd2amDstFVLTRs3x15UqQIO+hmFdlbSOterDkbg /o2/FhtZOJr7c75Pu3EWi/DDbT9pULk4Uwjlie1QBopv LLZ94SlqKO7eQ02NRyy5EL4gD2G5rSffsUqEkj8= ) ;; Query time: 206 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sun Dec 04 17:12:44 CET 2016 ;; MSG SIZE rcvd: 885
Le second test, celui fait avec le bit CD (Checking Disabled), montre que le problème vient bien de DNSSEC. Autre test, avec une signature expirée :
% dig A pastdate-a.test.dnssec-tools.org ... ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 46319 ... % dig +cd A pastdate-a.test.dnssec-tools.org ... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49547 ;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 5 ... ;; ANSWER SECTION: pastdate-a.test.dnssec-tools.org. 86400 IN A 64.90.35.104 pastdate-a.test.dnssec-tools.org. 86400 IN RRSIG A 5 4 86400 ( 20161201224321 20161101234821 19442 test.dnssec-tools.org. lIL0zcEZpG/4uG5hImvpivH1C/D3PFI3RNYHlPbZ [...]
La liste de tous les noms à tester est en ligne.
Le but de ce RFC est de lister tous les tests que peut et devrait faire un validateur local, pour arriver à valider malgré des résolveurs amont, ou bien un réseau, hostile. Ces stratégies sont mises en œuvre, par exemple, dans dnssec-trigger.
En détectant la non-conformité (compliance, un terme à la mode dans les organisations), le validateur situé sur la machine terminale, ou bien dans le réseau local, peut alors adopter la meilleure stratégie de contournement (ou, dans le pire des cas, prévenir loyalement l'utilisateur qu'on ne pourra pas faire de validation DNSSEC). Les tests doivent être faits au début d'une nouvelle connexion réseau, ou bien lorsque celle-ci change.
La section 3 du RFC est consacrée à ces tests de
non-conformité. Je ne vais pas décrire la totalité de ces tests,
un sous-ensemble suffira. Ainsi, le premier test, le plus trivial,
est que la machine puisse parler en UDP à son résolveur attitré (celui
typiquement reçu en DHCP). On lui demande
good-a.test.dnssec-tools.org
et on doit avoir
une réponse sous forme d'une adresse IP (comme son nom l'indique, ce nom est correctement
signé). Si un test aussi trivial ne marche pas, ce n'est sans
doute pas la peine d'aller plus loin. Un peu plus subtil, on teste
le même résolveur en TCP.
Après, on passe à EDNS (RFC 6891), qui est indispensable pour DNSSEC. Une requête pour ce même nom, mais avec une option EDNS, doit passer. Si EDNS ne marche pas, on peut arrêter, DNSSEC ne marchera pas non plus. Mais s'il marche ? On teste alors avec le bit DO (DNSSEC OK) qui indique au serveur qu'il doit envoyer les données DNSSEC, notamment les signatures. La réponse doit inclure ce même bit DO. (C'est plus tard qu'on teste qu'on a bien reçu des signatures. Rappelez-vous que la plupart des middleboxes sont horriblement boguées. Certaines acceptent le bit DO et le renvoient, sans pour autant transmettre les signatures.)
On teste alors des zones qu'on sait signées et on regarde si le
résolveur met le bit AD (Authentic Data), au
moins pour les algoritmes RSA
+ SHA-1 et RSA +
SHA-256. Si cela ne marche pas, ce n'est
pas forcément une erreur fatale, puisque, de toute façon, on
voulait faire la validation nous-même. Il faut aussi penser à
faire le test inverse : un résolveur validant doit mettre le bit
AD pour une réponse signée correctement, et doit répondre avec le
code de retour SERVFAIL (Server Failure) si la
réponse devrait être signée mais ne l'est pas, ou bien l'est
mal. Cela se fait en testant badsign-a.test.dnssec-tools.org
.
Dans les enregistrements DNSSEC, il n'y a pas que les
signatures (RRSIG), il y a aussi les enregistrements servant à
prouver la non-existence, NSEC et NSEC3. Il faut donc également
tester qu'ils sont reçus car, en pratique, on voit en effet des
middleboxes qui laissent passer les RRSIG mais
bloquent stupidement les NSEC et les NSEC3. On demande donc
non-existent.test.dnsssec-tools.org
, et on
doit récupérer non seulement une réponse avec le code NXDOMAIN
(No Such Domain) mais également les NSEC ou
NSEC3 permettant de valider cette réponse :
% dig AAAA non-existent.test.dnsssec-tools.org [...] ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 40218 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1 [...] ;; AUTHORITY SECTION: h9p7u7tr2u91d0v0ljs9l1gidnp90u3h.org. 900 IN NSEC3 1 1 1 D399EAAB ( H9PARR669T6U8O1GSG9E1LMITK4DEM0T NS SOA RRSIG DNSKEY NSEC3PARAM ) iruevfos0vs8jssfj22me5p458p0qj1e.org. 900 IN RRSIG NSEC3 7 2 86400 ( 20161222153046 20161201143046 3947 org. kgCZC/gE4ySP7eZUb1+2ORYRhTrvL5YBIHLCBK5F8pqK MXGJXJ/hX+8LLrg4jHJaER2AelUgUGywRn4uY80ajYpg eTuSGzRX1aVCKAR8UB80bX/YLUPUPKWOdfgxTekD4nZk eoi/9JNmIMZRc0cmMGp8LSVMqX98F2bVJnZro8U= ) iruevfos0vs8jssfj22me5p458p0qj1e.org. 900 IN NSEC3 1 1 1 D399EAAB ( IRVVBMC65HCBCFQNQS8NQFTAB943LCFU NS DS RRSIG ) vaittv1g2ies9s3920soaumh73klnhs5.org. 900 IN RRSIG NSEC3 7 2 86400 ( 20161222153046 20161201143046 3947 org. Nj/zvU0GB8vQ7bFfpSSWW+inE7RiOFjOpNc1K/TMnQqG QsKTLD9gBM8vgh3K1WdPXOCzthf/isDJAy2xLA/oRFFq KZ+Coo+33FManVmuyndGJ5bdgQqnpa0xGP7yOgjTfUsh Ff9HkX0mkzqYtWYzw0J7WnMPcOjmrlg26WsfwlU= ) vaittv1g2ies9s3920soaumh73klnhs5.org. 900 IN NSEC3 1 1 1 D399EAAB ( VAJB898DELVT5UJ4I9D1BRD2FRTBSCM1 NS DS RRSIG )
Certains serveurs DNS (ou, plus exactement, certains ensembles serveur+réseau+middlebox) n'acceptent que certains types d'enregistrement DNS (les plus connus, comme A, AAAA, MX, parfois SRV, etc). Il faut donc tester que le serveur accepte bien tous les types d'enregistrement,
Jusqu'à présent, on n'a testé que le résolveur « normal ». Même s'il ne valide pas, tant qu'il transmet fidèlement toutes les données DNS, on pourra au moins l'utiliser comme relais et cache. Par contre, dans certains cas, si on veut valider avec DNSSEC, il faudra complètement le court-circuiter. Ainsi, s'il ne transmet pas les signatures, on n'a pas d'autre choix que d'aller les demander à un autre résolveur, ou bien directement aux serveurs faisant autorité. Il faut donc tester qu'on puisse interroger ces serveurs, avec UDP et avec TCP. (Ce n'est pas toujours possible, certains réseaux violent tellement la neutralité de l'Internet qu'ils bloquent le port 53, celui du DNS.)
Avec DNSSEC, les réponses sont souvent de grande taille, et parfois fragmentées. Il faut donc tester que les fragments passent (ils sont souvent bloqués par des administrateurs réseau incompétents).
Une fois ces tests faits, il reste à synthétiser les résultats (section 4). L'idée est de pouvoir dire si le résolveur « normal » est :
En pratique, tous les résolveurs (ou plutôt l'ensemble du résolveur et du réseau situé devant, avec ses middleboxes qui cassent tout) ne rentrent pas parfaitement dans une de ces trois catégories. Ainsi, certains vont bloquer les fragments mais accepter TCP (ce qui permettra de quand même faire passer les données de grande taille), tandis que d'autres n'auront pas TCP mais qu'UDP fonctionnera bien, même en cas de fragmentation.
Une fois ces données collectées, et le résolveur correctement classé, on pourra alors déterminer comment contourner les éventuels problèmes (section 5 du RFC). Par exemple :
tcp80:
185.49.140.67
ou ssl443: 185.49.140.67
...
).La section 6 du RFC sert de voiture-balai, en mentionnant les
cas spéciaux qui peuvent être embêtants. Par exemple, DNSSEC
dépend de l'horloge, puisqu'il faut vérifier que les signatures
n'ont pas expiré. Mais la synchronisation de l'horloge dépend de
NTP donc parfois du
DNS si on a mis des noms de domaine dans son
ntp.conf
. Si la machine a une horloge assez
stable pour garder l'heure entre un arrêt et un démarrage, ce
n'est pas trop grave. Mais si la machine est un engin bon marché
avec une horloge qui dévie beaucoup (genre le Raspberry
Pi), que faire ?
Autre problème, les affreux portails captifs. Tant qu'on n'a pas cliqué sur « j'accepte cinquante pages de conditions d'utilisation que je n'ai pas lues, je veux recevoir du spam, et je promets de ne pas partager de la culture », on n'a pas un vrai accès Internet et le port 53 est sans doute bloqué. Il faudrait donc refaire les tests après le passage par le portail captif.
Face à ce genre de problèmes, une première solution est de ne pas tenter de faire du DNSSEC tant qu'on n'a pas synchronisé l'horloge, passé le portail captif (c'est ce que fait dnssec-trigger), au détriment de la sécurité. Au moins, on peut prévenir l'utilisateur et lui proposer de réessayer plus tard.
Date de publication du RFC : Novembre 2016
Auteur(s) du RFC : R. Danyliw (CERT)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF mile
Première rédaction de cet article le 1 décembre 2016
Pour rendre plus facilement analysables les innombrables rapports d'incidents de sécurité qui circulent sur Internet tous les jours, ce RFC spécifie un format standard XML, nommé IODEF, pour décrire ces incidents. Ici, il s'agit de la version 2 de ce format IODEF, la version 1 était dans le RFC 5070.
Tous les jours, des organisations comme les CERT et CSIRT, mais aussi les OIV, envoient et reçoivent des rapports détaillés concernant une attaque sur un réseau informatique ou un serveur. Ces rapports sont longs et détaillés mais, la plupart du temps, ce n'est pas une attaque isolée qui est intéressante, c'est l'image qui apparait lorsqu'on synthétise tous les rapports, et qu'on voit alors les tendances, par exemple l'arrivée d'un nouveau ver ou bien une attaque concertée contre un pays donné. D'où l'importance de pouvoir analyser automatiquement ces rapports, ce qui impose un modèle de données et un format standard, ce que fournit ce RFC.
Le modèle de données est proche des modèles
objet, par
exemple dans la descriptions des classes d'objets
manipulés (comme la classe Incident en section 3.2, avec la
cardinalité des attributs). Ces classes sont
composés avec des données élémentaires (booléens, entiers, dates)
décrites dans la section 2. Par exemple, parmi les attributs de la
classe Incident
, on trouve l'heure de début et de
fin de l'incident, l'heure de détection, etc. Le schéma XML complet, écrit en W3C Schema,
figure dans la section 8.
On trouve énormément de choses dans ce schéma (le RFC fait plus de
160 pages), pour traiter tous les cas prévus. Par exemple, on peut
exprimer une liste de ports comprenant à la fois des ports
individuels et des intervalles :
22,53,80,1024-2047
. De nombreuses classes
existent pour utiliser ces informations élémentaires. Ainsi, la classe
Discovery
, une nouveauté de la version 2, permet
d'indiquer comment l'incident a été découvert (avec un attribut
source
qui a vingt valeurs possibles, comme
av
- antivirus,
os-log
- journal,
passive-dns
- un système comme DNSdb, etc). Et
BusinessImpact
permet de décrire les conséquences
de l'incident sur l'activité (breach-privacy
,
loss-of-service
,
theft-financial
, etc). Ça peut même se quantifier
financièrement avec la classe MonetaryImpact
. Si
on met les incidents de sécurité dans une base de données (ça
s'appelle un SIEM, comme Prelude), on peut donc imaginer de regarder
d'abord les incidents qui ont coûté le plus cher...
Voici un exemple d'un rapport d'incident, tiré du RFC (section 7), et qui
décrit et qui décrit les systèmes de C&C
(quatre serveurs)
d'une campagne donnée (dans le RFC 5070,
l'exemple était une simple reconnaissance avec
nmap...). Cet exemple a l'avantage d'illustrer
la classe IndicatorData
, une nouveauté de la
version 2 :
<?xml version="1.0" encoding="UTF-8"?> <!-- A list of C2 domains associated with a campaign --> <IODEF-Document version="2.00" xml:lang="en" xmlns="urn:ietf:params:xml:ns:iodef-2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "https://www.iana.org/assignments/xml-registry/schema/ iodef-2.0.xsd"> <Incident purpose="watch" restriction="green"> <IncidentID name="csirt.example.com">897923</IncidentID> <RelatedActivity> <ThreatActor> <ThreatActorID> TA-12-AGGRESSIVE-BUTTERFLY </ThreatActorID> <Description>Aggressive Butterfly</Description> </ThreatActor> <Campaign> <CampaignID>C-2015-59405</CampaignID> <Description>Orange Giraffe</Description> </Campaign> </RelatedActivity> <GenerationTime>2015-10-02T11:18:00-05:00</GenerationTime> <Description>Summarizes the Indicators of Compromise for the Orange Giraffe campaign of the Aggressive Butterfly crime gang. </Description> <Assessment> <BusinessImpact type="breach-proprietary"/> </Assessment> <Contact type="organization" role="creator"> <ContactName>CSIRT for example.com</ContactName> <Email> <EmailTo>contact@csirt.example.com</EmailTo> </Email> </Contact> <IndicatorData> <Indicator> <IndicatorID name="csirt.example.com" version="1"> G90823490 </IndicatorID> <Description>C2 domains</Description> <StartTime>2014-12-02T11:18:00-05:00</StartTime> <Observable> <BulkObservable type="fqdn"> <BulkObservableList> kj290023j09r34.example.com 09ijk23jfj0k8.example.net klknjwfjiowjefr923.example.org oimireik79msd.example.org </BulkObservableList> </BulkObservable> </Observable> </Indicator> </IndicatorData> </Incident> </IODEF-Document>
Le RFC note sagement que le partage d'informations n'est pas uniquement une question technique, mais qu'elle dépend aussi des procédures bureaucratiques de chaque organisation, des contraintes légales, de la confiance (ou de l'absence de confiance, souvent justifiée) et enfin de la simple bonne ou mauvaise volonté. (Mon opinion personnelle est que, en France, le partage d'informations précises sur les incidents de sécurité est très insuffisant.)
Les changements depuis la version 1 (celle du RFC 5070) sont listés dans la section 1.4. Beaucoup de détails, beaucoup d'ajouts, parmi lesquels je note :
Contact
permette désormais d'indiquer une
adresse postale en un jeu de caractères quelconque,IndicatorData
ou
Discovery
cités
plus haut, ou comme DomainData
, pour des
informations sur un nom de domaine), et nouveaux attributs dans les classes
existantes (par exemple, Incident
y gagne
observable-id
, un identificateur qui peut être
utilisé dans des références croisées).
Si l'ajout de nouvelles classes ne rendent pas les anciennes
descriptions IODEF incorrectes, en revanche, certains changements cassent la compatibilité et un fichier
IODEF version 1 parfait ne sera pas forcément légal pour la version
2 (cf. section 4.4). Par exemple, la sous-classe
NodeRole
(qui permet de décrire si on est attaqué
par
une caméra de vidéosurveillance
ou bien par un routeur) a changé
de classe parente.
Et les mises en œuvre d'IODEF ? Un résumé de l'état de ces mises
en œuvre figure dans
l'Internet-Draft
draft-ietf-mile-implementreport
,
et qui référence une liste des programmes
IODEF (j'ai aussi trouvé celle-ci). Parmi d'autres, on peut noter la bibliothèque de
Prelude (et qui a une version pour l'IODEF v2 de
notre RFC), un
module Perl, un autre en
PHP, et un troisième
en Python. On trouve aussi des
moyens de connecter IODEF à des logiciels existants par exemple au
logiciel de suivi de tâche
Mantis, avec ce connecteur.
Pour des articles ou présentations sur IODEF, vous pouvez voir la Rump (session rapide) de Thomas Andrejak au SSTIC 2016 (vidéo en ligne).
Notez en France l'existence du projet SECEF (SECurity Exchange Format) qui a pour objectif de promouvoir et de faciliter l’usage des deux formats de fichier IDMEF (RFC 4765) et IODEF. Vous pouvez consulter leur Wiki, et leur tutoriel IODEF. Il y a aussi un article de synthèse sur SECEF, et un compte-rendu d'une de leurs réunions (mais vite fait et avec des erreurs). Enfin, le RFC 8274 donne quelques conseils sur la mise en œuvre d'IODEF.
Date de publication du RFC : Novembre 2016
Auteur(s) du RFC : Matthew Thomas, Allison Mankin, Lixia Zhang (UCLA)
Pour information
Première rédaction de cet article le 27 novembre 2016
Ce nouveau RFC est le compte-rendu d'un atelier qui s'était tenu du 8 au 10 mars 2014 à Londres sur le thème des « collisions ». Ce terme exagéré et sensationnaliste désigne le phénomène qui peut se produire quand un acteur de l'Internet a bêtement choisi de se créer un TLD à lui dans le DNS, et que ce TLD est ensuite créé par l'ICANN.
Supposons que l'entreprise Bidon décide de nommer ses
ressources internes (site Web réservé aux employés, etc) sous le
TLD inexistant
.bidon
. C'est une
mauvaise idée mais elle est fréquente. L'entreprise Bidon
compte sur le fait que ses employés utiliseront les résolveurs DNS
internes, qui ont été configurés pour reconnaître
.bidon
. Par exemple, avec
Unbound, et un serveur faisant autorité en 2001:db8:666::1:541f
, les résolveurs ont été configurés
ainsi :
stub-zone: name: "bidon" stub-addr: 2001:db8:666::1:541f
Si un employé
tente accidentellement d'accéder à une ressource en
.bidon
, alors qu'il n'utilise pas les
résolveurs de la boîte, la requête filera vers la racine du
DNS, qui répondra
NXDOMAIN
(No Such
Domain). C'est ainsi que la racine voit souvent des
requêtes pour des noms se terminant en
.local
, .home
ou
.belkin
. Si, quelques années après,
l'ICANN délègue effectivement ce TLD à une
autre organisation, ces requêtes à la racine donneront désormais
un vrai résultat. Au lieu d'un message d'erreur, le malheureux
employé sera peut-être redirigé vers un autre site Web que celui
attendu. C'est ce phénomène que Verisign
avait baptisé « collision » (name collision),
terme conçu pour faire peur.
C'est dans ce contexte qu'il y a plus de deux ans s'était tenu le « Workshop on Root Causes and Mitigation of Name Collisions », dont ce RFC est le compte-rendu tardif. Le premier rapport de l'ICANN qui mentionnait ce phénomène était le SAC 045 en 2010. Il pointait le risque que la délégation effective d'un nouveau TLD change la réponse obtenue, pour les clients mal configurés (qui interrogeaient à tort un résolveur extérieur, et donc la racine, au lieu de leurs résolveurs internes).
L'ICANN a même créé une page Web
dédiée à cette question, dont la source réelle est le
recouvrement de deux espaces de noms, l'interne et
l'externe. La bonne pratique idéale serait de ne pas utiliser de
noms qui n'existent pas ou, pire, qui existent avec une autre
signification dans l'arbre public des noms de domaine (et, là, relire le RFC 2826 peut aider). Pour reprendre l'exemple de
l'entreprise Bidon, si elle est titulaire de
bidon.fr
, elle devrait nommer ses ressources
internes avec des noms se terminant en
privé.bidon.fr
ou
interne.bidon.fr
. Si on ne veut pas faire les
choses proprement, et qu'on utilise quand même le TLD inexistant
.bidon
, alors il faut veiller très
soigneusement à séparer les deux espaces de nommage et à éviter
qu'ils ne se rencontrent un jour (ce qui est difficile à l'ère des
mobiles, avec des appareils qui rentrent et qui sortent du réseau
de l'entreprise). Sinon, on verra ces fameuses collisions.
En pratique, pas mal d'administrateurs système surestiment leurs compétences et croient qu'ils vont réussir à empêcher toute fuite vers le DNS public. C'est ce qui explique une partie des requêtes pour des noms inexistants que reçoit la racine (ces noms inexistants forment la majorité du trafic des serveurs racine du DNS). Un des problèmes de fond de l'Internet est en effet que l'administrateur de base ne se tient pas au courant et n'est pas informé des problèmes du monde extérieur. « Après moi, le déluge »
Autrefois, le problème était surtout théorique. Le nombre de
TLD n'avait pas bougé depuis de très
nombreuses années, et personne ne pensait que des TLD comme
.pizza
ou .green
verraient le jour. Mais, en 2012, l'ICANN a
lancé officiellement son programme d'ajout d'un grand nombre de
TLD, et le risque est soudain devenu une question pratique. D'où
l'atelier de 2014.
La section 2 du RFC revient en détail sur l'arrière-plan de ce
problème de collision. Outre le rapport SAC 045 cité plus haut, il
y avait eu une
déclaration de l'IAB, puis un autre rapport du
SSAC (Security and Stability Advisory
Committee, un comité de l'ICANN), le SAC 046,
une déclaration
du RSSAC et plein d'autres textes sur les conséquences d'un
agrandissement important de la zone racine. Par exemple, le rapport SAC 057 faisait remarquer que les
AC attribuaient souvent des certificats
pour des noms de domaine dans des TLD
purement locaux. Cela montrait le déploiement de ces TLD privés et
cela inquiétait. Si la société Bidon exploite
.bidon
et obtient d'une AC un certificat pour
www.compta.bidon
, après la délégation de ce
même TLD dans la racine publique, ce certificat pourrait être
utilisé pour usurper l'identité d'un autre serveur.
J'ai parlé plus haut des fuites vers le DNS public. Quelle est
leur ampleur exacte ? Ce n'est pas si évident que cela de le
savoir. Contrairement à un raccourci journalistique fréquent,
l'ICANN ne gère pas la racine. Chaque opérateur d'un
serveur DNS racine se débrouille
indépendamment, supervise son serveur mais ne rend pas forcément
compte à d'autres acteurs ou au public. En pratique, les
opérateurs des serveurs racine ont un niveau d'ouverture très
variable. (Cf. l'analyse
de l'ICANN à ce sujet.) Un des moments où plusieurs
opérateurs de serveurs racine collectent en même temps de
l'information est le Day in the Life of the
Internet et c'est sur la base de ces données qu'a
été fait le rapport d'Interisle « Name
Collision in the DNS ». Entre autres, ce rapport
classait les futurs TLD selon qu'ils présentaient un risque de
collision élevé ou faible (.home
,
.corp
et .site
se
retrouvaient en tête du classement). L'ICANN a alors publié un plan pour gérer ce risque de
collisions, notant que .home
et
.corp
étaient de loin les plus « risqués »,
car ils sont fréquemment utilisés comme TLD locaux. Bien d'autres
documents ont été publiés par l'ICANN, qui a une productivité
extraordinaire lorsqu'il s'agit de faire de la paperasse. Le
dernier
mettait en place le système dit de « controlled
interruption » qui, en gros, impose à tous les nouveaux
TLD de résoudre, pendant les premiers temps de leur délégation,
tous les noms de domaine vers l'adresse IP
127.0.53.53
. Voici l'exemple de
.box
en novembre 2016 (ce cas avait fait
l'objet d'un
article de Heise en allemand, car le routeur
Fritz!Box, très populaire en Allemagne,
utilisait ce TLD) :
% dig ANY box. ; <<>> DiG 9.10.3-P4-Debian <<>> ANY box. ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14573 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 24, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;box. IN ANY ;; ANSWER SECTION: box. 3600 IN A 127.0.53.53 box. 3600 IN SRV 10 10 0 your-dns-needs-immediate-attention.box. box. 3600 IN TXT "Your DNS configuration needs immediate attention see https://icann.org/namecollision" box. 3600 IN MX 10 your-dns-needs-immediate-attention.box. box. 900 IN SOA a.nic.box. support.ariservices.com. ( 1478481375 ; serial 1800 ; refresh (30 minutes) 300 ; retry (5 minutes) 1814400 ; expire (3 weeks) 1800 ; minimum (30 minutes) ) box. 172800 IN NS b.nic.box. box. 172800 IN NS d.nic.box. box. 172800 IN NS c.nic.box. box. 172800 IN NS a.nic.box. [...] ;; Query time: 89 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Mon Nov 21 17:23:17 CET 2016 ;; MSG SIZE rcvd: 2938
Ces enregistrements ont pour but d'attirer l'attention des
utilisateurs sur le risque de collision. Le TLD étant récent et
pas encore peuplé, il ne devrait pas y avoir de requêtes DNS. S'il
y en a quand même, c'est peut-être le résultat d'une
collision avec un usage local. L'adresse IP
127.0.53.53
est une adresse locale à la
machine. Si M. Michu tente de se connecter à
http://quelquechose.box/
aujourd'hui, il sera
redirigé vers la machine locale. Il verra une erreur (pas de
serveur HTTP qui écoute) ou bien la page
Web par défaut de sa machine (avec un message peu informatif comme
« It works ») s'il y a un serveur HTTP. Si
l'utilisateur regarde les enregistrements SRV, MX ou TXT, ou bien
si un administrateur système regarde les
requêtes DNS qui passent, ou bien les
journaux du serveur de messagerie,
peut-être comprendra-t-il qu'il doit agir. (Je trouve
personnellement que la probabilité que cela arrive est assez faible.)
L'atelier lui-même, financé par Verisign (l'entreprise qui avait le plus crié « au loup » sur les name collisions), s'est donc tenu du 8 au 10 mars à Londres. Un site Web avait été mis en place pour cet atelier, et il contient les supports et les vidéos.
Je ne vais pas décrire tous les exposés de l'atelier, la liste complète figure dans l'annexe C du RFC, et les supports sont en ligne. Le RFC note qu'il y a eu plusieurs interventions sur la qualité des données du DITL (Day in the Life of the Internet) : il est trivial de les polluer (le DITL est annoncé publiquement, et à l'avance) par des requêtes artificielles. Aucune preuve n'a été trouvée d'une manipulation délibérée. De toute façon, les données montrent surtout qu'il y a beaucoup de n'importe quoi dans le trafic que reçoivent les serveurs racine (par exemple des requêtes avec le bit RD - Recursion Desired - alors que les serveurs de la racine ne sont pas récursifs). Cela peut être le résultat de bogues dans les résolveurs, de tests ou bien d'attaques délibérées.
La question de l'éducation des utilisateurs est revenue plusieurs fois. Faut-il s'inspirer du téléphone ou du système postal, qui ont tous les deux connu des changements qui nécessitaient une adaptation de l'utilisateur, qui s'est faite par le biais d'importantes campagnes de sensibilisation et d'éducation ?
Le comité de programme avait conclu que le sujet était loin d'être épuisé. Manque de données, manque de théories explicatives, manque d'intérêt pour la question, en tout cas, celle-ci restait largement ouverte après l'atelier (et je ne suis personnellement pas sûr que cela soit mieux aujourd'hui, plus de deux ans après l'atelier de Londres).
Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : J. Laganier (Luminate Wireless), L. Eggert (NetApp)
Chemin des normes
Première rédaction de cet article le 26 novembre 2016
Le protocole HIP, décrit dans le RFC 7401 est très bien adapté au cas où l'adresse IP (le localisateur) change après l'établissement d'une association. Mais cela laisse ouvert le grand problème de la connexion initiale. Comment trouver une machine HIP ? Par le mécanisme de rendez-vous du RFC 8004 ? C'est certainement une bonne solution mais, alors, comment les machines HIP sont-elles connues du serveur de rendez-vous ? C'est là que notre RFC rentre en jeu pour normaliser un mécanisme d'enregistrement auprès d'un service. C'est un mécanisme générique, qui peut servir à d'autres choses que le rendez-vous, d'ailleurs. (Il était à l'origine spécifié dans le RFC 5203, que notre RFC remplace.)
Le mécanisme est très simple et le RFC court. On réutilise
simplement les établissements d'associations de HIP, avec de nouveaux
types de paramètres, notamment REG_INFO
(pour
l'hôte qui accepte d'être registrar, c'est-à-dire
d'enregistrer) et REG_REQUEST
(pour celui qui
demande un enregistrement). Le mécanisme exact est détaillé dans la
section 3 et les nouveaux
paramètres dans la section 4.
HIP authentifiant les deux parties bien plus solidement que IP seul, le registrar (terme d'ailleurs mal choisi, on risque de confondre avec les bureaux d'enregistrement de noms de domaine) peut alors décider s'il accepte l'enregistrement ou pas (sections 3.3 et 6).
Le rendez-vous, normalisé dans le RFC 8004 est donc une simple application de notre RFC mais d'autres pourront apparaître à l'avenir (comme celle du RFC 5770).
Quels sont les changements depuis le premier RFC, le RFC 5203 ? La principale est qu'HIP, qui avait le statut « Expérimental » est désormais sur le chemin des Normes et que les références de notre RFC ont donc changé (nouveau protocole HIP en RFC 7401). Mais ce nouveau RFC ajoute aussi la possibilité d'authentifier le registrar par certificat (RFC 8002), ainsi qu'un nouveau type d'erreur, le numéro 2, « ressources insuffisantes chez le registrar ».
Question mise en œuvre, je n'ai pas vérifié mais, normalement, HIP for Linux et OpenHIP devraient s'adapter aux nouveaux RFC HIP.
Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : J. Laganier (Luminate Wireless,), L. Eggert (NetApp)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 26 novembre 2016
HIP, par défaut, nécessite que l'initiateur d'une association connaisse le localisateur, l'adresse IP du répondeur. Si celui-ci bouge souvent, et qu'il n'est donc pas pratique de mettre cette adresse dans le DNS, une solution est d'utiliser le mécanisme de rendez-vous, décrit par ce RFC, où l'initiateur contacte un serveur de rendez-vous qui relaie vers le répondeur.
Le schéma est clairement expliqué dans la section 3 du RFC. En fonctionnement habituel de HIP, l'initiateur trouve l'identificateur et le localisateur du répondeur (typiquement, dans le DNS, cf. RFC 8005), puis le contacte directement. Si le localisateur n'est pas connu (ce qui est fréquent si le répondeur est un engin mobile, changeant souvent d'adresse IP), l'initiateur envoie le premier paquet (I1) au serveur de rendez-vous, qui le relaie au répondeur. Les autres paquets (R1, I2 et R2) seront transmis directement entre les deux machines HIP. Le mécanisme est détaillé dans la section 3.3 (il faut notamment procéder avec soin à la réécriture des adresses IP, en raison entre autre du RFC 2827).
Et comment l'initiateur trouve-t-il le serveur de rendez-vous ? En général dans le DNS, via les enregistrements de type HIP. Et comment le répondeur avait-il fait connaitre au serveur de rendez-vous son adresse IP ? Via le protocole d'enregistrement du RFC 8003, comme l'explique la section 4.
Comme toute indirection, le système de rendez-vous ouvre des problèmes de sécurité amusants. Si l'initiateur connaissait déjà l'identificateur du répondeur (donc sa clé publiqué), pas de problème, le passage par le serveur de rendez-vous ne diminue pas la sécurité. Si ce n'est pas le cas, alors, il n'y a rien à faire, l'initiateur n'a aucun moyen de vérifier l'identité du répondeur (section 5 du RFC).
Aucun changement depuis la première spécification, le RFC 5204, juste l'alignement avec la nouvelle version de HIP, celle du RFC 7401, désormais norme complète (et pas juste « expérimentale »).
Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : J. Laganier (Luminate Wireless)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF hip
Première rédaction de cet article le 26 novembre 2016
Le protocole HIP n'avait pas à l'origine de mécanisme pour trouver l'identificateur d'une machine distante. Cela avait été fait dans le RFC 5205, qui permettait de trouver l'identificateur dans le DNS. Ce nouveau RFC remplace le RFC 5205.
HIP fait partie de la famille des protocoles qui visent à séparer l'identificateur du localisateur. Les identificateurs HIP se nomment les HI (Host Identifier) et, autrefois, le seul moyen de trouver l'HI d'une autre machine était d'attendre qu'elle vous contacte, ou bien de le configurer manuellement. Avec ce RFC, on peut trouver l'HI, comme une adresse IP, dans le DNS.
Notre RFC crée donc un nouveau type d'enregistrement DNS, nommé logiquement HIP (numéro 55), qui stocke, en échange d'un nom de domaine, le HI, son condensat (résumé) cryptographique - le HIT (Host Identifier Tag) - et les éventuels serveurs de rendez-vous, serveurs qui, dans le protocole HIP, servent d'intermédiaires facultatifs lorsqu'on veut contacter une machine distante (cf. RFC 8004).
Notre RFC permet de trouver l'identificateur à partir du nom mais pas le localisateur ; les serveurs de rendez-vous sont une solution possible pour cela ; une autre est d'utiliser les traditionnels enregistrements A et AAAA du DNS, le localisateur HIP étant une adresse IP.
Les localisateurs peuvent changer fréquemment alors que le DNS n'est pas temps-réel et ne change pas instantanément. Si un hôte HIP veut pouvoir être contacté malgré des changements d'adresse IP rapides, il vaut peut-être mieux qu'il utilise le système de rendez-vous du RFC 8004.
Curieusement (pour moi), le HIT est donc stocké dans les données DNS, alors que celles-ci n'offrent aucune sécurité au point que le RFC exige en section 4.1 de recalculer le HIT qui vient d'être obtenu dans le DNS.
Le tout ressemble donc aux enregistrements IPSECKEY du RFC 4025, ce qui est normal, le HI étant une clé cryptographique publique.
Voici un exemple d'enregistrement HIP tel qu'il apparaitrait dans un fichier de zone (sections 5 et 6 de notre RFC). On y trouve l'algorithme cryptographique utilisé (2 = RSA), le HIT (en hexadécimal), le HI (encodé en Base64) et les éventuels serveurs de rendez-vous (ici, deux, indiqués à la fin) :
www.example.com. IN HIP ( 2 200100107B1A74DF365639CC39F1D578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p 9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQ b1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2.example.com. )
Par contre, je n'ai pas réussi à trouver encore ce genre d'enregistrement dans la nature.
L'ensemble du RFC est assez court, ce mécanisme d'annuaire qu'est le DNS étant simple et bien connu.
Quels sont les changements depuis le premier RFC, le RFC 5205 ? Évidement le passage sur le chemin des normes, faisant de HIP une norme complète. Mais aussi l'ajout de l'algorithme de cryptographie asymétrique ECDSA, et plusieurs clarifications du RFC original sur le format des enregistrements DNS, aussi bien leur format sur le réseau que dans le fichier de zone.
Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : M. Stiemerling (Hochschule
Darmstadt, S. Kiesel (University of
Stuttgart), M. Scharf
(Nokia), H. Seidel
(BENOCS), S. Previdi (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF alto
Première rédaction de cet article le 22 novembre 2016
Il est fréquent aujourd'hui sur l'Internet qu'une application cherche à accéder à un contenu (mettons un film, ou bien la mise à jour d'un gros logiciel) qui est disponible à plusieurs endroits. Dans ce cas (qui est notamment fréquent pour le téléchargement en pair-à-pair), quelle source utiliser ? La « meilleure », bien sûr, mais comment la connaître ? Le but du protocole ALTO est de permettre de distribuer de l'information sur la topologie du réseau, afin que les applications puissent choisir la source la plus proche d'elles. ALTO est déjà normalisé (RFC 7285), ce nouveau RFC sert juste à décrire les scénarios d'usage et à donner des conseils pratiques de déploiement (déploiement qui semble très limité pour l'instant).
Outre le RFC décrivant le protocole (RFC 7285), il peut être utile de lire la description du problème qu'ALTO veut résoudre, le RFC 5693, et le cahier des charges, dans le RFC 6708.
La section 2 de notre RFC résume le fonctionnement d'ALTO. C'est un protocole client-serveur, le serveur ALTO connait l'information (la topologie du réseau, qui est connecté à qui, par quel genre de liens), le client est l'application qui veut accéder au contenu, il connait un ensemble potentiel de sources, et il veut savoir quelle est la « meilleure ». Par exemple, dans le cas de BitTorrent, le client a les adresses IP de l'essaim, il veut savoir à laquelle ou lesquelles demander les bouts de fichier (chunks) qui forment le contenu. Le client ALTO peut être un processus séparé, tournant en permanence, ou bien une bibliothèque liée à l'application. Il doit évidemment parler le protocole ALTO, donc connaitre HTTP et JSON.
Pour déployer ALTO, il y a donc quatre entités logiques à considérer :
Ces entités sont typiquement gérées par des organisations différentes. Un exemple typique (mais ce n'est pas la seule possibilité) est que le FAI soit à l'origine de l'information (il connait son réseau), et la mette dans un serveur ALTO qu'il gère, ses abonnés ayant installé une application de partage de fichiers qui inclut un client ALTO. Dans ce cas, il y aurait deux organisations, le FAI gérant les deux premières entités et l'abonné les deux dernières. Mais d'autres répartitions peuvent exister.
Les organisations qui peuvent être impliquées sont en effet multiples : FAI et opérateurs réseau, bien sûr, utilisateurs, évidemment (agissant, soit seuls, soit en groupes se répartissant le travail), mais aussi des tiers, spécialisés dans la collecte et la distribution de cette information (par exemple des CDN). On pourrait même voir apparaitre des sociétés qui ne font que de l'ALTO.
Tout ceci a des conséquences sur le déploiement. Par exemple, un utilisateur peut faire confiance à un FAI mais pas à des tiers. Un FAI peut souhaiter distribuer de l'information à ses abonnés mais pas à tout l'Internet. ALTO définit un protocole, pas une politique : ce protocole permet différents modèles, y compris celui de serveurs ALTO spécialisés et payants. Autre conséquence de l'utilisation de telle ou telle répartition du travail, on pourrait avoir des serveurs ALTO partiels, qui ne contiennent de l'information que sur certains réseaux.
Dans tous les cas, le RFC rappelle qu'ALTO est juste une optimisation : une application doit fonctionner même si elle ne trouve aucun serveur ALTO, ou bien s'ils sont en panne.
Un petit rappel utile sur ALTO : il existe deux modes de
fonctionnement différents, qui ont tous les deux des conséquences
importantes, notamment sur la confidentialité. Dans le premier
mode, le serveur ALTO fournit l'information qu'il a (sous forme de
maps, des ensembles de données sur le réseaux,
les liens, leur coût, etc) et le client
cherche dedans ce qui l'intéresse. Ce mode préserve la vie privée
du client (qui ne dit pas au serveur ce qui l'intéresse) mais pas
celle du serveur (qui doit tout envoyer). Il n'est pas évident que
beaucoup de FAI acceptent cela. Dans le second mode, le
serveur permet des interrogations sur un point particulier (« qui
est le plus proche de moi ? 192.0.2.87
,
203.0.113.122
ou bien
198.51.100.20
? »). Ce mode évite au serveur
de tout divulguer mais oblige en revanche le client à révéler ses
intentions (ici, les adresses IP des pairs potentiels, ce qui peut
intéresser des organisations répressives comme la
HADOPI). Notez que la fuite d'informations
du serveur
existe aussi dans le second mode : plusieurs clients ALTO peuvent
coopérer pour poser beaucoup de questions et extraire ainsi une
partie substantive de la base.
La partie 3 de notre RFC en vient aux conseils concrets pour les FAI. On considère que l'objectif du FAI est de minimiser ses coûts, donc a priori de garder le maximum de trafic en local (il y a des exceptions, que liste le RFC). Le serveur ALTO que gère le FAI va donc annoncer des coûts plus faibles pour les liens locaux.
Mais, d'abord, le FAI doit « remplir » le serveur ALTO avec de l'information. Cette étape d'avitaillement commence par la récolte d'informations sur le réseau. A priori, le FAI connait son propre réseau, et n'a donc pas de mal à récolter ces informations. Outre sa propre documentation interne, le FAI peut aussi utiliser de l'information issue d'autres sources, par exemple les protocoles de routage comme BGP (cf., entre autres, le RFC 7752) ou bien des mesures actives ou passives (cf. entre autres, le RFC 7491). Rappelez-vous qu'ALTO est uniquement un protocole permettant d'accéder à de l'information sur la topologie. Comment cette information a été récoltée et agrégée n'est pas de la responsabilité d'ALTO, de même que le protocole HTTP ne se soucie pas de comment est fabriquée la page HTML qu'il sert.
Le FAI doit ensuite appliquer ses critères (coût, performance, etc) à la topologie. Ces critères sont forcément imparfaits. Le client ALTO ne doit pas s'attendre à ce que l'information qui lui est donnée soit idéale dans tous les cas. Par exemple, le serveur ALTO peut indiquer un lien rapide et pas cher mais qui, au moment où le téléchargement commencera, sera saturé par un trafic intense (ALTO ne prétend pas être temps-réel). Et il y a bien d'autres choses qui ne seront pas connues de ceux qui ont compilé l'information, ou bien qui n'auront pas été incluses dans la base de données du serveur ALTO (« la carte n'est pas le territoire »). Les données distribuées par ALTO, les maps, sont supposées être relativement statiques. Mais, dans le monde réel, les choses changent et le client recevra donc peut-être une information légèrement dépassée.
Si vous trouvez le concept de map un peu abstrait, la section 3.5 du RFC donne plusieurs exemples. Par exemple, dans le cas le plus simple, celui d'un petit FAI ayant un seul opérateur de transit, les adresses dudit FAI seront dans le PID (Provider-defined IDentifier, cf. RFC 7285, section 5.1) 1, tout le reste de l'Internet étant le PID 2. Cela donnera une map (syntaxe décrite dans le RFC 7285, section 9.2) :
{ ... "network-map" : { "PID1" : { "ipv4" : [ "192.0.2.0/24", "198.51.100.0/25" ], "ipv6" : [ "2001:db8:100::/48" ] }, "PID2" : { "ipv4" : [ "0.0.0.0/0" ], "ipv6" : [ "::/0" ] } } }
Un FAI plus gros, et à la topologie plus complexe, a plein de possibilités. Par exemple, ses propres réseaux peuvent être dans des PID différents, s'il veut pouvoir garder le trafic local à un de ses réseaux. Un exemple est celui où le même FAI a des abonnés fixes et mobiles, et où on souhaite limiter les transferts des abonnés fixes vers les mobiles, pour réduire l'utilisation des liens hertziens.
Reste ensuite à effectuer le déploiement des serveurs ALTO. Il
existe plusieurs mises en œuvre logicielles d'ALTO et des compte-rendus d'expérience figurent dans
les Internet-Drafts
draft-seidel-alto-map-calculation
et draft-lee-alto-chinatelecom-trial
et dans le RFC 6875
(ainsi que, pour un protocole antérieur à ALTO, dans le RFC 5632). Cette
expérience montre que certaines façons de collecter l'information
peuvent être coûteuses : si un FAI a plusieurs liens avec
l'Internet, et reçoit un flux BGP complet,
et veut mettre chaque préfixe de la DFZ
dans ses maps, il doit prévoir des machines
assez costaud pour traiter cette information importante et assez
changeante. Et le résultat serait une map qu'il
serait difficile d'envoyer à tous les clients, vu sa taille. Il
faut donc prévoir, dans ce cas extrême, de l'agrégation vigoureuse
des préfixes IP.
La section 4 de notre RFC couvre ensuite l'utilisation d'ALTO, une fois qu'il est déployé. Normalement, tout le monde a intérêt à ce que ALTO soit utilisé : le FAI veut que les utilisateurs épargnent les liens réseaux les plus lents et les plus coûteux et les utilisateurs veulent les meilleures perfomances. En théorie, tout le monde trouvera son intérêt à utiliser ALTO.
Un exemple est celui de BitTorrent. Si les pairs BitTorrent incluent un client ALTO, chaque pair, quand il reçoit une liste d'adresses IP de l'essaim, peut alors interroger le serveur ALTO et trouver les « meilleurs » pairs. Ils peuvent même échanger cette information entre eux (PEX, Peer EXchange, dans le monde BitTorrent). Mais une autre possibilité est que ce ne soient pas les pairs qui interrogent le serveur ALTO mais le tracker (pour les essaims fonctionnant avec une machine qui sert de tracker, ce qui n'est pas toujours le cas). Ainsi, il n'est pas nécessaire de mettre un client BitTorrent dans chaque pair, c'est le tracker qui, grâce à l'information ALTO, choisit les meilleurs pairs pour chacun, et ne leur envoie que cela.
Le RFC se conclut pas une section 7 sur la sécurité. Parmi les problèmes à considérer, il y a le fait qu'un serveur ALTO malveillant, ou bien un serveur se faisant passer pour un serveur ALTO légitime, peut empoisonner le client avec de fausses données.
Auteur(s) du livre : Andreas Antonopoulos
Éditeur : O'Reilly
978-1-449-37404-4
Publié en 2015
Première rédaction de cet article le 20 novembre 2016
Vous voulez connaitre tous les détails techniques sur Bitcoin ? Voici un livre recommandé. À la fin, vous en saurez davantage que vous ne vouliez.
Le livre a été écrit par Andreas Antonopoulos, personnage connu dans le monde Bitcoin, et qui écrit de nombreux articles et donne plein de conférences (celle qu'il a donné à Paris le 11 octobre est en ligne, vous pouvez aussi voir les nombreux tweets que cela a entrainé et une excellente « storifycation de ces tweets). Son livre commence de manière très pédagogique, à travers des scénarios d'utilisation. Alice utilise Multibit pour acheter un café à Bob à Palo Alto, Bob fait refaire le site Web de son café à Gonesh, à Bangalore, et Jing mine du bitcoin à Shanghai. Au début, l'auteur fait peu de technique, se focalisant sur les applications.
Ensuite, cela devient plus technique, en commençant par l'installation d'un nœud Bitcoin (le livre n'est pas destiné à M. Michu). Andreas Antonopoulos explique le fonctionnement du client en ligne de commande qui permet de parler à son nœud Bitcoin. De la commande la plus triviale, permettant de savoir à quel bloc en est la chaîne locale :
% bitcoin-cli getblockcount 439785
à des commandes plus complexes, ici pour voir l'achat du café d'Alice :
% bitcoin-cli gettransaction 0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2
(Si vous obtenez le message d'erreur Invalid or non-wallet transaction id, c'est que vous n'avez pas bien lu le livre et les instructions qu'il donne pour accéder à toutes les transactions.)
À noter que les exemples ont été réellement faits sur la chaîne
publique Bitcoin, et peuvent donc être vérifiés. L'adresse d'Alice est
1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK
et on peut
donc voir toutes
ses transactions en ligne, de sa première obtention de 0,1
bitcoin auprès de son ami Joe (transaction 7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18
),
à l'achat du café à Bob (transaction 0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2
). Le
code QR de la demande de bitcoins de Bob,
dans le livre, est également un vrai, et on peut le lire (bitcoin:1GdK9UzpHBzqzX2A9JFP3Di4weBwqgmoQA?amount=0.015&label=Bob%27s%20Cafe&message=Purchase%20at%20Bob%27s%20Cafe
).
L'auteur pense aussi aux programmeurs et leur explique comment accéder aux données Bitcoin et les manipuler depuis un programme. Par exemple, en Python, avec la bibliothèque pycoin.
Je l'ai dit, ce livre, malgré ses premières pages très pédagogiques sur Bitcoin, est prévu pour les techniciens. Vous y trouverez même une explication de la cryptographie sur courbes elliptiques, permettant de décrire ensuite les différents formats de clés.
Les utilisateurs de l'autre chaîne de blocs Ethereum savent qu'une adresse Ethereum ne désigne pas forcément un compte mais peut référencer un programme qui sera exécuté lorsqu'on enverra quelque chose à cette adresse. Mais peu savent que cette possibilité existe dans Bitcoin depuis longtemps. Antonopoulos décrit donc en détail les différents types d'adresses Bitcoin, notamment les P2SH (Pay To Script Hash) où le paiement va déclencher l'exécution d'un programme qui pourra, par exemple, demander plusieurs signatures pour valider un paiement (la grande différence entre Ethereum et Bitcoin n'est pas la présence ou l'absence de programmes stockés dans la chaîne, elle est dans le fait que seul Ethereum a un langage de Turing ; au passage, le livre contient un court chapitre présentant rapidement quelques chaînes de blocs concurrentes). Il y a même un peu d'assembleur Bitcoin dans le livre (mais pas un cours complet sur ce langage).
Les gens du réseau aimeront également le chapitre sur le
fonctionnement pair à pair de Bitcoin et
sur la façon dont les nœuds Bitcoin échangent. Un petit coup de
bitcoin-cli getpeerinfo
et je vois que ma
machine Bitcoin a 124 pairs, dont 11 se connectent en
IPv6. 86 font tourner le logiciel de
référence Bitcoin Core et 30
sont basés sur BitcoinJ (ce sont surtout des
clients utilisant Multibit).
Je l'ai dit plus haut, ce livre n'est pas du tout nécessaire pour utiliser Bitcoin, ni même pour comprendre comment il fonctionne. En revanche, il est indispensable si vous voulez comprendre les points les plus délicats du fonctionnement de Bitcoin, comme les UTXO, la structure de la chaîne avec les arbres de Merkle, le fonctionnement de SPV... Difficile de trouver une question technique sur Bitcoin qui n'aurait pas de réponse dans ce livre.
Avertissement : j'ai acheté ce livre en payant en euros, pas en bitcoins. J'en profite pour rappeler que, si vous aimez ce blog, je veux bien des bitcoins.
Première rédaction de cet article le 17 novembre 2016
Le 16 novembre, deux pannes successives ont affecté les résolveurs DNS d'Orange. Que s'est-il passé exactement, et quelles conséquences peut-on en tirer ?
Commençons par les observations. Au moins, il s'agira de faits. Les deux pannes sont survenues approximativement entre 0840 UTC (soit quasiment en même temps que la plénière de l'IETF dont le thème était... « Attacks Against the Architecture » !) et 1030 pour la première, et entre 1315 et 1410 (toujours UTC) pour la seconde. N'ayant pas de compte chez Orange, j'ai utilisé deux sources d'informations, les rézosocios, où d'innombrables messages ont signalé la panne, et les sondes RIPE Atlas. Pour ces dernières, j'ai demandé des sondes se trouvant dans l'AS 3215, celui d'Orange (notez qu'il abrite des services très différents, ne dépendant pas forcément des mêmes résolveurs DNS). À ma connaissance, Orange n'a rigoureusement rien communiqué, ni pendant la panne (malgré les innombrables cris lancés par ses clients sur les rézosocios), ni après, donc je ne peux me fier qu'à ces observations. Les messages des utilisateurs d'Orange étaient pour la plupart trop vagues (« rien ne marche »), ne citant même pas un nom de domaine qu'on puisse ensuite tester. Personne hélas pour procéder à une récolte sérieuse de données, par exemple avec dig. Ces messages des utilisateurs ne peuvent donc servir qu'à signaler et confirmer qu'il y avait un gros problème. Mais les sondes Atlas nous en disent davantage.
Que nous montrent-elles ? Je prends par exemple le domaine de l'Université Stanford. Si je veux vérifier qu'il est bien visible, je demande à cent sondes RIPE Atlas de résoudre ce nom en adresse IP :
% atlas-resolve --requested 100 online.stanford.edu [] : 1 occurrences [171.67.216.22] : 33 occurrences [171.67.216.23] : 28 occurrences [171.67.216.21] : 37 occurrences Test #6935163 done at 2016-11-17T04:56:58Z
C'était le lendemain de la panne, et tout marche bien (une seule sonde n'a pas eu de réponse, et cela peut être de la faute de son réseau d'accès). Mais pendant la panne ? On voyait, en se limitant à l'AS 3215, des choses comme :
% atlas-resolve --requested 100 --as 3215 online.stanford.edu [TIMEOUT(S)] : 13 occurrences [ERROR: SERVFAIL] : 65 occurrences [171.67.216.22] : 8 occurrences [171.67.216.23] : 7 occurrences [171.67.216.21] : 7 occurrences Test #6934676 done at 2016-11-16T08:53:51Z
Regardons de plus près. La majorité des sondes RIPE Atlas situées dans
l'AS d'Orange n'a pu résoudre le nom, et a au contraire obtenu un code
SERVFAIL
(SERVer FAILure),
indiquant que le résolveur (je reviens sur ce terme plus loin) utilisé
n'a pu joindre aucun des serveurs faisant autorité pour le domaine
stanford.edu
. Pas mal de sondes n'ont simplement
pas eu de réponses de leur résolveur à temps.
Mais cette unique observation ne nous permet pas de dire que le problème venait d'Orange. Il est parfaitement possible que ce soit Stanford qui ait des ennuis, panne ou dDoS. Il faut donc, comme toujours lorsqu'on fait des observations scientifiques, comparer avec des mesures faites dans d'autres circonstances. Ici, on va simplement demander aux sondes situées dans un pays voisin, l'Allemagne :
% atlas-resolve --requested 100 --country DE online.stanford.edu [] : 1 occurrences [171.67.216.22] : 33 occurrences [171.67.216.23] : 31 occurrences [171.67.216.21] : 35 occurrences Test #6934677 done at 2016-11-16T08:54:06Z
Au pays de Konrad Zuse, toutes les sondes ou presque ont une réponse. Cela laisse entendre que tout va bien à Stanford et que le problème ne vient pas de l'université californienne. (J'aurais aussi pu tester avec un autre AS français, celui de SFR ou de Free.)
Autre façon de voir que le problème était bien chez Orange et pas du côté des domaines testés, essayer avec d'autres domaines :
% atlas-resolve --requested 100 --as 3215 kotaku.com [ERROR: SERVFAIL] : 47 occurrences [151.101.1.34 151.101.129.34 151.101.193.34 151.101.65.34] : 50 occurrences Test #6934730 done at 2016-11-16T10:10:01Z % atlas-resolve --requested 100 --as 3215 spotify.com [194.132.197.147 194.132.198.165 194.132.198.228] : 76 occurrences [ERROR: SERVFAIL] : 19 occurrences [TIMEOUT(S)] : 4 occurrences Test #6934675 done at 2016-11-16T08:52:10Z
Tous ces domaines marchaient parfaitement depuis d'autres AS ou d'autres pays.
Donc, problème de résolution DNS chez Orange. Comme l'ont vite
découvert bien des utilisateurs, changer de résolveur DNS
suffisait à résoudre le problème (ce qu'on pouvait également
tester avec ce programme atlas-resolve
et
l'option --nameserver
).
Notons bien, qu'il s'agissait des résolveurs DNS, pas des serveurs faisant autorité, comme cela avait été le cas récemment lors de l'attaque contre Dyn. La distinction est cruciale car ces deux types de serveurs DNS n'ont pas grand'chose en commun. Si vous lisez un article qui parle de « serveur DNS » tout court, sans préciser s'il s'agit d'un résolveur ou bien d'un serveur faissant autorité, méfiez-vous, c'est souvent un signe d'ignorance, ou de négligence, de la part de l'auteur de l'article.
Maintenant, les remarques. D'abord, beaucoup de gens (par exemple dans cet article de Numerama, mais aussi dans d'innombrables tweets) ont suggéré de passer des résolveurs DNS d'Orange (ceux utilisés par défaut par les abonnés à ce FAI) à ceux de Google Public DNS ou bien à ceux de Cisco OpenDNS. La plupart des sociétés à but lucratif doivent payer des commerciaux et des chargés de relation publique pour faire leur publicité, mais Google n'en a pas besoin, ayant des millions de vendeurs bénévoles et enthousiastes parmi ses utilisateurs. Mais ceux qui écoutent ces conseils et passent à Google Public DNS lui donneront les données personelles qui permettent leur propre surveillance (cf. le RFC 7626 sur le caractère sensible des requêtes DNS). Je ne développe pas davantage ce point ici, Shaft l'a fait mieux que moi. J'observe que, si ce genre de pannes continue, les utilisateurs français dépendront presque tous, pour une activité critique, d'un résolveur états-unien d'une entreprise privée. Cela devrait logiquement agiter ceux qui nous parlent tout le temps de souveraineté numérique, mais, en général, ces gens ne sont pas intéressés par les problèmes concrets et opérationnels.
Mais alors quelle serait la bonne solution ? Le mieux évidemment est d'utiliser des résolveurs proches, donc a priori dans le cas idéal, ceux de son FAI. Ceux-ci ne devraient pas tomber en panne, le DNS étant absolument indispensable à tout usage de l'Internet. Mais lorsque des pannes aussi longues surviennent, il est normal d'envisager d'autres solutions, et la bonne est certainement d'avoir un résolveur sur son réseau local (pas forcément sur chaque machine), ce qui est facile avec des équipements comme le Turris Omnia.
Notez qu'une minorité des sondes RIPE Atlas sont déjà sur
un réseau local qui utilise un tel résolveur. Cela explique en
partie pourquoi, dans les tests ci-dessus, un certain nombre de
sondes arrivaient à résoudre les noms de domaine, même au plus
fort de la panne. (Cela n'explique qu'une partie du phénomène. Il
semble que certains noms avaient un taux de réussites plus fort
que d'autres, ce qui ne peut pas s'expliquer par le choix du
résolveur.) Notez qu'on peut avoir l'adresse IP du résolveur
utilisé par la sonde (avec l'option --displayresolvers
) mais que
cela ne renseigne pas tellement. D'abord, c'est souvent une
adresse IP privée (RFC 1918), ensuite, le premier
résolveur vu par la sonde fait fréquemment suivre à un résolveur
plus gros, qu'on ne voit pas, et qui peut être ou ne pas être un
résolveur « officiel » du FAI. Je vous montre quand même le
résultat pour l'une des mesures faites ci-dessus (notez la bogue
pour le cas du timeout, où le résolveur n'est
pas connu) :
% atlas-resolve -r 100 --as 3215 --displayresolvers --measurement 6934670 kotaku.com [ERROR: SERVFAIL] : 27 occurrences (resolvers ['172.31.255.254', '192.168.1.1', '80.10.246.2', '192.168.2.1', '192.168.254.254', '192.168.3.1']) [151.101.1.34 151.101.129.34 151.101.193.34 151.101.65.34] : 69 occurrences (resolvers ['2a01:cb08:898c:fc00::1', '172.16.3.1', '192.168.1.1', '10.10.11.4', '10.63.0.252', '10.112.0.1', '8.8.8.8', '192.168.119.1', '192.168.1.9', '192.168.0.1', '10.0.0.34', '80.10.246.136', '192.168.248.153', '192.168.4.10', '192.168.1.40', '192.168.221.254', '149.202.242.66', '192.168.255.254', '192.168.28.1', '192.168.2.1', '10.0.0.1', '192.168.0.31', '194.2.0.20', '192.168.10.10']) [TIMEOUT(S)] : 4 occurrences (resolvers <__main__.Set instance at 0x7fedc8194f80>) Test #6934670 done at 2016-11-16T08:44:41Z
Deuxième sujet de réflexions sur cette panne, que s'est-il
passé ? En l'absence de toute communication de la part d'Orange,
on ne peut guère que spéculer. Notons tout de suite qu'il ne
s'agissait pas cette fois d'un détournement (comme lorsque Orange
avait redirigé Google et Wikipédia vers le Ministère de
l'Intérieur) mais d'une absence de réponse. Cette absence
dépendait des domaines. Je n'ai pas eu immédiatement de signalement d'un
problème pour un domaine hébergé en France, seulement pour des
domaines états-uniens (c'est après, donc trop tard pour les
mesures, que j'ai appris que des domaines hébergés en France
étaient également touchés). Comme le code de retour
SERVFAIL
indique que le résolveur n'a pas
réussi à parler aux serveurs faisant autorité, on peut donc
supposer que les liens menant à ces réseaux outre-Atlantique
étaient inutilisables. Suite à une erreur de configuration, par
exemple dans des ACL ? À un problème de
routage vers certaines destinations ? À une
attaque par déni de service ? Je ne le
sais pas. Mais je me demande bien quelle était la panne ou
l'attaque qui pouvait bloquer les résolveurs, tout en laissant
passer toutes les autres machines (puisque, une fois qu'on avait
un résolveur normal, le trafic n'était pas affecté).
Date de publication du RFC : Novembre 2016
Auteur(s) du RFC : S. Bortzmeyer (AFNIC), S. Huque (Verisign Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 9 novembre 2016
Tout le monde apprend à l'école que les noms de domaine sont organisés en un
arbre. (Et j'invite tout le monde à lire la
section 3.1 du RFC 1034, pour dire moins de
bêtises sur les noms de domaine.) Il en découle logiquement que, si un
nœud de l'arbre n'existe pas, les nœuds situés en dessous
n'existent pas non plus. C'est évident ? Hélas, non. En pratique,
bien des résolveurs DNS sont prudents et, lorsqu'ils reçoivent une
réponse négative pour un nom, mettons
foo.example
, ils n'enregistrent pas pour
autant le fait que les sous-domaines comme
bar.foo.example
n'existent pas non plus, et,
si un client leur demande des informations sur ce sous-domaine,
ils vont relayer la question aux serveurs faisant autorité, alors
qu'ils auraient parfaitement pu répondre à partir de leur
cache. Ce nouveau RFC remet les choses en
place : les noms de domaine sont organisés en arbre, ce
comportement traditionnel est donc bel et bien erroné, et un
résolveur devrait, lorsqu'il reçoit une réponse négative,
mémoriser le fait qu'il n'y a pas non plus de sous-domaines de ce
nom. Cela améliorera les performances du DNS et, dans certains
cas, sa résistance à des attaques par déni de
service.
Voyons d'abord ce que fait un résolveur actuel. J'ai choisi
Unbound. Il vient de démarrer, on lui
demande foobar56711.se
, qui n'existe pas :
% dig MX foobar56711.se. ... ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 56324
On a logiquement un NXDOMAIN
(No
Such Domain, ce nom n'existe pas ; cette erreur se
nommait autrefois Name Error, et a le code 3). Où le résolveur
a-t-il trouvé cette information ? Il a demandé aux serveurs
faisant autorité, comme nous le montre
tcpdump :
14:57:14.488196 IP (tos 0x0, ttl 57, id 52537, offset 0, flags [none], proto UDP (17), length 1063) 130.239.5.114.53 > 10.10.86.133.44861: [udp sum ok] 64329 NXDomain*- q: MX? foobar56711.se. 0/6/1 ...
Le serveur d'IIS (le registre de .se
), 130.239.5.114
lui a bien dit NXDOMAIN
.
Maintenant, demandons au même résolveur
xyz.foobar56711.se
, sous-domaine du
précédent :
% dig MX xyz.foobar56711.se. ... ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 64776
Et, si on regarde le trafic avec tcpdump, on voit que le résolveur a demandé encore au serveur faisant autorité, alors que c'était inutile !
15:00:32.929219 IP (tos 0x0, ttl 64, id 42641, offset 0, flags [none], proto UDP (17), length 75) 10.10.86.133.40616 > 130.239.5.114.53: [bad udp cksum 0x8d98 -> 0xd7df!] 10643% [1au] MX? xyz.foobar56711.se. ar: . OPT UDPsize=4096 OK (47) 15:00:32.939437 IP (tos 0x0, ttl 57, id 14256, offset 0, flags [none], proto UDP (17), length 1067) 130.239.5.114.53 > 10.10.86.133.40616: [udp sum ok] 10643 NXDomain*- q: MX? xyz.foobar56711.se. 0/6/1 ...
Pourquoi le résolveur est-il si prudent, et pose-t-il au
serveur faisant autorité une question dont il aurait déjà dû
connaitre la réponse ? Il y a plusieurs raisons mais la principale
est que le RFC originel sur le
DNS, le RFC 1034, est
ambigu. Il ne décrivait pas de manière parfaitement claire ce
qu'il faut faire lorsqu'un nom de domaine est un ENT, un
Empty Non-Terminal, c'est-à-dire un nom de domaine qui n'a
pas d'enregistrements mais qui a des sous-domaines. Certains ont
pensé que cela autorisait à répondre NXDOMAIN
lorsque le nom demandé est un ENT. Ce comportement a été
clairement noté comme incorrect dans les RFC ultérieurs (section
7.16 du RFC 2136 et sections 2.2.2
et 2.2.3 du RFC 4592) mais tout le monde
n'en avait pas forcément tiré les conséquences. Autre RFC qui
contribuait au comportement erroné, le RFC 2308 (dans sa section 5) faisait l'erreur de dire qu'un résolveur ne pouvait
renvoyer un NXDOMAIN
que si la question
portait sur exactement le même nom que celui qui avait été mis en
cache. Notre nouveau RFC 8020 corrige cette erreur : un
résolveur doit également renvoyer NXDOMAIN
si
la question est un sous-domaine d'un domaine inexistant.
La règle qui forme le cœur de ce nouveau RFC tient en une phrase
(section 2) : « si un résolveur reçoit un
NXDOMAIN
, il peut et il devrait mémoriser le
fait que ce nom et tous ceux en dessous
n'existent pas ». Logiquement, les questions ultérieures portant
sur un sous-domaine de ce nom devraient recevoir immédiatement un
NXDOMAIN
, sans déranger les serveurs faisant
autorité. C'est d'ailleurs ce que fait
Unbound, si on active l'option
harden-below-nxdomain
ainsi :
server: harden-below-nxdomain: yes
On voit alors qu'Unbound, face aux deux requêtes successives pour
foobar56711.se
et
xyz.foobar56711.se
, n'écrit qu'une seule fois
aux serveurs de .se
.
(Si cela ne marche pas pour vous, c'est peut-être que votre Unbound
ne valide pas, vérifiez sa configuration DNSSEC, ou que le domaine
est signé avec l'option opt-out.) Unbound suit
donc le bon comportement mais, malheureusement, pas par
défaut. (C'est déjà mieux que BIND, qui a
toujours le mauvais comportement de demander systématiquement aux
serveurs faisant autorité, ce qui annule partiellement l'intérêt
d'avoir un cache.)
Voilà, vous savez maintenant l'essentiel sur le principe du
NXDOMAIN cut. Voyons quelques détails, toujours
en section 2 du RFC. D'abord, il faut noter que la règle n'est pas
absolue : un résolveur, s'il y tient, peut continuer à renvoyer des
réponses positives à une question sur un sous-domaine, même si le
domaine parent n'existe pas, si le cache (la mémoire) du résolveur
contenait des réponses pour ces sous-domaines. En terme
d'implémentation, cela veut dire que le mode préféré est de
supprimer tout le sous-arbre du cache lorsqu'on reçoit un
NXDOMAIN
, mais que ce n'est pas
obligatoire.
D'autre part, rien n'est éternel dans le monde du DNS. Les informations reçues par le résolveur ne sont valables que pendant une période donnée, le TTL. Ainsi, une information positive (ce domaine existe) n'est vraie que jusqu'à expiration du TTL (après, il faut revalider auprès des serveurs faisant autorité). Même chose pour une information négative : la non-existence d'un domaine (et de tout le sous-arbre qui part de ce domaine) est établie pour un TTL donné (qui est celui du champ Minimum du SOA, cf. RFC 2308).
Dernier petit piège, s'il y a une chaîne d'alias menant au nom
de domaine canonique, le NXDOMAIN
s'applique
au dernier nom de la chaîne (RFC 6604), et pas au nom explicitement demandé.
La section 4 de notre RFC détaille les bénéfices attendus du NXDOMAIN cut. Le principal est la diminution de la latence des réponses, et celle de la charge des serveurs faisant autorité. On aura moins de requêtes, donc un bénéfice pour tout l'écosystème. Cela sera encore plus efficace avec la QNAME minimisation du RFC 9156, puisque le résolveur pourra arrêter son traitement dès qu'il y aura un domaine absent.
Cela sera aussi utile dans le cas de certaines attaques par déni de service, notamment les attaques random QNAMEs avec un suffixe un peu long (comme dans le cas de l'attaque dafa888).
Mais tout n'est pas idéal dans cette vallée de larmes. Le
NXDOMAIN cut peut aussi poser des problèmes, ce
qu'examine la section 5. Le principal risque est celui que pose des
serveurs faisant autorité bogués, comme ceux
d'Akamai. Regardons le domaine de
l'Université de Pennsylvanie,
www.upenn.edu
:
% dig A www.upenn.edu www.upenn.edu. 300 IN CNAME www.upenn.edu-dscg.edgesuite.net.
C'est un alias pour un nom Edgesuite
(une marque d'Akamai). Mais les serveurs de
edgesuite.net
sont bogués, ils répondent
NXDOMAIN
pour un ENT (Empty
Non-Terminal, comme
edu-dscg.edgesuite.net
:
% dig @ns1-2.akam.net A edu-dscg.edgesuite.net ... ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 659 ...
La réponse correcte aurait dû être
NODATA
(c'est-à-dire le code
NOERROR
et une section
Answer de taille nulle). Tant qu'Akamai n'aura
pas réparé ses serveurs, des problèmes subsisteront.
Au fait, pourquoi ne pas se servir de
l'enregistrement SOA, qui est renvoyé en cas
de réponse négative, pour trouver un NXDOMAIN
cut situé encore plus haut, et qui sera donc plus
efficace pour limiter les requêtes ultérieures ? L'annexe A du RFC
explique pourquoi c'est une fausse bonne idée. Prenons l'exemple
d'un nom non existant,
anything.which.does.not.exist.gouv.fr
:
% dig AAAA anything.which.does.not.exist.gouv.fr ... ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 35377 ... ;; AUTHORITY SECTION: fr. 5400 IN SOA nsmaster.nic.fr. hostmaster.nic.fr. ( 2224131472 ; serial ...
Le SOA renvoyé indique fr
. Il ne faut pas en
déduire que les noms plus spécifiques n'existent pas
(gouv.fr
existe, mais ce n'est pas une zone
séparée, voilà pourquoi le SOA indiquait son parent fr
).
La section 6 du RFC contient quelques conseils pour les
implémenteurs. Rappelez-vous que les exigences de ce RFC concernent
le comportement extérieur du résolveur, pas la façon dont il est
mis en œuvre. Cette réalisation concrète va donc dépendre de
comment sont représentés les domaines dans la mémoire du
résolveur. La représentation la plus évidente est d'utiliser un
arbre puisque c'est le modèle des noms de
domaine. Mais ce n'est pas obligatoire. Un autre choix pourrait
être celui d'un dictionnaire, plus rapide
(pour un nom de domaine très profond, il y aura moins de lectures
dans la structure de données) mais qui rend certaines opérations
plus difficiles (toutes celles définies par rapport au modèle
d'arbre, et elles sont nombreuses dans le DNS). Et il existe des
implémentations intermédiaires, par exemple avec un arbre augmenté
d'un index. Bref, le programmeur a le
choix. S'il a opté pour un arbre, la façon la plus simple de
respecter les exigences du RFC et, en recevant un
NXDOMAIN
, de supprimer tout sous-arbre qui
partirait du nom ainsi nié.
Un petit mot de sécurité, maintenant qu'on approche de la
fin. Si un résolveur accepte un NXDOMAIN
mensonger (attaque par empoisonnement), les
conséquences risquent d'être sérieuses puisque c'est un sous-arbre
entier qui serait « détruit ». C'est pour cela que le RFC autorise
un résolveur prudent à ne pratiquer le NXDOMAIN
cut que si le NXDOMAIN
a été validé
avec DNSSEC. C'est ce que fait
Unbound, cité plus haut.
Notez que, si on a DNSSEC, une technique encore plus puissante
consiste à synthétiser des réponses NXDOMAIN
en utilisant les enregistrements NSEC. Elle
est décrite dans un
Internet-Draft
actuellement en cours de discussion.
Quels sont les résolveurs qui gèrent aujourd'hui le NXDOMAIN cut ? Outre Unbound, déjà cité, il y a PowerDNS Recursor, mais qui est, curieusement, limité au cas particulier de la racine.
Un peu d'histoire pour finir : la prise de conscience du problème que pose le manque d'agressivité des caches des résolveurs est ancienne. Voici par exemple une partie d'un rapport de Paul Mockapetris à la réunion IETF n° 4 en 1986 :
Mais le projet concret qui a mené à ce RFC est bien plus récent. Il a été lancé (cf. les supports) à la réunion IETF de Yokohama, à peine plus d'un an avant la publication du RFC (on peut voir ici l'histoire des différents brouillons). On voit que l'IETF peut agir vite.
Auteur(s) du livre : Olivier Iteanu
Éditeur : Eyrolles
978-2-212-11859-9
Publié en 2016
Première rédaction de cet article le 2 novembre 2016
On ne peut plus se plaindre que l'irruption du numérique dans toutes les activités humaines se fasse sans réflexion politique ou juridique. Voici encore un nouvel ouvrage sur la question, écrit par un juriste qui connait bien ce domaine depuis des années. Il tourne autour d'une question « est-ce que cette irruption du numérique va se faire au détriment du droit ? ».
Olivier Iteanu se penche sur quatre grandes questions politico-juridiques : la liberté d'expression, la vie privée, le droit d'auteur et la gouvernance de l'Internet. Sa thèse principale est que, oui, le numérique menace l'État de droit (au passage, il y a une différence entre « État de droit » et « état de droit » et Iteanu met bien la majuscule). En gros, les GAFA tentent d'imposer leurs lois (les fameuses CGU que personne ne lit, et qui sont souvent illégales, par exemple en obligeant d'aller traiter les litiges en Californie). Et cela se fait au détriment des lois nationales des pays vassaux.
La thèse est étayée par de nombreux exemples, les argumentaires des GAFA (« mais vous pouvez toujours changer les paramètres de vie privée, si vous ne voulez pas que vos données soient diffusées ») bien réfutés. Je ne vais pas en discuter ici, je ne cherche pas à défendre Google :-) Mais le problème est qu'Iteanu semble considérer qu'il n'y a menace pour les citoyens que lorsqu'elle vient d'un GAFA états-unien. Ainsi, la section sur la liberté d'expression oppose « liberté d'expression » et « freedom of speech » (en anglais dans le texte, pour bien montrer que c'est un concept étranger). L'idée est que le « freedom of speech » est absolu (et permet donc des discours racistes, par exemple), alors que la liberté d'expression est bornée par la loi. D'abord, cette opposition États-Unis-premier-amendement-freedom-of-speech-totale vs. France-pays-de-raison-et-de-mesure est largement fausse. Le premier amendement ne crée pas une liberté d'expression totale. Il dit juste que l'État ne doit pas la limiter. Cela laisse les entreprises privées ou des groupes de citoyens libres de limiter la liberté tant qu'ils veulent (cf. les censures de Facebook, par exemple). Mais, surtout, tout le chapitre sur la liberté d'expression fait comme si le seul problème lié à la liberté d'expression était l'abus que certains en font, pour de la propagande nazie, par exemple. Les menaces contre la liberté d'expression ne sont pas mentionnées. Et l'état d'urgence en France n'est jamais cité.
La tonalité « souverainiste » du livre est d'ailleurs assez agaçante. Les seuls reproches faits aux institutions françaises ou européennes sont de trop céder aux pressions états-uniennes. À lire ce livre, on a un peu l'impression que les États en Europe et notamment en France ne font jamais rien de dangereux ou de négatif, et que la seule question politique est de résister aux empiètements des GAFA et du gouvernement de Washington. L'auteur fait remarquer à juste titre que le passage du règne de la loi à celui de CGU dictées par une entreprise capilatiste n'est pas un progrès, mais cette dénonciation serait plus convaincante si elle était accompagnée d'une critique de la loi (qui est présentée comme l'expression indiscutable de la volonté du peuple).
Sur la vie privée (opposée à la « privacy » anglo-saxonne), Iteanu pointe à juste titre le danger de la surveillance massive que fait le gouvernement états-unien, notamment via la NSA, et le fait que le défunt Safe Harbor soit « un chiffon de papier ». Mais il ne mentionne qu'en passant, et sans critiques, les contributions françaises à la surveillance, comme la loi Renseignement.
Sur le droit d'auteur, Iteanu reprend la théorie comme quoi il y aurait une différence de philosophie entre « droit d'auteur » et « copyright » anglo-saxon, et que cette différence aurait des conséquences pratiques (ce qui n'est pas vraiment le cas). Par contre, il est cette fois bien plus critique pour le système français, pointant l'inefficacité et l'injustice du système répressif que symbolise en France la HADOPI.
Enfin, la partie sur la gouvernance de l'Internet critique logiquement l'ICANN (le livre a été écrit avant le léger changement des relations entre l'ICANN et le gouvernement états-unien le 1er octobre 2016, mais cela a peu d'importance). L'ICANN est une cible facile (et justifiée) mais il est dommage que l'ONU soit citée comme alternative crédible, sans l'once d'une critique. Iteanu cite entre autres des gens dont la crédibilité est très faible, comme Bellanger qui, dans un article fumeux, accusait Google de détournements imaginaires.
(Les techniciens pinailleurs comme moi seront surpris du
tableau présentant les serveurs racine, et
plus précisément de sa dernière colonne, « suffixe du nom de
domaine », qui place la NASA dans un
curieux .usg
, ne met pas l'armée
états-unienne sous
.mil
, et voit le
RIPE-NCC en
.int
. De toute façon,
aujourd'hui, tous les serveurs racine sont nommés sous
.net
.)
En résumé, l'analyse des GAFA, de leur attitude, des menaces qu'ils représentent pour la vie privée ou pour la souveraineté nationale, est très bonne et résume bien le problème. Mais l'« oubli » complet des menaces venant d'autres acteurs, comme l'État français ou comme les entreprises françaises, diminue sérieusement l'intérêt du livre. Olivier Iteanu connait bien son sujet (et évite donc de parler des pires énormités souverainistes comme le cloud souverain ou l'OS souverain) mais, hélas, il se laisse trop emporter par un point de vue national.
Tiens, ça me donne envie de parler en anglais. Full disclosure : j'ai reçu un exemplaire gratuit de ce livre.
Date de publication du RFC : Octobre 2016
Auteur(s) du RFC : T. King, C. Dietzel (DE-CIX
Management), J. Snijders
(NTT), G. Doering (SpaceNet
AG), G. Hankins (Nokia)
Pour information
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 20 octobre 2016
Lorsqu'on est soumis à une sérieuse attaque par déni
de service volumétrique, il faut parfois sacrifier la
machine qui en est la cible, afin de préserver le reste des
ressources réseau. On demande alors à son opérateur de jeter le
trafic à destination de cette machine, avant qu'il n'emprunte la
liaison qu'on veut préserver. Cela peut se faire manuellement mais
c'est évidemment plus rapide et moins risqué si on le fait
automatiquement, via une annonce BGP vers
le préfixe visé. Pour
cela, on marque l'annonce BGP avec une
communauté (RFC 1997)
qui veut dire « poubelle donc tout ce trafic ». Ce nouveau
RFC normalise une communauté standard,
« bien connue », pour cela, BLACKHOLE
(0xFFFF029A). Ainsi, il n'y aura plus besoin d'utiliser une
communauté différente pour chaque opérateur.
Cette méthode consistant à envoyer le trafic destiné à la victime vers un « trou noir » (blackholing) est décrite dans les RFC 3882 et RFC 5635. Comme elle agit au niveau IP, elle ne nécessite pas d'équipements spéciaux, et elle est très rapide, ne prenant que peu de ressources chez les routeurs. Par contre, elle est peu subtile : tout le trafic à destination d'un préfixe donné (préfixe en général réduit à une seule adresse IP, celle de la machine attaquée) est jeté, qu'il fasse partie de l'attaque ou pas. Quel est l'intérêt de couper tout le trafic ? Cela réalise l'objectif de l'attaquant, non ? C'est en effet une mesure désespérée mais rationnelle : son but est de préserver les ressources réseau pour que les autres machines fonctionnent. Si vous êtes connecté à l'Internet par une liaison à 10 Gb/s, et qu'une attaque de 20 Gb/s frappe votre opérateur, votre ligne va être complètement inutilisable. Aucune action de votre côté n'y changerait rien, dès que les paquets sont arrivés chez vous, c'est trop tard. Ce RFC traite le cas où on demande à l'opérateur de jeter le trafic avant qu'il ne soit envoyé sur la ligne entre l'opérateur et vous.
Le problème (section 1 du RFC) est qu'il existait plusieurs méthodes pour déclencher cet envoi dans un trou noir, ce qui compliquait la tâche des équipes réseau, une annonce BGP marquée avec une certaine communauté, une annonce BGP avec un certain next hop, et des méthodes non-BGP (dont le coup de téléphone au NOC). D'où la solution de notre RFC, définir une communauté standard. Plus besoin de se poser de question (à part celle de savoir si votre opérateur accepte cette commande, voir les sections 3.3 et 4). Au passage, les communautés BGP sont décrites dans le RFC 1997.
Une communauté BLACKHOLE
est donc définie
(section 2)
et mise dans le registre IANA des
communautés bien connues. Sa valeur est 0xFFFF029A. Le 666 à la
fin vient de la Bible et
était déjà couramment employé par les opérateurs. Notez donc que
ce RFC n'invente pas une nouvelle technique (demander à son pair
de jeter certains paquets est une technique très ancienne), il lui
donne juste une communauté standard.
Voilà, c'est tout, juste une réservation d'un nom et d'une
valeur. Si vous êtes intéressés par les détails pratiques, la
section 3 est consacrée aux problèmes opérationnels. D'abord, un
point essentiel : accepter des annonces BGP étiquetées
BLACKHOLE
est un choix local. Aucun opérateur
n'est obligé de respecter cette demande et, dans ce cas, ladite
communauté est ignorée. Lorsqu'on se connecte à
un nouveau pair BGP, il peut donc être prudent de lire leur
documentation ou de leur poser la question. N'utilisez
BLACKHOLE
qu'entre des adultes
consentants. (Notez que cet avertissement du RFC est un peu
contradictoire avec l'avantage proclamé de la normalisation de
BLACKHOLE
: en pratique, on est toujours
obligé de savoir ce que fait son pair, on ne peut pas compter sur
une méthode standard qui marcherait partout.) Une liste des
opérateurs et points d'échange qui acceptent
BLACKHOLE
est disponible
en ligne.
Si tout le monde accepte BLACKHOLE
, on
s'en sert comment ? Lorsqu'une attaque DoS
est en cours, on annonce un préfixe qui couvre l'adresse IP visée,
et on y ajoute cette communauté. On peut aussi utiliser
BLACKHOLE
pour les annonces du RFC 5635 (mais pas avec celles du RFC 5575).
Attention à ne pas propager ces annonces ! En effet, étant en
général très spécifiques (souvent une seule adresse IP), elles
seraient préférées, si elles étaient insérées dans une table de
routage. Leur effet est prévu
pour être strictement local et, donc, les annonces doivent être marquées avec la
communauté NO_EXPORT
(ou
NO_ADVERTISE
).
En parlant de spécificité, quelle doit être la longueur des
préfixes annoncés avec un BLACKHOLE
attaché ?
Souvent, l'attaque ne vise qu'une seule adresse et, donc, les
annonces BLACKHOLE
seront souvent des /32 (en
IPv4) et /128 (en IPv6), afin de ne sacrifier que le strict
minimum de son réseau. Si vous avez une politique BGP de n'accepter
que des préfixes plus généraux, c'est un point à
modifier. Aujourd'hui (RFC 7454, section
6.1.3), les préfixes plus spécifiques que /24 (IPv4) et /48 (IPv6)
sont rarement acceptés. Il faut donc faire des exceptions pour les
trous noirs.
Lorsqu'un opérateur reçoit une de ces annonces « envoie-moi
tout ça dans un trou noir », que doit-il vérifier ? Comme le
résultat de cette annonce est de jeter tout le trafic, une attaque
avec une annonce mensongère, ou bien une erreur d'un opérateur
maladroit, pourrait avoir de sérieuses conséquences. Notre RFC
recommande donc un certain nombre de tests de vraisemblance :
vérifier que le pair est autorisé à annoncer un préfixe couvrant
celui qu'il annonce avec BLACKHOLE
, et
vérifier que BLACKHOLE
avec ce pair a été
spécifiquement permis (le RFC recommande plus loin que ce ne soit
pas permis par défaut). Même chose s'il y a des
serveurs de route (RFC 7947) sur le trajet.
Par contre, il faut, pour le cas spécifique des annonces
BLACKHOLE
, débrayer les techniques de
validation comme celle du RFC 6811. Par
exemple, si un ROA (Route Origin Authorisation, RFC 6482) autorise une longueur maximale de préfixe de /48,
l'annonce BLACKHOLE
de longueur /128 doit
quand même être acceptée.
À des fins de traçabilité, pour faciliter l'analyse a
posteriori d'une attaque, et du traitement qu'elle a reçu, le RFC
recommande de journaliser toutes les
annonces BLACKHOLE
. (Cela permettra, par
exemple, de repérer les pairs qui abusent du mécanisme,
cf. section 6.)
Si vous travaillez chez un éditeur de logiciels pour routeurs,
n'oubliez pas les conseils de la section 4, destinés aux
programmeurs. D'abord, l'acceptation des annonces « trou noir » ne
devrait pas être faite par défaut. Le RFC demande qu'une action
explicite de l'administrateur réseau soit nécessaire. D'autre
part, pour ne pas
avoir à taper la valeur numérique de cette communauté, le RFC
suggère de permettre une valeur texte à indiquer, par exemple
blackhole
.
Quelques petits points sur la sécurité pour finir (section
6). D'abord, bien se rappeler que BGP n'a par défaut aucun
mécanisme pour empêcher ou détecter les modifications des
annonces. Si un attaquant actif retire ou ajoute la communauté
BLACKHOLE
, ça ne se voit pas. Même le futur
BGPSec ne l'empêchera pas, puisqu'il ne protège pas les
communautés. Il y a donc des possibilités d'attaques par déni de
service de ce côté.
C'est entre autre pour cela que le RFC demande qu'on vérifie
qu'un pair qui annonce un préfixe avec
BLACKHOLE
est autorisé à le faire (RFC 7454, section 6.2.1.1.2).
Première rédaction de cet article le 19 octobre 2016
Je viens d'installer chez moi un routeur Turris Omnia. Ça fait quoi et ça sert à quoi ?
Voici ce routeur avec ses copains et copines (sonde RIPE Atlas et Raspberry Pi de supervision) : (Version non réduite) Rassurez-vous, on peut contrôler par un bouton la luminosité des diodes (très intense par défaut).
Le Turris Omnia est avant tout un routeur pour la maison ou la petite entreprise. En tant que routeur, il... route, c'est-à-dire qu'il fait passer les paquets d'un réseau à l'autre, en l'occurrence entre le réseau de la maison et celui du FAI et, via ce dernier, à tout l'Internet. C'est donc l'équivalent de la box qui, en France (mais pas ailleurs) est souvent fournie par le FAI.
La différence principale est que l'Omnia ne comprend que du
logiciel libre et est ouvert, au sens où on
est super-utilisateur sur cette
machine et où on peut la configurer comme on veut, contrairement
aux boxes fermées dont
on ne sait pas exactement ce qu'elles font (elles peuvent par
exemple surveiller
le trafic, même local). L'Omnia n'est pas conçu par une
boîte commerciale mais par le registre du
.cz
, une organisation
sans but lucratif (qui développe des tas de choses
intéressantes).
D'autre part, des tas de services qui devraient être de base en 2016 (IPv6, validation DNSSEC) sont disponibles en série sur l'Omnia.
Si vous n'êtes pas technicien, je vous préviens que l'Omnia est installable et configurable sans trop de difficultés mais que toute adaptation un peu sérieuse nécessite, pour l'instant, de bonnes compétences d'administrateur système et réseau.
Suivons maintenant l'ordre chronologique de la mise en route. Commençons par le matériel. Voici l'Omnia vue de devant, posée sur le T-shirt (optionnel...) : (Version non réduite).
Je n'ai pas encore essayé la console série, il faudrait ouvrir la boîte et connecter les fils. Voici l'arrière de la boîte. Les antennes Wi-Fi ne sont pas encore montées (les connecteurs dorés en haut). Le port SFP est rare sur ce genre de routeurs à la maison, mais je ne l'ai pas encore utilisé (il peut permettre des connexions directes à une fibre optique, par exemple) : (Version non réduite).
Et voici l'Omnia ouverte, pour les amateurs d'électronique (la documentation du matériel est en ligne) : (Version non réduite). Curieusement, une vis avait été oubliée à l'intérieur... J'ai découvert par la suite que c'était une des vis censées tenir les cartes Wifi. Le Turris Omnia a 1 ou 2 Go de RAM (j'ai le modèle à 1 Go), un processeur ARM à 1,6 Ghz, une Flash de 8 Go, et quelques trucs que les électroniciens adoreront comme des ports GPIO.
Attention à vérifier les connecteurs des antennes radio. Dans mon cas, ils étaient mal vissés, ce qui faisait que les antennes tombaient et, ce faisant, tournaient la petite carte située derrière les connecteurs, ce qui arrachait le fil menant à la carte WiFi. Bien serrer ces connecteurs avant de commencer.
Branchons-la, maintenant. Je suis abonné chez
Free et, par défaut, c'est leur boitier qui
fait l'interface physique avec la ligne
ADSL (de toute façon, l'Omnia n'a pas de
prise adaptée, à moins de passer par le SFP ?). J'ai donc décidé de garder la
Freebox, mais elle s'occupe uniquement de
la télévision, du téléphone fixe, et du branchement à l'ADSL. Tout
le routage, le réseau local et le Wi-Fi
sont faits par l'Omnia. Je laisse donc le Freebox
Player (la boîte qui sert à la télé) branchée au
Freebox Server (la Freebox proprement dit),
comme avant. Et je passe la Freebox en mode
« bridge ». Avec cette configuration, la télévision classique
continue à fonctionner (regarder la télévision, gérer ses
enregistrements via
http://mafreebox.freebox.fr/
, etc). Le
téléphone marche aussi. Pour le reste, je branche la prise WAN de
la Turris Omnia en Ethernet, sur le
commutateur du Freebox
Server. Les autres machines sont branchées sur le
commutateur de l'Omnia (ou utilisent son Wi-Fi). Il y a cinq ports
Ethernet utilisables.
Une fois l'Omnia et au moins un PC branché, on configure le
routeur via le Web, en se connectant à
http://192.168.1.1/
(rassurez-vous, tout cela
est bien expliqué dans le joli manuel papier de quatre pages livré
avec l'Omnia, ou bien en
ligne. Il y a deux interfaces Web de
configuration du Turris Omnia, Foris,
orientée débutant, et spécifique à l'Omnia, et LuCI, bien plus
riche, dont je
parlerai plus longuement après. Voici ce que voit le célèbre
M. Michu, lorsqu'il utilise Foris :
Free ne fournit apparemment pas
de mécanisme pour la configuration automatique
d'IPv6, il a donc fallu la faire à la main,
statiquement.
Contrairement au Turris précédent, cette fois, on n'est plus obligé de parler la langue de Karel Čapek avec l'Omnia. Presque tout est traduit. (Mais pas encore les divers HOWTO en ligne.) C'est un progrès appréciable pour le non-polyglotte qui, en 2014, avec l'ancien Turris, recevait des notifications du genre « Upozorneni od Vaseho routeru Turris ##### Oznameni o aktualizacich ##### • Nainstalovaná verze 82 balíku updater... ». La documentation de Foris est très détaillée, et il est recommandé de la lire (par exemple pour configurer le Wi-Fi, lorsque Foris demande à M. Michu s'il veut du 2,4 GHz ou du 5 GHz... Au passage, l'Omnia peut faire les deux, en configurant deux interfaces avec des fréquences différentes, ce qui ne semble possible qu'avec LuCI ou le fichier texte de configuration.)
Si on découvre des bogues à signaler, il faut écrire à
info@turris.cz
qui répond bien. Il y a aussi
un canal IRC #turris
à
Freenode (peu d'activité). Questions forums collectifs, il y avait
un système de forums (avec les menus uniquement en
tchèque) qui a été abandonné au profit de
Discourse,
que je recommande d'utiliser (on a des réponses). Il est
apparemment nécessaire, pour se loguer, d'avoir mojeID (ce que j'utilise) ou bien un compte
sur un GAFA.
Ensuite, tout fonctionne, le routeur route, on peut regarder des vidéos de chats, envoyer du courrier, parler avec les copains en XMPP, télécharger de la culture, etc.
Notez que le routeur est sécurisé par défaut. Le pare-feu interne, dans sa configuration d'origine, bloque les connexions entrantes. (IPv4 et IPv6, bien sûr, une fonction qui manque terriblement à la Freebox, cf. RFC 6092.) De même, le routeur a SSH et un résolveur DNS mais n'accepte pas les connexions SSH ou DNS de l'extérieur. (Parfois, c'est même trop sécurisé.)
Une autre particularité du Turris Omnia est que le routeur se met à jour tout seul, récupérant automatiquement les nouvelles versions des logiciels, afin de corriger notamment les failles de sécurité (c'est évidemment configurable, via l'onglet Updater de Foris). C'est en effet une défaillance courante chez ces petits engins installés à la maison : le code n'est pas mis à jour et de vieilles failles durent longtemps. Tous les matins, on peut voir sur Foris ce qui a été changé :
On peut aussi le recevoir via le système de notification par courrier. Le Turris peut envoyer des messages via les MTA de NIC.CZ ou bien via le vôtre si vous la configurez ainsi (dans Maintenance).
Le Turris permet également d'envoyer ses données de trafic dans le nuage. Ce n'est évidemment pas activé par défaut mais, si on veut aider la science, cela se fait par l'onglet Data collection de Foris (« we'd like to inform you that you agreed with our EULA regarding data collection of your router »). Une fois cet envoi activé, et un compte sur le portail créé via le Turris, on pourra se connecter sur le portail (mojeID était nécessaire mais ce n'est plus le cas) et voir des jolis graphes de son trafic :
Naturellement, l'administrateur système consciencieux, même s'il se nomme Michu, va faire des sauvegardes. L'interface Foris a une option Configuration backup dans son onglet Maintenance.
Passons maintenant à l'interface Web avancée, LuCI. Elle n'est pas spécifique à l'Omnia et est au contraire bien connue des utilisateurs d'OpenWrt, système sur lequel est bâti l'Omnia. Ce n'est pas génial d'avoir deux interfaces Web pour la configuration, je trouve. Mais LuCI est indispensable pour les fonctions avancées, comme la configuration du pare-feu. Voici l'écran principal de LuCI :
LuCI peut servir à regarder l'état de certaines fonctions, ici le pare-feu :
Mais aussi à configurer des fonctions comme, ici, le commutateur interne avec ses VLAN (je n'ai pas encore testé mais cela semble nécessaire si on veut connecter le Freebox Player au réseau local) :
On peut aussi installer des programmes supplémentaires depuis LuCI. Le premier que j'ai mis était Majordomo (rien à voir avec le gestionnaire de listes de diffusion du même nom). Il permet d'intéressantes statistiques par machine (là aussi, quelque chose qui me manque sur la Freebox) :
Le vrai geek va sans doute vouloir se connecter à son beau routeur libre en SSH (chose qu'on ne peut certainement pas faire avec la Freebox...). Une fois le serveur activé (Advanced administration dans Foris mais attention avec SSH, une bogue sérieuse est décrite plus loin) :
% ssh root@turris Password: BusyBox v1.23.2 (2016-09-05 13:26:40 CEST) built-in shell (ash) _______ _ _ _____ _____ _____ _____ |__ __|| | | || __ \ | __ \ |_ _| / ____| | | | | | || |__) || |__) | | | | (___ | | | | | || _ / | _ / | | \___ \ | | | |__| || | \ \ | | \ \ _| |_ ____) | |_| \____/ |_| \_\|_| \_\|_____||_____/ root@turris:~# sensors armada_thermal-virtual-0 Adapter: Virtual device temp1: +86.1°C
Notez que je ne connais pas de moyen de connaitre le condensat de la clé publique SSH créée, depuis l'interface Web. On ne peut donc pas vérifier, la première fois, qu'on se connecte bien à son Turris Omnia.
Le Turris Omnia utilise OpenWrt, un Unix (avec noyau Linux). La plupart des commandes seront donc familières aux unixiens :
root@turris:~# uptime 11:32:39 up 1 day, 3:35, load average: 0.02, 0.05, 0.01 root@turris:~# df -h Filesystem Size Used Available Use% Mounted on /dev/mmcblk0p1 7.3G 180.5M 7.1G 2% / tmpfs 503.7M 6.9M 496.9M 1% /tmp tmpfs 512.0K 4.0K 508.0K 1% /dev root@turris:~# dig fr.wikipedia.org ; <<>> DiG 9.9.8-P4 <<>> fr.wikipedia.org ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38235 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;fr.wikipedia.org. IN A ;; ANSWER SECTION: fr.wikipedia.org. 3 IN A 91.198.174.192 ;; Query time: 7 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Wed Oct 19 11:36:54 UTC 2016 ;; MSG SIZE rcvd: 61 root@turris:~# uname -a Linux turris 4.4.13-05df79f63527051ea0071350f86faf76-7 #1 SMP Mon Sep 5 13:01:10 CEST 2016 armv7l GNU/Linux
Pour mémoire, l'ancien Turris, avant l'Omnia, affichait :
root@turris:~# uname -a Linux turris 3.10.18-b09ae823eeafb345725b393bc5efbba7 #1 SMP Tue May 6 16:24:28 CEST 2014 ppc GNU/Linux
Et n'avait que 250 Mo de stockage.
Le résolveur par défaut du Turris Omnia, l'excellent Knot Resolver (produit par la même organisation que Turris), valide avec DNSSEC (comme tout le monde devrait faire, en 2016). Dommage, il reste encore des sérieuses bogues (comme une mauvaise indication du résultat ou comme l'impossibilité de couper la validation).
Un des avantages du shell est qu'on peut
faire tout ce qu'on veut. Ainsi, le système de sauvegarde par
l'interface Foris dont je parlais plus haut ne sauvegarde que
/etc/config
. Si on veut tout garder, on peut
le faire avec un script et cron.
Pour faire quoi que ce soit sur l'Omnia, il vaut mieux connaitre OpenWrt (son Wiki, ses forums...) Par exemple, si vous préférez joe à vi (et, non, je n'ai pas trouvé d'emacs sur OpenWrt, système conçu pour des engins contraints en ressources matérielles) :
root@turris:~# opkg list | grep -i editor joe - 4.2-1 - Joe is world-famous Wordstar like text editor, that also features Emacs and Pico emulation nano - 2.6.0-1 - Nano (Nano's ANOther editor, or Not ANOther editor) is an enhanced clone of the Pico text editor. vim - 7.4-3 - Vim is an almost compatible version of the UNIX editor Vi. (Tiny build) zile - 2.3.24-4 - Zile is a small Emacs clone. Zile is a customizable, self-documenting real-time display editor. Zile was written to be as similar as possible to Emacs; every Emacs user should feel at home with Zile. ... root@turris:~# opkg install joe Installing joe (4.2-1) to root... Downloading https://api.turris.cz/openwrt-repo/omnia/packages//packages/joe_4.2-1_mvebu.ipk. % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 238k 100 238k 0 0 589k 0 --:--:-- --:--:-- --:--:-- 602k Configuring joe.
La configuration IPv6 ne s'est pas faite
toute seule (ce n'est pas entièrement la faute du Turris mais un peu
quand même). Par défaut, le Turris distribue sur le réseau local des
ULA (RFC 4193) comme
fde8:9fa9:1aba:0:X:W:Y:Z
. Pour réaliser la
configuration en étant connecté à Free, j'ai suivi un bon HOWTO de
OpenWrt mais il y manque un point important, la route par
défaut statique (à ce sujet, cela vaut aussi la peine de consulter la
documentation
OpenWrt sur le réseau). Donc, ce que j'ai du faire :
ifconfig eth1
),http://mafreebox.freebox.fr/
, « Paramètres de
la Freebox » puis « Configuration IPv6 »), mettre cette adresse en
Next hop pour le préfixe que nous a alloué
Free,/etc/config/network
) comme indiqué dans le
HOWTO ci-dessus,
Cela donc un /etc/config/network
qui ressemble
à (si 2001:db8:cafe:1234::1:fe/64
est le préfixe IPv6
alloué par Free, celui qu'on trouve dans l'interface Web de la Freebox) :
config interface 'lan' option ifname 'eth0 eth2' option force_link '1' option type 'bridge' option proto 'static' option netmask '255.255.255.0' option ipaddr '192.168.1.1' option ip6addr '2001:db8:cafe:1234::1:fe/64' option ip6prefix '2001:db8:cafe:1234::/64' option ip6gw '2001:db8:cafe:1234::1' option ip6assign '64' option mtu '1452' config interface 'wan' option ifname 'eth1' option proto 'dhcp' option mtu '1452' config interface 'wan6' option ifname '@wan' option _orig_bridge 'false' option proto 'static' option ip6addr '2001:db8:cafe:1234::2/126' option ip6gw '2001:db8:cafe:1234::1' option ip6prefix '2001:db8:cafe:1234::/64' # Route par défaut statique config route6 option interface 'wan6' option target '::/0' option gateway 'fe80::f6ca:e5ff:fe4d:1f41'
Si vous êtes attentifs, vous aurez remarqué qu'on force une MTU à 1 452 octets. L'IPv6 de Free en ADSL n'étant pas natif (mais un tunnel 6rd, cf. RFC 5969), ce réglage était nécessaire pour éviter les symptômes habituels d'un problème de PMTUD (ping qui marche mais pas curl, etc).
Si votre FAI ne fournit pas IPv6, le Turris Omnia permet d'établir un tunnel, en théorie, mais je n'ai jamais testé.
Autre jouet amusant, le Turris a un pot de
miel configurable, pour SSH et telnet. Les sessions
capturées sont également transmises aux responsables du
projet et visibles via le portail des utilisateurs (mon premier
« pirate » venait de Turquie et a tapé
uname -a
).
Passons maintenant aux problèmes, car le logiciel a des bogues embêtantes. J'ai eu beaucoup d'ennuis avec
le serveur NTP. Rien ne marchait. J'ai du finalement désactiver le
serveur par défaut (/etc/config/system
,
option enabled '0'
) et
ntpclient
, puis installer ntpd qui, lui,
fonctionne. (Normalement, sur OpenWrt, cela aurait
du marcher tout seul, la doc le
dit). Attention, supprimer avec opkg le paquetage ntpclient ne suffit
pas, la mise à jour automatique de l'Omnia le réinstalle. Maintenant,
la synchronisation temporelle marche :
root@turris:~# ntpq ntpq> peers remote refid st t when poll reach delay offset jitter ============================================================================== +mx4.nic.fr 138.96.64.10 2 u 585 1024 377 8.661 -1.611 1.186 webcgi1-g20.fre .INIT. 16 u - 1024 0 0.000 0.000 0.000 webcgi2-g20.fre .INIT. 16 u - 1024 0 0.000 0.000 0.000 +pob01.aplu.fr 40.179.132.91 2 u 555 1024 377 10.465 -4.789 4.553 -host3.nuagelibr 138.96.64.10 2 u 193 1024 377 10.405 3.660 2.096 vel.itat.io 131.188.3.223 2 u 98 1024 1 25.894 0.007 0.230 *cluster004.lino 82.95.215.61 2 u 557 1024 377 7.166 -0.876 0.973
Et les machines du réseau local peuvent se synchroniser sur le
Turris. (Au passage, la commande ntpq
est dans le
paquetage ntp-utils
.)
Second problème sérieux, avec le serveur SSH. Pour un
certain nombre d'utilisateurs de l'Omnia, la création des clés
SSH de la machine se passe mal et des fichiers de taille zéro sont
créés (et cela ne se produit pas uniquement, contrairement à ce que
racontent certains, lors d'une coupure de courant). Cela empêche
évidemment le serveur SSH de démarrer. On ne peut donc pas se
connecter au shell pour arranger les choses. Il faut alors utiliser le
port USB comme port série (je n'ai pas essayé)
ou bien réparer le problème entièrement depuis LuCI
(System puis Custom commands) en
exécutant de quoi rétablir le système. Et l'interface de LuCI est
pénible pour cela (par exemple, ssh-keygen -N ""
ne marchera pas car LuCI supprime la chaîne vide...). J'ai donc du
définir des commandes rm -f /etc/ssh/ssh_host_ecdsa_key
/etc/ssh/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_ecdsa_key
/etc/ssh/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_rsa_key
/etc/ssh/ssh_host_rsa_key.pub /etc/ssh/ssh_host_dsa_key
/etc/ssh/ssh_host_dsa_key.pub /etc/ssh/ssh_host_ed25519_key
/etc/ssh/ssh_host_ed25519_key.pub
(eh non, pas droit aux
jokers) puis ssh-keygen -A
puis
/etc/init.d/sshd start
.
Autre méthode pour s'amuser, jouer avec les VLAN. En faisant une erreur dans la configuration du commutateur de l'Omnia, j'avais déclenché une tempête de trafic interne qui rendait le routeur totalement inutilisable. Même pas moyen de se connecter en SSH pour réparer. L'erreur étant dans la configuration, redémarrer ne servait à rien (l'Omnia n'a apparemment pas de mémorisation temporaire des configurations réseau potentiellement dangereuses, comme ça existe sur JunOS). Le port série aurait peut-être été une solution mais il y avait plus simple : remettre l'Omnia à sa configuration d'usine, se reconnecter, et restaurer la configuration sauvegardée.
Voilà, prochaine étape, installer un serveur SNMP...
Quelques autres lectures sur le Turris Omnia :
PS : si vous voulez acheter un Turris Omnia (j'ai eu le mien via le crowdfunding), voyez cette annonce.
Première rédaction de cet article le 17 octobre 2016
Aujourd'hui, bien des clients d'Orange ont eu la mauvaise surprise de ne pas pouvoir visiter Google. La plupart n'avaient pas de messages d'erreur précis, juste une longue attente et un message d'erreur vague du genre « timeout ». Certains avaient la désagréable surprise de voir apparaitre une page menaçante, les accusant d'avoir voulu se connecter à un site Web terroriste. À l'origine de ce problème, une erreur de configuration dans les résolveurs DNS d'Orange, en raison de la fonction de censure administrative du Web.
D'abord, voyons l'étendue du problème. Il n'affectait que les
clients d'Orange, et seulement ceux qui
utilisaient les résolveurs DNS de
l'opérateur (voir plus loin pour une définition des termes
techniques). Les sites inaccessibles incluaient
, mais aussi
http://www.google.fr/
,
http://fr.wikipedia.org/
et quelques
autres. Beaucoup d'utilisateurs ont imputé le problème à Google à
tort (mot-croisillon http://www.ovh.com/
#GoogleDown
sur
Twitter, ce qui était complètement erroné).
Il est rapidement apparu que le problème venait du
DNS. Ce système permet d'associer à un nom de domaine (comme www.afnic.fr
ou youtube.com
) des données techniques, comme l'adresse IP de
la machine serveuse. Cette adresse IP est indispensable au bon fonctionnement de l'Internet. Résoudre (traduire)
un nom de domaine en adresse IP est le travail
de deux sortes de serveurs DNS : les serveurs faisant autorité, qui
connaissent le contenu d'une partie du DNS (par exemple, les serveurs faisant autorité gérés par l'AFNIC
connaissent le contenu de .fr
, les serveurs faisant autorité pour cfeditions.com
connaissent le contenu de
cfeditions.com
, etc), et les résolveurs. Ces derniers ne connaissent rien mais, demandant aux serveurs faisant
autorité, et mémorisant leur réponse (ce que les informaticiens appellent, bizarrement, « cacher »), ils
obtiennent l'information qu'ils distribuent aux utilisateurs. Les
résolveurs sont typiquement gérés par les FAI (comme Orange) mais il existe aussi des serveurs publics comme ceux de FDN.
L'utilisateur de l'Internet n'a en général pas à s'en soucier, son FAI lui indique automatiquement ses résolveurs
et tout roule.
Normalement, donc, un résolveur n'a pas de données propres et se contente de relayer entre l'utilisateur et le serveur faisant autorité. Mais, comme quasiment toute communication Internet commence par une requête DNS, il est tentant, lorsqu'on souhaite contrôler l'usage de l'Internet, de demander aux résolveurs de mentir, c'est-à-dire de donner une information qui n'est pas celle venue du serveur faisant autorité. C'est ce qui est prévu en France en application du décret n° 2015-125 du 5 février 2015. Le Ministère de l'Intérieur envoie aux principaux FAI une liste des domaines à bloquer (un article de Numérama détaille ce processus) et ceux-ci déploient la configuration nécessaire dans leurs résolveurs.
Mais, ce lundi matin, lorsqu'on interrogeait les résolveurs d'Orange au sujet de l'adresse IP de www.google.fr
, au
lieu de répondre avec l'adresse contenue dans les serveurs faisant autorité pour google.fr (serveurs gérés par
Google), par exemple 216.58.211.99
, ils répondaient 90.85.16.52
, une adresse appartenant à un sous-traitant du Ministère de l'Intérieur.
Lorsqu'un navigateur Web se connecte à cette adresse, il obtient normalement une page l'avertissant que le nom de
domaine fait partie de ceux qui sont bloqués, et un motif est indiqué
(promotion du terrorisme, par exemple, comme dans l'image ci-dessus).
Mais ce serveur était bien trop faible pour encaisser l'énorme trafic de Google et de Wikipédia, et a vite cessé de fonctionner correctement. C'est ce qui explique l'absence de réponse fréquemment rencontrée, faisant croire aux utilisateurs que Google était en panne. (Une autre raison est que la plupart des accès à Google se font désormais en HTTPS et que le serveur du Ministère ne gère pas HTTPS, ne répondant pas, même pas par un refus de connexion.)
Comment une telle bavure a pu se produire ? L'erreur était-elle dans la liste envoyée par le Ministère de l'Intérieur ou bien uniquement chez Orange ? On n'a évidemment pas d'information à ce sujet (les pannes Internet ne font jamais l'objet d'analyses indépendantes et publiques, ce qui explique que la sécurité ne progresse guère). Tout est possible, y compris des erreurs humaines qui sembleraient invraisemblables (mais on voit vraiment de tout dans le monde réel). Une des hypothèses les plus intéressantes (elle explique notamment pourquoi il y a eu plusieurs noms touchés) est celle d'un fichier de test installé par erreur à la place du « bon ».
Au fait, comment sait-on que les clients d'Orange (et uniquement eux) recevaient cette fausse information ? En effet, dans l'Internet d'aujourd'hui, complexe et international, une observation faite en un point n'est pas suffisante. Les clients d'Orange peuvent s'exclamer en chœur « Google est planté » et ceux de Free répondre « non, tout va bien ici ». Et les deux groupes ont raison... de leur point de vue. J'ai utilisé, outre les mesures faites par des experts chez différents FAI (merci, merci, merci), le réseau des sondes RIPE Atlas. Ces petits boitiers très utiles permettent de mesurer un certain nombre d'indicateurs techniques depuis de nombreux points du réseau. (Des détails pour les techniciens figurent à la fin de cet article.)
La panne elle-même, c'est-à-dire l'envoi de fausses informations par les résolveurs DNS d'Orange, a duré environ une heure. Mais son effet avait été prolongé par la mémorisation (les fameux « caches ») des informations dans certains composants du réseau (par exemple la « box » chez l'utilisateur). Cela fait que, plusieurs heures après, Google ou Wikipédia étaient toujours inaccessibles pour certains utilisateurs.
Les leçons à en tirer ? Le DNS est un composant critique de l'Internet et sa résilience, sa capacité à résister aux pannes et à repartir ensuite, est donc cruciale. D'où l'importance de l'Observatoire de la résilience Internet. Toute interférence avec le fonctionnement du DNS, que ce soit pour des raisons politiques ou autres, le met potentiellement en péril. C'est ce qu'avait analysé le rapport du Conseil Scientifique de l'AFNIC « Conséquences du filtrage Internet par le DNS », qui mettait bien en évidence le risque de tels filtrages ou blocages. Une bavure analogue à celle de Google était déjà arrivée au Danemark mais il semble que personne ne tire de leçons de l'expérience.
Que peuvent faire les utilisateurs face à de tels risques ? Le problème de fond est bien évidemment politique (la censure administrative, effectuée au mépris des contraintes opérationnelles) et doit donc être traité politiquement. Mais existe-t-il des solutions techniques ? Pour l'instant, la meilleure est d'avoir son propre résolveur DNS. Notez bien que je ne parle pas forcément d'un résolveur par machine à la maison. Cela peut être fait dans un équipement partagé, comme ce que permet le routeur Turris Omnia. Beaucoup de gens proposaient d'utiliser un résolveur DNS public. Ce n'est pas forcément une bonne solution. Google Public DNS a tous les inconvénients des services Google (bien expliqués dans le récent livre de Tristan Nitot). Cisco OpenDNS y ajoute le fait qu'il s'agit d'un résolveur menteur, comme ceux des principaux FAI français. Ceux d'OpenNIC marchent rarement et, de toute façon, sont une racine alternative, avec les inconvénients que cela présente. Et les résolveurs de FDN ? Ils sont honnêtes mais ils partagent un inconvénient commun avec presque tous les résolveurs DNS publics : ils n'offrent aucune authentification et rien ne garantit donc qu'on parle bien au résolveur qu'on veut. (C'est ainsi que Google Public DNS a déjà été détourné.)
Quelques lectures sur cet incident :
Le reste de cet article est uniquement pour les techniciens,
attention. Le script utilisé pour interroger les sondes Atlas est
décrit
ici. La commande exacte était atlas-resolve --as
3215 --requested 100 www.google.fr
,
l'AS 3215 étant
celui d'Orange.
La panne semble avoir duré d'environ 07:40 UTC à 08:35. Un utilisateur d'Orange qui testait avec dig voyait :
% dig A +short @192.168.10.1 www.google.fr 90.85.16.52 % dig A +short @8.8.8.8 www.google.fr 172.217.20.35
Les sondes Atlas, elles, voyaient :
% atlas-resolve --as 3215 -r 100 www.google.fr [74.125.24.94] : 1 occurrences [216.58.208.195] : 2 occurrences [74.125.206.94] : 2 occurrences [216.58.210.35] : 2 occurrences [216.58.210.227] : 3 occurrences [216.58.211.67] : 3 occurrences [172.217.16.67] : 2 occurrences [216.58.213.35] : 1 occurrences [216.58.211.99] : 2 occurrences [172.217.18.227] : 2 occurrences [216.58.204.3] : 1 occurrences [90.85.16.52] : 75 occurrences [216.58.208.227] : 2 occurrences Test #6886264 done at 2016-10-17T08:06:14Z
Remarquez que certaines sondes, minoritaires, voient la vraie
valeur, sans doute parce que le réseau où elles sont situées
n'utilise pas les résolveurs DNS d'Orange. Mais la grande majorité
voit le 90.85.16.52
mensonger. Un autre exemple
avec les sondes Atlas, mais en leur demandant d'utiliser un autre
résolveur (Google Public DNS) :
% atlas-resolve --as 3215 -r 100 -e 8.8.4.4 www.google.fr Nameserver 8.8.4.4 [172.217.18.227] : 3 occurrences [216.58.219.67] : 1 occurrences [172.217.23.67] : 1 occurrences [216.58.210.3] : 1 occurrences [216.58.211.67] : 8 occurrences [172.217.16.67] : 3 occurrences [216.58.210.163] : 1 occurrences [172.217.16.163] : 2 occurrences [172.217.19.131] : 8 occurrences [216.58.201.35] : 4 occurrences [74.125.206.94] : 4 occurrences [216.58.213.99] : 1 occurrences [172.217.23.99] : 1 occurrences [172.217.20.35] : 5 occurrences [216.58.208.227] : 10 occurrences [216.58.210.131] : 1 occurrences [216.58.204.67] : 2 occurrences [216.58.211.99] : 11 occurrences [216.58.210.227] : 8 occurrences [216.58.212.99] : 2 occurrences [172.217.23.3] : 1 occurrences [216.58.204.3] : 1 occurrences [216.58.208.163] : 1 occurrences [216.58.210.195] : 6 occurrences [216.58.192.99] : 1 occurrences [216.58.208.195] : 10 occurrences Test #6886273 done at 2016-10-17T08:13:06Z
Cette fois, personne ne voit le mensonge (notez que les serveurs DNS de Google servent des réponses très différentes, mais qui sont toutes dans un réseau Google). Notez aussi que d'autres services Google comme Gmail ou comme le spyware Analytics n'avaient aucun problème.
Wikipédia faisait partie des victimes, comme Google :
% atlas-resolve --as 3215 -r 100 fr.wikipedia.org [91.198.174.192] : 21 occurrences [90.85.16.52] : 73 occurrences [208.80.154.224] : 1 occurrences Test #6886283 done at 2016-10-17T08:22:22Z
Merci à tou·te·s c·eux·elles qui m'ont envoyé des informations et des résultats de mesure. Ça, c'est l'Internet, la coopération, l'échange d'informations et la décentralisation.
Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : F. Martin (LinkedIn), E. Lear (Cisco Systems), T. Draegen (dmarcian), E. Zwicky (Yahoo), K. Andersen (LinkedIn)
Pour information
Réalisé dans le cadre du groupe de travail IETF dmarc
Première rédaction de cet article le 11 octobre 2016
Le mécanisme DMARC permet d'indiquer
dans le DNS la politique d'un domaine
concernant l'authentification du courrier. Si je reçois un message
prétendant venir de ma-banque.example
, et
qu'il n'est pas authentifié (ni SPF, ni
DKIM, ni autre chose), comment savoir si
c'est parce que ma banque est nulle en sécurité du courrier, ou bien parce
que le message est un faux ? DMARC (normalisé dans le RFC 7489) permet de répondre à cette
question en publiant un enregistrement qui indique si le courrier
est censé être authentifié ou pas. Comme toutes les techniques de
sécurité, ce mécanisme est imparfait et il pose notamment des
problèmes avec les messages indirects. Par
exemple, si vous avez une adresse à votre ancienne université,
alice@univ.example
et que le courrier qui lui
est adressé est automatiquement transmis à votre adresse
professionnelle, alice@evilcorp.example
,
comment DMARC va-t-il réagir avec cette indirection ? C'est ce
qu'explore ce RFC.
Voici la politique DMARC de Gmail. Elle
est tolérante (p=none
, accepter les messages
non authentifiés) :
% dig TXT _dmarc.gmail.com ... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59294 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ... ;; ANSWER SECTION: _dmarc.gmail.com. 600 IN TXT "v=DMARC1; p=none; rua=mailto:mailauth-reports@google.com" ...
_dmarc.paypal.com. 300 IN TXT "v=DMARC1; p=reject; rua=mailto:d@rua.agari.com; ruf=mailto:dk@bounce.paypal.com,mailto:d@ruf.agari.com"
La question de départ de l'administrateur système est « si je
mets une politique DMARC restrictive (genre
p=reject
), vais-je perdre des courriers
légitimes, à cause d'indirections comme les listes de diffusion ? » (section 1 du
RFC). Il est d'autant plus difficile de répondre à cette question
que l'architecture du courrier électronique
est complexe et mal spécifiée (RFC 5598). Bien des logiciels ne suivent pas les règles,
d'autant plus que beaucoup de ces règles n'ont pas été explicites
dès le début. (Un bon exemple : avec un
.forward
, le serveur de courrier doit-il
garder l'expéditeur indiqué dans l'enveloppe
du message ? Essayez de trouver un RFC qui spécifie cela !)
La section 2 de notre RFC décrit les causes des problèmes
DMARC. Si un message est légitime (le destinataire veut le
recevoir), et qu'il est en outre techniquement correct, un
problème, au sens de ce RFC, est quand la politique de DMARC (qui
peut être de rejet) est appliquée à ce message, parce qu'il a été
transmis indirectement. C'est injuste. Évidemment, si la politique
DMARC est p=none
(ne rien faire), ce n'est
pas un vrai problème. Mais un p=reject
peut
être très ennuyeux.
Première cause de problèmes, des différences entre les
identificateurs utilisés. DMARC n'authentifie pas directement, il
dépend de SPF (RFC 7208) et DKIM (RFC 6376) pour cela. Ce qui intéresse l'utilisateur,
évidemment, c'est le nom dans le champ From:
(RFC 5322)
du message. Pour lui, c'est ça l'expéditeur. Mais DKIM, et surtout
SPF, n'ont pas la même conception : ils peuvent utiliser d'autres
identificateurs. DMARC considère que l'accord
(alignment, cf. RFC 7489, section 3.1) entre les identificateurs
authentifiés par SPF et DKIM, et le champ
From:
du message peut être strict ou
laxiste. « Strict » indique une correspondance parfaite, laxiste
se limite à vérifier que le nom de domaine
est le même.
Le principal identificateur utilisé par SPF est celui donné par
la commande
MAIL FROM
dans la session SMTP (RFC 5321). C'est la principale cause de
désaccord : si SPF authentifie cet identificateur et qu'il est
différent de l'adresse utilisée dans le champ
From:
de l'en-tête du message, que
faire ?
Deuxième cause de problème, le relayage d'un message. Si Bob
bob@isp.example
écrit à
alice@univ.example
, et qu'elle (ou son
administrateur système) a demandé un relayage automatique vers
alice@evilcorp.example
, les serveurs
de courrier de evilcorp.example
verront un
message prétendant être de isp.example
, mais
transmis par les serveurs de
univ.example
... SPF sera content ou pas,
selon la façon exacte dont a été fait le relayage (en préservant
le MAIL FROM
ou pas). DMARC ne sera jamais
content car, si le MAIL FROM
a été changé
(reflétant le relais), SPF authentifiera mais il n'y aura plus
d'accord entre les identificateurs.
Évidemment, si le message est modifié en cours de route, c'est encore pire. SPF ne protège pas l'intégrité du message, mais DKIM le fait. Mais qui diantre se permet de modifier les messages ? Hélas, pas mal de gestionnaires de listes de diffusion le font. DKIM a une option (déconseillée... voir la section 8.2 du RFC 6376) pour ne signer que le début du message, évitant ainsi que la signature soit invalidée par l'ajout, par exemple, d'un paragraphe final. Cela ne couvre que le cas des messages simples, sans MIME, où la modification est un simple ajout à la fin. Autre possibilité de DKIM pour éviter d'invalider les signatures en cas de modification du message, le mode relaxed de canonicalisation du contenu, qui permet de supporter des modifications triviales comme la transformation de N espaces consécutifs en un seul.
Reprenant le vocabulaire du RFC 5598
(relisez-le d'abord !), la section 3 de notre RFC liste les
différents composants de la messagerie qui peuvent jouer un rôle
dans les transmissions indirectes, et les problèmes qu'elles
posent. D'abord, le MSA (Message Submission
Agent.) C'est la première ligne de vérification : il fait
respecter les règles d'une organisation (ADMD,
ADministrative Management Domain). S'il accepte
un message où le champ From:
du RFC 5322 n'est pas dans un domaine contrôlé par
l'ADMD, il y a des chances que DMARC râle par la suite. Le RFC
cite plusieurs cas d'usage où cela se produit : la fonction
« envoyer cet article à un ami » de certains sites Web, par
exemple, puisque le message va partir avec le domaine du lecteur
de l'article, pas avec celui du site Web. On peut trouver de
nombreux autres exemples, comme un service de gestion d'agenda qui
envoie des courriers de rappel, en utilisant comme expéditeur
l'adresse de l'utilisateur, ce qui est plutôt une bonne chose
(pour des messages du genre « l'heure de la réunion a changé »)
mais peut gêner DMARC. (Mon exemple
préféré est le cas où
on a une adresse de courrier mais pas de moyen de soumettre du
courrier via cette organisation, ce qui est fréquent avec les
adresses de fonction. Par exemple, on est membre d'une
organisation qui fournit des adresses à ses membres et/ou
responsables, ce qui permet de recevoir du courrier, mais on n'a
pas de MSA pour en envoyer, on doit donc utiliser celui d'une
autre organisation.)
Et les MTA, eux, quel est leur rôle dans les problèmes DKIM ? S'il change l'encodage (par exemple en passant du « 8 bits » à l'abominable Quoted-Printable), il va invalider les signatures DKIM (la canonicalisation de DKIM ne prévoit pas des transformations aussi radicales, même si elles ne modifient pas le message final). Idem si le MTA corrige les en-têtes du message pour les rendre conformes (une tâche qui relève plutôt du MSA, le MTA devant lui, transmettre fidèlement les messages qu'il a choisi d'accepter) : cela sort également du champ de la canonicalisation DKIM et cela invalide donc les éventuelles signatures. Enfin, le changement ou la suppression de certaines parties MIME (par exemple l'élision d'un document ZIP attaché, pour des raisons de protection contre les logiciels malveillants transmis par courrier) va évidemment également rendre les signatures invalides.
Et le MDA ? Peut-il casser des choses, également ? Oui, s'il passe les messages par Sieve (RFC 5228), qui a la possibilité d'ajouter ou de retirer des en-têtes, voire de modifier le corps (extension Sieve du RFC 5703). Si les tests DMARC sont faits après le passage de Sieve, ou bien si le message est ensuite réinjecté dans le système de courrier, des problèmes peuvent se produire.
Reste le cas des intermédiaires
(mediators). Ce sont les entités qui prennent
un message, puis le ré-expédient (parfois après modification). Un
exemple est l'alias. Via une entrée dans
/etc/aliases
ou bien via un
.forward
, ou bien via le
redirect
de Sieve, ou encore via encore une autre
méthode, un message initialement destiné à une adresse est
finalement transmis à une autre. C'est par exemple courant pour
les adresses « ancien élève », que fournissent certaines
universités, et qui permettent de garder à vie une adresse dans le
domaine de l'établissement où on a fait ses études. Un certain
nombre d'associations professionnelles fournissent un service
équivalent. En général, ces intermédiaires ne cassent pas DKIM
(ils ne modifient pas le message) mais, selon la façon dont ils
redirigent, peuvent invalider l'autorisation SPF.
Un autre exemple d'intermédiaire classique est le gestionnaire
de listes de
diffusion. En plus de rediriger un message (ce qui
fait que le message écrit par
alice@univ.example
n'est
pas émis par les serveurs de courrier de
l'université), ces logiciels changent souvent le message, par
exemple en ajoutant une inutile étiquette [Ma jolie
liste]
aux sujets des messages, en ajoutant un texte à
la fin (instructions de désabonnement, pourtant déjà possibles
avec l'en-tête List-Unsubscribe:
), en retirant des pièces jointes, ou bien
(surtout dans les théocraties comme les États-Unis) en remplaçant
des gros mots par des termes plus acceptables.
Toutes ces modifications vont probablement invalider les
signatures DKIM (cf. RFC 6377) et faire que les
messages envoyés par certains participants à la liste (ceux qui
ont une politique DMARC p=reject
) ne seront
pas reçus par les destinataires qui testent cette politique. (Si
un avis de non-remise est transmis, le logiciel de gestion de la
liste peut en déduire que l'adresse n'existe pas, et désabonner
d'autorité le destinataire.)
Et les filtres ? Certaines organisations insèrent dans le
réseau des dispositifs qui vont analyser le courrier, par exemple
à la recherche de logiciel
malveillant. Souvent, ils vont modifier les messages,
afin de supprimer ces contenus indésirables. Ces modifications
vont évidemment invalider les signatures. Idem si on change ou
supprime des URL contenus dans le message
et considérés « dangereux ». Même chose avec un
système anti-spam qui ajouterait un [SPAM]
dans le sujet.
En revanche, le courrier reçu d'un serveur secondaire (MX de secours), qui a pris le relais pendant une panne du primaire, puis expédié le courrier quand le primaire remarche, ne pose pas de problèmes. Bien sûr, les tests SPF échoueront mais, normalement, on ne fait pas ces tests sur le courrier qui vient de son propre serveur secondaire.
Bon, voici le tour d'horizon complet de tout ce qui peut marcher mal. Mais que faire ? La section 4 du RFC s'attaque aux solutions. Elles sont nombreuses et très différentes. Mais attention : DMARC est là pour rejeter des messages considérés comme invalides. On peut arranger les choses pour que certains de ces messages « passent » mais cela va contre le but de DMARC. Si les messages sont de grande valeur (transactions financières, par exemple), il vaut mieux ne pas chercher de solutions, et simplement se contenter de messages transmis directement, ne subissant pas de traitements qui vont invalider SPF ou DKIM.
C'est d'autant plus vrai que l'écosystème du courrier électronique est très complexe. On trouve un zillion de logiciels différents, plus ou moins bien écrits. Par exemple, des gens utilisent encore Qmail, qui n'a plus eu une seule mise à jour depuis 1998. Certaines des mesures ou contre-mesures utilisées pour la sécurité du courrier sont parfaitement légales, mais vont casser tel ou tel logiciel qui est utilisé à certains endroits.
Assez d'avertissements, les solutions. D'abord, du côté de
l'expéditeur. Celui-ci (ou son premier MTA)
peut faire des efforts pour améliorer l'accord entre les
identificateurs. Un logiciel sur info.example
qui envoie du courrier pour le compte de
bob@univ.example
peut ainsi décider
d'utiliser un en-tête From:
qui ne posera pas
de problème, celui du vrai envoyeur, et de mettre l'adresse de
Bob dans un Reply-To:
. Comme la plupart des
solutions présentées dans cette section 4, elle est imparfaite (le
destinataire peut se demander qui est cet envoyeur qu'il ne
connait pas). Le RFC fournit de nombreux autres exemples de
désaccord entre identités, qui peuvent être réparés en changeant
un peu le processus d'envoi du message. Comme le disait ma
grand-mère, « il y a toujours une solution, pour peu que chacun y
mette du sien ».
Les envoyeurs peuvent aussi limiter le risque de modifications invalidantes, en ne signant pas trop d'en-têtes avec DKIM, ou en envoyant des messages parfaitement formés (pour éviter aux serveurs ultérieurs la tentation de les « réparer »).
Les receveurs peuvent aussi agir mais leurs possibilités sont plus limitées, note le RFC.
Entre les expéditeurs et les receveurs, il y a tous les
intermédiaires qui prennent un message et le ré-expédient. Ce sont
souvent eux qui causent le problème, et ils sont donc souvent en
position de le réparer. Par exemple, ils peuvent changer le
From:
du message pour mettre le leur, ce qui
permettrait à peu près n'importe quelle modification, et serait
plus « franc » (puisque le message n'est plus tout à fait
l'original, autant changer l'auteur...) Évidemment, dans ce cas,
assez violent,
il faut au minimum garder l'information sur l'émetteur originel,
avec l'en-tête Original-From:
(RFC 5703). Le problème est que le récepteur humain sera sans
doute déconcerté par cet expéditeur (d'autant plus
qu'Original-From:
est peu ou pas
affiché).
Comme les modifications invalident les signatures, les ré-expéditeurs pourraient les éviter, par exemple en ajoutant des en-têtes au lieu de modifier les existants, lorsqu'ils veulent ajouter un contenu (du genre « ceci est un spam »). Il serait peut-être préférable, dans certains cas, de rejeter les messages plutôt que de les modifier, ce qui cassera la vérification de signatures plus loin.
Et, en parlant des ré-expéditeurs, les listes de diffusion, pas vraiment prévues par DKIM, que
faire pour elles ? Le RFC 6377 a déjà traité
leur cas. Une technique courante est de modifier le champ
From:
pour mettre l'adresse de la liste,
réduisant l'auteur original à un commentaire dans cet en-tête
(avis personnel : je déteste ça). Comme cela rend difficile de
répondre en privé au vrai auteur d'un message, l'ajout d'un
Reply-To:
peut aider. Une autre solution est
d'emballer le message original dans une partie
MIME
message/rfc822
. Cette partie resterait intact
et le message emballant aurait comme expéditeur la liste. Mais peu
de MUA savent afficher proprement ce genre
de messages (spécialement dans le monde des mobiles).
Encore plus fasciste, le gestionnaire de liste pourrait
interdire l'abonnement des gens utilisant une adresse où il y a
une politique DMARC autre que p=none
. (Le RFC
oublie de parler du cas où une politique
p=reject
n'existait pas au moment de
l'abonnement mais a été rajoutée après.)
Enfin, il existe aussi des solutions qui sont encore en cours de discussion à l'IETF, et dont le RFC décourage l'usage dans un environnement de production. Ce sont entre autres des extensions au modèle du RFC 8601 pour créer une chaîne d'authentification où chaque acteur important signerait le message en route. Ou, plus radical, des mécanismes stockant l'état initial d'un message avant transformation, pour pouvoir retrouver cet état original et vérifier la signature.
Bref, le problème n'est pas résolu...
Date de publication du RFC : Août 2016
Auteur(s) du RFC : M. Bjorklund (Tail-f Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF netmod
Première rédaction de cet article le 10 octobre 2016
Le protocole standard Netconf (normalisé dans le RFC 6241) permet de configurer un équipement réseau (par exemple un commutateur) à distance. Netconf fonctionne par des RPC dont les paramètres sont des actions à faire effectuer par l'équipement configuré, ou bien les nouvelles valeurs que peut prendre telle ou telle des variables de configuration de cet équipement. Mais comment savoir quelles actions sont possibles, quelles variables existent, et quelles valeurs elles peuvent prendre ? Jusqu'à présent, cela pouvait se spécifier uniquement dans une documentation en langue naturelle fournie avec l'équipement. Désormais, il est possible de spécifier ces informations dans un langage formel, YANG. La première version de YANG était normalisée dans RFC 6020, ce nouveau RFC normalise la nouvelle version, la 1.1, qui a peu de changements, mais certains cassent la compatibilité ascendante.
Ce RFC 7950 est très détaillé, plus de deux cents pages. Et je n'ai pas personnellement d'expérience pratique avec YANG. Donc, je ne donne ici qu'un très bref résumé. Un tel survol se trouve également dans la section 4 du RFC : YANG modélise les données (configuration et état) qui seront utilisées par Netconf. Ces données sont représentées sous forme arborescente. YANG est modulaire (section 5.1 du RFC), un module YANG pouvant se référer à d'autres modules. YANG définit un ensemble de types pour décrire les données (section 9 et RFC 6991). Il permet également d'indiquer les contraintes que doivent respecter les données. YANG, langage de haut niveau, ne décrit pas l'encodage utilisé sur le câble.
Notez que YANG peut être utilisé avec d'autres protocoles que Netconf, comme RESTCONF (décrit dans le RFC 8040).
YANG a donc bien des points communs avec le SMI des RFC 2578 et RFC 2579. Avant Netconf, beaucoup de gens pensaient que toute la gestion des équipements réseau se ferait en SNMP, en s'appuyant sur ce modèle SMI. Si, pour la lecture des variables, SNMP s'est largement imposé, force est de constater que, pour l'écriture de variables et pour les actions, SNMP reste très peu utilisé, au profit de toute une galaxie de mécanismes privés (Web, REST, SSH + CLI, etc), galaxie que Netconf vise à remplacer. Une MIB du SMI peut donc être traduite en YANG, l'inverse n'étant pas vrai (YANG étant plus riche).
La syntaxe de YANG utilise des groupes emboîtés, délimités par des accolades. Mais une syntaxe équivalente, en XML, existe, sous le nom de Yin. Tout module YANG peut être traduit en Yin sans perte et réciproquement (voir la section 13 pour plus de détails sur Yin).
Donc, un engin donné, routeur ou autre équipement qu'on veut gérer, est décrit par des modules YANG. Lorsqu'un serveur Netconf à bord dudit engin met en œuvre un module YANG, cela veut dire qu'il permet de modifier, via Netconf, les variables décrites dans le module (le serveur typique met en œuvre plusieurs modules). Voici le début d'un module possible :
// Only an example, not a real module. module acme-system { namespace "http://acme.example.com/system"; prefix "acme"; organization "ACME Inc."; contact "joe@acme.example"; description "The module for entities implementing the ACME system."; revision 2010-08-05 { description "Initial revision."; } ...
On l'a dit, YANG est arborescent. Les feuilles de l'arbre (section 4.2.2.1 du RFC) contiennent une valeur particulière, par exemple, ici, le nom de l'engin géré :
leaf host-name { type string; description "Hostname for this system"; }
Ici, leaf
est un mot-clé de YANG qui indique une
feuille de l'arbre (plus de nœuds en dessous),
host-name
est le nom que l'auteur du module a
donné à une variable, de type « chaîne de caractères ». Lorsqu'un
serveur Netconf enverra cette information à un client (ou
réciproquement), elle sera encodée en XML ainsi
(Netconf utilise XML pour l'encodage des messages mais d'autres
encodages sont possibles, cf. RFC 7951) :
<host-name>my-router.example.com</host-name>
Donc, pour résumer, YANG modélise ce qu'on peut lire ou modifier, Netconf permet de le lire ou de le modifier effectivement.
Par contre, si un nœud de l'arbre YANG n'est pas une feuille,
il est désigné par le mot-clé container
. Par
exemple, il y a ici deux containers
emboîtés et
une feuille :
container system { container login { leaf message { type string; description "Message given at start of login session"; } } }
Lorsque Netconf utilise cette donnée, cela ressemblera, sur le câble, à ceci :
<system> <login> <message>Good morning</message> </login> </system>
YANG dispose d'un certain nombre de types pour représenter les données (section 4.2.4 et RFC 6991), mais on peut aussi créer ses types (sections 4.2.5 et 7.3) par exemple ainsi :
typedef percent { type uint8 { range "0 .. 100"; } description "Percentage"; } leaf completed { type percent; }
On a ajouté un intervalle de validité au type prédéfini uint8
.
Autre exemple, en indiquant une valeur par défaut, et en dérivant d'un
type défini dans le module inet
:
typedef listen-ipv4-address { type inet:ipv4-address; default "0.0.0.0"; }
YANG a bien d'autres possibilités, décrites en détail dans les
sections suivantes. Par exemple, dans un monde idéal, tous les engins
mettant en œuvre un module YANG donné géreraient la totalité des
variables du module. Mais, comme ce n'est pas forcément le cas, YANG
permet des déviations (sections 5.6.3 et 7.20.3). Prenons l'exemple du RFC, un
routeur BGP qui suit un module YANG BGP. Le
module ne donne pas de limite au nombre de pairs BGP mais un routeur
bas de gamme pourrait avoir une limite, disons à 16 pairs. Un client
Netconf qui tenterait de configurer un dix-septième pair recevrait
donc une erreur. Le mot-clé YANG deviation
permettrait audit client de savoir à l'avance en quoi ce routeur
particulier dévie du modèle BGP général. Le client Netconf n'aurait
donc pas à essayer pour voir, il pourrait savoir à l'avance que
l'opération de configuration du dix-septième pair ne marchera pas.
La syntaxe formelle de YANG est décrite en section 6. Elle ressemble à celle de langages de programmation comme C ou à celle de SMIng du RFC 3780 (RFC qui n'a pas eu de succès). Cette syntaxe favorise la lisibilité par des humains, le cahier des charges étant de privilégier les lecteurs, pas les auteurs de modules, ni les programmeurs d'outils YANG. À noter que, comme dans toutes les normes modernes, YANG n'est pas limité à l'ASCII et peut utiliser tout Unicode.
Bien que YANG n'utilise pas XML, il réutilise un langage de ce monde, XPath (sections 6.4 et 7.5.3). XPath sert à indiquer les dépendances entre nœuds de l'arbre.
YANG permet en effet de définir des contraintes (section 8) que doivent
respecter les variables, avec la directive
must
. Par exemple :
must "ifType != 'ethernet' or " + "(ifType = 'ethernet' and ifMTU = 1500)" { error-message "An ethernet MTU must be 1500"; }
Voici un exemple de requête Netconf complète, correspondant à une
variable YANG. Soit un équipement muni d'un serveur
SSH et d'un serveur Netconf pour
sa configuration. Disons que le serveur Netconf met en œuvre la variable
YANG port
, définie ainsi :
leaf port { type inet:port-number; default 22; description "The port which the SSH server listens to" }
La requête Netconf <edit-config>
(RFC 6241, section 7.2) qui configure le serveur SSH pour écouter sur le
port 2022 serait :
<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> <edit-config> <target> <running/> </target> <config> <system xmlns="http://example.com/schema/config"> <services> <ssh> <port>2022</port> </ssh> </services> </system> </config> </edit-config> </rpc>
Le choix de YANG comme langage standard pour la description des capacités d'un serveur Netconf ne s'était pas fait sans mal. Plusieurs concurrents avaient été envisagés notamment Relax NG, un choix logique puisque Netconf utilise XML. Un langage de description de schémas comme Relax NG semblait donc un choix raisonnable. Parmi les discussions à ce sujet, citons par exemple le débat qui avait eu lieu sur la liste du secteur Applications de l'IETF. Les raisons du choix de YANG, telles que vues par les concepteurs de YANG, sont décrites sur le site officiel du projet mais je trouve cette comparaison très unilatérale.
Un bon tutoriel Netconf, couvrant également YANG, est disponible en
http://www.aims-conference.org/issnsm-2008/06-netconf-yang.pdf
.
Quelles sont les mises en œuvre de YANG ? Il en existe une
liste sur le
site officiel. Voyons par exemple l'outil pyang, qui sert à valider
des schémas YANG (y compris de la nouvelle version 1.1 décrite dans ce
RFC) et à les convertir dans d'autres formats. Il ne
semble pas trop maintenu mais, bon, il marche. Il peut produire du XSD et
du RelaxNG - enfin du DSDL mais c'est presque
pareil. Voici un exemple de test d'un schéma invalide
(leaf
a été tapé laf
) :
% pyang test.yang test.yang:11: error: unexpected keyword "laf"
Et, si on corrige :
% pyang test.yang %
Maintenant, convertissons en Yin :
% cat test.yang module acme-foo { namespace "http://acme.example.com/foo"; prefix "acfoo"; list interface { key "name"; leaf name { type string; } leaf mtu { type uint32; description "The MTU of the interface."; } } } % pyang -fyin test.yang <?xml version="1.0" encoding="UTF-8"?> <module name="acme-foo" xmlns="urn:ietf:params:xml:ns:yang:yin:1" xmlns:acfoo="http://acme.example.com/foo"> <namespace uri="http://acme.example.com/foo"/> <prefix value="acfoo"/> <list name="interface"> <key value="name"/> <leaf name="name"> <type name="string"/> </leaf> <leaf name="mtu"> <type name="uint32"/> <description> <text>The MTU of the interface.</text> </description> </leaf> </list> </module>
Et voici une conversion du même code en DSL :
% pyang -fdsdl test.yang <?xml version='1.0' encoding='UTF-8'?> <grammar datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes" ns="http://acme.example.com/foo" xmlns="http://relaxng.org/ns/structure/1.0" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns:acfoo="http://acme.example.com/foo" xmlns:dc="http://purl.org/dc/terms" xmlns:dsrl="http://purl.oclc.org/dsdl/dsrl" xmlns:nm="urn:ietf:params:xml:ns:netmod:dsdl-attrib:1" xmlns:sch="http://purl.oclc.org/dsdl/schematron"> <dc:source>YANG module 'acme-foo' (automatic translation)</dc:source> <start> <zeroOrMore> <element name="interface" nm:key="name"> <element name="name"> <data type="string"/> </element> <optional> <element name="mtu"><a:documentation>The MTU of the interface.</a:documentation> <data type="unsignedInt"/> </element> </optional> </element> </zeroOrMore> </start> </grammar>
Le site officiel du projet, http://www.yang-central.org/
, contient beaucoup d'autre
information sur YANG.
Notez que l'ancien YANG, 1.0, décrit dans le RFC 6020, n'est pas abandonné. L'ancien RFC reste
d'actualité pour décrire la version 1.0, qui restera en usage un
certain temps. Les principaux changements apportés par la version
1.1 de YANG sont décrits dans la
section 1.1 du RFC. La liste est très longue, mais la plupart ne
sont que des points de détail. Parmi les changements qui peuvent
rendre illégaux des modèles YANG qui étaient légaux avant, il y a
par exemple le changement d'interprétation des échappements dans
les chaînes de caractères, ou bien le fait qu'une chaîne de
caractères qui n'est pas encadrée par des apostrophes ou des
guillemets n'a plus le droit de contenir des apostrophes ou
guillemets (section 6.1.3). De même, les clés (identificateurs
uniques) ne peuvent plus être conditionnelles (instructions
when
ou if-feature
) ce
qui est logique, mais rend également invalide certains anciens
modèles YANG.
Auteur(s) du livre : Tristan Nitot
Éditeur : C&F éditions
978-2-915825-65-7
Publié en 2016
Première rédaction de cet article le 9 octobre 2016
Si vous avez lu tous les articles d'Amaelle Guiton, de bluetouff et d'Andréa Fradin, si vous allez à tous les Quadr'Apéro de la Quadrature du Net (en lisant un livre de Schneier dans le métro) ou, bien sûr, si vous travaillez pour Facebook ou pour la DGSI, ce livre ne vous apprendra rien. Vous savez déjà que l'internaute ordinaire (pas le suspect de djihadisme ou de grand banditisme, non, le fameux M. Michu) est surveillé en permanence par les outils et services numériques qu'il utilise. Mais, contrairement au djihadiste ou au bandit, M. Michu ne le sait pas, ou bien il ne mesure pas exactement l'ampleur de la surveillance généralisée, ou alors il est complètement résigné, convaincu de ne rien pouvoir y faire. Le livre de Tristan Nitot vise à informer cet internaute innocent (dans tous les sens du terme) de la surveillance dont il fait l'objet, mais aussi à proposer des pistes pour améliorer les choses et faire reculer un peu la surveillance. (La préface d'Adrienne Charmet insiste sur l'importance de marcher sur ces deux jambes, l'exposition des problèmes, et celle des solutions.)
Ce livre est très court, ce qui reflète soit la paresse de l'auteur, soit son désir d'être utile à un maximum de gens qui pourraient être découragés en voyant un énorme pavé universitaire (qui, au passage, manque, sur ce sujet). L'auteur présente d'abord la variété des techniques de surveillance existantes. Contrairement à ce que prétendent les menteurs qui affirment qu'avec le chiffrement des smartphones, les policiers ne pourraient plus travailler, notre vie privée a énormément perdu avec l'arrivée de ce phono sapiens. Doté de capteurs perfectionnés, il enregistre tout et transmet tout à ses maîtres (qui ne sont pas son propriétaire...). Ensuite, les GAFA comme Google récoltent une quantité faramineuse de données, que leurs techniques perfectionnées permettent d'analyser. L'auteur donne plusieurs exemples concrets et précis (avec à chaque fois l'URL permettant d'aller se renseigner davantage, souci de sérieux rare). Toute cette partie est très pédagogique. Si vous êtes le geek instruit et politisé cité au début, c'est l'ouvrage à recommander à vos proches (et aux lointains aussi) moins informés, pour qu'ils comprennent ce qui arrive aujourd'hui à tout citoyen. Et ne leur racontez pas tout, laissez-leur le plaisir de découvrir l'erreur gravissime du cochon, citée à chaque conférence de l'auteur :-)
Tristan Nitot tord aussi le cou à quelques mythes comme le « je n'ai rien à cacher ». On a tous des choses (tout à fait légales) à cacher. Personnellement, je demande aux gens qui affirment n'avoir rien à cacher « votre dernier relevé bancaire, et la liste de vos dix derniers partenaires sexuels, avec les pratiques utilisées ».
Un point important de son livre est la question du modèle économique des acteurs de l'Internet. Si Google et Facebook nous surveillent autant, ce n'est pas parce qu'ils sont des filiales de la NSA, ni parce qu'ils sont vendus au diable ou aux reptiliens. C'est parce qu'ils sont gratuits, et qu'il faut bien se financer d'une manière ou d'une autre. Exploiter les données personnelles est une méthode rentable, et largement invisible pour l'utilisateur. Elle nécessite la récolte du plus grand nombre de données personnelles possible, et il n'est donc pas exagéré de noter que « le modèle d'affaires du Web, c'est la surveillance ».
Le désir de l'auteur (et de la préfacière) de ne pas uniquement décrire l'affreuse surveillance dont nous sommes l'objet, mais également de faire preuve d'un certain optimisme en indiquant des choix qui amélioreraient les choses, va parfois un peu loin. Si je peux comprendre l'analyse mesurée que Nitot fait d'Apple (société dont il ne cache pas les défauts mais qui, en matière de surveillance, semble en effet « moins pire » que les autres), j'ai plus de mal avec l'éloge qu'il fait de la société Sen.se dont le fondateur répète partout que la vie privée n'est pas son problème car « Facebook fait pire ». C'est ainsi que le produit Mother de cette société envoie tout dans « un ordinateur de quelqu'un d'autre » et que c'est présenté comme inévitable.
L'auteur continue en expliquant qu'un autre Internet est possible. Car dénoncer la surveillance, c'est très bien, mais cela peut mener à la sidération : convaincu d'être surveillé de partout, et de ne pas pouvoir l'empêcher, sauf à vivre dans une grotte sans électricité, le citoyen pourrait se décourager et renoncer à son droit à la vie privée. Il est donc nécessaire de proposer des pistes d'amélioration. Plusieurs sont avancées : le logiciel libre, bien sûr, condition nécessaire (mais pas du tout suffisante), le paiement des services (« si c'est gratuit, c'est que vous n'êtes pas le client, vous êtes la marchandise »), l'auto-hébergement (sans cacher, comme pour les autres solutions, les extrêmes difficultés que cela pose), le chiffrement (encore une condition nécessaire mais pas suffisante)... Nitot demande aussi que les partisans d'un autre Internet s'attaquent aussi au problème difficile de faire aussi bien, voire mieux, que les GAFA en matière de vécu utilisateur.
L'auteur détaille aussi, avec beaucoup de précision, quelques mesures d'hygiène numérique qui peuvent permettre de limiter un peu les dégâts de la surveillance. Par exemple, bloquer le spyware Google Analytics, ou bien avoir son propre nom de domaine permet de ne pas dépendre d'un seul fournisseur, et d'être donc libre de le quitter si ses pratiques ne sont pas acceptables.
Notons que ces manipulations sont parfois longues, ce qui reflète le désir des maîtres de la surveillance de nous empêcher de diminuer celle-ci. Il faut ainsi neuf étapes pour configurer Twitter de manière plus respectueuse de la vie privée.
Pour une genèse du livre, par son auteur, et pour une liste exhaustive des articles qui en parlent, voir sur le Standblog.
Déclaration de conflit d'intérêts : j'ai reçu un exemplaire gratuit de ce livre, mais il n'était pas accompagné d'une bouteille de vin, donc j'écris cet article à jeun et en toute objectivité.
Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : L. Iannone (Telecom ParisTech), D. Lewis (Cisco), D. Meyer (Brocade), V. Fuller
Intérêt historique uniquement
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 23 septembre 2016
Le protocole expérimental LISP a besoin
d'identificateurs pour les machines qui participent à
l'expérimentation. Comme les identificateurs LISP sont pris dans
le même espace de nommage que les adresses IP, il était préférable d'avoir un
préfixe IP spécifique. C'est désormais chose faite, avec ce
RFC, qui demande et obtient le préfixe
2001:5::/32
. Si vous voyez quelque chose qui
ressemble à une adresse IP et qui emploie ce préfixe, c'est qu'il
s'agit d'un identificateur LISP.
En effet, LISP (RFC 9300) repose sur le principe de
la séparation
de l'identificateur et du localisateur. Les identificateurs
sont stables et servent à... identifier une machine, les
localisateurs sont liés aux connexions qu'on a au réseau et
servent au routage. Les deux ont la forme physique d'une adresse
IP, et on ne peut donc pas les distinguer par leur syntaxe. Les
identificateurs sont formellement nommés EID (Endpoint
IDentifier) et c'est pour eux que
2001:5::/32
a été réservé (section 1 du RFC).
La section 3 explique les raisons de cette réservation :
2001:5::/32
au
lieu de devoir découper une partie de son espace
d'adressage.D'où cette réservation d'un préfixe dédié, en suivant les règles du RFC 3692.
Les réseaux qui utiliseront ce préfixe ne doivent évidemment pas annoncer de routes dans la DFZ (section 4 du RFC), ce préfixe ne servant qu'à des identificateurs et pas aux localisateurs. Pour la communication entre un réseau LISP numéroté avec le nouveau préfixe, et un réseau IP traditionnel, il faut utiliser les techniques d'interconnexion des RFC 6832 et RFC 7215. Le préfixe complet pourra être annoncé (comme un tout, ou comme des sous-préfixes très généraux, pour ne pas surcharger la table de routage) par des routeurs d'interconnexion (section 8 du RFC). Pour les routeurs non-LISP, ce sera un préfixe comme un autre, et il n'y a aucune raison de lui appliquer un traitement particulier.
Notre RFC exige également que ce nouveau préfixe
2001:5::/32
ne soit utilisé que par
configuration explicite et ne soit donc pas mis en dur dans le
logiciel des routeurs, d'abord parce que LISP pourra en utiliser
d'autres dans le futur, ensuite parce que des réseaux feront quand
même du LISP avec leurs propres adresses.
Pourquoi un préfixe de 32 bits ? Pourquoi pas plus spécifique ou moins spécifique (cela a été une grosse discussion dans le groupe de travail) ? La section 5 donne les raisons de ce choix :
Le préfixe 2001:5::/32
est alloué pour
trois ans, ce qui est suffisant pour l'expérimentation (sections
6 et 7). À la fin de celle-ci, le préfixe sera rendu ou bien transformé
en allocation permanente (qu'il faudra justifier et
documenter, cf. RFC 2860, section 4.3). L'allocation, faite en octobre 2015, est notée dans le registre IANA.
L'allocation des préfixes à l'intérieur de
2001:5::/32
est décrite dans le RFC 7955.
Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : L. Iannone (Telecom
ParisTech), R. Jorgensen (Bredbandsfylket
Troms), D. Conrad (Virtualized,
LLC), G. Huston (APNIC)
Intérêt historique uniquement
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 23 septembre 2016
Le RFC 7954 réservait un préfixe
IP, 2001:5::/32
, pour
les identificateurs du protocole expérimental
LISP. Ce RFC 7955 décrit les
mécanismes d'allocation à l'intérieur de ce préfixe. Ils sont
simples et légers : un peu de documentation et on a son sous-préfixe.
Le RIPE-NCC assure la gestion de ce préfixe. La politique d'enregistrement est simple (sections 4 et 9 de notre RFC) :
2001:5::/32
. Si l'expérience
se termine et que le 2001:5::/32
cesse
d'être utilisé, tous ses sous-préfixes disparaitront aussi.Quelles sont les règles que suivra le registre de
2001:5::/32
(section 5) ?
ip6.arpa
correspondants au préfixe géré.La section 6, en effet, contient les informations demandées aux titulaires (ce sont à peu près les mêmes que pour obtenir un numéro d'organisation privé). On y trouve les grands classiques, nom de l'organisation qui demande, adresse, informations de contact, taille du préfixe demandé, raisons de la demande...
Comme indiqué plus haut, c'est le RIPE-NCC qui gérera le préfixe. Normalement, tout est déjà en place mais pas encore annoncé (cela sera mis en ligne après la publication du RFC).
Auteur(s) du livre : Cyril Hlakkache
Éditeur : Kawa
978-2-36778-097-9
Publié en 2016
Première rédaction de cet article le 21 septembre 2016
Je suis perplexe devant ce livre. D'un côté, j'apprécie (comme Jean-Michel Planche, qui fait la postface) qu'on prenne de la hauteur par rapport aux transformations induites par le numérique, et qu'on essaie d'en parler à un large public. De l'autre, je me méfie des livres qui tentent de traiter tout en 250 pages, sautant d'un sujet à l'autre, et abusant de termes grandiloquents (mutation, digital, agilité...).
Mais le résultat n'est pas mauvais : l'auteur connaît ses sujets et, s'il se livre à quelques approximations et raccourcis, je n'ai pas trouvé de grosse erreur ridicule pour faire rire les lecteurs de mon blog. Pour donner une idée du style du livre, l'auteur parle de NTP en disant « C'est [NTP] qui permet au réseau des réseaux de battre la mesure pour que le tout fonctionne dans un même espace-temps ».
Cyril Hlakkache couvre à peu près tout ce qui a un rapport avec le numérique : Internet, la sécurité, le logiciel libre, les mégadonnées, la sous-traitance (pardon, cloud, c'est plus joli), la vie privée, la réalité virtuelle (avec Second Life ressorti des poubelles de l'histoire), l'IA, Bitcoin et le transhumanisme... Régulièrement, il dérape en se lançant dans des discours quasi-commerciaux et a-critiques, puis il corrige en reprenant un point de vue humaniste, soucieux des droits et des libertés des humains.
Globalement, c'est donc un livre que vous pouvez suggérer aux gens qui ne sont pas eux-mêmes complètement immergés dans cet univers numérique, et qui cherchent à s'informer et comprendre.
Déclaration de conflit d'intérêt : j'ai reçu un exemplaire de ce livre gratuitement.
Pour le suivi, il existe un blog du livre.
Date de publication du RFC : Août 2016
Auteur(s) du RFC : J. Saldana (University of
Zaragoza), A. Arcia-Moret (University of
Cambridge), B. Braem
(iMinds), E. Pietrosemoli (The Abdus Salam
ICTP), A. Sathiaseelan (University of
Cambridge), M. Zennaro (The Abdus Salam ICTP)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF gaia
Première rédaction de cet article le 17 septembre 2016
On pourrait croire que la seule façon d'accéder à l'Internet est via un FAI commercial, géré hiérarchiquement (avec directeur, plein de sous-directeurs, etc), dont les utilisateurs paient pour bénéficier de l'accès (mais sans avoir leur mot à dire sur le fonctionnement du FAI), et disposant de grands moyens financiers et techniques. C'est certainement la vision dominante et elle arrange bien les gens des médias et des gouvernements, qui se retrouvent dans une situation connue, avec un petit nombre d'acteurs « professionnels ». Heureusement, l'Internet n'est pas comme cela : c'est une confédération de réseaux très variés, certains effectivement gérés comme indiqué plus haut, mais d'autres fonctionnant sur des modèles très différents, ayant fait des choix techniques, de gouvernance et de financement très différents et très variés. Cet excellent RFC décrit et classe les réseaux « alternatifs ».
Il a été écrit dans le cadre du groupe de recherche GAIA (Global Access to the Internet for All) de l'IRTF. GAIA vise à documenter ces déploiements « alternatifs » et à faciliter le partage d'expérience. Outre le simple rappel de l'existence de ces réseaux « alternatifs », son mérite est de proposer une taxonomie de ces réseaux (forcément imparfaite, vu leur variété) et de donner une idée de la variété des technologies qu'ils utilisent.
Ces techniques sont en effet souvent différentes de celles utilisées dans les réseaux « officiels » (mainstream). Ces réseaux « alternatifs » visent en général des situations difficiles, comme la connexion de lieux lointains, où l'argent ne coule pas à flots. À part cela, ces réseaux n'ont rien en commun, ni leur organisation, ni leurs buts. Qu'est-ce qui motive leur création ? (Au passage, le RFC fait comme si ces réseaux « alternatifs » étaient une création récente ; certains sont au contraire aussi vieux que l'Internet.) Les raisons de ces projets sont elles aussi très diverses : absence pure et simple de FAI commercial, insatisfaction vis-à-vis des FAI officiels existants, désir d'essayer quelque chose d'autre...
Passons au difficile jeu des définitions. Le RFC (section 1.1) définit le réseau « officiel » (mainstream) ainsi :
Et les réseaux « alternatifs », comment se définissent-ils (section 1.2) ? C'est plus difficile car il en existe de nombreuses variantes :
Ce problème des définitions est évidemment très présent dans tout le RFC. Par exemple, comment parler des pays qui ne sont pas les membres de l'OCDE (et encore, l'OCDE compte deux ou trois membres « intermédiaires ») ? Le Tiers-Monde ? Le Sud ? Les pays pauvres ? Les sous-développés ? Les « en voie de développement » ? La section 2 du RFC propose des définitions :
Maintenant, les cas où on déploie ces réseaux « alternatifs » (section 3 du RFC). Il y aurait actuellement 60 % de gens sur Terre sans connectivité Internet. Et la répartition est très inégale (20 % sans connexion au « Nord », 69 % au « Sud »). Parmi les facteurs qui vont intervenir :
Dans les zones rurales, on a vu que c'était souvent pire. Johnson, D., Pejovic, V., Belding, E., et G. van Stam, dans leur article « Traffic Characterization and Internet Usage in Rural Africa » (In Proceedings of the 20th International Conference Companion on World Wide Web) rapportent des latences mesurées à plusieurs secondes. Les problèmes des zones rurales sont souvent cruciaux : faible revenu monétaire, manque d'infrastructures de base comme l'électricité et les routes, densité de population réduite, manque de compétences (les techniciens compétents quittent rapidement ces zones pour aller en ville), etc.
La section 4 de notre RFC s'attaque ensuite au difficile problème de la classification de ces réseaux « alternatifs ». Sur quels critères faire cette classification ? Les auteurs du RFC en trouvent cinq. D'abord, quelle organisation gère le réseau ? Un groupe plus ou moins formel d'utilisateurs ? Une collectivité publique ? Une société privée ? Un organisme de recherche ou d'enseignement ? (En France, on aurait ajouté « Une association loi 1901 ? »)
Second critère de classification, le but de la création de ce réseau : fournir un accès qui n'existerait pas du tout autrement ? Fournir une alternative bon marché ? Expérimenter et tester ? S'attaquer à d'autres problèmes de fracture numérique (comme la littératie numérique) ? Fournir un accès d'urgence suite à une catastrophe ? Ou bien un but plus politique, par exemple des mécanismes de gouvernance différents, une approche davantage « bien commun » ? Ou fournir un accès libre et neutre, contrairement à ce que font la quasi-totalité des FAI ? (Ce dernier point est présenté de manière très modérée dans le RFC qui, globalement, évite de parler des choses qui fâchent, comme la politique.)
Bien sûr, un réseau alternatif peut avoir plusieurs de ces mobiles. Et ceux-ci peuvent être plus ou moins explicites, et ils évoluent dans le temps. Le réseau Redhook avait commencé plutôt comme outil local, avant de devenir le seul réseau à fonctionner après Sandy.
Un autre critère, proche du premier, est celui du modèle de gouvernance : très ouvert, avec une participation active des utilisateurs, ou bien plus traditionnelle, avec une organisation centrale qui s'occupe de tout ? (On peut avoir un réseau qui est la propriété d'un groupe d'utilisateurs mais qui, en pratique, est géré par une petite organisation structurée.)
Autre critère, qui va plaire aux techniciens, quelles sont les techniques employées dans ce réseau ? Wi-Fi traditionnel ? Wi-Fi modifié pour les longues distances (WiLD) ? WiMAX ? Espaces blancs de la télévision (cf. RFC 7545) ? Satellite comme dans le projet RIFE ? Voire des fibres optiques terrestres ?
Enfin, dernier critère de classification, le contexte : zone rurale ou urbaine, Nord ou Sud.
Avec ces critères, on peut maintenant procéder à la classification (section 5 du RFC). Notre RFC distingue (un peu arbitrairement) six catégories, caractérisées par les réponses à ces cinq critères. Première catégorie, les réseaux d'un groupe local (community networks). Géré par un groupe de citoyens proches, ils ont typiquement un fonctionnement très ouvert et participatif. Leur croissance est en général non planifiée et non organisée : les premiers membres se connectent puis d'autres volontaires les rejoignent. Le mécanisme de décision est la plupart du temps très décentralisé. En général, ils utilisent le Wi-Fi et chaque membre contribue donc à la croissance du réseau « physique » sous-jacent. Plusieurs exemples de tels réseaux sont décrits dans l'article de Braem, B., Baig Vinas, R., Kaplan, A., Neumann, A., Vilata i Balaguer, I., Tatum, B., Matson, M., Blondia, C., Barz, C., Rogge, H., Freitag, F., Navarro, L., Bonicioli, J., Papathanasiou, S., et P. Escrich, « A case for research with and on community networks », et une analyse technique détaillée d'un réseau d'un groupe local figure dans Vega, D., Baig, R., Cerda-Alabern, L., Medina, E., Meseguer, R., et L. Navarro, « A technological overview of the guifi.net community network ».
Seconde catégorie, les WISP (Wireless Internet Service Providers). Cette fois, le réseau est géré par une société traditionnelle, mais il est « alternatif » par le public visé (typiquement des régions rurales mal desservies, où l'infrastructure est minimale, et où les FAI traditionnels ne vont pas). C'est par exemple le cas de la société Airjaldi en Inde, ou d'EveryLayer.
Troisième catégorie de réseaux alternatifs, l'infrastructure partagée (Shared Infrastructure model). L'infrastructure du réseau est partagée entre un opérateur traditionnel et les utilisateurs. C'est le cas lorsque les utilisateurs détiennent le matériel (par exemple femtocell) mais que la gestion est assurée par un FAI. Les utilisateurs sont payés, soit directement par le FAI qui leur loue l'infrastructure, soit indirectement par l'accès à l'Internet qu'ils obtiennent via ce FAI. Dans pas mal de régions rurales dans le monde, la 3G a été déployée ainsi, via les femtocells. Prévue à l'origine pour fournir une meilleure couverture dans les bâtiments, cette technologie peut aussi être utilisée pour fournir des accès aux téléphones mobiles sans que l'opérateur ait eu à supporter de gros investissements.
Un exemple d'infrastructure partagée est le projet TUCAN3G, en utilisant WiLD Ce projet est décrit par Simo-Reigadas, J., Morgado, E., Municio, E., Prieto-Egido, I., et A. Martinez-Fernandez dans « Assessing IEEE 802.11 and IEEE 802.16 as backhaul technologies for rural 3G femtocells in rural areas of developing countries » et par Simo-Reigadas, J., Municio, E., Morgado, E., Castro, E., Martinez-Fernandez, A., Solorzano, L., et I. Prieto- Egido dans « Sharing low-cost wireless infrastructures with telecommunications operators to bring 3G services to rural communities ».
Autre catégorie possible, les approches « foule de volontaires » (Crowdshared approaches) où des utilisateurs qui ne se connaissent pas forcément mettent la main au portefeuille pour participer à un projet commun, qui sera géré par une une société ou par eux-mêmes. Typiquement, les utilisateurs mettent à la disposition de tous une partie de leur capacité réseau, et l'entité qui gère le réseau est une simple coordination, elle ne possède rien. C'est ce que promeut le mouvement OpenWireless. Parmi les exemples, on peut citer des sociétés comme FON, les projets municipaux comme décrit dans l'article de Heer, T., Hummen, R., Viol, N., Wirtz, H., Gotz, S., et K. Wehrle, « Collaborative municipal Wi-Fi networks- challenges and opportunities », ou les réseaux Wi-Fi de Sathiaseelan, A., Crowcroft, J., Goulden, M., Greiffenhagen, C., Mortier, R., Fairhurst, G., et D. McAuley, « Public Access WiFi Service (PAWS) ».
Il y a aussi des réseaux montés par des coopératives en milieu rural, ce qui forme la cinquième catégorie identifiée. Ce genre de coopératives fournissant un service local est courant et ancien. Le RFC cite l'exemple des États-Unis où l'électricité en milieu rural est souvent fournie ainsi, et ce depuis les années 1930. Ces coopératives peuvent même passer leurs propres fibres optiques (« CO-MO'S D.I.Y. model for building broadband »). Des partenariats sont possibles avec ceux qui fournissent d'autres services que l'Internet, comme l'électricité dans l'exemple ci-dessus. Deux exemples sont donnés dans l'article de Mitchell « Broadband at the Speed of Light: How Three Communities Built Next-Generation Networks » ou dans le guide « Broadband Guide for Electric Utilities ».
Enfin, dernière catégorie de réseau alternatif, ceux créés à des fins de recherche. Par exemple, le réseau est créé par une université pour explorer une technique et/ou des usages (comme Bernardi, B., Buneman, P., et M. Marina, « Tegola tiered mesh network testbed in rural Scotland »).
Après cette catégorisation des réseaux alternatifs, penchons-nous sur les technologies utilisées (section 6 du RFC). Le cas de réseaux filaires est rare mais existe (comme à Lowenstedt ou dans certains endroits de Guifi.net). La plupart du temps, les réseaux alternatifs utilisent l'hertzien. Les normes techniques en œuvre sont en général celles du groupe IEEE 802.
La plus connue est évidemment Wi-Fi (802.11). Mais on trouve aussi du GSM (une norme ETSI) par exemple dans un village mexicain ou dans le projet Village Base Station. Il y a même du GSM en logiciel libre, dans les projets OpenBTS ou OpenBSC. Ces projets sont en train de migrer vers des technologies plus rapides (mais, ce que le RFC oublie de dire, bien moins libres, notamment car pourries de brevets) comme la 4G.
On a signalé plus haut que certains réseaux peuvent utiliser les espaces blancs laissés par la télévision, découvrant les fréquences utilisables via une base de données (RFC 7545) ou bien en regardant le trafic existant pour voir si l'espace est vraiment blanc.
Le Wi-Fi est limité en portée, et certains réseaux utilisent des techniques plus adaptées aux longues distances comme WiMAX (IEEE 802.16) ou bien 802.22, qui utilise justement ces espaces blancs.
Et dans les couches au-dessus de ces couches 1 et 2, quelles techniques utilisent les réseaux alternatifs ? La section 7 du RFC décrit rapidement les divers choix. D'abord, la couche 3. La plupart des réseaux n'utilisent qu'IPv4 et, ne pouvant pas obtenir suffisamment d'adresses IP des RIR sans gros efforts, se limitent aux adresses IP privées du RFC 1918. (Avant l'épuisement des adresses IPv4, obtenir des adresses des RIR était plus simple que beaucoup de gens ne le croyaient, mais il fallait quand même se taper une bureaucratie complexe et des règles difficiles.)
Pour la plupart des réseaux alternatifs, IPv6 était déjà normalisé depuis longtemps lorsqu'ils ont démarré leur projet. Mais peu l'utilisent (ninux.org est une exception), probablement essentiellement par ignorance. (Le questionnaire « Questionnaire based Examination of Community Networks » incluait des questions sur IPv6).
Pour le routage, les choix dépendent souvent de la structure du réseau alternatif. Certains sont de type mesh, avec peu ou pas d'autorité centrale, d'autres sont plus structurés. Il y a donc des protocoles de routage traditionnels comme OSPF (le RFC cite aussi BGP, ce qui me surprend pour un réseau alternatif).
Mais il y a aussi des protocoles prévus pour des réseaux moins
structurés, comme ceux utilisés dans les
MANET. On peut trouver de
l'OLSR (RFC 3626),
parfois dans des versions modifiées (ce qui est le cas de http://olsr.org/
), ou parfois sa récente version 2 (RFC 7181). D'autres réseaux utilisent du
BATMAN. Le RFC cite l'excellent
Babel (RFC 8966) mais
n'indique pas s'il est très employé sur le terrain (il semble
moins connu, dans un milieu où l'information circule mal).
Et la couche au-dessus, la couche transport ? L'un des problèmes que doit traiter cette couche est celui de la congestion : il faut assurer le partage de la capacité réseau entre plusieurs acteurs. Dans les réseaux alternatifs, pas forcément gérés centralement, et aux frontières pas toujours nettement délimitées, le défi est encore plus important. Il peut donc être intéressant d'enourager des protocoles « raisonnables » (RFC 6297), qui cèdent le pas systématiquement aux autres protocoles, afin que les activités non-critiques ne rentrent pas en compétition avec le trafic « important ».
Enfin, les utilisateurs ne s'intéressent typiquement qu'à une seule chose, les services, et il est donc utile de se demander ce que ces réseaux alternatifs proposent. Il y a bien sûr tous les services de base, notamment le Web. Certains services très répandus (vidéo haute définition, par exemple), peuvent être très coûteux pour les ressources souvent limités du réseau alternatif. Leur utilisation peut donc être restreinte. Et il y a aussi des services spécifiques des réseaux alternatifs : des VPN comme IC-VPN, des portails d'intérêt local comme Tidepools, des télévisions ou radios locales, des systèmes de relais de VoIP pour permettre des appels bon marché, des réseaux de capteurs permettant de la citizen science, etc.
Voilà, c'est terminé, cet article était long mais le RFC est plus long encore, et il se termine par une impressionnante bibliographie dont je n'ai cité que quelques extraits : plein de choses passionnantes à lire.
Date de publication du RFC : Août 2016
Auteur(s) du RFC : F. Le
Faucheur, G. Bertrand, I. Oprescu, R. Peterkofsky
(Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF cdni
Première rédaction de cet article le 16 septembre 2016
Ce RFC fait partie de la série qui normalise les interactions entre un CDN amont (celui choisi par le client) et un CDN aval (celui auquel, pour une raison ou pour une autre, une partie du trafic est délégué). Il traite la question de la journalisation : comment est-ce que le CDN aval remonte au CDN amont le journal d'activité ?
Cette idée d'interconnexion standard des CDN est expliquée dans le RFC 6707, le cadre général est dans le RFC 7336, dont la section 4.4 identifie le besoin d'un mécanisme de journalisation, et le cahier des charges est dans le RFC 7337, la journalisation étant couverte dans sa section 8.
Notre nouveau RFC décrit d'abord (section 2) le modèle de la journalisation. Certains des aspects de celle-ci (comme la possibilité pour le CDN amont de configurer ce que le CDN aval va journaliser ou pas) sont considérés comme hors-sujet. Dans le modèle, la seule activité normalisée est la remontée des journaux depuis le CDN aval. Cela permettra au CDN amont de faire de jolies statistiques, de payer son CDN aval selon son activité, etc.
Après, on descend dans le concret : la section 3 décrit le
format des journaux. Il est très inspiré du format
ELF. Un fichier journal est composé d'enregistrements,
chacun composé de champs. Voici un exemple d'une requête
HTTP (où
<HTAB>
désigne une
tabulation horizontale) :
2013-05-17<HTAB>00:39:09.145<HTAB>15.32<HTAB>FR/PACA/NCE/06100<HTAB>GET<HTAB>http://cdni-ucdn.dcdn-1.example.com/video/movie118.mp4<HTAB>HTTP/1.1<HTAB>200<HTAB>15799210<HTAB>"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.127 Safari/533.4"<HTAB>"host1.example.com"<HTAB>1
Mais attention en lisant cet exemple, le format effectif peut être modifié par des directives placées au début du fichier. (La liste des directives figure dans un registre IANA.)
Le fichier journal peut être transmis par divers protocoles (sections 4 et 5 du RFC) mais celui décrit dans ce RFC est fondé sur Atom (RFC 4287). Le CDN aval publie un flux Atom où le CDN amont trouvera les noms des fichiers à télécharger, a priori en HTTP (et même plutôt HTTPS puisque ces journaux sont confidentiels, cf. section 7.3).
Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : E. Jasinska (BigWave
IT), N. Hilliard (INEX), R. Raszuk
(Bloomberg LP), N. Bakker (Akamai)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 9 septembre 2016
Ce nouveau RFC spécifie le comportement des serveurs de routes des points d'échange Internet. Un serveur de route collecte avec BGP les routes envoyées par ses pairs et les redistribue. Cela nécessite quelques ajustements du protocole BGP, expliqués ici. Un autre RFC, le RFC 7948, décrit le côté opérationnel.
Un point d'échange Internet connecte un certain nombre d'acteurs (opérateurs, hébergeurs, FAI, etc) à un réseau commun, en général au niveau de la couche 2, et avec Ethernet. Chacun de ces acteurs gère son ou ses routeurs, connecté au·x commutateur·s commun·s. Pour savoir à quel pair envoyer des paquets IP, ces routeurs ont besoin de s'informer mutuellement des préfixes IP qu'ils gèrent. Cela se fait avec le protocole BGP (RFC 4271).
Si le point d'échange rassemble N acteurs, connecter tout le monde nécessiterait N*(N-1)/2 sessions BGP. À chaque fois qu'un participant arriverait, il faudrait qu'il négocie N-1 accords de peering. Et, en fonctionnement quotidien, il devrait superviser N-1 sessions BGP. L'idée de base du serveur de routes est d'introduire un intermédiaire (le serveur de routes, route server), qui reçoit les routes de chacun et les redistribue à tous. Ainsi, il n'y a qu'une seule session BGP à établir, avec le serveur de routes. Il est en général géré par l'opérateur du point d'échange. (Sur la plupart des points d'échange, l'usage de ce serveur de routes n'est pas obligatoire, et il y a donc également des sessions BGP directes entre les participants, pour des raisons variées.)
Le serveur de routes parle BGP avec ses pairs (les routeurs des participants au point d'échange) mais lui-même n'est pas un routeur : il ne transmet pas les paquets IP. Il travaille sur le plan de contrôle, pas sur celui des données.
Un serveur de routes est donc très proche d'un réflecteur (RFC 4456). La différence est que le réflecteur de routes travaille à l'intérieur d'un AS (protocole iBGP), alors que le serveur de routes travaille entre AS différents (protocole eBGP).
Un serveur de routes ressemble aussi à un collecteur de routes, comme ceux du RIS. La différence est que le collecteur ne redistribue pas d'information à ses pairs BGP, il collecte des données, pour analyse, affichage, etc.
La section 2 du RFC forme le cœur de ce document. Elle
rassemble les modifications du protocole BGP qui sont nécessaires
pour le bon fonctionnement du serveur de routes. D'abord, le
serveur ne doit pas modifier sans bonne raison les annonces qu'il
reçoit : son but est de distribuer de l'information, pas de la
bricoler. Le RFC demande ainsi que les attributs BGP bien connus
(comme AS_PATH
)
ne soient pas modifiés, sauf très bonne raison. Ainsi, l'attribut
NEXT_HOP
qui indique l'adresse IP du routeur
à qui faire suivre les paquets, ne doit pas être changé (ce que
demandait la section 5.1.3 du RFC 4271) : le
serveur de routes n'est pas un routeur, c'est à l'annonceur
original qu'il faut transmettre les paquets. Idem pour
AS_PATH
cité plus haut : le serveur de routes
ne doit pas mettre son propre numéro d'AS
dans le chemin. De même, MULTI_EXIT_DISC
(qui
sert à choisir entre plusieurs routeurs d'un même AS voisin) doit
être propagé aux clients du serveur de routes (normalement, il
n'est pas propagé aux autres AS). Et, enfin, les communautés BGP
(RFC 1997)
indiquées dans une annonce ne doivent pas être changées, sauf
évidemment si elles sont destinées au serveur de routes
lui-même. On trouve des exemples de communautés destinées au
serveur de routes dans la
documentation du serveur de routes d'AMS-IX ou bien dans celle de celui de
Netnod, alors que celle
de France-IX se trouve dans un objet RIPE. Il y a aussi des
serveurs de routes (comme ceux du France-IX
qui étiquettent les annonces apprises avec une communauté
indiquant où la route a été apprise (dans quel POP.)
Par défaut, toutes les routes de tous les clients sont
distribuées à tous les autres clients. C'est le but d'un serveur
de routes. Mais on peut souhaiter parfois une certaine restriction
à cette redistribution. Cela peut être mis en œuvre par le serveur
de routes (puisque le routeur original de l'annonce parle au
serveur de routes, pas au client final). Idéalement, le serveur de
routes devrait donc maintenir une base de routes, et un processus
de décision BGP, pour chacun de ses clients. Cela permet de coller
au mode de fonctionnement normal de BGP. Et cela ne nécessite
aucun changement chez les clients. Mais c'est plus coûteux en
ressources pour le serveur de routes. (Pour
BIRD, voir l'option
secondary
, qui réduit l’usage mémoire et CPU
de manière importante, expliquée dans
cet exposé.)
Les autres solutions à ce problème d'un filtrage par client
nécessitent des extensions à BGP, comme le Diverse
path du RFC 6774 ou comme la future option
ADD-PATH
.
L'annexe de ce RFC consacrée aux remerciements résume un peu d'histoire des serveurs de routes. La première description de ce système date de 1995, dans le RFC 1863 (depuis reclassé comme « d'intérêt historique seulement », cf. RFC 4223).
Plusieurs mises en œuvre de serveurs de route existent évidemment, conformes à ce RFC. C'est par exemple le cas chez Cisco, BIRD et Quagga (voir le rapport technique sur ces programmes).
Merci à Arnaud Fenioux pour sa relecture et ses ajouts et corrections.
Date de publication du RFC : Septembre 2016
Auteur(s) du RFC : N. Hilliard (INEX), E. Jasinska (Netflix), R. Raszuk (Mirantis), N. Bakker (Akamai Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 9 septembre 2016
Les points d'échange Internet sont un des maillons essentiels du bon fonctionnement de l'Internet, permettant des connexions faciles et relativement bon marché entre opérateurs. Une fois physiquement connecté au point d'échange, l'opérateur Internet doit encore établir une connexion BGP (RFC 4271) avec ses pairs. Si ceux-ci sont nombreux, établir N connexions bilatérales représente un coût administratif important. Il est souvent préférable d'établir une seule connexion multilatérale, par l'intermédiaire d'un serveur de routes (route server). Celui-ci récolte les annonces BGP de tous ses pairs et les redistribue. Ainsi, il suffit à l'opérateur d'une seule connexion, avec le serveur de routes. Ce nouveau RFC documente les questions opérationnelles liées aux serveurs de routes.
Le principe et le fonctionnement d'un serveur de routes sont expliqués dans le RFC 7947, produit par un autre groupe de travail IETF. Ce RFC 7948 se consacre aux détails opérationnels. Un serveur de routes est l'équivalent, pour le BGP externe (eBGP) de ce qu'est un « réflecteur de routes » (route reflector, RFC 4456) pour le BGP interne (iBGP). Le serveur de routes, lorsqu'il existe, est un composant crucial du point d'échange. Par exemple, s'il tombe en panne, les sessions BGP sont coupées, les annonces retirées et, même si les commutateurs et le réseau du point d'échange continuent à fonctionner, plus aucun trafic ne passe (à part si des sessions BGP bilatérales existent également). D'où l'importance d'une bonne gestion de ce composant.
Les sections 2 et 3 de notre RFC rappelent la différence entre sessions BGP bilatérales et multilatérales à un point d'échange. Si on ne fait que des sessions bilatérales (pas de serveur de routes), avec seulement quatre routeurs BGP sur le point d'échange, il faudra six sessions BGP pour une connectivité complète. Avec dix routeurs, il en faudrait quarante-cinq ! Établir, superviser et maintenir toutes ces sessions représente du travail. Les sessions multilatérales, via un serveur de routes, sont une bien meilleure solution. Avec dix routeurs au point d'échange, il n'y a plus besoin que de dix sessions BGP, chacun des dix routeurs ne faisant que BGP qu'avec le serveur de routes.
Le serveur de routes doit
juste veiller à ne pas toucher à l'attribut BGP
NEXT_HOP
(RFC 4271, section
5.1.3), qui ne doit pas indiquer le serveur de
routes, mais le routeur qui a annoncé la route (le serveur de routes
n'est pas un routeur, et ne fait pas de
transmission du trafic IP). Pour le point d'échange typique, il n'y a
pas besoin de faire de la résolution récursive (utiliser un protocole
de routage pour trouver comment joindre le routeur suivant) du
NEXT_HOP
: tous les routeurs sont sur le même
réseau L2 et sont donc
joignables directement. Par exemple, si je regarde le looking glass du France-IX et que
lui demande les routes vers 194.0.9.0/24
, il me
montre :
194.0.9.0/24 via 37.49.236.20 on eth1 [RS1_PAR 2016-08-11 from 37.49.236.250] * (100) [AS2484i] via 37.49.236.21 on eth1 [RS1_PAR 2016-08-11 from 37.49.236.250] (100) [AS2486i] ...
(L'AFNIC est connectée sur deux points de
présence de ce point d'échange, d'où les deux routeurs.) Les
NEXT_HOP
sont les adresses des routeurs dans le
point d'échange, 37.49.236.0/23
.
La section 4, le gros morceau de notre RFC, décrit ensuite divers points que le serveur de routes doit garder en tête, pour faire un bon travail.
D'abord, le cas où on n'envoie pas exactement les mêmes informations à tous les clients. Sauf si le client BGP coopère, cela implique que le serveur garde une base des routes par groupe de clients, un groupe étant composé de tous les clients pour qui on applique la même politique de filtrage. Attention, cela consomme pas mal de mémoire (autant de base que de groupes) et de processeur (il faut faire tourner les algorithmes de sélection BGP pour tous les groupes) mais heureusement, en pratique, on utilise rarement ces politiques différentes. Traiter tous les clients de la même façon permet de garder une consommation de ressources raisonnable.
Qu'en est-il du risque de fuite de préfixes ? Si un routeur connecté au serveur de routes fuit et envoie, par exemple, la totalité de la DFZ au serveur de routes, celui-ci va-t-il transmettre tous ces préfixes à ses infortunés clients ? Cela serait très ennuyeux car tout le trafic partirait alors vers le routeur fautif, qui ne serait peut-être pas capable de le gérer. Il est donc très recommandé que le serveur de routes prenne des précautions contre les fuites. Au minimum, imposer un nombre maximal de préfixes à chaque client, et, idéalement, filtrer les préfixes autorisés pour chaque client. C'est moins grossier que la simple limite quantitative, mais c'est aussi plus dur à maintenir (on ne peut pas espérer que tous les clients tiennent à jour leurs préfixes dans les IRR...). Il est certainement préférable que les administrateurs des clients et du serveur de routes regardent le journal de leur routeur pour repérer les différences entre ce qui est théoriquement annoncé et ce qu'il l'est réellement.
Question fiabilité, notre RFC recommande que le serveur de routes soit redondant : s'il n'est composé que d'une seule machine, et qu'elle plante, le point d'échange ne servira plus. Il faut donc au moins deux machines, et prendre soin qu'elles soient configurées de manière à annoncer les mêmes routes. (C'est trivial si les machines sont identiques, il suffit qu'elles aient la même configuration, cela l'est moins si, pour augmenter la redondance, on choisit des machines ayant des logiciels différents.)
Autre précaution à prendre, côté client, ne pas vérifier que le chemin d'AS est cohérent. Par exemple, le serveur de routes ne va pas mettre son propre AS tout à gauche du chemin d'AS (RFC 7947, section 2.2.2) et le client ne doit donc pas vérifier que son pair, le serveur de routes, a un chemin d'AS incluant l'AS du pair BGP.
Comment contrôler l'exportation des routes vers certains clients ? La section 4.6 liste plusieurs méthodes :
On a vu que la grande majorité des points d'échange travaillaient au niveau 2. Normalement, toute machine connectée au réseau du point d'échange peut donc joindre n'importe quelle autre. Mais, en pratique, on a déjà vu des bogues dans un commutateur qui menaient à des communications non transitives. Par exemple, les routeurs A et B peuvent tous les deux joindre le serveur de routes mais ne peuvent pas se joindre mutuellement. Dans ce cas, A reçoit bien les routes de B (et réciproquement) mais, lorsqu'il essaie de transmettre des paquets à B, ceux-ci finissent dans un trou noir. Ce problème est spécifique aux serveurs de route : lorsqu'on a une connexion bilatérale, les paquets de contrôle (ceux envoyés en BGP) suivent en général le même chemin que ceux de données (les paquets IP transmis) et partagent donc le même sort, bon ou mauvais.
La solution à ce problème passe peut-être par des solutions comme BFD (RFC 5881), pour tester la connectivité entre les deux routeurs. Mais BFD nécessite une configuration bilatérale entre les deux routeurs et il n'existe actuellement aucun protocole pour faire cette configuration automatiquement. On retombe donc dans les problèmes de configuration manuelle d'un grand nombre de connexions bilatérales. Même si un protocole de configuration automatique existait, il resterait le problème d'informer le serveur de routes. En effet, un échec BFD indiquerait à A qu'il ne peut pas joindre B, et lui ferait marquer les routes vers B comme invalides mais le serveur de routes, n'étant pas au courant, continuerait à n'envoyer à A que la route invalide (un pair BGP ne transmet que la meilleure route vers une destination donnée).
Dernier piège, le détournement de NEXT_HOP
. On
a vu que le fonctionnement normal d'un serveur de routes est de ne pas
se mettre comme « routeur suivant » mais au contraire de relayer
aveuglément les
NEXT_HOP
indiqués en BGP par ses clients.
Un
client malveillant pourrait annoncer des routes au serveur de routes en
indiquant comme « routeur suivant » le routeur d'un concurrent, pour
lui faire acheminer son trafic, par exemple ou, pire, pour faire une
attaque par déni de service en annonçant des
préfixes très populaires avec le concurrent comme routeur
suivant. Contrairement au problème précédent, celui-ci n'est pas
spécifique aux serveurs de route, il existe aussi avec des sessions
BGP bilatérales. Mais il peut faire davantage de dégâts lorsqu'on
utilise un serveur de routes, tous les clients croyant l'annonce
mensongère. Pour empêcher cela, il faudrait que les serveurs de route
vérifient que l'attribut BGP NEXT_HOP
corresponde
à l'adresse IP du client. (Les clients ne peuvent pas faire ce test,
ils doivent croire le serveur de routes, qui annonce des
NEXT_HOP
qui ne sont pas son adresse IP.)
Et pour finir, une sortie complète du looking
glass du route server du France-IX
concernant un serveur racine du DNS, M.root-servers.net
(et, au
passage, attention en anglais à ne pas confondre route
server et root server) :
RS1 show route for 202.12.27.33/32 all - View the BGP map 202.12.27.0/24 via 37.49.237.106 on eth1 [RS1 2015-08-21 from 37.49.236.250] * (100) [AS7500i] Type: BGP unicast univ BGP.origin: IGP BGP.as_path: 7500 BGP.next_hop: 37.49.237.106 BGP.med: 500 BGP.local_pref: 100 BGP.atomic_aggr: BGP.aggregator: 192.50.45.1 AS7500 BGP.community: (51706,51706) (51706,64601) (51706,64650)
Les pages de présentation de quelques serveurs de route :
Merci à Arnaud Fenioux pour sa relecture et ses ajouts et corrections.
Date de publication du RFC : Août 2016
Auteur(s) du RFC : J. Abley (Dyn), J. Schlyter (Kirei), G. Bailey (Microsoft)
Pour information
Première rédaction de cet article le 1 septembre 2016
Le mécanisme d'authentification des informations DNS nommé DNSSEC repose sur la même structure arborescente que le DNS : une zone publie un lien sécurisé vers les clés de ses sous-zones. Un résolveur DNS validant n'a donc besoin, dans la plupart des cas, que d'une seule clé publique, celle de la racine. Elle lui servira à vérifier les clés des TLD, qui serviront à valider les clés des domaines de deuxième niveau et ainsi de suite. Reste donc à configurer la clé de la racine dans le résolveur : c'est évidemment crucial, puisque toute la sécurité du système en dépend. Si un résolveur est configuré avec une clé fausse pour la racine, toute la validation DNSSEC est menacée. Comment est-ce que l'ICANN, qui gère la clé principale de la racine, publie cette clé cruciale ? Six ans après la signature de la racine du DNS, c'est enfin documenté, dans ce RFC.
Cela donne une idée de la vitesse des processus ICANN, organisation qui produit beaucoup de papier. Notez que ce nouveau RFC documente l'existant, déjà mis en œuvre, et ne prétend pas décrire la meilleure méthode. Notez aussi que ce format et cette méthode de distribution pourraient changer à l'avenir.
Si vous voulez réviser DNSSEC d'abord, outre les RFC de base sur ce système (RFC 4033, RFC 4034, RFC 4035...), notez surtout le RFC 6781, qui décrit les questions opérationnelles liées au bon fonctionnement de DNSSEC.
Les clés publiques configurées dans les résolveurs qui valident avec DNSSEC, sont appelées « points de départ de la confiance » trust anchors. Un point de départ de la confiance est une clé dont l'authenticité est admise, et non pas dérivée d'une autre clé, via une chaîne de signatures. Il en faut au moins un, celui de la racine, bien que certains résolveurs en ajoutent parfois deux ou trois pour des zones qu'ils veulent vérifier indépendamment. Lorsque le résolveur recevra une réponse de la racine, signée, il l'authentifiera avec la clé publique de la racine (le point de départ de la confiance). S'il veut vérifier une réponse d'un TLD, il l'authentifiera avec la clé publique du TLD, elle-même signée (et donc authentifiée) par la clé de la racine. Et ainsi de suite même pour les zones les plus profondes.
(Notez qu'il existe deux clés pour la plupart des zones, la KSK - Key Signing Key, et la ZSK - Zone Signing Key, mais on ne s'intéresse ici qu'aux KSK, c'est elles qui sont signées par la zone parente, et configurées comme points de départ de la confiance.)
La gestion de la clé de la racine par l'ICANN est décrite dans leur DNSSEC Practice Statement.
Le RFC rappelle aussi qu'il y a d'autres possibilités d'installation d'un point de départ de la confiance. Par exemple, si un tel point a été configuré une fois, ses remplacements éventuels peuvent être faits via le RFC 5011.
La section 2 du RFC décrit le format des clés publiées par l'IANA. Les trois formats, en fait :
Voici un exemple du fichier XML (à ne pas prendre comme s'il faisait autorité, évidemment) :
<TrustAnchor id="AD42165F-3B1A-4778-8F42-D34A1D41FD93" source="http://data.iana.org/root-anchors/root-anchors.xml"> <Zone>.</Zone> <KeyDigest id="Kjqmt7v" validFrom="2010-07-15T00:00:00+00:00"> <KeyTag>19036</KeyTag> <Algorithm>8</Algorithm> <DigestType>2</DigestType> <Digest> 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5 </Digest> </KeyDigest> </TrustAnchor>
L'élément <KeyTag>
indique
l'identifiant de la clé, actuellement 19036, comme on peut le
voir avec dig :
% dig +multi +nodnssec DNSKEY . ... ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ... ;; ANSWER SECTION: . 147724 IN DNSKEY 257 3 8 ( AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQ bSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh ... ) ; KSK; alg = RSASHA256; key id = 19036 ...
L'attribut id
de l'élément
<KeyDigest>
sert à
identifier un condensat particulier, et est utilisé pour nommer
les autres fichiers. Par exemple, le certificat PKIX va se trouver
dans le fichier Kjqmt7v.crt
.
Pour produire un enregistrement DS à
partir de ce fichier XML, il suffit de mettre
<KeyTag>
,
<Algorithm>
, <DigestType>
et <Digest>
bout à bout. Par exemple,
avec le fichier XML ci-dessus, cela donnerait :
. IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
(Des résolveurs comme Unbound acceptent ce format, pour le point de confiance de départ.)
Quant aux certificats, ils sont encodés en
DER et signés par
l'ICANN et leur champ
SubjectPublicKeyInfo
est la clé publique
DNSSEC. Voici ce qu'en voit OpenSSL :
% openssl x509 -text -inform DER -in Kjqmt7v.crt Certificate: Data: Version: 3 (0x2) Serial Number: 7 (0x7) Signature Algorithm: sha256WithRSAEncryption Issuer: O=ICANN, CN=ICANN DNSSEC CA/emailAddress=dnssec@icann.org Validity Not Before: Jun 11 18:43:20 2014 GMT Not After : Jun 10 18:43:20 2017 GMT Subject: O=ICANN, OU=IANA, CN=Root Zone KSK 2010-06-16T21:19:24+00:00/1.3.6.1.4.1.1000.53=. IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5 Subject Public Key Info: Public Key Algorithm: rsaEncryption ... X509v3 extensions: X509v3 Basic Constraints: critical CA:FALSE X509v3 Authority Key Identifier: keyid:8F:B2:42:69:C3:9D:E4:3C:FA:13:B9:FF:F2:C0:A4:EF:D8:0F:E8:22 X509v3 Subject Key Identifier: 41:1A:92:FA:1B:56:76:1E:62:2B:71:CD:1A:FD:BB:43:99:5F:09:C9 Signature Algorithm: sha256WithRSAEncryption ...
Comment récupérer le fichier XML
de manière à être sûr de son authenticité ? C'est ce que spécifie
la section 3 du RFC : on utilise HTTPS. L'URL est https://data.iana.org/root-anchors/root-anchors.xml
.
Une autre solution (section 4) est de le récupérer en
HTTP et de le vérifier avec une des
signatures fournies : l'une est en CMS
(RFC 5652) - son URL est https://data.iana.org/root-anchors/root-anchors.p7s
,
l'autre est en PGP (RFC 9580) - son URL est https://data.iana.org/root-anchors/root-anchors.asc
. Cette
signature PGP devrait être abandonnée à l'avenir.
Pour les amateurs d'histoire, l'annexe A rappelle que la clé actuelle, la 19036, a été générée au cours d'une cérémonie à Culpeper, le 16 juin 2010. Elle a été publiée dans le DNS pour la première fois le 15 juillet 2010.
Sinon, l'ISOC a écrit un bon article sur ce RFC, moins technique.
Date de publication du RFC : Août 2016
Auteur(s) du RFC : E. Lear, R. Housley
Pour information
Réalisé dans le cadre du groupe de travail IETF ianaplan
Première rédaction de cet article le 30 août 2016
Un certain nombre de fonctions administrativo-politico-techniques dans l'Internet sont assurées par un service nommé l'IANA (Internet Assigned Numbers Authority). Cela va du spectaculaire (l'instruction des demandes d'ajout ou de suppression des TLD) jusqu'au routinier (la gestion des innombrables registres techniques que l'IANA maintient pour le compte de l'IETF). L'IANA est un service de l'ICANN et l'ICANN est sous tutelle du gouvernement états-unien pour effectuer ce travail, dit « fonction IANA ». Le gouvernement états-unien a annoncé en 2014 qu'il envisageait peut-être dans le futur de diminuer la dépendance de l'ICANN et a demandé, en attendant, aux parties intéressées, de soumettre des propositions. L'ICANN, toujours ravie qu'on propose des discussions et des réunions, a créé le ICG (IANA stewardship transition Coordination Group) qui a à son tour sollicité des commentaires. Ce nouveau RFC est la réponse de l'IETF à cet appel, ne concernant que la gestion des registres techniques. La gestion des noms de domaine et des adresses IP, bien plus politicienne et bien plus brûlante (surtout pour les noms de domaine) n'y figure pas. Voici donc « la position de l'IETF concernant l'avenir de la gestion des registres IANA, dans l'hypothèse où le gouvernement états-unien relâcherait son emprise ». Pour résumer cette position : la gestion des registres des paramètres des protocoles fonctionne actuellement bien et, quelles que soient les manœuvres autour de l'évolution du rôle du gouvernement US, il ne faut pas la changer. Ce RFC a été terminé en janvier 2015 mais n'est publié que maintenant, après l'approbation du plan de transition par l'ICANN en mars 2016 à sa réunion de Marrakech, et après l'accord du gouvernement états-unien en août.
L'agence du gouvernement états-unien chargée de superviser l'ICANN se nomme NTIA, dépendant du ministère du commerce (notez la vision de l'Internet que cela implique). Notez que cette supervision n'est pas le seul levier direct de ce gouvernement sur la gestion de ressources critiques de l'Internet. Il y a aussi la gestion de la racine du DNS, effectuée via Verisign. En mars 2014, génée par les révélations de Snowden, la NTIA a annoncé un projet d'évolution du statut de l'ICANN, passant du gouvernement états-unien à quelque chose de nouveau, encore à discuter. La NTIA a posé ses conditions (par exemple que le quelque chose de nouveau ne devait pas être multi-gouvernemental), et annoncé que, s'il n'y avait pas de plan satisfaisant (satisfaisant pour la NTIA) proposé, le projet serait abandonné ou redéfini.
C'est là qu'a été créé l'ICG (IANA Stewardship Coordination Group) dont la charte figure en annexe B de ce RFC. C'est cet ICG qui a émis l'appel aux commentaires (qui figure en annexe C du RFC). Cet appel demande entre autre de préciser si les réponses concernent la partie « noms de domaine », la partie « adresses IP » ou bien la partie « paramètres des protocoles » du travail de l'IANA (ce RFC concerne la troisième partie). Les réponses sont disponibles en ligne.
La section 2 de ce RFC est la réponse formelle de l'IETF, suivant le plan de l'appel à commentaires de l'ICG. D'abord, l'IETF répond à la question « l'IANA sert à quoi, pour vous ? » Bien des protocoles conçus ou gérés par l'IETF ont besoin de registres pour des paramètres du protocole. Par exemple, le protocole HTTP (RFC 7231) a des codes de retour des opérations (comme le célèbre 404) qui sont stockés à l'IANA. Ajouter un tel code (par exemple 451 pour « contenu censuré ») ne nécessite donc pas de modifier la norme HTTP. Ou bien, pour prendre un exemple nettement moins connu, le protocole PCP (RFC 6887) dispose d'un certain nombre d'options, qui ne sont pas fixées une fois pour toutes dans la norme mais sont notées dans un registre IANA, ce qui permet d'en ajouter facilement de nouvelles.
Pour que l'Internet fonctionne, il faut que ces paramètres des protocoles soient utilisés de la même manière par tous. Par exemple, cela signifie que les développeurs de logiciels Internet doivent utiliser les mêmes registres, en l'occurrence, ceux de l'IANA. Ainsi, un serveur HTTP peut renvoyer le code 403 en sachant bien que cela sera interprété par tous les clients comme signifiant « Accès interdit », car le code 403 figure dans le registre IANA avec cette définition. Ce rôle de l'IANA pour l'IETF est documenté dans le RFC 5226.
L'IANA gère également le TLD
.arpa
, qui est
considéré comme un des registres de paramètres (RFC 3172).
Ce travail de l'IANA pour le compte de l'IETF est effectué en application du RFC 2860 (voir aussi ses déclinaisons concrètes), qui est le « contrat » entre les deux activités.
La question suivante est « qui êtes-vous ? » L'IETF se présente donc, SDO internationale, ouverte et dont la mission est décrite dans le RFC 3935. L'IETF fait les normes techniques de l'Internet « de la couche 3 jusqu'au bas de la couche 7 ». C'est elle qui est responsable d'IP de BGP, du DNS, de HTTP, etc. (Oui, tous les lecteurs de ce blog savent cela mais la réponse de l'IETF est conçue pour être lue par un public plus large.) Le côté ouvert de l'IETF est précisé dans le RFC 6852, le processus de création des normes dans le RFC 2026.
Une question difficile dans l'appel à commentaires était « quels recouvrements y a-t-il entre votre activité et celles d'autres organisations ou groupes ? » D'abord, la réponse met en avant le fait que les participants à l'IETF sont souvent membres d'autres organisations. (On parle de « participants » car l'IETF n'a pas de mécanisme d'adhésion formel.)
Ensuite, l'IETF a évidemment des activités qui s'approchent de très près de celles d'autres groupes, avec parfois des discussions sur la frontière. Ainsi, le RFC 6761, qui fait l'objet de beaucoup de débats en ce moment, prévoit un mécanisme d'enregistrement de noms de domaine par l'IETF, alors que certains voudraient que cela soit un monopole de l'ICANN. C'est aussi le cas des adresses IP (mais cela suscite bien moins d'intérêt car c'est plus important mais moins spectaculaire). Ainsi, si l'IANA gère l'espace d'adressage IP, l'IETF alloue également des portions de cet espace (RFC 7020, RFC 7249, et un exemple concret, les ULA du RFC 4193). Il y a aussi bien sûr des recouvrements envers ce que fait l'IETF, et le travail des opérationnels qui décident (ou pas) de déployer les protocoles normalisés. Par exemple, la gestion des serveurs racine du DNS est à la fois un secteur de l'IETF (RFC 7720) et des opérateurs de ces serveurs.
Les activités de l'IETF concernant IP et le routage l'amènent par contre du côté des RIR (par exemple lorsque l'IETF a ses propres allocations d'adresse, comme dans le RFC 6890). Un changement de norme technique peut impacter les opérationnels (nouvelles choses à gérer) et les RIR. Ainsi, l'extension de la taille des numéros d'AS de deux à quatre octets (RFC 6793) imposait évidemment aux RIR de changer leur logiciel et leur politique, pour allouer ces nouveaux numéros.
Pour tous ces points, le RFC insiste sur l'importance de la coordination entre ces acteurs, et sur les nombreux contacts que l'IETF maintient avec toutes ces communautés.
L'appel à commentaires de l'ICG demande ensuite comment les politiques sont décidées et comment les conflits sont gérés. Pour l'IETF, les principes figurent dans les RFC 6220 et RFC 5226. En gros, quelqu'un qui veut changer la politique de l'IETF, par exemple modifier le RFC 5226 (c'est justement en cours de discussion) va écrire un premier document, un Internet Draft, essayer de susciter de l'intérêt, en général le faire adopter par un des groupes de travail (à moins qu'un groupe soit créé spécialement), la proposition doit réunir un consensus (RFC 7282) et c'est souvent l'IESG qui prend la décision finale. Le tout est scandé par des last calls où les organisateurs demandent aux participants un dernier avis avant que le document n'avance. (Pour le fonctionnement des groupes de travail, on peut lire le RFC 2418, mais il n'est plus complètement à jour.)
Et les conflits ? Ils sont normalement réglés dans les groupes de travail mais, si c'est grave, la section 6.5 du RFC 2026 décrit un mécanisme d'appels successifs.
Un concept souvent cité en ce moment dans les discussions autour de l'ICANN et celui de redevabilité (accountability). L'organisation est-elle redevable à quelqu'un, ou bien est-ce un clan mafieux fermé qui décide de tout en interne et ne rend de comptes à personne (comme le CIO ou la FIFA) ? L'appel à commentaires demande donc de la documentation sur les mécanismes de redevabilité du répondeur. Pour l'IETF, c'est l'IAB qui joue ce rôle, en confirmant (ou pas) les nominations et en traitant les appels mentionnés un peu plus haut. C'est aussi l'IAB qui gère les canaux de communication (liaisons) avec les autres organisations. Et c'est l'IAB qui décide quel opérateur gère les registres de paramètres de protocole, actuellement l'ICANN via sa fonction IANA. L'IAB est officiellement décrite dans le RFC 2850. Elle est elle-même redevable devant les participants à l'IETF, par son mécanisme de désignation (RFC 3777).
Quel est le degré de formalisation de votre relation avec l'IANA, demande ensuite l'appel à commentaires ? Un MoU existe (RFC 2860). Son suivi quotidien est assuré par l'IAD (IETF Administrative Director), lui-même sous contrôle de l'IAOC (IETF Administrative Oversight Committee, cf. RFC 4071). Une de leurs tâches est de suivre les rapports de l'IANA sur ses résultats.
En théorie, si un conflit grave surgissait entre l'IETF et l'IANA, l'IETF pourrait mettre fin au travail en commun et choisir un nouvel opérateur pour ses registres (et ce RFC serait alors sans objet). Mais cela ne s'est jamais produit et une telle perspective semble peu probable.
L'appel à commentaires demande aussi à ceux qui répondent d'indiquer de quelle juridiction ils dépendent et quelles sont les lois qui leur sont applicables. L'IETF répond que son activité est mondiale (ce qui est vrai) et que les textes entre l'IANA et l'IETF ne spécifient pas de juridiction (ce qui est exact mais incomplet : l'IETF étant une activité de l'ISOC, l'IETF dépend de la juridiction états-unienne, comme le montrent, par exemple, les injonctions reçues).
Commencent ensuite les questions sensibles, par exemple les demandes de suggestions concernant les mécanismes futurs qui remplaceraient la NTIA. La réponse du RFC est qu'aucun changement n'est demandé par l'IETF : le système actuel avec l'IETF, l'ICANN, l'IAB, etc, a bien fonctionné, sans implication du NTIA, et n'a donc aucun besoin d'être remplacé ou « amélioré ». Les RFC 2860 et RFC 6220 fournissent un cadre satisfaisant et le résultat l'est également.
Cette partie de la réponse contient quand même quelques souhaits, pas forcément de changement mais de points importants à garder en tête :
Et le RFC réaffirme les principes que l'IAB avait posé en mars 2014 :
J'avais signalé plus haut que la NTIA avait posé un certain nombre d'exigences pour accepter un éventuel plan de transition. La suite de l'appel à commentaires rappelle ces exigences et demande dans quelle mesure les propositions faites sont conformes à ces oukases. D'abord, la NTIA demande de « continuer avec le modèle multi-partiesprenantes » (ne me demandez pas de définir ce modèle...) L'IETF répond qu'en tant qu'organisation ouverte à tous, elle suit déjà ce modèle (même réponse à la demande de la NTIA que le futur éventuel système « conserve l'ouverture de l'Internet »). Ensuite, la NTIA exige de préserver « la sécurité et la stabilité du DNS » (une des phrases les plus citées dans les milieux de la gouvernance Internet...) L'IETF ne proposant pas de changement, la stabilité est certainement préservée. Puis le gouvernement états-unien veut que les propositions « satisfassent les utilisateurs et répondent à leurs besoins ». Le RFC estime que l'utilisation massive dans le monde des protocoles TCP/IP et donc des registres de l'IANA montre clairement que les utilisateurs sont contents. Dernier ordre de la NTIA : que la solution future ne soit pas multi-gouvernementale (rappelons que le mécanisme actuel de supervision de l'ICANN est mono-gouvernemental). L'IETF réplique que l'IAB n'est pas une organisation gouvernementale et que l'ordre est donc suivi.
L'appel à commentaires de l'ICG demande également par quel processus la réponse a été élaborée, une bonne façon de vérifier que le répondant a appliqué ses beaux principes, y compris lors de la conception de sa réponse. L'IETF explique que la réponse a été développée par le groupe de travail IANAPLAN, qui, comme tous les groupes de travail de l'IETF, était ouvert à tous et faisait tout son travail publiquement (cf. les archives de la liste de diffusion du groupe). Pour le montrer, comme le demande l'appel à commentaire, l'IETF cite de nombreux documents publiquement accessibles :
Le RFC estime que tout ce processus montre un net consensus de
l'IETF en faveur de cette réponse. Quelques points sont restés
contentieux jusqu'au bout (comme la demande que le nom de domaine
iana.org
soit transféré à l'IETF Trust).
Quelques lectures supplémentaires sur cette opération de transition :
.gov
et .mil
),Date de publication du RFC : Août 2016
Auteur(s) du RFC : C. Percival (Tarsnap), S. Josefsson
(SJD AB)
Pour information
Première rédaction de cet article le 29 août 2016
Ce RFC normalise la fonction de dérivation de clé scrypt.
À quoi ça sert, une fonction de dérivation de clé ? Comme leur nom l'indique, elles permettent d'obtenir des clés cryptographiques (ou autre matériel cryptographique) à partir des données qu'on leur fournit. Une utilisation courante est de fabriquer une clé pour un algorithme de chiffrement, à partir d'une phrase de passe. Cela permet d'obtenir une clé (longueur fixe, format donné) pour les opérations cryptographiques tout en laissant l'utilisateur manipuler uniquement des textes mémorisables. Par exemple, pour chiffrer un disque dur, l'utilisateur va indiquer une phrase de passe, mais le disque sera chiffré à partir de la clé obtenue en appliquant la fonction de dérivation de clé (KDF, pour Key Derivation Function) à cette phrase. Une autre utilisation est pour transformer un mot de passe qu'on doit stocker dans un fichier en une information inutilisable pour un attaquant qui mettrait la main dessus. Pour se connecter, on tape le mot de passe, on refait tourner la KDF et on vérifie qu'on obtient bien le résultat stocké.
Problème de cette méthode, l'ennemi peut tenter de faire lui-même la dérivation : il essaie des tas de mots de passe et regarde s'il obtient le résultat stocké. C'est pour cela qu'une des qualités d'une bonne fonction de dérivation est, paradoxalement, d'être lente : les gens qui connaissent le mot de passe ne seront pas gênés (ils ne font qu'un seul essai) alors que l'attaquant par force brute qui essaie des milliards de mots sera ralenti. Idéalement, on voudrait une fonction qui ne puisse pas facilement être mise en œuvre dans des ASIC, pour qu'un attaquant riche ne puisse pas investir dans une « machine à deviner les mots de passe ». C'est l'un des avantages de scrypt. (Les fanas de chaîne de blocs noteront que des chaînes comme Litecoin utilisent scrypt justement pour cette raison : rendre le minage plus accessible à tous en contrariant les ASIC.)
Pourquoi encore ajouter des fonctions de dérivation de clés (section 1 du RFC) ? Il y en a eu plein dans l'histoire, de la vénérable crypt à PBKDF2 (RFC 2898) puis aux récents bcrypt et Argon2. On en imagine souvent de nouvelles, par exemple celle-ci qui n'utilise pas du tout de chiffrement, juste de la condensation. Pour résister aux attaques par force brute (que la loi de Moore rend plus efficace chaque année), certaines ont un nombre d'itérations variables. On applique plusieurs fois l'opération de dérivation, si les machines deviennent plus rapides, on augmente ce nombre d'itérations. Cela ne marche bien que si l'attaquant utilise les mêmes logiciels que les utilisateurs normaux. Mais si la fonction de dérivation est facilement programmable dans des circuits matériels spécialisés, l'attaquant pas trop pauvre pourra s'acheter une ferme de cassage de mots de passe, remplie de circuits conçus spécifiquement, et travaillant en parallèle (les circuits deviennent plus rapides mais aussi plus petits : on peut en entasser davantage). Il ne joue alors plus dans la même catégorie que les utilisateurs légitimes.
C'est là que scrypt intervient : l'algorithme a été délibérement conçu pour être difficile à mettre dans un ASIC. scrypt a été publié en 2009 (voir l'article original qui fut présenté à USENIX). Ce RFC a commencé en 2013 et a eu une longue gestation. Il ne décrit pas scrypt, renvoyant au papier original, mais se contente de préciser les points qui sont nécessaires pour des mises en œuvre interopérables.
La section 2 du RFC décrit les paramètres de la fonction. Le plus évident est la phrase de passe, souvent choisie par un humain. Il y a aussi un sel, en général choisi aléatoirement (RFC 4086), et divers paramètres techniques, permettant notamment d'ajuster l'algorithme aux caractéristiques des machines dont on dispose. Une taille de bloc de 8 et un facteur de parallélisation de 1 conviennent bien à l'heure actuelle, mais vont sans doute augmenter dans le futur.
scrypt dépend de la fonction de condensation Salsa20 Core, plus exactement de sa version simplifiée Salsa20/8 Core (section 3 du RFC). Une mise en œuvre en C est incluse dans le RFC. (Voir la description originelle et la spécification de Salsa20.)
scrypt est un « chef d'orchestre », qui dépend de plusieurs autres algorithmes comme BlockMix (section 4), ROMix (section 5), le PBKDF2 du RFC 2898 et le HMAC-SHA-256 du RFC 6234. L'algorithme de scrypt, qui fait fonctionner ensemble tout cela, figure en section 6.
Si vous êtes programmeur et que vous mettez en œuvre scrypt,
les sections 8 à 13 du RFC contiennent des vecteurs
de test pour les différents algorithmes
utilisés. Par exemple, avec la phrase de passe
pleaseletmein, le sel
SodiumChloride
(exemple contestable, ce sel
n'a pas été généré aléatoirement), le facteur CPU/mémoire à
16384, la taille de bloc 8 et le facteur de parallélisation 1,
la clé dérivée par scrypt sera 70 23 bd cb 3a fd 73 48
46 1c 06 cd 81 fd 38 eb fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54
5d a1 f2 d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 e6 1e
85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87
. Si vous
trouvez une autre valeur, vérifiez votre programme.
Lisez aussi la section 14, consacrée aux questions de sécurité. Par exemple, scrypt peut consommer beaucoup de mémoire (c'est fait exprès, cela fait partie des techniques qui rendent difficile sa mise en œuvre en ASIC) et il y a donc un risque de déni de service si on accepte d'exécuter scrypt avec des paramètres quelconques, fournis depuis l'extérieur.
scrypt est, entre autres, présents dans OpenSSL depuis le 1.1.0, officiellement publiée juste après le RFC.
Date de publication du RFC : Août 2016
Auteur(s) du RFC : K. Davies (ICANN), A. Freytag
(ASMUS)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF lager
Première rédaction de cet article le 29 août 2016
Lorsqu'on a des identificateurs en Unicode (par exemple pour les noms de domaine internationalisés), on souhaite souvent limiter le nombre de caractères autorisés, et avoir des possibilités de variante (par exemple, dire que deux chaînes de caractères Unicode sont en fait équivalentes sémantiquement). Il faut donc rédiger ces règles, et un langage formel est certainement utile pour cela. C'est ce que propose ce nouveau RFC, qui normalise un langage XML pour décrire les règles d'enregistrement de ces identificateurs Unicode.
Le terme utilisé par le RFC est LGR, pour Label Generation Ruleset. Label est le composant de base d'un nom de domaine, et Ruleset fait référence à l'ensemble des règles décrites en XML et qui permettront de savoir si un composant est valide, et quelles transformations éventuellement effectuer avant de l'enregistrer. C'est un concept qui vient de l'ICANN, qui a toujours présenté les IDN comme une chose dangereuse (bien à tort), nécessitant des variant tables ou autres algorithmes compliqués. Donc, si vous ne travaillez pas avec l'ICANN, il n'est pas nécessaire de connaitre ce RFC.
Le langage présenté dans ce RFC est assez complexe, mais le problème est complexe. Ceci dit, dans les cas « simples » (alphabet latin), les règles LGR seront également simples. Si on veut juste dire que é, è et ë sont autorisés dans les noms, et avec e comme variante, c'est trivial à faire, à peine plus compliqué que les tables du RFC 4290.
Notez que l'algorithme décrit par un LGR ne suffit pas comme règle d'enregistrements des noms de domaine : il existe d'autres règles (comme la priorité aux entreprises titulaires de propriété intellectuelle) qui ne sont pas exprimables par ces algorithmes.
Avant ce RFC, les règles concernant les
IDN étaient publiées en langue naturelle,
ou parfois dans le langage formel des RFC 3743 et/ou RFC 4290. Le langage
décrit ici a vocation à les remplacer. Il est structuré, donc
lisible par un programme, et permet de dériver automatiquement les
programmes de vérification d'un nom (par exemple ceux qui sont
lancés par un serveur EPP recevant un ordre
<domain:create>
, RFC 5731, section 3.2.1).
Le format est relativement simple si on a une politique simple mais permet le cas échéant de mettre en œuvre des politiques très complexes (qui sont utiles pour certaines écritures asiatiques, par exemple). Il est conçu pour les IDN mais peut être utilisé si on a à enregistrer des identificateurs Unicode dans un autre contexte.
Le cahier des charges du format des LGR figure en section 2 du RFC :
Un point important de ce RFC est qu'il décrit un format, pas une politique : le RFC ne dit pas si le caractère Unicode U+00E8 (è) doit être considéré comme une variante du U+0065 (e) : il fournit juste le moyen d'exprimer cette équivalence, si on le décide.
La section 4 du RFC spécifie le format exact. (Le schéma formel
- en
Relax NG - est dans l'annexe D.) Un
ensemble de règles LGR est mise dans un élément XML
<lgr>
. Il contient quelques
métadonnées, dont la date et la langue ou
l'écriture pour lesquels ce LGR est prévu. Comme l'ICANN, dans ses
politiques IDN, mélange très souvent langue et écriture (par
exemple en parlant de « domaines multilingues », ce qui est
absurde), il faut préciser que la plupart des politiques portent
sur des écritures (un nom de domaine n'a pas de langue :
coca-cola.com
est-il de l'anglais ?) La
valeur de l'élément XML <language>
est
une étiquette du RFC 5646, avec la langue
marquée comme « non définie » (und
pour
undeterminate). Un exemple pour une politique
consacrée à l'alphabet cyrillique :
<language>und-Cyrl</language>
.
Les règles elle-mêmes sont en section 5. La plus simple est
celle qui autorise un caractère donné, ici le
tiret (cp
=
Code Point Unicode, ici U+002D) :
<char cp="002D"/>
On peut aussi autoriser un intervalle, ici tous les chiffres arabes :
<range first-cp="0030" last-cp="0039"/>
Comme on le voit, les caractères sont identifiés par leur point de code Unicode, écrit sans le « U+ » initial. Bien que XML permettre de représenter nativement tous les caractères Unicode, cette possibilité n'est pas exploitée par ce RFC (cf. Unicode Standard Annex #42).
Voici maintenant un exemple de règle qui précise que le point médian U+00B7 n'est autorisé qu'entre deux l (c'est le cas en catalan mais notez qu'en français, il est aussi utilisé dans une perspective féministe). Cela se fait en indiquant une séquence :
<char cp="006C 00B7 006C" comment="Catalan middle dot"/>
Et voici une règle contextuelle plus complexe. On veut n'autoriser
le gluon de largeur nulle U+200D qu'après un virāma. Si une règle
follows-virama
(non montrée ici) a été
définie, on peut écrire :
<char cp="200D" when="follows-virama" />
Et les variantes ? Voici d'abord comment exprimer que le é est une simple variante du e (non pas que je recommande cette politique : c'est juste un exemple) :
<char cp="00E8"> <var cp="0065"/> </char>
Et une variante où un caractère (œ) est mis en correspondance avec deux caractères (oe) :
<char cp="00F6"> <var cp="006F 0065"/> </char>
Ces règles portaient sur des caractères qui formaient une partie d'un composant d'un nom. Mais il y a aussi des règles qui portent sur la totalité du composant (section 6 du RFC). Pour cela, d'abord un petit mot sur la notion de classe. On définit une classe de caractères à partir de propriétés Unicode. Ici, on a la classe des virāma, définie à partir de la propriété Unicode CCC (Canonical Combining Class) :
<class name="virama" property="ccc:9" />
On peut ensuite combiner les classes par intersection, union, etc.
Les règles permettent aussi d'utiliser des opérateurs
booléens. Voici par exemple la règle
traditionnelle des noms de machines (et pas des noms de domaine,
contrairement aux bêtises qu'on lit souvent), autorisant lettres
ASCII, chiffres et tiret. Elle utilise
<choice>
, qui fait un OU logique entre
les termes :
<rule name="ldh"> <choice count="1+"> <class by-ref="letter"/> <class by-ref="digit"/> <char cp="002D" comment="literal HYPHEN"/> </choice> </rule>
Des exemples plus réalistes et plus détaillés figurent dans l'annexe A.
Le document XML complet a le type MIME
application/lgr+xml
.
Quelques petits mots sur la sécurité (section 12 du RFC). Le RFC part du préjugé (qui est faux) comme quoi les noms en Unicode poseraient des problèmes de sécurité. La section 12 note ensuite (si on accepte cette prémisse) que les règles de ce RFC ne résolvent pas complètement le problème (qui est largement imaginaire). Il reste possible de faire des noms « trompeurs » même avec les règles les plus strictes. Outre question de sécurité à garder en tête : les règles de ce RFC peuvent permettre de concevoir des politiques LGR très complexes, qui peuvent épuiser les ressources de la machine qui tenterait de les évaluer.
Si vous voulez pratiquer avec vos propres LGR, l'ICANN a fait développer un outil qui est accessible en ligne (lisez la documentation pour connaitre le mot de passe) ou bien en source sur GitHub : lgr-core et lgr-django pour l'interface Web en Django.
Première rédaction de cet article le 28 août 2016
Tous les jours, plusieurs articles apparaissent dans les médias pour expliquer que la chaîne de blocs (blockchain dans la langue de Satoshi Nakamoto) va résoudre encore un nouveau problème. Pour le non-spécialiste, il n'est pas évident de faire la part du réel et du fantasme dans toutes ces applications de la chaîne de blocs. C'est en pensant à ce non-spécialiste que j'ai écrit cet article : peu ou pas de technique, juste une exploration des choses où la chaîne de blocs est vraiment utile, par rapport à celles où elle n'a pas d'intérêt.
D'abord, je vais me permettre un court paragraphe rappelant ce qu'est la chaîne de blocs : il s'agit d'une base de données ordonnée (les blocs contiennent des transactions, opérations d'écriture dans la chaîne, qui sont dans un ordre précis), répartie sur un réseau (typiquement Internet), et qui n'a pas de gérant unique. Chaque machine, chaque nœud, porte toute la chaîne et détruire celle-ci nécessiterait donc de détruire des dizaines de milliers de machines, gérées par des gens différents. La chaîne de blocs est publique : tout le monde peut créer un nœud du jour au lendemain, qui va automatiquement télécharger et vérifier la chaîne, avec toutes les données qu'elle contient. Tout le monde peut y écrire (souvent moyennant finances) et ces écritures sont signées, et sont gardées éternellement dans la chaîne, qui est donc un livre des opérations, contenant tout l'historique. L'intégrité de la chaîne est garantie par la cryptographie. Toute modification est détectable par tous. Notez bien que j'ai dit toute modification. La chaîne ne distingue pas entre modification « légitime » ou « illégitime ». Une fois qu'une transaction est dans la chaîne, elle y est pour toujours, même si on croit avoir de bonnes raisons de l'annuler. (Oui, les techniciens vont noter que c'est plus compliqué que cela ; mais c'est toujours plus compliqué que cela, j'essaie d'en rester aux grandes lignes.)
Il n'y a donc pas besoin de faire confiance au Président de la Chaîne de Blocs (il n'existe d'ailleurs pas). La chaîne permet donc à des acteurs ne se connaissant pas, et ne se faisant a priori pas confiance, de travailler sur une base de données commune, consensuelle. C'est tout mais c'est énorme. La chaîne est « vérifiable par tous et contrôlée par personne ».
Les applications de la chaîne de blocs sont donc a priori nombreuses : toutes les fois où des acteurs différents faisaient appel à une autorité centrale, on pourrait mettre à la place une chaîne de blocs. L'exemple évident est la monnaie. Depuis le Moyen Âge, elle est typiquement garantie par un État (autorité centrale). Avec la chaîne de blocs, on peut concevoir une monnaie sans autorité centrale, et c'est bien le cas de Bitcoin, la technologie qui a lancé et popularisé cette idée de chaîne de blocs. Outre le plaisir de se débarrasser d'une autorité centrale qui ne mérite pas forcément la confiance qu'on lui porte, cela présente des avantages comme de faciliter les micropaiements.
Donc, est-ce que tout ce qui a besoin de vérification publique, sans autorité centrale, est « chaînedeblocsisable » ? Prenons quelques exemples.
Après la monnaie, un autre cas de service qui est souvent géré de manière centralisé est celui de la gestion de noms (création, suppression, etc) dans un espace de nommage. Par exemple, les noms d'utilisateur de Twitter sont gérés de manière centralisée par Twitter, ce qui permet d'assurer l'unicité de ces noms (il n'y a qu'une AdrienneCharmet sur Twitter). Mais cette centralisation donne aussi un contrôle excessif à Twitter : cette entreprise a pu ainsi à de nombreuses reprises fermer des comptes sur la base d'un simple signalement, souvent mensonger. La chaîne de blocs fournit une alternative : l'enregistrement des noms « premier arrivé, premier servi » peut se faire sur une chaîne de blocs, comme le fait le système Twister. Ainsi, plus personne ne peut supprimer des comptes, la censure devient bien plus difficile.
Un exemple très proche de celui-ci est celui des registres de noms de domaine. Ceux-ci enregistrent des noms de domaine, indispensables pour l'utilisation de l'Internet. Mais ils ont aussi le pouvoir de les supprimer (comme dans l'affaire Sci-Hub). On peut donc envisager de remplacer ces registres par une chaîne de blocs, où les transactions sont la création d'un nom de domaine. Le premier exemple avait été le système Namecoin, un autre exemple a été présenté par moi à la Journée du Conseil Scientifique de l'AFNIC de 2016. Attention, j'ai dit que le remplacement des registres de noms de domaine était possible techniquement, pas forcément qu'il était souhaitable, ni qu'il serait adopté (des tas de très bonnes idées n'ont connu aucun succès). En effet, la chaîne de blocs a aussi ses limites (voir plus loin).
Autre exemple d'application sans doute bien adaptée à la chaîne de blocs, le cadastre. Là aussi, on veut une information publique, et modifiable, et publiquement vérifiable. Au lieu de faire confiance à des autorités centrales, on pourrait tout mettre sur une chaîne de blocs. (Un exemple est souvent cité dans les médias mais sans jamais citer de source originelle donc je ne suis pas sûr qu'il soit réel.)
Dernier exemple d'une application qui est bien adaptée à la chaîne de blocs, l'enregistrement d'œuvres à des fins de prouver l'antériorité. Imaginons un artiste qui produise une vidéo, ne peut pas ou ne veut pas la publier tout de suite, mais souhaite pouvoir prouver plus tard qu'on était bien l'auteur. Même chose pour un chercheur scientifique qui est en train de rédiger un article, il ne sait pas encore quand il pourra le publier (il faut terminer certains détails, et puis le processus de publication scientifique peut être très long) mais, en cas de fuite, il veut pouvoir faire valoir son antériorité. Il existe des solutions centralisées traditionnelles, nécessitant une confiance aveugle dans un organisme comme l'INPI avec les enveloppes Soleau ou comme Ma Preuve. À la place, on pourrait utiliser la chaîne. Mais mettre directement leur œuvre dans la chaîne de blocs aurait deux inconvénients : cela pourrait leur coûter cher (voir plus loin les coûts de stockage dans la chaîne) et cela révèlerait leur œuvre (puisque la chaîne est publique, et lisible par tous). Une solution possible est le condensat. C'est une opération mathématique simple qui réduit (condense) un document de taille quelconque en un nombre relativement court. La condensation n'est pas inversible (à partir du condensat, on ne peut pas retrouver le contenu original). Les fonctions mathématiques utilisées ont pour propriété qu'on ne peut pas fabriquer un document ayant un condensat donné (sauf chance extraordinaire). Ainsi, si le condensat est stocké dans la chaîne de blocs, seul l'auteur original pourra, le jour venu, produire un document qui correspondra, prouvant ainsi qu'il était bien celui qui avait enregistré le condensat. J'ai développé cette idée dans mon exposé à Pas Sage en Seine 2016 mais ce n'est pas une idée originale. Elle est également mise en œuvre dans le système Blockai. Il a même été proposé d'utiliser une technique analogue pour faciliter le travail des historiens.
Dans le monde de la haute technologie, un bon moyen de trier entre les techniques sérieuses et celles qui relèvent du pipeau, c'est de regarder non pas ce qu'une technique sait faire mais ce qu'elle ne sait pas faire. Si la description d'une technique ne liste pas ses limites, n'indique pas ce qu'elle ne peut pas faire, c'est probablement que cette technique est du pipeau. Voyons donc les cas où la chaîne de blocs n'est pas adaptée. D'abord, un mot sur les coûts. Comme tous les nœuds (toutes les machines du réseau) doivent exécuter les transactions (pour pouvoir les vérifier), il n'est pas exagéré de dire que « la chaîne de blocs est le plus lent et le plus cher calculateur du monde ». Pour éviter les abus, toutes les transactions doivent être payées, et le coût dépend, par exemple, de la taille des données stockées. Pas question, donc, de stocker des vidéos dans la chaîne. (Tout au plus peut-on stocker de courtes données, comme les condensats cités plus haut.) Pour la même raison, les applications qui nécessitent de longs calculs ne sont pas adaptées à la chaîne de blocs.
Celle-ci a d'autres limites : comme la chaîne est publique, il ne faut surtout pas stocker de données confidentielles. On peut parfois stocker uniquement un condensat, comme dans l'exemple plus haut, mais il faut rappeler que les métadonnées (qui stocke des données et quand, par exemple) restent visibles et qu'elles peuvent déjà beaucoup révéler. Contrairement à une légende souvent reprise par des médias sensationnalistes, la chaîne n'est pas adaptée aux transactions vraiment confidentielles. Vouloir, comme je l'ai lu dans certains articles, stocker données de santé ou fichiers scolaires est donc absurde.
La chaîne de blocs est une construction virtuelle, ne vivant que sur un réseau d'ordinateurs. Elle ne permet donc pas de contrôler des objets physiques. Ainsi, on a vu parfois des articles promettant de remplacer Airbnb par la chaîne de blocs. On peut à la rigueur gérer une serrure connectée via une application qui lit la chaîne. Mais ce n'est pas l'application qui va regarder l'état de l'appartement après le passage du locataire et faire un rapport qui influencera la réputation du locataire (une information essentielle sur Airbnb, que connaissent tous les gens qui l'ont réellement utilisé).
Cette présentation était forcément assez générale. Le monde des chaînes de blocs est en pleine effervescence et les projets sont innombrables. Parmi les propositions nouvelles, on entend souvent parler de « chaînes de blocs privées ». Souvent, ce n'est pas décrit de manière assez précise pour qu'on puisse se faire une opinion sur ces « chaînes privées ». Disons qu'une chaîne vraiment privée n'a aucun intérêt : ce serait une base de données plus lente et plus chère que les bases existantes. À la rigueur, il peut y avoir un intérêt pour des chaînes « semi-privées », par exemple au sein d'un consortium dont les membres ne se font pas confiance.
Et pour finir, un petit rappel sur des inconvénients des chaînes. Je ne veux pas dire que cette technologie est sans intérêt, bien au contraire (je ne prendrais pas la peine d'écrire sur quelque chose absolument sans intérêt). Mais elle a des limites. On a dit que toutes les transactions étaient signées, ce qui est crucial pour la sécurité de la chaîne. Mais cette sécurité repose sur la bonne gestion des clefs cryptographiques utilisées. Il faut à la fois empêcher des tiers de lire les clefs privées (pas facile sur une machine Windows infestée de logiciels malveillants) et s'assurer que ces clefs privées sont bien sauvegardées, pour faire face, par exemple, à une panne du disque dur. Cela complique sérieusement l'utilisation de la chaîne de blocs pour M. Michu ! Il existe bien sûr des solutions techniques (signatures multiples) et organisationelles (des « notaires » à qui on sous-traiterait ce travail) à ce problème mais elles sont encore rares.
D'autre part, le caractère immuable des transactions dans la chaîne a des avantages (la censure est difficile) et des inconvénients (pas de droit à l'oubli, les transactions sont visibles éternellement...)
Merci à Michel Guillou pour ses articles et pour l'idée de celui-ci.
Date de publication du RFC : Août 2016
Auteur(s) du RFC : P. Wouters (Red Hat)
Expérimental
Réalisé dans le cadre du groupe de travail IETF dane
Première rédaction de cet article le 25 août 2016
Dernière mise à jour le 12 décembre 2017
Un problème classique du système de
cryptographie
OpenPGP, normalisé dans le RFC 9580 est de vérifier les clés publiques des
correspondants. Les trouver, c'est relativement facile : le
correspondant pense à vous les envoyer ou bien on se sert tout
simplement d'un serveur de clés. Mais
ceux-ci ne garantissent rien sur la clé. N'importe qui peut créer
une clé marquée flotus@whitehouse.gov
et la
mettre sur les serveurs de clé, même si cette clé n'a rien à voir
avec la Maison-Blanche. Avant la solution
de ce nouveau RFC, il n'existait pas de
mécanisme sécurisé pour récupérer une clé publique PGP. Que
propose ce RFC ? De mettre les clés dans le
DNS (nouveau type d'enregistrement OPENPGPKEY
), dans le domaine de la partie droite de
l'adresse de courrier, sécurisée par
DNSSEC. En gros, il s'agit de faire pour le
courrier et PGP ce que fait déjà DANE (RFC 6698) pour
le Web/TLS.
Les serveurs de clés utilisent le protocole HKP (jamais décrit dans un RFC). Ils fournissent un service très utile en permettant de chercher une clé, par son identificateur, ou par l'adresse de courrier associé. Voici un exemple par identificateur :
% gpg --recv-key 0xF3396311465F8E5D gpg: requesting key 465F8E5D from hkps server hkps.pool.sks-keyservers.net gpg: key 465F8E5D: public key "Amaelle G <amaelle.guiton@techn0polis.net>" imported ... gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1)
et un par adresse (notez que les adresses sont probablement toutes fausses) :
% gpg --search-key elysee.fr gpg: searching for "elysee.fr" from hkps server hkps.pool.sks-keyservers.net (1) hollande (flamby) <hollande@elysee.fr> 2048 bit RSA key CF22758A, created: 2014-01-06 (2) jacques chirac (ancienne adresse) <jacques-chirac@elysee.fr> 2048 bit RSA key 2A97F759, created: 2007-11-15, expires: 2007-11-16 (expired) (3) kaziwan <kaziwan@elysee.gouv.fr> 1024 bit DSA key AA7FD67C, created: 2005-11-28 (4) Gerard Calestroupat <gerard.calestroupat@elysee.fr> 1024 bit DSA key 82F02C73, created: 2003-08-05, expires: 2003-08-08 (expired) (5) Toto Berlingo <T.Berlingo@Elysee.fr> 1024 bit DSA key E9E920B7, created: 1999-06-10
Ces serveurs n'offrent aucune garantie : n'importe qui peut y publier une clé, avec n'importe quelle adresse et certaines clés sont clairement mensongères. L'usage normal est de récupérer la clé et ses signatures, puis de vérifier les signatures. Si elles sont faites par des gens qu'on a validés (directement, ou bien transitivement, jusqu'à une certaine profondeur), on estime la clé correcte (c'est ce qu'on nomme le web of trust). Autrement, la clé ne vaut rien. En outre, le seul système de révocation est de signer une révocation avec sa clé privée : si on l'a perdue, on ne pourra jamais retirer la clé des serveurs de clé. Pour ces deux raisons (fausses clés, et clés devenues inutilisables), il est donc difficile d'utiliser automatiquement, depuis un MUA ou un MTA, ces serveurs.
La solution proposée dans ce RFC est, comme souvent aujourd'hui, d'utiliser le DNS, qui a montré sa fiabilité et son ubiquité. Tout le monde peut faire des requêtes DNS, même coincé derrière un pare-feu, et tout le monde peut les valider, grâce à DNSSEC (RFC 4035).
On va donc publier dans sa zone DNS des enregistrements de type
OPENPGPKEY
, indexés par la partie gauche de
l'adresse de courrier (c'est un peu plus compliqué, car elle peut
contenir des caractères qui sont spéciaux pour le DNS ; voir plus
loin). Le correspondant qui veut envoyer du courrier à quelqu'un
cherchera cet enregistrement dans le DNS, et, s'il en trouve un,
le validera avec DNSSEC et récupérera ainsi une clé PGP
relativement sûre. La révocation d'une clé se fait simplement en
retirant l'enregistrement du DNS.
La solution de ce RFC rend envisageable de récupérer et de vérifier automatiquement une clé avant l'envoi d'un message. Mais le RFC note bien qu'elle ne remplace pas complètement le web of trust, qui reste nécessaire si on veut une vérification sérieuse.
Ce RFC a le statut « Expérimental ». Il s'agit de tester l'idée
et de voir si elle marche bien, et n'a pas trop
d'inconvénients (par exemple de taille des zones DNS pour les
domaines gérant beaucoup de comptes de courrier, surtout vu la
taille des enregistrements OPENPGPKEY
). Si le nombre de messages chiffrés avec OpenPGP
augmente significativement suite à ce RFC, ce sera bon
signe.
Notez qu'une expérience ressemblant à celle-ci avait déjà
été faite avec le type d'enregistrement DNS
CERT
du RFC 4398. Ce fut un échec
(peu de déploiement, peut-être en raison de la complexité du type
CERT
).
La section 2 de notre RFC décrit le format du nouveau type d'enregistrement DNS. Chaque enregistrement contient une et une seule clé. Si un utilisateur a plusieurs clés, il doit créer plusieurs enregistrements. Le type est 61 (et enregistré à l'IANA depuis août 2014). La partie droite de l'enregistrement (les données) contient la clé et au moins un ID et une auto-signature. Les clés PGP complètes, avec des tas de signatures, peuvent être grosses, trop pour le DNS ; le RFC recommande de ne publier que des clés minimales (pas trop de signatures, par exemple, et évidemment pas les photos qu'on peut inclure dans un attribut de la clé, cf. RFC 9580, section 5.12.1). Avec GnuPG, regardez l'exportation de ma clé avec toutes ses méta-données, et en exportation minimale (l'annexe A du RFC décrit les commandes GnuPG à utiliser) :
% gpg --export CCC66677 > key.pgp % ls -lh key.pgp -rw-r--r-- 1 bortzmeyer bortzmeyer 86K Aug 25 17:17 key.pgp % gpg --export --export-options export-minimal,no-export-attributes CCC66677 > key.pgp % ls -lh key.pgp -rw-r--r-- 1 bortzmeyer bortzmeyer 5.8K Aug 25 17:18 key.pgp
Le format utilisé est celui du RFC 9580,
section 10.1. C'est donc du binaire qui circule sur le réseau
(rappelez-vous bien que, dans le DNS, le format de présentation,
celui des fichiers de zone, et de la sortie de
dig, n'a rien à voir avec le format binaire
utilisé sur le réseau.) Les formats « texte » d'OpenPGP
(« ASCII armor ») ne sont pas utilisés sur le
réseau. (Donc, avec GnuPG, pas d'option --armor
.)
Le format de présentation (celui des fichiers de zone et de la sortie de dig) encode la clé en Base64.
Et la partie gauche de l'enregistrement DNS ? Quel est le nom de domaine utilisé ? La section 3 du RFC fixe les règles :
OPENPGPKEY
. La clé pour l'adresse
stephane+chose@trucmachin.example
sera donc dans
la zone trucmachin.example
.stephane+chose
, dans l'exemple ci-dessus),
et du composant _openpgpkey
,
avec le domaine de l'adresse de courrier
(trucmachin.example
dans l'exemple
ci-dessus). Le condensat est tronqué à 28 octets. (Le nom de domaine n'est pas utilisé dans le
condensat, pour faciliter la vie des opérateurs qui proposent la
même adresse dans différents domaines.)"jipoune le meilleur"@example.com
est une
adresse de courrier légale) sont retirés.
Ainsi, si l'adresse de l'utilisateur est
hugh@example.com
, la requête
OPENPGPKEY
devra chercher
c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6._openpgpkey.example.com
.
Voici comment calculer cela avec les outils du
shell Unix (28
octets = 56 caractères dans la représentation en hexadécimal) :
% echo -n hugh | sha256sum | cut -c -56 c93f1e400f26708f98cb19d936620da35eec8f72e57f9eec01c1afd6
Une des difficultés pour trouver le bon nom de domaine est que
les applications doivent traiter la partie gauche des adresses de
courrier comme opaque (pas le droit d'analyser sa structure) et
qu'elles ne connaissent pas les règles de canonicalisation
qu'appliquera le domaine de destination, comme
d'ignorer la casse de la partie locale (ce
qui est souvent fait, mais pas toujours). Par exemple,
Gmail ignore les points dans les adresses
(donc foobar@gmail.com
et
foo.bar@gmail.com
arrivent dans la même boîte
aux lettres). L'émetteur qui ne connait pas cette règle va
chercher la clé dans un domaine qui ne sera pas le bon. Idem avec
les sous-adresses utilisées par certains domaines (en général
avec le séparateur plus, comme
stephane+blog
,
stephane+ietf
, etc). Le RFC rappelle que
l'émetteur ne peut pas se permettre de deviner ces règles locales,
et qu'elles peuvent changer à tout moment. C'est au destinataire
de se débrouiller, en publiant la clé à plusieurs noms, et en
faisant attention aux variantes qu'il publie.
L'internationalisation des adresses de courrier complique évidemment encore un peu les choses (voir par exemple la section 10.1 du RFC 6530).
La section 6 du RFC se penche sur un problème pratique qu'on rencontre parfois avec le DNS : la difficulté à recevoir des réponses au-delà d'une certaine taille (il y a trois limites fréquemment rencontrées, la très ancienne limite de 512 octets du DNS, largement dépassée de nos jours, la limite de la MTU à 1 500 octets, au-delà de laquelle peut commencer la fragmentation, et la limite par défaut de la plupart des clients DNS à 4 096 octets). Les clés PGP peuvent être grosses, et le RFC recommende donc si possible de les récupérer sur TCP, pas UDP.
La section 7 de notre RFC analyse les questions de sécurité
liées à cette technique. Elle rappelle que
DNSSEC doit être
utilisé : les enregistrements OPENPGPKEY
récupérés ne doivent être utilisés que s'ils sont signés, et que
la signature est valide. (Autrement, il serait trop facile à un
attaquant de répondre avec une fausse clé.) Mais si DNSSEC est
nécessaire, il n'est pas suffisant et la validation habituelle des
clés PGP reste nécessaire si on veut un haut niveau de
confidentialité. Ceci dit, comme souvent en sécurité, le mieux est
l'ennemi du bien, et il vaut mieux une clé pas très vérifiée
plutôt que d'envoyer le message en clair, comme le fait presque
tout le monde aujourd'hui.
Et, évidemment, la sécurité DNSSEC doit être équivalente à la sécurité PGP puisqu'un attaquant qui aurait cassé la clé DNSSEC pourrait remplacer toutes les clés PGP du domaine. Il faut donc une cohérence dans les politiques de sécurité entre PGP et DNSSEC (section 7.6).
Autre problème de sécurité, cette fois lié à la vie
privée : les requêtes DNS révèlent avec qui on veut
communiquer de manière sécurisée par courrier (RFC 7626). Le fait que le nom de domaine utilisé soit un
condensat de la partie locale de l'adresse de courrier limite un
peu les risques, mais pas suffisamment (si on soupçonne qu'Alice
écrit à bob@example.com
mais qu'on n'en est
pas sûr, il suffit de construire le nom où se trouve
l'enregistrement OPENPGPKEY
et de vérifier
que ce nom est demandé, cf. section 7.4). C'est d'autant plus grave que les clients
DNS actuels envoient en général le nom de domaine complet à
tous les serveurs, même ceux qui n'en ont pas
besoin. La minimisation de la requête (RFC 9156) limite ce problème. Le chiffrement des requêtes
DNS (RFC 7858) peut faire le reste. Le cache
du DNS limite un peu les risques et il est donc essentiel de ne
pas faire une requête DNS externe à chaque fois qu'on envoie un
message PGP à quelqu'un, cela ferait fuiter bien trop
d'informations (section 7.5).
Pour limiter les risques qu'un attaquant récolte toutes les adresses de courrier du domaine, le RFC recommande de signer la zone en utilisant NSEC3 (RFC 5155).
À l'inverse de ce souci de protection de la vie privée, si une organisation veut lire le courrier de ses employés, la solution est qu'elle publie une clé d'organisation dans le DNS, pour pouvoir déchiffrer les messages entrants.
Un autre problème de sécurité est le risque d'utilisation dans
des attaques par
amplification. La taille importante des enregistrements
OPENPGPKEY
(surtout avec les clés
RSA) aggrave ce risque. Le RFC suggère de
n'envoyer ces enregistrements via UDP que si l'adresse IP source de la
requête a été vérifiée, par exemple avec les petits gâteaux du
RFC 7873.
Où en sont les mises en œuvre de ce RFC ? GnuPG contient le code pour gérer ces clés dans le DNS depuis la version 2.1.9. Même chose pour openpgp-milter.
L'outil hash-slinger
permet quant à lui de générer et de vérifier des enregistrements
OPENPGPKEY
:
% openpgpkey --fetch --uid paul@nohats.ca paul@nohats.ca -----BEGIN PGP PUBLIC KEY BLOCK----- Comment: paul@nohats.ca key obtained from DNS Comment: key transfer was protected by DNSSEC Version: GnuPG v1 mQENBFaJkKsBCADDSwQawRsKYqY/DuxWZjNNn39f14tDaswbpuF+PorNnt0MrepI 0yVY28NQ+5P09j75Os1jlqksK06aAVBtkJvr+T1ip85AxPUdTjD3U3zhM5/YATMi ...
On peut alors enregistrer la clé dans le trousseau PGP :
% openpgpkey --fetch --uid paul@nohats.ca paul@nohats.ca | gpg --import gpg: key BBAE5D31: public key "Paul Wouters (online key) <paul@nohats.ca>" imported gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1)
Voici un exemple de récupération de ma clé :
% openpgpkey --fetch --uid 'stephane@bortzmeyer.org' stephane@bortzmeyer.org |gpg pub 4096R/CCC66677 2014-02-08 Stéphane Bortzmeyer (Main key) <stephane@bortzmeyer.org> uid Stéphane Bortzmeyer <stephane@sources.org> uid Stéphane Bortzmeyer (Work address) <bortzmeyer@nic.fr> uid TextSecure fingerprint (05 d6 3b dc b7 e4 d7 69 2f f6 24 d5 51 31 88 2f a5 59 ae 96 e0 fb a5 75 ab e6 6c 64 ca e9 bb 6a 77) <BdY73Lfk12kv9iTVUTGIL6VZrpbg+6V1q+ZsZMrpu2p3@base64> sub 4096R/96A4A254 2014-02-09 [expires: 2018-01-10] sub 4096R/57F02AA1 2014-02-09 [expires: 2017-01-10]
Mais comment ai-je fait pour que ça marche ? hash-slinger permet de créer la clé directement au bon format :
% openpgpkey --create stephane@bortzmeyer.org ; keyid: 555F5B15CCC66677 28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. IN OPENPGPKEY mQINBFL2VNABE...
Il n'y a plus qu'à la mettre dans le fichier de zone, et à re-signer.
Mais, car il y a un mais, cela ne marche que si on a des logiciels
récents, qui connaissent le type 61
(OPENPGPKEY
). Si ce n'est pas le cas, le signeur
refusera de signer, ou le serveur de recharger la zone. C'était mon
cas, en raison d'une trop vieille version
d'OpenDNSSEC. Trois solutions, commençons par la
plus simple, demander à hash-slinger de générer un enregistrement DNS
à la syntaxe générique (« types inconnus », du RFC 3597) :
% openpgpkey --create stephane@bortzmeyer.org --output generic ; keyid: 555F5B15CCC66677 28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. IN TYPE61 \# 5874 99020d0452f654d001100096b30513d96c42e697fd06674b1...
Et c'est cet enregistrement à la syntaxe générique qu'on met dans le fichier de zone. Sinon, si on aime bien faire l'encodage soi-même, utilisons xxd :
% openpgpkey --create stephane@bortzmeyer.org > key.zone [Edit to keep the zone data] % base64 -d key.zone > key.bin [wc -c key.bin to know what number to put in the zone file] % xxd -p key.bin > key.hex
Et on met le contenu de key.hex
dans le fichier
de zone.
Sinon, l'annexe A du RFC fournit une variante de cette solution,
utilisant hexdump.
Voici la récupération de cette clé dans le DNS, avec un
dig récent, qui connait ce type
OPENPGPKEY
et sait formater le résultat :
% dig OPENPGPKEY 28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org ;; Truncated, retrying in TCP mode. ... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36368 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 9, ADDITIONAL: 13 ... ;; ANSWER SECTION: 28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. 85841 IN OPENPGPKEY ( mQINBFL2VNABEACWswUT2WxC5pf9BmdLHzPeXzHZfvik ExJHaQ7LHPRVjAQtBiBN0vI3Uh0VgFzjA+0H2sqTduJY tqd8mrTh9clDnCbrMU8svc7MeWxkW21ogjqBYL8puA3d ...
Notez le « Truncated, retrying in TCP mode ». L'enregistrement est trop gros pour les paquets UDP qu'accepte dig par défaut (il fait huit kilo-octets, dig accepte quatre par défaut). Notez aussi le bit AD (Authentic Data) dans la réponse : celle-ci a bien été validée par DNSSEC.
Avec un dig ancien, qui ne connait pas ce nouveau type (et, cette fois, on demande directement en TCP, comme le recommande le RFC) :
% dig +tcp -t TYPE61 28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org ... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19989 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 9, ADDITIONAL: 29 ... ;; ANSWER SECTION: 28182f0a278161989f90f090dabd6cab331663d8509ddbae617bb1e7._openpgpkey.bortzmeyer.org. 86206 IN TYPE61 \# 5874 ( 99020D0452F654D001100096B30513D96C42E697FD06 674B1F33DE5F31D97EF8A4131247690ECB1CF4558C04 2D06204DD2F237521D15805CE303ED07DACA9376E258 B6A77C9AB4E1F5C9439C26EB314F2CBDCECC796C645B ...
Sur ce sujet, vous pouvez aussi lire l'article de Johannes Weber, qui détaille une utilisation de l'outil de Shumon Huque.
Date de publication du RFC : Juillet 2016
Auteur(s) du RFC : D. Kutscher (NEC), S. Eum (NICT), K. Pentikousis (EICT), I. Psaras (UCL), D. Corujo (Universidade de Aveiro), D. Saucez (INRIA), T. Schmidt (HAW HAmburg), M. Waehlisch (FU Berlin)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF icnrg
Première rédaction de cet article le 25 août 2016
Quels sont les défis qui attendent l'ICN (Information-Centric Networking), ce paradigme où le composant de base du réseau n'est pas la machine ou l'interface réseau mais l'unité d'information ? Le concept est à la mode depuis pas mal d'années mais ne progresse guère sur plusieurs points importants. Ce RFC de synthèse fait le point sur ce qui ne marche pas ou pas parfaitement dans l'ICN, et les axes de recherche souhaitables.
L'idée de base de l'ICN (également nommé
CCN pour Content-Centric Networking) est de
considérer que le réseau sert surtout à accéder à du contenu (un
point de vue Minitel 2.0 très contestable)
et qu'il faut donc architecturer le réseau autour de cet accès au
contenu. Une unité d'information a un nom et
le réseau permet avant tout d'accéder à cette unité d'information,
en échange de ce nom (get(NOM)
...) L'unité
d'information est parfois nommée NDO pour Named Data
Object. On voit
que la localisation de l'information (que ce soit dans l'espace
physique, ou dans celui défini par la topologie du réseau
Internet) n'est pas prise en compte. Cette
approche permettrait, en théorie, une meilleure efficacité (la
mise en cache par les composants du réseau améliorerait les
performances), un meilleur passage à l'échelle (la réplication de
données populaires serait simple), et une meilleure résilience (le
contenu serait à plusieurs endroits). Cette idée
est décrite plus longuement dans le RFC 7476
(lecture recommandée, avant ce RFC 7927), et j'en ai
déjà écrit une critique.
Pour la mettre en œuvre, on peut envisager une couche supplémentaire « accès au contenu » au-dessus de l'Internet actuel, ou bien une approche « table rase » où on remplace IP par un protocole orienté ICN. Notez qu'il existe déjà des mécanismes pour accéder à du contenu par son nom, en ne se souciant pas de la localisation, mécanismes qui fournissent la rapidité, le passage à l'échelle et la robustesse dont on parlait plus haut. Le plus évident est bien sûr BitTorrent mais on notera que les promoteurs de l'ICN n'en parlent quasiment jamais...
D'abord, une synthèse des problèmes avec l'approche actuelle, vus du point de vue des partisans de l'ICN (section 2 du RFC). Cette approche, qualifiée de host-centric, met au centre du réseau la machine. Identifiée par des noms de domaine et/ou des adresses IP, c'est l'unité de base du réseau. On peut bien sûr bâtir une couche ICN (ou para-ICN) au-dessus de cette approche (un CDN est un exemple partiel) mais, comme le réseau n'est pas au courant, cela entraine des limitations :
Pour ce dernier point, celui de la validation, je suis personnellement toujours stupéfait que le Web n'ait toujours pas un mécanisme standard pour authentifier une page qu'on a récupéré. À l'heure actuelle, il faut toujours se contenter de mécanismes ad hoc, comme une signature PGP détachée du fichier qu'on veut valider. (Non, HTTPS n'est pas une solution, d'abord parce qu'il ne fonctionne qu'en transfert, pas après, donc on ne peut pas valider quelque chose qui stationne dans un cache, et ensuite parce qu'il est incompatible avec des miroirs, sauf à distribuer une clé privée à plein d'autres acteurs.)
Avant d'aller plus loin, la section 3 du RFC nous apporte une petite révision des termes et concepts essentiels en ICN. Pour les termes, il faut se souvenir de :
Une fois armé de cette terminologie, on peut expliquer le concept central de l'ICN : un réseau dont l'objet de base est le NDO (pas le paquet, pas la machine), et dont le service de base est d'envoyer des NDO aux demandeurs.
Ceux qui ont assisté à mon exposé à Pas
Sage En Seine 2016 ont pu voir un exemple d'ICN mis en
œuvre sur la chaîne de blocs (exemple FindByHash
).
Sur le papier, c'est très joli, mais voyons maintenant les défis que cela pose (section 4 du RFC, le gros morceau de ce texte). D'abord, le nommage et l'authentification (les deux sont en général liés dans l'ICN). Nommer un NDO est aussi crucial dans l'ICN que de donner une adresse IP à une machine dans l'Internet classique. Et comme l'objet nommé peut être récupéré à partir de divers endroits dans le réseau ICN, vérifier l'authenticité par le biais de l'origine marche encore moins que dans le Web actuel. Il y a des tas de solutions possibles, résumées dans des études comme « Naming in Content-Oriented Architectures » de Ghodsi, A., Koponen, T., Rajahalme, J., Sarolahti, P., et S. Shenker ou bien « A Survey of Information-Centric Networking » de Ahlgren, B., Dannewitz, C., Imbrenda, C., Kutscher, D., et B. Ohlman.
Il y a deux grandes façons d'organiser le nommage dans l'ICN :
espace de nommage hiérarchique, ou bien espace de nommage
plat. Par exemple, un nommage hiérarchique pourrait produire des
noms comme pays/éditeur/date/NDO
. Cette façon
de nommer simplifie nettement le routage et le passage à
l'échelle. La structure des noms permet de faire une structure
identique pour la PKI qui servira à
authentifier le contenu (ainsi, une AC pour
un éditeur donné ne pourra pas signer des certificats d'un autre
éditeur, contrairement à ce qu'on voit sur le Web aujourd'hui, où
la structure arborescente des noms de domaine n'est pas utilisée pour
limiter les dégâts que peut faire une AC.) Cette structure hiérarchique peut aussi permettre de faire des noms lisibles par des
humains. (Par contre, le RFC oublie de noter que de tels
noms suscitent d'innombrables disputes de
gouvernance : tout le monde veut être à la racine,
veut tel nom, etc.)
Autre solution, l'espace de nommage plat. Typiquement, le NDO est désigné par un condensat cryptographique de son contenu. Cela permet l'authentification de manière évidente : on récupère le contenu, on calcule le condensat, et on doit retrouver le nom. Et un tel système peut être complètement réparti, sans autorité jouant un rôle particulier. Par contre, l'absence de structure dans le nom nécessitera un système de résolution adapté (comme une DHT). Une telle solution est même déjà décrite dans un RFC, le RFC 6920.
Aucune des deux façons de gérer l'espace de nommage n'est parfaite (cf. le triangle de Zooko). Par exemple, les condensats cryptographique ne sont pas maniables par un humain, mais les noms hiérarchiques ne peuvent pas être alloués de manière complètement pair-à-pair.
Les sujets de recherche existants sur le nommage sont :
En parlant de restriction d'accès, la sécurité, dans son ensemble est un difficile problème pour l'ICN (section 4.2). C'est le cas de la plupart des solutions miracles qui sont proposées pour l'Internet : une idée simple qui semble bien marcher, puis, dès qu'on creuse les détails pratiques, les ennuis surgissent puis, dès qu'on arrive à la sécurité, l'idée simple s'effondre. Dans le cas de l'ICN, le RFC suggère plusieurs pistes de travail. D'abord, l'authentification des données, sans doute la partie la plus facile à réaliser (et celles, on l'a vu, où le Web actuel est défaillant). Comme on peut récupérer un NDO depuis n'importe où, pas forcément depuis le serveur d'origine, il est crucial de l'authentifier. Évidemment, si le nom de l'objet est un condensat de son contenu, comme c'est le cas avec le RFC 6920, la vérification de l'intégrité est facile : on récupère l'objet, on condense et on regarde si on tombe bien sur la même valeur. Pour des objets générés dynamiquement, cette solution ne fonctionne pas et il faut donc signer l'objet avec de la cryptographie asymétrique. D'ailleurs, cette cryptographie est nécessaire dans tous les cas : vérifier le nom-qui-est-un-condensat prouve l'intégrité de l'objet, pas que l'objet vient bien de l'auteur attendu. Ici, une signature cryptographique est donc également nécessaire. Comme toujours avec la cryptographie à clés publiques, cela laisse ouvert l'énorme problème de la distribution des clés... (cf. RFC 5280 pour une approche possible).
Pour l'utilisateur normal, vérifier que l'objet
148aec5042e7c05df755d9ce8adec80a1e9c10b1557194fd94e45146416a0de8
a bien un contenu qui correspond à ce condensat n'a qu'un intérêt
limité. M. Michu voudrait une authentification plus forte,
vérifier qu'il s'agit bien du guide
de sécurité Java de l'ANSSI ou que c'est bien la série télé qu'il
cherchait. Et, là, le problème est difficile. Les
défenseurs du pair-à-pair prétendent par exemple souvent que
BitTorrent est pair-à-pair, qu'il
fonctionne sans centre mais, pour la très grande majorité des
usages, c'est faux. M. Michu utilise un moteur de recherche
centralisé, comme The Pirate Bay ou comme
isoHunt. Il récupère alors un
magnet (qui contient un
condensat du fichier convoité), et, ensuite, on est vraiment en
pair-à-pair : on télécharge, on vérifie le condensat et on
s'installe dans son fauteuil pour regarder. Mais l'étape du moteur
de recherche, avec ses pubs mensongères, était tout, sauf
pair-à-pair.
En ICN, comment lier un NDO à une identité du monde extérieur, par exemple un acteur connu et de confiance ? C'est un problème essentiel mais non encore résolu.
Le contrôle d'accès, on l'a vu, est également un problème difficile. Comment faire si je veux vendre du contenu sans permettre aux destinataires de le redistribuer ? Il n'y a pas de solution évidente. Les approches intégrées sont celles où l'entité qui publie utilise des mesures pour limiter la redistribution (typiquement des menottes numériques), les approches séparées comptent sur une tierce-partie qui gère les accès (je vous laisse imaginer les conséquences en terme de liberté de choix de son logiciel par M. Michu...) On peut bien sûr chiffrer le contenu qu'on va distribuer (ah, Canal+...) mais il reste à distribuer les clés ensuite.
La cryptographie n'est pas éternelle, les algorithmes de cryptographie finissant par être affaiblis, puis cassés. Ce n'est pas un problème si on publie du contenu à courte durée de vie mais, si le contenu est encore utile et payant dans dix ans, l'efficacité de la cryptographie devient incertaine : comment garantir que l'algorithme utilisé sera toujours incassé ? L'idéal serait un mécanisme de re-signature et de re-chiffrement mais cela pose encore le problème de la gestion des clés privées.
Autre conséquence de la mise en cache et de la distribution à partir de plusieurs endroits, l'auteur d'un contenu n'aura plus de statistiques d'accès fiables. De la même façon, retirer un contenu publié sera encore plus difficile que sur le Web actuel (un contenu populaire est davantage répliqué et donc plus dur à supprimer).
Autre problème de sécurité avec l'ICN, le risque d'attaque par déni de service via le cache. Un des buts de l'ICN est de permettre, et même d'encourager, la mise en cache automatique du contenu par les éléments du réseau, comme les routeurs. Cela ouvre une possibilité d'attaque où le méchant téléchargerait plein de choses sans intérêt juste pour remplir les caches. Pire : comme l'ICN renonce explicitement au principe de bout en bout, ces éléments intermédiaires mantiennent un état et peuvent également être attaqués par ce biais. Par exemple, en annonçant plein de contenus divers, on pourrait remplir la table de routage.
Après la sécurité, le routage dans l'ICN pose également des défis intéressants. Le terme n'a pas tout à fait le même sens dans l'ICN que dans l'Internet actuel. L'ICN permet d'obtenir un contenu (le NDO, Named Data Object) en échange d'un nom. Cela nécessite trois étapes : la première est de résoudre le nom en un localisateur, plus concret. La deuxième est d'envoyer la demande de contenu à cet endroit. La troisième est d'obtenir la réponse (le NDO). Ces trois étapes peuvent être faites de différentes manières, catégorisées comme routage par nom (route-by-name), recherche par nom (lookup-by-name) et hybride.
Le routage par nom consiste à ne pas avoir la première étape, celle de résolution, ce qui simplifie le modèle : le réseau comprend directement les noms. Il faut donc une « table de routage » dont la taille permette de stocker tous les NDO. Comme on envisage entre 10^15 et 10^22 NDO, le défi technique est colossal. Sans compter qu'il faut aussi identifier la source de la requête, puisqu'il faudra bien lui envoyer le contenu demandé (c'est ce que fait l'algorithme des miettes de pain, cf. Rosensweig, E. et J. Kurose, « Breadcrumbs: Efficient, Best-Effort Content Location in Cache Networks »). Les sujets de recherche sur le routage par nom comportent donc, entre autres :
/IETF/IRTF/ICN/Research challenges
pour ce
RFC) afin de permettre l'agrégation, comment permettre aux
utilisateurs d'utiliser des noms plus simples ? (Se servir d'un
moteur de recherche serait de la triche,
puisqu'on voulait se dispenser de l'étape de résolution.)La catégorie « recherche par nom » regroupe les mécanismes de routage qui, eux, ont une étape de résolution explicite. On résout le nom (qui est pratique pour un humain, et stable) en un localisateur (qui est pratique pour le réseau et qui pourrait être une simple adresse IP). C'est par exemple ainsi que fonctionne le système « MDHT: A hierarchical name resolution service for information-centric networks ». Les défis techniques à relever sont l'accès rapide au localisateur (en se rappelant que le contenu peut être à plusieurs endroits) et la mise à jour efficace (car le contenu peut changer de localisation, c'est même un des buts de l'ICN). Notez que les gens de l'ICN aiment bien réinventer la roue et que le DNS n'est même pas mentionné.
Enfin, il y a les solutions de la catégorie hybride. Par exemple, on fait du routage par le nom en local mais on résout le nom en un localisateur dès qu'on sort de ce domaine local.
Vous aimez les défis techniques et la liste n'est pas encore assez longue pour vous ? Il reste plusieurs problèmes à affronter. Par exemple, le contrôle de congestion. Il n'a pas à être de bout en bout puisque, dans l'ICN, la communication peut se faire via des éléments intermédiaires (voir par exemple « ConTug: A Receiver-Driven Transport Protocol for Content-Centric Networks »).
On a vu qu'un des intérêts principaux de l'ICN était de permettre la mise en cache automatique par des éléments du réseau, et l'accès au contenu à partir de ces caches. La bonne utilisation de ceux-ci soulève plusieurs questions :
ni:
du RFC 6920) ne résout pas le problème : il faut maintenant un
mécanisme pour informer les clients du nouveau nom.Les administrateurs réseau sont habitués à des outils comme ping et traceroute pour tester et déboguer leur réseau. Comment feront-ils avec l'ICN ? C'est un autre défi. Étant donné que ping et traceroute ne sont apparus que de nombreuses années après IP, on peut prévoir que, pendant un certain temps, les administrateurs des réseaux ICN souffriront du manque d'outils adaptés.
Quelles applications utiliseront l'ICN, si tous ces défis sont relevés, et avec succès ? Le RFC se termine par une liste d'applications potentielles (cf. RFC 7476) :
GET
). Les noms des NDO
remmplaceront-ils les URI ? Il n'est pas
évident que tous les usages du Web (POST
,
PUT
, et autres méthodes utilisées par les
applications REST) s'adaptent aussi bien
à l'ICN.Une conclusion personnelle ? Il y a plein d'idées intéressantes dans l'ICN, et c'est donc un sujet de recherche utile, malgré la prémisse de départ (« tout est accès au contenu ») qui est fausse.
Date de publication du RFC : Juillet 2016
Auteur(s) du RFC : L. Colitti (Google), V. Cerf
(Google), S. Cheshire
(Apple), D. Schinazi (Apple)
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 24 juillet 2016
Combien d'adresses IPv6 faut-il permettre à une machine qui se connecte ? « Une » est évidemment le minimum mais est-ce suffisant ? Non, explique ce RFC qui recommande aux opérateurs et FAI de permettre aux machines de s'allouer autant d'adresses IPv6 qu'elles en ont besoin.
IPv6 est juste une nouvelle version d'IP. Ce n'est pas un nouveau protocole. Néanmoins, la taille bien plus importante de son espace d'adressage a des conséquences qui sont souvent oubliées par les administrateurs de réseaux. Ainsi, il est fréquent que la gestion des réseaux soit faite en limitant chaque machine à une seule adresse IPv6. En IPv4, il n'y a évidemment pas d'autre choix possible, en raison de la pénurie d'adresses publiques. Mais en IPv6, il n'y a aucune raison de se limiter, et beaucoup de raisons de permettre davantage d'adresses. Bref, bien qu'IPv6 ne soit pas complètement nouveau, cela ne veut pas dire que les bonnes pratiques IPv4 s'appliquent directement à IPv6.
Il est banal de faire remarquer que les adresses IPv6 sont, en pratique, illimitées. Un simple lien réseau (numéroté avec un préfixe de 64 bits) offre quatre milliards de fois plus d'adresses que tout l'Internet IPv4 ! Il n'est donc pas du tout obligatoire de rationner. IPv6 est conçu depuis le début (section 2 de notre RFC) avec l'idée que chaque machine (et même chaque interface réseau de chaque machine) aura plusieurs adresses IP (par exemple, une adresse locale au lien, une adresse publique stable, et au moins une adresse temporaire du RFC 8981). Et toutes les mises en œuvre d'IPv6 existantes gèrent cela correctement.
Mais quel est l'intérêt de permettre plusieurs adresses ? La section 3 de ce RFC répond à la question :
draft-herbert-nvo3-ila
).Et quels sont les problèmes si on ne fait pas ce que recommande ce RFC ? La section 4 les liste. Évidemment, si ajouter des adresses IP est complètement impossible, on est fichus. Et si la connexion au réseau permet d'ajouter des adresses IPv6 mais que cela nécessite une action explicite (par exemple via l'interface Web de l'hébergeur) ? Cela entraine :
Pourquoi les opérateurs restreindraient-ils ainsi l'obtention d'adresses IPv6 supplémentaires ? Par pur sadisme ? Non, il peut y avoir des raisons objectives :
Avec le temps, il faut espérer que les limites matérielles reculent et que la raison business (faire payer) soit rejetée par les utilisateurs (ils peuvent la contourner, par exemple en faisant du NAT, ce qui serait un comble pour IPv6).
À propos de NAT, est-ce que c'est une bonne stratégie pour résoudre le problème d'un opérateur qui ne laisserait pas assez d'adresses IPv6 à ses clients (section 5 du RFC) ? Les problèmes et limites du NAT sont bien connus (RFC 2993). Les applications sont plus complexes (car leurs programmeurs doivent déployer des trésors d'ingéniosité pour contourner le NAT), la gestion de la durée de vie des correspondances entre adresses dans le routeur NAT est pénible (quel intervalle entre les paquets d'entretien de la connexion ?), etc. C'est pour cela que le NAT sur IPv6 est très déconseillé (RFC 5902).
Ce n'est pas faute de mises en œuvre (le NAT66 est dans Linux depuis 2012...), un vendeur de virtualisation l'a aussi développé, précisement pour contourner ce manque d'adresses IPv6 allouées, mais il n'est pas souhaitable que cela continue. Le but d'IPv6 est d'avoir une vraie connectivité de bout en bout, qui ne soit limitée que par des choix délibérés (Alice ne veut plus parler à Bob), pas par des limites techniques inutiles.
Et si l'opérateur du réseau où se connecte la machine a été convaincu par ce RFC, et veut permettre à ses clients d'allouer les multiples adresses IPv6 dont ils ont besoin, quels sont les mécanismes techniques dont il dispose pour cela ? La section 6 les couvre :
Un tableau à la fin de la section 6 résume les forces et faiblesses de chaque solution.
Au fait, combien d'adresses exactement peut-on s'attendre à voir sur une seule machine ? La section 7 se lance dans la spéculation. Les adresses « vie privée » du RFC 8981 peuvent consommer jusqu'à huit adresses en même temps. Avec une demi-douzaine de services réseau, et une demi-douzaine de machines virtuelles (ou de containers) hébergés, avoir vingt adresses sur une seule machine peut donc être raisonnable. Mais, bien sûr, il est difficile de prévoir les usages futurs et, en pratique, ce sera peut-être bien plus.
Allez, c'est presque fini, la section 8 du RFC synthétise les recommendations officielles :
Ces recommandations, si elles sont suivies, auront quelques conséquences pratiques (section 9). Par exemple, elles ne permettent pas de garder trace de quelles adresses sont utilisées par quelle machine. (Alors qu'avec une demande d'allocation explicite, par exemple par le biais d'une nouvelle interface virtuelle, comme c'est le cas actuellement chez Gandi, ce suivi est possible.) C'est ennuyeux si on veut remonter d'une adresse IP qui pose un problème (par exemple parce qu'il a téléchargé Les tortues Ninja) à son propriétaire. Une solution de remplacement est de superviser le réseau et de relever les réponses NDP, permettant ainsi de se constituer une base de la relation entre les adresses IP et les adresses MAC. Le logiciel NDPMon permet de faire cela. (On peut aussi interroger les commutateurs en SNMP, pour avoir un résultat analogue.) Les auteurs du RFC notent que tous leurs employeurs ont déjà un tel système en place, et ils citent plusieurs gros campus universitaires qui font de même, ce qui montre le caractère réaliste de la proposition.
Puisqu'on parle de sécurité, il faut noter que de ne pas permettre officiellement aux machines de s'attribuer des adresses IP supplémentaires ne signifiera pas qu'elles ne le feront pas. Si on n'a pas de sécurité dans la couche 2 (cf. RFC 7039), les machines peuvent toujours se configurer ce qu'elles veulent. En outre, si le mode d'allocation est DHCP, les efforts actuels pour améliorer la vie privée des utilisateurs de DHCP (RFC 7844) vont de toute façon diminuer l'intérêt de DHCP pour la sécurité.
Autre problème pratique pour les administrateurs réseau, les limites du matériel. Si un commutateur connecte mille machines, sa table de correspondance adresses IP <-> adresses MAC aura mille entrées. Si chaque machine s'alloue dix adresses, cette table devra stocker dix mille entrées. Le commutateur a-t-il cette capacité ? S'il ne l'a pas, on risque des pertes de connectivité. Certes, le matériel va évoluer. Mais il existe une autre solution, suggérée par notre RFC : utiliser un préfixe IP par machine. Ainsi, le commutateur n'aura à gérer qu'une seule entrée par machine, quel que soit son nombre d'adresses. Évidemment, cela consommera davantage d'adresses IPv6, et cela compliquera un peu la gestion des adresses. Cette proposition est donc légèrement plus sujette à controverse que la principale (permettre plusieurs adresses par machine) qui, elle, est largement reconnue comme justifiée.
Date de publication du RFC : Juillet 2016
Auteur(s) du RFC : Y. Sheffer (Intuit), A. Farrel
(Juniper)
Première rédaction de cet article le 23 juillet 2016
L'IETF se vante souvent de ne pas croire au blabla des marketeux, mais uniquement au code qui tourne. Comme le dit fièrement sa devise, « We believe in rough consensus and running code ». Mais, en pratique, les normes produites et publiées en RFC ne contiennent pas toujours la mention d'une mise en œuvre effective de cette norme. Parfois, c'est parce qu'il n'y en a pas (contrairement à une légende tenace, ce n'est nullement une obligation pour la publication d'un RFC). Parfois, c'est parce qu'elle n'est pas mentionnée. Avant la publication d'un RFC, lorsque le document est encore un simple Internet-Draft, la mention de l'existence de programmes mettant en œuvre le protocole ou le format décrit est facultative. Ce RFC propose de formaliser et d'encourager cette mention. Son prédecesseur, le RFC 6982 avait lancé l'idée, comme une expérimentation. Elle a été un grand succès et ce nouveau RFC passe donc au stade supérieur : publier l'état des implémentations d'un draft est désormais une Bonne Pratique (BCP, « Best Common Practice »).
Cela ne concerne que les Internet-Drafts, pas les RFC. En effet, les RFC sont stables (jamais modifiés) alors que les URL pointant vers un programme ne le sont pas : un programme peut être abandonné, plus maintenu, on peut se retrouver avec des 404, etc. Donc, un RFC n'est pas le bon endroit pour stocker un catalogue de mises en œuvre d'un protocole. Ce RFC 7942 ne vise que les Internet-Drafts, afin d'aider à l'évaluation d'une proposition. La section décrivant les mises en œuvre est donc typiquement supprimée lors de la publication du RFC. Comparez par exemple le draft-ietf-dnsop-qname-minimisation (dont la section 8 décrit les mises en œuvre existantes) avec le RFC 7816 (qui n'a plus cette section).
Le concept de running code est décrit dans le Tao (cf. RFC 4677 et RFC 6722). Il synthétise l'approche pragmatique de l'IETF : une norme qui n'est pas mise en œuvre ne sert à rien. Malgré cela, bien des RFC n'ont jamais connu la moindre mise en œuvre. En effet, ce principe général du running code n'a jamais été traduit dans une exigence formalisée et globale pour les auteurs de RFC. Il existe par contre des règles locales. Ainsi, la Routing Area de l'IETF (les groupes de travail qui normalisent les protocoles de routage) a longtemps demandé (RFC 1264) au moins une mise en œuvre avant la publication d'un RFC sur le chemin des normes. Le RFC 4794 a supprimé cette règle, qui reste appliquée par certains groupes de la Routing Area comme IDR. À noter qu'avant le RFC 6982, il y avait déjà des compte-rendus de mise en œuvre (implementation reports) qui étaient des documents séparés, racontant des expériences concrètes de développement.
Notre RFC 7942 n'impose pas une règle (la section Implementation Status reste facultative), mais il encourage fortement à formaliser une section dans les Internet-Drafts, qui permettra de documenter les mises en œuvre connues. L'idée est que les Internet-Drafts ayant cette section seront examinés avec plus de bienveillance, sans toutefois qu'elle soit obligatoire.
La section 4 du RFC fait la liste de tous les avantages qu'il y a à indiquer ces mises en œuvre dans l'Internet-Draft : meilleure information pour la prise de décision (aussi bien sur la publication de l'Internet-Draft que sur le statut du futur RFC), encouragement aux tests d'interopérabilité, possibilité (lorsque le code est publié) de mieux comprendre le protocole (beaucoup de programmeurs préfèrent lire le source plutôt que le RFC mais attention, la référence doit rester le RFC, le code n'est pas une spécification), et enfin assurance que telle fonction du RFC peut effectivement être mise en œuvre. C'est en effet souvent le cas (par exemple lors de la discussion qui a mené au RFC 5155) que certaines personnes affirment que la technologie envisagée est tout simplement trop complexe pour être programmée. L'existence d'un programme qu'on peut tester permet de d'assurer que, si, la technologie est réaliste (bien d'autres SDO produisent sans hésiter des technologies impossible à programmer dans des conditions raisonnables).
Cette section, « Implementation status » est décrite en section 2 de ce RFC. Elle est située vers la fin (comme l'actuelle - et obligatoire, elle - « Security considerations ») et peut comporter les points suivants :
Cette section peut aussi indiquer l'expérience tirée de cette mise en œuvre, ainsi que des informations sur l'interopérabilité, au cas où plusieurs mises en œuvre existent. Les présidents des groupes de travail sont explicitement chargés de vérifier que cette section ne dégénère pas en simple marketing pour le produit d'un vendeur. Notre RFC propose aussi un texte standard d'avertissement (« boilerplate ») à inclure au début de cette section « Implementation status ».
D'autres endroits que l'Internet-Draft lui-même auraient pu être utilisés pour informer sur les mises en œuvre existantes. Le RFC suggère (section 3) de passer au wiki de l'IETF lorsque la liste des programmes devient trop longue, lorsqu'il semble préférable que cette liste soit maintenue par les implémenteurs plutôt que par les auteurs de l'Internet-Draft, lorsque le groupe de travail maintient activement un wiki, ou enfin lorsque la liste en question semble utile, même après la publication en RFC (pour indiquer le niveau d'adoption par les programmeurs). Dans tous ces cas, il est bon d'indiquer l'URL du wiki en question dans l'Internet-Draft.
De très nombreux
Internet-Drafts incluent
désormais une telle section Implementation
Status, « bien trop pour qu'on puisse les compter », note
l'IESG dans son approbation de ce
document. Quelques exemples d'Internet-Drafts qui
incluent actuellement cette section : draft-ietf-dnsop-nxdomain-cut
ou
draft-ietf-dane-openpgpkey
.
Le principal changement par rapport au RFC précédent, le RFC 6982 est un changement de statut. On passe de « expérimental » à « Bonne Pratique », reflétant le succès de cette expérience. Autrement, il n'y a que des changements de rédaction, rien de crucial.
Date de publication du RFC : Juin 2016
Auteur(s) du RFC : C. Bao, X. Li (CERNET
Center/Tsinghua University), F. Baker (Cisco
Systems), T. Anderson (Redpill
Linpro), F. Gont (Huawei
Technologies)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 22 juillet 2016
Parmi les nombreuses techniques de coexistence d'IPv4 et IPv6, l'ex-groupe de travail Behave développait un mécanisme de traduction permettant à une machine IPv6 de communiquer avec une machine v4 et réciproquement. Une des pièces de ce mécanisme (désormé transféré au groupe de travail v6ops) est l'algorithme de traduction, présenté dans ce RFC 7915. (Il remplace l'ancien RFC 6145, avec assez peu de changements.)
Ce nouveau mécanisme de traduction entre IPv4 et IPv6 s'inscrit dans le cadre décrit dans le RFC 6144. Il vise à remplacer « NAT-PT » (RFC 2765 et RFC 2766), officiellement retiré, après n'avoir eu aucun succès.
Plus spécifiquement, notre RFC 7915 est la version sans état du traducteur, c'est-à-dire que le traducteur peut traiter chaque paquet indépendamment des autres. Le traducteur n'a pas de table des flots en cours. S'il redémarre et perd toute mémoire, pas de problème, il peut immédiatement reprendre son travail. Cette technique permet notamment le passage à l'échelle : un traducteur d'adresses peut gérer un très grand nombre de clients sans épuiser sa mémoire. Et on peut mettre plusieurs traducteurs en parallèle, sans coordination entre eux : les paquets d'un même flot peuvent passer par des traducteurs différents. Mais cette technique a aussi quelques inconvénients comme le fait que les fragments ICMP ne seront pas traduits. Il existe donc également une version avec état du nouveau mécanisme, normalisée dans le RFC 6146. La section 1.3 discute plus en détail ces deux possibilités, avec ou sans état.
Donc, le NAT64 (son nom non officiel) vise à traduire des adresses IP entre deux réseaux, l'un v4 et l'autre v6. Comme notre RFC 7915 ne traite que le cas sans état, les adresses doivent être converties de manière purement algorithmique, sans référence à leur histoire (cf. RFC 6052, et la section 6 de ce RFC, pour ces algorithmes).
Dit comme ça, cela a l'air simple mais la traduction entre deux protocoles différents porte pas mal de pièges. Ainsi, les en-têtes de paquet n'ont pas la même taille en v4 (20 octets ou plus) et en v6 (40 octets, fixe), ce qui fait que des problèmes de MTU peuvent se poser (section 1.4). Le traducteur doit se comporter comme un routeur, donc fragmenter les paquets trop gros (en IPv4) ou retourner un message ICMP « Packet too big ».
La section 4 du RFC décrit en détail les opérations que doit faire le traducteur depuis IPv4 vers IPv6 (rappelez-vous que la traduction des adresses v4 en v6 est essentiellement dans le RFC 6052, section 2). Il y a des détails que ne connaissent pas les routeurs NAT44, qui se contentent de changer adresses et ports. En effet, ici, il faut traduire tout l'en-tête. Je ne vais pas résumer complètement cette section, juste pointer quelques pièges possibles. Ainsi, les en-têtes n'étant pas les mêmes en v4 et en v6, notre RFC doit spécifier quoi en faire. Certains cas sont évidents (comme le champ Longueur), d'autres moins. Ainsi, le champ TOS de IPv4 doit être copié verbatim dans le champ Traffic Class de IPv6. Mais le traducteur doit aussi offrir une option pour ignorer le TOS et mettre systématiquement zéro comme Traffic Class. Le champ TTL de IPv4 doit être copié dans Hop limit mais après avoir été décrémenté (rappelez-vous que le traducteur est un routeur).
La vraie difficulté n'est pas tellement dans la traduction d'IP que dans celle d'ICMP. En effet, le paquet ICMP contient le début du paquet IP qui a motivé son envoi, et ce début de paquet doit être traduit, également, sans quoi le destinataire du paquet ICMP n'y comprendra rien (par exemple, sans traduction ICMP, il recevrait en IPv6 un paquet ICMP dont le contenu est un paquet IPv4...). Notre RFC détaille donc les traductions à faire pour tous les modèles de paquets ICMP.
Le traducteur doit aussi veiller au champ Type d'ICMP, dont les valeurs sont différentes entre IPv4 et IPv6 (par exemple, Echo Reply est 0 en v4 et 129 en v6). Certains types n'ont pas d'équivalent (comme les types Timestamp ou Address Mask d'ICMPv4, absents d'ICMPv6) et le paquet ICMP doit donc être abandonné.
Enfin, le traducteur doit aussi prendre en charge les en-têtes de la couche 4 car la traduction des adresses peut ne pas être neutre pour la somme de contrôle (section 4.5) et il peut donc être nécessaire de recalculer cette dernière.
Et en sens inverse ? La section 5 décrit la traduction d'IPv6 vers IPv4. On retrouve TOS et Traffic Class, les problèmes de MTU et de fragmentation, et la traduction des messages ICMP.
La section 6 de notre RFC, une nouveauté depuis le RFC 6145, revient sur les algorithmes de correspondance entre les adresses IPv4 et IPv6. Les algorithmes obligatoires sont décrits dans le RFC 6052, mais un traducteur peut en ajouter d'autres.
Les problèmes de MTU et de fragmentation sont des cauchemars habituels sur l'Internet, notamment en raison d'équipements intermédiaires (typiquement des pare-feux) programmés avec les pieds par des anonymes, ou bien configurés n'importe comment, et qui bloquent les paquets ICMP, voire les modifient, en ignorant complètement le RFC 4890. Les traducteurs v4<->v6 auront donc ce problème, comme tant d'autres techniques utiles. La section 7 doit donc se pencher sur le traitement des paquets ICMP Packet too big qui signalent normalement que la MTU est plus réduite que ne le croit l'émetteur et qu'il faut fragmenter. Comme ces paquets sont parfois interceptés, voire modifiés, par des machines gérées par des incompétents, le traducteur doit donc parfois faire des efforts spécifiques. Si les paquets sont interceptés, la détection de la MTU du chemin n'est plus possible (RFC 2923) et il ne restera plus que la solution du RFC 4821 (faire faire le travail par les couches supérieures).
Rien n'étant parfait en ce bas monde, les traducteurs NAT64 vont aussi introduire de nouvelles questions de sécurité. La section 8 tente de prévoir lesquelles mais reste optimiste en considérant que la plupart des problèmes existent déjà dans IPv4 ou dans IPv6. Ainsi, comme avec le NAT traditionnel, l'authentification des paquets par IPsec (RFC 4302) ne marchera pas.
Pour les gens qui aiment bien les exposés concrets, avec des 0 et
des 1, l'annexe A explique en grand détail le
processus de traduction avec un réseau simple d'exemple, connectant le
réseau traditionnel 198.51.100.0/24
et le réseau
nouveau 2001:db8::/32
, via un
traducteur. Deux machines, H4 et H6, Alice et Bob du NAT64, vont tenter de communiquer. Le traducteur
utilise le préfixe 2001:db8:100::/40
pour
représenter les adresses IPv4 et 192.0.2.0/24
pour représenter les adresses IPv6. Ainsi,
H6, qui a l'adresse 2001:db8:1c0:2:21::
est
représenté en v4 par 192.0.2.33
. H4 a l'adresse
198.51.100.2
. Une fois le routage
correctement configuré pour passer par le traducteur, suivez le RFC
pour voir le trajet des paquets et les opérations qu'ils subissent,
dans le cas où c'est H6 qui initie la connexion, et dans le cas inverse.
Au moins deux mises en œuvre existent déjà, faite par Ecdysis/Viagénie (avec état) et Tayga (sans état, mais nettement plus simple, d'après ses utilisateurs). Pour compenser l'absence de traduction avec état chez Tayga, on peut, sur Linux, le coupler avec SNAT/MASQUERADE (merci à Guillaume Leclanché pour sa suggestion).
Quels sont les changements entre ce mécanisme et celui du RFC 6145 ? Rien de dramatique. Ils sont résumés en section 2. Certains traitent les bogues détectées dans l'ancien RFC. D'autres changements tiennent compte du conseil actuel qui est de ne plus compter sur les « fragments atomiques » du RFC 6946 (ils ont même été franchement abandonnés avec le RFC 8021.)
Pour réfléchir à la grande question « avec état ou sans état », un article « pro-état » : « Stateless NAT64 is useless ».
Date de publication du RFC : Juin 2016
Auteur(s) du RFC : A. Atlas (Juniper), T. Nadeau
(Brocade), D. Ward (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF i2rs
Première rédaction de cet article le 21 juillet 2016
Autrefois, la configuration des routeurs était relativement statique. On indiquait la politique de routage (le coût de tel ou tel lien, par exemple), les préfixes IP, les pairs BGP, parfois des routes statiques, et le routeur parlait avec ses copains routeurs, construisant ses tables qu'il allait ensuite utiliser pour la transmission des paquets. La configuration n'était pas modifiée tous les jours et quand c'était nécessaire, on se connectait à tous les routeurs qu'il fallait changer et on modifiait la config. Dans les organisations plus modernes, on édite la config, on la commite dans un VCS et on la pushe vers les routeurs avec Ansible ou un truc équivalent. Aujourd'hui, même cela ne suffit pas, on voudrait être plus agile. On voudrait modifier la configuration des routeurs à peu près en temps réel, pour répondre à des considérations de business (créer un nouveau service pour un client, profiter de variations de prix chez les transitaires...) ou à des problèmes de sécurité (déployer des filtres subtils). Cette exigence nécessite une interface vers le routeur, utilisable par des programmes. C'est le projet I2RS, Interface To the Routing System. Ce premier RFC du groupe de travail décrit précisement le problème qu'on essaie de résoudre. (Notez que le buzzword SDN n'apparait pas une seule fois dans ce RFC...)
C'est que les réseaux modernes sont grands et complexes : il n'est plus possible de faire les choses à la main en se connectant sur chaque routeur isolément. Il faut donc automatiser, et il faut donc qu'un programme puisse se connecter aux routeurs et changer leurs configurations. Cela se fait bien sûr depuis longtemps (cf. Rancid et l'exposé de Joe Abley à NANOG et l'annexe A de notre RFC qui liste les solutions existantes), mais, en l'absence d'interface normalisée, c'était assez pénible à programmer et maintenir. Il s'agit donc de standardiser ce qui existe déjà, ce qui ne devrait pas être une tâche insurmontable.
La terminologie utilisée par I2RS est décrite dans un autre RFC, le RFC 7921. Pour le résumer (section 2 du RFC) : le routeur contient un agent I2RS, qui sait parler aux différents composants du routeur (sa base de données indiquant les différents liens connectés, son système de gestion de la configuration, sa base de routes - RIB, etc). Le logiciel qui pilote les changements est le client I2RS. Il y aura sans doute un seul client pour beaucoup d'agents, installé dans le système de gestion du réseau. Entre le client et l'agent, le protocole I2RS, qui sera normalisé dans les futurs RFC du groupe de travail I2RS. A priori, le client sera juste un intermédiaire pour des applications qui piloteront le routage (le but du découplage client/application étant d'éviter que chaque application doive parler I2RS : elles pourront interagir avec le client au-dessus d'un protocole plus classique comme REST).
Pour que le client puisse parler intelligemment à l'agent, il devra avoir en tête un modèle de données décrivant le routeur, ce qu'il sait faire, ce qu'on peut lui demander.
La section 3 de notre RFC présente la nécessité de ce modèle de données. Un tel modèle avait déjà été développé pour le projet ForCES (RFC 3746), en se focalisant sur la transmission, alors que I2RS est surtout intéressé par le routage (le plan de contrôle, accès à la RIB, etc).
Comme le note la section 4, un logiciel qui voudrait vraiment donner des instructions au routeur devrait apprendre la topologie du réseau, quels sont les liens physiques ou virtuels auxquels le routeur est connecté, leur état, etc. C'est évidemment le routeur qui connait le mieux cette information et il est donc nécessaire de lui demander.
L'application aura souvent besoin de connaitre en outre le trafic réellement échangé. IPFIX (RFC 5470) est certainement utilisable pour cela, si l'application peut le configurer dynamiquement.
Enfin, la section 5 rassemble les « points divers ». Elle rappelle qu'I2RS n'impose pas forcément le développement d'un nouveau protocole ; si un protocole, ou un ensemble de protocoles existant(s) suffit, c'est parfait (l'annexe A du RFC propose des pistes en ce sens). Mais la solution doit penser à :
Voici pour le cahier des charges. L'annexe A propose quelques pistes qui vont en ce sens. À l'heure actuelle, l'interface la plus générale des routeurs est la CLI. Elle permet d'apprendre l'état du routeur et de changer sa configuration. Voici un exemple sur un Juniper :
bortzmeyer@MX-1> show interfaces ... Physical interface: ge-1/1/9, Enabled, Physical link is Up Interface index: 177, SNMP ifIndex: 531 Description: To infinity and beyond Link-level type: Ethernet, MTU: 1514, MRU: 1522, Speed: 1000mbps, BPDU Error: None, MAC-REWRITE Error: None, Loopback: Disabled, Source filtering: Disabled, Flow control: Enabled, Auto-negotiation: Enabled, Remote fault: Online Pad to minimum frame size: Disabled Device flags : Present Running Interface flags: SNMP-Traps Internal: 0x0 Link flags : None CoS queues : 8 supported, 8 maximum usable queues Current address: 5c:5e:ab:0e:4b:f1, Hardware address: 5c:5e:ab:0e:4b:f1 Last flapped : 2016-02-12 11:31:56 CET (22w5d 23:10 ago) Input rate : 672 bps (1 pps) Output rate : 672 bps (1 pps) Active alarms : None Active defects : None Interface transmit statistics: Disabled Physical interface: xe-0/0/2, Enabled, Physical link is Up Interface index: 156, SNMP ifIndex: 510 Link-level type: Ethernet, MTU: 1514, MRU: 1522, LAN-PHY mode, Speed: 10Gbps, BPDU Error: None, MAC-REWRITE Error: None, Loopback: None, Source filtering: Disabled, Flow control: Enabled Pad to minimum frame size: Disabled Device flags : Present Running Interface flags: SNMP-Traps Internal: 0x0 Link flags : None CoS queues : 8 supported, 8 maximum usable queues Current address: 5c:5e:ab:0e:4b:72, Hardware address: 5c:5e:ab:0e:4b:72 Last flapped : 2016-07-07 14:28:31 CEST (1w6d 21:11 ago) Input rate : 0 bps (0 pps) Output rate : 0 bps (0 pps) Active alarms : None Active defects : None PCS statistics Seconds Bit errors 0 Errored blocks 1 Interface transmit statistics: Disabled ...
Ce shell n'est pas normalisé : chaque marque de routeur a le sien. Comme l'information retournée n'est pas structurée, si on veut la traiter depuis un programme, il faut faire du scraping, ce qui est pénible et peu gratifiant (d'autant plus que le « format » peut changer sans prévenir lors de la sortie d'une nouvelle version du système d'exploitation du routeur).
Les routeurs ont aussi des interfaces reposant sur un protocole et des données structurées. La plus connue est SNMP. SNMP est très utilisé pour récupérer de l'information (état des interfaces, quantité de trafic qui passe) mais, bien qu'il permette en théorie la configuration des équipements réseau, en pratique, cette possibilité a été très peu utilisée. Les raisons de cette non-utilisation sont nombreuses (complexité, absence de sémantiques avancées comme le regroupement de plusieurs changements dans une « transaction » unique, sur laquelle on peut revenir globalement, etc). SNMP ne semble donc pas envisageable pour I2RS.
Enfin, cette annexe A cite Netconf comme étant sans doute la solution disponible la plus proche, même si elle n'est pas parfaite et aurait besoin d'être complétée (voir les travaux en cours dans le RFC 7921).
Date de publication du RFC : Juillet 2016
Auteur(s) du RFC : H. Tschofenig (ARM), T. Fossati
(Nokia)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dice
Première rédaction de cet article le 20 juillet 2016
Dans le futur, nous répètent les consultants, il y aura partout dans nos maisons, bureaux et usines, des petits objets électroniques connectés à l'Internet. C'est le fameux Internet des Objets. Ces choses serviront à mesurer le monde et à le modifier et poseront donc des problèmes de sécurité. Par exemple, sans précautions particulières, un capteur dans une usine qui envoie en Wi-Fi les informations qu'il récolte permettrait à un écoutant indiscret, même situé en dehors de l'usine, de surveiller l'activité de celle-ci. Il va donc de soi qu'il faut utiliser de la cryptographie dans ces objets. Mais celle-ci est parfois coûteuse en ressources machine, et ce nouveau RFC propose donc des profils du protocole TLS, limitant les options possibles de façon à économiser les ressources des objets.
Ces objets sont en effet contraints au sens du RFC 7228. Un TLS complet serait trop pour eux. Bien sûr, on pourrait concevoir des protocoles cryptographiques spécialement conçus à leur intention mais il faudrait développer, valider et déboguer ces protocoles et l'expérience de la cryptographie sur l'Internet montre que c'est beaucoup plus difficile que ça n'en a l'air. D'où le choix d'utiliser TLS (RFC 5246), protocole connu et éprouvé.
Notons au passage que, contrairement à ce que dit le RFC, le principal danger que pose l'Internet des Objets ne vient pas forcément d'un tiers inconnu : presque toute la domotique actuelle fonctionne avec le cloud, toutes les données récoltées étant envoyées sur les serveurs du vendeur, qui peut en faire ce qu'il veut. Chiffrer le trafic entre l'objet et ces serveurs ne comble pas cette énorme faille de sécurité.
Les profils de TLS (et de DTLS, son équivalent pour UDP, cf. RFC 6347) spécifiés dans ce RFC peuvent s'appliquer aux communications utilisant CoAP (RFC 7252) comme à celles utilisant d'autres protocoles applicatifs. Ce sont des profils, des restrictions de TLS, et ils n'introduisent donc pas un nouveau protocole, ni même de nouvelles extensions à ces protocoles.
Par exemple (section 4.4), ce RFC impose que, si on authentifie avec un certificat, les certificats X.509 utilisent ECDSA uniquement. (Gérer tous les algorithmes possibles dans un objet contraint serait trop coûteux, par exemple en occupation de la flash.) Au revoir, RSA, donc.
Toujours sur les certificats, le profil abandonne OCSP (RFC 6960) et les CRL (qui ne marchent guère, en pratique) : la révocation des certificats devra se faire uniquement par le biais d'une mise à jour du logiciel de l'objet.
Toujours concernant la cryptographie, ce RFC impose (section
13) de n'utiliser que des suites de chiffrement intègres
(AEAD) comme
TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
(AES
avec CCM,
cf. RFC 7251).
Comme l'utilisation de TLS dans ces objets contraints est récente, il n'y a pas trop à se préoccuper de la base installée. On peut donc décider de ne jamais gérer des trucs trop anciens. C'est ainsi que la version minimale de TLS acceptée dans les profils de ce RFC est la 1.2 (section 18).
Il y a quelques points où ce RFC rend obligatoire des fonctions qui étaient optionnelles dans TLS, parce qu'elles sont cruciales pour des objets contraints. C'est le cas de la reprise de session TLS précédente, qui permet d'éviter de refaire des opérations cryptographiques coûteuses à chaque démarrage. Par contre, certaines fonctions sont déconseillées, comme la compression, coûteuse et sans doute inutile dans l'Internet des Objets où les protocoles sont déjà optimisés pour réduire la taille des données échangées. (En outre, il existe de bonnes raisons de sécurité de couper la compression TLS, RFC 7525, section 3.3.) Idem pour la renégotiation du RFC 5746, qui est exclue.
Un problème courant en cryptographie est celui de la génération de nombres aléatoires (TLS en utilise plusieurs). Il est encore plus aigu dans l'Internet des Objets car ces objets n'ont souvent pas beaucoup de sources d'entropie (section 12 du RFC). Pas de disque dur mobile, pas de clavier, pas de souris dont les mouvements sont partiellement aléatoires. Il y a donc un risque élevé que tous les objets identiques génèrent les mêmes nombres « aléatoires ». Bref, il faut que les développeurs fassent très attention aux conseils du RFC 4086.
Autre manque des objets contraints, celui d'une horloge fiable. Pour des opérations comme la validation de la non-expiration d'un certificat, cela peut être très gênant.
Les objets contraints sont... contraints de bien d'autre façon, comme en puissance du processeur. Cela peut rendre certaines opérations cryptographiques irréalistes en logiciel. La section 19 du RFC donne des conseils sur la mise en œuvre matérielle de ces opérations :
Toujours en cryptographie, la section 20 donne des recommendations sur la longueur des clés. Un point important, et spécifique aux objets, est que les engins déployés restent souvent sur le terrain très longtemps, par exemple dix ans. On ne remplace pas les capteurs, ou l'ordinateur embarqué dans une machine, comme on change d'iPhone ! La longueur des clés doit donc être prévue pour les attaques du futur, pas pour celles d'aujourd'hui.
Les objets dont on parle dans ce RFC sont souvent déployés dans des environnements où les contraintes de vie privée sont fortes. Cela peut être une usine qui ne veut pas que ses processus soient espionnés, ou bien une maison dont les habitants ne veulent pas être surveillés (section 22 du RFC). TLS ne protège pas contre tout et certaines fuites d'information persistent même quand il est utilisé. Elles peuvent venir du protocole TLS lui-même (la reprise de session utilise des informations qui permettent de suivre une machine à la trace) ou bien provenir de métadonnées diverses. Par exemple, s'il existe un capteur de présence qui envoie un message lorsque quelqu'un rentre dans l'appartement, chiffrer ce message ne fait pas gagner grand'chose : une fois qu'un observateur a identifié le capteur de présence, le seul envoi du message suffit à l'informer d'une arrivée. Une vraie protection de la vie privée peut donc nécessiter des méthodes additionnelles comme l'envoi de trafic bidon.
Le RFC se termine en rappelant qu'il est crucial de fournir un mécanisme de mise à jour simple des engins. Les objets de l'Internet des Objets sont souvent de type « je pose et puis j'oublie », sans aucun moyen de mettre à jour leur logiciel. Or, la sécurité peut nécessiter une telle mise à jour, soit pour corriger une bogue dans la bibliothèque TLS, soit pour révoquer des clés et en mettre d'autres. Un exemple d'un mécanisme de mise à jour adapté est LWM2M.
Si vous voulez rire un peu, l'annexe A du RFC précise comment faire tourner DTLS sur... SMS.
Date de publication du RFC : Juin 2016
Auteur(s) du RFC : D. Bryan (Cogent Force), P. Matthews (Alcatel-Lucent), E. Shim (Samsung Electronics), D. Willis (Softarmor Systems), S. Dawkins (Huawei)
Pour information
Réalisé dans le cadre du groupe de travail IETF p2psip
Première rédaction de cet article le 19 juillet 2016
Le mécanisme de signalisation d'appels SIP, largement utilisé pour la téléphonie sur IP, dépend de serveurs stables et connectés en permanence (proxies, registrars, etc), pour la mise en relation des participants. Une solution entièrement pair-à-pair est en cours de développement, P2PSIP (peer to peer SIP). Ce nouveau RFC décrit ses concepts et le vocabulaire qu'elle emploie.
C'est en effet le cœur du problème de toute solution
pair-à-pair sur l'Internet : le
rendez-vous. Comment deux machines pas
toujours allumées, pas toujours connectées, coincées derrière des
équipements qui leur interdisent les connexions entrantes,
peuvent-elles rentrer en relation ? Si Alice appelle Bob via des
téléphones SIP, comment faire sonner la
machine de Bob, bloquée derrière son routeur
NAT ? La solution classique de SIP (RFC 3261) est de d'abord faire correspondre une adresse SIP
(appelée AoR pour Address of Record) avec un ou
plusieurs URI, qui indiquent les machines à
contacter. Ces machines sont des intermédiaires, reliés à
l'Internet en permanence, et qui peuvent donc tout le temps
recevoir le message INVITE
d'établissement de
connexion (cf. RFC 3263). L'idée de base du
SIP pair-à-pair, P2PSIP, est de remplacer ces intermédiaires, ces
relais, par un réseau P2P.
Le mécanisme exact, nommé RELOAD, est spécifié dans le RFC 6940 (notez que le protocole RELOAD peut servir à d'autres applications que SIP). Les machines des utilisateurs s'enregistrent dans une DHT, où les appelants vont trouver le moyen de les contacter. (Par défaut, la DHT utilisée est Chord.)
La section 2 de notre RFC donne une présentation générale de la solution complète. Un réseau pair-à-pair overlay sert à établir la correspondance entre adresses (AoR) et les URI indiquant les moyens de connexion. Ce même réseau sert également à acheminer les messages SIP, si les machines d'Alice et Bob n'arrivent pas à se parler directement (un problème fréquent dans l'Internet ossifié et fermé d'aujourd'hui). Ce réseau overlay de pairs stocke les correspondances, et les duplique sur plusieurs nœuds (comme dans tout réseau pair-à-pair, chaque machine peut faire défection à tout moment). Ce sont les services de base de l'overlay, ceux qui sont absolument indispensables au bon fonctionnement de P2PSIP. Mais certains pairs peuvent accepter de participer à d'autres services, comme un service de répondeur audio, pour les cas où Bob a éteint sa machine (cf. RFC 7374). De même, certains pairs peuvent assurer des services de proxy ou de registrar SIP traditionnel, pour permettre aux clients SIP anciens de se connecter via P2PSIP.
On n'est pas obligé d'être un pair dans ce réseau P2PSIP. Un softphone SIP peut être un simple client, utilisant les services de l'overlay sans y contribuer.
Notez qu'il existe d'autres moyens de faire du SIP sans l'appareil traditionnel des serveurs relais centraux. Ces moyens sont en général limités au réseau local (par exemple les RFC 6762 et RFC 6763).
Le cœur du RFC est sa section 4, qui regroupe les définitions. Je ne vais pas les reprendre ici. La plupart sont classiques dans le monde du pair-à-pair (overlay, peer...). À noter les termes de Node ID (l'identificateur unique d'un pair - RFC 6940, section 4.1) et de peer admission (le mécanisme par lequel on admet un nouveau pair : RELOAD permet un réseau fermé, où il faut montrer patte blanche à un serveur d'inscription avant de rentrer - RFC 6940, section 11.3.)
Première rédaction de cet article le 17 juillet 2016
On répète souvent aux utilisateurs que l'Internet est un lieu dangereux (ce n'est pas faux) et qu'il faut utiliser des logiciels qui les protègent magiquement : anti-virus, logiciels de contrôle parental, etc. Mais ce sont des logiciels, ils ont donc des bogues et ils ne sont pas mieux écrits que la moyenne des logiciels. Leurs bogues peuvent sérieusement affecter la sécurité de la machine. Morale : ajouter du logiciel de sécurité n'améliore pas forcément la sécurité.
Pour ceux qui ne seraient pas convaincus de ces évidences, je recommande très fortement la lecture de l'excellent article « Killed by Proxy: Analyzing Client-end TLS Interception Software ». Les auteurs, Mohammad Mannan et Xavier de Carné-Carnavalet, ont testé en labo un certain nombre de logiciels qui font de l'« interception TLS » et découvert que la plupart ouvraient des boulevards à des attaquants. Qu'est-ce qu'un logiciel d'interception TLS ? C'est un logiciel qui est un relais TLS, entre le logiciel de l'utilisateur (typiquement un navigateur Web) et le vrai serveur. L'intercepteur se fait passer pour le vrai serveur auprès du navigateur Web et pour le client auprès du vrai serveur. Pour ne pas lever d'alerte de sécurité dans le navigateur, il présente un certificat valable. Ce genre de logiciel est donc un détournement délibéré du modèle de sécurité de TLS : il casse la sécurité exprès. Il n'est donc pas étonnant qu'ils ouvrent des failles graves.
Pour comprendre ces failles, un petit mot sur le fonctionnement des ces logiciels : ils tournent sur la machine de l'utilisateur (contrairement aux relais TLS que les grandes entreprises et les administrations installent souvent près de l'accès Internet, pour surveiller les malwares et espionner les employés), ils détournent le trafic TLS (typiquement HTTPS) et ils présentent un certificat valable pour le nom de domaine demandé. Ce certificat a pu être généré en usine ou bien à l'installation du logiciel. Ce certificat est parfois protégé par une phrase de passe. Pour que le certificat soit accepté, ils mettent leur propre AC dans le magasin du système, avec une période de validité allant jusqu'à 20 ans. (En général, ils n'expliquent pas clairement à l'utilisateur ce qu'ils font, ce qui augmente encore le danger.) Le logiciel d'interception reçoit les connexions locales, venant du navigateur Web, et se connecte lui-même aux vrais serveurs distants. Ces logiciels sont presque toujours privateurs, aucun accès au code source (bien que tous utilisent, sans honte, un logiciel libre, OpenSSL), aucun moyen de les vérifier.
La totalité des logiciels testés par les auteurs a au moins une faille TLS. Inutile donc de chercher le « bon antivirus » ou le « bon logiciel de contrôle parental ». Voici une liste non limitative de ces failles :
Pourquoi les sociétés qui écrivent ces logiciels feraient des efforts pour la sécurité ? Leurs utilisateurs ne sont pas des connaisseurs, des tas de gens auto-proclamés experts en sécurité servent de vendeurs pour ces logiciels en répétant aux utilisateurs « pensez à installer un anti-virus » et la non-disponibilité du code source rend difficile toute analyse de ces logiciels.
Date de publication du RFC : Juin 2016
Auteur(s) du RFC : A. Langley (Google), W. Chang
(Google), N. Mavrogiannopoulos (Red
Hat), J. Strombergson (Secworks
Sweden), S. Josefsson (SJD)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 8 juillet 2016
Ce court RFC ajoute les algorithmes de cryptographie ChaCha20 et Poly1305 à la liste de ceux utilisables dans le protocole TLS.
ChaCha20 (dérivé de l'ancien Salsa20) est un algorithme de chiffrement symétrique et Poly1305 un authentificateur. Tous les deux ont été conçus par Dan Bernstein et sont décrits dans le RFC 8439. (Ce nouveau RFC ne fait que de les adapter à leur usage dans le cas spécifique de TLS.) ChaCha a été utilisé dans BLAKE, la version de ce RFC, ChaCha20 doit son nom au fait qu'il exécute 20 tours (rounds). Quant à Poly1305, c'est un authentificateur de Wegman-Carter. Que fait un authentificateur ? Il prend une clé, un message et fabrique une étiquette. Un attaquant n'a qu'une probabilité infime de produire une étiquette valide.
Les deux algorithmes ont été conçus en pensant surtout à une mise en œuvre en logiciel (AES restant sans doute plus rapide quand on peut utiliser du matériel spécialisé. On trouve des mesures de performance dans cet article de Google ou cet article de Cloudflare.)
Les algorithmes potentiellement concurrents ont des faiblesses : risques de sécurité pour AES-CBC ou RC4 (cf. RFC 7465), problèmes de performance pour les autres algorithmes AEAD comme AES-GCM. Comme RC4, ChaCha20 est un algorithme à flot continu, mais il n'a pas ses failles de sécurité.
Pour le cas de TLS (section 2 du RFC), ChaCha20 et Poly1305
sont utilisés ensemble, pour former un algorithme
AEAD (RFC 5116). Son identifiant TLS
est AEAD_CHACHA20_POLY1305
et il peut
s'utiliser avec les différents algorithmes d'authentification
utilisés dans TLS. Par exemple, on peut avoir une session TLS dont
la cipher suite est
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
ce qui veut dire :
Ces identifiants ont été ajoutés dans le registre IANA pour TLS.
Quel est le niveau de sécurité du nouvel algorithme ? Son prédécesseur Salsa20 a bénéficié d'analyses de sécurité sérieuses (Salsa20 security et The eSTREAM Portfolio). ChaCha20 traite les failles connues de Salsa. Et il était utilisé dans un des finalistes du concours SHA-3, ce qui lui a valu d'autres examens de près.
Si, en plus de ChaCha20 et Poly1305, on utilise Curve25519 pour la cryptographie asymétrique, on aura une cryptographie tout-Bernstein, ce qui peut aussi amener à se poser des questions.
Et les mises en œuvre ? ChaCha20 est dans OpenSSL depuis la version 1.1.0 (pas encore officiellement publiée, et qui semble encore peu répandue) et dans GnuTLS depuis la 3.4.0. Il existe une liste apparemment à jour des mises en œuvre.
Date de publication du RFC : Juin 2016
Auteur(s) du RFC : K. Sriram, D. Montgomery (US NIST), D. McPherson, E. Osterweil (Verisign), B. Dickson
Pour information
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 8 juillet 2016
Il est bien connu que le protocole de routage BGP connait fréquemment des « fuites de route » (route leaks). Les forums où les opérateurs discutent sont plein de discussions et d'alertes sur la dernière fuite en cours, il existe un compte Twitter dédié pour les alertes automatiques de fuites, le rapport sur la résilience de l'Internet en France en parle longuement. Bref, le sujet est bien connu. Curieusement, il n'y a pas de définition simple et consensuelle de ce qu'est une fuite. Il en existe en fait plusieurs sortes, et ce nouveau RFC tente de faire le point et de définir rigoureusement les différents types de fuite.
La fuite est en effet un sérieux problème : des routeurs vont recevoir des routes incorrectes et, s'ils les acceptent, le routage normal peut être perturbé, menant à des pannes, ou à du tromboning (paquets IP routés par un chemin bien plus long que l'optimum).
La liste des incidents de routage médiatiquement connus est longue : le détournement de YouTube par Pakistan Telecom, la fuite venue de Malaisie, et bien d'autres décrites dans l'abondante bibliographie de notre RFC (cf. section 1 du RFC). L'IETF travaille depuis longtemps à des solutions techniques à ce problème (notamment via son groupe de travail SIDR) mais, pour résoudre un problème, il vaut mieux bien le comprendre. C'est le travail de ce nouveau RFC, qui tente une taxonomie des fuites.
Donc, d'abord, une (tentative de) définition (section 2 du RFC). Une fuite est la propagation de l'annonce d'une route au-delà de la portée prévue. Ce n'est donc pas la seule annonce qui est le problème, c'est sa propagation. Si le Pakistan veut annoncer les routes de YouTube dans le pays, à des fins de censure, ce n'est pas une fuite de route, mais un détournement délibéré (comme celui de Google Public DNS en Turquie). La fuite a commencé quand Pakistan Telecom a bêtement laissé se propager cette annonce au monde entier.
La définition s'appuie donc sur une politique de routage qui définit « ce qui est prévu ». La politique de routage est décidée par chaque acteur (l'Internet n'a pas de Chef, chacun est maître de sa politique) et mise en œuvre dans la configuration des routeurs, sous forme de règles disant ce qui est accepté et ce qui est refusé. Si les opérateurs ne commettaient jamais d'erreurs, on pourrait dire que ces règles suffiraient à décrire la politique de routage. Mais ils en commettent (par exemple, le transitaire de Pakistan Telecom aurait dû n'accepter de son client qu'un ensemble fini de routes, celles correspondant aux préfixes alloués à Pakistan Telecom et à ses clients). Une fuite de route est donc l'équivalent pour les opérateurs réseau de ce qu'est une bogue pour les programmeurs : « ce n'est pas ce que je voulais, mais c'est ce que j'ai dit ».
La définition de la politique de routage dépend des relations entre acteurs (on n'accepte pas la même chose d'un client, d'un transitaire, d'un pair...) Le RFC cite (section 2) plusieurs études expliquant ces relations compliquées.
Au fait, on a supposé que les « fuites de routes » étaient mauvaises et qu'il fallait les combattre. Mais pourquoi ? Parce qu'elles peuvent mener à des pannes (la route annoncée à tort ne fonctionne pas) ou à des chemins sous-optimaux (un long détour). Cela concerne les fuites accidentelles, de loin les plus nombreuses (il y a davantage de maladroits que de malveillants). Mais il y a aussi des fuites délibérées, provoquées pour faire une attaque par déni de service, ou bien pour forcer le trafic à passer en un point où il pourra être plus facilement surveillé.
C'est pour cela que les gens qui ne chiffrent pas leurs communications avec des arguments du genre « non, mais ça ne sort pas du pays, de toute façon », ont gravement tort. La vulnérabilité du routage fait que leur trafic peut soudainement partir bien plus loin.
Voyons maintenant la classification des fuites (section 3). Le RFC les classe en différents types, identifiés par un numéro. Le type 1 est « virage en épingle à cheveux avec un préfixe complet ». C'est ce qui se produit quand un AS de bordure apprend un préfixe d'un de ses transitaires et le ré-annonce à un autre transitaire (d'où l'épingle à cheveux). Le second transitaire, s'il ne filtre pas les préfixes que peut annoncer son client, risque fort d'accepter la route (préférence donnée aux routes des clients sur celles des fournisseurs) et le trafic sera donc envoyé à l'AS de bordure (qui pourra ou pas le gérer). Ce fut le cas de l'incident Dodo, ainsi que de la fuite en Malaisie citée plus haut.
Le type 2, lui, est « fuite latérale ». Un acteur reçoit une route d'un pair et la transmet à un autre pair. (Voir la conférence de Jared Mauch à NANOG, où il observe qu'il n'est pas facile de détecter automatiquement ces fuites, car les relations entre acteurs peuvent être compliquées.)
L'incident de type 3, lui, se produit lorsque un AS apprend d'un transitaire des routes qu'il annonce à son pair (normalement, on n'annonce à un pair que ses routes à soi). L'exposé de Mauch en cite également des exemples.
Le type 4 est l'inverse : un pair laisse fuir les préfixes d'un pair vers un transitaire. Ce fut le cas de l'incident Moratel contre Google, ou d'un problème frappant Amazon.
Le type 5 se nomme « ré-origination ». L'AS maladroit annonce les routes comme si elles venaient de lui, et c'est son numéro d'AS qui apparait comme origine (le début du chemin d'AS). Ce fut le cas lors de grande fuite chinoise de 2010, ou pendant le curieux détournement islando-biélorusse (un des rares cas où le shunt semblait volontaire).
Le type 6 est la « fuite de préfixes plus spécifiques ». Un AS typique annonce dans son IGP des préfixes bien plus spécifiques que ce qu'il annonce publiquement, afin de contrôler plus finement le routage interne. Une erreur (redistribution de l'IGP dans l'EGP...) et paf, les préfixes spécifiques fuient. Étant plus spécifiques que le préfixe « normal », ils seront préférés lors de la transmission des paquets. Le cas le plus spectaculaire fut celui de l'AS 701.
Le RFC ne discute pas des solutions possibles, ce n'est pas son but. Les curieux pourront regarder du côté des systèmes d'alerte ou de RPKI/ROA.
Première rédaction de cet article le 7 juillet 2016
Le 21 juin, dans les locaux de Radio France, j'ai eu le plaisir de parler aux employés de la direction du numérique sur le thème « Libertés dans le numérique, un Internet favorable ou défavorable aux droits de l'homme ? » Cette conférence était largement inspirée des travaux du groupe de recherche HRPC (Human Rights [and] Protocol Considerations).
La présentation était :
Lawrence Lessig est fameux pour sa phrase « code is law » qui rappelait l'importance des infrastructures dans les possibilités offertes aux citoyens. Si on a le droit de se déplacer librement mais qu'il n'y a pas de transports en commun et que les voitures sont hors de prix, que vaut ce droit ?
De même, dans le monde numérique, les techniques effectivement disponibles encouragent les droits de l'homme ou au contraire les limitent. Par exemple, certains composants de l'Internet rendent trop facile la censure.
On explorera ces caractéristiques de l'Internet, et on discutera de comment elles pourraient être modifiées.
Voici les supports de l'exposé :
Et la vidéo est maintenant disponible.
Merci à Maziar Dowlatabadi et Nadia Nwafo pour l'idée, et l'organisation.
Date de publication du RFC : Juin 2016
Auteur(s) du RFC : F. Gont (SI6 Networks /
UTN-FRH), J. Linkova
(Google), T. Chown (University of
Southampton), W. Liu (Huawei)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 5 juillet 2016
Normalement, l'Internet est un monde idéal où la machine d'Alice peut envoyer à celle de Bob les paquets qu'elle veut, Bob les recevra intacts (s'il le veut). Dans la réalité, pas mal de machines intermédiaires ne respectent pas ce principe de bout en bout. Il est fréquent que les paquets « inhabituels » soient jetés en route. Cela peut être le résultat d'une politique délibérée (pare-feu appliquant le principe « dans le doute, on jette ») ou bien, souvent, de l'incompétence des programmeurs qui n'ont pas lu les RFC et ne connaissent pas telle ou telle option. Par exemple, IPv6 permet d'ajouter au paquet, entre l'en-tête proprement dit et la charge utile du paquet, un ou plusieurs en-têtes d'extension. C'est rare en pratique. Est-ce que les programmeurs des middleboxes ont fait attention à cette possibilité ? Les paquets ayant ces en-têtes d'extension ont-ils de bonne chances d'arriver au but ? Ce nouveau RFC est un compte-rendu de mesures effectuées dans l'Internet pour essayer de quantifier l'ampleur exacte du problème.
Un point important du travail effectué par les auteurs du RFC
est qu'ils ne sont pas contentés de chercher
si les paquets étaient jetés mais également
où ils étaient jetés. La différence est
politiquement cruciale. Si le paquet IPv6
portant un en-tête d'extension est jeté par la machine de Bob, car
Bob n'aime pas ces en-têtes et il a configuré son
Netfilter pour les envoyer vers
DROP
, pas de problème : Bob est libre
d'accepter ou de refuser ce qu'il veut. Si, par contre, le paquet
a été jeté par le FAI d'Alice ou de Bob,
ou, encore pire, par un opérateur de transit entre les deux FAI,
c'est grave, c'est une violation de la neutralité du réseau,
violation qui empêche deux adultes consentants de s'envoyer les
paquets qu'ils veulent. Le mécanisme de mesure cherche donc à
trouver dans quel AS le paquet a
disparu.
Les mesures ont été faites en août 2014 et juin 2015. Le RFC détaille suffisamment la façon dont elles ont été faites (annexe A) pour qu'une autre équipe puisse recommencer les mesures à une date ultérieure, pour voir si la situation s'améliore.
Les en-têtes d'extension IPv6 sont décrits dans le RFC 2460, section 4. Ils sont de deux plusieurs sortes, entre autre :
Outre la fragmentation, un exemple d'utilisation de ces en-têtes est le protocole CONEX (RFC 7837). Si vous voulez ajouter des options pour la destination dans un paquet IPv6, vous pouvez regarder mon tutoriel.
Quelles sont les chances de survie des paquets portant ces en-têtes d'extension dans le sauvage Internet ? Des études comme « Discovering Path MTU black holes on the Internet using RIPE Atlas », « Fragmentation and Extension header Support in the IPv6 Internet » ou bien « IPv6 Extension Headers in the Real World v2.0 » s'étaient déjà penchées sur la question. Les mesures de ce RFC détaillent et complètent ces résultats préliminaires, notamment sur la différenciation entre perte de paquet près de la destination, et perte du paquet en transit. La conclusion est, qu'hélas, les paquets IPv6 portant des en-têtes d'extension font effectivement l'objet d'une discrimination négative (« entêtophobie » ?).
Donc, qu'est-ce que ça donne dans l'Internet réel (section 2) ?
Deux listes de serveurs IPv6 ont été utilisées, celle du
World IPv6
Launch Day et le premier million d'Alexa. De ces listes de
domaines ont été extraits les adresses IP des sites Web
(dig AAAA LE-DOMAINE
et, oui, je sais que
c'est un sérieux raccourci de supposer que tout domaine a un
serveur Web à l'apex), des relais de
messagerie (dig MX LE-DOMAINE
puis obtenir
l'adresse IPv6 des serveurs), et des serveurs de noms
(dig NS LE-DOMAINE
). Les adresses absurdes (::1
...)
ont été retirées. Ensuite, pour chaque adresse ainsi obtenue,
trois types de paquets ont été envoyés :
Les paquets étaient tous du TCP à destination d'un port correspondant au service (25 pour les serveurs de messagerie, par exemple).
Un point très important et original de cette expérience était la recherche d'information sur où se produisait l'éventuelle perte de paquets (dans quel AS). L'hypothèse de base est qu'une élimination du paquet dans l'AS de destination peut être acceptable, parce qu'elle résulte d'une décision consciente du destinataire. En tout cas, il sera plus facile de changer la politique de l'AS de destination. En revanche, une élimination dans un AS intermédiaire est inacceptable : elle indique filtrage ou erreur de configuration dans un réseau qui devrait être neutre. Notez que l'hypothèse n'est pas parfaite : si un particulier héberge un serveur chez lui et que son FAI filtre les paquets IPv6 avec en-tête d'extension, c'est quand même inacceptable, et c'est difficile pour le particulier de le faire corriger.
Comment identifier l'AS qui jette le paquet ? L'idée est de faire l'équivalent d'un traceroute (en fait, deux, un avec l'en-tête de destination et un sans, pour comparer : cf. annexe B.1) et de voir quel est le dernier routeur qui a répondu. C'est loin d'être idéal. Des routeurs ne répondent pas, pour d'autres, il est difficile d'évaluer à quel AS ils appartiennent (dans un lien de peering entre deux acteurs A et B, les adresses IP utilisées ont pu être fournies par A ou bien par B ; cf. annexe B.2). Et l'absence d'un routeur dans le résultat de traceroute ne prouve pas que le routeur n'a pas transmis le paquet juste avant. La mesure indique donc deux cas, l'optimiste, où on suppose, en l'absence de preuve opposée, que les paquets manquant ont été jetés par l'AS de destination et le pessimiste où on fait la supposition inverse.
Les résultats complets des mesures figurent dans le RFC. Je résume ici une partie. Pour les serveurs Web de la liste du World IPv6 Launch Day :
Les résultats ne sont guère différents pour les autres services (comme SMTP), indiquant que le problème, quand il est présent, est bien dans la couche 3. Idem avec le jeu de données Alexa : peu de différences.
On voit que les paquets utilisant l'en-tête d'extension « Options pour chaque intermédiaire » sont ceux qui s'en tirent le plus mal (c'est un peu logique, cet en-tête étant censé être examiné par tous les routeurs intermédiaires). Les fragments passent assez mal également. Enfin, on note qu'un pourcentage significatif des paquets sont jetés par un AS de transit, qui viole ainsi massivement le principe de bout en bout. Triste état de l'Internet actuel, pourri de middleboxes qui se permettent tout.
Si vous voulez refaire l'expérience vous-même, pour contrôler
les résultats, ou bien pour mesurer l'évolution dans quelque
temps, l'annexe A vous donne les éléments nécessaires. Vous aurez
besoin du toolkit de
SI6. Les données d'Alexa sont disponibles
en ligne. L'outil
script6
dans le toolkit
SI6 permet d'obtenir les adresses IP nécessaires. Par exemple :
% cat top-1m.txt | script6 get-mx | script6 get-aaaa
Et on obtient ainsi les adresses IP des relais de messagerie. Pour
supprimer les adresses incorrectes (par exemple
::1
), on utilise l'outil
addr6
du toolkit :
% cat top-1m-mail-aaaa.txt | addr6 -i -q -B multicast -B unspec -k global
Il n'y a plus maintenant qu'à envoyer les paquets portant les en-têtes d'extension, ou fragmentés. Ici, les serveurs de messagerie avec l'en-tête Destination Options (« do8 ») :
% cat top-1m-mail-aaaa-unique.txt | script6 trace6 do8 tcp 25
L'annexe B de notre RFC contient quelques avertissements méthodologiques.
Un
traceroute ordinaire ne suffit pas à faire
les mesures décrites plus haut pour identifier le routeur
responsable d'une perte de paquet (le traceroute ordinaire ne
permet pas d'ajouter l'en-tête d'extension aux paquets utilisés). Il faut utiliser un outil
spécial comme le path6
du
toolkit SI6. Encore plus simple, dans le même
paquetage, l'outil blackhole6
. Voyons d'abord
path6
pour comprendre les détails :
% sudo path6 -d yeti.ipv6.ernet.in Tracing path to yeti.ipv6.ernet.in (2001:e30:1c1e:1::333)... 1 (2001:4b98:dc0:41::250) 1.1 ms 0.5 ms 0.4 ms 2 (2001:4b98:1f::c3d3:249) 1.2 ms 3.5 ms 3.4 ms 3 (2001:7f8:54::173) 1.1 ms 0.8 ms 0.6 ms 4 (2001:1a00:1:cafe::e) 141.3 ms 140.7 ms 140.6 ms 5 (2001:1a00:1:cafe::145) 118.8 ms 118.8 ms 119.5 ms 6 (2001:1a00:1:cafe::141) 140.7 ms 137.2 ms 137.3 ms 7 (2001:1a00:1:cafe::10b) 144.0 ms 144.3 ms 144.1 ms 8 (2001:1a00:1:cafe::212) 140.5 ms 140.5 ms 140.5 ms 9 (2001:1a00:1:cafe::207) 137.0 ms 137.0 ms 136.9 ms 10 (2001:1a00:acca:101f::2) 136.5 ms 136.4 ms 136.5 ms 11 (2001:4528:ffff:ff04::1) 152.2 ms 152.1 ms 152.2 ms 12 (2001:4528:fff:c48::1) 163.6 ms 163.7 ms 163.6 ms 13 (2001:e30:1c1e::1) 162.6 ms 162.3 ms 162.2 ms 14 (2001:e30:1c1e:1::333) 174.5 ms 175.1 ms 175.2 ms
OK, on arrive à joindre la machine en Inde. Maintenant, ajoutons l'en-tête Hop-by-Hop Options :
% sudo path6 --hbh-opt-hdr 8 -d yeti.ipv6.ernet.in Tracing path to yeti.ipv6.ernet.in (2001:e30:1c1e:1::333)... 1 (2001:4b98:dc0:41::250) 20.9 ms 20.0 ms 19.0 ms 2 (2001:4b98:1f::c3d3:249) 20.8 ms 20.2 ms 18.5 ms 3 (2001:4b98:1f::c3c4:3) 20.7 ms 20.4 ms 18.5 ms 4 (2001:1a00:1:cafe::e) 154.3 ms 14.4 ms 152.1 ms 5 (2001:1a00:1:cafe::e) 151.0 ms 129.6 ms 148.9 ms 6 (2001:1a00:1:cafe::141) 151.2 ms 126.2 ms 148.8 ms 7 (2001:1a00:1:cafe::141) 156.5 ms 156.8 ms 158.6 ms 8 (2001:1a00:1:cafe::212) 153.6 ms 191.2 ms 151.4 ms 9 (2001:1a00:1:cafe::212) 155.3 ms 151.1 ms 157.7 ms 10 (2001:1a00:1:cafe::207) * 155.619995 ms * 11 () * * * 12 () * * * 13 () * * * ...
Aïe, ça n'arrive plus. Le routeur situé après
2001:1a00:1:cafe::207
a jeté le paquet. En
comparant les deux path6
, on peut voir que le
coupable est 2001:1a00:acca:101f::2
(Flag, désormais une marque de Reliance). L'outil
blackhole6
fait tout ce travail
automatiquement (EH = Extension Header, HBH 8 =
Hop-by-Hop, size 8) :
% sudo blackhole6 yeti.ipv6.ernet.in hbh8 SI6 Networks IPv6 Toolkit v2.0 (Guille) blackhole6: A tool to find IPv6 blackholes Tracing yeti.ipv6.ernet.in (2001:e30:1c1e:1::333)... Dst. IPv6 address: 2001:e30:1c1e:1::333 (AS2697 - ERX-ERNET-AS Education and Research Network, IN) Last node (no EHs): 2001:e30:1c1e:1::333 (AS2697 - ERX-ERNET-AS Education and Research Network, IN) (14 hop(s)) Last node (HBH 8): 2001:1a00:1:cafe::207 (AS15412 - FLAG-AS Flag Telecom Global Internet AS, GB) (10 hop(s)) Dropping node: 2001:1a00:acca:101f::2 (AS15412 - FLAG-AS Flag Telecom Global Internet AS, GB || AS Unknown - Unknown)
Sur ce sujet et ces tests, on peut aussi regarder l'exposé de Mehdi Kouhen au symposium Polytechnique/Cisco, ou bien celui d'Eric Vyncke à Protosec à Buenos Aires.
Première rédaction de cet article le 4 juillet 2016
Dernière mise à jour le 6 juillet 2016
Le 2 juillet, au festival Pas Sage en Seine / Hacker Space Festival, j'ai eu le plaisir de faire un exposé sur la chaîne de blocs Ethereum, plus précisement sur l'écriture de programmes (on dit parfois contrats) Ethereum. Cet exposé s'adresse donc surtout aux programmeurs.
Voici les supports de l'exposé :
Il y aussi la vidéo en ligne.
Les deux contrats présentés à Pas Sage En Seine, Soleau et FindByHash, ont été installés
sur la chaîne de blocs. Sur la chaîne de
tests « Morden », Soleau est installé en 0x165180498e843c5119d7d57b866da1392b8e8185
et FindByHash en 0x78db9a1dfe1b46c4361ac91cda111f5366ddc0e5
.
Sur la « vraie » chaîne,
Soleau est en 0x39aa4006ee5941c0c0e41b924fdafcb2c4c918e8
et FindByHash en 0x9b6e416ea0d89a09b4ae036a774b1d31825252f8
. Si
vous voulez interagir avec ces contrats, voici
l'ABI de Soleau :
[{"constant":true,"inputs":[{"name":"hash","type":"string"}],"name":"get","outputs":[{"name":"success","type":"bool"},{"name":"theBlock","type":"uint256"},{"name":"theTime","type":"uint256"},{"name":"holder","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"string"}],"name":"record","outputs":[{"name":"success","type":"bool"},{"name":"already","type":"bool"},{"name":"theBlock","type":"uint256"}],"type":"function"}]
Et celle de FindByHash :
[{"constant":true,"inputs":[{"name":"key","type":"string"},{"name":"index","type":"uint256"}],"name":"get","outputs":[{"name":"","type":"bool"},{"name":"","type":"string"}],"type":"function"},{"constant":true,"inputs":[{"name":"key","type":"string"}],"name":"num_of","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"key","type":"string"},{"name":"value","type":"string"}],"name":"set","outputs":[{"name":"","type":"bool"}],"type":"function"},{"inputs":[],"type":"constructor"}]
Ça s'utilise comment ? Prenons l'exemple de Soleau sur la chaîne de test. Si on utilise le logiciel geth, avec sa console JavaScript, on déclare le contrat et on indique l'adresse :
soleauC = eth.contract([{"constant":true,"inputs":[{"name":"hash","type":"string"}],"name":"get","outputs":[{"name":"success","type":"bool"},{"name":"theBlock","type":"uint256"},{"name":"theTime","type":"uint256"},{"name":"holder","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"hash","type":"string"}],"name":"record","outputs":[{"name":"success","type":"bool"},{"name":"already","type":"bool"},{"name":"theBlock","type":"uint256"}],"type":"function"}]) soleau = soleauC.at("0x165180498e843c5119d7d57b866da1392b8e8185")
Une fois que c'est fait, on peut appeler l'ABI du contrat. Ici, on demande si un condensat est bien stocké dans la chaîne :
> soleau.get("98461ec184a39f0b8d89401a2756ffc84c2473a772655b425d794db6e7b68a8a") [true, 1211232, 1467041583, "0xaf8e19438e05c68cbdafe33ff15a439ce6742972"] > soleau.get("666") [false, 0, 0, "0x0000000000000000000000000000000000000000"]
Sur la chaîne principale, le même contrat a une valeur
5e1e7a61931acb3f0e2bb80fc1d88e242d8556e6
stockée :
> soleau.get("5e1e7a61931acb3f0e2bb80fc1d88e242d8556e6") [true, 1830809, 1467745954, "0xc90cd1fa9940a4d4a07a37c53bb4f423fd286945"]
On peut aussi ajouter des valeurs (ici, sur la chaîne de test). Comme cela change l'état de la chaîne, il faut faire une transaction, et payer, à la fois l'essence (ici, 400000 unités mais moins de 100000 seront effectivement utilisées) et le prix prévu dans le contrat :
> soleau.record.sendTransaction("d479b91d7a2cdd21f605c5632344228dd5f75d66", {from: eth.accounts[0], gas: 400000, value: web3.toWei(0.001)}) "0xfb6bc725e303c79c2c5426c3a0d4fce90b635521826e5bd3e94ddfa3d80c48da"
Le résultat est l'identificateur de la transaction, que vous pouvez
regarder
en ligne (avec le bouton Convert to ASCII,
vous verrez le condensat enregistré, dans les données de la transaction). Sur la chaîne principale, un exemple de transaction
de ce contrat est disponible
ici.
Pour le contrat FindByHash, si vous voulez regarder des valeurs
enregistrées, il y a
cf4163b8f4c13b915e246ea7d2792156
sur la chaîne de
tests et
3d10dcb5e503d3b8abc2fa5a72adb0a503930e0b6b8a893f17dda63b9b717dba
sur la chaîne principale :
> findhash.num_of("cf4163b8f4c13b915e246ea7d2792156") 2 > findhash.get("cf4163b8f4c13b915e246ea7d2792156", 0) [true, "https://localhost/"] > findhash.get("cf4163b8f4c13b915e246ea7d2792156", 1) [true, "https://www.bortzmeyer.org/toto"]
Pour enregistrer des URL dans ce contrat, le plus simple est ce petit script shell, qui s'utilise ainsi :
% findbyhash-register-url.sh http://www.bortzmeyer.org/pas-sage-en-seine-ethereum.html ... "0x82a808828a115547b242f335783bf75a0c96d2d746ab9dff160898a8f28a5411" 3d10dcb5e503d3b8abc2fa5a72adb0a503930e0b6b8a893f17dda63b9b717dba registered for http://www.bortzmeyer.org/pas-sage-en-seine-ethereum.html
(Et vous pouvez voir la transaction en ligne.)
Si le sujet vous intéresse, j'en parlais plus longuement à la Journée du Conseil Scientifique de l'AFNIC le 11 juillet (avec d'autres exemples de code, rassurez-vous).
Il y avait plein d'autres trucs géniaux à PSESHSF, n'hésitez pas à regarder le programme. Mes préférés (c'est complètement subjectif), faire son pain soi-même (et avec du levain), les explications (avec démo de diffuseur d'odeurs et bonbons qui sentent bon) sur le marketing sensoriel, le projet pour un camp de hackers en été en France, la conférence sur l'éducation au numérique (qui ne sortira sans doute pas en vidéo, l'auteur étant mineur), même si sa seconde partie, sur l'éducation au business a suscité (à juste titre), des réactions houleuses, la reprise de contrôle de l'alimentation, le système d'exploitation Qubes (j'avais parlé de ce système sur ce blog mais sans le tester), la bière libre (j'ai goûté ; un peu forte), l'appel aux citoyens à participer à la science, la synthèse du récent virage de la Quadrature du Net, le bilan de la loi Renseignement, etc.
Date de publication du RFC : Juin 2016
Auteur(s) du RFC : G. Lozano (ICANN)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF eppext
Première rédaction de cet article le 28 juin 2016
Les registres de noms de domaine ont parfois des règles d'enregistrement spéciales, pendant une période limitée, lorsqu'on ouvre un nouveau TLD, ou si on change radicalement ses règles d'enregistrement. Ces règles spéciales pour les périodes de « lever de soleil » (sunrise, lorsque le nouveau TLD est créé) servent en général à favoriser les détenteurs de marques ou autres titres de propriété intellectuelle. L'idée est que, pendant le lever de soleil, seuls ces détenteurs aient le privilège d'enregistrer un nom, les autres attendront. Pour que le registre puisse facilement vérifier la possession d'une marque déposée, il faut un format standard pour les décrire, et c'est ce que contient ce RFC. Il a été écrit par un employé de l'ICANN car il vise surtout un service de l'ICANN, la TMCH (Trade Mark Clearing House).
La TMCH est un registre de marques créé par l'ICANN (voir sa
description
officielle). Il a
suscité d'innombrables débats (par exemple, de quel droit l'ICANN crée un
registre mondial faisant autorité, excluant les marques qui n'ont
pas voulu passer par ce processus ?) mais ce RFC ne concerne que la
partie technique, le format de description de ces marques. Il
s'applique a priori aux TLD ICANN comme
.pizza
ou .maif
mais les
autres sont libres de s'en servir également. Comme les objets
décrits dans ce RFC peuvent être signés, il faut avoir une
PKI. Dans le cas des TLD ICANN, elle est
décrite dans le document officiel cité plus haut. Les objets
eux-mêmes sont décrits en XML, pour pouvoir
être utilisés dans le protocole EPP (RFC 5730).
Les objets sont dans les espaces de noms
urn:ietf:params:xml:ns:mark-1.0
(abrégé en
mark:
dans ce RFC) et
urn:ietf:params:xml:ns:signedMark-1.0
(abrégé
en smd:
dans ce RFC).
Les objets XML décrivant les marques incluent des informations
sur les personnes ou entités qui gèrent les marques. Il y a ainsi
des <mark:holder>
et des
<mark:contact>
, qui comprennent des
éléments classiques : nom, adresse postale (qui comprend elle-même
ville, pays...), adresse de courrier
électronique, etc.
Les marques sont décrites par un élément
<mark:mark>
. Celui-ci contient le nom
de la marque, des
références au registre initial (par exemple, en France,
l'INPI), le contact et le titulaire
(décrits au paragraphe précédent) et d'autres informations utiles
aux juristes (comme les biens et services couverts par cette
marque, puisque les marques, contrairement aux noms de domaine,
sont normalement spécifiques).
Les objets décrivant une marque peuvent être signés, grâce à XML Signature. Voici un exemple (très simplifié, voir la section 2.3 du RFC pour le XML complet) d'une marque avec sa signature :
<?xml version="1.0" encoding="UTF-8"?> <smd:signedMark xmlns:smd="urn:ietf:params:xml:ns:signedMark-1.0" id="smd1"> <smd:issuerInfo issuerID="65535"> <smd:org>ICANN TMCH TESTING TMV</smd:org> <smd:email>notavailable@example.com</smd:email> ... </smd:issuerInfo> <mark:mark xmlns:mark="urn:ietf:params:xml:ns:mark-1.0"> <mark:trademark> <mark:id>00052013734689731373468973-65535</mark:id> <mark:markName>Test & Validate</mark:markName> <mark:holder entitlement="owner"> <mark:org>Ag corporation</mark:org> ... <mark:jurisdiction>US</mark:jurisdiction> <mark:class>15</mark:class> <mark:label>testandvalidate</mark:label> ... <mark:regNum>1234</mark:regNum> <mark:regDate>2012-12-31T23:00:00.000Z</mark:regDate> </mark:trademark> </mark:mark> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> ... <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> ... <SignatureValue> jMu4PfyQGiJBF0GWSEPFCJjmywCEqR2h4LD+ge6XQ+JnmKFFCuCZS/3SLKAx0L1w ... </Signature> </smd:signedMark>
L'élement XML peut aussi être intégralement encodé en
Base64 (RFC 4648), et
ça sera alors un <smd:encodedSignedMark>
.
La syntaxe exacte est spécifiée dans la section 3 du RFC, avec le langage W3C Schema.
Quelles sont les mises en œuvre de ce format ? Le kit de
développement logiciel de Verisign
l'intègre (il est disponible
en ligne), et c'est aussi le cas de Net::DRI (dans
Net::DRI::Protocol::EPP::Extensions::ICANN::MarkSignedMark
,
ouf). Côté serveur, le serveur
EPP de Verisign pour des TLD comme
.com
. D'autres
serveurs EPP peuvent utiliser ce format comme REngin, ou celui d'Uniregistry.
Date de publication du RFC : Juin 2016
Auteur(s) du RFC : J. Scudder (Juniper
Networks), R. Fernando
(Cisco), S. Stuart (Google)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF grow
Première rédaction de cet article le 28 juin 2016
Ce nouveau protocole BMP
(BGP Monitoring
Protocol) va faciliter le travail des administrateurs
réseaux qui font du BGP. Il permet d'obtenir sous une forme
structurée les tables BGP. Avant, la solution la plus répandue
était d'utiliser l'interface en ligne de
commande du routeur (show ip bgp
routes
sur un Cisco), et d'analyser le résultat depuis
son programme, une méthode qui est très fragile, le format de
sortie ayant été conçu pour des humains et pas pour des
programmes.
Les tables convoitées sont bien sûr la RIB mais aussi des informations comme les mises à jour de routes reçues. BMP donne accès à une table BGP nommée Adj-RIB-In, « Adjacent [peers] Routing Information Base - Incoming », définie dans le RFC 4271, section 1.1. Elle stocke les informations brutes (avant les décisions par le routeur) transmises par les pairs BGP.
BMP fonctionne (section 3) en établissant une connexion TCP avec le routeur convoité. Celui-ci envoie ensuite l'information qu'il veut. Il n'y a pas de négociation ou de discussion au début. Dès que la connexion est établie, le routeur transmet. Il envoie d'abord des messages Peer Up pour chacun de ses pairs, puis des messages Route Monitoring pour toute sa base de routes (la section 5 les décrit plus en détails). Une fois que c'est fait, le routeur transmet des messages indiquant les changements : Route Monitoring en cas d'annonce ou de retrait d'une route, Peer Up ou Peer Down s'il y a des changements chez les pairs. Autres messages possibles : Stats Report pour envoyer des statistiques globales (voir les sections 4.8 et 7), Initiation et Termination pour les débuts et fins de sessions, Route Mirroring pour envoyer verbatim les annonces BGP reçues (c'est une vision de plus bas niveau que Route Monitoring et cela permet, par exemple, d'analyser des annonces BGP syntaxiquement incorrectes, cf. section 6).
Le client BMP ne transmet jamais de message au serveur (au routeur), à tel point que le routeur peut parfaitement fermer la moitié de la connexion TCP, ou mettre sa fenêtre d'envoi à zéro (ou encore, jeter tous les messages qui seraient envoyés). Toute la configuration est dans le routeur.
Le format des messages est décrit en section 4. C'est du classique. On trouve dans le message un numéro de version (actuellement 1), la longueur du message, le type du message (la liste des types est indiquée plus haut) représentée par un entier (0 pour Route Monitoring, 1 pour Stats Report (ou Statistics Report), etc), puis les données. À noter que le type arrive après la longueur, alors que c'est en général le contraire (encodage TLV).
Pour la plupart des messages BMP, il y aura un second en-tête, rassemblant les informations sur le pair (son adresse IP, son AS, etc).
Les différents paramètres numériques sont désormais stockés dans un registre IANA.
Quelques petits mots sur la sécurité pour finir. Pour économiser ses ressources, le routeur peut évidemment (section 3.2) restreindre l'ensemble des adresses IP autorisées à se connecter en BMP à lui, tout comme il peut limiter le nombre de sessions BMP (par exemple, une au maximum par adresse IP, cinq au total). Il peut aussi y avoir des questions de confidentialité (section 11). Bien sûr, la liste des routes dans la DFZ est publique, mais ce n'est pas forcément le cas des peerings privés ou de VPN utilisant BGP comme ceux du RFC 4364. Donc, attention à bien restreindre l'accès.
BMP est en cours d'élaboration depuis pas mal de temps déjà. Résultat, des mises en œuvre ont eu le temps d'apparaitre. Wireshark sait analyser le BMP. Et il existe deux récepteurs (clients) libres, BMPreceiver et OpenBMP. Côté serveur (routeur), Cisco et Juniper savent envoyer du BMP.
Date de publication du RFC : Juin 2016
Auteur(s) du RFC : P. Wouters (Red Hat)
Expérimental
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 24 juin 2016
Lorsqu'un client DNS parle à un résolveur, il pose une question et obtient une réponse. Avant DNSSEC, ce mode de fonctionnement simple était souvent satisfaisant. Mais, avec DNSSEC, il est beaucoup plus fréquent de devoir faire plusieurs requêtes pour obtenir toute l'information nécessaire pour valider les réponses. (Il faut les clés de toutes les zones situées entre la racine et la zone visée.) Cela coûtait cher en latence. Cette extension EDNS expérimentale permet au client DNS de demander au résolveur de chercher et de renvoyer toutes les réponses d'un coup.
Cette extension est particulièrement utile pour le cas de
machines terminales hébergeant leur propre résolveur validant (ce
qui est la meilleure configuration, question confiance et
sécurité). Ce n'est donc pas un hasard si l'auteur du
RFC travaille chez
Red Hat, système qui est livré par défaut avec
une telle configuration. Mais, lorsqu'un tel résolveur validant veut
vérifier les informations obtenues sur
foo.bar.example
, il devra (en supposant qu'il y
a une zone par composant du nom de domaine)
obtenir la délégation sécurisée de example
(dig @la-racine DS example
), la clé de
example
(dig @ns-example DNSKEY
example
), la délégation sécurisée de
bar.example
, etc (la clé de la racine,
elle, est en dur dans le résolveur, il faut bien partir de quelque part). À faire séquentiellement,
cela serait beaucoup de requêtes, donc du temps passé à attendre les
réponses. Sur des liens à latence élevée (ce qui arrive souvent aux
machines terminales), cela peut être pénible, même si le
cache DNS aidera, pour les requêtes suivantes.
L'idée de cette extension (sections 1 et 3 du RFC) est donc que le résolveur validant
local ait un forwarder (attention, le RFC utilise
un vocabulaire erroné, en donnant à forwarder un
sens différent de celui qu'il a dans les RFC 2308 et RFC 8499 ; j'utilise, moi, la terminologie standard). Le résolveur
validant local va demander à ce forwarder, grâce
à la nouvelle extension EDNS CHAIN
, d'envoyer tout
d'un coup (tous les DS et
DNSKEY nécessaires). Bien sûr, le
forwarder, lui, devra faire toutes les requêtes
mais, a priori, il a un plus gros cache et sera mieux connecté.
Cette nouvelle extension est donc conçue pour des résolveurs, et est ignorée par les serveurs faisant autorité. Notez que le résolveur validant local peut être un démon autonome (Unbound tournant sur mon portable Unix) ou bien une partie d'une application qui embarquerait ses propres fonctions de résolution de noms.
Le format de l'extension est décrit en section 4 du RFC. C'est
une option EDNS (RFC 6891), encodée, comme les autres options EDNS, en
TLV. Le type (le code) est 13. La valeur est composée d'un seul champ,
l'ancêtre le plus proche (Closest Trust Point)
dont on connaisse les informations nécessaires à la validation. Le
résolveur validant local a en effet certaines informations (dans sa
configuration ou dans son cache) qu'il n'est pas nécessaire de lui
envoyer. Dans l'exemple plus haut, si le résolveur validant local
connait déjà la clé DNSSEC de example
, il
mettra dans le champ Closest Trust Point ce nom
de domaine, indiquant au forwarder qu'il peut se
contenter des informations situées plus bas, dans l'arbre du
DNS. Ce nom est encodé dans le format habituel du DNS (qui n'est
pas le format texte avec les
points).
La section 5 du RFC décrit comment utiliser cette extension au
DNS. Si on veut tester les capacités du résolveur qu'on interroge,
on peut utiliser une option CHAIN
vide
(longueur nulle). Si le serveur à qui on a envoyé cette option
répond avec la même option nulle, c'est bon. Attention, les serveurs
récursifs qui mettent en œuvre CHAIN
n'accepteront des requêtes « réelles » (longueur non nulle) qu'au-dessus d'un transport où l'adresse IP source est vérifiée. Le but
est d'éviter les attaques par
réflexion avec amplification (voir aussi la section 7.2). Pour vérifier l'adresse IP
source (ce qui ne se fait normalement pas en
UDP), il y a plusieurs solutions, notamment
TCP (RFC 7766) et les
gâteaux (RFC 7873).
Une fois qu'on a un tel transport, et que le client DNS a testé
que le serveur qu'il interroge gère bien CHAIN
,
on peut y aller. Le client met l'ancêtre le plus proche (dont il a
les clés) du nom
demandé dans le champ Closest Trust Point. Dans
le cas le plus courant (résolveur validant configuré avec une seule
clé, celle de la racine), le résolveur « froid », qui vient de
démarrer et dont le cache est vide, il commencera par mettre la
racine en Closest Trust Point puis, au fur et à
mesure qu'il se « réchauffera » (que son cache se peuplera), il
pourra mettre des noms plus proches du nom demandé (et donc plus
éloignés de la racine). Par exemple, si le résolveur validant local
est configuré avec la clé de la racine, et qu'il a appris par les
réponses précédentes la clé de example
, mais
pas celle de bar.example
, et qu'il veut des
informations sur le nom foo.bar.example
, son
option CHAIN
vaudra {type = 13, longueur = 9,
valeur = 0x07 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x00} (la longueur
est celle de la partie « valeur » uniquement, le nom
example
est encodé selon la norme DNS). S'il
connaissait également la clé de bar.example
, son option
CHAIN
vaudrait {type = 13, longueur = 13,
valeur = 0x03 0x62 0x61 0x72 0x07 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65
0x00}. D'autres exemples figurent en section 9 du RFC.
Faut-il envoyer l'option CHAIN
à chaque
requête ? On peut mais il est recommandé de se souvenir de quels
serveurs la gèrent et de n'envoyer qu'à ceux-ci (autrement, non
seulement on fait du travail inutile mais on renseigne des serveurs
extérieurs sur l'état de son cache). Comme il existe des
middleboxes boguées sur
certains trajets, la stratégie de repli du RFC 6891, section 6.2.2 peut être utile.
Et le serveur interrogé, que fait-il ? S'il accepte de répondre à
une requête contenant l'extension CHAIN
, il
doit :
CHAIN
dans la réponse, avec
la valeur Closest Trust Point mise au nom le
plus bas (le plus éloigné de la racine) pour lequel ces
informations sont nécessaires. (C'est surtout utile lorsque le
serveur n'envoie pas une chaîne complète, par exemple pour
économiser le réseau.)
Évidemment, si la question avait une erreur de syntaxe (taille de la
partie Valeur inférieure à la Longueur, par exemple), le serveur
répond FORMERR
(FORmat
ERRor).
La section 7 sur la sécurité étudie quelques
programmes que peut poser cette extension au DNS. D'abord, mettre en
œuvre cette option fatigue davantage le serveur interrogé, en terme
de travail et de capacité du réseau. Un serveur est donc toujours
libre d'ignorer les options CHAIN
et de s'en
tenir au service minimum.
Ensuite, comme vu plus haut, les réponses suivant une question
qui utilise CHAIN
vont être évidemment plus
grosses que les réponses DNS habituelles. Il y a donc un risque d'attaques par
réflexion avec amplification, si un attaquant usurpe
l'adresse IP de sa victime. C'est pour cela que notre RFC impose de
ne répondre avec une chaîne complète que si l'adresse IP du client a
été vérifiée (par exemple parce qu'il utilise
TCP, ou bien les cookies
du RFC 7873).
CHAIN
a aussi quelques effets sur la
vie privée. Le résolveur validant local va
indiquer à son forwarder (et à tout espion qui
surveille le trafic) comment il est
configuré et ce qu'il y a dans son cache.
Il ne semble pas qu'il existe de mise en œuvre de cette option
CHAIN
pour l'instant, même si c'est en projet pour Go.
Si vous vous intéressez à la conception des protocoles réseaux, notez que cette extension a fait l'objet d'une discussion pour savoir s'il ne valait pas mieux, pour réduire la latence, envoyer toutes les requêtes possibles en parallèle (cette idée a finalement été rejetée).
Première rédaction de cet article le 22 juin 2016
Le 21 juin, la nouvelle version d'Unicode est sortie, la 9.0. Une description officielle des principaux changements est disponible mais voici ceux qui m'ont intéressé particulièrement. (Il n'y a pas de changement radical.)
Pour explorer plus facilement la grande base Unicode, j'utilise un programme qui la convertit en SQL et permet ensuite de faire des analyses variées. Faisons quelques requêtes SQL :
ucd=> SELECT count(*) AS Total FROM Characters; total -------- 128237
Combien caractères sont arrivés avec la version 9 ?
ucd=> SELECT version,count(version) FROM Characters GROUP BY version ORDER BY version; ... 8.0 | 7716 9.0 | 7500
7 500 nouveaux pile. Lesquels ?
ucd=> SELECT To_U(codepoint) AS Codepoint, name FROM Characters WHERE version='9.0'; codepoint | name -----------+---------------------------------------------------------------------------- ... U+8BA | ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE ... U+8E2 | ARABIC DISPUTED END OF AYAH ... U+23FB | POWER SYMBOL U+23FC | POWER ON-OFF SYMBOL U+23FD | POWER ON SYMBOL U+23FE | POWER SLEEP SYMBOL ... U+104D8 | OSAGE SMALL LETTER A U+104D9 | OSAGE SMALL LETTER AI U+104DA | OSAGE SMALL LETTER AIN ... U+17000 | TANGUT IDEOGRAPH-17000 U+17001 | TANGUT IDEOGRAPH-17001 U+17002 | TANGUT IDEOGRAPH-17002 ... U+1F921 | CLOWN FACE U+1F922 | NAUSEATED FACE U+1F923 | ROLLING ON THE FLOOR LAUGHING ... U+1F933 | SELFIE ... U+1F953 | BACON U+1F954 | POTATO U+1F955 | CARROT
On trouve également des écritures entièrement nouvelles comme l'osage ou le tangoute, qui fait 91 % des nouveaux caractères de cette version. Et il y a bien sûr l'habituel lot d'emojis pour faire rire les réseaux sociaux (signe des temps, il y a maintenant un emoji pour selfie). Je ne sais pas pourquoi on ajoute des caractères arabes pré-composés comme le « ARABIC LETTER YEH WITH TWO DOTS BELOW AND SMALL NOON ABOVE » au lieu de permettre sa composition à partir de caractères existants. On note aussi un caractère dont le nom indique qu'il est contesté... (Il existe déjà U+6DD, « ARABIC END OF AYAH » mais on me souffle que le nouveau serait nécessaire au Pakistan.) On note qu'après un long lobbying, les symboles d'allumage et d'extinction de votre machine sont désormais dans Unicode.
Si vous avez les bonnes polices de caractères, voici les caractères pris en exemple plus haut : ࢺ ⏻ ⏼ ⏽ ⏾ 𐓘 𐓙 𐓚 𗀀 𗀁 𗀂 🤡 🤢 🤣 🤳 🥓 🥔 🥕
Il n'y a pas que l'ajout de nouveaux caractères, mais aussi quelques légers changements techniques. Par exemple, les règles de passage à la ligne (UAX #14) prennent désormais en compte les gens qui ont un signe $ dans leur nom (comme Travi$ Scott) et les règles IDN (UTS #46) ont corrigé une bogue.
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : S. Previdi, C. Filsfils (Cisco
Systems), B. Decraene, S. Litkowski
(Orange), M. Horneffer (Deutsche
Telekom), R. Shakir (Jive
Communications)
Pour information
Réalisé dans le cadre du groupe de travail IETF spring
Première rédaction de cet article le 22 juin 2016
Traditionnellement, la transmission d'un paquet IP au routeur suivant était faite uniquement sur la base de l'adresse de destination, sans tenir compte du reste du paquet. Et la décision est prise par chaque routeur, sur le trajet, en complète indépendance. Or, l'émetteur d'un paquet voudrait souvent décider de la route suivie ou, au minimum, l'influencer. C'est pour cela qu'il existe des mécanismes de routage par la source (source routing). Leurs défauts et leurs limites ont mené à la recherche d'une meilleure solution, dite SPRING (Source Packet Routing In NetworkinG). Ce RFC est la description du problème.
Notez que le terme « source » a, pour SPRING, un sens plus large que lorsqu'on parle habituellement de source routing. Dans ce dernier cas, la source était uniquement l'émetteur original. Pour SPRING, la source est l'endroit où on définit la politique de routage ultérieur, elle peut se situer au milieu du trajet.
Avant SPRING, il y avait plusieurs solutions permettant à la source de décider du routage mais aucune n'a été largement déployée (à part MPLS). C'est dû en partie à leur manque de souplesse, en partie à des problèmes de sécurité.
La future solution SPRING doit être un meilleur système (section 1 du RFC), et déployable de manière incréméntale (il ne serait évidemment pas réaliste de devoir changer tout l'Internet). En outre, l'état doit être maintenu dans le paquet lui-même, pas dans les routeurs intermédiaires. L'expérience de l'Internet a en effet largement montré que pour faire marcher un grand réseau complexe, il ne faut pas maintenir d'état dans les nœuds intermédiaires.
SPRING devra être assez général marcher avec plusieurs mécanismes de transmission des paquets (dataplanes, cf. section 2). Les principaux visés sont MPLS et IPv6 avec un nouvel en-tête de routage (cf. RFC 2460, section 4.4).
La section 3 présente plusieurs scénarios d'usage, pour montrer pourquoi un système tel que SPRING est utile. Il y a par exemple la création de tunnels pour faire des VPN (RFC 4364).
Il y a aussi le reroutage rapide de paquets (FRR, Fast ReRoute), et bien sûr l'ingéniérie de trafic. Pour ce dernier scénario, notre RFC demande que la future solution SPRING permette des options strictes (le paquet suit exactement le chemin spécifié) ou laxistes (le paquet suit à peu près le chemin spécifié), puisse fonctionner en centralisé (SDN) ou en décentralisé, etc.
Une des raisons du peu de déploiement des solutions de routage par la source est évidemment la sécurité (section 4 du RFC). SPRING met le chemin désiré dans le paquet (pour éviter de garder un état dans le réseau). Or, si on suit aveuglément les desiderata de chaque paquet, on ouvre la voie à des tas d'attaques. Par exemple, un paquet spécifie un détour considérable par un autre pays, et cela occupe pour rien les liaisons internationales. Un paquet spécifie un trajet qui boucle et les routeurs qui lui obéiraient feraient une attaque par déni de service contre eux-mêmes.
Le RFC impose donc que SPRING fournisse un mécanisme de « domaines de confiance » avec des frontières bien claires. Si un paquet vient d'un domaine de confiance, on lui obéit. S'il vient de n'importe où sur l'Internet, on ignore ses demandes (ou bien on vire ces options de routage par la source lorsque le paquet change de domaine).
La réalisation concrète de SPRING sur un système de transmission donné (comme MPLS ou IPv6) doit également documenter les risques spécifiques à ce dataplane. Par exemple, MPLS est en général utilisé uniquement à l'intérieur d'un domaine contrôlé et connu (le réseau d'un opérateur) alors qu'IPv6 est de bout en bout donc pose davantage de risques (mais il dispose de possibilités supplémentaires, comme la signature cryptographique des en-têtes).
Il faut maintenant attendre les RFC décrivant les solutions, ils sont en cours de développement dans le groupe SPRING.
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : JM. Valin (Mozilla), C. Bran
(Plantronics)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF rtcweb
Première rédaction de cet article le 21 juin 2016
Ce très court RFC expose les exigences en matière de codec audio pour WebRTC. Opus et G.711 sont ainsi obligatoires.
WebRTC permet de communiquer (texte, audio et vidéo) entre deux machines, typiquement via les navigateurs Web (ainsi, Firefox et Chrome sont tous les deux capables de faire du WebRTC.) On sait qu'il existe un grand nombre de moyens de représenter les sons sous forme d'un flux de données numériques et, pour que la communication puisse se faire, il faut que les participants aient au moins un de ces moyens en commun. C'est le but de ce RFC. D'autres codecs peuvent évidemment être gérés par le logiciel mais ceux-ci sont obligatoires (section 3 du RFC) :
audio/telephone-event
du
RFC 4733 (DTMF), qui permet d'envoyer les indispensables
signaux « si vous voulez de la musique d'attente pendant une
heure, tapez 1, si vous voulez parler à un incompétent sous-payé
qui ne
comprendra pas votre problème, tapez 2 ».Les autres codecs facultatifs sont décrits dans le RFC 7875, ce qui a permis à chacun de faire citer son codec favori.
Notre RFC spécifie également le niveau sonore (section 4). Contrairement aux recommandations UIT G.169 et G.115, il n'est pas constant car il dépend de la bande passante.
Il y a aussi une mention de la suppression d'écho (section 5 du RFC), mais sans solution unique imposée.
Première rédaction de cet article le 20 juin 2016
Vendredi 17 juin 2016, une attaque spectaculaire contre l'organisation The DAO a eu lieu, menant à la soustraction d'environ un tiers de ses fonds. Quelles leçons à en tirer ?
Si vous connaissez au moins un peu The DAO et Ethereum, vous pouvez lire tout de suite mes réflexions sur cette crise. Si vous ne connaissez pas, vous pouvez lire en anglais la bonne explication de Robert Graham ou bien en français les articles de Wikipédia sur Ethereum et les contrats.
Comme d'habitude lorsqu'un gros problème de cybersécurité est publié, on trouve du grand n'importe quoi dans les médias ou sur les rézosocios. Il est donc important de commencer par être précis sur les faits :
Mais cela ne veut pas dire que cette bogue est juste un détail sans importance et qu'on peut passer. Il s'agit d'une crise grave, dont il faudra tirer les leçons. D'abord, sur l'aspect technique (mais je parle des questions financières, légales et de gouvernance par la suite). L'origine du problème est une bogue dans le code de The DAO (pour les cœurs bien accrochés, voici les explications techniques complètes). C'est une banalité de noter qu'on ne sait pas écrire du logiciel sans bogues. Tout logiciel a des bogues et, avant de confier des fonds à un contrat, il faut garder ce point en tête. Un des rares cas dans cette affaire où les pessimistes systématiques (« ce n'est pas moi qui a inventé ce truc, donc ça va rater ») avaient raison est quand ils pointaient le fait qu'il y aura forcément des bogues dans les contrats et, qu'en l'absence de mécanisme de recours, on aura du mal à en gérer les conséquences.
Cela ne veut pas dire qu'il faut baisser les bras et renoncer à programmer. Mais il faut changer, et d'état d'esprit, et sans doute de techniques utilisées. Emin Gün Sirer fait remarquer à juste titre que l'écriture d'un contrat devrait ressembler à celle du code d'un avion ou d'une centrale nucléaire, pas à celle d'un site Web avec images et CMS. Or, aujourd'hui, pas mal de programmeurs de contrat sont plutôt dans la mentalité « si le code semble faire vaguemement ce qu'on veut, c'est bon », qui a mené à pas mal de désastres de sécurité sur le Web. Du point de vue des techniques utilisées, le même Sirer a raison de dire qu'il faut se poser la question des langages de programmation. Un langage impératif comme Solidity est-il vraiment la meilleure solution pour faire des contrats sûrs, et ne faudrait-il pas plutôt utiliser des langages plus adaptés, par exemple plus fonctionnels, inspirés d'Haskell ? Ces langages ont un fossé plus réduit entre la spécification et l'exécution. Plus radicale, la vérification formelle des contrats devrait-elle être la norme ? A priori oui, mais soyons prudents : les mécanismes de vérification formelle des programmes sont lourds et compliqués et ont leurs propres bogues.
En parlant de spécification, Vitalik Buterin a fait un très bon article pour expliquer qu'une bogue, c'est par définition une déviation par rapport à la spécification, et que réduire le nombre de bogues implique d'être clair dans la spécification, ce qui est déjà un défi considérable. Dans un message non authentifié, un individu se présentant comme l'attaquant prétend ainsi que, le code du contrat étant sa loi, par définition, toute opération faite avec le contrat The DAO est légale, y compris son vol. Il est bien sûr de mauvaise foi, mais on peut noter qu'il n'est pas possible de lui opposer une spécification précise de ce que le contrat était censé faire.
Autre leçon technique, un rappel que la complexité est l'ennemie de la sécurité. Le code de The DAO comprenait de nombreuses fonctions (comme celle permettant de retirer ses fonds, à l'origine de la bogue), ce qui augmentait la probabilité d'avoir une bogue. J'ai toujours expliqué que le terme de smart contract était dangereux car il encourageait les programmeurs à faire du code compliqué, alors qu'un bon contrat est au contraire trivial à lire et à analyser. Un programmeur de contrat ne devrait pas être admiré pour ses hacks astucieux mais au contraire pour sa capacité à faire du code ennuyeux et évident. (Je pensais à la validation d'un contrat par ses utilisateurs, mais ce raisonnement s'applique également à la sécurité.)
A posteriori, il est clair qu'on est passé trop rapidement du petit contrat « Hello, World », à un gros truc complexe, avec plein de fric, comme The DAO. C'est un peu comme si, immédiatement après la traversée de la Manche par Blériot, on avait lancé sur l'Atlantique un avion de 500 passagers payants...
Il y a aussi des leçons à tirer de l'excessive focalisation sur l'argent, commune à une bonne partie de la communauté Ethereum, et aux médias. Les médias ont surtout présenté cette crise sous son angle financier (The DAO a perdu 50 millions, l'ether a baissé de 50 %, etc) alors que la chaîne de blocs Ethereum, contrairement à celle de Bitcoin, ne sert pas qu'à des transactions financières. Des tas de contrats ne consomment des ethers que pour acheter l'essence (le mécanisme par lequel on paie pour l'exécution des contrats). Se focaliser sur les contrats à caractère financier, comme The DAO, empêche de voir toutes les potentialités de la chaîne de blocs (plusieurs articles ont ainsi présenté, de manière erronée, Ethereum comme étant juste « une crypto-monnaie concurrente de Bitcoin »). Et, évidemment, stocker autant d'argent allait attirer les voleurs. Bref, tant que les articles sur Ethereum continueront à mettre en avant le cours de l'ether en comparant avec la monnaie étatique traditionnelle, on n'arrivera pas à comprendre toutes les potentialités (disruptives, forcément disruptives) de la chaîne de blocs.
Il y a également bien des leçons à tirer de la crise de The DAO en terme de gouvernance de la chaîne de blocs. Normalement, les contrats « intelligents » étaient censés se gouverner tout seuls. Le code est la loi, il est exécuté fidèlement par la la machinerie Ethereum, et il n'y a donc pas de place pour l'interprétation ou l'action humaine. Face à la crise et au vol d'ethers, que fallait-il faire ? En schématisant, il y avait deux positions : les principiels voulaient qu'on laisse les choses se produire. The DAO avait une bogue, ils perdent leur argent. Selon eux, toute autre solution aurait mis en cause ce qui était justement l'un des principaux arguments en faveur des contrats, leur côté automatique, insensibles aux passions et aux manipulations humaines. Les réalistes, de l'autre côté, considéraient qu'on ne pouvait pas rester sans rien faire et voir le voleur emporter l'argent. Ils prônent un fork, c'est-à-dire une scission délibérée de la chaîne : une nouvelle version des logiciels est produite, appliquant des règles différentes (par exemple empêchant les transferts depuis le compte du voleur). Certains nœuds du réseau adoptent le fork, d'autres pas. Si les premiers sont plus nombreux, leur chaîne est considérée comme la bonne, les autres n'ont plus qu'à se soumettre, ou à partir et faire leur chaîne de leur côté (ce qui serait évidemment une grosse tuile pour Ethereum). Vu superficiellement, cela serait une décision centrale dans un système, la chaîne de blocs, conçu justement pour éviter cela. Mais si une telle décision peut en effet être prise par un petit groupe de gens (en gros, les développeurs des logiciels qui font marcher la chaîne ; notez que, contrairement à Bitcoin, il n'existe pas qu'un seul logiciel), sa mise en œuvre, elle, dépend de tous les gens qui gèrent des nœuds (enfin, surtout des mineurs), et qu'il faut convaincre. C'est pour cela que les articles de Buterin, par exemple, insistent sur le fait que les développeurs comme lui n'imposent pas, ils proposent. Une attitude tout à fait opposée était celle de de Stephan Tual qui, dans ce tweet et celui-ci accusait tout opposant (ceux qui refusent le fork, les principiels), d'être forcément en cheville avec le voleur, et appelait même à les dénoncer ! Ce délire robespierro-stalinien a certainement fait bien plus de mal à Ethereum que la bogue elle-même.
Un des éléments du débat était aussi le statut particulier de The DAO. Pourquoi forker juste pour eux, disent les principiels ? Fera-t-on pareil à chaque fois qu'un contrat a une bogue ? Le seul argument des réalistes est la taille : The DAO est « too big to fail ». Après que tant de gens, aussi bien à l'intérieur de la communauté Ethereum qu'à l'extérieur, aient entretenu une certaine confusion entre Ethereum et The DAO, il est difficile de laisser tomber le canard boiteux. Même si cela a mené à des injustices flagrantes, comme l'appel lancé par Slock.it à faire une attaque par déni de service contre toute la chaîne Ethereum, pour ralentir l'attaquant (cette boîte a fait une bogue, et la fait payer à tout le monde).
Cette crise pose donc évidemment la question de ce mode de gouvernance « le code [des contrats] est la seule règle ». Thibault Verbiest a ainsi estimé que ce n'était pas souhaitable et qu'il fallait une régulation étatique des chaînes de blocs.
Les habituels ricaneurs ont évidemment proclamé qu'ils avaient bien raison, et que la chaîne de blocs était fichue, et que cela les faisait bien rigoler (manger le popcorn en regardant le film est évidemment plus facile que de travailler). Mais on est loin d'une telle conclusion. Si The DAO ne survivra probablement pas à cette crise, l'idée de contrat, les autres contrats et Ethereum lui-même sont bien vivants et continueront, une fois la crise actuelle digérée. Les contrats sont une innovation et, comme toute innovation, les débuts sont un peu cahotiques. Lors des débuts de l'aviation, le projet le plus sérieux, celui qui avait de très loin le plus gros budget et la plus grande attention des médias était celui de Langley. Le 8 décembre 1903, son projet se termine après un nouveau crash, qui mène beaucoup de gens à affirmer que l'aviation est morte. Une semaine après, le premier avion des frères Wright décolle avec succès... Matthew Spoke estime même que cette attaque est une bonne chose, elle va forcer à être plus sérieux.
PS : j'ai oublié d'en parler initialement, mais voici la déclaration de conflit d'intérêt. Je ne possède pas (et n'ai jamais possédé) de tokens (de parts) de The DAO.
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : C. Contavalli, W. van der Gaast
(Google), D. Lawrence (Akamai
Technologies), W. Kumari (Google)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 20 juin 2016
Dernière mise à jour le 13 juin 2022
Ce nouveau RFC décrit une option EDNS qui permet à un client DNS d'indiquer au serveur l'adresse IP d'origine de la requête DNS. Pourquoi diable ferait-on cela, au prix de la vie privée ? Cette option est surtout utile dans le cas de l'utilisation d'un gros résolveur DNS public (comme Google Public DNS) et d'un CDN.
Pour comprendre pourquoi, il faut se rappeler que le
DNS ne fonctionne pas de bout en bout. La
machine de M. Michu émet des requêtes DNS à un
résolveur (en général fourni par le
FAI ou par le réseau local, mais certaines
personnes, victimes du marketing, préfèrent les résolveurs publics
comme OpenDNS, plus lointains et plus
lents). Ce résolveur, à son tour, interroge les serveurs
faisant autorité. Si M. Michu voulait se connecter à un
site Web pour voir des vidéos de chats, il est possible qu'un nouvel
acteur soit présent, le CDN (comme
Akamai) qui héberge les
dites vidéos. Les serveurs DNS faisant autorité pour le CDN
renvoient souvent une adresse IP différente selon l'adresse IP du
résolveur qui les interroge. Si l'adresse IP du client est au
Sénégal, l'adresse IP du serveur de vidéos
qui sera renvoyée sera celle du centre de
données le plus « proche » du Sénégal. En temps normal,
cela fonctionne plus ou moins. Bien sûr, le serveur DNS faisant
autorité pour le CDN ne voit pas le « vrai » client, M. Michu, il
voit le résolveur DNS utilisé mais les deux sont proches : si
M. Michu est en Colombie, son résolveur DNS le sera aussi. Voici un
exemple, vu avec les sondes RIPE Atlas, où on
demande, au Sénégal (SN) puis en Colombie (CO) l'adresse IP de www.elysee.fr
, hébergé
sur un CDN états-unien :
% blaeu-resolve --country SN www.elysee.fr [207.123.59.254 209.84.7.126 8.27.7.254] : 1 occurrences [209.84.7.126 8.253.3.254 8.27.7.254] : 1 occurrences [4.26.233.254 4.26.236.126 8.254.119.126] : 1 occurrences [207.123.59.254 209.84.7.126 8.253.3.254] : 1 occurrences [207.123.59.254 8.26.223.254 8.27.7.254] : 1 occurrences Test #4106632 done at 2016-06-15T22:52:44Z % blaeu-resolve --country CO www.elysee.fr [192.221.116.253] : 3 occurrences [205.128.71.253 4.27.25.125 8.27.155.126] : 1 occurrences [206.33.52.253 209.84.20.126 8.253.16.126] : 1 occurrences Test #4106633 done at 2016-06-15T22:52:46Z
On voit qu'on a obtenu des adresses IP très différentes et, espérons-le, adaptées à chaque pays.
Autre exemple, avec un service de PowerDNS, qui renvoyait (il semble ne plus marcher) une géolocalisation du client. Ici, j'utilise dig depuis deux machines différentes, une en France et l'autre aux États-Unis :
% dig +short -t txt www.geo.powerdns.com "bonjour france 2a01:db8:8bd9:85cb:21e:8cff:fe76:29b6/26" % dig +short -t txt www.geo.powerdns.com "hello USA 204.62.14.153/22"
On voit que le résolveur que j'utilise (qui, à chaque fois, était sur le réseau local de la machine cliente), a bien été géolocalisé. Si j'utilise un résolveur public :
% dig @8.8.8.8 +short -t txt www.geo.powerdns.com "bonjour france XX.YY.152.0/11"
Ici, cela a marché car Google Public DNS a des serveurs en France. Si cela n'avait pas été le cas, j'aurais été géolocalisé... quelque part ailleurs.
Tout change (section 1 du RFC) si on utilise un résolveur DNS public comme Verisign Public DNS ou bien Yandex DNS. Dans ce cas, l'adresse IP du résolveur, vue par le serveur faisant autorité pour le CDN, n'a plus grand'chose à voir avec celle du vrai client, elle peut être très lointaine. Les serveurs DNS faisant autorité risquent donc de renvoyer une adresse IP de serveur Web qui ne soit pas optimale. Certes, tout marchera quand même mais ça sera plus lent alors qu'officiellement, le but des CDN est d'accélerer l'arrivée de la vidéo du chat (non, de François Hollande).
On voit que ce RFC résout donc un problème que n'a pas tout le monde. Seuls ceux qui se servent d'un résolveur public lointain, et qui visitent des sites Web hébergés sur un CDN (en général les gros sites commerciaux) auront le problème. C'est une des raisons qui expliquent que ce RFC a pas mal trainé (voyez cet article, qui date de plusieurs années) à l'IETF : son intérêt n'est pas évident, et il y avait beaucoup de contestation. Mais l'IETF a finalement choisi de documenter cette option (qui est effectivement déployée), sans forcément la recommander.
Donc, comment est-ce que cela résout le problème décrit plus
haut ? L'idée est de standardiser une option EDNS que les résolveurs
publics ajouteront dans leur requête aux serveurs faisant autorité,
et qui indiquera la « vraie » adresse IP d'origine (section 5 du RFC). Imaginons que
M. Michu ait pour adresse IP 192.0.2.56
et
qu'il utilise Google Public DNS. Ce dernier va transmettre la
requête au CDN et ajoutera l'option Client
Subnet (ce n'est donc pas M. Michu qui le fera). Le serveur DNS du CDN verra
une requête arriver de, mettons,
74.125.17.1
. L'option EDNS Client
Subnet contiendra le préfixe de l'adresse IP de M. Michu,
192.0.2.0/25
. Il saura alors qu'il doit adapter
ses réponses, non pas au préfixe 74.125.17.0/24
(son client direct) mais au préfixe
192.0.2.0/25
(le vrai client). C'est donc une
option entre résolveur et serveur faisant autorité, pas entre
machine terminale et résolveur.
Le format de l'option est décrite dans la section 6 du RFC. Comme toutes les options EDNS (RFC 6891), elle est encodée en TLV : le type est 8, la valeur est composée de :
192.0.2.0
dans
l'exemple plus haut).La section 7 du RFC décrit les détails du protocole. Le résolveur va mettre dans son cache les réponses du serveur faisant autorité. Normalement, l'information dans le cache est indexée par le nom de domaine (et le type de données demandé, mais je simplifie). Avec ECS (EDNS Client Subnet), l'information est indexée par le couple {nom de domaine, préfixe IP}. En effet, deux requêtes pour le même nom peuvent avoir donné des résultats différents selon le préfixe IP (c'est bien le but !).
Le résolveur qui met cette option doit choisir la longueur du préfixe envoyé. Il tient compte de deux choses :
Mais l'affaire est un peu plus compliquée : le client d'origine (la machine de M. Michu, le stub resolver) a pu mettre une option ECS elle-même (ce n'est pas courant aujourd'hui mais ça pourrait arriver). Dans ce cas, le résolveur doit en tenir compte et mettre comme longueur la plus courte entre celle demandée par le client (a priori pour protéger sa vie privée) et celle que le résolveur aurait choisi tout seul.
Si la requête reçue par le résolveur avait l'option ECS et une longueur de zéro, cela indique le souhait du client qu'on ne transmette pas son adresse IP du tout. Le résolveur doit évidemment respecter cette demande.
Et le serveur faisant autorité, que doit-il mettre dans sa réponse ? (S'il envoie des réponses différentes selon la source, et s'il gère l'option ECS, EDNS Client Subnet ; autrement, c'est simple, il ne fait rien de particulier.) Il met une option ECS dans la réponses, avec :
(Notez que le RFC est bien plus détaillé que ce résumé, car il y a plein de cas rigolos. Je me suis limité à une présentation générale, je n'essaie pas de traduire tout le RFC.)
En recevant cette réponse, le résolveur va la mettre dans son
cache, en tenant compte de la longueur du préfixe (et, bien sûr,
le résolveur transmet la réponse à son client). Une réponse
valable pour 2001:db8:43:bef::/64
ne pourra
pas être utilisée pour le client
2001:db8:43:bed::1
. Quelle longueur sera
utilisée pour indexer le cache ? Celle demandée ou bien celle
effective ? Les régles exactes sont un peu complexes (il faut
tenir compte de la longueur effective, mais aussi des limites du
cache, qui ne veut pas stocker une réponse pour des préfixes trop spécifiques), je vous
renvoie à la section 7.3.1 du RFC.
Les questions ultérieures des clients du résolveur pourront
recevoir une réponse tirée du cache, sans repasser par les
serveurs faisant autorité. Mais ECS impose d'organiser le cache
différemment. Avec le DNS classique, si on a dans le cache la
réponse à une question pour cat.example.com
(je simplifie en ne tenant pas compte du type des données DNS),
et qu'on reçoit une question pour ce nom, on peut répondre avec
les données du cache. Avec ECS, le cache doit en plus tenir compte
du préfixe stocké avec la réponse, et de l'adresse IP du
client.
Et avec DNSSEC, ça se passe comment (section 9 du RFC) ? Les CDN ne signent pas leur zone en général. Mais s'ils s'y mettent (il le faudrait), il y aura quelques précautions à prendre.
Et avec le NAT ? Il n'y a normalement pas de problèmes, sauf évidemment si le résolveur est NATé et ne le sait pas : il mettrait, dans ce cas, une adresse privée dans l'option ECS, ce qui serait idiot.
Reste à regarder les problèmes de sécurité et notamment de vie privée. ECS diminue forcément votre vie privée. Il ajoute en effet une information qui n'était pas là sans lui (et le RFC 8165 dit bien que c'est mal). C'est pour limiter les dégâts que le RFC recommande aux résolveurs qui ajoutent une option Client Subnet de la limiter aux 24 premiers bits en IPv4 et aux 56 premiers en IPv6. Un résolveur qui connait bien la topologie de son réseau peut faire encore mieux : s'il sait que tous ses clients sont proches, et couverts par le même /20, il peut ainsi ne transmettre que les vingt premiers bits, sans diminuer l'intérêt du service.
Notez que, avec les clients DNS d'aujourd'hui, votre résolveur mettra votre adresse IP dans ses requêtes sortantes. On peut en sortir (opt-out en mettant une option ECS avec une longueur nulle) mais cela nécessite une action explicite (que ne permettent pas forcément les clients DNS actuels, notamment les stub resolvers, ceux qui sont intégrés dans le système d'exploitation). Le RFC recommande donc que cette option ECS soit désactivée par défaut, en raison de ces risques.
L'option ECS peut être vue par les serveurs faisant autorité, mais également par les tiers qui espionnent le trafic. Pour empêcher cela, il faudra déployer des solutions de chiffrement du trafic DNS, comme celles sur lesquelles travaille le groupe DPRIVE.
Un bon article sur les problèmes de vie privée liés à ECS est le « Understanding the Privacy Implications of ECS » de Panagiotis Kintis, Yacin Nadji, David Dagon, Michael Farrell et Manos Antonakakis. Un autre bon article sur cette question est celui de Frank Denis.
Voyons maintenant cette option ECS en action. Elle est par exemple utilisée par Google dont le résolveur public ajoute cette option avant de l'envoyer aux serveurs faisant autorité. Mais on trouve une liste d'utilisateurs plus détaillée sur le site de promotion de la technologie.
Parmi les logiciels libres qui la mettent en œuvre, on note la
bibliothèque getdns. Ou
bien le programme dig livré avec
BIND. Voici un exemple avec la nouvelle
option +subnet
de dig (prise sur un BIND
9.11, l'option était déjà en 9.10) :
% dig +subnet=8.189.152.0/25 @ns-1568.awsdns-04.co.uk A www.amazon.com ... ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; CLIENT-SUBNET: 8.189.152.0/25/0 ... ;; ANSWER SECTION: www.amazon.com. 60 IN A 54.239.25.192 ...
Et ce que voit le serveur faisant autorité ? On peut le savoir
en faisant tourner tcpdump sur un serveur
faisant autorité qu'on contrôle, mais il y a plus simple, utiliser
un domaine dont les serveurs faisant autorité renverront
l'information ECS qu'ils ont reçu. J'en connais trois, qui
répondent aux requêtes DNS de type TXT
:
_country.pool.ntp.org
,whoami.fastly.net
et
whoami6.fastly.net
,ecs.dyn.bortzmeyer.fr
(qui
utilise le logiciel Drink).Voici un exemple :
% dig ecs.dyn.bortzmeyer.fr TXT ... ;; ANSWER SECTION: ecs.dyn.bortzmeyer.fr. 0 IN TXT "78.196.62.0/24" ;; Query time: 15 msec ;; SERVER: 8.8.8.8#53(8.8.8.8) ;; WHEN: lun. juin 13 14:08:23 CEST 2022
Un service analogue, edns-client-sub.net
renvoie sous
forme d'un objet JSON les options ECS reçues, ainsi que la
géolocalisation. Ici, mon résolveur n'envoie pas ECS :
% dig +short -t txt edns-client-sub.net "{'ecs':'False','ts':'1447875683.94','recursive':{'cc':'FR','srcip':'XX.YY.152.187','sport':'37512'}}"
Mais Google, lui, le fait (et heureusement, sinon j'aurais été géolocalisé en Belgique, où se trouve le serveur de Google utilisé) :
% dig @8.8.8.8 +short -t txt edns-client-sub.net "{'ecs_payload':{'family':'1','optcode':'0x08','cc':'FR','ip':'XX.YY.152.0','mask':'24','scope':'0'}, 'ecs':'True','ts':'1447875689.25','recursive':{'cc':'BE','srcip':'74.125.47.152','sport':'41735'}}"
Mais ce service ne semble plus fonctionner, en juin 2022.
Enfin, voici un exemple de code Python qui coupe ECS chez le résolveur, pour protéger la vie privée de l'utilisateur. Il utilise la bibliothèque dnspython :
opt = dns.edns.ECSOption(address='', srclen=0) # Disable ECS (RFC 7871, section 7.1.2) options = [opt] message = dns.message.make_query(qname, dns.rdatatype.from_text(qtype), use_edns=True, options=options)
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : S. Krishnan (Ericsson), T. Mrugalski
(ISC), S. Jiang (Huawei
Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF dhc
Première rédaction de cet article le 12 juin 2016
Le protocole DHCP sert à transmettre à une machine qui vient de se connecter au réseau, des informations utiles pour sa connexion. Il est surtout connu pour son utilisation avec IPv4 mais DHCP existe aussi pour IPv6 (il est normalisé dans le RFC 8415). Comme son équivalent IPv4, DHCP pour IPv6 pose un certain nombre de problèmes de vie privée, que ce RFC explore.
Il fait donc partie de la série de RFC développés après le RFC 6973 et, surtout, après les révélations de Snowden qui ont mené l'IETF à s'engager plus vigoureusement contre la surveillance massive. Ce RFC ne propose pas de solutions (elles sont décrites dans le RFC 7844), il décrit le problème.
Le problème fondamental est le même qu'en IPv4 (RFC 7819) : le client DHCP, lorsqu'il vient de se connecter à un réseau et émet des requêtes, publie des informations trop détaillées, dont certaines sont des véritables identificateurs stables (cf. section 2 de notre RFC), permettant au serveur DHCP, mais aussi à toute machine qui écoute le réseau, de suivre à la trace une machine donnée. Au contraire des solutions comme SLAAC, où le client est purement passif, DHCP impose au client d'annoncer son existence et de donner des informations. Bref, si vous avez déjà lu le RFC équivalent pour IPv4, le RFC 7819, vous n'apprendrez pas grand'chose de nouveau.
La section 3 du RFC donne une liste aussi complète que possible
des options DHCPv6 qui peuvent servir à la surveillance. D'abord,
l'adresse IP source. Bon, elle ne fait pas partie
de DHCP à proprement parler et tout protocole va la publier,
puisqu'elle apparait dans tous les paquets émis. (Dans le cas
de DHCP, la requête du client est émise depuis une adresse locale
au lien, link-local, celles qui commencent par
fe80::
.) Néanmoins, l'adresse IP source
mérite une mention car certains mécanismes de génération d'une
adresse IPv6 peuvent poser des problèmes de vie privée (cf. RFC 7721). Il faut
donc utiliser des mécanismes comme ceux du RFC 8981 ou du RFC 7217.
L'exemple suivant est celui d'une option particulièrement dangereuse pour la vie privée, Client Identifier, qui envoie au serveur le DUID (DHCPv6 Unique Identifier, RFC 8415, section 11) du client. Comme son nom l'indique, il identifie chaque machine de manière unique et, par défaut, il est stable. La méthode la plus courante pour le générer est d'utiliser l'adresse MAC, elle-même un identificateur unique et stable. Même si on prend la précaution de changer l'adresse MAC, le DUID ne change pas. C'est donc un excellent moyen de suivre une machine, cassant complètement la sécurité de techniques comme celle du RFC 8981.
Certaines options peuvent être moins clairement indiscrètes mais peuvent néanmoins révéler indirectement l'identité du client. C'est le cas de l'option Option Request qui dit au serveur quelles options on souhaiterait qu'il utilise. Cette liste de choix peut servir à distinguer entre plusieurs clients DHCP : toutes les fois où il y a un choix dans un protocole, il y a une possibilité de fingerprinting.
Certaines options n'envoient pas directement un identificateur unique mais envoient de l'information sur une classe à laquelle appartient la machine. Par exemple, les options Vendor Class et Vendor-specific Information (sections 21.16 et 21.17 du RFC 8415), ou encore l'option Client System Architecture (RFC 5970), indiquent le matériel et le logiciel du client.
On n'a vu ici que des options allant du client vers le serveur mais l'inverse existe aussi, et certaines options qu'un serveur peut envoyer sont révélatrices (par exemple Civic Location, RFC 4776). Mais les problèmes de vie privée du serveur sont moins graves que ceux du client et notre RFC passe donc rapidement (voir aussi la section 5.3).
En dehors des options DHCP, certains mécanismes utilisés dans le cadre de DHCP peuvent être bien indiscrets. C'est par exemple le cas de la demande d'adresses temporaires (RFC 8415, section 6.5), pourtant bien intentionnée. Le but était de pouvoir obtenir des adresses qui ne soient pas stables, pour minimiser justement les risques pour la vie privée. Le RFC détaille les nombreux problèmes et pièges que récèle ce mécanisme. Mais le principal problème est que la seule demande de ces adresses, visible par tout surveillant, est déjà très révélatrice ! Cela revient à sa promener avec une cagoule sur sa tête pour préserver sa vie privée.
Autre mécanisme qui peut être révélateur, la mise à jour du DNS que font certains serveurs DHCP. Si le nom utilisé est stable (cf. l'option Client FQDN mentionnée plus haut), tout surveillant ayant accès au DNS (c'est-à-dire tout le monde) pourra suivre les changements d'adresse IP de la machine, connaissant ainsi ses déplacements d'un réseau à l'autre.
Les stratégies d'allocation d'adresses du serveur DHCP peuvent également être dangereuses pour la vie privée. Le serveur DHCP dispose d'une certaine plage d'adresses. S'il alloue les adresses en commençant toujours par la plus basse adresse libre, les adresses attribuées vont être assez prévisibles, ce qui n'est en général pas bon pour la discrétion. (Et ce mécanisme, qui a certes l'avantage d'être simple et rapide, tend à concentrer les adresses allouées au début de la plage.) Autre possibilité, allouer des adresses fixes (le même client - identifié par une option comme Client Identifier - a toujours la même adresse IP). C'est évidemment très pratique pour l'administrateur du réseau local. Mais c'est la pire solution pour la vie privée, puisque cela oblige le client à divulguer son identité, et cela permet même aux serveurs extérieurs de le suivre à la trace lorsqu'il communique avec eux avec son adresse fixe. Pour la vie privée, la meilleure stratégie d'allocation est sans doute le tirage au sort parmi les adresses libres de la plage.
Maintenant qu'on a vu les vulnérabilités de DHCPv6, voyons ce qu'un attaquant peut en faire (section 5 du RFC). D'abord, il peut découvrir le type de machine chez le client (matériel et/ou logiciel), ce qui peut être utile, par exemple pour sélectionner une attaque spécifique à un système d'exploitation, ou bien, si le matériel/logiciel utilisé est rare, pour identifier un client particulier. Cette information sur le type de machine peut être trouvé dans l'adresse MAC (les premiers octets identifient le vendeur), dans les identificateurs dérivés de l'adresse MAC, ou dans les options comme Vendor Class.
L'espion peut également utiliser ces faiblesses de DHCPv6 pour identifier les réseaux visités précédemment (je n'en ai pas parlé plus haut, mais il existe une option qui indique la précédente adresse IP utilisée : elle est pratique pour obtenir une adresse stable, mais elle est indiscrète).
Plus généralement, le surveillant peut essayer de découvrir une identité stable, lui permettant de savoir combien de machines utilisent ce serveur DHCP, et lui permettant également de corréler deux machines sur deux réseaux, découvrant qu'il s'agit en fait de la même. Le DUID est particulièrement sensible ici.
Le surveillant peut ainsi suivre une machine, soit dans le temps (toutes ses activités en un réseau donné), soit dans l'espace (suivre à la trace un engin mobile).
Si le surveillant a les moyens d'une agence d'un État riche
(par exemple si le surveillant est la NSA),
il peut effectuer une surveillance massive très efficace (RFC 7258). Il est par exemple conceptuellement
aisé de bâtir une liste de très nombreuses machines, en observant
beaucoup de réseaux : les failles de sécurité de DHCPv6 citées
dans ce RFC permettront de reconnaitre chaque machine
individuelle. Ainsi, un organisme comme la NSA peut se faire une
base de données permettant de répondre très vite à des questions
du genre « où était 38:59:f9:7d:b6:47
la
dernière fois qu'on l'a vu ? »
Enfin, la section 6 de notre RFC rappelle une triste réalité : en sécurité, il faut en général faire des compromis. Ici, le RFC note que toute authentification du client va à l'encontre du souhait de préserver la vie privée. Ce genre de choix (sécurité de son réseau, ou bien vie privée des utilisateurs) est bien embêtant pour l'administrateur système.
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : Donald Eastlake (Huawei), Mark
Andrews (ISC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 10 juin 2016
La grande majorité des requêtes DNS passent aujourd'hui sur UDP. Ce protocole ne fournit aucun mécanisme permettant de vérifier un tant soit peu l'adresse IP source de la requête. Contrairement à ce qui arrive avec TCP, il est trivial de mentir sur l'adresse IP source, sans être détecté. Cela permet des comportements négatifs, comme les attaques par réflexion. Ce nouveau RFC propose un mécanisme simple et léger pour s'assurer de l'adresse IP source du client : des petits gâteaux, les cookies.
Le principe est le même que pour les cookies de HTTP (décrits dans le RFC 6265) : le serveur DNS génère un nombre imprévisible qu'il transmet au client. Celui-ci renvoie ce nombre à chaque requête, prouvant qu'il recevait bien les réponses, et n'avait donc pas triché sur son adresse IP. (Notez une grosse différence avec les cookies du Web : ils changent quand l'adresse IP du client change et ils ne peuvent donc pas être utilisés pour suivre à la trace un client mobile.)
Bien sûr, une autre solution serait d'utiliser TCP (comme proposé dans le RFC 7766) ou bien DTLS (RFC en cours de discussion). Mais les petits gâteaux se veulent une solution moins radicale, de déploiement peut-être plus facile. Ils ne sont pas forcément utilisés seuls, ils peuvent être combinés avec d'autres mesures anti-usurpation, comme celles du RFC 5452.
Comme avec toute technique de sécurité, il faut regarder en détail les menaces auxquelles elle répond (section 2 du RFC). En usurpant l'adresse IP source, un méchant peut effectuer des attaques par déni de service, et il peut empoisonner un cache. Voyons ces deux cas.
D'abord, l'attaque par déni de service : en usurpant l'adresse IP source, on peut effectuer une attaque par réflexion. Dans ces attaques, le méchant envoie un paquet à un tiers, le réflecteur, en mentant sur son adresse IP source : le méchant met celle de la victime. Lorsque le réflecteur répondra, il enverra un message à la victime. Cette attaque est surtout intéressante lorsqu'elle est combinée avec l'amplification. Si la réponse est plus grosse que la question (ce qui est en général le cas avec le DNS), le méchant aura frappé la victime avec davantage d'octets que ce qu'il a lui-même envoyé.
Avec les cookies, cette attaque ne serait pas possible, la réponse à une requête ayant un cookie erroné étant plus petite que la question.
Notez que les cookies ne protègent pas contre un attaquant situé sur le chemin (on-path attacker) et qui peut lire le trafic réseau : voyant les paquets, il verra le cookie et pourra le transmettre. Les cookies n'empêchent donc pas toutes les attaques. D'autre part, si l'attaquant matraque directement le serveur DNS (sans réflexion), les cookies n'empêcheront pas l'attaque mais ils permettent de s'assurer que l'adresse IP source est exacte, ce qui autorisera de remonter à la source de l'attaque.
Le déni de service peut aussi viser le serveur DNS (au lieu de simplement l'utiliser comme réflecteur dans une attaque par réflexion). Chaque requête DNS va donner du travail au serveur et un nombre excessif peut dépasser ses capacités (comme dans l'attaque dafa888). Le problème est surtout aigu pour les serveurs récursifs, qui ont nettement plus à faire lorsqu'une requête arrive. Et ceux qui ont le plus de travail sont les serveurs récursifs qui valident avec DNSSEC : lors de la réception d'une réponse, il faut faire des calculs cryptographiques pour cette validation. Ces attaques par déni de service, au contraire de celles faites par réflexion, n'imposent pas de tricher sur l'adresse IP source mais, en le faisant, l'attaquant a l'avantage de rendre plus difficile son identification. Et cela peut lui permettre de faire traiter des requêtes qui seraient normalement refusées. Par exemple, si un résolveur n'accepte de requêtes que de son réseau (ce qui est la bonne pratique, cf. RFC 5358), et si on a oublié de filtrer en entrée les requêtes prétendant venir du réseau local, une attaque reste possible, en usurpant les adresses IP locales (une telle attaque est décrite dans l'exposé de Lars Nøring).
Après les attaques par déni de service, voyons les attaques visant à faire accepter de fausses réponses, ce qui peut mener à empoisonner le cache. Le principe est de répondre à la place du vrai serveur faisant autorité, en usurpant son adresse IP. Si le méchant est plus rapide, sa réponse peut, dans certains cas, être acceptée par un résolveur (qui la mettra peut-être dans son cache, ce qui sera encore pire). L'attaque Kaminsky est une version améliorée de cette vieille attaque. Les cookies sont une bonne protection contre ce genre d'attaques.
Après les attaques, voyons les défenses. Il n'y a pas que les cookies dans la vie. D'abord, il y a DNSSEC (RFC 4034 et RFC 4035). DNSSEC permet d'authentifier les réponses DNS, résolvant ainsi complètement les attaques par empoisonnement. Par contre, il ne résout pas les attaques par déni de service et, pire, les calculs cryptographiques qu'il impose et la taille des réponses plus élevées peuvent dans certains cas aggraver une partie de ces attaques. (Le RFC ne le note pas, mais DNSSEC a une autre limite, que les cookies résolvent : s'il empêche l'empoisonnement, il ne permet pas pour autant d'obtenir la réponse DNS correcte. DNSSEC protège bien du hameçonnage, beaucoup moins de la censure.)
Autre solution de sécurité, TSIG (RFC 8945). TSIG est meilleur que les cookies dans la mesure où il permet de vérifier cryptographiquement l'identité de la machine avec qui on parle DNS. Mais il est non trivial à déployer : reposant sur de la cryptographie symétrique, il impose un partage des clés préalable. Cela le limite à des usages entre parties qui se connaissent bien (typiquement pour sécuriser les transferts de zone). On note aussi que, comme DNSSEC, mais contrairement aux cookies, il nécessite des horloges synchronisées.
Pour résoudre ce problème de déployabilité, on peut envisager le mécanisme de distribution de clés TKEY (RFC 2930) ou bien passer à de la cryptographie asymétrique avec SIG(0) (RFC 2931). Mais aucune de ces deux techniques n'a connu de déploiement significatif.
Bref, les solutions de sécurité existantes ne résolvent pas réellement les problèmes que veulent traiter les cookies. Mais assez parlé de la « concurrence », venons-en aux cookies, comment marchent-ils (section 4 de notre RFC) ? Les cookies s'appuient sur EDNS (RFC 6891). Ils sont donc une option dans l'enregistrement EDNS. L'option cookie de EDNS porte le numéro 10. Comme toutes les options EDNS, elle est codée en TLV : le type 10, la longueur et la valeur, qui comprend un ou deux cookies. S'il n'y a que le cookie client, la longueur est fixe, de 8 octets. S'il y a en plus le cookie serveur, la longueur peut aller de 16 à 40 octets.
Le cookie client est normalement le résultat d'une fonction non-prévisible des adresses IP du client et du serveur, et d'un secret connu du client (par exemple, généré aléatoirement en suivant le RFC 4086, et changé de temps en temps). Cette fonction est, par exemple, une condensation mais le client prend ce qu'il veut : il est le seul à avoir besoin d'interpréter ses propres cookies, ils sont opaques pour tout autre acteur. L'adresse IP du client est incluse dans les paramètres de la fonction notamment pour des raisons de vie privée : empêcher le client d'être reconnu s'il change d'adresse IP (le but de nos cookies DNS n'est pas du tout le même que celui des fameux cookies du Web).
Le cookie serveur prend comme paramètres de sa propre fonction (qui n'est pas forcément la même) l'adresse IP de son client, un secret (mêmes propriétés que chez le client), et le cookie du client (et pourquoi le cookie client ne se sert pas du cookie serveur ? Voyez la section 6.) Voilà comment on fabrique les gâteaux.
Mais comment les utilise-t-on ? La section 5 l'explique. Le client qui gère les gâteaux fabrique un cookie client qu'il envoie dans ses requêtes DNS. S'il n'a jamais parlé au serveur, il envoie une option cookie de forme courte, ne comprenant qu'un seul cookie, le sien. S'il a déjà parlé au serveur et mémorisé le cookie de celui-ci, il fabrique une option EDNS cookie longue, incluant les deux cookies.
Si le serveur ne comprend rien aux cookies, il ne met pas l'option dans la réponse, et le client sait alors qu'il s'agit d'un vieux serveur, sans gestion des cookies. (Ou bien c'était une attaque par repli ; le cas ne semble pas traité dans le RFC, la solution est sans doute que le client mémorise les serveurs cookie-capable, pour détecter ces attaques.)
Si, par contre, le serveur gère les cookies, il y a cinq possibilités :
FORMERR
(FORmat
ERRor).BADCOOKIE
(valeur 23), incluant le
cookie du serveur, ou enfin de répondre
normalement, en ajoutant son cookie. En
effet, dans ce cas, le client n'est pas « authentifié ». On n'a
pas vérifié son adresse IP source. Il peut donc être justifié
de ne pas donner la réponse tout de suite (le
BADCOOKIE
) ou bien, par exemple, de
limiter le trafic de ce client (comme
on le fait
aujourd'hui, avant les cookies, puisqu'on n'est jamais sûr de l'adresse IP
du client).
Lorsqu'il reçoit une réponse, le client doit mémoriser le
cookie du serveur. C'est particulièrement
important la première fois, lorsque le client n'est pas encore
authentifié. Si la réponse était BADCOOKIE
,
cela veut dire qu'on a affaire à un serveur grognon qui ne veut
pas répondre sans qu'on lui donne un cookie
correct : on retransmet alors la requête, cette fois en incluant
le cookie transmis par le serveur.
Voilà, c'est tout. Avec ce système, on a une authentification légère et simple de l'adresse IP du client. Dans la vraie vie, il y aura peut-être quelques problèmes pratiques, que couvre la section 6 de notre RFC. Par exemple, si le client est derrière du NAT (RFC 3022), un méchant situé sur le même réseau local que lui pourrait faire une requête au serveur, obtenir le cookie du serveur et envoyer ensuite des requêtes en usurpant l'adresse IP locale du client légitime. Le serveur ne peut pas distinguer ces deux clients, le bon et le méchant. C'est pour cela que le cookie serveur inclut dans les paramètres de sa fonction le cookie du client. Ainsi, les deux machines, la gentille et la méchante auront des cookies serveur différents.
Un problème du même genre (plusieurs machines derrière une même adresse IP) pourrait survenir côté serveur, par exemple en raison de l'anycast. Mais on ne peut pas appliquer la même solution : si le cookie serveur dépend du cookie client et le cookie client du cookie serveur, on a une boucle sans fin. Le serveur doit donc se débrouiller : soit avoir le même secret (et donc les mêmes cookies) sur toutes les machines (c'est l'approche la plus simple, et c'est celle recommandée par le RFC), soit faire en sorte qu'un client donné arrive toujours sur la même machine.
D'autres considérations pratiques figurent en section 7, notamment sur le remplacement d'un secret (ce qui invalidera les cookies précédemment distribués).
Et quelques discussions sur la sécurité, pour finir (section 9 du RFC). L'« authentification » fournie par les cookies est faible : elle ne protège pas contre un attaquant situé sur le chemin de communication entre client et serveur, lorsqu'il peut lire le trafic. Dans ce cas, l'attaquant a en effet accès au cookie et peut facilement le rejouer. Par exemple, si on est connecté à un réseau Wi-Fi public sans sécurité (pas de WPA), n'importe quel client du même réseau peut voir passer les cookies. Néanmoins, les cookies réduisent quand même sérieusement l'ampleur du problème. Une attaque (l'usurpation d'adresse IP) que tout l'Internet pouvait faire est maintenant restreinte à un sous-ensemble de l'Internet. Si cela est encore trop, il faut passer à une sécurisation cryptographique comme celle que fournit le RFC 7858.
L'algorithme utilisé pour calculer les cookies est évidemment crucial. Il n'a pas besoin d'être normalisé, puisque seule la machine qui émet le cookie original a besoin de le comprendre. Mais il doit garantir des cookies très difficiles à prévoir par un attaquant. On peut par exemple utiliser SHA-256 (RFC 6234, mais il n'y a pas forcément besoin de cryptographie top canon, les cookies n'étant qu'une authentification faible, de toute façon). Depuis la parution de notre RFC, le RFC 9018 a décrit un algorithme recommandé si des serveurs veulent être compatibles, par exemple s'ils font partie du même service anycast.
Des exemples d'algorithmes figurent dans les annexes A et B (mais le RFC 9018 en a abandonné certains). Pour le client DNS, un algorithme simple serait d'appliquer la fonction simple et rapide FNV-64 à la concaténation des adresses IP du client et du serveur, et du secret. Un algorithme plus compliqué, mais plus sûr, serait de remplacer FNV par SHA-256, plus coûteux.
Pour le serveur, l'algorithme simple serait un FNV-64 de la concaténation de l'adresse IP du client, du cookie du client, et du secret. Pour l'algorithme compliqué, on peut tirer profit de la longueur plus grande du cookie serveur pour y mettre davantage d'informations : par exemple, huit octets calculés comme dans l'algorithme simple suivis de l'heure de génération du cookie (pour détecter plus facilement les vieux cookies, avant même toute opération cryptographique).
Et les mises en œuvre ? Les cookies sont gérés par BIND à partir de la version 9.11 (pas encore officiellement publiée). Ils sont activés par défaut. Et Wireshark sait les afficher. Ici, un client nouveau (il ne connait pas encore le cookie serveur) :
No. Time Source Destination Protocol Length Info 1 0.000000 192.168.2.9 192.168.2.7 DNS 97 Standard query 0x0000 SOA foobar.example OPT ... Domain Name System (query) ... Additional records <Root>: type OPT ... Data length: 12 Option: COOKIE Option Code: COOKIE (10) Option Length: 8 Option Data: fb40ce9a68a6f1f0 Client Cookie: fb40ce9a68a6f1f0 Server Cookie: <MISSING> No. Time Source Destination Protocol Length Info 2 0.003910 192.168.2.7 192.168.2.9 DNS 200 Standard query response 0x0000 SOA foobar.example SOA ns1.foobar.example NS ns1.nic.fr NS ns2.nic.fr OPT ... Additional records <Root>: type OPT ... Data length: 28 Option: COOKIE Option Code: COOKIE (10) Option Length: 24 Option Data: fb40ce9a68a6f1f0727e7501575acc5977ced0351ad20d56 Client Cookie: fb40ce9a68a6f1f0 Server Cookie: 727e7501575acc5977ced0351ad20d56
L'algorithme de condensation peut être choisi mais, apparemment,
uniquement à la compilation (avec
--with-cc-alg=ALG
où
ALG
vaut aes|sha1|sha256
).
Le dig livré avec cette version de BIND peut passer des cookies :
% dig +cookie @192.168.2.7 foobar.example ... ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ; COOKIE: 51648e4b14ad9db8eb0d28c7575acbdde8f541a0cb52e2c2 (good) ;; QUESTION SECTION: ;foobar.example. IN A ...
Pour les programmeurs en Go, la bibliothèque Go DNS gère désormais les cookies. Un exemple de code Go pour les envoyer :
m := new(dns.Msg) m.Question = make([]dns.Question, 1) c := new(dns.Client) m.Question[0] = dns.Question{zone, dns.TypeSOA, dns.ClassINET} o := new(dns.OPT) o.Hdr.Name = "." o.Hdr.Rrtype = dns.TypeOPT o.Hdr.Class = 4096 e := new(dns.EDNS0_COOKIE) e.Code = dns.EDNS0COOKIE e.Cookie = "fb40ce9a68a6f1f0" o.Option = append(o.Option, e) m.Extra = make([]dns.RR, 1) m.Extra[0] = o
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : A. Morton (AT&T Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 30 mai 2016
Dans le monde de la métrologie, il existe deux classes de mesures effectuées sur l'Internet : les mesures actives et les mesures passives. La signification de ces termes semble assez intuitive mais ce nouveau RFC fournit des définitions rigoureuses, qui n'étaient pas encore publiées. (Il y a aussi des mesures hybrides.)
Cela fait pourtant de très nombreuses années que ces deux termes sont largement utilisés. Par exemple, en 2000 s'est tenue une conférence « Passive and Active Measurement (PAM) ». Et les termes étaient certainement plus anciens.
En première approximation, on peut caractériser ces deux classes ainsi (section 1 du RFC) :
Du point de vue des outils, on peut donc noter que les ultra-traditionnels ping et traceroute font des mesures actives et que tcpdump permet des mesures passives.
Mais, les choses étant plus compliquées dans la vraie vie des vrais réseaux, notre RFC va un peu plus loin que cela. Sa section 3 définit plus précisement les termes. Elle s'appuie sur des RFC précédents comme les RFC 2330 et RFC 6390 qui définissaient, par exemple, la notion de métrique (une grandeur qu'on mesure), ou comme le RFC 7011, qui définissait la notion de point d'observation. On s'appuie aussi sur des documents qui ne sont pas des RFC comme la norme UIT Y.1540 qui définit la notion de « population [de paquets] qui nous intéresse » (stream of interest) ou comme la norme UIT Y.1731.
Notez que les adjectifs « actif » et « passif » peuvent s'appliquer aux méthodes de mesure ou bien aux métriques.
Armé de ces définitions, on peut dire que les méthodes de mesure actives ont les caractéristiques suivantes :
Comme la mesure active introduit du trafic réseau qui n'existerait pas sans elle, elle perturbe le réseau qu'on veut mesurer. Un des défis importants des mesures actives est de minimiser cette perturbation ou, au minimum, de pouvoir quantifier cette perturbation pour l'indiquer comme marge d'erreur dans les résultats (section 4.1).
Une métrique active est simplement une métrique dont la définition inclut des méthodes actives. Par exemple, le type des paquets qu'on a injecté dans le réseau.
Les méthodes passives, par contre, ont ces propriétés :
Il faut faire attention en observant les paquets : comme on ne choisit pas leurs caractéristiques, on risque de ne pas voir le vrai phénomène, car on n'observait que le phénomène supposé. (Il m'est arrivé d'utiliser tcpdump pour observer un trafic LDAP et de filtrer sur l'adresse du serveur LDAP. Je ne comprenais pas pourquoi aucun trafic n'était visible. En fait, je ne capturais que les paquets IPv4 alors que le trafic se faisait en IPv6.)
Une observation passive peut se faire en un seul point, ou en plusieurs. Un exemple d'observation passive est ce que fait un routeur IPFIX (RFC 7011).
Une métrique passive est une métrique fondée uniquement sur l'observation passive. Par exemple, le temps de trajet entre deux points peut être formalisée dans une métrique passive : on observe le paquet à un point et à l'autre, et on en déduit le temps de son voyage.
Évidemment, dans le monde réel, les classifications ne sont pas toujours très simples. Par exemple, il existe des méthodes hybrides. Les « hybrides de type I » partent d'un flux de paquets existant mais le modifient, ou bien modifient le traitement qu'il subit. Par exemple, si on observe un flux existant mais qu'on envoie en même temps des données dans le réseau pour le charger, on est en présence d'une méthode hybride de type I. Les métriques spatiales du RFC 5644 sont un cas de métriques hybrides.
Et les hybrides de type II ? Le terme indique les méthodes où il y a plusieurs populations intéressantes générées activement (et d'autres qu'on observe passivement).
La section 4 de notre RFC discute de certains problèmes de métrologie et compare l'effet des méthodes et métriques actives ou passives. Par exemple, si on veut mesurer la capacité d'un lien, une méthode active serait de tenter d'envoyer le plus de données possible, une méthode passive d'observer le trafic et de regarder le débit maximum atteint. La première méthode va remplir le tuyau, gênant les applications en cours. La seconde risque de sous-estimer la capacité (si les machines sont lentes, elles peuvent ne pas réussir à remplir le tuyau.)
Au passage, l'importance des mesures est telle que l'IETF envisage un mécanisme de mesure instrumentant les paquets eux-mêmes : c'est l'option IPv6 PDM (Performance and Diagnostic Measurements, actuellement à l'état de projet), qui consiste à ajouter un nouvel en-tête d'extension aux paquets IP pour y noter les informations nécessaires aux mesures. Les mesures ainsi faites seraient plutôt des hybrides de type I. (On ajoute des données à des paquets existants.)
Première rédaction de cet article le 29 mai 2016
La chaîne de blocs Ethereum permet bien plus que de gérer de l'argent : elle autorise la création de programmes (appelés contrats) qui peuvent être invoqués par des utilisateurs, qui envoient leur argent au contrat, espérant que celui-ci va bien faire ce qui est promis. Mais comment le vérifier ?
Les contrats (le terme marketing est smart contracts) sont des programmes informatiques : dans le cas le plus courant, ils sont écrits par un programmeur dans un langage « de haut niveau » puis compilé dans le langage machine d'Ethereum.
Le contrat, comme son nom l'indique, est censé faire quelque chose. Imaginons par exemple un serveur de clés PGP dans la chaîne de blocs : il est censé recevoir des clés, les stocker, et les restituer à la demande. Les gens qui stockent des clés paient (en ethers) pour cela. Il est légitime de se demander « est-ce que ce programme va bien faire ce qui est prévu, ou bien va-t-il soudainement détruire toutes les clés, et j'aurais alors dépensé mes ethers pour rien ? » C'est d'autant plus critique qu'il existe des contrats qui brassent des sommes d'argent importantes. Les utilisateurs se fient typiquement à la documentation publique de ce contrat, alors qu'on ne peut pas être sûr qu'elle corresponde au contrat réel (soit par suite d'une erreur, soit par suite d'une volonté délibérée). Le code s'exécute dans la chaîne de blocs, sans intervention humaine (c'est le but des smart contracts). Comment valider ce code ? C'est à mon avis le gros problème de ces « contrats intelligents ».
Arrivé à ce stade, mes lecteurs partisans du logiciel libre ont déjà une réponse : on distribue le code source (rappelez-vous qu'un contrat n'est qu'un programme), des gens le liront et le vérifieront. Si suffisamment de gens compétents le lisent, le contrat est vérifié, on peut lui faire confiance. Mais c'est très insuffisant.
Déjà, analyser un code source complexe peut être difficile (on peut espérer que les auteurs de contrats, voulant inspirer confiance, essaieront d'écrire du code clair et lisible). Il est clair que la disponibilité du code source est un pré-requis : s'il n'est pas public, il ne faut jamais envoyer de l'argent à ce contrat. Seulement, ça ne suffit pas : ce qui est stocké et exécuté sur la blockchain, c'est du langage machine d'Ethereum (à peu près du même niveau d'abstraction que le langage des processeurs matériels). Ça, c'est vraiment dur à valider. Pour donner un exemple, voici un contrat très très simple écrit en Solidity, il stocke une valeur et permet de la récupérer :
contract SimpleStorage { uint storedData; function set(uint x) { storedData = x; } function get() constant returns (uint retVal) { return storedData; } }
Il est trivial à analyser et à vérifier. Seulement, ce n'est pas
ça qu'exécute la chaîne de blocs, mais un code machine. Voici sa
version en assembleur, produite par
l'option --asm
du compilateur
solc
: storage.asm
(je ne l'ai
pas incluse dans cet article, elle est trop longue). Mais ce n'est
pas non plus ce que stocke la chaîne de blocs, en fait, on a juste
les opcodes, sans les
jolis commentaires et tout :
% solc --opcodes storage.sol ======= SimpleStorage ======= Opcodes: PUSH1 0x60 PUSH1 0x40 MSTORE PUSH1 0x97 DUP1 PUSH1 0x10 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN PUSH1 0x60 PUSH1 0x40 MSTORE PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x60FE47B1 EQ PUSH1 0x41 JUMPI DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x57 JUMPI PUSH1 0x3F JUMP JUMPDEST STOP JUMPDEST PUSH1 0x55 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH1 0x78 JUMP JUMPDEST STOP JUMPDEST PUSH1 0x62 PUSH1 0x4 DUP1 POP POP PUSH1 0x86 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST DUP1 PUSH1 0x0 PUSH1 0x0 POP DUP2 SWAP1 SSTORE POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 POP SLOAD SWAP1 POP PUSH1 0x94 JUMP JUMPDEST SWAP1 JUMP
À noter que c'était sans l'optimisation. Celle-ci réduit sérieusement le nombre d'instructions :
% solc --opcodes storage.sol |wc -w 137 % solc --opcodes --optimize storage.sol |wc -w 73
Si vous voulez observer ce contrat en ligne, il a été déployé sur
la chaîne de blocs, à l'adresse
0x48b4cb193b587c6f2dab1a9123a7bd5e7d490ced
(et ça m'a coûté 69 558 unités d'essence, payées 0,00139116
ethers). Le résultat est visible sur les explorateurs de la
chaîne, comme etherscan.io,
Etherchain
ou ether.camp. Sur
Etherscan.io, la fonction Switch To Opcodes
View vous permet de passer des instructions en
assembleur au code binaire. Sur Ether.camp, ce sont les liens
code et asm.
Au passage, si vous voulez interagir avec ce contrat (après l'avoir
vérifié !), les instructions en console sont :
storage = eth.contract([{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"type":"function"}]).at("0x48b4cb193b587c6f2dab1a9123a7bd5e7d490ced")
Et cela permet de stocker et de récupérer des valeurs depuis la
console de geth
(cela vous coûtera 26 563 unités d'essence, soit, aujourd'hui, 0,00053126 ether) :
> storage.set(42,{from:eth.accounts[0]}) "0x36084ff3d5bf0235326277b2d5ba30b1964f6d8b3720b9aef0578faeaeb2678b" ... > storage.get() 42
Quittons ce détour technique et revenons à la question de fond, la vérification. Cette préoccupation est relativement fréquente dans le monde Ethereum. Il y a quelques mois, elle ne suscitait guère d'intérêt. Il y a plusieurs solutions pour vérifier un contrat avant de lui confier ses précieux ethers :
Dans le cas de la première méthode, la recompilation, si le binaire obtenu correspond à celui déployé, on est tranquille. Mais s'il ne correspond pas ? Est-ce que cela veut dire que quelqu'un essaie de nous tromper ? Non, car le code obtenu dépend du compilateur, et de sa version exacte. Si le binaire correspond, on est rassuré, s'il ne correspond pas, on n'est pas plus avancé. Et le problème devient plus compliqué avec le temps (certains contrats peuvent être éternels) : comment on retrouve le compilateur utilisé deux ans après ? Il faudrait que le code soit étiqueté avec la version du compilateur, ce qui n'est pas le cas, et qu'on dispose d'une copie de cet ancien compilateur.
Bref, il n'y a pas de solution parfaite aujourd'hui. Lorsque vous mettez de l'argent dans un contrat sérieux, vous avez forcément une incertitude. Vous pouvez la réduire en regardant les vérifications faites par d'autres. Pour The DAO, le code source est en ligne. Il existe une documentation sur cette vérification et des détails. Et le code a été vérifié par certains explorateurs, comme Etherscan.
Et, pour finir, une copie d'écran d'un cas où ça a marché, la vérification du contrat montré plus haut :
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : J. Halpern, L. Daigle, O. Kolkman (Internet Society), Internet Architecture Board (IAB)
Pour information
Première rédaction de cet article le 29 mai 2016
Les textes sacrés de l'Internet, les RFC, comprennent un certain nombre d'éléments obligatoires, souvent collectivement appelés boilerplates et comprenant, par exemple, les conditions légales d'utilisation du RFC. Ce RFC 7841 écrit par l'IAB les décrit et les précise.
Les éléments utilisés autrefois comme Category: Experimental ne suffisaient pas à transporter toute l'information nécessaire. Depuis la formalisation des voies dans le RFC 4844, les différents circuits de publication des RFC, il était devenu crucial de déterminer facilement de quelle voie venait un RFC. (Les anciens RFC étaient tous marqués comme provenant d'un mystérieux Network Working Group, cf. RFC 3.) Cela avait été fait dans le RFC 5741, que notre RFC 7841 remplace.
Donc, dans sa section 2, notre méta-RFC rappelle que, non seulement tous les RFC ne sont pas des normes (RFC 1796), mais que tous ne sont pas des documents issus de l'IETF, qui n'est qu'une voie parmi d'autres (quoique la plus prolifique). Ainsi, un RFC peut très bien être publié sans que l'IETF n'aie pu donner un avis sur des points comme la sécurité ou le contrôle de congestion, par le biais de procédures comme le IETF Last Call ou l'examen par l'IESG. En termes para-légaux, disons que l'IETF refuse toute responsabilité pour les RFC non-IETF. (À noter que, si tous les RFC ne sont pas des normes IETF, en revanche, toutes les normes IETF sont publiées sous forme d'un RFC.) Si vous tenez à tout connaitre sur les processus de l'IETF, et la publication des RFC, consultez les RFC 2026, RFC 8728, RFC 8729, RFC 5742, RFC 6410 et RFC 7127.
La section 3 liste les éléments qui forment la structure d'un RFC. Leur forme exacte, plus susceptible de changer, figure sur une page Web séparée. Il y a l'en-tête général (section 3.1) qui, pour notre RFC, est :
Internet Architecture Board (IAB) J. Halpern, Ed. Request for Comments: 7841 Obsoletes: 5741 L. Daigle, Ed. Updates: 7322 Category: Informational O. Kolkman, Ed. ISSN: 2070-1721 Internet Architecture Board (IAB) April 2016
indiquant qu'il est issu de la voie IAB, qu'il porte le numéro 7841, qu'il est de la catégorie « Pour information » (les catégories sont décrites dans le RFC 2026), etc. Les autres voies sont IETF, IRTF et « contribution indépendante ».
Après cet en-tête vient un paragraphe (section 3.2) qui décrit clairement la voie par laquelle ce RFC est passé. Par exemple, pour une soumission indépendante, le texte (qui est sujet à évolution, en synchronisation avec la définition des voies) actuel est « This is a contribution to the RFC Series, independently of any other RFC stream. The RFC Editor has chosen to publish this document at its discretion and makes no statement about its value for implementation or deployment. ».
Cet en-tête indique également les relations de ce RFC avec d'autres RFC. Par exemple, notre RFC 7841 indique :
Obsoletes: 5741
car il remplace le RFC 5741, qui n'a désormais plus qu'un un intérêt historique.
Je ne reprends pas ici tous les éléments, qui sont décrits dans cette section 3. Notons simplement le copyright, issu des RFC 5378 et RFC 8179, et l'ISSN des RFC, 2070-1721. Pour le reste du RFC, il faut utiliser le guide stylistique du RFC 7322.
Notre RFC ne décrit que les principes gouvernant ce boilerplate. Les détails, qui sont changeants, sont désormais sur une page Web dédiée à l'IAB. C'est l'un des gros changements depuis le RFC 5741. L'annexe A de notre RFC contient l'état initial de ces textes. Ainsi, un RFC de l'IETF sur le chemin des normes commencera par « This is an Internet Standards Track document. This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). »
Outre ce déplacement du texte effectif depuis le RFC (document rigide et stable) vers une page Web, le principal changement depuis le RFC 5741 est l'allègement de certaines règles de présentation, pour tenir compte du projet de réforme du format de publication des RFC (qui, dans le futur, ne seront plus publiés uniquement sous forme de texte brut).
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : C. Huitema (Microsoft), T. Mrugalski
(ISC), S. Krishnan (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dhc
Première rédaction de cet article le 29 mai 2016
Vous vous connectez à un réseau IP, vous obtenez la configuration via un serveur DHCP, mais vous voulez rester relativement anonyme, et vous n'avez pas envie que le serveur, ou que des indiscrets qui écoutent, sachent qui vous êtes ? C'est là que ce RFC est utile en proposant un profil de requête DHCP qui envoie le moins d'informations possibles.
C'est que DHCP, par défaut, est trop bavard. Comme l'expliquent bien les RFC 7819 et RFC 7824, une requête DHCP comporte pas mal de champs et d'options qui peuvent contenir des identificateurs stables, qui permettront au serveur DHCP, ou à des espions qui écoutent le trafic, de reconnaitre une machine. Un exemple d'une telle surveillance est celle effectuée dans les aéroports canadiens mais ce n'est certainement pas la seule. Un des buts de cette surveillance peut être, pour quelqu'un qui peut écouter en plusieurs endroits, de suivre à la trace les utilisateurs en déplacement, en reconnaissant les requêtes spécifiques de leur ordinateur portable ou smartphone. Bien sûr, DHCP n'est pas le seul outil pour faire cela. L'identificateur stable le plus évident est l'adresse MAC, mais c'est aussi le plus connu : les utilisateurs soucieux de leur vie privée prennent souvent des mesures pour la changer de temps en temps. Mais peu de gens pensent aux risques pour la vie privée associés à DHCP. Ceux-ci sont désormais bien établis, et documentés dans les RFC 7819 et RFC 7824.
Mais pourquoi en faire un RFC, une norme ? Après tout, on pourrait se contenter d'attendre que les différents fournisseurs de clients DHCP minimisent les informations envoyées. Le problème est qu'ils risquent de le faire légèrement différemment (certains supprimant une option de la requête que d'autres garderont, par exemple). Cette différence permettra une différenciation des utilisateurs, justement ce qu'on veut éviter (cf. la section 2.4). Au contraire, si tout le monde met en œuvre ce profil standard, tous les clients seront pareils, ce qui protège nettement mieux leur anonymat.
La section 2 de notre RFC détaille certains problèmes concrets. J'ai dit plus haut que l'identificateur le plus évident pour suivre une machine à la trace était l'adresse MAC. En Wi-Fi, n'importe qui peut la voir, même si le réseau utilise le chiffrement, puisqu'elle est dans la partie en clair du paquet. En la corrélant avec d'autres informations qu'on retrouve ailleurs, on peut remonter à l'individu qui utilise la machine en question. Le danger est donc réel.
La contre-mesure évidente est de changer l'adresse MAC, en la remplaçant par une valeur aléatoire, par exemple avec macchanger. Cela a fait d'ailleurs l'objets de tests en grand à la réunion IETF de Honolulu, ainsi que dans d'autres réunions. Il n'y a pas de norme technique décrivant cette « aléatoirisation ». Parmi les choix possibles :
En tout cas, un changement de l'adresse MAC est nécessaire, sinon, le profil DHCP « anonyme » de ce RFC aura une utilité limitée. Mais, inversement, attention à ne pas se contenter de changer un seul identificateur. Si on change d'adresse MAC en gardant tout le reste, la tâche d'un surveillant est trop facile, et il déduira sans problème la nouvelle adresse MAC. Il faut changer l'adresse MAC, l'adresse IP et les identificateurs DHCP en même temps.
Notre RFC mentionne qu'il existe des techniques de plus bas niveau (couche 1) qui peuvent défaire tout le travail de protection de la vie privée. Par exemple, certains récepteurs radio permettent d'identifier des particularités d'un émetteur physique et, en observant le trafic Wi-Fi, on peut ainsi identifier une machine donnée quels que soient ses efforts pour ne pas laisser de traces (cf. « Wireless Device Identification with Radiometric Signatures »). Heureusement, tous les surveillants n'ont pas les moyens de placer ce genre de récepteurs. S'ils doivent se contenter de capter le trafic, sans pouvoir analyser le signal physique, les précautions recommandées plus loin dans ce RFC vont suffire.
Le profil d'« anonymat » décrit dans ce RFC n'est pas explicite. On ne peut pas distinguer les clients DHCP qui appliquent ce profil de ceux qui n'ont simplement pas mis en œuvre les options trop révélatrices. Il y avait eu une discussion à l'IETF sur une mention explicite, un bit dans la requête disant « je veux être anonyme et ne vous étonnez donc pas si je ne publie pas grand'chose ». Cette idée avait été rejetée avec l'idée que proclamer publiquement qu'on veut être anonyme peut être au contraire un excellent moyen de se distinguer, comme de sortir dans la rue avec un masque de Guy Fawkes. Au contraire, le vrai anonymat s'obtient en ne faisant rien de trop extraordinaire.
Enfin, comme toute mesure de sécurité, celles qui préservent la vie privée ont des inconvénients. La plus évidente est que l'« anonymat » va rendre plus difficile la gestion des réseaux. Si l'administrateur réseaux suit les machines sur le réseau local en les identifiant par leurs adresses MAC, il devra s'adapter. D'autre part, il y a un conflit entre la protection de la vie privée, qui requiert des changements fréquents d'adresse MAC, et le bon fonctionnement du réseau, qui demande qu'on limite le trafic DHCP (mais aussi ARP et NDP). Attention donc à ne pas changer d'adresse MAC « trop souvent ».
Autre inconvénient, le changement de l'identificateur DHCP par le client, s'il permet davantage de vie privée, empêchera d'obtenir des paramètres de connexion stables (comme l'adresse IP, cf. RFC 7618) dans le temps. On n'a rien sans rien !
Et la vie privée du serveur DHCP, on en parle ? On ne s'est préoccupé jusqu'à présent que du client. C'est parce que le RFC considère que c'est le client qui est aujourd'hui suivi à la trace, et c'est son cas qui nécessite des solutions urgentes. Pour le serveur, cela peut attendre (par exemple parce qu'un serveur qui veut être discret peut ne répondre qu'aux clients authentifiés au niveau 2).
Bien, assez de préliminaires, voyons maintenant le profil proposé. D'abord, pour IPv4 (section 3). Donc, le client qui veut minimiser la surveillance doit donc :
DHCPDISCOVER
,
mettre les options « identificateur de client » et « paramètres
demandés » mais rien d'autre. (Voir comme contre-exemple cette
bogue
de Tails.)DHCPREQUEST
,
ajouter éventuellement la demande d'une adresse IP précise.L'option « identificateur de client » (Client Identifier, RFC 2132, code 61) est, comme son nom l'indique, dangereuse pour la vie privée. Elle permet un suivi très efficace d'une machine, précisement ce qu'on voudrait empêcher. Ne pas la mettre n'est pas une solution car tous les clients DHCP l'incluent. Ne pas le faire serait se singulariser (voir la remarque sur Guy Fawkes plus haut). Notre RFC demande donc qu'on envoie cette option mais qu'on lui donne comme valeur l'adresse MAC (qui est déjà dans l'en-tête couche 2 du paquet). Cela contredit le RFC 4361, section 6.1, mais ce changement de politique reflète l'accent désormais mis sur la préservation de la vie privée. Si on n'a pas d'adresse MAC (cas de certaines liaisons point à point), on doit tirer au hasard (après avoir lu le RFC 4086 et la section 5 du RFC 7217) un identificateur.
Et l'autre option acceptable, la liste des paramètres demandés (Parameter Request List, RFC 2132, code 55) ? La liste doit être réduite au minimum, et ordonnée au hasard, pour éviter qu'on reconnaisse le type de client DHCP utilisé.
L'adresse MAC est indispensable, on ne peut pas ne pas la mettre dans le paquet, et, donc, il ne sert à rien de l'omettre du champ correspondant dans la requête DHCP, mais il est recommandé de la changer (et que le client DHCP utilise cette adresse dans son paquet, qu'il ne garde surtout pas l'ancienne).
Le champ « adresse IP du client » ne pose guère de problème de vie privée (puisque la même adresse IP figure dans l'en-tête IP du paquet) sauf si le client est nouveau sur ce réseau, l'adresse IP indiquée étant alors celle du précédent réseau. Donc : pensez à effacer l'adresse IP lorsque le matériel signale qu'on vient de changer de réseau. Pour la même raison, le profil anonyme ne comprend pas l'option « adresse IP souhaitée » (RFC 2132, code 50). Elle est certes bien pratique (permettant de conserver son adresse IP) mais très révélatrice.
Parmi les autres options, le nom de la machine (code 12) est très
révélateur. Même si ce n'est pas un FQDN, il
peut être très spécifique
(« pc-de-jean-dupont
»). Il ne doit pas être
utilisé dans ce profil. Si on doit quand même le faire, le nom doit
être choisi aléatoirement. Une méthode possible est de
condenser un secret et l'adresse MAC, puis
prendre la représentation en hexadécimal de six premiers octets
(quelque chose comme echo -n "$SECRET" "$MACADDRESS" |
sha256sum | cut -c 1-12
en shell Unix).
L'option Client FQDN (RFC 4702, code 81) est évidemment également à proscrire. Ou alors, il faut l'« anonymiser » avec la même méthode qu'au paragraphe précédent.
Le RFC 4578 décrit une option UUID, prévue pour PXE, et identifiant de manière unique un client DHCP. Normalement, on n'utilise PXE que dans des environnements contrôlés et sécurisés. Dans un cyber-café inconnu, télécharger son système d'exploitation serait une très mauvaise idée. Il ne faut donc utiliser cette option que dans un réseau que l'on sait sûr.
Enfin, les options indiquant le type de logiciel utilisé (comme Vendor Specific Information, code 43, ou Vendor Class, code 60 sont évidemment à rejeter.
Pour éviter le fingerprinting, le client ne devrait pas ajouter d'autres options, mêmes si celles-ci sont inoffensives du point de vue de la vie privée. En effet, si certains clients mettent telle option, quel que soit son contenu, ils diffusent une information. Et, si on envoie des options DHCP, leur ordre doit être tiré au hasard avant l'envoi, là encore, pour éviter de révéler le type de client utilisé (DHCP permet pas mal de choix, et le choix facilite le fingerprinting). Si on n'a pas de bon générateur de nombres aléatoires, un repli possible est d'envoyer toujours les options dans l'ordre de leur code : ainsi, tous les logiciels (qui sont dans ce cas) feront pareil.
La section 4 du RFC fait la même chose, mais pour IPv6. DHCP v6 a d'autres possibilités (comme l'existence de deux modes, avec ou sans état). Le profil est donc un peu plus compliqué mais bien des conseils sont identiques (par exemple ceux sur les options Client FQDN, sections 3.8 et 4.9), et je ne les répéterai donc pas ici. Dans le mode sans état, les clients configurent l'adresse avec d'autres mécanismes, comme le SLAAC et ne se servent de DHCP que pour récupérer des informations générales. Le choix entre les deux modes dépend d'options publiées dans les Router Advertisement (RFC 4861, section 4.2, les bits M et O).
Parmi les messages spécifiques à DHCP v6,
Confirm
(RFC 8415,
section 16.5) est dangereux, car il contient de
l'information sur le précédent réseau où on s'est connecté. En mode
« anonyme », il ne faut pas l'envoyer, sauf si on est certains qu'on
est toujours sur le même réseau (ce qui est une vérification pas
toujours triviale, le RFC recommande d'utiliser
802.1X).
L'option Client Identifier (code 1) en DHCP v6 contient un identificateur unique, le DUID (DHCP Unique Identifier, RFC 8415, section 11). Elle rend donc le suivi d'un client très facile. Pour empêcher ce suivi, le profil demande d'utiliser le format 3, « adresse MAC », du DUID (RFC 8415, section 11.4), avec une adresses MAC changée comme indiquée plus haut. Dans les cas où cette option n'est pas exigée par le protocole (comme les Information-Request, RFC 8415, section 18.2.6, qui sont sans état), elle ne doit pas être envoyée.
DHCP v6 permet évidemment d'obtenir des adresses IPv6 (mais ce n'est pas le seul moyen, contrairement à ce qui se passe en IPv4). Une option semble intéressante pour la vie privée, la demande d'adresses temporaires (RFC 8415, section 13.2). Mais elle n'est pas si utile que ça : car peu de serveurs la mettent en œuvre (le client ne peut donc pas se reposer dessus), le renouvellement de ces adresses n'est pas spécifié, et le fait que le client doive la demander est déjà une fuite d'informations (« je veux être anonyme »). Elle est donc déconseillée.
Notre RFC met également en garde contre des options qui peuvent être amusantes mais qui sont rares : les utiliser revient, pour le client DHCP, à « sortir du lot ». C'est le cas par exemple de la demande de délégation de préfixe (RFC 8415), que le PC typique n'utilise pas.
Le RFC se termine par quelques considérations opérationnelles (section 5). La plus évidente, et la plus « gênante » est que l'application de ce profil va cache l'identité du client au serveur DHCP. C'est le but. Mais cela peut être ennuyeux. Des fonctions comme la publication de l'adresses du client dans le DNS, ou comme la relative stabilité des adresses IP (redonner la même adresse lorsqu'un client revient) ne seront plus possibles. On n'a rien sans rien.
D'autre part, les clients utilisant ce profil consommeront davantage de ressources. Par exemple, à chaque changement au niveau 2, ils réclameront une nouvelle adresse IP, alors que l'ancienne reste réservée, jusqu'à la fin du bail.
Et certains serveurs DHCP fascistes ne donnent une adresse IP qu'aux clients connus, interdisant ainsi l'anonymat. Pour ces raisons, le RFC recommande aux programmeurs de permettre la configuration du client DHCP, configuration allant jusqu'à permettre de débrayer l'anonymisation.
Ce profil a été mis en œuvre dans un client Microsoft, ce qui a donné lieu à un compte-rendu d'expérience à une réunion IETF.
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : Z. Hu, L. Zhu, J. Heidemann
(USC/Information Sciences Institute), A. Mankin, D. Wessels (Verisign
Labs), P. Hoffman (ICANN)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dprive
Première rédaction de cet article le 18 mai 2016
Traditionnellement, les requêtes DNS voyageaient sur le réseau en clair, visibles par tous. Ce n'est évidemment plus acceptable, notamment depuis les révélations de Snowden, et ce RFC normalise donc un mécanisme, DoT (DNS over TLS) qui permet de chiffrer les requêtes DNS pour en assurer la confidentialité vis-à-vis d'un éventuel surveillant.
Le chiffrement est le deuxième pilier de la protection des données, après la minimisation des données (qui, pour le DNS, est spécifiée dans le RFC 9156). Ce chiffrement est motivé notamment par le développement de la surveillance de masse (RFC 7258), par le souci de protéger la vie privée (RFC 6973) et par la prise de conscience des risques spécifiques au DNS (RFC 7626).
Il y avait plusieurs choix possibles pour le groupe de travail DPRIVE qui a produit ce RFC. Il pouvait utiliser une technique extérieure à l'IETF comme DNSCrypt. Il pouvait s'appuyer sur un protocole existant comme IPsec ou TLS. Et il pouvait développer un nouveau protocole (plusieurs propositions avaient été faites en ce sens). Finalement, le choix s'est porté sur un protocole facile à déployer, bien connu, et éprouvé, TLS. D'où le surnom de DoT (DNS over TLS) pour ce protocole. Pour résumer techniquement ce RFC (section 1) : on met les requêtes DNS sur un canal TLS lui-même évidemment transporté sur TCP. (Le groupe DPRIVE travaille également sur une future solution utilisant DTLS et donc UDP.) Outre la confidentialité, TLS permet de protéger les données contre une modification en cours de route.
Notons au passage que DNSSEC ne résout pas ces problèmes : son but est d'authentifier les réponses, pas de protéger contre l'espionnage.
Il y a deux liens à protéger dans une requête DNS, celui entre la machine de l'utilisateur et le résolveur, et celui entre le résolveur et les serveurs faisant autorité. La charte du groupe DPRIVE précisait qu'il fallait d'abord s'attaquer au premier problème, plus facile (une machine ne parle qu'à peu de résolveurs, et elle a une relation avec eux, alors qu'un résolveur parle à beaucoup de serveurs faisant autorité, qu'il ne connait pas.)
La section 3 décrit la gestion des connexions TLS. TLS tourne sur TCP (un de ses copains, DTLS, tourne sur UDP), et il faut donc utiliser ce protocole (notez que l'évolution récente du DNS fait de plus en plus de place à TCP, cf. RFC 7766). DNS-sur-TLS tourne sur un port fixe, le port 853 (les premières versions de ce protocole utilisaient un protocole de négociation de TLS, comme pour SMTP mais, trop compliqué et trop dangereux, il a été abandonné). Le serveur DNS-sur-TLS écoute donc sur le port 853, le client se connecte à ce port, et démarre tout de suite une session TLS (RFC 5246). Ensuite, il y fait circuler le DNS, encodé comme sur TCP (le message DNS précédé de deux octets indiquant sa taille, cf. RFC 1035, section 4.2.2). Comme pour tout usage de DNS sur TCP (RFC 7766), le client et le serveur ne doivent évidemment pas couper la connexion après une seule requête. S'ils le faisaient, les performances seraient catastrophiques, vu le temps qu'il faut pour établir la connexion TCP et la session TLS. Au contraire, la session doit être réutilisée (section 3.4) pour les requêtes ultérieures (et le RFC demande aussi qu'un serveur traite les requêtes en parallèle, pas séquentiellement dans leur ordre d'arrivée, section 3.3.) Un autre moyen de gagner du temps lors de l'établissement d'une nouvelle connexion TCP, moyen recommandé par notre RFC, est d'utiliser TCP Fast Open (RFC 7413).
Notez bien la règle : jamais de contenu chiffré sur le port 53, jamais de contenu en clair sur le port 853. Si le serveur ne répond pas aux requêtes sur le port 853, cela peut être parce qu'une affreuse middlebox bloque tout le trafic vers le port 853, ou tout simplement parce que ce résolveur ne gère pas encore DNS sur TLS. Le client doit alors décider, selon sa politique de sécurité, s'il se rabat sur du trafic DNS en clair ou bien s'il renonce à communiquer. Le RFC recommande que le client se souvienne des serveurs qui répondent sur le port 853, pour détecter un filtrage récemment apparu.
À noter aussi que je n'ai pas parlé encore d'authentification du serveur. Comment être sûr qu'on parle bien au serveur à qui on veut parler et pas au terrible Homme du Milieu ? Pour l'instant, gardez la question de côté, on y reviendra.
Dit comme cela, c'est peut-être un peu compliqué, mais l'un des gros avantages du choix de TLS est qu'il existe déjà des bibliothèques toutes faites pour ce protocole. Ajouter TLS à un client ou un serveur existant est donc relativement simple. (Plus simple que la gestion du RFC 7766, qui est un pré-requis pour DNS-sur-TLS.)
Revenons à l'authentification. A priori, elle est indispensable. Si on n'authentifie pas, on risque d'envoyer ses requêtes DNS à un serveur qui n'est pas le bon, et, dans ce cas, le chiffrement n'aura servi à rien. Pour se faire passer pour le bon serveur DNS, les attaquants actifs ont bien des moyens à leur disposition, comme d'injecter des fausses routes, comme en Turquie. Un chiffrement sans authentification ne protégerait que contre des attaquants strictement passifs.
Oui, mais l'authentification, c'est difficile. Il y a plein de pièges, de problèmes possibles, et d'argent à dépenser (par exemple pour acheter un certificat). Imposer dès le début une authentification stricte dans tous les cas aurait tué le projet dans l'œuf. Le choix a donc été de prévoir un certain nombre de profils d'authentification, que le client choisit, en fonction du degré de sécurité souhaité. (Le serveur, lui, n'authentifie pas le client, en tout cas aucun mécanisme n'est prévu pour cela.) Notre RFC propose deux profils d'authentification (section 4), et d'autres ont décrits par la suite dans le RFC 8310.
Le premier profil est celui « opportuniste » (opportunistic privacy). Le client DNS qui utilise ce profil va tenter de chiffrer, il peut même essayer d'authentifier mais, si cela échoue, il continue quand même à envoyer des requêtes DNS, se disant qu'il est au moins protégé contre les attaques passives.
Le second profil est celui de l'« épinglage de clé »
(out-of-band key-pinned »). La clé publique (SPKI
pour Subject Public Key Info) du
serveur DNS est connue du client (par un mécanisme non spécifié dans
ce RFC), et il ne se connecte à un serveur
DNS-sur-TLS que s'il utilise une des clés correspondant à son
adresse. C'est un mécanisme analogue à l'épinglage
HTTP du RFC 7469. Une
syntaxe possible, pour un /etc/resolv.conf
sur
Unix serait, par exemple (l'annexe A propose
une autre syntaxe) :
domain example.net nameserver 2001:db8:90e:241a::1 NjAwZGI5YTVhMzBiY2EzOWY1OTY5YzM0ZGYzMTllYTVkNmYxNjAwYjJmNzZhOGFhYTNhMDEyMzU4MTIwNjNkMwo=
Où le dernier champ est le condensat de la clé publique.
Au passage, si vous voulez trouver le condensat de votre clé, vous
pouvez le faire avec gnutls-cli
(cela dépend de
comment est fait l'échange de clés) ou bien, si le certificat est dans
le fichier tmp.pem
, avec cette commande utilisant
OpenSSL :
openssl x509 -pubkey -in tmp.pem | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
Ce mécanisme est sûr, empêchant toute attaque de l'Homme du Milieu. Il est peut-être même trop sûr, par exemple pour les réseaux qui utilisent ces horribles portails captifs qui font des attaques de l'Homme du Milieu pour vous rediriger vers le portail. Il peut donc être préférable de ne pas activer ce profil avant de s'être authentifié auprès du portail. (dnssec-trigger utilise un mécanisme analogue.)
J'ai déjà parlé des performances au moment de l'établissement de la connexion, et des problèmes de latence qui peuvent survenir en raison de l'utilisation de TCP et de TLS. La section 5 revient sur ces histoires (il est également recommandé de lire le rapport « T-DNS: Connection-Oriented DNS to Improve Privacy and Security »). Évidemment, une connexion TCP plus une requête DNS, c'est plus coûteux qu'une requête DNS tout court. La requête et la réponse DNS nécessitent deux voyages entre client et serveur, l'etablissement de la connexion TCP en nécessite trois à lui seul, et TLS deux de plus. On pourrait en déduire que DNS-sur-TLS-sur-TCP aura une latence plus élevée de 250 %. On peut réduire ce coût avec des trucs TCP qui réduisent le temps d'établissement de la connexion, comme le TCP Fast Open du RFC 7413 et avec des trucs TLS comme la reprise de session du RFC 5077. Mais, de toute façon, ce calcul n'est vrai que si on établit une connexion TCP par requête DNS, ce qui n'est pas conseillé, la bonne méthode étant au contraire, dans l'esprit du RFC 7766, de réutiliser les connexions.
D'autre part, TCP nécessite de stocker un état dans le serveur. Pour éviter que beaucoup de clients n'écroulent celui-ci, il faut donc ajuster les délais d'inactivité, pour couper les connexions TCP inutilisées.
La section 7 de notre RFC intéressera les ingénieurs qui se
demandent pourquoi les choses sont comme elles sont et pourquoi un
autre choix n'a pas été fait. Elle est consacrée à l'évolution de la
solution de chiffrement du DNS, au sein du groupe de travail
DPRIVE. Comme indiqué plus haut, le premier projet prévoyait de tout
faire passer sur le port 53, avec un passage en TLS à la demande du
client, lorsqu'il envoyait une requête DNS « bidon » avec un nouveau
bit EDNS, TO
(TLS OK), mis à un, et avec le QNAME
(Query NAME) STARTTLS
(reprenant un mot-clé utilisé par SMTP, dans
le RFC 3207).
Cette méthode avait des avantages : elle permettait par exemple à un serveur d'accepter TLS quand il n'était pas trop chargé, et de le refuser autrement. Et, réutilisant le port existant, elle ne nécessitait pas de changer les ACL sur les pare-feux. Mais elle avait aussi des inconvénients : les affreuses middleboxes ont une longue habitude d'interférence avec EDNS et il n'était pas du tout sûr qu'elles laissent passer le bit TO. Et puis, même si le RFC ne le mentionne pas, il y avait un risque qu'une middlebox trop zélée ne fasse du DPI sur le port 53, s'aperçoive que ce qui passe n'est pas du DNS, et coupe la communication. Mais le principal problème de cette approche était qu'elle rendait les attaques par repli triviales. Un attaquant actif n'avait qu'à supprimer le bit TO et le client n'avait alors plus aucun moyen de savoir si l'absence de TLS était due à un serveur trop ancien, à une middlebox boguée... ou bien à une attaque par repli.
Une proposition alternative amusante avait été de mêler le trafic chiffré et non chiffré sur le port 53 sans signalisation : la structure de l'en-tête TLS est telle qu'une machine interprétant le TLS comme étant du DNS en clair aurait vu une réponse DNS (bit QR à 1) et il n'y aurait donc pas eu de confusion avec le trafic DNS en clair. Astucieux mais évidemment très fragile.
La section 8 de notre RFC synthétise les questions de sécurité. D'abord, TLS n'est évidemment pas une formule magique. Il y a eu plein d'attaques contre TLS (par exemple pour forcer un repli vers des algorithmes de chiffrement faibles), ou contre ses mises en œuvre (on pense évidemment tout de suite à OpenSSL). Pour éviter cela, outre le respect des bonnes pratiques TLS (RFC 7525), le client prudent tâchera de se souvenir quels serveurs acceptaient DNS-sur-TLS. Si un serveur qui l'acceptait ne répond tout à coup plus sur le port 853, c'est peut-être qu'un attaquant tente de forcer un repli sur le port 53, en clair. Le client prudent peut ainsi détecter une attaque possible. Si c'est un nouveau serveur, que le client ne connait pas, la marche à suivre dépend de la politique du client (sécurisé ou laxiste).
Quant aux attaques non-TLS (comme le blocage du port 853 mentionné ci-dessus), c'est également au client, en fonction de son profil de sécurité, de décider ce qu'il va faire (renoncer à communiquer, essayer un mécanisme de résolution alternatif, s'en foutre et tout passer en clair, etc).
Revenons à TLS pour noter que ce protocole ne fait pas d'effort pour dissimuler la taille des paquets. Un attaquant passif peut donc, en observant cette taille, et d'autres informations comme le temps écoulé entre deux paquets, en déduire certaines informations, malgré le chiffrement. L'option de remplissage du RFC 7830 permet de remplir les paquets avec des données bidons, afin de rendre cette analyse plus difficile.
Pour un bilan d'étape du projet « DNS et vie privée » à l'IETF, vous pouvez regarder mon exposé State of the "DNS privacy" project: running code à l'OARC.
Question mises en œuvre de ce RFC, où en est-on ? Aujourd'hui, le résolveur Unbound a le code nécessaire depuis longtemps (depuis la version 1.4.14). On peut génerer les clés nécessaires avec OpenSSL ainsi :
openssl req -x509 -newkey rsa:4096 \ -keyout privatekeyfile.key -out publiccertfile.pem \ -days 1000 -nodes
et configurer le serveur ainsi :
server: interface: 2001:db8:1::dead:beef@853 ssl-service-key: "/etc/unbound/privatekeyfile.key" ssl-service-pem: "/etc/unbound/publiccertfile.pem" ssl-port: 853
Unbound va alors activer DNS sur TLS au démarrage et annoncer fièrement « setup TCP for SSL [sic] service ». Les clients pourront alors l'interroger en DNS sur TLS.
Bon, mais quel client utiliser ? Dans la bibliothèque getdns, le logiciel d'exemple
getdns_query
sait faire du DNS sur TLS :
% ./getdns_query @2001:db8:1::dead:beef -s -a -A -l L www.bortzmeyer.org ... Response code was: GOOD. Status was: At least one response was returned
(C'est l'option -l L
qui lui indique de faire du TLS.)
Si on capture le trafic entre getdns_query
et Unbound, on peut afficher le résultat avec
tshark :
% tshark -n -d tcp.port==853,ssl -r /tmp/dnstls.pcap 4 0.002996 2001:db8:1::63a:671 -> 2001:db8:1::dead:beef SSL Client Hello 6 0.594206 2001:db8:1::dead:beef -> 2001:db8:1::63a:671 TLSv1.2 Server Hello, Certificate, Server Key Exchange, Server Hello Done 8 0.734094 2001:db8:1::63a:671 -> 2001:db8:1::dead:beef TLSv1.2 Client Key Exchange 16 0.751614 2001:db8:1::dead:beef -> 2001:db8:1::63a:671 TLSv1.2 Application Data 17 0.759223 2001:db8:1::63a:671 -> 2001:db8:1::dead:beef TLSv1.2 Application Data
On voit un trafic TLS classique, chiffré. Notez que tshark, par défaut, ne sait pas que c'est du TLS sur le
port 853 (cela sera fait lors de la prochaine version majeure). On lui indique donc explicitement (-d
tcp.port==853,ssl
).
Et si j'ai la flemme d'installer un Unbound configuré pour TLS,
est-ce que je peux quand même tester un client DNS-sur-TLS ? Oui, si
les serveurs de test publics listés en
veulent bien répondre.https://portal.sinodun.com/wiki/display/TDNS/DNS-over-TLS+test+servers
Question client, vous avez aussi le démon Stubby. Vous le lancez en indiquant le résolveur à qui il va tout relayer en DNS-sur-TLS :
% sudo stubby @145.100.185.16 -L
Et vous pouvez alors l'utiliser comme résolveur (il écoute par
défaut sur 127.0.0.1
.)
Et vous pouvez aussi utiliser Unbound comme client ! Par rapport à Stubby, il a l'avantage d'être un vrai résolveur, validant et avec un cache, et l'inconvénient de ne pas savoir authentifier le résolveur auquel il va parler. Pour configurer Unbound en client DNS-sur-TLS (et non plus en serveur comme dans l'exemple précédent) :
server: ... ssl-upstream: yes forward-zone: name: "." forward-addr: 2001:4b98:dc2:43:216:3eff:fea9:41a@853 forward-first: no
Si vous préférez développer en Go, l'excellente bibliothèque GoDNS gère DNS sur TLS (depuis janvier 2016) et vous permet de faire vos propres programmes. Par exemple, ce code Go :
c := new(dns.Client) c.Net = "tcp-tls" if *insecure { c.TLSConfig = new(tls.Config) c.TLSConfig.InsecureSkipVerify = true } in, rtt, err := c.Exchange(m, net.JoinHostPort(myResolver, "853"))
va ouvrir une connexion avec le serveur
myResolver
, sur le port 853, et utiliser TLS. Par
défaut, la bibliothèque TLS de Go vérifie le certificat, et que le nom
(ou l'adresse IP) dans le certificat correspond bien (ce qui est la
bonne approche). Mais cela peut être embêtant si on n'a pas acheté de
certificat. D'où l'option (dangereuse !) pour
débrayer la vérification (les trois lignes qui commencent par
if *insecure
). Voici un exemple d'utilisation (au
fait, le programme est en dns-tls.go
,
-k
active l'option dangereuse) :
% ./dns-tls my-resolver internautique.fr Error in query: x509: certificate signed by unknown authority % ./dns-tls -k my-resolver internautique.fr (time 43051 µs) 2 keys. TC=false
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : S. Krishnan (Ericsson), M. Kuehlewind (ETH Zurich), B. Briscoe (Simula Research Laboratory), C. Ralli (Telefonica)
Expérimental
Réalisé dans le cadre du groupe de travail IETF conex
Première rédaction de cet article le 15 mai 2016
Le mécanisme ConEx, normalisé dans le RFC 7713, permet d'informer les routeurs situés en aval qu'un flot de données se heurte à la congestion. Il y a plusieurs façons d'indiquer cette congestion, et ce RFC le fait par une option dans l'en-tête Destination Options d'IPv6.
En effet, le mécanisme décrit dans le RFC 7713 est abstrait : il spécifie des concepts, pas comment ils sont représentés sur le câble. Notre RFC 7837, au contraire, est concret : il indique comment mettre l'information ConEx dans des champs du paquet que les équipements réseau, notamment les routeurs, pourront lire. ConEx est actuellement un projet expérimental (et même très expérimental) et il n'est pas sûr qu'il soit déployé avec enthousiasme. En attendant, puisque c'est expérimental, le but est de récolter de l'information et, pour cela, il faut du code qui tourne, avec des paquets concrets (section 1 de notre RFC). Mettre l'information ConEx dans le champ Options d'IPv4 est délicat : ce champ est de taille limitée, et pose souvent des problèmes dans le réseau. L'idée est donc d'utiliser le protocole du futur, IPv6, et ses en-têtes d'extension (RFC 2460, section 4).
La section 3 détaille les choix techniques effectués et leurs raisons. Les sections 3.3 et 4 du RFC 7713 expliquent les contraintes d'encodage concret de ConEx dans les paquets. Ici, les exigences considérées ont été :
Quatre solutions IPv6 avaient été envisagées par le groupe de travail à l'IETF :
L'en-tête d'extension Hop-by-hop aurait été l'option logique puisqu'elle est examinée par chaque routeur, ce qui est bien ce qu'on veut pour ConEx. Elle aurait été conforme aux principes d'IPv6. Mais, dans les routeurs actuels, le traitement de cette option se fait de manière extrêmement lente (elle n'emprunte pas le chemin rapide dans le routeur, mis en œuvre en ASIC ou FPGA), ce qui viole la troisième exigence. Le choix de l'en-tête Destination, qui est normalement de bout en bout et que les intermédiaires ne sont pas censés regarder, est donc surprenant, mais justifié. Il viole un peu la première exigence (si le paquet est encapsulé, le routeur aura du mal à voir cet en-tête). Et, surtout, analyser la chaîne des en-têtes d'extension IPv6 est anormalement compliqué. Mais il n'y avait guère d'autre choix réaliste. En pratique, certains routeurs auront donc besoin d'un changement de leurs règles de traitement des en-têtes d'extension s'ils veulent voir les marques ConEx.
(Sur la survivabilité des en-têtes d'extension IPv6 dans l'Internet, voir l'étude de Mehdi Kouhen en février 2016 et le RFC 7872.)
La section 4 présente le format concret. La nouvelle option Destination se nomme CDO, pour ConEx Destination Option. Elle est mise dans un en-tête d'extension Destination Options (RFC 2460, section 4.6). Comme les autres options Destination, elle est encodée en TLV. Le type de l'option est 0x1E (30, valeur réservée aux expérimentations, non définitive), sa longueur est 1 (un seul octet, et encore, tous les bits ne sont pas utilisés) et sa valeur est composée de quatre bits (RFC 7713, notamment la section 2.1) : X (« je sais faire du ConEx »), L (« des paquets ont été perdus »), E (« de la congestion a été signalée par ECN ») et C (« pas (encore) de congestion, j'accumule des crédits »). Le dernier bit, C, est à utiliser avant qu'on détecte la congestion (RFC 7713, notamment la section 5.5).
Au passage, si vous écrivez des programmes en C qui veulent ajouter des options dans l'en-tête Destination, vous pouvez consulter mon article.
On a dit plus haut que la principale raison pour utiliser l'en-tête Destination et pas le Hop-by-Hop (qui aurait été plus logique), est le souci que les paquets restent sur le fast path des routeurs (le traitement fait par le matériel, par opposition au slow path, confié au processeur généraliste, bien plus lent). Mais le problème est que l'en-tête Destination, n'étant pas prévu pour être lu par les équipements réseau sur le chemin, peut se trouver n'importe où dans la chaîne des en-têtes (alors que l'en-tête Hop-by-hop est forcément au début, cf. RFC 2460, section 4.1). Et l'option CDO pourrait, en théorie, se trouver n'importe où dans l'en-tête Destination. Notre RFC est donc obligé de recommander (section 5) que l'option CDO soit la première dans l'en-tête Destination.
Reste à voir s'il sera effectivement possible de déployer cette option. L'ossification de l'Internet rend tout déploiement de ce type difficile (les en-têtes d'extension sont rares dans les paquets IPv6 actuels).
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : M. Kuehlewind (ETH
Zurich), R. Scheffenegger (NetApp)
Expérimental
Réalisé dans le cadre du groupe de travail IETF conex
Première rédaction de cet article le 15 mai 2016
C'est après une très longue genèse (ce document avait été adopté par le groupe de travail il y a plus de quatre ans) que voici les protocoles concrets pour la signalisation de la congestion aux routeurs situés en aval. Ici, l'utilisation de ce système avec TCP.
ConEx (pour Congestion Exposure, signalement de la congestion) est décrit dans le RFC 6789. L'idée de base est d'informer le réseau qu'un flot de données rencontre de la congestion, afin que les éléments actifs de ce réseau puissent prendre des décisions intelligentes. ConEx est divisé en une spécification abstraite (RFC 7713) et une ou plusieurs spécifications de protocoles concrets. Ce RFC ne spécifie pas un encodage sur le câble, juste le changement de comportement des mises en œuvre de TCP. (Un autre RFC concret spécifie un encodage pour IPv6, le RFC 7837.)
Il n'y a pas besoin de négociation au début (section 1 du RFC), comme avec les options TCP. Les émetteurs qui connaissent ConEx utilisent les informations existantes (pertes de paquets et ECN, stockées dans deux compteurs différents, cf. la section 3 du RFC).
Pour bien utiliser ConEx, le TCP de l'émetteur a besoin d'informations. Bien qu'il ne soit pas indispensable, c'est mieux si SACK (RFC 2018) est disponible.
La section 2 du RFC résume les modifications chez l'émetteur TCP (le récepteur n'a pas besoin d'être changé pour ConEx). Le comportement de l'émetteur dépendra du fait que le récepteur met en œuvre (ou pas) SACK et ECN. L'émetteur est responsable du marquage des paquets (suivant l'encodage du RFC 7837) avec des signaux ConEx. Il doit tenir compte du nombre d'octets, pas du nombre de paquets (RFC 7141).
En cas de perte de paquets, l'émetteur va mettre le signal ConEx L (loss experienced). Dans certains cas (retransmission inutile parce que le paquet était bien arrivé, c'est l'accusé de réception qui s'était perdu), l'émetteur ne connait pas le nombre exact d'octets perdus. Il peut donc surestimer la congestion dans les signaux ConEx qu'il envoie. Pour avoir de meilleurs mesures, l'émetteur peut toujours mettre en œuvre les RFC 5682, RFC 3708 ou RFC 3522.
Si c'est par des marques ECN, et non pas par des pertes de paquets, que l'émetteur a appris qu'il y avait congestion, il va utiliser les marques ConEx E (ECN experienced).
Dans tous les cas (perte de paquets ou bien ECN), les paquets marqués ConEx devront également porter une marque X, qui indique que l'émetteur sait faire du ConEx (section 4 du RFC).
Un émetteur ConEx est aussi censé envoyer des crédits lorsqu'il n'y a pas de congestion. Ces crédits seront ensuite « consommés » lors des épisodes de congestion. Cela se fait avec le signal C (Credit).
Les paquets contenant les signaux ConEx peuvent se perdre, comme tous les paquets IP (section 5 du RFC). Cela peut mener à des pénalités injustes (un émetteur détecte qu'il y a congestion en aval, le signale avec un L ou un E, le paquet portant le signal est perdu, un routeur qui fait de l'audit ConEx se dit alors « ah, ah, il essaie de tricher, il n'a pas signalé la congestion »). Le problème étant du second ordre (si la probabilité de perdre un paquet est P, la probabilité qu'il y ait perte du paquet et perte du signal est de P au carré), on peut choisir de l'ignorer.
Plus délicat, le problème de la fraîcheur des informations ConEx (section 6 du RFC). Ces informations ne sont utiles que si elles sont très récentes (typiquement moins d'un RTT depuis que la congestion est apparue). L'émetteur doit donc faire attention à ne pas retarder les signaux ConEx. Parfois, il n'a pas trop le choix, par exemple si l'application arrive d'envoyer des données, il n'y aura pas de paquets à marquer.
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : M. Andrews (ISC)
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 13 mai 2016
Il existe un registre des zones
DNS qui doivent être gérées localement par
le résolveur DNS et pour lesquelles les requêtes ne sont pas
transmises aux serveurs de la
racine. Ce nouveau RFC ajoute à
ce registre les zones correspondant au préfixe
IPv4 100.64.0.0/10
,
que le RFC 6598 avait réservé pour la
numérotation des machines situées derrière les
CGN.
Le but de ce registre est d'éviter de surcharger les
serveurs racine avec des requêtes qui sont
inutiles puisque les noms dans ces zones n'ont qu'une
signification locale, et ne pourraient pas recevoir une réponse
sensée de la racine. Le RFC 6303 avait donc
créé ce registre des noms pour lesquels, par défaut, le résolveur
DNS doit retourner NXDOMAIN
(code indiquant
que le nom n'existe pas) tout de suite. On y trouve par exemple la
zone 10.in-addr.arpa
, zone correspondant aux
adresses IP du RFC 1918.
Le RFC 6598 avait réservé tout le préfixe
100.64.0.0/10
pour les
CGN. Notre nouveau
RFC met donc les zones
64.100.in-addr.arpa
à
127.100.in-addr.arpa
dans le
registre des zones à servir localement. Au fur et à mesure
des mises à jour des résolveurs (leur code, ou bien la
configuration locale), toute requête
PTR
dans une de ces
zones doit être traitée localement par le résolveur.
Ces zones sont déléguées aux serveurs de noms de l'IANA, pour attraper les requêtes qui ne suivent pas ces règles :
% dig +short NS 64.100.in-addr.arpa a.iana-servers.net. b.iana-servers.net. c.iana-servers.net.
Sinon, aujourd'hui, par défaut, Unbound
« délègue » ces zones à... localhost
(si on
veut un vrai contenu, il faut configurer explicitement ces
zones) :
% dig +short NS 64.100.in-addr.arpa localhost.
% dig +short NS 64.100.in-addr.arpa 64.100.IN-ADDR.ARPA.
Date de publication du RFC : Mai 2016
Auteur(s) du RFC : A. Mayrhofer (nic.at GmbH)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dprive
Première rédaction de cet article le 11 mai 2016
Ce nouveau RFC fait partie de la série de ceux qui tentent d'améliorer la situation du DNS pour tout ce qui concerne la protection de la vie privée. Parmi les efforts dans ce domaine, il y a une possibilité de chiffrement des communications DNS, dans le RFC 7858 (DNS-sur-TLS). Elle utilise le protocole TLS. Ce dernier ne fait rien pour dissimuler la longueur des requêtes et réponses DNS. Or, de telles métadonnées peuvent suffire à identifier les requêtes faites. Il est donc important de compléter le chiffrement avec un mécanisme de remplissage (padding). C'est ce que permet la nouvelle option EDNS normalisée dans ce RFC.
Trouver la requête effectuée uniquement à partir de la taille de la réponse est d'autant plus facile que les données DNS ne sont pas confidentielles. Un espion qui soupçonne que M. Michu fait des requêtes pour tel nom de domaine peut faire la même requête, noter la taille de la réponse chiffrée, et voir s'il trouve la même taille dans les réponses reçues par M. Michu. Voilà pourquoi il faut ajouter aux requêtes et aux réponses un certain nombre d'octets, pour rendre plus difficile cette analyse des métadonnées.
Ce RFC est court car le mécanisme est très simple (section 3 du RFC). Ce mécanisme utilise une nouvelle option EDNS (EDNS est normalisé dans le RFC 6891.) Cette option porte le numéro 12 et sa partie « données » porte le remplissage. (Comme toute option EDNS, elle est encodée en TLV : un champ indique le type de l'option, ici, 12, un champ indique la longueur de l'option, et le dernier contient les données.)
Que mettre comme remplissage ? Cette question a été la plus discutée lors de la création de ce RFC (qui a été plutôt calme et consensuelle, pour le reste.) Le RFC précise que l'émetteur d'un message DNS devrait remplir avec des octets nuls (0x00). Si l'émetteur craint que certains traitements (par exemple de la compression, voyez cependant la section 6 qui demande de ne pas l'utiliser) appliqués avant le chiffrement ne suppriment l'essentiel du remplissage, il est autorisé à mettre une autre valeur. De toute façon, le récepteur doit accepter n'importe quelle valeur, pour permettre les évolutions futures. En pratique, il doit donc ignorer le contenu des données de cette option.
Pourquoi n'avoir pas simplement dit que l'émetteur pouvait mettre ce qu'il voulait, dans ce cas ? Parce qu'il semblait possible, dans ce cas, que des programmeurs naïfs utilisent de la variable non initialisée, et laissent ainsi fuiter le contenu de leur mémoire (comme dans la faille Heartbleed.) Et pourquoi n'avoir pas spécifié un remplissage avec des données aléatoires ? Parce que ce n'est pas normalement nécessaire : pour un observateur, le contenu chiffré doit apparaitre aléatoire, quel que soit le texte en clair (si TLS ne fournissait pas cette propriété, des tas d'attaques seraient possibles, par exemple à base de texte en clair connu.)
Voilà, l'essentiel du RFC tient dans cette courte section 3. Mais quelques détails suivent. Par exemple, quelle quantité d'octets mettre dans la nouvelle option ? Le RFC ne fournit pas de guide à ce sujet, il rappelle juste qu'il ne faut pas aboutir à des messages plus gros que ce que le client spécifiait dans son champ Payload size EDNS (souvent 4 096 octets mais cela dépend du client.) Des règles plus précises sur la politique de remplissage ont été normalisées par la suite dans le RFC 8467. Le serveur DNS ne doit évidemment pas utiliser cette option si la requête ne contenait pas d'EDNS. Si elle contenait de l'EDNS sans cette option, le serveur est libre de remplir ou pas. Si la requête contenait de l'EDNS avec l'option Padding, alors, le serveur doit effectuer du remplissage.
Quelques trucs à ne pas oublier en section 6 : le remplissage augmente la taille des paquets (évidemment). Cela mènera donc à un accroissement du trafic. Dans l'Internet d'aujourd'hui, où tous les États qui en ont les moyens procèdent à une surveillance massive de leurs citoyens (RFC 7258), c'est un petit prix à payer, pour l'avantage de compliquer le travail des surveillants.
Autre piège, l'option de remplissage ne doit être utilisée que si le trafic DNS est chiffré. Autrement, non seulement elle ne servirait à rien, mais elle augmenterait le risque d'attaques avec amplification.
À noter que, comme plein d'autres champs des messages DNS (comme par exemple le QNAME, le Query Name), cette option peut servir de canal caché. Peut-être verra-t-on un jour une mise en œuvre d'IP-sur-DNS utilisant cette option ?
Notez que cette technique est indépendante du protocole de chiffrement sous-jacent, puisqu'elle est faite au niveau applicatif. DNScrypt pourrait l'utiliser (sauf qu'il a son propre système de remplissage.)
Et les mises en œuvre de cette technique ? A-t-on du code qui tourne ? getdns a le remplissage depuis sa version 0.5.1 (cf. le Changelog.) GoDNS y travaille. Wireshark peut analyser cette option. La page officielle sur cette option de remplissage liste d'autres mises en œuvre.
Depuis la sortie de ce RFC, les clients et serveurs DNS ont peu à peu intégré cette option de remplissage. Voyons ici kdig avec le serveur public de Cloudflare :
% kdig +dnssec +tls +padding @1.1.1.1 A chatons.org ... ;; EDNS PSEUDOSECTION: ;; Version: 0; flags: do; UDP size: 1232 B; ext-rcode: NOERROR ;; PADDING: 301 B
Notez que 1.1.1.1
met du remplissage même si
le client ne l'a pas demandé, ce que permet la section 4 du RFC.
Daniel Kahn Gillmor, qui avait programmé cette extension dans getdns, en a profité pour faire quelques statistiques :
Ethernet Frame sizes for packet containing DNS query Transport | query to | query to used | example.com | www.example.com --------------------------+--------------+------------------- cleartext UDP | 82 octets | 86 octets cleartext TCP | 108 octets | 112 octets TLS over TCP | 137 octets | 141 octets (padded to 512) TLS over TCP | 609 octets | 609 octets
On voit que le remplissage brouille la différence de taille entre les deux requêtes. Mais restons prudents : le remplissage est une bonne technique pour rendre plus difficile l'analyse des métadonnées mais il n'est pas parfait. Lisez par exemple l'excellent « Peek-a-Boo, I Still See You : Why Efficient Traffic Analysis Countermeasures Fail ».
Première rédaction de cet article le 8 mai 2016
Dernière mise à jour le 10 mai 2016
Une tribune sensationnaliste dans le Monde le 6 mai prétendait que « Google [avait] changé l'Internet » et portait une accusation précise : le navigateur Google Chrome utiliserait une racine DNS spécifique à Google. Passons sur le fond politique de l'article, est-ce qu'au moins les faits allégués sont exacts ?
Un petit mot au passage sur ce concept de « racine » (les
explications dans la tribune publiée dans le Monde
sont... floues). Un logiciel qui veut utiliser un nom
de domaine (par exemple un navigateur
Web qui veut aller voir
https://www.laquadrature.net/fr
) va devoir
interroger le DNS, un système technique qui
permet, à partir d'un nom de domaine, d'obtenir des informations
techniques indispensables (comme l'adresse
IP du serveur). Les noms de domaine sont organisés
sous forme d'arbre, avec la racine
représentée en haut (contrairement aux botanistes, les
informaticiens mettent la racine des arbres en haut). L'interrogation du DNS est faite par
un logiciel nommé résolveur, qui est en général indiqué
automatiquement à la machine (c'est la plupart du temps une machine du
FAI, mais on peut utiliser son propre
résolveur). Le résolveur commence par la racine, d'où il est
aiguillé vers les TLD puis de fil en
aiguille vers tous les autres noms de domaine. On voit donc que
qui contrôle la racine contrôle le DNS.
L'article publié dans le Monde dit « le navigateur Chrome de Google
remplace sans avertissement l’annuaire de
l’ICANN par le sien ». Au milieu de toutes les
vagues affirmations de ce texte, voici un fait précis, qu'on peut contrôler. Cela
prend cinq minutes à n'importe quel technicien. Avec un outil d'usage
courant, tcpdump, on peut voir le trafic DNS de
la machine. Lançons Chrome, tentons de visiter
et observons ce trafic. (Les lignes suivantes
sont triviales à interpréter pour le technicien ordinaire dont je
parlais.)
http://nic.la/
11:38:24.549321 IP6 2001:691:1348:7::bad:209.27121 > 2001:67c:217c:6::2.53: 58483% [1au] A? nic.la. (35) 11:38:24.551217 IP6 2001:67c:217c:6::2.53 > 2001:691:1348:7::bad:209.27121: 58483- 0/8/9 (685)
Que voit-on ? La machine d'adresse IP 2001:691:1348:7::bad:209
a fait une requête DNS au serveur
2001:67c:217c:6::2
, qui est bien un
serveur de la racine (leurs adresses IP
sont publiques et connues).
Amusant détail, je n'utilise personnellement pas la « racine ICANN » mais une racine « alternative », Yeti. Donc, même si on a fait un choix différent de la majorité, Chrome respecte ce choix (en fait, Chrome ne parle pas directement à la racine : comme tout bon logiciel, il parle au résolveur configuré par l'utilisateur, et ce résolveur a été configuré pour utiliser telle ou telle racine). Le complot s'effondre donc : le principal reproche fait à Google dans cet article ne repose sur rien. Alors que la vérification des faits prend quelques minutes à n'importe quel technicien, les auteurs de la tribune n'ont pas vérifié, ni demandé à un technicien de le faire.
Est-ce un accident isolé dans une tribune par ailleurs raisonnable ? Non, il y a beaucoup d'autres erreurs techniques. Par exemple, les auteurs affirment « [la racine de Google est] plus rapide puisque souvent délivré d'étapes de contrôle et de surveillance ». Enregistrer les requêtes (comme le fait la NSA) ne ralentit rien, cette affirmation est donc dénuée de sens.
Autre exemple du manque de rigueur de cette tribune, la mention
du .google
comme étant
« la racine de Google » alors qu'il s'agit d'un banal
TLD... Est-ce une distinction importante ou bien
est-ce que je pinaille excessivement ? Oui, c'est important car
cette erreur permet de juger le sérieux d'un texte. Imaginez un
article portant sur la production laitière. L'article confond à un
moment vaches et chèvres. Sans importance, puisqu'après
tout ce sont bien deux mammifères produisant du lait ? Mais si un
article sur ce sujet comportait une telle erreur, lui
accorderait-on la moindre crédibilité ? C'est pareil ici :
confondre TLD et racine, dans un article sur le DNS, est un signe
d'extrême légèreté.
On notera aussi que des affirmations tout aussi fausses (« Cependant Google (et Chrome) utilise leur propre racine (copie de la
racine ICANN) dont une est l’adresse IP 8.8.8.8
»
se trouvent depuis longtemps sur le
serveur Web de la société commerciale Open-Root, pour laquelle
travaillent deux des auteurs. (8.8.8.8
, alias
Google Public DNS, est un
résolveur DNS, qui n'a donc rien à voir avec une racine. Vaches
et chèvres, encore.)
Ces erreurs techniques sont d'autant plus curieuses que, si on
souhaite dire du mal de Google et mettre en
garde contre le pouvoir dont jouit cette société, les exemples ne
manquent pas. Google a un poids important, par sa
part de marché, peut influencer ce que font les internautes, et
ce poids important est certainement une question politique à traiter, comme toutes les
fois où une boîte privée a trop de pouvoir. Alors, pourquoi rajouter
des accusations fantaisistes ? Est-ce parce qu'il y a un risque
que Chrome, un jour, fasse ce qui lui est reproché dans cette
tribune ? Tout est possible mais ce ne serait pas très malin de la
part de Google. En effet, l'utilisation d'une autre racine se voit
(comme montré avec tcpdump plus haut). Ce ne
serait pas très discret de la part de Google (la tribune parle de
« substitution invisible », ce qui n'a pas de sens, vu cette
visibilité du trafic réseau). D'autre part, pas mal d'entreprises
utilisent en interne des TLD non-existants comme
.corp
, qui ne sont connus que de leurs
résolveurs. Si Chrome n'utilisait pas ces résolveurs, ces TLD ne
fonctionneraient pas.
Autre chose frappante, ce texte a largement circulé sur les réseaux sociaux, étant repris sans nuances, sans aucune vérification. On l'a par exemple vu cité sur le site de l'émission Arrêt sur Images. Apparemment, le fait d'être publié dans le Monde a un poids qui suffit à débrayer toute critique. (Alors qu'il s'agissait d'une tribune et pas d'un article, ce qui indique que le Monde n'a pas exercé de contrôle trop serré sur le contenu.)
Depuis, il y a eu une
réponse à ce texte. Elle a été annoncée sur
Twitter en utilisant le
raccourcisseur d'URL de Google
(goo.gl
). Le site d'Open-Root utilise
d'ailleurs le spyware
Google Analytics. Cela indique leur niveau de cohérence (mais
c'est courant chez les souverainistes : de grands discours
anti-GAFA à la tribune, mais l'utilisation de tous leurs outils
en pratique.) Sans compter la paranoïa « nous sommes attaqués de
toute part », de la part de gens qui passent dans le Monde ou à la
télé quand ils veulent, et qui sont invités à tous les colloques ministériels...
Bon, je critique cette réponse sur la forme, mais sur le fond ? Sur le fond, il n'y a rien à dire, parce qu'il n'y a pas d'éléments nouveaux : la réponse cite comme preuve que Google a son propre DNS... l'existence de Google Public DNS. Confondre un résolveur DNS public avec une racine, c'est comme l'expert en élevage cité plus haut qui confondrait vache et chèvre... C'est tellement désespérant que c'est au delà de toute discussion.
Pour les reste, pas de détails, pas de tcpdump montrant Chrome faire des requêtes à la soi-disant racine Google, rien.
First publication of this article on 8 May 2016
Last update on of 9 December 2017
The service Sci-Hub is a great help for
the scientists, allowing them to access to a lot of scientific
papers that were before locked behind paywalls. The publishing companies keep
trying to censor Sci-Hub and block access to this service, for
instance by taking down domain names like it happened a few days ago
with sci-hub.io
. If you control your
DNS resolver, you can easily restore
access.
Sci-Hub's domain sci-hub.io
was recently
taken down. There are several ways to still use Sci-Hub, such as
"domain hopping" (using another TLD such as
sci-hub.bz
) or using
Tor (the address is scihub22266oqcxt.onion
). But there is one which does not
seem to have been publically documented yet.
For the rest of the article, we will rely on a local DNS
resolver. ("local" does not imply it is on your own machine: it may
be on the local network. The important point is that you can
change its configuration.) A local resolver is a great tool
against DNS censorship. By default, it does not see Sci-Hub
domains (NXDOMAIN
means "No Such
Domain"). Let's test with dig:
% dig A sci-hub.io ; <<>> DiG 9.10.4 <<>> A sci-hub.io ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 45356 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1 ... ;; QUESTION SECTION: ;sci-hub.io. IN A ... ;; Query time: 1408 msec ;; SERVER: ::1#53(::1) ...
OK, it failed, the domain being taken down. Let's configure our
local resolver to work around the problem. Sci-Hub has a public name server
that answers to the Sci-Hub domains. First, we'll be using the excellent
program Unbound. We just add in unbound.conf
:
server: domain-insecure: "sci-hub.io" forward-zone: name: "sci-hub.io" forward-addr: 80.82.77.83 forward-addr: 80.82.77.84
and we restart Unbound and it works:
% dig A sci-hub.io ; <<>> DiG 9.10.3-P4-Debian <<>> A sci-hub.io ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22120 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;sci-hub.io. IN A ;; ANSWER SECTION: sci-hub.io. 3483 IN A 80.82.77.83 ;; AUTHORITY SECTION: sci-hub.io. 3483 IN NS ns1.sci-hub.cc. sci-hub.io. 3483 IN NS ns2.sci-hub.cc. ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sun Dec 03 17:51:49 CET 2017 ;; MSG SIZE rcvd: 101
(DNS experts may discuss the use of
forward-zone
instead of
stub-zone
. The Sci-Hub servers accept
recursive requests so both work. In my opinion,
forward may be a bit more future-proof if the
authoritative name server changes its IP address but a recursor
stays in place at the old address.)
With Knot resolver, you just add a rule:
-- Sci-Hub policy.add(policy.suffix(policy.STUB({'80.82.77.83', '80.82.77.84'}), policy.todnames({'sci-hub.io.'})))
to the configuration.
Doing the same with BIND is
possible. Just put in its configuration file (somewhere/named.conf
):
zone "sci-hub.io" { type forward; forwarders {80.82.77.83; 80.82.77.84;}; };
The trick is to use the fact that
80.82.77.83
also allows DNS zone
transfers. You can therefore configure your BIND as a slave for
sci-hub.io
. Once BIND is authoritative for
this domain, it won't check with DNSSEC:
zone "sci-hub.io" { type slave; masters {80.82.77.83; 80.82.77.84;}; };
Note: the option dnssec-must-be-secure
addresses a different issue and is not useful here.
I do not use dnsmasq but Canari
Bleu does and says you have to add
server=/sci-hub.io/80.82.77.83
in dnsmasq.conf
.
Of course, this hack is far from perfect. It doesn't scale (imagine if there were dozens of censored domains to make accessible this way). It's brittle (the IP addresses can change without warning). But this sort of imperfect workarounds will become more and more common with the increase of politically or business-motivated censorship.
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : S. Jiang (Huawei
Technologies), S. Krishnan
(Ericsson), T. Mrugalski (ISC)
Pour information
Réalisé dans le cadre du groupe de travail IETF dhc
Première rédaction de cet article le 3 mai 2016
Le protocole DHCP est bien connu : la grande majorité des machines « client » qui se connectent à l'Internet l'utilisent pour récupérer des éléments de configuration indispensables, comme l'adresse IP à utiliser. Mais peu de gens sont conscients que DHCP peut être dangereux pour la vie privée : le client DHCP n'est en effet pas passif, il envoie au serveur des informations qui peuvent permettre de suivre à la trace une machine mobile.
DHCP pour IPv4 est normalisé dans le RFC 2131. (Le RFC 7824 traite le cas de DHCP pour IPv6, qui pose des problèmes similaires.) Son principe de fonctionnement est simple : le client DHCP (la machine de M. Michu) envoie à la cantonade une requête pour demander des informations de configuration réseau, le serveur DHCP se reconnait, il répond avec ces informations. Voici une transaction DHCP, vue par tcpdump :
21:32:13.284690 IP (tos 0x0, ttl 64, id 960, offset 0, flags [none], proto UDP (17), length 377) 0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from b8:27:eb:84:35:e3, length 349, xid 0x4feaaa6f, Flags [none] (0x0000) Client-Ethernet-Address b8:27:eb:84:35:e3 Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: Request Client-ID Option 61, length 19: hardware-type 255, eb:84:35:e3:00:01:00:01:c7:92:bc:8a:b8:27:eb:ba:90:94 Requested-IP Option 50, length 4: 192.168.2.9 MSZ Option 57, length 2: 1500 Vendor-Class Option 60, length 46: "dhcpcd-6.9.0:Linux-4.4.8-2-ARCH:armv6l:BCM2708" Hostname Option 12, length 5: "amour" T145 Option 145, length 1: 1 Parameter-Request Option 55, length 14: Subnet-Mask, Classless-Static-Route, Static-Route, Default-Gateway Domain-Name-Server, Hostname, Domain-Name, BR NTP, Lease-Time, Server-ID, RN RB, Option 119 END Option 255, length 0 21:32:13.299825 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 576) 192.168.2.254.67 > 192.168.2.9.68: [udp sum ok] BOOTP/DHCP, Reply, length 548, xid 0x4feaaa6f, Flags [none] (0x0000) Your-IP 192.168.2.9 Client-Ethernet-Address b8:27:eb:84:35:e3 Vendor-rfc1048 Extensions Magic Cookie 0x63825363 DHCP-Message Option 53, length 1: ACK Server-ID Option 54, length 4: 192.168.2.254 Lease-Time Option 51, length 4: 43200 Subnet-Mask Option 1, length 4: 255.255.255.0 Default-Gateway Option 3, length 4: 192.168.2.254 Domain-Name-Server Option 6, length 8: 192.168.2.254,149.20.64.21 BR Option 28, length 4: 192.168.2.255 END Option 255, length 0 PAD Option 0, length 0, occurs 264
Malheureusement, dans la requête du client se trouvent plein de détails sur la machine demanderesse (section 1 du RFC). Compte-tenu de la sensibilité aux problèmes de vie privée (RFC 6973) et de l'ampleur de la surveillance de masse exercée par les États (RFC 7258), il était nécessaire de limiter cette fuite d'informations. Ce premier RFC va décrire le problème, et proposer quelques pratiques qui le limitent. Le RFC 7844 détaille un profil DHCP qui limite sérieusement la fuite. Dans une prochaine étape, il y aura peut-être des modifications au protocole DHCP mais ce n'est pas encore fait.
Pour cette analyse de sécurité, la section 2 de notre RFC introduit la notion d'identificateur stable. Un identificateur stable (stable identifier) est une information envoyée par le client DHCP qui change peu ou pas dans le temps (et qui peut donc permettre de tracer une machine mobile). La stabilité peut dépendre de la mise en œuvre logicielle utilisée. Ainsi, une adresse MAC est typiquement un identificateur stable mais, si macchanger est utilisé, ce n'est plus le cas. Un identificateur stable n'est pas forcément mondialement unique.
Le gros de ce RFC est la section 3, qui liste les identificateurs envoyés par le client DHCP. Le plus évident, car il est prévu pour cela, est l'option DHCP Client Identifier (RFC 2131, section 2, et RFC 2132, section 9.14). Il est en général stable (le RFC 1533, prédécesseur du RFC 2132, recommandait même d'utiliser une adresse MAC, mais on voit parfois un nom de domaine, ou bien un DUID - décrit dans le RFC 4361). Même si on utilise un logiciel comme macchanger pour changer d'adresse MAC, pas mal de mises en œuvre de DHCP utiliseront la valeur initiale et la stockeront... pour toujours.
Moins spectaculaire, plusieurs champs de la
requête transportent des identificateurs fondés sur une adresse. C'est le cas de
yiadrr
, qui indique l'adresse IP actuelle du
client ou chaddr
qui indique l'adresse MAC. Plusieurs options font de même comme
la Requested IP Address (qui permet d'indiquer
l'adresse IP qu'on souhaiterait recevoir).
Autre option qui envoie un identificateur stable, et souvent unique, l'option Client FQDN (RFC 4702) qui transmet au serveur le FQDN.
Après les adresses et les noms de domaine, un autre danger se
présente avec les options qui permettent au client d'indiquer le
logiciel qu'il utilise. C'est le cas de l'option Vendor
class (RFC 2132, section 9.13,
une sorte d'équivalent du User-Agent:
de
HTTP,
dans l'exemple plus haut, elle indique une machine
ARM sous Linux), du
Vendor-Identifying du RFC 3925, et de toutes les options
Vendor-specific information (RFC 2132, section 8.4), qui peuvent
indiquer le numéro de version du logiciel utilisé, sa
configuration spécifique, etc. Certes, elles ne
sont pas uniques (elles ne désignent pas une machine particulière)
mais elles font quand même fuiter de l'information sur le client
et, combinées avec d'autres informations, elles peuvent mener à
une identification unique. Une option analogue est Client
System Architecture Type (RFC 4578) qui indique
le type exact d'architecture pour les clients DHCP qui vont
démarrer sur le réseau (par exemple avec PXE), en téléchargeant une version particulière
du système d'exploitation. Si l'architecture utilisée est un peu
rare, cette option donne des informations précieuses à un observateur.
En lisant cette liste, le paranoïaque peut se dire que la NSA a envoyé des gens à l'IETF pour faire normaliser le plus grand nombre possible d'extensions indiscrètes, de façon à être sûr d'identifier tous les clients DHCP observés. Il y a même une option pour indiquer l'adresse (civile, dans le monde physique, pas sur le réseau), Civic Location, dans le RFC 4776. Il est vrai que, contrairement à la plupart des options listées ici, elle est fournie par le serveur et pas par le client, et ne permet donc pas de suivre un client à la trace. Mais elle peut permettre à un observateur de savoir où, dans le monde physique, se situe le client.
Outre tous ces champs et ces options par lesquels une information souvent excessive est transmise, DHCP dispose de certains mécanismes qui peuvent être utilisés pour compromettre la vie privée (section 4 du RFC). Par exemple, l'option Client FQDN du RFC 4702, citée plus haut, sert souvent à faire des mises à jour dynamiques du DNS (RFC 2136), et, dans ce cas, l'adresse IP du client DHCP (qui peut indiquer sa localisation) et son nom, identificateur stable, sont publiés dans le DNS, que tout le monde peut consulter. On peut connaitre les déplacements d'une machine simplement en consultant ce DNS public, sans avoir besoin d'espionner des milliers de réseaux. L'observateur peut être très discret et, en toute légalité, vous suivre.
Autre mécanisme dangereux, la stratégie d'allocation du serveur DHCP. Lorsqu'un client DHCP réclame une adresse IP, le serveur peut la choisir de plusieurs façons, et certaines ont des conséquences pour la vie privée :
La taille très restreinte de l'espace d'adressage IPv4 complique le problème, en limitant les possibilités du serveur d'utiliser certaines stratégies d'allocation, comme l'allocation fondée sur un identificateur (le serveur DHCP n'a pas forcément assez d'adresses IP pour tous ses clients potentiels.)
Bon, OK, le client DHCP envoie des tas d'identificateurs stables. Mais en quoi est-ce dangereux ? Qu'est-ce qu'un observateur indiscret peut en faire (section 5 du RFC) ? Déjà, il peut découvrir le type de machine qu'est le client (directement, via des options comme Vendor Class, ou indirectement, via l'adresse MAC (dont le préfixe, l'OUI, dépend en général du matériel utilisé). L'espion peut aussi trouver le système d'exploitation utilisé.
Il peut aussi apprendre les réseaux que le client avait visité précédemment. Le client met en effet dans l'option Requested IP Address la précédente adresse IP qu'il avait obtenue. Si c'est une adresse publique (pas issue du RFC 1918), cela renseigne sur le précédent réseau utilisé.
L'observateur peut facilement trouver un identificateur stable à partir d'une requête DHCP (en combinant les options comme Client FQDN). Cela lui permet, s'il a accès au trafic de plusieurs serveurs DHCP, de suivre les déplacements d'une machine (c'est ce qui se produit dans les cas de surveillance massive, cf. RFC 7258.)
Dans certains cas, l'observateur n'a même pas besoin d'être présent sur le réseau du serveur DHCP : si on fait des mises à jour dynamiques du DNS, il lui suffit de faire des requêtes DNS pour suivre les changements d'adresse IP (et donc de réseau) du client.
Bref, un client DHCP en dit en général trop à son serveur, et cela permet aux machines mobiles d'être facilement pistées. Notre RFC ne fournit pas de solutions immédiates, une solution est décrite dans le RFC 7844, d'autres feront l'objet d'un futur travail.
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : D. Saucez (INRIA), L. Iannone
(Telecom ParisTech), O. Bonaventure (Université
catholique de Louvain)
Pour information
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 30 avril 2016
Le protocole LISP (à ne pas confondre avec le langage de programmation) est un protocole à séparation de l'identificateur et du localisateur. Ces protocoles présentent des défis de sécurité particuliers et ce RFC est donc consacré à une étude détaillée des menaces et risques associés à LISP.
LISP est normalisé dans le RFC 9300. Il peut être utilisé dans un réseau interne ou bien sur l'Internet public et ce RFC étudie sa sécurité dans ce dernier cas, évidemment plus difficile.
Le RFC est en trois parties : la section 2 détaille le modèle de menaces (qui est l'attaquant), la section 3 expose les techniques que peut utiliser l'attaquant, la section 5 décrit les solutions possibles. Il s'agit bien de regarder les attaques génériques contre LISP, pas celles contre une mise en œuvre particulière de LISP, qui peut évidemment avoir ses bogues spécifiques.
Commençons donc par le modèle de menace (section 2). On suppose un attaquant situé quelque part sur l'Internet, éventuellement en plusieurs points de celui-ci. Il peut être sur le chemin des paquets (on path) ou pas (off path). Le premier est évidemment le plus dangereux. S'il est attaquant actif, il peut modifier des paquets et même faire des attaques de l'Homme du Milieu. Si l'attaquant est en dehors du chemin, cela va être plus difficile pour lui. Il ne peut pas modifier les paquets échangés, il peut par contre envoyer des paquets mais, pour que ceux-ci soient acceptés, il faudra qu'ils correspondent à ce qu'attendent les parties légitimes, ce qui fait que l'attaquant devra souvent deviner des informations et compter sur la chance.
Autre façon de classer les attaquants, il y a ceux qui sont internes à un site LISP et ceux qui sont externes. Les attaquants de l'intérieur sont plus dangereux car la machine qu'ils contrôlent (suite à une trahison ou un piratage) est a priori jugée de confiance.
Il faut aussi distinguer les attaquants permanents (live) des attaquants ponctuels (time-shifted). L'attaquant permanent est celui qui reste actif pendant toute la durée de l'attaque. Dès qu'il est neutralisé, l'attaque stoppe. L'attaquant ponctuel peut lancer une attaque, puis se retirer et les effets de l'attaque vont continuer. Ce genre d'attaques est évidemment bien plus dangereux.
L'attaquant peut viser le système de contrôle (control plane) de LISP ou bien son système de transmission des données (data plane). Un exemple typique est le mécanisme de correspondance (mapping) qui permet aux routeurs LISP de trouver le localisateur (le RLOC) en échange de l'identificateur (l'EID). Ce mécanisme de correspondance fait partie du système de contrôle. Si un attaquant veut détourner les paquets, il n'est pas obligé de trouver une faille dans le routage lui-même : s'il arrive à modifier les correspondances, il obtiendra le même résultat. (Comme le ferait une attaque DNS dans l'Internet classique.)
Plusieurs types d'attaques peuvent être faites contre un protocole réseau comme LISP. Il y a les attaques par rejeu, où un attaquant capture des paquets légitimes pour les rejouer intacts plus tard. Ces attaques marchent souvent, même quand les paquets sont protégés par de la cryptographie (l'attaquant n'a pas besoin de modifier les paquets, ni même de les comprendre). Il y a les manipulations de paquets (l'attaquant prend un paquet légitime et le réinjecte). Il y a la suppression complète des paquets.
Plus complexe et plus vicieux, il y a l'usurpation (spoofing). L'attaquant injecte des paquets prétendant venir d'une autre machine. C'est quelque chose qu'on voit souvent sur l'Internet. LISP est une technologie de tunnel et l'usurpation peut donc porter sur deux endroits : l'adresse externe, celle que voient les routeurs IP ordinaires (c'est le RLOC), et l'adresse interne, celle du paquet encapsulé (c'est l'EID). Identifier un usurpateur est bien plus compliqué lorsque des tunnels sont en jeu !
L'attaquant n'est pas forcément un usurpateur. Il peut très bien dire la vérité sur son adresse (rogue attack) par exemple parce qu'il se moque d'être identifié, ou bien parce qu'il est un zombie.
Autre type d'attaque, évidemment, les attaques par déni de service, où l'attaquant ne cherche pas à prendre le contrôle du système, mais à le paralyser (ou à le ralentir).
Parfois, la cible immédiate de l'attaque n'est pas la principale victime : dans les attaques par réflexion, un attaquant utilise un tiers pour renvoyer ses paquets vers la vraie victime. C'est surtout utilisé en combinaison avec l'amplification : lorsque la réponse est plus grosse que la question, un attaquant peut amplifier son trafic. En outre, pour LISP, le système de transmission est certainement bien plus rapide que celui de contrôle et il y a donc en théorie une possibilité d'attaquer le second avec le premier.
Et, bien sûr, il y a les attaques d'espionnage passif, où des grandes oreilles écoutent votre trafic pour vous surveiller, sans eux-mêmes envoyer de paquets. Grâce à Edward Snowden, l'ampleur de ce type d'attaques par les États est désormais bien connu (RFC 7258).
Bon, assez de théorie, comment fait-on avec LISP quand on est un méchant et qu'on veut effectuer une des attaques en question ? Rentrons désormais dans les détails techniques (qui nécessitent de connaitre un peu LISP : relisez les RFC 9300, RFC 7215, RFC 6832, RFC 9301 et RFC 9302). D'abord, le « glanage » (gleaning), la collecte passive d'informations sur les correspondances identificateur->localisateur (RFC 6830, section 6). Il peut être utilisé pour empoisonner le cache des correspondances d'un routeur : le méchant envoie un paquet LISP fabriqué, les routeurs innocents l'observent et enregistrent la correspondance entre l'EID et le RLOC dans leur cache et paf, le méchant a pu détourner le trafic futur. C'est un exemple d'attaque ponctuelle : l'attaquant envoie juste un paquet puis plus rien, mais l'effet persiste pendant toute la durée de vie de l'information dans le cache (quelques secondes, si on suit fidèlement les conseils du RFC 6830, section 6.2).
Autre exemple d'empoisonnement d'un routeur LISP avec de fausses informations, le champ LSB (Locator Status Bits), qui indique l'état (joignable ou pas) des machines situées sur le site de départ du paquet (RFC 6830, section 6.3). En envoyant un paquet usurpé avec un faux LSB, on peut tromper des routeurs innocents. On peut par exemple mettre tous les bits à zéro (qui signifie que le préfixe est injoignable par ce routeur), menant à une attaque par déni de service ou bien les mettre tous à zéro sauf un, menant à une surcharge de cet unique routeur. C'est également une attaque ponctuelle : ses effets se feront sentir même si l'attaquant est neutralisé.
Un point important de LISP est le test de la « joignabilité » (reachability, RFC 6830, section 6.3). LISP vérifie que la machine qui prétend être joignable, et par tel routeur, l'est effectivement. Un des outils pour cela est un numnique envoyé à l'autre machine et qu'elle doit renvoyer. Un attaquant qui arriverait à tricher avec la joignabilité pourrait pousser un routeur LISP d'entrée du tunnel (un ITR) à changer de routeur de sortie (l'ETR) au profit d'un routeur qui ne marche pas. Cela réaliserait une attaque par déni de service. Même s'il n'arrive pas à faire changer de routeur, il pourrait perturber le routage en envoyant des tas de numniques différents. (Rassurez-vous, cette attaque est plus dure à réussir qu'il ne semble, voyez la section 5.)
LISP permet que plusieurs espaces d'adressage coexistent, différenciés par leur instance ID indiquée dans l'en-tête (RFC 6830, section 5.5). Elle n'est pas authentifiée et un attaquant peut donc envoyer des paquets à une autre instance ID que la sienne.
LISP permet de l'interconnexion avec des réseaux non-LISP (RFC 6832). Ces mécanismes ont des attaques très similaires à celles qu'on peut faire contre LISP lui-même. Par exemple, un paquet avec une adresse source usurpée peut être transmis sur l'Internet par la passerelle LISP.
Mais les pires attaques se situeront sans doute sur le système de correspondance (mapping). Le point central de tous les systèmes à séparation de l'identificateur et du localisateur est de découpler deux fonctions qui, dans IP, sont confondues. Cela suit un grand principe de l'informatique : « tout problème peut être résolu en ajoutant un degré d'indirection ». Sauf que cette séparation se paie en sécurité : il faut bien, à un moment, faire correspondre identificateur et localisateur et, là, cette nouvelle fonction, la correspondance, offre de nouvelles possibilités d'attaque.
Ainsi, les messages Map-Request
(RFC 6830, section 6) peuvent
être utilisés de plusieurs façons. Envoyés en masse, à un système
de contrôle qui est bien moins rapide que le système de
transmission, ils peuvent saturer les routeurs. Comme la réponse
(Map-Reply
) est plus grosse que la question,
ils peuvent servir à des attaques par amplification.
Et si un attaquant réussit à fabriquer de fausses réponses
(Map-Reply
) et à les faire accepter ? Il
devra pour cela mettre le numnique correct dans ses paquets. Comme
il fait 64 bits, si on a suivi les bons principes du RFC 4086 pour le générer, un attaquant qui n'est
pas sur le chemin (et doit donc deviner le numnique) n'a que peu
de chances de réussir. Mais attention, le numnique n'est pas une
signature : il indique juste que le paquet est bien une réponse à
une question posée. Si l'attaquant peut modifier les paquets, il
peut empoisonner le cache de correspondance du routeur. Variante
de cette attaque, si le méchant est un routeur légitime
(rogue attack), il peut répondre, mais avec de
fausses réponses. Il ne peut pas annoncer des préfixes quelconques
mais il peut annoncer des préfixes plus généraux que ceux qu'il
gère réellement (par exemple annoncer qu'il gère
192.0.2.0/24
alors qu'il ne contrôle que 192.0.2.0/26
), ce qui lui permet de détourner le trafic.
Enfin, il y a les Map-Register, ces messages envoyés par les routeurs aux serveurs de correspondance pour les informer des préfixes gérés (RFC 9301, section 4.2). Ils sont authentifiés donc, normalement, un attaquant quelconque ne peut pas les usurper. Mais il reste des attaques résiduelles comme l'annonce de préfixes plus généraux que les siens.
Au passage, un problème de sécurité qu'on oublie parfois est celui de la vie privée (section 4). Les correspondances LISP sont publiques (comme les tables BGP dans l'Internet classique) et il ne faut donc pas oublier qu'on ne peut pas participer à LISP discrètement.
Et pour finir, les solutions (section 5). Comment faire pour éviter ces menaces ? Le RFC donne des conseils très généraux (« déployer soigneusement », « appliquer les règles habituelles de sécurité ») mais aussi des indications plus précises et spécifiques à LISP. Clairement, le plan de contrôle est la partie la plus sensible. Il est donc important d'utiliser les techniques d'authentification décrites dans le RFC 9301 (voir notamment sa section 6). Des extensions de sécurisation de LISP sont en cours de développement.
D'autre part, les conseils de sécurité du RFC 9300 doivent être suivis. Par exemple, quand ce RFC
écrit qu'il faut limiter le rythme des
Map-Request
, cela doit être appliqué.
L'information obtenue par examen des paquets (comme le glanage cité plus haut) n'est évidemment pas de confiance : à n'utiliser que pour le flot de données qui contenait cette information, ou alors à vérifier avant. (Voir aussi « How to mitigate the effect of scans on mapping systems ».)
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : R. Penno (Cisco), S. Perreault (Jive Communications), M. Boucadair (Orange), S. Sivakumar (Cisco), K. Naito (NTT)
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 29 avril 2016
Le mécanisme de traduction d'adresses IPv4 connu sous le nom de NAT (et qui devrait plutôt être appelé NAPT pour Network Address and Port Translation, car il ne se contente pas de traduire les adresses IP) cause beaucoup de problèmes, car il casse le modèle normal de fonctionnement d'IP, modèle de bout en bout. Pour limiter les problèmes dus à ce mécanisme, plusieurs RFC posent certaines exigences que doivent respecter (en théorie) les routeurs NAT. Ce nouveau document met à jour certaines de ses exigences. Il met donc légèrement à jour les règles des RFC 4787, RFC 5382 et RFC 5508.
Ce RFC de maintenance ne s'applique qu'au « NAT44 » traditionnel, où une adresse IP publique n'est partagée que par les membres d'un même foyer, ou bien les employés d'une même entreprise. Pour le CGN, les exigences sont dans le RFC 6888.
D'abord, le suivi de connexions TCP (section 2 du RFC). Notre RFC formalise rigoureusement la machine à états que doit suivre un routeur NAT (elle est proche de celle du RFC 6146). Le RFC 5382 spécifiait bien des délais pour certains états mais sans décrire précisement la machine complète. Par exemple, l'exigence 5 du RFC 5382 donne un délai pour le temps minimum d'attente avant de considérer une connexion partiellement ouverte, ou fermée, comme abandonnée, mais il n'était pas clair si ces deux cas devaient avoir le même délai. Notre RFC tranche donc : le cas des connexions partiellement ouvertes et celui des connexions fermées sont différents et les délais devraient pouvoir être configurés différemment.
Et les paquets TCP RST
(ReSeT), on en fait quoi ? Notre RFC précise
clairement (suivant ce que faisait déjà le RFC 6146) qu'un paquet RST doit être considéré comme
détruisant la connexion TCP et donc comme mettant fin à la
correspondance dans le routeur NAT (après un délai, pour tenir
compte du fait que le paquet RST
a pu être
reçu par le routeur NAT mais pas par la machine terminale). Attention, il faut d'abord
vérifier que ce paquet RST
correspond bien à
une connexion existante, sinon, on permet des attaques
par déni de service faciles (RFC 5961).
Les RFC 4787 et RFC 5382 précisaient qu'on pouvait utiliser le même couple {adresse IP externe, port externe} pour des connexions allant vers des machines extérieures différentes. Mais ils ne traitaient que du cas où il n'y avait qu'une machine interne qui allait vers ces machines extérieures. Désormais, on précise (section 3 de notre RFC) que cette utilisation est également valables si plusieurs machines internes se connectent. Sans cette règle, il faudrait beaucoup plus de ports externes disponibles, ce qui poserait un problème avec les environnements où le facteur de partage d'adresses est important (cf. RFC 6269).
Est-ce qu'un routeur NAT doit/peut utiliser les mêmes correspondances pour UDP et TCP (section 5 de notre RFC) ? Ce n'est pas précisé dans les RFC 4787 (exigence 1) et RFC 5382 (exigence 1). On fait une connexion TCP sortante, est-ce qu'un paquet UDP sortant va réutiliser la même correspondance ? La règle est désormais explicite : non, il ne faut pas ; par défaut, les correspondances doivent être spécifiques à un protocole (donc, différentes pour UDP et TCP).
Autre piège du NAT, le fait qui peut parfois changer une distribution aléatoire des ports en une distribution prévisible. Cela pose un problème pour certaines méthodes de sécurité qui dépendent du caractères imprévisible (par exemple le RFC 5452). Notre RFC reprend (section 9) une recommandation de la section 4 du RFC 6056 : un routeur NAT ne doit pas choisir les ports de sortie de manière prévisible ou régulière.
Comme d'habitude, la fragmentation est une source d'ennuis (section 10). Notre RFC rappelle donc qu'il faut suivre les règles de la section 5.3.1 du RFC 6864, notamment sur le caractère unique et imprévisible de l'identificateur de fragment.
Le routeur NAT voit parfois passer des paquets en « épingle à
cheveux » (hairpinning). Cela désigne les
paquets (section 12) qui, venus du réseau interne, y retournent,
après être passés par le routeur. Si le réseau interne est
172.17.42.0/24
, et qu'un serveur
HTTP est sur la machine
172.17.41.1
et accessible de l'extérieur en
192.0.2.71
, alors, une machine interne qui
tente d'aller en http://192.0.2.71/
va
envoyer des paquets qui iront au routeur NAT, prendront un
virage en épingle à cheveux et reviendront
dans le réseau interne, vers
172.17.41.1
. Historiquement, pas mal de
routeurs NAT étaient incapables de gérer ce cas. La situation est
désormais meilleure mais il reste des cas limites. Ainsi,
l'exigence 7 du RFC 5508 devait rappeler
que le virage en épingle à cheveux était possible même en
ICMP. Notre RFC insiste sur le respect de
cette règle.
Enfin, la sécurité (section 13). Notre RFC estime que ses exigences renforcées vont améliorer la sécurité. Par exemple, des règles strictes (sections 7 et 11) sur la suppression des correspondances dans la table du routeur NAT évitent qu'un attaquant puisse garder ouvertes des correspondances qui devraient être fermées (et la mémoire récupérée). Les règles sur les ports sources imprévisibles de la section 9 rendront (entre autres) plus difficile le suivi des machines situées derrière un routeur NAT.
Notez enfin qu'il y a des gens qui prétendent avoir un brevet sur certaines de ces recommandations...
Première rédaction de cet article le 24 avril 2016
J'ai déjà parlé ici de la bogue DNS de Free affectant certains domaines signés avec DNSSEC. Six mois après, elle n'a pas été réparée et le problème se montre en fait encore plus complexe qu'à première vue.
Le problème a été signalé sur la liste FRnog et analysé par
Rémy Duchet. En gros, certains usagers de Free n'arrivent pas à
aller en
. Si on regarde
avec dig, on voit bien un problème
DNS (ici, j'interroge explicitement un des
résolveurs DNS officiels de Free, puisque j'ai un résolveur local) :
http://test-yann.myshopify.com/
% dig @212.27.40.240 test-yann.myshopify.com ; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> @212.27.40.240 test-yann.myshopify.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 393 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;test-yann.myshopify.com. IN A ;; Query time: 27 msec ;; SERVER: 212.27.40.240#53(212.27.40.240) ;; WHEN: Sun Apr 24 17:00:03 CEST 2016 ;; MSG SIZE rcvd: 52
Ah, en effet, nous avons un problème
(SERVFAIL
= Server
Failure). Avec d'autres résolveurs de Free, pas de
problème. Et ça varie dans le temps (en d'autres termes, des fois,
ça marche, des fois, ça marche pas).
On peut également tester avec les sondes RIPE
Atlas, dans l'AS de Free, 12322 :
% atlas-resolve -r 500 --as 12322 -t A test-yann.myshopify.com [ERROR: SERVFAIL] : 61 occurrences [23.227.38.68 23.227.38.69 23.227.38.70 23.227.38.71] : 133 occurrences [TIMEOUT(S)] : 1 occurrences Test #3682131 done at 2016-04-24T14:57:13Z
Cela montre bien que certains résolveurs de Free ont le problème
SERVFAIL
mais pas tous.
Si on essaie avec l'option
+cd
(Checking Disabled,
couper la validation DNSSEC), tout marche :
% dig +cd @212.27.40.240 test-yann.myshopify.com ; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> +cd @212.27.40.240 test-yann.myshopify.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18276 ;; flags: qr rd ra cd; QUERY: 1, ANSWER: 22, AUTHORITY: 4, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;test-yann.myshopify.com. IN A ;; ANSWER SECTION: test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com. test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 12663 myshopify.com. K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+ nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= ) test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 39852 myshopify.com. lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv 7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r 1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= ) test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com. test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 12663 myshopify.com. K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+ nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= ) test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 39852 myshopify.com. lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv 7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r 1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= ) test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com. test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 12663 myshopify.com. K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+ nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= ) test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 39852 myshopify.com. lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv 7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r 1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= ) test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com. test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 12663 myshopify.com. K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+ nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= ) test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 39852 myshopify.com. lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv 7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r 1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= ) test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com. test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 12663 myshopify.com. K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+ nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= ) test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 39852 myshopify.com. lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv 7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r 1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= ) test-yann.myshopify.com. 1800 IN CNAME shops.shopify.com. test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 12663 myshopify.com. K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+ nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= ) test-yann.myshopify.com. 1800 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 39852 myshopify.com. lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv 7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r 1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= ) shops.shopify.com. 1800 IN A 23.227.38.71 shops.shopify.com. 1800 IN A 23.227.38.69 shops.shopify.com. 1800 IN A 23.227.38.70 shops.shopify.com. 1800 IN A 23.227.38.68 ;; AUTHORITY SECTION: shopify.com. 6458 IN NS ns4.p19.dynect.net. shopify.com. 6458 IN NS ns3.p19.dynect.net. shopify.com. 6458 IN NS ns1.p19.dynect.net. shopify.com. 6458 IN NS ns2.p19.dynect.net. ;; Query time: 41 msec ;; SERVER: 212.27.40.240#53(212.27.40.240) ;; WHEN: Sun Apr 24 17:44:13 CEST 2016 ;; MSG SIZE rcvd: 2376
On a la réponse mais on voit bien qu'il y a un problème : ces
enregistrements DNS CNAME
(Canonical
Name) répétés ne sont pas normaux. Il ne sont pas dans les
serveurs faisant autorité pour le domaine :
% dig @ns1.p19.dynect.net test-yann.myshopify.com ; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> @ns1.p19.dynect.net test-yann.myshopify.com ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7499 ;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 3, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;test-yann.myshopify.com. IN A ;; ANSWER SECTION: test-yann.myshopify.com. 600 IN CNAME shops.shopify.com. test-yann.myshopify.com. 600 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 12663 myshopify.com. K3oRwkmXUkzNYbFO1jNLGLrSkhaRRBnKeGvld9YdcZo+ nUOpJzGUECTzrzOTBGpbGXdJB5M3nJ6pebAGpr46m5Rk HfG3+FOdgCRS+CG5lpu0+KC8w80718ywOFO8LROdIjwm h4swblM+0Aft4o1lj5ChnCBefWgn2Cs4qSqMT0g= ) test-yann.myshopify.com. 600 IN RRSIG CNAME 5 2 600 ( 20160519013040 20160419013040 39852 myshopify.com. lBsyv5zrQ4twd4LNzLrdQpHWyxL9SQGM2wfhVR/GfnWE TXNV3wyW5bIwRDySbmdRg9RLiz9h1sBFByIeITYEJeKv 7daLBZSwoI7551mz0jJX5fMgEuW7FEFOP25pYb6p5o1r 1VFvc47+X8qTLaV5j0Uz+PXJjFBvF7GB4i3gFb0= ) ;; AUTHORITY SECTION: test-winkel.myshopify.com. 60 IN NSEC test1012345.myshopify.com. CNAME RRSIG NSEC test-winkel.myshopify.com. 60 IN RRSIG NSEC 5 3 60 ( 20160519013040 20160419013040 12663 myshopify.com. BHS+QE4Pdu0qFdTW2XHN4Z6mbiqu3eb89UhwO3f5/C7W vpQmlNEmuYNlUlAHgUWbXvCwmDr+9k0bVZuiZh0UuSCp pveXWvYzr6nJjCRy5CZoUJy6C60Dyt1LfW2kCNTXUdjX Vp8HwMlKN0np6jxe2o/ryU/BphzdYA1OEmqp9/0= ) test-winkel.myshopify.com. 60 IN RRSIG NSEC 5 3 60 ( 20160519013040 20160419013040 39852 myshopify.com. I8LqnvjOSLhivVteqv6gqeeytZ9YZU9heYIj/hNfYUz+ vOQ2PQBCk7N0ujbI9vWpFkj+3YSNnsxBshxjVZfWQoLp Cpde8Ir+zP8WK95/04VQBpU1HjI7QBAARkPCD0YCnTBY U/hTVe6gcB43c9CFAUaJ5qynRmnTZFIsvtcGBz8= ) ;; Query time: 22 msec ;; SERVER: 2001:500:90:1::19#53(2001:500:90:1::19) ;; WHEN: Sun Apr 24 17:45:54 CEST 2016 ;; MSG SIZE rcvd: 831
Donc, ce sont les résolveurs de Free qui les ont inventé. La bogue est clairement de la responsabilité de Free.
Dans mon article
précédent, j'avais émis l'hypothèse que le problème était
lié à l'utilisation de NSEC3
(RFC 5155) et des jokers. Ici, la zone est
signée avec NSEC
, pas
NSEC3
(ce qui est curieux, d'ailleurs,
puisque cela permet de connaitre la liste des clients de
shopify.com
), donc
NSEC3
ne semble pas responsable. On
retrouve par contre les jokers, dont l'interaction avec DNSSEC
est régulièrement une source d'ennuis. D'une façon ou d'une
autre, une combinaison de caractéristiques de la zone
myshopify.com
déclenche la bogue, multiplie
les CNAME
(la réponse du résolveur de Free
a une taille supérieure à la MTU
d'Ethernet...), l'enregistrement
NSEC
obligatoire est supprimé, et paf.
En résumé, je ne sais pas quel logiciel résolveur utilise Free (aucun des logiciels que je connais, comme Unbound ou BIND, ne montre ce comportement) mais il est bogué et devrait impérativement être réparé, si on veut que DNSSEC soit plus largement utilisé.
Et du côté de l'utilisateur ordinaire, que peut-on faire ? Le client final peut utiliser son propre résolveur (ce qui est une bonne idée, de toute façon), le webmestre qui veut publier des choses accessibles aux utilisateurs de Free ne peut pas grand'chose, à part peut-être configurer sa zone DNS de manière plus conservatrice (les jokers sont presque toujours une mauvaise idée).
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : M. Stenberg, S. Barth (Independent)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF homenet
Première rédaction de cet article le 23 avril 2016
Ce nouveau protocole DNCP (Distributed Node Consensus Protocol) est prévu notamment pour les réseaux non organisés comportant beaucoup de petites machines, comme on peut en trouver en domotique (Internet des Trucs et tout ça). Il s'appuie sur l'algorithme Trickle (RFC 6206) pour distribuer dans le réseau des informations quelconques. Aucune machine ne joue un rôle particulier dans DNCP : pas de maître ou de racine. DNCP est un algorithme générique, et son utilisation effective nécessite la définition d'un profil, comme HNCP (Home Networking Control Protocol, RFC 7788) dans le cas du réseau « Homenet ».
L'information distribuée par DNCP est sous forme de TLV. Chaque tuple TLV fait 64 ko au maximum et, une fois que l'algorithme a convergé, tous les nœuds du réseau ont la même base de tuples : le réseau est synchronisé. L'état d'un nœud (l'ensemble des tuples qu'il connait) est représenté par un condensat des données (nommé network state hash). Au début, chaque nœud ne connait que ses propres tuples et son état reflète cela. Il diffuse cette information avec Trickle et chaque nœud apprend alors que la synchro n'est pas complète (puisqu'il existe des nœuds avec un condensat différent). Puis chaque nœud modifie l'état (le condensat) en intégrant les tuples des autres nœuds. À la fin, tous les nœuds ont le même état et trouvent donc le même condensat. Ils sont alors heureux et synchronisés. En situation stable, DNCP ne transmet que les condensats (pour que les nœuds puissent vérifier qu'il n'y a pas eu de changement), pas les données, ce qui le rend assez frugal.
DNCP est donc utile pour tous les cas complètement répartis, où des machines sans chef veulent se coordonner. Cela peut servir, par exemple, pour l'affectation automatique des préfixes IP dans un réseau non géré (RFC 7695). DNCP est à l'origine issu d'un projet moins général, le projet « Homenet » de l'IETF ; le groupe Homenet s'est aperçu que le protocole de synchronisation pouvait avoir son utilité en dehors de la domotique et a créé DNCP (et un protocole concret pour Homenet, HNCP).
Comme indiqué plus haut, DNCP est abstrait : plusieurs choix techniques essentiels sont laissés à de futurs profils (comme HNCP, décrit dans le RFC 7788). Parmi ces choix :
DNCP est très chouette mais le RFC précise qu'il ne peut pas servir à tout. Quelques exemples de cas où DNCP n'est pas adapté :
Si on a des données qui changent très souvent, il peut être préférable d'utiliser DNCP pour publier l'adresse d'un serveur où récupérer ces données.
DNCP est résumé en section 3 du RFC. Les nœuds sont découverts automatiquement (la méthode exacte dépend du profil) ou manuellement, et leur joignabilité est vérifiée. Les TLV peuvent être des demandes d'information ou bien les données elles-mêmes.
Chaque nœud commence par calculer le condensat des données (la fonction utilisée depend du profil) qu'il veut publier. Il l'annonce ensuite à ses voisins. Quand un voisin annonce un condensat différent, le nœud sait que le réseau n'est pas encore synchronisé. Il demande alors au voisin toutes ses données, les ajoute à sa base, met à jour son condensat et recommence.
Pour jouer son rôle, le nœud DNCP a besoin de quelques informations (section 5). Il a un identificateur unique (la façon doit il est choisi dépend du profil), ses données à publier, une ou plusieurs instances Trickle (le terme ne vient pas du RFC 6206 mais est défini ici : c'est un état Trickle autonome, avec les valeurs des paramètres Trickle), etc. Le nœud a également en mémoire un ensemble de voisins avec, pour chacun, son identificateur, son adresse IP, etc.
Les TLV et leur format sont décrits en
section 7 : un type de deux octets, une longueur de deux octets et
la valeur. Des TLV peuvent être inclus dans les TLV. Quelques
exemples de types : REQ-NETWORK-STATE
(type
1) sert à demander l'état du réseau (le condensat de tous les
tuples), NETWORK-STATE
(type 4) sert pour les
réponses à ces requêtes et donne l'état du réseau, etc. L'ensemble
des valeurs possibles figure dans un
registre IANA.
La section 8 discute de la sécurité de DNCP. Le traitement de celle-ci dépend essentiellement du profil, qui peut décider, par exemple, d'utiliser TLS ou DTLS.
La section 9 discute en détail ce qu'on attend des profils, ce que doivent définir les protocoles concrets qui réalisent DNCP :
Des indications sur les choix à faire sont présentées dans l'annexe B. Par exemple, si on utilise UDP, il est recommandé que les données restent d'une taille inférieure à une MTU typique, notamment pour éviter la fragmentation. D'un autre côté, UDP donne davantage de contrôle sur l'envoi des données (mais pas forcément sur leur réception).
Un exemple de profil figure dans l'annexe A. On peut aussi regarder un vrai profil, dans le RFC 7788, qui normalise HNCP. Le profil d'exemple est pour un protocole fictif nommé SHSP (il a existé un projet de protocole nommé Simple Home Status Protocol mais qui semble abandonné, et sans lien avec ce SHSP fictif), un protocole pour l'automatisation de la maison. Ses choix sont :
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : M. Stenberg, S. Barth
(Independent), P. Pfister (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF homenet
Première rédaction de cet article le 23 avril 2016
Ce nouveau protocole, HNCP (Home Networking Control Protocol), est conçu pour la domotique. Son rôle est de distribuer de l'information de configuration (les services comme celui d'impression, par exemple) à toutes les machines de la maison. C'est un profil (une instance particulière) du protocole DNCP du RFC 7787.
Cet HNCP est issu du projet Homenet, visant à créer à la maison des réseaux non gérés (M. Michu a autre chose à faire) et non limités à un seul lien (donc, avec des routeurs). L'architecture d'Homenet est décrite dans le RFC 7368. Dans ce cadre Homenet, HNCP doit permettre de :
HNCP n'est pas un protocole de routage (quoique on puisse considérer que le routage, c'est distribuer de l'information de configuration, mais HNCP n'est pas prévu pour cela), il faut l'utiliser avec un protocole de routage comme Babel (RFC 8966).
Comme HNCP est un profil de DNCP, il en hérite les caractéristiques (RFC 7787). Par exemple, il n'est pas adapté à de l'information très changeante. C'est pour cela que, pour la résolution de noms, HNCP distribue les adresses des serveurs de noms, mais n'assure pas cette fonction lui-même.
Le RFC sur DNCP décrit les points laissés libres dans DNCP et qu'un profil de DNCP doit spécifier (RFC 7787, section 9). La section 3 de notre RFC sur HNCP précise ces points :
Je n'ai pas d'expérience pratique avec HNCP donc je vais passer rapidement sur le reste du RFC. Parmi les points amusants à noter :
.home
, remplacé depuis par
home.arpa
par le RFC 8375.Comme tous les protocoles instanciés à partir de DNCP, HNCP transporte l'information sous forme de TLV (section 10). Ces TLV peuvent être emboîtés (un sous-TLV dans la partie Valeur d'un TLV). Parmi les TLV possibles (la liste complète est dans un registre IANA), on trouve :
La section 11 du RFC résume les exigences qui pèsent sur les nœuds d'un réseau HNCP. En plus de gérer le protocole HNCP lui-même, ils doivent aussi, s'ils sont routeurs, respecter le RFC 7084, qui spécifie les règles (légèrement assouplies dans notre RFC sur HNCP) que doivent suivre les routeurs IPv6 situés chez l'utilisateur.
Enfin, un petit mot sur la sécurité (section 12) : HNCP est conçu pour être simple pour l'utilisateur et pour marcher tout seul. Sa sécurité sera donc forcément très faible : un réseau à la maison sans administrateur système professionnel offrira plein de trous à un éventuel attaquant (le RFC 7368 parle de la sécurité des réseaux domotiques). On ne peut pas avoir à la fois le beurre (l'auto-configuration) et l'argent du beurre (la sécurité).
Quelles sont les mises en œuvre de HNCP aujourd'hui ? Il y a, en logiciel libre, hnetd (qui est accessible également sous forme de paquetages pour OpenWrt, depuis la version Barrier Breaker - 14.07 - en juillet 2014). hnetd fait partie du projet HomeWrt. Complètement indépendant de hnetd, il existe également shncpd. On peut aussi citer pysyma, écrit en Python.
En non-libre, il y a du HNCP en cours de développement dans des environnements aussi différents que les routeurs Cisco ou D-Link, les systèmes Nest, le système Xfinity de Comcast... Il parait même que c'est prévu pour les Freebox mais je n'ai pas trouvé de détails à ce sujet. D'autre part, HNCP est apparemment cité dans la spécification (fermée et non publique) Thread.
Les protocoles Homenet sont en développement depuis longtemps et, si vous allez à des salons ou des conférences, vous avez certainement vu des démonstrations utilisant HNCP.
Et si vous aimez l'histoire des protocoles, notez que HNCP, à l'origine, était prévu pour assurer l'auto-configuration de routeurs dans un réseau OSPF (RFC 7503). Cette idée d'« auto-configuration OSPF » n'a pas rencontré un grand succès car tout le monde n'aime pas OSPF et aurait préféré découpler le routage (OSPF, Babel, etc) de la distribution d'informations. HNCP, protocole limité à cette distribution, était né. Il a ensuite été abstrait dans le protocole DNCP (RFC 7787), dont HNCP n'est qu'un profil.
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : F. Baker, R. Pan (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF aqm
Première rédaction de cet article le 21 avril 2016
Au cœur de l'Internet se trouvent les routeurs, et la façon dont ils traitent les paquets IP est cruciale pour le bon fonctionnement du réseau. C'est particulièrement important lorsque le trafic augmente et que les files d'attente dans les routeurs se remplissent. Que faire, alors ? Ce nouveau RFC discute des stratégies des routeurs confrontés à des files d'attente bien remplies.
Pas de « bonne » ou de « mauvaise » méthode dans ce RFC mais une discussion des possibilités. Il y a longtemps que le sujet est discuté, souvent avec des termes dangereux, car trop chargés, comme « juste » (qu'est-ce qui est juste ? Quels paquets jeter lorsque la file d'attente est pleine ? Les plus anciens ? Les plus gros ? Ceux venant de certains réseaux ?) Ainsi, le RFC 970 parle de gestion juste de la file d'attente... Le problème (à part la question de philosophie « qu'est-ce que la justice ? ») est que toute politique de gestion de la file d'attente peut entrainer des adaptations non souhaitées de la part des machines connectées au réseau (si on jette en priorité les paquets les plus gros, on encourage les machines à envoyer des paquets plus petits, comme dans le Silly Window Syndrome).
Sur la question de principe de l'équité ou de la justice, il faut toujours lire l'article de référence, « Flow Fairness: Dismantling a Religion ».
Historiquement, des modèles de trafic peu réalistes avaient été utilisés. Par exemple, certains modèles partent du débit moyen d'un flot tout au long de son existence et raisonnent là-dessus. Mais le trafic Internet est tout, sauf moyen. Il est plutôt en quanta, avec des sursauts brusques. Par exemple, une caméra va envoyer trente images par seconde et cela se traduira par beaucoup de données lorsqu'une nouvelle image est disponible, puis un silence d'un trentième de seconde avant l'image suivante.
Au passage, j'ai parlé de flot sans l'expliquer. Le terme est courant dans les discussions réseau mais souvent assez flou. Cela peut désigner une session du protocole de transport (identifiée par le fameux tuple à cinq éléments du RFC 2990), tous les paquets entre deux machines données, tous les paquets vers une machine donnée...
Autre question pratique dès qu'on discute d'équité entre les flots, comment est-ce qu'on la mesure, pour déterminer si elle est respectée ou pas ? Le RFC 7141, entre autres, se penche sur cette question.
Le gros du RFC est formé par la section 3, qui discute des outils habituels de gestion des paquets par les routeurs : mettre en file d'attente (queuing), marquer les paquets (marking) et les jeter (dropping). Tous ces outils sont indispensables (tant que la mémoire des routeurs sera finie, et donc les files d'attente n'auront pas une taille illimitée, il faudra parfois jeter des paquets) et sont interprétés par le reste du réseau comme des signaux indiquant l'approche ou le début de la congestion.
Ce RFC discute de divers concepts, il ne spécifie pas un algorithme. Pour un exemple d'algorithme récent de gestion des files d'attente des routeurs, voir FQ-Codel, même s'il ne suit pas forcément les avis du RFC (CoDel a été finalement publié dans le RFC 8289.)
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : M. Nottingham (Akamai), P. McManus
(Mozilla), J. Reschke (greenbytes)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpbis
Première rédaction de cet article le 15 avril 2016
Une nouveauté dans le monde HTTP : ce RFC décrit un mécanisme permettant d'indiquer des endroits alternatifs où trouver le contenu demandé. Ce n'est pas une classique redirection : l'URI reste le même, on découple simplement l'identificateur (l'URI) et le localisateur (l'endroit où chercher et le protocole à utiliser).
Ce concept est assez nouveau dans le monde
HTTP (section 1 du RFC). En effet, le RFC 7230 tend à mélanger l'identificateur d'une
ressource (http://www.example.com/foo/bar
) et
les moyens d'y accéder (la même ressource peut aussi être en
https://www.example.com/foo/bar
voire sur un
miroir à un URL très
différent). Le but du mécanisme de ce nouveau RFC 7838 est de séparer plus clairement
identificateur et
localisateur.
Quelques exemples pratiques sont donnés dans cette section 1 :
Actuellement, ce genre de choses est fait par des redirections
HTTP explicites (codes 301, 302, 307 ou 308, voir le RFC 7231, section 6.4). L'URL vers lequel on est
redirigé est montré par le navigateur (ce qui n'est clairement pas
une bonne idée dans le cas de redirections temporaires comme
307). Autre façon de faire, un relais, qui se
connecte au serveur effectif, sans le dire du tout au client
HTTP. Les « services alternatifs » de ce RFC 7838
sont situés entre les deux façons : annoncés au client HTTP mais pas mémorisés
et pas montrés à l'utilisateur (l'URI ne
change pas). Le contexte de sécurité n'est
pas modifié (si l'URI commençait par le plan
https://
, le service alternatif devra donc
présenter un certificat valide), le champ
Host:
de la requête HTTP contiendra toujours
le nom original (notez qu'il existe désormais un champ
Alt-Used:
pour indiquer le nom alternatif,
cf. section 5). Normalement, l'utilisateur ne verra donc pas
qu'on utilise un
service alternatif (ceci dit, comme son logiciel client, lui, est
au courant, des options de débogage pourront permettre de
l'afficher, contrairement à ce qui se passe avec un relais).
La solution est en deux parties : des concepts abstraits
(section 2) puis des mécanismes concrets pour les différents
protocoles, dans les sections 3 et 4. Commençons par le cadre
abstrait. Un « service alternatif » existe lorsqu'un serveur
d'origine (concept lui-même défini dans le RFC 6454, section 4) sait que ses ressources sont accessibles avec une
combinaison {protocole, serveur, port} différente. Un tel service
alternatif fait autorité (au sens du RFC 7230, section 9.1), ce n'est pas un simple miroir, ni un
cache. Notez
que la granularité est pour une origine complète (la combinaison
{protocole, serveur, port}) : on ne peut pas faire un service
alternatif qui couvrirait uniquement le chemin /foo
de
l'URI.
Un exemple de service alternatif ? Mettons que l'origine soit {http, www.example.com, 80} et que les mêmes ressources soient accessibles en HTTP 2 à {h2, new.example.com, 81}, alors on peut dire que ce {h2, new.example.com, 81} est un service alternatif de l'origine.
Notez que j'ai appelé « protocole » le premier membre du
tuple. Ce n'est pas le plan
(scheme) dans l'URI (plan que pas mal de gens
appellent à tort protocole). En effet, cette valeur est plus
spécifique que le plan, elle peut inclure des détails techniques
supplémentaires (par exemple, lorsque le plan est
http://
, on peut y accéder avec les
protocoles http
ou h2
,
ce second désignant HTTP 2.) Le protocole, pour les services
alternatifs, est un nom ALPN (RFC 7301 et le registre IANA ALPN).
Le tuple {protocole, serveur, port} peut être accompagné d'une durée de vie, indiquant combien de temps le client HTTP peut garder en mémoire l'information sur le service alternatif.
Au passage, un mot de sécurité : le client doit évidemment être conscient que, si la communication n'est pas sécurisée (par exemple par TLS), il peut être envoyé vers un faux service alternatif (section 9). Si le service d'origine n'a pas TLS mais que le service alternatif l'a, et présente un certificat au nom du service d'origine, c'est bon. Si aucun des deux n'a TLS, le risque d'avoir été trompé est bien plus élevé. Il n'est donc pas forcément prudent d'utiliser les services alternatifs sans TLS.
Notons enfin que les services alternatifs sont optionnels. Le client n'est pas obligé de les utiliser (d'autant plus que les clients HTTP actuels ne gèrent pas ces services et n'utiliseront donc pas les alternatives, tant qu'ils n'ont pas été mis à jour). Le serveur d'origine doit donc rester prêt à assurer les requêtes.
Maintenant, les mécanismes pour signaler ces services
alternatifs. En HTTP 1, en utilise l'en-tête
Alt-Svc:
(section 3, et désormais dans le
registre IANA). La réponse contient,
par exemple :
Alt-Svc: h2="new.example.org:80"
Cela indique que le client devrait plutôt aller voir avec le
protocole h2
(HTTP 2), sur la machine
new.example.org
. Si on ne change que le
protocole et le
port, on pourrait avoir :
Alt-Svc: h2=":8000"
Il peut y avoir plusieurs valeurs, dans l'ordre des préférences décroissantes :
Alt-Svc: h2="alt.example.com:8000", h2=":443"
Par défaut, le service alternatif peut être mémorisé par le
client pendant 24 h. Si on veut changer cette durée, on utilise
le paramètre ma
(Maximum
Age, en secondes) :
Alt-Svc: h2=":443"; ma=3600
Si le serveur veut qu'on oublie tout ce qu'on a mémorisé sur les
services alternatifs, et n'a pas envie d'attendre l'expiration des
caches, il envoie la valeur spéciale
clear
:
Alt-Svc: clear
À part ce paramètre ma
, et un autre
paramètre persist
(qui indique que,
contrairement au comportement par défaut, le client HTTP ne
devrait pas vider cette information de son cache si sa
configuration réseau change), d'autres paramètres sont possibles
dans le futur. Ils devront passer par le procédure « Examen par un
expert » du RFC 5226 et seront mis dans
le registre IANA.
Et si on utilise HTTP 2, où on est en binaire et plus en texte,
et où les en-têtes sont représentés d'une
façon complètement différente ? Dans ce cas, on se sert de trames du
type ALTSVC
(section 4). C'est une extension
au protocole original. La trame
ALTSVC
a le type 0xa (10, dans le registre IANA) et contient un
champ Longueur (de l'origine), l'origine, et le service
alternatif sous une syntaxe identique à celle de la section
précédente.
On l'a vu, le service alternatif fait normalement autorité et doit donc gérer les mêmes ressources. Que se passe-t-il si un serveur maladroit redirige vers une machine qui n'est pas configurée comme service alternatif ? Idéalement, cette machine ne faisant pas autorité doit répondre 421 (RFC 7540, section 9.1.2). Le client doit alors réessayer avec un autre service alternatif, s'il existe, ou bien avec le serveur d'origine. (Aujourd'hui, je crois qu'il est plus fréquent que la machine ne faisant pas autorité renvoie les ressources de sa configuration par défaut.)
Un petit mot d'histoire : ce système des services alternatifs
vient d'une solution spécifique à Chrome qui
se nommait Alternate-Protocol:
. Un bon
article de synthèse sur ces services alternatifs est celui de
l'auteur du RFC.
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : R. Sparks (Oracle)
Pour information
Première rédaction de cet article le 13 avril 2016
Un des gros avantages de travailler à l'IETF est qu'il existe un ensemble d'outils de travail en groupe très perfectionnés, permettant de gérer un grand nombre de documents qui changent tout le temps. Dans la plupart des SDO, ou organisations similaires, on a juste des piles de documents Word (ou, dans les dernières années, Google Docs) inexploitables. Comme le gros du travail IETF est fait sur des listes de diffusion, un des outils les plus cruciaux est le moteur de recherche dans ces listes de diffusion. Mais aucun outil n'est parfait et ce nouveau RFC est une liste de points à améliorer dans l'outil actuel, liste fondée sur l'expérience récente.
Ce
permet notamment
de retrouver un ou plusieurs messages, parmi les centaines de
messages échangés sur les listes IETF chaque jour. Voici un
exemple de recherche de « tcp encryption
eliot » (Eliot = Eliot Lear, auteur entre autres des
RFC 1918, RFC 4192,
RFC 6557...). On y voit la liste des
messages correspondants en haut à droite, à gauche les noms des
listes (en général, des groupes de travail IETF) où les messages
apparaissent, en bas à droite l'URL stable
du message en cours (ce qui permet des références précises
lorsqu'on affirme « Brian Trammel a dit que ») :
https://mailarchive.ietf.org/
L'outil actuel avait eu comme cahier des charges le RFC 6778 et avait été déployé en janvier 2014. Notre nouveau RFC liste les améliorations souhaitées.
Par exemple, lorsqu'on choisit « Group by Thread », la liste résultante est plate, sans hiérarchie. Cela rend difficile de voir où un fil de discussion commence et où il finit :
Notre RFC demande que, dans les améliorations de l'outil, l'affichage montre la hiérarchie.
Autre problème, il n'y a pas actuellement de boutons de navigation (message suivant/précédent par date, ou suivant le fil de discussion), que cela soit dans la liste des messages affichés, ou bien lorsqu'on regarde un seul message. Le RFC demande que ces boutons soient ajoutés.
C'est en lisant ce RFC que j'ai appris qu'on pouvait changer la taille de la fenêtre où s'affiche la liste des messages. Je la croyais fixe, et c'était apparemment le cas de bien des utilisateurs. Le RFC demande donc qu'on rende cette possibilité d'agrandissement plus évidente (personnellement, je n'ai pas trouvé). En prime, la façon dont est faite la troncation aujourd'hui ne semble pas rationnelle. Ici, on voit bien que les sujets sont coupés (et la fin remplacée par des ellipses) sans vraiment de raison.
Le service actuel est difficile à utiliser sur un petit écran, comme celui des phono sapiens puisque les divers éléments de l'interface sont toujours présents. Pour une interface riche, il vaudrait mieux être responsive, ce que demande le RFC (par exemple, on pourrait supprimer le menu des filtres quand l'écran est trop petit).
Par contre, sur des grands écrans, l'interface actuelle est au contraire trop économe et sous-utilise l'écran.
Enfin, notre RFC regrette que l'interface actuelle ne marche guère sans JavaScript. La prochaine version doit évidemment être capable de fonctionner sans JavaScript, quitte à accepter quelques fonctions en moins (comme les filtres appliquées dynamiquement).
Reste à développer, maintenant... Je n'ai pas encore vu d'appel d'offres.
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : P. Wouters (Red Hat), J. Abley
(Dyn), S. Dickinson
(Sinodun), R. Bellis (ISC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 11 avril 2016
Dernière mise à jour le 12 avril 2016
Historiquement, le DNS utilisait surtout UDP et le transport sur TCP ne servait qu'à des cas particuliers, comme lorsqu'un client DNS ré-essayait avec TCP de récupérer des données trop grosses pour UDP. Depuis le RFC 7766, ce n'est clairement plus le cas : TCP est désormais aussi utilisable qu'UDP pour le DNS. Mais les mises en œuvre typique du DNS sur TCP ont des restrictions, par exemple des délais maximum d'attente avant de « raccrocher » qui sont trop courtes, de l'ordre de quelques secondes lorsqu'il n'y a plus de trafic sur la connexion. Ce nouveau RFC propose un mécanisme EDNS permettant au client DNS de signaler au serveur qu'il souhaite garder la connexion ouverte, si le serveur est d'accord, s'il vous plait. (Notez qu'il existe une autre façon d'indiquer le temps pendant lequel on souhaite garder la session, celle des DSO du RFC 8490 ».)
Utiliser une connexion TCP par requête
DNS serait en effet très inefficace,
notamment question latence. Il
faudrait effectuer la triple poignée de
mains TCP à chaque requête. Le DNS sur TCP n'est
envisageable que si les connexions restent ouvertes et que la même
connexion peut servir pour plusieurs requêtes. Dans ce cas,
lorsque la connexion a déjà été ouverte, la latence peut être
aussi faible qu'avec UDP, voire meilleure (dans le cas de données
de grande taille, par exemple avec DNSSEC,
plus besoin d'essayer d'abord sur UDP). Reste une question pour le
serveur DNS : faut-il laisser la connexion ouverte dès
qu'il n'y a plus de requêtes à traiter ? Cette nouvelle option
EDNS
edns-tcp-keepalive
permet au client DNS
d'indiquer que, lui, il est prêt à réutiliser la connexion et
qu'il souhaite qu'on la garde ouverte.
Le serveur souhaite économiser ses ressources (mémoire, notamment). Contrairement à UDP, TCP nécessite que le serveur garde un état. Imaginons que chaque connexion TCP prenne une entrée dans un grand tableau des connexions TCP en cours. Si c'était « open bar » pour les clients, qu'ils puissent ouvrir autant de connexions qu'ils veulent, et les garder éternellement ensuite, le tableau serait vite rempli, menant à un déni de service. (Et si vous pensez qu'à la place du tableau, une structure de données dynamique, grossissant automatiquement, résoudrait le problème, rappelez-vous que la mémoire du serveur est finie...) Le serveur choisit donc s'il garde les connexions ouvertes, et combien de temps.
Au passage, la section 1 du RFC rappelle aussi qu'UDP a des problèmes sérieux, notamment parce qu'il permet des attaques par réflexion et parce qu'il implique, pour les grosses données, de la fragmentation, qui est en général une source d'ennuis (voir par exemple « Fragmentation Considered Poisonous de Herzberg et Shulman). D'où cet encouragement, depuis des années, à utiliser de plus en plus TCP.
La section 3 est la partie centrale du RFC, la spécification de la nouvelle option. Elle utilise EDNS (RFC 6891). Elle permet d'indiquer le délai d'attente avant la fermeture de la connexion, délai qui commence à courir lorsque la connexion devient inactive (« idle », cf. la section 3 du RFC 7766).
L'option se nomme edns-tcp-keepalive
et a
reçu le code 11 (stocké dans le registre
des options EDNS). Elle prend un seul argument, encodé sur
deux octets, TIMEOUT
qui indique la durée
du délai de garde, exprimée en unités de 100
millisecondes. Cette valeur n'apparait que dans les réponses du
serveur, pas dans les requêtes du client. Si TIMEOUT
vaut 600, cela
signifie que les connexions restent
ouvertes pendant une minute après la dernière requête reçue.
Ensuite, une fois cette option définie, comment on s'en sert ?
Elle ne doit évidemment pas être utilisée sur UDP, où elle
n'aurait aucune signification. Le client doit utiliser cette
option pour signaler qu'il souhaiterait garder cette connexion
ouverte (il ne doit pas indiquer de valeur pour
TIMEOUT
). Le serveur utilise cette option
pour indiquer le temps pendant lequel il va garder la
connexion (rappelez-vous que le client peut demander ce qu'il
veut, c'est le serveur qui décide). Le client est censé « raccrocher » juste avant
l'expiration de ce délai. Une valeur de 0 pour TIMEOUT
signifie « raccroche tout de suite » (un serveur
l'envoie, par exemple, lorsqu'il est soumis à un fort stress et
n'a plus de ressources disponibles.)
Au passage, si le serveur n'a plus envie de supporter cette
connexion, pourquoi ne raccroche-t-il pas lui-même, au lieu de
demander au client de le faire ? C'est parce que le pair TCP qui
ferme la connexion le premier passe ensuite en état
TIME-WAIT
(RFC 793,
section 3.5) et que cela l'oblige à garder un état pendant deux
fois la durée de vie maximale d'un segment TCP (soit quatre
minutes en tout). Il vaut donc mieux demander au client de le
faire. Par contre, après avoir envoyé le
TIMEOUT=0
, le serveur va avoir un délicat
arbitrage à faire entre attendre que le client raccroche et fermer
de lui-même la connexion (et donc garder une prise en état
TIME-WAIT
) quand le client n’obtempère pas
suffisamment vite.
La section 5 du RFC recommande d'ailleurs aux serveurs de suivre l'activité de leurs clients et de « punir », d'une façon ou d'une autre, ceux qui violeraient ces règles, par exemple en continuant à envoyer des requêtes alors qu'on leur a demandé de raccrocher.
J'insiste mais cela vaut la peine d'être dit et répété : cette
option edns-tcp-keepalive
ne diminue pas la liberté des clients et des serveurs
DNS. En cas de problème (tableau des connexions TCP en cours
presque plein, par exemple), clients et serveurs sont libres de
couper les connexions TCP plus tôt, ce qu'on appelle le
« TCP session management ».
Comme d'habitude avec toute nouvelle option, on peut s'attendre à des problèmes avec les stupides middleboxes. Une requête contenant cette option peut ainsi être jetée alors qu'elle ne l'aurait pas été sans l'option. Une stratégie de repli comme celle de la section 6.2.2 du RFC 6891 peut donc être utile.
Merci à Kim-Minh Kaplan pour d'utiles précisions sur TCP.
Date de publication du RFC : Avril 2016
Auteur(s) du RFC : A. Zimmermann (NetApp), W. Eddy (MTI
Systems), L. Eggert (NetApp)
Pour information
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 11 avril 2016
Un peu de nettoyage dans l'imposante bibliothèque des RFC sur le protocole TCP. Bien des extensions à TCP n'ont jamais connu de déploiement réel dans la nature et d'autres, qui ont été déployées, ne sont plus utilisées depuis longtemps. Un grand nombre de RFC sont donc reclassifiés « intérêt historique seulement » ou bien « pour information ». Cela concerne surtout des vieux RFC, qui étaient bien oubliés de toute façon.
Le RFC 7414 (le guide des normes sur TCP) avait déjà fait cette classification mais sans mentionner le changement de statut dans la base de l'éditeur des RFC. C'est désormais chose faite. Il y a aussi des RFC très anciens qui n'avaient jamais été classés comme le RFC 675, la première norme TCP, à l'époque où les RFC n'avaient pas de statut clair. Remplacé par le RFC 793 (avec des modifications sérieuses du format des paquets), ce RFC 675 est désormais « intérêt historique seulement ». (À noter que le précédent grand nettoyage de TCP était dans le RFC 6247.)
Dans la liste, le RFC 1078 (TCPMUX) a suscité quelques controverses car il est apparemment mis en œuvre dans certains systèmes d'exploitation (la partie serveur, pas la partie client, qui semble absente). On ne peut donc pas le caractériser comme « non déployé ». Néanmoins, les failles, notamment de sécurité, de TCPMUX font que le RFC 1078 se retrouve lui aussi classé « intérêt historique seulement ». Notre RFC donne la liste des problèmes techniques qu'il pose.
Ce sort touche aussi des RFC récents comme le RFC 6013, proposition d'une ouverture de connexion TCP plus rapide et plus légère, publiée en 2011, implémentée, mais jamais déployée, et remplacée depuis par des RFC qui ont eu plus de succès comme le RFC 7413.
D'autres RFC sont seulement classés « pour information ». C'est le cas du RFC 700 car il ne décrivait pas un protocole mais était une analyse des premiers résultats du déploiement de TCP, ou du RFC 814, un important document de réflexion sur des concepts comme les adresses, les ports et les routes, toujours d'actualité, mais qui n'avait jamais reçu de classement auparavant. Parmi les autres RFC désormais classés, le RFC 889, qui était également un compte-rendu d'expérience sur la variation de certains paramètres numériques de TCP, comme le délai maximal d'attente. Faisons enfin une place à part pour le très utile RFC 1071 qui n'est pas abandonné, bien au contraire, juste classé comme « pour information ».
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : M. Nottingham
(Akamai), E. Wilde
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 1 avril 2016
Lorsqu'on fait une requête HTTP, on récupère un code à trois chiffres qui indique notamment si tout s'est bien passé (si le code commence par 2, c'est bon, s'il commence par 4 ou 5, c'est qu'il y a un problème). Ces codes ne sont pas toujours assez fins et bien des API de services REST (donc reposant sur HTTP) voudraient des précisions. Plutôt que de créer un nouveau code, ce RFC propose un mécanisme qui permet d'envoyer du JSON normalisé indiquant tous les détails sur le problème survenu. (Ce RFC a depuis été remplacé par le RFC 9457.)
Les codes de statut de HTTP sont définis dans la section 6 du RFC 7231. Parmi les plus célèbres, on note 200 (qui veut dire que tout s'est bien passé) ou 404 (qui indique que le serveur n'a pas trouvé la ressource demandée). Si le serveur veut fournir des détails, il envoie traditionnellement de l'HTML dans le corps de sa réponse. Le navigateur Web peut alors l'afficher. Mais si la requête n'était pas envoyée par un humain derrière son navigateur, si elle venait d'un client REST ? HTML ne convient alors pas et il faut passer à une information analysable par une machine. C'est ce que fait ce RFC, qui définit deux formats, un en JSON (RFC 8259) et un en XML. Le client REST va donc avoir un résumé simple (le code de statut) et tous les détails nécessaires s'il le souhaite. « Comprenant » l'erreur exacte, le client pourra même, dans certains cas, la corriger.
Le RFC utilise surtout des exemples avec l'erreur 403 Forbidden mais j'ai préféré me servir de 402 Payment required. Ce code n'a jamais été clairement documenté (il est marqué « réservé pour un usage futur » dans le RFC 7231, section 6.5.3) et c'est sans doute pour cela que notre RFC ne l'utilise pas, mais je le trouve plus rigolo. Voici par exemple une page Web payante :
% wget https://www.bortzmeyer.org/faut-vraiment-payer.html --2016-03-26 15:54:00-- https://www.bortzmeyer.org/faut-vraiment-payer.html Resolving www.bortzmeyer.org (www.bortzmeyer.org)... 2001:4b98:dc0:41:216:3eff:fece:1902, 2605:4500:2:245b::42, 204.62.14.153 Connecting to www.bortzmeyer.org (www.bortzmeyer.org)|2001:4b98:dc0:41:216:3eff:fece:1902|:443... connected. HTTP request sent, awaiting response... 402 Payment Required 2016-03-26 15:54:00 ERROR 402: Payment Required.
On peut envisager plein de choses dans cette réponse analysable par une machine, comme un URI unique pour ce problème donné, qui pourrait être, par exemple, transmis au support pour faciliter la communication. Ou bien un URI d'un service REST de paiement permettant d'envoyer l'argent souhaité. Mais, naturellement, l'utilisation de cette réponse est facultative : parfois, le code de statut est suffisant et il n'y a rien à ajouter (c'est souvent le cas du 404), et parfois il vaut mieux utiliser un format spécifique à l'application utilisée (c'est d'ailleurs le cas pour toutes les API développées avant ce RFC). Ceci dit, pour les nouvelles applications, le mécanisme décrit dans ce RFC peut être très utile, pour doter toutes les applications d'un mécanisme commun de signalement des erreurs et problèmes.
Le modèle de données utilisé est celui de
JSON et le type MIME
est application/problem+json
. Comme je l'ai
dit plus haut, il y a aussi une version XML
mais la référence est le JSON. La section 3 du RFC décrit ce
modèle. Commençons par un exemple, une API qui demandait entre
autres d'indiquer un âge et à qui on a envoyé un nombre négatif :
HTTP/1.1 400 Bad Request Content-Type: application/problem+json Content-Language: en { "type": "https://example.net/validation-error", "title": "Your request parameters didn't validate.", "invalid-params": [ { "name": "age", "reason": "must be a positive integer" } ] }
Ce message d'erreur est de type
https://example.net/validation-error
, une
explication en langue naturelle est donnée par le membre
title
, et la liste des paramètres invalides
est donnée dans le membre (une extension à la norme) invalid-params
.
Quels sont les membres possibles de l'objet JSON renvoyé ?
type
est un
URI (il est donc unique) servant
d'identificateur au problème, par exemple lorsqu'on va écrire au support. Il est recommandé qu'il soit
déréférençable (c'est-à-dire qu'on puisse le visiter avec un
navigateur Web et obtenir des informations sur le problème en
question). S'il est absent, sa valeur par défaut est le très
vide about:blank
(RFC 6694, section 3).title
est un titre conçu pour des
humains, par exemple pour les messages d'erreurs présentés à l'utilisateur. Étant en
langue naturelle, il est, contrairement au
type
, ambigu. Il peut être
adapté à la langue de l'utilisateur, via l'habituelle
négociation de contenu de HTTP. detail
(absent dans l'exemple ci-dessus) le complète éventuellement. Le
RFC précise que detail
est fait pour
l'utilisateur, pas pour le programmeur qui a conçu le
service. Il devrait donc contenir des informations aidant
l'utilisateur à corriger sa requête, pas des informations de
débogage (pas de pile d'appels
Java, par exemple...) D'ailleurs, envoyer
ces informations de débogage poserait un problème de sécurité
(cf. section 5).instance
(absent dans l'exemple) est un URI qui,
contrairement à type
, n'identifie pas la
classe du problème mais une instance particulière. Si
http://example.com/not-enough-credit
indique la
classe « pas assez d'argent »,
https://example.com/account/12345/msgs/abc
va indiquer le problème d'argent d'un compte particulier.Notez que type
et
instance
peuvent être des URI relatifs.
Voici maintenant un exemple sur mon blog (c'est conçu comme une application REST donc les résultats sont toujours en JSON et, en effet, ce n'est pas en HTTPS, ce serait intolérable en production) :
% curl -v https://www.bortzmeyer.org/apps/payme ... < HTTP/1.1 402 Payment required ... < Content-Length: 253 < Content-Type: application/problem+json < { "type": "http://errors.bortzmeyer.org/nopay", "detail": "Bitcoin address 1HtNJ6ZFUc9yu9u2qAwB4tGdGwPQasQGax, Ethereum address 0xbe1f2ac71a9703275a4d3ea01a340f378c931740, Flattr https://flattr.com/profile/bortzmeyer", "title": "You must pay" } % curl -v https://www.bortzmeyer.org/apps/payme\?pay=30 ... < HTTP/1.1 200 OK < Content-Length: 36 < Content-Type: application/json < { "title": "OK, 30 credits paid" }
Le code Python WSGI correspondant est :
def payme(start_response, environ): form = cgi.parse_qs(environ['QUERY_STRING']) response_headers = [] amount = 0 if form.has_key("pay"): try: amount = int(form["pay"][0]) except ValueError: # Bad syntax amount = 0 if amount > 0: status = '200 OK' response_headers.append(('Content-type', 'application/json')) output = json.dumps({"title": "OK, %i credits paid" % amount}, indent=2) else: status = '402 Payment required' response_headers.append(('Content-type', 'application/problem+json')) output = json.dumps({"type": "http://errors.bortzmeyer.org/nopay", "title": "You must pay", "detail": "Bitcoin address 1HtNJ6ZFUc9yu9u2qAwB4tGdGwPQasQGax, Ethereum address 0xbe1f2ac71a9703275a4d3ea01a340f378c931740, Flattr https://flattr.com/profile/bortzmeyer"}, indent=2) response_headers.append(('Content-Length', str(len(output)))) start_response(status, response_headers) return [output]
Si vous n'avez pas ce que vous voulez dans les membres prévus,
vous pouvez étendre l'objet JSON. Les clients doivent donc ignorer
les membres inconnus. C'est le cas du
invalid-params
dans l'exemple, qui n'est pas
un membre standard.
Bien, maintenant, vous êtes programmeur dans une start-up, vous créez un nouveau
service qui a une API, un nom de domaine en
.io
, un
business plan pipeau et vous vous demandez si
vous devez utiliser ce RFC et comment. La section 4 du RFC fournit
quelques conseils. D'abord, je le répète, ce n'est pas un outil de
débogage pour vous, ne serait-ce que pour
des raisons de sécurité (cf. section 5). C'est un outil pour aider
vos utilisateurs. Ensuite, si le problème est un problème
classique et standard, il est inutile de se servir de ce RFC. Si
l'utilisateur demande une ressource qui n'existe pas, le
traditionnel et générique 404 (RFC 7231,
section 6.5.4) convient parfaitement et je ne vois pas de raison
d'ajouter des détails analysables par une machine (dans une page
HTML d'erreur, c'est différent, on peut
fournir des conseils aux visiteurs, mais rappelez-vous que ce RFC
est pour les API, quand le client est un programme).
D'autre part, une application peut avoir de très bonnes raisons d'utiliser un format à elle pour décrire en détail les problèmes. (Sans compter les applications existantes qui ne vont évidemment pas modifier la définition de leur API juste pour coller à ce RFC.)
En revanche, une application nouvelle, qui n'a pas de format d'erreur établi, a tout intérêt à utiliser le cadre de ce RFC plutôt que de réinventer la roue. Dans ce cas, vous allez devoir définir :
type
(le seul type prédéfini est about:blank
),invalid-params
plus haut).Ces extensions peuvent utiliser les liens de HTTP (RFC 8288).
Le format principal décrit par ce RFC utilise JSON. Mais, comme il y a des goûts différents, il y a aussi une variante XML, décrite dans l'annexe A. Elle est spécifiée en Relax NG. Le modèle de données étant le même, cela donne à peu près :
start = problem problem = element problem { ( element type { xsd:anyURI }? & element title { xsd:string }? & element detail { xsd:string }? & element status { xsd:positiveInteger }? & element instance { xsd:anyURI }? ), anyNsElement }
Et le résultat serait :
HTTP/1.1 400 Bad Request Content-Type: application/problem+xml Content-Language: en <?xml version="1.0" encoding="UTF-8"?> <problem xmlns="urn:ietf:rfc:XXXX"> <type>https://example.net/validation-error</type> <title>Your request parameters didn't validate.</title> <invalid-params><param><name>age</name><reason>must be a positive integer</reason></param></invalid-params> </problem>
On a presque fini, quelques petits mots sur la sécurité en section 5 : attention à ne pas laisser fuiter de l'information qui pourrait aider un attaquant à préparer son attaque. Il faut notamment se méfier des détails de mise en œuvre (du genre afficher la requête SQL qui a échoué...)
Les deux nouveaux types MIME,
application/problem+json
et
application/problem+xml
figurent désormais
dans le registre IANA.
Les développeurs d'API n'ont pas attendu ce RFC pour renvoyer des
messages d'erreurs structurés, utilisant d'autres schémas (voici, par
exemple, les erreurs possibles
de l'API Github). Un concurrent sérieux à ce RFC est, par
exemple,
qui a son propre mécanisme de
signalement d'erreur.
http://jsonapi.org/
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : M. Douglass (Spherical Cow
Group), C. Daboo (Apple)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tzdist
Première rédaction de cet article le 1 avril 2016
Ah, les fuseaux horaires... Quelle source infinie de complications pour le programmeur, pour l'administrateur système de machines situées partout dans le monde, ou tout simplement pour le voyageur ou l'organisateur de télé-réunions internationales... Comme tout serait plus simple si, comme dans le roman d'Asimov « Les cavernes d'acier », les hommes vivaient en permanence sous terre, utilisant un temps uniforme. Mais, en attendant ce futur béni, il faut bien gérer les fuseaux horaires (time zones). Il existe une base de données officielle de ces fuseaux, il ne reste plus qu'à la distribuer efficacement, pour que toute machine connectée à l'Internet ait la même information. C'est le but du protocole normalisé dans ce RFC.
Que contient une base de données des fuseaux horaires (section 1 du RFC) ? Typiquement une liste de ces fuseaux avec, pour chacun d'entre eux, son décalage par rapport à UTC et ses règles concernant l'heure d'été. Les fuseaux ne suivent pas strictement le méridien, ils collent en général à des frontières inter ou intra-étatiques. Les fuseaux eux-même, et leurs décalages avec UTC, sont très stables. Mais les règles concernant l'heure d'été changent, elles, souvent. Il y a aussi le problème des secondes intercalaires, qui sont ajoutées (ou, en théorie, retirées) par l'IERS de manière imprévisible (car la rotation de la Terre n'est pas prévisible). La base actuelle représente un travail d'érudition formidable.
Au passage, un point de terminologie. Le RFC parle de « time zone » là où on dit en général en français « fuseau horaire ». Le terme français n'est pas idéal car il fait penser à un fuseau allant d'un pôle à l'autre (et englobant donc des pays différents, ayant des heures d'été différentes) alors qu'une time zone est plus restreinte. Il faut donc bien se rappeler qu'on parle ici de zones limitées à un pays, et ayant des règles (décalage avec UTC, heure d'été) uniformes. Il faut donc peut-être mieux dire « zone » ou « zone horaire » en français.
Cette information est essentielle pour les protocoles et les
formats qui gèrent le temps, comme
iCalendar (RFC 5545),
ainsi que pour les systèmes
d'exploitation. Il faut donc maintenir à jour la base
de données et, jusqu'à ce RFC, il n'existait pas de mécanisme
standard pour cela. Par exemple, pour un système d'exploitation
comme Debian, la mise à jour se fait
typiquement via le mainteneur d'un paquetage « base des fuseaux
horaires » (chez Debian, le paquetage se nomme tzdata
), qui introduit les changements dans son paquetage,
paquetage qui est ensuite installé sur chaque machine lorsque
l'administrateur système décide des mises à jour. Si le système
est vieux et plus maintenu, ce sera à l'administratreur système
local de « patcher » ses fichiers. Parfois, des
paquetages viennent avec leur propre base des fuseaux horaires,
distincte de celle du système, pour compliquer un peu les choses.
Au passage, signalons que ce RFC normalise le protocole mais qu'il faut également disposer d'une source de données de référence. Il en existe une à l'IANA, décrite dans le RFC 6557.
La section 2 décrit à grands traits l'architecture du système. Tout en amont, des contributeurs envoient des données sur les fuseaux horaires, elles sont agrégées par le fournisseur de référence (root provider, par exemple l'IANA citée plus haut). Ce fournisseur l'envoie ensuite aux clients (par exemple par le protocole de ce RFC). Le schéma du RFC est un peu plus compliqué, supposant que divers intermédiaires pourraient apparaitre. Notez que le protocole décrit ici est entre fournisseur et clients. En amont (entre contributeurs et fournisseur), il n'y a pas de mécanisme spécifié.
La section 3 de notre RFC définit la terminologie. Une zone
(time zone) se caractérise donc par un ensemble
de règles uniformes. La zone a un nom (utilisé par exemple dans la
propriété TZID
du RFC 5545) mais il n'existe pas de norme pour cela. Chaque
fournisseur pourrait utiliser son schéma de nommage. Ainsi, la
base IANA utilise un nom de région, une
barre oblique et un nom de pays ou de ville comme
Europe/Paris
ou Indian/Cocos
. En tout
cas, il faut se méfier des abréviations ambigues, n'ayant souvent
qu'une signification locale, comme PST (qui peut désigner
trois
zones différentes).
L'information sur les zones change (autrement, on n'aurait pas besoin d'un protocole pour télécharger les mises à jour) et il est donc important d'avoir un numéro de version permettant de savoir si on a bien la dernière version. Il peut être global à la base, ou bien spécifique à chaque zone.
Maintenant, le protocole lui-même (section 4 du RFC). Il repose, comme souvent de nos jours, sur le couple « HTTP (RFC 7230) et JSON (RFC 8259) », ce dernier servant à représenter les méta-données sur les zones. Les ressources auxquelles on accède en HTTP utilisent les gabarits d'URI du RFC 6570. Et les données elle-mêmes, les informations sur une zone horaire, en quoi sont-elles codées ? Le format par défaut est celui d'iCalendar (RFC 5545). Mais on peut aussi utiliser la représentation en XML du RFC 6321 ou celle en JSON du RFC 7265. La classique négociation de contenu de HTTP (RFC 7231, section 5.3.2) sert au client à choisir son format parmi ceux que le serveur veut bien fournir.
La base peut être assez grosse et les clients vouloir la toute dernière version. La charge sur le réseau des fournisseurs risquerait alors de devenir insupportable. C'est pourquoi il est possible de faire des requêtes conditionnelles, de façon à ne récupérer des données que si elles sont nouvelles. Là encore, c'est du classique HTTP avec les Etags (RFC 7232). Un client peut alors interroger le serveur du fournisseur une fois par jour (valeur recommandée par le RFC) sans risque de saturer le réseau.
Si le client reçoit uniquement le décalage avec UTC et les règles pour l'heure d'été, calculer une heure dans le futur peut être délicat car ces règles sont complexes. Le protocole prévoit donc la possibilité pour le client de demander au serveur de faire ces calculs et de lui envoyer les résultats.
Et si ça ne marche pas, que le serveur, pour une raison ou pour une autre, ne peut pas envoyer ce qui lui est demandé ? Il doit alors utiliser les erreurs structurées du RFC 7807 pour signaler ce qui ne va pas. (Les types d'erreurs possibles figurent dans un registre IANA.)
Comment est-ce qu'un client de ce protocole trouve le serveur ?
Il doit de toute façon connaître le nom de
domaine de son fournisseur, supposons ici
example.net
. Ensuite, il y a au moins deux
méthodes :
_timezone._tcp.example.net
. Il obtiendra
ainsi le nom du serveur et le port à
utiliser. Un enregistrement supplémentaire, sous le même nom que
l'enregistrement SRV, de type TXT, indique un éventuel chemin à
ajouter dans l'URI..well-known
du RFC 8615, en faisant une requête HTTP pour la ressource timezone
.La section 5 du RFC décrit ensuite les actions que le serveur
peut effectuer à la demande. Elles sont spécifiées en utilisant
les gabarits du RFC 6570. Donc, par exemple,
un gabarit {/service-prefix}/capabilities
indique que le client doit ajouter
/capabilities
au préfixe de chemin découvert comme
indiqué précédemment. Prenons un exemple complet : le client sait
que son fournisseur de zones horaires est
example.net
. Il fait deux requêtes
DNS et obtient deux enregistrements :
_timezone._tcp.example.net. SRV 0 1 8081 tz.example.com. _timezone._tcp.example.net. TXT "path=/timezones"
S'il cherche à déterminer les capacités du serveur, il va alors
faire une requête à l'URL
http://tz.example.com:8081/timezones/capabilities
.
C'est quoi, ces capabilities que je viens
d'utiliser dans l'exemple ? C'est la première des actions
possibles sur un serveur. Comme son nom l'indique, elle renverra
un objet JSON contenant un membre
actions
qui sera la liste des actions
possibles sur ce serveur (avec, pour chacune, le gabarit d'URI à
utiliser). Une liste des actions standards possibles figure dans un
registre IANA.
L'action list
, elle, donne la liste des
zones horaires connues du serveur. Et l'action
get
renvoie les données pour une zone
précise. Son gabarit est
{/service-prefix,data-prefix}/zones{/tzid}{?start,end}
(tzid
étant l'identificateur de la zone, par
exemple Pacific/Noumea
)
et un exemple d'utilisation est :
[Requête] GET /timezones/zones/America%2FNew_York HTTP/1.1 Host: tz.example.com:8081 Accept:text/calendar [Réponse] HTTP/1.1 200 OK Date: Wed, 4 Jun 2008 09:32:12 GMT Content-Type: text/calendar; charset="utf-8" Content-Length: xxxx ETag: "123456789-000-111" BEGIN:VCALENDAR ... BEGIN:VTIMEZONE TZID:America/New_York ... END:VTIMEZONE END:VCALENDAR
Les codes d'erreur habituels de HTTP sont utilisés donc,
par exemple, si on demande un tzid
inconnu,
on récupérera un beau 404, mais avec le corps de la réponse en
JSON, suivant le RFC 7807 :
[Requête] GET /timezones/zones/Atlantid%2FPlutopolis HTTP/1.1 Host: tz.example.com:8081 Accept:text/calendar [Réponse] HTTP/1.1 404 Not Found Date: Wed, 4 Jun 2008 09:32:12 GMT Content-Type: application/problem+json; charset="utf-8" Content-Language: en Content-Length: xxxx { "type": "urn:ietf:params:tzdist:error:tzid-not-found", "title": "Time zone identifier was not found on this server", "status": 404 }
Il existe plusieurs autres actions, comme
expand
qui dit au serveur de faire les
calculs d'heure d'été lui-même, ou find
, qui
permet de chercher une zone par une partie de son nom.
Notez bien qu'il n'y a pas d'URI fixe et pré-déterminé pour les actions : il faut utiliser les gabarits pour les générer.
Les détails des objets JSON qui peuvent être renvoyés en réponse à ces actions figurent en section 6 de notre RFC.
Et la sécurité ? Elle est cruciale car, si on peut changer la connaissance qu'une machine a de l'heure, plein d'attaques deviennent possibles (fausser les estampilles temporelles dans les journaux, activer ou désactiver un certificat, etc). Il faut donc prendre soin d'utiliser un fournisseur fiable, et de récupérer la base de manière sécurisée. (HTTPS, forcément, et avec vérification sérieuse de l'identité du serveur, en suivant le RFC 6125 ou bien le RFC 6698).
Il n'y a apparemment pour le moment qu'une mise en œuvre, dans
le système de calendrier
Bedework. Je
ne connais pas encore de service disponible qui serve la base
de données suivant ce protocole (c'est pour cela que je ne montre
pas d'exemple réel). Notamment, l'IANA ne le fait pas (ce n'était
pas demandé dans le RFC). Il existe des services qui distribue la base,
mais avec un autre protocole, comme https://timezonedb.com/api
.
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : V. Dolmatov (Research Computer Center MSU)
Pour information
Première rédaction de cet article le 25 mars 2016
Encore un algorithme de cryptographie venu de l'Est, avec cette spécification sous forme de RFC d'un algorithme GOST, connu sous le petit nom de « Kuznyechik » (dans la transcription anglo-saxonne), et, plus formellement, sous celui de GOST R 34.12-2015. C'est un algorithme de chiffrement symétrique par blocs.
Comme d'autres algorithmes de cryptographie normalisés par GOST, Kuznyechik a été développé en partie par le secteur public (Service des communications spéciales et d'information du Service fédéral de protection de la Fédération de Russie) et par le secteur privé (InfoTeCS). Le décret n° 749 du 19 juin 2015, pris par l'Agence fédérale pour la régulation technique et la métrologie en a fait un algorithme russe officiel. C'est donc apparemment un concurrent d'AES.
Les sections 3 et 4 du RFC décrivent l'algorithme en détail. Pour les connaisseurs en cryptographie seulement, d'autant plus que le format actuel (c'est en cours de révision) des RFC n'est pas idéal pour décrire des mathématiques, il vaut mieux utiliser la version en anglais de la norme russe. Des vecteurs de test figurent en section 5.
Merci à André Sintzoff, qui sait utiliser Canard, canard, va.
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : A.B. Roach (Mozilla)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF rtcweb
Première rédaction de cet article le 24 mars 2016
Ce court RFC expose les exigences portant sur les codecs vidéo de WebRTC. Le point principal était le choix du codec obligatoire. Après une très longue et très amère discussion à l'IETF, le choix a été plus politicien que technique : le codec H.264 est obligatoire au même titre que VP8.
Le système WebRTC (voir le RFC 7478) permet de faire de la vidéoconférence, notamment entre deux navigateurs Web. Il permet aux parties qui communiquent de choisir le codec. Un point important des protocoles IETF est que, lorsqu'il existe un tel choix, au moins un des choix doit être mis en œuvre dans toutes les implémentations. Le but est d'assurer l'interopérabilité, en vérifiant que les programmes ont tous au moins un codec en commun.
Mais quel codec choisir ? Il y avait deux concurrents, un codec de l'UIT, H.264 (normalisé ici), qui avait la faveur des compagnies de télécommunication traditionnelles, et un codec issu de l'Internet, VP8 (RFC 6386), qui était le plus apprécié par les entreprises Internet et par le monde du logiciel libre. Le débat a été très long et très houleux à l'IETF. Le problème n'était pas uniquement sentimental, il portait également sur les innombrables brevets qui verrouillent H.264 (son concurrent VP8 a aussi des brevets, mais avec une licence très libérale pour la plupart). Quant aux critiques sur VP8, elles portaient surtout sur sa relative jeunesse (en fait, certaines entreprises avaient investi pas mal dans H.264 et ne voulaient pas recommencer).
Le débat a donc duré, générant plus de mille messages sur la liste de diffusion du groupe de travail, et occupant une bonne partie des réunions physiques de l'IETF (réunions IETF 81, 82, 85, 86, et 88...), affectant notablement la patience des participants. Des tas de solutions ont été proposées pour sortir de l'affrontement, y compris un inhabituel vote (dans ce message, MTI = Mandatory To Implement). Le sujet est revenu sur le tapis et revenu encore. La solution, adoptée à la réunion IETF 91 à Honolulu, a finalement été de prendre les deux.
Notez bien que ce RFC n'est pas la description complète de WebRTC, loin de là. C'est juste le cahier des charges minimum des codecs (le cahier des charges du transport des données a été publié dans le RFC 8834).
D'abord, les considérations générales, indépendantes du codec (section 3). Par exemple, l'espace de couleur à utiliser est sRGB. Cette section conseille également sur l'utilisation de la caméra de capture : si elle le permet, il est recommandé d'utiliser ses capacités propres, comme la mise au point automatique, ou le réglage automatique de la luminosité. Le RFC rappelle également que la résolution de la source peut changer en cours de route (parce que la source est une fenêtre de l'écran qui change soudain de taille, ou bien parce que la source est la caméra d'un mobile qui change soudain d'orientation, cf. section 4) et que WebRTC doit donc s'y adapter.
La section 5 est le morceau sensible du RFC : la description du, ou plutôt des, codecs obligatoires. Le principe est que toute mise en œuvre de WebRTC doit accepter VP8 et H.264. Une note du RFC précise que, si le problème des brevets s'arrange pour un des codecs et pas pour l'autre, cette décision pourra être reconsidérée et un des codecs devenir optionnel (évidemment, tout le monde pense à H.264, beaucoup plus lardé de brevets avec licences hostiles). À noter que des codecs comme Theora ont été discutés, et sont possibles dans WebRTC, mais sans qu'il ait vraiment été envisagé de les rendre obligatoires.
La section 6 précise ensuite quelques exigences techniques pour chacun des codecs. Notamment, plusieurs options de H.264 ont une valeur fixe en WebRTC, pour simplifier la tâche des programmeurs. (H.264 a bien trop de variables possibles.)
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : S. Leonard (Penango)
Pour information
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 23 mars 2016
Ce RFC est un complément du RFC 7763, qui enregistrait le type
MIME text/markdown
. Il contient
tout ce qui ne tenait pas dans le RFC original, c'est donc un
pot-pourri de considérations philosophiques, de descriptions des
variantes les plus courantes de Markdown, de techniques de
stockage local de contenus en Markdown...
Le RFC 7763 était plus sec, contenant
uniquement ce qui était nécessaire à l'enregistrement de
text/markdown
. Cet autre RFC est plus disert,
expliquant d'abord (section 1) la philosophie de Markdown, et ses usages. Rappelons
donc que Markdown est un format de
marquage du texte. Lorsqu'on veut stocker
des textes (romans, rapports techniques, articles scientifiques,
lettres d'amour, etc) sur un système informatique, on a plusieurs
solutions : elles vont du texte brut à un
format binaire. Le texte brut est le stockage des seuls
caractères Unicode (cf. RFC 6838, section 4.2.1 : le texte est distribué sur
l'Internet avec un type MIME
text/quelquechose
, par exemple
text/plain
pour le texte brut). Son gros avantage est
qu'il est lisible et modifiable avec n'importe quel logiciel. Bon, en fait, le texte brut n'est jamais tout à fait
brut. Il contient quelques caractères de contrôle comme le
saut de ligne ou la marque d'un
nouveau paragraphe (U+2029 en
Unicode, mais ce séparateur de paragraphe n'est que
rarement géré par les logiciels).
À l'autre extrémité se trouve les formats binaires : lisibles
et modifiables uniquement par des applications spécifiques (et
c'est pour cela qu'ils sont distribués avec le type MIME
application/quelquechose
).
Entre les deux se trouvent le texte formaté ou marqué. Il s'agit à première vue de texte brut mais il inclut en fait quelques marques qui ont une signification non prévue par le jeu de caractères. Un exemple classique est la mise en évidence qui, en Markdown, se fait en encadrant le texte avec des étoiles : « il est *très* important de comprendre que... » Le texte reste lisible sans logiciel spécifique (d'autant plus qu'ici, Markdown reprend une ancienne convention d'écriture largement utilisée sur l'Internet). Et n'importe quel éditeur (et n'importe quel clavier) permet de créer un tel texte.
On sépare souvent les formats de texte marqués en formats stricts (markup) et formats légers (lightweight markup). Les premiers sont plus proches des formats binaires, dans la mesure où ils ont des marques bien séparées du texte, et suivent une syntaxe rigide. Ce sont par exemple XML et LaTeX. Cette syntaxe rigide permet de vérifier la qualité technique du document et mène à une meilleure interopérabilité. Mais elle peut être pénible pour les utilisateurs débutants ou occasionnels. Plus proches du texte brut, les formats de texte marqué légers ont des marques plus discrètes, et ont souvent une syntaxe moins formelle, plus tolérante (un cas extrême est Markdown, qui ne connait même pas la notion d'erreur de syntaxe). Ils sont conçus pour être facilement accessibles au nouvel utilisateur (ou à celui qui n'a pas pratiqué depuis longtemps). Jeff Atwood qualifiait ces formats légers d'« humains ».
Markdown est issu d'un langage originellement développé par John Gruber (et Aaron Swartz). Il a été rapidement un grand succès, notamment pour les tâches simples (comme de saisir un commentaire ou un rapport de bogue dans un formulaire Web). Et il a connu de nombreuses extensions. Beaucoup de programmes et de langages savent traiter le Markdown, chacun avec sa variante particulière.
Markdown est clairement dans le camp de l'« informalité ». Un des événements fondateurs fut un problème avec de nombreux flux de syndication rendus invalides juste par un article contenant du code incorrect (la norme XML dit bien qu'une fois qu'une erreur apparait dans un fichier XML, le processeur ne doit pas continuer). Avec Markdown, cela ne risque pas d'arriver, tout texte est du Markdown légal. Cela ressemble au fameux principe de robustesse des protocoles réseau. (À noter que ce principe a été suivi, en pratique, par la plupart des navigateurs Web, lorsqu'il s'agit d'analyser du HTML. Résultat, les auteurs se sont habitués à taper n'importe quoi et le Web est aujourd'hui une poubelle de fichiers HTML bourrés d'erreurs.) Lorsqu'on soumet un fichier Markdown à un processeur, cela « marche » toujours. Si on n'est pas satisfait du résultat, on modifie le source et on réessaie (cf. « The Talk Show: Ep. 88: 'Cat Pictures' (Side 1) ».) Pas de processus de validation, comme en XML ou HTML strict, seul le résultat compte.
Malgré ou bien à cause de ce principe, Markdown est un grand succès. On le trouve utilisé partout et il est probablement le plus populaire des langages de marquage « légers ». On peut l'éditer avec n'importe quel logiciel et lire le source, même sans avoir subi aucun apprentissage de sa syntaxe. Des gens utilisent Markdown pour des articles scientifiques, l'écriture de scénarios, ou pour faire des maths, le domaine qui était autrefois le bastion de LaTeX. (Personnellement, je m'en sers pour les rapports de bogue sur GitHub, les README de logiciels, les rapports techniques internes à mon employeur, LaTeX ou DocBook prenant le relais pour les choses plus « sérieuses ». Markdown avec les sites qui le gèrent permet aussi de faire du mini-blogging très simplement et très rapidement. Regardez aussi le témoignage de Yann Houry.)
Depuis le RFC 7763, il existe un
type MIME pour identifier Markdown,
text/markdown
. (Une extension de nom de
fichier comme .md
ne suffit pas : tout le
contenu n'est pas forcément dans des fichiers.) Un seul type MIME
décrit toutes les variantes puisque n'importe quel processeur
pourra traiter n'importe quelle variante (même si le résultat ne
sera pas toujours celui voulu.) À noter que la
plupart des variantes de Markdown n'ont pas de mécanisme pour
mettre les métadonnées : il faut les
placer à l'extérieur.
Comment préserver ce type MIME lorsque du contenu Markdown est
copié sur l'Internet ? Parfois, la copie ne préserve pas cette
information et Markdown n'a pas l'équivalent du <?xml
version="1.0">
qui, au début des contenus en
XML, indique sans ambiguité qu'il s'agit
de XML (il a été proposé de l'introduire mais cela peut casser les
mécanismes de métadonnées existants). Utiliser le contexte (le
répertoire où se trouve un fichier, par exemple...) est casse-gueule
car, justement, l'envoi d'un document fait facilement perdre le
contexte. La section 2 du RFC propose et discute plusieurs
stratégies. Utiliser le nom de fichier, lorsqu'on passe par des
fichiers, est possible. mon-roman.md
est un
texte en Markdown, on le sait par l'extension. Et la variante ? On
peut l'indiquer avant, par exemple
mon-roman.pandoc.md
si le texte est écrit
dans la variante Pandoc. Si le
système de fichiers permet de stocker des
attributs ou métadonnées, c'est une autre bonne solution.
Mais il y en a d'autres. Une solution, suggérée par le RFC 6533, est de
stocker les métadonnées et notamment l'en-tête
MIME dans un fichier séparé,
conventionnellement nommé. Si le fichier texte est
mon-roman.md
, le fichier des métadonnées
pourrait être mon-roman.md.headers
.
Ou alors dans le même fichier ? L'idée est de transformer le fichier Markdown en un fichier au format IMF (Internet Message Format, spécifié dans le RFC 5322) en mettant des en-têtes d'abord, puis le contenu en Markdown :
MIME-Version: 1.0 Content-Type: text/markdown; charset=utf-8 Date: Wed, 10 Feb 2016 20:59:06 +0100 (CET) Exemple d'un fichier « armé » ============================= Notez la ligne vide qui sépare les en-têtes du corps. Il est *important* que son extension ne soit pas .md ou .markdown, ce n'est plus du Markdown pur mais de l'IMF, son extension doit donc être .eml ou .msg. ...
Le RFC contient plein d'autres stratégies rigolotes pour résoudre ce problème. Par exemple, on pourrait, lors de la réception, voire de l'envoi, d'un contenu en Markdown, générer/envoyer un script qui contienne les commandes permettant de le traiter convenablement. Ou on pourrait carrément envoyer le résultat du traitement, et pas le Markdown : si on veut juste que le destinataire puisse lire, pas la peine de lui envoyer le « source », on pourrait juste lui transmettre le XHTML (je ne suis pas sûr d'être d'accord avec cette curieuse idée : un des gros avantages de Markdown est qu'il est lisible même si on n'a aucun logiciel spécifique, et si on n'a jamais entendu parler de ce format).
Cette section 2 se termine avec le cas des
VCS. Subversion
offre un excellent mécanisme de stockage et de versionnement des
méta-données. Il suffit donc de définir la métadonnée standard
svn:mime-type
et on ne risque plus de perdre
cette information :
% svn propset svn:mime-type text/markdown mon-roman.md property 'svn:mime-type' set on 'mon-roman.md' % svn commit -m "Type indiqué" mon-roman.md ...
Hélas, git n'a, lui, aucun moyen propre de stocker les métadonnées. Il faut donc recourir à une autre des stratégies mentionnées plus haut (fichier d'en-têtes avec un nom conventionnel, extension du fichier, etc).
La section 3 de notre RFC est consacrée aux formulaires d'enregistrement des différentes variantes de Markdown, désormais mémorisées à l'IANA. Cette section est utile si vous voulez vous renseigner sur une variante particulière, mais aussi si vous avez développé votre propre variante (sans doute une mauvaise idée mais les programmeurs adorent réinventer la roue) et que vous voulez l'enregistrer à l'IANA. Vous pouvez alors utiliser les cas de cette section comme exemples concrets, avant d'écrire votre propre demande.
Prenons par exemple la variante que j'utilise le plus souvent,
Pandoc
. Contrairement au Markdown originel,
elle ne vise pas uniquement la génération de
HTML mais également des tas d'autres
formats de sortie. Elle a des tas d'extensions par rapport à
l'original, comme les tableaux ou bien les notes de bas
de page. Sa fiche contient :
Identifier: pandoc Name: Pandoc ... Extensions to turn off (on by default): escaped_line_breaks blank_before_header header_attributes ... References: <http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown> Contact Information: (individual) Prof. John MacFarlane <jgm@berkeley.edu> <http://johnmacfarlane.net/>
Les autres variantes enregistrées via cette section 3 sont MultiMarkdown, GitHub, Fountain, CommonMark, Markdown for RFCs, Pandoc for RFCs (RFC 7328) et PHP Markdown (utilisé par plusieurs CMS comme Drupal).
La section 4 de notre RFC fournit des exemples de ces différentes variantes et de ce qu'elles apportent. Par exemple, la variante GitHub apporte la transformation automatique des URL en liens hypertexte.
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : S. Bortzmeyer (AFNIC)
Expérimental
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 23 mars 2016
La meilleure façon de protéger les données contre la surveillance, c'est de ne pas avoir de données. Ce principe de base de la protection de la vie privée est souvent oublié. C'est pourtant un des deux piliers de la confidentialité, avec la protection technique des données. Le DNS a pendant longtemps transmis trop de données, et ce RFC décrit une technique qui va limiter les fuites, la QNAME minimisation, ou « réduction de la question posée ». (Il a depuis été remplacé par le RFC 9156.) Demandez à votre FAI ou à votre service informatique de l'activer !
Si vous regardez les vidéos sur le fonctionnement du
DNS (comme celle-ci) ou lisez les textes expliquant « le
DNS pour les nuls », vous y trouverez souvent une fausse
explication de la résolution DNS, où les serveurs faisant autorité
ne reçoivent que la question strictement nécessaire. Ainsi, dans
la vidéo citée ci-dessus, le serveur de la
racine reçoit une question où ne figure que le
TLD. Mais la réalité du DNS, aujourd'hui,
est tout autre : les serveurs faisant autorité reçoivent la
totalité de question originale. Ainsi, si vous visitez
www.alcooliques-anonymes.fr
, la racine voit
que vous vous intéressez à l'alcoolisme, alors que ce n'était
nullement nécessaire pour son travail (puisqu'elle ne connait que
les TLD). Si votre logiciel
BitTorrent demande
_bittorrent-tracker._tcp.domain.example
, les
serveurs faisant autorité pour .example
sauront que vous faites du BitTorrent, alors qu'ils ne
connaissaient que les domaines situés immédiatement sous
.example
. Le RFC 7626
décrit plus en détail les problèmes de vie privée liés au DNS.
Dans le dernier cas, pour que la
résolution se passe bien, il aurait suffit de demander à la racine
« quels sont les serveurs de noms de .example
»
et à ces serveurs « quels sont les serveurs de noms de
domain.example
». C'est le principe de base
de la QNAME minimisation.
Bien sûr, on pourrait chiffrer le trafic DNS (et le groupe de travail DPRIVE de l'IETF travaille précisément sur ce sujet). Mais cela ne protège que contre un tiers écoutant le réseau : les serveurs faisant autorité verraient quand même les données et pourraient en faire ce qu'ils veulent. C'est pour cela qu'un principe de base en matière de protection de la vie privée est de marcher sur deux jambes (RFC 6973) : minimiser les données envoyées et les protéger. Lorsqu'on parle de vie privée, pas mal d'informaticiens réagissent en criant « cryptographie ! » alors que celle-ci ne protège pas contre tout et notamment pas contre le serveur à qui on parle.
Et pourquoi est-ce que les résolveurs DNS envoyaient la question complète (full QNAME où QNAME veut dire Query NAME) ? Uniquement parce que la protection de la vie privée n'était pas tellement prise en compte à l'époque ? Pas uniquement : il y avait quelques raisons techniques spécifiques à l'époque (le RFC les détaille mais, surtout, il ne faut pas oublier que toutes les décisions concernant le DNS n'ont pas forcément été mûrement réfléchies).
La section 2 décrit la QNAME minimisation. Elle est mise en œuvre dans le
résolveur DNS (aucun changement n'est fait
dans le serveur faisant autorité, la QNAME minimisation ne change pas le protocole DNS). Avant,
lorsqu'il recevait une requête demandant l'adresse
IPv6 pour
_foobar._tcp.sub.internautique.fr
et qu'il
connaissait les serveurs faisant autorité pour
.fr
, mais pas ceux
faisant autorité pour internautique.fr
, le
résolveur envoyait à l'AFNIC une requête
avec comme QNAME (Query NAME) le nom complet
_foobar._tcp.sub.internautique.fr
et comme
QTYPE (Query TYPE) AAAA
(indiquant une demande d'adresse IPv6). Désormais, le résolveur
moderne qui met en œuvre la QNAME minimisation
enverra une requête avec le QNAME
internautique.fr
et le QTYPE
NS
(demande des serveurs de noms). Plus
rigoureusement, la requête est faite avec un QNAME qui est
l'original, où on a retiré les premiers composants, jusqu'à un
seul composant de plus que celui pour lequel on connait les
serveurs faisant autorité.
Les experts en DNS ont noté un problème : il n'y a pas
forcément un jeu de serveurs faisant autorité pour chaque
composant. Si je prends
www.st-cyr.terre.defense.gouv.fr
, il n'y a
par exemple aujourd'hui pas de serveurs de noms pour
gouv.fr
, ce sont ceux de
.fr
. En termes
techniques, il n'y a pas de limite de zone (zone
cut, cf. RFC 2181, section 6) à
chaque composant. Dans le cas de ce dernier nom, il y a une limite
de zone entre la racine et .fr
, une autre
entre fr
et
defense.gouv.fr
mais pas entre
.fr
et gouv.fr
. Un
résolveur qui veut faire de la QNAME minimisation doit donc tenir compte des limites de
zone. S'il valide avec DNSSEC, pas de
problème, il les connait déjà, car leur connaissance est
nécessaire au bon fonctionnement de DNSSEC. Sinon, il doit les
trouver tout seul, par exemple avec l'algorithme de l'annexe
A.
Est-ce un changement « légal » du fonctionnement du résolveur DNS ? La section 4 discute ce problème et conclut que oui. La QNAME minimisation est permise par les RFC existants (RFC 1034, section 5.3.3 et RFC 1035, section 7.2). C'est un changement unilatéral de la part du résolveur, ne nécessitant pas de changement dans les serveurs faisant autorité. Comme c'est un changement unilatéral, différents résolveurs pourront choisir de la mettre en œuvre de façon légèrement différente. L'annexe B décrit certaines de ces alternatives, comme d'utiliser des requêtes « traditionnelles » avec le nom de domaine complet, au démarrage du résolveur, attendant que le cache soit peuplé pour passer à la QNAME minimisation, qui préserve la vie privée mais peut nécessiter davantage de paquets.
La QNAME minimisation ne change pas le protocole DNS. Elle ne pose donc pas de problème avec les vieux serveurs. En théorie car, en pratique, il existe pas mal de serveurs incorrects qui ne suivent pas les règles et poseront quelques problèmes (section 3 du RFC, voir aussi un intéressant exposé et un « storify » d'une discussion.) Le problème n'est en général pas dû aux serveurs en logiciel libre sérieux qui forment l'essentiel de l'infrastructure du DNS (BIND, NSD, Knot...) mais plutôt aux appliances boguées que certains s'obstinent à placer devant des serveurs qui marcheraient parfaitement autrement.
C'est par exemple le cas de certains répartiteurs de
charge qui répondent aux requêtes pour certains QTYPE
mais qui échouent lorsque le QTYPE vaut NS
(répondant, par exemple REFUSED
). Pire,
certains ne répondent pas du tout, comme ceux de
www.ratp.fr
.
Il s'agit bien d'une bogue, et qui cause plein de
problèmes, pas seulement à la QNAME minimisation.
Un autre problème est celui des serveurs bogués (comme
djbns) qui ne réagissent pas correctement aux
ENT. Qu'est-ce qu'un ENT ? Un Empty
Non-Terminal (terme décrit dans le RFC 8499, section 7) est un domaine qui n'a pas
d'enregistrements DNS mais qui a des sous-domaines qui en
ont. gouv.fr
, cité plus haut, est un ENT mais
ceux-ci sont particulièrement fréquents sous
ip6.arpa
. Normalement, la bonne réponse à un
ENT est le code NOERROR
, sans enregistrements
(ce qu'on appelle parfois NODATA
, bien que ce
dernier ne soit pas un code de retour explicite dans le
DNS). Mais certains serveurs boguées répondent à la place
NXDOMAIN
, code qui indique normalement que le
domaine n'existe pas (ce qui est faux). Voici ce que répond djbdns à une requête sur l'ENT
temporary.cr.yp.to
:
% dig A temporary.cr.yp.to ... ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 23636
C'est bien un ENT puisqu'il y a des noms en dessous (par exemple pairings.temporary.cr.yp.to
).
Le résolveur qui se
fierait à ce NXDOMAIN
croirait alors que sa
recherche est terminée et que le nom demandé n'existe pas. C'est
pour cela que les mises en œuvre existantes de la QNAME minimisation ont des comportements spécifiques pour les
réponses NXDOMAIN
, pour contourner cette
bogue.
La protection de la vie privée fait qu'on enverra moins de données. C'est bien le but. Résultat, les serveurs faisant autorité et les sniffeurs recevront moins d'information. Cela peut gêner certains gros silos de données, qui exploitaient cette information.
Et les performances ? Elles seront parfois meilleures et
parfois pires, avec la QNAME minimisation. Meilleures car le résolveur enverra
moins de requêtes aux serveurs faisant autorité. Aujourd'hui, si
un résolveur reçoit trois requêtes successives, pour
A.example
, B.example
et
C.example
, les trois requêtes seront envoyées
aux serveurs racine, et donneront toutes
les trois un NXDOMAIN
(puisque
.example
n'est pas délégué). Avec la QNAME minimisation,
seule la première requête déclenchera une demande à la racine,
pour le nom example
. Cela suffira au résolveur.
Par contre, les performances peuvent se dégrader dans certains
cas. Si un nom comporte beaucoup de composants (c'est
fréquent dans ip6.arpa
), la recherche
initiale des limites de zone nécessitera bien plus de
paquets. Ceci dit, cela ne durera que le temps de remplir le
cache, tout ira plus vite après, une fois que le résolveur
connaitra les limites de zone.
Ce RFC est issu du projet « DNS privacy », lancé initialement au CENTR, puis passé à l'IETF (le premier RFC de ce projet avait été le RFC 7626 ; comme lui, cette idée de QNAME minimisation était née dans un avion de la KLM).
À noter que Verisign a un brevet dont ils prétendent qu'il couvre la QNAME minimisation. Ils promettent une licence (attention, le diable est dans les détails) gratuite et non-discriminatoire. Ces brevets ont bien perturbé la réflexion du groupe de travail. Personnellement, je pense que ce brevet n'a pas de sens : l'idée de QNAME minimisation est évidente et avait déjà été discuté plusieurs fois, mais sans laisser de trace écrite précise, ce qui permet à Verisign de prétendre qu'il n'y a pas de prior art. Ce n'est sans doute pas un hasard si les deux premières mises en œuvre de la QNAME minimisation ont été faites en Europe, où il n'y a (normalement) pas de brevet logiciel. Ceci dit, lors des discussions sur la licence de ces brevets, en marge de la réunion IETF d'Honolulu, c'est Verisign qui a payé les boissons, reconnaissons-leur ce mérite.
La QNAME minimisation est mise en œuvre dans Unbound et
dans le résolveur
Knot (ce dernier n'étant pas encore officiellement publié).
Pour Knot (qui le fait par défaut), voici le résultat vu par tcpdump d'une requête
dig -x
d'une adresse
IPv6. Par exemple, le serveur racine n'a reçu
qu'une demande pour
.arpa
. Notez aussi que
Knot fait varier la casse (une protection
contre certains empoisonnements) :
02:36:39.673268 IP6 2400:8900::f03c:91ff:fe69:60d3.54216 > 2001:e30:1c1e:1::333.53: 38773% [1au] NS? aRpA. (33) 02:36:40.114074 IP6 2400:8900::f03c:91ff:fe69:60d3.59934 > 2001:dc3::35.53: 22056% [1au] NS? Ip6.aRPa. (37) 02:36:40.428545 IP6 2400:8900::f03c:91ff:fe69:60d3.47793 > 2001:500:86::86.53: 43002% [1au] NS? 2.ip6.arPA. (39) ...
Pour se protéger contre les serveurs bogués dont je parlais plus haut
(ceux qui répondent NXDOMAIN
en cas d'ENT), Knot
réessaie avec le QNAME complet lorsqu'il reçoit un
NXDOMAIN
(les deux dernières lignes). Mauvais pour la vie privée mais sans
doute nécessaire aujourd'hui (ici, par la faute d'Akamai) :
02:34:45.050913 IP 106.186.29.14.51228 > 128.175.13.17.53: 24014% [1au] A? WwW.UpENn.edU. (42) 02:34:45.227102 IP 128.175.13.17.53 > 106.186.29.14.51228: 24014*- 2/0/1 CNAME www.upenn.edu-dscg.edgesuite.net., RRSIG (270) 02:34:45.228413 IP6 2400:8900::f03c:91ff:fe69:60d3.46525 > 2001:503:231d::2:30.53: 52576% [1au] NS? edGeSUItE.NEt. (42) 02:34:45.297319 IP6 2001:503:231d::2:30.53 > 2400:8900::f03c:91ff:fe69:60d3.46525: 52576- 0/17/15 (1034) 02:34:45.298284 IP 106.186.29.14.45604 > 23.61.199.64.53: 22228 [1au] NS? EdU-DScG.EdGesUITe.nET. (51) 02:34:45.373238 IP 23.61.199.64.53 > 106.186.29.14.45604: 22228 NXDomain*- 0/1/1 (114) 02:34:45.373795 IP 106.186.29.14.34320 > 72.246.46.66.53: 1355 [1au] A? WWW.UPenN.edu-dSCG.EdgESuItE.net. (61)
Un autre exemple de ce repli sur les requêtes classiques est donné
ici, lorsque je demande
www.long.verylong.detail.example
. Comme le
TLD .example
n'existe pas,
Knot débraye hélas la QNAME minimisation :
20:08:49.615421 IP6 2400:8900::f03c:91ff:fe69:60d3.51723 > 2001:1398:1:21::8001.53: 19881% [1au] NS? ExaMpLE. (36) 20:08:49.900009 IP6 2400:8900::f03c:91ff:fe69:60d3.59917 > 2001:6d0:6d06::53.53: 40708% [1au] AAAA? www.LONg.VeRylONG.DEtaIl.eXamPLE. (61)
Même chose avec un ENT où la réponse est pourtant correcte. Knot se méfie et réessaie sans QNAME minimisation :
20:14:15.479872 IP6 2400:8900::f03c:91ff:fe69:60d3.45418 > 2001:67c:1010:11::53.53: 18200% [1au] NS? gOUV.Fr. (36) 20:14:15.740424 IP 106.186.29.14.33850 > 194.0.36.1.53: 54260% [1au] A? www.ST-cYr.TerRE.DeFeNSe.GouV.fR. (61)
Lorsque le cache commence à être rempli, Knot a besoin de moins de
requêtes. Ici, je lui ai demandé
l'adresse de www.bortzmeyer.org
, et il connaissait déjà les
serveurs de .org
, il passe
donc directement à la question « quels sont les serveurs de noms de
bortzmeyer.org
? » :
20:08:20.420757 IP 106.186.29.14.41889 > 199.249.120.1.53: 39126% [1au] NS? bOrtzMEYeR.oRg. (43) 20:08:20.941797 IP 106.186.29.14.35536 > 217.70.190.232.53: 33709% [1au] AAAA? Www.bOrtZmEyER.Org. (47)
Unbound a la QNAME minimisation depuis la version 1.5.7 (sortie en décembre 2015, cf. l'historique de ce travail). Ce n'est pas activé par défaut, il faut mettre dans la configuration :
server: qname-minimisation: yes
(Un pcap est disponible.)
Pour vérifier si votre résolveur met bien en œuvre la QNAME minimisation, vous
pouvez tester avec le domaine
qnamemintest.internet.nl
. Ici, le résolveur est un Unbound
récent :
% dig +nodnssec +short TXT qnamemintest.internet.nl a.b.qnamemin-test.internet.nl. "HOORAY - QNAME minimisation is enabled on your resolver :)!"
Avec un résolveur traditionnel (ici, Verisign Public DNS, qui utilise Unbound mais une vieille version) :
% dig @64.6.64.6 +nodnssec +short TXT qnamemintest.internet.nl a.b.qnamemin-test.internet.nl. "NO - QNAME minimisation is NOT enabled on your resolver :("
À noter qu'à la réunion de l'OARC à Buenos Aires, Ralph Dolmans a présenté un très intéressant exposé technique sur la mise en œuvre de la QNAME minimisation dans Unbound.
Questions articles sur la QNAME minimisation, notez celui de Robert Graham.
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : S. Leonard (Penango)
Pour information
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 23 mars 2016
Le format Markdown est un excellent
format léger de marquage de textes, permettant d'enrichir un
texte, sans pour autant avoir à apprendre un gros langage de
marquage comme LaTeX. Markdown est très bien
adapté aux courts rapports, aux articles simples, aux fichiers
README, à la génération
de pages Web... Markdown a de nombreuses variantes et le but de ce
nouveau RFC n'est pas de normaliser
Markdown (une tâche probablement impossible) mais juste
d'enregistrer un type MIME pour ce format,
text/markdown
. Donc, on décrit, on ne
normalise pas.
Markdown est un langage de marquage du texte, comme ReST (utilisé dans le livre CNP3) ou comme les langages des Wiki. On peut donc éditer du Markdown avec n'importe quel éditeur (mes lecteurs ne seront pas surpris d'apprendre que j'utilise Emacs). Le source Markdown est donc du texte lisible tel quel, sans logiciel spécifique, mais un logiciel peut le traiter pour produire une forme plus agréable et plus efficace, par exemple du HTML pour publication sur le Web.
Voici un exemple de document Markdown n'utilisant, sauf erreur, que
les constructions communes à toutes les variantes : test1.md
. On peut le traiter, par exemple avec discount,
une mise en œuvre simple de Markdown, en C, qui ne peut
produire que du HTML :
% markdown test1.md <h1>Début</h1> <p>Un test très simple en Markdown.</p> ... <h2>Suite</h2> ...
Mais on peut aussi utiliser le bien plus riche Pandoc, qui a de nombreuses extensions à Markdown, et peut produire beaucoup de formats de sortie, ici du PDF, via LaTeX :
% pandoc --to latex --latex-engine=xelatex -o test1.pdf test1.md % evince test1.pdf ...
Un point important de Markdown est qu'il n'y a jamais d'erreur de syntaxe (section 1 du RFC) : tout fichier texte est un fichier Markdown légal (même s'il ne donne pas toujours le résultat attendu par son auteur). C'est donc un monde très différent de LaTeX ou de XML (au passage, ce blog est écrit en XML). Markdown se veut un langage léger, imposant peu de contraintes et peu d'apprentissage. Avec Markdown, on a toujours un résultat, même suboptimal. Ce n'est pas considéré comme un problème. Si on veut du « sérieux », il faut utiliser LaTeX ou DocBook.
La « spécification » de Markdown est très grossière, et laisse le doute sur beaucoup de points mais le choix de l'IETF a été de ne pas essayer d'en écrire une correcte : Markdown est fait ainsi.
Un autre point important est le grand nombre de variantes, souvent incompatibles. L'auteur original, John Gruber, a toujours refusé de permettre des évolutions du langage et chacun a donc ajouté les siennes. Il y a eu plusieurs tentatives de normalisation (la principale étant CommonMark), mais sans résultat clair. Au début du processus long et compliqué qui a abouti à ce RFC, il était question de faire une nouvelle tentative, sous la houlette de l'IETF cette fois. Mais le projet RFC s'est assez vite rabattu sur une ambition plus modeste : enregistrer le type MIME et documenter (partiellement) l'état de Markdown. Un autre RFC, le RFC 7764, décrit les usages de Markdown. La discussion a été d'autant plus chaude que la « communauté » Markdown est largement extérieure à l'IETF.
On pourrait dire que Markdown n'est pas un langage, mais une famille de langages, ayant des éléments communs. Un bon exemple de la variété de Markdown est, par exemple, le cas des métadonnées. Pandoc permet d'écrire en début de fichier :
% Document title % Document author % Document date
Mais d'autres variantes de Markdown ne vont pas comprendre ces métadonnées, les laissant telles quelles. Autre exemple de variété, les commentaires, pour lesquels il n'existe pas de solution standard (il y a un bon article sur StackOverflow qui discute les différentes possibilités.)
Cet enregistrement du type MIME de Markdown s'inspire de celui de
text/troff
, un type pour un autre langage de marquage (RFC 4263). Après tout,
beaucoup de gens considèrent que Markdown est « le
troff d'aujourd'hui ».
La section 2 de notre RFC décrit formellement l'enregistrement
du type MIME text/markdown
et de
l'extension associée,
.md
(.markdown
est
également accepté). Ce type a
plusieurs paramètres possibles (les paramètres sont mis après un
point-virgule, par exemple
text/markdown; charset=UTF-8;
variant=Original
va désigner du Markdown à la syntaxe
originale de Gruber, encodé en UTF-8).
Premier paramètre, et obligatoire (RFC 6838, section 4.2.1),
charset
, qui désigne l'encodage du
texte. Les autres paramètres sont facultatifs.
Le plus important est sans doute variant
qui désigne le dialecte Markdown particulier utilisé. Ce fut l'une
des plus chaudes discussions à l'IETF avant la sortie de ce
RFC. Notamment, fallait-il un registre
IANA des variantes (une sorte de catalogue des
dialectes) ou bien laisser les auteurs mettre
ce qu'ils veulent, ce qui correspondait mieux au côté très peu
organisé de la « communauté » Markdown, très informelle ?
(Différentes versions du draft qui a mené à ce
RFC faisaient des choix différents.) Le
paramètre variant
a finalement un
registre (section 6.1) mais l'émetteur n'est pas obligé de se
limiter aux valeurs de ce registre. Il faut considérer la valeur
de ce paramètre comme une simple indication. Parmi les valeurs
actuellement enregistrées : Original
(le
Markdown des débuts, celui de Gruber), GFM
(celui de
GitHub), pandoc
(celui
de ce logiciel),
CommonMark
(le candidat à la
normalisation) etc. Notez que ce paramètre variant
, au gré des
évolutions du draft à l'IETF, s'est nommé
syntax
, flavor
, processor
...
Des valeurs sont interdites dans ce registre :
Standard
, Common
et
Markdown
ne peuvent être enregistrés comme
variantes. C'est parce que « une partie de la communauté » (en
réalité Gruber seul) a protesté contre la volonté de déclarer une
variante particulière comme étant « standard » ou
« officielle ».
Et si on veut ajouter une entrée à ce registre des variantes de Markdown ? La politique d'enregistrement est le « Premier Arrivé, Premier Servi » du RFC 5226, donc très légère. Il suffit d'indiquer deux-trois trucs sur la variante et roulez, jeunesse. Dans des versions initiales de ce RFC, le gabarit d'enregistrement d'une variante était bien plus complexe, bien trop détaillé, avec des infos très volatiles comme currently maintained ou anticipated output types mais il est maintenant réduit à seulement cinq champs obligatoires.
Un des projets qui avaient été lancés était celui d'enregistrer
non pas les noms des variantes mais leurs caractéristiques
(« permet les notes de base de page », « permet la création
automatique de liens hypertexte »). À la réunion IETF 90, la
proposition était de pouvoir écrire des choses comme
text/markdown;variations=footnotes,line_blocks
pour désigner du texte Markdown utilisant les notes de bas de page
et les blocs de lignes considérés comme un paragraphe. Une telle
approche aurait nécessité la constitution d'un catalogue
compliqué, et aurait imposé aux auteurs de garder trace de quelles
extensions ils utilisent. Elle n'a finalement pas été retenue.
L'enregistrement d'un type MIME nécessite une analyse de ses risques de sécurité. Rien d'extraordinaire ici, le RFC note juste que du texte avec du marquage ne présente guère de risque (contrairement à un format comme TrueType qui inclut un langage de Turing). Attention toutefois : ce que le processeur Markdown ne comprend pas, il l'envoie verbatim dans le format de sortie (ce truc est souvent utilisé pour mettre du HTML spécifique, ou du JavaScript, lorsqu'on utilise Markdown pour produire des pages Web). Du logiciel malveillant peut donc être copié ainsi.
Et la section sur l'interopérabilité rappelle ce qui a été dit plus haut : les différents Markdown vont donner des résultats différents, d'autant plus différents qu'ils utilisent des techniques spécifiques d'une variante.
Et si on veut indiquer un point précis d'un document Markdown ?
Contrairement à HTML, Markdown n'a pas d'identificateurs de
fragments d'un texte (section 3 du RFC). Mais on peut réutiliser
une partie de la syntaxe du RFC 5147 : en
terminant un URI par
#lines=N
, on accède (si le logiciel client
connait le RFC 5147) à la Nième ligne du
document Markdown.
À noter qu'on peut écrire des RFC en Markdown : c'est expliqué dans le RFC 7328 et c'est utilisé, par exemple, pour ceux du groupe Human Rights Protocol Considerations de l'IRTF (ce groupe est typiquement moins geek que la moyenne de l'IETF/IRTF).
Un exemple plus important que l'exemple un peu artificiel test1.md
que je donnais au début est mon rapport sur la panne DNS
d'Oleane. On peut le traiter avec
Pandoc et un
Makefile comme :
TARGETS=panne-dns-oleane-2016.pdf panne-dns-oleane-2016.html all: ${TARGETS} %.pdf: %.md pandoc --latex-engine=xelatex -o $@ $^ %.html: %.md pandoc -o $@ $^ clean: rm -f ${TARGETS}
Markdown est souvent présent dans les « micro-éditeurs » qui
permettent de remplir des documents via le Web. C'est le cas à
GitHub où les gists dont
le nom se termine par .md
sont
automatiquement convertis. C'est ainsi que j'ai fait un
gist de ce rapport (cliquez sur le bouton
Raw pour avoir le source).
Quelques lectures sur Markdown :
Première rédaction de cet article le 19 mars 2016
Dernière mise à jour le 27 juin 2016
FedeRez est la fédération nationale des associations d'étudiants qui gèrent des réseaux informatiques. Elle tient des journées annuelles et, à celles de 2016 dans un coin perdu de la grande banlieue parisienne, j'ai fait un exposé sur le thème « Objets qui communiquent entre eux ou bien esclaves du cloud ? ».
Voici les transparents de mon exposé :
L'enregistrement vidéo est disponible ici.
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : P. Resnick (Qualcomm
Technologies), A. Farrel (Juniper
Networks)
Première rédaction de cet article le 13 mars 2016
La question du harcèlement dans le cadre des activités professionnelles (ou autres, d'ailleurs) est maintenant largement reconnue comme cruciale et toute organisation doit se demander « que dois-je faire ? » L'IETF décrit dans ce RFC ses procédures à ce sujet, avec notamment le rôle de l'ombudsteam, l'équipe de justice privée qui doit traiter les cas de harcèlement signalés.
Tout groupe humain est évidemment confronté au problème des comportements négatifs, les trolls, par exemple. L'IETF a eu sa dose, bien que mon impression soit que le problème est nettement moins grave que dans certains groupes, comme chez certains gamers. Mais c'est difficile à dire, c'est un domaine où on n'a pas facilement des statistiques précises. L'IETF a donc son « guide des bonnes manières » (RFC 7154), et les documents de cuisine procédurale interne (RFC 2418 et RFC 3934) prévoient la gestion des cas les plus sérieux. Ces documents se focalisent sur les comportements négatifs qui impactent directement le travail de l'IETF, et le mettent en péril (par exemple, un troll qui assomme le groupe de travail de longs messages répétés en quantité et n'apportant pas de contenu). Mais il y a aussi, et c'est le sujet de ce nouveau RFC, des pratiques négatives qui ne gênent pas directement l'IETF mais peuvent pourrir la vie des participant·e·s qui en sont victimes, par exemple du harcèlement sexuel lors d'une réunion physique. Ces pratiques sont évidemment interdites (déclaration de l'IESG) mais il restait à préciser quoi faire en cas de violation de cette règle.
Il faut noter (et c'est oublié dans la plupart des ces guides de bonnes manières d'origine états-unienne qui fleurissent dans beaucoup de conférences informatiques) que le harcèlement est déjà interdit par la loi dans la plupart des pays où l'IETF tient ses réunions. Comme le note le RFC, les règles de l'IETF ne remplacent pas la loi. Nul besoin d'une déclaration de l'IESG pour interdire, par exemple, les insultes racistes ou le harcèlement sexuel à une réunion IETF. C'est pour cela que la plupart de ces codes of conduct sont inutiles. Celui de l'IETF est très orienté par ses origines états-uniennes, mêlant la demande d'un comportement « professionnel » (comme si le harcèlement n'était fait que par des amateurs) et le puritanisme (« sexual imagery in public presentations », sachant qu'aux États-Unis, la vue d'un torse nu est déjà de la sexual imagery).
La déclaration de l'IESG citée plus haut donne une définition du harcèlement, définition forcément très large (il y a hélas bien des formes de harcèlement, et bien des raisons pour lesquelles un·e participant·e à l'IETF peut être pris·e pour cible). Le problème est-il fréquent à l'IETF ? Je n'ai jamais entendu parler d'un cas précis (contrairement aux cas documentés qui sont arrivés à DEFCON), mais, évidemment, toutes les victimes ne se signalent pas publiquement et le harcèlement est donc très difficile à mesurer scientifiquement.
En première ligne dans ce RFC est l'ombudsteam. Je n'ai pas essayé de traduire ce terme, d'origine suédoise (ombudsman, devenu en anglais ombudsperson pour éviter d'exclure les femmes, puis ombusteam pour marquer son caractère collectif). Disons que c'est une équipe chargée de gérer les cas d'accusation de harcèlement, et c'est la principale ligne de défense de l'IETF dans ces cas.
L'ombudsteam est composé d'au moins trois personnes. Elles sont désignées - pour deux ans, renouvelable - par le président de l'IETF (actuellement Jari Arkko), éventuellement après consultations. Il est recommandé de suivre une certaine diversité (éviter un ombudsteam qui serait uniquement composé d'hommes blancs d'âge mûr et issus des classes dominantes, comme l'est l'auteur de ces lignes...) et de faire en sorte qu'au moins un des membres soit un participant actif à l'IETF. Il n'est donc pas nécessaire, ni même souhaitable, que l'ombudsteam soit sélectionné uniquement en interne. L'idéal, demande le RFC, est que l'ombudsteam rassemble des compétences variées, par exemple des gens qui connaissent très bien l'IETF, des gens qui sont des experts en médiation et en gestion de conflits, etc.
Les membres de l'ombudsteam ne sont pas payés pour leur activité. (À mon humble avis, cela est en contradiction avec l'objectif d'avoir de la diversité : s'ils ne sont pas payés, on n'aura que des gens favorisés socialement.)
Si quelqu'un n'est pas content de la désignation de telle ou telle personne, il peut en appeler à l'IESG (section 6.5.4 du RFC 2026).
L'ombudsteam dispose d'une page Web officielle. La liste des membres du ombudsteam a été publiée deux semaines après le RFC.
Une fois l'ombudsteam constitué, que se passe-t-il en cas de plainte
(section 4) ? La victime, ou un témoin du harcèlement, contacte l'ombudsteam, en présentiel ou bien par
courrier (ombuds@ietf.org
). Tout
participant·e à l'IETF peut contacter l'ombudsteam, soit pour une
plainte formelle, soit pour solliciter un avis.
Les pratiques de l'ombudsteam seront en grande partie définies par l'ombudsteam, qui est supposé en discuter avec l'IESG puis publier ses principes de fonctionnement. Au minimum, le RFC demande à l'ombudsteam que :
Bon, donc, des gens signalent des problèmes à l'ombudsteam, l'ombudsteam investigue, se réunit, discute et à la fin, il peut décider quoi ? La section 5 décrit les solutions disponibles pour l'ombudsteam :
Ces sanctions les plus sérieuses peuvent provoquer des problèmes délicats si le harceleur occupait une position de responsabilité à l'IETF. Bien sûr, ces personnes en position de responsabilité (président d'un groupe de travail, par exemple) n'ont pas d'immunité. Mais il ne faut pas non plus que l'ombudsteam puisse empêcher, de facto, un responsable de tenir son rôle. Une possibilité est, dans ce cas, que l'ombudsteam fasse jouer les procédures de révocation normales de l'IETF (RFC 7437, notamment la section 7). Dans le cas d'un poste qui passe par le NomCom (Nominating Commitee), l'ombudsteam demande alors le lancement de la procédure de révocation, et n'a pas besoin pour cela d'une pétition de 20 participants (RFC 7437, section 7.1). Dans le cas de poste pourvus par l'ISOC, l'IAB ou un autre organisme, l'ombudsteam peut demander à cet organisme la révocation du harceleur. Idem si le poste a été pourvu via un directeur de zone (AD, Area Director) ou un président de groupe de travail.
On le voit, l'ombudsteam dispose d'un large pouvoir, sans contrôle (en raison de l'obligation de confidentialité) et la section 5.1 du RFC dit bien que les organismes à qui l'ombudsteam demande une révocation doivent, sauf raison très sérieuse, donner suite à cette demande. Mais que se passe-t-il si quelqu'un est en désaccord avec l'ombudsteam ? La section 6 traite ce problème.
Après discussion avec l'ombudsteam la question doit être remontée au président de l'IETF. Si celui-ci préfère ne pas être impliqué (voir par exemple la section 7, sur les conflits d'intérêt), il peut demander à l'IESG de désigner un de ses membres pour jouer son rôle (les protocoles réseaux, c'est compliqué, mais la bureaucratie interne de l'IETF, c'est pire). Si la discussion entre le président et l'ombudsteam ne débouche pas sur une solution, un mécanisme formel d'appel est prévu. Le groupe qui étudiera l'appel est composé du président de l'IETF et de deux membres de l'IESG qu'il·elle a choisi. Ce groupe peut évaluer la question sur le fond. S'il y a un problème de forme, il existe un dernier mécanisme d'appel auprès de l'ISOC. Notez que les procédures ont été légèrement mises à jour par le RFC 8716.
Le RFC se termine par une jolie citation d'Aung San Suu Kyi : « Human beings the world over need freedom and security that they may be able to realize their full potential. »
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : F. Gont (Huawei Technologies), T. Chown (University of Southampton)
Pour information
Réalisé dans le cadre du groupe de travail IETF opsec
Première rédaction de cet article le 11 mars 2016
Soit un pauvre petit réseau innocent, et un méchant attaquant qui va essayer de faire subir les derniers outrages au réseau en question. L'attaquant commence souvent par une phase de reconnaissance, où il cherche à améliorer sa connaissance du réseau visé. Un outil souvent utilisé dans cette phase est le balayage (scanning) systématique du réseau, à la recherche d'adresses IP de machines à attaquer. En IPv6, contrairement à IPv4, la tâche semble colossale, vu le nombre d'adresses IP possibles. Mais, comme l'avait déjà noté le RFC 5157, cette tâche n'est pas impossible. Ce nouveau RFC fait le point sur le balayage IPv6 et détaille les techniques utilisables.
Comme exemple de la différence de situation entre IPv4 et IPv6, prenons un réseau local typique. La densité de machines (nombre de machines réellement présentes par rapport au nombre d'adresses possibles) est bien inférieure en IPv6. Sur un /26 IPv4, on a 62 adresses théoriquement possibles et la plupart correspondront sans doute effectivement à une machine. Balayer ce /26 est à la fois très rapide et très avantageux. En IPv6, un simple /64 permet d'avoir plus de 10^19 adresses (c'est bien la principale motivation pour déployer IPv6 : avoir davantage d'adresses). Même si on a bien plus de machines, la densité sera infime. Si les adresses étaient attribuées au hasard et que le balayage se fasse également au hasard, les chances de tomber sur une machine réelle sont quasi-nulles. Heureusement pour l'attaquant, les adresses réelles ne sont pas attribuées au hasard, et le balayage n'est pas forcément fait au hasard. Ce nouveau RFC, deux fois plus long que l'ancien (le RFC 5157) fait le point sur ce que les défenseurs et les attaquants doivent savoir sur le balayage en IPv6.
Avant de tester, installons l'outil de balayage scan6, distribué avec le SI6 toolkit (et déjà utilisé dans mon article sur les attaques en IPv6) :
% wget http://www.si6networks.com/tools/ipv6toolkit/ipv6toolkit-v2.0.tar.gz % tar xzvf ipv6toolkit-v2.0.tar.gz % cd ipv6toolkit-v2.0 % make
C'est parti, en commençant par les techniques les plus classiques
(section 3 de notre RFC). D'abord, lorsque le réseau visé configure
les adresses IP avec le SLAAC du RFC 4862. Le SLAAC fonctionne en concaténant un
préfixe appris du routeur avec un suffixe, l'IID (Interface
IDentifier). Comment la machine choisit-elle son IID ? Il
existe plusieurs techniques, qui ont des conséquences sur la facilité
de balayage. Par exemple, une technique courante (mais de moins en
moins employée) est de fabriquer
l'IID à partir de l'adresse MAC de la machine,
en mettant juste le bit 6 à 1 et en ajoutant au milieu 0xfffe. Ainsi,
mon adresse MAC 38:59:f9:7d:b6:47
me donne
actuellement une adresse IPv6 de
2003:88:6c71:c7f8:3a59:f9ff:fe7d:b647
(préfixe
2003:88:6c71:c7f8
chez Deutsche
Telekom et IID
3a59:f9ff:fe7d:b647
). A priori, il y a 64 bits
possibles pour l'IID. Mais ce n'est pas tout à fait vrai. D'abord, 16
sont fixes (le 0xfffe). Ensuite, les 24 premiers bits identifient le
vendeur de la carte via son OUI (sauf si, comme dans l'exemple ci-dessus,
on a changé son adresse MAC...) Tous les OUI possibles n'étant pas encore
affectés, cela réduit le champ de recherche. Et ceux qui sont affectés
le sont souvent pour du matériel qui n'est plus fabriqué, réduisant
encore ce champ. Enfin, un attaquant malin observera qu'une
organisation donnée a souvent un parc matériel homogène (par exemple
uniquement des ordinateurs Dell). Cela permet
de réduire encore l'espace de recherche (option
--tgt-vendor
de scan6). En outre, si les machines
ont été achetées en même temps, il est tout à fait possible
qu'elles fassent partie du même lot et que leurs adresses MAC soient
consécutives. Une fois qu'on en a trouvé une, on peut supposer que les
autres sont proches.
Un cas particulier est celui des techniques de
virtualisation. Par exemple,
VirtualBox utilise l'OUI
08:00:27
et, avec le 0xfffe du milieu, cela fait
que l'espace de recherche réel n'est que de 24 bits, bien moins que
les 64 théoriques. VMware est encore pire, pour
ses adresses MAC automatiques :
l'OUI est 00:05:69
, 16 bits sont tirés de
l'adresse IPv4 de la console, 8 bits sont un
condensat du nom du fichier de
configuration. Il peut donc n'y avoir que 8 bits à chercher ! (Les
adresses MAC manuelles de VMware ont 22 bits variables.)
Et les adresses temporaires du RFC 8981, n'avaient-elles pas été conçues justement pour éviter qu'on suive à la trace une machine ? L'IID est cette fois aléatoire, et change souvent (par exemple une fois par jour). Ces adresses temporaires sont une très bonne chose, mais elles ont quelques limites. D'abord, elles viennent en plus des adresses classiques, auxquelles la machine répond toujours. Les adresses temporaires étant utilisées pour les connexions sortantes, le risque de fuite de l'adresse globale permanente est plus faible mais elles n'empêchent pas le balayage, avec les techniques données plus haut.
C'est en partie pour combler les faiblesses des adresses temporaires que les adresses du RFC 7217 ont été développées. L'IID est un condensat de certaines caractéristiques de la machine et du réseau. Ces adresses sont stables tant que la machine ne change pas de réseau (ce qui permet de n'utiliser que ces adresses et d'oublier les adresses globales classiques). Du point de vue de la vie privée, elles représentent la meilleure solution, et devraient être systématiquement utilisées. Pour l'instant, comme l'indique « IPv6 Address Analysis - Privacy In, Transition Out », la grande majorité des clients IPv6 utilisent les adresses temporaires du RFC 8981 (et 7 % utilisent encore les adresses MAC).
Et DHCP ? La politique d'allocation des
adresses dépend du serveur DHCP. Parfois, elle mène à des adresses
prévisibles, mais pas toujours. Par exemple, si on configure un
serveur DHCP pour allouer des adresses dans la plage
2001:db8:a35:b24::/64
, et que le serveur DHCP
décide qu'une allocation séquentielle
(2001:db8:a35:b24::1
puis
2001:db8:a35:b24::2
, puis
2001:db8:a35:b24::3
...) est la meilleure
solution, alors les adresses seront prévisibles. C'est pour cela que
le RFC 5157 conseillait aux serveurs DHCP
d'allouer au hasard à partir de la plage d'adresses configurée et ce
conseil est répété ici.
Et les adresses attribuées manuellement, par l'administrateur système ? C'est utile pour les routeurs (qui ne peuvent pas utiliser SLAAC) et les serveurs (qui ne cherchent pas à se cacher, et pour qui il est très souhaitable d'avoir une adresse IP stable). En théorie, l'administrateur système peut choisir l'IID librement parmi 2^64 valeurs. En pratique, on observe que ces IID ne sont pas choisis au hasard mais que les ingénieurs suivent un de ces quatre schémas, utilisant :
PREFIX::1
,
PREFIX::2
, etc. L'option
--tgt-low-byte
de scan6 permet de tester en
premier ces valeurs. Dans le cas le plus simple, il suffit de tester
les 256 valeurs correspondant aux huits bits finaux (certaines
variantes de ce schéma utilisent les deux ou trois derniers octets,
ce qui rend le balayage un peu plus long). Ce schéma est de loin le
plus fréquent pour les serveurs et les routeurs (voir « IPv6 Network Reconnaissance: Theory &
Practice », cité en section 3.1.5).2001:db8:88:12a::192.0.2.21
. Balayer
ces adresses revient à balayer l'espace IPv4 correspondant (option
--tgt-ipv4,
de scan6).PREFIX::53
, le
serveur IMAP
PREFIX::993
, etc. Le cas le plus simple (numéro
de port dans le dernier octet) est très rapide à balayer (option
--tgt-port
de scan6, il n'y a
que quelques dizaines de ports populaires), certaines variantes sont
un peu plus lentes.::dead:beef
ou
::a11
. Balayer ces termes se fait à partir d'un
dictionnaire.Bon, armés de ces connaissances, voyons maintenant concrètement
comment balayer un réseau. D'abord, un réseau distant (section
3.2). Un balayage par la force brute est impossible en IPv6 : un seul
/64 peut avoir dans les 10^20 machines, ce qui, même à un million de
paquets par seconde, prendrait trois millions d'années à examiner. Un
balayeur IPv6 doit donc être plus astucieux que la force brute et
exploiter les propriétés des adresses IPv6, qui font que l'espace
réel à explorer est plus réduit que l'espace théorique. Ainsi, en
balayant dans l'ordre, de PRÉFIXE::
puis
PRÉFIXE::1
, PRÉFIXE::2
,
etc, on tire profit des adressses de faible valeur. De même, on peut
deviner le plan d'adresssage et utiliser les adresses IPv4 du réseau,
les numéros des bâtiments, etc.
À noter que le balayage peut aussi être utilisé pour faire une attaque par déni de service. Certaines mises en œuvres d'IPv6 gèrent mal leur cache NDP et un grand nombre de requêtes pour des machines inexistantes peut planter certains routeurs IPv6 (RFC 6583).
Revenons au balayage fait dans le but de découvrir des adresses
actives. Si on balaye le réseau local, celui où on se trouve, il y a
encore d'autres possibilités, notamment les adresses
multicast. Par exemple, en
envoyant un seul paquet à l'adresse multicast
ff02::1
, on récupère plein de machines :
% ping6 -I eth0 ff02::1 PING ff02::1(ff02::1) from fe80::e349:a3a5:ad58:a21 eth0: 56 data bytes 64 bytes from fe80::e349:a3a5:ad58:a21: icmp_seq=1 ttl=64 time=0.250 ms 64 bytes from fe80::21e:8cff:fe76:29b6: icmp_seq=1 ttl=64 time=1.17 ms (DUP!) 64 bytes from fe80::f6ca:e5ff:fe4d:1f41: icmp_seq=1 ttl=64 time=4.96 ms (DUP!) 64 bytes from fe80::ce0d:dad3:6bc2:6da4: icmp_seq=1 ttl=64 time=4.96 ms (DUP!) ...
Ça ne marche pas avec les machines Windows, qui ne répondent pas à ce ping. Mais il y a d'autres astuces comme d'envoyer à cette adresse multicast un paquet IPv6 ayant une option inconnue et dont le type commence par 10 (qui signifie « si cette option n'est pas connue, jeter le paquet et envoyer une erreur ICMP », cf. RFC 2460, section 4.2). Windows répondra alors par un message ICMP Parameter problem. Voici le résultat de scan6 vu avec tcpdump, montrant cette technique :
19:01:06.204431 IP6 fe80::e349:a3a5:ad58:a21 > ff02::1: DSTOPT ICMP6, echo request, seq 34994, length 64 19:01:06.205469 IP6 fe80::21e:8cff:fe76:29b6 > fe80::e349:a3a5:ad58:a21: ICMP6, parameter problem, option - octet 42, length 120 19:01:06.214792 IP6 fe80::ba27:ebff:feaa:78b9 > fe80::e349:a3a5:ad58:a21: ICMP6, parameter problem, option - octet 42, length 120 ...
Ces techniques ne sont pas purement théoriques. Certes, un outil comme nmap sait faire du balayage en IPv4 mais pas en IPv6 à distance, mais d'autres outils existent. Ces techniques sont mises en œuvre dans l'outil scan6 du SI6 toolkit, cité plus haut. Une fois compilé et installé, on peut utiliser cet outil pour découvrir ses voisins (sur le même réseau local) :
% sudo scan6 -L -i eth0 ... 2a01:f23:a65:6721:21e:8cff:fe76:29b6 2a01:f23:a65:6721::1 2a01:f23:a65:6721:666:6c7c:9bed:b390 2a01:f23:a65:6721:b5a5:dfd6:4e7b:2584 ...
Ou bien tester un réseau distant :
% sudo scan6 -d 2001:7b2:dc0:41::/64 2001:7b2:dc0:41::250 ...
Le dernier exemple ci-dessus est évidemment complètement irréaliste (balayage d'un /64 en force brute), même si ici on a trouvé tout de suite une machine « low-byte ». Ne soyez pas trop optimiste : scan6, livré à lui-même, est très lent et vous trouverez rarement quelque chose. Un balayage d'un site où on connait le vendeur des cartes Ethernet (et donc l'OUI) :
% sudo scan6 --tgt-ieee-oui b8:27:eb -d 2001:db8:8469:a30::/64 -i eth0 -e print-global
prend de très nombreuses heures et risque fortement d'être détecté. En pratique, pour utiliser scan6 avec succès, il faut récolter beaucoup d'informations sur le réseau qui vous intéresse, et guider scan6 en lui mettant beaucoup d'options. Un projet intéressant serait de tenter d'automatiser cette phase heuristique.
Une des conséquences de la difficulté de balayer en IPv6 est que la gestion de réseaux devient plus compliquée. L'administrateur réseaux ne peut pas découvrir facilement tout ce qui a été branché et fonctionne sur son réseau. Il doit donc changer ses pratiques. Une des approches, pour connaitre tout son réseau, est l'écoute passive, avec ndpmon, qui permet de se constituer automatiquement une base des machines et de leur adresse MAC.
Et l'administrateur réseaux qui veut défendre son réseau et limiter le balayage, que peut-il faire (section 3.5 du RFC) ? Il existe plusieurs techniques qui aident, en rendant les adresses moins prévisibles :
Ces solutions ne sont pas parfaites. Consolez-vous avec l'idée que la sécurité de vos machines ne doit de toute façon pas dépendre uniquement de la résistance de votre réseau au balayage. Tôt ou tard, l'attaquant découvrira vos adresses IP, et les machines doivent donc être préparées à tout.
Le balayeur n'utilisera pas que des techniques de couche 3 comme décrit dans la précédente section, la section 3 du RFC. Il peut aussi se servir, par exemple, du DNS (section 4). Par exemple, s'il est possible de récupérer la zone DNS, le balayeur obtient beaucoup d'adresses IPv6. Mais il peut aussi tester des noms communs dans le DNS et obtenir ainsi des adresses (et, si votre algorithme d'allocation est prévisible, un petit nombre d'adresses lui permettra d'en déduire d'autres). Un tel balayage est facile à automatiser.
Mieux (du point de vue de l'attaquant), on peut énumérer les
enregistrements PTR dans votre sous-arbre de
ip6.arpa
. (C'est
automatisable, avec l'outil dnsrevenum6, qui fait partie de la boîte à outils THC.)
Outre le DNS classique, mDNS (RFC 6762) peut également aider (section 5) : des requêtes envoyées à la cantonade peuvent découvrir des machines qui se signaleraient imprudemment.
L'attaquant en mission de reconnaissance peut aussi utiliser des
archives publiques (section 6). Par exemple, une liste de
diffusion dont les messages seraient stockées
intégralement, y compris les en-têtes Received:
,
qui contiennent souvent des adresses IP. Difficile d'être discret sur l'Internet !
Certaines applications peuvent également aider l'attaquant à récolter des adresses IP (section 7). Par exemple, BitTorrent ne fait aucun effort pour dissimuler l'adresse du pair avec qui on échange des fichiers. Même chose avec NTP, si les machines de votre réseau local se synchronisent directement à l'extérieur, ce qui les rend visibles à Shodan.)
On trouve également des adresses IP dans les caches NDP (section 8) - et ces caches peuvent parfois être examinés à distance avec SNMP (section 13), dans les journaux (gérer un serveur Web populaire permet d'en récolter beaucoup, cf. section 9), via les protocoles de routage (section 10), via traceroute (section 12)... Au passage, il est recommandé de lire l'excellent article de Bellovin, S., Cheswick, B., et A. Keromytis, « Worm propagation strategies in an IPv6 Internet » dans login: en 2006.
L'annexe A du RFC décrit une mise en œuvre des principales idées expliquées dans ce document. Si vous voulez tous les détails techniques sur le balayage en IPv6, c'est le texte à lire. Il faut par exemple être prudent : un balayage exhaustif en IPv6 peut nécessiter un nombre colossal de paquets et, si on les envoie trop vite, l'augmentation du trafic vous fera repérer (variante : vous surchargerez le réseau, des paquets seront perdsu et vous raterez ainsi des réponses). Cette annexe couvre également les méthodes de dissimulation, pour éviter d'être détecté (avec la plupart des IDS IPv6, il suffit d'ajouter des en-têtes d'extension au paquet). Le tout est évidemment très inspiré de l'expérience de l'un des auteurs du RFC avec l'outil scan6, déjà cité.
Je ne fais pas ici un résumé des différences avec son prédécesseur, le RFC 5157, car il y en a beaucoup trop (notre nouveau RFC est bien plus détaillé).
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : A. Cooper (Cisco), F. Gont (Huawei Technologies), D. Thaler (Microsoft)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 11 mars 2016
Il y a eu pas mal de trollage depuis les débuts d'IPv6, au sujet de son mécanisme de génération d'adresses, et des risques qu'il pouvait poser pour la vie privée. Ces débats étaient souvent motivés par une inquiétude de la nouveauté, davantage que par une réelle analyse des menaces. Plus d'un amateur a écrit sur les forums qu'IPv6 était un complot contre la vie privée, alors même que son navigateur Web faisait fuiter bien davantage d'informations personnelles. Ce nouveau RFC analyse l'état actuel des mécanismes de génération des adresses IPv6, leurs avantages et leurs inconvénients en terme de protection de la vie privée, et les compromis à faire lors du choix d'un mécanisme donné.
IPv6 permet des nouvelles façons d'allouer des adresses. Outre les méthodes qui existaient déjà en IPv4, comme l'allocation statique, et celle via DHCP, il permet une méthode dite « sans état ». Dans ce cas, le routeur annonce le préfixe IP du lien, et les machines ajoutent à ce préfixe un suffixe qui les identifie de manière unique sur le lien. Ainsi, on peut obtenir une adresse globale sans qu'un serveur ait besoin de maintenir un état des allocations faites.
Au début d'IPv6, des formulations malheurseuses dans les RFC ont pu faire croire que ce suffixe, l'IID (Interface IDentifier) était forcément dérivé de l'adresse MAC de la machine, mais cela n'a jamais été obligatoire (le RFC 7136 a clarifié ce point). D'autre part, on peut noter que préfixe et suffixe ont en général la même longueur, qui est de 64 bits, pour les raisons expliquées dans le RFC 7421.
Aujourd'hui, la liste complète des mécanismes possibles d'allocation d'adresses IPv6 est :
:53
...), ou
enfin en utilisant un mot rigolo, en profitant de
l'hexspeak.Parmi ces nombreuses méthodes, la méthode « SLAAC et IID dérivé de l'adresse MAC » est celle qui pose le plus de problèmes, côté vie privée. Pourquoi ? Parce que l'adresse MAC d'une machine est en général stable (sauf si on utilise un logiciel comme macchanger) même lorsque la machine se déplace. Si on se connecte à un pair sur l'Internet, depuis un certain réseau, le pair verra l'adresse IP source et, si on change de réseau, l'adresse MAC, donc l'IID, dans les 64 derniers bits de l'adresse IP, seront les mêmes et le pair verra donc qu'il s'agit de la même machine.
La section 3 de notre RFC décrit plus précisement les vulnérabilités de cette méthode. La première vulnérabilité est le risque de corrélation. Un pair avec qui on communique, ou bien un observateur du trafic réseau, peuvent se rendre compte que deux machines d'adresses IPv6 différentes sont en fait la même machine, en raison de l'égalité des deux IID. Comme on ne change pas de carte Ethernet tous les mois, la corrélation, dans le cas d'un IID fondé sur l'adresse MAC peut durer des années (cf. RFC 8981 pour l'analyse).
Bien sûr, on peut faire de la corrélation avec autre chose que les adresses MAC, comme l'illustre très bien le Panopticlick (voir aussi la section 5.2.1 du RFC 6973) et une bonne partie des critiques contre ce risque de corrélation avec les IID liés aux adresses MAC étaient juste du FUD anti-IPv6 (des gens qui critiquent le manque de vie privée avec IPv6 mais qui ne filtrent pas les cookies...) Mais cela n'interdit pas d'essayer de résoudre le problème.
Un autre risque est celui de la localisation. Si une machine garde le même IID en changeant de réseau, on peut la suivre à la trace. « Tiens, c'est encore elle, et, cette fois, elle est en Allemagne. Tiens, elle est maintenant à l'université de Berlin. » Cette attaque n'aurait pas marché en IPv4 où l'adresse attribuée est complètement différente à chaque fois.
Les adresses IPv6 dérivées de l'adresse MAC présentent un autre
risque : on peut balayer le réseau à la recherche de machines à
attaquer. Normalement, la taille de l'espace d'adresssage IPv6
rend le balayage complet irréaliste. Mais, si on sait que le
réseau visé n'utilise, par exemple, que des Apple, on
peut réduire le nombre de paquets à envoyer en disant au logiciel
de balayage de n'utiliser que des adresses IPv6 dérivées
d'adresses MAC ayant le préfixe Apple. Et cette possibilité est
mise en œuvre dans les outils réels, par exemple avec l'option --tgt-ieee-oui
de scan6.
(Voir le RFC 7707 pour plus de détail sur le balayage en
IPv6.)
Enfin, le fait que les adresses MAC aient un préfixe qui indique le fabricant (sauf si on a pensé à utiliser macchanger ou un logiciel équivalent) fournit une information qui peut être utile à un attaquant, en lui dévoilant le type de machines qu'on utilise.
Bien sûr, ces adresses IPv6 dérivées de l'adresse MAC sont minoritaires, et sont de moins en moins utilisées. Mais les alternatives ne sont pas toujours parfaites. La section 4 de notre RFC fait le point sur les solutions, et leurs propriétés. Les adresses temporaires du RFC 8981 sont la première solution à laquelle on pense. Elles sont typiquement utilisées pour les connexions sortantes, une adresse stable, dérivée de l'adresse MAC, restant en place pour les connexions entrantes. À noter qu'au début, les problèmes de vie privée étant supposés moins importants que les considérations opérationnelles de gestion des réseaux, les RFC demandaient que les adresses temporaires ne soient pas utilisées par défaut. Plusieurs systèmes, comme Windows, ont décidé à juste titre d'ignorer cette demande, et c'est ce qui explique que les adresses dérivées d'une adresse MAC soient aujourd'hui minoritaires dans les journaux des serveurs Internet (voir les mesures à la fin de cet article). L'ancienne recommandation a été abandonné et le RFC 6724 dit clairement qu'il faut utiliser les adresses temporaires par défaut.
D'autre part, comme l'adresse stable fondée sur l'adresse MAC demeure, en plus de l'adresse temporaire, les inconvénients liés au balayage « optimisé » du réseau demeurent.
Il faut aussi noter qu'il n'y a pas que l'IID (la partie droite de l'adresse IP) qui est révélatrice. Le préfixe (la partie gauche) peut l'être également. Par exemple, si on suivait le RFC 3314, qui recommande un préfixe unique par téléphone en GPRS, ce préfixe, s'il était attribué de manière stable, serait caractéristique d'un téléphone donné.
Un tableau au début de la section 4 résume la vulnérabilité des différents choix d'allocation d'adresses IPv6 aux différents risques indiqués en section 3 (corrélation, localisation, balayage et indication du vendeur). Par exemple, une adresse attribuée manuellement permet la corrélation, tant que cette adresse dure (ces attributions manuelles concernent en général les serveurs, pour lesquels les problèmes de vie privée sont nettement moins graves) et une adresse dérivée de l'adresse MAC permet la corrélation tant qu'on ne change pas la carte Ethernet ou Wifi (ou son adresse MAC, ce que les gens oublient souvent, mais qui est possible avec la plupart des cartes).
En revanche, les adresses temporaires ne permettent la corrélation que pendant la durée de vie de ces adresses (une journée, par défaut), et les adresses stables et opaques du RFC 7217 permettent la corrélation tant que la machine ne change pas de réseau mais la bloquent dès qu'on bouge.
Le tableau est explicité dans les sections suivantes :
Enfin, la section 5 de notre RFC traite de divers problèmes liés à ce souci de vie privée. Par exemple, il rappelle que des adresses qui changent (telles les adresses temporaires du RFC 8981) peuvent être une plaie pour l'administration de réseaux et que certaines organisations vont donc les désactiver sur les postes de travail, et tant pis pour la vie privée.
Autre cas embêtant, il existe apparemment des suites de test IPv6 qui vérifient que l'adresse IPv6 est bien dérivée de l'adresse MAC. C'est évidemment une mauvaise idée et notre RFC demande que ces suites soient mises à jour.
À noter qu'il existe un outil pratique,
addr6
, qui fait partie du SI6
toolkit. Utilisant divers techniques (et
heuristiques : il se trompe parfois), il vous dit à quelle
catégorie appartient une adresse :
[L'adresse de base d'une machine] % addr6 -a 2a01:ff41:916b:3bb0:ba27:ebff:feaa:78b9 unicast=global=global=ieee-derived=b8-27-eb [Une des adresses temporaires de la même machine (c'est un FreeBSD avec ipv6_privacy="YES" dans rc.conf] % addr6 -a 2a01:ff41:916b:3bb0:810e:9c6d:341:e7a unicast=global=global=randomized=unspecified [Un serveur public, d.nic.fr] % addr6 -a 2001:678:c::1 unicast=global=global=low-byte=unspecified
Quelle est la situation aujourd'hui ? Quels types d'adresses sont utilisés par les machines IPv6 ? J'ai fait un petit test avec les visiteurs de mon blog (qui ne sont pas forcément représentatifs : vus les sujets traités sur ce blog, les visiteurs sont sans doute techniquement plus avancés que la moyenne) :
% zgrep -h -E '^[0-9]+:' /var/log/apache2/access.log* | awk '{print $1}' | \ sort | uniq | addr6 -i -s ** IPv6 General Address Analysis ** Total IPv6 addresses: 1997 Unicast: 1997 (100.00%) Multicast: 0 (0.00%) Unspec.: 0 (0.00%) ** IPv6 Unicast Addresses ** Loopback: 0 (0.00%) IPv4-mapped: 0 (0.00%) IPv4-compat.: 0 (0.00%) Link-local: 0 (0.00%) Site-local: 0 (0.00%) Unique-local: 0 (0.00%) 6to4: 9 (0.45%) Teredo: 0 (0.00%) Global: 1988 (99.55%) ** IPv6 Interface IDs ** Total IIDs analyzed: 1997 IEEE-based: 230 (11.52%) Low-byte: 323 (16.17%) Embed-IPv4: 0 (0.00%) Embed-IPv4 (64): 122 (6.11%) Embed-port: 7 (0.35%) Embed-port (r): 1 (0.05%) ISATAP: 1 (0.05%) Byte-pattern: 23 (1.15%) Randomized: 1190 (59.59%)
On voit que la majorité utilise des adresses temporaires (Randomized) ce qui est bon signe (et tord le cou à la légende comme quoi les adresses IPv6 permettraient de suivre un utilisateur à la trace). Le second type, en nombre d'adresses distinctes (je n'ai pas cherché à pondérer par le nombre de visites faites par chaque adresse), est celui des adresses manuelles avec un octet de faible valeur (Low-byte). Il peut s'agir de serveurs, par exemple des crawlers. Les adresses IPv6 fondées sur l'adresse MAC sont le troisième type, avec plus de 11 %, et des efforts seront sans doute nécessaires pour sensibiliser ces utilisateurs.
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : R. Barnes (Mozilla), A. Cooper (Cisco), O. Kolkman (ISOC), D. Thaler (Microsoft), E. Nordmark (Arista)
Pour information
Première rédaction de cet article le 10 mars 2016
Normalement, l'Internet est ouvert. C'est même une de ses principales caractéristiques : un outil de communication ouvert, où tout le monde peut s'exprimer. C'est cette ouverture qui est à la base de son succès. Mais une de ses conséquences est que certaines communications vont être indésirables pour certains. Il y a donc une demande pour du « blocage » ou du « filtrage », afin d'empêcher ces communications. Ce nouveau RFC, dû à l'IAB, examine les techniques de blocage et de filtrage et cherche lesquelles sont le plus compatibles avec une architecture saine et robuste de l'Internet. Évidemment, les techniques qui menacent le moins la robustesse de l'Internet sont celles qui se déroulent entièrement aux extrémités. Si je ne veux pas voir les publicités, j'installe un logiciel qui télécharge sur ma machine une liste noire de serveurs distribuant ces publicités, et je peux ainsi bloquer et filtrer sans risques pour l'utilisation de l'Internet par les autres. Mais, hélas, pas mal de gens puissants se moquent de fragiliser l'Internet (ou la démocratie) et bien d'autres méthodes de blocage ou de filtrage existent.
On voit tout de suite que ce RFC est très politique. Les filtrages dont il parle sont évidemment ceux de gens ayant du pouvoir (entreprises, États) et qui vont essayer d'empêcher M. Michu de voir ce qu'il veut. Mais l'IAB essaie de ne pas faire trop de politique, et se limite à analyser le problème technique. Ce RFC est un excellent document, analysant très finement les systèmes de filtrage et blocage, et restant sous l'angle technique, à la fois par désir de ne pas prendre position trop clairement et aussi parce que, pour l'Internet, une censure légale/légitime et une attaque ne sont pas différentes.
Le problème des « communications non souhaitées » est vaste. Il ne se limite pas aux pages Web qui déplaisent aux ministres et que ceux-ci souhaitent censurer. Il y a aussi le logiciel malveillant (qui remonte à loin), les attaques, le spam, etc. C'est donc depuis longtemps qu'il existe des techniques de blocage et de filtrage, et depuis aussi longtemps qu'elles sont vigoureusement contestées.
Le RFC 4084 notait déjà que certains FAI bloquaient l'accès à certains services. Parfois, cela se fait avec le consentement de l'utilisateur, consentement parfois très contestable : si, pour avoir un accès Internet à l'hôtel, vous devez cliquer « J'accepte » après un texte de vingt pages, y a-t-il réellement eu consentement ? Mais, souvent, il n'y a même pas de semblant de consentement : certains voudraient bloquer sans que l'utilisateur soit d'accord, et parfois sans même qu'il soit informé. Si ces « certains » ne contrôlent pas le réseau, ils cherchent à atteindre leurs fins en agissant sur des intermédiaires (comme les résolveurs DNS), et tant pis pour les dommages collatéraux.
J'ai parlé de « blocage » et de « filtrage », quelle est la différence ? On dit en général « blocage » quand on interdit complètement l'accès à un agrégat de ressources et « filtrage » quand il s'agit de sélectivement empêcher l'accès à certaines ressources seulement, dans cet agrégat. Si on empêche l'accès à tout YouTube, c'est du blocage. Si on empêche seulement l'accès à certaines vidéos, c'est du filtrage. Pour l'analyse dans ce RFC, cela ne change pas grand'chose, et on parlera indifféremment de filtrage ou de blocage.
Selon le pays, l'époque, les opinions politiques de la personne à qui on parle, ce filtrage peut être vu comme légal, illégal, éthique, acceptable, dégueulasse, souhaitable, stupide, scandaleux et contraire aux droits de l'homme, indispensable, etc. Mais, pour l'analyse technique qui est faite par l'IAB, cela ne fait pas de différence. Notamment, la distinction légale/illégale est non seulement très complexe (le gouvernement turc a-t-il le droit de détourner l'adresse IP d'un serveur états-unien ?) mais également sans conséquences pour la technique. (Un logiciel ne sait pas ce qui est légal ou illégal et il travaille de la même façon dans les deux cas.)
C'est encore plus vrai pour la distinction éthique/pas éthique, que notre RFC considère comme hors sujet, et sur laquelle il ne prend donc pas position.
La section 2 du RFC donne plusieurs exemples de filtrage ou blocage. Historiquement, les premiers systèmes qui se mettaient sur le trajet entre Alice et Bob étaient les pare-feux (RFC 2979). Ils peuvent être déployés sur les machines terminales (c'est aujourd'hui le cas du Netfilter de Linux) ou bien sur le réseau (souvenir personnel lointain : les débuts avaient été difficiles car certains systèmes supportaient mal qu'une machine soit joignable via certains ports et pas d'autres : c'est ainsi qu'au début des années 1990, Ultrix coupait toute communication avec une machine dès qu'il recevait un ICMP indiquant qu'un port était bloqué).
Il y a bien des sortes de pare-feux, le RFC 4949 contient des définitions, et le RFC 4948 décrit les différents types de trafic non souhaités, ceux qu'on veut typiquement bloquer avec le pare-feu. Notamment, on distingue traditionnellement (ces termes sont absents du RFC 4949, qui est assez ancien) :
Autre exemple de filtrage, celui du Web. Comme les dirigeants, en général, ne connaissent de l'Internet que le Web, c'est souvent sur celui-ci que portent les efforts de censure. Il est donc fréquent que le filtrage soit spécifique à certains URI, soit en détournant tout le trafic HTTP vers un proxy qui examine les URI, soit par DPI. Évidemment, HTTPS rend bien plus compliqué ce filtrage. Mais ne l'empêche pas complètement, en raison des failles du modèle de sécurité de X.509 : par exemple, le filtreur peut obtenir un faux certificat d'une autorité existante, ou bien faire installer sur les ordinateurs une autorité de certification qui validera les faux certificats générés par le système de filtrage.
Le filtrage n'est pas forcément fait par des méchants dictateurs voulant empêcher les citoyens d'accéder à des informations honnêtes. Un bon exemple d'un filtrage que la majorité des utilisateurs apprécie, et même réclame, est le filtrage du spam. C'est même sans doute dans la lutte contre le spam que le filtrage a trouvé une de ses premières applications. Une des armes utilisées, les listes noires, est, techniquement, tout à fait comparable aux outils de la censure (RFC 5782).
Un autre exemple cité dans le RFC d'un filtrage volontaire par les utilisateurs est le safe browsing, quand le navigateur Web connait une liste de sites Web méchants ou dangereux, et refuse de s'y connecter.
Et le filtrage des noms de domaine ? Cela peut se faire en supprimant ledit nom, par exemple par la procédure de justice privée UDRP (cf. Moore, T. et R. Clayton, « The Impact of Incentives on Notice and Take-down », Workshop on the Economics of Information Security 2008, et Chachra, N., McCoy, D., Savage, S., et G. Voelker « Empirically Characterizing Domain Abuse and the Revenue Impact of Blacklisting », Workshop on the Economics of Information Security 2014. Cette approche nécessite de disposer d'un moyen politique d'action contre le registre qui gère le nom (notez que c'est la loi du pays du registre qui compte, pas la loi du titulaire, comme l'avait illustré l'affaire RojaDirecta).
Mais la censure d'un nom de domaine peut aussi se faire dans le DNS. (Au passage, arrêtez de lire ici et allez, si ce n'est pas encore fait, allez voir l'excellent rapport du conseil scientifique de l'AFNIC « Conséquences du filtrage Internet par le DNS ».) Dans ce cas, un résolveur menteur va donner, pour ce nom de domaine, un autre résultat que celui prévu par le titulaire du nom (c'est ainsi que fonctionne la censure administrative française). Cette technique est utilisée dans de nombreux pays, même si elle fragilise l'Internet, par exemple en perturbant le déploiement de DNSSEC.
Une autre technologie d'infrastructure qui risque d'être utilisée pour le filtrage est le routage. En manipulant le routage de l'Internet, on peut empêcher l'utilisateur d'accéder où il veut. Un exemple typique a été l'action aux Pays-Bas contre le RIPE-NCC dans l'affaire DNSChanger.
Après ce tour des exemples de filtrage (le RFC en cite plusieurs autres que je n'ai pas repris ici), passons maintenant à la théorie et essayons de classer ces systèmes de blocage. Il y a quatre critères de classement importants :
La liste des cas présentés à la section 2 était délibérement très variée, utilisant des cas qui se classent très différemment selon ces critères.
Commençons, par le premier critère, qui bloque. On a vu des blocages par la police, par des tribunaux, par des entreprises, par des opérateurs réseau et par des utilisateurs individuels. Souvent, la décision est prise par une entité et ensuite appliquée par une autre. Par exemple, le ministère de l'Intérieur décide de bloquer un site Web « djihadiste » mais c'est un FAI qui, via son résolveur DNS menteur, effectue le blocage. (Le RFC n'en parle pas mais un autre exemple est celui où une entreprise choisit d'utiliser un résolveur menteur, par exemple OpenDNS, comme résolveur. OpenDNS affirme toujours que leurs clients ont choisi le blocage. Mais, dans ce cas, l'employé de base a-t-il réellement choisi ?)
Second critère, pourquoi on bloque. On peut bloquer « pour des raisons de sécurité » (c'est souvent une excuse pipeau mais il y a aussi des vraies raisons de sécurité). Par exemple, on va bloquer les sites Web qui distribuent du logiciel malveillant. Ou bien on va bloquer les communications avec tel préfixe IP, d'où partent souvent des attaques.
On peut aussi bloquer un contenu dont on ne veut pas. Le RFC ne cite pas cet exemple mais on pense évidemment aux bloqueurs de pub. Il y a aussi bien sûr les cas de censure étatique, où l'État ne veut pas que les citoyens accèdent à tel site Web. Les raisons sont nombreuses, de la pédopornographie au jeu en ligne en passant par la vente de drogues, la propagande raciste ou la violation des droits sacrés des ayant-droits.
Le blocage peut aussi se faire pour des raisons économiques, par exemple un service d'accès à l'Internet gratuit mais qui bloquerait la plupart des sites, nécessitant une option payante pour y accéder.
Le blocage peut se faire par liste noire (on laisse passer par défaut, et on a une liste des choses interdites, c'est typiquement le cas avec la censure) ou carrément par liste blanche (on bloque par défaut et on a une liste des choses autorisées, c'est typiquement le cas des offres limitées). Une entreprise qui ne veut pas que ses employés passent du temps sur autre chose que les tâches qui leur sont affectées pourrait utiliser une liste noire (interdire ce qui leur ferait « perdre » du temps) ou la liste blanche (limiter les employés à quelques destinations connues).
Troisième critère de classification, quelle est la cible
exacte ? Veut-on bloquer un service entier (par exemple la
voix sur IP, pour protéger la vache à lait
des opérateurs téléphoniques) ? Ou un contenu très spécifique (une
seule vidéo sur YouTube) ? Certaines
techniques bloquent facilement plus que la cible visé. Par
exemple, supprimer un nom de domaine parce
que le site Web sert un contenu à problèmes va aussi couper tous
les services associés à ce nom de domaine (le
courrier par
exemple). Les demandes de take down (« le site
Web en http://example.com/
vend de la
contrefaçon, supprimez immédiatement ce nom ») prennent rarement
en compte ce problème. Si on les écoutait, chaque fois que le
WordPress d'une mairie est piraté et sert à
du hameçonnage, on supprimerait le nom de
domaine, coupant ainsi l'accès des citoyens à leur ville.
Enfin, quatrième cas, le comment, quels composants de l'Internet vont être utilisés pour le blocage. Cela peut être :
Par exemple, lorsque M. Michu veut accéder à
http://example.com/comment-partir-en-syrie
avec son navigateur Web, les machines terminales sont son
PC et le serveur
HTTP, le réseau, ce sont tous les routeurs
et autres équipements actifs sur le trajet, le service de
rendez-vous, c'est le DNS (par exemple le
registre de
.com
). Autre exemple,
Alice appelle Bob en SIP, les machines
terminales sont le
smartphone d'Alice et le
PC de Bob, le réseau, ce sont tous les routeurs
et autres équipements actifs sur le trajet, le service de
rendez-vous, c'est le proxy SIP.
Dans l'exemple HTTP ci-dessus, on peut empêcher M. Michu de regarder la page Web à de très nombreux endroits. Le RFC donne la liste complète mais voici quelques extraits, aux trois endroits possibles :
example.com
.
Le choix dépendra souvent de qui bloque. Si c'est l'utilisateur
(cas des bloqueurs de pub), il fera en général le blocage sur sa
machine terminale. Si c'est l'État, il utilisera plus souvent le
réseau ou bien le système de rendez-vous (s'il est sur son
territoire, ainsi, un
.com
peut être saisi
par les autorités états-uniennes).
Le gros du RFC est représenté par la section 4, qui évalue les différentes techniques. Les critères d'évaluation sont la portée, la granularité, l'efficacité et la sécurité. Commençons par la portée (qui est affecté).
Si je configure Shorewall sur ma machine
Linux pour bloquer le trafic vers
2001:db8:bad:1:ef5:34:aba1:96
, je n'affecte
qu'une toute petite partie de l'Internet. Si le gouvernement des
États-Unis décidait de supprimer
.ir
de la racine du
DNS, il affecterait bien plus de monde (« About
35,400,000 results » me dit
Google). D'une manière générale, le blocage
fait aux bords de l'Internet affecte peu de gens, celui fait dans
le réseau affecte beaucoup de monde, sans doute bien plus que ce
qui était nécessaire. Les exemples de « bavures » (le blocage
« bave » au delà de sa portée normale) sont nombreux, de l'Inde
censurant Oman, au célèbre cas de Pakistan Telecom bloquant
YouTube, en passant par la
censure chinoise débordant en Allemagne.
Le « bon » blocage devrait avoir la portée
la plus petite possible.
Et la granularité ? Est-ce qu'on pourra bloquer un service sans bloquer les autres ? Par exemple, si une machine héberge un serveur SMTP qui envoie du spam, peut-on la bloquer sans empêcher l'accès aux autres ressources qu'elle héberge, comme un serveur HTTP ? Idéalement, là encore, on souhaite que le blocage puisse être fait avec la granularité la plus fine possible.
Et l'efficacité ? Si on bloque, on veut qu'il ne soit pas facile de « débloquer », c'est-à-dire d'accéder aux ressources bloquées. Évidemment, si le blocage est fait par l'utilisateur (comme dans le cas des bloqueurs de publicité), pas de problème : il ne va évidemment pas chercher à contourner ce blocage. Mais si le blocage est imposé, l'expérience de l'Internet montre que les utilisateurs vont chercher à le contourner (voir par exemple les articles « Failures in a Hybrid Content Blocking System » et « Empirically Characterizing Domain Abuse and the Revenue Impact of Blacklisting »). Un service bloqué se déplace facilement, comme le montre les fréquents changements de TLD de The Pirate Bay. Du côté client, les solutions de contournement sont également nombreuses, du passage par Tor, à l'utilisation de son propre résolveur DNS pour contourner les résolveurs menteurs. Ces contournements mènent parfois à une escalade puis à une course aux armements comme dans le cas turc où le DNS menteur était contourné par l'utilisation de Google Public DNS, ce qui avait mené au piratage du routage de Google. Un autre exemple de course aux armements est le blocage des services par leur numéro de port, poussant les applications à toujours utiliser le port 80, celui de HTTP, poussant les bloqueurs à faire du DPI, poussant les applications à chiffrer, poussant les bloqueurs à faire de l'analyse de trafic pour essayer de détecter, sous le chiffrement, certains type de trafic, etc. Une telle course ne peut pas avoir de fin.
Certains de ces contournements ont d'ailleurs des conséquences pas forcément positives pour l'architecture de l'Internet. C'est ainsi que beaucoup d'applications se pressent sur le port 443, celui de HTTPS, car il est rarement filtré. Ou bien que des victimes d'un blocage de SIP passent à des solutions fermées comme Skype. Le RFC note au passage que le chiffrement rend évidemment plus difficile tout filtrage sélectif, et que cela va donc jouer dans la diabolisation du chiffrement.
Dernier exemple de technique de contournement du blocage, citée par le RFC mais jamais vue en pratique (mais elle amusera les nerds), l'ajout d'en-têtes d'extension dans les paquets IPv6 (par exemple une option Destination) suffit souvent aujourd'hui à rendre aveugles les filtres (ces en-têtes sont parfois difficiles à analyser).
Dans l'évaluation du blocage, reste la question de la sécurité : les techniques de sécurité sur l'Internet cherchent à empêcher toute interférence d'un tiers. Le blocage ne va-t-il pas entrer en conflit avec ce souhait ? Techniquement, rien ne distingue une attaque légale d'une attaque illégale : les mêmes techniques de sécurité vont réagir contre les deux. C'est le cas des protocoles qui visent (entre autres) à assurer l'intégrité des communications (TLS - RFC 5246 ou IPsec - RFC 4301). Lorsqu'on accède au site de sa banque en TLS, c'est précisement pour empêcher un tiers de modifier les données, justement ce que la censure aimerait bien faire.
La sécurité sur l'Internet repose en général sur des techniques de bout en bout, les seules sûres (RFC 4924). Certains blocages (comme le détournement des sessions TLS) nécessitent d'insérer dans le trafic un intermédiaire non prévu à l'origine, ce qui casse cette sécurité.
La section 4 du RFC se penche ensuite sur les trois lieux où on peut faire le blocage, le réseau, puis le rendez-vous, puis la machine terminale. D'abord, le réseau, par exemple via un pare-feu. Est-ce un bon endroit pour bloquer ? Si on bloque dans un réseau périphérique, proche d'une des machines terminales qui communiquent, la portée reste faible. Si, par contre, on bloque dans l'épine dorsale d'un grand réseau, la portée sera bien plus étendue (dans le cas d'une censure volontaire, une portée importante n'est pas un défaut...) Notez que le blocage dans le réseau nécessite que le réseau ait accès à suffisamment d'informations pour prendre sa décision. Cela peut mener à des pratiques comme le DPI.
Notez qu'un filtrage dans le réseau peut être complexe car rien
ne dit qu'un point du réseau verra passer tout le trafic entre
Alice et Bob. Pour des blocages sommaires (« couper toute
communication avec 192.0.2.0/24
»), ce n'est
pas un problème. Mais cela interdit des choses plus subtiles, par
exemple de bloquer certains URI sur un site
Web mais pas tous. Le routage dans l'Internet étant ce qu'il est, un
point donné peut ne voir qu'une partie des paquets d'une même
communication. C'est d'ailleurs pour cela que les censeurs
essaient toujours d'obtenir que les réseaux soient architecturés
de manière à faciliter le blocage, notamment en limitant le nombre
de points de sortie vers l'extérieur et en empêchant l'asymétrie
du routage (en se moquant des conséquences que cela peut avoir
pour les performances et la fiabilité).
Quant à l'efficacité et la sécurité du blocage dans le réseau... Le chiffrement suffit à gêner une grande partie de ces blocages. Il ne laisse que quelques métadonnées comme les adresses IP, qui peuvent être trop grossières pour le système de filtrage.
Et les techniques de contournement sont nombreuses, comme cela a pu être vu dans la lutte des ayant-droits contre The Pirate Bay. Le site visé peut changer d'adresse IP, ou de nom, ses clients peuvent passer par Tor ou par un VPN, etc. Évidemment, plus le blocage reste en place longtemps, plus les techniques de contournement se développeront et seront déployées. Si on bloque dans le réseau, c'est en général parce que les deux parties qui communiquent ne sont pas d'accord avec ce blocage. Elles ont donc des bonnes motivations pour le contourner et la lutte de l'épée et de la cuirasse va donc durer longtemps.
Le bloqueur peut essayer de bloquer l'accès aux services qui permettent un contournement. Par exemple, il peut interdire TLS vers certains sites. Comme l'a montré le projet Telex, même cela n'est pas forcément suffisant : on peut toujours, avec la participation d'un pair accessible, faire des tunnels peu repérables. Plus radical, le censeur peut interdire tout le chiffrement (en France, des tas de politiciens ne demanderaient pas mieux). Cela serait évidemment catastrophique pour la sécurité de l'Internet.
Le RFC conclut donc que le blocage dans le réseau est en général une mauvaise idée.
Bon, mais alors, se dit le censeur qui lit les RFC (cela doit être rare...), pourquoi ne pas bloquer via les systèmes de rendez-vous à la place ? En effet, on a beau parler de pair à pair, presque toutes les communications réelles sur l'Internet nécessitent un mécanisme mettant en rapport les machines de Bob et d'Alice. C'est souvent le DNS mais cela peut être un moteur de recherches (Pirate Bay joue ce rôle, mettant en rapport un utilisateur de BitTorrent et le contenu convoité) ou bien d'autres mécanismes (comme les DHT ou une blockchain).
Le blocage sur le service de rendez-vous est surtout utile pour
un État si ledit service est sous sa juridiction. Si vous utilisez
un .ly
, vous dépendez
logiquement des lois libyennes. Si le service
est global (c'est le cas d'un registre de noms de
domaine), la portée du blocage est également
globale. C'est ce qui fait qu'un service légal dans son pays a pu
perdre son .com
et
donc tous ses clients.
Si par contre le service est local (un résolveur DNS), la portée est
limitée aux utilisateurs de ce service.
Lorsque le système de rendez-vous est le DNS, la granularité du blocage est mauvaise : supprimer le nom de domaine supprime tous les services associés. Quant à l'efficacité, elle n'est jamais parfaite (voir mon article pour une étude sur le cas du DNS ou bien le rapport de l'ISOC) : les utilisateurs peuvent souvent changer de point de rendez-vous (passer à un autre résolveur DNS, par exemple), d'autant plus que la plupart des systèmes de rendez-vous n'ont aucune sécurité (des techniques d'authentification comme DNSSEC pour le DNS changeront peut-être partiellement les choses).
Un autre système de rendez-vous est souvent oublié : les IRR et, d'une manière plus générale, le mécanisme d'allocation d'adresses IP. Dans au moins un cas (déjà cité plus haut), un État a essayé de l'utiliser pour bloquer un service illégal.
En résumé, le blocage par action sur un service de rendez-vous est simple (et donc tentant pour les autorités) car on n'agit que sur un seul point, ou un petit nombre de points, mais n'est pas très efficace et, comme il consiste à bricoler l'infrastructure de l'Internet, il est dangereux pour le bon fonctionnement de celui-ci.
Reste un dernier endroit, dans l'une des machines terminales. Quelles sont les propriétés d'un blocage fait à cet endroit ? À chaque instant, le logiciel installé sur ces machines ou bien leur utilisateur prend des décisions sur le fait de communiquer ou pas. Les utilisateurs choisissent (ou pas) de cliquer sur un lien hypertexte. Le logiciel de messagerie décide si un message doit être montré ou classé dans le dossier Spam. Netfilter jette les paquets ou pas. L'utilisateur installe un nouveau logiciel de communication (ou pas). Les choix du logiciel sont guidés par l'utiisateur (cas d'un filtre bayésien à qui l'utilisateur dit « ce message est un spam ») mais le contraire arrive aussi (SafeBrowsing).
La portée d'un tel blocage est strictement locale. Si j'installe Ghostery pour bloquer les mouchards, cela n'affecte (en bien ou en mal) que moi.
La granularité est très fine : la machine terminale maitrise tous les aspects de la connexion contrairement à, par exemple, le serveur DNS, qui n'a aucune idée de pourquoi on demande ce nom de domaine. Elle peut donc ne bloquer qu'un seul service. Encore mieux si le blocage est fait dans l'application (le cas, là encore, des bloqueurs de publicité) car ils ont la totalité de l'information sur la connexion, sous une forme qui permet des traitements sans ambiguité (cf. RFC 7288).
L'efficacité est bonne. D'abord, puisque le blocage est décidé par l'utilisateur, il ne va évidemment pas chercher à le contourner. Ensuite, les services bloqués peuvent, évidemment, essayer de s'adapter (le point de distribution d'un malware va changer souvent de nom de domaine et d'adresse IP, pour disparaitre des listes noires) mais la machine terminale ayant une visibilité complète (y compris de ces changements) est dans une meilleure position que quiconque pour s'y adapter. Comme le blocage se fait aux extrêmités, il ne gêne pas l'architecture de bout en bout (chacun est bien sûr libre d'accepter de communiquer avec qui il veut).
À noter qu'il existe deux extrêmités à la communication : le blocage peut aussi être fait de l'autre côté, par le serveur (dans le cas d'une communication client/serveur). Voici par exemple les compteurs du nombre de paquets rejetés sur le serveur qui porte ce blog. On voit que je n'accepte pas tout :-)
% sudo iptables -n -v -L net-fw Chain net-fw (2 references) pkts bytes target prot opt in out source destination 9360K 659M blacklst all -- * * 0.0.0.0/0 0.0.0.0/0 679K 49M smurfs all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID,NEW,UNTRACKED 9041K 625M tcpflags tcp -- * * 0.0.0.0/0 0.0.0.0/0 74720 11M Drop all -- * * 0.0.0.0/0 0.0.0.0/0 8881 631K DROP all -- * * 0.0.0.0/0 0.0.0.0/0
On peut faire la même chose de tas de façons. Par exemple, un serveur HTTP comme Apache a plein de techniques permettant toutes sortes de blocages des visiteurs importuns. Et, évidemment, pour bloquer un service entier sur le serveur, c'est très facile, on ne fait tout simplement pas tourner le logiciel correspondant.
Bien sûr, ce blocage nécessite l'accord de la personne qui utilise ladite machine terminale et les censeurs ne seront donc pas enthousiastes à l'idée de lui demander.
Bref, le blocage sur une des machines terminales est de loin celui qui a le moins de chances de causer des dommages collatéraux sur l'Internet.
Comme tous les RFC, notre RFC 7754 contient une section dédiée à la sécurité, la section 5. Son point essentiel est que le blocage dans le réseau ou dans les services de rendez-vous est un danger pour la sécurité de l'Internet : il s'oppose frontalement aux mesures de sécurité. Par exemple, pour bloquer, on va essayer de casser le chiffrement, avec une attaque de l'homme du milieu, comme le font beaucoup d'entreprises, avec les produits de société comme Blue Coat, en fabriquant de faux certificats pour que les logiciels ne détectent pas cette attaque.
En outre, le système qui effectue cette attaque devient lui-même une cible tentante pour un attaquant extérieur puisqu'il donne accès à tout le trafic en clair. On a donc mis en péril toutes les machines de l'entreprise en introduisant cette « machine du milieu ». (En tant qu'ancien ingénieur système, je suis également sensible à la remarque du RFC comme quoi l'administrateur de cette machine court un gros risque juridique personnel, puisqu'il va avoir accès à des tas de données sensibles.)
La conclusion du RFC (section 6) est que, si on tient à faire du blocage, il faut le faire sur les machines terminales et laisser le réseau tranquille, afin qu'il puisse faire son travail avec rapidité et sécurité. Gageons que cet avis ne sera pas suivi. Parmi toutes les discussions sur le blocage, le filtrage et la censure, beaucoup de temps a été passé sur la légitimité ou non de ces blocages (« si vous vous opposez à la Main Rouge, c'est que vous sympathisez avec les terroristes ») et nettement moins sur les conséquences techniques de ces blocages. En gros, si on veut faire de la censure efficace, il faut ré-architecturer l'Internet pour la censure et non pas pour la communication. (Cf. mon exposé à l'Assemblée Générale de France-IX, et les supports.)
Un des auteurs du RFC, Olaf Kolkman, a écrit ses réflexions personnelles.
Première rédaction de cet article le 4 mars 2016
Tout le monde, surtout les gens qui ne savent pas distinguer ROT13 de SHA-256, l'a constaté et largement commenté sur les rézosocios : le site de la CNIL a un problème de certificat. Que s'est-il donc passé ? C'est de leur faute ? Ce sont des gros nuls, doublés de feignants ? Les certificats servent-ils à quelque chose ?
Pour commencer, essayez ces deux liens :
et https://cnil.fr/
. Avec le certificat installé
aujourd'hui, le premier lien devrait déclencher une erreur de
sécurité (genre « The certificate is only valid for the
following names: www.cnil.fr [...] »), le second lien va
marcher avec certaines machines, mais, avec d'autres, vous aurez
un avertissement de sécurité (comme « The certificate is
not trusted because the issuer certificate is
unknown »).https://www.cnil.fr/
Avant de répondre aux questions que je posais plus haut, revenons au rôle des certificats (si vous lisez le X.509 en codé en DER sans l'aide d'un ordinateur, et en faisant les calculs RSA de tête, vous pouvez sauter ce paragraphe). La communication avec le site de la CNIL utilise le protocole HTTPS, qui est HTTP avec en prime la sécurité qu'apporte la cryptographie. Celle-ci, fournie par un mécanisme nommé TLS (et que certains conservateurs s'obstinent à nommer de son nom du siècle précédent, SSL), permet d'éviter l'écoute de votre conversation par un tiers indiscret. Elle fournit également une certaine authentification du site distant, vous garantissant (en théorie) que vous allez bien sur le site de la CNIL. (Les deux fonctions, confidentialité et authentification, sont en fait liées : sans l'authentification, vous pourriez parler à l'Homme du Milieu, qui pourrait alors lire vos communications.) Le certificat est une clé cryptographique, celle qu'utilise le serveur distant pour chiffrer ses communications avec vous, agrémenté d'une série de noms (la norme technique des certificats, X.509, les appelle « sujets »), de quelques métadonnées et signé par une Autorité de Certification. Cette signature par une AC vous garantit que le certificat est bien celui de la CNIL et pas un certificat qu'un plaisantin a généré lui-même, en y mettant comme nom celui de la CNIL.
Deux points sont particulièrement à retenir dans ce résumé très simplifié : le certificat indique les noms possibles pour le site Web, et il ne sera accepté que s'il est signé par une AC elle-même « acceptée ». Or, le nouveau site de la CNIL a deux problèmes, portant sur ces deux points.
Premier problème, dans la liste des noms (les « sujets ») du
certificat, on ne trouve pas cnil.fr
. Si on
se connecte à
,
on aura donc systématiquement une erreur du genre :
(Dans la version française du navigateur, « Le certificat n'est valide que pour les noms suivants : www.cnil.fr […])https://cnil.fr/
Comment trouver cette liste ? Le navigateur Web peut vous la donner. Sur Firefox, cliquer sur le cadenas, demander More information puis View certificat et, dans la liste des attributs du certificat, sélectionner subject et Subject Alt Name :
Une méthode plus geek est d'utiliser OpenSSL en ligne de commande :
% openssl s_client -connect cnil.fr:443 | openssl x509 -text ... Subject: C=FR, O=COMMISSION NAT INFORMATIQUE ET LIBERTE, OU=0002 11000012200025, L=PARIS, CN=www.cnil.fr/serialNumber=1-3291 ... X509v3 Subject Alternative Name: DNS:www.cnil.fr, DNS:piwik.cnil.fr, DNS:backoffice.cnil.fr, DNS:www.jeunes.cnil.fr, DNS:www.educnum.fr
On voit bien que cnil.fr
ne figure pas dans les
noms. Cette erreur là (car, oui, à mon avis, c'est une erreur de
la part de la CNIL, qui permet les connexions à
https://cnil.fr/
mais ne présente pas de quoi
l'authentifier) explique le premier problème.
Le second problème, maintenant. Il ne se produit qu'avec certains systèmes. Par exemple, le Firefox sur ma Debian affiche :
www.cnil.fr uses an invalid security certificate. The certificate is not trusted because the issuer certificate is unknown. (Error code: sec_error_unknown_issuer)
Ici, le problème est tout différent. Rappelez-vous que le certificat doit être signé par une Autorité de Certification (le issuer du message ci-dessus). Chaque logiciel qui se connecte avec le protocole TLS a un magasin stockant les AC (Autorités de Certification) qu'il reconnait. (Parfois, le magasin est global au système d'exploitation, ou bien à une bibliothèque logicielle particulière, et le navigateur Web ne fait qu'utiliser ce magasin qu'on lui a fourni.) Qui décide de ce qu'on met dans le magasin ? Eh bien, c'est ça qui est drôle, personne. Il n'existe pas d'autorité qui décide de ce qu'on met ou pas dans ce magasin. Chaque gestionnaire d'un magasin d'AC (donc, chaque navigateur Web, ou système d'exploitation) a ses propres critères (parfois documentés - ici, la politique de Mozilla, parfois opaques, parfois arbitraires) pour décider. Résultat, deux magasins n'ont jamais le même contenu. On peut donc avoir un certificat qui est accepté par une machine et refusé par une autre, ou même accepté par un navigateur Web et refusé par un autre sur la même machine.
C'est ce qui est arrivé à la CNIL. Leur certificat est signé par l'AC Certinomis et certains n'ont pas le certificat de l'AC dans leur magasin (ou, peut-être, n'ont qu'un autre certificat de cette AC). C'est un problème fréquent, et qui n'est pas réellement de la faute de la CNIL. (À noter que la version HTTPS de mon blog a souvent le même problème, en raison de son utilisation de l'AC CAcert.)
Ce petit incident est donc l'occasion de rappeler quelques règles de fonctionnement du système X.509, qui est derrière l'authentification des sessions TLS :
Date de publication du RFC : Mars 2016
Auteur(s) du RFC : J. Dickinson, S. Dickinson (Sinodun), R. Bellis (ISC), A. Mankin (Verisign Labs), D. Wessels (Verisign Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 4 mars 2016
Ce nouveau RFC décrit des exigences bien plus importantes pour l'utilisation du DNS au-dessus de TCP : non seulement les serveurs DNS doivent gérer TCP (ce qui a toujours été le cas), mais ils doivent le faire sur un pied d'égalité avec UDP. TCP n'est pas une solution de secours pour des cas rares, c'est désormais une alternative complète à UDP pour le service DNS. La règle est donc désormais plus radicale qu'avec le RFC précédent, le RFC 5966, maintenant retiré.
Traditionnellement, surtout avant la sortie du RFC 5966, le DNS utilisait surtout UDP. Beaucoup de gens croyaient même, bien à tort, que TCP ne servait que pour des cas très particuliers comme le transfert de zones ou comme la récupération de données plus grosses que 512 octets. Ces croyances étaient déjà fausses lors de la sortie des RFC originels sur le DNS, mais le RFC 5966 leur a tordu le cou complètement. UDP a en effet des limites :
La formulation des sections 3.7 du RFC 1034 et 4.2 du RFC 1035 sur l'usage de TCP étaient assez claires (mais personne ne lit les RFC...) Par contre, la section 6.1.3.2 du RFC 1123 avait semé la confusion en laissant entendre que TCP était facultatif. C'est désormais corrigé, TCP est bien obligatoire pour le DNS.
Mais TCP, utilisé bêtement, souffre de plusieurs défauts : si on ouvre une connexion TCP à chaque requête DNS, la latence va être bien plus élevée qu'en UDP, et, si on fait passer toutes les requêtes séquentiellement sur une seule connexion TCP, et que le serveur les traite dans l'ordre, une requête lente peut faire attendre des requêtes qui auraient été rapides. Voici pourquoi notre RFC impose un certain nombre de comportements intelligents (section 3) :
J'ai parlé plus haut de la taille des réponses DNS (section 4 du RFC). C'était autrefois une des bonnes raisons de passer en TCP, afin d'obtenir des réponses supérieures à 512 octets. Les clients DNS le font typiquement automatiquement. Par exemple, ici, dig tente d'obtenir une réponse de plus de 512 octets, et elle est donc tronquée (flag TC pour TrunCation) :
% dig +bufsize=0 +noedns +nodnssec +ignore NS fox.com ... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38102 ;; flags: qr tc rd ra ad; QUERY: 1, ANSWER: 15, AUTHORITY: 0, ADDITIONAL: 0 ... ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; MSG SIZE rcvd: 494
J'ai utilisé l'option +ignore
pour voir cette
troncation. Si on ne l'utilise pas, dig passe automatiquement en TCP
(le message « Truncated, retrying in TCP mode ») :
% dig +bufsize=0 +noedns +nodnssec NS fox.com ;; Truncated, retrying in TCP mode. ... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24693 ;; flags: qr rd ra; QUERY: 1, ANSWER: 16, AUTHORITY: 0, ADDITIONAL: 0 ... ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; MSG SIZE rcvd: 522
Maintenant qu'on a EDNS (RFC 6891), TCP est moins utile
pour ce problème de taille (il reste utile pour les autres raisons
énumérées au début). Voici un exemple avec EDNS pour une donnée de
grande taille (comme le note la section 4, une réponse négative,
NXDOMAIN
dans une zone signée avec
DNSSEC/RSA et utilisant le NSEC3 du RFC 5155 va presque toujours faire plus de 512 octets) :
% dig +bufsize=4096 A nimportequoinexistepas.fr ... ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 27274 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 1 ... ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; MSG SIZE rcvd: 1012
Le +bufsize=4096
active EDNS, avec une taille
maximale des réponses de 4 096 octets.
(Notez que la troncation est aussi utilisée pour des raisons de sécurité, lorsqu'un serveur détecte une attaque par amplification. Avec la technique RRL, le serveur répond alors avec des paquets tronqués - paquets nommés SLIP, pour forcer le client à réessayer en TCP, où il n'y aura pas d'usurpation d'adresse IP possible.)
Reste la question de la MTU. La réponse précédente faisait 1 012 octets, inférieure à la MTU typique (en général de 1 500 octets, à cause d'Ethernet). Si elle est plus grande, la réponse va être fragmentée et, là, les ennuis commencent. On ne peut pas compter sur la bonne réception des paquets fragmentés : trop de pare-feux configurés avec les pieds sont sur le trajet, et ils jettent souvent bêtement les fragments. En parlant de middleboxes, il faut aussi noter que certaines perturbent EDNS (RFC 5625). Les réponses supérieures à 1 500 octets, elles, auront peut-être besoin de TCP :
% dig DNSKEY cpsc.gov ... ;; MSG SIZE rcvd: 1733
La section 5 du RFC est la partie normative. Elle contient la nouvelle règle : un serveur DNS doit parler TCP. Et un client DNS peut s'en servir, il n'est même pas forcé d'attendre la troncation.
Maintenant, les détails pratiques. D'abord (section 6), la gestion des connexions TCP. Compte-tenu de la « triple poignée de mains » qui ouvre les connexions TCP, et de son coût en latence, il est fortement recommandé d'éviter de faire une connexion TCP par requête DNS. L'idée est donc, pour le serveur, de ne pas fermer la connexion dès qu'elle est inactive mais de la garder ouverte (comme le font HTTP 1.1 - RFC 7230 et HTTP 2 - RFC 7540) et, pour les clients, de ne pas fermer après la première requête (ce qu'ils font actuellement, en général). Mais, contrairement à HTTP, le DNS n'a pas encore de mécanisme de fermeture explicite de ces connexions TCP persistentes (certains ont été proposés). Il faut donc utiliser des heuristiques pour savoir quand fermer une connexion.
Au fait, j'ai parlé de « connexion inactive » sans l'expliquer. La section 3 la définit comme « pour un client, lorsqu'il a reçu toutes les réponses à ses questions, pour un serveur, lorsqu'il a répondu à toutes les questions posées ».
Les serveurs actuels laissent en général les connexions assez longtemps (deux minutes par défaut, sur Unbound ou sur NSD), et ont un nombre de connexions TCP maximal assez faible. Cela permet des attaques par déni de service triviales (ouvrir N connexions TCP, attendre) ou même des simples accidents, où un petit nombre de clients, sans le faire exprès, épuisent complètement les maigres ressources allouées à TCP. Avec BIND, vous pouvez par exemple regarder combien de clients TCP sont actuellement actifs par rapport au maximum autorisé. Si le nombre de clients actifs se rapproche trop du maximum, il y a un risque :
% rndc status | grep tcp tcp clients: 8/100
Notre RFC recommande donc (section 6.2) une série de bonnes pratiques qui vont
permettre à TCP d'être utilisé massivement pour le DNS. D'abord,
réutiliser les connexions, de façon à amortir le coût, relativement
élevé, de l'établissement d'une connexion, sur plusieurs
requêtes. Attention, le client DNS ne doit pas réutiliser
l'identicateur de requête (Query ID, ou
id:
dans la sortie de dig) sur la même connexion,
tant qu'il reste une question non répondue utilisant cet
identificateur (autrement, le client ne saurait pas à quelle question
correspond une réponse).
Ensuite, une requête ne devrait pas avoir à attendre la réponse à la requête précédente. Dès que le client a une question, il l'envoie (pipelining).
Au passage, un client DNS gourmand pourrait être tenté d'ouvrir plusieurs connexions TCP avec le serveur. Notre RFC le déconseille (sauf pour des cas ponctuels comme les longs transferts de zone) : cela use des ressources, et c'est inutile, si on a le pipelining et le traitement en parallèle. Un serveur a donc le droit de mettre des limites et, par exemple, de ne pas accepter plus de N connexions TCP par adresse IP (avec N probablement strictement supérieur à 1 car il faut tenir compter des clients différents situés derrière une même adresse IP, par exemple en cas de CGN).
Bon, et le quantitatif ? C'est bien de dire qu'un serveur ne devrait pas laisser les connexions TCP inactives ouvertes trop longtemps, mais combien, exactement ? Le RFC recommande quelques secondes, pas plus, après le traitement de la dernière requête, sauf si on a reçu une demande explicite (voir le RFC 7828). À comparer avec les 120 secondes actuelles de NSD ou Unbound... Cette durée peut évidemment être réglée dynamiquement, par exemple pour répondre à la disponibilité de ressources chez le serveur (nombre maximum de connexions TCP atteint, je coupe des connexions inactives...)
Dans tous les cas, outre la coupure d'une connexion par un client qui a fini son travail, le client doit aussi se rappeler qu'un serveur DNS a le droit de couper les connexions TCP quand ça lui chante, et sans prévenir à l'avance. Le client doit donc gérer ces coupures (détecter et reconnecter). C'est d'autant plus important qu'un serveur peut redémarrer (perdant ses sessions TCP) ou que tout simplement, le routage peut changer, amenant le client DNS vers une autre instance d'un nuage anycast, instance qui n'a pas les sessions TCP en cours.
Et le traitement en parallèle (section 7) ? C'est un des points importants de DNS sur TCP, sans lequel TCP n'aurait guère d'intérêt. Lorsqu'un résolveur minimum (rappel, la terminologie du DNS est dans le RFC 8499) se connecte à un résolveur complet en TCP, le résolveur complet va mettre un temps très variable à répondre aux questions. De quelques dizaines de micro-secondes si la réponse est dans le cache à des centaines de milli-secondes s'il a fallu interroger trois ou quatre serveurs faisant autorité avant d'avoir sa réponse. Si le traitement des requêtes était fait de manière strictement séquentielle, la requête rapide qui aurait la malchance d'être située après une requête lente devrait patienter très longtemps. Il est donc crucial de traiter les requêtes en parallèle.
Conséquence : il est parfaitement normal que, lorsqu'on envoie les questions Q1 puis Q2, la réponse R2 arrive avant R1. Tous les clients DNS doivent être prêts à cela. Le démultiplexage des réponses doit se faire sur le Query ID du DNS (et voilà pourquoi il ne faut pas le dupliquer) et, dans le cas le plus fréquent, également sur le nom demandé (QNAME, pour Query NAME).
L'encodage d'un message DNS en TCP est très légèrement différent de ce qu'il est en UDP. Un champ Longueur, de deux octets, précède en effet le message, pour faciliter la lecture. Cela permet au récepteur de savoir combien d'octets il va lire dans le flux TCP (qui, rappelons-le, n'a pas la notion de messages, c'est juste un flux d'octets sans séparateurs). Par exemple, en Go, on lirait ainsi :
// Lire le champ Longueur smallbuf := make([]byte, 2) n, error := connection.Read(smallbuf) msglength := binary.BigEndian.Uint16(smallbuf) // RFC 1035, section 4.2.2 "TCP usage" // Allouer un tampon pour le message message := make([]byte, msglength) // Lire le message DNS n, error = connection.Read(message)
Le RFC recommande (section 8) que les émetteurs DNS passent ce champ Longueur et
le message ensemble, dans un seul write()
sur le
réseau, de façon à maximiser les chances qu'ils se trouvent dans le
même paquet IP, certaines mises en œuvre réagissant mal dans le cas contraire. Ce n'est pas une garantie absolue (TCP peut découper
en paquets IP comme il veut). Les experts en Go noteront que le code
ci-dessus ne tient pas compte de ce risque :
Read()
peut lire moins d'octets que la taille du
tampon, il faudrait tester ce cas (ou bien utiliser
ReadFull()
.) Et, naturellement, il faudrait
tester les cas d'erreur.
On a vu qu'un des problèmes potentiels dus à l'utilisation de
TCP était la latence liée à l'ouverture des connexions. Outre la
réutilisation des connexions pour plusieurs requêtes, un autre
mécanisme peut aider à limiter ce problème (section 9) : TCP Fast Open (RFC 7413). En permettant aux données d'être transportées dès le
paquet initial (le paquet SYN
), il fait
gagner du temps. Contrairement à d'autres tentatives précédentes de
faire de l'« ouverture rapide », TCP Fast Open ne
permet pas d'attaques par réflexion, grâce à un
cookie. C'est donc une solution à considérer, pour
les clients et serveurs DNS utilisant TCP.
C'est un bon prétexte pour discuter de sécurité (section 10). Lors de la mise au point de ce RFC, il y a eu beaucoup
de discussions concernant le risque d'attaque par déni de
service pour les serveurs DNS. Le traitement d'une requête
TCP (y compris l'établissement de la connexion) nécessite, après tout,
davantage de ressources que celui d'une requête UDP. Mais on a aussi
davantage d'expérience avec les attaques utilisant TCP (c'est le
protocole sous HTTP, après tout, et de
nombreuses attaques sont faites contre les serveurs Web). Outre la
lecture du « Security
Assessment of the Transmission Control Protocol
(TCP) », notre RFC recommande de permettre de
configurer le serveur DNS sur des points comme le nombre total de
connexions TCP (tcp-clients
pour
BIND,
tcp-count
pour NSD,
incoming-num-tcp
pour Unbound), le nombre maximal de connexions TCP par adresse IP de
client, la durée de vie des connexions inactives
(tcp-timeout
pour NSD et, attention, il faut
redémarrer le serveur si on le change), le nombre maximal de
requêtes DNS par connexion (tcp-query-count
pour NSD), etc. Sans compter les réglages permis par
le système d'exploitation (comme les
innombrables paramètres sysctl
net.ipv4.tcp_*
de
Linux et, oui, c'est ipv4
même pour IPv6).
En prime, le RFC rappelle que les résolveurs ne devraient pas accepter des connexions du monde entier (RFC 5358), mais, sauf cas rares, uniquement de certains préfixes IP, leurs clients. Cela contribue à limiter les risques.
Pour les amateurs de choix technologiques complexes, l'annexe A du RFC résume les avantages et les inconvénients de TCP pour le DNS. Avantages :
Inconvénients :
Le rapport « Connection-Oriented DNS to Improve Privacy and Security » discute bien plus en détail ces choix.
Enfin, l'annexe B liste les principaux changements depuis le RFC 5966. Ils sont importants puisqu'on passe d'un modèle « TCP dans certains cas » à un modèle « pouvoir faire tout en TCP si on veut ». Par exemple, un client peut désormais utiliser TCP avant d'avoir testé en UDP. Les autres changements sont des conséquences de ce principe : les logiciels DNS doivent désormais permettre la réutilisation des connexions, le pipelining et le traitement en parallèle des requêtes parce que, sans cela, TCP ne serait pas vraiment utilisable pour le DNS.
Allez, pour finir, un example avec dig où on demande explicitement du TCP :
% dig +tcp @d.nic.fr NS gouvernement.fr ; <<>> DiG 9.9.5-9+deb8u3-Debian <<>> +tcp @d.nic.fr NS gouvernement.fr ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14247 ;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 7, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;gouvernement.fr. IN NS ;; AUTHORITY SECTION: gouvernement.fr. 172800 IN NS ns2.produhost.net. gouvernement.fr. 172800 IN NS ns33.produhost.net. gouvernement.fr. 172800 IN NS ns1-sgg.produhost.net. 98dsof44tab20a3p7gv0cgelh01vlv9j.fr. 5400 IN NSEC3 1 1 1 D0D3AC0C ( 98ECUBNBQN7GCK4GQ1KQURRJTRUF6P83 NS SOA TXT NAPTR RRSIG DNSKEY NSEC3PARAM ) 98dsof44tab20a3p7gv0cgelh01vlv9j.fr. 5400 IN RRSIG NSEC3 8 2 5400 ( 20160213101014 20151215091014 1146 fr. MDAHRaeLGVQiK6KEQvFn8PNSl608bd5iMup4cwkqgStB uXEFWOpQLeSy37IattIDOt0AhwEirpNe7pzH+KMOdrM0 mEWGiGa3iSdsF9hc29JDUtVyfalNmJqPIoDplw+Q0lpI Jxd8XlI/229PEH64Nua2jgLk5gxyZPCFt7yVvGg= ) ceast34o75e1lj5eprb3j5i82re4g1ug.fr. 5400 IN NSEC3 1 1 1 D0D3AC0C ( CEB3B4VDS9MG7Q92A7FVCRQ5TTIVJ3LT NS DS RRSIG ) ceast34o75e1lj5eprb3j5i82re4g1ug.fr. 5400 IN RRSIG NSEC3 8 2 5400 ( 20160213054416 20151215054416 1146 fr. Eusw6LfnNPxmquf8JDHJnWZpBFJj8hrvJi1lx3bounyO YW8ceJsrm0AkjMHm5Sh40TDfXcVrLeTK5U9PWJYqpUAG 7LABfh4nwwnlofvuyKtSx1yl44G6Gv/MSyQUnj0dIgQ5 6MB+b3tsUx2rHI2D0w9kiV50xJeCYVBiViQP2y8= ) ;; Query time: 19 msec ;; SERVER: 2001:678:c::1#53(2001:678:c::1) ;; WHEN: Tue Dec 15 22:07:36 CET 2015 ;; MSG SIZE rcvd: 607
Et le tcpdump correspondant :
% sudo tcpdump -n -vvv host 2001:678:c::1 tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes 22:08:08.073682 IP6 (hlim 64, next-header TCP (6) payload length: 40) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [S], cksum 0x2782 (correct), seq 2640844175, win 28400, options [mss 1420,sackOK,TS val 2942466 ecr 0,nop,wscale 7], length 0 22:08:08.090127 IP6 (hlim 57, next-header TCP (6) payload length: 40) 2001:678:c::1.53 > 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105: Flags [S.], cksum 0xcb39 (correct), seq 1288542264, ack 2640844176, win 17856, options [mss 8940,sackOK,TS val 1674059577 ecr 2942466,nop,wscale 7], length 0 22:08:08.090175 IP6 (hlim 64, next-header TCP (6) payload length: 32) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [.], cksum 0x5c1c (correct), seq 1, ack 1, win 222, options [nop,nop,TS val 2942470 ecr 1674059577], length 0 22:08:08.090246 IP6 (hlim 64, next-header TCP (6) payload length: 78) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [P.], cksum 0x71d1 (correct), seq 1:47, ack 1, win 222, options [nop,nop,TS val 2942470 ecr 1674059577], length 4619356+ [1au] NS? gouvernement.fr. ar: . OPT UDPsize=4096 OK (44) 22:08:08.107559 IP6 (hlim 57, next-header TCP (6) payload length: 32) 2001:678:c::1.53 > 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105: Flags [.], cksum 0x5c2e (correct), seq 1, ack 47, win 140, options [nop,nop,TS val 1674059595 ecr 2942470], length 0 22:08:08.109126 IP6 (hlim 57, next-header TCP (6) payload length: 641) 2001:678:c::1.53 > 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105: Flags [P.], cksum 0x6c2e (correct), seq 1:610, ack 47, win 140, options [nop,nop,TS val 1674059595 ecr 2942470], length 60919356- q: NS? gouvernement.fr. 0/7/1 ns: gouvernement.fr. [2d] NS ns2.produhost.net., gouvernement.fr. [2d] NS ns33.produhost.net., gouvernement.fr. [2d] NS ns1-sgg.produhost.net., 98dsof44tab20a3p7gv0cgelh01vlv9j.fr. [1h30m] Type50, 98dsof44tab20a3p7gv0cgelh01vlv9j.fr. [1h30m] RRSIG, ceast34o75e1lj5eprb3j5i82re4g1ug.fr. [1h30m] Type50, ceast34o75e1lj5eprb3j5i82re4g1ug.fr. [1h30m] RRSIG ar: . OPT UDPsize=4096 OK (607) 22:08:08.109137 IP6 (hlim 64, next-header TCP (6) payload length: 32) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [.], cksum 0x5961 (correct), seq 47, ack 610, win 244, options [nop,nop,TS val 2942474 ecr 1674059595], length 0 22:08:08.109743 IP6 (hlim 64, next-header TCP (6) payload length: 32) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [F.], cksum 0x595f (correct), seq 47, ack 610, win 244, options [nop,nop,TS val 2942475 ecr 1674059595], length 0 22:08:08.130087 IP6 (hlim 57, next-header TCP (6) payload length: 32) 2001:678:c::1.53 > 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105: Flags [F.], cksum 0x59b3 (correct), seq 610, ack 48, win 140, options [nop,nop,TS val 1674059614 ecr 2942475], length 0 22:08:08.130133 IP6 (hlim 64, next-header TCP (6) payload length: 32) 2001:db8:cafe:1234:21e:8cff:fe76:29b6.60105 > 2001:678:c::1.53: Flags [.], cksum 0x5946 (correct), seq 48, ack 611, win 244, options [nop,nop,TS val 2942480 ecr 1674059614], length 0
Question mise en œuvre, remarquez que les dernières versions de BIND ont un outil nommé mdig qui permet d'envoyer plusieurs requêtes DNS sur une même connexion TCP (en pipeline, sans attendre la réponse à la première).
Première rédaction de cet article le 2 mars 2016
Dernière mise à jour le 3 novembre 2017
J'ai déjà raconté ici comment j'avais enregistré dans la
blockchain
Namecoin le nom
d/bortzmeyer
, mon
premier nom Namecoin. Eh bien, je l'ai perdu
accidentellement et stupidement (puis récupéré après), et cette perte est l'occasion de regarder
quelques faiblesses de Namecoin.
Pourquoi Namecoin ? Parce que, disent ses promoteurs, il permet l'enregistrement de noms de manière complètement pair à pair. En prime, depuis quelques mois, « blockchain » est devenu un buzzword et, justement, Namecoin utilise une blockchain, un livre des opérations public, permettant une vérification par tous. Mais les fans de Namecoin oublient de signaler que le prix à payer, pour cette indépendance vis-à-vis de tout organisme, est qu'il faut s'occuper de tout soi-même (par exemple faire sa gestion de clés cryptographiques) et que les erreurs ne pardonnent pas.
C'est une telle erreur que j'ai bêtement fait. Je n'ai pas renouvelé le nom. Il a donc été retiré, puis ré-enregistré mais par quelqu'un d'autre. Voyons les étapes, en utilisant un explorateur public. (Comme je l'ai récupéré par la suite, vous pouvez également chercher cette récupération.)
Le nom a été enregistré le
16 janvier 2014. Il a ensuite été modifié, chaque
modification remettant à zéro le compteur. Le dernier
renouvellement (qui était juste un renouvellement, sans changement
du contenu) a été fait
le 22 janvier 2015. Non renouvelé, le nom
d/bortzmeyer
a expiré et a été
ré-enregistré le
29 septembre 2015. Une seule donnée dans ce nom a été mise
par le nouveau titulaire, le
même jour. Cette donnée était une adresse BitMessage. (Toute l'histoire peut se
voir d'un coup en https://namecha.in/name/d/bortzmeyer
. À noter qu'un autre
explorateur de la blockchain, plus connu mais
plus bogué, ne voit pas le ré-enregistrement.)
Pourquoi le nouveau titulaire a-t-il indiqué une adresse BitMessage ? Probablement pour qu'on le contacte afin de payer une rançon pour récupérer le nom maladroitement perdu. Cette pratique semble assez courante dans le monde Namecoin en ce moment. Elle illustre l'absence de toute sécurité autre que technique : si on fait une erreur, ou qu'on est négligent, on est fichu. (J'ai écrit à l'adresse BitMessage en question, sans réponse, ce compte semble hors-ligne, mon client BitMessage ne reçoit pas sa clé publique, ou alors c'est que le réseau BitMessage ne marche plus.) Cette pratique d'enregistrer un nom abandonné est très répandu dans le monde des noms de domaine traditionnels.
Comme Namecoin est très peu utilisé en pratique, je ne m'étais même pas aperçu de la perte. J'étais abonné au système d'alarme Name Alert mais celui-ci semble très bogué. Je n'ai pas reçu les messages prévenant que l'expiration approchait, et je n'ai reçu le message m'avertissant du nouveau contenu du nom que le 2 mars, plusieurs mois plus tard ! Cela donne une idée de l'état de l'écosystème Namecoin.
Par la suite, le détourneur a dû se lasser de ne pas avoir de
proposition de rachat, et a laissé tomber le nom, que j'ai alors
repris. (Cherchez avec les explorateurs, cela vous fera un bon
exercice.) Si vous avez un résolveur DNS
qui gère le .bit
, vous
pouvez à nouveau voir le nom :
% dig AAAA bortzmeyer.bit ... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3037 ... ;; ANSWER SECTION: bortzmeyer.bit. 86257 IN AAAA 2605:4500:2:245b::42 ;; AUTHORITY SECTION: bit. 70716 IN NS ns5.opennic.glue. bit. 70716 IN NS ns6.opennic.glue. ... ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Fri Nov 03 09:39:55 CET 2017 ;; MSG SIZE rcvd: 264
Le problème de perte de noms est-il soluble ? Oui, bien sûr, on pourrait imaginer la mise en place d'un système de notariat où des notaires stockent les clés et renouvellent les noms pour le compte de leurs clients. Cela permettrait à des non-experts d'avoir des noms Namecoin, tout en préservant la liberté du choix : chacun serait libre d'utiliser le notaire qu'il veut. En l'absence d'un tel système, il y a peu de chance que Namecoin soit un jour adopté massivement.
Première rédaction de cet article le 1 mars 2016
Dernière mise à jour le 5 mars 2016
Aujourd'hui a été publiée la faille de sécurité Drown, touchant notamment la bibliothèque cryptographique OpenSSL. C'est l'occasion de se livrer à quelques réflexions sur Drown, TLS et la sécurité.
Le même jour, huit (!) failles de sécurité dans OpenSSL ont été publiées (Drown a été éclaté en deux failles, CVE-2016-0800 et CVE-2016-0703). Cela ne facilite pas le travail de ceux qui essaient de démêler tout cela mais Drown est très bien documenté sur son site officiel (très complet, avec logo et tout). Je recommande également le papier officiel, très clair. Il n'y a normalement donc pas besoin de ré-expliquer ce qu'est Drown.
Pourtant, je suis étonné de constater que certaines choses n'ont pas été comprises. Par exemple bien des gens croient que, puisque leur serveur HTTPS n'accepte pas SSLv2, ils sont en sécurité. Rien n'est plus faux et c'est bien expliqué dans la FAQ de Drown : pour effectuer cette attaque, il suffit que la clé du site visé soit disponible sur un autre site, qui, lui, accepte SSLv2. Et, c'est là un point qui m'a personnellement surpris, ce cas est assez fréquent. Comme le note l'article Drown, le modèle de financement des AC encourage à acheter le moins de certificats possibles, et donc à les utiliser sur plusieurs serveurs, ou bien sur le serveur de production et sur celui de développement.
Prenons un exemple : le serveur du journal quotidien Ouest-France n'est apparemment pas vulnérable, il ne gère pas SSLv2 :
% openssl s_client -connect www.ouest-france.fr:443 -ssl2 CONNECTED(00000003) write:errno=104 --- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 0 bytes and written 48 bytes --- New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : SSLv2 Cipher : 0000 ...
Mais on trouve, sur un tout autre réseau, une machine
93.17.51.145
qui, elle, acceptait (elle a été
réparée depuis) SSLv2 et a un
certificat *.ouest-france.fr
(les certificats
avec joker sont évidemment les plus vulnérables à Drown puisqu'on les
achète justement pour les mettre sur plusieurs machines) :
% openssl s_client -connect 93.17.51.145:443 -ssl2 CONNECTED(00000003) ... subject=/C=FR/postalCode=35000/ST=Ille-et-Vilaine/L=RENNES/street=10 rue Du Breil/street=ZI Rennes Sud-Est/O=SOCIETE OUEST FRANCE/OU=0002 377714654/CN=*.ouest-france.fr ... SSL handshake has read 1609 bytes and written 367 bytes --- New, SSLv2, Cipher is RC2-CBC-MD5 Server public key is 2048 bit Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : SSLv2 Cipher : RC2-CBC-MD5 Session-ID: 6F1500003AE7F4EF421B7C964089D28B
Le journal Ouest-France est hébergé par SDV et
cette 93.17.51.145
est apparemment dans les
locaux du journal. Machine de développement ? Serveur utilisé pour des
applications internes ? En tout cas, contrairement au site Web public,
cette machine ne semble pas avoir fait l'objet de tests de sécurité
et, à elle seule, elle rendait l'attaque Drown possible.
En effet, il s'agit bien de la même clé (pas uniquement du même nom
dans le certificat) :
% openssl s_client -connect 93.17.51.145:443 | openssl x509 -pubkey -noout ... -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu83rhWk01bad5z55tfKN TlqWSdXou/QXTNVsk0J47FFEYCvumcd5TgrLtsRDjz23K1+8T9KXgIzNN4wXwWUc 7O1Hu0ddX4w0OOiSaq2rxPcXdzeF98Mth+MtclUliYZTPa94TXEMSM/xPeELkfmi sAqJjVFfGqacFcuzI0QryQPkAAU4ts0JtAoaUhHDNc+3Mz2UnHtaYsLEh9cHdkKq QzpggPPN4emqcEr3fbvTPl0JIYossH/mOI8E4NTyVaZaScimi8efklxF3JEc+/6w AqzGXt8CL2/ce+E4BojHCfilGrxU4WEeo7e9sMXHuhWCQ/fxT/6o3yktI+sLSv61 RQIDAQAB -----END PUBLIC KEY----- % openssl s_client -connect www.ouest-france.fr:443 | openssl x509 -pubkey -noout -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu83rhWk01bad5z55tfKN TlqWSdXou/QXTNVsk0J47FFEYCvumcd5TgrLtsRDjz23K1+8T9KXgIzNN4wXwWUc 7O1Hu0ddX4w0OOiSaq2rxPcXdzeF98Mth+MtclUliYZTPa94TXEMSM/xPeELkfmi sAqJjVFfGqacFcuzI0QryQPkAAU4ts0JtAoaUhHDNc+3Mz2UnHtaYsLEh9cHdkKq QzpggPPN4emqcEr3fbvTPl0JIYossH/mOI8E4NTyVaZaScimi8efklxF3JEc+/6w AqzGXt8CL2/ce+E4BojHCfilGrxU4WEeo7e9sMXHuhWCQ/fxT/6o3yktI+sLSv61 RQIDAQAB -----END PUBLIC KEY-----
On trouvait d'ailleurs cette clé sur plein d'autres machines
du réseau 93.17.51.128/26
, presque toutes
acceptant SSLv2 d'une façon ou d'une autre.
En revanche, si on regarde un autre domaine signalé sur le site
Web de Drown, blockchain.com
, on voit que le
site Web public n'a pas du tout la même clé (ce n'est même pas le
même algorithme) que la machine vulnérable (alors que le nom dans
le certificat de la machine vulnérable est bien *.blockchain.com
). Leur situation est
donc moins grave (attention toutefois aux attaques actives) :
# Machine vulnérable car acceptant SSLv2 dans certaines conditions % openssl s_client -connect 50.87.196.92:443 | openssl x509 -pubkey -noout -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsXMk8xOJaaqKmz88RicY Mt4e4VlY0uTVaUS7mbgnUGgd15wQ/tLH91RL5S9c1C1FFrcjBpomODJXBdgTXjWi x4OVRl0sEe6OjIX1FLqBl15n+Lx++933lQUWinMSInEVLnBBjcr9If5+ozJvscRS eF/hikjhDYW/rDwF1f7ivTiiok8f12zTa2lhlxOH4KxcFPaFklXDa45DccDjdCIZ uVLpFSngo5iS3nney+LPK4afYYffEWK9aN2Rj9NE8zRm3hGoGDva2vNmKGbewd3w 1huqr3o7fc3WZyW9HZlM7PjZF6YLhgJnAI09XXDHD3t+G4ijcS6F4Rh9B36whuoo CQIDAQAB -----END PUBLIC KEY----- # Serveur Web public % openssl s_client -connect www.blockchain.com:443 | openssl x509 -pubkey -noout -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8DGz/3DLSflRPxO5uHuiww7EbqEP /S3VWfdw4PGs4WcuqWTtIGht1rwiuTjrU3Es1uxm3T+JfT1JOOhYut8IjA== -----END PUBLIC KEY-----
Pour résumer ce point essentiel « Même si votre serveur n'accepte pas SSLv2, vous êtes peut-être quand même vulnérable ».
(Au passage, petite note technique : certains
systèmes d'exploitation, et à juste titre,
compilent OpenSSL sans SSLv2. La commande ci-dessus vous dira
alors « unknown option -ssl2 ». Il faut
utiliser un système non sécurisé, comme Arch
Linux, ou bien prendre un OpenSSL qu'on a compilé
soi-même. C'est à cause de ce problème que l'excellent script
testssl.sh
vient avec son
propre OpenSSL.)
On voit d'ailleurs un effet négatif de la gamification popularisée, dans le monde HTTPS, par SSLlabs. Pendant que tout le monde s'amuse à obtenir la meilleure note possible pour s'en vanter sur les rézosocios (« j'ai un A sur SSLlabs alors que la banque Machin a uniquement un B, je suis trop un geek crypto-expert »), des machines comme ce pauvre serveur restent ignorés.
Autre question posée par Drown, pourquoi est-ce qu'il y a autant de machines qui acceptent encore SSLv2 ? Il a été officiellement abandonné en 2011 par le RFC 6176. Et le RFC est sorti bien tard, tous les experts savaient depuis longtemps que SSLv2 était cassé sans espoir de réparation. Mais les mises à jour ne se font, sur l'Internet, qu'à un rythme glacial (voir nul). Le problème n'est pas technique, il vient du fait que les mises à jour ne rapportent rien, n'ont pas de retour sur investissement, et ne sont donc en général jamais faites. Tout le monde s'indigne lorsqu'une faille comme Drown est publiée mais, en temps normal, personne ne s'en préoccupe. La prévention est toujours le parent pauvre de la sécurité. L'opérationnel et la sécurité concrète n'intéressent personne.
Compte-tenu de cela, est-ce que Drown représente un réel danger aujourd'hui, et faut-il patcher d'urgence ? Bien sûr, il faut patcher, c'est le B. A. BA de la sécurité pour une machine connectée à l'Internet. Mais le danger exact de Drown n'est pas facile à évaluer. On est dans le cas classique en sécurité du verre que l'optimiste voit à moitié plein alors que le pessimiste le voit à moitié vide. L'optimiste va faire remarquer que l'exploitation effective de Drown est très difficile, dans les conditions du monde réel (en laboratoire, ça marche toujours mieux). Le pessimiste rétorquera que les attaques ne vont toujours qu'en s'améliorant. Si Drown est difficile à exploiter aujourd'hui, cela ne durera pas éternellement. À noter que, pour la raison expliquée plus haut, cela ne sert à rien de patcher votre serveur principal : il faut patcher toutes les machines qui ont le certificat du serveur principal.
Je suggère d'ailleurs d'en tirer une leçon : ne jamais partager un certificat (et donc une clé privée) entre des machines qui ont des administrateurs différents : le risque est en effet très élevé que l'une d'elles soit moins sécurisée que les autres, permettant une attaque.
Ah, notez aussi que patcher OpenSSL ne servira que pour le futur : si un attaquant a utilisé Drown contre vous, et a réussi à obtenir des informations tels que vos mots de passe, il serait prudent de les changer...
Merci à Léo pour avoir signalé une grosse approximation dans l'article original.
Date de publication du RFC : Février 2016
Auteur(s) du RFC : Y. YONEYA (JPRS), T. Nemoto (Keio University)
Pour information
Réalisé dans le cadre du groupe de travail IETF precis
Première rédaction de cet article le 1 mars 2016
PRECIS (preparation, enforcement, and comparison of internationalized strings), décrit désormais dans le RFC 8264, est un cadre général pour l'internationalisation d'identificateurs sur l'Internet. Il expose un certain nombre de règles, parmi lesquelles les développeurs de protocoles Internet et d'applications vont pouvoir choisir, au lieu de partir de zéro à chaque fois. Ce nouveau et court RFC donne des indications aux concepteurs de nouveaux profils PRECIS sur les correspondances (mappings) à effectuer (par exemple, mais pas uniquement, entre des caractères majuscules et minuscules). Il n'est pas normatif : l'internationalisation est quelque chose de compliqué et il n'est pas facile d'obtenir un consensus. L'utilisateur indique un identificateur, en quoi peut-on le transformer ?
Au départ de cet identificateur, on trouve une saisie par l'utilisateur (clavier physique ou clavier virtuel), ou bien une sélection par ce même utilisateur (copier/coller depuis du texte, choix d'un signet, choix parmi les résultats d'un moteur de recherche...) À ce stade, l'utilisateur ne tient pas compte de certaines caractéristiques du texte, qu'il considère non pertinentes. C'est ainsi qu'il va ignorer la casse, ou bien la largeur du caractère (pour les caractères qui ont une version étroite et une version large comme le point d'exclamation, qui existe en U+0021, « ! » et U+FF01, « ! ») Il est donc souhaitable d'avoir une phase de correspondance (mapping) entre cette saisie ou cette sélection et le moment où l'identificateur est passé au programme. C'est lors que cette phase qu'on va, par exemple, tout mettre en minuscules, et remplacer les caractères larges par leur version étroite.
Pour le cas des noms de domaine (IDN), cette correspondance est déjà traitée dans le RFC 5895. Pour les autres identificateurs, le cadre PRECIS (PReparation, Enforcement, and Comparison of Internationalized Strings), dans le RFC 8264, s'en charge. Mais il ne traite qu'une partie des correspondances souhaitables (comme la casse) et il était donc souhaitable de l'étendre. C'est ce que fait ce nouveau RFC.
La section 2 de notre court RFC spécifie ces correspondances supplémentaires. Par exemple, les délimiteurs (comme le point). Chaque protocole et format a ses propres délimiteurs (@ pour le courrier électronique, / dans les URL, etc). L'idée est de faire correspondre les caractères qui ressemblent au(x) délimiteur(s) du protocole vers le caractère canonique. Ainsi, si un protocole utilise le point (U+002E) come délimiteur, et que le texte saisi par l'utilisateur contient un point idéographique (U+3002, alias « 。 »), il est logique de remplacer ces points par le point « officiel » du protocole.
Après la correspondance des délimiteurs, les « correspondances spéciales ». Le terme désigne des règles qui sont différentes des règles par défaut de PRECIS. Par exemple, supprimer les caractères de contrôle (pas les transformer en un autre caractère, non, les supprimer franchement) ou bien transformer des espaces différents du caractère espace d'ASCII en espaces ASCII (U+0020). C'est ce que font des protocoles comme EAP (RFC 3748) ou les ACL d'IMAP (RFC 4314).
Autre cas rigolo, celui où le changement de casse dépend de la locale, c'est-à-dire en général de la langue utilisée. L'exemple le plus fameux, toujours mentionné dans les discussions Unicode, vient du turc où la minuscule du I (U+0049) n'est pas i (U+0069) mais ı (U+0131, et encore, la règle exacte est un peu plus compliquée). Comme PRECIS est conçu pour des protocoles Internet, qui ne connaissent pas la langue, les applications (qui, elles, connaissent souvent la langue de leur utilisateur) doivent traiter ce cas, avant de passer l'information sur l'Internet (voir aussi l'annexe B et C, pour des cas spéciaux dans le cas spécial).
L'annexe A de notre RFC résume dans un tableau ces correspondances selon divers protocoles (IDN, iSCSI, EAP, etc).
Date de publication du RFC : Février 2016
Auteur(s) du RFC : T. Bray (Textuality)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpbis
Première rédaction de cet article le 1 mars 2016
Voici donc un nouveau code de retour HTTP qui a fait couler énormément d'encre : 451 est désormais l'erreur HTTP à utiliser lorsqu'un serveur HTTP ne peut pas envoyer la ressource demandée par son client pour des raisons légales, en clair lorsqu'il y a censure.
Rappelons que les codes d'erreur HTTP (RFC 7231, section 6) sont composés de trois chiffres, le premier indiquant la catégorie. 4 (RFC 7231, section 6.5) est une erreur due au client (et il ne sert donc à rien de réessayer plus tard).
Ce nouveau code 451 permet de la censure avouée, suivant les principes du RFC 4924 et de la section 4 du RFC 4084. On peut dire clairement à l'utilisateur que sa demande est légalement impossible à satisfaire. Notez que toutes les dictatures ne seront pas ravies de cette transparence. Du temps de Ben Ali, la censure tunisienne générait des faux 404 (Not found) pour faire croire que la ressource demandée n'existait pas.
La section 3 de notre RFC expose les détails techniques. Notez que le serveur qui répond 451 n'est pas forcément le serveur d'origine de la ressource (s'il l'était, il ne souhaiterait probablement pas mettre en œuvre la censure de son propre contenu). 451 sera donc sans doute plutôt renvoyé par des serveurs intermédiaires, genre proxy ou moteurs de recherche.
Vu l'objectif de transparence, le RFC demande que la réponse 451 soit accompagnée d'une explication, indiquant qui bloque, pourquoi, et selon quelle loi. Le RFC fournit un exemple amusant, inspiré du film La vie de Brian :
HTTP/1.1 451 Unavailable For Legal Reasons Link: <https://spqr.example.org/legislatione>; rel="blocked-by" Content-Type: text/html <html> <head><title>Unavailable For Legal Reasons</title></head> <body> <h1>Unavailable For Legal Reasons</h1> <p>This request may not be serviced in the Roman Province of Judea due to the Lex Julia Majestatis, which disallows access to resources hosted on servers deemed to be operated by the People's Front of Judea.</p> </body> </html>
Le RFC note bien que le code 451 n'indique pas si la ressource existe ou pas (par exemple, un proxy peut bloquer toutes les requêtes allant vers un nom de domaine donné).
Notre RFC fournit également des indications sur comment la censure peut être contournée, par exemple avec un VPN vers un pays plus libre, ou bien avec Tor. C'est d'ailleurs un des intérêts pratiques de ce code 451 : un client HTTP pourra agir automatiquement lorsqu'il rencontrera cette erreur. Ce code n'est donc pas purement décoratif (une objection qui lui avait souvent été faite au début du processus à l'IETF.) En prime, ce code pourra être utile à des systèmes de suivi de la censure, comme Lumen. Peut-être cela aidera-t-il à mesurer la censure (du moins dans les pays les plus légalistes, les autres n'utiliseront pas 451). Pour les mêmes raisons, des organisations de défense des droits de l'homme comme le CDT ou comme article 19 ont exprimé leur soutien pour ce code.
L'en-tête Link:
dans l'exemple plus haut
est là pour identifier formellement l'entité responsable du
blocage (section 4 du RFC), en utilisant les liens du RFC 8288. Cela suppose évidemment que celle-ci
assume ses décisions, ce qui n'est pas toujours le cas (section 5
du RFC, qui rappelle qu'il y aura toujours une censure hypocrite).
Le code 451 est désormais ajouté au registre
IANA des codes de retour HTTP, et la relation
blocked-by
est dans le registre
des relations. (Notez bien que l'exemple ci-dessus, copié du
RFC, est erroné.)
« Thanks also to Ray Bradbury », dit l'annexe A du RFC, puisque ce code d'erreur est évidemment une référence geek au roman du célèbre écrivain.
Un exemple de mise en œuvre parmi tant d'autres : la bibliothèque Pylons. Le magasin d'applications de Firefox a 451 parmi ses réponses possibles si l'application est illégale dans le pays du client. Et 451 a une image parmi les fameux HTTP status cats, montrant Bradbury et son chat.
Ce code d'erreur a suscité beaucoup d'intérêt, il a une page Wikipédia, un site Web en Grande-Bretagne et a fait l'objet de nombreux articles dans les médias.
En France, le serveur « La Main Rouge » du Ministère de l'Intérieur n'utilise pas 451 lorsqu'on tente d'accéder à un site Web interdit. Au lieu de cela, leur serveur renvoie 200, ce qui est illogique. (Un point amusant : si on utilise wget - mais pas curl - le serveur renvoie 403.)
À la réunion IETF de Prague en juillet 2017, le hackathon a été l'occasion de travailler sur des utilisations de ce code 451. Voici la présentation qui a été faite et l'Internet-Draft draft-451-imp-report. Le code a été mis sur Github.
Date de publication du RFC : Février 2016
Auteur(s) du RFC : A. Yourtchenko (Cisco), L. Colitti
(Google)
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 19 février 2016
Lorsque des machines parlent IPv6, elles reçoivent fréquemment des messages RA (Router Advertisment), que les routeurs émettent souvent avec trop d'enthousiasme. Le traitement de ces messages RA nécessite des ressources et, sur des petites machines alimentées par une pile et souhaitant économiser les ampèreheures, ces RA fréquents, qui les obligent à se réveiller et à travailler, sont une plaie. Ce court RFC suggère quelques moyens d'économiser l'énergie.
À l'époque où IPv6 avait été conçu, on ne pensait pas vraiment à l'Internet des Objets, à ces millions de petits machins connectés. Des messages RA (RFC 4861, section 3) fréquents ne sont pas un problème pour des serveurs alimentés électriquement en permanence. Mais le monde a changé, et il faut maintenant économiser la batterie (section 1 du RFC).
Regardons quelques cas typiques (section 2 du RFC). Un RA (Router Advertisement) peut être sollicité ou pas (RFC 4861). Un RA sollicité est typiquement dû à l'arrivée d'une machine dans le réseau. Elle émet alors un RS (Router Solicitation) et le ou les routeurs, en le recevant, répondent par un RA. Dans certains cas (par exemple si la machine émettrice n'a pas encore d'adresse IPv6 propre), ce RA est envoyé à une adresse multicast, ce qui fait que toutes les machines le recevront et devront le traiter. Si beaucoup de machines quittent et rejoignent le réseau fréquemment (ce qui arrive dans les réseaux sans-fil, lorsque la liaison est mauvaise), ces RA sollicités peuvent représenter un trafic non négligeable (un maximum d'un RA toutes les trois seconde et par routeur est toutefois imposé par les sections 6.2.6 et 10 du RFC 4861).
Même en l'absence de sollicitations, les routeurs IPv6 émettent des RA périodiques, parfois un toutes les cinq ou dix secondes, de manière à éviter que des machines ratent l'information importante.
Conséquences (section 3 du RFC) ? La batterie se vide plus vite, ce qui est très frustrant puisque la plupart de ces RA étaient « inutiles » pour la machine qui les recevait. Certaines machines traitent le problème en ignorant les RA lorsqu'elles sont dans un mode de basse consommation (par exemple Android, avec des conséquences négatives). C'est compréhensible mais cela fait qu'elles risquent, en se réveillant, d'avoir perdu leur connectivité car le réseau a changé ou, tout simplement, parce qu'elles ont « oublié » la route par défaut. Encore plus violent, certaines machines ignorent tous les paquets lorsqu'elles veulent économiser leur batterie. Ces comportements poussent certains administrateurs réseau à augmenter la fréquence des RA, aggravant ainsi encore le problème.
Une autre conséquence (merci à Gabriel Kerneis pour l'exemple), les NAS du constructeur Synology refusent de passer en hibernation profonde s’ils reçoivent des RA (ou des paquets DHCP d’ailleurs). Le seul moyen de faire fonctionner IPv6 sur ces machines tout en préservant l’hibernation est de configurer l’adresse manuellement.
Quelle serait la bonne fréquence d'envoi de RA (section 4) ? Un ordinateur de type portable ne verra pas grand'chose, même pour des RA envoyés toutes les cinq secondes. Sa batterie en a vu d'autres. Les engins plus petits (tablettes, téléphones, montres connectées et autres objets) ont davantage de contraintes. Aujourd'hui, un engin typique va consommer 5 mA quand il dort. Le traitement d'un RA qu'il n'a pas demandé va lui coûter 200 mA pendant un quart de seconde, ce qui fera en tout presque 14 µAh.
Pour limiter la consommation électrique due aux RA à moins de 2 % de la consommation du mode « économique », il faut rester en dessous de 100 µA, ce qui fait moins de 7 RA par heure. Comme des RA se perdent, le routeur ne peut pas être sûr que toutes les machines ont reçu cette information. Le RFC fait un choix conservateur : avec une moyenne de 8-9 minutes entre deux RA (afin de rester en dessous de 7 par heure), le routeur doit compter que l'information devra durer au moins 5 fois ce temps (ce qui fera 40-45 minutes). Pas question donc de changer de configuration IPv6 trop souvent.
Il est possible que certains environnements (réseaux de capteurs industriels) soient encore plus limités en énergie et doivent donc recevoir encore moins de RA.
Pour synthétiser, les recommandations de notre RFC pour les routeurs sont :
Notez que cela ne change pas le protocole IPv6 : ces recommandations sont déjà des comportements légaux.
Et les recommandations pour les machines terminales sont :
Enfin, la section 8 du RFC, portant sur la sécurité, rappelle qu'un routeur méchant peut ignorer ces conseils et envoyer beaucoup de RA exprès pour vider les batteries. Il faut donc prendre des mesures contre de tels routeurs (par exemple celle du RFC 6105).
Merci beaucoup à Benjamin Cama pour ses corrections, son analyse détaillée et ses excellentes références (reprises ici).
Première rédaction de cet article le 10 février 2016
En janvier et février 2016, j'ai eu le plaisir de faire une série de quatre cours au CELSA (master Médias Informatisés et Stratégies de Communication) sur le thème « Internet derrière l'écran ». Que se passe-t-il derrière les jolies images de chatons ?
Ce cours était décliné en quatre parties et voici les supports de cours correspondants :
Merci à Étienne Candel pour avoir insisté :-) à Alexis Tamas, mon prédécesseur, et à Céline Leclaire pour l'organisation et donc pour avoir supporté mes retards et cafouillages.
Date de publication du RFC : Février 2016
Auteur(s) du RFC : F. Gont (SI6 Networks / UTN-FRH)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 7 février 2016
Le protocole IPv6 a un mécanisme de fragmentation des paquets. L'en-tête d'un fragment contient un champ « Identification » (RFC 2460, section 4.5) qui, avec les deux adresses Source et Destination, identifie de manière unique un paquet fragmenté (tous les fragments de ce paquet ont le même identificateur), et permet donc le réassemblage à la destination. La façon la plus simple d'affecter ces identificateurs est d'avoir, dans chaque machine, un compteur global incrémenté à chaque paquet qu'on fragmente (section 1 du RFC). Une telle façon de faire mène à des identificateurs prévisibles : un observateur qui se connecte à cette machine peut prévoir quel sera l'identificateur du paquet suivant. Cela a de sérieuses conséquences en terme de sécurité. Ce RFC explore ces conséquences, et propose des solutions.
Petit rappel au passage sur la fragmentation IPv6 : contrairement à la fragmentation IPv4, elle ne peut se faire que dans la machine émettrice, pas dans les routeurs intermédiaires. Voici un exemple de paquet fragmenté, vu par tcpdump, la réponse DNS, trop grosse, a été fragmentée en deux :
10:45:24.818912 IP6 (hlim 56, next-header Fragment (44) payload length: 432) 2001:4b98:dc2:45:216:3eff:fe4b:8c5b > 2001:67c:1348:7::86:133: frag (0x000079cc:0|424) 53 > 37407: 25110*- q: ANY? . 24/0/1 . [1d] DNSKEY, . [1d] DNSKEY, . [1d] DNSKEY[|domain] 10:45:24.819008 IP6 (hlim 56, next-header Fragment (44) payload length: 1458) 2001:4b98:dc2:45:216:3eff:fe4b:8c5b > 2001:67c:1348:7::86:133: frag (0x000079cc:424|1450)
Le paquet a l'identificateur 0x000079cc, seul le premier fragment (de l'octet 0 à l'octet 423) a pu être analysé (il avait le début de la réponse DNS). Et voici les deux fragments, analysés par tshark :
Type: IPv6 (0x86dd) Internet Protocol Version 6, Src: 2001:4b98:dc2:45:216:3eff:fe4b:8c5b, Dst: 2001:67c:1348:7::86:133 Next header: Fragment Header for IPv6 (44) Fragment Header Next header: UDP (17) Reserved octet: 0x0000 0000 0000 0000 0... = Offset: 0 (0 bytes) .... .... .... .00. = Reserved bits: 0 .... .... .... ...1 = More Fragments: Yes Identification: 0x000079cc Type: IPv6 (0x86dd) Internet Protocol Version 6, Src: 2001:4b98:dc2:45:216:3eff:fe4b:8c5b, Dst: 2001:67c:1348:7::86:133 Next header: Fragment Header for IPv6 (44) Fragment Header Next header: UDP (17) Reserved octet: 0x0000 0000 0001 1010 1... = Offset: 53 (424 bytes) .... .... .... .00. = Reserved bits: 0 .... .... .... ...0 = More Fragments: No Identification: 0x000079cc [2 IPv6 Fragments (1874 bytes): #2(424), #3(1450)] [Frame: 2, payload: 0-423 (424 bytes)] [Frame: 3, payload: 424-1873 (1450 bytes)] [Fragment count: 2] [Reassembled IPv6 length: 1874] [Reassembled IPv6 data: 0035921f0752901c6216850000010018000000010000ff00...]
Le RFC 2460, section 4.5, indique une seule obligation à la machine fragmenteuse : l'identificateur de paquet doit être unique parmi tous les paquets émis récemment par cette machine, pour éviter toute collision. Ce RFC 2460 donne même le conseil malheureux d'utiliser un compteur global, incrémenté à chaque paquet, pour cela.
Pourquoi, « malheureux » ? Parce que cela rend l'identificateur de paquet prévisible pour un observateur extérieur, faisant ainsi fuir de l'information qui peut être utilisée pour certaines attaques (section 3) :
Ces attaques n'ont rien de spécifique à IPv6 : des identificateurs de paquet prévisibles ont les mêmes conséquences en IPv4 (voir les articles pionniers de Sanfilippo ici ou là, puis de nombreux autres papiers cités dans la bibliographie de notre RFC, en section 9). Le RFC 6274 décrit en détail ces attaques pour IPv4.
En IPv4, le champ Identification fait partie de chaque paquet (RFC 791, section 3.1) puisque tout routeur pourra fragmenter ce paquet. En IPv6, ce champ n'est présent que dans les paquets fragmentés, dans un « en-tête d'extension » optionnel. Cela rend les attaques un peu plus compliquées en IPv6 : l'attaquant doit d'abord forcer une fragmentation. Une des possibilités pour cela est d'envoyer un paquet ICMP Packet Too Big. Si, en plus, le paquet ICMP contient une MTU inférieure à 1 280 octets, les paquets ne seront pas fragmentés mais porteront quand même l'en-tête d'extension Fragment Header (c'est ce qu'on appellait des « fragments atomiques », cf. RFC 6946, fragments atomiques dont l'usage est désormais abandonné, voir le RFC 8021).
En théorie, rien de plus simple que d'envoyer un faux paquet ICMP Packet Too Big. En pratique, il y a quelques limitations pour l'attaquant :
Pour éviter ces attaques, que faudrait-il faire ? On souhaite des identificateurs de paquets imprévisibles, mais en même temps ils ne doivent pas être réutilisés, du moins tant qu'on n'est pas sûr que les paquets portant précédemment cet identificateur n'ont pas terminé leur voyage dans le réseau. Des identificateurs complètement aléatoires, par exemple, ne sont pas si idéaux qu'ils le paraissent : il y a un risque de réutilisation accidentelle. Autre contrainte sur les algorithmes de génération de ces identificateurs : ils doivent être très rapides, puisqu'il faut les faire tourner pour chaque paquet fragmenté.
La section 5 de notre RFC décrit les algorithmes possibles. On a vu que l'algorithme « compteur global » était exclu, car il produit des identificateurs prévisibles. Que reste-t-il ?
Le premier algorithme possible (section 5.1) est « un compteur par destination ». On maintient un compteur par adresse IP de destination utilisée, qu'on initialise avec une valeur aléatoire. Simple à mettre en œuvre (il faut juste un générateur de nombres aléatoires), sans réutilisation (pour qu'il y ait collision, il faudrait qu'on émette tellement de paquets vers une destination donnée que le compteur, de 32 bits, déborde), et très rapide (une fois la valeur initiale choisie). Par contre, le prochain identificateur de fragment reste prévisible, mais uniquement pour la machine de destination. Cela peut être utilisé dans certaines attaques. Et il consomme pas mal de mémoire (une entrée par destination), mémoire qu'on ne peut pas libérer, sauf à risquer des collisions d'identificateurs.
Deuxième algorithme envisageable, « identificateur aléatoire » (section 5.2). Idéal pour la sécurité, mais il fait courir des risques de réutilisation des identificateurs, et il est plus coûteux en temps de calcul.
Enfin, un troisième algorithme possible est « condensation de variables » (section 5.3). On prend des variables comme les adresses source et destination, un compteur (pas forcément global), une valeur secrète et on condense le tout. Non, je simplifie trop. En fait, pour être le plus rapide possible tout en étant imprévisible, on a un tableau de compteurs (pas un par destination, mais pas non plus un seul), la condensation des adresses et d'un secret donne l'index dans ce tableau, et on concatène ce compteur avec un autre condensat, fait avec un autre secret. Le résultat est imprévisible de l'extérieur (mais prévisible par le destinataire) et la réutilisation est plus lente qu'avec un compteur global, et cet algorithme peut être mis en œuvre de façon à être très rapide.
L'annexe B de notre RFC est le résultat d'une étude de la
prédictabilité par système d'exploitation,
en utilisant l'outil frag6
, qui vient du
toolkit
SI6. On peut refaire la même étude chez soi :
% sudo frag6 --frag-id-policy -d www.example Identifying the 'Fragment ID' generation policy of the target node.... Fragment ID policy: Per-destination IDs with increments of 2 (sdev: 1.112134)
La destination est un FreeBSD, qui utilise des identificateurs aléatoires depuis sa version 9 :
% sudo frag6 --frag-id-policy -d www.freebsd.org Identifying the 'Fragment ID' generation policy of the target node.... Fragment ID policy: Randomized IDs (Avg. inc.: 2101165500, sdev: 1531579889.681898)
Ici, un Linux récent, avec des compteurs par destination :
% sudo frag6 --frag-id-policy -d 2001:db8:9321:8bb0:9da8:f055:5381:d54c Identifying the 'Fragment ID' generation policy of the target node.... Fragment ID policy: Per-destination IDs with increments of 1 (sdev: 1.504380)
On voit, après cet essai sur trois machines différentes, que les différents algorithmes sont toujours utilisés.
Date de publication du RFC : Février 2016
Auteur(s) du RFC : J. Reschke (greenbytes)
Pour information
Première rédaction de cet article le 7 février 2016
Contrairement à beaucoup de SDO, l'IETF n'a pas de format standard pour l'écriture de ses documents. XML est toutefois le plus répandu, avec le vocabulaire qui avait été autrefois décrit dans le RFC 2629, et qui est maintenant spécifié dans ce RFC. (Il a depuis été remplacé par le RFC 7991.)
Vous voulez écrire un RFC ? Un des choix possibles est un format XML, fondé sur un vocabulaire spécifique aux RFC, et mis en œuvre dans l'outil xml2rfc. Ce vocabulaire n'avait pas été mis à jour depuis seize ans (alors que l'outil évoluait) et c'est seulement maintenant, après un processus long et douloureux, que les auteurs d'Internet-Drafts et de RFC disposent enfin d'une description officielle et à jour du format dans lequel ils travaillent. Voici donc le vocabulaire « XML2RFC version 2 ».
Le format principal de publication des RFC est du texte brut, pour des raisons de portabilité, d'indépendance vis-à-vis de tout éditeur de logiciels spécifique, et de facilité de traitement automatique. Mais aucun auteur n'écrit les RFC directement dans ce format (rien que pour la numérotation des pages, cela serait infernal). Ils écrivent en des formats divers, et le convertissent ensuite en texte brut. À noter que certains éléments XML décrits ici ne produisent rien de particulier dans le texte final, mais sont utiles pour d'autres usages, comme l'indexation.
Voici le squelette d'un Internet-Draft écrit avec ce XML :
<?xml version="1.0" encoding="utf-8"?> <rfc docName="draft-ietf-dnsop-qname-minimisation-09" category="exp" ipr="trust200902"> <front> <title abbrev="Qname minimisation">DNS query name minimisation to improve privacy</title> ... <middle> <section anchor="intro" title="Introduction and background"> <t>The problem statement is described in <xref target="RFC7626"/>. [...] ... </back> </rfc>
(Un squelette plus détaillé est disponible en https://www.rfc-editor.org/materials/template-bare-06.txt
.)
Sur ce squelette simple, on voit l'élément racine
(<rfc>
), l'utilisation des attributs
(comme category
qui indique le statut du
futur RFC, ici « expérimental »), la séparation en trois parties,
<front>
, qui regroupe les
métadonnées,
<middle>
, qui est le texte principal,
et <back>
, où se trouvent la
bibliographie, les annexes, etc.
Parmi les attributs de cet élément racine
<rfc>
, notez ipr
,
qui indique les conditions légales d'utilisation de ce RFC. Dans
cet example, la valeur est la plus couramment utilisée :
trust200902
(cf. l'annexe A.2) indique les règles de
l'IETF Trust datant de 2009 (qui disent en
gros que le texte du RFC peut être librement copié, reproduit,
distribué et mis en œuvre dans des programmes). L'annexe A de
notre RFC détaille ce qu'on appelle le
boilerplate, ces textes juridiques obligatoires
qui sont ajoutés automatiquement par le logiciel xml2rfc. Ainsi,
si on met ipr="trust200902"
dans l'élément
<rfc>
, xml2rfc va automatiquement
ajouter « Copyright (c) 2015 IETF Trust and the persons identified as the
document authors. All rights reserved. \ This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents [...] »...
Le gros morceau du RFC est la section 2, qui donne la liste des éléments XML acceptés. Je ne vais pas reproduire ici cette liste, juste parler de quelques éléments qui me semblent rigolos.
<section>
contient une partie du
RFC. Cet élément est hiérarchique : on crée des sous-sections en
les mettant sous les sections existantes, et ainsi de suite,
récursivement. (Contrairement à ce qui se passe avec
HTML, où on indique explicitement le niveau
de la section, <h1>
,
<h2>
, etc.)
<t>
contient un paragraphe et est
donc l'équivalent du <p>
de HTML.
<artwork>
est le seul élément
qui permet de spécifier du texte qui sera représenté comme tel,
sans aucune justification, mise à la ligne, etc. Il a gagné plusieurs
attributs par rapport au RFC 2629, pour bien contrôler le résultat. <artwork>
permet
d'include du code source ou bien
de mettre de l'art ASCII dans un RFC (pour
l'instant, il n'y a pas encore d'autre mécanisme simple pour des
images, mais c'est quand même possible, cf. le RFC 5598 avec ses différentes versions). Notez que l'attribut
src
permet de spécifier un fichier externe,
l'art ASCII ne servant alors que de solution de secours, pour le
format en texte seul. Voici un exemple :
<figure title="A network"> <artwork> +--------------+ +----------------+ | Alice |------------------------------------| Bob | | 2001:db8::1 | | 2001:db8::2 | +--------------+ +----------------+ </artwork> </figure>
<eref>
permet de faire un lien
hypertexte vers l'extérieur :
<t>More text and a <eref target="http://www.rfc-editor.org/">lien vers le site du RFC Editor</eref>.</t>
<list>
permet de représenter les
traditionnelles listes à puces :
<t>There are three sorts of DNS requests being issued: <list> <t>Primary request: [...]</t> <t>Secondary requests: [...]</t> <t>Tertiary requests: [...]</t> </list> </t>
<references>
permet d'indiquer une
bibliographie. Il y en a typiquement deux
dans un RFC (cf. la section 4.8.6 du RFC 7322), la bibliographie normative (ce qu'il faut absolument
avoir lu et compris car le RFC en dépend) et l'informative (ce
qu'on peut sauter si on est pressé). Pour aider, le RFC
Editor distribue des fichiers XML contenant les
références aux RFC publiés, comme http://www.rfc-editor.org/refs/bibxml/reference.RFC.7626.xml
.
Si vous voulez un exemple plus complet, regardez ce fichier. Vous pouvez le traiter avec xml2rfc :
% xml2rfc test-xml2rfc-v2.xml [...] Created file test-xml2rfc-v2.txt
Et vous obtenez un joli RFC.
Ce format de RFC s'appuie sur XML et il faut donc suivre les règles de XML, notamment sur les caractères spéciaux. Ainsi, le chevron ouvrant doit être remplacé par une séquence d'échappement (< au lieu de <). Si cette contrainte est trop forte, on peut aussi enclore les parties à « échapper » dans une section CDATA.
Le format des RFC ne permet pas d'autres caractères que ceux du jeu ASCII. Néanmoins, certains caractères Unicode peuvent être utiles dans le source XML (section 4), pour contrôler certains aspects de la présentation :
La restriction actuelle à ASCII (elle était dans le RFC 2223, section 3a, mais n'a pas été formellement reprise dans son successeur, le RFC 7322) sera peut-être levée dans le futur, et ce RFC devra alors être mis à jour (section 6).
Le format actuel ne permet pas l'inclusion d'autres documents, donc un RFC doit être en une seule pièce, un seul fichier XML (section 5). On peut toutefois utiliser les mécanismes génériques d'inclusion de XML, et c'est souvent utilisé pour la bibliographie :
<!DOCTYPE rfc [ <!ENTITY rfc7830 PUBLIC "http://xml.resource.org/public/rfc/bibxml/reference.RFC.7830.xml"> ]> [...] <references> &rfc7830; </references>
À noter qu'il existe désormais un type
MIME pour les sources XML de RFC,
application/rfc+xml
(section 8 de notre RFC).
Si vous voulez voir le schéma XML complet, il est en annexe
C (j'en ai exporté une version utilisable telle quelle, sans les
sauts de page des RFC, en rfc-schema.rnc
). Comme il est écrit en Relax NG, il
permet l'utilisation de tous les outils Relax NG, comme le mode
emacs nxml-mode et comme
rnv. Ainsi, une fois le fichier
rfc-schema.rnc
chargé dans emacs (menus XML puis
Set schema puis File), on
dispose de fonctions d'édition bien pratiques (par exemple, on
tape un < puis une tabulation et emacs propose de compléter
uniquement avec les éléments autorisés à cet endroit). Cela évite
bien des erreurs.
À noter que ce RFC ne décrit que les éléments et attributs XML,
pas les processing
instructions (PI) <?rfc
... ?>
qui servent, par exemple, à contrôler si une
table des matières est affichée. Pour connaitre celles
acceptées par xml2rfc, il faut regarder la
documentation de l'outil et la FAQ.
Avec un logiciel comme rnv, on peut tester la syntaxe (uniquement la syntaxe : certaines contraintes dans le RFC ne sont pas exprimables dans le schéma, il a fallu les formuler en langue naturelle dans le texte du RFC) :
% rnv rfc.rnc test-xml2rfc-v2.xml test-xml2rfc-v2.xml
Parfait, ici, tout est bon. S'il y avait eu une erreur :
% rnv rfc.rnc test-xml2rfc-v2.xml test-xml2rfc-v2.xml test-xml2rfc-v2.xml:9:4: error: element ^t not allowed required: element ^section
Si le RFC contient des références externes (que rnv ne sait pas traiter), on peut utiliser xmllint pour les remplacer :
% xmllint --dropdtd --noent draft-ietf-dnsop-nxdomain-cut.xml | rnv rfc.rnc
À noter que le RFC n'utilise pas rnv mais Jing (annexe C.1). Mode d'emploi très court, on télécharge :
% https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/jing-trang/jing-20091111.zip % unzip jing-20091111.zip % java -jar ./jing-20091111/bin/jing.jar -c rfc.rnc draft-ietf-dnsop-nxdomain-cut.xml %
Les changements depuis le texte précédent, le RFC 2629, seize ans auparavant, sont résumés dans l'annexe
B. L'élément <appendix>
, qui servait
pour les annexes des RFC (annexes assez fréquentes, de nos jours),
a été supprimé. Pour faire une annexe, désormais, on met une
<section>
dans le
<back>
. En revanche, sept nouveaux
éléments ont été ajoutés dont les plus importants, à mon avis,
sont <texttable>
,
<ttcol>
et <c>
, qui permettent enfin de faire
des tableaux proprement dans les RFC.
Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : G. Almes (Texas A&M), S. Kalidindi (Ixia), M. Zekauskas (Internet2), A. Morton (AT&T Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 1 février 2016
Ce RFC définit une métrique, une grandeur à mesurer, en l'occurrence le délai d'acheminement d'un paquet d'un point à un autre du réseau. Cela semble trivial, mais la définition rigoureuse de la métrique, permettant des mesures scientifiques et leur comparaison, prend vingt pages... Elle remplace l'ancienne définition, qui était normalisée dans le RFC 2679.
Comme tous les RFC du groupe de travail ippm, celui-ci s'appuie sur les définitions et le vocabulaire du RFC 2330, notamment la notion de Type-P (paquets IP ayant la même « signature », c'est-à-dire même protocole de couche 4, même numéro de port, etc, car certains équipements réseaux traitent différemment les paquets selon ces variables).
Commençons par le commencement, c'est-à-dire l'introduction, en section 1. Le RFC définit une métrique pour une mesure unique (un singleton) nommé Type-P-One-way-Delay, ainsi qu'un échantillonnage, pour le cas où la mesure est répétée, et enfin diverses statistiques agrégeant les résultats de plusieurs mesures. Pourquoi une telle métrique ? Comme le rappelle la section 1.1, celle-ci est utile dans des cas comme, par exemple :
Mais pourquoi un délai d'acheminement « aller-simple » et pas « aller-retour », comme le fait ping, ou bien comme le normalise le RFC 2681 ? Après tout, le délai aller-retour est bien plus simple à mesurer. Mais il a aussi des défauts :
Le RFC ne le mentionne apparemment pas, mais on peut aussi dire que la mesure d'un délai aller-retour dépend aussi du temps de réflexion par la machine distante (avec ping, si la machine visée est très chargée, la génération du paquet ICMP de réponse peut prendre un temps non négligeable ; c'est encore pire avec des protocoles applicatifs, où la réflexion n'est pas faite dans le noyau, et est donc sensible à par exemple, le swapping).
Comme avec tout système de mesure, les horloges et leurs imperfections jouent un rôle crucial. La section 2 rappelle des concepts (voir le RFC 2330) comme la synchronisation (le fait que deux horloges indiquent la même valeur) ou le décalage (le fait qu'une horloge aille plus ou moins vite qu'une autre).
Enfin, après tous ces préliminaires, le RFC en arrive à la définition de la métrique, en section 3. Type-P-One-way-Delay est définie comme une fonction de divers paramètres comme les adresses IP des deux parties et l'instant de la mesure. La mesure dépend aussi du Type-P (par exemple parce que certains ports sont favorisés par la QoS ; notez que si la QoS dépend d'une DPI, la définition du Type-P ne suffira pas). Elle est en secondes. Et sa définition (section 3.4) est « Le temps entre l'envoi du premier bit du paquet sur le câble et la réception du dernier bit du paquet depuis le câble ». Si le paquet n'arrive pas, le délai est dit « indéfini » et, en pratique, pris comme étant infini. Les programmeurs noteront donc qu'il n'est pas possible de mesurer cette valeur avec l'API Posix, qui ne donne pas accès à des détails aussi précis.
Ce n'est pas tout de définir une métrique, il faut aussi la mesurer. Dans le monde réel, cela soulève quelques problèmes, couverts par la section 3.5. Le principal étant évidemment la synchronisation des horloges. Si le paquet part à 1247389451,578306110 (en secondes depuis le 1er janvier 1970) et arrive à 1247389453,018393817, le délai a-t-il réellement été de 1,44 secondes ou bien seulement de 1,32 secondes mais les horloges différaient de 0,12 secondes ? Comme des délais peuvent être aussi bas que 100 µs, une synchronisation précise est nécessaire. Le GPS est une bonne solution pour cela, NTP une moins bonne, car sa résolution est plus faible (de l'ordre de plusieurs ms) et il dépend du réseau qu'on veut mesurer.
Il faut aussi tenir compte de problèmes comme les paquets perdus (si le délai de garde est de cinq secondes, un paquet perdu ne doit pas compter pour un délai d'acheminement de cinq secondes, ou bien des agrégats comme la moyenne seront complètement faussés) ou comme la duplication de paquets (dans ce cas, le RFC précise que c'est la première occurrence qui compte). Le délai de garde (délai d'attente maximal avant de considérer un paquet comme perdu) ne doit pas être trop bas, sinon on risque de sur-estimer les performances du réseau, en éliminant les paquets lentement acheminés.
Enfin, pour celui qui voudrait concevoir un protocole de mesure de cette métrique, le RFC suggère une méthodologie, en section 3.6 :
Cette question de l'analyse d'erreur fait l'objet de la section
3.7. Les deux principales sources d'erreur seront liées aux horloges
(qui ne sont jamais parfaites) et à la différence entre le temps de
départ ou d'arrivée mesuré et le temps réel. Sur un système d'exploitation multi-tâches et non
temps réel comme Unix,
le temps entre le moment où le paquet arrive dans la carte
Ethernet et celui où l'application peut appeler
gettimeofday()
est souvent
significatif (section 3.7.2) et, pire, variable et imprévisible (car
on dépend de l'ordonnanceur). Parmi les
mécanismes pour déterminer l'erreur, de façon à pouvoir effectuer les
corrections, le RFC suggère la calibration
(section 3.7.3), en répétant de nombreuses fois la mesure. Cette partie sur l'analyse des erreurs est détaillée
et explique en partie la longueur du RFC : la métrologie n'est pas une
science simple !
À noter que les deux horloges, à l'arrivée et au départ, ont besoin d'être synchronisées mais n'ont pas forcément besoin d'être correctes. La correction reste quand même utile, car les délais peuvent dépendre de l'heure de la journée et il faut donc indiquer celle-ci dans le rapport final.
Une fois qu'on a bien travaillé et soigneusement fait ses mesures, il est temps de les communiquer à l'utilisateur. C'est l'objet de la section 3.8. Elle insiste sur l'importance d'indiquer le Type-P, les paramètres, la méthode de calibration, etc. Si possible, le chemin suivi par les paquets dans le réseau devrait également être indiqué.
Maintenant, la métrique pour une mesure isolée, un singleton, est définie. On peut donc bâtir sur elle. C'est ce que fait la section 4, qui définit une mesure répétée, effectuée selon une distribution de Poisson, Type-P-One-way-Delay-Poisson-Stream.
Une fois cette métrique définie, on peut créer des fonctions d'agrégation des données, comme en section 5. Par exemple, la section 5.1 définit Type-P-One-way-Delay-Percentile qui définit le délai d'acheminement sous lequel se trouvent X % des mesures (les mesures indéfinies étant comptées comme de délai infini). Ainsi, le 95e percentile indique le délai pour lequel 95 % des délais seront plus courts (donc une sorte de « délai maximum en écartant les cas pathologiques »). La section 5.2 définit Type-P-One-way-Delay-Median qui est la médiane (équivalente au 50e percentile, si le nombre de mesures est impair). La moyenne, moins utile, n'apparait pas dans ce RFC.
Au moins un protocole a été défini sur la base de cette métrique, OWAMP, normalisé dans le RFC 4656 et mis en œuvre notamment dans le programme de même nom.
Le but principal du nouveau RFC (projet documenté dans le RFC 6576) était de faire avancer cette métrique sur le « chemin des normes » (cf. RFC 2026), de « proposition de norme » à « norme [tout court] ». Les tests du RFC 6808 (voir aussi le rapport sur le RFC 2679) ont montré que les métriques Internet étaient sérieuses et utilisables, justifiant cet avancement sur le chemin des normes.
La section 7 décrit les (rares) changements depuis le
RFC 2679. Le RFC 6808
notait plusieurs problèmes avec le RFC 2679,
problèmes qui ont été traités par ce nouveau RFC 7679. Par
exemple, la métrique
Type-P-One-way-Delay-Inverse-Percentile
, définie
dans le RFC 2679 mais jamais mise en œuvre, est
abandonnée. D'autre part, une bogue a
été corrigée. Les autres changements sont l'introduction
des références au RFC sur la publication de mesures, RFC 6703 et à d'autres RFC publiés depuis, ainsi que l'accent plus important sur la
protection de la vie privée. Notre nouveau RFC
note aussi que le groupe de travail a étudié les conséquences du RFC 6921 (dont vous noterez la date de parution) et conclut que,
même avec des délais de propagation négatifs, les métriques décrites
ici ne nécessitaient pas de mise à jour.
Date de publication du RFC : Janvier 2015
Auteur(s) du RFC : G. Almes (Texas
A&M), S. Kalidindi
(Ixia), M. Zekauskas
(Internet2), A. Morton (AT&T
Labs)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF ippm
Première rédaction de cet article le 1 février 2016
Une des tristes réalités de l'Internet d'aujourd'hui est que les paquets se perdent. Ils quittent la machine émettrice et ne sont jamais reçus par la machine réceptrice. Il y a de nombreuses causes à cela (abandon du paquet par un routeur surchargé, par exemple), mais ce RFC 7680, comme les autres documents du groupe de travail IPPM se focalise sur la mesure du phénomène, pas sur ses causes. Il définit donc une métrique « perte de paquet » permettant de comparer des mesures entre elles en sachant qu'on parle bien de la même chose. (Ce RFC remplace la première définition, qui était dans le RFC 2680.)
Comme les autres RFC décrivant des
métriques, des grandeurs rigoureusement définies et qu'on va mesurer,
il s'appuie sur les définitions et le vocabulaire des RFC 2330 et RFC 7312. Par ailleurs, il suit de très près le plan du RFC 2679, qui spécifiait la mesure du délai
d'acheminement d'un paquet. Cette fois, ce qui est défini est une
mesure binaire (un paquet est perdu ou bien ne l'est pas),
Type-P-One-way-Loss
, puis une statistique
pour le cas où il y a plusieurs paquets, le taux de
perte moyen. (Petit rappel : Type-P
signifie que
le rapport de mesure doit indiquer le type du
paquet - protocole de transport, port, etc - car le
résultat peut en dépendre. Cf. section 2.8.1.)
Pourquoi cette métrique est-elle utile ? La section 1.1 rappelle l'intérêt de connaître les pertes :
Mais pourquoi mesurer les pertes sur un chemin aller-simple (one-way) plutôt que aller-retour (two-way) ? La célébrissime commande ping affiche en effet des pertes après un aller-retour (ici 57 %) :
% ping -c 19 198.51.100.80 PING 198.51.100.80 (198.51.100.80) 1450(1478) bytes of data. 1458 bytes from 198.51.100.80: icmp_seq=1 ttl=46 time=168 ms 1458 bytes from 198.51.100.80: icmp_seq=5 ttl=46 time=167 ms 1458 bytes from 198.51.100.80: icmp_seq=6 ttl=46 time=167 ms 1458 bytes from 198.51.100.80: icmp_seq=9 ttl=46 time=169 ms 1458 bytes from 198.51.100.80: icmp_seq=10 ttl=46 time=167 ms 1458 bytes from 198.51.100.80: icmp_seq=13 ttl=46 time=168 ms 1458 bytes from 198.51.100.80: icmp_seq=15 ttl=46 time=168 ms 1458 bytes from 198.51.100.80: icmp_seq=18 ttl=46 time=167 ms --- 198.51.100.80 ping statistics --- 19 packets transmitted, 8 received, 57% packet loss, time 18013ms rtt min/avg/max/mdev = 167.407/168.034/169.066/0.639 ms
Mais les mesures aller-retour ont bien des limites :
Mais les mesures aller-simple sont plus difficiles à effectuer entre autres parce qu'elles ont souvent besoin d'horloges synchronisées (section 1.2). Le principe de la mesure de notre métrique est en effet d'émettre un paquet depuis la machine source à un temps T et de l'attendre à la machine destination jusqu'au temps T + t (où t est le délai qu'on accepte d'attendre). Si les horloges des deux machines ne sont pas synchronisées, leurs mesures de T vont différer, faussant ainsi les résultats. La section 1.2 rappelle donc le vocabulaire à utiliser pour évaluer la synchronisation. Les gourous de l'horlogerie verront qu'il est différent de celui des documents UIT comme le G.810, « Definitions and terminology for synchronization networks ».
Une fois ces préliminaires achevés, la section 2 décrit la métrique
principale de notre RFC,
Type-P-One-way-Packet-Loss
. Sa valeur est
simplement 0 lorsque le paquet est arrivé et 1 autrement.
Il y a bien sûr davantage de choses à dire sur cette métrique. Par exemple (section 2.5), faut-il distinguer le cas où un paquet a vraiment été perdu et le cas où il est simplement arrivé en retard, après l'expiration du délai ? En théorie, on devrait attendre 255 secondes, la durée de vie maximale d'un paquet IPv4 (RFC 791, section 3.2, notez qu'IPv6 n'a aucune limite, cf. RFC 2460, section 8.2). En pratique, on attendra moins longtemps : après tout, pour beaucoup d'applications, un paquet en retard n'a aucun intérêt, on peut aussi bien le considérer comme perdu. C'est l'approche retenue ici. (Par exemple, l'outil de test DNS dig attend, par défaut, cinq secondes avant de considérer la réponse comme perdue.)
Et si le paquet arrive corrompu, le considère-t-on comme perdu ? Là encore, oui, pas de distinction. En effet, si le paquet est corrompu, on ne peut même pas être sûr qu'il était bien le paquet attendu, puisque les bits qui permettent de le reconnaître sont peut-être ceux qui ont été changés.
Même chose si le paquet est fragmenté et que certains des fragments n'arrivent pas du tout. On ne peut pas reconstituer le paquet, on le considère comme perdu. En revanche, la duplication, elle, n'est pas considérée comme une perte.
Notre RFC 7680 décrit une métrique (une grandeur définie rigoureusement), pas une méthodologie de mesure, encore moins un protocole. Toutefois, la section 2.6 donne des indications sur ce que pourrait être une telle méthodologie. Le mécanisme recommandé est de mettre une estampille temporelle dans le paquet émis, et de regarder à l'arrivée si on détecte le paquet au bout d'un temps « raisonnable ». À noter que cette méthode n'implique pas une stricte synchronisation des horloges entre les deux machines. On est loin d'un protocole complet (je n'ai pas l'impression qu'il ait jamais été mis au point) et, par exemple, on n'indique pas comment la destination sait qu'elle doit s'attendre à voir arriver un paquet.
Toute mesure implique des erreurs et des incertitudes et la section 2.7 les analyse. D'abord, si les horloges ne sont pas synchronisées du tout, un paquet peut être déclaré comme perdu à tort (si l'émetteur a une horloge qui retarde, le paquet arrivera tard et le destinataire aura pu s'impatienter et le considéré perdu). Même problème si le délai d'attente n'est pas raisonnable, si le destinataire renonce trop vite. Ces deux problèmes peuvent être évités en synchronisant à peu près les horloges (il suffit que leur écart soit petit par rapport au délai d'attente) et en choisissant bien le délai (par exemple, sur une liaison utilisant un satellite géostationnaire, la finitude de la vitesse de la lumière impose un délai d'attente minimum de 240 ms - 2 * 35 786 / 300 000).
Une troisième source d'erreur est plus subtile : le paquet peut arriver jusqu'à la machine de destination (donc le réseau fonctionne bien) mais celle-ci le rejeter car ses ressources (par exemple les tampons d'entrée/sortie) sont pleines. Pour éviter de compter à tort des paquets comme perdus, il faut s'assurer que la machine de mesure a des ressources suffisantes pour traiter tous les paquets.
La section 2.8 se penche sur la publication des résultats (voir aussi l'excellent RFC 6703). Par exemple, elle impose de publier le Type-P (comme vu plus haut, le taux de pertes peut être différent en TCP et en UDP, par exemple), le seuil de patience (« le pourcentage de paquets non arrivés au bout de 1 500 ms est de X % »), et recommande de publier, autant que possible, le chemin parcouru (entre deux machines, si le chemin change par suite de modifications de routage, le taux de perte va probablement changer).
La métrique présentée en section 2 était pour
un paquet. La section 3 définit une métrique
supplémentaire,
Type-P-One-way-Packet-Loss-Poisson-Stream
pour le
cas où on utilise plusieurs paquets. Elle utilise une
distribution de Poisson (ce n'est pas la seule
possible mais elle est d'usage très fréquent). Et la section 4 s'en sert pour
définir une statistique utile.
Type-P-One-way-Packet-Loss-Ratio
(section 4.1,
attention, elle a changé de nom depuis le RFC 2680)
est le taux de pertes moyen. Si
on envoie cinq paquets et que quatre arrivent, elle vaut 0,2 (c'est ce
qu'affiche ping sous l'intitulé %
packet loss mais attention, ping fait une mesure
aller-retour et pas aller-simple comme notre RFC).
Cette moyenne n'est pas toujours facile à évaluer. Ainsi, sur un lien Internet typique, le taux de pertes est bas (nettement moins de 1 %). Pour obtenir une valeur statistiquement significative, il faut souvent tester avec des centaines de paquets.
Comme le note la section 5, consacrée à la
sécurité, un problème courant des mesures actives est qu'elles
peuvent perturber le réseau qu'elle observent. Si ces mesures actives
ne posent pas trop de problèmes de vie privée (on ne
mesure pas le trafic existant, mais seulement celui qu'on a créé),
elles peuvent par contre faire mal au réseau. Il faut donc prendre
soin de ne pas injecter « trop » de paquets (cf. l'option
-f
de ping).
Après « les mesures qui font du mal au réseau », il y a un autre risque de sécurité, « le réseau qui fait du mal aux mesures ». Imaginons qu'on mesure les performances d'un opérateur réseau et qu'un concurrent envoie exprès un trafic intense au même moment, les résultats seront mauvais. La publication des résultats devrait donc être accompagnée d'une description des solutions utilisées qui permettent de limiter le risque de ce genre d'attaques. (Cela peut être aussi simple que de ne pas communiquer à l'avance les moments où se font les mesures.)
Le RFC mentionne aussi le risque d'une « mesure Volkswagen » : un opérateur peut reconnaître les paquets de mesure et leur donner un traitement préférentiel. Là encore, il faut indiquer les solutions choisies pour que les paquets de mesure ne soient pas favorisés (par exemple en faisant en sorte qu'ils ressemblent autant que possible à des paquets « normaux »).
La section 6 de notre RFC présente les (très faibles) différences avec la précédente norme, le RFC 2680. Le but principal du nouveau RFC (projet documenté dans le RFC 6576) était de faire avancer cette métrique sur le « chemin des normes » (cf. RFC 2026), de « proposition de norme » à « norme [tout court] ». Les tests du RFC 7290 (voir aussi le rapport sur le RFC 2680) ont montré que les métriques Internet étaient sérieuses et utilisables, justifiant cet avancement sur le chemin des normes.
Les changements dans le texte sont minimes, comme l'introduction des références au RFC sur la publication de mesures, RFC 6703 et à d'autres RFC publiés depuis (comme le RFC 4737 sur le réordonnancement des paquets), la correction de petites erreurs, l'accent plus important sur la protection de la vie privée, etc.
Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : A. Langley (Google), M. Hamburg
(Rambus Cryptography Research), S. Turner
(IECA)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF cfrg
Première rédaction de cet article le 24 janvier 2016
Dernière mise à jour le 29 janvier 2016
Ce nouveau RFC est la description de deux courbes elliptiques largement utilisées mais qui n'avaient pas fait l'objet d'une description formelle complète : curve25519 et curve448. Maintenant que c'est fait, elles pourront être utilisées dans des normes Internet utilisant la cryptographie comme TLS ou DNSSEC.
La cryptographie sur les courbes elliptiques est une alternative aux algorithmes traditionnels fondés sur la décomposition en facteurs premiers, comme le classique RSA. Il est toujours bon de ne pas mettre tous ses œufs dans le même panier, car on ne sait jamais quelle sera la prochaine victime de la cryptanalyse (d'où le RFC 7696, sur l'importance de ne pas être prisonnier d'un seul algorithme). Grâce aux courbes elliptiques, si RSA est cassé complètement, on aura une solution de rechange. En outre, la cryptographie sur les courbes elliptiques a des propriétés intéressantes, comme des clés de taille plus petite. Dans les deux cas, RSA ou courbes elliptiques, je n'y connais pas grand'chose donc n'espérez pas des explications plus pointues.
Le schéma général de la cryptographie sur courbes elliptiques est décrit dans le RFC 6090 (voir aussi le cours « SEC 1: Elliptic Curve Cryptography »). Ce schéma permet l'utilisation d'une infinité de courbes elliptiques mais attention, toutes n'ont pas les propriétés requises. La plus connue est la courbe P-256 normalisée par le NIST. Comme il y a de très bonnes raisons de se méfier du NIST (leur rôle dans l'affaiblissement délibéré de Dual EC DRBG, cf. l'article de Schneier et celui de Greenemeier), et comme les raisons des choix des paramètres de P-256 n'ont jamais été rendues publiques, beaucoup de gens se méfient de P-256 (voir une bonne discussion sur StackExchange). Il est donc important, là encore, d'avoir plusieurs fers au feu, et de disposer d'autres courbes.
Les deux courbes décrites dans ce RFC sont curve25519 et curve448. Elles sont de la famille des courbes de Montgomery (et donc ont une équivalence avec une courbe d'Edwards).
Il n'est pas facile de faire des maths dans un RFC, avec leur format actuel. La section 3 décrit la notation utilisée dans le RFC, mais je ne vais pas reproduire les équations ici (je suis complètement ignorant de MathML et ce blog ne le gère pas). Des formules comme (section 4.1) :
(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x) (x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))
sont nettement moins jolies dans le texte brut des RFC.
La section 4 du RFC décrit les deux courbes. Curve25519 doit son nom au fait qu'un des nombres premiers utilisés pour la génération des paramètres de la courbe est 2^255-19. Sa description originale est dans l'article de Bernstein « Curve25519 -- new Diffie-Hellman speed records », et son équivalent en courbe d'Edwards, ed25519 dans « High-speed high-security signatures ».
L'autre courbe, curve448, utilise le nombre premier 2^448-2^224-1. La courbe d'Edwards équivalente est nommée Goldilocks et est décrite dans « Ed448-Goldilocks, a new elliptic curve ».
La section 5 du RFC présente les fonctions X25519 et X448, utilisées pour faire du Diffie-Hellman avec ces courbes. Des vecteurs de test sont également fournis, si vous voulez vérifier votre implémentation (rappel au passage : il y a plein de pièges quand on programme de la crypto.)
En parlant de Diffie-Hellman, la section 6 est la description de l'utilisation de ces deux courbes pour un échange de clés ECDH, utilisant les deux fonctions de la section précédente.
Quelle est la sécurité de ces deux courbes (section 7) ? Le niveau de sécurité de curve25519 lors d'une attaque par force brute est d'un peu moins de 128 bits. Une attaque par force brute est normalement l'essai de toutes les clés possibles. Toutefois, le terme est souvent utilisé en cryptographie (avec un abus de langage) pour désigner des méthodes où on fait beaucoup d'essais, sans forcément tester toutes les clés (comme l'algorithme rho). D'autre part, le RFC rappelle qu'il n'est pas facile de comparer des algorithmes de cryptographie, surtout entre algorithmes symétriques et asymétriques, cf. l'article de Bernstein « Understanding brute force ».)
curve448 est normalement « meilleure », avec 224 bits de sécurité (mais plus lente : on n'a rien sans rien). Le RFC note que, pour des ordinateurs quantiques (si on en a un jour...), les deux courbes seront aussi faciles à casser l'une que l'autre. En attendant, curve25519 est parfaitement suffisant.
Notez que, si vous aimez la cryptographie quantique et les discussions sans fin, la NSA a publié en août 2015 un texte qui a stupéfié beaucoup de monde car il affirmait que, vu l'arrivée supposée proche des calculateurs quantiques, il n'était pas recommandé de faire des efforts pour migrer depuis RSA vers les courbes elliptiques. Certains en ont déduit que la NSA avait déjà des calculateurs quantiques et savaient donc que les courbes elliptiques étaient cassées ou proches de l'être, d'autres ont supposé que, si la NSA essayait de décourager les utilisateurs de se servir des courbes elliptiques, c'était au contraire une raison supplémentaire pour migrer vers ces courbes au plus vite. La polémique et l'état des informations disponibles sont très bien expliqués dans l'article « A riddle wrapped in an enigma ».
L'annexe A du RFC décrit comment les paramètres de ces deux courbes ont été générés. Des courbes comme la P-256 du NIST ou comme la courbe elliptique souveraine FRP256 de l'ANSSI ont été très critiquées car les différentes constantes utilisées sont juste annoncées, sans explication. Il n'y a pas besoin d'être excessivement paranoïaque, ou d'avoir lu les documents publiés par Snowden, pour se demander « Pourquoi ces valeurs plutôt que d'autres ? Ne serait-ce pas parce que ces constantes ont des propriétés qui facilitent leur décryptage par la NSA ou un organisme similaire ? ». Il y a consensus aujourd'hui pour dire qu'on ne doit utiliser que des courbes pour lesquelles le choix des paramètres a été fait « objectivement », selon une méthodologie expliquée et vérifiable. C'est ce que fait l'annexe A.
Notez que les paramètres des deux courbes de ces RFC n'ont pas été choisis complètement « objectivement ». Ils ont fait l'objet d'« optimisations », notamment pour des raisons de performance. Si on veut une courbe générée entièrement par un algorithme objectif et publiquement vérifiable, il faudra se tourner (elle est très récente) vers des courbes « publiquement vérifiables » comme la « courbe d'un million de dollars », qui proclame être « a procedure, more than a curve ».
Maintenant que ces courbes font l'objet d'une documentation
complète, il sera plus facile de les utiliser depuis un protocole
IETF (ceci dit, elles sont déjà dans au moins une norme, voir RFC 7479). Plusieurs travaux sont en cours pour
cela ; il y avait un Internet-Draft pour
permettre curve25519 dans TLS,
draft-ietf-tls-curve25519
mais il a été
remplacé par le plus général
RFC 8422. Un autre
Internet-Draft traite le cas de
DNSSEC, draft-sury-dnskey-ed25519
.
Notez que les deux courbes de ce RFC sont décrites selon un formalisme qui ne permet pas de les utiliser telles quelles dans un algorithme comme ECDSA (explications sur StackOverflow). Mais on peut avec EdDSA.
OpenSSH dispose de curve25519 depuis la version 6.5. (« Add support for key exchange using elliptic-curve Diffie Hellman in Daniel Bernstein's Curve25519. This key exchange method is the default when both the client and server support it. [...] Add support for Ed25519 as a public key type. Ed25519 is a elliptic curve signature scheme that offers better security than ECDSA and DSA and good performance. It may be used for both user and host keys. »). Dans les sources d'OpenSSH, ce sont les fichiers ayant 25519 dans leur nom :
/tmp/openssh-7.1p2 % ls *25519* ed25519.c fe25519.c fe25519.h ge25519_base.data ge25519.c ge25519.h kexc25519.c kexc25519c.c kexc25519s.c sc25519.c sc25519.h smult_curve25519_ref.c ssh-ed25519.c
Pour générer des clés utilisant cette courbe, on utilise le classique ssh-keygen :
% ssh-keygen -t ed25519 Generating public/private ed25519 key pair. ... Your identification has been saved in /home/stephane/.ssh/id_ed25519. Your public key has been saved in /home/stephane/.ssh/id_ed25519.pub. ...
Par contre, ces courbes ne sont pas encore dans
OpenSSL (voir la discussion #309). Autrement,
on trouve des mises en œuvre de curve25519 à plein d'endroits : https://github.com/msotoodeh/curve25519
, https://code.google.com/p/curve25519-donna/
et bien sûr http://cr.yp.to/ecdh.html
et https://nacl.cr.yp.to/
.
Merci à Patrick Mevzek pour son exploration d'OpenSSH et OpenSSL, à Émilien Gaspar pour les discussions et à Manuel Pégourié-Gonnard pour des corrections, notamment sur la force brute.
Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : S. Kiesel (University of
Stuttgart), R. Penno (Cisco
Systems), S. Cheshire (Apple)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF pcp
Première rédaction de cet article le 23 janvier 2016
Le protocole PCP, normalisé dans le RFC 6887, permet à une machine de signaler à la
box, au
routeur CPE, au
pare-feu, ses désirs en terme d'ouverture
de ports,
d'obtention d'information sur l'adresse IP externe, etc. Mais
comment l'ordinateur de M. Michu trouve t-il l'adresse du serveur
PCP ? Une des solutions est celle introduite par ce
RFC : une adresse
anycast « bien connue »,
192.0.0.9
en IPv4 et
2001:1::1
en IPv6.
Souvent, l'adresse IP du serveur PCP est évidente : c'est l'adresse du routeur par défaut. Mais il y a des cas plus compliqués, par exemple en cas de CGN (section 1 du RFC). Avant notre RFC 7723, les seules autres solutions étaient la configuration manuelle, ou une option DHCP (RFC 7291).
Ce nouveau RFC ajoute une possibilité : le client PCP écrit
tout simplement à l'adresse bien connue, 192.0.0.9
ou
2001:1::1
, et le serveur PCP
approprié
répondra. L'anycast
s'occupera de router le message du client au bon serveur. Une
simple diffusion n'aurait
pas suffi : le serveur PCP n'est pas forcément sur le réseau local
(notamment en cas de CGN). Avec
l'anycast, il n'y a pas besoin d'installer quoi
que ce soit de particulier dans le réseau local ou les équipements
CPE. Et l'adresse bien connue étant
immuable, on peut la mettre en dur dans les applications PCP, sans
avoir besoin de l'obtenir du système
d'exploitation. (Personnellement, je trouve cela un peu
optimiste : comme cette option anycast est
nouvelle, et qu'elle ne sera pas forcément déployée partout,
l'application aura toujours besoin d'un « plan B » en demandant au
système d'exploitation « une idée de l'adresse IP du serveur PCP ? »)
Le comportement du client et du serveur PCP est décrit dans la section 2 du RFC. La liste des serveurs PCP possibles pour le client (section 8.1, étape 2 du RFC 6887) s'enrichit des adresses anycast bien connues. Le traitement de cette liste continue à suivre la norme PCP du RFC 7488. Le serveur, lui, a juste à écouter sur les adresses anycast bien connues, en plus de ses adresses habituelles. Le RFC ne le mentionne apparemment pas, mais l'administrateur réseaux doit aussi évidemment configurer le routage pour que la route vers le serveur PCP soit annoncée partout, et appliquée.
L'anycast peut être déroutant au début pour les administrateurs réseaux et la section 3 du RFC rappelle donc quelques règles de déploiement (en plus des documents existants sur l'anycast, RFC 4786 et RFC 7094). Par exemple, si le réseau a deux connexions vers l'extérieur, chacune avec son propre serveur PCP, l'anycast ne va pas forcément aider car le message PCP du client ne sera reçu que par un seul des deux serveurs (même si tous les serveurs ont été configurés pour écouter sur l'adresse anycast).
Si le routage est toujours symétrique, ce n'est pas un problème, car le serveur PCP qui recevra le message envoyé à l'adresse anycast est également celui qui verra passer tout le trafic, et pourra donc faire ce qui lui a été demandé par le client PCP. Même si le routage change, et qu'on passe subitement par un autre lien, avec un autre serveur PCP, ce n'est pas grave (c'est l'équivalent du redémarrage d'un serveur PCP, cas qui est géré par les clients PCP).
Mais, si le routage est asymétrique... Eh bien, dans ce cas, c'est fichu, c'est une limite de PCP plus que de ces adresses anycast. La seule solution est de développer un mécanisme (qui n'existe pas encore) pour synchroniser deux serveurs PCP.
La section 4 de notre RFC rappelle les enregistrements des deux adresses à l'IANA, dans les registres d'adresses spéciales IPv4 et IPv6.
(Les fanas de sécurité peuvent lire la section 5 mais il n'y a pas grand'chose à dire d'original : les messages PCP, anycast ou pas, peuvent être attaqués comme tous les autres paquets IP, ni plus, ni moins.)
Pour l'instant (PCP est, de toute façon, très peu déployé), je ne crois pas que quiconque utilise déjà ces adresses anycast.
Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : T. Manderson (ICANN)
Pour information
Première rédaction de cet article le 21 janvier 2016
Ce court RFC décrit un schéma
XML qu'utilise
l'ICANN pour gérer les zones
DNS dans les domaines
ip6.arpa
et
in-addr.arpa
. Rien de standard, juste la
documentation d'une pratique locale.
Depuis 2011, l'ICANN utilise ce système
pour gérer et produire les zones DNS dont
elle a la responsabilité sous
.arpa
(in-addr.arpa
est documenté dans le RFC 1034 et ip6.arpa
dans le
RFC 3152). L'ICANN délègue des zones aux
RIR et ceux-ci souhaitent un système le plus
fiable, simple et prévisible possible.
La gestion de ces zones se faisait, il y a fort longtemps, à la main, avec un éditeur ordinaire, mais cela n'est évidemment plus possible depuis le déploiement de DNSSEC : les clés changent, les enregistrements DS (Delegation Signer) doivent être mis à jour, etc. Et la plus petite erreur casse la validation cryptographique. Bref, pour ce service comme pour d'autres, DNSSEC pousse fortement à automatiser sérieusement les processus.
Le principe de base (section 3, le gros du RFC) est que le
RIR prépare sa demande sous forme d'un
fichier XML conforme au schéma décrit dans
ce RFC, et l'envoie à l'ICANN par une
requête REST. Elle est évidemment en
HTTPS et authentifiée par un
certificat client (et un pour le serveur,
également). L'AC est l'ICANN elle-même. Recevant le XML, l'ICANN met à jour automatiquement
les zones sous .arpa
.
En bonne logique REST, les requêtes
HTTP sont
GET
, PUT
et
DELETE
. GET
sert à
interroger l'état actuel de la base (et le RIR n'utilise donc que
l'URI, il n'envoie pas de XML).
Voici un exemple d'une requête en XML qui pourrait être envoyée
(requête PUT
)
pour mettre à jour la zone 10.in-addr.arpa
,
avec deux enregistrements DS (pour la même clé, la 33682) :
<zone xmlns="http://download.research.icann.org/rdns/1.1" name="10.in-addr.arpa" cust="IANA" ipversion="ipv4" version="1.1" modified="2012-01-18T01:00:06" state="active" href="https://host.example.org/ipv4/10"> <nserver> <fqdn>BLACKHOLE-1.IANA.ORG.</fqdn> </nserver> <nserver> <fqdn>BLACKHOLE-2.IANA.ORG.</fqdn> </nserver> <ds> <rdata>33682 5 1 ea8afb5fce7caf381ab101039</rdata> </ds> <ds> <rdata>33682 5 2 7d44874f1d93aaceb793a88001739a</rdata> </ds> </zone>
Notez que la modification n'est pas forcément instantanée : il peut y avoir un système de vérification manuelle et d'approbation explicite.
Les URL utilisés par le client sont variables. Par exemple,
pour mettre à jour le domaine 10.in-addr.arpa
cité plus haut, l'URL serait
http://icann.example/4/10.in-addr.arpa
(en
remplaçant icann.example
par le vrai nom du
serveur REST à l'ICANN). Pour avoir une liste des demandes en
attente (rappelez-vous que le système n'est pas synchrone), le
client ferait un GET sur
http://icann.example/queuelist
, etc.
Les annexes A et B du RFC donnent le schéma Relax NG complet des éléments XML possibles. Par exemple, une zone DNS se définit ainsi :
# A single zone record zone = element zone { # The zone record's name, eg 10.in-addr.arpa attribute name { text }, ... # The administrative state of the zone (optional) attribute state { "active" | "pending" | "error" }?, # The last modified timestamp in UTC (optional) attribute modified { xsd:dateTime }?, ... # A zone NS RRset MUST have at least two NS records nserver, nserver+, # It MAY contain some DS records ds* }
À noter que ce schéma ne permet pas d'indiquer de la
colle
(adresses IP de serveurs de noms situés dans la zone elle-même)
puisqu'il ne sert que pour les zones sous
.arpa
(on ne voit jamais de serveurs de noms
nommés ainsi).
Pourquoi développer un tel système plutôt que d'utiliser la norme EPP ? Le RFC ne le dit pas mais on peut supposer que c'est parce qu'EPP est bien plus complexe.
Première rédaction de cet article le 17 janvier 2016
Dernière mise à jour le 23 janvier 2016
Il y a un vieux problème sur ce blog, qui se pose depuis que j'ai activé l'accès en HTTPS : les flux de syndication ne fonctionnaient pas avec un grand nombre d'agrégateurs. J'ai contourné le problème en ayant désormais deux flux, un en HTTPS et un sans.
Quel est le problème ? Comme j'utilise une AC gratuite et automatique, CAcert, qui n'est pas dans tous les magasins de certificats, loin de là, je ne peux pas forcer l'usage de HTTPS, cela perturberait trop de lecteurs. (Pourtant, j'ai publié des enregistrements DANE mais, malheureusement, il y a encore bien des navigateurs qui, bêtement, ne les utilisent pas. Demandez aux auteurs de votre navigateur et dites-leur bien que DANE est la bonne solution à ce problème.)
Pour les flux de syndication Atom,
j'avais pensé résoudre le problème en utilisant des liens
« presque absolus ». Ces liens commencent par deux
barres obliques, par exemple
//www.bortzmeyer.org/toot.html
et le logiciel
client est supposé, pour le plan (http:
ou
https:
) utiliser le même plan que celui
utilisé pour récupérer le fichier où il y avait ces liens.
Avec tous les navigateurs Web, ça marche, le
navigateur ajoute http:
ou https:
selon l'URL utilisé pour récupérer
la ressource originale. J'ai malheuresement constaté que ce n'était
pas le cas avec les agrégateurs de
syndication. De nombreux agrégateurs ne comprennent pas
ces liens, et font, par exemple, des requêtes pour une ressource
//www.bortzmeyer.org/toot.html
, ce qui produit
une erreur 404. Le problème semble affecter, entre autres,
Liferea ou spaRSS. Certains agrégateurs ont corrigé
(Netvibes) mais d'autres trainent la patte.
Qui a raison ? Ce n'est pas évident. La syntaxe des
URI est normalisé par le RFC 3986, qui semble autoriser ces URI relatifs commençant
par deux barres obliques (section 4.2 du RFC, « A relative reference that begins with two slash characters is termed
a network-path reference », et l'exemple
//g
en 5.4.1). Ces URI « double slash » sont également appelés
« protocol-relative
URIs » ou « protocol-less URIs », termes tout à fait
erronés puisque le plan n'est pas forcément un protocole,
« scheme-relative URIs » serait un meilleur terme. De toute façon,
personnellement, je trouve le RFC peu clair sur ce point : ces URI sont
légaux mais leur sémantique est mal expliquée. En attendant, le
RFC sur Atom (RFC 4287) semble décourager
l'usage de liens non-absolus (sections 4.2.7.1 et 4.2.6). (Pour
RSS, les liens non-absolus sont clairement
interdits car RSS n'a pas de notion d'« URL de base »,
contrairement à Atom.)
Un autre inconvénient de ces liens presques absolus étaient qu'ils ne donnent pas le résultat attendu si le flux Atom a été récupéré par un autre moyen que HTTP ou HTTPS (par exemple un fichier sur le disque local).
Plutôt que d'essayer de faire corriger tous les agrégateurs, j'ai préféré offrir le choix au lecteur, qui va donc devoir manuellement sélectionner le flux qu'il préfère.
Voici donc les quatre flux Atom. Il y a en effet le choix entre TLS ou pas (pour la sécurité et la vie privée) et article complet ou pas :
Merci à tous les signaleurs de bogue et notamment à Styx.
Première rédaction de cet article le 16 janvier 2016
Dernière mise à jour le 22 janvier 2016
La commission des lois de l'Assemblée Nationale a voté le 13 janvier le principe de la création d'un « OS souverain », et cet amendement a été confirmé par le vote de l'Assemblée les 20 et 21 janvier (voir l'actuel texte consolidé). Si cette initiative ni réfléchie, ni étudiée, a, à juste titre, déclenché l'hilarité de Twitter, c'est l'occasion d'expliquer ce que cela veut dire et où ça mène.
L'idée est en effet ancienne, dans tous les endroits où se promènent des Excellences et des gourous à ministres, on entend ce projet, en général jamais explicité et jamais détaillé. Comme les zombies dans les jeux vidéo, cette idée est très difficile à tuer et renait tout le temps. C'est en bonne partie parce qu'il n'y a aucun cahier des charges digne de ce nom : juste un slogan creux.
Mais imaginons qu'on cherche un peu. Qu'est-ce que pourrait être un OS souverain et pourquoi est-ce que ce serait une mauvaise idée ?
D'abord, questionnons un peu ce qu'on entend par « OS ». Le terme de « système d'exploitation » (OS = Operating System dans la langue d'Edgar Hoover) peut désigner deux choses en français :
Rappelez-vous, l'Assemblée a voté un projet sans définir ce qu'elle entendait par là. On va donc supposer que c'est le deuxième sens, celui d'un ensemble complet, permettant à des gens ordinaires de commencer à travailler.
Si c'est bien le cas, c'est une tâche colossale et, franchement, déraisonnable. Cela représente une quantité de logiciels astronomique, que ne peuvent réaliser que de très grosses entreprises comme Microsoft, ou bien les myriades de développeurs du logiciel libre. Le futur « Commissariat à la Souveraineté Numérique » n'aura certainement pas les moyens de financer un tel développement. Clamer « on va écrire un système d'exploitation » est donc une vantardise ridicule.
Peut-être qu'il y aura simplement adaptation d'un système d'exploitation existant ? Prendre un système qui existe, par exemple en logiciel libre, modifier deux ou trois choses et lui coller un drapeau tricolore sur l'écran de démarrage ? Techniquement, c'est plus raisonnable. C'est ce qu'ont fait des États soucieux de souveraineté comme la Corée du Nord avec Red Star OS, ou bien l'administration française avec CLIP (non cité à l'Assemblée : la main droite de l'État ignore ce que fait sa main gauche). Il existe plein de systèmes existants qui pourraient servir de base pour éviter de réinventer la roue (réinvention qu'adorent les députés, ainsi bien sûr que les gagneurs de marchés publics habituels). On peut citer, entre autres :
On ne peut plus alors dire « on va développer un OS souverain » mais, est-ce que, sur le fond, le résultat ne serait pas le même ?
Dans l'hypothèse où ce soit la stratégie suivie, quelles modifications pourraient être apportées au système existant ? C'est là que commencent les problèmes politiques : soucieux d'unanimité, les députés n'ont pas expliqué ce point. Pas la moindre plus petite ébauche de liste des fonctions souhaitées, dans l'amendement voté à l'Assemblée. Essayons de faire le travail des députés. Un tel système pourrait permettre :
Ce n'est qu'une liste partielle. Mes lecteurs ont certainement plein d'autres idées intéressantes. Mais le point important de cette liste est que, toute partielle qu'elle soit, elle est déjà très contradictoire. C'est en effet le problème de fond avec la souveraineté : il s'agit de la souveraineté de qui ? Du citoyen qui veut se protéger ? De l'État qui veut tout voir et tout entendre ? Le futur système d'exploitation souverain offrira-t-il du chiffrement solide de bout en bout ou bien facilitera-t-il la surveillance des utilisateurs ? Ça, c'est une vraie question politique, et c'est normalement le travail des députés. Qu'ils ne l'aient pas discuté dans leur amendement illustre bien leur manque de sérieux.
D'autant plus qu'écrire un tel « OS souverain » n'est pas tout. Encore faut-il que les gens l'utilisent. En Corée du Nord, citée plus haut, pas de problème, il suffit qu'on leur demande gentiment et tous les citoyens le font. Mais en France ? Il faudrait convaincre les citoyens et cela sera difficile si on leur dit juste « c'est un fantasme de Pierre Bellanger, installez-le, ça lui fera plaisir. » Après tout, il n'y a aucune demande des utilisateurs.
Les députés eux-mêmes seront sans doute les plus réticents : ils crient bien fort à la tribune qu'ils veulent de la souveraineté numérique, mais les rares parmi eux qui répondent aux courriers électroniques le font depuis une adresse Yahoo ou Gmail. Jamais ils ne se dégooglisent, mais ils voudraient dégoogliser les autres.
Une administration particulièrement difficile à convaincre sera l'Éducation Nationale : comme elle a signé un accord scandaleux avec Microsoft, elle n'utilisera sans doute pas l'« OS souverain » (sur lequel il y a peu de chances que Microsoft porte ses applications...).
Enfin, il faut noter que l'expérience ne sert à rien : après les sommes faramineuses englouties dans l'escroquerie nommée « cloud souverain » (alors qu'il existait déjà plusieurs acteurs français du cloud), on pourrait s'attendre à davantage de précautions de la part de l'État, et à une analyse du passé, avant de prétendre influencer l'avenir... Sans compter l'expérience récente de Louvois, qui laisse des doutes sur la capacité de l'État français à gérer des grands projets informatiques.
Que va donner le projet actuel ? Verrons-nous naître le « Commissariat à la Souveraineté Numérique » ? Réalisera-t-il le fameux « OS souverain » ? Je vois cinq scénarios possibles :
Le scénario 5 semble le moins probable, le 4 serait le pire, il en ferait même souhaiter que ce soit le scénario 3 qui soit réalisé : mieux vaut le gaspillage que la dictature.
Quelques lectures en plus :
Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : R. Sparks (Oracle), T. Kivinen
(INSIDE Secure)
Pour information
Première rédaction de cet article le 14 janvier 2016
Le processus de production des normes par l'IETF suit de nombreuses étapes, toutes se déroulant en public. Il est en effet essentiel que de nombreux yeux puissent regarder les documents en voie de devenir des RFC. Et que de nombreux examens (reviews) aient lieu. Pour suivre ces examens, il est préférable de disposer d'outils et ce sont les futurs outils à développer que décrit ce RFC.
Parmi les équipes qui effectuent des examens des Internet-Drafts en cours d'avancement figurent Gen-ART et SecDir. Mais il en existe plusieurs autres, parfois très spécialisées, et qui n'examinent que les documents relevant de leur spécialité (par exemple les MIB par les MIB doctors ou bien les schémas YANG par les YANG doctors).
Les équipes en question doivent se tenir au courant des documents en cours, leur affecter un examinateur parmi ceux qui sont enregistrés pour cette tâche, fixer une date limite et relancer l'examinateur s'il est en retard, etc. Cela serait évidemment très pénible à faire à la main et ces équipes utilisent actuellement un outil, développé il y a longtemps. Du fait de son âge, il n'est pas bien intégré avec le principal outil de travail en groupe de l'IETF, le Datatracker. Par exemple, pour obtenir certaines informations, l'outil analyse des pages HTML du Datatracker :-) .
[Au passage, notez que le Datatracker est vraiment un excellent outil, qui facilite beaucoup la vie du participant à l'IETF. On voudrait tous avoir des outils de travail en groupe équivalents au bureau.]
Une meilleure intégration avec le Datatracker permettrait de simplifier l'accès à ces informations, et à d'autres qui ne sont pas utilisées actuellement, car trop pénibles à extraire. Ce nouveau RFC est le cahier des charges du futur outil (voir aussi le système de gestion de tickets de l'outil actuel).
Pour comprendre ce cahier des charges, il est utile de revenir sur l'utilisation actuelle de l'outil des examens (section 2 du RFC). Typiquement, l'équipe a un secrétariat qui, une fois par semaine environ, dresse une liste des documents qui sont prêts à subir un examen, par exemple parce qu'ils sont en IETF Last Call (dernier appel avant approbation) ou parce qu'ils sont sur l'agenda des réunions (virtuelles) de l'IESG.
Le secrétariat prend ensuite un examinateur parmi la liste des examinateurs possibles, en tenant compte de paramètres comme le fait qu'un auteur ne doit évidemment pas être examinateur de son propre Internet-Draft. L'idée est en général de prendre un examinateur qui a un regard neuf et n'a pas été impliqué dans le développement du document.
Les différentes équipes d'examen n'ont pas toutes le même fonctionnement. Certaines, comme indiqué plus haut, s'« auto-saisissent » alors que d'autres sont plutôt en mode « on examine si on nous le demande » (c'est le cas de l'équipe du routage, par exemple).
Les examinateurs eux-même n'utilisent pas en général l'outil directement : ils communiquent par courrier avec le secrétariat. Et c'est par courrier qu'ils envoient le résultat de leur examen, après avoir rempli un « courrier-type ». Voici par exemple l'examen fait par Gen-ART pour le futur RFC sur la QNAME minimisation ou bien celui de RTG-Dir pour un futur protocole d'HomeNet.
Voici donc le fonctionnement actuel. Pour le futur outil, les exigences sont dans la section 3 de notre RFC. D'abord, ce qui intéresse le secrétariat de l'IETF (section 3.1) :
Plus importantes, les exigences pour le secrétariat de l'équipe d'examen (section 3.2), entre autres :
^draft-(michu|ietf-dprive).*
, l'excluant de
ses drafts et de ceux de DPRIVE,Et pour l'examinateur lui-même, que doit savoir faire l'outil (section 3.3) ? Par exemple :
draft-ietf-cuterabbit-security-analysis-09.txt
»),Comme tout le monde aime les statistiques, et qu'il est bon de pouvoir évaluer si une équipe d'examen marche bien ou pas, l'outil devra également fournir des chiffres (section 3.5) :
Les outils actuels de l'IETF sont écrits en Django. Pour rendre ce cahier des charges plus concret, l'annexe A fournit un modèle Django tout prêt. Par exemple, l'état d'un examen peut être :
class ReviewRequestStateName(NameModel): """ Requested, Accepted, Rejected, Withdrawn, Overtaken By Events, No Response , Completed """
Un examinateur est ainsi modélisé :
class Reviewer(models.Model): """ These records associate reviewers with review team, and keeps track of admin data associated with the reviewer in the particular team. There will be one record for each combination of reviewer and team. """ role = models.ForeignKey(Role) frequency = models.IntegerField(help_text= "Can review every N days") available = models.DateTimeField(blank=True,null=True, help_text= "When will this reviewer be available again") filter_re = models.CharField(blank=True) skip_next = models.IntegerField(help_text= "Skip the next N review assignments")
Et une demande d'examen est :
class ReviewRequest(models.Model): """ There should be one ReviewRequest entered for each combination of document, rev, and reviewer. """ # Fields filled in on the initial record creation: time = models.DateTimeField(auto_now_add=True) type = models.ReviewTypeName() doc = models.ForeignKey(Document, related_name='review_request_set') team = models.ForeignKey(Group) deadline = models.DateTimeField() requested_rev = models.CharField(verbose_name="requested_revision", max_length=16, blank=True) state = models.ForeignKey(ReviewRequestStateName) # Fields filled in as reviewer is assigned, and as the review # is uploaded reviewer = models.ForeignKey(Reviewer, null=True, blank=True) review = models.OneToOneField(Document, null=True, blank=True) reviewed_rev = models.CharField(verbose_name="reviewed_revision", max_length=16, blank=True) result = models.ForeignKey(ReviewResultName)
Vous avez envie de réaliser cet outil ? L'annonce a été publiée le 28 décembre 2015 et vous avez jusqu'au 18 janvier 2016 pour proposer vos services.
Date de publication du RFC : Janvier 2016
Auteur(s) du RFC : M. Mathis (Google), B. Briscoe (BT)
Pour information
Réalisé dans le cadre du groupe de travail IETF conex
Première rédaction de cet article le 6 janvier 2016
Le projet ConEx de l'IETF vise à développer des mécanismes permettant à l'émetteur de paquets IP de prévenir le réseau situé en aval que ce flot de données rencontre de la congestion. Les routeurs pourront alors éventuellement prendre des décisions concernant ce flot. Ce nouveau RFC expose le mécanisme abstrait de signalisation (le mécanisme concret, dans des protocoles comme TCP, a été normalisé plus tard).
La spécification se fait donc en trois temps, décrire le problème et les scénarios d'utilisation (RFC 6789), décrire un mécanisme de signalisation de la congestion abstrait, sans se soucier des détails techniques (ce RFC 7713), puis enfin normaliser le protocole concret (RFC 7786 et RFC 7837), avec les inévitables compromis que cela implique.
Aujourd'hui, les équipements réseau comme les routeurs signalent la congestion vers l'aval, en utilisant ECN (RFC 3168), en retardant les paquets (car les files d'attente mettent du temps à se vider) ou, tout simplement, en laissant tomber des paquets. Ce signalement arrive au récepteur qui peut alors informer l'émetteur, par exemple en réduisant la fenêtre, dans TCP. Cette boucle de rétroaction préserve l'Internet de la congestion (RFC 5681). (De ces trois signaux, le temps d'acheminement est le moins utilisé, car il n'est pas un indicateur univoque de la congestion.)
Mais ce signalement n'est pas visible de tous les équipements réseau traversés par ce flot de paquets. Ceux situés en amont du premier routeur qui détecte la congestion ne sont pas prévenus, alors qu'ils auraient pu jouer un rôle. Le rôle de ConEx est justement que tout le monde soit informé. Le principe de base est que l'émetteur, une fois prévenu de la congestion, mette dans les paquets qu'il envoie un indicateur que ce flot rencontre de la congestion quelque part sur le trajet.
Pour que ConEx soit déployé, il faudra que les gens y trouvent un avantage, surtout au début où le déploiement sera limité. Ce problème est commun à tous les nouveaux protocoles mais il sera encore plus crucial pour un protocole qui permettra de signaler les gros consommateurs... Ceux-ci pourraient se retrouver pénalisés (« vos flots signalent tous de la congestion, vous devriez ne les lancer qu'aux heures creuses ») ou poussés à utiliser des protocoles moins gourmands comme LEDBAT (RFC 6817).
ConEx semblait moins nécessaire autrefois car les protocoles comme TCP étaient conçus pour limiter la congestion, en se calmant dès qu'ils la détectaient. Un problème jamais résolu était celui de machines qui ignorent délibérement cet objectif et, par exemple, utilisent des protocoles de transport qui maximisent le débit individuel et tant pis pour le reste de l'Internet. Difficile de lutter contre cet égoïsme. Il pourrait être contagieux puisque les bons citoyens se trouveraient alors défavorisés, et seraient donc tentés de suivre la voie égoïste à leur tour, poussant les gros consommateurs à faire des protocoles encore plus agressifs, etc. L'IETF a toujours découragé ces pratiques (comme celle d'ouvrir plusieurs connexions TCP simultanées pour avoir une plus grosse part du gâteau) avec un succès variable.
ConEx est une approche complémentaire : les gens peuvent consommer de la capacité réseau mais ils doivent le signaler.
Comme une des conséquences de ce signalement pourrait être un traitement différencié du flot en question (« il encombre le réseau, je le limite »), une partie importante du projet ConEx est de s'assurer qu'il n'y aura pas de triche (par exemple d'émetteur « négligeant » d'informer le réseau des problèmes qu'il pose). Les signaux ConEx doivent donc être auditables, pour détecter les tricheurs. (Voir Briscoe, « Re-feedback: Freedom with Accountability for Causing Congestion in a Connectionless Internetwork »).
Une dernière chose avant d'attaquer le cahier des charges exact de ConEx, le vocabulaire :
Re-Echo-Loss
),
soit une marque ECN (signal
Re-Echo-ECN
), soit que l'émetteur s'attend
à déclencher de la congestion bientôt, par exemple parce qu'il
démarre et teste la capacité du réseau (signal Credit
),
soit qu'il n'a rien à signaler, à part qu'il sait faire du ConEx
(signal ConEx-Not-Marked
).La section 3 de notre RFC décrit les exigences précises de ConEx. D'abord, pour les signaux :
Ces exigences sont parfois contradictoires et le RFC note qu'il faudra sans doute, en passant de ces abstractions à un protocole concret, accepter quelques compromis.
J'ai parlé de l'importance d'auditer les signaux ConEx. La fonction d'audition n'est pas normalisée dans ce RFC mais il pose des exigences qu'elle doit suivre, notamment :
Ce RFC décrit des mécanismes abstraits. Le futur travail du groupe de travail ConEx devra en faire un ensemble de mécanismes concrets, traitant entre autres de ces points :
Là encore, il ne sera sans doute pas possible de tout satisfaire. Les futurs RFC ConEx devront donc noter quelles exigences ont été délibérement affaiblies, voire abandonnées.(Cf. les RFC 7837 et RFC 7786.)
Place à l'encodage, maintenant, pour satisfaire mes lecteurs qui préfèrent savoir à quoi vont ressembler les bits sur le câble. Je rappelle que le protocole précis n'est pas encore normalisé, cette section 4 du RFC ne fait que pointer les problèmes liés à l'encodage des signaux. Prenons en effet un encodage naïf : on décide d'un bit dans l'en-tête IP qu'on met à 1 dès qu'il y a eu une retransmission TCP (des données sans accusé de réception, qu'il a fallu réémettre), ou dès qu'on a réduit la fenêtre TCP en réponse à ECN. Cet encodage semble satisfaire les premières exigences de ConEx : il est trivial à réaliser (sans doute une seule ligne de code dans la plupart des mises en œuvre de TCP/IP), il est compatible avec les matériels et logiciels existants (les non-ConEx ignoreront tout simplement ce bit), tout routeur ConEx sur le trajet peut lire ce bit et agir en fonction de sa valeur.
Mais cet encodage trop simple a des défauts : comme dans le cas du RFC 3514, il ne permet pas un audit. On n'a aucun moyen de vérifier si l'émetteur triche ou pas. Bon, ne soyons pas trop critique : un tel encodage est utile pour aider à comprendre ConEx et à se représenter à quoi cela peut bien ressembler. Dans des environnements fermés où tout le monde est honnête, il peut suffire.
D'autres encodages sont imaginables. Par exemple, on pourrait ne rien encoder du tout et dire aux routeurs ConEx de regarder les flots TCP et d'en déduire s'il y a eu rencontre avec la congestion en aval ; en effet, si on voit des retransmissions, ou la fenêtre TCP se réduire, on peut en déduire que l'émetteur a vu de la congestion et a réagi. Cela implique que les routeurs analysent TCP (ce qu'ils ne font normalement pas) et gardent un état (au moins un RTT de données), ce qui serait coûteux. Mais cela dispenserait de toute modification des émetteurs. Et cela ne permet pas de triche.
Dans un routeur implémenté en logiciel, en bordure du réseau, cela pourrait être réaliste (dans un routeur de cœur traitant des milliards de paquets à la seconde, cela le serait moins). À noter que des protocoles de sécurité comme TLS ou SSH ne masquent pas TCP et ne seraient donc pas un problème pour une analyse ConEx (contrairement à IPsec avec ESP, mais qui est beaucoup moins répandu). Mais si ConEx était ainsi déployé, cela pourrait motiver certains pour tout faire passer dans un VPN qui empêcherait cette observation.
Et encoder avec ECN ? Il existe une
proposition (Internet-Drafts
draft-briscoe-conex-re-ecn-tcp
et draft-briscoe-conex-re-ecn-motiv
) d'intégration d'ECN avec ConEx, qui
a l'avantage d'empêcher la triche.
L'inconvénient de l'approche précédente est de nécessiter ECN,
que n'ont pas tous les récepteurs. Une approche purement ConEx à
l'encodage serait d'avoir des bits dédiés à ConEx dans l'en-tête
IP (ou dans un en-tête d'extension en
IPv6). On peut utiliser un bit par signal
ConEx (ConEx
,
Re-Echo-Loss
,
Re-Echo-ECN
et Credit
),
ou bien essayer de profiter du fait que certains sont mutuellement
exclusifs pour condenser un peu.
Un sous-problème intéressant est celui de savoir si on compte la congestion en bits ou bien en paquets ? Est-ce que la perte d'un paquet de 1 500 octets vaut celle d'un paquet de 64 octets ? La perte d'un gros paquet est-elle due à sa taille ou bien un petit paquet aurait-il été également jeté ? Certaines parties du réseau sont limitées en nombre de bits (c'est typiquement le cas des tuyaux), d'autres en nombre de paquets (c'est partiellement le cas des équipements actifs). Le RFC 7141 recommande d'utiliser plutôt les bits, le RFC 6789 suggère la même chose, au moins dans l'Internet actuel.
La section 5 du RFC décrit les composants du réseau qui auront un rôle à jouer dans ConEx (voir aussi la section 6). Les équipements intermédiaires (notamment les routeurs) d'aujourd'hui ignorent les signaux ConEx et passent les paquets tels quels (espérons qu'aucun pare-feu trop zélé ne se permettra de les bloquer). Ceux qui seront modifiés ConEx, soit des routeurs, soit des engins spécialisés (congestion policer ?) liront les signaux ConEx, les vérifieront (cf. la partie sur l'audit) et pourront agir, par exemple en shapant les émetteurs qui déclenchent de la congestion.
Les émetteurs, typiquement des machines terminales, devront voir leur code TCP/IP modifié pour émettre des signaux ConEx. A priori, ceux qui n'ont même pas encore ECN n'utiliseront pas ConEx non plus, mais ceux qui ont ECN trouveront peut-être l'ajout de ConEx intéressant.
Les récepteurs, typiquement des machines terminales, n'ont pas à être modifiés.
L'audit des signaux ConEx, pour détecter les tricheurs (pensez au RFC 3514) est évidemment essentiel (section 5.5). Si des équipements réseaux limitent le trafic des émetteurs qui déclenchent de la congestion, afin d'épargner le réseau aval, ces émetteurs auront évidemment un bon mobile pour tricher. Ils risquent de ne pas mettre les signaux ConEx. (Voir aussi la section 8, sur la sécurité.)
Comment détecter les tricheurs ? Une solution possible est de
détecter les pertes de paquets et de voir si l'émetteur envoie bien des
Re-Echo-Loss
. Mais attention : rien ne dit
que l'auditeur voit tous les paquets d'un flot. Si le trafic passe
par deux liens différents, l'auditeur situé sur un des liens
risque de ne pas voir certains paquets et croire à tort qu'ils
sont perdus.
Les signaux ECN peuvent aussi servir à l'audit. Pour être sûr de les voir, il faut être en aval des points où il y a congestion.
Une autre solution est d'utiliser les retransmissions de TCP. Si l'émetteur réémet, c'est que que paquets ont été perdus. Là, il vaut mieux être proche de l'émetteur (donc le plus en amont possible), pour être sûr de voir tous ses paquets, même en cas de chemins multiples dans le réseau.
Le routeur qui doit jeter des paquets (ou les marquer avec ECN) car il n'arrive plus à tout transmettre est aussi un bon endroit pour faire de l'audit : il peut directement comparer ce qu'il fait (jeter les paquets d'un flot donné) avec l'apparition, un RTT plus tard, des signaux ConEx.
La thèse de B. Briscoe (un des auteurs du RFC), « Re-feedback: Freedom with Accountability for Causing Congestion in a Connectionless Internetwork » contient une analyse détaillée de toutes les techniques de triche, et d'audit, connues.
Première rédaction de cet article le 3 janvier 2016
Je viens d'installer FreeBSD sur un Raspberry Pi. Rien d'extraordinaire, je voulais juste expliquer pourquoi je ne garderai pas ce système en production.
Il y a désormais des images officielles pour le
Raspberry Pi chez
FreeBSD : ftp://ftp.freebsd.org/pub/FreeBSD/releases/ISO-IMAGES/10.2/
(« ...arm-armv6-RPI-B...
»). On télécharge,
on décomprime, on copie sur un carte SD
avec dd et on démarre le Pi dessus :
wget ftp://ftp.freebsd.org/pub/FreeBSD/releases/arm/armv6/ISO-IMAGES/10.2/FreeBSD-10.2-RELEASE-arm-armv6-RPI-B.img.xz unxz FreeBSD-10.2-RELEASE-arm-armv6-RPI-B.img.xz sudo dd if=FreeBSD-10.2-RELEASE-arm-armv6-RPI-B.img of=/dev/sdb bs=1M conv=sync [Démarrage du Pi ; il faut être patient la première fois, cela prend plusieurs minutes pour générer les clés SSH.]
Ensuite, on peut se connecter au Pi en SSH (login/mot de passe freebsd/freebsd). On crée des comptes, on change les mot de passe, tout va bien :
amour% uname -a FreeBSD amour 10.2-RELEASE FreeBSD 10.2-RELEASE #0 r286666: Thu Aug 13 03:16:22 UTC 2015 root@releng1.nyi.freebsd.org:/usr/obj/arm.armv6/usr/src/sys/RPI-B arm amour% uptime 1:59PM up 39 mins, 2 users, load averages: 1.67, 1.83, 1.66
(Les messages de démarrage du noyau sont disponibles ici.)
C'est ensuite que les ennuis commencent. Le programme
bsdinstall
censé permettre de configurer la
machine facilement ne marche pas, la liste des miroirs n'étant pas
adapté au processeur ARM : la plupart des
miroirs n'ont pas ARM et on n'a aucun moyen de le savoir à
l'avance. bsdinstall
quitte donc
rapidement. Il faut donc faire les réglages à la main. Par
exemple, pour la date et le fuseau horaire :
ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime ntpdate ntp.nic.fr
Et pour le clavier :
% kbdmap kbdcontrol: getting keymap: Inappropriate ioctl for device You are not on a virtual console - expect certain strange side-effects lang_default = en dialect = en lang_abk = en keymap="fr.kbd"
Mais le plus gênant concerne les paquetages. Dans la terminologie
FreeBSD, le port est le source et le
paquetage le binaire (pré-compilé,
donc). Quand on a démarré sur l'image officielle, on n'a que le
système de base. Pour des raisons historiques (enfin, plutôt,
pré-historiques), FreeBSD maintient une division des anciens Unix,
entre un système de base et les applications. La distinction est
assez arbitraire (le système « de base » contient un
compilateur, par exemple, alors que
l'écrasante majorité des machines n'en ont pas besoin). Pour
installer des applications utiles, il existe plusieurs mécanismes
(et qui changent tout le temps, donc les vieux articles récupérés
sur le Web ne vous aideront pas). Un peu au hasard, j'ai testé
avec pkg
:
# pkg update The package management tool is not yet installed on your system. Do you want to fetch and install it now? [y/N]: y Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:10:armv6/quarterly, please wait... pkg: Error fetching http://pkg.FreeBSD.org/FreeBSD:10:armv6/quarterly/Latest/pkg.txz: No address record A pre-built version of pkg could not be found for your system. Consider changing PACKAGESITE or installing it from ports: 'ports-mgmt/pkg'.
Le message « No address record » est erroné. Le site existe bien, mais n'a rien pour les processeurs ARM. En fait, le fond du problème est qu'il n'y a pas de paquetages (donc de binaires) pour le Raspberry Pi ; il parait qu'ils apparaitront dans la prochaine version de FreeBSD (je rappelle que les mises à jour du système sont très complexes avec FreeBSD, rien à voir avec ce que permet un système comme Debian, donc je n'envisage pas de passer dans les systèmes ultérieurs).
Il faut donc tout compiler soi-même ce qui, sur le Raspberry
Pi, prend des siècles (et use la carte
SD). J'ai utilisé portsnap
pour
extraire les ports (les sources, ou plutôt les références aux
sources) comme suggéré par
Johnson D :
portsnap fetch portsnap extract
puis, cd /usr/ports/CATEGORY/SOFTWARE
et
make install
. C'est horriblement lent et je ne
rêve même pas d'arriver à installer emacs
ainsi. Donc, pas utilisable « en vrai ».
Autre problème, j'ai eu du mal à activer
IPv6 (qui ne l'est pas par défaut, ce qui est
incroyable en 2016). Il existe d'innombrables variables IPv6 pour le
/etc/rc.conf
et les explications sur leur
interaction sont confuses. Mon réseau utilise
SLAAC pour la configuration IPv6. Un peu au hasard, j'ai mis :
ipv6_enable="YES" ipv6_activate_all_interfaces="YES" ipv6_privacy="YES" ifconfig_ue0_ipv6="inet6 accept_rtadv"
Où ue0
est le nom de l'interface Ethernet du
Pi. Avec un peu de patience ensuite, cela marche.
Quelques documentations et articles :
Des alternatives possibles :
Première rédaction de cet article le 1 janvier 2016
À l'heure où le fanatisme religieux est à l'offensive dans le monde, il faut lire et relire le journal d'Anne Frank. C'est plus facile désormais qu'il est monté dans le domaine public, ce premier janvier.
La famille d'Anne Frank, jeune juive allemande, réfugiée, déchue de sa nationalité, s'est installée à Amsterdam en 1934. C'est à Amsterdam qu'elle a écrit son journal intime, notamment pendant la période où sa famille était cachée, pendant l'occupation allemande. Elle a été arrêtée et assassinée par les nazis.
Ce journal monte dans le domaine public aujourd'hui. Malheureusement, un groupe de professionnels de l'appropriation intellectuelle prétend que le journal d'Anne Frank lui appartient, et menace ceux qui le publieraient. Il est donc crucial que le plus d'internautes possibles relayent cette publication, à l'image de Olivier Ertzscheid et d'Isabelle Attard, que je félicite chaleureusement au passage.
Voici donc le texte original, en néerlandais. Point juridique : la montée dans le domaine public se fait en général 70 ans après la mort de l'auteur (une durée incroyablement et anormalement longue). Mais cela ne vaut que pour le texte original, toute traduction (en français, par exemple), remet le compteur à zéro. Voici pourquoi il n'y a « que » le texte original.
anne-frank.txt
anne-frank.epub
anne-frank.doc
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.