Les RFC (Request For Comments) sont les documents de référence de l'Internet. Produits par l'IETF pour la plupart, ils spécifient des normes, documentent des expériences, exposent des projets...
Leur gratuité et leur libre distribution ont joué un grand rôle dans le succès de l'Internet, notamment par rapport aux protocoles OSI de l'ISO organisation très fermée et dont les normes coûtent cher.
Je ne tente pas ici de traduire les RFC en français (un projet pour cela existe mais je n'y participe pas, considérant que c'est une mauvaise idée), mais simplement, grâce à une courte introduction en français, de donner envie de lire ces excellents documents. (Au passage, si vous les voulez présentés en italien...)
Le public visé n'est pas le gourou mais l'honnête ingénieur ou l'étudiant.
Date de publication du RFC : Août 2013
Auteur(s) du RFC : M. Goyal (University of Wisconsin, Milwaukee), E. Baccelli (INRIA), A. Brandt (Sigma Designs), J. Martocci (Johnson Controls)
Expérimental
Réalisé dans le cadre du groupe de travail IETF roll
Première rédaction de cet article le 27 août 2013
Le protocole RPL (Routing Protocol for Low power and Lossy Networks), normalisé dans le RFC 6550, est conçu pour des réseaux de machines très bon marché, ayant peu de capacités (mémoire et calcul), étant souvent très limitées en énergie, et étant connectées par des liens de qualité médiocre. Un tel environnement peut par exemple se rencontrer dans des réseaux de capteurs dispersés dans un environnement industriel. Une partie des machines du réseau va se dévouer pour router les paquets des autres. RPL permet de trouver et de diffuser des routes mais celle choisie ne sera pas forcément optimale. D'où ces deux extensions à RPL permettant à un routeur de 1) mesurer une métrique donnée en émettant un paquet de contrôle vers la destination, paquet qui accumulera au fur et à mesure, dans les routeurs intermédiaires, les informations à propos de la route utilisée actuellement et, 2) découvrir à la demande une route meilleure (si tant est qu'il y en a une).
C'est que ce n'est pas une vie que d'être routeur dans un LLN (Low power and Lossy Network, les réseaux difficiles dont je parlais au paragraphe précédent). Le RPL classique du RFC 6550 essaie de faciliter les choses en limitant le réseau à un graphe acyclique dirigé vers un puits de données et en calculant toutes les routes à l'avance (ce qu'on nomme un protocole proactif). Une extension à RPL, nommée P2P-RPL (P2P pour pair-à-pair) et normalisée dans le RFC 6997, permet à RPL de devenir réactif et donc de calculer des routes à la demande. Elle permet aussi de trouver des routes plus courtes, en évitant le passage par le sommet du graphe pré-établi. Le routeur utilise, pour ces calculs, les métriques du RFC 6551 (latence, capacité, qualité, et autres métriques dans le registre IANA). Mais comment connaître leur valeur effective dans un réseau ? Eh bien, en les mesurant, tout simplement.
Le protocole RPL ne transmettant pas cette information pour toutes les routes, c'est au routeur qui en a besoin de demander. Il génère un paquet de contrôle RPL d'un nouveau type, Measurement Request indiquant ce qu'il veut savoir à propos du chemin entre lui-même et la destination. Chaque routeur sur le trajet va mettre à jour ce paquet avec le coût (pour la métrique demandée) du lien effectivement emprunté. Au bout, le destinataire répondra au demandeur, avec un message de contrôle Measurement Reply, contenant toute l'information accumulée. Le demandeur pourra alors agir (changer d'avis pour certaines routes, par exemple).
En fait, les deux messages utilisent le même type de paquets, les Measurement Object de code 0x06 (section 3 et registre IANA). Un bit dans son en-tête, le bit T (pour Type) sert à distinguer si ce Measurement Object est un Measurement Request ou un Measurement Reply. Le paquet contient surtout des options Metric Container (section 6.7.4 du RFC 6550 et section 2.1 du RFC 6551) qui accumuleront au fur et à mesure les valeurs demandées.
Il est intéressant de comparer ce mécanisme à celui de traceroute qui n'accumule pas les mesures mais compte sur une réponse de chaque routeur intermédiaire vers la source ; des options avaient été proposées pour un traceroute « enregistreur » - Record Route du RFC 791 ou option IP du RFC 1393 - mais elles n'ont eu aucun succès.
Notez bien que, dans un réseau ad hoc, rien ne garantit que tous les routeurs accepteront de procéder à cet enregistrement de données. Ils ont parfaitement le droit de refuser de le faire (voir la section 5 de notre RFC), par exemple pour économiser leur batterie ou bien parce qu'ils trouvent une telle demande trop indiscrète (section 8 du RFC).
Il existe déjà plusieurs mises en œuvre de cette extension expérimentale et un test d'interopérabilité a été documenté. Sinon, un bon article consacré aux mesures de P2P-RPL est « The P2P-RPL Routing Protocol for IPv6 Sensor Networks: Testbed Experiments ».
Merci à Emmanuel Baccelli pour sa relecture attentive.
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : J. Mitchell (Microsoft)
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 29 juillet 2013
Comme pour beaucoup de nombres utilisés dans les protocoles TCP/IP, les numéros de système autonome ont une plage réservée aux usages privés, ne devant pas être transmis à l'extérieur. Ce nouveau RFC élargit la plage existante, qui était jugée trop petite par des gens qui gèrent des gros centres de données (comme Microsoft ou certains acteurs de l'infonuagique).
La section 10 du RFC 1930 réservait la plage allant de 64 512 à 65 535 (soit 1 024 numéros) pour des AS privés. Augmenter la taille de cette plage était délicat tant que les numéros d'AS étaient limités à 16 bits. Mais ils sont désormais sur 32 bits (RFC 6793) et il n'y a donc plus de raison de faire des économies. Une seconde plage, utilisant des numéros sur 32 bits, est donc réservée, allant de 4 200 000 000 à 4 294 967 294 (94 967 295 numéros). Ces deux plages sont documentées dans le registre IANA. (Notez que d'autres plages sont réservées pour la documentation, par le RFC 5398. Les numéros des deux plages de notre RFC sont, eux, conçus pour être utilisés par de vrais routeurs.)
La section 4 de notre RFC met en garde les opérateurs qui
utilseraient ces numéros privés : ils ne doivent
pas apparaître sur l'Internet public. Lorsqu'une
annonce BGP dont le chemin (attributs
AS_PATH
ou AS4_PATH
) sort du
domaine privé, ces numéros d'AS doivent être retirés. Les commandes sont neighbor x.x.x.x remove-private-as
pour IOS (c'est configuré pour chaque voisin BGP) et neighbor x.x.x.x remove-private
pour
JunOS mais attention : les anciennes versions
de ces logiciels ne connaissaient que la première plage d'AS privés et
ne retireront donc pas les numéros de la seconde plage. D'autre part,
certains logiciels pour les routeurs ne
retirent pas les numéros d'AS privés si le chemin dans l'annonce BGP
contient un mélange d'AS privés et publics. Si le routeur en question
n'a pas été mis à jour pour connaître la seconde plage de numéros d'AS
privés, il va les prendre pour des numéros d'AS publics et ne rien
retirer...
À noter que l'idée même d'avoir des nombres pour usage privé (que ce soient les numéros d'AS ou d'autres comme les adresses IP) défrise toujours un certain nombre de gens à l'IETF et que cette minorité s'était fait entendre dans le débat sur cet élargissement.
Date de publication du RFC : Août 2013
Auteur(s) du RFC : J. Touch (USC/ISI)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 24 août 2013
Le protocole TCP dispose d'un champ « Options » permettant d'indiquer des fonctions spécifiques. Ce champ commence par un identificateur d'option (sur un octet) et deux valeurs sont réservées pour des options expérimentales, non enregistrées. Deux, c'est trop peu, et, en prime, il y a parfois collision entre deux options expérimentales différentes. Notre RFC propose donc un nouveau mécanisme éliminant ces collisions, en ajoutant un deuxième identificateur, l'ExID, dans les options expérimentales.
Le champ « Options » est décrit dans le RFC 793. Il a deux formes mais la plus courante est composée d'un octet indiquant l'option, d'un octet indiquant la longueur de l'option et de données spécifiques à l'option (un TLV, donc). Les options sont enregistrées à l'IANA et sont aujourd'hui au nombre d'une trentaine. 30 sur 256 possibles, cela justifie de les allouer avec prudence (RFC 2780) et les gens qui veulent juste essayer une idée amusante, sans enregistrer leur option, n'avaient pas de solution simple avant que le RFC 4727 ne réserve les options 253 et 254 pour les expérimentations. Si vous avez une idée qui nécessite une option TCP, et que vous voulez la mettre en œuvre, prenez un de ces deux numéros et mettez-le dans vos paquets TCP, vous serez dans la légalité (le RFC 3692 dit toutefois que cela ne doit pas être activé par défaut).
Mais ces expérimentations risquent de se marcher sur les pieds entre elles. Par exemple, le RFC 6013 s'alloue l'option 253. Si vous voulez tester une option en même temps que celle du RFC 6013, il ne vous reste plus qu'un numéro, ce qui peut être insuffisant (certains systèmes nécessitent plusieurs options). À noter que cet usage d'un numéro d'option expérimental est légal (c'est fait pour) mais qu'il existe aussi des squatteurs, qui utilisent des numéros normalement réservés sans les avoir enregistrés proprement. Les options 31 et 32 avaient ainsi été squattées autoritairement, comme 76 à 78, 33, 69, 70, et 76 à 78 (ces derniers dans des produits commerciaux). Le registre IANA les note comme « known unauthorized use without proper IANA assignment ».
Plusieurs approches ont été suggérées à
l'IETF pour régler ce problème. Il a été
proposé d'élargir l'espace des numéros d'options
(Internet-Draft
draft-eddy-tcpm-addl-exp-options
) et/ou de
libéraliser les règles d'allocation, actuellement très strictes (il
faut un RFC sur le chemin des normes pour réserver une option). Ce
RFC 6994 utilise une autre approche : il crée un
« sous-espace » à l'intérieur des options expérimentales, dans lequel on
peut (mais ce n'est pas obligatoire) enregistrer sans trop de
formalités une expérimentation et son identificateur. C'est désormais
l'approche recommandée pour les nouvelles options expérimentales TCP
(et obligatoire si l'option expérimentale est déployée sur l'Internet public).
Le principe (section 3) est de remplacer la structure {numéro d'option, longueur, valeur} par {numéro d'option, longueur, ExID, valeur} où le ExID est l'identificateur d'une expérimentation. La taille des ExID (16 ou 32 bits) permet d'en avoir beaucoup et donc d'avoir une politique d'enregistrement libérale sans craindre d'épuiser une ressource finie. L'IANA les enregistre donc sur une base toute simple : « premier arrivé, premier servi » (RFC 5226 pour les différentes options d'allocation possibles). Le registre de ces ExID est en ligne (il compte actuellement trois expérimentations dont le Fast Open TCP qui a été décrit dans le RFC 7413).
Bon, mais l'ExID fait 16 ou 32 bits, alors ? C'est subtil : les 16 premiers bits doivent être uniques pour identifier une expérimentation. Les 16 bits optionnels suivants servent de nombre magique, pour éviter le risque de collision avec des mises en œuvre de TCP qui ne connaissent pas ce RFC (ou bien l'ignorent) et mettent leurs données juste après l'octet de longueur. Si on veut économiser de la place, on choisit un ExID de 16 bits, si on veut minimiser le risque de collision, on prend 32 bits.
Que va donc faire une mise en œuvre de TCP qui rencontre ces options (section 3.2) ? Si l'option est 253 ou 254, elle doit lire l'ExID et ignorer l'option s'il s'agit d'une expérimentation qui lui est inconnue.
Mais les collisions, alors ? Elles peuvent toujours exister. Si une implémentation ancienne de TCP utilise l'option 253 et met au début des données qu'elle envoie la valeur 0x15df, et que le récepteur TCP, conforme à ce nouveau RFC 6994, croit qu'il s'agit de l'expérimentation 5599, qu'il connait, et se met à analyser l'option comme telle ? Il n'y a pas de solution magique. La section 4 de notre RFC recommande aux receveurs TCP d'être robustes face à de telles collisions, ou bien de mettre en œuvre un mécanisme de contrôle de la cohérence des données, pour rejeter les faux positifs.
Un problème classique (et non spécifique à TCP) avec les options expérimentales est qu'un jour, elles seront peut-être normalisées et qu'il faudra alors gérer une transition depuis l'option expérimentale vers l'option standard. La section 5 couvre ce cas mais ne recommande pas une stratégie particulière. Elle se contente de dire qu'envoyer les deux options (l'expérimentale et la standard) dans le même paquet est une mauvaise idée (l'espace des options est limité en TCP).
La section 6 discute des autres approches qui auraient pu être choisies. Par exemple, au lieu des ExID, on aurait pu marquer les options avec un identificateur de l'organisation qui dirige l'expérience, en utilisant les OUI de l'IEEE ou bien les Enterprise Numbers de l'IANA (RFC 1155). Mais les OUI sont très chers (comme souvent à l'IEEE), plus de 1 800 dollars. Les PEN (Private Enterprise Numbers) sont gratuits mais ne sont normalement pas allouables à un individu. Et, dans les deux cas, ces nombres sont plus grands que l'ExID (les PEN n'ont pas de taille définie actuellement mais ils sont déjà trop nombreux pour 16 bits) alors que l'espace est limité dans le champ Options de TCP, puisque tout octet prend la place d'un octet utile aux données.
Si on regarde les versions de développement de
Linux et de FreeBSD, on
ne trouve rien dans ce dernier
(sys/netinet/tcp_input.c
dans tcp_dooptions()
), qui ne connait pas, par défaut, les
options expérimentales. Pour Linux, seul Fast Open
est reconnu. Le code dans net/ipv4/tcp_input.c
,
tcp_parse_options()
dit :
case TCPOPT_EXP: /* Fast Open option shares code 254 using a * 16 bits magic number. It's valid only in * SYN or SYN-ACK with an even size. */ if (opsize < TCPOLEN_EXP_FASTOPEN_BASE || get_unaligned_be16(ptr) != TCPOPT_FASTOPEN_MAGIC || foc == NULL || !th->syn || (opsize & 1)) break; foc->len = opsize - TCPOLEN_EXP_FASTOPEN_BASE; if (foc->len >= TCP_FASTOPEN_COOKIE_MIN && foc->len <= TCP_FASTOPEN_COOKIE_MAX) memcpy(foc->val, ptr + 2, foc->len); ... }
Où TCPOPT_FASTOPEN_MAGIC
vaut 0xF989 (l'ExID sur
16 bits dans le registre IANA).
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : J. Schoenwaelder (Jacobs University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF netmod
Première rédaction de cet article le 31 juillet 2013
Le langage de modélisation YANG, normalisé dans le RFC 6020, est notamment utilisé dans le protocole de gestion à distance NETCONF (RFC 6241). C'est en YANG que les utilisateurs de NETCONF décrivent les données à manipuler via NETCONF. Ce RFC, successeur du RFC 6021, normalise une bibliothèque de types de données d'usage général, dérivés des types de base de YANG.
Ces types de base sont décrits dans la section 9 du RFC 6020. On y trouve les classiques de l'informatique,
boolean, entiers,
string, etc. Deux modules YANG sont décrits dans ce
nouveau RFC,
ietf-yang-types
pour des types non limités à
l'Internet et ietf-inet-types
pour des types
spécifiques à TCP/IP.
Je ne vais pas ici reprendre la liste de tous ces nouveaux types,
juste donner quelques exemples de ce qu'apporte ce RFC. En section 3,
les types généraux, on trouve par exemple,
counter32
. C'est un compteur, c'est à dire une
variable qui ne fait que grimper, jusqu'au moment d'atteindre une
valeur maximale (elle repart alors de zéro). Comme son nom l'indique,
il est stocké sur 32 bits. Par contre, gauge32 peut
monter et descendre.
Le type yang-identifier, un nouveau venu, est
une chaîne de caractères ASCII (ne commençant
pas par xml
). Il est défini
en YANG par une expression rationnelle :
typedef yang-identifier { type string { length "1..max"; pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; ...
date-and-time, lui, existait déjà dans le RFC 6021. C'est une date au format du RFC 3339 qui est proche du format traditionnel des schémas XML (mais, par contre, est différent de celui utilisé dans le SMI). Au contraire de date-and-time, qui est formaté, timeticks est simplement un nombre de secondes depuis l'epoch (non spécifiée : chaque schéma qui utilisera ce type indiquera quelle est l'epoch).
Il y a aussi des types plus orientés réseau comme mac-address pour les adresses MAC :
typedef mac-address { type string { pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; }
Et d'autres qui empruntent à des identificateurs existants comme uuid (RFC 9562).
En section 4, les types spécifiques aux protocoles TCP/IP, on a entre autres ip-version qui permet d'indiquer si on parle d'IPv4 ou d'IPv6 :
typedef ip-version { type enumeration { enum unknown { value "0"; description "An unknown or unspecified version of the Internet protocol."; } enum ipv4 { value "1"; description "The IPv4 protocol as defined in RFC 791."; } enum ipv6 { value "2"; description "The IPv6 protocol as defined in RFC 2460."; } } ...
Il y a bien sûr les numéros de port :
typedef port-number { type uint16 { range "0..65535"; } ...
Et de système autonome :
typedef as-number { type uint32; ...
Et évidemment les adresses IP :
typedef ip-address { type union { type inet:ipv4-address; type inet:ipv6-address; } ... typedef ipv6-address { type string { pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + '(%[\p{N}\p{L}]+)?'; pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + '(%.+)?'; } ...
Un exercice amusant : essayez de retrouver dans quel RFC est défini l'expression rationnelle officielle pour les adresses IPv6... (Avertissement : c'est difficile.)
Enfin, ce RFC donne aussi une définition du type domain-name pour les noms de domaine :
typedef domain-name { type string { pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + '|\.'; length "1..253"; } ...
C'est une définition très contestable car, limitée à
l'ASCII, elle oblige à représenter les
IDN par un A-label
(café.fr
doit être écrit
xn--caf-dma.fr
, RFC 5890). Pire, le texte d'explication qui
accompagne le module est plutôt embrouillé quant à la la définition des noms de domaine par rapport à
celle des noms de machines (plus restrictive).
Par rapport au RFC 6021, qui contenait la bibliothèque originale, ce RFC ajoute quelques types (yang-identifier, uuid, etc, la liste complète est dans l'annexe A).
Date de publication du RFC : Septembre 2013
Auteur(s) du RFC : J. Quittek, M. Chandramouli (Cisco Systems), R. Winter (NEC Europe), T. Dietz (NEC Europe), B. Claise (Cisco Systems)
Pour information
Réalisé dans le cadre du groupe de travail IETF eman
Première rédaction de cet article le 1 octobre 2013
L'augmentation considérable des coûts de l'énergie, et la montée plus que justifiée des préoccupations écologiques, fait que la question de la consommation énergétique des équipements informatiques devient de plus en plus cruciale (certaines études estiment que la consommation d'énergie de l'Internet dépasse celle d'un pays comme la Russie). Les gros centres de données du nuage, usines à consommer du mégawatt, sont particulièrement visés. Cela a amené l'IETF à se lancer dans un domaine nouveau pour elle, et à créer un groupe de travail consacré à la gestion de l'énergie, EMAN, dont voici le premier vrai RFC, le cahier des charges du problème.
Le modèle envisagé est celui d'engins qui consomment ou fournissent de l'énergie, typiquement sous forme électrique, et qu'on veut pouvoir à la fois surveiller (monitoring function) et piloter (control function). Ces engins ont parfois une adresse IP, permettant de leur parler directement, et parfois pas, et il faut alors passer par un relais, qui va être la face visible de l'engin. Ce premier RFC du groupe EMAN définit les services indispensables dans les futures normes de gestion de l'énergie, suivant le modèle décrit dans le RFC 7326 (attention, ce RFC est un cahier des charges pour les normes, les futurs RFC d'EMAN, pas forcément pour les mises en œuvres qui suivront).
La gestion d'engins connectés au réseau n'est évidemment pas un problème nouveau et il existe déjà solutions et normes. Mais la gestion de l'énergie a trois particularités :
Avant d'aborder le cahier des charges proprement dit, la section 2 de notre RFC expose la terminologie, car tous les participants à l'IETF, bien versés dans le vocabulaire TCP/IP, ne connaissent pas forcément celui du monde de l'énergie (l'IEEE a un « Authoritative Dictionary of IEEE Standards Terms » d'où le RFC extrait plusieurs termes, mais je ne trouve pas ce dictionnaire en ligne). Donc, révisons un peu physique et ingéniérie :
La section 3 complète cette section 2 de terminologie en exposant quelques problématiques générales, qu'il faut avoir en tête lorsqu'on veut gérer l'énergie. D'abord, la notion d'état (Power state) : un engin peut être en état normal (il fonctionne, il répond et il consomme du courant), endormi (il consomme moins de courant, il ne répond pas aux requêtes normales mais il peut revenir en état normal rapidement) ou éteint (il ne consomme plus rien mais peut prendre un certain temps à se rallumer et à redevenir opérationnel). Les engins les plus simples n'ont que deux états, allumé et éteint. Les plus perfectionnés en ont plus que trois : par exemple, ils peuvent avoir des modes de basse consommation où l'engin reste complètement opérationnel mais avec des performances réduites. Sur des engins composés de plusieurs parties relativement indépendantes, il est parfois possible de couper le courant dans une partie de ces sous-ensembles et pas seulement dans l'engin entier.
Le but ultime de la gestion de l'énergie est d'économiser du courant. Comme rien n'est parfait en ce bas monde, cela se fera souvent au prix d'un service moins bon. Il sera donc en général nécessaire de faire des compromis.
La gestion de l'énergie peut être entièrement locale (à l'intérieur de l'engin lui-même) ou bien globale au réseau. Un exemple de gestion locale est une machine qui se met en sommeil automatiquement lorsqu'elle n'a pas eu d'activité depuis N minutes. Cela peut se faire sans réseau, sans collecter l'information et sans système central. Un exemple de gestion globale est un système qui voit que la consommation électrique du réseau devient trop importante (en coût ou, tout simplement, par rapport aux capacités du fournisseur d'énergie) et qui éteint alors autoritairement certains engins. Le système de gestion ayant plus d'informations que les machines locales, il peut prendre des décisions plus appropriées, et tenir compte de politiques globales (on éteint les machines dans le bureau la nuit). Les deux méthodes ont leurs avantages et leurs inconvénients et, en général, on combine les deux.
À noter (section 3.4) que la supervision de la consommation d'énergie, à elle seule, ne diminue pas la consommation. Elle va même l'augmenter, puisque le système de supervision consomme lui-même du courant. Pour que ce système mène à une diminution de la consommation, il faut aussi qu'il soit utilisé pour chercher les économies possibles, évaluer les mesures de réduction de consommation, assurer la comptabilité de chaque entité, etc.
Pour assurer une bonne supervision, avec une granularité permettant cette comptabilité, il va falloir des identificateurs pour désigner les différentes entités (section 4). Une entité peut être une machine ou bien seulement une partie d'une machine (un disque dur, par exemple, ou bien une line card). En effet, certaines mesures d'économie d'énergie peuvent être à ce niveau de détail (éteindre une seule line card). Il existe déjà de tels identificateurs, par exemple dans les MIB des RFC 4133 et RFC 3621. Il faudra donc lier les informations de gestion de l'énergie à ces identificateurs, traitant des problèmes comme la persistence en cas de redémarrage.
Ensuite, il faut connaître, pour chaque entité supervisée et/ou contrôlée, un certain nombre d'informations (section 5). Par exemple, il est préférable de connaître l'importance d'une entité, pour éviter d'éteindre une machine importante alors qu'on voulait économiser quelques watts. Une autre propriété utile est l'ensemble des caractéristiques statiques de son alimentation électrique : utilise-t-elle du courant continu ou alternatif, quelle est la tension normale, la fréquence normale (par exemple, 230 V à 50 Hz), etc. Il faut aussi connaître la liste des interfaces utilisées pour l'énergie, et s'il s'agit de production (power outlet, par où on envoie de l'énergie) ou de consommation (power inlet, par où on reçoit de l'énergie).
Et il y a des caractéristiques dynamiques :
Après la supervision, le contrôle (section 6). Contrairement à la supervision, il est actif. Il s'agit d'agir. Agir sur quoi ?
Une section 9 détaillée couvre les problèmes de sécurité. On a beaucoup parlé des risques de sécurité des SCADA, souvent connectés à l'Internet sans réflechir. Ces systèmes de contrôle, souvent anciens et n'ayant pas fait l'objet d'une analyse de sécurité sérieuse, sont parfois reliés à ce réseau mondial sans précautions. Contrôler l'état des machines et leur fourniture d'électricité est clairement une fonction très sensible. La sécurité doit donc être soigneusement pesée. Tout doit être authentifié et autorisé. Et les engins qui mettent en œuvre les services décrits dans ce RFC ne devraient pas être connectés à l'Internet public sans une très bonne raison (section 9.2).
Il n'y a pas que le contrôle qui pose des problèmes de sécurité. Par exemple, la supervision soulève des problèmes de vie privée, comme cela a été plusieurs fois évoqué dans le débat sur les compteurs intelligents.
Depuis ce cahier des charges, plusieurs RFC sur le sujet ont été publiés comme les RFC 7326 et le RFC 7603.
Date de publication du RFC : Août 2013
Auteur(s) du RFC : V. Dolmatov (Cryptocom), A. Degtyarev (Cryptocom)
Pour information
Première rédaction de cet article le 5 septembre 2013
Ce RFC documente en anglais une norme russe de l'organisme GOST. GOST R 34.11-2012 est une fonction de condensation cryptographique. Elle pourra notamment être utilisée pour DNSSEC.
Les algorithmes GOST (un abus de langage puisque GOST est normalement le nom de l'organisme de normalisation) sont une alternative russe aux algorithmes de cryptographie d'origine états-unienne comme RSA ou ECDSA (qui peuvent être remplacés par GOST R 34.10-2001) ou comme SHA-2 (qui peut être remplacé par GOST R 34.11-2012, qui fait l'objet de ce RFC). Pour être utilisés dans les protocoles IETF, il leut fallait une documentation en anglais. GOST R 34.10-2001 avait été documenté dans le RFC 5832. Notre RFC 6986 documente le petit dernier membre de la famille (son prédécesseur pour la condensation, GOST R 34.11-94, était dans le RFC 5831). Notez que les algorithmes GOST sont normalisés pour un usage dans le cadre de DNSSEC (RFC 9558).
Comme les autres algorithmes GOST, notre R 34.11-2012 est donc un algorithme officiel en Russie. Il a été approuvé par le décret n° 216 de l'agence fédérale chargée de la régulation technique, en août 2012. À terme, il vise à remplacer l'ancien R 34.11-94. C'est un algorithme de condensation cryptographique, qui peut produire des condensats de 256 ou 512 bits.
Je ne vais pas essayer de vous expliquer son principe de fonctionnement (sections 4 à 10), car c'est trop loin de mon domaine de compétence. Si vous êtes plus courageux que moi, notez qu'il y a beaucoup de maths et que, dans le formatage texte brut des RFC, ce n'est pas forcément idéal.
Questions mises en œuvre, notez qu'OpenSSL
1.0.1c n'a apparemment pas d'algorithmes de condensation
GOST par défaut. openssl dgst
-h
pour voir la liste. Il faut apparemment éditer le openssl.cnf pour y avoir accès.
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : A. Morton (AT&T Labs)
Pour information
Réalisé dans le cadre du groupe de travail IETF bmwg
Première rédaction de cet article le 19 juillet 2013
Traditionnellement, les mesures des caractéristiques d'un réseau en labo (RFC 2544) se faisaient avec des paquets de taille constante, afin de bien contrôler les conditions de la mesure, de savoir exactement ce qui était mesuré et donc de pouvoir reproduire la mesure à volonté. C'est par exemple ce que fait la commande ping avec son option -s. Mais les réseaux réels sont bien différents : ils font passer des paquets de taille très diverses. Il est donc fréquent aujourd'hui de tester avec un mélange de paquets de différentes tailles, ce qu'on nomme un IMIX (Internet MIXture). De nos jours, les équipements de test ont souvent la possibilité d'utiliser des IMIX. Mais les tests doivent être reproductibles, il faut donc un moyen de caractériser un IMIX, d'indiquer sa composition (autrement que par un vague « on a utilisé un IMIX »). C'est le but du mini-langage présenté dans ce RFC.
En gros, les petits paquets vont tester la capacité du réseau à traiter les en-têtes et les gros vont tester sa capacité à faire circuler des bits. On a donc besoin des deux dans un test. L'IMIX genome est la description, dans un langage formel, de la répartition des tailles de paquets. (Comme un génome décrit une espèce.)
Donc, à quoi ressemble un IMIX (section 3 du RFC) ? À une série de
lettres dont chacune code une taille de paquet donnée, en utilisant
les tailles « standard » du RFC 2544. Ainsi,
avec la table a = 64 octets, b = 128, c = 256, d = 512, e = 1 024, f =
1 280 et g = 1518, l'IMIX aaafg
désigne une
séquence de cinq paquets, les trois premiers faisant 64 octets, le
quatrième 1 280 et le dernier ayant la taille maximale sur
Ethernet. Une lettre z est utilisée pour dire
« la MTU du lien », donc, ici, on aurait pu
utiliser aaafz
. Notez bien qu'avec cette notation, les autres tailles
ne peuvent pas être représentées (il faut choisir la taille la plus
proche) et qu'un test avec des milliers de paquets est décrit par un
IMIX assez illisible...
Si on tient à utiliser des tailles non prévues par le RFC 2544, la section 4 prévoit un moyen de définir
localement des lettres, notées en majuscule. Avec la table locale A =
98, B = 1 020, l'IMIX BBAA
indiquera deux gros
paquets puis deux petits.
Ce système manque clairement de souplesse : et si, pour un test long, une séquence de
base est répétée ? Ou bien si les tailles sont
choisies par un processus pseudo-aléatoire ? La
section 5 décrit deux fonctions utiles du mini-langage de description
des génomes IMIX. Pour les séquences répétées, on se sert simplement
d'un encodage en RLE. Le RFC ne propose pas de
syntaxe concrète pour le décrire, l'exemple est juste un tableau « 20
fois abcd
puis 5 fois ggga
et enfin 10 fois dcba
». Le RFC propose également
un autre mécanisme (à nouveau sans syntaxe précise), en indiquant les
pourcentages de chaque taille (sans spécifier la séquence) : « 23 % de
64 octets, 67 % de 128 et 10 % de 1 000 ».
Le RFC prévoit aussi le cas où les tailles sont générées par un algorithme. Dans ce cas, pas de langage particulier, il faut le décrire en langage naturel lorsqu'on publie les résultats de la mesure (« on part de paquets de 64 octets et on incrémente leur taille de 1 à chaque paquet, s'arrêtant à la MTU »). Idem si l'algorithme utilisé est un générateur pseudo-aléatoire, qui doit également être décrit (avec la graine utilisée).
Si vous voulez lire des articles sur les IMIX, voir « "Test Methodology Journal: IMIX (Internet Mix) », « Library: Test Plans » ou « The Journal of Internet Test Methodologies ». Pour une discussion sur la normalisation d'IMIX (et pas du langage qui les décrit), voir une discussion terminologique dans le groupe de travail.
Date de publication du RFC : Août 2013
Auteur(s) du RFC : W. Wang (Zhejiang Gongshang University), K. Ogawa (NTT Corporation), E.H. Haleplidis (University of Patras), M. Gao (Hangzhou BAUD Networks), J. Hadi Salim (Mojatatu Networks)
Pour information
Réalisé dans le cadre du groupe de travail IETF forces
Première rédaction de cet article le 25 août 2013
Un élément essentiel de la culture IETF est l'importance donnée aux programmes qui marchent : rough consensus and running code. D'où les fréquents tests d'interopérabilité, entre diverses mises en œuvre des protocoles IETF, afin de vérifier que, non seulement le code tourne mais qu'il peut interagir avec d'autres instances. Le groupe de travail ForCES, qui normalise des protocoles de communication internes aux routeurs, a ainsi procédé à deux ateliers de tests d'interopérabilité, ce RFC documentant le second.
Le premier avait eu lieu en 2009 à l'université de Patras et avait été documenté dans le RFC 6053. Le second a eu lieu en février 2011 à l'ITL (Internet Technology Lab) à l'université de Zhejiang Gongshang. (Oui, je sais, c'est long, entre l'atelier et la publication du compte-rendu dans un RFC...)
Rappelons ce que fait ForCES : il normalise la communication entre les éléments d'un routeur (ou autre engin du réseau : la norme parle de NE pour Network Element). Le but est de permettra la construction de routeurs en kit, en assemblant des parties d'origines différentes, mais parlant toutes ForCES. Le système ForCES est riche et complexe et cet atelier d'interopérabilité testait cinq composants : le protocole de communication entre CE (Control Element) et FE (Forwarding Element), normalisé dans le RFC 5810, le protocole de transport sous-jacent (RFC 5811), le modèle des FE (RFC 5812), la bibliothèque standard (RFC 6956) et le mécanisme de haute disponibilité (dont le RFC n'a pas encore été publié). Des CE et FE d'origines diverses ont été connectés entre eux, se sont parlé, la bonne compréhension a été vérifiée et tcpdump et Wireshark ont été utilisés pour un contrôle supplémentaire.
Trois mises en œuvre de ForCES ont été testées, les mêmes qu'à l'atelier précédent (ForCES n'a pas pour l'instant suscité un intérêt massif) : celle de NTT, celle de l'université de Patras, et celle faite en commun entre l'université de Zhejiang Gongshang et la société BAUD Network. Les Grecs n'ayant pu se déplacer, ils ont participé aux tests à distance, connectés via un VPN (dans la réalité, bien sûr, les FE et les CE seront toujours proches, souvent dans le même boîtier physique). Globalement, les tests ont été des succès, à part un problème embêtant avec l'encapsulation des données dans une réponse ForCES (voir les détails plus loin). Comme toujours, ces tests ont permis de découvrir des erreurs ou des approximations dans les RFC.
Les communications utilisaient IPsec, puisque le RFC sur le transport de ForCES, RFC 5811, fait obligation à chaque mise en œuvre de ForCES d'avoir IPsec (mais pas forcément de l'activer par défaut : c'est sa disponibilité qui est obligatoire, pas son usage).
Un exemple d'un des scénarios testés (section 3.4) : deux machines terminales sur deux réseaux locaux différents étaient connectées via deux routeurs OSPF. L'un était un routeur classique, l'autre une machine ForCES dont le CE (Control Element) parlait OSPF avec le routeur classique pendant que le FE (Forwarding Element) transmettait les paquets. Ce scénario nécessitait que le CE communique au FE les règles qu'il avait apprises en OSPF et testait la mise en œuvre correcte de plusieurs fonctions du RFC 6956. Une variante de ce test remplaçait le routeur classique par une autre machine ForCES : les deux CE se parlaient en OSPF et chacun disait ensuite à son FE ce qu'il devait faire des paquets IP.
La section 4 donne les résultats complets des tests. Il y a une très grande majorité de succès mais aussi deux échecs, qui vont nécessiter du travail chez les programmeurs.
Mais le principal problème de l'atelier a été un problème lors de la communication de tableaux (et pas de simples valeurs scalaires) entre deux programmes. Le problème est que ForCES permet plusieurs encodages possibles pour les données complexes (RFC 5810, section 6 et notamment 6.4). La règle est que chaque élément ForCES peut choisir librement parmi ces encodages (pas moins de trois possibilités légales, dans l'exemple discuté dans la section 5 de notre RFC). Mais un programme considérait que la réponse venait forcément dans l'encodage de la question, et plantait si ce n'était pas le cas. Bien qu'il soit clairement en tort, notre RFC considère qu'il vaut mieux en effet générer une réponse en utilisant le même encodage que la question ou la commande. Personnellement, je pense plutôt que c'était très gentil de donner un vaste choix aux CE et FE (par exemple pour optimiser le cas de grands tableaux ayant beaucoup de vide) mais que cela mène forcément à ce genre de problèmes. Traditionnellement, les protocoles IETF préfèrent l'interopérabilité à la liberté et ForCES était peut-être allé trop loin dans les possibilités de choix.
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : Y. Sheffer (Porticor), A. Farrel (Juniper)
Expérimental
Première rédaction de cet article le 18 juillet 2013
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 complètement facultative. Ce nouveau RFC propose de formaliser et d'encourager cette mention. Il a depuis été remplacé par le RFC 7942.
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. L'expérimentation décrite dans ce nouveau RFC 6982 ne vise que les Internet-Drafts, afin d'aider à l'évaluation d'une proposition.
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.
Notre tout nouveau RFC 6982 est purement expérimental : il ne propose pas de définir une nouvelle règle, juste de formaliser une section dans les Internet-Drafts, facultative, 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), 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 nouvelle section, « Implementation status » est décrite en section 2 de ce RFC. Elle sera située vers la fin (comme l'actuelle - et obligatoire, elle - « Security considerations ») et pourra 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 à inclure au debut 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 programeurs). Dans tous ces cas, il est bon d'indiquer l'URL du Wiki en question dans l'Internet-Draft.
Le RFC se donnait 18 mois pour l'évaluation de l'expérience, ce qui est la durée typique de production d'un RFC). Cette expérimentation est alors devenue la politique officielle de l'IETF (RFC 7942). On a évalué si cette section a été utilisée (par exemple pour trouver du code qu'on va ensuite tester) et si les décisions prises ont effectivement été meilleures. Curieusement, alors que cette nouvelle section n'est nullement obligatoire, ce RFC 6982 ne propose pas parmi les critères de succès de voir tout simplement combien d'auteurs d'Internet-Drafts ont inclus une telle section. Il faut dire qu'un certain nombre le font déjà de façon informelle.
Quelques exemples d'Internet-Drafts qui incluent
actuellement cette section : draft-clausen-lln-loadng
, draft-wilde-xml-patch
ou draft-ietf-mpls-multipath-use
.
Date de publication du RFC : Août 2013
Auteur(s) du RFC : F. Gont (SI6 Networks / UTN-FRH)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 26 août 2013
Ce court RFC traite un problème de sécurité lorsqu'on combine la fragmentation avec le protocole NDP d'IPv6. Il interdit désormais cette combinaison, qui pouvait être exploitée pour des attaques sur le réseau local.
NDP est normalisé dans le RFC 4861 (que ce RFC 6980 met à jour). Ce protocole est utilisé pour bien des choses, notamment pour résoudre une adresse IPv6 en adresse MAC et pour découvrir les routeurs du réseau local, ainsi que les préfixes des adresses IP de ce réseau (pour l'auto-configuration). Ses faiblesses de sécurité (très proches de celles d'ARP en IPv4) sont bien connues (RFC 3756). Notamment, n'importe quelle machine peut émettre des paquets NDP et répondre aux questions adressées à une autre machine. Ou bien l'attaquant peut se faire passer pour le routeur et émettre des « RAcailles », ces faux paquets RA (Router Advertisment).
Il existe plusieurs moyens de gérer ces dangers. On peut mettre des ACL statiques dans les commutateurs, n'autorisant les RA que sur le port où se trouve le routeur. Ou bien on peut utiliser la solution un peu plus sophistiquée du RA guard (RFC 6105). On peut aussi surveiller le trafic, avec un IPS ou bien un logiciel comme NDPmon ou ramond, et lever une alarme lorsque quelque chose d'anormal se produit. Mais toutes ces techniques ont un défaut commun : elles reposent sur une analyse du paquet pour détecter si c'était du NDP et il est trop facile de les tromper en fragmentant le paquet. S'il est en deux parties, avec les informations permettant de reconnaître et d'analyser le NDP dans le deuxième paquet, aucun des systèmes existants ne voit ce qui se passe, alors que la machine terminale réassemblera le paquet et se fera donc avoir. À l'heure actuelle, la totalité des mises en œuvre de RA guard est ainsi vulnérable (cf. RFC 7113). Bien sûr, des outils comme les IPS pourraient réassembler les paquets eux-aussi, pour voir le paquet original, mais c'est plus difficile pour les commutateurs Ethernet. Et cela leur fait courir un risque (si l'attaquant génère des quantités de fragments afin d'épuiser la mémoire des réassembleurs, pour faire une attaque par déni de service).
C'est d'autant plus balot que les vrais paquets NDP sont rarement assez grands pour avoir réellement besoin de la fragmentation (section 2). Même si un routeur a besoin d'annoncer de nombreux préfixes dans ses RA, il peut le faire en plusieurs datagrammes IP, il n'est pas nécessaire de tout mettre dans un seul grand datagramme fragmenté. Bref, la fragmentation est quasi-inutile pour NDP alors qu'elle est dangereuse. (Une exception partielle est décrite en section 3, pour SEND, dans le RFC 3971, dans le cas où il y a des gros certificats à transmettre. Je ne la mentionne pas davantage puisque SEND n'est quasiment jamais utilisé. Il résout radicalement presque tous les problèmes de sécurité de NDP mais le manque de mises en œuvre de ce protocole, et la difficulté qu'il y a à distribuer les clés cryptographiques nécessaires font qu'en pratique, SEND n'est pas une approche envisageable. Voir la conférence de l'auteur à DEEPSEC.)
La section 4 résume les raisons d'abandonner la fragmentation pour NDP :
Donc, la section 5 du RFC expose la nouvelle règle, qui met à jour le RFC 4861 : une machine qui émet des paquets NDP ne doit pas fragmenter ces paquets. (Une exception partielle est faite pour les messages Certification Path Advertisement utilisés par SEND. Mais, pour tous les messages habituels, la règle est l'interdiction de la fragmentation.) À la réception, les paquets NDP fragmentés doivent être ignorés.
Si vous voulez créer vous-même de tels paquets NDP fragmentés (qui
seront ignorés par les systèmes modernes, vous pouvez utiliser la
boîte à outils SI6 présenté dans mon article
sur le hacking IPv6, avec l'option -y
. Par exemple :
# ./ra6 -y 8 -i eth1 -d 2001:db8:8bd9:8bb0:ba27:ebff:feba:9094
va générer deux fragments, huit octets n'étant pas assez pour mettre le RA. tcpdump les voit ainsi :
08:34:29.122863 IP6 fe80::8609:88f4:14:a635 > 2001:db8:8bd9:8bb0:ba27:ebff:feba:9094: frag (0|8) ICMP6, router advertisement, length 8 08:34:29.122883 IP6 fe80::8609:88f4:14:a635 > 2001:db8:8bd9:8bb0:ba27:ebff:feba:9094: frag (8|8)
Notez que tcpdump ne s'est pas laissé avoir : il a bien identifié le premier fragment comme appartenant à un RA.
Date de publication du RFC : Août 2013
Auteur(s) du RFC : T. Pornin
Pour information
Première rédaction de cet article le 24 août 2013
Les algorithmes de signature DSA et ECDSA ont une particularité qui est souvent oubliée : chaque signature doit utiliser un nombre imprévisible. On peut, par exemple, générer ce nombre par un processus aléatoire. Mais tous les systèmes qui voudraient utiliser DSA ou ECDSA n'ont pas forcément un tel générateur aléatoire. Ce RFC propose une autre méthode : fabriquer ce nombre par dérivation déterministe d'un certain nombre de paramètres, produisant le même effet, sans pour autant nécessiter de source d'aléa.
Ces deux algorithmes sont très utilisés dans le monde. (À noter qu'ECDSA repose sur les courbes elliptiques, décrites dans le RFC 6090.) Mais cette nécessité de générer un nombre unique et imprévisible par signature n'a pas d'équivalent avec des algorithmes comme RSA. Le pourquoi de cette nécessité est bien expliqué dans un article de Nate Lawson. Si vous l'oubliez, vous serez piraté, comme Sony l'a été. Mais que ce nombre soit aléatoire n'est pas strictement nécessaire. En fait, l'aléatoire a deux défauts :
L'algorithme permettant de générer un nombre unique et imprévisible, mais sans générateur aléatoire, est décrit dans les sections 2 et 3 de notre RFC (il est fondé sur l'idée de derandomization, décrite dans « How Risky is the Random-Oracle Model? »). Je ne vais pas résumer cet algorithme ici (la cryptographie, c'est trop fort pour moi) mais ses propriétés importantes sont :
L'annexe A contient un exemple détaillé de calcul du nombre unique pour une signature.
Si vous envisagez de programmer cet algorithme de génération déterministe de signature, faites bien attention à la section 4, qui résume les problèmes de sécurité. Par exemple, comme rappelé plus haut, la procédure de ce RFC ne s'applique pas aux clés qui doivent, comme avant, être générées aléatoirement. Pour des engins sans générateur aléatoire, comme les carte à puce de bas et de milieu de gamme, cela peut par exemple être fait à l'usine, pendant la fabrication de l'engin.
D'autre part, comme la génération de la signature est déterministe, le même messsage aura donc toujours la même signature (tant qu'on garde la même clé privée, bien sûr). Cela n'est pas un problème dans certaines applications (RSA, tel que décrit dans le RFC 3447, fait pareil). Ainsi, TLS (RFC 5246), SSH (RFC 4251) ou CMS (RFC 5652) peuvent utiliser cet algorithme déterministe sans risque pour leur sécurité.
À noter que, de manière surprenante pour un RFC, la section 5 est consacrée aux risque de brevets sur cet algorithme (apparemment assez faibles). C'est surprenant car, comme la situation change tout le temps (nouveaux brevets, brevets reconnus comme futiles, etc), cette information est normalement distribuée en ligne et pas mise dans un RFC stable (c'est expliqué dans le RFC 8179). Les brevets actuellement connus pour ce RFC sont sur le site Web de l'IETF.
L'annexe B contient une mise en œuvre, en
Java, de cet algorithme (copiée ici dans le
fichier DeterministicDSA.java
). On peut l'utiliser, par
exemple, ainsi :
import java.math.BigInteger; import org.ietf.DeterministicDSA; public class TestDeterministicDSA { // http://stackoverflow.com/questions/5470219/java-get-md5-string-from-message-digest private static String binary2string(byte []bin) { StringBuilder binString = new StringBuilder(); for (int i = 0; i < bin.length; i++) { String hex = Integer.toHexString(bin[i]); if (hex.length() == 1) { binString.append('0'); binString.append(hex.charAt(hex.length() - 1)); } else binString.append(hex.substring(hex.length() - 2)); } return binString.toString(); } public static void main (String args[]) { int i; DeterministicDSA dsa = new DeterministicDSA("SHA-256"); String signature; // We use the private key for the appendix A.2.1 of the RFC BigInteger p = new BigInteger("86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED8873ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779", 16); BigInteger q = new BigInteger("996F967F6C8E388D9E28D01E205FBA957A5698B1", 16); BigInteger g = new BigInteger("07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA417BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD", 16); BigInteger x = new BigInteger("411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", 16); dsa.setPrivateKey(p, q, g, x); for (i=0; i<args.length; i++) { dsa.update(args[i].getBytes()); signature = binary2string(dsa.sign()); System.out.println(args[i] + " -> " + signature); dsa.reset(); } } }
Et on retrouve les valeurs indiquées dans le RFC (ce qui est logique pour un processus déterministe...) :
% java TestDeterministicDSA sample test sample -> 302d02150081f2f5850be5bc123c43f71a3033e9384611c54502144cdd914b65eb6c66a8aaad27299bee6b035f5e89 test -> 302c021422518c127299b0f6fdc9872b282b9e70d079081202146837ec18f150d55de95b5e29be7af5d01e4fe160
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : J. Touch (USC/ISI)
Expérimental
Première rédaction de cet article le 20 juillet 2013
Le protocole d'authentification des paquets TCP AO (Authentication Option), normalisé dans le RFC 5925, a une limite : il ne fonctionne pas du tout lorsque la session est établie à travers au moins un routeur NAT. Ce nouveau RFC propose une extension qui lui permet d'authentifier quand même les paquets dans ce cas, au prix d'une légère baisse de la sécurité.
En effet, l'authentification AO range et génère ses clés en tenant compte d'un ensemble de paramètres de la session (RFC 5925, sections 3.1 et 3.2), parmi lesquels se trouvent les adresses IP de source et de destination, ainsi que les ports de source et de destination. Un routeur NAT modifie en général l'adresse IP source et les routeurs existants (qui font souvent du NAPT et pas du NAT à proprement parler, cf. RFC 2663) modifie également le port source. AO ne retrouve donc plus ses clés (RFC 5925, section 9.2). Ce n'était pas un gros problème pour le premier client d'AO, le protocole BGP : on met rarement des routeurs BGP derrière du NAT. Mais cette limite est gênante pour généraliser AO à d'autres utilisations, sans compter les futures améliorations de TCP, par exemple le multipath du RFC 6824, où la même connexion TCP utilise plusieurs adresses IP.
Donc, la nouvelle option se nomme TCP-AO-NAT et consiste (section 4
de notre RFC) à ajouter au MKT (Master Key Tuple,
cf. RFC 5925, section 3.1) deux booléens,
localNAT
et remoteNAT
indiquant si un routeur NAT est présent en local ou en distant. Si
localNAT
est vrai, AO va mettre à zéro l'adresse
IP source et le port source avant de calculer les clés. Si c'est
remoteNAT
qui est vrai, ce sera l'adresse et le
port de
destination qu'on ignorera.
Le MKT n'est pas transmis à la machine distante (et n'apparait
donc pas dans l'option TCP AO), il est typiquement configuré à la main
des deux côtés. La valeur à donner à localNAT
et
remoteNAT
est déterminée manuellement, mais elle
peut aussi être découverte par les méthodes habituelles de détection
de NAT. Le client situé immédiatement derrière un routeur NAT (par
exemple la machine de M. Michu à la maison) va mettre
localNAT
à 1. Le serveur en face va mettre
remoteNAT
à 1. Si les deux partenaires sont
derrière un NAT (et utilisent une technique comme celle du RFC 8489), les deux booléens peuvent être à 1.
Notez bien qu'AO ne protège que TCP et ne tient pas compte du contenu des paquets. Si un ALG sur le trajet modifie les adresses contenues, mettons, dans une connexion FTP, TCP-AO-NAT n'y pourra rien.
Attention, rappele la section 6 : TCP-AO-NAT revient à ignorer
certaines valeurs qui identifient la connexion et donc à diminuer
l'entropie. Si localNAT
est vrai, on passe d'une
source de hasard pour la KDF qui est composée de deux adresses IP, deux ports et
deux ISN (l'Initial Sequence Number de TCP) à une seule adresse, un seul port et les deux ISN. Si les deux booléens localNAT
et
remoteNAT
sont vrais, il ne reste plus que les
deux ISN comme source d'entropie. Bref, l'extension normalisée dans ce
RFC diminue la sécurité. Toutefois, comme les
ports ne sont pas toujours très aléatoires (malgré le RFC 6056) et les adresses encore moins, l'essentiel de
l'entropie venait des deux ISN, de toute façon.
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : S. Crocker (Shinkuro Inc.), S. Rose (NIST)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 4 juillet 2013
Le système d'authentification du DNS DNSSEC repose sur la signature cryptographique des enregistrements DNS. Cette signature peut se faire par des algorithmes différents. Comment savoir si tel algorithme, récemment spécifié, est désormais d'un usage fréquent ou pas chez les résolveurs validants ? Ce nouveau RFC propose que le résolveur indique, dans sa requête DNS, la liste des algorithmes qu'il comprend. Cela permettra, dans le futur, de mesurer objectivement l'état du déploiement de tel ou tel algorithme.
L'algorithme utilisé dans une signature DNSSEC apparait dans
l'enregistrement RRSIG
sous forme d'un octet dont
la signification est stockée dans un registre
IANA. Ainsi, dans cette signature de
.fr
:
% dig +dnssec SOA fr. ... ;; ANSWER SECTION: fr. 172800 IN SOA nsmaster.nic.fr. hostmaster.nic.fr. 2222283656 3600 1800 3600000 5400 fr. 172800 IN RRSIG SOA 8 1 172800 20130814151003 20130615141003 62646 fr. FSSGO0iZ6OBoSUE12Q/NYOU2f3AMNbOf/b4FoC48F8f5gDfSNpJStZF7 zGsN51+zFE3FCucNDw4cQMY8YqBeu6BN5IG4StqAjEp+3FqLYSzyUu4s tZY8GnLa9ZzJCTf6dGT0CE2JbEzc705hc6X6I7DDxqwrzzpj23F/Rg9 PEk= ...
La signature est faite avec l'algorithme 8,
RSA + SHA-256. Dans le cas de
ecdsa.isc.org
:
% dig +dnssec SOA ecdsa.isc.org ... ;; ANSWER SECTION: ecdsa.isc.org. 3600 IN SOA ns-int.isc.org. hostmaster.isc.org. 2013052903 7200 3600 604800 3600 ecdsa.isc.org. 3600 IN RRSIG SOA 14 3 3600 20130712033157 20130612023157 30631 ecdsa.isc.org. o+Q1WDDeiCM3z2b793Ni/FtMT223gJ/1Lr+RWOgPJLVxB+AlLKyKvLOs vWRBqUjwYeKE4Dx/ZUSIx8eVzOUt5g6HvBuGaYX/camsYn9ocuTp6J+w J2Fn69Qi6/WbhAa4 ...
Elle est fait avec 14, ECDSA avec SHA-384. On trouve également des numéros identifiant un algorithme, celui de condensation cryptographique, dans les enregistrements DS et un autre dans NSEC3 (les valeurs possibles étant dans un autre registre IANA).
Actuellement, les serveurs faisant autorité pour une zone ne savent
pas quels algorithmes sont compris par les résolveurs qui les
interrogent. Le serveur qui fait autorité envoie toutes les signatures
qu'il connait et le résolveur se débrouille. Reprenons le cas de
.fr
, signé avec
RSA. Pourrait-on passer à
ECDSA, normalisé dans le RFC 6605, et qui a l'avantage de fournir des clés et des
signatures plus courtes ? Le problème est qu'ECDSA dans DNSSEC est
très récent et qu'on pense que peu de résolveurs sont capables de
valider avec ECDSA. Mais quel pourcentage exactement ? Et, avec le
temps, ce pourcentage augmentera. Comment saura-t-on qu'on est arrivé
au point où la grande majorité des résolveurs parlent ECDSA ? Si ce
nouveau RFC 6975 est déployé, il fournira un moyen de
répondre à ces questions.
Le principe est d'utiliser trois nouvelles options
EDNS pour signaler les algorithmes connus. Le
résolveur mettra ces options dans la requête et le serveur faisant
autorité pourra les examiner pour connaître les capacités de ses
clients (notez bien que c'est uniquement à des fins d'information : le
serveur ne doit pas modifier sa réponse en
fonction de ces options). EDNS est normalisé dans le RFC 6891 et l'enregistrement OPT
qu'il
ajoute contient zéro, une ou plusieurs options (la liste des options
possibles est dans un registre IANA). Les
trois options ajoutées sont (section 2 de notre RFC) :
L'encodage d'une option EDNS se fait en trois champs, le code sur deux octets (5, 6 ou 7 ici), la longueur des données sur deux octets et les données. Ici, les données consistent en une liste d'algorithmes, un octet pour chacun, dans un ordre quelconque (l'ordre n'exprime pas une préférence). Par exemple, un résolveur validant qui accepte RSA-SHA1, RSA-SHA256 et ECDSA-SHA384 encodera un DAU avec les octets {5, 0, 3, 5, 8, 14}. En pratique, le RFC estime que les trois options toutes ensemble devraient prendre de 22 à 32 octets (en comptant 6 à 10 algorithmes de signature, plus quelques uns pour la condensation).
Bon, et une fois le format défini, on s'en sert comment ? Pour les clients (les résolveurs), c'est en sections 3 et 4 du RFC. Si le client valide, il ajoute une, deux ou trois des nouvelles options dans sa requête. Sinon, il ne doit pas les utiliser.
Si le résolveur valide et qu'il reçoit une requête ayant déjà une de ces options, il doit ajouter ses propres algorithmes. La liste finale sera donc l'union des deux. Un simple relais (forwarder) qui ne valide pas mais qui reçoit une requête ayant une de ces options, doit passer l'option telle quelle car ce qui compte, ce sont les capacités du résolveur qui fera la validation DNSSEC.
Et le serveur faisant autorité ? C'est en section 5. Le point important est qu'il ne doit rien faire. Il suit le même algorithme que d'habitude et, par exemple, il envoie les mêmes signatures quels que soient les algorithmes compris par l'émetteur. Les trois nouvelles options sont là pour information uniquement. D'autres part, les trois options DAU, DHU et N3U sont uniquement dans les requêtes. Le serveur faisant autorité n'en met pas dans les réponses.
Revenons aux administrateurs d'une zone qui voudraient mesurer le déploiement d'un nouvel algorithme cryptographique. Que faire si les clients n'envoient pas cette option ? La section 6 conseille de les considérer comme du vieux logiciel, n'ayant pas les nouvelles options, ni les nouveaux algorithmes. C'est un peu court, à mon avis, car on peut aussi imaginer qu'il y aura des résolveurs récents qui n'enverront pas cette option, peut-être par souci de discrétion (ce point est également couvert dans la section 7, consacrée aux risques de sécurité).
Il ne semble pas exister beaucoup de mises en œuvre de ce RFC. Par exemple, Wireshark, au moment de la publication du RFC, ne savait pas décoder ces options et affichait juste :
Additional records <Root>: type OPT Name: <Root> Type: OPT (EDNS0 option) UDP payload size: 1200 Higher bits in extended RCODE: 0x0 EDNS0 version: 0 Z: 0x0 Data length: 8 Data
Depuis r50840, Wireshark a le code nécessaire et on n'a plus qu'à patienter que cela arrive dans une version officielle.
L'examen des requêtes envoyées à un gros serveur de noms ne montrait, au moment de la sortie du RFC, pratiquement pas d'utilisation de cette option.
Trois ans après la publication du RFC, une discussion lors d'une réunion OARC semblait indiquer qu'il n'avait connu aucun déploiement et devait être considéré comme un échec. Mais en juin 2020, OpenDNS l'a activé sur ses serveurs.
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : A. Cooper (CDT), H. Tschofenig (Nokia
Siemens Networks), B. Aboba (Microsoft
Corporation), J. Peterson
(NeuStar), J. Morris, M. Hansen (ULD
Kiel), R. Smith (Janet)
Pour information
Première rédaction de cet article le 25 juillet 2013
La question de la vie privée est désormais une question de première importance sur l'Internet. La sortie de ce RFC en plein scandale PRISM est une coïncidence mais elle tombe bien. Pendant longtemps, la vie privée avait pourtant été plutôt négligée par les ingénieurs et cette négligence se retrouvait dans les normes techniques, par exemple les RFC, qui ne contenaient pas grand'chose sur la question. Désormais, l'importance du problème est reconnue à l'IETF et ce nouveau RFC vise à expliquer à tous les auteurs de RFC ce qu'il faut connaître de la vie privée et de sa protection, lorsqu'on conçoit un protocole réseau.
Ce n'est donc pas un texte général sur la vie privée (il en existe déjà beaucoup) même s'il explique les principes de base (le membre typique de l'IETF peut être très ignorant à ce sujet). Son objectif est de faire en sorte que les protocoles de la famille TCP/IP prennent en compte les problèmes de vie privée dès leur conception. Cela a été un long chemin. Peu de RFC traitaient explicitement cet aspect (une exception intéressante est le RFC 8981). Mais, petit à petit, entre autre grâce au travail d'Alissa Cooper, une des auteures de ce document, l'IETF est passé de « bof, c'est de la politique, ça ne nous concerne pas, et d'ailleurs la technique est neutre » à un atelier sur la protection de la vie privée (le compte-rendu figure dans le RFC 6462) puis à ce RFC 6973 qui dit en substance que tout nouveau protocole de la famille TCP/IP devrait avoir, lors de sa conception, une réflexion sur les risques qu'il pose pour la vie privée et les moyens de les limiter. S'il reste encore à l'IETF quelques partisans du « on s'en fiche, que toutes les données soient accessibles et que tout le monde soit à poil », ils se font nettement moins entendre désormais. Sans aller jusqu'à imposer une section Privacy considerations dans chaque RFC (sur le modèle de l'obligatoire section Security considerations, cf. RFC 3552), ce RFC l'encourage et aide à sa rédaction.
Le problème n'est pas trivial : la vie privée est quelque chose de complexe. Et tout le monde n'a pas la même opinion sur l'importance de son respect. Sans compter que le cadre légal est très différent d'un pays à l'autre, alors que les RFC sont censés avoir une portée mondiale. Si certains RFC ne semblent pas poser de problème de vie privée (notre RFC cite le RFC 6716...) d'autres sont ou seront entièrement consacrés à ce sujet (RFC 3325) et d'autres nécessiteront un paragraphe ou une section dédiée.
La section 2 détaille les responsabilités des concepteurs de protocoles Internet. Ces protocoles sont souvent utilisés dans une grande variété de cas, parfois non prévus lors de leur conception originelle. Bref, on ne peut pas demander au rédacteur du RFC sur un nouveau protocole de prévoir tous les usages et il y a donc des limites à l'analyse qu'il peut faire sur les conséquences de « son » protocole sur la vie privée. D'autre part, une grande partie, peut-être la majorité des problèmes de vie privée, prennent naissance dans un comportement de l'utilisateur, mal ou peu guidé par des mauvaises interfaces utilisateur. La conception de ces interfaces est typiquement hors-sujet pour l'IETF, qui ne se préoccupe que de protocoles.
Un bon exemple est fourni par HTTP (RFC 7230). Quand on voit la variété des usages de HTTP aujourd'hui, de l'accès à des pages Web statiques à l'échange de données médicales, on se dit qu'une analyse des risques qu'il pose pour la vie privée, faite à l'époque de son développement, aurait été bien limitée.
Le RFC commence vraiment avec la section 3, sur la terminologie. Section bien nécessaire pour ce sujet, où le vocabulaire utilisé est souvent trop flou. Un RFC précédent sur la terminologie de la sécurité avait été le RFC 4949 mais il parlait peu de vie privée. Donc, quelques termes nouveaux (d'autres sont dans le RFC) :
canari95
). Notez aussi que l'anonymat n'est pas
uniquement le fait de garder son nom officiel secret. Cela peut être
aussi de vouloir empêcher le rapprochement de deux de ses identités.Par exemple, avec IP, le routeur est un intermédiaire, et peut être un observateur (s'il est équipé pour cela, disons que si le routeur est une machine Unix, il devient un observateur dès qu'il lance tcpdump). Quelqu'un qui s'est branché sur le câble sans autorisation est un écoutant.
À noter que l'analyse de sécurité du RFC 3552 supposait que les deux extrémités de la communication étaient sûres et que seuls les intermédiaires représentaient un danger. En matière de vie privée, ce n'est évidemment pas le cas (section 4 de notre RFC). Comme l'a montré l'affaire PRISM, ou comme le montrent les pratiques des gros silos commerciaux du Web 2.0 comme Facebook, le danger est souvent chez l'une des parties en train de communiquer, pas chez un tiers...
Et quelles sont exactement les menaces qui pèsent sur la vie privée ? La section 5 les détaille, suivant en partie le livre de Solove et la recommandation du Conseil de l'Europe. D'abord, leurs conséquences. Les atteintes à la vie privée peuvent provoquer de la gêne mais aussi une perte de dignité, ou des pertes financières. Dans des cas extrêmes (violence conjugale, par exemple), ces atteintes peuvent mettre la vie des victimes en danger. D'autre part, même s'il n'y a pas eu accès à des informations privées, le seul fait d'être sous surveillance peut mettre très mal à l'aise, voir créer un sentiment d'angoisse. Il peut aussi entraîner un changement de comportement (on hésitera à commettre un acte légal, de peur des conséquences s'il était révélé) pouvant aller jusqu'à l'auto-censure. La vie privée est donc une affaire sérieuse, pas un simple détail.
Première attaque contre la vie privée envisagée, la surveillance des communications. Le RFC rappelle qu'elle n'est pas limitée au cas où l'attaquant a accès au contenu des communications. La seule analyse de trafic peut déjà en révéler beaucoup. Le chiffrement n'est pas une protection parfaite : le type de trafic reste visible, via des indicateurs comme la taille des paquets ou leur fréquence. Pour déjouer sérieusement la surveillance, il faudrait des protocoles avec des tailles de paquets variables, n'ayant pas de chaîne de bits prévisibles à un endroit fixe dans le paquet, etc. Pour sérieusement gêner l'analyse de trafic, il faut des systèmes comme Tor. Parmi les entitées présentées plus haut, aussi bien les écoutants que les observateurs peuvent avoir une activité de surveillance.
Une fois les messages arrivés à bon port, tout n'est pas terminé. Les données stockées à destination peuvent faire l'objet d'une compromission, si le serveur qui les stocke n'est pas suffisamment protégé et peut être piraté. Sans compter le cas, traité plus loin, où le serveur de destination est lui-même un attaquant. Ceci dit, ces problèmes ne sont pas du ressort de l'IETF qui s'occupe normalement uniquement des réseaux.
Les risques ci-dessus sont une combinaison de risques pour la vie privée avec les risques plus généraux de sécurité. Mais il y a aussi des risques très spécifiques à la question de la vie privée. Par exemple, la corrélation, qui permet d'acquérir des informations normalement privées en reliant des données qui, séparément, semblaient inoffensives. Par exemple, si des identificateurs stables sont utilisés, les protocoles réseaux facilitent la corrélation. Une adresse IP stable sur le long terme présente un certain nombre d'avantages techniques mais est aussi un danger pour la vie privée (cf. RFC 8981). Autre exemple, le protocole TLS permet de reprendre une session cryptographique existante, pour gagner du temps et éviter de recommencer la négociation de tous les paramètres (cela peut se faire côté serveur, RFC 5246 ou côté client, RFC 5077). Mais comme cette reprise de session se fait avant la négociation de ces paramètres de cryptographie, elle a lieu en clair. Un écoutant peut donc voir que le second client TLS qu'il écoute est en fait le même que le premier, s'il utilise cette fonction.
Autre attaque contre la vie privée, celle passant par
l'identification. Savoir que la machine
192.0.2.67
accède au site Web du gouvernement,
c'est une chose. Pouvoir accéder à des informations sur la personne
qui utilise cette machine, c'est bien mieux, pour l'attaquant. Cela
peut se faire facilement avec les protocoles qui identifient une
personne (une adresse SIP ou
XMPP par exemple) mais aussi de manière
indirecte même si le protocole permet l'anonymat. Prenons par exemple un site Web qui n'identifie pas ses
utilisateurs. Aucun risque qu'un attaquant qui l'observe retrouve qui
a accédé à la page /page-sensible.html
, non ?
Sauf que, si le même attaquant peut écouter le trafic d'un autre site
Web qui authentifie ses utilisateurs, il peut faire une corrélation
(via, par exemple, le champ User-Agent:
) et ainsi
identifier l'utilisateur.
Dans beaucoup de cas, l'utilisateur sait qu'on récolte des données personnelles sur lui. Si je me crée un compte sur amazon.com, il est clair qu'Amazon va savoir des choses sur moi, par exemple mon adresse postale pour me livrer les produits achetés. Il peut aussi y avoir des usages secondaires, des cas où le détenteur des données s'en sert pour autre chose que ce qu'il a annoncé. L'usage secondaire est techniquement indétectable et, comme cela se passe en dehors de la communication standardisée par l'IETF, notre RFC estime que ce problème, si grave qu'il soit en pratique, n'est pas de la responsabilité de l'IETF.
Encore plus sérieux, la révélation de données à des tiers. Comme il est trivial de copier des données numériques, il est techniquement impossible de savoir si les données personnelles qu'on a accepté de confier à l'entreprise X ne vont pas être copiées chez son partenaire Y. Là encore, c'est en dehors de la sphère IETF mais c'est quand même une des menaces les plus sérieuses. Le système PRISM est un exemple d'une telle copie, où les données qu'on avait accepté de confier à Google ou Facebook sont accessibles à la NSA. (Cet exemple n'est pas mentionné dans ce RFC qui, pour ne vexer personne et surtout pas les grosses entreprises états-uniennes qui contribuent beaucoup à l'IETF, passe rapidement sur ce risque, pourtant l'un des plus fréquents.)
Certains protocoles IETF permettent à l'utilisateur d'indiquer ses préférences en matière de protection de la vie privée, et notamment d'interdire la révélation de ces données à un tiers. C'est le cas par exemple du système décrit dans le RFC 6280. Évidemment, il n'existe aucun moyen technique de savoir si ces préférences sont respectées...
Notez aussi que la révélation peut être accidentelle : certains administrateurs systèmes sont assez négligents avec les données personnelles (ou bien ne se rendent pas compte qu'elles sont personnelles) et les laissent parfois accessibles par accident.
Dernière menace envisagée, l'exclusion. C'est le fait d'interdire à l'utilisateur de savoir ce qu'on sait sur lui. (La loi Informatique & Libertés appelle cela le droit d'accès aux données.) C'est une attaque tentante pour les gens qui veulent utiliser vos données personnelles. Cela limite le contrôle que l'individu peut faire.
Maintenant, assez déprimé sur les menaces, place aux solutions. La section 6 envisage les différentes méthodes connues pour limiter les dégâts. Améliorer la protection de la vie privée dans les protocoles réseau n'est pas facile car une protection sérieuse dépend de très nombreux facteurs, qui ne relèvent pas de la seule responsabilité des protocoles (ni même des logiciels). Je pense personnellement (et le RFC a tort de ne pas le rappeler) que le problème requiert avant tout des solutions politiques et juridiques. Mais ce RFC 6973 est un RFC, pas une loi, et se focalise donc surtout sur les aspects techniques : lorsqu'on est membre de l'IETF, que peut-on faire de concret aujourd'hui ?
Première chose évidemment, récolter moins de
données (data minimization ou No data, no
privacy problem). Les protocoles devraient être conçues de
façon à ne transmettre que les données strictement nécessaires à
l'accomplissemnt de la tâche. Les choix vont être délicats car les
informations envoyées, même pas strictement nécessaires, peuvent avoir
une utilité (le User-Agent:
en HTTP, énorme
risque pour la vie privée, mais si rigolo pour faire des
statistiques). Le RFC se focalise donc surtout sur un point,
l'identifiabilité. Il faut tout faire pour éviter qu'on identifie un
utilisateur. Cela peut passer par l'absence d'identificateurs dans le
protocole (ce que permet HTTP mais pas SMTP) ou par l'utilisation
d'identificateurs de durée de vie limitée, choisis aléatoirement et changés régulièrement (les
adresses IP temporaires du RFC 8981).
La meilleure protection de la vie privée est quand l'utilisateur
peut rester anonyme. Cela implique qu'il existe un ensemble d'anonymat
assez vaste pour qu'on soit réellement protégé. Un
User-Agent:
HTTP à lui seul vous place dans un
ensemble d'anonymat qui peut être très réduit (j'ai vu une fois dans
mes journaux un
User-Agent:
qui proclamait que le navigateur
tournait sur OpenBSD, ce qui diminue
considérablement le nombre de « suspects »). Par exemple, pour
SIP, le RFC 3325 permet
de choisir une adresse anonyme (notez que, comme souvent en matière
d'anonymat, l'information sur votre identité peut venir
d'ailleurs comme le champ Via:
).
Proche de la notion d'anonymat, celle de pseudonymat. Dans ce cas,
on a une identité stable et réutilisable, elle n'est simplement pas
liée aux identités qu'on veut protéger (comme son nom officiel, par
exemple). Dans l'exemple SIP ci-dessus, l'adresse utilisée est
toujours anonymous@anonymous.invalid
et est la
même pour tout le monde. C'est de l'anonymat. Si par contre je me crée
un compte aucbbf51n
chez un fournisseur SIP
example.net
qui ne
garde pas trace de mes informations personnelles, mon adresse
aucbbf51n@example.net
est un pseudonyme. Un
pseudonyme a l'avantage, par rapport à l'anonymat, de permettre de
construire une réputation.
Beaucoup d'identificateurs sur l'Internet vont être des pseudonymes
puisque les protocoles Internet n'obligent pas (et heureusement,
comparez avec ce que réclame l'UIT qui voudrait
obliger à utiliser des « vraies » identités) à se servir d'un nom
officiel. Ainsi, mon adresse de courrier pour ce blog est
stephane+blog@bortzmeyer.org
mais vous ne savez
pas si c'est mon nom officiel ou un pseudonyme. Parfois, tout de même,
des protocoles ou formats Internet transportent des identités qui
peuvent être des noms officiels. Un exemple typique est le format
vCard du RFC 6350.
Les pseudonymes ne sont pas parfaits, deux pseudonymes utilisés
dans des contextes différents peuvent parfois être reliés par exemple
via une information que vous communiquez. Si vous publiez sur
l'informatique avec une
adresse professionnelle
monsieursérieux@example.com
et que vous tenez un
blog sur la sexualité des hamsters avec l'adresse
lol-hamster218@example.net
, ne faites pas les mêmes
fautes d'orthographe, n'utilisez pas les mêmes tournures de phrase
dans les deux contextes ou bien vous serez démasqué. Un exemple de
pseudonymes impossibles à lier est fourni par Romain Gary et Émile Ajar : étant donné la
différence des styles, personne n'avait jamais suspecté que c'était le
même écrivain.
Un problème supplémentaire survient fréquemment de nos jours : beaucoup de services sur l'Internet ne font plus la gestion de l'identité eux-mêmes mais la délèguent à un fournisseur d'identité, utilisant des techniques comme OpenID ou des protocoles privés. Selon le protocole utilisé, les risques pour la vie privée peuvent être plus ou moins grands. Par exemple, si le service voulant authentifier (RP pour relying party, celui qui compte sur le fournisseur d'identité) communique directement avec le fournisseur d'identité (au lieu que tout passe via le client final), le fournisseur d'identité peut apprendre à quels services se connectent ses clients. Autre exemple, le fournisseur d'identité ne devrait pas envoyer au RP la totalité des informations dont il dispose sur un client.
Et, pour clore cette section 6 sur les solutions techniques améliorant la protection de la vie privée, le RFC note que le protocole doit fournir des mécanismes permettant à l'utilisateur de contrôler ses propres données (savoir ce que les autres savent sur lui, et pouvoir exprimer des préférences).
Plus pratique, la section 7 transforme ces bons conseils techniques en une liste de choses à vérifier lorsqu'on conçoit un nouveau protocole réseau. Une fois qu'on a développé un modèle du nouveau protocole (RFC 4101), lire cette liste et se poser les questions qu'elle contient devrait aider à limiter les risques pour la vie privée.
D'abord, minimiser la quantité de données distribuées. La meilleure
protection des données est quand il n'y a pas de données. Quels sont
les identificateurs utilisés par le protocole ? Est-ce qu'ils
permettent la corrélation entre des sessions différentes (c'est
souvent le cas s'ils sont stables sur le long terme) ? Ne pourrait-on
pas limiter leur utilisation ? Leur mettre une durée de vie limitée ?
Permettre aux utilisateurs d'en changer facilement ? Ensuite les données qui ne sont pas
officiellement des identificateurs ? Qu'est ce qui est échangé entre
les parties qui communiquent ? N'est-ce pas trop de données ? Ces
données ne permettraient-elles pas de retrouver les identificateurs
(pensez au Panopticlick) ? À qui sont envoyés ces identificateurs
et ces données (rappelez-vous qu'il y a typiquement plus que deux
parties impliquées dans une communication) ? Par exemple, lors d'une
connexion HTTP à http://www.example.com/
, la
requête DNS est envoyéee à des assistants (cf. le vocabulaire au
début), les serveurs de la racine et ceux de
.com
. La racine apprend donc qu'on se connecte à
www.example.com
. Et le risque d'empreinte
numérique ? Par exemple, si le protocole permet N opérations au début
d'une connexion, sans
spécifier leur ordre, un observateur peut apprendre quel logiciel vous
utilisez en regardant l'ordre choisi. Et enfin est-ce que le protocole
permet, voire impose, la conservation de données ou d'identificateurs
sur le long terme, en dehors des sessions de communication ?
Ça, c'était pour minimiser les données. Pour le contrôle par
l'utilisateur, les questions à se poser sont : quels sont les
mécanismes dans le protocole pour contrôler
quelles données on diffuse et à
qui ? Là encore, il ne faut pas penser qu'au
destinataire mais aussi à tous les intermédiaires possibles. Un
exemple, HTTP n'impose pas des en-têtes indiscrets comme
User-Agent:
et Referrer:
et
cela permet à certains navigateurs ou relais de les supprimer.
Les attaques contre la vie privée ne seront pas menées que par les participants légitimes à une communication. On aura aussi des tiers qui essaieront d'accéder à une information qu'ils ne sont pas censés avoir. Le protocole doit donc prendre en compte la possibilité de surveillance. Qu'est-ce qui est prévu contre l'écoute ? En général, c'est l'utilisation du chiffrement et le RFC contient donc une phrase « utilisez TLS si vous ne voulez pas être écouté ». Mais cela n'empêche pas l'analyse de trafic. Le protocole a-t-il des mécanismes qui facilitent ou au contraire compliquent cette analyse ? Par exemple, avec SSH, on voit facilement si on a affaire à un transfert de fichiers ou à une session interactive, par la quantité de données qui passe et leur cadencement. Lors d'un transfert de fichiers, on a beaucoup d'octets dans un sens et peu dans l'autre, les accusés de réception. Lors d'une connexion à un shell, on a peu d'octets de l'utilisateur vers le shell et une quantité moyenne (les réponses) en sens inverse. Le chiffrement ne dissimule pas cela. SSH a un mécanisme de remplissage de la communication avec des données bidon, pour brouiller les pistes mais je n'ai pas l'impression qu'OpenSSH l'utilise.
Toujours en sécurité classique, comment se comporte le protocole en cas de compromission des données stockées ? Ou contre une attaque active ?
Souvent, les préférences de protection de la vie privée sont réglables. Mais la plupart des utilisateurs ne modifieront jamais le réglage. Le RFC demande donc qu'on prête attention aux réglages par défaut. En l'absence d'intervention explicite, est-on protégé ou, au contraire, faut-il activer cette protection délibérement ? Par exemple, pour le cas des adresses IP temporaires, le RFC 4941 demandait qu'elles ne soient pas utilisées par défaut (sa mise à jour dans le RFC 8981 a changé les choses) alors que le RFC 6724 a demandé le contraire. Écrit quatre ans après, à un moment où les préoccupations de protection de la vie privée sont devenues plus importantes, ce RFC 6724 avait des priorités différentes.
D'ailleurs, la fin de cette section 7 rappelle que, comme Schneier aime le répéter, la sécurité est toujours un compromis. Elle prend du temps, ralentit le réseau, complique les choses (pour les programeurs et pour les utilisateurs), bref a un coût. La protection de la vie privée n'échappe pas à cette nécessité de chercher un compromis.
Pour clore ce RFC, la section 8 fournit un exemple complet d'analyse de sécurité d'un service donné. Les auteurs ont choisi la difficulté, car cette analyse porte sur un service particulièrement indiscret et intrusif, le service de présence (faire connaître à l'extérieur si on est disponible ou pas, par exemple pour être contacté par messagerie instantanée). Ce service permet d'illustrer toute la palette des questions soulevées par la protection de la vie privée. Présentée dans le RFC 2778, la présence (« je suis dispo », « je déjeune », « je suis en réunion ») est un service très dynamique, nécessitant de nombreuses mises à jour. Ses implications pour la vie privée sont évidentes et, dès le début, l'IETF avait prévu un contrôle des utilisateurs sur cette information (RFC 3859). Les protocoles qui utilisent un système de présence comme SIMPLE (RFC 6914) ou XMPP (RFC 3922) s'appuient sur ce contrôle.
Voici la gestion de la présence par l'utilisateur dans le client de
messagerie instantanée Pidgin :
Dans l'architecture standard, il y a un tiers, un assistant, le serveur de présence, qui reçoit les informations des clients et les transmet aux lecteurs autorisés. Ce tiers est nécessaire pour les cas où la/les machine(s) du client soient toutes éteintes ou injoignables. Il sert également à agréger de l'information envoyée par les différentes machines de l'utilisateur (son ordinateur peut être éteint mais l'utilisateur être toujours joignable via son smartphone). Mais il complique évidemment beaucoup la sécurité puisqu'il va être au courant de beaucoup de choses. Bien sûr, le serveur ne distribue l'information qu'aux lecteurs autorisés. Mais il n'y a pas de protection technique : il faut faire une confiance totale au serveur, confiance en son honnêteté et ses bonnes pratiques de sécurité. On pirate un serveur de présence et on peut suivre les gens à la trace. Le serveur oublie de rendre TLS obligatoire et les écoutants peuvent tout apprendre (et le client du serveur de présence n'a aucun moyen de vérifier si TLS est activé ou pas). Encore pire, c'est le serveur de présence qui authentifie les lecteurs, pas le client final. L'anonymat n'est ici pas une solution puisque le but d'un service de présence est justement d'obtenir des informations sur des personnes identifiées (« quelqu'un est allé déjeuner » n'est pas une information intéressante).
Pour compléter le tableau, d'autres informations que la présence sont souvent transmises, par exemple les capacités du logiciel utilisé (accepte t-il les appels vidéo, par exemple). Elles peuvent permettre d'identifier l'appareil utilisé. En outre, les extensions ultérieures au service de présence ont permis de publier également la localisation physique. Un groupe de travail a été créé pour travailler sur la protection de la vie privée dans le cas où on distribue cette information, le groupe GEOPRIV, dont le premier RFC fut le RFC 4079 (mais il y en a d'autres).
Avec tellement d'information, l'analyse de sécurité du service de présence doit évidemment commencer par se demander si le jeu en vaut la chandelle. Déjà, on pourrait utiliser une autre architecture, plus pair à pair, où les utilisateurs se préviennent directement de leur présence. Il existe un format standard pour transporter cette information, PIDF (Presence Information Data Format), qu'on peut chiffrer pour empêcher toute écoute. Mais cette solution ne semble pas réaliste aux auteurs du RFC : elle ne fonctionne pas si la machine de publication est éteinte ou injoignable, chaque machine qui publie doit connaître les clés publiques de tous les abonnés, et enfin elle suscite un trafic important (la présence est très dynamique, avec des changements fréquents). Une variante est l'architecture où le serveur de présence ne sert que de redirecteur : il ne connait pas l'information, mais sait rediriger vers la machine actuelle de chaque personne qui publie de l'information de présence. Le serveur peut ainsi prévenir qu'une personne est injoignable et rediriger vers cette personne dans le cas contraire. Mais cette architecture, comme la précédente, a ses propres problèmes de vie privée, puisqu'elle permet à chaque participant d'apprendre les adresses IP des autres (normalement connues du seul serveur de présence). En outre, ces deux solutions, davantage pair à pair, souffrent du difficile problème de la connexion d'une machine à une autre, lorsqu'une des deux, ou les deux, sont derrière un pare-feu ou un routeur NAT. Avec le serveur de présence, il suffit aux clients d'une connexion sortante, ce qui est bien plus souvent possible.
Bref, cette intermédiaire dangereux qu'est le serveur de présence va être difficile à éliminer. D'où l'approche actuelle, qui repose plutôt sur des préférences quant à la divulgation de l'information, préférences (RFC 4745, RFC 5025 et RFC 6772) qui sont envoyées au serveur de présence, et à qui il faut faire confiance pour les respecter. Le RFC note bien que le succès est très limité : peu de logiciels exploitent cette information. Au moins, on peut documenter leurs limites, ce qui est fait ici.
On a donc là un bel exemple d'un compromis entre la protection de la vie privée (qui justifierait qu'on ne publie jamais rien sur sa présence) et le désir de faciliter la vie des utilisateurs en indiquant à l'avance si un appel a des chances d'aboutir ou pas.
Mon commentaire à une version préliminaire de ce RFC est disponible en ligne (notez la note de cloture du ticket). Globalement, mon regret est que ce document (même après les changements) est très axé sur les risques dus aux tierces parties et parle peu des risques du méchant silo qui stocke les données personnelles, ou sur les risques étatiques type PRISM.
Si vous voulez approfondir ces questions, ce RFC cite trois sources : le « FAIR INFORMATION PRACTICES: A Basic History » de Gellman, les directives de l'OCDE et le « Privacy Indexes: A Survey of Westin’s Studies ».
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : Y. Zhang, N. Zong (Huawei Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF ppsp
Première rédaction de cet article le 20 juillet 2013
Il existe actuellement des tas de logiciels qui font du streaming (audio ou vidéo) en pair à pair mais toujours en utilisant des protocoles privés et fermés. Cela a des tas de conséquences négatives, notamment sur le plan du choix : l'utilisateur est enfermé dans l'offre d'une compagnie particulière. Il est donc urgent de développer un protocole libre et ouvert de streaming pair à pair et c'est la tâche du groupe de travail PPSP de l'IETF. Son premier RFC, ce RFC 6972, est le cahier des charges du protocole (comme toujours à l'IETF, le travail a commencé bien avant la publication du cahier des charges et des mises en œuvre du protocole PPSP - normalisé dans le RFC 7574 - existent déjà).
Le streaming est un usage essentiel de l'Internet (le RFC cite une étude de Cisco à ce sujet). Dans sa version classique, avec un gros serveur ou une batterie de gros serveurs qui distribuent à des millions de clients, le streaming ne passe pas à l'échelle. Si on en était resté à ce mode de distribution, seule une poignée de très grosses entreprises pourraient héberger du contenu vidéo. Heureusement, il existe une meilleure solution, la distribution en pair à pair où chaque client se transforme en distributeur pour une partie du contenu. Le streaming pair à pair permet à n'importe qui de distribuer de la vidéo sur l'Internet, avec seulement des serveurs ordinaires.
Mais, car il y a un mais, ce streaming pair à pair, aujourd'hui, se fait essentiellement avec des protocoles privés d'une entreprise capitaliste particulière. La section 3 décrit les problèmes que cela pose. D'abord, sur le plan technique, cela interdit de développer des mécanismes de cache communs, le cache devant connaître le protocole utilisé (imaginez les caches Web si tout le monde ne parlait pas HTTP). Même chose pour les CDN qui ne peuvent pas être exploités facilement pour aider ce streaming puisqu'ils ne peuvent pas connaître tous les protocoles utilisés.
Enfin, les protocoles existants ne sont pas forcément bien adaptés aux mobiles qui sont pourtant une bonne partie des clients. Il y a eu des recherches à ce sujet (cf. J. Peltotalo et autres, « A real-time Peer-to-Peer streaming system for mobile networking environment » en 2009) mais qui ne se retrouvent pas forcément dans les protocoles existants. PPSP va donc devoir gérer :
À noter que la section 3 ignore les problèmes plus politiques comme l'excès de pouvoir que ces protocoles fermés donnent à l'entreprise qui les contrôle, et peut ainsi limiter la liberté des clients.
La section 4 décrit à un haut niveau les missions du protocole de streaming pair-à-pair. Pour modéliser ce protocole, elle reprend largement la terminologie de BitTorrent (la section 2 décrit tout le vocabulaire à connaître mais le RFC ne cite jamais BitTorrent), avec notamment la notion de tracker, le mécanisme (pas forcément une machine, cela peut être une DHT) qui garde trace de tous les pairs servant un contenu donné (ce qu'on nomme l'essaim). Il y a en fait deux protocoles, un entre le pair et le tracker et un entre pairs. Lorsqu'il rejoint un essaim, le pair doit pouvoir trouver les autres pairs (avec le premier protocole) et les contacter (avec le second). Il doit pouvoir connaître les caractéristiques des pairs, pour les choisir astucieusement. Le protocole doit bien sûr être efficace (le streaming vidéo fait passer d'énormes quantités de données) et doit être robuste (par exemple en cas de panne du tracker).
Le protocole pair<->tracker va nécessiter un identifiant unique pour les pairs (peer ID). Il va falloir aussi classer les pairs, par exemple selon le fait qu'ils ont une adresse IP publique ou pas, qu'ils sont en IPv4 ou en IPv6, qu'ils ont des ressources importantes ou pas, etc. Ce sera plutôt un protocole requête/réponse (le pair se connecte, transmet ses infos, et reçoit une liste de pairs).
Le protocole pair<->pair devra se colleter avec les problèmes de l'identification du contenu et de son intégrité (un problème important en pair-à-pair). Le contenu envisagé pour ce problème étant souvent de grande taille, il faudra le découper en morceaux (chunks) et il faudra donc un mécanisme d'identification des morceaux et de leur disponibilité. Ce sera plutôt un protocole de bavardage (échange continu d'information).
Avant d'aborder le cahier des charges précis, le RFC pose une dernière question, quels sont les usages envisagés pour ce nouveau protocole de streaming (section 5) ? Il y a la distribution de vidéo en temps réel, par exemple lors d'un événement (cela ressemble fortement à l'usage décrit dans les RFC 6707 et RFC 6770). Il y a aussi la VoD. D'autres usages sont moins évidents à première vue comme la possibilité d'avoir des caches pour le streaming. Même si on est dans une relation client/serveur, un protocole pair-à-pair de streaming permet d'envisager des systèmes de caches automatiques entre le client et le serveur, qui intercepteraient les requêtes et les mémoriseraient pour les futurs utilisateurs. Un exemple proche est l'extension P2Pyoutube du navigateur Opera.
Enfin, le cahier des charges proprement dit. Je ne vais pas reprendre ici toutes les exigences, classées en catégories (REQ : la base, OAM : gestion du protocole, TP : protocole pair<->tracker, PP : protocole pair<->pair) et numérotées. Certaines sont de l'ordre de l'évidence (PPSP.REQ.1 : chaque pair doit avoir un identificateur unique, PPSP.REQ.2 dit la même chose pour l'essaim et PPSP.REQ.4 pour le morceau). D'autres sont toujours bonnes à rappeler (PPSP.OAM.REQ-2 : il doit y avoir des paramètres de configuration, ayant des valeurs par défaut, PPSP.OAM.REQ-7 : on doit pouvoir les changer). Beaucoup sont communes à tout système de distribution de contenu en pair-à-pair et se retrouvent déjà dans BitTorrent. D'autres sont plus spécifiques au streaming. Ainsi PPSP.OAM.REQ-4 parle des mécanismes pour atteindre une qualité suffisante pour le flux audio ou vidéo. Cela implique un délai raisonnable. Le RFC dit par exemple qu'une minute de délai pour la retransmission d'un évenement sportif est inacceptable (imaginez le supporter du PSG ayant encore son verre de bière à la main alors que dans les maisons environnantes, tous les autres hurlent déjà « Buuuuuuuuuuuuuuut ! »).
Souci classique à l'IETF, le protocole doit être gérable. Des exigences comme PPSP.OAM.REQ-5 demandent qu'on puisse accéder à l'information nécessaire pour déboguer et/ou optimiser le protocole et PPSP.OAM.REQ-6 ajoute qu'il faut pouvoir tester un pair, sa connectivité, son bon fonctionnement, etc.
De même, les exigences sur le protocole tracker<->pair sont assez standards et évidentes (PPSP.TP.REQ-1 : le pair doit pouvoir obtenir du tracker une liste de pairs potentiels...). Notez quand même une exigence que l'authentification du pair soit possible, pour les essaims fermés (PPSP.TP.REQ-4). Même chose pour le protocole pair<->pair. Notez toutefois PPSP.PP.REQ-3 (obtenir directement du pair, sans passer par le tracker, d'autres pairs, de préférence vérifiés, ajoute PPSP.PP.REQ-5) et PPSP.PP.REQ-8, la possibilité d'obtenir plein d'informations sur les pairs.
Voilà, le cahier des charges est fini. Une faiblesse traditionnelle des systèmes pair-à-pair, la sécurité, fait l'objet d'une section à part, la 7. Elle analyse les risques dus à des pairs ou des trackers malveillants :
Cela entraîne l'ajout de quelques exigences supplémentaires, étiquetées SEC pour SECurity. PPSP.SEC.REQ-1 reprend l'exigence déjà mentionnée de pouvoir faire des essaims fermés, avec pairs authentifiés. PPSP.SEC.REQ-2 rappelle qu'il est indispensable d'avoir un mécanisme de contrôle de l'intégrité du contenu, pour empêcher un pair malveillant d'injecter des morceaux incorrects, et PPSP.SEC.REQ-3 appelle au réalisme en demandant que tout mécanisme de sécurité passe bien à l'échelle, on peut avoir des essaims immenses.
Les auteurs annoncent qu'il y a déjà trois mises en œuvre du protocole mais il ne semble pas y avoir beaucoup de documentation à ce sujet. Le protocole correspondant à ce cahier des charges a été normalisé dans le RFC 7574.
Date de publication du RFC : Juin 2013
Auteur(s) du RFC : U. Herberg (Fujitsu), A. Cardenas (University of Texas at Dallas), T. Iwao (Fujitsu), M. Dow (Freescale), S. Cespedes (U. Icesi)
Expérimental
Première rédaction de cet article le 29 juin 2013
Traditionnellement, l'acheminement à bon port d'un paquet IP nécessitait deux processus distincts : le routage (routing) à proprement parler, où les routeurs calculent des tables de routage indiquant, pour divers préfixes IP, la prochaine étape (next hop) à atteindre, et la transmission (forwarding) où les routeurs choisissent le prochain routeur, et l'interface de sortie, pour un paquet donné. Le premier processus, le routage, est fait à l'avance, indépendemment d'un paquet précis, et nécessite des protocoles complexes comme OSPF. Le second processus, la transmission, nécessite de faire tourner l'algorithme de plus long préfixe, et se fait par contre en temps réel, pour chaque paquet entrant. Pourquoi cette séparation en deux ? Car ces deux processus ont des caractéristiques très différentes. Le premier, nécessitant des protocoles et des algorithmes élaborés, est mieux réalisé sur un processeur classique. Le second est typiquement le domaine d'ASIC spécialisés. Les routeurs haut de gamme utilisent d'ailleurs les deux types de matériel, selon la tâche. Mais cette séparation a aussi des inconvénients. Ainsi, la détection qu'un lien ne marche plus est typiquement du ressort des algorithmes de routage, qui ajusteront alors leurs routes. Pourtant, certains réseaux physiques permettent la détection, lors de la transmission d'un paquet, d'une panne et d'une impossibilité d'envoi. Pourquoi ne pas utiliser cette information pour que les paquets suivants aillent essayer une autre étape suivante ? C'est ce que propose ce RFC.
Notez que, comme souvent en matière de réseaux informatiques, le vocabulaire est flou et incohérent. Ainsi, le terme de routage est souvent utilisé pour désigner les deux processus qui concourent à l'acheminement, le routage à proprement parler et la transmission. Par exemple, j'ai parlé de table de routage alors que le sigle FIB (Forwarding Information Base) aurait été plus correct. Et le terme routeur désigne une boîte qui fait de la transmission et parfois (sur le moyen et haut de gamme) le routage. On lit ainsi des phrases fausses comme « Quagga permet de transformer un PC Unix en routeur » alors que le noyau Unix a toujours été capable de faire de la transmission de paquets (Quagga met en œuvre les protocoles de routage, qui ne sont pas nécessaires à un routeur).
Mais passons. Il faut bien faire avec le vocabulaire que nous avons. Revenons à la proposition expérimentale de notre RFC 6971. Elle ne cherche pas à couvrir tous les cas de transmission de paquets. Ce RFC s'applique aux paquets IPv6, lors de leur transmission sur des liens peu fiables, avec une topologie sans cesse changeante, un trafic assez faible, et où le protocole de couche 2 permet de savoir si un paquet a été transmis avec succès ou pas. C'est typiquement le monde des MANET et des LowPAN, des réseaux de petites machines connectées en radio. L'idée centrale de ce protocole DFF est d'avoir, dans le processus de transmission, certaines techniques utilisées d'habitude uniquement dans le routage, pour chercher un chemin alternatif. DFF va transmettre un paquet au premier routeur, s'il ne reçoit pas de nouvelles, il va essayer le second et ainsi de suite. Par contre, si la transmission vers la première étape se fait avec succès, DFF va laisser le paquet continuer, passer au routeur suivant, etc. Il fonctionne donc en profondeur d'abord (on essaie d'aller le plus loin possible, avant de tester d'autres « frères »). Les essais successifs se font séquentiellement (et non pas en parallèle comme dans les protocoles d'inondation) pour éviter qu'un destinataire ne reçoive plusieurs copies du même message. Cela peut donc prendre pas mal de temps s'il y a beaucoup de routeurs potentiels. À noter que le tout fonctionne de manière répartie, sans composant central.
N'est-ce pas un peu bizarre que de refaire une partie du travail du processus de routage dans celui de transmission ? Mais c'est lié à la façon dont fonctionnent les protocoles de routage. Travaillant à l'avance, ils ne peuvent pas s'adapter assez vite à tous les changements de topologie, qu'on ne découvrira qu'en envoyant réellement des paquets. Les protocoles de routage fonctionnent typiquement en envoyant de temps en temps des messages d'information. L'information peut donc être dépassée au moment de la transmission. Pour avoir une information plus à jour (section 1.1), il faudrait augmenter le rythme des messages d'information et cela se ferait au détriment de la consommation d'énergie des machines (rappelez-vous que DFF est prévu pour des réseaux de petites machines, souvent sans autre source d'énergie que leur batterie). Se placer sur le dos du processus de transmission (qui doit avoir lieu de toute façon) permettra donc, si ce protocole DFF tient ses promesses (ce RFC est expérimental), d'augmenter le pourcentage de paquets effectivement transmis, sans augmenter les coûts.
DFF va donc récolter de l'information sur le fonctionnement effectif du réseau, information qui peut être utile au processus de routage. DFF peut donc la réinjecter dans ce dernier, pour l'aider à calculer de meilleures routes, mais ce point n'est pas détaillé dans ce RFC.
La section 3 du RFC revient sur l'applicabilité limitée de ce protocole DFF. On l'a dit, il ne s'agit pas de remplacer tous les mécanismes de routage existants par ce mécanisme utilisant le succès de la transmission comme indication. D'abord, tous les réseaux n'offrent pas de possibilité de détecter cet échec. 802.15.4 ou 802.11 le permettent mais pas Ethernet, par exemple. D'autre part, DFF n'est utile que si la topologie change souvent. Dans un réseau filaire stable et fiable, les mécanismes de routage actuels marchent très bien et n'ont pas besoin de DFF. Et DFF nécessite un réseau ayant une topologie dense, avec plusieurs liens possibles entre deux points. S'il n'existe qu'un seul lien, DFF ne servira à rien puisque, en cas de perte d'un paquet, il n'y aura pas d'alternative. Enfin, DFF, contrairement à la transmission IP traditionnelle, nécessite un état dans le routeur. Il faut se souvenir de chaque paquet envoyé, le temps qu'on soit sûr de son bon acheminement. DFF ne peut donc être utilisé qu'en cas de faible trafic.
DFF peut fonctionner aussi bien dans les réseaux route-over (réseaux routés par les méthodes IP classiques) que dans les réseaux mesh-under (réseaux utilisant un mécanisme de « routage » dans la couche 2, cette terminologie est empruntée au RFC 6775).
La section 4 résume le fonctionnement du protocole : pour chaque paquet qu'il a reçu et qu'il doit transmettre, le routeur construit une liste des prochaines étapes possibles. Il tente d'envoyer le paquet en essayant successivement ces étapes. Si toutes échouent, le routeur renvoie le paquet à l'expéditeur, qui va alors essayer l'étape suivante dans sa liste à lui (rappelez-vous qu'on est en profondeur d'abord). On voit donc que, pour chaque paquet pas encore transmis avec succès, le routeur doit garder cette information en mémoire : routeur précédent (qui a envoyé le paquet), numéro et prochaines étapes possibles en indiquant lesquelles ont déjà été essayées. C'est quoi, ce numéro ? C'est un identifiant unique par routeur et permettant de distinguer un paquet des autres (section 12). La liste des paquets en cours de transmission, avec les métadonnées, est nommée le Processed Set (section 6.2).
DFF doit connaître la liste des prochaines étapes possibles. Il a pu utiliser un protocole de découverte des voisins (comme le NHDP du RFC 6130), ou bien il a pu trouver cette information dans la RIB (Routing Information Base), la base de données construite par le processus de routage (voir la section 5 pour les détails).
Les informations dont a besoin DFF peuvent être représentées de
deux manières différentes dans le paquet. En
route-over, on utilise un en-tête d'extension
IPv6 standard, le hop-by-hop
options (et pas un destination options,
malgré les recommandations du RFC 6564 car cet
en-tête doit être examiné par tous les routeurs sur le trajet). Le
type de l'option DFF est 0xEE. Comme il commence par deux bits à Un,
le paquet sera rejeté par les routeurs non-DFF (RFC 2460, section 4.2). La section 13.1 de notre RFC fournit les
détails sur cette adaptation à IPv6. En mesh-under, on se sert des
en-têtes 6LoWPAN, avec les adresses du RFC 4944 (section 13.2 pour les précisions). Outre le numéro, il faut
mettre dans chaque paquet deux booléens : RET
indique un paquet renvoyé à l'expéditeur car non distribuable, et
DUP
indique une retransmission, au moins un essai
ayant apparemment échoué. Comme le paquet a pu être distribué quand
même (même si le routeur émetteur n'a pas été notifié),
DUP
sert à indiquer la possibilité de duplication
d'un paquet, avec laquelle les couches hautes vont devoir se débrouiller.
Rien ne garantit que le réseau soit un arbre
pur. Des boucles sont parfaitement possibles et DFF doit les
détecter.
Ces booléens RET
et DUP
permettent
notamment de distinguer un paquet délibérement renvoyé à l'émetteur
d'un paquet qui boucle dans le réseau. Si le routeur reçoit un paquet
qu'il a déjà transmis (il le sait d'après le numéro), avec DUP
et
RET
tous les deux à Zéro, c'est que le paquet
est en train de boucler. Si RET
est à Un, c'est
un retour délibéré car le routeur suivant n'a pas pu transmettre le
paquet.
Le format exact des paquets figure en section 7. Le traitement des paquets par les routeurs est détaillé en sections 10 et 11 du RFC. Des examples de fonctionnement de DFF dans diverses topologies, et pour divers cas de figure, se trouvent dans l'annexe A.
Notez que, comme la plupart des protocoles conçus pour ce type de réseau (sans administrateur réseaux, et où il y a beaucoup de machines, qu'il n'est pas question de configurer une par une), DFF ne présente guère de sécurité. Par exemple, en envoyant beaucoup de paquets à une adresse inexistante, on force les routeurs à retenir ces paquets en mémoire le temps de détecter la non-délivrabilité, réalisant ainsi facilement une attaque par déni de service (section 16.3.1).
Maintenant, il reste à tester DFF en vrai, et à récolter de
l'information sur les points détaillés en section 1.2 : quelles sont
les bonnes valeurs pour le délai d'attente
P_HOLD_TIME
(trop long, et on consomme
de la mémoire sur les routeurs, qui doivent se souvenir du paquet, trop
court, on risque d'oublier un paquet et de le croire nouveau lorsqu'il
revient après un échec, cf. section 8) ? Et les valeurs idéales pour le nombre de sauts
maximum MAX_HOP_LIMIT
? Et l'interaction idéale entre DFF et les protocoles de
routage ? Tous ces points vont devoir être étudiés en pratique.
L'annexe B du RFC rassemble un certain nombre d'informations sur le
déploiement effectif de DFF et ses mises en œuvre (au moins deux à
l'heure actuelle, une sur 802.11 et une sur 802.15.4). Par exemple, les
compteurs électriques de la
smart grid au
Japon utilisent apparemment DFF mais les détails
n'ont pas été publiés. Un autre distributeur d'électricité qui utilise
DFF est la Kit Carson Electric Cooperative au
Nouveau-Mexique, qui
en a http://www.kitcarson.com/index.php?option=com_content&view=article&id=45&Itemid=1
fait
état publiquement. Une mise en œuvre en logiciel libre de DFF en Java a été annoncée par
Fujitsu mais apparemment pas encore publiée
(en tout cas, je ne l'ai pas trouvée).
Merci à Laurent Toutain pour sa relecture et ses remarques pertinentes sur l'algorithme DFF.
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : M. Boucadair (France Telecom), R. Penno, D. Wing (Cisco)
Chemin des normes
Première rédaction de cet article le 24 juillet 2013
Le RFC 6887 normalise le protocole PCP (Port Control Protocol) qui permet de contrôler un routeur NAT ou un pare-feu depuis une machine cliente, par exemple pour ouvrir un port en entrée lorsqu'on utilise un logiciel de transfert de fichiers pair-à-pair ou bien un logiciel de téléphonie sur IP. PCP fonctionne également dans le cas des CGN. Mais cela ne sert à rien d'avoir des routeurs PCP si la quasi-totalité des applications sur les postes clients n'utilise toujours que le vieux protocole UPnP, certes très limité mais qui est largement déployé. Ce nouveau RFC décrit donc une solution de transition : une passerelle entre UPnP et PCP, permettant de satisfaire les clients UPnP et les serveurs PCP.
Cette passerelle sera typiquement installée dans le routeur
CPE (la box). Ainsi,
lorsque, par exemple, l'application qui parle UPnP fera un
AddPortMapping
, la passerelle le traduira en une
requête MAP
PCP (avec l'option
PREFER_FAILURE
puisque cette requête, contrairement
à AddAnyPortMapping
, réclame un numéro de port
spécifique et échoue s'il n'est pas disponible ; cf. section 5.6). Si vous aimez les sigles, vous
serez ravis car le nom complet de la passerelle est UPnP IGD-PCP IWF
pour UPnP Internet Gateway Device PCP Interworking
Function.
La section 4 donne les correspondances complètes entre les méthodes
UPnP et les méthodes PCP, ainsi qu'entre leurs codes d'erreur. Ainsi,
toute passerelle UPnP<->PCP sait qu'elle doit traduire une
erreur 8 de PCP (NO_RESOURCES
) en une erreur
501 ActionFailed
chez UPnP v1 et 728
NoPortMapsAvailable
chez UPnP v2 (qui a des codes d'erreur
bien plus détaillés). De la même façon, une erreur 2 de PCP
(NOT_AUTHORIZED
) devient 718
ConflictInMappingEntry
en UPnP v1 et 606
Action not authorized
en UPnP v2.
La passerelle UPnP<->PCP n'est pas un simple relais,
transférant des requêtes dans un sens et les réponses dans
l'autre. Elle doit garder un état, la mémoire de
toutes les correspondances demandées (section 5.3). Cela permet, par exemple de
faire face au fait que UPnP permet de créer une correspondance
{adresse interne, port
interne, adresse externe, port externe} de durée illimitée, ce que ne
sait pas faire PCP (RFC 6887, section 7.1). Dans
ce cas, la passerelle enregistre la correspondance et la renouvelle
dans le serveur PCP à chaque fois qu'elle approche de
l'expiration (section 5.9). D'autre part, des requêtes UPnP d'information comme
GetListOfPortMappings
ne sont pas relayés au
serveur PCP mais
traitées en examinant l'état local (section 5.7).
Autre point important de ce RFC : la passerelle peut être sur un routeur NAT ou pas (par exemple, dans certains cas de CGN, le routeur CPE ne fait pas de NAT). Si elle doit faire du NAT, la réception d'une requête UPnP va se traduire par une mise à jour de la table NAT locale et l'émission d'une requête au serveur PCP.
Ah, et pour trouver le serveur PCP à utiliser, comment fait la passerelle ? Comme un client PCP normal (via DHCP, par exemple).
Date de publication du RFC : Juin 2013
Auteur(s) du RFC : M. Boucadair (France Telecom), J. Touch (USC/ISI), P. Levis (France Telecom), R. Penno (Cisco)
Pour information
Réalisé dans le cadre du groupe de travail IETF intarea
Première rédaction de cet article le 19 juin 2013
Lorsque plusieurs machines sont situées derrière un routeur NAT, leurs pairs sur l'Internet ne peuvent pas facilement les distinguer. Tout le trafic vient de la même adresse IP, l'adresse publique allouée au routeur NAT, et c'est gênant pour certaines applications. Par contre, cela est positif d'un autre point de vue : cela fournit un certain niveau de masquage des machines individuelles, qui peut aider à protéger sa vie privée. Pris entre ces deux exigences contradictoires, l'IETF propose dans ce RFC une analyse des techniques permettant de révéler la machine individuelle derrière le routeur NAT, sans prendre position sur le fait de savoir si cette révélation est une bonne ou une mauvaise chose.
L'idée est que chaque machine a une identité unique (notée HOST_ID) et que les techniques étudiées ici doivent permettre de communiquer ce HOST_ID au pair avec qui on parle sur l'Internet. Autrefois, l'adresse IPv4 pouvait servir de HOST_ID mais cela ne marche plus désormais en raison de la prévalence du NAT. Le cas du petit routeur NAT à la maison n'est pas forcément le plus intéressant (toutes les machines appartiennent au même foyer) mais le problème est plus crucial avec les CGN, où des machines n'ayant aucun lien entre elles se partagent la même adresse IP, ce qui a des tas d'effets néfastes (RFC 6269) : impossible de mettre en liste noire la machine coupable, par exemple, sans risquer de gêner des utilisateurs n'ayant commis d'autre délit que de partager l'adresse IP d'un méchant. Même problème avec des techniques comme l'A+P du RFC 6346.
J'ai dit plus haut que le but était d'avoir des HOST_ID uniques. En fait, il doivent être uniques par adresse IP publique. Deux routeurs NAT qui utilisent des adresses IPv4 publiques différentes peuvent générer des HOST_ID identiques, seul le couple {adresse IPv4 publique, HOST_ID} a besoin d'être unique au niveau mondial (section 2 du RFC).
À ce stade, rappelez-vous que ce RFC présente un problème en terme très général et expose des solutions possibles. Par exemple, le HOST_ID peut figurer dans chaque paquet IP ou bien uniquement au début d'une session. Et il peut être ajouté par l'engin qui gère le partage d'adresse (le routeur NAT ou CGN) ou bien par la machine originale (qui pourra donc mentir, mais c'est pareil avec l'adresse IP source). Enfin, bien des identificateurs peuvent être utilisés comme HOST_ID (l'adresse IP à la source, les seize bits de poids le plus faible de l'adresse IP, un identifiant opaque compris uniquement par le FAI de départ, un VLAN ID, etc).
Une telle fonction de révélation des identités soulève évidemment des problèmes liés à la protection de la vie privée. Certains voient en effet dans le NAT des avantages en terme de sécurité comme, via le partage d'adresses, le fait que l'observateur extérieur ne puisse pas savoir quelle machine exactement, parmi toutes les machines situées derrière le routeur NAT, il est en train d'observer. En fournissant un HOST_ID à l'extérieur, on perdrait cette intimité. Notez qu'HOST__ID ramènerait juste au cas où on utilise une adresse IP publique sur sa machine, ni plus, ni moins. Notamment, un HOST_ID, comme une adresse IP publique, ne serait pas forcément permanent (lisez le RFC 8981 pour un exemple d'adresses publiques temporaires préservant la vie privée). Ainsi, une machine en redémarrant pourrait acquérir un nouvel HOST_ID.
Pour limiter les risques, ce RFC suggère deux règles : que les HOST_ID ne soient uniques que localement, pas globalement. Et qu'ils soient toujours temporaires. Cette question de la vie privée avait été la plus chaude lors des discussions à l'IETF sur le futur RFC, et le document a beaucoup évolué vers davantage de prise en compte du problème de la protection de la vie privée. Alissa Cooper, du CDT et auteure du RFC 6462 avait été particulièrement critique sur les premières versions de ce document, réclamant des modifications comme le fait que le HOST_ID ne soit pas forcément unique mondialement.
D'autre part, les logiciels qui visent à mettre en œuvre des mécanismes de dissimulation, afin de protéger la vie privée, comme Tor, supprimeront évidemment le HOST_ID, comme ils suppriment aujourd'hui d'autres informations bien plus révélatrices. Regardez le Panopticlick pour voir qu'on est facilement identifié de manière unique lorsqu'on navigue sur le Web, même derrière un routeur NAT.
La section 4 de notre RFC présente ensuite toutes les solutions étudiées pour transmettre l'HOST_ID. Certaines sont clairement mauvaises et ne sont mentionnées que pour documenter les raisons de leur rejet. D'autres méritent davantage d'étude.
D'abord, utiliser le champ Identification des paquets IP. Ce champ est surtout connu pour servir lors du réassemblage des datagrammes mais on peut théoriquement s'en servir pour « exfiltrer » de l'information sur une machine. Ce champ fait seize bits, ce qui est suffisant pour identifier une machine. Cela empêche évidemment de s'en servir pour le réassemblage après fragmentation (voir l'excellent RFC 6864 si vous voulez tout comprendre sur ce champ). Comme il n'est pas toujours facile pour le routeur NAT de garantir que les datagrammes ne seront jamais fragmentés, ni avant, ni après, cette solution est déconseillée par notre RFC.
On peut alors imaginer de définir une nouvelle option IP, conçue
uniquement pour notre but d'identification, et dont l'usage
n'entrerait pas en conflit avec des usages existants. Elle permettrait
de transporter l'information qu'on veut. (Cela avait été documenté dans l'Internet-Draft draft-chen-intarea-v4-uid-header-option
, abandonné depuis.) Cette solution, comme la
précédente, a l'avantage d'être indépendante du protocole de
transport. Elle pose quelques
problèmes techniques (que faire si le paquet a une taille proche de la
MTU et qu'on veut y ajouter cette option ? que
faire si l'espace pour les options, qui a une taille maximale en IPv4,
est plein ?) Mais elle a surtout comme défaut que les options IP sont
souvent bloquées sur
l'Internet (voir aussi « Measuring interactions between transport protocols
and middleboxes » par Alberto Medina, Mark Allman et Sally Floyd). Le RFC la regarde donc comme non
viable.
On peut alors monter d'une couche et choisir une nouvelle option
TCP, qui indiquerait le
HOST_ID. (Documenté dans
l'Internet-Draft
draft-wing-nat-reveal-option
qui a été abandonné
par la suite.) Cela aurait l'avantage qu'on n'aurait pas
à la répéter dans chaque paquet mais uniquement dans le paquet
SYN
. Cela aiderait à résoudre les problèmes de
MTU (le paquet SYN
est petit). Et les mesures indiquent que les options TCP
sont bien mieux respectées que les options IP sur l'Internet (voir
l'article de Medina, Allman et Floyd cité plus haut, ainsi que
l'Internet-Draft draft-abdo-hostid-tcpopt-implementation
).
Mais cette solution ne marcherait évidemment pas pour les autres protocoles de
transport. Et il y a quelques
problèmes techniques (une vision générale est dans l'article de Honda, M., Nishida, Y., Raiciu, C., Greenhalgh, A.,
Handley, M. et H. Tokuda, « Is it
still possible to extend TCP? »). Par exemple,
l'espace pour les options a une taille maximum dans TCP.
Si on n'a pas trouvé son bonheur dans la couche
3 (champ ID
d'IP ou option IP), ni
dans la couche 4 (option TCP), les couches
supérieures seront-elles plus accueillantes ? Pourquoi ne pas
transmettre l'information dans les applications ? Par exemple, pour
HTTP, l'en-tête
Forwarded:
(RFC 7239) pourrait être l'endroit idéal pour
cela. L'engin qui fait le partage d'adresses pourrait ainsi ajouter à
la requête HTTP :
Forwarded: for=192.168.13.1
Il existait avant un en-tête non-standard,
X-Forwarded-For:
, dit aussi XFF, qui faisait
quelque chose de ce genre. Comme les autres solutions au problème de la révélation du
HOST_ID, elle permet la triche. C'est pour cela que
Wikipédia maintient une liste des
FAI à qui on peut faire confiance pour mettre
de l'information XFF correcte. Wikipédia peut alors utiliser
l'information dans ce champ pour attribuer les responsabilités (de
vandalisme, par exemple, ou d'introduction délibérée d'informations
fausses) à la bonne adresse IP.
La principale limite de cette solution est qu'elle ne marche que pour
certains protocoles, comme HTTP. Pour les autres, il faudrait au fur
et à mesure concevoir une extension permettant de diffuser cette
information. Même pour HTTP, elle nécessite de modifier les requêtes
en cours de route, ce qui est impossible avec
HTTPS.
Pour éviter de devoir développer une extension ou un en-tête
spécifique par protocole applicatif, la solution PROXY a été
proposée. Elle consiste à ajouter l'information juste avant les
données de la couche
Application. L'information a cette allure (au moment du
partage d'adresses, 192.168.13.1:56324
voulait
parler à 192.0.2.15:443
) :
PROXY TCP4 192.168.13.1 192.0.2.15 56324 443\r\n
En la recevant, le serveur a juste à retirer cette ligne et à passer ce qui suit à l'application. En pratique, cette solution n'est pas réaliste car elle casse la compatibilité : un client qui a PROXY ne peut pas parler à un serveur qui ne l'a pas (l'opposé est vrai, par contre). Sans même parler des pare-feux qui n'accepteront pas ce qui leur semblera une requête invalide. Bref, elle n'est envisageable que dans des environnements fermés.
Le NAT tel que déployé aujourd'hui dans le monde IPv4 ne mérite pas
réellement son nom. Il ne traduit pas une adresse pour une autre mais
un couple {adresse, port} pour un autre. Il devrait plutôt être
qualifié de NAPT (Network Address and Port
Translation). Peut-on utiliser les ports alloués pour
transporter l'information sur le HOST_ID ? L'idée
est d'allouer un jeu de ports à chaque machine située derrière le
routeur NAPT. Par exemple, imaginons trois machines derrière le
routeur, celui-ci utilise les ports publics de 1 024 à 20 000 pour la
première machine, de 20 001 à 40 000 pour la seconde et de 40 001 à
65 535 pour la troisième (voir l'Internet-Draft draft-donley-behave-deterministic-cgn
). Il ne reste plus ensuite qu'à publier cette
information à l'extérieur (le RFC est muet sur ce point). Le RFC 6346 propose
une solution de ce genre. Malheureusement, cela contredit
partiellement les
exigences de sécurité des RFC 6056 et RFC 6269 qui demandent des ports sources
imprévisibles.
Plus disruptive est la solution qui consiste à utiliser un protocole nouveau, au dessus d'IP, le protocole HIP. HIP a déjà cette notion de HOST_ID (l'identité d'une machine est une clé cryptographique, ce qui résout bien des problèmes de sécurité). Mais cela nécessite que le client et le serveur parlent HIP tous les deux, ce qui parait irréaliste. À la rigueur, si tous les serveurs parlaient HIP, le routeur NAT pourrait se contenter de prendre des requêtes non-HIP et de les traduire en HIP. Mais tous les serveurs ne parlent pas HIP, loin de là.
Bon, si on n'arrive pas à mettre le HOST_ID dans
le canal normal de communication, peut-on le mettre à l'extérieur ?
Par exemple, peut-on utiliser ICMP pour
signaler l'adresse originale d'une communication en cours ? Dans cette
idée, le routeur NAT, en même temps que le paquet TCP initial vers le
serveur, enverrait une requête ICMP contenant l'information
utile. Cela avait été documenté dans
l'Internet-Draft
draft-yourtchenko-nat-reveal-ping
, qui a expiré
depuis. Cela marcherait pour tous les protocoles ayant la notion de
port (puisque c'est ce qu'on mettrait dans le
paquet ICMP pour indiquer de quelle session on parle). Et un problème
éventuel sur cette fonction de révélation de
l'HOST_ID (par exemple de l'ICMP bloqué) ne
gênerait pas la session normale (contrairement aux options IP ou
TCP). Par contre, on n'est pas sûr que ce soit la même machine qui
reçoive l'ICMP et qui reçoive les autres paquets (en cas d'utilisation
de répartiteurs de charge). Et cette technique
rend plus difficile l'examen de l'HOST_ID par des
intermédiaires, genre IDS.
Toujours dans la série « communications hors bande », l'idée de ressortir le vieux protocole IDENT (RFC 1413), qui récupérerait le HOST_ID par une connexion TCP vers la source d'une session. Il faudra donc un serveur IDENT dans la machine faisant le partage d'adresses et publier cette information (dans le DNS ?) pour éviter que les serveurs ne bombardent les pauvres CPE de requêtes IDENT. Il y a aussi des craintes quant aux performances de cette solution. Et quant à sa sécurité la requête IDENT pourrait être émise par un méchant.
Voilà, on a fait le tour de toutes les solutions envisageables. La section 5 de notre RFC présente une synthèse sous forme d'un tableau dont les lignes sont les solutions présentées plus haut et les colonnes sont les critères d'évaluation (« nécessite une modification de TCP/IP dans les machines », « a un impact sur les performances », « déployable aujourd'hui (sans refaire l'Internet de zéro) », etc).
Date de publication du RFC : Mai 2013
Auteur(s) du RFC : P. Saint-Andre (Cisco Systems)
Première rédaction de cet article le 24 mai 2013
Voici un nouvel espace de nommage pour les
URN, urn:example
, qui
servira pour les exemples et la documentation.
Les URN sont normalisés dans le RFC 8141 et offrent un moyen de construire des
URI stables et indépendants de toute notion de
localisation. L'URN commence par urn:
puis par un
NID (namespace identifier). Le RFC 3406
définissait trois genres de NID, formel, informel et expérimental (nom
commençant par x-
, et supprimé depuis par le RFC 8141). Lorsqu'on a besoin d'URN pour
une documentation ou un cours, on utilisait en général ces NID
expérimentaux. Mais les identificateurs commençant par
x-
sont désormais mal vus dans le monde
IETF (cf. RFC 6648) et ce
nouveau RFC propose donc d'abandonner ces NID expérimentaux et, pour
les exemples, d'utiliser le NID example
. De tels
noms réservés pour les exemples sont courants dans les RFC (par
exemple le RFC 2606 pour les noms de
domaine ou le RFC 5612 pour les
numéros d'organisations).
Ainsi, on peut désormais créer comme ça, gratuitement, l'URN
urn:example:foo:bar
et être sûr qu'il n'entrera
jamais en collision avec un « vrai » URN. (Par contre, deux URN
example
peuvent être accidentellement identiques
puisqu'aucune autorité ne les attribue.) Ces URN ne doivent être
utilisés qu'à des fins d'exemple et pas pour court-circuiter les
mécanismes normaux d'allocation des URN formels et informels, décrits dans le RFC 8141.
Date de publication du RFC : Juin 2013
Auteur(s) du RFC : B. Laurie, A. Langley, E. Kasper (Google)
Expérimental
Première rédaction de cet article le 7 juin 2013
Plusieurs attaques spectaculaires, notamment celle contre DigiNotar, ont montré la fragilité de l'actuel système de gestion de certificats X.509. Comme n'importe quelle AC peut émettre un certificat pour n'importe quel nom de domaine, il ne suffit pas d'évaluer la sécurité de son AC, il faudrait idéalement évaluer toutes les AC. Ce RFC propose une approche différente : encourager/obliger les AC à publier « au grand jour » les certificats qu'elles émettent. Un titulaire d'un certificat qui craint qu'une AC n'émette un certificat à son nom sans son autorisation n'a alors qu'à surveiller ces publications. (Il peut aussi découvrir à cette occasion que sa propre AC s'est fait pirater ou bien est devenue méchante et émet des certificats qu'on ne lui a pas demandés.) À noter qu'une deuxième version du système décrit ici a été publiée en décembre 2021, dans le RFC 9162 mais elle reste, fin 2021, peu déployée.
Ce n'est pas par hasard que les auteurs de ce RFC sont trois
employés de Google. Dans l'affaire
DigiNotar, comme dans d'autres affaires
analogues, le premier vrai/faux certificat émis par celui qui a piraté
une AC est souvent un certificat pour
gmail.com
, de façon à permettre d'espionner le
trafic vers Gmail. La proposition de ce RFC
(qui est encore expérimental) est d'empêcher l'émission « discrète »
de vrais/faux certificats qui seraient ensuite utilisés uniquement à
certains endroits (l'Iran dans le cas de
DigiNotar mais cela peut aussi concerner des entreprises qui font des
attaques de l'homme du milieu contre leurs propres employés).
Le principe est donc de créer un (ou plusieurs) journal des certificats émis. Le journal doit être public, pour que Google ou n'importe qui d'autre puisse l'auditer. Il doit être en mode « ajout seulement » pour éviter qu'on puisse réécrire l'histoire. Les certificats sont déjà signés mais le journal a ses propres signatures, pour prouver son intégrité. Conceptuellement, ce journal est une liste de certificats dans l'ordre de leur création. Toute AC peut y ajouter des certificats (la liste ne peut pas être ouverte en écriture à tous, de crainte qu'elle ne soit remplie rapidement de certificats bidons). En pratique, le RFC estime que la liste des AC autorisées à écrire dans le journal sera l'union des listes des AC acceptées dans les principaux navigateurs Web (voir aussi la section 4.7).
À chaque insertion, le journal renvoie à l'AC une estampille temporelle signée, permettant à l'AC de prouver qu'elle a bien enregistré le certificat. Si une AC peut présenter cette signature mais que le certificat est absent du journal, l'observateur aura la preuve que le journal ne marche pas correctement. Le format exact de cette estampille temporelle est décrit en section 3.2. Elle devra être envoyée au client par les serveurs TLS, comme preuve de la bonne foi de l'AC (cf. sections 3.3 et 5.2).
Les titulaires de certificats importants, comme Google, mais aussi des chercheurs, des agences de sécurité, etc, pourront alors suivre l'activité de ce(s) journal (journaux) public(s) (section 5.3 du RFC). Ce qu'ils feront en cas de détection d'un certificat anormal (portant sur leur nom de domaine, mais qu'ils n'ont pas demandé) n'est pas spécifié dans le RFC : cela dépend de la politique de l'organisation concernée. Ce RFC fournit un mécanisme, son usage n'est pas de son ressort. Ce journal n'empêchera donc pas l'émission de vrais/faux certificats, ni leur usage, mais il les rendra visibles plus facilement et sans doute plus vite.
Pour que cela fonctionne, il faudra que les clients TLS vérifient que le certificat présenté est bien dans le journal (autrement, le méchant n'aurait qu'à ne pas enregistrer son vrai/faux certificat, cf. section 5.4 du RFC).
En pratique, la réalisation de ce journal utilise un arbre de Merkle, une structure de données qui permet de mettre en œuvre un système où l'ajout de certificats est possible, mais pas leur retrait. La section 2 du RFC détaille l'utilisation de ces arbres et la cryptographie utilisée.
Le protocole utilisé entre les AC et le journal, comme celui
utilisé entre les clients TLD et le journal, sera
HTTP et le format des données sera
JSON (section 4). Ainsi, pour ajouter un
certificat nouvellement émis au journal géré sur
sunlight-log.example.net
, l'AC fera :
POST https://sunlight-log.example.net/ct/v1/add-chain
et le corps de la requête HTTP sera un tableau JSON de certificats encodés en Base64. La réponse contiendra notamment l'estampille temporelle (SCT pour Signed Certificate Timestamp). Pour récupérer des certificats, le programme de surveillance fera par exemple :
GET https://sunlight-log.example.net/ct/v1/get-entries
D'autres URL permettront de récupérer les condensats cryptographiques contenus dans l'arbre de Merkle, pour s'assurer qu'il est cohérent.
Notez que Google a produit une mise en œuvre de ce RFC, qui semble activement développée. Et il existe un pilote écrit en Go. Il y a aussi une liste de diffusion sur ce projet et un site officiel du projet par Google. Sinon, si vous voulez en savoir plus sur cette idée de vérification publique, consultez « Efficient Data Structures for Tamper-Evident Logging » de Scott A. Crosby et Dan S. Wallach. Autres lectures sur la certificate transparency, un article de promotion de Ben Laurie et un article violemment critique.
Quelles sont les chances de succès de cette idée ? Tant que peu d'AC participent, ces journaux ne serviront pas à grand'chose (le méchant attaquera uniquement les AC non participantes). L'idée est qu'à moyen terme, la pression sur les AC (directement ou bien via les navigateurs Web qui ne feraient plus confiance aux AC non participantes) pourra faire que tous les certificats devront être dans le journal et que l'examen de celui-ci suffira à détecter les « vrais/faux certificats ».
Merci à Florian Maury pour sa relecture très détaillée.
Date de publication du RFC : Juin 2013
Auteur(s) du RFC : S. Santesson (3xA Security), M. Myers
(TraceRoute
Security), R. Ankney, A. Malpani (CA
Technologies), S. Galperin (A9), C. Adams (University of Ottawa)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF pkix
Première rédaction de cet article le 7 juin 2013
Le protocole OCSP permet à un client X.509 (par exemple un navigateur Web engagé dans une connexion HTTPS) de s'informer en temps réel sur l'état d'un certificat, notamment afin de savoir s'il est révoqué ou pas. Ce nouveau RFC remplace (avec de légers changements) l'ancienne norme OCSP qui était dans le RFC 2560.
Normalement, le destinataire d'un certificat X.509 (par exemple le navigateur Web cité plus haut), authentifie ce dernier en utilisant les clés publiques des AC qu'il a dans son magasin, et en vérifiant dans une liste de CRL, mise à jour périodiquement, que le certificat est toujours d'actualité, qu'il n'a pas été révoqué par l'AC émettrice (section 3.3 du RFC 5280). En complément, ou à la place de ces CRL, le destinataire peut utiliser le protocole OCSP normalisé dans ce RFC. OCSP est un protocole synchrone : le destinataire du certificat émet une requête à un serveur OCSP et attend sa réponse avant de valider le certificat. Il peut ainsi obtenir des informations plus à jour qu'avec des CRL.
La requête OCSP contient (un survol du protocole figure en section
2 de ce RFC) le numéro de série du certificat qu'on veut authentifier. La réponse dépend
de si le répondeur (le serveur OCSP) a l'information sur ce
certificat. Si oui, il répond positivement (good
,
le certificat est valable)
ou négativement (revoked
, le certificat ne doit pas être accepté), en indiquant
l'heure (un certificat valable à un moment peut être révoqué par la
suite) et sa réponse est signée (typiquement
avec le certificat de l'AC). Si non, si le
répondeur n'a pas l'information, il répond unknown
.
Les réponses possibles sont donc good
,
revoked
et unknown
. Notez
que, de manière surprenante, good
ne dit pas que le certificat existe,
simplement qu'il n'a pas été révoqué. (Cette question a fait l'objet
de chauds débats dans le groupe de travail : que doit faire un
répondeur OCSP lorsqu'il reçoit une requête pour un certificat qu'il
est censé connaître mais qu'il
n'a pas émis ?)
Le répondeur peut aussi être dans l'incapacité de fournir une
réponse et, dans ce cas, le message d'erreur résultant n'est pas
signé. Parmi les causes possibles d'erreur, une requête incorrecte,
une erreur dans le répondeur (équivalent du 500 Internal
server error
de HTTP), un problème
temporaire qui nécessite que le client réessaie plus tard, un client
non autorisé, etc.
La réponse inclut souvent des temps : dernier moment où l'information retournée était correcte, moment de la prochaine mise à jour de l'information, moment de la signature de l'information (les réponses peuvent être pré-produites) ou moment où la révocation a eu lieu.
Mais comment un destinataire de certificat sait-il
où trouver le serveur OCSP ? Il est typiquement indiqué dans le
certificat qu'on teste, dans l'extension Authority Information
Access (section 4.2.2.1 du RFC 5280). Si la méthode d'accès est
id-ad-ocsp
, le contenu de cette extension est un
URL pointant
vers le serveur OCSP.
Voici un exemple dans un certificat récupéré sur l'Internet :
% openssl x509 -text -in /tmp/site.pem ... Authority Information Access: OCSP - URI:http://rapidssl-ocsp.geotrust.com CA Issuers - URI:http://rapidssl-aia.geotrust.com/rapidssl.crt
Mais cette information peut aussi être codée en dur dans le client.
La plupart du temps, l'URL en question sera un URL
HTTP, et OCSP tournera donc au dessus de ce
protocole (parfois en HTTPS). L'annexe A décrit en détail ce mécanisme. OCSP peut
utiliser GET
ou POST
. Dans
ce dernier cas, la requête HTTP aura le type
application/ocsp-request
et la requête OCSP forme le corps de la requête
POST
, après son encodage en
DER. Même chose pour la réponse, type
application/ocsp-response
, et du DER dans le
corps HTTP.
Voilà, vous savez l'essentiel, la section 4 décrit tout le
protocole, en ASN.1 (en s'appuyant sur les
modules de l'annexe B). Par exemple, une requête
est une TBSRequest
qui contient plusieurs
Request
, chacune concernant un certificat :
OCSPRequest ::= SEQUENCE { tbsRequest TBSRequest, optionalSignature [0] EXPLICIT Signature OPTIONAL } TBSRequest ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, requestorName [1] EXPLICIT GeneralName OPTIONAL, requestList SEQUENCE OF Request, requestExtensions [2] EXPLICIT Extensions OPTIONAL } ... Request ::= SEQUENCE { reqCert CertID, singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } CertID ::= SEQUENCE { hashAlgorithm AlgorithmIdentifier, issuerNameHash OCTET STRING, -- Hash of Issuer's DN issuerKeyHash OCTET STRING, -- Hash of Issuers public key serialNumber CertificateSerialNumber }
Et la réponse est un code de retour et la réponse elle-même :
OCSPResponse ::= SEQUENCE { responseStatus OCSPResponseStatus, responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } OCSPResponseStatus ::= ENUMERATED { successful (0), --Response has valid confirmations malformedRequest (1), --Illegal confirmation request internalError (2), --Internal error in issuer tryLater (3), --Try again later --(4) is not used sigRequired (5), --Must sign the request unauthorized (6) --Request unauthorized } ResponseBytes ::= SEQUENCE { responseType OBJECT IDENTIFIER, response OCTET STRING }
Avec response
comportant à son tour des
structures ASN.1 arrivant finalement à :
SingleResponse ::= SEQUENCE { certID CertID, certStatus CertStatus, thisUpdate GeneralizedTime, nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, singleExtensions [1] EXPLICIT Extensions OPTIONAL } CertStatus ::= CHOICE { good [0] IMPLICIT NULL, revoked [1] IMPLICIT RevokedInfo, unknown [2] IMPLICIT UnknownInfo } RevokedInfo ::= SEQUENCE { revocationTime GeneralizedTime, revocationReason [0] EXPLICIT CRLReason OPTIONAL }
On note que la raison de la révocation est indiquée. Elle n'est pas toujours indiquée par le répondeur OCSP (cela peut être une information sensible). La présence de cette information dans les CRL a permis à l'EFF de réaliser une intéressante étude sur les raisons des révocations (la section « How often are these attacks occurring? »).
La section 5 revient sur l'analyse de sécurité d'OCSP. On notera que les problèmes de vie privée n'y sont pas mentionnés. Pourtant, la requête OCSP indique au répondeur (en général l'AC) quels sites Web ont été visités. C'est d'ailleurs ainsi qu'il a été possible de prouver l'utilisation en Iran des vrais/faux certificats de DigiNotar, en regardant les requêtes OCSP de leurs navigateurs vers l'AC.
Un autre problème de sécurité n'est pas mentionné : que doit faire le navigateur Web qui tente d'authentifier un certificat lorsque la requête OCSP n'aboutit pas (peut-être parce qu'un Homme du Milieu bloque l'accès au serveur OCSP) ? S'il refuse d'authentifier le certificat, la connexion échoue. Mais s'il accepte, OCSP ne protège plus tellement.
Les changements depuis le RFC 2560 sont mineurs, et sont résumés dans la section 1.
Merci à Erwann Abalea pour sa relecture précise.
Date de publication du RFC : Mai 2013
Auteur(s) du RFC : D. McPherson (VeriSign), F.J. Baker (Cisco Systems), J.M. Halpern (Ericsson)
Pour information
Réalisé dans le cadre du groupe de travail IETF savi
Première rédaction de cet article le 30 mai 2013
On sait que, sur l'Internet, il est possible et même facile d'usurper une adresse IP , c'est-à-dire d'émettre un paquet IP avec une adresse source allouée à quelq'un d'autre (ou pas allouée du tout). Le projet SAVI (Source Address Validation Improvement) vise à améliorer la validation de l'adresse source, de manière à rendre l'usurpation plus rare et plus difficile. Ce RFC décrit la menace à laquelle SAVI répondra et étudie les contre-mesures existantes.
L'Internet emploie un protocole de réseau sans connexion (que ce soit en IPv4 ou en IPv6). Lorsqu'une machine veut communiquer avec une autre, elle met son adresse IP comme source d'un paquet, celle de son correspondant en destination et elle envoie le paquet. Substituer l'adresse IP d'une autre machine à la sienne est donc aussi simple que d'écrire une autre chaîne de bits à la place de l'adresse authentique. Le réseau n'essaie pas d'empêcher cela. Certes, le fraudeur ne pourra pas forcément recevoir les réponses (elles arriveront à celui dont l'adresse a été usurpée) mais ce n'est pas forcément un problème dans un réseau sans connexion. Il existe des mécanismes pour empêcher cette usurpation, le plus connu étant BCP 38 (les RFC 2827 et RFC 3704) mais ils sont insuffisamment déployés, car ils n'apportent pas de bénéfices à celui qui les déploie, uniquement aux autres acteurs de l'Internet. En outre, BCP 38 ne protège pas toujours suffisamment. Par exemple, s'il est mis en œuvre dans le premier routeur, il n'empêchera pas les machines du LAN d'usurper les adresses de leurs voisines.
L'une des idées de SAVI est donc de compléter BCP 38 avec des validations locales, apportant un bénéfice local, et qui permettraient une meilleure traçabilité.
Quelques termes à apprendre pour bien suivre les documents sur SAVI :
La section 3 détaille ensuite les attaques rendues possibles, ou facilitées par l'usurpation d'adresses IP source (la section 4 couvrira les contre-mesures). D'abord, les attaques en aveugle : l'assaillant, qui a usurpé l'adresse IP source, ne peut pas recevoir les réponses à ses paquets. Il peut les envoyer, ces paquets, mais c'est tout. Cela lui complique évidemment sérieusement la vie. Certaines attaques restent possibles. Il y a celles ne nécessitant qu'un seul paquet (et donc pas de réponse). Par exemple, si un paquet spécialement construit plante le logiciel du routeur qui le traite, un attaquant peut monter une attaque par déni de service en envoyant un unique packet of death. Un autre cas est celui où, en envoyant un paquet où l'adresse source et destination sont identiques, le destinataire se réponde à lui-même, puis à la réponse de la réponse, et entretienne ainsi lui-même la boucle sans fin (une bogue de cette famille avait frappé PowerDNS).
Une autre attaque en aveugle est le RST (ReSeT) TCP usurpé (section 2.3 du RFC 4953). Un seul paquet TCP accepté (l'attaquant doit deviner un numéro de séquence contenu dans la fenêtre en cours) va couper la connexion (notez que les protocoles applicatifs comme TLS et SSH ne sont d'aucune utilité contre cette attaque). Cela peut être très gênant pour les connexions censées durer longtemps (sessions BGP par exemple). Il existe des contre-mesures (voir le RFC 5961) mais empêcher l'usurpation d'adresse IP empêcherait complètement cette attaque.
Après les attaques en aveugle formées d'un seul paquet, place aux attaques volumétriques, reposant sur l'envoi d'un grand nombre de paquets. L'idée est de remplir certaines tables de taille fixe (par exemple la table des connexions entrantes) ou, encore plus simplement, de saturer le réseau de la victime. L'attaquant n'ayant pas besoin de réponse, il a tout intérêt, dans ces paquets, à usurper l'adresse IP source pour déguiser son identité. On constate que beaucoup de gens n'ont pas encore compris la facilité avec laquelle cette usurpation est possible, et croient réellement que l'adresse IP source qu'ils observent dans les paquets entrants est réellement celle de leur attaquant (pensez à cela la prochaine fois que vous lirez dans les médias quelque chose du genre « attaque par déni de service contre tel organisme, l'examen de l'attaque montrait que l'attaquant venait de Russie/Chine/Moyen-Orient »). Pire, la victime bloque parfois les paquets IP entrants en fonction de cette adresse source, réalisant ainsi une autre attaque par déni de service, contre la victime de l'usurpation d'adresse. Certaines attaques peuvent d'ailleurs être montées dans ce seul but.
Une autre raison pour l'attaquant d'usurper l'adresse IP source est la possibilité d'attaque par réflexion : comme au billard, on va viser une autre boule que celle qu'on veut vraiment toucher. L'attaquant envoie un paquet UDP au réflecteur (qui n'est pas sa vraie victime, juste un complice involontaire) en usurpant l'adresse IP source de la victime. Le réflecteur va alors répondre à ce qu'il croit être l'émetteur et qui est en fait la victime, qui sera ainsi bombardée par le ou les réflecteurs. La réflexion sert à l'attaquant à dissimuler ses traces (le paquet va suivre un tout autre chemin dans le réseau) mais elle est surtout intéressante couplée avec l'amplification. Avec certains protocoles, la réponse va être plus grande, voire beaucoup plus grande, que la requête. Avec une amplification de 20, l'attaquant pourra ainsi obtenir un bombardement de 1 Gb/s en ne dépensant lui-même que 50 Mb/s. Plusieurs protocoles permettent l'amplification, comme NTP, SNMP et surtout le DNS comme ce fut le cas lors de l'attaque de 2006 (le RFC ne les cite pas mais des attaques plus violentes ont eu lieu en 2012 et 2013).
Le RFC classe aussi dans les attaques volumétriques les actions visant à empoisonner les données d'un serveur distant. Le cas le plus courant est celui des empoisonnements DNS où le méchant va tenter de répondre avant le serveur légitime (cas, par exemple, des attaques Kaminsky). Ici, le volume élevé des requêtes n'est pas dû au désir de saturer la victime, mais à la nécessité de faire beaucoup d'essais pour en voir un accepté. (Dans le cas du DNS, il s'agit d'essayer beaucoup de Query ID et de ports source UDP.) À noter qu'il existe aussi des attaques par empoisonnement contre les caches ARP.
Cela, c'était les attaques en aveugle. Mais, parfois, un attaquant qui usurpe une adresse IP peut observer les réponses, par exemple parce qu'il est sur le même réseau local à diffusion que la victime de l'usurpation ou bien, si le réseau local ne diffuse pas à tous, parce qu'il a empoisonné les caches ARP. L'attaquant a alors bien plus de possibilités comme le détournement d'une connexion TCP à son profit, les tests de vulnérabilité d'un objectif sans se trahir, la subversion des protocoles de routage en se faisant passer pour un des routeurs participants, etc.
La section 4 décrit ensuite les contre-mesures qui peuvent être
adoptées aujourd'hui et qui sont effectivement déployées, au moins
partiellement. Par exemple, un commutateur peut
(en violant légèrement le modèle en couches),
refuser les paquets dont l'adresse IP source ne correspond pas à
l'adresse MAC du paquet (que le commutateur a pu apprendre en
examinant les requêtes et réponses ARP). Ou bien ceux qui viennent d'un autre port
physique que d'habitude. Si les paquets de
192.168.7.64
venaient toujours du port 3 et que,
tout à coup, ils viennent du port 4, le commutateur peut soupçonner
une usurpation (ou tout simplement une machine qui a été déplacée : la
sécurité peut se tromper).
On peut donc jeter un paquet lorsque son adresse IP source ne correspond pas aux informations qu'on possède. Notez bien que, plus on s'éloigne de la source des paquets, plus il est difficile d'être sûr que c'est bien une usurpation. Néanmoins, le RFC identifie cinq endroits où peut se faire cet examen de validité, du plus proche de la source au plus éloigné :
2001:db8:32:a17::/64
à l'Internet peut
raisonnablement jeter un paquet venant du réseau local et prétendant
avoir comme source 2001:db8:cafe::666
. Notez que
le routeur ne peut en général rien faire contre une machine qui
usurperait une adresse du même réseau local (ici,
2001:db8:32:a17::b00c
qui se ferait passer pour
2001:db8:32:a17::babe
). Dans des cas moins
triviaux (routeurs avec beaucoup d'interfaces et ayant de nombreux préfixes derrière eux), pour savoir quels
préfixes sont acceptables, le routeur peut simplement consulter une
ACL maintenue manuellement ou alors utiliser
RPF (RFC 3704).En pratique, il y a des tas de détails qui compliquent la validation d'adresse IP source. Par exemple, pour un commutateur réseau, le cas simple est celui où il y a une et une seule machine derrière chaque port physique et où chaque adresse MAC ne correspond qu'à une seule adresse IP. Si ce n'est pas le cas, le problème devient plus difficile. Pensez par exemple à une machine physique, connectée par le port d'un commutateur mais portant plusieurs machines virtuelles, chacune avec sa propre adresse IP et sans doute sa propre adresse MAC. Ce cas est en fait un commutateur interne, le commutateur physique n'étant que le deuxième commutateur sur le trajet et n'ayant donc que des capacités de validtaion limitées. Idéalement, c'est le commutateur virtuel dans le système de virtualisation qui devrait faire respecter les règles SAVI, mais l'administrateur réseaux n'en a pas forcément le contrôle et ne lui fait pas forcément confiance.
Pour apprendre le lien entre une adresse MAC et une adresse IPv4, la meilleure solution pour un commutateur est d'écouter les requêtes et les réponses DHCP et de considérer qu'elles font autorité au sujet de ce lien (cf. RFC 7513). Par exemple, en voyant passer cette réponse (vue avec tcpdump) :
09:49:23.191187 00:10:db:ff:40:70 > 18:03:73:66:e5:68, ethertype IPv4 (0x0800), length 368: (tos 0x0, ttl 64, id 16537, offset 0, flags [none], proto UDP (17), length 354) 192.0.2.20.67 > 192.0.2.54.68: BOOTP/DHCP, Reply, length 326, hops 1, xid 0x903b4b00, Flags [none] Your-IP 192.0.2.54 Client-Ethernet-Address 18:03:73:66:e5:68 ...
Le commutateur sait alors que l'adresse IP
192.0.2.54
a été allouée à
18:03:73:66:e5:68
et qu'un paquet IP dont
l'adresse MAC source serait 18:03:73:66:e5:68
et
l'adresse IP source serait autre chose que
192.0.2.54
est probablement une usurpation et
doit être jeté.
Pour IPv6, outre le trafic DHCP, le commutateur doit écouter les paquets DAD (Duplicate Address Detection) du protocole d'auto-configuration (RFC 4862). Le commutateur sera alors au courant des adresses IP légitimement enregistrées, et de l'adresse MAC correspondante, et pourra se servir de cette information pour valider. Par contre, contrairement à ce qu'on pourrait penser, le protocole d'authentification 802.1x n'aide pas : il authentifie un utilisateur mais ne limite pas les adresses IP qu'il peut utiliser. Enfin, il existe des techniques cryptographiques qui pourraient être utiles pour SAVI comme le SEND du RFC 3971 mais qui sont tellement peu déployées qu'on ne peut pas réellement compter dessus.
Certaines topologies de réseau, quoique parfaitement légales, peuvent sérieusement handicaper SAVI (section 5). Par exemple, si toutes les adresses sont statiques et stables, le problème est relativement bien circonscrit. Mais dans beaucoup de réseaux, ce n'est pas le cas et des adresses sont attribuées dynamiquement. Une même adresse IP sera, dans le temps, allouée à plusieurs adresses MAC et une même adresse MAC n'aura pas forcément la même adresse IP à chaque visite de ce réseau. (Ceux qui utilisent arpwatch sur un tel réseau savent le nombre d'« alarmes » que cela génère. SAVI a exactement le même problème.) D'autre part, si certaines machines sont simples (une adresses MAC, une adresse IP), d'autres sont plus complexes pour le validateur. Un exemple typique est un routeur. Par définition, il émet sur le réseau local des paquets avec sa propre adresse MAC mais des adresses IP source qui ne sont pas la sienne. Il est donc difficile de valider ces paquets.
Autre cas rigolo, notamment en cas de virtualisation : si une machine se déplace dans le data center mais garde son adresse IP. Les commutateurs vont devoir oublier la vieille information sur le port où est connecté cette machine et apprendre la nouvelle. (On appelle cela « mettre à jour son état SAVI ».)
La mobilité entraîne aussi des problèmes. Dans IP, elle peut se réaliser de plusieurs façons. Dans l'une, dite « en jambe de chien », la machine mobile émet des paquets avec son adresse IP source stable (home address), quel que soit le réseau physique où elle est attachée. Un tel mécanisme est évidemment incompatible avec toute solution de validation. Il faut donc que tous les paquets du mobile, aussi bien en émission qu'en réception, soient relayés par la station de base située sur son réseau d'attachement habituel.
Un petit mot aussi sur IPv6 : il crée des difficultés supplémentaires en raison de l'auto-configuration, très pratique mais, par son caractère local, non contrôlé centralement, pas forcément très sûre. Et son espace d'adressage très large (une bonne chose, et la principale raison pour laquelle il est important de déployer IPv6) a comme effet de bord la facilité à utiliser beaucoup d'adresses usurpées. En IPv4, un usurpateur a en théorie 2^32 adresses à usurper et, en pratique, plutôt moins de 2^24 (uniquement celles de son réseau local). En IPv6, même si on arrive à limiter l'usurpateur à son réseau local, il aura 2^64 adresses, ce qui permet de court-circuiter certains mécanismes de sécurité.
La section 6 revient en détail sur la question de la granularité de la validation. Aujourd'hui, il est relativement facile d'empêcher les usurpations inter-sites (où un attaquant prend l'adresse IP d'une machine sur un autre site). Mais empêcher les usurpations intra-sites est plus complexe or, justement, la plupart des attaques viennent de l'intérieur.
Notez que SAVI se limite aux couches basses : il n'est pas prévu de
vérifier les adresses IP qui apparaissent dans les applications (par
exemple dans le champ Received:
des messages
formatés suivant le RFC 5322).
Enfin, la section 7 revient sur les questions de sécurité à un haut niveau. Elle rappelle que SAVI n'a pas pour but de produire des preuves, au sens judiciaire du terme (dans le meilleur cas, la validation permet de s'assurer de l'adresse IP, mais certaines machines sont multi-utilisateurs). Elle rappelle aussi que SAVI est une technique relativement légère et que, même si elle était massivement déployé, il ne faudrait pas utiliser les adresses IP source comme authentiques. La seule solution fiable pour être certain de l'identité de son correspondant est la cryptographie.
Cette section 7 revient aussi en détail sur les conséquences de SAVI pour la vie privée. Une adresse IP peut être vue, dans certains cas, comme une donnée identifiant une personne et le fait de la valider a donc des implications. Le RFC note bien que la validation SAVI ne nécessite pas d'enregistrer de l'information et que, si on réalise cet enregistrement avec des adresses IP, on peut engager sa responsabilité morale et/ou légale.
Aujourd'hui, des fonctions de type SAVI sont présentes dans pas mal de systèmes (par exemple les commutateurs haut de gamme) mais pas forcément toujours activées. Le RFC 5210 contient un compte-rendu d'expériences à ce sujet.
Date de publication du RFC : Juin 2013
Auteur(s) du RFC : W. Wang (Zhejiang Gongshang University), E. Haleplidis (University of Patras), K. Ogawa (NTT Corporation), C. Li (Hangzhou DPtech), J. Halpern (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF forces
Première rédaction de cet article le 29 juin 2013
Le protocole ForCES vise à permettre la création d'équipements réseaux (par exemple des routeurs) en assemblant des pièces d'origines diverses, parlant un protocole commun et pouvant donc interagir. Ce RFC marque l'achèvement de la première (et très longue) phase de ForCES, la normalisation complète de ce protocole. Notre RFC 6956 décrit la bibliothèque standard de ForCES, les parties d'un routeur qu'on trouvera partout et qui assurent les fonctions indispensables comme faire suivre un paquet IP.
ForCES peut servir à bien d'autres choses et il y aura aussi des bibliothèques pour d'autres équipements que les routeurs, et aussi des bibliothèques non-standard, développées par tel ou tel projet. Mais pour atteindre l'objectif premier de ForCES, créer un routeur par assemblage de pièces standards, cette bibliothèque « routeur » était le dernier élement manquant.
Avant de lire ce RFC 6956, il faut bien se pénétrer du cadre général (RFC 3746), du protocole (RFC 5810) et du modèle de données (RFC 5812). J'en extrais quelques termes qu'il faut connaître :
Ethernet/0/2
», etc). Un LFB est une fonction logique : dans la matériel, on ne
retrouve pas forcément ce concept.La bibliothèque composée des classes définies dans ce RFC 6956 permet de réaliser un routeur complet, mettant en œuvre toutes les fonctions obligatoires du RFC 1812, notamment :
Place maintenant au cœur de ce RFC, les classes qui y sont définies. Le choix du groupe de travail forces (section 3.2) a été de privilégier la souplesse en définissant plutôt trop de classes que pas assez. Chaque classe ne va donc effectuer qu'un minimum de fonctions, être logiquement séparée des autres classes et notre routeur devra donc mettre en œuvre beaucoup de classes. Cela rend donc le RFC très long et je ne vais donc pas parler de toutes les classes, seulement de quelques unes choisies comme exemples. Pour la totalité des classes, vous devez lire le RFC.
Les définitions des classes s'appuient sur un certain nombre de
types définis en section 4. Le RFC 5812 avait
normalisé les types de base comme uint32
,
char
ou
boolean
. Notre RFC y ajoute quelques types
atomiques comme IPv4Addr
,
IPv6Addr
, IEEEMAC
(une
adresse MAC),
PortStatusType
(permettant d'indiquer si le port
est activé ou non et s'il fonctionne), VlanIDType
pour le numéro de VLAN, etc. Il définit
également des types composés comme MACInStatsType
(une entrée dans le tableau de statistiques pour les paquets entrants, analysés à la
couche 2), IPv6PrefixInfoType
(un préfixe IPv6),
IPv4UcastLPMStatsType
(une entrée dans le tableau de
statistiques pour les paquets IPv4), etc. Logiquement, les
tableaux qui utilisent ces types sont également définis comme
IPv6PrefixTableType
(un tableau de préfixes IPv6)
ou VlanInputTableType
(un tableau de
VLAN).
Un NE manipule des paquets donc il y a évidemment des types de
paquets parmi lesquels EthernetII
,
IPv4
, IPv6
, et même
Arbitrary
pour des paquets quelconques.
Le tout est formellement décrit en XML dans la section 4.4. Ainsi, une adresse IPv4 est :
<dataTypeDef> <name>IPv4Addr</name> <synopsis>IPv4 address</synopsis> <typeRef>byte[4]</typeRef> </dataTypeDef>
et une IPv6 est :
<dataTypeDef> <name>IPv6Addr</name> <synopsis>IPv6 address</synopsis> <typeRef>byte[16]</typeRef> </dataTypeDef>
Un type atomique comme la capacité du lien est définie par :
<dataTypeDef> <name>LANSpeedType</name> <synopsis>LAN speed type</synopsis> <atomic> <baseType>uint32</baseType> <specialValues> <specialValue value="0x00000001"> <name>LAN_SPEED_10M</name> <synopsis>10M Ethernet</synopsis> </specialValue> <specialValue value="0x00000002"> <name>LAN_SPEED_100M</name> <synopsis>100M Ethernet</synopsis> </specialValue> ...
Même chose pour le PortStatusType
mentionné plus haut :
<dataTypeDef> <name>PortStatusType</name> <synopsis> Type for port status, used for both administrative and operative status. </synopsis> <atomic> <baseType>uchar</baseType> <specialValues> <specialValue value="0"> <name>Disabled</name> <synopsis>Port disabled</synopsis> </specialValue> <specialValue value="1"> <name>Up</name> <synopsis>Port up</synopsis> </specialValue> <specialValue value="2"> <name>Down</name> <synopsis>Port down</synopsis> </specialValue> </specialValues> </atomic> </dataTypeDef> <dataTypeDef>
Et les types structurés ? Un exemple est celui des statistiques sur les paquets sortants, qui a deux composants (les champs des objets), un pour les paquets transmis et un pour les paquets jetés :
<dataTypeDef> <name>MACOutStatsType</name> <synopsis> Data type defined for statistics in EtherMACOut LFB. </synopsis> <struct> <component componentID="1"> <name>NumPacketsTransmitted</name> <synopsis>Number of packets transmitted</synopsis> <typeRef>uint64</typeRef> </component> <component componentID="2"> <name>NumPacketsDropped</name> <synopsis>Number of packets dropped</synopsis> <typeRef>uint64</typeRef> </component> </struct> </dataTypeDef>
Un autre exemple est le préfixe IPv6, qui réutilise le type atomique IPv6Addr
:
<dataTypeDef> <name>IPv6PrefixInfoType</name> <synopsis>Data type for entry of IPv6 longest prefix match table in IPv6UcastLPM LFB. The destination IPv6 address of every input packet is used as a search key to look up the table to find out a next hop selector.</synopsis> <struct> <component componentID="1"> <name>IPv6Address</name> <synopsis>The destination IPv6 address</synopsis> <typeRef>IPv6Addr</typeRef> </component> <component componentID="2"> <name>Prefixlen</name> <synopsis>The prefix length</synopsis> <atomic> <baseType>uchar</baseType> <rangeRestriction> <allowedRange min="0" max="32"/> </rangeRestriction> </atomic> </component> ...
Une fois tous ces types définis (et cela prend un bon bout du RFC),
on peut les utiliser pour bâtir les classes (section 5). Chaque classe
va être un gabarit dont on tirera les instances. Premier exemple :
notre routeur ForCES va évidemment avoir besoin de connaître
Ethernet et de traiter des paquets Ethernet, en
envoi et en réception. Ethernet étant très varié, commençons par un
LFB (Logical Function Block) qui représente le
niveau physique, EtherPHYCop
. Ce LFB (cette
partie logique d'un routeur) a des composants pour indiquer l'état du
port (AdminStatus
et
OperStatus
), composants qui peuvent être lus et
modifiés via le protocole ForCES. Ce LFB peut aussi générer des
événements comme par exemple le changement d'état d'un port
(PHYPortStatusChanged
).
Au niveau au dessus (couche 2), il y a le
LFB EtherMACIn
. C'est par exemple là que se
trouve le composant LocalMACAddresses
qui indique
l'adresse MAC. ou bien le composant
PromiscuousMode
qui dit si on veut recevoir (ou
pas) tous les paquets, même adressés à une autre machine.
Rappelez-vous : cette bibliothèque standard de ForCES privilégie la
souplesse, et crée donc beaucoup de LFB, pour
pouvoir les arranger comme souhaité. Rien que pour Ethernet, il y en a
encore plusieurs comme EtherEncap
qui modélise
les fonctions d'encapsulation et de décapsulation des
trames (ajout ou retrait des en-têtes
Ethernet).
Mais on ne peut pas passer toute la journée sur les couches
basses. Pour « construire » un routeur par assemblage de LFB, il nous
faut maintenant des fonctions de manipulation
d'IP. C'est le cas du LFB
IPv6Validator
qui représente les fonctions de
validation d'un paquet (avant qu'on décide de le traiter, ou de le
jeter s'il est invalide). On suit le RFC 2460 et
on considère comme invalide (ne devant pas être transmis) les paquets
ayant une taile inférieure à la taille minimale, les paquets
ayant une adresse source ou destination inacceptable, etc. Il y a
aussi des paquets nommés « exceptionnels » qui, sans être à proprement
parler invalides, ne pourront pas être transmis normalement (par
exemple ceux avec un hop limit descendu à
zéro).
Et, ensuite, le travail sera fait par les LFB de transmission. Oui,
ils sont plusieurs. Pour IPv6, au moins IPv6UcastLPM
(trouver le LPM, Longest Prefix Match, dans la
table) et IPv6NextHop
(sélection du routeur
suivant), sans compter des futurs LFB optionnels, par exemple pour
mettre en œuvre RPF.
Les LFB sont eux aussi formalisés en XML
(section 6). Par exemple, le dernier que nous avons vu,
IPv6NextHop
, sera :
<LFBClassDef LFBClassID="13"> <name>IPv6NextHop</name> <synopsis> The LFB abstracts the process of next hop information application to IPv6 packets. It receives an IPv6 packet with an associated next hop identifier (HopSelector), uses the identifier as a table index to look up a next hop table to find an appropriate output port. </synopsis> <inputPorts> <inputPort group="false"> <name>PktsIn</name> <synopsis> A port for input of unicast IPv6 packets, along with a HopSelector metadata. </synopsis> ... </inputPort> </inputPorts> <outputPorts> ... </outputPorts> <components> <component componentID="1"> <name>IPv6NextHopTable</name> <synopsis> The IPv6NextHopTable component. A HopSelector is used to match the table index to find out a row which contains the next hop information result. </synopsis> <typeRef>IPv6NextHopTableType</typeRef> </component> </components> </LFBClassDef>
Si la tête commence à vous tourner sérieusement, c'est sans doute
normal et prévu. Les auteurs du RFC ont pensé à vous et inclus une
section 7 qui décrit comment on crée une fonction de haut niveau à
partir des LFB de cette bibiothèque standard. Leur premier exemple est
la transmission de paquets IPv4 et le dessin ne compte pas moins de
treize LFB... (Dont, il est vrai, neuf juste pour Ethernet.) Pour
ajouter ARP, cela prend sept LFB (certains sont
communs par exemple EtherEncap
est utilisé à la
fois par la transmission de paquets IPv4 et par ARP).
Les classes des LFB sont désormais dans un registre IANA, ce qui permettra d'en ajouter plus facilement d'autres.
Voilà, arrivé à ce stade, on a de quoi « fabriquer » un routeur ou plus exactement de quoi le modéliser. En pratique, les vrais routeurs seront bien différents mais ils exporteront aux clients ForCES des fonctions représentées par ces LFB standards, fonctions qu'on pourra configurer avec Forces.
Date de publication du RFC : Mai 2013
Auteur(s) du RFC : J. Schaad (Soaring Hawk Consulting), H. Prafullchandra (Hy-Trust)
Chemin des normes
Première rédaction de cet article le 30 mai 2013
Lorsqu'on détient une clé cryptographique privée et qu'on veut le prouver à un correspondant, la méthode la plus simple et la plus standard est de signer un message avec cette clé et de l'envoyer audit correspondant, qui, en vérifiant la signature, s'assurera qu'on était bien en possession de la clé privée. Mais dans certains cas, signer n'est pas possible. Ce RFC décrit trois algorithmes qui permettent de prouver qu'on connait une clé, sans signer. Il remplace le RFC 2875.
Ce test de POP (Proof Of Possession) est un de ceux que doit faire, par exemple, une autorité de certification, avant de signer un certificat. (Le RFC 4211, annexe C, explique pourquoi c'est important.) Ainsi, une CSR (demande de signature d'un certificat) faite par OpenSSL est signée et cela peut se vérifier :
% openssl req -verify -in server.csr -noout verify OK
Le format CRMF du RFC 4211 et le format PKCS#10 permettent tous les deux d'envoyer une demande de signature de certificat à une AC mais seul CRMF a un moyen d'inclure une POP pour les algorithmes ne permettant pas de signature. PKCS#10 (RFC 2986) n'a rien. Cela existe, de tels algorithmes, ne permettant pas de signature ? Oui, c'est le cas de Diffie-Hellman et de ECDH.
Les trois algorithmes de POP de notre RFC sont le Diffie-Hellman statique en section 4, le logarithme discret en section 6 et l'ECDH statique en section 6. Ne me demandez pas de vous les expliquer, cela dépasse largement mes compétences en cryptographie. Lisez le RFC pour cela. (Et révisez le RFC 6090 pour le troisième, qui utilise les courbes elliptiques.) Notre RFC 6955 fournit les algorithmes et les modules ASN.1 qui les décrivent.
La section 1.1 décrit les changements depuis le RFC 2875. Les deux algorithmes du précédent RFC ont été réécrits pour permettra leur paramétrisation par rapport à la fonction de condensation (obligatoirement SHA-1 dans l'ancien RFC, alors que plusieurs fonctions sont désormais possibles, notamment la famille SHA-2). Et un troisième algorithme a été ajouté, pour ECDH.
Date de publication du RFC : Mai 2013
Auteur(s) du RFC : M. Jethanandani (Ciena Corporation), K. Patel (Cisco Systems), L. Zheng (Huawei Technologies)
Pour information
Réalisé dans le cadre du groupe de travail IETF karp
Première rédaction de cet article le 25 mai 2013
Dans le cadre du travail du groupe KARP de l'IETF, consacré à la sécurisation des protocoles de routage de l'Internet, ce RFC est consacré à l'analyse de la sécurité des protocoles de routage utilisant TCP, notamment BGP.
Deux petits rappels : KARP travaille sur les protocoles eux-mêmes, ni sur le contenu des informations transmises (c'est le rôle de SIDR, qui a produit le système RPKI+ROA), ni sur les pratiques quotidiennes d'administration des routeurs. Son rôle est d'améliorer la sécurité des protocoles, et pour cela il commence par des analyses de la sécurité des protocoles existants, suivant une méthode décrite dans le RFC 6518. Il y avait déjà eu une analyse d'OSPF (RFC 6863) et ce nouveau RFC s'attaque à des protocoles très différents mais qui ont en commun d'utiliser TCP comme transport : BGP (RFC 4271) et LDP (RFC 5036), ainsi que les moins connus PCEP (Path Computation Element Communication Protocol, RFC 5440) et MSDP (RFC 3618). Ils appartiennent tous à la catégorie un-vers-un du RFC 6518 (les messages d'un routeur sont transmis à un seul autre routeur).
Donc, aujourd'hui, quels sont les risques de sécurité pour ces protocoles et les défenses existantes ? D'abord, ceux et celles spécifiques à la couche transport. Il y a les attaques par déni de service et les attaques où l'ennemi va tenter d'établir une session avec sa victime, sans en avoir normalement le droit. Parmi les contre-mesures (RFC 4732 pour un point de vue plus général), il y a des ACL par adresse IP (tous ces protocoles utilisant TCP, il n'y a normalement pas de possibilité pour un attaquant en dehors du chemin d'usurper une adresse IP, si tout le monde suit bien le RFC 4953 et le RFC 5961) et le fait d'écouter les connexions entrantes uniquement sur les interfaces où on s'attend à avoir des pairs. Pour éviter les attaques de méchants lointains, il y a la technique GTSM du RFC 5082, qui consiste à n'accepter des paquets que s'ils ont un TTL maximal (ou proche du maximum).
Cela ne suffit pas contre des assaillants situés sur le chemin (par exemple parce qu'ils sont sur le réseau local). Ceux-ci peuvent établir une connexion avec une fausse adresse IP, ou bien simplement envoyer des resets TCP pour couper les sessions existantes (notez que TLS ou SSH ne protégeraient pas contre ce dernier risque car ils fonctionnent au-dessus de TCP). Pour assurer l'authentification et l'intégrité de la connexion TCP, on a l'« authentification MD5 » du RFC 2385, normalement remplacée par l'AO du RFC 5925. AO est très supérieur, fournissant notamment l'agilité cryptographique (la possibilité de changer d'algorithme si la cryptanalyse en a trop affaibli un, ce qui est le cas de MD5). Mais AO est loin d'avoir remplacé MD5.
Et puis il y a les problèmes qui ne dépendent pas du transport utilisé, comme l'absence d'un protocole de gestion des clés (KMP pour Key Management Protocol). Actuellement, la gestion des clés dans tous ces protocoles est purement manuelle et, résultat, les clés cryptographiques des routeurs ne sont quasiment jamais changées, même lorsqu'un administrateur quitte la société.
Maintenant, place à chaque protocole individuellement. Le RFC fait une présentation de chaque protocole (section 2), puis de l'état de sécurité idéal qu'on souhaite atteindre (section 3), puis de la différence entre l'état actuel et cet idéal (section 4). Enfin, la section 5 étudie les questions de transition vers une meilleure solution de sécurité (tous ces protocoles étant pair-à-pair, il faut que les deux pairs soient d'accord pour la nouvelle technique de sécurité). Ici, je procède différemment en traitant tous les aspects de chaque protocole successivement (enfin, pas chacun, je ne couvre que BGP et LDP, ne connaissant pas vraiment PCEP et MSDP). Donc, honneur à BGP pour commencer, puisque c'est sans doute le protocole de routage le plus important pour l'Internet (section 2.3). Comme il ne fonctionne que sur TCP, sa sécurité est en bonne partie celle de ce protocole de transport. Autrement, il devra attendre le déploiement d'AO, puis d'un KMP pour que sa sécurité s'améliore.
LDP, lui, est utilisé par
MPLS et le RFC général de sécurité sur MPLS, le
RFC 5920 est donc une utile lecture, ainsi que
la section 5 du RFC 5036. LDP (sections
2.4, 3.1 et 4.1 de notre RFC) peut, lui, fonctionner sur TCP ou sur UDP. Ce
dernier sert notamment aux messages Hello
d'établissement d'une session. Cet établissement n'est donc pas
protégé par les mesures de sécurité de TCP. En fait, il n'existe même
quasiment aucune protection pour ces messages.
Et pour TCP ? LDP peut utiliser l'authentification MD5 du RFC 2385 mais on a vu que MD5 n'était pas conseillé
(RFC 6151 et section 2.9 du RFC 5036) et LDP ne permet pas encore d'utiliser AO (RFC 5925).
L'état de sécurité idéal pour LDP serait clairement un état où les
messages Hello
seraient authentifiés. En
attendant, les contre-mesures minimales sont de n'accepter des
Hello
que sur les interfaces réseau qui en ont
réellement besoin, et d'utiliser GSTM. Cela ne supprime pas toutes les
attaques, mais un travail est déjà en cours pour l'authentification
des Hello
(Internet-Draft draft-zheng-mpls-ldp-hello-crypto-auth
).
Date de publication du RFC : Mai 2013
Auteur(s) du RFC : M. Tuexen (Muenster Univ. of Appl. Sciences), R. R. Stewart (Adara Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 30 mai 2013
Normalement, un nouveau protocole de transport comme SCTP ne devrait avoir besoin de l'autorisation de personne pour être déployé entre deux machines majeures et consentantes. Le modèle de l'Internet, fondé sur le protocole IP, permet aux machines terminales, sans autorisation d'un intermédiaire, de communiquer en mettant ce qu'elles veulent dans les paquets IP. Cela, c'est la théorie. En pratique, par incompétence, sécurité ultra-rigide ou paresse, des tas d'intermédiaires se permettent de se placer sur le chemin entre deux machines et ne laissent passer qu'un petit nombre de protocoles de transport (typiquement uniquement TCP et UDP). Un nouvel arrivé (SCTP a quand même été normalisé dans le RFC 2960 en 2000 donc, « nouveau » est relatif ; la norme actuelle est le RFC 4960) a donc le plus grand mal à se faire une place au soleil. On en est donc réduit à des astuces plus ou moins propres comme celle décrite dans ce RFC : encapsuler SCTP dans de l'UDP.
La principale cible visée est donc le grand nombre de machines coincées derrière un routeur NAT. Mais cette encapsulation peut aussi servir pour mettre en œuvre SCTP sans avoir accès au noyau, entièrement dans une application, sans avoir de privilèges particulier (ce qui est souvent nécessaire pour implémenter un protocole de transport). Attention, il ne s'agit pas de faire un tunnel pour mettre en relation deux réseaux, mais de faire communiquer deux machines terminales qui voudraient faire du SCTP et qui en sont empêchées par une middlebox (cf. section 4).
Pourquoi UDP, au fait, et pas TCP ? Parce que SCTP fournit tous les services de TCP (notamment le contrôle de congestion et la fiabilité) et qu'il ferait donc double emploi avec TCP.
Notez que rien n'empêcherait de faire un routeur NAT qui permettrait SCTP, comme ils permettent aujourd'hui de faire du TCP et de l'UDP. C'est juste que de tels routeurs, s'ils existent, sont très rares.
Bon, et comment SCTP sur UDP fonctionne (section 5) ? On utilise par défaut le port de destination et de source 9899. Toutefois, celui-ci aura pu être modifié en route par un routeur NAT et le port à l'arrivée sera donc peut-être différent. D'autre part, certaines machines peuvent se trouver dans l'obigation d'écouter sur un autre port et il faut donc qu'une mise en œuvre de ce RFC soit capable d'utiliser un port différent par correspondant (cf. l'API plus loin), et de se souvenir de ces ports. On met le paquet SCTP dans un paquet UDP qui sera lui-même transporté dans IP (peut-être avec des en-têtes d'extension, dans le cas d'IPv6). La somme de contrôle UDP doit être mise (même en IPv4 où elle est normalement facultative ; et, pour IPv6, on n'a pas le droit d'utiliser l'exception du RFC 6935).
C'est simple mais il y a quelques petits pièges. D'abord, avec les messages ICMP (section 5.5) : lors de leur réception, il n'y aura pas forcément assez d'octets du message original pour trouver l'association SCTP à qui envoyer le message ICMP. Il faudra alors jeter ce dernier sans remords. La mise en œuvre de SCTP doit donc être capable de se débrouiller sans les messages ICMP, dont la réception ne peut pas être garantie.
Deuxième piège, commun à toutes les techniques d'encapsulation, la MTU (section 5.6). SCTP doit penser à diminuer la MTU de la taille de l'en-tête UDP. Et se souvenir qu'ICMP est encore moins garanti lorsqu'on utilise l'encapsulation UDP donc les procédures de découverte de la MTU du chemin (RFC 4820, RFC 4821 et surtout RFC 8899) doivent fonctionner même si on ne reçoit pas les messages ICMP.
Dernier piège, mais crucial, le contrôle des adresses IP source
des paquets UDP. Pour les associations SCTP à une seule adresse IP, il ne faut
pas indiquer l'adresse IP de la machine dans les
sous-paquets (chunks) de type INIT
(section 3.3.2 du RFC 4960) mais la mettre dans
le paquet UDP (ce que fait UDP par défaut). Et si la machine a
plusieurs adresses IP, il faut se servir des mécanismes des RFC 5061 et RFC 4895 pour les faire connaître au correspondant, et non pas mettre les adresses IP dans les sous-paquets
SCTP car l'intervention d'un routeur NAT modifierait l'adresse source,
rendant ces sous-paquets invalides.
Et pour les applications, quels mécanismes sont nécessaires pour
faire fonctionner cette encapsulation ? La section 6 propose des
changements à l'API du RFC 6458, avec l'ajout d'une option
SCTP_REMOTE_UDP_ENCAPS_PORT
qui prendra en
paramètre une structure :
struct sctp_udpencaps { sctp_assoc_t sue_assoc_id; struct sockaddr_storage sue_address; uint16_t sue_port; };
Ce qui permettra de définir/connaître les adresses IP et les ports utilisés par l'encapsulation UDP.
Depuis sa version 9.1, FreeBSD a la capacité
d'utiliser cette encapsulation pour envoyer des paquets SCTP. Un
portage a été fait vers Mac OS X, disponible en
http://sctp.fh-muenster.de
.
Date de publication du RFC : Octobre 2013
Auteur(s) du RFC : J. Peterson (NeuStar), O. Kolkman (NLnet Labs), H. Tschofenig (Nokia Siemens Networks), B. Aboba (Microsoft Corporation)
Pour information
Première rédaction de cet article le 10 octobre 2013
Le DNS est un des plus grands succès de l'Internet : une base de données répartie, fiable, sur laquelle on peut compter, et qui est très souple dans ses usages, lui permettant d'être utilisée pour beaucoup de choses (seuls les journalistes écrivent encore que « le DNS sert à trouver une adresse IP à partir d'un nom de domaine » : la réalité est bien plus riche). Mais, justement, la disponibilité et l'efficacité du DNS font qu'il est utilisé par beaucoup d'applications dont les auteurs ne sont pas forcément conscients des forces et faiblesses du DNS. Ne faudrait-il pas les appeler à réfléchir deux secondes sur ces forces et ces faiblesses ?
Le DNS permet de récupérer des données (quelconques : ce ne sont pas forcément des adresses IP) à partir d'un nom de domaine. Il est même utilisé par des applications dont les identifiants ne sont pas des noms de domaine : une petite transformation pour convertir l'identifiant en nom de domaine et hop (ONS, ENUM, etc). Le premier RFC à avoir décrit l'usage du DNS pour autre chose qu'une correspondance nom->adresse est le RFC 974 en 1986. C'est dire que c'est ancien et cela explique mes critiques sévères des ignorants qui continuent à considérer le DNS comme un simple moyen de trouver des adresses. Depuis ce RFC 974, qui introduisait l'enregistrement MX, l'idée a suivi son chemin. Un mécanisme plus général, le SRV, a été introduit par le RFC 2052 (remplacé depuis par le RFC 2782). Et, pour faire des mécanismes de délégation aussi compliqués qu'on le souhaite, il y a le NAPTR créé par le RFC 2168, généralisé ensuite par le RFC 3401. Enfin, il y a des applications qui mettent simplement leurs données dans le très général et pas structuré enregistrement TXT, ce que fait par exemple DKIM (RFC 6376).
Mais ce succès, comme tous les succès, a aussi son revers : les applications demandent de plus en plus au DNS alors que son vaste déploiement est largement dû à sa focalisation sur un petit nombre de fonctions qu'il réalise très bien. La mentalité fréquente aujourd'hui de « on met tout dans le DNS » (illustrée par un gadget fameux) est parfois en conflit avec les principes du DNS. La confidentialité est un bon exemple : elle était délibérement exclue du cahier des charges du DNS (et à juste titre : lisez le RFC 3414 si vous voulez un exemple de la complexité que la confidentalité apporte à un protocole requête-réponse). Vouloir l'ajouter aujourd'hui risque fort de faire perdre au DNS ses propriétés intéressantes (il n'est pas cité par ce RFC, mais c'est l'une des raisons de l'échec de DNScurve, qui essayait de faire trop de choses). Bien des applications qui veulent utiliser le DNS ont réclamé une certaine dose de confidentialité, alors que le DNS doit une partie de son efficacité au fait que toutes les données sont publiques. Ainsi, un cache n'a pas à s'inquiéter si les données qu'il mémorise doivent être servies à tous ou pas.
Ce nouveau RFC de l'IAB vise donc à aider les concepteurs d'applications en exposant clairement ce que le DNS fait bien, ce qu'il peut faire, et ce qu'il ne sait pas faire. C'est un excellent document pour qui veut comprendre en détail le DNS et, malgré sa longueur, il mérite d'être lu attentivement. Il fournit les informations nécessaires pour que ledit concepteur puisse répondre intelligemment à la question « Dois-je mettre cette information dans le DNS ou bien ailleurs ? » Il complète le RFC 5507, qui restait plutôt sur les questions de syntaxe, alors que ce nouveau RFC 6950 adopte une vue plus générale, plus tournée vers l'architecture du système. Pour le résumer en deux mots : le DNS doit son succès à ce qu'il n'essaie pas de résoudre tous les problèmes mais un ensemble bien précis de problèmes, pour lesquels il est une bonne solution. Comme il existe d'autres protocoles que le DNS, une application ou un service qui envisage d'utiliser le DNS dit sérieusement étudier s'il est vraiment la solution la plus adaptée (parfois oui mais parfois non).
La section 2 de notre RFC présente un certain nombre d'usages du
DNS par des applications. Il commence évidemment par le routage du
courrier, avec les enregistrements
MX. Le MX était la première utilisation du DNS pour faire
autre chose que de la simple traduction de nom en adresse IP. En
partie droite d'un MX, on trouve le nom du ou des serveurs qui gèrent
la messagerie pour le domaine en partie
gauche. Bien sûr, une convention de nommage (du
genre « le serveur de messagerie de example.org
se nomme mail.example.org
») aurait pu jouer un
rôle similaire. Mais les MX sont plus souples (le serveur d'un domaine
n'est pas obligé d'avoir un nom dans le domaine, cf. RFC 4367) et offrent des
possibilités supplémentaires (plusieurs serveurs, avec des priorités
différentes). Mais le MX est spécifique au courrier électronique. Les
enregistrements SRV, créés par le RFC 2052 (aujourd'hui RFC 2782), ont étendu le principe à
tous les protocoles qui voulaient en profiter (avec des choses en plus
comme l'indication du numéro de port ou bien
comme la répartition de charge). Tous les
protocoles créés depuis utilisent ces enregistrements, à la triste
exception de HTTP qui, stupidement (l'avis est
le mien, il n'est pas dans le RFC), ne fournit
pas de mécanisme pour trouver le serveur d'un domaine (obligeant à
utiliser des conventions de nommage comme
www.example.com
ou, pire, à mettre une adresse IP
sur le domaine lui-même, et empêchant d'utiliser le DNS pour la
répartition de charge et la résilience, ce qu'auraient permis les SRV).
Autre service fourni aux applications par le DNS, les
enregistrements NAPTR. L'idée au début était de
pouvoir trouver n'importe quel identificateur, même distinct d'un nom
de domaine, dans le DNS (RFC 2915). Les NAPTR permettent de
spécifier des transformations complexes depuis une famille
d'identificateurs, vers les noms de domaine. L'idée est ancienne. Sa
première manifestation avait été le domaine
in-addr
dans le RFC 883 (c'était un TLD à l'époque, il est
devenu in-addr.arpa
dans
le RFC 973). Son but était de permettre de traduire des
adresses IP en noms, en convertissant d'abord l'adresse IP en un nom
de domaine se terminant en in-addr
. Ce genre de
transformation textuelle sur un identificateur pour en faire un nom de
domaine a ensuite été reprise par tpc.int
(RFC 1530, un
mécanisme pour router des appels téléphoniques via l'Internet, qui
allait déboucher sur ENUM). Ces mécanismes ne
changent pas le protocole DNS mais ils changent la manière dont on se
sert du DNS, et apportent de nouveaux utilisateurs, ayant de nouvelles attentes.
Une des demandes de ces « nouvelles » applications est de stocker des données quelconques dans le DNS. On peut mettre ce qu'on veut dans un URI (et même directement des données, cf. RFC 2397). Donc, comme un NAPTR mène à un URI, il peut nous mener à n'importe quoi. Mais, avant même cette astuce, le DNS pouvait déjà stocker n'importe quoi. Il existe même un type d'enregistrement, TXT, spécialement prévu pour des données non structurées. La souplesse du TXT et son absence de contraintes ont attiré plein de gens, malgré les conseils de prudence du RFC 5507. Il y a même eu une proposition de structurer le contenu des TXT (RFC 1464).
Bon, mais qui y a-t-il de mal à ce que les gens se servent du DNS pour y mettre des informations ? En combinant les différentes techniques vues ci-dessus, on pourrait faire tenir n'importe quel protocole requête/réponse dans le DNS. Mais ce n'est pas complètement exact. La section 3 décrit les défis auxquels son succès confronte le DNS. Certes, le DNS est une base de données répartie, fiable, et rapide. Mais lorsqu'on dit « base de données », certains utilisateurs voudraient que le DNS fournisse des services classiques des bases de données, comme la confidentialité, le contrôle d'accès, l'introspection (utiliser le protocole d'accès pour découvrir le schéma) et la possibilité de requêtes structurées complexes, un peu comme ce que fournit SQL. Mais le DNS n'a pas été conçu pour cela et ce RFC argumente que, plutôt que de forcer le DNS à fournir ces services, on utiliserait mieux son temps à développer d'autres protocoles ou tout simplement à utiliser d'autres protocoles existants. Le succès du DNS et ses qualités viennent justement de ce qu'il n'essayait pas de tout faire.
Les exemples donnés par le RFC sont tous empruntés au monde ENUM (RFC 6116) mais les questions soulevées ne sont pas spécifiques à ENUM.
D'abord, les critères de recherche : dans le DNS, la clé d'accès
est le triplet {nom de domaine, classe, type}, par exemple (en syntaxe
dig) www.afnic.fr. IN
AAAA
, et la correspondance doit être exacte (pas de
recherche floue). Or, certains souhaiteraient pouvoir exprimer des
requêtes plus riches. Des tentatives ont été faites pour mettre des
critères supplémentaires dans le nom de domaine lui-même (par exemple,
pour ENUM, tg011.0.0.4.5.4.3.4.1.7.5.1.e164.arpa
pour ajouter au nom normal,
0.0.4.5.4.3.4.1.7.5.1.e164.arpa
, qui est dérivé
du numéro de téléphone, le
trunk group
tg011
) mais cela devient vite pénible lorsque le
nombre de critères augmente.
Autre solution envisagée, EDNS (RFC 6891), en passant les critères supplémentaires comme options EDNS. Mais cela ne marche pas comme certains le prévoient car EDNS est de saut en saut et pas de bout en bout : un serveur DNS relais ne va pas transmettre les options EDNS.
Enfin, les requêtes complexes posent un problème pour les caches, si fréquents avec le DNS. Les caches actuels considèrent que la réponse ne varie qu'avec le triplet {nom de domaine, classe, type} et pourrait donc garder en cache à tort des réponses faites à des requêtes plus complexes.
Autre demande fréquente des nouveaux utilisateurs du DNS, avoir des
réponses « à la tête du client », dépendant de l'émetteur de la
question. Il est par exemple courant aujourd'hui de servir des réponses
différentes selon l'adresse IP de la source (option
view
de BIND). Tant que cela ne sert
qu'à présenter des versions adaptés d'un contenu (un
portail Web différent selon le pays d'origine
de la requête), sans problème de sécurité, ce n'est pas trop grave :
une erreur n'aura pas de conséquences trop ennuyeuses. Pour des cas
plus sensibles, cela peut être gênant. D'autant plus que l'adresse IP
de la source n'est pas celle du vrai client, mais celle du résolveur
qu'il utilise. Dans certains cas (Google
Public DNS), la distance entre les deux peut être énorme. Une
option EDNS a été proposée pour que le résolveur puisse indiquer au
serveur faisant autorité la vraie adresse IP du client mais elle n'est
pas encore adoptée (entre autres, elle pose des problèmes si le client
a une adresse IP privée, genre RFC 1918).
Le DNS a d'autres limites lorsqu'on veut l'utiliser comme base de
données générique, par exemple la taille des noms de domaine (limitée
à 63 caractères par composant) et la taille des réponses. Quelle
limite de taille ? L'ancienne limite de 512 octets n'est normalement
plus qu'un souvenir (mais il existe encore des
pare-feux bogués ou mal gérés qui imposent
cette limite) mais il y a deux autres seuils derrière, la
MTU (si la réponse est plus grosse, on risque
de la fragmentation) et les 4 096 octets qui
sont, en pratique, la limite de la plupart des serveurs. Si la réponse
est un URI, notez que le RFC 2397 sur les URI
data:
indique que ceux-ci doivent être « courts »
mais il ne définit pas cet adjectif. Le RFC note que, dans le contexte
d'ENUM, stocker des sonneries de téléphone rigolotes sous forme de
fichiers MP3 dans un URI
data:
n'est probablement pas raisonnable.
En outre, le DNS reposant sur UDP, qui ne
garantit pas l'adresse IP source, des données de grande taille
augmentent les risques d'attaque avec amplification (RFC 4732, section 3). Dans ces attaques, le méchant
émet une requête DNS (de petite taille, donc) en usurpant l'adresse IP
source de sa victime. Le serveur va alors répondre à celle qu'il croit
être l'émetteur et la réponse est souvent bien plus grande que la
question (le RFC cite l'exemple d'un certificat stocké dans le DNS,
comme dans le RFC 4398). L'attaquant pourra donc obtenir
ainsi un trafic plus important que ce qu'il peut lui-même
générer. C'est d'ailleurs une des raisons pour lesquels les serveurs
de .com
, par exemple,
limitent leurs réponses à 1 460 octets. Bref, malgré EDNS, on ne peut
pas espérer faire passer dans le DNS des données de taille
quelconque. Le DNS est prévu pour des informations courtes.
Autre limite du DNS lorsqu'on essaie de s'en servir comme d'une base de données générique, la non-correspondance des frontières administratives avec celles du DNS : les frontières des composants d'un nom de domaine ne sont pas forcément celles qu'on voudrait. Par exemple, pour la téléphonie, les anciennes numérotations étaient très hiérarchiques (et correspondaient donc bien au DNS) alors que, depuis la portabilité des numéros de téléphone, ce n'est plus le cas et il n'est donc pas évident de savoir où déléguer les noms ENUM. Ce n'est pas juste un problème esthétique : le bon fonctionnement du DNS dépend des délégations qui sont « cachées » (gardées en mémoire) dans les résolveurs, et qui épargnent à la racine la grande majorité des requêtes. Avec la portabilité des numéros téléphoniques, il faut interroger la racine ENUM pour tout numéro (puisqu'on ne peut pas savoir à l'avance quel opérateur téléphonique le gère). C'est d'autant plus ennuyeux pour la racine ENUM que les correspondances entre un numéro et un opérateur changent et qu'on souhaite souvent une portabilité rapide (de l'ordre de quinze minutes), peu compatible avec une racine simple et efficace.
Si vous pensez que ce n'est pas si grave, que
.com
est un espace plat
avec de nombreux noms et des changements rapides, ce qui démontre que
le DNS peut s'en tirer, pensez que dans les seuls
États-Unis, il y a trois cents millions de
numéros de téléphone attribués, trois fois la taille de
.com
.
Le problème n'est évidemment pas spécifique à ENUM : si on créait
un mécanisme de portabilité pour les adresses IP, les domaines comme
in-addr.arpa
auraient les mêmes problèmes.
La section 4 est entièrement consacrée à un problème particulier
qui a fait couler beaucoup d'encre, le désir d'avoir des réponses DNS
« à la tête du client ». Officiellement, le DNS présent une vue unique
à tous les utilisateurs (ce point est développé dans le RFC 2826) qui affirme que les noms doivent être
uniques et donc donner un résultat unique. Mais il existe une forte
demande pour avoir des noms qui ne fonctionnent que dans un espace
privé (à l'intérieur d'une entreprise, par exemple), afin de limiter
l'accès à certaines ressources. Il existe plusieurs solutions
techniques pour avoir des réponses différentes en local et en public
mais aucune n'est parfaitement satisfaisante. Par exemple, si on
utilise des noms locaux avec un TLD bidon comme
.prive
ou .local
, ces noms
« fuiront » un jour ou l'autre, seront vus à l'extérieur, ce qui
générera de la confusion (section 3.3 du RFC 5507).
Bien, après toutes ces critiques et toutes ces limites du DNS, quels conseils pratiques donner à ceux et celles qui voudraient quand même utiliser le DNS ? La section 5 est composée d'excellents conseils pour les développeurs d'applications ou de services utilisant le DNS. En gros, le DNS sera sans doute une bonne solution si le service qui veut l'utiliser a toutes ces propriétés :
Si une seule de ces propriétés manque, le DNS n'est peut-être pas la bonne solution pour le problème. À l'inverse, de bons signaux d'alarme, indiquant qu'on utilise le DNS à tort, sont :
Bon, mais si on n'utilise pas le DNS, alors quoi ? Le RFC suggère que, dans beaucoup de cas de protocole requête/réponse, HTTP convient parfaitement (par exemple, il a de l'authentification, il peut transporter des données de taille quelconque, il est largement déployé...)
Pendant l'élaboration de ce RFC, des commentaires intéressants ont été enregistrés dans le système de suivi des tâches.
Date de publication du RFC : Mai 2013
Auteur(s) du RFC : H. Flanagan (RFC Series Editor), N. Brownlee (Independent Submissions Editor)
Pour information
Première rédaction de cet article le 15 mai 2013
Cela fait longtemps que le format des RFC est critiqué, à l'IETF ou ailleurs. Pour d'excellentes raisons (détaillées plus loin), ce format est très ancien et très rigide, sans concessions aux gadgets modernes. Il n'a pas encore été possible de le modifier, à la fois en raison des difficultés de prise de décision au sein de la communauté, et aussi parce que le problème est réellement difficile. Contrairement à ce que prétendent certains yakafokon, trouver un format idéal n'est pas trivial. Ce RFC est la première étape d'une tentative de réforme, commençant par un cahier des charges sur les changements souhaitables. Les règles rigides de formatage (longueur des pages et des lignes) disparaissent, l'Unicode fait son entrée dans les RFC, et la possibilité d'inclure des images apparait.
Une des raisons de la stagnation du projet de changement depuis des années était la réorganisation de la fonction de RFC Editor. Désormais, les nouvelles règles sur cette fonction sont écrites (RFC 6635), une nouvelle RFC Editor a pris ses fonctions, jeune et dynamique (Heather Flanagan, un des auteurs de ce RFC), et il va peut être être enfin possible de faire évoluer le format traditionnel. (Depuis cet article, le nouveau format des RFC a été adopté, cf. RFC 7990.)
Le format actuel est documenté dans le RFC 7322 mais à l'époque de notre RFC, c'était le RFC 2223 qui s'appliquait : texte brut sans enrichissement, en ASCII, pages de 58 lignes, lignes de 72 caractères au maximum, pas de notes de base de page, références croisées par numéro de section et pas de page, etc. PostScript était autorisé et quelques RFC ont été publiés ainsi. Une tentative de mise à jour de ce RFC, avec écriture d'une proposition de nouvelle version, avait eu lieu en 2004 mais avait été abandonné. J'avais déjà écrit un article détaillé expliquant le pourquoi du format traditionnel et les raisons pour lesquelles il est difficile à changer.
La section 1 de ce RFC commence par rappeler la longue histoire des RFC. Ils ont commencé il y a plus de quarante ans, et dans les débuts, certains étaient écrits à la main (!), d'autres tapés à la machine, d'autres encore produits par les outils de formatage invraisemblables qu'on trouvait sur les mainframes de l'époque. Résultat, certains sont devenus illisibles avec le temps, les outils tombant en désuétude. Ce problème de permanence est un des problèmes les plus cruciaux pour les RFC et explique pourquoi le RFC Editor n'a jamais été très chaud à l'idée d'utiliser le logiciel à la mode du moment : l'informatique en a déjà enterré beaucoup.
Au bout d'un moment, un format standard a émergé, fondé sur du texte brut et un encodage en ASCII. À partir de là, la série des RFC a vécu une longue période de calme et de stabilité et cette permanence (songez aux formats à la mode vite disparus comme WordPerfect) a beaucoup contribué à son succès. On peut relire aujourd'hui sans problème un RFC de 1980 comme le RFC 768. Ce n'est pas que le format ait été jugé parfaitement satisfaisant par tout le monde, ni qu'aucune proposition de changement n'ait été faite, bien au contraire. Mais aucun des ces propositions n'a connu de consensus : toutes résolvaient un problème précis... en en créant plusieurs autres.
Avant de regarder les propositions actuellement sur la table, il faut bien comprendre qu'il y a plusieurs endroits dans le cycle de vie d'un RFC où un format standard est nécessaire ou utile. Cette terminologie est très importante car l'incompréhension de ces étapes du cycle de vie est l'une des causes principales de la confusion des débats sur la réforme des RFC :
http://tools.ietf.org
par exemple voici ce RFC), du PDF formaté différemment, etc.Évidemment, les choses ont changé depuis (le RFC 2223 date de seize ans...) Quels sont les points qui suscitent le plus de protestations ? D'abord, l'utilisation d'art ASCII et lui seul pour les graphiques. Elle a l'avantage d'encourager les auteurs à écrire des descriptions textuelles claires, plutôt que de passer du temps à faire de jolis dessins. Sans les limitations de l'art ASCII, les diagrammes seraient probablement moins concis. D'un autre côté, des choses comme les automates finis sont vite illisibles en art ASCII et les protocoles où il y a plus de trois acteurs qui interagissent sont difficiles à dessiner. Des graphiques plus élaborés que l'art ASCII permettraient également de représenter des équations mathématiques complexes.
Après les images, le sujet le plus chaud est évidemment l'encodage. ASCII a des tas d'avantages : standard, très répandu, facile à manipuler (outils de recherche, par exemple), plus pratique lorsqu'il faut renumériser un document (oui, le cas s'est déjà produit dans le passé)... Et la langue des RFC étant de toute façon l'anglais, les limites d'ASCII ne sont pas trop graves.
Mais il y a quand même des limites : lorsqu'un RFC parle
d'internationalisation (comme le RFC 5890 ou le
RFC 6530, ou comme de plus en plus de normes), c'est bien dommage de ne pas pouvoir
donner d'exemple lisible dans ce RFC. Devoir écrire
U+00c9
pour parler de É
est
pénible... Des exemples comme ceux de XMPP
(RFC 6121, section 5.2.3) bénéficieraient de
l'acceptation d'Unicode dans les RFC.
Et certains auteurs de RFC ont des noms qui ne peuvent pas s'écrire correctement en ASCII et ils regrettent de devoir les modifier.
Autres points sur lesquels des gens ont souvent râlé contre le format actuel : la pagination et l'ajustement du texte. La pagination en unités fixes fait vraiment rétro : elle avait un sens quand les RFC étaient souvent imprimés pour être lus mais à l'ère des tablettes, cela semble bien dépassé. Plus compliqué est le cas de l'ajustement du texte. La largeur de colonne fixe qui est la norme actuelle convenait aux VT100 mais pas aux écrans modernes, avec leurs tailles très variables.
Enfin, ce n'est pas tout de définir des formats, il faut aussi des outils qui rendent la production de RFC conforme à ces formats facile (pour avoir une idée des difficultés, lire le RFC 5385). Ces outils doivent-ils être développés à l'IETF ou bien doit-on utiliser des outils standard ? Les exigences de l'IETF sont-elles tellement spécifiques qu'on ne puisse pas utiliser des outils existants ? D'un autre côté, les outils spécifiques donnent plus de souplesse et de pouvoir et, aujourd'hui, il en existe déjà beaucoup (par exemple, la version 2 de xml2rfc - une réécriture complète, abandonnant TCL pour Python, pour produire des RFC suivant le schéma du RFC 7749, est bien meilleure que la précédente) donc on peut dire que le modèle « faisons tout nous-même » marche bien (il y a beaucoup d'informaticiens à l'IETF).
Enfin, s'il y a des réclamations des lecteurs et des auteurs, il y en a aussi du RFC Editor : il voudrait pouvoir abandonner nroff (65 % des RFC aujourd'hui sont soumis au format XML, qu'il faut traduire en nroff au lieu de l'utiliser directement comme format d'entrée pour les différentes publications).
Après les contraintes et les réclamations, les décisions (section 3). D'abord, ce qui ne change pas :
Ensuite, les nouvelles exigences effectivement retenues, notamment :
Et il y a aussi des exigences qui ont été supprimées :
Voilà, le cahier des charges est posé, il reste à définir le
nouveau format, développer les outils, et déployer le tout... Ce sera
pour le prochain épisode. À la réunion IETF 86 a été annoncé
le choix de s'appuyer sur le format XML comme format canonique, avec
comme formats de publication le texte brut, HTML, PDF et
EPUB (voir la FAQ sur ces décisions.)
Deux Internet-Drafts sont
en cours, un sur le format, draft-rfc-format-flanagan
,
et un sur le style, draft-flanagan-style
. (Depuis,
le premier draft a été publié, RFC 7990.)
Date de publication du RFC : Juillet 2013
Auteur(s) du RFC : A. Keranen, J. Arkko (Ericsson)
Pour information
Première rédaction de cet article le 18 juillet 2013
Le World IPv6 Day le 8 juin 2011 avait pour but de tester le comportement d'IPv6 si de nombreux services sur l'Internet activaient ce protocole. On peut noter que rien de spectaculaire ne s'est produit (tant mieux : comme prévu, cette activation n'a rien cassé) mais les impressions ne suffisent pas, il faut aussi mesurer ce qui s'est passé. C'est une de ces mesures que raconte ce RFC ; ses auteurs ont compté le nombre de sites Web qui activaient IPv6 et le résultat que cela avait sur le temps d'établissement d'une connexion, pour un client qui avait déjà IPv4 et IPv6.
Pourquoi est-ce que, alors qu'IPv6 est normalisé depuis de nombreuses années (RFC 2460), certains gros acteurs de l'Internet hésitent toujours à l'activer ? Les raisons vont de la simple passivité à la crainte que, dans certains cas, l'activation d'IPv6 ne dégrade le vécu de l'utilisateur (RFC 6555). Le but des IPv6 days (il y en avait d'autres avant celui de 2011 et d'autres sont apparus après) est à la fois d'encourager les frileux, et de tester pendant 24 h si les craintes sont justifiées (l'IPv6 Day de 2012, considérant que les tests avaient été suffisants et n'avaient guère montré de problèmes, était au contraire prévu pour qu'IPv6 reste activé). Pendant 24 h, le 8 juin 2011, un certain nombre d'opérateurs de services Internet ont donc configuré leurs services pour répondre en IPv6, leur permettant de tester que tout allait bien, et d'avoir une idée du pourcentage de leurs utilisateurs prêts à faire de l'IPv6. Cette configuration impliquait l'activation du protocole sur les différents équipements : serveurs, bien sûr, mais aussi applications car celles-ci gèrent parfois des adresses IP, par exemple à des fins de statistiques, et également les diverses middleboxes qui sont en général le maillon faible de la connectivité Internet.
Une fois qu'IPv6 était disponible et testé sur le service (normalement, bien avant le grand jour), il n'y avait plus qu'à le faire savoir au reste du monde, ce qui se fait en publiant un enregistrement AAAA dans le DNS.
Les mesures décrites dans ce RFC étaient donc le pourcentage de domaines avec des enregistrements AAAA et le temps pris à établir une connexion avec le serveur (ainsi que le pourcentage d'échecs).
Comme l'Internet est grand, l'étude de ce RFC s'est limitée 10 000 sites Web les mieux placés dans le
classement d'Alexa (section 3 du RFC). Pour
chaque domaine, le logiciel a fait une requête DNS AAAA pour
ledomaine
, www.ledomaine
, et
aussi des noms spécifiques à IPv6 comme
www.ipv6.ledomaine
(noms peu susceptibles d'être
utilisés par le visiteur moyen). Ce logiciel de mesure active était
écrit en Perl avec le module Net::DNS
. Ensuite, un petit programme en
C tentait une connexion TCP vers l'adresse
obtenue et mesurait le délai. Les mesures ont commencé une semaine
avant l'IPv6 day et se sont terminées trois jours
après. Le client était situé dans les locaux
d'Ericsson à
Helsinki.
Quels ont été les résultats ? La section 4 donne les valeurs obtenues, avec des liens vers des graphiques externes (les RFC ne permettent pas de mettre d'images). Le pourcentage d'enregistrements AAAA est ainsi passé de 2,45 % une semaine avant le grand jour et a culminé à 4,91 % pendant. Il est ensuite redescendu (contrairement à 2012, il n'était pas demandé aux sites de garder leurs AAAA), mais est resté plus élevé qu'avant le jour IPv6. Si on prend seulement les 100 sites les mieux classés par Alexa, on trouve la même courbe mais des pourcentages bien plus élevés (les gros sites sont plus sérieux pour ce qui concerne IPv6).
Ce n'est pas tout de publier des adresses IPv6. Encore faut-il que le serveur HTTP situé derrière réponde effectivement. Si on teste toutes les adresses (v4 et v6) en TCP vers les ports 80 et 443, on trouve entre 1 et 3 % d'échecs. Pour IPv6 seul, le pourcentage d'échec est bien plus élevé. Cela ne recoupe pas les résulats vus par DNSdelve (qui montrent nettement moins d'échecs de connexion) probablement parce qu'il s'agit ici d'une journée exceptionnelle, que tout le monde n'a pas bien préparé. Apparemment, certains ont publié leur AAAA avant de configurer leur serveur, leurs routeurs et leurs pare-feux (notez la baisse du pourcentage d'échecs au fur et à mesure que la journée avance).
Et si TCP marche, OK, mais marche-t-il vite ? La connexion prend t-elle plus ou moins de temps en IPv4 et en IPv6 ? Après tout, autrefois, en raison de l'utilisation de mauvaises technologies comme 6to4 (RFC 3056 et RFC 7526) ou comme des tunnels amateurs, IPv6 avait la réputation d'être lent. Qu'en est-il aujourd'hui ? En prenant la médiane et la moyenne, on voit que la différence est très faible (même pour la moyenne, pourtant plus sensible aux petites variations), et qu'IPv6 est un peu plus rapide en temps normal mais plus lent pendant le jour IPv6 (sans doute parce que l'arrivée de nombreux sites mal configurés a fait baisser les chiffres).
En conclusion, le jour IPv6 de 2011 n'a pas été inutile. Le RFC estime qu'avant celui de 2012, il a été une des journées où l'Internet avait changé le plus. Mais les utilisateurs ordinaires n'ont rien remarqué, ce qui était justement le but. Même ceux qui mesurent les temps de connexion n'auront guère vu de différences. Le principal problème est le nombre trop élevé de sites qui publient un AAAA mais avec qui la connexion IPv6 échoue.
Autres mesures équivalentes :
.fr
annonçant un
enregistrement AAAA pour leur serveur Web,Date de publication du RFC : Mai 2013
Auteur(s) du RFC : F. Gont (Huawei)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 15 mai 2013
Dernière mise à jour le 20 juin 2013
Une particularité amusante de la gestion de la fragmentation dans IPv6 est qu'un paquet peut très bien avoir un en-tête de fragmentation sans être fragmenté du tout. Cela se nomme un « fragment atomique » (le terme est très malheureux car il n'a rien à voir avec les « datagrammes atomiques » du RFC 6864). Ils n'ont aucun intérêt pratique mais sont engendrés par certains systèmes lorsqu'ils reçoivent un message ICMP Packet too big indiquant une MTU inférieure à 1280 octets (la taille miminale pour une MTU IPv6). Le problème est que ces fragments atomiques sont ensuite traités par bien des systèmes comme des vrais fragments, permettant ainsi certaines attaques subtiles. Ce nouveau RFC demande donc que les fragments atomiques soient gérés à part, compte tenu de leurs particularités. (Depuis, le RFC 8021 a carrément rendu ces fragments atomiques obsolètes.)
Si vous voulez réviser les règles de la fragmentation dans IPv6, c'est dans le RFC 2460 (depuis remplacé par le RFC 8200, qui a changé ces règles). Contrairement à IPv4, seules les machines de départ (pas les routeurs intermédiaires) peuvent fragmenter. Si une machine de départ doit envoyer un paquet qui est trop grand pour la MTU, elle le fragmente en plusieurs morceaux, chaque morceau indiquant son décalage par rapport au début du paquet original. Même si ce n'est pas explicite dans ce RFC, le recouvrement des fragments était autorisé, ce qui complique sérieusement le réassemblage et pouvait permettre d'échapper à certains IDS. Il n'est donc pas étonnant que le RFC 5722 ait finalement interdit ces fragments recouvrants. Bon, et les fragments atomiques, ils sont fabriqués pourquoi ? La section 5 du RFC 2460 ne laissait pas le choix aux mises en œuvre d'IPv6 : normalement, elles devaient fabriquer un fragment atomique (un paquet qui a l'en-tête de fragmentation, sans pour autant être fragmenté) si la taille indiquée par le paquet ICMP est inférieure aux 1280 octets minimaux d'IPv6 (c'est pour aider certains mécanismes de traduction IPv4<->IPv6). Dans un fragment atomique, le décalage (fragment offset) sera de zéro (puisque ce fragment est le premier) et le bit M sera à Zéro (puisque ce fragment est le dernier du datagramme). Comme ces paquets ICMP Packet too big ne sont pas authentifiés, même quand c'est possible (section 5.3 du RFC 4443 et RFC 5927), un attaquant peut donc faire fabriquer des fragments atomiques assez facilement. Notez que le RFC 8200 a changé cette règle et donc interdit les fragments atomiques.
Ensuite, comme bien des systèmes traitent ces fragments atomiques en même temps que les fragments normaux, ils peuvent, par exemple, être fusionnés avec d'autres fragments prétendant venir de la même source.
Les problèmes de sécurité liés aux fragments sont bien connus : voir notamment le RFC 5722 mais aussi le RFC 6274 qui décrit ces attaques pour IPv4 (beaucoup sont communes aux deux versions). Ce problème est encore aggravé par le fait que certains systèmes génèrent des identificateurs de fragment trop prévisibles, permettant à l'attaquant de savoir où il devra frapper.
La section 4 décrit ensuite les nouvelles règles, visant à résoudre ce problème. En deux mots, en recevant un fragment atomique (que l'on reconnait à la combinaison décalage=0 et bit M =0), on doit le traiter différemment des autres fragments et il ne peut être réassemblé qu'à partir du fragment unique.
L'annexe A contient un tableau listant un certain nombre de systèmes d'exploitation actuels en indiquant s'ils génèrent des fragments atomiques, et s'ils mettent en œuvre ce RFC (les traitent différemment des autres fragments). La plupart des systèmes génèrent ces fragments atomiques lorsqu'ils reçoivent le faux paquet ICMP Too big (une exception est NetBSD). Et plusieurs d'entre eux (Linux récent, NetBSD, OpenBSD) suivent déjà la recommandation de ce RFC et ne sont donc normalement pas vulnérables aux attaques décrites ici.
Si vous voulez tester vous-même, l'outil frag6 dans la boîte à outils SI6 permet de le faire facilement. D'abord, on envoie un fragment incomplet qui est le premier du datagramme :
# frag6 -v -i em0 --frag-type first --frag-id 1234 -d $MACHINE_UNDER_TEST
Dans une autre fenêtre, et avant l'expiration du délai de garde pour le réassemblage (60 secondes par défaut), on envoie un fragment atomique de même identificateur (1234 ici) :
# frag6 -v -i em0 --frag-type atomic --frag-id 1234 -d $MACHINE_UNDER_TEST
Si les fragments atomiques sont réellement traités à part (ce que notre RFC exige), ce qui est le cas sur un FreeBSD >= 9 ou un Linux >=> 3), le fragment atomique est « réassemblé » avec lui-même et on obtient une réponse :
ICMPv6 echo Reply from $MACHINE_UNDER_TEST (RTT: 5 seconds)
Si on n'a pas cette réponse, c'est que le système en face traite incorrectement les fragments atomiques avec les autres. Dans les deux cas, système correct ou non, le premier fragment ne sera jamais réassemblé et, au bout des 60 secondes, on aura :
Response from $MACHINE_UNDER_TEST: ICMPv6 Time Exceeded error message (Reassembly timeout: 60 seconds)
Et rappelez-vous que, normalement, les mises en œuvre d'IPv6 ne doivent plus générer de fragments atomiques depuis le RFC 8021.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : S. Rose (NIST)
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 2 mai 2013
Mais quel algorithme de cryptographie choisir pour mes signatures DNSSEC, se demande l'ingénieur système ? Il y a bien un registre IANA des algorithmes normalisés mais c'est juste une liste non qualifiée, qui mêle des algorithmes de caractéristiques très différentes. Ce nouveau RFC vise à répondre à cette question en disant quels sont les algorithmes recommandés. (Il a depuis été remplacé par le RFC 8624.)
La première liste d'algorithmes possibles avait été faite dans le RFC 4034. D'autres algorithmes avaient été ajoutés par la suite. Certains sont devenus populaires. Par exemple, RSA avec SHA-2 est utilisé pour presque tous les TLD importants et est donc difficilement contournable pour un résolveur validant. D'autres ont été peu à peu abandonnés, parfois parce que les progrès de la cryptanalyse les menaçaient trop, parfois simplement parce qu'ils n'avaient pas un bon marketing.
Aujourd'hui, le développeur qui écrit ou modifie un logiciel résolveur validant (comme Unbound ou BIND) doit donc se taper pas mal de RFC mais aussi pas mal de sagesse collective distillée dans plusieurs listes de diffusion pour se faire une bonne idée des algorithmes que son logiciel devrait gérer et de ceux qu'il peut laisser tomber sans trop gêner ses utilisateurs.
Ce RFC 6944 détermine pour chaque algorithme s'il est indispensable (on n'a pas le droit de faire l'impasse), recommandé (ce serait vraiment bien de l'avoir, sauf raison contraire impérieuse), facultatif (si vous n'avez rien d'autre à faire de vos soirées que de programmer) ou tout simplement à éviter (pour le cas de faiblesses cryptographiques graves et avérées). La liste se trouve dans la section 2.3 : RSA avec SHA-1 est le seul indispensable. RSA avec SHA-1 plus NSEC3 (voir plus loin l'explication de ce cas particulier), RSA SHA-256 ou SHA-512 (connus collectivement comme SHA-2), ECDSA avec SHA-256 ou SHA-384 sont recommandés. Tous les autres sont facultatifs (c'est par exemple le cas de GOST dans le RFC 5933) sauf RSA avec MD5 qui est à éviter (RFC 6151).
La section 2.2 justifie ces choix : RSA+SHA-1 est l'algorithme de référence, celui qui assure l'interopérabilité (tout logiciel compatible DNSSEC doit le mettre en œuvre). Normalisé pour DNSSEC avant l'apparition de NSEC3 dans le RFC 5155, il existe en deux variantes, une sans NSEC3 (celle qui est indispensable) et une avec (qui est recommandée car la plupart des TLD utilisent NSEC3). RSA+SHA-2 est recommandé car, comme indiqué plus haut, la racine et la plupart des TLD l'utilisent. Un résolveur qui ne comprendrait pas ces algorithmes ne servirait pas à grand'chose.
Au contraire, ECDSA est très peu utilisé en pratique. Mais les courbes elliptiques suscitent beaucoup d'intérêt, et sont une alternative au cas où il y aurait un gros problème avec RSA. D'où le statut « Recommandé ».
Des nouveaux algorithmes vont certainement apparaître dans le registre (cf. RFC 6014). Ils seront automatiquement considérés comme facultatifs, jusqu'à la sortie d'un nouveau RFC (qui a été le RFC 8624, qui privilégie désormais les algorithmes utilisant les courbes elliptiques).
Et si vous parlez plutôt la langue de Manuel Puig, ce RFC est également commenté en espagnol.
Date de publication du RFC : Mai 2013
Auteur(s) du RFC : D. Thaler (Microsoft)
Pour information
Première rédaction de cet article le 10 mai 2013
Utiliser des identificateurs (noms
de domaine, URI, noms
d'utilisateur, adresses de courrier, etc) comme
clés d'accès à des informations de sécurité est courant. Par exemple,
on autorise machin@truc.example
et lui seul à
accéder à certains contenus. Cela implique une
comparaison entre l'identificateur présenté et
ceux stockés dans une base. En apparence, rien de plus simple que de
comparer deux chaînes de caractères. En réalité, il existe plein de
pièges, que documente ce RFC de
l'IAB. Si tout le monde n'utilise pas
exactement le même algorithme de comparaison (et certains sont mal
spécifiés ou mal connus et permettent donc des variations), alors on
peut avoir aussi bien des dénis de service (utilisateur légitime
refusé) que des augmentations de privilèges (utilisateur illégitime
accepté).
L'informaticien naïf peut croire que comparer deux identificateurs, c'est simplement faire une comparaison bit à bit de leur représentation mais non, c'est plus compliqué que cela.
Pour comprendre le problème, la section 1 du RFC commence par parler du cycle de vie d'un identificateur. Il est d'abord généré, par exemple par une autorité centrale. Il est ensuite souvent stocké en deux endroits, chez l'utilisateur qui va s'en servir et dans une base des identificateurs enregistrés. Par exemple, si c'est une autorité centrale qui a fabriqué l'identificateur, elle le met dans sa base de données (cas, par exemple, d'un registre de noms de domaine). Naturellement, il y a des tas de possibilités différentes. Par exemple, un identificateur peut être une clé publique cryptographique, générée localement et stockée de même.
L'identificateur est ensuite distribué à ceux et celles qui en auront besoin. Cela peut se faire par des moyens numériques mais aussi par des moyens traditionnels comme une carte de visite ou une communication téléphonique. Pensez à un URL que l'on utilise dans des publicités, dans l'espoir que des gens tapent ensuite cet URL dans la barre d'adresse de leur navigateur. Ce passage par des moyens de communication non numériques est une des sources de problèmes car taper correctement un identificateur lu en vitesse sur le flanc d'un autobus n'est pas trivial.
Enfin, quelqu'un va utiliser cet identificateur. Par exemple, il va
essayer d'envoyer un message à
barack@whitehouse.gov
et espère que cela
atteindra la boîte aux lettres de quelqu'un de l'équipe du
Président. Ou bien un utilisateur va récupérer un identificateur et
essayer de le comparer avec celui qu'il connait. C'est le cas d'un
navigateur Web voulant valider un certificat
X.509 (RFC 6125).
À noter qu'il existe plein d'autres complications possibles. Par
exemple, une entité peut être désignée par plusieurs identificateurs
(ce RFC est à la fois http://www.ietf.org/rfc/rfc6943.txt
et
http://www.rfc-editor.org/rfc/rfc6943.txt
, un être humain
peut être référencé par son numéro de passeport ou bien par son
numéro de Sécu). Notre RFC ne se préoccupe pas
de ce cas, se limitant à celui, déjà assez difficile, de la
comparaison de deux identificateurs pour voir s'ils sont identiques.
Cela peut se faire de trois façons (section 1.1, et voir aussi le RFC 6885 qui avait introduit ces trois cas) :
2001:db8:1::1317
dans une
ACL, il n'y a aucune ambiguité pour déterminer
si l'adresse présentée est égale ou non à celle-ci. (Attention, ce
n'est vrai que pour la forme binaire des adresses IP, pas pour leur
représentation textuelle.)Une technique courante pour faciliter les comparaisons des identificateurs définis est la canonicalisation. On réduit d'abord l'identificateur à une forme canonique et on fait ensuite une comparaison absolue (bit à bit). Pour des noms de domaines, on peut par exemple toujours les passer en minuscules avant de comparer. Dans le cas d'identificateurs Unicode, c'est évidemment plus complexe mais il existe plusieurs algorithmes de canonicalisation Unicode. L'important est que toutes les parties impliquées utilisent le même.
On peut bien sûr comparer sans canonicaliser mais avoir une forme canonique est tellement pratique (par exemple pour l'affichage) que cela vaut toujours la peine d'en définir une. Ce faisant, on définit aussi un algorithme de comparaison.
La section 2 cite des exemples d'utilisation d'identificateurs dans
des contextes de sécurité. Par exemple, trouver une clé en échange
d'un nom (a principal, dit-on en sécurité),
chercher dans une ACL si une entité est
autorisée, compter l'activité d'une entité donnée (et il faut donc
ajouter son activité dans la bonne ligne du tableau). Le point
important est qu'il faut que tout le monde utilise le même
algorithme. Si on stocke l'activité d'adresses de courrier
électronique sans les canonicaliser, et que quelqu'un change son
adresse de jean@durand.example
à
jean@Durand.EXAMPLE
(pourtant la même adresse),
il pourra apparaître comme vierge, comme n'ayant pas d'activité
précédente.
Les cas réels peuvent être très compliqués. Par exemple, en HTTPS, on compare ce qu'a tapé un utilisateur dans la barre d'adresses du navigateur avec ce que contient le certificat (RFC 6125). Plusieurs protocoles différents sont en jeu (de la définition des URL à celle de X.509) et plusieurs acteurs (des utilisateurs qui tapent plus ou moins bien, sur des systèmes très variés, et tout le monde des AC), chacun de ces acteurs pouvant avoir ses propres règles.
En cas d'algorithmes différents utilisés par des parties
différentes, on peut avoir aussi bien des faux
positifs que des faux négatifs. Les
faux positifs, c'est quand deux identificateurs sont considérés comme
identiques alors qu'ils ne devraient pas. (Je me souviens d'un vieux
système Unix où le nom de
login était silencieusement tronqué à huit
caractères, donc bortzmeyer
et
bortzmeye
étaient considérés identiques.) Si les
privilèges sont attribués en fonction de cette égalité, on a un gain
en privilèges. Si, par contre, les privilèges sont refusés en fonction
de cette égalité (cas d'une liste noire), on a
un refus d'un service légitime. Le faux négatif, c'est le contraire :
deux identificateurs considérés comme différents alors qu'ils sont
équivalents (cas de jean@durand.example
et
jean@Durand.EXAMPLE
plus haut, si on oublie que
le nom de domaine est insensible à la casse). Les conséquences sont
opposées : si les
privilèges sont attribués en fonction de cette égalité, on a un refus
de service. Si, par contre, les privilèges sont refusés en fonction
de cette égalité, on a un gain de privilèges, à tort.
Évidemment, le gain de privilèges est plus grave que le refus de service et c'est pour cela qu'on trouve, par exemple, dans la section 6.1 du RFC 3986 « comparison methods are designed to minimize false negatives while strictly avoiding false positives ». (Cet exemple suppose que les privilèges sont accordés en fonction de l'égalité et que les faux positifs sont bien plus graves.)
Le RFC donne un exemple où les identificateurs sont des
URI. La société Foo paie
example.com
pour accéder à un service nommé
Stuff. Alice, employée de Foo, a un compte identifié par
http://example.com/Stuff/FooCorp/alice
. En
comparant des URI, Foo tient compte du fragment (la partie après le
#, section 3.5 du RFC 3986) ce qu'example.com
ne fait pas. Et
Foo permet les # dans les noms de compte. Un autre employé de Foo, le
malhonnête Chuck, se fait créer un compte avec l'identificateur
http://example.com/Stuff/FooCorp/alice#stuff
. Foo
ne voit pas le problème puisque cet identificateur n'existe pas. Chuck
va donc pouvoir obtenir des autorisations d'accès de Foo. Il
peut ensuite se connecter auprès d'example.com
comme étant
http://example.com/Stuff/FooCorp/alice
,
l'identificateur d'Alice. Certes, l'autorisation de Chuck n'était
valable que pour
http://example.com/Stuff/FooCorp/alice#stuff
mais
rappelez-vous qu'example.com
compare les URI en
ignorant les fragments... Voici un cas où les différences entre les
mécanismes de comparaison d'identificateurs ont permis un
accroissement illégitime de privilèges.
Après cet exemple, la section 3 fait le tour des identificateurs
les plus courants et de leurs pièges spécifiques. D'abord, les noms de
machines. Ce sont normalement un sous-ensemble des noms de domaines (RFC 6055) mais notre RFC utilise ce terme
dans un sens plus large, pour parler de tous les fois où un
identificateur ou composant d'identificateur est appelé Host. Ils sont souvent utilisés comme
identificateurs, soit directement (par exemple dans le RFC 5280), soit indirectement, comme partie d'un identificateur (le RFC cite
l'exemple des URI et des adresses de courrier). Le RFC note bien que
ce terme de nom de machine (hostname) est
ambigu. Ainsi, dans tyrion.lannister.got
, le nom
de machine est-il tyrion
ou bien
tyrion.lannister.got
(section 3.1 du RFC 1034) ? Cela peut entraîner des
problèmes lorsqu'on veut décider si la machine
tyrion
a accès aux privilèges de la machine
tyrion.lannister.got
...
Dans le sens large qu'il a ici « nom de machine » peut aussi être
une adresse IP littérale. Cela entraîne
d'autres confusions possibles. Par exemple, si le
TLD .42
existe et qu'un
nom 103.2.1.42
est enregistré, comment le
distinguer de l'adresse IPv4
103.2.1.42
? Normalement, la section 2.1 du RFC 1123 règle la question : on doit tester l'adresse
IP d'abord et 103.2.1.42
n'est donc jamais un
nom. Mais il n'est pas sûr que tous les programmes appliquent le RFC 1123... Certaines personnes pensent donc qu'il y
a un risque à accepter des TLD numériques, même si le RFC 1123 est clair.
Autre source d'ambiguité : la norme POSIX
1003.1 de l'IEEE admet pour une adresse IPv4
plusieurs formes, pas seulement la forme classique en quatre
composants séparés par des points. Ainsi, 10.0.258
,
0xA000201
et 012.0x102
sont
des représentations légales de la même adresse, 10.0.1.2
. Certaines normes se
tirent d'affaire en imposant la forme stricte, celle avec les quatre
composants décimaux séparés par des points. C'est le cas des URI, par
exemple (« an IPv4 address in dotted-
decimal form »). Même chose avec
inet_pton
qui n'accepte que la forme
stricte. Si les différentes formes sont acceptées, on peut avoir un
problème d'ambiguité.
Et avec IPv6 ? Il y a également plusieurs
représentations texte possibles (mais, à mon avis, moins susceptibles
de poser des problèmes en pratique), par exemple
2001:db8::1
et
2001:DB8:0:0:0:0:0:1
pour la même adresse, sans
compter des cas plus tordus comme les identificateurs de zone dans les
URL (RFC 6874). Contrairement à IPv4, il existe
une représentation canonique, normalisée dans le RFC 5952 mais elle n'est pas forcément utilisée par tous.
L'internationalisation (RFC 2277) ajoute
évidemment quelques questions. Par exemple, la section 3.2.2 du RFC 3986 autorise un nom de domaine
Unicode à être écrit en encodage pour-cent
ou en punycode (le second
étant recommandé mais pas imposé). Comment
comparer caf%C3%A9.fr
et
xn--caf-dma.fr
? Comme souvent en matière
d'internationalisation (qui n'a jamais été complètement acceptée par
certains), le RFC pinaille même plus loin en imaginant le cas
(purement hypothétique) d'un registre qui accepterait l'enregistrement
de noms commençant par xn--
, entrainant ainsi une
confusion avec des IDN.
Autre façon de comparer des noms : les résoudre en adresses IP et comparer les adresses. C'est ce que fait la bibliothèque standard Java par défaut (classe URL). Cette méthode a évidemment toujours été dangereuse, mais c'est encore pire maintenant, avec les adresses IP privées, les trucs du DNS pour avoir une réponse dépendant de la source, les mobiles, etc. Elle était conçue pour lutter contre des failles de sécurité comme le changement DNS mais le jeu en vaut-il la chandelle ? Sans compter qu'il est contestable d'attendre le DNS juste pour comparer deux identificateurs.
Après les noms de machines, les ports. L'URL
http://www.example.com:443/
est-il égal à
http://www.example.com:https
,
https
ayant été enregistré (RFC 6335) comme équivalent de 443 ? (Cet exemple est facile : la
seconde forme est illégale dans un URL HTTP. Mais, dans d'autres cas,
cela peut être ambigu.)
On a souvent vu les URI dans les deux sections précédentes, consacrées aux noms de machines et aux ports. Le principal problème de la comparaison d'URI est qu'un URI est formé de plusieurs composants, chacun suivant des règles de comparaison différentes. Second problème, il existe plusieurs mécanismes standard de comparaison d'URI (RFC 3986, section 6.2, qui décrit l'échelle des comparaisons, de la plus simple à la plus complète). Le but de cette variété est de permettre aux diverses applications des URI d'optimiser pour les performances ou pour la sécurité. L'inconvénient est que deux comparateurs d'URI peuvent donner des résultats différents sans même qu'on puisse accuser l'un d'eux d'être bogué ou non standard.
Certains composants de l'URI posent des problèmes particuliers :
les plans définissent la syntaxe spécifique d'un type d'URI et il ne
faut donc jamais essayer de comparer deux URI de plans différents
(http
et ftp
par exemple,
même si, dans ce cas, la syntaxe est la même).
Un autre cas souvent oublié dans les URI est la partie nommée
userinfo avant le @, par
exemple dans
ftp://alice:bob@example.com/bar
. Doit-elle être
considérée significative en comparant des URI ? Le RFC ne fournit pas
de règles à ce sujet.
Le chemin après le nom de machine pose un autre problème, celui des
caractères .
et
..
qui, normalement, indiquent un chemin relatif.
Mais la section 5.2.4 du RFC 3986 fournit un
algorithme pour les retirer, transformant
http://example.com/a/b/c/./../../g
en
http://example.com/a/g
. Un nouveau piège pour la
comparaison ?
Continuons vers la fin de l'URI. Après le ?
il y a une requête. Doit-elle être prise en compte dans la
comparaison ? Là encore, pas de réponse simple, c'est à l'application
de décider si
http://www.example.org/foo/bar?ref=323
est
identique à http://www.example.org/foo/bar
. Un
exemple où cette question se pose est celle d'un site de référencement
d'URI, avec les nombreux cas où la requête ne stocke en fait qu'une
variable de suivi de la circulation de l'URI (lu sur
Twitter, lu sur
Facebook, etc).
Reste le fragment, la dernière partie d'un URI, après le #. En général, lorsqu'on utilise un URI comme identificateur dans un contexte de sécurité, on ignore le fragment (voir l'exemple plus haut avec Chuck et Alice...) Mais ce n'est pas une règle qui marche dans tous les cas. Là encore, l'important est la cohérence : que toutes les applications qui gèrent cet URI fassent pareil.
Comme pour les noms de machine, dans l'exemple Java plus haut, on pourrait se dire qu'une façon simple de comparer deux URI est de les déréférencer et de voir s'ils pointent vers des contenus identiques. Mais tous les URI ne sont pas déréférençables, on n'a pas forcément envie d'imposer une connexion Internet en état de marche juste pour comparer deux identificateurs et, de toute façon, un tel algorithme serait très fragile (que faire si on trouve le même document XML mais avec des encodages différents ?) En outre, toute démarche active comme celle-ci est dangereuse pour la vie privée (elle informe les gérants des serveurs Web de ce que l'on est en train de faire, comme le font les Web bugs).
Après les URI, place à une catégorie d'identificateurs très souvent
utilisés pour identifier une entité, les adresses de courrier (RFC 5322 pour leur syntaxe, et RFC 6532 pour le cas où elles sont internationalisées). Une
adresse de courrier, comme un URI, a plusieurs parties, qui suivent
des règles différentes pour la comparaison. La partie à droite du
@ est un nom de domaine et ce cas a été traité
plus haut. La partie gauche, dite partie locale, est un identificateur
indéfini : ses règles ne sont pas connues à l'extérieur et on ne peut
donc pas savoir, par exemple, si rms@gnu.org
et
RMS@gnu.org
sont le même utilisateur, ou si
stephane+ps@bortzmeyer.org
est le même que
stephane+ump@bortzmeyer.org
. Dans le cas où des
adresses de courrier sont utilisées dans un certificat, on choisit
souvent une comparaison bit à bit... qui peut donner plein de faux négatifs.
Après cette liste à la Prévert de problèmes,
la section 4 de notre RFC tente une synthèse. Elle identifie quatre
problèmes. Le premier est la confusion. Un
identificateur est utilisé sans que son type soit clair. Par exemple,
si je tape telnet 1000
, est-ce l'adresse
IPv4 0.0.3.232
ou bien
l'adresse IPv6 ::3:e8
?
Et si je tape ping 10.1.2.42
, est-ce que
10.1.2.42
est un nom ou une adresse (le TLD
.42
peut exister) ?
Résoudre la confusion nécessite un algorithme clair. Dans le
premier exemple ci-dessus, il n'y a pas de
confusion. 100
ne peut pas être une adresse IPv6
légale (la présence ou l'absence d'un :
suffit à
les reconnaître). Le second exemple est normalement clair : l'adresse
IP a priorité donc 10.1.2.42
ne peut pas être un
nom même si le TLD .42
existe. Si cette règle de
précédence est respectée par les implémentations, il n'y aura pas de
problèmes (identificateurs définis). Mon avis personnel est que ce RFC
pinaille quand même très fort sur ce point, en s'interrogeant
gravement sur des problèmes théoriquement intéressants mais extrêmement
tordus et donc rares en pratique.
Deuxième problème, l'internationalisation. Un logiciel n'a aucun
problème à comparer google.com
et
goog1e.com
et à dire qu'ils sont
différents. C'est plus difficile pour un humain (vous aviez repéré le
L qui était en fait un 1 ?) Toutes les fois où un humain est impliqué,
dans la saisie ou la reconnaissance d'un identificateur, ce genre d'erreur peut se produire. Comme le montre cet exemple, cela n'a
d'ailleurs rien de spécifique aux chaînes de caractères Unicode. Mais
ce problème est souvent cité comme argument contre
l'internationalisation. Bref, le point important : la sécurité ne
devrait pas dépendre d'une vérification visuelle faite par un
humain. (Cf. l'article
de Weber et le RFC 6885.)
Problème suivant, la portée. Certains
identificateurs ne sont pas uniques au niveau
mondial. localhost
est un bon exemple. C'est
également le cas des adresses du RFC 1918. On
peut aussi citer l'adresse de courrier alice
qui,
utilisée depuis une machine d'example.com
arrivera à une Alice et, depuis une machine d'un autre domaine, à une
autre. Dans ce dernier cas, la bonne solution est de toujours utiliser
une adresse unique (par exemple
alice@example.com
) même dans un contexte local :
l'expérience prouve que les identificateurs fuient souvent d'un
domaine local vers un autre.
Enfin, dernier problème identifié par cette section 4, la
durée. Certains identificateurs ne sont pas
éternels et peuvent disparaître, ou désigner une autre entité. Par
exemple, bob@example.com
peut désigner un Bob
aujourd'hui et, s'il quitte l'entreprise et qu'un autre est embauché,
un Bob complètement différent dans quelques mois. C'est la même chose
pour les adresses IP et des tas d'utilisateurs ont déjà souffert de se
voir attribuer une adresse IP qui avait une mauvaise réputation.
La section 5 résume les conseils les plus importants : se méfier des identifcateurs indéfinis, prévoir une comparaison absolue ou définie pour tous les identificateurs futurs, penser aux mécanismes pour valider les identificateurs (RFC 3696). Le gros risque restera toujours le cas où plus d'un protocole utilise un identificateur donné, car les différents protocoles n'auront pas forcément les mêmes règles de comparaison des identificateurs.
Date de publication du RFC : Janvier 2014
Auteur(s) du RFC : C. Jennings (Cisco), B. Lowekamp (Skype), E. Rescorla (RTFM, Inc.), S. Baset, H. Schulzrinne (Columbia University)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF p2psip
Première rédaction de cet article le 17 janvier 2014
Le groupe de travail IETF p2psip travaille à permettre la communication (par exemple téléphonique) entre utilisateurs de SIP sans passer par un fournisseur SIP, mais en se débrouillant en pair-à-pair. Pour cela, le groupe a choisi une approche modulaire et a d'abord développé un protocole de communication pair-à-pair, qui va servir de socle aux futures utilisations. Ce protocole se nomme RELOAD (pour REsource LOcation And Discovery), et fait l'objet de ce très long RFC, le premier du groupe p2psip.
L'enjeu est d'importance : le système fermé Skype a obtenu beaucoup d'utilisateurs en s'appuyant partiellement sur des techniques pair-à-pair. Le SIP traditionnel, où deux correspondants ne communiquent que via leurs fournisseurs SIP respectifs devait être amélioré en exploitant ces capacités pair-à-pair. Échanger des paquets RTP directement est facile. Se trouver et initier la communication l'est moins. Pour le faire en pair-à-pair, il n'existait pas de protocole ouvert et normalisé. On notera d'ailleurs que RELOAD est le premier protocole pair-à-pair (au sens moderne parce que, objectivement, IP a toujours été pair-à-pair) normalisé par l'IETF.
RELOAD est suffisemment général pour pouvoir être utilisé dans le futur par d'autres systèmes que SIP. Qu'est-ce qu'il fournit comme service que les autres protocoles existants ne fournissaient pas ?
Si vous voulez vous cultiver sur Chord, l'article original est « Chord: A Scalable Peer-to-peer Lookup Protocol for Internet Applications » (IEEE/ACM Transactions on Networking Volume 11, Issue 1, 17-32, Feb 2003, 2001) et Wikipédia en anglais a un bon article.
Une instance RELOAD est donc un overlay (un réseau virtuel utilisant un algorithme donné) où chaque nœud (pair ou simple client) a un identificateur, le Node-ID. Cet overlay forme un graphe où tout nœud n'a pas forcément directement accès à tout autre nœud, et les pairs doivent donc se préparer à router les messages (les simples clients en sont dispensés).
L'instance RELOAD offre deux services, la transmission de messages et le stockage de données (données de petite taille, a priori, celles nécessaires à la communication). Chaque donnée a un identificateur, le Resource-ID, qui utilise le même espace de nommage que les Node-ID. Il y a ensuite une relation entre les Node-ID et les Resource-ID par exemple, qu'un nœud est responsable de toutes les données dont le Resource-ID est compris entre son Node-ID et le Node-ID précédent (si vous connaissez les DHT, ce genre de concept vous est familier. Sinon, cela peut être le moment de s'arrêter pour lire des choses sur les DHT.) La relation exacte dépend de l'algorithme d'overlay utilisée. Celle donnée en exemple est valable pour Chord.
Pour accomplir ses tâches, RELOAD a plusieurs composants. De haut en bas (si cela ressemble au modèle en couches, c'est exprès, sauf que ces couches sont entassées sur l'overlay, pas sur un réseau physique) :
La sécurité est traditionnellement le point
faible des DHT (et du pair-à-pair en général). (Voir l'excellent exposé d'Eric Rescorla.) Le principe de base de la sécurité de RELOAD est que chaque
pair aura un certificat délivré par une
instance centrale (qui ne sera responsable que de l'inscription des
pairs : elle ne participera ni au routage, ni à l'envoi des messages,
ni au stockage,). Chaque message, et chaque objet stocké, sera signé avec ce certificat et
toutes les communications de bas niveau chiffrées (par exemple avec
TLS). Une machine qui veut rejoindre
l'overlay doit se connecter en
HTTPS au serveur central, qui lui attribuera un
Node-ID (dans le champ
subjectAltName
du certificat RFC 5280). Le serveur central demandera probablement une
authentification (par exemple nom et mot de passe). Ce serveur et les
vérifications qu'il fait sont le cœur de la sécurité de RELOAD. La machine joindra ensuite le réseau virtuel (les détails
sur la façon dont elle le fait dépendent de l'algorithme utilisé pour
le maintien de l'overlay).
Ne vous inquiétez pas forcément de ces obligations de sécurité : elles ne sont valables que pour un overlay installé sur le grand Internet public. Si vous avez un environnement restreint et sécurisé (disons un groupe de machines formant un réseau ad hoc local), vous avez le droit de vous en dispenser et de vous contenter de certificats auto-signés par les pairs, où le Node-ID est simplement un condensat de la clé publique. Une telle façon de fonctionner laisse le réseau très vulnérable aux attaques Sybil mais peut convenir si vous savez que vous êtes « entre vous ». Autre possibilité de simplification de la sécurité : RELOAD a un mode où les pairs s'authentifient, non pas par un certificat, mais par un secret partagé (par exemple RFC 4279).
Voici donc les grands principes de RELOAD. Je ne vais pas ensuite détailler les 186 pages du RFC, juste quelques points que je trouve intéressants. Le mécanisme de routage est présenté en section 3.3. Par défaut, RELOAD utilise du récursif symétrique (section 6.2). La requête enregistre les nœuds par lesquels elle est passée (dans la Via List) et la réponse suivra le même chemin en sens inverse. Si la topologie a changé entre-temps, la réponse sera perdue et ce sera aux couches supérieures de réémettre. (Il existe une alternative à ce stockage du chemin dans le message lui-même : si les pairs intermédiaires peuvent stocker des données, ils peuvent garder la mémoire des routes suivies, au lieu d'utiliser la Via List.)
L'inscription initiale dans l'overlay est un
problème intéressant, car on voudrait que cela soit simple pour
l'utilisateur, par exemple qu'il n'ait pas à rentrer 50 paramètres
dans son client SIP. L'idée est que le nouveau pair n'a à connaître que le
nom de l'overlay (un FQDN)
et peut-être des informations d'authentification. Une requête
SRV dans le DNS à partir
du nom du réseau (précédé de _reload-config._tcp
) donne le nom du serveur de configuration, qu'on
contacte en HTTPS en lui demandant la ressource
.well-known/reload-config
(RFC 8615 pour .well-known
). Ce serveur envoie alors tous les détails de
configuration de l'overlay, en
XML, un exemple figure en section 11 et à la
fin de cet article. (Une machine peut aussi avoir cette
configuration dans un fichier local.) C'est alors que le futur pair
connait le nom du serveur d'inscription et peut le contacter pour
apprendre son Node-ID.
Le stockage pair-à-pair dans RELOAD (section 4.1) permet de stocker différents
types (kind) d'objets. Un type peut être défini
comme stockant un scalaire, un
tableau ou un
dictionnaire (section 7.2 pour les détails). Tous les objets stockés sont
signés par le déposant, qui pourra ainsi vérifier que ses pairs ne se
sont pas moqués de lui. (Voir mon article « Assurer l'authenticité des données
stockée dans une DHT».) À noter qu'un pair ne peut pas stocker des
objets sous des noms arbitraires. Typiquement (cela dépend de l'application), il ne peut stocker que
sous son propre nom (alice@example.com
pour du SIP), ce qui fait qu'il ne pourra pas noyer tous les
nœuds de la DHT sous des objets à stocker.
Une des choses les plus nécessaires pour communiquer en pair-à-pair est la découverte. Trouver quelqu'un ou quelque chose dans l'immensitude de l'Internet est difficile (alors que c'est trivial en centralisé, d'où le succès de services comme Facebook). Il existe actuellement plusieurs Internet-Drafts décrivant de futurs services de découverte qui tourneront au dessus de RELOAD.
Le format des messages RELOAD est décrit en section 6.3 : format binaire, avec les premiers en-têtes, qui sont obligatoires, à une position fixe (pour une analyse plus rapide) et les suivants, qui sont optionnels, encodés en TLV (pour la souplesse et l'extensibilité). Chaque message est auto-suffisant, un peu comme un datagramme. Sa première partie, le Forwarding Header, est la seule qui ait besoin d'être examinée par les routeurs intermédiaires. Les deux autres, le Message Content et le Security Block (les signatures), ne concernent que la machine de destination.
Notre RFC utilise une syntaxe analogue à celle du
C pour décrire le format des messages (un peu
comme le fait le RFC 5246). Principal point à
noter pour lire cette syntaxe (la section 6.3.1 fournit tous les détails) : les termes entre
chevrons sont des valeurs de taille
variable. Par exemple data<0..15>
désigne
de zéro à quinze octets de données.
Le Forwarding Header contient les Via Lists vues plus haut et les destinations (la plupart du temps, il n'y en a qu'une seule mais RELOAD permet d'indiquer une liste de destinations à parcourir successivement : pour comparer avec le datagramme IP, disons que la liste des destinations est une fusion de l'adresse IP de destination et de l'option Source route). Cela donne :
struct { ... uint32 overlay; /* Un condensat du nom */ ... uint8 ttl; ... uint32 length; ... uint16 via_list_length; /* Pour le routage symétrique */ uint16 destination_list_length; ... Destination via_list[via_list_length]; Destination destination_list [destination_list_length]; ... } ForwardingHeader;
Pour cet en-tête, qui doit être lu très vite par les routeurs
intermédiaires, RELOAD utilise l'encodage {longueur, tableau}. Les
autres termes de longueur variable utiliseront un encodage moins
rapide à analyser mais plus propre. Le type
Destination
est, en résumant, un Node
ID ou Resource ID (rappelez-vous que ces
ID ont la même forme - dépendante du type
d'overlay - et sont tirés du même espace).
La deuxième partie du message, Message Content, est largement opaque :
struct { uint16 message_code; opaque message_body<0..2^32-1>; MessageExtension extensions<0..2^32-1>; } MessageContents;
C'est donc surtout une suite d'octets, 2^32 au maximum. Le code indique la sémantique du message (demande de stockage de données, « ping », annonce d'un nouveau pair, etc) et la liste des codes est dans un registre IANA.
La troisième et dernière partie du message, le Security Block, est une liste de certificats X.509 et une signature :
struct { GenericCertificate certificates<0..2^16-1>; Signature signature; } SecurityBlock;
Tous les messages doivent être signés et les signatures vérifiées à la réception.
Les responsabilités du greffon de gestion de la topologie figurent
dans la section 6.4. Elles sont décrites sous forme de messages
abstraits, à incarner pour chaque algorithme
d'overlay. Un exemple, le message
Join
lorsqu'un nouveau pair arrive :
struct { NodeId joining_peer_id; opaque overlay_specific_data<0..2^16-1>; } JoinReq;
Les protocoles de communication entre deux nœuds devront fournir des mécanimes d'authentification du Node ID, d'intégrité et de confidentialité, par exemple en s'appuyant sur TLS (section 6.6.1). Le RFC suggère d'explorer la possibilité d'utiliser HIP (RFC 7401 et section 6.6.1.1) qui a toutes les propriétés voulues. Ils doivent aussi respecter les principes du RFC 8085, i.e. ne pas noyer les destinataires sous les retransmissions.
Le stockage des données fait l'objet de la section 7. On stocke des objets qui ont cette forme :
struct { uint32 length; uint64 storage_time; uint32 lifetime; StoredDataValue value; Signature signature; } StoredData;
On voit qu'ils sont signés, et ont une durée de vie maximale.
On l'a dit, RELOAD utilise par défaut la DHT Chord et toutes les mises en œuvre de RELOAD doivent connaître Chord, pour assurer l'interopérabilité. Le mécanisme utilisé par RELOAD est légèrement différent du Chord original et la section 10 détaille ces différences. Les deux principales :
Les grands principes de Chord sont gardés : nœuds organisés en un anneau (le dernier nœud dans l'ordre des Node ID est donc le précédesseur du premier), utilisation de SHA-1 (tronqué aux 128 premiers bits dans Chord-RELOAD) pour trouver le Resource ID à partir des données, table de routage composée, non seulement des voisins immédiats, mais aussi de pointeurs (les fingers) vers un certain nombre de non-voisins (pour des raisons de performance, car cela évite de parcourir la moitié de l'anneau, mais aussi de résilience, pour survivre à la perte des voisins), etc
Un exemple de fichier de configuration d'un réseau virtual (overlay) figure en section 11 :
<overlay> <configuration instance-name="overlay.example.org" sequence="22" expiration="2002-10-10T07:00:00Z" ext:ext-example="stuff" > <!-- Le greffon de topologie par défaut : --> <topology-plugin>CHORD-RELOAD</topology-plugin> <!-- Le certificat qui va signer tout : --> <root-cert> MIIDJDCCAo2gAwIBAgIBADANBgkqhkiG9w0BAQUFADBwMQswCQYDVQQGEwJVUzET... </root-cert> <!-- Les serveurs à contacter pour avoir Node-ID et certificat : --> <enrollment-server>https://example.org</enrollment-server> <enrollment-server>https://example.net</enrollment-server> <!-- Les pairs à contacter pour rejoindre l'overlay : --> <bootstrap-node address="192.0.0.1" port="6084" /> <bootstrap-node address="192.0.2.2" port="6084" /> <bootstrap-node address="2001:db8::1" port="6084" /> <!-- Les paramètres spécifiques à la DHT : --> <chord:chord-update-interval> 400</chord:chord-update-interval> <chord:chord-ping-interval>30</chord:chord-ping-interval> <chord:chord-reactive>true</chord:chord-reactive> <!-- Et bien d'autres choses encor... --> </overlay>
6084 est le port par défaut pour RELOAD (section 14.2). La grammaire pour ce fichier de configuration est normalisée (en Relax NG) en section 11.1.1.
Pour contacter les serveurs d'inscription (enrollment
server), le protocole à utiliser est en section 11.3. L'IETF
a choisi de ne pas réutiliser les protocoles existants (RFC 5272 et RFC 5273) car ils sont trop complexes. À la
place, le futur pair fait juste une requête HTTPS
POST
dont le contenu comprend
du PKCS#10 (contenant la demande de certificat,
cf. RFC 2311). Cette requête doit aussi contenir les
informations d'authentification du pair (par exemple un nom et un mot
de passe). En échange, le serveur enverra un certificat dont le sujet
(le nom) sera un Node ID, choisi au hasard (RFC 4086 ; c'est important car certaines attaquent
contre les DHT nécessitent que l'attaquant choisisse son Node
ID). En outre, le champ subjectAltName
doit contenir le nom que l'utilisateur sera autorisé à présenter à
l'application (pour SIP, ce sera un nom de type
machin@truc.example
). Certaines autorisations
(par exemple d'accès aux données stockées) dépendront de ce nom.
La faiblesse traditionnelle des DHT (ou du pair-à-pair en général) est la sécurité (RFC 5765). Sans chef pour contrôler les échanges, que faire si un méchant s'insère dans le réseau pair-à-pair pour l'espionner, modifier les données, ou bien empêcher le réseau de fonctionner ? La section 13 revient en détail sur les questions de sécurité. Le fond du problème est qu'on dépend des pairs (pour envoyer des messages à d'autres pairs ou bien pour stocker des données) et qu'on n'a pas de relation bien définie avec ces pairs. Sur un réseau public comme l'Internet, les pairs peuvent être n'importe qui, y compris des méchants. Si la majorité des pairs sont dans ce cas, on est fichu, aucun algorithme astucieux ne peut marcher dans ces conditions. Il faut donc agir sur l'inscription (enrollment). C'est ce que fait RELOAD (section 13.3) en imposant le passage par un serveur d'inscription pour obtenir un certificat, puis en imposant de prouver la possession d'un tel certificat (en signant les messages avec la clé).
RELOAD permet des certificats auto-signés mais, dans ce cas, l'overlay peut être vite noyé sous les pairs malveillants (ce qu'on nomme une attaque Sybil). La seule sécurité qui reste est le Node ID (qui est dérivé du certificat et est donc cryptographiquement vérifiable). Bref, une telle sécurité ne convient que dans des environnements fermés, où on est sûr de toutes les machines présentes. Un exemple typique est un réseau ad hoc entre les machines des participants à une réunion (et encore, en Wifi, attention à l'attaquant de l'autre côté du mur...). Dans ce cas, on peut même se passer complètement des certificats en choisissant la solution du secret partagé : on le distribue à tous les participants à la réunion et ça roule (section 13.4).
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : G. Fairhurst (University of Aberdeen), M. Westerlund (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 1 mai 2013
Le RFC 2460 qui normalise IPv6 indique dans sa section 8.1 que les paquets UDP sur IPv6 doivent avoir une somme de contrôle (elle était facultative en IPv4) calculée selon le RFC 1071. Dans quels cas est-elle réellement nécessaire ? Peut-on s'en passer parfois ? Ce nouveau RFC discute des conditions qui peuvent permettre de mettre zéro dans le champ Checksum, indiquant qu'on n'a pas utilisé de somme de contrôle. Pour résumer : si on veut se passer de somme de contrôle, cela doit se faire application par application, il faut être sûr qu'on supporte les paquets corrompus ou délivrés à tort, et il faut tester le chemin emprunté pour être sûr que les « nouveaux » paquets passent bien.
Ce RFC discute des solutions à un problème de performance d'UDP et des conditions dans lesquels on peut ne plus mettre de somme de contrôle. Il sert donc d'arrière-plan au RFC normatif, le RFC 6935 qui définit les nouvelles règles pour UDP sur IPv6 (somme de contrôle facultative) et fait donc un choix ferme parmi les propositions discutées ici. Notez toutefois qu'il y a pas mal de recouvrement et de redites entre les deux RFC.
UDP est très utilisé, et pour beaucoup d'applications (le RFC 8085 donne des conseils à ce sujet). Un des usages fréquents est pour construire des tunnels, afin de pouvoir passer à travers les millions de middleboxes stupides qui infestent l'Internet, et qui bloquent souvent tous les protocoles autres que UDP et TCP. Or, un routeur d'entrée ou de sortie de tunnel peut avoir à encapsuler ou décapsuler des millions de paquets par seconde et la génération ou la vérification des sommes de contrôle de chaque paquet peut avoir un effet mesurable sur ses performances (sections 1.3.2 et 1.3.3). D'autant plus qu'il n'est pas toujours possible d'utiliser le matériel spécialisé du routeur pour cela car il ne donne souvent accès qu'aux N premiers octets du paquet (avec N typiquement < 128), alors que le calcul de la somme de contrôle nécessite d'accéder à tout le paquet.
En UDP/IPv4, la solution est de couper la somme de contrôle sur le paquet externe (le protocole interne, qui n'est pas forcément UDP, reste protégé par sa propre somme de contrôle), ce qui est légal en IPv4. Le tunnel devient alors un lien virtuel non fiable, pouvant corrompre des paquets (comme c'est le cas d'un certain nombre de liens physiques). C'est par exemple la solution recommandée pour un gros consommateur de tunnels UDP, LISP. Il est donc tentant de l'utiliser également en UDP/IPv6.
Cela peut poser des problèmes avec certaines middleboxes qui vérifient la somme de contrôle UDP et n'accepteront pas d'y trouver zéro. Décréter que la somme de contrôle UDP en IPv6 devient facultative ne signifie donc pas que ces paquets optimisés pourront voyager dès demain sur tout l'Internet : un certain nombre de pare-feux les bloqueront. Cela peut sembler un problème rédhibitoire (on utilisait UDP justement pour passer facilement à travers les middleboxes puis on réforme les règles d'UDP, créant des paquets qui sembleront illégaux à beaucoup de ces middleboxes) mais il faut noter que la plupart des ces middleboxes ne font pas encore d'IPv6 et que donc les premiers déploiements ont des chances de se faire avec des middleboxes conformes à la nouvelle règle.
À part l'UDP existant, et l'UDP avec somme facultative du RFC 6935, quelles sont les autres technologies disponibles pour des tunnels (section 2 du RFC) ? Il y a UDP Lite (RFC 3828), avec une somme de contrôle qui ne couvre que le début du paquet (et est donc rapide à calculer), et qui est certes mis en œuvre dans le noyau Linux mais qui est peu reconnu par les middleboxes. Il utilise un identifiant (champ Next Header qui identifie en général le protocole de transport) différent de celui d'UDP (136 contre le 17 d'UDP) et est donc souvent bloqué par des pare-feux trop zélés. Il y a les techniques de tunnels génériques comme IP-in-IP et GRE. Elles n'ont pas de somme de contrôle du tout et sont donc rapides. Ce sont les solutions idéales pour les tunnels mais elles aussi utilisent un champ Next Header qui peut ne pas être connu de la middlebox (94 pour IP-in-IP et 47 pour GRE) et ils passent certainement moins souvent qu'UDP (d'où le choix d'UDP pour LISP). Notons aussi que la section 6 déconseille les tunnels récursifs (un tunnel dans un tunnel dans un tunnel...) qui augmentent les risques d'erreur pour le paquet le plus interne (et ajoutent une grande complexité à la fragmentation).
La section 3 examine ensuite les choses qui peuvent aller mal avec la solution retenue par le RFC 6935. Si on ne met pas de somme de contrôle dans le paquet UDP (ou, plus exactement, qu'on met zéro, indiquant qu'on n'a pas calculé de somme et que le récepteur ne doit pas vérifier), et qu'un bit du paquet est modifié, que peut-il se passer d'horrible ? Pour IPv4, la somme de contrôle UDP ne servait qu'à protéger les numéros de port et les données, des informations comme l'adresse IP de destination étaient protégées par la somme de contrôle de la couche 3. Celle-ci a disparu en IPv6 et la somme de contrôle UDP doit donc tout faire. Si elle est erronée, on n'est même pas sûr que le paquet nous était bien destiné (l'adresse IP de destination a pu être modifiée).
Comme l'expliquent le RFC 3819 ou des études comme « When the CRC and TCP Checksum Disagree », la corruption arrive réellement dans l'Internet. Des mesures ont indiqué jusqu'à 1 paquet corrompu sur 10 000 (cela dépend fortement du chemin suivi : le taux de corruption est quasi-nul sur certains chemins). Le RFC note (section 3.2) qu'on ne sait pas exactement où la corruption survient : cela peut être dans la RAM du routeur, sur le câble, dans les récepteurs et les émetteurs optiques ou électriques, etc.
Si c'est l'adresse IP de destination qui est modifiée, le paquet peut n'arriver nulle part, ou bien arriver à une machine qui ne l'attend pas. Si aucun programme n'écoute sur le port en question, le paquet est jeté (et un message d'erreur envoyé à la source, qui sera bien surprise). Si un programme écoute, il va recevoir un paquet invalide. Même chose si c'est le port de destination seul qui a été corrompu. Si l'application n'a pas de mécanisme (comme des numéros de séquence) pour détecter le problème, le paquet invalide pourra être accepté. Donc, une règle importante : une application qui est prête à débrayer les sommes de contrôle UDP doit être prête à réagir proprement si elle reçoit un datagramme envoyé à tort. C'est une des raisons pour lesquelles le RFC exige que la suppression de la somme de contrôle UDP ne se fasse pas globalement, pour toute la machine ou pour toute l'interface réseau, mais uniquement sur requête explicite d'une application majeure et consentante (section 3.5)
Si c'est l'adresse IP source qui est corrompue, le paquet arrivera sans doute à la bonne destination (mais pas à coup sûr, par exemple en cas de filtrage RFC 2827). Si l'application garde en mémoire ses correspondants, le paquet de ce correspondant inconnu sera jeté. Si elle ne le fait pas, si une réponse est envoyée... elle le sera au mauvais correspondant.
Et si c'est l'information de fragmentation qui est corrompue ? Cela peut empêcher le réassemblage (menant à la perte du paquet) mais aussi, ce qui est bien pire, conduire à des réassemblages erronés (par exemple, si le champ ID est modifié, attribuant le fragment à un autre datagramme). Comme le note le RFC 5722, il faut multiplier les tests lors du réassemblage.
Nous avons vu plus haut qu'un certain nombre de boîtiers intermédiaires jetteraient probablement sans autre forme de procès ces « nouveaux » paquets UDP avec une somme de contrôle nulle (ils étaient illégaux avant la sortie du RFC 6935). Il est donc essentiel, pour une application qui veut utiliser cette nouveauté, de tester le chemin et de vérifier que rien sur le trajet ne jette les paquets sans somme de contrôle. Il faut aussi penser à répéter ce test de temps en temps : le chemin peut changer (par exemple parce que BGP l'a décidé) et passer tout à coup par des boîtiers différents. (Et il faut faire le test dans les deux sens, ne serait-ce que parce que le routage n'est pas forcément symétrique.)
Dans tous les cas, il faut se rappeler que la somme de contrôle ne fournit de protection que contre la corruption accidentelle. Ce n'est pas un mécanisme d'authentification, et elle ne protège pas du tout contre un attaquant (qui peut modifier le paquet sans changer la somme de contrôle).
Les règles d'applicabilité sont formalisées dans les sections 4 (pour les implémentations) et 5 (pour l'usage de ces implémentations). Les programmes qui mettent en œuvre UDP sur IPv6 :
Cela, c'était pour l'implémentation d'UDP et d'IPv6 (qui, dans un Unix, est dans le noyau). Maintenant, pour les applications qui l'utilisent, la section 5 dit qu'elles :
Voilà, les règles d'applicabilités sont posées. Mais le RFC compte aussi une annexe intéressante, l'annexe A, qui est consacrée aux propositions alternatives. La solution choisie par le RFC 6935 a été d'autoriser les sommes de contrôle nulles. Mais on aurait pu faire différemment. Par exemple, le problème de performance et d'accès à la totalité du paquet aurait pu être traité par les calculs incrémentaux de somme de contôle du RFC 1624 (mais ils ne marchent pas quand il y a fragmentation IP). On aurait pu, comme cité, utiliser un protocole comme UDP Lite, ou UDPTT. Il avait aussi été proposé une mesure unilatérale, qu'un receveur ignore la somme de contrôle, quoiqu'ait mis l'émetteur (c'était plus simple mais il était alors impossible de détecter la corruption, pour tous les paquets). D'autres avaient suggéré une nouvelle option dans un en-tête Destination Options, ce qui revenait, à mon avis, à réintroduire une somme de contrôle en couche 3, ce qu'IPv6 avait délibérement abandonné. De toute façon, beaucoup de middleboxes auraient jeté les paquets avec cet en-tête (qui est rare, en pratique). Ces différentes propositions sont examinées en fonction de plusieurs critères : traversabilité des middleboxes, performances, déployabilité et résistance à la corruption de paquets.
Pour la traversée des middleboxes, l'UDP actuel ou bien un UDP avec un calcul incrémental des sommes de contrôle, est ce qui marche le mieux. Aucun changement à faire. L'UDP sans somme de contrôle du RFC 6935 aura sans doute quelques soucis (actuellement, de tels paquets sont illégaux), ainsi que les paquets avec l'en-tête Destination Options (pourtant légaux). Et les tunnels génériques seront sans doute bloqués par défaut par la plupart des pare-feux, ainsi qu'UDP Lite.
C'est à peu près la même chose pour la déployabilité : l'UDP actuel existe déjà et n'a pas à être déployé. Les sommes de contrôle facultatives du RFC 6935 nécessiteront au moins un changement dans les extrémités (ne pas calculer la somme, ne pas la vérifier) mais aussi dans certaines middleboxes qui se mêlent de vérifier la somme de contrôle, alors qu'on ne leur a rien demandé.
Pour les performances, l'UDP actuel est certainement le pire, puisqu'il faut calculer la somme de contrôle sur la totalité du paquet. C'est bien cela qui a motivé tout ce travail sur la réforme des sommes de contrôle UDP. UDP Lite, qui ne vérifie qu'une partie du paquet, et l'UDP réformé du RFC 6935 ont des bien meilleures performances (c'est aussi le cas des tunnels génériques).
Bref, il n'y a pas de solution parfaite, qui résolve tous les problèmes. Si on veut avant tout passer partout, l'UDP actuel est la meilleure solution. Si on veut une solution propre architecturalement, IP-in-IP est parfait. Si on se préoccupe des performances, l'UDP avec somme de contrôle facultative du RFC 6935 est une bonne approche et reçoit un avis favorable dans ce RFC.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : M. Eubanks (AmericaFree.TV LLC), P. Chimento (Johns Hopkins University Applied Physics Laboratory, M. Westerlund (Ericsson)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 1 mai 2013
Ne dites plus qu'en IPv6, la somme de contrôle est toujours obligatoire dans les en-têtes des paquets UDP. Depuis ce RFC 6935, ce n'est plus vrai dans tous les cas. Lors de l'encapsulation de paquets dans un tunnel UDP, on a désormais le droit de ne pas mettre de somme de contrôle dans les paquets UDP, essentiellement pour des raisons de performance.
Le principal demandeur de cette modification était le protocole LISP (RFC 9300), qui dépend énormement de tunnels UDP. Même si le calcul de la somme de contrôle Internet est rapide (RFC 1071), comme ce calcul peut se faire des millions de fois par seconde pour un routeur très actif, on peut chercher à l'économiser. D'autant plus qu'il n'est pas forcément utile puisque, dans le cas d'un tunnel, le protocole qui circule dans le tunnel est déjà protégé par une somme de contrôle. À noter que d'autres protocoles que LISP (comme ceux utilisés pour le multicast) peuvent bénéficier de cette nouvelle indulgence. Mais elle ne s'applique pas aveuglément à tout UDP (comme l'avaient proposé certains au début de la discussion), uniquement aux tunnels.
La norme actuelle sur IPv6, le RFC 2460, imposait (dans sa section 8.1) une somme de contrôle pour les paquets UDP (en IPv4, elle était facultative). En effet, IPv6 n'a pas de somme de contrôle dans la couche 3 (contrairement à son prédecesseur).
Ce RFC est un produit du groupe de travail IETF 6man, qui produit inlassablement d'innombrables RFC pour combler tous les petits problèmes qui trainent encore dans IPv6 et sont révélés par son utilisation dans le vrai monde.
Notez bien que cette dispense de somme de contrôle n'est pas générale : elle concerne les cas où il y a un tunnel et où il utilise UDP. Pourquoi UDP, alors qu'il existe des protocoles de tunnel qui s'en dispensent ? Parce que l'Internet est hélas de plus en plus ossifié, et que des middleboxes stupides et boguées sont partout sur le trajet des pauvres paquets. Les techniques de tunnel directement sur IP (comme l'excellent GRE du RFC 2784) sont souvent bloquées, alors qu'UDP passe partout. On aura donc un protocole X (LISP ou un autre) à l'intérieur du tunnel et de l'UDP à l'extérieur. Hier, cet UDP à l'extérieur était forcément protégé par une somme de contrôle. Pour un routeur qui sert de terminaison à des dizaines de milliers de tunnels (ce qui n'aurait rien d'étonnant avec LISP), calculer et vérifier ces sommes peut être très douloureux. D'autant plus que le protocole X a souvent sa propre somme de contrôle : ne serait-ce pas mieux pour tout le monde que le tunnel soit non sécurisé, ses éventuelles corruptions de paquets étant détectées par le protocole X uniquement ?
La section 4 discute plus en détail de certains aspects du problème mais il vaut mieux consulter le RFC 6936 pour tout savoir. Cet autre RFC précise notamment dans quels cas supprimer la somme de contrôle est une bonne idée et dans quels cas il vaut mieux la garder. La section 4 de notre RFC note particulièrement que les paquets de contrôle du tunnel, ceux qui servent à la signalisation, devraient rester protégés (s'ils sont corrompus, le tunnel peut cesser de fonctionner, c'est-à-dire que la corruption d'un paquet va affecter d'autres paquets). Notons que certains protocoles de tunnel comme GRE n'ont aucun mécanisme de contrôle. Lorsqu'il y en a un, il est souvent utilisé pour établir un contexte au début, avec choix des paramètres pour le tunnel : ce peut être le bon moment pour négocier le non-usage des sommes de contrôle sur les paquets de données.
Autre piège rigolo : certaines middleboxes vont tiquer en voyant les paquets UDP sans somme de contrôle (bien que, normalement, la somme de contrôle soit de bout en bout et ne regarde pas ces équipements intermédiaires). Bien que ce soit désormais légal, il va falloir attendre longtemps avant que tous ces engins soient mis à jour (section 4.3). En attendant ce jour, il est prudent que le tunnel détecte les problèmes en envoyant des paquets avec et sans somme de contrôle au début : si seuls les premiers passent, c'est qu'on a une middlebox agressive sur le trajet et qu'il faut renoncer à appliquer ce RFC 6935. Le test est d'ailleurs à répéter de temps en temps : la route peut changer et on peut donc se retrouver soudain à traverser une nouvelle middlebox.
La section 4.1 conseille également de tenter de détecter la corruption avant de décapsuler, par exemple en examinant l'adresse IP source, pour minimiser le risque d'envoyer au protocole encapsulé un paquet reçu corrompu. Mais cette détection ne marchera pas à tous les cas (sinon, on pourrait supprimer les sommes de contrôle dans tous les cas) et le protocole encapsulé doit donc être robuste et réagit proprement lorsque ces paquets corrompus sont injectés dans un flux existant (section 4.2).
La section 5 contient la nouvelle norme pour les sommes de contrôle UDP. Elle remplace le texte du RFC 2460 (qui disait que la somme de contrôle UDP était toujours obligatoire en IPv6) par un texte plus nuancé : par défaut, la somme de contrôle doit être calculée et mise dans le paquet. Mais on peut s'en dispenser dans le cas de tunnels (et uniquement celui-ci), sur le paquet extérieur. Le protocole à l'intérieur du paquet (qui n'est pas forcément de l'UDP et même pas forcément de l'IPv6) doit rester protégé par sa propre somme de contrôle. Cela ne doit s'appliquer que pour une liste explicite de ports (ceux utilisés par le tunnel) et pas pour tout le trafic UDP de la machine. Et le tout doit se faire en lisant le RFC 6936 qui précise les conditions d'application de cette nouvelle règle.
Les curieux et les chercheurs en informatique noteront que la section 6 liste des points qui mériteraient davantage d'étude. Ainsi, il n'y a pas eu d'étude systématique de la corruption de paquets sur l'Internet depuis 2000 et personne ne sait donc trop si c'est un phénomène fréquent ou pas. Cette section note aussi qu'il existe en théorie une meilleure solution pour les tunnels, UDP Lite (RFC 3828), mais que sa probabilité de passer les middleboxes est plus faible que celle d'UDP.
Plusieurs des mises en œuvre de LISP envoient déjà des paquets UDP sans somme de contrôle (ou plus exactement avec une somme à zéro).
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : Donald Eastlake (Huawei)
Chemin des normes
Première rédaction de cet article le 18 avril 2013
Il existe tout un ensemble de normes pour assurer la sécurité de documents XML, par exemple les protéger contre la lecture non autorisée, ou bien permettre leur authentification. Ces normes dépendent d'algorithmes cryptographiques identifiés par un URI. Ce RFC met à jour la liste précédente de ces URI (qui était dans le RFC 4051) et crée un registre des identificateurs d'algorithmes. Il a depuis été remplacé par le RFC 9231.
Ces normes de sécurité de XML étaient à l'origine un travail conjoint de l'IETF et du W3C. C'était par exemple le cas des signatures XML du RFC 3275, du XML canonique des RFC 3076 ou RFC 3741. Elles sont désormais maintenues par le W3C qui a produit des versions plus récentes (par exemple pour les signatures XML, le XML canonique ou le chiffrement XML).
Dans un monde dynamique comme celui de la
cryptographie, où les progrès de la
cryptanalyse nécessitent des changements
d'algorithmes, les normes ne sont pas liées à un algorithme
particulier. Elles permettent l'agilité cryptographique (le changement
d'algorithme) et il faut donc pouvoir indiquer quel algorithme est
utilisé pour signer ou chiffrer un document donné. Pour une norme
W3C, on ne s'étonnera pas que l'indication se
fait par le biais d'un URI. Ceux-ci commencent
désormais par le préfixe
http://www.w3.org/2007/05/xmldsig-more#
(les
anciens algorithmes pouvant avoir d'autres préfixes). Ces nouveaux
algorithmes (avec 2007/05
dans leur
identificateur) sont relativement rares dans ce RFC : on n'invente
quand même pas un bon algorithme de cryptographie tous les jours et la
plupart des exemples dans cet article utilisent donc le vieux
préfixe. Rappelez-vous qu'il s'agit d'URI, pas
forcément d'URL et que vous n'obtiendrez donc
pas forcément un résultat en pointant votre navigateur
Web vers http://www.w3.org/2001/04/xmlenc#sha256
.
Notons que notre RFC 6931 ne prend pas position sur la qualité cryptographique des algorithmes : il fournit un moyen de les désigner sans ambiguité, c'est tout. Si on veut étudier cette qualité cryptographique, il faut lire d'autres documents (comme le RFC 6194 pour SHA-1).
Un exemple d'un ancien algorithme est MD5
pour calculer les condensats
cryptographiques. Son URI est
http://www.w3.org/2001/04/xmldsig-more#md5
. Sa
sécurité est aujourd'hui sérieusement battue en brèche (cf. RFC 6151). Autre exemple d'un algorithme qui était déjà dans le
RFC 4051, SHA-384, identifié par http://www.w3.org/2001/04/xmldsig-more#sha384
.
Un exemple d'un nouvel algorithme pour la condensation
cryptographique ? Le NIST ayant récemment
annoncé que le vainqueur du concours « SHA-3 »
était Keccak, des URI utilisant le nouveau
préfixe ont été créés pour lui, par exemple
http://www.w3.org/2007/05/xmldsig-more#sha3-512
(regardez bien : sha-3
et plus
sha
, et la nouvelle date dans le préfixe).
Il existe aussi des identificateurs pour les
MAC combinés avec une condensation, par exemple
http://www.w3.org/2001/04/xmldsig-more#hmac-sha512
(RFC 6234).
Et pour les signatures avec un système à clé
publique ? L'identificateur indique l'algorithme de
cryptographie asymétrique et celui de condensation, par exemple
http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
(voir aussi le RFC 3447). SHA-256
n'est pas tout récent et, si vous cherchez un algorithme enregistré
par notre nouveau RFC, pourquoi pas Whirlpool
avec http://www.w3.org/2007/05/xmldsig-more#rsa-whirlpool
. Si on trouve
RSA ennuyeux, il existe aussi des
identificateurs pour un algorithme à courbes
elliptiques (RFC 6090 mais notez ses errata), ECDSA, par exemple
http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512
.
Enfin, il y a les algorithmes de chiffrement symétrique. Par exemple, Camellia (RFC 3713) sera identifié par
http://www.w3.org/2001/04/xmldsig-more#camellia256-cbc
. Le
plus récent SEED (RFC 4269) sera http://www.w3.org/2007/05/xmldsig-more#seed128-cbc
.
Voici pour la cryptographie. Mais les normes de sécurité XML
prévoient aussi une étape de canonicalisation avant chiffrement ou
signature, et là aussi, il y a plusieurs algorithmes, identifiés par
des URI comme http://www.w3.org/2000/09/xmldsig#minimal
ou http://www.w3.org/2006/12/xmlc14n11#WithComments
.
Quelle est la politique d'allocation dans le nouveau registre ? La
section 5 décrit celle du W3C (le préfixe
http://www.w3.org/2007/05/xmldsig-more#
est figé,
a priori, on n'y mettra pas de nouveaux algorithmes) et celle de
l'IETF : comme il est facile d'obtenir un URI (n'importe qui peut en
créer un), la seule question est celle de leur enregistrement. Il se
fera après un examen par un expert (voir le RFC 5226 pour les politiques d'allocation IETF) après
publication d'un texte décrivant le nouvel algorithme.
Quels changements depuis la version précédente de ce RFC, le RFC 4051 ? L'annexe A les liste. Les principaux, à mon avis, sont :
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : Alan DeKok (Network RADIUS), Avi Lior
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF radext
Première rédaction de cet article le 1 mai 2013
RADIUS, un protocole utilisé pour l'authentification (et la configuration) d'accès à l'Internet, est ancien et marche toujours. Lorsque vous accédez à l'Internet depuis chez vous, sans vous en rendre compte, vous avez probablement indirectement utilisé RADIUS. Il marche toujours très bien mais, rançon du succès, il a été tellement étendu qu'un certain nombre de champs du message RADIUS sont désormais pleins : toutes les options possibles seront allouées très bientôt. Ce nouveau RFC décrit un mécanisme d'extension de RADIUS, permettant de continuer l'enregistrement de nouvelles options, au prix de quelques bricolages.
Il y a peu de gens qui manipulent RADIUS (RFC 2865) explicitement. Ce protocole se trouve en effet caché dans le réseau du FAI, entre la machine qui contrôle l'accès (le NAS) et un serveur RADIUS qui contient les données sur les utilisateurs. RADIUS permet de ne pas avoir à copier les informations d'authentification, ou les paramètres d'un utilisateur donné, directement dans tous les NAS, mais de les centraliser dans un petit nombre de serveurs RADIUS.
La requête, et surtout la réponse RADIUS peuvent contenir un
certain nombre d'attributs (RFC 2865, section 5) comme « nom de l'utilisateur », « mot de
passe », « adresse IP à attribuer », etc. Le champ
« Attribute » est en TLV et
le type (User-Name
= 1,
User-Password
= 2,
Framed-IP-Address
= 8, etc) est encodé sur un
seul octet. La liste (un registre
IANA) est aujourd'hui bien remplie et devrait l'être
complètement en 2014 ou
2015. C'est le principal problème de RADIUS
aujourd'hui (section 1 de notre RFC). Mais il y en a d'autres comme le
fait que la longueur d'un attribut soit codé sur un octet seulement
(donc 253 octets maximum pour la valeur d'un attribut, puisqu'il faut
retirer le type et la longueur).
Notre RFC fait donc les changements suivants :
Voilà, c'est l'essentiel du RFC. Ceux qui étendent le protocole RADIUS vont sans doute migrer vers les nouveaux types, dès aujourd'hui, ou bien lorsque les anciens seront épuisés.
Des exemples d'encodage figurent en section 9. Par exemple, un
attribut utilisant un type étendu (ici, 241.1) et ayant une valeur de type texte
(la chaîne "bob") se représentera f1 06 01 62 6f
62
(f1
, le type, 241,
06
la longueur totale, 01
le
sous-type du type étendu, 1 (à la place du premier octet de la
valeur), 62 6f 62
la vraie valeur, la chaîne
de caractères). Plus compliqué, un attribut 241.2 contenant un TLV
dont le type est 1, la longueur 4 et la valeur 23
45
, sera représenté f1 07 02 01 04 23
45
.
Avec les étendus longs (Long Extended
Type), un attribut 245.1 contenant le même "bob" sera
f5 07 01 00 62 6f 62
(f5
est
le type, la longueur est de sept octets, 01
est
la suite du type, l'octet supplémentaire est à 0 (donc le bit M
aussi : pas d'autres attributs à attendre) et la valeur est la chaîne
"bob" (62 6f 62
en
ASCII). Si un type 245.4 encode plus de 251
octets (ici, 260 octets de valeur), on
aura le premier attribut qui commencera par f5 ff 04
80
(longueur totale à 256 octets, l'octet supplémentaire vaut 80, indiquant que le bit M
est à Un) et un deuxième attribut qui commencera par f5 13
04 00
(octet supplémenaire à 0 donc bit M à Zéro, ce second
attribut est le dernier). La longueur totale est ff +
13
soit 260 octets pour la valeur.
Si vous voulez tester vous-même ces nouveaux types et leur encodage, l'annexe A du RFC contient un programme en C qui permet exactement cela (copie locale du source). Il s'utilise ainsi :
% echo '241.1 "bob"' | ./radius-attr-generator 241.1 "bob" -> f1 06 01 62 6f 62 % echo '243.2 42' | ./radius-attr-generator 243.2 42 -> f3 04 02 42 # Plus drôle, un TLV dans un TLV : % echo '241.4 { 1 23 45 } { 3 { 1 ab cd } }' | ./radius-attr-generator 241.4 { 1 23 45 } { 3 { 1 ab cd } } -> f1 0d 04 01 04 23 45 03 06 01 04 ab cd
Parmi les autres nouveautés du RFC, il y a la formalisation de la
convention de nommage informel des attributs : mots séparés par des
tirets (par exemple Framed-MTU
), attributs
spécifiques à un vendeur préfixés par le nom du vendeur (par exemple
Starbucks-Latte-Size
pour un vendeur nommé
Starbucks).
Le changement apporté au protocole n'est pas trivial, mais soigneusement conçu pour maintenir la compatibilité. La section 5 du RFC note toutefois quelques problèmes potentiels. D'abord, certains vendeurs se sont approprié des numéros de types qui étaient marqués comme réservés (et qui sont désormais utilisés pour les types étendus). Comme le notait le RFC 6158, c'est un comportement anti-social. Maintenant que ces numéros réservés sont utilisés, ces attributs spécifiques au vendeur anti-social ne marcheront plus (bien fait).
Autre problème potentiel, il est fréquent que les messages RADIUS soient relayés par un serveur intermédiaire (RFC 2865, section 2.3), notamment en cas d'itinérance. Idéalement, le relais devrait ignorer les attributs qu'il ne comprennent pas. Si, par contre, il rejette les messages contenant ces attributs nouveaux, un client et un serveur conformes au nouveau format ne pourront pas communiquer à travers un tel relais. Notre RFC rappelle bien qu'un relais devrait être transparent et relayer même ce qu'il ne comprend pas.
Les sections 6.6 et 10.3 fournissent les règles d'enregistrement des nouveaux types. Il est recommandé d'y aller mollo : les nouveaux espaces sont plus grands mais pas infinis. Le registre IANA stocke désormais des attributs des nouveaux types.
Devoir ajuster a posteriori un protocole, qui avait été conçu d'une certaine manière, et qui esr assez rigide, est toujours une opération délicate, spécialement lorsqu'il faut maintenir la compatibilité avec l'existant. Des tas de propositions ont été faites depuis des années, pour étendre RADIUS. La section 7 du RFC documente pourquoi celle-ci a été choisie. D'abord, elle est relativement simple, avec peu de modifications du format. Son principal inconvénient est que le format des Long Extended Type est assez baroque.
Quant au mécanisme pour agrandir la taille possible des valeurs, il a d'abord été conçu pour ne pas changer les attributs dont la valeur restait petite. D'après une étude de 2010 (citée en section 7.1) portant sur tous les dictionnaires Radius connus, les entiers représentent près de la moitié des valeurs d'attributs RADIUS publics. En ajoutant les autres types de taille fixe (adresses IP, par exemple), on arrive à plus de la moitié. Il fallait donc éviter de faire payer ces types peu consommateurs en octets.
Plusieurs des mises en œuvre de Radius gèrent déjà ces extensions, par exemple FreeRADIUS. Il faut dire qu'il n'y a guère le choix, vue l'imminence de l'épuisement.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : J. Chu, N. Dukkipati, Y. Cheng, M. Mathis (Google)
Expérimental
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 30 avril 2013
Sur l'Internet, il y a des choses qu'on hésite à toucher. Depuis quelques épisodes fameux de « catastrophes congestives », où tout l'Internet s'est arrêté en raison de l'encombrement des tuyaux, la mémoire collective du réseau, incarnée notamment par l'IETF, voit avec une extrême méfiance toute modification des algorithmes de TCP, qui sont la principale ligne de défense de l'Internet face à la congestion. Néanmoins, le réseau évolue, les choses changent et il y a des gens qui insistent pour essayer des changements. Cela fait un certain temps que Google réclame une modification connue sous le doux nom de IW10 (pour Initial Window 10 segments) et ce RFC est le premier à la documenter officiellement, après trois ans de discussion dans le groupe de travail. Pour l'instant, c'est encore étiqueté comme « expérimental ».
La norme reste celle du RFC 3390. Elle dit que la fenêtre initiale d'une connexion TCP, à savoir le nombre maximal d'octets qu'on peut envoyer avant le premier accusé de réception, est donnée par une formule qui, en pratique est d'environ 4 kilo-octets, soit deux à trois segments (paquets TCP), parfois quatre. Voici, vu par tcpdump sur le client, un exemple entre deux machines séparées par 100 ms de RTT, un client HTTP qui demande un gros fichier et un serveur :
21:54:15.371487 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [.], seq 1:1449, ack 118, win 1810, options [nop,nop,TS val 1079804426 ecr 2768078], length 1448 21:54:15.371509 IP 192.168.2.1.57886 > 204.62.14.153.80: Flags [.], ack 1449, win 137, options [nop ,nop,TS val 2768109 ecr 1079804426], length 0 21:54:15.372574 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [.], seq 1449:2897, ack 118, win 181 0, options [nop,nop,TS val 1079804426 ecr 2768078], length 1448 21:54:15.372593 IP 192.168.2.1.57886 > 204.62.14.153.80: Flags [.], ack 2897, win 182, options [nop ,nop,TS val 2768109 ecr 1079804426], length 0 21:54:15.372615 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [.], seq 2897:4345, ack 118, win 181 0, options [nop,nop,TS val 1079804426 ecr 2768078], length 1448 21:54:15.372630 IP 192.168.2.1.57886 > 204.62.14.153.80: Flags [.], ack 4345, win 227, options [nop ,nop,TS val 2768109 ecr 1079804426], length 0 21:54:15.372897 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [P.], seq 4345:5793, ack 118, win 18 10, options [nop,nop,TS val 1079804426 ecr 2768078], length 1448 21:54:15.372910 IP 192.168.2.1.57886 > 204.62.14.153.80: Flags [.], ack 5793, win 273, options [nop ,nop,TS val 2768109 ecr 1079804426], length 0 21:54:15.488019 IP 204.62.14.153.80 > 192.168.2.1.57886: Flags [.], seq 5793:7241, ack 118, win 181 0, options [nop,nop,TS val 1079804455 ecr 2768109], length 1448
On voit que 204.62.14.153
a envoyé quatre
segments avant de devoir s'arrêter, les accusés de réception n'ayant
pas eu le temps de l'atteindre. La pause dure 116 ms, avant que le
serveur ne reprenne son envoi.
Ce nombre de segments est trop petit (bien plus petit que les tampons d'entrée/sortie d'un équipement réseau typique) car, sur les réseaux modernes, cela veut dire qu'un pair TCP qui veut envoyer un gros fichier va très vite remplir cette fenêtre et va devoir attendre ensuite, alors qu'il ne sait absolument pas si le réseau est congestionné ou pas. D'où la proposition IW10 qui est de permettre l'envoi de dix segments. (Pourquoi dix ? Comme l'explique l'annexe A, c'est le résultat de tests avec plusieurs valeurs possibles. Dix était la valeur qui était le meilleur compromis entre les gains et les inconvénients. Regardez le dessin 2 dans l'article An Argument for Increasing TCP's Initial Congestion Window si vous avez besoin d'être convaincu : il montre un progrès jusqu'à 16 et une baisse ensuite. Notez qu'une des techniques étudiées par le groupe de travail - et finalement abandonnée - avait été un système complexe de mesure et de rétroaction, avec des tailles initiales de fenêtre variables.)
La formule proposée par ce RFC (section 2) est fenêtre_initiale (en octets) = minimum (10*MSS, maximum (2*MSS, 14600)). Cela pourra faire jusqu'à dix segments, en fonction de la MSS. Naturellement, la machine aura le droit de choisir une fenêtre plus petite, ce choix n'est en effet pas dangereux ; mais pas de fenêtre plus grande, le but étant d'éviter la congestion de réseau.
Notez bien que cette formule ne s'applique qu'au début de la connexion. Lorsque TCP reprend son algorithme de démarrage en douceur (slow start), par exemple suite à des pertes de paquets, il doit s'en tenir au RFC 2581.
Il y a aussi quelques questions pratiques à se poser. Par exemple, une connexion TCP est bi-directionnelle : ce n'est pas tout d'utiliser une fenêtre plus grande à l'émission, il faut aussi annoncer à son pair une fenêtre de réception plus grande (cf. « An Argument for Increasing TCP's Initial Congestion Window » de Dukkipati, N., Refice, T., Cheng, Y., Chu, J., Sutin, N., Agarwal, A., Herbert, T. et J. Arvind, article de 2010 qui va être souvent cité ici et dont je recommande fortement la lecture. À l'époque de l'article, la plupart des systèmes annonçaient cette grande fenêtre, sauf Linux.)
Ce changement a des conséquences pour les applications qui utilisent TCP (section 3). Ainsi, HTTP 1.1 n'autorisait que deux connexions TCP simultanées vers le même serveur (RFC 2616, section 8.1.4, mais le RFC 7230 a libéralisé cette consigne). Les navigateurs en ouvrent en général plus que cela, pour éviter l'attente due à la faible taille de la fenêtre TCP. (Voir « A Swifter Start for TCP », par Partridge, C., Rockwell, D., Allman, M., Krishnan, R. et J. Sterbenz, rapport technique n° 8339 de BBN en 2002.) C'est égoïste de leur part (cela s'oppose aux mécanismes de contrôle de congestion de TCP) et cela ne devrait logiquement plus être nécessaire avec le déploiement d'IW10. Le RFC conseille donc de réduire le nombre de connexions HTTP simultanées.
La section 4 du RFC donne des éléments de contexte et d'histoire. Au début (cf. le célébrissime article de Van Jacobson, « Congestion Avoidance and Control », en 1998), TCP ne pouvait envoyer qu'un seul segment avant de recevoir le premier accusé de réception. Ce n'était pas un problème pour de longues communications, comme celles de telnet. Mais l'Internet aujourd'hui voit surtout du trafic Web (cf. « Atlas Internet Observatory 2009 Annual Report » de Labovitz, C., Iekel-Johnson, S., McPherson, D., Oberheide, J. Jahanian, F. et M. Karir, présenté à NANOG 47 en 2009.), avec des connexions de courte durée. Attendre longtemps avant de pouvoir envoyer plusieurs segments est très pénalisant (la plupart de ces connexions courtes ne quitteront jamais l'état TCP « démarrage en douceur »).
Surtout, les changements dans la capacité des réseaux ont été spectaculaires. Le rapport « The State of the Internet » d'Akamai en 2010, annonce que les accès à plus de 2 Mb/s forment désormais la majorité, ce qui met la capacité moyenne à 1,7 Mb/s, alors que, pendant ce temps, la fenêtre d'envoi initiale de TCP restait aux 4 ko du RFC 2414, sans bouger pendant dix ans. Avec un RTT de 200 ms, cette fenêtre ne permettait que 200 kb/s.
Des tas de changements avaient été proposés (pour ne citer que les RFC, voir RFC 4782 et RFC 6077) mais sans être réellement déployés. Ce sont donc les applications qui se sont adaptées, comme vu plus haut avec les navigateurs qui ouvrent plusieurs connexions, et les sites Web créant des sous-domaines sans autre raison que de débrayer la limitation du nombre de connexions par serveur (cf. « A Client-Side Argument For Changing TCP Slow Start » en 2010). Le déploiement d'IW10 devrait logiquement s'accompagner d'un changement de stratégie de ces navigateurs Web.
Au fait, en parlant d'HTTP, les connexions persistentes de HTTP 1.1 ne devraient-elles pas résoudre le problème ? Le problème est que les mesures faites avec Chrome (article de Dukkipati et al. cité plus haut) montrent que 35 % des requêtes sont faites sur des nouvelles connexions, ne pouvant pas tirer profit des connexions persistentes.
Bon, mais, au fait, quels sont les avantages exacts qu'il y a à agrandir la fenêtre initiale ? La section 5 les examine en détail. D'abord, on réduit la latence. Par exemple, si on a 21 segments à envoyer, IW3 (fenêtre initiale de trois segments) va nécessiter 4 aller-retour (envoi de données + attente de l'accusé de réception) contre 2 pour IW10. Ensuite, une telle augmentation est cohérente avec l'augmentation régulière de taille des objets. Par exemple, sur le Web, les études citées par le RFC (mesures faites sur le moteur de recherche Google) montrent que seules 10 % des ressources sur le Web tiennent encore dans les 4 ko du RFC 3390. En outre, si on utilise les connexions persistentes de HTTP 1.1, on aura encore plus de données à transmettre sur une connexion HTTP. Le Web grossit, il est logique que la fenêtre initiale de TCP suive le mouvement.
Et il n'y a pas d'inconvénients à augmenter la taille de la fenêtre initiale ? Les sections 6 et 7 décrivent le côté obscur. D'abord, en section 6, les risques pour l'utilisateur. Il y a notamment le risque de remplir complètement les tampons d'entrée-sortie dès le démarrage, pour des petits routeurs. Le RFC estime toutefois que ce risque est faible avec les tampons actuels, en s'appuyant sur l'étude « Characterizing Residential Broadband Networks » de Dischinger, M., Gummadi, K., Haeberlen, A. et S. Saroiu, en 2007, qui montre que le routeur typique de M. Michu a au moins 130 ms de tampon.
Ça, c'était pour l'utilisateur. Et pour le réseau (section 7) ? Risque t-on davantage de congestion ? Probablement pas puisque IW10 ne s'applique qu'au début de la connexion. Tout le reste du mécanisme de contrôle de la congestion de TCP reste en place, inchangé, notamment sa réaction aux pertes de paquets. En revanche, il peut y avoir un problème de justice. Tant qu'une partie des machines applique IW10 et qu'une autre partie en est resté au RFC 3390, les machines IW10 vont prendre une part plus grande des ressources réseau (c'est une question générale de l'Internet : la répartition juste entre différentes connexions concurrentes dépend de leur bonne volonté). C'est donc un point à surveiller. (Un autre problème de justice est traité dans l'annexe A, entre des machines toutes IW10 mais où certaines n'ont pas dix segments à envoyer. Les mesures semblent indiquer que ces dernières machines ne sont pas défavorisées.)
Autre inconvénient possible : comme IW10 remplit plus vite les tampons d'entrée/sortie des routeurs, si ceux-ci sont trop grands (phénomène du bufferbloat), IW10 va aggraver le problème. Les protocoles sensibles à la latence comme le DNS ou certains jeux vont alors souffrir. Les mécanismes proposés comme alternative au bufferbloat (ECN, AQM, etc) sont alors encore plus nécessaires.
En synthèse (section 8), le RFC estime que le plus gros risque est pour les utilisateurs ayant des liaisons lentes avec des tampons d'entrée/sortie réduits, dans leur box. Les 10 segments initiaux peuvent, dans certains cas, faire déborder ces tampons, le réseau ne pouvant pas les envoyer assez vite. Le RFC suggère, si on détecte qu'on est sur un tel lien, de ne pas envoyer forcément les dix segments autorisés, et d'annoncer une fenêtre de réception plus petite. Voir aussi le RFC 3150, sur le problème général de ces liens lents.
La théorie, c'est bien joli mais, quand elle dit qu'il ne faut pas trop s'inquiéter, il est prudent de vérifier par des mesures effectives, pas juste des raisonnements. C'est ce que fait la section 10. L'expérience a été faite par Google dans deux de ses centres de données, l'un voyant plutôt des clients ayant la capacité réseau moyenne, l'autre ayant en moyenne des utilisateurs de connexions lentes (20 % à moins de 100 kb/s). Avec IW10, la latence a baissé de 11,7 % dans le centre moyen et 8,7 % dans le centre lent. En regardant plus finement, les auteurs ont constaté que, comme l'indiquait la théorie, les bénéfices les plus importants d'IW10 ont été pour les gens situés loin (forte latence réseau) mais ayant des connexions rapides (ce qu'on nomme le BDP élévé avec BDP = Bandwidth-Delay Product). Mais, contrairement à la théorie, même les clients à capacité réseau limitée ont vu une amélioration. (Voir l'exposé « Increasing TCP initial window » de Dukkipati, D., Cheng, Y., Chu, J. et M. Mathis, présenté à l'IETF 78 en 2010.) Aucun problème grave n'a été observé.
D'autres expériences ont été faites, listées sur le site Web du projet IW10 ou en section 11 de ce RFC. Notez toutefois que la plupart sont des simulations, pas des mesures sur le vrai Internet. Mais ce n'est pas forcément très grave, l'étude de Google, par son ampleur, a semblé largement suffisante. Bien des RFC ont été adoptés sans une aussi grande étude préalable !
L'annexe A du RFC contient une liste d'inquiétudes théoriques sur IW10 et les résultats des tests spécifiquement liés à chacune de ces inquiétudes. Ainsi, le taux de pertes de paquets n'a pas augmenté lors des tests, sauf lors de cas extrêmes où, même avec les valeurs du RFC 3390, le phénomène de pertes se produisait. De même, des mesures ont été faites en Afrique, pas seulement en Europe et en Amérique du Nord, pour s'assurer qu'IW10 n'aurait pas d'effet pénible pour les liens moins favorisés.
En conclusion, le RFC recommande (section 12) d'activer IW10 mais que les fournisseurs de mises en œuvre de TCP et/ou les administrateurs réseau surveillent le trafic, à la recherche d'indicateurs comme le taux de pertes de paquet, pour détecter une éventuelle augmentation des phénomènes négatifs.
Ce changement de la fenêtre initiale est déjà apparue dans certains
systèmes. Par exemple, pour Linux, cela a été
fait en 2011 dans le commit
git
442b9635c569fef038d5367a7acd906db4677ae1
. Notez
que, sur Linux, ip route ... initcwnd N
vous
permet d'ajuster cette variable, pour expérimenter.
Un peu de lecture supplémentaire ? Le premier exposé sur IW10 date de
2010. Une argumentation hostile à IW10 ? Vous pouvez lire
l'Internet-Draft draft-gettys-iw10-considered-harmful
.
Date de publication du RFC : Mai 2013
Auteur(s) du RFC : J. Levine (Taughannock Networks), P. Hoffman (VPN Consortium)
Pour information
Première rédaction de cet article le 7 mai 2013
Beaucoup d'utilisateurs des noms de domaine pensent que deux noms qui,
pour eux, sont « le même », devraient être traitées d'un bloc par le
DNS et/ou par les systèmes d'enregistrement de
noms. Tout le problème est évidemment de définir « le même » : il n'y
a en général pas d'accord entre les utilisateurs sur ce point. Ainsi,
des anglophones peuvent penser que
meter.example
et
metre.example
sont « le même nom » et devraient
donc se comporter ainsi. D'autres pensent que
pizzeria-napoli.example
et
pizzerianapoli.example
sont « le même nom ». Et,
évidemment, depuis l'arrivée des IDN, le
potentiel pour des noms « identiques » a encore augmenté. Il a donc
été proposé que ces variantes d'un « même » nom
soient explicitement reconnues. Ce RFC ne
suggère pas de mécanisme en ce genre (je pense personnellement que le
problème est bien trop flou et subjectif pour cela). Il se contente de
regarder les pratiques actuellement déployées par les
registres en matière de « variantes ».
Des exemples de caractères qui sont une « variante » d'un autre ne
manquent pas dans les écritures du monde. Ainsi, la
Chine a connu sous Mao
une réforme orthographique, passant des
sinogrammes
« traditionnels » aux
« simplifiés ». La plupart des sinophones
considèrent que 雲
et 云
sont des variantes du même mot. Dans les langues utilisant
l'alphabet latin avec des
accents, certains considèrent que le mot avec
et sans accent sont des variantes l'un de l'autre. Le RFC note qu'en
français certains omettent les accents sur les majuscules (c'est
incorrect, mais cela se fait parfois) et que donc
INTERNÉ
et INTERNE
sont
considérés comme « équivalents ». Ce qui est sûr, c'est
qu'historiquement, les difficultés à manier les caractères
non-ASCII dans beaucoup d'environnements
informatiques avaient mené bien des utilisateurs à considérer les
accents comme purement décoratifs, et pouvant être omis.
Est-ce que ce vague sentiment que deux groupes de caractères sont
« la même chose » peut être formalisé dans une définition rigoureuse
des « variantes » ? Il y a eu quelques tentatives comme à
l'ICANN, ou à l'IETF dans le RFC 3743 (non standard). Mais un autre
document de la même ICANN concluait
qu'il n'existait pas de définition utilisable. Ensuite, sur le
comportement attendu de deux noms identiques ne fait pas non plus
l'objet d'un consensus. Par exemple, si on veut, non pas seulement une
réponse identique dans le DNS, mais un vécu de
l'utilisateur identique, par exemple sur le
Web, il n'y a aucune solution purement DNS (en
raison du comportement de HTTP avec le champ
Host:
). Si vous voulez lire davantage sur cette
question, je vous renvoie à mon article « Que veut dire synchroniser deux
domaines ? ».
Ce RFC n'essaie donc pas de régler ce problème (très ancien et sans doute insoluble). Il fait un tour d'horizon des pratiques des gTLD (qui sont contractuellement obligés par l'ICANN de rédiger leurs pratiques IDN et de les déposer à l'ICANN, et qui rendent accessibles le contenu de leurs zones, permettant aux chercheurs de l'étudier) et d'un certain nombre de ccTLD. Ces obligations de l'ICANN sont décrites dans « Guidelines for the Implementation of Internationalized Domain Names ». Le RFC note que ces règles ne sont guère respectées, les politiques déposées à l'ICANN étant souvent dépassées et plus à jour (URL cassés, personnes désormais parties, etc). (Mon opinion personnelle est que ces « IDN Guidelines » n'ont aucun sens et sont motivées par des frayeurs bureaucratiques plutôt que par des considérations pratiques.)
Pensez à réviser la terminologie en section 2. Un lot (bundle, on dit aussi IDL package) est un ensemble de noms qui sont tous des variantes les uns des autres (RFC 3743). Un nom est alloué (allocated) ou enregistré s'il est attribué à un titulaire. Il est actif (active) s'il apparait dans le DNS. Il est bloqué (blocked) s'il ne peut pas être alloué du tout et réservé (witheld) s'il ne peut être alloué que dans certaines conditions.
La section 4 décrit les politiques des gTLD (avec vérification dans
les fichiers de zone de la réalité de ces politiques). Certains sont
faciles : .aero
,
.coop
ou .pro
n'ont pas
d'IDN (même chose pour .xxx
). D'autres ont un grand intérêt pour les IDN. Ainsi,
.asia
a évidemment une
politique
IDN détaillée, avec gestion de lots, via les enregistrements
NS (les variantes ont le même jeu de
NS). .cat
a un cas plus
simple que .asia
puisqu'il ne reconnait qu'une
seule langue, le catalan. La liste des
caractères autorisés est
publiée et elle comprend des caractères comme le l·l
(considéré comme un caractère en catalan mais représenté par trois
caractères Unicode). Lorsqu'on enregistre un nom IDN, l'ASCII
« équivalent » est aussi enregistré et un DNAME
(RFC 6672) est mis dans le fichier de
zones (il semble que cela soit le seul gTLD à procéder ainsi). Par
exemple :
xn--caball-gva.cat. 43200 IN DNAME caballe.cat.
Le nom IDN caballé.cat
pointant vers
l'ASCII caballe.cat
(et merci à DNSDB pour permettre l'exploration facile du DNS
à la recherche d'exemples).
Contrairement à .asia
et a fortiori à
.cat
,
.com
doit gérer toutes les
écritures du monde. VeriSign a transmis à
l'ICANN des tables pour des écritures
hiéroglyphiques et pour
l'araméen... Les politiques suivies sont
décrites en détail dans plusieurs documents (voir la liste dans la
bibliographie du RFC). Pour l'écriture
chinoise, et pour elle seule, les variantes d'un nom
alloué sont
bloquées. (.net
et
.name
suivent la même
politique que .com
.)
.org
publie une liste des langues gérées (notez que
c'est absurde puisque IDN gère des écritures, pas des langues, mais
cette confusion est fréquente dans les cercles ICANN, où il est
toujours mal admis que des gens osent utiliser d'autres écritures que
celle des États-Unis). Les tables déposées à l'ICANN sont un
sous-ensemble de ces tables publiées par le registre (pas de mise à
jour ?) Les documentations officielles de .org
font allusion à une politique
de gestion des variantes mais apparemment sans dire en quoi consiste
cette politique.
.tel
a beaucoup d'IDN
et une politique
publique. Les noms avec l'écriture
japonaise utilisent un système de blocage (le premier
arrivé empêche l'allocation des variantes) alors que pour l'écriture
chinoise, les variantes sont publiées (avec des enregistrements NS identiques).
La section 5 passe aux ccTLD. Je ne vais pas tous les citer mais
ils ont souvent des politiques
intéressantes. .cl
publie sa
politique, qui ne tient pas compte d'éventuelles variantes.
.cn
a évidemment plus
de travail : leur politique est publiée sous forme d'un
RFC, le RFC 4713. Les
variantes sont publiées, avec des enregistrements NS. Par contre,
.ir
n'a pas d'IDN. Comme
un certain nombre de registres des pays utilisant
l'écriture arabe (qui va de droite à gauche),
ils considèrent que le mélange d'un nom en écriture arabe avec un
TLD en écriture latine (allant de gauche à droite) n'est pas
souhaitable. (Mais il y a des IDN dans le TLD équivalent en écriture arabe, ایران.
)
Bien que TLD d'un pays majoritairement anglophone,
.nz
a une politique IDN (qui ne
parle pas des variantes) pour le maori. On
notera que le domaine compte des DNAME par exemple
māori.dns.net.nz
qui pointe vers l'équivalent
ASCII :
xn--mori-qsa.dns.net.nz. 86400 IN DNAME maori.dns.net.nz.
Contrairement aux autres ccTLD, il semble que
.ru
ne publie pas sa
politique directement, uniquement via la table déposée à l'ICANN.
La politique utilisée par
.fr
n'est pas étudiée dans
ce RFC. Elle est disponible
en ligne.
La liste des caractères acceptés figure en section 2 (ce sont les
caractères utilisés pour les langues d'Europe de l'Ouest). S'il y a eu
un système de variantes pendant la période d'ouverture (section 4), il
a ensuite disparu.
Voilà, si vous voulez approfondir la question et voir la politique des autres TLD, consulter ce RFC. J'espère en tout cas avoir donné une bonne idée de la variété des écritures du monde et des solutions pour les gérer dans les noms de domaine.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : B. Leiba (Huawei)
Pour information
Première rédaction de cet article le 11 avril 2013
Dans la grande famille des URN,
l'IETF avait son propre espace, commençant par
ietf
. Mais il n'existait pas de registre des
sous-espaces de ietf
. C'est désormais fait.
Le RFC 2648 avait créé cet espace
ietf
. Il avait quelques sous-espaces comme
rfc
(donc, par exemple, ce
RFC est urn:ietf:rfc:6924
.) Le RFC 3553 avait
créé un nouveau sous-espace params
, et un registre pour ce sous-espace. Ainsi, on voit des
URN comme
urn:ietf:params:xml:ns:vcard-4.0
(RFC 6350) ou
urn:ietf:params:xml:ns:netconf:base:1.0
(RFC 6241). Mais peut-on créer encore d'autres sous-espaces
que params
? Et où les décrire ?
Un registre existe désormais à cette fin. Il sera rempli selon la procédure (assez lourde) « examen par l'IETF » du RFC 5226. On n'y trouve pour l'instant que les sous-espaces des RFC 2648 et RFC 3553.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : Y. Shafranovich (BioFortis)
Pour information
Première rédaction de cet article le 11 avril 2013
Premier enregistrement d'un nouveau type de données (type
MIME) fait depuis les nouvelles règles du RFC 6838, ce RFC enregistre un
type très ancien mais qui n'avait jamais été normalisé,
application/sql
, pour le code source
SQL.
Donc, les nouvelles procédures du RFC 6838
marchent, même pour un type très ancien. SQL a
plus de trente ans d'usage derrière lui. La section 3 contient le
formulaire d'enregistrement du nouveau type
application/sql
. Ce formulaire rempli met en
garde contre quelques pièges de SQL comme le fait que
l'encodage puisse être indiqué dans le fichier
(ce qui rend inutile le paramètre charset
du type
MIME), ou comme les problèmes de sécurité si un client était assez
naïf pour exécuter aveuglément du SQL récupéré sur le réseau (quoique
j'ai rarement vu du malware
en SQL...). Le formulaire d'enregistrement comprend aussi une section
sur les problèmes d'interopérabilité et elle note que, bien que SQL
soit une norme ISO (norme 9075.2011, pas
disponible en ligne), les
différences entre mises en œuvre du langage sont quand même très
grandes. Verra t-on un jour des types plus spécifiques comme
application/oracle+sql
ou application/postgres+sql
?
J'ai modifié la configuration Apache de ce blog pour y ajouter :
AddType application/sql .sql
Et, désormais, des fichiers comme joins.sql
(cité dans
cet article) sont servis avec le
nouveau type MIME. N'était-ce pas mieux en text/plain
(par défaut affiché dans le navigateur) ? J'hésite.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : S. Farrell (Trinity College Dublin), D. Kutscher (NEC), C. Dannewitz (University of Paderborn), B. Ohlman, A. Keranen (Ericsson), P. Hallam-Baker (Comodo Group)
Chemin des normes
Première rédaction de cet article le 22 avril 2013
Dernière mise à jour le 23 avril 2013
La question des identificateurs sur le
Web agite des électrons depuis le début. Il
n'existe pas d'identificateurs idéaux, ayant toutes
les bonnes propriétés. Dans la grande famille des
URI (RFC 3986), il faut donc choisir selon l'importance
qu'on donne à tel ou tel critère. Par exemple, si on attache du prix à
la stabilité de l'identificateur et qu'on veut qu'il ne désigne pas
seulement un endroit où se trouve un contenu, mais qu'on veut qu'il
désigne ce contenu et pas un autre ? Alors, on peut choisir les
nouveaux URI ni:
(Named
Information) qui désignent un contenu par un
condensat (hash). Un URI
ni:
ne change pas si le contenu change de
serveur, mais il est modifié si le contenu lui-même change. C'est donc
une forme d'adressage par le contenu.
À quoi cela sert ? À éviter un problème de l'indirection : si je
dis « regardez l'image en
http://www.example.org/holidays/beach.png
» et
que l'image de vacances à la plage est remplacée par une photo de
LOLcat, l'URI sera
toujours valable, alors que le contenu a changé. Inversement, si un
webmestre incompétent et qui n'a pas lu
« Cool URIs don't change »
réorganise le site et met le contenu en
http://www.example.org/bigcomplicatedcmswithsecurityholes.php?kind=image&tag=beach&foo=bar&id=612981
,
l'URI ne marchera plus alors que le contenu est inchangé. Un autre
exemple, plus positif, est le cas où un contenu est répliqué en
plusieurs endroits, ayant des URL
différents. Il faut pouvoir désigner le contenu, indépendamment du
service qui l'héberge. C'est pour
répondre à ces deux problèmes qu'a été créé par ce
RFC le plan d'URI ni:
(désormais dans le registre IANA des plans d'URI). Le
contenu en question pourra donc être désigné par
ni:///sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc
. Une
telle technique a déjà été employée mais de manière non standard (par
exemple, on voit parfois des URI du genre
http://www.example.org/hash?function=sha256&value=rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc
où un programme situé sur www.example.org
récupère la ressource selon le contenu). Désormais, le but est de
permettre du vrai adressage par le contenu sur le Web. Cela se nomme
information-centric sur les
PowerPoint des gourous. Sur ce sujet, le RFC recommande la lecture de « Design
Considerations for a Network of Information » de Ahlgren, D'Ambrosio, Dannewitz, Marchisio, Marsh, Ohlman,
Pentikousis, Rembarz, Strandberg, et Vercellone, ainsi que des articles de Van Jacobson. On peut
aussi lire des articles sur les autres mécanismes d'adressage par le
contenu comme les magnet links de plusieurs systèmes
pair-à-pair, comme Freenet.
Une fois le contenu récupéré (en HTTP ou par d'autres moyens), le lecteur peut alors recalculer le condensat et vérifier s'il a bien reçu le bon fichier (des protocoles comme BitTorrent utilisent un mécanisme analogue pour s'assurer que le fichier transmis par les pairs est bien celui qu'on voulait).
D'autres informations peuvent se retrouver dans l'URI
ni:
(voir des exemples plus loin) mais la
comparaison de deux URI ni:
se fait uniquement
sur le couple {fonction de hachage utilisée,
valeur du condensat}.
Le condensat est calculé par une fonction de hachage
cryptographique et, par défaut, c'est
SHA-256 (vous avez noté le
sha256
dans l'URI ni:
donné
en exemple plus haut ?) Les valeurs possibles pour l'algorithme de
hachage figurent dans un nouveau
registre. Les nouvelles valeurs sont enregistrées selon une
procédure légère d'examen par un expert (RFC 5226 et section 9.4 de notre RFC).
Les condensats de SHA-256 sont de grande taille, parfois trop pour
certaines utilisations. On a donc le droit de les tronquer à leurs N
premiers bits et le nom d'algorithme indiqué doit préciser cette
troncation. Ainsi, si on garde les 32 premiers bits, on doit indiquer
sha256-32
et pas juste
sha256
. Attention, c'est évidemment au détriment
de la sécurité (si la sortie de SHA-256 est si longue, c'est pour une
bonne raison, cf. RFC 3766) et ces condensats raccourcis, quoique simples à
manipuler, ne protègent plus tellement. (Notez que le
VCS git, qui identifie
les commits par un condensat
cryptographique, permet également de les raccourcir, pour faciliter
son utilisation, par exemple depuis le
shell.)
Le format exact des URI ni:
figure en section
3. On note un composant dont je n'ai pas encore parlé, l'autorité. On
peut écrire
ni:///sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc
mais aussi
ni://www.example.net/sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc
. L'autorité
(ici, www.example.net
) désigne un endroit où on
pourra peut-être récupérer la ressource. Le gros problème des
identificateurs fondés sur le contenu du fichier, en effet, est qu'ils
sont inutiles pour accéder effectivement au fichier : pas moyen de
télécharger un fichier dont on ne connait que le condensat ! Il existe
plusieurs solutions et l'une d'elles est de passer par
l'autorité. L'idée est que l'URI ni:
est
automatiquement transformé en un URL HTTP sous
.well-known
(cf. RFC 8615 et section 4 de notre RFC). Ainsi,
ni://www.example.net/sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc
devient
http://www.example.net/.well-known/ni/sha256/rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc
qu'on peut ensuite récupérer par des moyens classiques. On combine
alors les avantages de l'adressage par le contenu (le condensat est là
pour vérifier le contenu) et du fait que les URL marchent bien pour
récupérer un contenu. On notera que le système d'identificateurs
ARK a un mécanisme analogue (un identificateur
stable et non résolvable plus un préfixe qui
permet de faire un URL résolvable et actionnable). On a ainsi le beurre
et l'argent du beurre. ni
fait désormais partie
des termes enregistrés dans le registre "well-known".
Petite question : pourquoi http:
et pas
https:
, qui serait plus sûr ? Parce que tous les
serveurs ne gèrent pas HTTPS et aussi parce que
ce n'est pas nécessaire pour s'assurer de l'intégrité du fichier
récupéré, le condensat cryptographique suffit. Bien sûr, une mise en
œuvre de ce RFC est autorisée à essayer avec HTTPS, par exemple
pour la confidentialité.
Comme indiqué plus haut, la comparaison entre deux URI
ni:
se fait uniquement sur le couple {algorithme,
condensat} donc ni://datastore.example/sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc
et
ni://www.example.net/sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc
sont identiques.
Au fait, SHA-256 peut être affiché en binaire ou bien sous une
forme hexadécimale. Laquelle est utilisée ? Le format binaire
suivi d'un encodage en
Base64 (RFC 4648), sous
sa forme URL encoding, celle qui utilise
_ et - au lieu de
/ et + (ce n'est pas la forme par
défaut : songez que l'outil base64
sur Unix ne permet pas de produire cette
variante).
Si on n'a pas besoin d'être lisible par des humains et
transmissible dans des textes, il existe aussi une forme binaire, plus
compacte, des URI ni:
, spécifiée en section
6.
Signe de leur souplesse, les URI ni:
ont
également une forme « prononçable ». S'il faut dicter un URI au
téléphone, l'encodage par défaut est très ambigu (par exemple,
minuscules et majuscules n'ont pas la même
valeur). D'où la syntaxe nih:
(NI for
Humans et non pas Not Invented Here, cf. RFC 5513) de la section
7. Les URI sous leur forme nih:
sont en
Base16 (RFC 4648), peuvent inclure
des tirets supplémentaires, pour la lisibilité,
et incluent une somme de contrôle (le dernier
chiffre, calculé selon l'algorithme de Luhn de
la norme ISO 7812) pour détecter les erreurs de
compréhension. Un exemple est nih:sha-256-120;5326-9057-e12f-e2b7-4ba0-7c89-2560-a2;f
.
Enfin, des paramètres peuvent apparaître dans l'URI, par exemple
pour indiquer le type de la ressource
(ni:///sha256;rJAeWFhQWIoTExwyEQ8w_L5uB0UkfmnCGfNIPy7CdDc?ct=image/png
). Une
liste de paramètres possibles est enregistrée.
À noter que l'abréviation ni
veut
officiellement dire Named Information mais que tout
geek va évidemment penser aux chevaliers qui disent Ni...
Avant d'utiliser les URI ni:
, il est prudent
de lire la section 10, consacrée aux questions de sécurité. Ainsi, il
ne faut pas oublier que le condensat cryptographique n'est
pas une signature. Il sert
à vérifier l'intégrité mais, comme n'importe qui peut générer un
condensat pour n'importe quel contenu, il ne prouve rien quant à
l'authenticité.
La fonction SHA-256 et ses camarades ne sont
pas inversibles. D'un condensat, on ne peut pas remonter au
contenu. Toutefois, celui-ci n'est pas vraiment secret. Un attaquant
peut toujours deviner plus ou moins le contenu (c'est particulièrement
facile si le contenu est très structuré, avec peu de variations
possibles) et tester les différentes possibilités. Il peut aussi
utiliser un moteur de recherche, si des pages
existent déjà avec la correspondance entre une ressource et son
condensat (pour empêcher cela, il faudrait que les condensats
ni:
soient salés, ce qui
n'est pas le cas).
Et, naturellement, si vous utilisez des condensats tronqués, comme le permet de RFC, vous perdez beaucoup en sécurité.
La notion d'autorité dans les URI
ni:
peut être trompeuse. Le nom de domaine qui peut apparaître dans un URI
ni:
n'est pas forcément la source du contenu,
puisque n'importe qui peut copier la ressource, et la servir depuis un
programme. Il ne faut donc pas attribuer de sémantique à la soi-disant « autorité ».
Si vous voulez regarder un tel système « en vrai », les articles de
ce blog sont tous accessibles via un URI
ni:
. L'identificateur est calculé toutes les
nuits et stocké dans une base de données. Un simple petit programme
WSGI permet ensuite de récupérer un fichier
en fonction de son identificateur. À noter que ce n'est pas la forme
HTML qui est utilisée mais le source en
XML (la forme en HTML change trop souvent, par
exemple si les outils qui la produisent automatiquement à partir du
source sont modifiés). Ainsi, l'URI
ni:///sha256;6OuucQ1RgugCDVinT2RGmzYYpra0fenH-zw7tilsx9k
correspond au source XML de cet
article. En indiquant explicitement l'autorité (le serveur qui
permet de faire la récupération), c'est l'URI
ni://www.bortzmeyer.org/sha256;6OuucQ1RgugCDVinT2RGmzYYpra0fenH-zw7tilsx9k
. Et
la version sous forme d'URL est
. Si
vous préferez un autre article,
https://www.bortzmeyer.org/.well-known/ni/sha256/6OuucQ1RgugCDVinT2RGmzYYpra0fenH-zw7tilsx9k
ni:///sha256;1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp92lueI
correspond au source de cet article.
Notez qu'il n'est pas possible de mettre l'URI
ni:
de l'article que vous êtes en train de lire
dans cet article (inclure le condensat change l'article et il faut
donc changer le condensat, ce qui change l'article...)
Vous voulez vérifier ? Allons-y.
% wget -O /tmp/x.xml https://www.bortzmeyer.org/.well-known/ni/sha256/1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp92lueI ... % openssl dgst -sha256 -binary /tmp/x.xml | base64 1etMCVZtd7/cq38MrtnQcoZW/e7J2cslulrFp92lueI=
Et on retrouve bien l'identificateur 1etMCVZtd...
(aux transformations URL encoding près).
Si vous voulez faire depuis le shell Unix les calculs nécessaires, voici quelques exemples avec OpenSSL. Pour calculer le NI de Hello World! :
% echo -n 'Hello World!' | openssl dgst -sha256 -binary | base64 f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=
Il faut ensuite rechercher/remplacer car base64
(ou bien la commande
openssl enc -base64
) ne sait pas faire de
l'URL encoding de Base64. Avec
sed :
% echo -n 'Hello World!' | openssl dgst -sha256 -binary | base64 | sed -e 's#/#_#g' -e 's#+#-#g' -e 's#=$##' f4OxZX_x_FO5LcGBSKHWXfwtSx-j1ncoSt3SABJtkGk
(Pour la même manipulation, on peut aussi utiliser tr :
tr -cd a-zA-Z0-9+/ | tr +/ -_
. Comme expliqué par
Kim-Minh Kaplan : « Note le tr -cd
pour nettoyer le résultat de l’encodage en Base 64.
Si avec SHA-256 il n’est pas nécessaire, avec SHA-512, l’encodeur
d’OpenSSL introduira un retour à la ligne qu’il faudra aussi supprimer. »)
Si on reprend l'exemple plus haut, on peut combiner les deux opérations : on récupère le fichier grâce au condensat et on vérifie que le contenu est bien le contenu attendu. Utilisons ce simple script :
#!/bin/sh BASE_URL="https://www.bortzmeyer.org/.well-known/ni/sha256/" if [ -z "$1" ]; then echo "Usage: $0 ni" >&2 exit 1 fi ni=$1 hash=$(wget -q -O - ${BASE_URL}/${ni} | openssl dgst -sha256 -binary | openssl enc -base64 | \ sed -e 's#/#_#g' -e 's#+#-#g' -e 's#=$##') if [ "$hash" != "$ni" ]; then echo "Error: hash is $hash instead of $ni" >&2 exit 1 else exit 0 fi
Et voyons :
% get-and-check-ni 1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp92lueI %
Si on met une valeur fausse :
% get-and-check-ni 1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp922ueI Error: hash is 47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU instead of 1etMCVZtd7_cq38MrtnQcoZW_e7J2cslulrFp922ueI
Si vous voulez lire de source de mon programme, il est dans les fichiers de mon blog, scripts/blog2db/blog2db.py
pour le
stockage dans la base de données et wsgis/ni.py
pour la récupération.
Il existe une autre implémentation, par certains des auteurs du RFC, en http://sourceforge.net/projects/netinf/
.
Si vous voulez d'autres lectures, le RFC 1737. sur les URN, parlait déjà (en
1994) d'utiliser un condensat cryptographque
(avec MD5) pour désigner un contenu. En
2003, une proposition plus élaborée,
draft-thiemann-hash-urn
décrivait un système d'URN avec adressage par le contenu (des choses
comme
urn:hash::sha1:LBPI666ED2QSWVD3VSO5BG5R54TE22QL
).
Mais, avec draft-thiemann-hash-urn
, il y a un gros manque : pas moyen d'indiquer un (ou
plusieurs, comme dans le cas des magnets) serveur pouvant servir le
document en question. Avec draft-thiemann-hash-urn
, on n'a que des
URN (ils ne sont pas « actionnables »). Enfin, si vous voulez une
critique des ni:
par rapport aux
magnets, voyez la discussion sur LinuxFr.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : F. Gont (UTN-FRH / SI6 Networks), C. Pignataro (Cisco Systems)
Chemin des normes
Première rédaction de cet article le 18 avril 2013
Allez, encore un peu de nettoyage dans les registres IANA. Le protocole ICMP pour IPv4 a plein de types de messages différents. Beaucoup sont dépassés mais n'avaient pas été officiellement marqués comme tel. Ce RFC range le registre et reclasse quinze types de messages. En revoyant ces types, nous plongeons dans les essais ratés de TCP/IP...
La notion de type de message ICMP est normalisée dans le RFC 792. Les plus connus des types de message ICMPv4 sont le 8 (echo request) et le 0 (echo reply) à cause de leur utilisation dans ping. Mais il existe bien d'autres types, enregistrés à l'IANA et servant à de nombreuses fonctions discrètes, mais indispensables (comme l'indication qu'un paquet n'a pas pu être délivré, type 3). Le registre des types a aussi vu l'arrivée d'un certain nombre de types expérimentaux, qui n'ont guère eu de succès, et notre RFC s'occupe de les trier. (Rappelez-vous qu'IPv6 a un autre registre ICMP, complètement différent.)
Voici donc la liste des types abandonnés :
draft-simpson-ipv6-mobility
qui n'est jamais
devenu un RFC.)Tous ces types sont désormais marqués Deprecated dans le registre IANA.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : R. Gagliano (Cisco Systems), S. Kent (BBN Technologies), S. Turner (IECA)
Réalisé dans le cadre du groupe de travail IETF sidr
Première rédaction de cet article le 11 avril 2013
La grosse infrastructure de sécurisation du routage RPKI+ROA est en train de se mettre en place, les RFC sont sortis, mais l'IETF ne s'arrête pas là. Ce document décrit la façon de changer les algorithmes de cryptographie utilisés par la RPKI lorsque les progrès de la cryptanalyse l'exigeront.
Disons-le tout de suite, cela va être un énorme travail. La RPKI n'a pas de centre, les décisions dépendent d'un grand nombre d'acteurs non coordonnés, des AC qui émettent les certificats aux RP (Relying Parties, les validateurs qui vérifient les ROA - Route Origin Authorizations). Le RFC ne sème pas d'illusion et affirme qu'un éventuel changement d'algorithmes dans la RPKI prendra plusieurs années.
Il y avait en théorie plusieurs stratégies possibles, du bas vers le haut (les acteurs situés le plus bas dans la hiérarchie migrent les premiers) ou celle finalement choisie, après de longues discussions dans le groupe de travail SIDR, du haut vers le bas (les acteurs les plus haut placés commencent).
À noter qu'il s'agit bien de changer d'algorithmes. Remplacer les clés (key rollover) est prévu et normal dans le fonctionnement de la RPKI (RFC 6489). Mais les algorithmes ne sont pas éternels. Ceux normalisés actuellement dans le RFC 6485 (RSA et SHA-256) ne résisteront pas toujours à la cryptanalyse et devront laisser un jour la place à d'autres (fondés sur les courbes elliptiques ?).
Comme le processus sera long, il devra commencer par une mise à jour de ce RFC 6485, documentant les nouveaux algorithmes et par la publication d'un plan de migration, avec chronologie. Puis la procédure décrite en section 4 sera appliquée, dans l'ordre chronologique : les AC commencent à émettre des certificats avec le nouvel algorithme, puis les RP (les validateurs) commencent à pouvoir vérifier le nouvel algorithme, puis les AC arrêtent d'utiliser l'ancien algorithme (période nommée Twilight dans le RFC, mais rien à voir avec Stephenie Meyer), puis on peut déclarer l'ancien algorithme mort. Le passage à chaque étape nécessite que tous les acteurs impliqués aient migré, ce qui explique le délai de plusieurs années envisagé (aucune procédure n'est envisagée pour le cas, catastrophique, où de brusques percées de la cryptanalyse obligeraient à un remplacement d'urgence). Le RFC est plein de phrases comme « If a substantial number of RPs are unable to process product sets signed with Suite B [le nouvel algorithme], the algorithm transition timeline document MUST be reissued, pushing back the date for this and later milestones [...] », qui donnent une idée des problèmes qui vont surgir à cause de cette règle « pas de passage sans unanimité ».
Il y aura donc une (longue) période de coexistence entre les deux algorithmes. La section 6 décrit ce que devra être le comportement des validateurs pendant cette période, notamment si les deux algorithmes donnent des résultats opposés (l'un valide et l'autre pas ; l'expérience avec des techniques cryptographiques comme DNSSEC montre que ce genre de choses arrive).
Et n'oubliez pas que ce beau plan n'a jamais été testé. Rendez-vous dans sept ou quinze ans pour le premier changement d'algorithme de la RPKI...
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : J. Rosenberg (jdrosen.net)
Pour information
Réalisé dans le cadre du groupe de travail IETF simple
Première rédaction de cet article le 22 avril 2013
Le monde de la messagerie instantanée est marqué par l'absence d'une norme unique et largement reconnue (au contraire de celui du courrier électronique, où SMTP et ses copains ont remplacé tous les concurrents). La plupart des protocoles courants de messagerie instantanée sont fermés et spécifiques à une seule entreprise. Et, même chez les standards ouverts, il y a deux normes, la plus connue, autour de XMPP, et une seconde, issue de la même organisation (l'IETF), autour de SIP. Car SIP ne sert pas qu'à la téléphonie sur IP. C'est un mécanisme de signalisation très général et il peut être utilisé pour la messagerie instantanée. En fait, de nombreux RFC, depuis des années, normalisent l'utilisation de SIP dans ce cas. Tellement nombreux, ces RFC, qu'il faut faire un méta-RFC pour servir de guide. C'est le rôle de ce RFC 6914 : la liste commentée des RFC qui, tous ensemble, décrivent SIMPLE, la messagerie instantanée utilisant SIP.
SIP lui-même est décrit dans le RFC 3261. Ce nouveau RFC 6914 fait la liste des RFC qui décrivent l'utilisation de SIP pour deux services :
Accrochez-vous, la liste est longue et SIMPLE ne mérite guère son nom. À noter que le groupe de travail IETF SIMPLE a été fermé le 26 février 2013, son travail étant considéré comme achevé.
Commençons par la présence (section 2). Elle se décompose en un service de base, permettant de publier des notifications (« je suis disponible ») et de s'y abonner (« qui est réveillé ? »), et une galaxie de services auxiliaires enrichissant tel ou tel aspect du service de base. Le seul service de base compte cinq RFC :
SUBSCRIBE
et NOTIFY
, au cœur
du service de présence. Il est bâti sur le RFC 3856.Ensuite, comment exprime-t-on les informations publiées et lues ? Le format de base (fondé sur XML) est dans le RFC 3863. Un modèle de données plus général est dans le RFC 4479, avec, dans le RFC 4480, plein d'extensions au format du RFC 3863. Autres extensions, celles du RFC 4481, qui ajoute la gestion du temps (évenements dans le passé et le futur, alors que le RFC 3863 se limitait au présent), et celles du RFC 4482 qui permettent de diffuser des informations sur un correspondant, par exemple une image le représentant.
Enfin, le RFC 5196 permettait d'indiquer, en sus de la présence et des données ci-dessus, les capacités du logiciel SIP qu'on utilise, par exemple pour prévenir ses correspondants qu'on accepte la vidéo.
Tout service de présence soulève évidemment des questions délicates de protection de la vie privée. Je ne souhaite pas forcément que la Terre entière soit au courant de mes déplacements et activités. La section 2.3 décrit les RFC qui s'attaquent au problème de la vie privée dans SIMPLE. Le RFC 4745 définit un format (basé sur XML) pour exprimer des préférences sur la vie privée (du genre « ne jamais diffuser cette information »). Le RFC 5025 utilise ensuite ce format pour décrire les souhaits spécifiques au service de présence. Les RFC 3857 et RFC 3858 décrivent un système d'autorisation préalable où l'utilisateur peut être prévenu si quelqu'un demande s'il est présent.
Un service SIMPLE nécessite un certain nombre de données, par exemple les carnets d'adresse. Comment les enregistre t-on ? Cela se fait avec XCAP (RFC 4825), un protocole qui permet d'envoyer des données stockées en XML. Il en existe des optimisations comme le RFC 5874 qui permet de n'envoyer que les différences avec les données précédentes, pour économiser des ressources réseau. Il se sert pour cela du format XML Diff du RFC 5261. On peut être prévenu de l'apparition de différences avec les mécanismes du RFC 5875. Les formats des données sont ensuite décrites par des documents comme le RFC 4826 (format des carnets d'adresses).
Un des gros intérêts des techniques IETF de messagerie instantanée, comme SIMPLE ou XMPP est qu'elles reposent sur une fédération. Il n'y a pas un service centralisé à qui faire confiance (comme c'est le cas avec les services des silos fermés comme MSN). Chacun peut installer son serveur et les différents serveurs peuvent communiquer entre eux, le DNS leur servant à se trouver. Le RFC 5344 approfondit les mécanismes utilisés pour la fédération.
La présence peut être un service très coûteux. Imaginez que vous receviez des notifications de présence pour une centaine de personnes, et que leurs états changent toutes les minutes (par exemple suite à des connexions/déconnexions). Au-dessus d'une liaison sans-fil, cela peut faire mal au réseau. Le RFC 4460 fournit donc des mécanismes de filtrage, pour ne pas tout recevoir. Les règles sont écrites dans le format du RFC 4461. Le RFC 5262 permet de ne pas recevoir la totalité de la notification mais uniquement la partie qui a changé (là encore, avec le format XML Diff du RFC 5261).
Maintenant qu'on en a terminé avec la présence (un service bien
plus compliqué qu'il n'avait l'air au premier abord), revenons à la
messagerie instantanée proprement dite (section 3). Dans SIMPLE, il y
a deux modes de fonctionnement pour celle-ci. En mode non connecté
(page mode, analogue au
SMS), une requête SIP
MESSAGE
est envoyée au
destinataire, contenant le message. En mode connecté (session
mode), une INVITE
SIP est envoyée au
destinataire et, une fois la session établie, on envoie les textes de
la conversation, comme on enverrait de l'audio avec de la téléphonie
SIP.
Le RFC 3428 décrit le mode non connecté et la méthode
MESSAGE
, le « texto » de SIP. Le RFC 5365 l'étend au cas où
il y a plusieurs destinataires.
Le mode connecté utilise des méthodes SIP classiques et sa description est uniquement celle des types de données envoyées, notamment RFC 4975 pour le type « message texte » et RFC 3862 pour les métadonnées.
Une extension très utile aux services de messagerie instantanée est la pièce collective (chat room, ou MUC - pour Multi-User Channel en XMPP). SIMPLE réutilise pour cela les mécanismes de conférence de SIP, normalisés dans les RFC 4353 et RFC 5239. Ensemble, ils indiquent comment on rejoint une conférence, comment on la quitte, etc.
Enfin (rassurez-vous, on arrive au bout), deux fonctions sympa : l'indication de composition dans le RFC 3994 (permettant d'indiquer que le correspondant est en train de taper un texte, il faut patienter), et l'accusé de réception dans le RFC 5438.
Voilà, vous savez désormais tout ce qu'il faut lire si vous voulez faire de la messagerie instantanée avec SIP...
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : A. Sullivan (Dyn, Inc), D. Thaler (Microsoft), J. Klensin, O. Kolkman (NLnet Labs)
Pour information
Première rédaction de cet article le 16 avril 2013
Ce RFC de l'IAB expose les principes que, selon l'IAB, devraient suivre les registres de noms de domaine lorsqu'ils décident quels caractères Unicode sont autorisés ou pas, pour l'enregistrement de noms de domaine internationalisés.
Notons tout de suite que les principes exposés dans ce RFC ne sont guère argumentés (les sections 6, 7 et 8, normalement consacrées à cette tâche, sont très pauvres). Dès l'introduction, le RFC dit qu'il ne faut pas autoriser tous les caractères mais ne dit pas pourquoi, ou quels dangers mystérieux menacent ceux qui oseraient passer outre. Mais, une fois qu'on a décidé de ne pas permettre tous les caractères Unicode (enfin, tous ceux qui sont légaux selon le RFC 5892), il reste le problème du choix. Il n'existe pas d'algorithme pour cela (le monde Unicode est bien trop complexe, reflétant la complexité des écritures du monde et nos connaissances insuffisantes) et ce RFC, plutôt que de donner un tel algorithme, pose des principes qui devraient guider ceux et celles qui feront le choix.
La section 1 donne quelques objectifs (sans que la suite du RFC
n'indique le rapport entre les principes et ces objectifs) : limiter
les possibilités de confusion entre deux noms (par exemple
google.com
et goog1e.com
,
regardez bien le second), éviter qu'une adresse IP soit prise pour un nom de domaine comportant des
éléments numériques (un faux problème typique, cf. RFC 1123,
section 2.1), et favoriser l'accessibilité
(cf. WCAG). Le RFC introduit une notion importante, celle de
zone publique. Une zone du
DNS est un ensemble de sous-domaines contigus
et gérés par la même organisation. Certaines sont privées, au sens où
une seule organisation les utilisent (par exemple la zone
univ-paris-diderot.fr
n'est utilisée que par
l'université Denis Diderot). D'autres sont
publiques au sens où le registre qui la gère
accepte des enregistrements de diverses organisations. La plupart des
TLD sont des zones publiques (par exemple
.fr
,
.org
ou
.pm
), ainsi que la
racine. En effet, le RFC estime qu'il faut des
règles particulières pour ces zones publiques (cf. section 4).
L'IAB s'est déjà exprimée sur cette question du choix des
caractères autorisés pour les IDN. Notons que
personne ne s'est posé la question pour les noms de domaines en
ASCII alors que, comme le montre l'exemple
goog1e.com
plus haut, ils posent exactement les
mêmes « problèmes ». Mais l'idée même de permettre à chacun, et pas
seulement aux anglophones, d'écrire les noms de domaine avec leur
écriture n'est toujours pas complètement acceptée. À part quelques
ultra-réactionnaires, plus personne n'ose
dire ouvertement qu'il est contre mais l'anti-IDNisme s'exprime plutôt
aujourd'hui par un discours de peur, parlant de dangers (jamais
clairement spécifiés) et laissant entendre qu'il faudrait contrôler
sévèrement les IDN. Les déclarations précédentes de l'IAB peuvent être
trouvées dans « IAB Statement: "The
interpretation of rules in the ICANN gTLD Applicant
Guidebook" » et « Response
to ICANN questions concerning 'The interpretation of rules in the ICANN gTLD
Applicant Guidebook' ». Dans ces textes, l'IAB
plaidait pour un extrême conservatisme dans l'autorisation de
caractères, en restreignant encore les règles techniques des RFC 5890 et RFC 5892, par
exemple en n'autorisant que les caractères de la catégorie Unicode
« Lettres ».
Dans ce RFC, l'IAB veut aller plus loin en interdisant également des caractères de cette catégorie. Le RFC prend l'exemple de ʼ (U+02BC, une apostrophe), qui a un rendu quasiment toujours identique à ’ (U+2019) alors qu'il est dans la catégorie Lettre (U+2019 étant dans la catégorie Ponctuation, mystères des catégories Unicode). Sans compter la traditionnelle ' (U+0027). Bien que, légalement, U+02BC soit un caractère autorisé dans un IDN, le RFC suggère que ce n'est sans doute pas une bonne idée de l'autoriser.
S'il y a des caractères dans la catégorie Lettres qui ne devraient sans doute pas être autorisés (cas ci-dessus), l'inverse existe aussi : des caractères situés dans d'autres catégories sont néanmoins indispensables dans certaines langues, notamment indiennes. Cela illustre le point mentionné plus haut : il n'y a pas d'algorithme pour établir automatiquement la liste des caractères autorisés, il va falloir y aller à la main. La section 4.2.4 du RFC 5891 mentionnait ce travail comme une reponsabilité indispensable du registre, et ce RFC 6912 ajoute que ce travail doit être fait à l'avance, pas décidé lorsqu'une demande d'enregistrement de nom se présente. Une telle décision lorsqu'une demande survient offrirait trop de possibilités à l'arbitraire. Non, il faut des règles pré-établies, et publiées. (À titre d'exemple, vous pouvez regarder les règles d'enregistrement des IDN dans .fr.)
Le RFC estime que ces règles doivent être d'autant plus sévères (doivent autoriser moins de caractères) que l'on monte dans la hiérarchie des zones et que la zone racine doit donc avoir des règles particulièrement conservatrices, puisqu'elle concerne tous les utilisateurs de l'Internet.
Donc, pas d'algorithme (s'il était possible, il aurait sans doute déjà été développé) mais des principes. Quels sont-ils ? La section 3 en fournit une liste. D'abord, le principe de longévité : comme un caractère peut changer de catégorie, invalidant son usage (un exemple figure dans le RFC 6452), il est prudent de n'autoriser que des caractères qui sont stables depuis plusieurs versions d'Unicode.
Ensuite, le principe de moindre étonnement : un utilisateur normal ne devrait pas être trop surpris de la présence ou de l'absence de tel caractère. Notez que cela dépend du contexte : un utilisateur d'une écriture donnée ne sera pas surpris par les mêmes choses qu'un utilisateur d'une autre écriture.
Ces principes étaient valables pour toutes les zones. Mais les zones publiques ont des contraintes supplémentaires (section 4). Il y a le principe conservateur (dans le doute, rejeter le caractère), le principe d'inclusion (les caractères sont interdits par défaut et on inclut ensuite explicitement ceux qu'on estime « sûrs », terme que le RFC ne définit pas, et qui vient du FUD anti-Unicode), le principe de simplicité (un « honnête homme », avec des compétences modérées en DNS et en Unicode, doit pouvoir comprendre les raisons qui ont amené au choix d'acceptation ou de rejet, sans avoir eu besoin d'être présent aux quinze dernières réunions de l'IETF)...
Ce principe de simplicité dépend là encore du contexte. Si l'honnête homme cité plus haut ne connait aucune langue indienne, il ne comprendra sans doute pas les raisons qui ont mené à l'ajout de caractères non-lettres, indispensables pour certaines de ces langues. La racine servant à tous, ses règles devraient être ultra-simples et ne pas demander de compétences linguistiques particulières. Un ccTLD d'un pays donné peut se permettre des règles plus complexes pour des étrangers, mais qui sembleront simples à ceux qui connaissent les langues locales.
Pour les zones publiques, il y a aussi le principe de prédictabilité (les règles doivent donner un résultat identique, dès qu'on les applique sérieusement) et de stabilité (la liste des caractères autorisés ne devrait changer que rarement).
La racine, pour les raisons expliquées plus haut, a droit à une section spéciale (section 5). Le RFC demande qu'elle soit strictement peuplée de lettres, en s'appuyant sur une note de la section 2.1 du RFC 1123 qui dit que c'est le cas (c'était vrai lorsque le RFC 1123 a été publié, mais il n'y a aucun consensus à l'IETF sur l'interprétation de cette note : exprime t-elle une constatation ou une prescription ?) L'idée derrière cette restriction (RFC 4690) est que les noms de domaines n'ont pas vocation à permettre d'écrire tous les mots, encore moins des phrases correctes et complètes, mais uniquement celle de permettre la création de mnémoniques pratiques.
Ce RFC exprimant des opinions très contestables, la discussion avait été animée (voir par exemple les commentaires que j'avais fait sur une précédente version, violemment anti-Unicode).
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : W. Dec (Cisco Systems), B. Sarikaya (Huawei), G. Zorn (Network Zen), D. Miles (Google), B. Lourdelet (Juniper Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF radext
Première rédaction de cet article le 30 avril 2013
Le protocole RADIUS joue un rôle important dans l'accès à l'Internet : c'est le principal mécanisme utilisé pour faire communiquer la machine qui contrôle l'accès physique avec la machine qui contient la base des utilisateurs et les informations sur les autorisations, les configurations spécifiques... RADIUS avait bien sûr déjà la capacité de transporter des informations IPv6 mais ce nouveau RFC en ajoute quelques unes.
Une petite révision sur RADIUS d'abord (vous pouvez suivre sur la figure 1 du RFC). Lorsqu'un utilisateur accède à l'Internet, plusieurs machines sont utilisées. Il y a d'abord la machine terminale de l'utilisateur, ou bien un petit routeur, nommé RG (Residential Gateway). L'un des deux porte les informations d'authentification (identificateur et mot de passe). Cette machine terminale ou bien se petit routeur se connecte au réseau et parle à un AN (Access Node : dans le cas de l'ADSL, c'est le DSLAM qui sert d'AN, dans le cas d'un accès commuté, c'est le serveur de modems). L'authentification pourrait être faite par l'AN. Mais l'utilisateur ne parle pas toujours au même AN (par exemple s'il est mobile) et puis, on gagne en souplesse en découplant les fonctions d'accès et d'authentification. On a donc un serveur qui stocke les informations d'authentification et les paramètres des clients, le AAA (Authentication, Authorization and Accounting). Entre l'AN et le AAA se trouve souvent un NAS (Network Access Server), un routeur IP (dans certains cas, AN et NAS sont confondus, par exemple pour la plupart des serveurs PPP). Le NAS est client RADIUS et utilise ce protocole pour demander à l'AAA « j'autorise ce client ? » L'AAA, serveur RADIUS, répond oui ou non et ajoute une série d'attributs, qui sont les paramètres de la session, par exemple l'adresse IP à utiliser. Notez que RADIUS ne sert qu'entre le NAS et le AAA. Entre le RG et le NAS, on peut utiliser plusieurs autres protocoles, comme PPP ou, plus courant aujourd'hui, DHCP (RFC 8415).
RADIUS avait déjà des attributs pour IPv6 :
le RFC 3162 avait Framed-IPv6-Prefix
pour indiquer le préfixe IPv6 à utiliser et
Framed-Interface-Id
qui, combiné avec la valeur
précédente, permettait de fabriquer une adresse IP6 pour
l'utilisateur (cette séparation puis recombinaison était plus adaptée
à PPP qu'à DHCP, qui donne des adresses entières). Et le RFC 4818 avait
Delegated-IPv6-Prefix
qui permettait de
transmettre un préfixe à déléguer à un routeur par l'option de
délégation DHCP du RFC 8415.
Quels sont ces attributs qui manquaient dans les RFC 3162
et RFC 4818 ? La section 3 en fournit la liste,
et ils sont désormais notés dans le registre
IANA (cf. section 6). Le premier est
Framed-IPv6-Address
qui permet d'attribuer une
adresse IPv6 complète au visiteur (a priori via DHCP). Elle peut apparaître dans les
réponses RADIUS, mais aussi dans les questions, pour exprimer un
souhait (que le serveur RADIUS peut ignorer). Framed-IPv6-Address
peut être envoyé dans une
réponse RADIUS en même temps que les anciens
Framed-IPv6-Prefix
and
Framed-Interface-Id
(par exemple si le réseau
local, derrière le RG, utilise à la fois DHCP et l'auto-configuration sans état
- SLAAC).
Le second attribut, DNS-Server-IPv6-Address
, indique
l'adresse IP d'un résolveur DNS. (Un seul
résolveur ; mais la réponse RADIUS peut contenir plusieurs attributs
DNS-Server-IPv6-Address
, afin de transmettre les
adresses de plusieurs résolveurs.) Ces serveurs DNS peuvent ensuite être indiqués aux machines du réseau
local par les Router Advertisement du RFC 8106 ou bien en DHCP (RFC 3646).
Ensuite, Route-IPv6-Information
permet de
spécifier une route statique. L'attribut existant,
Framed-IPv6-Route
(RFC 3162), ne suffit
pas car elle est pour l'usage du NAS, il ne la transmet pas au RG. Au
contraire, le nouvel attribut
Route-IPv6-Information
est prévu pour être
redistribué. Le NAS pourra transmettre cette information au RG avec les annonces
Router Advertisement du
RFC 4191 ou bien une méthode équivalente. Les autres données
nécessaires dans l'option Route Information de
l'annonce (par exemple la préférence ou la durée de vie), devront
être connues du NAS par un autre moyen (ce point a été le plus chaud
lors des discussions dans le groupe de travail).
Enfin, dernier attribut,
Delegated-IPv6-Prefix-Pool
indique le nom d'un
pool d'adresses IPv6 à utiliser par le NAS. Là encore, c'est un
attribute RADIUS conçu pour être relayé avec DHCP mais qui peut
coexister avec Framed-IPv6-Pool
, plutôt fait pour les Router
Advertisement.
Date de publication du RFC : Mars 2013
Auteur(s) du RFC : Y. Lee (Comcast), R. Maglione (Telecom Italia), C. Williams (MCSR Labs), C. Jacquenet (France Telecom), M. Boucadair (France Telecom)
Pour information
Réalisé dans le cadre du groupe de travail IETF softwire
Première rédaction de cet article le 26 mars 2013
DS-Lite est une des nombreuses techniques de transition / co-existence IPv4 / IPv6. Elle est normalisée dans le RFC 6333. Ce nouveau RFC se penche plutôt sur des problèmes opérationnels : comment déployer DS-Lite, quels pièges éviter, etc.
DS-Lite (Dual-Stack Lite) est conçu pour un FAI récent, qui vient d'arriver et n'a donc pas pu obtenir d'adresses IPv4, toutes épuisées. Ce FAI a donc dû numéroter son réseau en IPv6, et comme ses clients ont encore de l'IPv4 à la maison, et comme ils souhaitent accéder à des machines Internet qui sont encore uniquement en IPv4, le FAI en question va donc devoir 1) NATer les adresses de ses clients (RFC 3022) vers le monde extérieur 2) tunneler leurs paquets depuis leur réseau local IPv4 (RFC 2463) jusqu'au CGN, en passant par le réseau purement IPv6 du FAI. C'est là que DS-Lite intervient (RFC 6333).
Apparemment, il n'y a eu qu'un seul déploiement effectif de DS-Lite chez un vrai FAI (le RFC ne dit pas lequel) et ce RFC 6908 est largement tiré de cette expérience réelle. Il est donc une lecture intéressante pour les opérateurs qui aiment le concret.
Ce RFC est en deux parties : les questions liées à l'AFTR et celles liées au B4. Vous ne savez pas ce qu'est un AFTR ou un B4 ? Vous n'avez pas envie de lire le RFC 6333 qui explique cela ? Alors, en deux mots, l'AFTR (Address Family Transition Router) est le gros routeur NAT (le CGN) situé entre le FAI et l'Internet. Et le B4 (Basic Bridging Broadband element) est chez le client, typiquement dans sa box et représente le point d'entrée du tunnel, du « lien virtuel » (soft wire). Prononcez les sigles à voix haute : le B4 est avant le tunnel (before) et l'AFTR après (after).
Donc, bien qu'il soit « après », notre RFC commence par l'AFTR (section 2). D'abord, comme DS-Lite utilise un tunnel, il va y avoir des problèmes dus à la MTU inférieure. Le RFC recommande donc d'essayer de faire un lien entre le B4 et l'AFTR ayant une MTU d'au moins 1540 octets pour que, après avoir retiré les 40 octets de l'encapsulation dans le tunnel, on ait les 1500 octets d'Ethernet. Si ce n'est pas possible, alors le B4 et l'AFTR vont devoir gérer la fragmentation. Comme le réassemblage des paquets est une opération coûteuse en ressources (il faut garder les fragments en mémoire tant que tout n'est pas arrivé), la tâche va être particulièrement lourde pour l'AFTR (des milliers de tunnels peuvent se terminer sur un seul AFTR). Il faut les dimensionner largement ! (C'est un problème général des CGN.)
Ensuite, il faut penser à la journalisation. Le principe de DS-Lite est que tous les clients du FAI partageront la poignée d'adresses IPv4 publiques que NATeront les AFTR. Si un client fait quelque chose de mal (par exemple accéder à un site Web qui déplait au gouvernement), il faut pouvoir l'identifier. Un observateur situé à l'extérieur a vu une adresses IPv4 du FAI et des milliers de clients pouvaient être derrière. L'AFTR doit donc noter au moins l'adresse IPv6 du B4 (elle est spécifique à chaque client) et le port source utilisé après le NAT (en espérant que l'observateur extérieur ne notera pas que l'adresse IPv4 source mais aussi le port, cf. RFC 6302).
Les adresses IP partagées sont une plaie du NAT, ce n'est pas nouveau (RFC 6269). Par exemple, si une adresse IPv4 est mise sur une liste noire suite à son comportement, ce seront des centaines ou des milliers de B4 qui seront privés de connectivité IPv4. Si le destinataire ne tient pas compte du RFC 6302 et bloque sur la seule base de l'adresse IPv4, le support téléphonique du FAI qui a déployé DS-Lite va exploser. (Un travail est en cours à l'IETF pour aider à l'identification de l'utilisateur derrière un CGN. Mais il n'est pas terminé et, de toute façon ne sera pas forcément déployé. L'obstination de tant d'acteurs à rester en IPv4 va se payer cher.)
Un problème analogue se posera si le FAI veut faire de la comptabilité des octets échangés, et s'il ne met pas cette fonction dans le CPE. Le tunnel et le NAT rendront cette analyse plus compliquée (section 2.6). À noter que le RFC 6519 normalise des extensions à Radius pour les problèmes particuliers de DS-Lite.
Mais tout ceci n'est rien par rapport aux problèmes de fiabilité que posent les AFTR. L'Internet normal est très robuste car les équipements intermédiaires (les routeurs) n'ont pas d'état : s'ils redémarrent, rien n'est perdu. S'ils s'arrêtent de fonctionner, on en utilise d'autres. Le NAT met fin à tout cela : le routeur NAT a un état en mémoire, la table des correspondances {adresse interne, adresse externe} et, s'il redémarre, tout est fichu. C'est bien pire pour un CGN : s'il redémarre, ce sont des centaines ou des milliers d'utilisateurs qui perdent leurs connexions en cours. La fiabilité des AFTR est donc cruciale (cf. annexe A.3 du RFC 6333). Notre RFC propose que des AFTR de remplacement soient installés pour être prêts à prendre le relais. Ils peuvent fonctionner en « remplacement à chaud » (Hot Standby), se synchronisant en permanence avec l'AFTR primaire, prêts à le remplacer « sans couture » puisqu'ils ont le même état, ou bien en « remplacement à froid » (Cold Standby), sans synchronisation. Dans ce second cas, l'AFTR de secours fait qu'un AFTR en panne est vite remplacé, mais il n'y a pas de miracle : les clients doivent recommencer toutes leurs sessions. Vue la complexité qu'il y a à mettre en œuvre correctement la synchronisation des états, notre RFC recommande le remplacement à froid, et tant pis si c'est moins agréable pour les utilisateurs.
Et les performances ? Combien faut-il d'AFTR pour servir les utilisateurs ? La section 2.8 discute de ce point et du meilleur placement de ces équipements.
Comme avec tout CGN, DS-Lite, en centralisant les adresses IPv4, limite les possibilités de géo-localisation. Le B4 (donc la maison de l'utilisateur) et l'AFTR peuvent parfaitement être dans des villes différentes (RFC 6269, section 7). Les applications ne devraient donc pas se fier à la géo-localisation mais demander à l'utilisateur où il se trouve, par exemple avec le protocole HELD du RFC 5985 ou en suivant l'architecture du RFC 6280. Le RFC conseille, curieusement, de mettre les AFTR le plus près possible des utilisateurs, pour limiter ce problème (alors que les AFTR ont besoin d'une connectivité IPv4, et que le réseau du FAI ne la fournit pas forcément, sinon il n'aurait pas besoin de DS-Lite).
Autre problème douloureux avec les CGN (dont DS-Lite), les connexions entrantes. Contrairement au NAT traditionnel, celui fait par la box à la maison, plus question de configurer sa box via une interface Web pour rediriger certains ports. Et plus moyen de se servir d'UPnP. Les éventuelles redirections doivent être sur l'AFTR, un engin largement partagé. Donc, pas question de demander une redirection du port 80...
Pour « programmer » l'AFTR, lui demander d'ouvrir certains ports en entrée, notre RFC recommande d'installer un serveur PCP (Port Control Protocol, RFC 6887) sur les AFTR. Il n'est pas évident que cela soit une solution satisfaisante. D'une part, il existe encore très peu de clients PCP (par rapport aux clients UPnP). D'autre part, l'AFTR étant partagé entre plusieurs clients ne se connaissant pas, rien ne dit que la coexistence se passera bien et que les opérateurs accepteront d'ouvrir PCP à leurs clients.
Voilà, c'étaient les points essentiels pour les AFTR, lisez la section 2 du RFC si vous voulez la liste complète. Et les B4 ? Ils font l'objet de la section 3. D'abord, le problème du DNS. Le B4 est censé s'annoncer comme résolveur DNS et relayer les requêtes DNS au dessus d'IPv6 vers l'extérieur. Ce faisant, il est important qu'il suive les recommendations pour les relais DNS du RFC 5625 (en pratique, la grande majorité des boxes et des petits routeurs bas de gamme violent affreusement ces recommendations). C'est notamment nécessaire si on veut que DNSSEC fonctionne.
Si un client sur un réseau local IPv4 fait des requêtes DNS en IPv4 vers une adresse qui n'est pas celle du B4, ces requêtes seront tunnelisées et NATées comme n'importe quel trafic IPv4. Compte-tenu du fait que, du point de vue du NAT, chaque requête DNS est une session à elle seule, l'augmentation de la charge sur les AFTR sera sensible. Ce n'est donc pas conseillé.
Le B4 étant le début du réseau de l'opérateur, et beaucoup de choses dépendant de sa configuration et de son bon fonctionnement, il est important que l'opérateur puisse y accéder à distance, et au dessus d'IPv6, pas au dessus du lien virtuel (qui a davantage de chances d'avoir des problèmes).
À propos d'administration et de supervision du réseau, il est
important que les AFTR répondent aux paquets utilisés pour
ping et traceroute, afin
que le B4 puisse tester que la connectivité IPv4 au dessus du tunnel
marche bien. Des adresses IPv4 spéciales ont été réservées pour cela
(rappelez-vous que, si vous déployez DS-Lite, c'est que vous n'avez
pas assez d'adresses IPv4 publiques),
192.0.0.0/29
. Les AFTR sont censés tous répondre
aux paquets envoyés à 192.0.0.2
.
Date de publication du RFC : Mars 2013
Auteur(s) du RFC : E. Wilde (EMC Corporation)
Pour information
Première rédaction de cet article le 21 mars 2013
Les liens sont à la base du
Web, tout le monde le sait, mais on sait moins
que les liens sont typés, marqués avec un type qui indique leur
sémantique. Ainsi, le type profile
, décrit dans
ce RFC, indique que le lien pointe vers un
profil, une spécification du format utilisé qui restreint les
possibilités d'un format donné.
Ce concept de profil est très fréquent en informatique (mais pas vraiment défini de manière rigoureuse). Lorsqu'on veut réutiliser un format mais qu'on n'a besoin que d'une petite partie de ses possibilités, on définit un profil qui consiste en gros à dire « dans tel format, n'utiliser que ci et ça ». Un profil peut être un peu plus compliqué qu'une simple restriction, par exemple il peut spécifier quelques extensions obligatoires. Le point important est qu'un programme qui sait traiter le format doit savoir traiter un fichier utilisant un profil de ce format. Ainsi, un podcast est un flux de syndication (et doit donc pouvoir être traité par tout programme gérant ces flux) mais avec des éléments spécifiques, qui peuvent être compris par un lecteur de podcasts, comme Apple iTunes.
Le format lui-même est indiqué par d'autres méthodes. Par
exemple, en HTTP, le format peut être indiqué
par le type de media (ou type MIME), comme
text/html
. On peut aussi indiquer le format dans
le document lui-même : en HTML, on va utiliser la déclaration
DOCTYPE
pour cela. Et pour indiquer
le profil ? Eh bien on va se servir d'un lien. (HTML 4 avait un attribut
profile
dans l'élément
<head>
mais il n'est pas sûr que HTML 5 le
garde et, de toute façon, la solution de ce RFC est plus
générale.)
Ces liens suivent le cadre général normalisé dans le RFC 8288. Ce cadre comprend notamment un registre
des types de liens (dans lequel se trouve désormais
profile
), et plusieurs syntaxes pour mettre les
liens dans le document (cas du <link>
de HTML)
ou dans le protocole d'accès (cas de l'en-tête
Link:
de HTTP).
La distinction entre profils et formats est parfois subtile. Ainsi, XHTML n'est pas considéré comme un profil de XML parce que, pour les usages de XHTML, afficher du XML brut, sans les traitements spécifiques de XHTML, n'aurait guère d'intérêt. En revanche, hCard est bien un profil de XHTML, car, si un logiciel ne comprend pas hCard, le traiter et l'afficher comme du bête XHTML est utile.
Les profils sont identifiés par un URI
(comme les espaces de noms de
XML). Ces URI ne sont pas forcément
déréférençables (on ne peut pas toujours les donner à un
navigateur Web), ce sont juste des
identificateurs et le logiciel doit donc les traiter comme tels, pas
les présenter systématiquement comme des liens cliquables. Le RFC conseille
juste (ce n'est pas une obligation) de les rendre déréférençables, et
de mettre une jolie documentation du profil au bout de l'URI. Ainsi,
si je crée un profil de HTML nommé
http://www.example.org/profiles/myprofile
, il est
recommandé (juste recommandé) qu'une page Web décrivant myprofile
se
trouve effectivement à cette adresse.
Une curiosité : un document peut correspondre à plusieurs profils
et le lien de type profile
peut donc pointer vers
une liste.
La section 5 du RFC donne quelques exemples concrets.
D'abord, hCard, déjà cité. Il permet de mettre
des vCard (RFC 6350) dans HTML. Son
URI est
, on peut donc l'indiquer par un lien comme http://microformats.org/profile/hcard
<link rel="profile" href="http://microformats.org/profile/hcard" />
et on trouve plein d'exemples dans la documentation
Autre exemple, Dublin Core, identifié par le
profil
http://dublincore.org/documents/2008/08/04/dc-html/
qui permet de mettre des métadonnées Dublin Core dans une page en
HTML. (Je n'en ai pas mis dans ce blog mais mes flux de
syndication, en XML, continnent du
Dublin Core.) Un exemple simple, les éléments Dublin Core ayant un nom commençant par DC :
<html> <head> <title>Expressing Dublin Core in HTML/XHTML meta and link elements</title> <link rel="profile" href="http://dublincore.org/documents/2008/08/04/dc-html/"/> <meta name="DC.title" lang="en" content="Expressing Dublin Core in HTML/XHTML meta and link elements" /> <meta name="DC.creator" content="Andy Powell, UKOLN, University of Bath" /> <meta name="DCTERMS.issued" scheme="DCTERMS.W3CDTF" content="2003-11-01" /> <meta name="DCTERMS.abstract" content="This document describes how qualified Dublin Core metadata can be encoded in HTML/XHTML <meta> elements" /> <meta name="DC.format" scheme="DCTERMS.IMT" content="text/html" /> </head>
Dernier exemple, déjà cité, les podcasts. Il n'y a pas
d'identificateur officiel (on pourrait utiliser l'URI http://www.apple.com/itunes/podcasts/specs.html
).
Il existe désormais un registre de ces profils, créé par le RFC 7284.
Date de publication du RFC : Mars 2013
Auteur(s) du RFC : Tissa Senevirathne (CISCO), David Bond (IBM), Sam Aldrin, Yizhou Li (Huawei), Rohit Watve (CISCO)
Pour information
Réalisé dans le cadre du groupe de travail IETF trill
Première rédaction de cet article le 30 mars 2013
Le protocole TRILL est un protocole de routage pour réseaux locaux, qui veut combiner les avantages des réseaux L2 (non routés) et L3 (routés, avec des protocoles plus complexes). Ce RFC est le cahier des charges pour les futurs mécanismes d'administration et de supervision des réseaux TRILL.
TRILL est normalisé dans le RFC 6325. Il vise surtout les gros data centers et les fournisseurs d'infonuagique. Il est par exemple déployé sur le service d'hébergement de Gandi. Comme tous les protocoles, il a besoin d'OAM : Operations, Administration and Maintenance, c'est-à-dire l'ensemble des activités de l'administrateur réseaux pour maintenir le réseau en bon état de marche (cf. RFC 6291 et RFC 5860). Un réseau TRILL est composé de RBridges, engins intermédiaires entre les ponts et les routeurs et ce sont eux qu'il faut gérer. La section 4 du RFC énumère les exigences des futurs mécanismes OAM de TRILL. Parmi elles :
Il ne reste plus qu'à développer tout cela. Un expert de TRILL parmi mes lecteurs pour expliquer ce que peuvent faire les RBridges actuels, avec résultat de commandes à l'appui ?
Date de publication du RFC : Mars 2013
Auteur(s) du RFC : J. Snell
Pour information
Première rédaction de cet article le 21 mars 2013
Allez, encore tout un lot de types de liens Web qui sont enregistrés. Pas de point commun entre les types créés par ce RFC, juste quelques types intéressants.
Tous suivent les principes du RFC 8288 qui normalise cette idée de type de lien et décrit le registre où ils sont désormais stockés.
Le premier, about
pointe vers une ressource
qui décrit celle qui contient le lien. L'exemple donné par le RFC est
celui d'un article de test d'un produit, qui pointe vers une page Web
décrivant le produit. Avec les en-têtes HTTP :
HTTP/1.1 200 OK Content-Type: text/html Link: <http://store.example.org/product/abc>; rel="about"
Le second, preview
permet de pointer vers une
ressource qui offre une version limitée, plus courte ou à plus basse
résolution, pour ceux qui voudraient aller vite. Ici, par exemple, une
vidéo a un lien vers une version courte de dix secondes :
HTTP/1.1 200 OK Content-Text: video/mpeg Link: <http://example.org/preview/10-second-preview.mpg>; rel="preview"; type="video/mpeg"
Le troisième, privacy-policy
, permet de
pointer vers une ressource (par exemple une page Web) décrivant la
politique du gérant, relative à la vie privée. Si vous regardez le source de ce blog, vous
trouverez un tel lien en HTML, allant vers
ma politique :
<link rel="privacy-policy" href="/privacy-policy.html"/>
Le RFC rappelle bien que cela n'a aucune valeur juridique : le Web est plein de « politiques de vie privée » que personne ne consulte et qui n'engagent nullement le site Web qui les affiche.
À noter que, pour indiquer ces pratiques (collectes de
données personnelles, enregistrement des
visites, etc), il existe un autre mécanisme,
P3P. Le mécanisme de lien
privacy-policy
peut pointer vers une ressource
P3P mais ce n'est pas obligatoire.
Le quatrième type est terms-of-service
, qui
pointe vers les conditions d'utilisation. Comme
vous le savez, personne ne les
lit, et pour des bonnes raisons (ce sont de longs textes incompréhensibles). Un exemple :
<html> <head> ... <link href="/tos.html" rel="terms-of-service"/> ... </head> <body> ... </body> </html>
Le RFC note à juste titre que celui qui les écrit peut ensuite les violer impunément. Ce lien n'a donc d'autre rôle que de signaler ces conditions d'utilisation.
Enfin, dernier type décrit ici, type
, permet
de dire qu'une ressource est une instance d'une classe plus générale,
identifiée par un URI,
ici qu'une page décrit une personne :
HTTP/1.1 200 OK Content-Type: text/plain Link: <http://example.org/Person/givenName>; rel="type" Jeanne Michu
C'est probablement surtout utile pour le Web sémantique. Attention, ce type
n'a
rien à voir avec le Content-type
qui indique le
format physique (dit souvent « type MIME »).
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : P. Bryan (Salesforce.com), M. Nottingham (Akamai)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 3 avril 2013
Le format de données structurées JSON, normalisé dans le RFC 8259, a pris une importance de plus en plus grande et est désormais utilisé dans bien des contextes. Cela entraine l'apparition de normes auxiliaires, spécifiant comment faire telle ou telle opération sur des fichiers JSON. Ainsi, le RFC 6901 indique comment désigner une partie d'un document JSON et ce RFC 6902, sorti en même temps, indique comment exprimer les modifications (patches) à un document JSON.
Logiquement, le patch est lui-même un fichier
JSON (de type application/json-patch
, cf. la
section 6 de notre RFC) et il indique les opérations à faire (ajouter, remplacer,
supprimer) à un endroit donné du document (identifié par un pointeur
JSON, ceux du RFC 6901). Voici un
exemple de patch :
[ { "op": "add", "path": "/baz", "value": "qux" } ]
Il va ajouter (opération add
) un membre nommé
baz
et de valeur qux
. Si le
document originel était :
{ "foo": "bar"}
Celui résultant de l'application du patch sera :
{ "baz": "qux", "foo": "bar" }
À noter que ces patches travaillent sur le modèle de donnéees JSON, pas directement sur le texte (autrement, on utiliserait le traditionnel format diff), et peuvent donc s'appliquer sur des données qui ont un modèle similaire, quelle que soit la syntaxe qu'ils avaient. Dans les exemples de code Python à la fin, le patch est appliqué à des variables Python issues d'une analyse d'un fichier JSON, mais qui pourraient avoir une autre origine. (Au passage, je rappelle l'existence d'un format équivalent pour XML, le XML patch du RFC 5261.)
Le patch peut être envoyé par divers moyens,
mais l'un des plus courants sera sans doute la méthode PATCH
de HTTP (RFC 5789). Voici un exemple d'une requête HTTP avec un
patch :
PATCH /my/data HTTP/1.1 Host: example.org Content-Length: 326 Content-Type: application/json-patch If-Match: "abc123" [ { "op": "test", "path": "/a/b/c", "value": "foo" }, { "op": "remove", "path": "/a/b/c" }, { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] }, { "op": "replace", "path": "/a/b/c", "value": 42 }, { "op": "move", "from": "/a/b/c", "path": "/a/b/d" }, { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" } ]
Un patch JSON a quelle forme (section 3) ? C'est un tableau dont chaque object qui le compose est une opération, à appliquer dans l'ordre du tableau (dans le premier exemple ci-dessus, le tableau ne comportait qu'une seule opération). L'entité à laquelle on applique le patch est donc transformée successivement et chaque opération s'applique au résultat de l'opération précédente.
Quelles sont les opérations possibles (section 4) ? Le membre
op
indique l'opération,
path
la cible et value
la
nouvelle valeur. op
peut être :
add
: si la cible est dans un tableau, on
ajoute la valeur à ce tableau (si le pointeur pointe vers la fin du
tableau, avec la valeur -
, on ajoute après le
dernier élément). Si la cible est un membre inexistant
d'un objet, on l'ajoute. S'il existe, on le remplace (ce point a été
vigoureusement critiqué au sein du groupe de travail, où plusieurs
personnes regrettaient qu'on mélange les sémantiques de
add
et de replace
; parmi
les propositions alternatives, il y avait eu de nommer cette opération
set
ou put
plutôt qu'add
).remove
: on retire l'élément pointé.replace
: on remplace la valeur pointée.move
: on déplace l'élément (ce qui
nécessite un paramètre supplémentaire, from
).copy
: on copie la valeur pointée vers un
nouvel endroit.test
: teste si une valeur donnée est
présente à l'endroit indiqué. Cela sert lorsqu'on veut des opérations
conditonnelles. Les opérations étant appliquées dans l'ordre, et la
première qui échoue stoppant tout le patch, un
test
peut servir à faire dépendre les opérations
suivantes de l'état du document JSON.
Mais à quel endroit applique-t-on cette opération ? C'est indiqué par
le membre path
qui est un pointeur JSON
(cf. RFC 6901). Enfin,
value
indique la valeur, pour les opérations qui
en ont besoin (par exemple add
mais évidemment
pas remove
).
La section 5 spécifie ce qui se passe en cas d'erreurs : le
traitement s'arrête au premier problème. Pour le cas
de la méthode HTTP PATCH
, voir la section 2.2 du
RFC 5789. PATCH
étant
atomique, dans ce cas, le document ne sera pas
du tout modifié.
Quelles mises en œuvre existent ? Une liste est disponible en ligne, ainsi que des jeux de test. Je vais ici essayer celle en Python, python-json-patch. D'abord, il faut installer python-json-pointer et python-json-patch :
% git clone https://github.com/stefankoegl/python-json-pointer.git % cd python-json-pointer % python setup.py build % sudo python setup.py install % git clone https://github.com/stefankoegl/python-json-patch.git % cd python-json-patch % python setup.py build % sudo python setup.py install
Ensuite, on écrit un programme Python qui utilise cette bibliothèque. On va le faire simple, il prend sur la ligne de commande deux arguments, un qui donne le nom du fichier JSON original et un qui donne le nom du fichier contenant le patch. Le résultat sera écrit sur la sortie standard :
#!/usr/bin/env python import jsonpatch import json import sys if len(sys.argv) != 3: raise Exception("Usage: patch.py original patchfile") old = json.loads(open(sys.argv[1]).read()) patch = json.loads(open(sys.argv[2]).read()) new = jsonpatch.apply_patch(old, patch) print json.dumps(new)
Maintenant, on peut écrire un fichier JSON de test,
test.json
, qui décrit ce RFC :
% cat test.json { "Title": "JSON Patch", "Number": "NOT PUBLISHED YET", "Authors": [ "P. Bryan" ] }
On va maintenant essayer avec différents fichiers
patch.json
contenant des patches (l'annexe A
contient plein d'autres exemples). Un ajout à un tableau :
% cat patch.json [ { "op": "add", "path": "/Authors/0", "value": "M. Nottingham" } ] % python patch.py test.json patch.json {"Title": "JSON Patch", "Number": "NOT PUBLISHED YET", "Authors": ["M. Nottingham", "P. Bryan"]}
Un changement d'une valeur :
% cat patch.json [ { "op": "replace", "path": "/Number", "value": "6902" } ] % python patch.py test.json patch.json {"Title": "JSON Patch", "Number": "6902", "Authors": ["P. Bryan"]}
Un ajout à un objet :
% cat patch.json [ { "op": "add", "path": "/Status", "value": "standard" } ] % python patch.py test.json patch.json {"Status": "standard", "Title": "JSON Patch", "Number": "NOT PUBLISHED YET", "Authors": ["P. Bryan"]}
Une suppression d'un champ d'un objet :
% cat patch.json [ { "op": "remove", "path": "/Authors" } ] % python patch.py test.json patch.json {"Title": "JSON Patch", "Number": "NOT PUBLISHED YET"}
Si vous aimez les controverses, un des débats les plus animés, plus
d'un an avant la sortie du RFC, avait été de savoir si l'opération
d'ajout devait se noter add
(comme cela a
finalement été choisi) ou bien simplement +
. Le
format diff traditionnel utilise des
mnémoniques plutôt que des noms et cela peut accroître la lisibilité
(cela dépend des goûts).
Merci à Fil pour sa relecture attentive qui a trouvé plusieurs problèmes techniques.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : P. Bryan (Salesforce.com), K. Zyp (SitePen), M. Nottingham (Akamai)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 3 avril 2013
Ce court RFC spécifie une syntaxe pour identifier un élément particulier dans un document JSON. Cela permettra de pointer vers l'intérieur d'un document, par exemple depuis un URI.
JSON (RFC 8259) est un format structuré de données très populaire sur le Web. Les documents JSON peuvent être de taille très variable et il serait intéressant d'avoir une syntaxe formelle pour désigner une partie bien spécifique d'un document JSON, comme XPointer le permet pour XML et le RFC 5147 pour le texte brut. Outre les URI cités plus haut, un des usages envisagés est la modification de documents JSON, via la norme JSON patch du RFC 6902, puisque la mise à jour nécessite de dire exactement où on va faire l'ajout ou la suppression de données.
La syntaxe est exposée en section 3 : un JSON
pointer est une chaîne de caractères
Unicode (JSON pointer
travaille entièrement avec des caractères Unicode,
pas avec des octets).
Il contient plusieurs éléments séparés
par des barres obliques. Ce caractère, ainsi
que le tilde, sont donc spéciaux et, si on veut
avoir leur valeur littérale, il faut un
échappement, ~0
pour le ~
et ~1
pour le /. (Programmeurs, attention, en
décodant, il faut d'abord remplacer tous les ~1
par des /
avant de s'attaquer à la deuxième
substitution, sinon ~01
sera mal décodé.)
Pour illustrer ces pointeurs, je vais utiliser pour tous les
exemples les données des chemins de fer britanniques
disponibles en JSON en http://api.traintimes.im/
. Commençons par récupérer la liste des stations :
% wget http://api.traintimes.im/stations_all.json
On peut alors connaître les codes tiploc des gares, ici, on va utiliser WMOR
pour Woodsmoor.
Cherchons les trains qui passent à Woodsmoor aux alentours de midi :
% wget -O wmor.json http://api.traintimes.im/locations.json\?location=WMOR\&date=2013-02-14\&startTime=1200
Le fichier JSON (passé à jsonlint) ressemble à :
{ ... "services" : [ { "departure_time" : "1141", "destination" : { "arrival_time" : "1145", "crs" : "HAZ", "description" : "Hazel Grove", "tiploc" : "HAZL" }}, "departure_time" : "1206", "destination" : { "arrival_time" : "1227", "crs" : "MAN", "description" : "Manchester Piccadilly", "tiploc" : "MNCRPIC" }} ...
Par exemple, avec ces données
/services
, /services/1
et /services/1/destination/description
sont tous des pointeurs JSON
valides.
Et comment est-ce que cela s'interprète ? La section 4 le
décrit. On part de la racine du document JSON. Donc, le pointeur
composé d'une chaîne vide identifie la totalité du document. Ensuite,
si la racine est un objet JSON (avec des champs nommés),
l'élement suivant identifie un des champs. Ainsi,
/foo
identifie le champ foo
de l'objet situé à la racine (il doit être unique). Si par contre la racine est un tableau,
l'élement suivant doit être un nombre, l'index dans le tableau (en
partant de zéro donc /1
identifie le deuxième
élément du tableau situé à la racine). Une seule valeur non-numérique
est permise, -
qui indique l'élément situé après
la fin du tableau (pour le JSON patch du RFC 6902, cela sert aux ajouts à la fin du
tableau, autrement, cela désigne un élément non-existant).
Donc, attention, /
n'identifie pas la racine du document mais un élément de nom vide
situé à la racine.
Le pointeur JSON est ensuite représenté sous forme texte comme une
chaîne de caractères JSON (section 5) ce qui oblige à échapper les
caractères spéciaux des chaînes JSON comme la barre
inverse ou comme le guillemet. Par
exemple, il faudra écrire a\\b
pour trouver
le membre d'objet JSON nommé a\b
.
Et dans un URI (section 6) ? Il faudra
encoder le pointeur en UTF-8 et faire un
échappement « pour cent » (RFC 3986, section
2.1) des caractères qui sont spéciaux dans un URI (comme le
point d'interrogation, section 2.2 du RFC 3986). Ainsi,
http://api.traintimes.im/locations.json?location=WMOR\&date=2013-02-14\&startTime=1200#/services/1/destination/arrival_time
pointera vers la valeur 1227
(regardez
l'identificateur de fragment après le
croisillon : c'est un pointeur JSON). À noter que tous les types
MIME n'accepteront pas forcément le pointeur
JSON comme un moyen normal de désigner un fragment du document
JSON et l'exemple ci-dessus est donc hypothétique.
Reste à traiter le cas des erreurs (section 7). Deux erreurs typiques sont un élément non numérique dans le pointeur alors que la valeur est un tableau, ou bien un nom de champ inexistant. Le RFC ne spécifie pas ce qui doit se produire dans un tel cas, cela doit être défini par l'application qui utilise les pointeurs (pour JSON patch, voir les sections 4.1 et 5 du RFC 6902).
Une liste des mises en œuvre connues des pointeurs JSON est disponible à l'IETF (en fait, ce sont les mises en œuvre de JSON Patch mais, comme les pointeurs sont un pré-requis, elle couvre aussi les mises en œuvre des pointeurs). Il existe aussi une implémentation « faite en 20 minutes » en node.js, js-6901. Testons l'implémentation Python :
% git clone https://github.com/stefankoegl/python-json-pointer.git % cd python-json-pointer % python setup.py build % sudo python setup.py install
Et lançons l'interpréteur Python pour voir :
>>> import jsonpointer >>> import json >>> doc = json.load(open("wmor.json")) >>> jsonpointer.resolve_pointer(doc,'/services/1/destination/description') u'Manchester Piccadilly' >>> jsonpointer.resolve_pointer(doc,'/services/0/destination/description') u'Hazel Grove' >>> jsonpointer.resolve_pointer(doc,'/services/2/destination') {u'crs': u'BUX', u'arrival_time': u'1251', u'description': u'Buxton', u'tiploc': u'BUXTON'}
Tout marche donc bien et on récupère, soit des valeurs, soit des objets JSON. Et avec un pointeur qui ne pointe vers rien ?
>>> jsonpointer.resolve_pointer(doc,'/zzz') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python2.7/dist-packages/jsonpointer.py", line 105, in resolve_pointer return pointer.resolve(doc, default) File "/usr/local/lib/python2.7/dist-packages/jsonpointer.py", line 140, in resolve doc = self.walk(doc, part) File "/usr/local/lib/python2.7/dist-packages/jsonpointer.py", line 183, in walk raise JsonPointerException("member '%s' not found in %s" % (part, doc)) jsonpointer.JsonPointerException: member 'zzz' not found in { ...
On a, fort logiquement, une exception.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : Donald Eastlake (Huawei)
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 17 avril 2013
Un RFC un peu bureaucratique, pour détailler les mécanismes utilisés pour l'enregistrement dans les registres de l'IANA des paramètres liés au DNS. Il met très légèrement à jour son prédécesseur, le RFC 6195, libéralisant encore un peu plus l'enregistrement de nouveaux types de données dans le DNS.
Un certain nombre de paramètres (section 2, qui résume le format des paquets DNS), dans le DNS, sont enregistrés à l'IANA, afin de s'assurer d'une interprétation identique partout. C'est ainsi que l'IANA gère un registre des paramètres DNS où on trouve, entre autres, les types d'enregistrement (A, codé 1, pour une adresse IPv4, AAAA, codé 28, pour une adresse IPv6, LOC, codé 29, pour les positions géographiques du RFC 1876, TLSA, codé 52, pour le RFC 6698, etc). Cet espace n'étant pas de taille infinie, il faut y enregistrer de nouveaux paramètres avec prudence.
L'affectation dans cet espace forme le point le plus important de
ce RFC (section 3). Il faut comprendre qu'il y a trois types de
numéros utilisés dans cet espace : ceux qui identifient un type de
données (comme les quatre cités plus haut), ceux qui identifient une
question et le cas particulier des méta-types. Une question, dans le
DNS, peut être un type de données (on met 52 dans le champ
QTYPE
de la requête pour dire qu'on veut des
enregistrements TLSA), mais il existe aussi des questions qui ne
correspondent pas à un type unique comme 255
(noté ANY
ou ALL
ou *
) qui veut dire
« envoie-moi toutes les données que tu as, quelles que soit leur
type ». Enfin, les méta-types sont des données temporaires, liées à
une transaction, comme les TSIG
(numéro 250) du RFC 8945, qui n'existent que le temps de la session
DNS.
Pour les types de données, la politique d'allocation est simple et
libérale : on remplit un formulaire (qui se trouve en annexe A du RFC), on l'envoie à
l'IANA (via l'adresse
dns-rrtype-applications@ietf.org
) et un expert l'examinera (procédure
Expert Review du RFC 5226) et rendra son jugement. (Il est recommandé de l'envoyer d'abord à la liste du
liste de groupe de travail
dnsext pour un examen préalable.) Les formulaires approuvés
sont ensuite publiquement archivés (mais je n'ai pas trouvé où).
Le RFC donne les critères que doit suivre l'expert pour sa décision :
CNAME
,
DS
), on
revient à la procéédure, bien plus lourde, d'une norme en bonne et due
forme. Notez que, pour certains types, un traitement spécial est
possible mais pas obligatoire (cas de MX
, où il
est conseillé d'inclure les adresses IP des serveurs de courrier dans
la réponse mais, si ce n'est pas fait, le service marche quand
même). Dans ce cas, c'est la procédure libérale qui s'appliqueOutre l'enregistrement de nouveaux types de ressources DNS, notre
RFC mentionne également d'autres champs des messages DNS. Un
changement ou une extension de leur sémantique continue à nécessiter
une action plus lourde à l'IETF. C'est le cas des classes (comme la
plus courante, IN
pour Internet). C'est aussi le
cas de bits comme RD (Recursion
Desired), qui n'a de signification que dans une question DNS. Dans
une réponse, il est indéfini et son éventuelle utilisation future nécessitera
un RFC sur le chemin des normes. Même chose pour le dernier bit qui
reste libre dans les options, le bit Z (section 2.1). Quant aux
opcodes qui indiquent le type du message (requête /
notification / mise à jour dynamique / etc), un ajout à leur liste
nécessitera le même chemin (section 2.2). Ils ont leur
propre registre.
Les codes de réponse (rcodes), comme
NXDOMAIN
(nom inexistant),
FORMERR
(erreur de format) ou
BADTIME
(signature trop ancienne ou trop récente,
cf. RFC 8945) sont tirés d'un
espace plus vaste (il n'y a pas que les quatre bits 12 à 15 dans l'en-tête
classique, il y a aussi des extensions comme les pseudo-enregistrements
OPT
) et la procédure est donc un peu plus
libérale (IETF Review, c'est-à-dire un RFC non
individuel mais pas
forcément sur le chemin des normes, cf. section 2.3). Il y a également
un registre de ces codes. À
noter qu'une gestion trop légère des registres avait entraîné à une
époque une double affectation du rcode 16,
enregistré par le
RFC 2671, puis ré-enregistré par le RFC 2845...
Notez aussi que notre RFC mentionne (section 3.3) l'allocation des noms, pour rappeler qu'il existe des noms réservés (RFC 2606) et qu'il existe un RFC (bien dépassé par les évolutions politiciennes ultérieures à l'ICANN), le RFC 1591, sur l'allocation et la gestion des TLD.
Les changements depuis le RFC 6195 sont décrits dans l'annexe B. Le seul vraiment important est une simplification du processus d'enregistrement des nouveaux types de données (par exemple, l'examen de la demande d'enregistrement d'un nouveau type de données par le groupe de travail dnsext n'est plus obligatoire). Cette simplification était largement consensuelle. Le reste des changements est un ensemble varié de clarifications et de précisions.
Date de publication du RFC : Mars 2013
Auteur(s) du RFC : E. Wilde (EMC Corporation)
Pour information
Première rédaction de cet article le 13 mars 2013
Dans le registre des types de liens, il y
avait déjà un describedby
qui indiquait une
ressource Web décrivant la ressource courante. Désormais, il y a aussi
l'inverse, describes
, qui va d'une ressource à
celle qu'elle décrit.
C'est dans le RFC 8288 que sont spécifiés ces
types de liens. describedby
avait été spécifié
par la norme W3C POWDER
mais celle-ci ne spéficiait pas le type du lien inverse. Notons que
describes
est très général, il ne spécifie pas le
format à utiliser et, notamment, on n'est pas obligé de se limiter à
RDF, on a tout à fait le droit de fournir des
descriptions en XML ou
JSON (section 4 de notre RFC).
Par exemple, si une page Web parle du livre Net.Lang, elle peut le référencer ainsi, en utilisant comme identificateur du livre l'URL de son site officiel :
<link rel="describes" href="http://net-lang.net/"/>
ou bien, pourquoi pas, avec l'ISBN (RFC 8254) :
<link rel="describes" href="urn:isbn:978-2-915825-08-4"/>
Il peut y avoir sur le Web plusieurs ressources qui pointent, via
un lien describes
, vers une ressource donnée.
Attention, n'importe qui peut toujours mettre un lien
describes
pointant vers n'importe où : la seule
existence de ce lien n'implique pas qu'il fasse autorité (section 5).
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : J. Damas (Bond Internet Systems), M. Graff, P. Vixie (Internet Systems Consortium)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 17 avril 2013
L'extension EDNS au traditionnel DNS a plus de treize ans et fête cette longue durée avec une nouvelle version, essentiellement cosmétique. EDNS a servi à faire sauter un certain nombre de barrières qui limitait la croissance du DNS, notamment l'antédiluvienne limite des réponses à seulement 512 octets.
Le protocole DNS, dans sa forme originale, spécifiée dans le RFC 1034, ne permettait pas de négocier des options, d'indiquer au serveur ce que sait faire le client, en plus des capacités minimales qu'impose le protocole. La norme originale (RFC 1035, section 2.3.4) imposait une limite de 512 octets aux messages DNS envoyés sur UDP. Une telle limite est bien trop basse, depuis longtemps, par exemple pour DNSSEC (section 3 de notre RFC), et ne correspondait pas aux capacités des réseaux et des machines modernes. Le DNS avait d'autres limites comme des champs de taille fixe, ne permettant qu'un petit nombre de valeurs possibles, désormais presque toutes définies (par exemple, avant EDNS, les codes de réponse - RCODE - ne faisaient que quatre bits, donc étaient presque tous épuisés).
EDNS0 est un mécanisme d'extension du DNS et une première extension, pour indiquer une taille supérieure aux 512 octets. L'extension se fait en squattant des champs inutilisés du paquet (DNS est un format binaire rigide, il ne permet donc pas facilement d'ajouter de nouvelles possibilités) et en créant un pseudo-type d'enregistrement, le type OPT. Déclaré comme indispensable par certaines autres extensions (notamment DNSSEC), EDNS fait aujourd'hui partie du bagage nécessaire à toute mise en œuvre du DNS.
L'extension pour indiquer la taille permet au client de
spécifier la quantité d'octets qu'il est capable de recevoir (section 4.3). Avec le
client DNS dig, cela se fait avec l'option
bufsize
(désormais activée par défaut dans les
versions récentes de dig). Notre RFC recommande une valeur par défaut
de 4 096 octets (section 6.2.5).
Prenons par exemple le TLD
.hk
car c'est un des plus
gros en nombre de serveurs de noms. Si je demande cette liste :
% dig NS hk. ; <<>> DiG 9.8.1-P1 <<>> NS hk. ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 65212 ;; flags: qr rd ra; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 14 ;; QUESTION SECTION: ;hk. IN NS ;; ANSWER SECTION: hk. 69658 IN NS X.HKIRC.NET.hk. hk. 69658 IN NS T.HKIRC.NET.hk. hk. 69658 IN NS S.HKIRC.NET.hk. hk. 69658 IN NS A.HKIRC.NET.hk. hk. 69658 IN NS B.HKIRC.NET.hk. hk. 69658 IN NS W.HKIRC.NET.hk. hk. 69658 IN NS Z.HKIRC.NET.hk. hk. 69658 IN NS U.HKIRC.NET.hk. hk. 69658 IN NS Y.HKIRC.NET.hk. hk. 69658 IN NS V.HKIRC.NET.hk. ;; ADDITIONAL SECTION: A.HKIRC.NET.hk. 69658 IN A 203.119.2.18 B.HKIRC.NET.hk. 69658 IN A 203.119.87.19 B.HKIRC.NET.hk. 69658 IN AAAA 2001:dca:1000::cb77:5713 S.HKIRC.NET.hk. 69658 IN A 128.32.136.3 S.HKIRC.NET.hk. 69658 IN AAAA 2607:f140:ffff:fffe::3 T.HKIRC.NET.hk. 69658 IN A 128.32.136.14 T.HKIRC.NET.hk. 69658 IN AAAA 2607:f140:ffff:fffe::e U.HKIRC.NET.hk. 69658 IN A 210.201.138.58 U.HKIRC.NET.hk. 69658 IN AAAA 2404:0:10a0::58 V.HKIRC.NET.hk. 69658 IN A 204.61.216.46 V.HKIRC.NET.hk. 69658 IN AAAA 2001:500:14:6046:ad::1 W.HKIRC.NET.hk. 69658 IN A 202.12.28.140 W.HKIRC.NET.hk. 69658 IN AAAA 2001:dc0:1:0:4777::140 X.HKIRC.NET.hk. 69658 IN A 202.45.188.39 ;; Query time: 1 msec ;; SERVER: 130.129.5.6#53(130.129.5.6) ;; WHEN: Tue Mar 12 19:30:33 2013 ;; MSG SIZE rcvd: 486
On voit que la réponse était proche des 512 octets et que, pour qu'elle tienne dans cette limite, le serveur a dû sérieusement réduire la taille de la section additionnelle (additional section). Si le serveur avait dû réduire encore plus, jusqu'à retirer des enregistrements de la section réponse (answer section), il aurait dû mettre le bit TC (troncation) à VRAI, imposant ainsi au client de reessayer en TCP.
Mais EDNS0 permet d'avoir la totalité de la section additionnelle (notez la pseudo-section lié à l'enregistrement OPT) :
% dig +bufsize=4096 NS hk. ; <<>> DiG 9.8.1-P1 <<>> +bufsize=4096 NS hk. ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50455 ;; flags: qr rd ra; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 20 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;hk. IN NS ;; ANSWER SECTION: hk. 69632 IN NS Z.HKIRC.NET.hk. hk. 69632 IN NS S.HKIRC.NET.hk. hk. 69632 IN NS A.HKIRC.NET.hk. hk. 69632 IN NS X.HKIRC.NET.hk. hk. 69632 IN NS T.HKIRC.NET.hk. hk. 69632 IN NS V.HKIRC.NET.hk. hk. 69632 IN NS W.HKIRC.NET.hk. hk. 69632 IN NS Y.HKIRC.NET.hk. hk. 69632 IN NS U.HKIRC.NET.hk. hk. 69632 IN NS B.HKIRC.NET.hk. ;; ADDITIONAL SECTION: A.HKIRC.NET.hk. 69632 IN A 203.119.2.18 B.HKIRC.NET.hk. 69632 IN A 203.119.87.19 B.HKIRC.NET.hk. 69632 IN AAAA 2001:dca:1000::cb77:5713 S.HKIRC.NET.hk. 69632 IN A 128.32.136.3 S.HKIRC.NET.hk. 69632 IN AAAA 2607:f140:ffff:fffe::3 T.HKIRC.NET.hk. 69632 IN A 128.32.136.14 T.HKIRC.NET.hk. 69632 IN AAAA 2607:f140:ffff:fffe::e U.HKIRC.NET.hk. 69632 IN A 210.201.138.58 U.HKIRC.NET.hk. 69632 IN AAAA 2404:0:10a0::58 V.HKIRC.NET.hk. 69632 IN A 204.61.216.46 V.HKIRC.NET.hk. 69632 IN AAAA 2001:500:14:6046:ad::1 W.HKIRC.NET.hk. 69632 IN A 202.12.28.140 W.HKIRC.NET.hk. 69632 IN AAAA 2001:dc0:1:0:4777::140 X.HKIRC.NET.hk. 69632 IN A 202.45.188.39 X.HKIRC.NET.hk. 69632 IN AAAA 2405:3001:1:58::1:39 Y.HKIRC.NET.hk. 69632 IN A 137.189.6.21 Y.HKIRC.NET.hk. 69632 IN AAAA 2405:3000:3:60::21 Z.HKIRC.NET.hk. 69632 IN A 194.146.106.70 Z.HKIRC.NET.hk. 69632 IN AAAA 2001:67c:1010:17::53 ;; Query time: 1 msec ;; SERVER: 130.129.5.6#53(130.129.5.6) ;; WHEN: Tue Mar 12 19:30:59 2013 ;; MSG SIZE rcvd: 613
Et voilà, tout le monde est désormais content.
La section 6 décrit le pseudo-enregistrement OPT, dont la présence
marque un paquet comme conforme à EDNS. Il est situé dans la section
additionnelle du message DNS, a le type 41, le nom de domaine est
forcément .
(la racine), la classe est détournée
de son rôle normal pour indiquer la taille des paquets que l'envoyeur
pourra recevoir en retour et le champ TTL est
également détourné de son usage normal pour offrir de nouvelles
options et de nouveaux codes de retour (rappelez-vous qu'il n'y avait
que quatre bits pour ces codes dans le DNS original). Pour l'instant, une seule
nouvelle option, le bit DO (DNSSEC OK) qui
indique la capacité de l'émetteur à traiter les signatures DNSSEC (il
avait été normalisé dans le RFC 3225).
L'ex-champ TTL sert aussi à indiquer le numéro de version d'EDNS, zéro actuellement (d'où le nom EDNS0 qu'on utilise parfois). Programmeurs, attention, certaines API (par exemple celle de DNS Python) nécessitent d'indiquer le numéro de version pour activer EDNS et il faut donc indiquer zéro pour dire qu'on veut de l'EDNS, ce qui peut être déroutant.
Ensuite, les données peuvent contenir plusieurs options. À l'heure actuelle, l'écrasante majoritéé des paquets EDNS n'en contiennent aucune. Mais, si c'est le cas, elles sont codées en TLV, un code indiquant l'option (les valeurs possibles étant dans un registre IANA), une longueur et les données spécifiques à l'option. Un exemple d'une telle option est le NSID du RFC 5001.
On notera qu'EDNS est ce que le DNS appelle une extension
hop by hop ce qui veut dire qu'elle s'applique
entre deux logiciels adjacents, pas de bout en bout. Si un client DNS
demande à un résolveur local, qui demande à son tour à un serveur de
.re
, les options EDNS
mises par le client sont transmises uniquement au résolveur, qui
fabriquera ensuite une requête différente (peut-être avec d'autres
options), pour le serveur faisant autorité pour
.re
.
Encore aujourd'hui, il existe des serveurs qui ne gèrent pas
EDNS. Par exemple, ceux de microsoft.com
répondent FORMERR
(Format Error) :
% dig +bufsize=4096 @ns2.msft.net. SOA microsoft.com. ; <<>> DiG 9.8.1-P1 <<>> +bufsize=4096 @ns2.msft.net. SOA microsoft.com. ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: FORMERR, id: 54935 ...
La section 6.2.2 de notre RFC précise donc qu'un émetteur intelligent peut alors se rabattre sur du DNS classique et ne pas envoyer l'enregistrement OPT :
% dig @ns2.msft.net. SOA microsoft.com. ; <<>> DiG 9.8.1-P1 <<>> @ns2.msft.net. SOA microsoft.com. ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 22484 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2 ;; WARNING: recursion requested but not available ;; QUESTION SECTION: ;microsoft.com. IN SOA ;; ANSWER SECTION: microsoft.com. 3600 IN SOA ns1.msft.net. msnhst.microsoft.com. 2013031202 300 600 2419200 3600 ...
Au moins, les serveurs de microsoft.com
répondent, même si c'est par un refus. Plus embêtant, les serveurs qui
ne répondent plus du tout lorsque la requête est en EDNS, en général
en raison d'une boîte noire mal programmée et mal gérée installée
devant le serveur (un pare-feu par exemple :
beaucoup d'administrateurs réseaux ne supportent pas que le serveur
DNS marche bien et mettent donc une
middlebox boguée devant,
cf. section 8 de notre RFC, ainsi que le RFC 5625). Un
logiciel comme BIND, lorsqu'il ne reçoit pas de
réponse, réessaie sans EDNS pour voir si c'est cela la cause du
problème. Cette possibilité est décrite en section 6.2.5 qui
recommande d'essayer d'abord EDNS avec une taille plus petite
(inférieure à la MTU, au cas où le problème
soit lié à la fragmentation), puis enfin sans EDNS.
L'EDNS original, du RFC 2671, prévoyait également des nouvelles façons de stocker les composants d'un nom de domaine, en plus des deux méthodes DNS traditionnelles, comprimée ou non (sections 4.2 et 5 de notre RFC et section 4.1.4 du RFC 1035). Cette pratique a été très peu utilisée, en raison des difficultés de déploiement (cf. RFC 3363 et RFC 3364). Notre RFC 6891 abandonne donc cette possibilité et reclasse le RFC 2673 (le seul qui avait utilisé un nouveau type de composants, les « composants binaires ») dans le cimetière des RFC dépassés. C'est le principal changement de ce nouveau RFC (les autres étant plutôt des détails, cf. annexe A.) Notons aussi que ce nouveau RFC est désormais « Norme Internet » et plus simplement « Proposition de norme ».
Pour les amateurs de programmation, du code C d'analyse d'un paquet DNS contenant de l'EDNS est dans mon article « Décoder les paquets DNS capturés avec pcap ».
Quelques exemples de code pour finir. Pour analyser un enregistrement OPT d'EDNS, voir comment c'est fait dans DNSmezzo. Ensuite, pour envoyer des requêtes EDNS, en Go, avec godns :
const ( EDNSBUFFERSIZE uint16 = 4096 ) ... m := new(dns.Msg) ... m.SetEdns0(EDNSBUFFERSIZE, true)
En Python, avec DNSpython (notez qu'on indique la version d'EDNS donc zéro pour activer EDNS n'est pas une erreur) :
message = dns.message.make_query(name, type, use_edns=0, payload=4096)
Et pour finir, en C, si vous assemblez le paquet à la main (il y a évidemment des façons plus simples de faire de l'EDNS), le code pourra ressembler à :
/* OPT pseudo-RR */ after_qname[4] = 0; /* root domain */ /* OPT = type 41 */ after_qname[5] = 0; after_qname[6] = 41; /* Class stores the payload size */ bufsize_wire = htons(bufsize); memmove(after_qname + 7, &bufsize_wire, sizeof(bufsize)); /* TTL store the RCODE and flags */ after_qname[9] = 0; after_qname[10] = 0; if (dnssec) { after_qname[11] = 128; /* DO: request DNSSEC signatures */ } else { after_qname[11] = 0; } after_qname[12] = 0; /* Resource data length (empty, here) */ after_qname[13] = 0; after_qname[14] = 0;
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : M. Cotton (ICANN), L. Vegoda (ICANN), R. Bonica (Juniper), B. Haberman (Johns Hopkins University Applied Physics Lab)
Première rédaction de cet article le 30 avril 2013
Dernière mise à jour le 16 juin 2017
Un certain nombre de préfixes d'adresses IP sont spéciaux, réservés à des tâches comme les exemples dans la documentation, ou bien prévus pour des protocoles particuliers. Ces préfixes n'étaient pas documentés à un endroit unique, ils étaient dans certains RFC, avec parfois des registres IANA. Ce RFC restructure le système, désormais la seule source faisant autorité est le registre IANA (un pour IPv4 et un pour IPv6). En outre, ces deux registres ont désormais une structure bien définie, notamment pour indiquer les propriétés d'un préfixe spécial.
Parmi les nombreux préfixes spéciaux, on peut citer le
0.0.0.0/8
du RFC 1122, qui
sert à désigner le réseau local, ou le fe80::/10
que le RFC 4291 dédie aux adresses locales au
lien. De temps en temps, un RFC rassemble tous
ces préfixes en un seul document et c'est ainsi que le RFC 5735 cataloguait tous les préfixes spéciaux
IPv4 alors que le RFC 5156 faisait la même chose pour
IPv6. Certains préfixes sont affectés à
l'IANA pour une allocation ultérieure (comme le
192.0.0.0/24
du RFC 5736). Ces prefixes-là ont un registre à l'IANA, pour
enregistrer ces allocations mais il n'existait pas de registre général
de toutes les adresses IPv4 spéciales. Même chose en IPv6 : le RFC 2928 et le RFC 4773 affectaient
2001:0000::/23
à l'IANA et créaient un registre
pour les adresses de ce préfixe mais sans prévoir de registre pour
tous les préfixes spéciaux. Résultat, lorsqu'un nouveau préfixe était
déclaré, il n'y avait plus de source à jour, avant qu'on publie un
nouvel RFC de synthèse. Notre RFC 6890 change ce système
et crée
ce registre unique de la totalité des préfixes spéciaux, pour IPv4 et pour IPv6. Notre RFC annule donc
les RFC 5735 et RFC 5156.
La section 2 du RFC liste les décisions prises et que l'IANA devra appliquer (suivant les sections 4.1 et 4.3 du RFC 2860 qui décrit les tâches de l'IANA). Le registre doit conserver, pour chaque préfixe IP, un certain nombre d'informations parmi lesquelles :
Évidemment, si les adresses IP d'un préfixe n'ont pas le droit d'être présentes en destination, les deux booléens suivants (transmissible par un routeur, et transmissible à d'autres domaines) n'ont pas de sens.
Voici quelques exemples de ces préfixes spéciaux (en mélangeant IPv4 et IPv6 qui, en pratique, sont dans deux registres) :
0.0.0.0/8
: désigne ce réseau local. Décrit
dans la section 3.2.1.3 du RFC 1122. Peut
apparaître en source, pas en destination.10.0.0.0/8
: adressage privé. Décrit dans
le RFC 1918. Peut apparaitre en source et en
destination, transmissible par les routeurs, pas d'unicité
mondiale.2001:10::/28
: préfixe dit
« ORCHID » (Overlay Routable Cryptographic Hash Identifiers), utilisé pour des adressages
sécurisés avec adresse dépendant d'une clé cryptographique. Décrit dans le RFC 4843. Ne peut
apparaitre ni en source, ni en destination (il n'est pas prévu de les
mettre directement dans les champs Source et Destination des paquets IPv6). Non transmissible par les routeurs, pas d'unicité
mondiale (mais une quasi-unicité due à leur choix imprévisible dans un espace très large).100.64.0.0/10
: partage d'adresses en
CGN. Décrit dans le RFC 6598. Peut apparaitre en source et en
destination, transmissible par les routeurs, pas d'unicité
mondiale.169.254.0.0/16
: adresses locales au lien,
typiquement auto-attribuées. Décrit dans le RFC 3927. Peut apparaitre en source et en
destination, non transmissible par les routeurs (locales au lien...), pas d'unicité
mondiale.fc0::/7
:
ULA. Décrit dans le RFC 4193. Peut apparaitre en source et en
destination, transmissible par les routeurs, pas d'unicité
mondiale (il avait été prévu un registre mondial pour une partie de
l'espace des ULA mais cela ne s'était jamais concrétisé).2001:0002::/48
ou 198.18.0.0/15
: adresses réservées pour les
mesures en laboratoire. Décrit dans le RFC 2544 ou le
RFC 5180. Peut apparaitre en source et en
destination, transmissible par les routeurs, pas d'unicité
mondiale.198.51.100.0/24
(et deux autres en IPv4) ou 2001:db8::/32
: adresses réservées à la
documentation. Décrit dans le RFC 5737 ou le
RFC 3849. Ne peut
apparaitre ni en source, ni en destination. Non transmissible par les routeurs, pas d'unicité
mondiale. Notez que, en IPv6, ces adresses pourraient être
quasi-uniques si elles étaient choisies au hasard dans l'espace
immense du 2001:db8::/32
. Mais, en pratique, tout
le monde prend la première, 2001:db8::1
.Date de publication du RFC : Avril 2013
Auteur(s) du RFC : S. Perreault (Viagenie), I. Yamagata, S. Miyakawa (NTT Communications), A. Nakagawa (Japan Internet Exchange (JPIX)), H. Ashida (IS Consulting G.K.)
Réalisé dans le cadre du groupe de travail IETF behave
Première rédaction de cet article le 1 mai 2013
Qu'on les approuve (ce qui n'est pas mon cas) ou pas, les CGN, ces gros routeurs NAT installés dans le réseau du FAI et gérant des centaines ou des milliers de clients, sont d'ores et déjà une réalité douloureuse dans de nombreux pays d'Asie, pour les pauvres utilisateurs de la 3G, et peut-être demain sur d'autres continents pour les accès fixes. Pour limiter les dégâts qu'ils causent, ce RFC 6888 pose un certain nombre de règles que devraient respecter ces CGN.
D'abord, qu'est-ce qu'un CGN ? Fonctionnellement, il ressemble au petit routeur NAT (RFC 2663) que vous avez chez vous. Comme lui, il fait du NAPT (Network Address and Port Translation), c'est-à-dire qu'il traduit dynamiquement des adresses IP du réseau interne vers celles utilisées à l'extérieur (et vice-versa pour les paquets dans l'autre sens). La grosse différence avec le petit routeur ou box chez vous est qu'il travaille pour de nombreux clients du FAI. Au lieu que l'adresse IP externe soit partagée uniquement entre les membres de votre cercle de famille, elle sera partagée avec des centaines d'inconnus.
Avec le CGN, il y a souvent « double NAT », une fois dans le CPE et une fois dans le CGN. Mais ce n'est pas obligatoire. Lorsqu'il y a double NAT, on parle souvent de NAT444 (deux traductions, d'IPv4 en IPv4).
Sur cette image, on voit du double NAT. Un FAI gère un
CGN.
Les adresses IP publiques du FAI, allouées par son
RIR sont ici
198.51.100.0/25
. Ce sont celles qui seront vues,
par exemple, par les sites Web où se connectent les clients du FAI. Le
FAI n'a pas assez d'adresses IP publiques pour son réseau interne et
il utilise donc le 10.0.0.0/8
du RFC 1918. Prenons maintenant le client 1 : son réseau local a des adresses
dans la plage 192.168.3.0/24
. Les paquets seront
donc émis avec ces adresses, NATés une première fois par la machine
CPE 1, vers l'adresse 10.0.5.22
. Ils seront
ensuite NATés une seconde fois par le CGN.
Le CGN a des conséquences, par exemple dans le domaine légal (en théorie, vous pourrez voir les agents de la HADOPI débarquer chez vous parce qu'un autre utilisateur du même CGN a téléchargé illégalement, cf. RFC 6269). Et cela limite sérieusement les activités que vous pourrez avoir sur l'Internet. Par exemple, un moyen courant d'accepter les connexions entrantes, normalement interdites par le NAPT, est de configurer sa box pour rediriger tel numéro de port vers tel service sur le réseau local (par exemple pour faire fonctionner des applications pair-à-pair). Le routeur CGN étant partagé entre de nombreuses personnes qui ne se connaissent pas, cela n'est plus possible. Contrairement au routeur NAT à la maison, le CGN n'est pas géré par les abonnés, qui ne peuvent pas modifier sa configuration.
D'autre part, la simple taille du CGN en fait un engin compliqué et fragile, et sa panne affecte bien plus de clients que le redémarrage d'une box. Enfin, ayant moins de ports sources à sa disposition par client, par rapport au routeur de la maison ou du SOHO, il risque plus souvent de tomber à cours, si les clients font beaucoup de connexions sortantes.
Mais, alors, pourquoi met-on des CGN ? Juste pour embêter les clients ? En fait, les FAI n'ont pas forcément beaucoup le choix. La pénurie d'adresses IPv4, bien que niée par beaucoup de négationnistes, est réelle depuis de nombreuses années. Par exemple, cela fait longtemps qu'on ne peut plus avoir une adresse IP par machine à la maison. Mais, jusqu'à récemment, on pouvait encore avoir une adresse IP publique par foyer. Désormais, l'espace d'adressage IPv4 disponible se resserrant chaque jour, ce n'est même plus le cas. S'il n'y a pas d'adresse IPv4 publique disponible pour chaque client, le CGN est la seule solution pour pouvoir continuer à faire de l'IPv4 (passer à IPv6 ferait moins de travail mais les acteurs du marché sont frileux).
Cela, c'était la raison avouable pour mettre des CGN. Il y en a une moins avouable, c'est que le CGN, grosse machine centrale et point de passage obligatoire pour tous les abonnés, est bien en phase avec la mentalité des opérateurs telco traditionnels. C'est ainsi que, dans l'Internet mobile où les libertés sont bien plus limitées, et l'utilisateur bien plus restreint dans ce qu'il a le droit de faire, tous les opérateurs 3G ont déployé cette solution depuis longtemps, refusant de donner une adresse IPv4 publique à chaque abonné, même avant l'épuisement complet des réserves. Comme le note prudemment le RFC, « there are driving forces other than the shortage of IPv4 addresses ».
À noter qu'un RFC décrit le déploiement de CGN comme une des techniques pouvant aider à la transition vers IPv6 : RFC 6264. Le CGN est un des composants de la solution DS-Lite, décrite dans le RFC 6333 et ce composant doit donc suivre les règles données plus loin.
Maintenant qu'on a présenté les CGN, que contient ce RFC ? Il liste des conseils qui, s'ils étaient appliqués, rendraient les CGN un peu moins insupportables. Comme le note la section 1, la publication de ce RFC ne signifie pas que l'IETF approuve ou même accepte les CGN, simplement que, puisqu'ils existent, autant essayer de limiter leurs effets négatifs. Comme un CGN est un routeur NAT, les précédents documents du groupe de travail Behave, concernant tous les types de NAT, s'appliquent aussi au CGN : RFC 4787, RFC 5382 et RFC 5508 notamment.
Les section 3 à 5 représentent donc le cœur de ce RFC. Elles contiennent les recommandations spécifiques pour les CGN. Chacune est nommée REQ-n où n est un numéro d'ordre. Ainsi, REQ-1 dit que, pour chaque protocole de transport, le CGN doit suivre les recommandations spécifiques à ce protocole (RFC 4787 pour UDP, RFC 5382 pour TCP, RFC 5508 pour ICMP, et RFC 5597 pour DCCP). Notons que les autres protocoles de transport (comme SCTP) ont donc de sérieuses chances de ne pas fonctionner au travers du CGN.
Exigence suivante, REQ-2, qui dit que le comportement de l'IP address pooling doit être paired. Cela signifie quoi ? Qu'une machine donnée doit toujours obtenir la même adresse IP externe (un CGN, contrairement au petit routeur NAT de la maison, a en général plusieurs adresses IP externes à sa disposition). Cela limite les risques de casser les applications. Le RFC 4787, section 4.1, donne les détails sur ce concept de paired.
À propos du nombre d'adresses externes disponible pour le CGN : REQ-3 exige que ces adresses puissent être en nombre quelconque et dans des plages non-contigües (avec l'épuisement des adresses IPv4, il sera de plus en plus dur de trouver des plages contigües).
REQ-4 traite un problème spécifique aux CGN, que n'avaient pas les petits routeurs NAT de la maison : il faut pouvoir limiter le nombre de ports utilisables par un utilisateur donné. Dans le NAPT, il y a moins d'adresses externes que d'adresses internes. On se sert donc des ports pour désambigüiser. Un seul utilisateur gourmand pourrait lancer plein de sessions et épuiser à lui seul la plage de ports disponibles (cela peut même être volontaire, pour faire un déni de service, cf. section 8). C'est pour se protéger contre cette attaque que REQ-4 exige une limitation, configurable, par client. Le RFC recommande aussi qu'on puisse limiter le rythme de création de sessions par utilisateur. C'est nécessaire pour protéger les autres utilisateurs, mais c'est un bon exemple des inconvénients du CGN, qui casse sérieusement la transparence du réseau et le principe de bout en bout. Les routeurs NAT cassaient ces principes mais uniquement entre membres d'un même foyer ou d'un même SOHO. Avec le CGN, on dépend de gens dont on ne connait rien.
Même chose avec REQ-5, consacrée à d'autres ressources partagées dans le CGN, comme sa mémoire. Un CGN a des problèmes d'équité que n'ont pas les routeurs NAT classiques, vue son utilisation entre personnes qui n'ont rien en commun a priori.
Parfois, les cibles que vise l'utilisateur sont situées dans le réseau du FAI, et donc atteignables sans traduction d'adresse. Pour ce cas, REQ-6 demande que le CGN puisse être configuré pour ne pas traduire si la destination est dans une liste d'adresses configurées par l'administrateur réseaux.
Lorsqu'un routeur NAT accepte des paquets entrants du moment qu'il a, dans sa table des traductions, une entrée pour ce couple {adresse,port} de destination, indépendemment de l'adresse IP source d'émission, on dit qu'il fait du Endpoint-Independent Filtering (RFC 4787, section 5). REQ-7 souhaite que ce soit le comportement du CGN, car il casse moins d'applications (notamment jeux en ligne et pair-à-pair) que le Address-Dependent Filtering (où les paquets sont refusés si l'adresse source n'est pas celle dans l'entrée de la table).
REQ-8 légifère sur la réutilisation d'un port externe lorsqu'il n'est plus utilisé. Par défaut, il devrait rester réservé pendant deux minutes, le Maximum Segment Lifetime de TCP (RFC 793, section 3.3), après lequel on est sûr que le paquet ne traîne plus dans le réseau. Cela permet d'éviter une collision entre une ancienne correspondance et une nouvelle, qui utiliserait le même port externe et recevrait par erreur de vieux paquets. Des exceptions sont prévues, notamment :
REQ-9 est plus ambitieux car il exige quelque chose qui n'existe pas dans les CGN actuels : un mécanisme permettant à l'utilisateur de changer les affectations de port, et que ce mécanisme soit de préférence PCP (Port Control Protocol, RFC 6887). Aujourd'hui, sur les petits routeurs NAT de la maison ou du SOHO, ce mécanisme d'affectation manuelle des correspondances {adresse externe, port externe} -> {adresse interne, port interne} est typiquement fait par l'interface Web d'administration du routeur, ou bien par UPnP. La disparition d'un tel mécanisme dans les CGN actuels est un des plus gros problèmes que posent les CGN. Il était donc nécessaire de le rétablir, pour que toutes les applications puissent bien fonctionner. Mais PCP est encore très récent et peu déployé.
REQ-10 concerne plutôt les besoins de l'opérateur plus que ceux des simples utilisateurs : il demande que les routeurs CGN soient gérables (MIB du RFC 4008, etc).
Une autre exigence, REQ-11 concerne le traitement des erreurs. Si un routeur CGN ne peut pas créer une corrrespondance entre adresse+port externe et interne, il doit jeter le paquet et devrait renvoyer un message ICMP Destination unreachable / code 1 (Host unreachable). et déclencher une trap SNMP. Le « devrait » (et pas « doit ») est parce que ces deux types de messages peuvent légitimement avoir un débit limité.
Pourquoi Host unreachable et pas Communication administratively prohibited comme c'était le cas dans le RFC 5508, section 6 ? Parce que le code 1 (Host unreachable) est une erreur « douce » (cf. RFC 1122) et ne coupera pas les connexions TCP en cours entre les mêmes machines (RFC 5461).
En outre, le RFC interdit de supprimer des entrées existantes dans la table de correspondances, ce qui permettrait pourtant de faire de la place pour de nouvelles connexions. C'est parce que la plupart des applications gèrent beaucoup mieux une impossibilté à établir une connexion qu'une perturbation ou une interruption d'une connexion en cours (RFC 5508, section 6).
Un bon routeur CGN devrait pouvoir journaliser son activité. La section 4 encadre cette tâche. La principale question qui se pose est l'identification des clients, si une adresse IP externe est repérée pour son comportement abusif (envoi de spam, écriture d'un commentaire de blog défavorable aux autorités, partage de fichiers musicaux, et autres crimes). Le site distant va noter que « 192.0.2.42 a fait quelque chose de mal » et les enquêteurs vont chercher la personne qui est derrière cette adresse. En raison du CGN, des dizaines ou des centaines de personnes peuvent avoir utilisé cette adresse. Pour que l'enquêteur ait la moindre chance de retrouver le coupable, il faut que le site distant journalise, non seulement l'adresse IP source (comme c'est typiquement le cas aujourd'hui), mais aussi le port source (cf. RFC 6302). Et il faut que le routeur CGN ait journalisé ses correspondances, protocole de transport, adresse+port internes, adresse+port externes et heure exacte. (C'est une obligation légale dans certains pays, par exemple en France avec la LCEN.)
Non seulement c'est très Big Brother comme comportement mais, en plus, cela peut rapidement produire une énorme quantité de données, ce qui ne va pas faciliter la tâche de l'opérateur. C'est pour cela que REQ-12 demande que ce ne soit pas activé par défaut, à la fois pour préserver la vie privée des utilisateurs et pour éviter de remplir les disques durs. (Notez aussi que le RFC ne conseille pas de loguer l'adresse IP de destination, ce qui serait bien pire.)
Et, au fait, comment allouer aux utilisateurs cette ressource limitée, les numéros de ports externes ? La section 5 formule trois exigences. Le problème est que les trois sont contradictoires. REQ-13 dit qu'il faudrait chercher à maximiser l'utilisation des ports (ils sont en nombre limités, 65 536 par adresse IP), REQ-14 (qui a suscité beaucoup de discussions dans le groupe de travail) qu'il faudrait minimiser le nombre d'entrées produites dans le journal, par exemple en allouant toute une plage de ports par adresse IP, et REQ-15 que, pour des raisons de sécurité, il faudrait rendre difficile pour un attaquant la prédiction des ports sélectionnés (RFC 6056). Pas de miracle, ces trois exigences ne peuvent pas être satisfaites simultanément et un routeur CGN doit donc choisir lequel est le plus important pour lui. J'emprunte à Simon Perreault une description de la situation en mai 2013 : « Le CGN de Cisco allouait les ports 100 % dynamiquement, comme un NAT traditionnel, et génèrait donc beaucoup de logs. Mais ceux d'autres vendeurs, dont Alcatel, Juniper et Huawei, [ainsi que Cisco désormais, note de Nicolas Février] allouent les ports en bloc, ce qui génère beaucoup moins de logs au prix d'une légère perte de taux d'utilisation des adresses IPv4 externes. Il y a aussi le deterministic NAT qui alloue les ports statiquement tout en conservant une plage d'allocation dynamique pour les débordements. »
Merci à André Sintzoff pour la relecture technique et la détection d'une grosse faute technique. Merci à Nicolas Février pour ses utiles commentaires, même s'il n'est pas d'accord avec moi sur les défauts du CGN.
Date de publication du RFC : Avril 2013
Auteur(s) du RFC : D. Wing (Cisco), S. Cheshire (Apple), M. Boucadair (France Telecom), R. Penno (Cisco), P. Selkirk (ISC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF pcp
Première rédaction de cet article le 1 mai 2013
Aujourd'hui, l'utilisateur de l'Internet ne bénéficie que rarement d'une connexion neutre, d'un simple tuyau le connectant à toutes les autres machines de l'Internet. La plupart du temps, il est au contraire bloqué derrière des engins comme les routeurs NAT ou les pare-feux. Par défaut, ces engins bloquent les connexions entrantes, limitant l'utilisateur à un usage type Minitel. Dans ce cas, on a souvent besoin de dire à l'engin sur le trajet « laisse entrer des connexions vers tel port » (par exemple pour le pair à pair). Cela se fait aujourd'hui en général par une interface spécifique (par exemple une page Web d'administration du routeur NAT) ou par le protocole privé UPnP. Il y avait donc une demande pour un protocole standard, adapté aux mécanismes d'aujourd'hui comme les CGN : c'est ce nouveau protocole, PCP (Port Control Protocol).
Voici un exemple de configuration manuelle comme on fait souvent
aujourd'hui, via une interface Web, ici celle d'une
Freebox :
Avec PCP, ces interfaces vont-elles
disparaître complètement ?
Le principe est simple : un serveur PCP tourne sur l'engin bloquant (routeur NAT ou pare-feu) et autorise des clients PCP à lui parler et à demander des services comme l'ouverture d'un port entrant, ou comme une durée de vie plus longue pour les sessions en cours. Redonnant du contrôle à la machine de l'utilisateur, il rétablit un peu de neutralité dans le réseau. Avec PCP, on a un moyen propre de gérer un serveur (acceptant des connexions entrantes) derrière un routeur NAT et même derrière un CGN. Rappelez-vous qu'accepter des connexions entrantes n'est pas seulement utile si on a un serveur Web à la maison, c'est également une fonction demandée par les protocoles de voix sur IP comme SIP ou bien par le pair-à-pair.
Une fois que le client PCP a obtenu une réponse positive du serveur
PCP (« OK, j'envoie les connexions entrantes sur le
port 8080 à 172.19.1.1
,
port 80, comme tu me l'as demandé »), il peut alors prévenir le reste
du monde. Cette information sur le rendez-vous n'est pas gérée par
PCP : on se sert de fonctions spécifiques au protocole (SIP
REGISTER
auprès du mandataire, pour SIP, par exemple), ou bien du
DNS (éventuellement avec mise à jour dynamique
du RFC 2136 pour cela). Les enregistrements
SRV du DNS (RFC 2782) sont la solution idéale, puisqu'ils
permettent d'indiquer le numéro de port.
On notera que PCP diminue le besoin d'ALG dans les engins intermédiaires. Une nouvelle application n'aura pas besoin d'attendre que des ALG apparaissent, elle pourra contrôler les connexions dont elle a besoin elle-même, via PCP.
Même si on n'accepte pas de connexions entrantes, qu'on est un pur client, PCP peut être utile. Les routeurs NAT et les pare-feux coupent typiquement la session au bout de N minutes d'inactivité. Pour empêcher cela, les applications qui doivent rester connectées longtemps (SSH, par exemple), envoient régulièrement des paquets keepalive. Avec PCP, ce n'est plus nécessaire, l'application peut dire au serveur PCP « augmente N, s'il te plait ».
PCP est conçu, au contraire d'UPnP, pour une large gamme de besoins : du NAT traditionnel (RFC 3022), au NAPT commun aujourd'hui dans les boxes (cf. RFC 3022, section 2.2), en passant par le CGN (RFC 6888) et des choses plus exotiques comme DS-Lite (RFC 6333 et RFC 6619), NAT64 (RFC 6146), et même NAT66/NPT (RFC 6296).
PCP est prévu pour fonctionner avec les protocoles de transport qui ont la notion de port (UDP, TCP, SCTP, DCCP, etc). Pour les autres (ICMP, RSVP, ESP...), PCP ne fournit que des services partiels.
Autre limitation : PCP suppose que la machine de M. Toutlemonde n'a qu'une seule connexion à l'Internet, passant par l'équipement qui héberge le serveur PCP. Le but est de garantir que l'équipement qui répond en PCP verra bien passer tous les paquets. Ce modèle convient à la maison ou à la petite entreprise actuelle, avec son réseau local connecté via une unique box. Le dessin 1 en section 4 du RFC illustre ce modèle.
Les sections suivantes fournissent les détails du
protocole. Celui-ci manipulant souvent des adresses IP, la représentation de celles-ci (section
5) va servir
souvent : PCP utilise systématiquement un champ de taille fixe de 128
bits (même pour des adresses IPv4, qui sont
alors représentées préfixées du ::ffff:0:0/96
), car c'est
plus simple.
Une description de haut niveau du protocole est en section 6. À première vue, PCP pourrait être traité comme un protocole requête/réponse (un peu comme le DNS) mais, en fait, comme il n'est pas synchrone (on peut envoyer plusieurs requêtes à la suite et lire ensuite plusieurs réponses), il vaut peut-être mieux le considérer comme un protocole suggestion/notification. Le client PCP fait des suggestions au routeur ou au pare-feu (qui sont donc libres de refuser) et le serveur PCP (le routeur ou pare-feu) envoie des notifications indiquant son état. Dans ce modèle, il y a donc deux flux de données indépendants, un du client PCP vers le serveur et un du serveur PCP vers le client. Bien sûr, l'envoi d'une notification est en général corrélé à une suggestion (elle indique indirectement l'acceptation de la suggestion) mais, je le répète, ce n'est pas synchrone. (Une des raisons de ce choix est de permettre au serveur de résister aux attaques par déni de service en ignorant les suggestions lorsque la charge est trop élevée, laissant le client ré-émettre si nécessaire.) PCP tourne sur UDP (ports 5350 et 5351) et n'a pas de notion de transaction (les messages ne portent pas d'identificateur de transaction.) La notification donne l'état actuel du routeur ou pare-feu. Si le client tient à savoir à quelle suggestion est liée telle notification, il doit examiner le contenu du message et le corréler aux suggestions qu'il a envoyées.
La section 7 indique le format standard de tous les paquets : un
numéro de version (aujourd'hui 2), un bit indiquant s'il s'agit d'une
question ou d'une réponse, un code indiquant l'opération (la plus
importante est sans doute MAP
, décrite en section
11), l'adresse IP
du client PCP, la durée de vie demandée ou obtenue (pour certaines opérations) et quelques autres informations, qui dépendent de
l'opération. Parmi elles, les options, encodées en
TLV et enregistrées dans un registre IANA.
Les réponses ont un champ indiquant le code de retour d'une requête. 0 est un succès, tous les autres codes indiquent une erreur. Par exemple, 2 est la réponse à une requête non autorisée (rappelez-vous que le serveur PCP a sa propre politique et n'obéit pas aveuglément à tout ce que demande le client), 3 la réponse à une requête syntaxiquement incorrecte, etc. Ces deux erreurs sont permanentes (renvoyer le même paquet PCP ne changera rien). Mais il existe aussi des erreurs temporaires comme 8 qui indique que le serveur PCP aurait bien voulu répondre favorablement mais qu'il manque de ressources (par exemple de ports libres) pour cela. Ré-essayer automatiquement, après un délai raisonnable, peut donc être une bonne solution.
Le fonctionnement de base de PCP figure en section 8. Le client PCP
doit d'abord trouver le serveur. Il a pu le connaître par
configuration statique, ou tout simplement l'apprendre via une option
DHCP (RFC 7291). Sinon, il tente le routeur par défaut,
qui sera en général le serveur PCP. Le client va ensuite générer un
message, où l'adresse IP du client est sa propre adresse IP (qui sera
souvent une adresse privée, du RFC 1918). La
section 16.4 explique comment connaître cette adresse grâce à
getsockname()
. Le
client doit être prêt à retransmettre (section 8.1.1 pour les détails) : UDP ne
garantit pas l'acheminement.
Le serveur reçoit la requête, vérifie qu'elle arrive sur la bonne interface (le CPE typique de M. Toutlemonde, par exemple, n'acceptera pas les requêtes PCP venant de l'Internet, uniquement celles venant du réseau local), vérifie que l'adresse du client dans le paquet correspond à l'adresse IP source (autrement, c'est qu'un NAT supplémentaire se trouvait accidentellement sur le chemin) et répond. Il inclus dans la réponse un champ Epoch qui est un compteur s'incrémentant une fois par seconde. Si le client voit ce compteur diminuer, cela indiquera que le routeur a probablement redémarré, et donc perdu toutes les correspondances enregistrées, qu'il va falloir re-créer.
C'est quoi, ces « correspondances » (mappings
dans la langue de George Martin) ? Le routeur
NAT maintient une table des correspondances entre un couple {adresse
IP interne, port interne} et un couple {adresse IP externe, port
externe}. Cette table est en partie remplie automatiquement lors des
connexions sortantes mais peut aussi être partiellement gérée par
PCP. Par exemple, le fonctionnement classique du NAT d'un petit
routeur à la maison, lorsqu'un paquet venant de {192.168.10.10
,
5623} sort, est de réserver un port pour cette session (mettons le
port 7891) et de mémoriser une correspondance
{203.0.113.254
, 7891} <=> {192.168.10.10
,
5623} (on suppose que l'adresse IPv4 externe du routeur est
203.0.113.254
). Avec cette correspondance en tête,
le paquet de réponse destiné à {203.0.113.254
,
7891} sera automatiquement NATé et dirigé vers {192.168.10.10
,
5623}. PCP permet de manipuler de telles correspondances et, par
exemple, pour reprendre un exemple donné plus haut, de dire « envoie
les connexions entrantes sur le port 8080 à 192.168.10.1
,
port 80 », ce qui se traduira par la création d'une correspondance
(mapping) {203.0.113.254
, 8080} <=> {192.168.10.11
,
80}. On notera que le client PCP n'a pas indiqué l'adresse externe
203.0.113.254
. PCP permet de le faire mais, dans
le cas le plus courant, le client PCP ne connait pas cette adresse et
laisse le serveur la choisir.
La section 10 résume les opérations les plus importantes de PCP,
MAP
(détaillée en section 11) et
PEER
(détaillée en section 12). MAP
permet de
créer les correspondances statiques, pour gérer un serveur,
PEER
permet notamment de manipuler les correspondances dynamiques,
celles crées automatiquement par le routeur NAT. La liste de toutes
les opérations est dans un registre IANA
(cf. section 19.2, sur la politique d'affectation des codes numériques
correspondants.)
Prenons l'exemple d'un serveur du
réseau local (comme {192.168.10.11
,
80} dans mon exemple), qui va appeler MAP
pour
« ouvrir » le routeur ou pare-feu aux connexions entrantes. En
pseudo-code :
/* Les variables précédées de & sont des pointeurs, pour pouvoir écrire un résultat dans la variable. */ externalport = 80; pcp_send_map_request(myport, myaddr, &externalport, &externaladdr, requestedlifetime, &assignedlifetime); if (!pcp_response_received()) panic("No answer"); } else { /* Éventuellement mettre à jour le DNS, un serveur de rendez-vous, pour dire au reste du monde qu'il peut y aller */ } /* La suite est le code habituel, sans PCP */ if (received_incoming_connection_or_packet()) process_it(s);
Si l'application se moque du port externe attribué, il suffit de ne pas l'indiquer dans la requête et de regarder dans la réponse quel port a été alloué. De toute façon, le routeur ne lui allouera pas forcément le port demandé. Par exemple, pour un CGN, tout le monde voudra sans doute s'allouer le port 80, ce qui n'est pas possible. Soit le CGN le refusera à tous, soit il le donnera au premier arrivé et allouera un autre port pour les suivants. Un client PCP bien fait doit donc être préparé : il doit lire le port effectivement attribué et réagir intelligemment s'il n'a pas eu le port souhaité (ce n'est pas fait dans le programme d'exemple ci-dessus). Bien sûr, le client PCP doit aussi être prêt à ce que sa requête soit complètement rejetée, par exemple parce que la table des correspondances a une taille fixe et que ladite table est pleine.
La lecture de la réponse permet aussi au client PCP de savoir quelle est l'adresse externe allouée, ce qui peut être pratique. (Si on n'est intéressé que par cela, il suffit donc de créer une correspondance avec une très courte durée de vie et de lire la réponse.)
La réponse PCP inclut la durée de vie de la correspondance
(champ Lifetime du paquet, variable
assignedlifetime
du programme plus haut). C'est
la responsabilité du client de renouveller la correspondance avant
qu'elle n'expire (cf. section 15).
Si l'application ne sait pas si elle est derrière un routeur NAT ou un
pare-feu, ce qui est fréquent, la solution recommandée est quand même
d'essayer PCP. S'il n'y a pas de réponse, cela peut vouloir dire que
la machine a une connectivité complète (sans NAT) ou malheureusement
que le routeur ne gère pas PCP. (Le code plus haut suppose que
l'absence de réponse indique qu'on n'a pas de connectivité en tant que
serveur, donc panic()
.)
Le routeur doit créer des correspondances ayant la sémantique Endpoint Independent Filtering, ce qui veut dire que cette correspondance sera la même quelle que soit l'adresse IP de la machine distante. Il va devoir aussi se débrouiller pour que les messages ICMP correspondant à cette correspondance soient bien acheminés à la machine.
Outre les champs génériques communs à tous les paquets PCP,
MAP
a quelques champs qui lui sont propres
notamment le port interne (la variable myport
dans le pseudo-code), le port externe suggéré
(la variable externalport
dans le programme en
pseudo-code) et l'adresse IP externe suggérée (rappelez-vous que le
petit routeur NAT de la maison n'a pas le choix : il n'a en général
qu'une seule adresse IPv4 externe, donc il ignorera ce
paramètre). Dans la réponse à un MAP
, la valeur
de ces champs indiquera au client ce que le serveur PCP a finalement
choisi (pas forcément ce qui était demandé). Une option de la requête
permet de dire si les adresses et ports suggérés sont impératifs (on
préfère un échec plutôt qu'une correspondance avec d'autres valeurs
que celles demandées) ou
pas (cf. section 13.2).
MAP
permet aussi de contrôler un
pare-feu, avec son option
FILTER
(section 13.3) où on décrit les adresses
IP et ports autorisés, le reste étant bloqué. Séparer la fonction de
NAT de celle de pare-feu est essentiel : actuellement, les routeurs
NAT typiques mélangent les deux, ce qui a mené certaines personnes à
croire que le NAT avait un rôle de
protection. Outre la sécurité, FILTER
peut
être utile pour des machines sur batterie :
elles éviteront ainsi de gaspiller du courant à traiter des paquets
non désirés.
PCP est également utile au cas où on n'a certes besoin que de
connexions sortantes mais où on veut influencer des paramètres comme
la durée de vie des correspondances créées automatiquement, de manière
à ne pas avoir besoin d'envoyer de temps en temps des paquets
keepalive. On utilise pour cela l'opération
PEER
. Cette opération a à peu près les mêmes
champs que MAP
mais les correspondances crées
peuvent avoir des sémantiques autres que Endpoint Independent
Filtering. (MAP
a le code 1 et
PEER
2, dans le registre IANA.)
Un autre usage de l'opération PEER
est pour
re-créer des correspondances perdues. Un des plus gros inconvénients du NAT est qu'il maintient un
état dans le routeur. Normalement, l'Internet est
un réseau de paquets, les routeurs intermédiaires font passer les
paquets mais n'ont aucune notion de session associées, il font passer
du TCP, de l'UDP ou
n'importe quel autre protocole sans faire de différence. Un des
avantages de ce principe est que le redémarrage d'un routeur ne change
rien : les connexions TCP, par exemple, continueront comme si rien ne
s'était passé, l'état des connexions étant entièrement contenu dans
les machines terminales. Le NAT change tout cela : si un routeur NAT
redémarre, toutes les correspondances sont perdues. Si les machines
tentent de continuer la communication, de nouvelles correspondances
seront créées, avec de nouveaux numéros de port, et ce changement
cassera les connexions TCP en cours. C'est notamment insupportable
pour SSH.
Comment PCP peut-il aider ? Une machine qui connait la
liste des correspondances (elle a pu l'apprendre avec l'opération
PEER
) peut, lorsqu'elle détecte un redémarrage du
routeur, lui renvoyer cette liste (toujours avec
PEER
mais, cette fois, en remplissant les champs
Suggested Address et Suggested Port), rétablissant ainsi la même table
des correspondances (section 14). À noter que, pour accélérer la
reconstitution de l'état du routeur, un routeur qui sait qu'il va
redémarrer peut aussi envoyer des paquets PCP avec l'opération
ANNOUNCE
(section 14.1.3) pour prévenir les
clients. Ces envois se font aux adresses
multicast
224.0.0.1:5350
et
[ff02::1]:5350
(224.0.0.1
et ff02::1
voulant dire « toutes les machines du réseau »). Les machines clientes
peuvent alors savoir qu'elles vont devoir recréer leurs
correspondances (après avoir attendu un délai aléatoire, pour éviter
qu'elles ne le fassent toutes en même temps).
PEER
peut enfin créer une nouvelle
correspondance mais cela n'a pas un grand intérêt, puisque tout
routeur NAT sait le faire automatiquement au premier paquet d'une
nouvelle connexion sortante. (La seule exception est le cas cité plus
haut où on restaure l'état d'un routeur NAT qui a redémarré.)
Je ne connais pas l'état actuel de mise en œuvre de PCP dans les routeurs NAT typiques. Pour le programmeur qui veut s'y mettre sérieusement, la section 16 contient un certain nombre de conseils pratiques, aussi bien pour l'écriture de serveurs que pour celle de clients PCP. Quant à la section 17, elle se penche sur les problèmes de déploiement de cette nouvelle technologie. Par exemple, il est important que le routeur rejette les paquets entrants dont l'adresse source ne correspond pas à celles du réseau interne (RFC 2827) pour éviter qu'un méchant n'usurpe une adresse IP.
Tiens, puisqu'on parle de sécurité, la section 18 lui est entièrement consacrée. PCP permet de contrôler plus finement les correspondances dans le routeur, voire de modifier les filtres d'un pare-feu. Il est donc essentiel que ces nouvelles possibilités ne se fassent pas au détriment de la sécurité. Par exemple, une machine du réseau interne autorisée à créer ou modifier des correspondances peut voler le trafic d'une autre. Ce n'est pas très grave pour un réseau local à la maison mais bien plus embêtant dans le cas d'un grand CGN.
PCP, s'il est correctement mis en œuvre, est protégé contre les
attaquants situés en dehors du chemin. Par exemple, si une machine
quelque part sur l'Internet envoie un paquet PCP prétendant venir
d'une des adresses internes (mettons
192.168.1.1
), le routeur/serveur PCP rejettera ce
paquet qui arrive par l'interface externe (il ne doit accepter les
requêtes PCP que si elles sont internes). Par contre, un attaquant
interne a à peu près open bar avec PCP. Un serveur
PCP doit donc être déployé uniquement si toutes les machines internes
sont considérées comme membres de la même bande (une supposition
raisonnable pour un réseau domestique) ou si on peut séparer les
clients en plusieurs domaines, empêchant M. Michu de voler le trafic
de Mme Toutlemonde, située derrière le même CGN.
Une façon de limiter les risques est que le serveur PCP ne configure explicitement que des correspondances qu'il aurait de toute façon configuré implicitement, lorsqu'une nouvelle connexion sort. Cela veut dire qu'il y a des opérations PCP sûres (créer une correspondance sans spécifier le port et l'adresse externes) et d'autres qui peuvent être dangereuses (créer une correspondance avec un port externe spécifié).
Si on autorise PCP à configurer un pare-feu, il faut évidemment faire encore plus attention. Il n'existe pas à l'heure actuelle de mécanisme de sécurité standard pour PCP : son premier domaine d'application concerne des cas où il n'y a déjà pas de sécurité aujourd'hui. Pour d'autres domaines, il faudra trouver de nouvelles solutions de sécurité.
Quelques autres attaques possibles avec PCP :
PCP est le successeur d'un protocole très proche nommé PMP (Port Mapping Protocol, RFC 6886). L'annexe A décrit la coexistence entre les implémentations de PMP qui restent, et PCP. L'autre protocole qui avait été envisagé par le groupe de travail PCP était bien sûr UPnP, mais qui était techniquement moins proche de ce qui était souhaité (non routé, peu sécurisé, peu fiable). PMP utilisant les mêmes ports, des dissecteurs de paquets analysent parfois le PCP sous le nom de PMP.
Aujourd'hui, on trouve très peu de mises en œuvre de PCP déployées. Aucun système d'exploitation n'a de client PCP en série. Une solution possible sera peut-être (suggestion de Gunther Ozerito) de faire un relais UPnP <=> PCP comme décrit dans le RFC 6970. Sinon, Wireshark va bientôt avoir un dissecteur PCP (il vient d'être développé et sera livré avec la future version 1.10 ; un autre, sous forme d'un greffon en Lua, est disponible). Attention, Wireshark a aussi un dissecteur pour un autre PCP (Performance Co-Pilot Protocol).
Et j'ai bien envoyé des paquets PCP à ma Freebox, mais je reçois toujours une triste réponse ICMP port 5351 unreachable d'où je déduis qu'elle n'a pas encore de serveur PCP. (Et elle ne diffuse apparemment rien vers le port 5350.)
Au fait, pour les envoyer, j'ai utilisé ce (très grossier) script Scapy, qui est loin de remplir tous les champs mais permet quelques tests :
from scapy.all import * # http://www.secdev.org/projects/scapy/doc/build_dissect.html class PCP(Packet): name = "Port Control Protocol" fields_desc = [ ByteField("Version", 2), BitField("R", 0, 1), # 0 = Request / 1 = Response BitField('Opcode', 1, 7), # MAP is 1, PEER is 2 ShortField("Reserved", 0), IntField("RequestedLifetime", 0), LongField("ClientAddressUpper", 0), LongField("ClientAddressLower", 0) ] p = IP(dst="192.168.2.254")/UDP(sport=0,dport=5351)/PCP(RequestedLifetime=5000, ClientAddressLower=232236033) sr1(p)
Un bon article d'introduction sur PCP est « New Technology Demo: PCP » dans le numéro 7.2 de l'IETF Journal.
Date de publication du RFC : Mars 2013
Auteur(s) du RFC : M. Blanchet (Viagenie), A. Sullivan (Dyn, Inc.)
Pour information
Réalisé dans le cadre du groupe de travail IETF precis
Première rédaction de cet article le 14 mars 2013
Dans bien des protocoles, il y a besoin de comparer deux chaînes de caractères, pour voir si elles sont égales. Par exemple, un protocole d'authentification va comparer un identificateur à ceux enregistrés dans sa base, pour voir s'il est présent. Si les chaînes de caractères sont uniquement en US-ASCII, il n'y a guère de problèmes, à part décider si la comparaison est sensible à la casse. Mais si elles sont en Unicode ce qui, en 2013, est la moindre des choses ? Alors, c'est plus compliqué. Dans ce cas, on décide de préparer les chaînes avant la comparaison, pour les ramener à une forme de référence (en ASCII, un exemple simple de préparation serait de tout mettre en minuscules). Beaucoup de protocoles IETF utilisaient pour cette opération le stringprep du RFC 3454, popularisé par son utilisation dans les noms de domaines internationalisés. Mais la mise à jour de ces noms de domaines, en 2010, a abandonné stringprep (cf. RFC 5890). Dans ces conditions, les autres protocoles se retrouvaient privés d'une référence bien pratique. Le groupe de travail PRECIS a été créé pour étudier la mise en place d'un cadre général de préparation des chaînes Unicode pour tous les protocoles. Ce RFC 6885 est son premier RFC et il décrit le problème, sans proposer encore de solution.
C'est que stringprep avait été un grand succès. Voici une liste incomplète des protocoles qui l'utilisent :
stéphane@dns-oarc.net/Théâtre
est légal),Pour gérer plus facilement ce bestiaire, on peut les regrouper en quelques catégories (voir l'étude de Marc Blanchet), d'autant plus que beaucoup utilisent le même profil SASLprep du RFC 4013. L'annexe A de notre RFC liste ces catégories.
On l'a dit, la motivation immédiate pour le travail du groupe PRECIS était la perte de la référence que constituait les IDN, qui utilisent désormais d'autres méthodes. Puisque, de toute façon, il va falloir remettre à plat cette question de la préparation des identificateurs Unicode, c'était l'occasion de faire un bilan (il a commencé à la réunion IETF 77 dans une Bof nommée « Newprep » dont le compte-rendu est en ligne). La section 4 étudie les profils de stringprep existants et leurs limites :
Bref, c'est sur la base de ce cahier des charges informel qu'a été créé le groupe PRECIS avec l'ambition de servir des protocoles très différents (mais qui ne bénéficiaient pas des compétences d'experts en internationalisation), en s'inspirant (sans forcément le copier aveuglément) de l'IDN bis du RFC 5890 et suivants.
La section 5 de ce RFC est le cahier des charges formel. D'abord, sur la question de la comparaison entre chaînes, un rappel du problème. Il y a trois catégories de chaînes, pour ce qui concerne la comparaison :
Par exemple, deux chaînes Unicode identiques pour la deuxième catégorie (même séquence de points de code) peuvent ne pas l'être pour la première (par exemple si une est en UTF-8 et l'autre en UTF-32). Mais il peut exister un algorithme pour les comparer (tout convertir en UTF-8 puis comparer les octets). Le tableau en annexe A indique, pour les protocoles existants, à quelle catégorie ils appartiennent.
Ensuite, les caractères eux-même, un problème que la taille du bestiaire Unicode (plus de 100 000 caractères) rend difficile. Commençons par la casse. IDN v1 faisait une comparaison indépendante de la casse en convertissant tout en minuscules. IDN v2 a décidé de n'accepter que les minuscules, une éventuelle conversion des majuscules étant à faire en dehors du cadre IDN (RFC 5892). Le système défini par PRECIS doit donc gérer plusieurs cas, avec ou sans sensibilité à la casse, avec ou sans préservation de la casse.
Ensuite, la canonicalisation. Comme il existe plusieurs chaînes Unicode dont le rendu peut être identique (exemple classique : U+00C8, d'une part, et U+0045 U+0300, d'autre part, vont tous les deux donner É), Unicode prévoit des algorithmes de canonicalisation qui réduisent les chaînes de caractères à une forme canonique, avant la comparaison. La plupart des profils de stringprep se servent de NFKC. Est-ce le bon choix ? Dans tous les cas ? NFC peut être une meilleure idée (au fait, dans l'exemple ci-dessus, la chaîne deviendra U+00C8 avec NFC et avec NFKC).
Autre question délicate à considérer, les caractères interdits. Par exemple, un protocole peut avoir des caractères spéciaux comme @ ou / qu'il faudra interdire dans les identificateurs. Faut-il définir les caractères interdits (et autoriser donc le reste) ou au contraire les caractères permis (et donc interdire tous les autres) ?
Cette question est partiellement liée à la question de l'homographie. Ce RFC reprend la légende (pourtant bien démontée par UTR36) comme quoi les caractères pourraient avoir un rôle dans le hameçonnage. Mais il reconnait qu'il n'y a pas de solution technique à cette question.
Autre question sur les données, d'où viennent-elles ? Sont-elles typiquement saisies par un utilisateur (et, dans ce cas, il faut probablement lui laisser un grand choix de variantes possibles) ou bien sont-elles générées par un programme ? Derrière cette question se trouve la frontière oh combien mouvante entre ce qui relève de l'interface utilisateur et ce qui relève des protocoles (voir le RFC 5895 et aussi, même s'il n'est pas cité, le RFC 2277).
Après l'entrée, la sortie de ces chaînes de caractères soulève aussi des questions. Si les caractères sortent du monde « machine » et sont imprimés, pour se retrouver sur une carte de visite ou sur les flancs d'un autobus, les problèmes de risque de confusion visuelle seront plus aigus.
Et il y a le fait que certaines chaînes de caractères servent d'entrée au processus suivant, condensation cryptographique ou concaténation, par exemple.
Dernier problème à garder en mémoire, le risque de changements incompatibles lors de la sortie d'une nouvelle version d'Unicode. Idéalement, un caractère, une fois déclaré valide pour un protocole donné, devrait le rester éternellement, assurant ainsi la stabilité des identificateurs construits avec ce caractère. Mais Unicode ne fournit pas cette garantie (au passage, c'est pour cela que stringprep était lié à une version particulière d'Unicode). Un caractère peut changer de catégorie et, si sa validité était déterminée algorithmiquement à partir de sa catégorie, il peut passer de valide à invalide. Le cas s'est déjà produit (cf. RFC 6452).
La section 6 est ensuite le relevé des décisions (unanimes) concernant le travail du groupe PRECIS :
Date de publication du RFC : Mars 2013
Auteur(s) du RFC : B. Carpenter (Univ. of Auckland), S. Jiang (Huawei)
Pour information
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 8 mars 2013
Ce nouveau RFC sur IPv6 ne spécifie pas un protocole réseau mais rassemble simplement un ensemble de conseils pour les gens qui gèrent des serveurs Internet et qui veulent les rendre accessibles en IPv6. Bien sûr, en 2013, tous les serveurs devraient depuis longtemps être ainsi accessibles. Mais le déploiement d'IPv6 a pris du retard et ce RFC est une des nombreuses tentatives pour tenir la main des retardataires qui hésitent encore à traverser le gué.
Pourquoi faut-il une stratégie de déploiement IPv6 ? Pourquoi ne pas tout simplement se dire « Au diable les mines ! En avant toute ! » ? Parce que l'administrateur typique d'un serveur Internet pense à ses utilisateurs et il veut que l'introduction d'IPv6 ne rende pas les choses moins bonnes qu'en IPv4. Certaines techniques de transition et/ou de coexistence entre IPv4 et IPv6 ayant eu des effets négatifs, il est prudent de réfléchir et de ne pas se lancer aveuglément.
Comme indiqué plus haut, ce RFC ne concerne pas le pur utilisateur qui veut se connecter en IPv6, mais le gérant de serveurs, qui est un professionnel de l'hébergement, ou simplement une organisation qui gère ses propres serveurs (serveurs Web ou autres). Il n'est pas écrit pour l'expert IPv6 (qui n'apprendra rien de nouveau) mais pour l'administrateur système/réseaux de l'hébergeur de serveurs.
La stratégie recommandée par le RFC est celle dite de la « double pile » (RFC 6180), qui consiste à avoir à la fois IPv4 et IPv6 sur les serveurs. Comme on ne va pas déployer IPv6 instantanément partout, elle se subdivise en deux approches : de l'extérieur vers l'intérieur (on rend les serveurs externes accessibles en IPv6, peut-être via un relais comme décrit en section 7, puis on migre progressivement l'infrastructure interne) ou bien de l'intérieur vers l'extérieur (on passe l'infrastructure, les serveurs de base de données, les serveurs LDAP, etc, en IPv6, avant de petit à petit ouvrir IPv6 à l'extérieur). La première approche, de l'extérieur vers l'intérieur, a l'avantage qu'un bénéfice visible pour les utilisateurs est immédiat. Elle marche même si certains services internes sont coincés en IPv4 (par exemple une vieille application tournant sur un vieux système, indispensable à votre activité mais qu'on ne peut pas mettre à jour). Certaines organisations se vantent donc d'être accessibles en IPv6 alors qu'à l'intérieur, le déploiement du nouveau protocole est loin d'être achevé.
La deuxième approche, de l'intérieur vers l'extérieur, est surtout intéressante pour les organisations de petite taille (qui contrôlent tous les systèmes internes) ou récentes (qui n'ont plus d'AS/400 en production, et encore puisque même celui-ci a IPv6). Avec cette approche, l'activation d'IPv6 sur les serveurs externes sera simple, tout sera en place avant.
Le fournisseur de services doit aussi se rappeler qu'il ne contrôle pas les clients. Certains resteront en IPv4 pur pendant longtemps, d'autres seront double-pile et on verra sans doute apparaître bientôt des clients purement IPv6. Certains clients (les mobiles, par exemple) passeront même d'IPv4 à IPv6 au cours d'une seule visite sur le site Web.
Bref, le déploiement d'IPv6 nécessitera quelques études préalables, en vérifiant les capacités du logiciel déployé (cf. RFC 8504).
Maintenant, en route vers le déploiement. Première étape suggérée par le RFC, la formation (section 3). Aujourd'hui, rares sont les formations initiales qui mentionnent IPv6 (en France, la situation dans les IUT semble particulièrement mauvaise). C'est donc souvent dans l'entreprise qu'il faudra former les employés aux différences entre IPv4 et IPv6. Il faut surtout éviter le syndrome de l'expert IPv6 isolé. En 2013, tout professionnel IP doit connaître IPv6 aussi bien qu'IPv4. C'est donc la totalité du personnel informaticien qui va devoir progresser. Le RFC dit « everybody who knows about IPv4 needs to know about IPv6, from network architect to help desk responder ».
Le but est d'éviter des résultats ridicules comme ce réseau où, lors du déploiement d'IPv6, les adresses comportant les chiffres hexadécimaux entre A et F étaient soigneusement évitées, de peur de créer de la confusion chez les techniciens ! Évidemment, si on a des techniciens assez arriérés pour ne pas savoir gérer de l'hexadécimal, on a un problème... Autre anecdote embarrassante, cet employé du help desk qui parlait à un client de « one Pv6 » car il avait cru voir un 1 dans IPv6... L'un des buts de la formation est d'éviter ce genre de bavure.
L'approche du RFC est d'éviter de traiter IPv6 à part, par exemple d'avoir une procédure de remontée des problèmes différente pour IPv6, menant vers l'unique gourou IPv6. Plutôt qu'un « service IPv6 » spécialisé, le RFC recommande qu'IPv6 soit simplement traité comme IPv4.
Dernier point délicat sur la formation, le meilleur moment où la faire. Trop tôt, et elle sera oubliée lorsque le déploiement effectif commencera. Il faut donc essayer de la synchroniser avec le déploiement.
Ensuite, il faut obtenir une connectivité IPv6 (section 4). Elle peut être native (directement sur la couche 2, comme en IPv4) ou via un tunnel géré. Historiquement, bien des expérimentations IPv6 ont été faites en se connectant par un tunnel non géré et les résultats (en performances et en fiabilité) ont découragé beaucoup de gens de continuer avec IPv6. Le RFC recommande très fortement de ne pas perdre de temps avec les tunnels et de faire du natif. Toutefois, si on se connecte via un tunnel, cela doit être un tunnel géré (le RFC ne donne pas de noms mais c'est, par exemple, un service qu'Hurricane Electric offre très bien). Les solutions avec des tunnels automatiques, non gérés, comme 6to4 (que le RFC ne cite pas) sont à fuir.
Un tunnel géré a quand même des défauts : les performances seront inférieures, et la MTU réduite va mener à des problèmes pénibles à déboguer. Bref, le fournisseur de services ne devrait pas utiliser autre chose qu'une connexion native avant d'offrir un accès de production à ses services.
Notez que cela ne concerne que le fournisseur : on ne contrôle pas les clients et il faut donc se préparer à ce que certains utilisent des bricolages non fiables comme Teredo (cf. section 9).
Étape suivante (dans le RFC ; dans le déploiement, on peut paralléliser ces tâches), l'infrastructure IPv6 (section 5). D'abord, l'attribution des adresses. Comme en IPv4, on peut utiliser des adresses PI ou PA, selon ses besoins et selon la politique du RIR local. Si on utilise du PA, il faut se préparer à de futures renumérotations et, pour cela, bien relire le RFC 4192. Naturellement, si le fournisseur de service a hébergé ses services dans le cloud, il n'a pas le choix, il devra suivre la politique de l'hébergeur.
Pour gérer les adresses IPv6 locales, on peut utiliser un logiciel spécialisé, un IPAM. Pour distribuer les adresses aux machines, on peut le faire manuellement ou via un programme qui automatise partiellement la gestion du parc, comme Puppet ou Chef. Mais on peut aussi les distribuer par DHCP (RFC 8415). Le RFC suggère DHCP, car il facilitera une éventuelle renumérotation.
Plus exotique est la possibilité de ne pas avoir d'adresses statiques pour les serveurs mais de compter uniquement sur l'auto-configuration sans état d'IPv6 (SLAAC, RFC 4862), combinée avec des mises à jour dynamiques du DNS (RFC 3007). Dans ce cas, ce sont les noms des serveurs qui sont statiques, pas leurs adresses IP. Le RFC note bien que c'est une possibilité théorique mais que personne n'a encore essayé cela pour un grand réseau de production.
Pour la topologie du réseau (physique, via les câbles, ou logique, via les VLAN), le RFC recommande d'avoir la même topologie en IPv4 et IPv6. Ce n'est pas obligatoire mais cela facilitera grandement le débogage lorsqu'il y aura un problème.
Une fois les adresses attribuées, le routage : tous les protocoles de routage ont la capacité de router IPv6, même RIP (RFC 2080). La méthode la plus courante aujourd'hui est de déployer deux routages parallèles et indépendants, un pour IPv4 et un pour IPv6. Toutefois, deux protocoles de routage, IS-IS (RFC 5308) et OSPF (RFC 5838), ont la capacité de gérer les deux versions de manière intégrée, ce qui peut simplifier la gestion du réseau. (Pour OSPF, c'est encore très peu déployé, la plupart des sites OSPF font tourner deux routages parallèles.) Comme les concepts de routage sont les mêmes en IPv6 et en IPv4, il ne devrait pas y avoir trop de problèmes pour l'équipe qui s'en occupe.
Parmi les points qui risquent d'être différents en IPv6 figurera le cas où un site a plusieurs préfixes PA (un pour chaque fournisseur de connectivité). Il faudra alors soigner le routage pour éviter de faire sortir via le fournisseur A un paquet dont l'adresse source est prise dans le préfixe du fournisseur B : si A met en œuvre les filtrages recommandés par les RFC 2827 et RFC 3704, le paquet sera jeté.
C'est seulement lorsque tout est déployé et testé, au niveau
adressage et routage, qu'on pourra envisager d'annoncer les adresses
IPv6 des serveurs dans le DNS. Ne faites pas
l'erreur d'un gros fournisseur de raccourcisseur
d'URL qui avait fait cette annonce alors que son serveur
ne marchait pas en IPv6 ! Ou comme l'avait fait Yahoo qui avait mis le AAAA sans configurer Apache.Testez donc d'abord (par exemple avec un nom
spécifique comme ipv6.example.com
, comme expliqué
en section 9). Ensuite, mettez les
enregistrements AAAA dans le DNS. Dès qu'ils
seront publiés, le trafic arrivera.
Un équipement souvent placé devant les serveurs est le répartiteur de charge (section 6). Comme tous les intermédiaires, ils sont une source importante de problèmes. Après un long retard, la plupart gèrent aujourd'hui IPv6, mais il est important d'insister auprès des fournisseurs de tels équipements pour qu'IPv6 ait le même niveau de performance qu'IPv4.
Le logiciel sur les serveurs, maintenant (section 8). Dans les systèmes d'exploitation, il n'y a guère de problème, tout fonctionne en IPv6 depuis longtemps. C'est le cas des noyaux mais aussi des « grands » logiciels serveurs comme Apache, NSD ou Postfix. Mais les applications spécifiques, c'est une autre histoire, certaines ne sont pas forcément prêtes. Pour les applications client, le fait d'utiliser des noms de domaines au lieu des adresses IP aide beaucoup. Pour les serveurs, il peut y avoir des surprises, par exemple au moment de journaliser la requête, lorqu'on voudra enregistrer l'adresse IP du client. Des tests soigneux seront nécessaires.
Beaucoup de fournisseurs de service géo-localisent leurs utilisateurs. Dans ce cas, les bases de géo-localisation typiques comme GeoIP n'étant pas forcément prêtes pour IPv6, il y aura des problèmes, à moins de passer à une méthode de géolocalisation plus fiable que celle fondée sur l'adresse IP, par exemple avec la technique HELD du RFC 5985.
Lorsque le client change d'adresse IP (ce qui arrive avec les mobiles), il peut même changer de version d'IP. Si les cookies distribués sont liés à une adresse IP, il faudra en tenir compte.
On l'a vu plus haut, le fournisseur de service ne contrôle pas ses clients. Il peut tout à fait arriver que ceux-ci ont choisi des techniques de transition/coexistence entre IPv4 et IPv6 et que celles-ci soient peu fiables (par exemple Teredo). Avec l'approche recommandée dans ce RFC, la double pile, il n'y aura normalement pas de requêtes venant de NAT64 (RFC 6146). Mais on peut imaginer d'autres problèmes, y compris des doubles traductions, de v6 en v4 puis encore en v6, et que le serveur ne peut pas détecter.
Reste le cas des tunnels automatiques comme le 6to4 du RFC 3068. Le RFC 6343 donne plein de bons conseils pour limiter les dégâts. Les deux points importants, du côté du serveur, sont :
Mais l'hébergeur a un pouvoir limité : il peut vérifier que les paquets ICMP passent bien sur son réseau mais il ne peut rien garantir quant aux autres réseaux traversés. C'est pour cela que 6to4 est désormais abandonné (RFC 7526).
Certains fournisseurs de service ont donc choisi une approche plus violente en configurant leurs serveurs DNS pour ne pas envoyer les enregistrements AAAA au résolveur si celui-ci est dans un réseau dont on sait qu'il a des problèmes, notamment de PMTUd. Encore plus pessimiste, l'approche inverse où on n'envoie les AAAA qu'aux réseaux dont on sait qu'ils ont une connectivité IPv6 native correcte (Google avait utilisé ce mécanisme au début). Cette solution, décrite dans le RFC 6589, est coûteuse en temps (il faut gérer la liste noire ou la liste blanche) et pas tenable sur le long terme.
Malheureusement, les pouvoirs du fournisseur de service s'arrêtent là. Il ne contrôle pas la chaîne complète jusqu'au client et ne peut donc pas garantir à celui-ci un vécu parfait. La voie la plus prometteuse semble être le déploiement progressif du mécanisme happy eyeballs (globes oculaires heureux) du RFC 6555.
Et si le fournisseur de service utilise des CDN (section 10) ? Cela peut marcher, avec IPv6 comme avec IPv4 si le fournisseur du CDN suit, comme celui du serveur principal, les recommandations de ce RFC. À noter que, le CDN étant géré par une organisation différente de celle qui gère le serveur original, on aura parfois, si le CDN est plus avancé, un contenu partiellement accessible en IPv6 alors que le serveur original n'a pas IPv6. Sinon, parmi les pièges spécifiques aux CDN, la synchronisation. Le contenu à servir est distribué à tous les nœuds du CDN via l'Internet et ce processus n'est pas instantané. Comme le contenu n'est pas forcément servi en IPv4 et en IPv6 par les mêmes machines, un visiteur peut avoir, pendant les périodes où la synchronisation est en cours, un contenu différent selon qu'il y accède en v4 ou en v6.
La section 12 rassemble ensuite une liste hétérogène de problèmes potentiels supplémentaires. Par exemple, comme vu plus haut dans le cas du CDN, un service moderne comprend typiquement plusieurs éléments, parfois hébergés à des endroits différents (pensez à une page Web contenant du JavaScript et du Flash stockés sur les serveurs de Google). Dans ce cas, le service peut être partiellement accessible en IPv6 sans même que son gérant ne s'en rende compte. Si le visiteur a des problèmes de connectivité IPv6, les équipes du fournisseur de service risquent de ne pas comprendre tout de suite ce qui se passe en cas d'« IPv6 involontaire ».
C'est donc l'occasion de rappeler (section 13) que le déploiement d'IPv6 n'est pas juste un coup sans lendemain, qu'on pourrait sous-traiter, en « mode projet » : au contraire, il faut assurer la maintenance et le fonctionnement opérationnel dans le futur. Cela n'a rien d'extraordinaire et ne nécessite pas de compétences surhumaines. Il existe des réseaux et des sites en double pile depuis de nombreuses années. Mais il faut le faire.
Un exemple parmi d'autres : il est important d'assurer la supervision aussi bien en IPv6 qu'en IPv4. Cela concerne bien sûr les réseaux (pinguer les adresses IPv6 comme les adresses IPv4) mais aussi les services (si un service a été accidentellement lancé sans écoute en IPv6, il faut que cela soit détecté). À noter que, avec la plupart (peut-être tous) les logiciels de supervision existants, tester des machines ou des services qui écoutent sur plusieurs adresses IP (que celles-ci soient une adresse v4 et une adresse v6 ou bien plusieurs adresses v4) est souvent un peu pénible et pas vraiment prévu. Par exemple, avec Icinga, il faut mettre explicitement deux tests, un en IPv4 et un en IPv6, le programme de test ne testant qu'une seule des adresses du service. Si on ne fait pas attention, on risque donc de se rassurer en voyant l'écran vert du logiciel de supervision, sans avoir perçu que le service ne marchait plus en IPv6 (ou en v4, selon le cas).
Et la sécurité (section 14) ? Elle est évidemment aussi importante en IPv6 qu'en IPv4 mais on manque encore d'expérience. En pratique, début 2013, très peu d'attaques sont lancées en IPv6 (elles bénéficient par contre d'une exposition médiatique démesurée, justement parce qu'elles sont rares). Cela ne durera pas éternellement et les responsables réseaux et systèmes doivent donc se préoccuper de ces risques. En gros, comme IPv6 est uniquement une nouvelle version d'IPv4, fondée sur les mêmes concepts, la quasi-totalité des risques présents en IPv4 (de l'attaque par déni de service aux tentatives de se connecter au serveur SSH) existent en IPv6.
Aujourd'hui, il est difficile de répondre simplement à une question comme « est-ce plus dangereux en IPv6 ? » Comme on l'a vu, il y a beaucoup moins d'attaques. Mais les défenses sont également moins bonnes : il est fréquent qu'une organisation soit protégé par un pare-feu en IPv4 mais que tout le trafic IPv6 passe librement. En fait, aujourd'hui, aussi bien les attaquants que les défenseurs ne prennent guère en compte IPv6. On a donc un équilibre... instable. Sur ce sujet de la sécurité d'IPv6, on peut consulter mon exposé à l'ESGI.
Date de publication du RFC : Février 2013
Auteur(s) du RFC : S. Jiang, B. Liu (Huawei Technologies), B. Carpenter (University of Auckland)
Pour information
Réalisé dans le cadre du groupe de travail IETF 6renum
Première rédaction de cet article le 28 février 2013
Ce RFC ne normalise pas un protocole mais a pour ambition de servir de guide lors de la rénumérotation d'un réseau IPv6. Pourquoi renuméroter ? Et comment ? Les administrateurs réseaux ont tout intérêt à le lire, et de préférence avant la renumérotation et même avant la mise en production du réseau, pour ne pas mettre dans l'architecture de celui-ci des éléments qui gêneront les renumérotations futures.
C'est le deuxième RFC du groupe de travail 6renum qui planche sur les scénarios de renumérotation de réseaux IPv6, ainsi que sur les moyens de rendre ces renumérotations plus faciles. Ce RFC particulier se focalise sur le cas d'une organisation de taille significative : ni un SOHO, ni un opérateur réseau, un client de taille moyenne qui a IPv6 sur son réseau local, une ou plusieurs connexions à l'Internet et au moins un employé chargé d'administrer le réseau (cf. RFC 4057).
La seule façon d'être sûr de ne jamais renuméroter serait de n'utiliser que des adresses PI. Mais, comme le note le RFC 4116, cela aurait des conséquences quantitatives néfastes pour BGP. Donc, on part du principe que l'organisation aura à renuméroter un jour. Lisons les prérequis (RFC 4192 et RFC 5887) et allons-y.
Les machines reçoivent des adresses IP dynamiques (si elles ont des adresses statiques, le problème est plus compliqué, et c'est le domaine du RFC 6866). Pour cela, on utilise DHCP ou les annonces des routeurs (SLAAC).
Mais pourquoi renumérote-t-on ? Pourquoi s'embêter dans cette opération au lieu de se contenter de garder ses adresses actuelles ? La section 3 décrit plusieurs scénarios déclencheurs. Certains peuvent être externes, d'autres internes. Parmi les externes :
Et les causes internes ?
La section 4 décrit ensuite les méthodes existantes pour faire ces renumérotations avec le moins de douleur possible. Parmi les mécanismes qui peuvent aider, il ne faut pas oublier la délégation de préfixe IP (RFC 8415 et RFC 6603), qui permet à un routeur d'informer d'autres routeurs sur les préfixes qu'ils vont devoir gérer (annoncer avec des RA, router, etc). Ainsi, on n'aura pas à reconfigurer tous les routeurs. Autre mécanisme important, l'utilisation de noms de domaine le plus souvent possible, car ils sont plus stables que les adresses IP. Par exemple, pour IPsec, nul besoin de configurer en utilisant des adresses, des noms peuvent être utilisés (RFC 5996), simplifiant ainsi beaucoup les futures renumérotations. (Pour les réseaux sans serveur DNS, le RFC rappelle l'existence de Multicast DNS, RFC 6762.) De même, les applications devraient aussi utiliser des noms et pas des adresses. Configurer une application avec une adresse IP, c'est placer une bombe qui explosera lors de la prochaine renumérotation du réseau.
Mais les adresses IP peuvent se cacher en d'autres endroits, comme dans les ACL des pare-feux. Au minimum, ces configurations devraient être paramétrisées : on n'utilise l'adresse IP qu'une fois, pour lui donner un identificateur, puis on se sert de cet identificateur partout (des outils comme m4 ou cpp peuvent être utilisés pour cela). C'est le B A BA de l'administration réseaux, mais ce n'est pas toujours fait.
Pendant qu'on parle d'adresses IP qui traînent, il ne faut évidemment pas mettre dans ses configurations des adresses IP d'autres sites. Sinon, lorsqu'ils renuméroteront, ils ne penseront sans doute pas à vous prévenir...
Un truc plus exotique est l'utilisation d'ULA, des adresses IP locales (RFC 4193). L'idée est de tout numéroter avec les ULA et d'effectuer une traduction d'adresses ou un relayage dans les routeurs de sortie. Ainsi, la renumérotation n'impacte que ces routeurs. Les ULA sont donc une sorte de substitut aux adresses PI.
Continuons avec les techniques utilisées sur le réseau local :
comment les adresses IP arrivent-elles aux machines terminales ? En
IPv6, il y a deux solutions, SLAAC (RFC 4862) et DHCP (RFC 8415). Ce RFC ne tranche pas entre les deux : du
point de vue de la renumérotation, ils ont à peu près les mêmes
possibilités. (DHCP a une option, RECONFIGURE
qui
permet, si le client DHCP la gère, de faire des renumérotations
imprévues.)
Et le DNS ? Un petit site ne gère pas forcément ses propres serveurs DNS. Leur reconfiguration pourra nécessiter une coordination avec l'hébergeur DNS. Ce que le RFC recommande, c'est de ne pas le faire manuellement. Le fichier de zone édité avec vi et contenant les adresses IP de toutes les machines de l'organisation, c'est un mécanisme archaïque, et, en 2013, on doit normalement mieux faire : soit les données DNS sont dérivées automatiquement d'une base de données de machines (cela n'a pas besoin d'être une usine à gaz, cela peut être un simple script Perl/Python/Ruby), soit les machines (ou les serveurs DHCP) mettent à jour le DNS automatiquement avec les mises à jour dynamiques (RFC 3007).
Une fois qu'on a fait le tour de son réseau et des techniques utilisées, il faut se préparer, et planifier soigneusement. D'abord, diminuer la durée de vie des annonces d'adresses pour que la transition soit la plus courte possible et que les vieilles adresses ne trainent pas dans les caches. Avec l'autoconfiguration sans état (SLAAC), on ne peut pas réduire la durée de vie des annonces à moins de deux heures, il faudra faire avec. D'autre part, cette diminution va évidemment augmenter le trafic et il ne faut donc pas la faire des semaines à l'avance. Une telle durée de vie est stockée dans les enregistrements DNS (qu'il faut donc ajuster), mais aussi dans les annonces indiquant le résolveur DNS à utiliser (RFC 8106 pour SLAAC et RFC 3646 pour DHCP, où il faut réduire la durée du bail, on ne peut pas réduire seulement la durée de vie de l'option DNS). À noter que les applications qui maintiennent des connexions sur de longues périodes (SSH, par exemple), n'ont pas de mécanisme propre pour gérer la renumérotation. Il faudra faire une déconnexion/reconnexion.
Bref, anticiper et planifier sont des nécessités.
Date de publication du RFC : Mars 2013
Auteur(s) du RFC : A. B. Roach (Mozilla)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sipcore
Première rédaction de cet article le 2 mars 2013
Cet ultra-court RFC crée officiellement un
registre pour stocker les valeurs possibles du champ
Priority
du protocole
SIP.
Le RFC 3261, qui normalise le système de
téléphonie sur IP SIP
incluait un champ pour indiquer la priorité d'une communication
(section 20.26 du RFC 3261). Quatre valeurs
possibles étaient définies, non-urgent
,
normal
, urgent
et
emergency
, tout en précisant que d'autres
pourraient l'être mais sans indiquer comment. Ce RFC 6878
comble ce manque.
Il y donc désormais :
Date de publication du RFC : Février 2013
Auteur(s) du RFC : S. Kamei (NTT Communications), T. Momose (Cisco), T. Inoue, T. Nishitani (NTT Communications)
Pour information
Première rédaction de cet article le 23 février 2013
Ce RFC décrit une expérience faite il y a quelques années au Japon pour tester l'efficacité des mécanismes de sélection de pairs dans un réseau pair à pair. Elle montre que cette sélection peut améliorer l'efficacité des protocoles pair à pair, une leçon utile pour le projet ALTO (Application-Layer Traffic Optimization, RFC 5693).
Le réseau pair à pair typique relie des machines, les pairs, qui peuvent être très éloignées les unes des autres. Les relations des machines entre elles ne correspondent pas forcément aux réalités de l'interconnexion. En bref, un pair risque de télécharger des données depuis un pair lointain alors qu'il en existait un plus proche. Des tas de propositions ont été faites pour un mécanisme de sélection des pairs, menant théoriquement à une plus grande efficacité. De 2007 à 2008, au Japon, le P2P Network Experiment Council a réalisé une série de mesures pour comparer théorie et pratique. Une intense répression sous les ordres de l'industrie du divertissement, avec plusieurs arrestations, a réduit l'usage du pair à pair dans ce pays depuis, sans toutefois réussir à le réduire à zéro.
Le Japon est souvent un cas à part et, à l'époque en question, le système de pair à pair le plus populaire n'était pas Bit Torrent mais Winny ou Share. Leur trafic total combiné était estimé à 40 % du trafic total. Pour l'opérateur de réseaux, le pair à pair (P2P) a donc un impact important et cela les motive pour chercher des économies, justement ce que promettent les techniques de sélection du pair. Parmi les autres solutions envisagées par les FAI : faire un effort pour placer le contenu très demandé plus près des utilisateurs (les CDN, par exemple), augmenter les prix, ou limiter autoritairement le trafic.
L'approche choisie par le P2P Network Experiment Council, organisme créé par le gouvernement japonais en 2006, était de tester les solutions de sélection du pair. Pour cela, le conseil a déployé un réseau de serveurs indicatifs (les oracles, selon la terminologie généralement utilisée chez les chercheurs de ce domaine), indépendants d'un système de P2P particulier et donnant des indications sur le meilleur pair.
La section 3 décrit plus en détail ce « conseil pour des expériences P2P ». Créé par le ministère des télécommunications, à la suite de débats sur des sujets comme la neutralité du réseau, il est documenté (en japonais) dans le rapport « Disclosure of the Report `Working Group on P2P Networks' » et placé sous l'égide d'une fondation (oui, encore un texte dans la langue de Naoki Urasawa). Outre les tests qui font l'objet de ce RFC, le conseil a une activité de promotion des bonnes pratiques en matière de P2P.
La section 4 de notre RFC décrit les expériences menées : au début, il n'y avait aucun doute sur les économies en matière de serveurs, lorsqu'on migre vers le pair à pair. Ainsi, l'entreprise Utagoe annonçait une réduction de 90 % de son trafic sortant en migrant vers leur système UGLive. Et TV Bank Corp a vu 80 à 96 % de gain avec BB Broadcast. Mais ce sont des gains pour les fournisseurs de contenu. Et pour les opérateurs réseau ? Il y a eu de études au Japon sur le trafic total (comme celle de Cho, Fukuda, Esaki et Kato). Mais étudier le comportement des applications réellement installées sur les utilisateurs demande des mesures fort intrusives, par exemple avec du DPI.
Le choix du conseil avait donc été d'installer des faux utilisateurs : des PC munis de logiciels P2P modifiés (pour demander à l'oracle) ont été placés dans les réseaux des FAI. On peut ainsi faire varier librement et facilement tous les paramètres de mesure (et, bien que le RFC ne le dise pas, cela évite tout problème lié à la vie privée). Le faux utilisateur est donc un PC avec CentOS, VMware et un Windows par dessus. Le système hôte CentOS peut ainsi observer tout le trafic sans déranger. 60 machines ont été installées chez 40 FAI.
La section 5 décrit l'oracle (hint server), le serveur qui va distribuer les indications. C'est l'équivalent du « serveur ALTO » dans le protocole ALTO (RFC 6708). Lorsqu'un pair démarre, il indique à l'oracle son adresse IP et des informations comme les caractéristiques de la liaison Internet utilisée. L'oracle, en utilisant des informations sur la topologie du réseau informations fournies par le FAI et une table de routage obtenue via BGP (l'oracle inclut un Quagga), peut alors envoyer au pair une table des meilleurs pairs possibles. Dans ce cas idéal, l'optimisation réalisée est presque parfaite. En pratique, l'oracle n'a pas forcément toute l'information nécessaire : le FAI, l'estimant confidentielle, a pu ne pas donner une information complète.
Pour prendre sa décision, l'oracle s'appuie sur :
Voici un exemple simplifié d'une requête d'un pair à l'oracle, et de la réponse de l'oracle. Le tout est transporté sur HTTP et les données sont encodées en couples {type, valeur} :
POST /PeerSelection HTTP/1.1 Host: OracleServerName User-Agent: ClientName Content-Type: text/plain; charset=utf-8 v=Version number ip=IP address of physical interface port=1978 nat=unknown ub=256 db=15000
Vous avez compris que ub
et
db
sont les capacités réseau montant et
descendantes, et que nat
indique (si le pair le
sait), si le pair est coincé ou non derrière un routeur
NAT, qui rend difficile les connexions
entrantes. Et voici la réponse :
HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 v=Version number ttl=ttl client_ip=192.0.2.67 numpeers=11 ...
La section 6 résume les résultats de l'expérience. Soit un pair situé à Tokyo. Sans l'oracle, de 22 à 29 % des pairs sélectionnés étaient déjà dans le même FAI, et de 19 à 23 % dans le même district (il est important de connaître ces valeurs car, si un contenu est peu populaire et ne se trouve pas du tout dans le même FAI que l'utilisateur, aucun oracle au monde ne pourra indiquer un pair proche). Avec l'oracle, la distance moyenne avec le pair a été réduite de 10 %. (Opinion personnelle : le RFC est beaucoup plus détaillé sur la configuration de l'expérience que sur les résultats obtenus, très brefs.)
Les auteurs estiment que ces résultats montrent l'intérêt d'un système de sélection du pair. Quelles conclusions pour le groupe de travail ALTO, qui standardise une technologie analogue ? Que l'information publiquement accessible via BGP est une source utile pour optimiser le trafic entre FAI. Que, pour le trafic interne au FAI, il faut une information détaillée de la topologie du réseau de ce FAI, information qui peut être difficile à obtenir. Que les demandes futures seront peut-être d'avoir une sélection plus précise, nécessitant peut-être une structure hiérarchique dans ALTO (des serveurs ALTO utilisant eux-même d'autres serveurs ALTO). Et qu'il serait bon que l'oracle soit un peu plus bavard sur les mécanismes qu'il a utilisé pour trier les pairs possibles, afin que le pair puisse combiner le jugement de l'oracle avec ses propres critères.
Sur l'évaluation des mécanismes de sélection du pair, voir aussi le RFC 6821.
Date de publication du RFC : Février 2013
Auteur(s) du RFC : B. Carpenter (Univ. of Auckland), S. Cheshire (Apple), R. Hinden (Check Point)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 23 février 2013
Ce court RFC normalise la façon d'indiquer la zone dans un URI contenant une adresse IPv6 littérale.
Les zones sont définies et expliquées dans le RFC 4007. En gros, une adresse IPv6
n'est pas forcément globale, elle peut avoir une signification limitée
à une seule zone, une zone étant un ensemble de sous-réseaux contigus,
souvent composé d'un seul lien Ethernet. Les adresses locales au lien,
par exemple, celles qui sont dans le préfixe
fe80::/10
, sont dans ce cas, le lien qui les
relie forme une zone. Pour indiquer cette zone, la convention de
mettre un %, puis l'identificateur de la zone,
après l'adresse, est fréquemment utilisée. Mais elle n'était pas
normalisée, dans le cas où l'adresse apparaissait dans un
URI. Ce RFC répare ce manque.
Car il peut y avoir des adresses IP littérales dans un URI (section
3.2.2 du RFC 3986). Par exemple,
http://[2001:db8:1::23]/
est un URI valide. (Et
je viens de tester avec mon Firefox qui l'a
accepté sans problèmes.) Mais, si cette adresse est locale à une
zone ? D'habitude, on utilise la convention du
% (décrite en section 11 du RFC 4007). Ici, sur une machine
Linux récente (cela ne marchait pas autrefois, il fallait utiliser l'option -I
) :
% ping6 -c3 fe80::21e:8cff:fe76:29b6%eth0 PING fe80::21e:8cff:fe76:29b6%eth0(fe80::21e:8cff:fe76:29b6) 56 data bytes 64 bytes from fe80::21e:8cff:fe76:29b6: icmp_seq=1 ttl=64 time=8.36 ms 64 bytes from fe80::21e:8cff:fe76:29b6: icmp_seq=2 ttl=64 time=4.97 ms 64 bytes from fe80::21e:8cff:fe76:29b6: icmp_seq=3 ttl=64 time=4.84 ms --- fe80::21e:8cff:fe76:29b6%eth0 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 4.847/6.060/8.363/1.631 ms
On teste la machine fe80:1::23
reliée au réseau
identifié par eth0
(dans le cas de Linux, c'est
le nom d'une interface réseau mais d'autres systèmes d'exploitation
peuvent utiliser une syntaxe différente, par exemple identifier les
zones par un simple numéro). Cette possibilité de désigner une zone
spécifique est essentielle pour les activités de débogage
(M. Toutlemonde n'a sans doute jamais besoin d'URI incluant des
adresses IP). Mais si on
utilise un navigateur Web pour cette activité,
comment mettre la zone ? Le RFC 4007 était muet à ce
sujet. Certains navigateurs (par exemple certaines versions anciennes de
Firefox) acceptaient des adresses suivies d'un
pour-cent (alors que ce caractère est spécial dans les URI et que ces
navigateurs violaient donc le RFC 3986).
Encore mieux, comme le RFC 4007 ne précise pas quels sont les caractères autorisés dans un identificateur de zone, on pourrait voir des zones avec un nom invalide dans un URI (comme / ou #).
La syntaxe standard normalisée par notre RFC est donc :
%25
, ce qui était déjà la méthode déployée par
Internet Explorer),
Pour faciliter la vie de l'administrateur réseaux, notre RFC recommande que les navigateurs
acceptent un URI incluant un % tout nu, s'il est suivi d'au moins deux
caractères qui ne peuvent pas être des chiffres hexadécimaux. Cela permet de
copier-coller une adresse comme
fe80::a%en1
dans le navigateur et que cela
marche. (Par contre, fe80::a%ee1
ne serait pas
accepté car E peut être un chiffre hexadécimal et il y aurait une
ambiguité entre %ee
et î, qui est encodé
ainsi en notation pour-cent.) Cette opération de copier/coller sera
sans doute le principal usage de ces URI comportant une adresse IPv6
et une zone : on ne voit pas bien dans quels cas
ils se retrouveraient dans une page HTML, sauf
peut-être produite automatiquement par des systèmes d'administration
de réseaux (l'interface Web d'un routeur, par
exemple).
Donc, désormais,
http://[fe80::dead:beef%25en1]
ou
http://[fe80::1:2%25Ethernet%230]
sont des URI
légaux (dans le deuxième, le nom de la zone était
Ethernet/0
). Essayez-les sur votre navigateur !
Comme ces identificateurs de zone n'ont de signification que pour une machine donnée, les relais HTTP, par exemple, doivent les retirer des URI.
Voilà, c'est tout, les amateurs d'alternatives peuvent lire l'annexe A, consacrée aux raisons du choix qui a été fait. Il a l'avantage de ne pas changer le format des URI et les inconvénients qu'il n'est pas très joli, et que le copier/coller d'une console vers un navigateur ne marche pas toujours. Les autres possibilités considérées (les discussions ont été chaudes et longues) étaient :
http://[fe80::a-ee1]
(au passage, pourquoi pas un
tiret bas ? parce que les navigateurs
soulignent souvent automatiquement les URI, rendant le trait
invisible). Mais une telle réforme du RFC 4007 aurait
nécessité de changer tous les outils IPv6 et toutes les documentations.IPvFuture
de la
section 3.2.2 du RFC 3986 pour écrire, par
exemple http://[v6.fe80::a-en1]
. Mais cela ne
permettait pas le copier/coller. (Et j'ajoute qu'aucun navigateur ne
gère cette possibilité IPvFuture
.)Date de publication du RFC : Février 2013
Auteur(s) du RFC : G. Salgueiro (Cisco), V. Gurbani (Bell Labs, Alcatel-Lucent), A. B. Roach (Tekelec)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sipclf
Première rédaction de cet article le 15 février 2013
La question d'un format standard et commun pour la journalisation des événements SIP est exposée et discutée dans le RFC 6872. Ce RFC 6873, lui, spécifie un format standard conforme aux exigences et au modèle de données du RFC 6872. Techniquement, sa principale originalité est d'être un format texte... indexé. Il a donc les avantages des formats textes (lisible sans outil particulier, utilisable avec des outils génériques comme grep ou awk) tout en gardant de bonnes performances si on développe des outils qui lisent ces index.