Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Ève

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


RFC 7504: SMTP 521 and 556 Reply Codes

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : J. Klensin
Chemin des normes
Première rédaction de cet article le 1 juillet 2015


Ce RFC enregistre officiellement deux nouveaux codes de retour SMTP (qui étaient déjà largement utilisés), 521 (« I do not accept mail ») et 556 (« The remote domain does not accept mail »). Tous les deux sont prévus pour le cas où un serveur ou un domaine n'acceptent jamais de courrier, en aucune circonstance (par opposition aux codes de rejet plus généraux comme 554).

Petit rappel au passage : les codes de retour SMTP, spécifiés dans la section 4.2 du RFC 5321, ont un premier chiffre qui indique notamment si l'erreur est temporaire (si le premier chiffre est un 4) ou permanente (si le premier chiffre est un 5). Dans le second cas, pas la peine de réessayer plus tard. Ici, le 521 dit bien « ne t'embête pas à revenir, demain, ce sera comme aujourd'hui, je n'accepterai jamais ton message »).

SMTP avait été prévu au début dans un monde où tout le monde acceptait du courrier. Dans les années 1980, toute station de travail Unix venait avec un sendmail activé qui pouvait recevoir des messages. Le paysage aujourd'hui est très différent (section 2 de notre RFC) avec un grand nombre de machines qui ne reçoivent pas de courrier. De même, certains domaines ne sont pas utilisés pour le courrier et il serait pratique de pouvoir indiquer cela à l'avance (RFC 7505).

Dans le premier cas (machine qui ne veut pas recevoir de courrier), le plus simple semble être de ne pas avoir de serveur SMTP du tout. Mais l'impossibilité de se connecter (réponse TCP RST, ou bien timeout, si le pare-feu jette les requêtes TCP) va être interprétée par le client SMTP comme temporaire, et celui-ci va alors réessayer pendant des jours. Si, par la suite d'une erreur de configuration, un client SMTP tente de se connecter à une machine sans serveur, il faudra donc attendre avant de détecter le problème. Avoir un simple serveur SMTP qui ne fait rien d'autre que dire tout de suite « arrête d'insister, ça ne sert à rien » pourrait être plus efficace.

Pour le second cas, le domaine qui n'a pas du tout de service de courrier, le RFC 7505 fournit un moyen simple de l'indiquer dans le DNS, avec le « MX nul ». Il ne manquait qu'un code de retour adapté, pour que le premier relais SMTP de l'utilisateur puisse dire « je ne peux pas envoyer de courrier à ce domaine, ils ne veulent pas ».

Le code 521 est décrit dans la section 3 du RFC. Il est renvoyé au début de la connexion puisqu'il décrit un refus général (pas d'exceptions). Si le refus du courrier est dû à certaines caractéristiques du courrier (par exemple l'emploi de tel émetteur), il ne faut pas utiliser 521 mais plutôt 554. Voici à quoi pourrait ressembler l'accueil d'un serveur SMTP simple, qui ne fait que rejeter imédiatement :

% telnet mail.example.net smtp
Trying 2001:db8:666::1...
Connected to mail.example.net.
Escape character is '^]'.
521 I hate everybody, do not come back
[Connexion fermée]

Le serveur peut clore la connexion immédiatement, ou bien la laisser ouverte et renvoyer des 521 systématiquement. Un message moins pittoresque pourrait être « Server does not accept mail ».

À noter que le code 521 avait déjà été décrit dans le RFC 1846 mais pas normalisé.

La section 4 décrit l'autre code, 556. Le premier code était prévu pour un serveur qui refusait le courrier, le second pour un relais qui essaie d'envoyer au serveur suivant mais découvre que le domaine de destination n'a pas l'intention d'accepter du courrier. Cette découverte se fait typiquement en voyant le « MX nul » du domaine en question (RFC 7505). En faisant une requête MX pour connaître le serveur suivant, le relais peut découvrir que le domaine n'accepte pas de courrier, et il renvoie alors un 556 à son client.

Les deux codes sont désormais enregistrés à l'IANA.


Téléchargez le RFC 7504


L'article seul

RFC 7505: A "Null MX" No Service Resource Record for Domains that Accept No Mail

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : J. Levine (Taughannock Networks), M. Delany (Apple)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 1 juillet 2015


Comment indiquer qu'un domaine ne reçoit jamais de courrier ? Jusqu'à présent, il n'existait pas de mécanisme standard, permettant d'indiquer aux clients de ne pas perdre de temps à essayer d'écrire. Ce nouveau RFC indique une méthode, le « MX nul » qui consiste à mettre un point en partie droite de l'enregistrement MX.

Normalement, un logiciel de messagerie qui veut envoyer du courrier à bob@example.net va chercher dans le DNS l'enregistrement MX du domaine example.net. (Le processus exact est décrit dans le RFC 5321, section 5.1.) A priori, si on ne veut pas recevoir de courrier, il suffit de ne pas mettre d'enregistrement MX, non ? Malheureusement, ce n'est pas le cas : le RFC 5321 précise que, s'il n'y aucun MX, on essaie alors les adresses IP associées au nom (règle dite du « MX implicite »).

Or, il existe des domaines qui ne reçoivent pas de courrier, parce qu'ils sont seulement réservés sans intention d'être utilisés, ou bien parce qu'ils ne servent que pour le Web ou bien encore pour toute autre raison. Si un message tente de parvenir à ces domaines, la machine émettrice va perdre du temps à essayer des MX délibérement invalides (avant la norme de notre RFC 7505, des gens mettaient un MX pointant vers localhost) ou bien des adresses où aucun serveur SMTP n'écoute. Ce n'est pas joli. Et cela peut prendre du temps (lorsque la délivrance échoue, l'émetteur met en attente et réessaie) donc l'utilisateur qui s'est trompé de domaine ne sera prévenu que plusieurs jours plus tard, lorsque le serveur émetteur renoncera enfin.

Au contraire, avec le nouveau « MX nul », dit officiellement No Service MX, le rejet sera immédiat et l'utilisateur, notifié tout de suite, pourra corriger son erreur.

La syntaxe exacte du MX nul figure en section 3. On utilise l'enregistrement MX (RFC 1035, section 3.3.9), avec une partie droite comprenant une préférence égale à zéro et un nom de domaine (exchange, dans la terminologie du RFC 1035) vide (de longueur nulle), ce qui se note, en représentation texte, par un simple point. Voici un exemple :

% dig +short MX  internautique.fr 
0 .

Ce nom ne pouvait pas être un nom de machine légal, il n'y a pas de risque de confusion avec les MX actuels. (Les enregistrements SRV du RFC 2782 utilisent le même truc pour dire qu'il n'y a pas de service disponible à ce nom : « A Target of "." means that the service is decidedly not available at this domain. ».)

La section 4 liste les effets de l'utilisation du MX nul. Comme indiqué plus haut, il permet une réponse immédiate à l'utilisateur, lorsque celui-ci s'est trompé d'adresse (bob@example.net alors qu'il voulait écrire à bob@example.com). L'erreur SMTP à utiliser dans ce cas est 556 (Server does not accept mail, RFC 7504) avec comme code amélioré (codes définis dans le RFC 3643) le nouveau 5.1.10 Domain has null MX.

Le MX nul sert aussi si, par erreur ou par usurpation, un serveur tente d'envoyer du courrier avec une adresse d'émission qui est un domaine à MX nul : le récepteur peut rejeter tout de suite ce message, pour la raison qu'il ne pourrait de toute façon pas lui répondre (ou pas lui envoyer de DSN). C'est ainsi que procèdent beaucoup de serveurs de messagerie avec les adresse d'émission dont le domaine n'existe pas. Dans ce cas, les codes d'erreurs à utiliser sont 550 (mailbox unavailable) avec le code étendu 5.7.27 (Sender address has null MX). (Les nouveaux codes sont dans le registre IANA.)

Notez enfin que ce RFC concerne le cas où on ne reçoit pas de courrier. Si on veut dire qu'on n'en envoie pas, le plus simple est un enregistrement SPF -all.

Tous les hébergeurs DNS ne permettent pas encore de mettre un MX nul. Par exemple, l'un d'eux m'envoie promener « La valeur et/ou la priorité MX est incorrecte ».


Téléchargez le RFC 7505


L'article seul

RFC 7586: Scaling the Address Resolution Protocol for Large Data Centers (SARP)

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : Youval Nachum (Ixia), Linda Dunbar (Huawei), Ilan Yerushalmi, Tal Mizrahi (Marvell)
Expérimental
Première rédaction de cet article le 28 juin 2015


Le problème de passage à l'échelle de protocoles de recherche d'adresse MAC des voisins, les protocoles comme ARP, sont connus depuis un certain temps, et documentés dans le RFC 6820. Résumé en deux mots, dans un grand centre de données non partitionné en sous-réseaux IP, le trafic ARP peut représenter une partie significative du travail à effectuer par les machines. Ce nouveau RFC expose une des solutions pour faire face à ce problème : SARP (Scaling the Address Resolution Protocol) fait appel à des relais ARP qui peuvent générer localement la plupart des réponses.

Si le centre de données est rigoureusement découpé en sous-réseaux IP (par exemple un sous-réseau, et donc un routeur par baie), il n'y a pas de problème ARP : le trafic ARP reste local. Mais si on veut profiter de la souplesse que permet la virtualisation, par exemple en déplaçant des machines virtuelles d'un bout à l'autre du centre de données en gardant leur adresse IP, on doit alors propager les requêtes ARP sur une bien plus grande distance et les problèmes de passage à l'échelle apparaissent (RFC 6820). La mémoire consommée par la FDB (Filtering Data Base, la table des adresses MAC connues) augmente, ainsi que le temps de traitement de tous ces paquets ARP diffusés.

Les premières versions des brouillons ayant mené à ce RFC ne mentionnaient qu'ARP (RFC 826), protocole de résolution IP->MAC pour IPv4. Mais la version finale considère que le protocole marche aussi bien pour ND (RFC 4861), son équivalent pour IPv6. Seul le nom de la solution garde trace de cette préférence pour ARP. Dans le reste de cet article, je parlerais de ARP/ND.

L'idée de base de SARP est que chaque domaine d'accès (un groupe de machines proches, par exemple dans la même baie ou dans la même rangée) ait un relais (SARP proxy) qui connaisse les adresses MAC de tout le domaine, et réponde aux requêtes ARP/ND pour les autres domaines avec sa propre adresse MAC. Ainsi, la taille de la table ARP des machines du domaine reste proportionnelle à la taille du domaine d'accès, pas au nombre total de machines (comme ce serait le cas avec un réseau « plat » classique, entièrement en couche 2, et sans SARP).

Le relais SARP peut être l'hyperviseur d'un groupe de machines virtuelles (commutateur virtuel) ou bien il peut être dans un commutateur physique, ToR (Top of Rack) ou bien EoR (End of Row). En gros, le relais SARP est là où un domaine d'accès se connecte au cœur du réseau interne du centre de données. Ce doit être une grosse machine car elle va devoir stocker les adresses MAC de toutes les machines qui communiquent avec une machine d'un autre domaine d'accès. Et il peut aussi faire l'objet d'attaques délibérées (cf. section 4).

La section 3 de notre RFC décrit plus en détail le fonctionnement de SARP. Si la machine source et la destination sont dans le même domaine d'accès (même baie, ou même rangée, selon l'endroit où se trouve le commutateur), ARP/ND fonctionne comme d'habitude et SARP n'intervient pas. Si la machine de destination est dans un autre sous-réseau IP, on passe alors par le routeur, selon le mécanisme normal de la couche 3. Mais si la destination est dans le même sous-réseau IP, mais dans un domaine d'accès différent ? Le relais SARP voit alors passer la requête ARP/ND. Si la réponse est dans son cache (qui associe des adresses IP à des adresses MAC), il répond avec sa propre adresse MAC (ainsi, les machines du domaine d'accès local ne sont pas noyées par des milliers d'adresses MAC de tout le centre de données). Sinon, il transmet à tous les domaines d'accès qui peuvent avoir cette adresse IP puis relaie la réponse. Seuls les relais SARP ont un cache qui contient des adresses MAC de tout le centre de données. Les machines ordinaires n'ont que les adresses MAC de leur propre domaine d'accès.

Et pour transmettre un paquet de données ? La machine source, ayant reçu l'adresse MAC du relais SARP en réponse à sa requête ARP/ND va donc mettre sur le câble un paquet ayant pour adresse Ethernet de destination le relais SARP. Le relais SARP, utilisant son propre cache (qui, lui, est complet), remplace l'adresse MAC de destination par la « vraie », et l'adresse MAC source par la sienne (pour qu'une réponse puisse revenir), et remet le paquet sur le câble.

Un tel mécanisme fait que des opérations comme la migration d'une VM d'un bout à l'autre du centre de données sont complètement invisibles. Les mécanismes normaux de résolution feront tout le travail. Cela suppose toutefois que la machine qui se déplace (ou plutôt son hyperviseur qui, contrairement à la VM, est conscient du déplacement) émette tout de suite un paquet ARP gratuit ou un paquet ND non sollicité, pour que les caches soient mis à jour (autrement, la machine migrée restera injoignable le temps que l'entrée dans le cache expire).

Une conséquence de cette technique est que le relais SARP est absolument vital : s'il est en panne, plus rien ne marche, à part les communications locales à un domaine d'accès. Il vaut donc mieux en avoir plusieurs, pour chaque domaine d'accès.

Ce RFC n'a que le statut « Expérimental » car l'IESG n'est pas convaincue que ce soit la seule méthode. Le RFC 7342 liste un certain nombre d'autres techniques (pas forcément directement comparables à SARP). À noter que les approches de type overlay (RFC 7364) résolvent une partie du problème mais pas la question de la taille de la table des adresses MAC. Mais il y a les RFC 4664, RFC 925, RFC 4389 (ces deux derniers sont, à mon avis, proches de SARP), RFC 4541 et RFC 6575...


Téléchargez le RFC 7586


L'article seul

Dépanner un Raspberry Pi utilisé comme serveur

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


Parmi les joies de l'administration système, il y a le dépannage d'un serveur headless (sans console physique, ni écran ni clavier), lorsque ce dernier ne veut pas redémarrer. Comment faire sur un Raspberry Pi ?

(Si vous ne connaissez pas le Pi, il y a aussi un de mes articles.) Si le Pi est habituellement connecté à une télévision et à un clavier, on voit le processus de démarrage du système et on peut intervenir. Mais c'est plus facile à dire qu'à faire, car un Pi qui ne démarre pas et qui dit juste :

Requested init /bin/systemd failed (error -2)
kbd>

a de quoi laisser perplexe même l'administrateur système Unix expérimenté. Ce problème m'est arrivé avant-hier après une mise à jour d'Arch Linux. Ce système, en raison de ses rolling releases est évidemment plus vulnérable à ce genre de problèmes qu'un système très stable comme Debian, mais aucun système n'est 100 % à l'abri. Un jour ou l'autre, on se retrouve avec uniquement la diode rouge et le Pi qui n'est plus joignable en SSH.

Les gros serveurs dans les centres de données ont des cartes d'accès à distance comme les DRAC de Dell. Mais le Pi, très bon marché, n'a rien de tel. Brancher une télé, avec le câble HDMI, permet d'avoir au moins le message d'erreur. Curieusement, la plupart des articles qu'on trouve avec DuckDuckGo indiquent des méthodes compliquées pour réparer, avec des commandes tapées au clavier du Pi défaillant. Mais je trouve qu'il y a bien plus simple.

La méthode que j'ai utilisé la plupart du temps est simplement d'éteindre le Pi, de prendre la carte SD et de la mettre dans un PC Linux où on pourra réparer tranquillement. Bien sûr, cela nécessite d'avoir un PC sous la main mais je suppose que peu de gens ont un Pi sans aucun autre ordinateur.

Une fois la carte SD montée sur la machine Linux, on a alors un environnement Unix complet pour investiguer, et réparer. Cela va bien plus vite.

Et quel était le problème dans le cas cité plus haut ? Au cours de la mise à jour, Arch Linux avait mis dans les instructions de démarrage init=/bin/systemd alors que systemd était dans /lib/systemd. init est le premier programme en mode utilisateur qui est lancé par le noyau Linux du Pi, et l'erreur -2 voulait simplement dire qu'il n'était pas trouvé. Sur la carte SD montée sur un PC de secours, un ln -s /lib/systemd/systemd /bin a suffit à réparer, en mettant un lien symbolique depuis le nom utilisé vers le « vrai » nom. Une autre solution aurait évidemment été d'éditer le cmdline.txt (qui se trouve dans l'autre partition de la carte SD, la première, celle formatée en VFAT), et de remplacer init=/bin/systemd par init=/lib/systemd/systemd.


L'article seul

Fiche de lecture : La boîte à outils de la créativité

Auteur(s) du livre : Edward de Bono
Éditeur : Eyrolles
978-2-212-55658-2
Publié en 2004
Première rédaction de cet article le 27 juin 2015


C'est l'année dernière à Paris-Web que j'avais reçu ce livre. Après chaque conférence, l'orateur choisissait une personne du public qui avait posé une question particulièrement pertinente, et c'était moi (je suis désolé, j'ai oublié la question que j'avais posé). Mais je ne suis pas sûr que le choix des livres ait toujours été pertinent...

Ceci dit, sans Paris-Web, je n'aurais jamais pensé à lire ce livre. C'est un de ces ouvrages de consultant, écrit par un gourou qui passe son temps à expliquer à des gens comment être plus... efficace, productif, créatif, même. Je suis toujours surpris qu'on se moque des peuples premiers qui ont des sorciers pour faire venir la pluie ou faire en sorte que la chasse soit favorable, mais que des entreprises par ailleurs souvent sérieuses dépensent des sommes importantes pour payer ces gourous dont la seule compétence est le talent à faire croire qu'ils servent à quelque chose. À chaque fois, ils me font penser au sorcier Shadok à qui un sceptique reprochait de ne pas faire de miracles et qui répondait « 25 ans que je fais se lever le soleil tous les matins : pas un échec ». De nos jours, dans les pays riches du monde, on ne croit plus aux sorciers ou aux prêtres mais on n'est pas devenu plus intelligent pour autant : on croit aux gourous.

Pourtant, celui-ci fait des efforts pour qu'on évite de le prendre au sérieux. Il utilise plein d'exemples enfantins et j'ai du mal à croire qu'une assemblée de cadres supérieurs et de dirigeants, dans un grand hôtel international, ait pu suivre sans rire ses exercices de pseudo-psychologie avec les chapeaux jaunes et les chapeaux noirs...

Ce gourou est tellement convaincu de son importance qu'il n'a pas peur de lasser la patience de ses lecteurs avec ses diatribes contre les méchants plagiaires qui lui piquent ses remarquables idées (il y a vraiment des gourous secondaires, qui utilisent les chapeaux jaunes et les chapeaux noirs sans payer de droits d'auteurs ?) Pas une seconde, il ne se demande si celui qui a acheté (ou, dans mon cas, reçu) son livre n'a pas autre chose à faire que de lire ses plaintes.

Et, puisqu'on parle de fric et de droits, il est également significatif que de Bono parle pendant 450 pages de méthodes pour augmenter la « créativité » sans jamais s'interroger sur le but, sur le pourquoi. On rassemble des gens devant le gourou, il les fait travailler avec des exercices de l'école maternelle, mais jamais il ne les laisse ébrécher le tabou : on peut discuter des moyens pour atteindre le but (vendre plus de voitures, ou plus de hamburgers) mais jamais du but lui-même...

Preuve de son efficacité de vendeur, la page du Wikipédia francophone qui lui est consacrée est un article publicitaire « Ses techniques sont relativement simples d'usage et d'une bonne efficacité pratique » (le Wikipédia anglophone est plus prudent). Bref, une brochure commerciale pour ses activités de consultant, mais certainement pas un livre.


L'article seul

RFC 7568: Deprecating Secure Sockets Layer Version 3.0

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : R. Barnes, M. Thomson (Mozilla), A. Pironti (INRIA), A. Langley (Google)
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 26 juin 2015


Ce nouveau RFC formalise un point déjà bien connu des experts en sécurité : le dernier survivant de la famille SSL, SSL version 3, a de graves failles et ne doit pas être utilisé.

Il y a bien longtemps que SSL est dépassé, remplacé par TLS (même si des ignorants continuent de parler de SSL dès qu'ils voient un petit cadenas sur leur navigateur Web). Mais les vieux protocoles ne meurent pas facilement sur l'Internet. Manque de ressources humaines qualifiées, absence d'intérêt pour la sécurité, blocage par la direction financière qui demande quel est le ROI, des tas de raisons font que pas mal de serveurs acceptent encore le SSL v3. Celui-ci, décrit dans le RFC 6101 (mais qui avait été défini et déployé bien avant, en 1996, le RFC 6101 ne faisant que documenter longtemps après), devrait pourtant être abandonné définitivement, ne laissant que TLS (dont la version actuelle est la 1.2, en RFC 5246).

La première fin de SSL v3 était en 1999, avec la sortie de TLS, dans le RFC 2246. Le fait que SSL v3 soit toujours bien vivant aujourd'hui, plus de quinze ans après, donne une idée de l'ossification de l'Internet et du manque de réactivité des techniciens.

La section 3 de notre RFC résume la bonne pratique actuelle : NE PAS UTILISER SSL v3. Les clients ne doivent pas le proposer dans le ClientHello, ni les serveurs dans leur ServerHello.

Bien plus longue, la section 4 décrit pourquoi SSL v3 est cassé sans espoir de réparation. Première raison, qui a permis la faille POODLE (cf. un bon article d'explication pour tous), c'est que le remplissage en mode CBC n'est pas spécifié (et donc pas vérifiable par le pair). Autre faille, SSL v3 fait forcément du MAC-then-encrypt, ce qui est aujourd'hui considéré comme dangereux. TLS fait aussi du MAC-then-encrypt par défaut mais on peut le changer (RFC 7366) grâce aux extensions. Or, SSL v3 n'a pas la notion d'extensions.

Les algorithmes de chiffrement stream de SSL v3 ont tous des défauts sérieux, par exemple RC4 est désormais officiellement abandonné (RFC 7465). Question condensation, ce n'est pas mieux, certaines opérations de SSL v3 imposant MD5 (RFC 1321, abandonné par le RFC 6151).

L'échange de clés dans SSL v3 a aussi des failles permettant à un homme du milieu de se placer. Corrigées dans TLS par des extensions, elles ne sont pas corrigeables en SSL v3.

Toujours en raison de son manque d'extensibilité, SSL v3 ne peut pas avoir certaines des nouvelles fonctions développées depuis sa naissance. Pas d'algorithmes dans les modes AEAD (RFC 5246, section 6), pas de courbes elliptiques (RFC 4492), pas de reprise d'une session existante sans état sur le serveur (RFC 5077), pas de mode datagramme pour UDP (RFC 6347), pas de négociation de l'application utilisée (RFC 7301).

Comme le notait le texte d'accompagnement à l'IESG, où on doit indiquer les mises en œuvre du protocole, « Are there existing implementations of the protocol? Yes, and that's the problem;-) ». Ceci dit, une bonne partie des déploiements de TLS ont commencé à supprimer SSL v3. Logiquement, il devrait être retiré du code des bibliothèques TLS (alors que, encore aujourd'hui, la page d'accueil de GnuTLS se vante de gérer SSL v3). Espérons que ce RFC, qui n'apporte aucune information technique nouvelle, par son côté « officiel », contribue à faire bouger les choses.

Pour déterminer si un serveur accepte SSL v3, on peut utiliser le client d'OpenSSL :

% openssl s_client -connect www.bortzmeyer.org:443 -ssl3 
CONNECTED(00000003)
depth=0 CN = www.bortzmeyer.org
...
SSL handshake has read 2276 bytes and written 470 bytes
...
SSL-Session:
    Protocol  : SSLv3
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 8B815B79611AB6FB105E84AA3159A0E57D50BA61BEE33478BB5DFEAFD5E4979B

Ici, le serveur a accepté SSL v3 (handshake terminé, algorithme de chiffrement - DHE-RSA-AES256-SHA - sélectionné alors qu'on a forcé SSL v3). Si vous voulez savoir pourquoi ce serveur particulier accepte malheureusement SSL v3, voir à la fin de cet article.

Avec un qui n'a pas SSL v3, on voit :

% openssl s_client -connect www.example.net:443 -ssl3
CONNECTED(00000003)
3073382076:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:s3_pkt.c:348:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 5 bytes and written 7 bytes
---
...
SSL-Session:
    Protocol  : SSLv3
    Cipher    : 0000
    Session-ID: 

Les messages d'OpenSSL, comme toujours, sont peu clairs, mais on peut voir que le handshake n'a pas abouti (très peu de données transmises), qu'aucun algorithme de chiffrement n'a été choisi et qu'aucune session n'a commencé (ID vide). Ce serveur est donc correct.

Notez que l'administrateur système est dépendant des logiciels utilisés et qu'il ne peut pas tout reprogrammer lui-même. Ainsi, GnuTLS a un module Apache, mod_gnutls, qui a une très sérieuse bogue (ancienne et jamais réparée) qui fait que SSLv3 n'est pas interdit, même quand la configuration le demande. Personnellement, je vais arrêter d'utiliser GnuTLS sur mes sites Web, pas à cause de la bibliothèque elle-même, qui est excellente, mais à cause de ce module Apache pas maintenu.


Téléchargez le RFC 7568


L'article seul

RFC 7590: Use of Transport Layer Security (TLS) in the Extensible Messaging and Presence Protocol (XMPP)

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : P. Saint-Andre (&yet), T. Alkemade
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF uta
Première rédaction de cet article le 25 juin 2015


Le groupe de travail UTA de l'IETF produit des recommandations pour un usage correct de TLS par les applications. En effet, indépendamment des forces et faiblesses propres de TLS, plusieurs problèmes de sécurité sont survenues en raison d'une mauvaise utilisation. Ce nouveau RFC traite le cas spécifique de l'utilisation de TLS par le protocole XMPP.

Les problèmes généraux identifiés par le groupe UTA avaient été documentés dans le RFC 7457 et les solutions généralistes, applicables à toutes les applications, dans le RFC 7525. Et pour le protocole XMPP, normalisé dans le RFC 6120 ? XMPP utilise TLS depuis au moins 1999. Les sections 5, 9 et 13 du RFC 6120 expliquent déjà comment faire du TLS avec XMPP. Mais notre nouveau RFC va plus loin et, dans l'esprit du manifeste XMPP/TLS , décide que XMPP doit suivre les recommandations plus strictes du RFC 7525, notamment concernant le choix des algorithmes de chiffrement.

La section 3 du RFC répète les recommandations du RFC 7525, que doivent désormais suivre les mises en œuvre de XMPP, notamment :

  • Toute mise en œuvre de XMPP doit avoir l'option <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/> qui indique qu'elle est prête à démarrer TLS (RFC 6120, section 5.4.1 et quelques autres). Mais, comme cette option n'est pas elle-même protégée par TLS, elle peut être supprimée par un homme du milieu (attaque dite de stripping, RFC 7457, section 2.1). XMPP doit donc tenter de faire du TLS avec son partenaire, que cette option soit présente ou pas (le manifeste cité plus haut impose TLS, de toute façon).
  • La compression TLS étant désormais rejetée (RFC 7525, section 3.3), XMPP peut se rabattre sur la compression XMPP du XEP-0138.
  • XMPP a un mécanisme de reprise rapide des sessions (XEP-0198), on peut encore l'améliorer en le couplant avec la reprise de sessions de TLS.
  • En théorie (RFC 6125), un client XMPP devrait authentifier le serveur (et, de préférence, le serveur authentifier les autres serveurs). En pratique, ce n'est pas toujours le cas (avec Pidgin, un certificat à problèmes est signalé mais un seul clic suffit à l'accepter). Une des raisons pour lesquelles on ne peut pas imposer immédiatement une authentification généralisée est que les serveurs XMPP sont souvent hébergés dans un environnement multi-clients, chaque client hébergé ayant son propre nom de domaine et qu'un tel serveur devrait donc avoir un certificat pour chaque client, ou un certificat couvrant tous les clients. DANE résoudra peut-être le problème. En attendant, le RFC recommande fortement de préférer une connexion chiffrée et non authentifiée à une connexion en clair (se replier sur du trafic en clair parce que le certificat est invalide est absurde, mais courant). C'est par exemple ce que recommande le RFC 5386 pour le cas d'IPsec. Bref, « TLS tout le temps, authentification si possible » est le principe.
  • SNI (Server Name Indication, RFC 6066, section 3) est inutile en XMPP, l'attribut to suffit à indiquer le domaine concerné (l'attribut to envoyé avant TLS n'indique que le domaine, pas le destinataire).
  • En sécurité, il est bien connu que le point faible est l'utilisateur humain. La section 3.6 fait donc des recommandations pour les développeurs d'interface utilisateur : indiquer si la connexion avec le serveur est chiffrée par TLS, indiquer si l'authentification a réussi et, si oui, comment, permettre d'afficher l'algorithme de chiffrement utilisé et le certificat présenté, être averti si un certificat change (ce qu'on nomme parfois l'épinglage - pinning). Je viens de tester avec un Pidgin 2.10.10 et la seule de ces recommandations qui semble mise en œuvre est la possibilité d'afficher les certificats (menu Tools -> Certificates).

La section 5 rappelle que XMPP sur TLS chiffre aussi les informations de routage (contrairement à SMTP) et limite donc les fuites de méta-données. Elle revient aussi sur quelques limites de TLS : XMPP passe par plusieurs serveurs et, si ceux-ci sont piratés ou indiscrets, le chiffrement TLS, qui n'est pas de bout en bout, ne protège pas contre ceux qui ont le contrôle des serveurs. En termes moins gentils, si vous utilisez Google Talk, le chiffrement TLS avec Google Talk (qui marche bien) ne vous protège pas de PRISM. (À noter que notre RFC ne cite pas la solution de bout-en-bout OTR, qui existe mais est mal intégrée à XMPP.)

Je n'ai pas trouvé de liste de toutes les implémentations XMPP, avec leur degré de conformité à ce RFC.


Téléchargez le RFC 7590


L'article seul

RFC 7595: Guidelines and Registration Procedures for URI Schemes

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : D. Thaler (Microsoft), T. Hansen (AT&T Laboratories), T. Hardie (Google), L. Masinter (Adobe)
Réalisé dans le cadre du groupe de travail IETF appsawg
Première rédaction de cet article le 24 juin 2015


Ce n'est pas tous les jours qu'on enregistre un plan d'URI (le plan - scheme en anglais - est le premier composant d'un URI, la partie avant le premier deux-points). Ils sont peu nombreux et on voit rarement autre chose que le fameux http:. Mais, si jamais vous voulez ajouter un plan à la liste existante, ce RFC vous explique les règles d'enregistrement. Il remplace le RFC 4395.

Les plans d'URI sont normalisés dans le RFC 3986, section 3.1. Le plan est souvent appelé à tort « protocole » alors que, dans la grande majorité des cas, il n'a aucun rapport avec un protocole (voir la section 3.8 de notre RFC), et, même quand le nom du plan est celui d'un protocole (comme http:), il n'implique pas l'utilisation de ce protocole (un URI ne sert pas forcément à accéder à une ressource). Il existe de nombreux plans, du très connu http: au moins fréquent tag: (RFC 4151) en passant par bien d'autres, souvent assez confidentiels comme le acct: du RFC 7565 ou le dict: du RFC 2229. La liste des plans enregistrés se trouve à l'IANA. Le RFC 3986 décrit seulement la syntaxe générique des URI, celle commune à tous les URI et qui se limite largement à « un plan, deux points, puis du texte » (par exemple, http://www.bortzmeyer.org/608.html ou tag:bortzmeyer.org,2006-02:Blog/608). La grande majorité du contenu de l'URI a une syntaxe et une signification qui dépendent du plan et un logiciel d'usage très général doit donc connaître ces plans et leurs particularités.

Il existe un registre des plans, qui permet aux développeurs de ces applications de trouver tous les plans en un endroit, et de limiter le risque de collision. La politique d'enregistrement est déliberement assez libérale pour éviter la prolifération de plans non-enregistrés.

Petite note d'internationalisation au passage : les plans sont les mêmes pour les URI (qui doivent s'écrire uniquement en ASCII) et les IRI du RFC 3987, qui peuvent utiliser Unicode (ce n'était pas clair dans le RFC précédent, le RFC 4395).

En section 3 de notre RFC, les règles à suivre. D'abord, la syntaxe générale des URI doit être respectée (ce qui est facile, elle est très générale). Par exemple, l'identificateur de fragment (ce qui suit le croisillon, cf. RFC 3986, section 3.5), garde la même sémantique (notamment le fait qu'il n'est utilisé que par le client, pas par le serveur Web), un nouveau plan d'URI ne peut pas utiliser cette syntaxe pour exprimer autre chose.

Est-ce que le nouveau plan d'URI est une bonne idée ? Pour que son enregistrement soit accepté, le plan doit présenter une utilité à long terme, répond la section 3.1. Cette restriction est justifiée par le fait que tout nouveau plan peut nécessiter une modification de tous les logiciels qui traitent des URI et agissent différemment selon le plan. Et le Web contient autre chose que des clients et serveurs, il y a les relais, les caches, etc. (Le RFC note également que, bien que l'espace de nommage des plans soit infini, en pratique, il pourrait y avoir une concurrence trop forte pour les noms courts et facilement mémorisables et que cela justifie donc de ne pas accepter toutes les candidatures.)

Il y a aussi des contraintes plus techniques. La définition d'un nouveau plan doit décrire la syntaxe de l'URI (rappelez-vous que la syntaxe générale des URI ne couvre qu'une petite partie des règles). La section 3.2 impose que le nouveau plan respecte les règles syntaxiques existantes. Par exemple le // a une signification bien précise dans un URI, il précède le nom de la machine qui sert d'autorité de nommage, pour attribuer le reste de l'URI (section 3.2 du RFC 3986). En l'absence d'une telle machine de référence, le // ne doit donc pas être utilisé. (c'est pour cela que dict://dict.example.org/d:chocolate: a un //, car il contient le nom d'un serveur, ici dict.example.org alors que mailto:echo@generic-nic.net n'en a pas, car les adresses de courrier sont globales, elles ne dépendent pas d'un serveur particulier). D'une manière générale, notre RFC déconseille l'utilisation de la barre oblique, sauf si on accepte des URI relatifs, pour éviter qu'un logiciel trop zélé n'ajoute en prime un traitement spécial pour . ou .. (souvent interprétés pour dire « ce niveau » ou « le niveau supérieur »).

Il faut bien sûr que le plan soit correctement et complètement défini (sections 3.3 à 3.5). Par exemple, si l'URI est résolvable, sa description doit expliquer comment. Autre exemple, la description doit expliquer ce qu'on peut faire de l'URI. Accéder (et parfois modifier) à une ressource (cas du http:) ? À une machine (cas de telnet:, où le modèle « accès à une ressource » ne s'applique pas) ? S'il existe une opération par défaut (« je lance mon navigateur Web sur example:foo-bar-42, que fait-il ? », elle doit être sûre, au sens où elle ne doit pas avoir d'effets de bord. Enfin, le cas des URI qui servent juste à faire correspondre à un identificateur non-URI est normalement plus simple, avec une définition assez évidente. C'est le cas par exemple des mid: du RFC 2392, qui transforment un Message-ID: du courrier électronique en URI.

On a parlé plus haut des IRI. La section 3.6 nous rappelle les principes d'internationalisation des URI, et donne des bons conseils (faire bien attention à ne pas autoriser plusieurs représentations d'un même caractère, cf. RFC 3986, section 2.5). Le RFC donne aussi de mauvais conseils comme de prétendre (sans donner un seul exemple) qu'il faut restreindre le plus possible le jeu de caractères autorisé, certains caractères étant « dangereux ».

Pendant qu'on parle de danger, la section 3.7 rappelle la nécessité de bien documenter les questions de sécurité et de vie privée liées au nouveau plan. C'est une des nouveautés par rapport à l'ancien RFC 4395 que cette mention de la vie privée. Cela reflète l'importance croissante accordée à ce problème à l'IETF : de nombreux RFC mentionnent désormais la vie privée et pas seulement la sécurité informatique traditionnelle.

Enfin, le plan doit recevoir un nom (section 3.8), qui soit à la fois assez court pour être pratique et assez long pour être descriptif (et ce nom doit suivre la syntaxe de la section 3.1 du RFC 3986 qui limite notamment à ASCII, même pour des IRI). Pire, comme ces plans sont visibles (des URI sont souvent affichés dans les publications, sur les cartes de visite, sur les publicités), le nom du plan ne doit pas interférer avec des marques déposées défendues par des bataillons d'avocats. Il vaut donc mieux ne pas essayer de normaliser le plan coca-cola: (qui permettrait d'écrire des choses utiles comme coca-cola:light)... Le RFC recommande aussi d'éviter des noms trop marketing comme tout ce qui contient « universal » ou « standard ».

Pour les plans privés, spécifiques à une organisation et non enregistrés, notre RFC recommande d'utiliser un nom de domaine inversé comme préfixe, afin de limiter les risques de collisions (sections 3.8 et 6). Si la société Example, titulaire du domaine example.com, veut un plan pour son système Foobar, elle utilisera donc com.example.foobar: comme plan d'URI. Cela évite toute collision avec une autre société qui aurait un Foobar. (Le RFC 4395 recommandait un tiret au lieu d'un point dans ce nom inversé.)

Ces règles de la section 3 sont obligatoires pour les plans enregistrés de manière permanente. Mais le registre contient aussi des plans enregistrés à titre provisoire et les règles en question ne sont qu'indicatives pour eux (section 4). Les enregistrements provisoires sont soumis à une politique plus libérale, « premier arrivé, premier servi ». Cela permet de demander que les plans privés soient, s'ils ne sont pas fabriqués à partir d'un nom de domaine comme l'exemple précédent, enregistrés de manière provisoire. Parmi les plans provisoires, au moment de cet article, bitcoin:, dtn: (cf. RFC 5050), etc.

Notez que, dans le registre des plans d'URI, outre les caractéristiques « permanent » et « provisoire », il y a aussi « historique » qui désigne les plans abandonnés (comme le fax: du RFC 2806).

Bref, une fois qu'on a bien lu toutes ces considérations, on peut passer à l'enregistrement proprement dit. Pour cela, il faut suivre la procédure exposée en section 7 (qui utilise les termes du RFC 5226 comme « examen par un expert » ou « premier arrivé, premier servi »). On remplit un formulaire (section 7.4 pour un formulaire vierge), il est examiné (dans la plupart des cas) sur une liste de diffusion comme uri-review@ietf.org, puis par un expert (section 7.2).

Une éventuelle mise à jour d'un enregistrement se fait par le même mécanisme (section 7.3).

Une des nouveautés de notre RFC, par rapport à son prédécesseur RFC 4395, est la création d'un plan d'URI qui sert à la documentation (dans l'esprit du RFC 5398 pour les numéros d'AS et RFC 2606 pour les noms de domaine). Si vous voyez un URI qui commence par example:, c'est... un exemple. Imaginons une base de données qui stocke des URI et qu'on montre un exemple d'export de cette base en JSON, on est sûr de ne pas entrer en conflit avec un vrai URI, et on n'a pas trop à se soucier de la syntaxe (le plan example: autorise tout), en utilisant ce plan :

{"uris":
   {"date": "2014-09-02 09:58:23+00:00",
    "uri": "example:do-some-thing#test"},
   {"date": "2015-06-24 16:11:09+00:00",
    "uri": "example:foo.bar"},
   ...
}

Le formulaire d'enregistrement de ce plan figure dans la section 8 de notre RFC, si vous envisagez d'enregistrer un plan et que vous voulez un exemple. Si vous voulez un vrai exemple récent, vous pouvez regarder la section 7 du RFC 7565, qui enregistrait acct:. (Pour les enregistrements provisoires, la demande est indiquée à partir du registre IANA.)

L'annexe A de notre RFC liste les changements qui se sont produits depuis le RFC 4395. Les plus importants, à mon avis, sont :

  • Fusion des registres permanent et provisoire en un seul registre, avec une colonne Status,
  • Libéralisation de l'enregistrement des plans provisoires (cf. RFC 5226), de « Examen par un expert » à « Premier arrivé, premier servi » (les plans permanents restent à « Examen par un expert »),
  • Ajout du plan example:,
  • Changement des conventions pour les préfixes des plans privés non enregistrés (point au lieu du tiret entre les composants du nom de domaine),
  • Diverses clarifications, par exemple sur le fait que tout plan d'URI s'aapplique aux IRI aussi bien qu'aux URI,
  • Ajout de la vie privée aux considérations sur la sécurité.

Il y avait eu d'autres idées pendant le développement de ce RFC, mais toutes n'ont pas été retenues. Par exemple, à l'IETF 90, nous avions discuté de faire des plans avec préfixes (coap+ws:, coap+sms:, etc, au lieu du simple coap: du RFC 7252), par analogie avec les types MIME structurés du RFC 6839.


Téléchargez le RFC 7595


L'article seul

Version 8 d'Unicode

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


Le 17 juin a vu la sortie d'une nouvelle version du jeu de caractères Unicode, la 8.0, pile un an après la précédente. On peut trouver une description des principaux changements en http://www.unicode.org/versions/Unicode8.0.0/ mais voici ceux qui m'ont intéressé particulièrement. (Il n'y a pas de changement radical.)

Pour explorer plus facilement la grande base Unicode, j'utilise un programme qui la convertit en SQL et permet ensuite de faire des analyses variées. Faisons quelques requêtes SQL :

ucd=> SELECT count(*) AS Total FROM Characters;
 total  
--------
 120737

Plus de 120 000 caractères. Lesquels ont été apportés par la version 8 ?


ucd=> SELECT version,count(version) FROM Characters GROUP BY version ORDER BY version;
...
 7.0     |  2834
 8.0     |  7716

7 716 nouveaux. Lesquels ?

ucd=> SELECT To_U(codepoint) AS Codepoint, name FROM Characters WHERE version='8.0';
 codepoint |                                    name                                    
-----------+----------------------------------------------------------------------------
...
 U+8B4     | ARABIC LETTER KAF WITH DOT BELOW
...
 U+13FB    | CHEROKEE SMALL LETTER YU
...
 U+11294   | MULTANI LETTER DDHA
...
 U+12488   | CUNEIFORM SIGN DA TIMES TAK4
...
 U+1D96D   | SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING WRIST FLEX
...
 U+1F32F   | BURRITO
 ...
 U+1F3FF   | EMOJI MODIFIER FITZPATRICK TYPE-6
 ...
 U+1F54C   | MOSQUE
 U+1F54D   | SYNAGOGUE
...

Comme on le voit, c'est varié. On trouve des écritures entièrement nouvelles comme le multani ou le système Sutton pour la langue des signes, des nouvelles lettres pour des écritures existantes (le « ARABIC LETTER KAF WITH DOT BELOW » est ajouté à l'alphabet arabe pour écrire des langues de l'Asie du Sud-Est), des nouveaux emojis (comme le burrito)... L'alphabet cherokee a connu un grand changement, il est désormais bicaméral et les minuscules du Cherokee viennent donc s'ajouter à Unicode (comme la U+13FB ci-dessus). Par contre, comme il ne s'est écrit qu'en majuscules pendant longtemps, l'algorithme d'uniformimisation de casse d'Unicode met le Cherokee en majuscules, et pas en minuscules comme pour toutes les autres écritures.

Si vous avez les bonnes polices de caractères, voici les caractères pris en exemple plus haut : ࢴ, ᏻ, 𑊔 𒒈, 𝥭, 🌯, (U+1F3FF a été omis, voir à la fin), 🕌, 🕍 ... (UniView n'a apparemment pas encore été mis à jour avec les données de la version 8).

Comme toujours depuis quelques versions d'Unicode, tout le monde s'excite sur les nouveaux emojis (si vous ne les avez pas encore sur votre ordinateur, voyez les jolis dessins sur ce site). Plutôt que de donner des listes pittoresques, avec des glyphes rigolos, je suggère fortement à mes lecteurs de lire l'excellent Unicode Technical Report #51 sur la gestion des emojis dans Unicode. Vous y apprendrez le pourquoi de ces caractères, et les règles qu'ils suivent dans Unicode, et comment enregister un nouvel emoji. À la lecture de ce rapport, vous saurez pourquoi le policier tue le crocodile (et pas le contraire), pourquoi un emoji dont le nom inclut BLACK n'est pas forcément noir, quelles sont toutes les formes possibles du shortcake...

Une nouveauté importante des emojis dans cette version 8 est la gestion de la couleur de peau. Traditionnellement, les personnages humains dans des emojis sont représentés avec une peau jaune vif. C'est considéré comme « neutre » (notez que les emojis sont nés au Japon...) Cela ne convient pas forcément à tout le monde et il y a une demande depuis longtemps pour permettre de représenter des gens à la peau rose ou noire. C'est possible avec la nouveauté des modificateurs d'emojis. Ce sont des caractères Unicode qui se placent après l'emoji et modifient la couleur de la peau du personnage. Ils sont cinq, correspondant aux cinq degrés de l'échelle de Fitzpatrick. Par exemple, si votre navigateur gère ces récents modificateurs, en mettant les deux caractères U+1F477 (CONSTRUCTION WORKER) et U+1F3FE (EMOJI MODIFIER FITZPATRICK TYPE-5), vous devriez voir un ouvrier à la peau sombre (mais pas complètement noire). Essayons d'abord sans le modificateur : 👷 et avec : 👷 🏾. (Au passage, ce caractère U+1F477 est cité dans le rapport #51 pour une autre raison politique : il est neutre du point de vue du genre et peut donc être représenté par un homme ou une femme.)

À noter deux limites des modificateurs : ils ne peuvent pas s'appliquer à chaque membre d'un groupe. Donc, dans U+1F46C TWO MEN HOLDING HANDS, les deux hommes ont forcément la même couleur de peau. Et, autre limite, les modificateurs ne peuvent changer que la couleur de la peau, pas d'autres caractéristiques comme la minceur.


L'article seul

RFC 7575: Autonomic Networking - Definitions and Design Goals

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : M. Behringer, M. Pritikin, S. Bjarnason, A. Clemm (Cisco Systems), B. Carpenter (Univ. of Auckland), S. Jiang (Huawei Technologies), L. Ciavaglia (Alcatel Lucent)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF nmrg
Première rédaction de cet article le 19 juin 2015


Ce nouveau RFC, issu de l'IRTF et donc assez futuriste, se penche sur les « réseaux autonomes » (autonomic networking), c'est-à-dire sur les réseaux qui se débrouillent tout seuls, sans administrateur réseaux, sans DSI, sans ICANN, etc. Un réseau autonome doit se configurer, s'optimiser, guérir des pannes et se protéger des attaques sans intervention humaine. Ce RFC n'explique pas comment les réaliser (c'est le début d'un programme de recherche) mais définit la terminologie et les buts à atteindre. Il a été publié en même temps que le RFC 7576, qui analysait les techniques existantes et leurs limites. (Le groupe de travail IETF ANIMA travaille sur les aspects plus concrets de ce sujet.)

La première description de tels réseaux autonomes date de 2001 (l'article de Kephart et Chess). L'idée est que toutes les boucles de régulation du système doivent être fermées, sans interaction avec l'extérieur (d'où l'adjectif « autonome »). IP lui-même a éte partiellement conçu pour fonctionner ainsi (la fameuse demi-légende de l'Internet prévu pour résister à une attaque nucléaire). Un protocole comme OSPF est autonome dans la mesure où il s'adapte tout seul aux changements de topologie. Toutefois, IP n'a jamais été complètement autonome et les évolutions qu'il a subi allaient plutôt dans le sens de mettre plus d'intelligence dans la configuration externe que dans le réseau lui-même. Est-ce grave ? Pour un grand réseau d'un Tier 1, on peut penser que son propriétaire préfère que le réseau n'ait pas trop d'autonomie (Skynet ?) et suive plutôt la politique configurée. Mais les réseaux autonomes sont tentants pour l'Internet des objets, quand on a un grand nombre de petites machines très simples, ensemble qui serait très difficile ou impossible à configurer avec les outils existants. Notre RFC estime que les deux approches (configuration extérieure centralisée, et fonctionnement réparti autonome) ont leurs avantages et inconvénients, et que pas mal de réseaux utiliseront une de ces deux approches pour certaines fonctions et la seconde pour les autres fonctions. Ne cherchez donc pas de réseau complètement autonome tout de suite.

De toute façon, l'approche autonome ne peut pas tout faire. Elle nécessite de découvrir tout seul un certain nombre de choses et la politique de gestion du réseau (qui peut s'en servir, pour quoi...) est un bon exemple de quelque chose qui ne peut pas être découvert, qui doit être configuré explicitement.

Les réseaux autonomes ont fait l'objet d'un très grand nombre d'études scientifiques et de publications (la section 7 du RFC contient des lectures, pour les gourmands, notamment trois synthèses de l'existant). Attention, on dit « autonome » et pas « automatique ». Il faut se gérer seul, pas juste dérouler automatiquement un script pré-établi par un humain (voir la section 2 sur les définitions). Par exemple, un système automatique doit être reprogrammé lorsque l'environnement change alors qu'on attend d'un réseau autonome qu'il s'adapte seul.

Donc, que veut-on d'un réseau autonome ? La section 3 décrit les buts. Le réseau doit être auto-géré ce qui se décline en :

  • Se configure tout seul. Les machines démarrent, se découvrent, trouvent les liens qui les relient et se mettent à les utiliser. Pas d'admin' pour avoir tapé des default_router=fe80::1.
  • Se guérit tout seul. Une pelleteuse arrache un câble ? Le réseau contourne le problème automatiquement (ceci marche dans l'Internet actuel : rappelez-vous qu'on a déjà certaines fonctions qui peuvent marcher de manière autonome).
  • S'optimise tout seul en trouvant la meilleure façon d'accomplir les tâches définies.
  • Se protège tout seul car le monde est hostile et cruel et des hackers chinois islamistes à cagoule vont attaquer le réseau.

Évidemment, en trichant, on peut définir tout réseau comme « autonome » si on élargit la définition pour inclure, par exemple, un contrôleur central (comme avec le SDN). Le RFC est donc plus spécifique : « tout seul » veut dire « en n'utilisant que des fonctions qui sont sur les machines terminales ». Comme dit l'Internationale, le réseau autonome n'a « ni Dieu, ni César, ni tribun[, ni contrôleur SDN] ».

Comme on ne peut pas envisager un Internet complètement autonome, ces réseaux autonomes vont devoir coexister avec les méthodes de gestion traditionnelles (comme Netconf). Cela peut nécessiter un mécanisme d'arbitrage si les deux méthodes sont en désaccord. Le RFC utilise un exemple tiré de l'aviation : un avion où le pilote automatique se coupe automatiquement si le vol sort d'une certaine plage de paramètres (par exemple si l'angle d'incidence est trop élevé). Toutefois, on peut aussi se dire qu'une crise n'est pas le meilleur moment pour passer brutalement le contrôle au pilote stressé et le RFC demande donc que les mécanismes autonomes ne se coupent pas tout seuls, même dans des situations non prévues.

Autre but de nos réseaux autonomes : qu'ils soient sûrs. On doit pouvoir, par exemple, empêcher un intrus de rejoindre le réseau, ce qui implique un certain mécanisme d'authentification, qui ne sera pas forcément totalement autonome (par exemple un certificat émis par une AC, une base d'utilisateurs centralisée, etc). Bref, il faudra sans doute de la cryptographie.

« Autonome » ne veut pas dire « isolé et sourd-muet » (sinon, ce ne serait pas un réseau). La machine doit communiquer avec des pairs mais aussi avec des autorités, comme cela qui lui communique le travail à faire, à qui la machine terminale transmet des rapports, des statistiques, etc. C'est ce qu'on nomme l'interface Nord (car placée en haut sur les schémas et tant pis pour l'Australie).

On a vu que le réseau n'est pas créé pour satisfaire les machines mais pour accomplir un certain travail. Il faudra donc un mécanisme pour informer les machines de ce travail, et des changements dans les définitions de ce travail. Ce mécanisme doit être de haut niveau, sinon, ce ne sera plus un réseau autonome, on retournerait à la configuration centralisée traditionnelle. Par exemple, le RFC demande que ce mécanisme n'expose pas la version d'IP utilisée (IPv4 ou IPv6) : cela doit rester un détail technique interne au réseau.

J'ai parlé plus haut de transmettre des rapports à l'autorité centrale. Il est évidemment nécessaire de prévenir les humains qui ont acheté et déployé ces machines de l'efficacité de celles-ci : le travail a-t-il été fait ? Mais, pour respecter le principe d'un réseau autonome, les rapports ne doivent pas porter sur des détails d'implémentation que le réseau doit résoudre lui-même (comme « le lien entre la machine X et la machine Y ne marche plus »). Il faut au contraire un mécanisme de communication abstraite, synthétisant l'information, pour ne pas écrouler l'autorité centrale sous les détails. Imaginons que l'autorité ait envoyé le but de haut niveau « économise l'énergie », le rapport devrait être du genre « 30 % de réduction de la consommation, obtenu en éteignant 40 % des ports réseau ». Pour résumer : les rapports devraient décrire le réseau globalement, pas machine par machine ou lien par lien.

Le RFC 7576 montre qu'il existe déjà un certain nombre de protocoles et de fonctions autonomes dans la famille IP. Mais le but du projet « réseaux autonomes » n'est pas uniquement d'empiler des solutions mais de les intégrer dans un cadre commun, qui reste à développer.

Enfin, « autonome » est un adjectif qu'on peut appliquer à toutes les couches. Par exemple, les commutateurs typiques aujourd'hui sont autonomes au niveau 2 (on les branche n'importe comment et ils font une topologie qui marche). Les routeurs peuvent en faire autant au niveau 3, comme vu avec l'exemple OSPF.

Un bon cahier des charges doit aussi avoir des non-buts : ce qu'on ne cherche pas à atteindre. C'est le rôle de la section 4 du RFC. Les non-buts sont :

  • Supprimer complètement tout opérateur humain (Skynet, encore). Les humains vont rester, mais en se concentrant sur des fonctions de haut niveau, comme la définition et la vérification des politiques.
  • Résoudre tous les problèmes. De temps en temps, il se produira un évènement dont le réseau ne saura pas se dépêtrer seul. Là encore, des humains devront intervenir. Ce sera au moins le cas pour les pannes matérielles, tant que les ordinateurs n'auront pas de périphériques leur permettant d'aller à la casse eux-même...
  • Supprimer tout contrôle central. Comme le note le RFC, la Direction Générale ne serait sans doute pas d'accord.

Enfin, notre RFC se termine par une description, en section 5, d'un modèle de référence des réseaux autonomes, reprenant les points vus précédemment.


Téléchargez le RFC 7575


L'article seul

RFC 7572: Interworking between the Session Initiation Protocol (SIP) and the Extensible Messaging and Presence Protocol (XMPP): Instant Messaging

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : P. Saint-Andre (&yet), A. Houri (IBM), J. Hildebrand (Cisco Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF stox
Première rédaction de cet article le 17 juin 2015


Ce court RFC décrit une correspondance entre deux protocoles standards de messagerie instantanée, SIP et XMPP. Cela permet de développer proprement des passerelles connectant ces deux mondes, autorisant ainsi Juliette, utilisatrice de XMPP, à parler avec son Roméo, qui utilise SIP. C'est aussi un exercice intellectuel rigolo, mais parfois difficile, comment faire se parler deux protocoles différents, qui n'ont pas exactement les mêmes sémantiques.

C'est vrai qu'on ne sait pas forcément que SIP (RFC 3261) est aussi un protocole de messagerie instantanée. On le voit plutôt uniquement comme un protocole de signalisation pour la téléphonie sur IP. Mais SIP sait bel et bien échanger de courts messages textes, grâce à l'extension MESSAGE du RFC 3428. Quant à XMPP (RFC 6120), ses capacités de messagerie instantanée sont spécifiées dans le RFC 6121. C'est pour des raisons historiques variées que l'IETF a deux protocoles standard de messagerie instantanée, sans compter l'ancêtre IRC.

Le concept de messagerie instantanée, à l'IETF, est décrit dans le RFC 2779. Le but est de communiquer, donc il serait ennuyeux que Roméo et Juliette ne puissent pas échanger simplement parce qu'ils ont fait des choix technologiques différents. Spécifier un mécanisme de passerelle entre ces deux protocoles peut se faire en développant une sémantique abstraite (elle existe déjà, dans le RFC 3860), puis en définissant une correspondance entre cette abstraction et chaque protocole (ce qui a été fait pour XMPP : RFC 3922). En pratique, c'est bien compliqué et notre nouveau RFC 7572 choisit une autre approche, définir une correspondance entre SIP et XMPP, sans intermédiaire. L'inconvénient est que cela ne se généralise pas à davantage de protocoles, l'avantage est que c'est simple à comprendre et à programmer. En pratique, cette approche est donc bien plus répandue.

Notre RFC repose sur un modèle simple, l'envoi de courts textes, les messages, de manière synchrone, entre deux entités (Roméo et Juliette dans les exemples du RFC), ce qui se nomme page mode. Il existe d'autres modèles comme celui de conversations stables sur une certaine durée (session mode) ou comme celui de communications à plus de deux participants. Le groupe de travail STOX de l'IETF est penché dessus et produira d'autres RFC sur ces modèles, comme le RFC 7573 sur les sessions. Notre RFC s'appuie sur le RFC 7247, qui définissait une architecture pour l'interconnexion de SIP et XMPP.

Donc, commençons par XMPP vers SIP (section 4). Un message XMPP est une strophe (stanza) XML <message/> de type normal (le type par défaut). Voici l'exemple envoyé par Juliette :


<message from='juliet@example.com/yn0cl4bnw0yr3vym'
         to='romeo@example.net'>
   <body>Art thou not Romeo, and a Montague?</body>
</message>

Si le domaine dans l'attribut to est un domaine SIP (section 5 du RFC 7247), le serveur XMPP que Juliette utilise va transmettre le message à une passerelle XMPP->SIP qui va traduire en SIP :


MESSAGE sip:romeo@example.net SIP/2.0
Via: SIP/2.0/TCP x2s.example.com;branch=z9hG4bK776sgdkse
Max-Forwards: 70
To: sip:romeo@example.net
From: <sip:juliet@example.com;gr=yn0cl4bnw0yr3vym>;tag=12345
Call-ID: D9AA95FD-2BD5-46E2-AF0F-6CFAA96BDDFA
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 35

Art thou not Romeo, and a Montague?

Notez que l'identificateur de ressource dans le JID (le JID nu est juliet@example.com, la ressource est yn0cl4bnw0yr3vym, cf. RFC 6120, section 1.4) a été traduit en GRUU (Globally Routable User Agent URIs, cf. RFC 5627) SIP.

Le serveur SIP de Roméo répondra automatiquement avec le code 200 (tout va bien) :

SIP/2.0 200 OK
Via: SIP/2.0/TCP x2s.example.com;branch=z9hG4bK776sgdkse
From: sip:juliet@example.com;tag=12345
To: sip:romeo@example.net;tag=vwxyz
Call-ID: D9AA95FD-2BD5-46E2-AF0F-6CFAA96BDDFA
CSeq: 1 MESSAGE
Content-Length: 0

La correspondance entre les termes utilisés figure dans le tableau 1 dans cette section 4. Ainsi, le <body/> de XMPP est transformé en corps du message SIP, l'attribut to de XMPP qui indique le destinataire devient le champ To: de SIP, l'attribut xml:lang de XMPP (absent dans cet exemple) devient un champ Content-Language:, etc. Certaines valeurs n'ont pas de correspondance (comme l'attribut type de XMPP, inutilisé dans l'exemple).

En sens inverse, lorsque Roméo répond, il va utiliser SIP (avec l'extension du RFC 3428) et il va donc falloir traduire le SIP en XMPP. Sa réponse était (section 5 de notre RFC) :


MESSAGE sip:juliet@example.com SIP/2.0
Via: SIP/2.0/TCP s2x.example.net;branch=z9hG4bKeskdgs677
Max-Forwards: 70
To: sip:juliet@example.com
From: sip:romeo@example.net;tag=vwxyz
Call-ID: 9E97FB43-85F4-4A00-8751-1124FD4C7B2E
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 44

Neither, fair saint, if either thee dislike.

Et la passerelle SIP->XMPP qu'utilisera le serveur SIP de Roméo traduira en :


<message from='romeo@example.net/dr4hcr0st3lup4c'
         to='juliet@example.com'>
  <body>Neither, fair saint, if either thee dislike.</body>
</message>

La correspondance entre les termes (tableau 2) est la même, mais inversée. Le champ To: est traduit en attribut to, le corps du message devient un élément XMPP <body>, etc. Notez que la passerelle connaissait le GRUU SIP (par un moyen non spécifié, peut-être parce qu'elle fait partie du serveur SIP) et l'a utilisé pour générer un JID complet avec identificateur de ressource (romeo@example.net/dr4hcr0st3lup4c).

Faire des passerelles entre deux protocoles indépendants, conçus de manière différente et sans coordination a toujours été délicat. Par exemple, la section 6 fait remarquer qu'il y a un problème... de taille. SIP met une limite de 1 300 octets aux messages (RFC 3428, section 8) alors que les RFC sur XMPP ne spécifient pas de limite. En pratique, les messages XMPP dépassent rarement cette taille et, de toute façon, les mises en œuvre effectives de XMPP ont souvent une limite (RFC 6120, section 13.12), mais plus élevée (au moins 10 000 octets doivent être acceptés, dit le RFC 6120). Si Juliette, qui utilise XMPP, essaie d'envoyer un message de 1 500 octets à son Roméo, la passerelle XMPP->SIP n'aura pas d'autre choix que de le rejeter, avec une erreur <policy-violation/>. (Des solutions plus sophistiquées existent, comme de passer en session mode mais notre RFC ne les spécifie pas.)

Autre cause d'incompatibilités possibles, mais en sens inverse, cette fois, les questions de format des données (section 7). Un message SIP peut contenir des données de n'importe quel type (dans les exemples ci-dessus, c'était toujours du text/plain mais ce n'est pas obligatoire). XMPP traitant le contenu de manière très différente, notre RFC impose aux passerelles SIP->XMPP de :

  • Accepter le contenu text/plain, comme dans les exemples ci-dessus, en le mettant dans le <body/> XMPP,
  • Accepter le contenu text/html en le transformant en XHTML qu'on met dans le <body/> XMPP (comme décrit dans le XEP-0071),
  • Faire ce qu'elle veut avec les autres types, aucune règle n'est spécifiée pour eux.

Et si on veut le dire autrement qu'en anglais ? Pas de problème, les deux protocoles permettent d'étiqueter le message avec la langue utilisée, et tous les deux permettent de transporter des caractères Unicode (en général en UTF-8). Si Roméo décide de parler tchèque :


MESSAGE sip:juliet@example.com SIP/2.0
Via: SIP/2.0/TCP s2x.example.net;branch=z9hG4bKeskdgs677
Max-Forwards: 70
To: sip:juliet@example.com
From: sip:romeo@example.net;tag=vwxyz
Call-ID: 5A37A65D-304B-470A-B718-3F3E6770ACAF
CSeq: 1 MESSAGE
Content-Type: text/plain
Content-Length: 45
Content-Language: cs

Nic z obého, má děvo spanilá, nenávidíš-li jedno nebo druhé. 

La passerelle le traduira sans problème (j'ai utilisé ici les notations commençant par &#x mais ce n'est pas obligatoire, XMPP utilise XML et peut donc se servir d'UTF-8) :


<message from='romeo@example.net'
         to='juliet@example.com'
         xml:lang='cs'>
	 <body>
           Nic z ob&#x00E9;ho, m&#x00E1; d&#x011B;vo spanil&#x00E1;, nen&#x00E1;vid&#x00ED;&#x0161;-li jedno nebo druh&#x00E9;.
       </body>
</message>

Un mot sur la sécurité pour finir. L'introduction de la passerelle entre les deux protocoles ajoute évidemment quelques risques. Notamment, il est plus difficile de garantir une sécurité de bout en bout. Il existe des solutions standard peu déployées (RFC 3862 et RFC 3923) ou une solution non standard, OTR.

Parmi les serveurs qui mettent déjà en œuvre cette passerelle, on peut apparemment citer Cisco, Kamailio, ou AG Projects (dans Silk Server).


Téléchargez le RFC 7572


L'article seul

RFC 7556: Multiple Provisioning Domain Architecture

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : D. Anipko
Pour information
Réalisé dans le cadre du groupe de travail IETF mif
Première rédaction de cet article le 16 juin 2015


Ce RFC décrit une architecture nouvelle permettant de mieux gérer les machines ayant plusieurs connexions à l'Internet. On ne parle pas ici de gros routeurs ou serveurs connectés à plusieurs réseaux, non, un simple smartphone qui a à la fois le WiFi et la 4G est un exemple d'une machine qui a plusieurs interfaces. Et cela pose des sérieux problèmes avec l'Internet d'aujourd'hui, car, parfois, chaque interface va nécessiter des réglages différents. Notre nouvelle architecture aborde ce problème en définissant le PvD (ProVisioning Domain ou domaine d'avitaillement), un ensemble cohérent de réglages, qui sera attaché à chaque interface.

Pourquoi est-ce un problème d'avoir plusieurs interfaces actives ? Car certains réglages ne sont valables que pour une seule interface, alors que TCP/IP considérait au début que toutes les interfaces se valaient et pouvaient être utilisées. Par exemple, l'adresse IP obtenue sur une interface ne doit pas être utilisée comme adresse IP source sur une autre interface, de peur de se faire mordre par le RFC 2827. Le résolveur DNS obtenu sur une interface ne doit pas être utilisé pour une autre car il refusera probablement de répondre (RFC 5358). Et, même si les résolveurs DNS acceptaient tous les clients, il arrive qu'ils renvoient des données qui ne sont pas les mêmes pour tout le monde (par exemple pour un serveur qui n'est accessible que depuis un certain réseau). Le RFC 6418 décrit plus en détail le problème des interfaces multiples, et le RFC 6419 proposait déjà quelques solutions, chacune spécifique à une plate-forme donnée. Pour résumer (à l'extrême) le RFC 6418, les risques sont :

  • Incohérence entre les informations obtenues depuis les différentes interfaces (comme dans l'exemple DNS ci-dessus),
  • Risque de mélanger les informations obtenues sur différentes interfaces (tenter de résoudre le nom d'un relais avec le serveur DNS d'un autre opérateur...),
  • Usage non conforme à la politique d'un des réseaux (par exemple, téléchargement d'un jeu via le VPN de l'entreprise...)

Donc, pour résoudre ce genre de problème, on introduit le concept de PvD. Mais c'est quoi, un PvD (section 2) ? Un ProVisioning Domain est simplement un ensemble cohérent d'informations de configuration d'un réseau, pour une interface donnée. Cela comprend par exemple l'adresse IP à utiliser (ou le préfixe IP), les adresses IP des résolveurs DNS, le routeur par défaut, le proxy Web à utiliser, etc. Une machine PvD-aware sait gérer cette information (notamment en l'association à une interface et en gardant en mémoire que, par exemple, ce résolveur DNS est fait pour cette interface). Une application PvD-aware a du code pour gérer la coexistence de différents PvD.

Aujourd'hui, les PvD sont implicites. La machine connectée reçoit de l'information de configuration sur chaque interface, via des processus divers (DHCP, mais pas seulement), et cette information n'est pas groupée, sous l'étiquette d'un PvD donné. C'est à la machine PvD-aware de gérer une table de PvD en les nommant et en les associant à chaque interface. Par défaut, avec les PvD implicites, une interface = un PvD.

Mais il y aura plus tard des PvD explicites. Cette distinction entre PvD implicites et explicites est essentielle. L'idée est de développer via l'IETF des mécanismes (qui n'existent pas encore) pour communiquer à la machine des PvD explicites, regroupant sous un nom donné un jeu d'informations de configuration cohérentes. Par exemple, on peut imaginer une option DHCP qui indique le nom du PvD correspondant aux options de configuration contenues dans cette réponse DHCP (ce n'est qu'une hypothèse : le RFC liste d'autres possibilités, cf. section 3). Avec les PvD explicites, il n'y aura plus forcément une interface = un PvD. On pourra avoir plusieurs interfaces utilisant le même PvD (si elles sont gérées par la même organisation).

Cela impliquera un système (non encore défini) de nommage des PvD. Le « PvD ID » devra être unique (puisque le but est de différencier les informations de configuration de réseaux différents), par exemple en le tirant au hasard dans un espace de grande taille. Le PvD ID ne sera donc pas forcément lisible par un humain ; si on veut une telle lisibilité, il faudra développer une solution, par exemple de méta-données associées au PvD.

Un PvD peut être commun à plusieurs familles IP (par exemple IPv4 et IPv6) et comporter donc plusieurs adresses. C'est utile si certaines options ont un sens pour plusieurs familles (c'est le cas de la politique de sélection de l'adresse du RFC 7078). Pour les PvD implicites, utiliser un seul PvD pour toutes les familles présentes sur l'interface est la politique recommandée.

La section 3 examine quelques protocoles existants pour voir comment ils pourraient être modifiés pour transporter de l'information explicite sur les PvD. Aujourd'hui, la configuration des machines terminales est faite en général par DHCP (RFC 3315) ou RA (RFC 3971). Notons qu'elles ne sont pas sécurisées par défaut. Des solutions existent pour authentifier la machine qui émet la réponse DHCP ou RA mais authentification n'est pas autorisation : elle ne nous dit pas si cette machine est autorisée à annoncer explicitement tel PvD. Pour cela, il faudrait un moyen de signer les PvD.

Évidemment, si on ajoute des mécanismes de PvD à ces protocoles, cela devra être fait d'une manière compatible avec les machines existantes, qui ne sont pas PvD-aware. Pendant la phase de coexistence, il faudra peut-être dupliquer de l'information dans les réponses DHCP ou RA, pour satisfaire tout le monde.

La section 4 du RFC présente trois études de cas concrètes. La première est celle d'une machine mobile, un smartphone, par exemple. Il a une interface avec un réseau mobile, mettons 3G, et une interface WiFi. S'il est dehors, loin de tout hotspot, il n'aura qu'une interface active et donc un seul PvD : pas de difficultés. S'il s'approche d'un point d'accès WiFi et s'y connecte, le dilemme commence : quelle interface utiliser ? Android, par exemple, ne peut en utiliser qu'une à la fois et va donc cesser d'utiliser la 3G. Cela simplifie le modèle de connexion pour les développeurs mais n'est pas satisfaisant pour l'utilisateur. Il serait plus satisfaisant de pouvoir utiliser les deux, mais en respectant à chaque fois le PvD (qui peut être différent) de chaque interface.

Autre étude de cas, un VPN, qui peut être considéré comme une interface supplémentaire, quoique virtuelle, et un réseau à la maison, connecté à la fois à un FAI généraliste classique et à un service de VoD, avec une interface séparée qu'on n'utilise que pour la vidéo, et qui est donc décrite par un PvD différent.

La section 5 de notre RFC étudie plus en détail certains points spécifiques qui doivent être traités par un nœud PvD-aware. Par exemple, la résolution de noms, déjà citée plus haut, qui dépend fortement du PvD : un résolveur DNS n'est typiquement utilisable que par certains clients, et pas par le monde entier. En outre, les résultats d'une résolution de noms peuvent varier selon le résolveur interrogé (cas d'un service spécifique à un FAI, par exemple le MMS). La machine doit donc savoir quel PvD utiliser pour chaque nom, avec des règles du genre « pour tous les noms se terminant en ma-boîte.example, se servir du résolveur DNS du PvD du VPN de ma boîte ». Si plusieurs PvD correspondent à des FAI généralistes, pouvant servir pour tout accès à un serveur public, la machine PvD-aware peut faire les résolutions de noms en parallèle, et prendre le plus rapide, selon un approche identique à celle des globes oculaires heureux du RFC 6555.

Et puisqu'on parle de sélectionner le « meilleur » PvD, il faut rappeler que la connectivité au réseau local, tel qu'elle s'obtient lorsqu'une requête DHCP ou RA a réussi, ne garantit pas un bon accès à tout l'Internet. Le signal local peut être fort, le serveur DHCP très réactif... et la connexion ultérieure échouer. Il est donc prudent de tester les connexions obtenues, par exemple en essayant de se connecter à un amer bien connu.

On a vu qu'une application pouvait être PvD-aware si elle sait utiliser l'information sur les PvD pour prendre des décisions. La section 6 décrit les propriétés attendues de l'API qui permettra de développer ces applications. Dans le cas le plus simple, une application PvD-aware peut se limiter à n'utiliser qu'un seul PvD. C'est le cas d'une application MMS qui dépend d'un opérateur particulier et qui devra donc passer par l'interface correspondante. Un peu plus complexe serait une application qui exprime des exigences et des préférences, du genre « il me faut IPv6 » ou « je fais de la vidéo-conférence, je veux une faible latence » ou bien « je suis paranoïaque, je ne veux passer que par un PvD cité dans telle liste » ou encore « je ne suis pas pressé, il vaut mieux utiliser la connexion la moins chère ». Le système pourrait alors choisir, en regardant les informations obtenues pour chaque PvD, quel PvD utiliser. Dans le dernier cas (une application qui télécharge beaucoup, comme la mise à jour du système d'exploitation, ou comme une application pair-à-pair d'accès à la culture), un mécanisme de sélection automatique via le PvD simplifierait nettement la tâche de l'utilisateur en le dispensant d'options comme la « n'utiliser qu'avec la WiFi » qu'on trouve souvent sur les applications Android, qui veulent éviter de faire exploser le forfait de téléphonie mobile.

Enfin, les applications les plus avancées pourraient simplement obtenir la liste des PvD et leurs caractéristiques et faire leurs choix elles-mêmes. Ces choix ne seront pas forcément respectés par le système, qui peut avoir ses propres exigences (par exemple forcer la passage par le VPN de l'entreprise pour les connexions aux services de la dite entreprise).

Puisqu'on a parlé de sécurité (« je suis paranoïaque, je ne veux passer que par un PvD cité dans telle liste »), un mot sur les PvD de confiance ou pas (section 7). Par défaut, un PvD n'est pas « de confiance ». Si je me promène dans la rue et que je me connecte à un hotspot inconnu, le PvD associé ne sera pas considéré comme de confiance. Certains systèmes ou applications ne voudront se connecter à tel service que via un PvD de confiance. Mais attention : supposons qu'on ait une telle liste (le PvD du VPN de la boîte, le PvD d'un opérateur à qui on fait confiance, le réseau local à la maison...), il ne faut pas pour autant considérer que le PvD est ce qu'il annonce. Si le PvD de l'entreprise est 6a97f31e-34ec-4ef9-ba75-b1e3addd8222 (ce n'est pas la vraie syntaxe des PvD ID, qui n'est pas encore décidée), et que le serveur DHCP du hotspot annonce ce PvD ID, il ne faut pas pour autant lui faire confiance (voir aussi la section 8). Un PvD de confiance nécessite deux choses : une relation de confiance avec son opérateur, et un moyen de vérifier qu'il s'agit bien du PvD attendu. Ce moyen d'authentification peut passer par une signature du PvD ID, ou bien simplement par le mécanisme d'attachement au réseau : on peut décider que, si on est connecté à un réseau physique stable et sûr, l'annonce du PvD ID sur ce réseau peut être crue. À noter que le RFC fournit un autre exemple, où on fait confiance au réseau d'un opérateur mobile, ce qui ignore le risque des IMSI-catchers.

La section 8 revient d'ailleurs sur les problèmes de sécurité. Par exemple, même si le serveur DHCP ou RA est sûr, un attaquant a pu modifier les données en cours de route. On peut utiliser les techniques (très peu déployées en pratique) de l'option AUTH du RFC 3315, section 22.11, ou le SEND du RFC 3971.


Téléchargez le RFC 7556


L'article seul

RFC 7553: The Uniform Resource Identifier (URI) DNS Resource Record

Date de publication du RFC : Juin 2015
Auteur(s) du RFC : P. Faltstrom (Netnod), O. Kolkman (ISOC)
Pour information
Première rédaction de cet article le 14 juin 2015


Ce RFC est la documentation d'un nouveau type d'enregistrement DNS, le type URI qui permet de publier des URI et donc d'avoir un mécanisme pour faire correspondre un nom de domaine à un URI.

Petit rappel, les URI sont normalisés dans le RFC 3986 et permettent sous une forme simple et compacte d'identifier une ressource sur le Web et, très fréquemment, fournissent les moyens d'y accéder. Traditionnellement, quand on voulait mettre des URI dans le DNS et permettre de les retrouver, on utilisait les NAPTR des RFC 3401 et RFC 3404. Notre nouveau RFC critique cette solution en notant qu'une requête NAPTR récupère tous les NAPTR qu'il faut trier ensuite, pas uniquement ceux liés à un seul service (le triage est d'autant plus compliqué qu'il n'existe toujours aucune bibliothèque en logiciel libre pour manipuler des NAPTR). En effet, le nom du service fait partie des données du NAPTR, pas du nom de domaine (le seul critère de sélection dans une requête DNS, avec le type). La solution de notre RFC 7553 permet cette sélection en mettant le type de service souhaité dans le nom de domaine. En outre, l'URI est trivial à extraire, il est le dernier composant des données de l'enregistrement, et ne nécessite pas de traitement ultérieur (on est loin de la complexité des NAPTR, même si les S-NAPTR du RFC 3958 l'ont un tout petit peu simplifiée).

Donc, dès que vous avez besoin d'une correspondance simple entre un nom de domaine et un URL, allez-y, ce type d'enregistrement est fait pour vous. À quoi ressemble-t-il (section 4 du RFC) ? Le format de présentation en texte met dans les données (la partie droite de l'enregistrement) une priorité, suivie d'un poids et de l'URI (nommé Target). Cela donne comme exemple :

_ftp._tcp.example.net.    IN URI 10 1 "ftp://ftp1.example.com/public"

Priorité et poids ont la même sémantique que dans le RFC 2782 (voir plus loin).

Le nom de domaine suit certaines conventions (section 4.1), notamment d'indiquer le service demandé (pris dans le registre IANA qu'avait créé le RFC 6335) et le protocole utilisé, précédés d'un tiret bas.

L'enregistrement URI a le type 256 et figure à ce titre dans le registre IANA des types DNS.

On peut avoir plusieurs URI pour un même nom de domaine (donc un même service). La sélection se fait en examinant d'abord la priorité, puis le poids. La priorité est absolue. On contacte d'abord les URI ayant la priorité la meilleure (c'est le chiffre le plus bas, attention), et, seulement si cela échoue, on tente les autres. Par contre, à priorité équivalente, la sélection selon le poids est probabiliste. Cela permet de faire de la répartition de charge dans le DNS. Si j'écris deux URI avec la même priorité mais des poids différents :

_ftp._tcp.example.net.    IN URI 10 2 "ftp://ftp1.example.net/public"
                          IN URI 10 1 "ftp://ftp4.example.com/mirrors/example.net/"

Alors, l'URI ftp://ftp1.example.net/public a deux fois plus de chances d'être sélectionné, il recevra donc les deux tiers des requêtes. Si j'avais mis des priorités différentes :

_ftp._tcp.example.net.    IN URI 10 1 "ftp://ftp1.example.net/public"
                          IN URI 20 1 "ftp://ftp4.example.com/mirrors/example.net/"

Alors, ftp://ftp4.example.com/mirrors/example.net/ ne sera sélectionné que s'il n'y a pas le choix, uniquement si ftp1.example.net est en panne.

Et sur le réseau, comment est encodé ce nouveau type (section 4.5) ? C'est simple, deux octets pour la priorité, deux pour le poids et l'URI lui-même, sous forme de texte.

Les enregistrements URI permettent d'indiquer la même chose qu'un SRV (RFC 2782), à savoir un nom de serveur et un port, mais ils permettent en outre d'exprimer d'autres choses (comme le répertoire dans les exemples FTP plus haut). En contre partie, il faut pouvoir traiter les URI, les analyser, mais c'est aujourd'hui une tâche bien connue, pour laquelle on a déjà du code. Ainsi, ces deux informations sont presque équivalentes (si on sait que le protocole à utiliser est HTTP) :

_http._tcp    IN  SRV   0  1 8081  www.example.net.
_http._tcp    IN  URI   0  1 "http://www.example.net:8081"

Mais les enregistrements URI sont plus puissants, ceci ne pourrait pas être exprimé en SRV :

_http._tcp    IN  URI   0  1 "http://www.example.net:8081/actu/2015"

Les futurs protocoles pourraient donc n'utiliser que URI, et plus du tout SRV. (À l'heure actuelle, certains protocoles utilisent une combinaison de SRV + un enregistrement TXT, pour résoudre ce problème : l'enregistrement URI est plus élégant.)

Je ne peux pas m'empêcher de noter que bien des problèmes du Web auraient été évités si, dès le début, Tim Berners-Lee avait pensé à découpler le nom de domaine et le serveur, en utilisant les SRV. Actuellement, le nom dans l'URL doit être un nom de machine (il doit obéir aux règles syntaxiques restrictives sur les noms de machine, et il doit avoir une adresse IP). Cela oblige à mettre une adresse à l'apex (le sommet) de la zone DNS (si on veut que http://example.com/ marche, il faut une adresse IP mise au nom example.com, ce qui est compliqué à réaliser proprement). Si le Web utilisait les SRV ou, aujourd'hui, les enregistrements URI, on ne serait pas obligé de polluer l'apex de la zone avec des adresses IP, on aurait séparé le nom court (example.com), dans l'URL, et celui du serveur (qui ne serait pas visible à l'utilisateur ordinaire).

Bien que ce type d'enregistrement ait déjà plusieurs années (le RFC 6895 permet d'enregistrer un type d'enregistrement DNS sans avoir de RFC), certains logiciels ne le gèrent pas encore. Voici une version un peu ancienne d'OpenDNSSEC (je n'ai pas testé avec les versions plus récentes) :

ods-signerd: [adapter] error parsing RR at line 28 (Syntax error, could not parse the RR's rdata):   IN URI 0 1 "http://www.bortzmeyer.org/"

Aïe. Et pareil avec le signeur DNSSEC d'une version un peu vieille de BIND :

dnssec-signzone: warning: sources.org:23: unknown RR type 'URI'
dnssec-signzone: fatal: failed loading zone from 'sources.org': unknown class/type

Idem pour les formulaires Web qui permettent de créer des enregistrements DNS dans une zone gérée par son hébergeur DNS. Tous n'ont pas encore ce type, loin de là.

Pour une vision optimiste, voici le commit qui a ajouté le type URI à PowerDNS.


Téléchargez le RFC 7553


L'article seul

Alerte en Malaisie, une nouvelle fuite BGP

Première rédaction de cet article le 12 juin 2015
Dernière mise à jour le 14 juin 2015


C'est un accident qui, à cette ampleur, se produit tous les... quoi... trois ou quatre ans sur l'Internet. Un opérateur, en l'occurrence Telekom Malaysia, a laissé fuiter des centaines de milliers de routes Internet, attirant ainsi une quantité de trafic qu'il n'a pas su gérer. Le problème a duré environ deux heures. Du classique, à quelques exceptions près.

Merci à Buck Danny pour la référence :

D'abord, les observations brutes : les premières observations publiques qu'il y avait un problème ont été divers tweets comme celui de Nathalie Rosenberg à 0855 UTC. Une bonne partie de l'Internet semblait injoignable, et des gens ont commencé à accuser Free ou CloudFlare. En fait, on pouvait voir à plusieurs endroits que la source du problème était dans une crise BGP. Par exemple, les fichiers stockant les annonces BGP à RouteViews augmentaient brusquement de taille, montrant une forte activité BGP, ce qui n'est pas en général bon signe. De fichiers de moins d'un Mo en temps normal, on est passé à 2,2 Mo à 0845 puis à 14 Mo à 0900 et 19 Mo à 0915. L'examen du contenu de ces fichiers montre la cause du problème : l'AS 4788 (Telekom Malaysia) a laissé fuiter dans les 200 000 routes BGP (au lieu de 1 300 en temps normal, ce qui est déjà beaucoup)... Voici la première annonce erronnée :

TIME: 06/12/15 08:43:29
TYPE: BGP4MP/MESSAGE/Update
FROM: 208.51.134.246 AS3549
TO: 128.223.51.102 AS6447
ORIGIN: IGP
ASPATH: 3549 4788 3491 4651 9737 23969
NEXT_HOP: 208.51.134.246
MULTI_EXIT_DISC: 24968
COMMUNITY: 3549:4992 3549:7000 3549:7003 3549:7004 354
9:32344 4788:400 4788:410 4788:415
ANNOUNCE
  1.0.208.0/22
  1.0.212.0/23
  1.1.176.0/22
  ...

Aucune de ces préfixes n'est géré par Telekom Malaysia ou ne devrait être annoncé par eux. C'est à tort que leur transitaire Level 3/GlobalCrossing (AS 3549) a accepté ces annonces. (Rappelez-vous qu'un chemin d'AS se lit de droite à gauche, ici 23969 est l'origine.) Normalement, on filtre les annonces de ses clients ou de ses pairs BGP, à partir des IRR. Même si on ne filtre pas sur les données des IRR (souvent mal maintenues), on devrait, au minimum, mettre un nombre maximal de préfixes annoncé et couper la session autrement (si Free l'avait fait, ses clients auraient eu moins de problèmes, voir plus loin). Mais personne ne veut prendre le risque de mécontenter un client. Et puis filtrer demande davantage de travail, alors que la sécurité ne rapporte rien.

Level 3 relayant ce grand nombre de routes, bien des routeurs qui avaient configuré un nombre maximum de préfixes BGP annoncés ont coupé leur session. Ainsi, au RING, on voyait :

id	timestamp	raised_by	short
2413	2015-06-12 09:33:52	linode01	linode01.ring.nlnog.net: raising ipv4 alarm - 17 new nodes down
2412	2015-06-12 09:32:46	ovh04	ovh04.ring.nlnog.net: raising ipv4 alarm - 43 new nodes down
2411	2015-06-12 09:31:56	ovh03	ovh03.ring.nlnog.net: raising ipv4 alarm - 29 new nodes down
2410	2015-06-12 09:27:49	adix01	adix01.ring.nlnog.net: raising ipv4 alarm - 1 new nodes down
2409	2015-06-12 09:27:46	octopuce01	octopuce01.ring.nlnog.net: raising ipv4 alarm - 20 new nodes down
2408	2015-06-12 09:20:51	berkeley01  berkeley01.ring.nlnog.net: raising ipv4 alarm - 3 new nodes down

Notons que tout n'est pas passé par Level 3. Les gens qui peeraient avec Telekom Malaysia et qui, bien à tort, ne filtraient pas les annonces, ont également reçu les annonces fausses. C'est le cas de Free, ce qui explique l'ampleur de la crise pour les abonnés de Free. Voici un traceroute actuel, montrant le peering entre Free et Telekom Malaysia :

% traceroute www.tm.com.my
traceroute to www.tm.com.my (58.27.84.129), 30 hops max, 60 byte packets
 1  freebox (192.168.2.254)  12.533 ms  12.510 ms  12.498 ms
...
 7  bzn-crs16-1-be1024.intf.routers.proxad.net (212.27.56.149)  25.686 ms  14.741 ms  14.706 ms
 8  th2-9k-1-be1003.intf.routers.proxad.net (78.254.249.97)  12.186 ms  31.208 ms  31.177 ms
 9  yankee-6k-1-po1.intf.routers.proxad.net (212.27.57.14)  115.595 ms  117.136 ms  117.129 ms
10  ash-bo02.tm.net.my (206.126.236.176)  106.776 ms  106.789 ms  115.466 ms
11  10.55.36.116 (10.55.36.116)  366.449 ms  366.450 ms  367.967 ms
12  58.27.84.6 (58.27.84.6)  375.796 ms  375.787 ms  382.950 ms
...

Résultat de ces annonces, le trafic filait effectivement en Malaisie comme le montre ce test :

$ mtr -4rwc100 cloudflare.com
Start: Fri Jun 12 11:06:26 2015
HOST: laptop Loss% Snt Last Avg Best Wrst StDev
1.|-- box 0.0% 100 3.4 3.7 3.3 10.5 0.8
2.|-- 129.120.16.109.rev.sfr.net 0.0% 100 28.2 27.7 26.0 39.6 1.4
3.|-- 193.45.66.86.rev.sfr.net 0.0% 100 27.0 27.8 26.0 32.6 0.8
4.|-- 181.45.66.86.rev.sfr.net 0.0% 100 28.6 32.3 26.4 225.8 26.1
5.|-- v3790.poi1-co-1.gaoland.net 0.0% 100 30.6 30.7 27.6 46.4 2.4
6.|-- 54.247.5.109.rev.sfr.net 0.0% 100 38.4 36.2 33.1 42.6 1.5
7.|-- ae1.parigi32.par.seabone.net 2.0% 100 33.8 34.5 32.4 49.1 2.1
8.|-- xe-5-1-2.parigi52.par.seabone.net 0.0% 100 35.1 35.1 33.1 48.0 1.7
9.|-- global-crossing.parigi52.par.seabone.net 72.0% 100 378.4 612.6 378.4 3819. 796.8
10.|-- telekom-malaysia-berhad.xe-0-2-0.ar2.clk1.gblx.net 74.0% 100 399.2 399.3 397.4 412.8 2.8
11.|-- ??? 100.0 100 0.0 0.0 0.0 0.0 0.0
12.|-- 13335.sgw.equinix.com 83.0% 100 460.9 462.5 459.8 480.8 5.1
13.|-- 198.41.214.163 84.0% 100 460.3 460.2 459.0 462.3 0.9

Notez que Telekom Malaysia n'a annoncé que 200 000 routes, sur les environ 600 000 qu'on trouve dans l'Internet donc environ les deux tiers des sites connectés n'ont pas eu de problème. On voit ici, via DNSmon, l'effet sur les serveurs DNS de .fr : deux des serveurs perdent environ 1 % des paquets au plus fort de la crise, c'est tout

Les annonces erronnées ont été supprimées vers 1030 UTC mais le trafic BGP n'est complètement revenu à la normale que vers 1200 UTC. (Attention, ce graphique affiche les heures en UTC+2, alors qu'une supervision de l'Internet devrait toujours utiliser UTC.)

Une des originalités de cette fuite est que l'origine du chemin d'AS n'était pas le fuiteur, Telekom Malaysia. La plupart du temps, le fuiteur émet les routes comme s'il en était l'origine et des techniques comme RPKI+ROA détectent l'usurpation. Ici, au contraire, l'origine... originelle a été préservée et RPKI+ROA n'auraient donc rien vu. On voit ici une annonce Telekom Malaysia sur un routeur qui valide et on note qu'il a validé l'annonce :

193.0.0.0/21
                      [BGP/170] 00:20:29, MED 1000, localpref 150
                      AS path: 3549 4788 12859 3333 I, validation-state: valid
                    > to 64.210.69.85 via xe-1/1/0.0

Alors, BGP mérite-t-il le surnom de « Bordel Gateway Protocol » que Nathalie Rosenberg lui avait donné ? Il est vrai que l'acceptation sans discussions d'annonces par les autres opérateurs est une source de fragilité. Mais les ingénieurs réagissent rapidement et s'adaptent et la panne, finalement, n'aura pas duré longtemps.

D'autres articles sur ce sujet :


L'article seul

RFC 7557: Extension Mechanism for the Babel Routing Protocol

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : J. Chroboczek (PPS, University of Paris-Diderot)
Expérimental
Première rédaction de cet article le 11 juin 2015


Le protocole de routage Babel, spécifié dans le RFC 6126, est désormais doté d'un mécanisme d'extension documenté.

Un paquet Babel comprend un en-tête fixe, suivi d'une série de TLV. Babel prévoyait des mécanismes d'extension en réservant certaines valeurs et en précisant le comportement d'un routeur Babel lors de la réception de valeurs inconnues. Ainsi :

  • Un paquet Babel avec un numéro de version différent de 2 doit être ignoré, ce qui permet de déployer une nouvelle future version de Babel sans que ses paquets ne cassent les implémentations existantes,
  • Un TLV de type inconnu doit être ignoré (RFC 6126, section 4.3), ce qui permet d'introduire de nouveaux types de TLV en étant sûr qu'ils ne vont pas perturber les anciens routeurs,
  • Les données contenues dans un TLV au-delà de sa longueur indiquée, ou bien les données présentes après le dernier TLV, doivent également être silencieusement ignorées (au lieu de déclencher une erreur). Ainsi, une autre voie d'extension est possible, où on pourra glisser des données supplémentaires.

Bien sûr, ces règles ne garantissent pas à elles seules que les extensions cohabiteront bien. D'où ce nouveau RFC, qui décrit comment utiliser ces possibilités, sans conflit entre deux extensions différentes.

La section 2 décrit toutes les possibilités d'extensions propres. Cela commence par une nouvelle version du protocole (l'actuelle version est la 2), qui utiliserait des numéros 3, puis 4...

Moins radicale, une extension de la version 2 peut introduire de nouveaux TLV (qui seront ignorés par les mises en œuvre anciennes de la version 2). Ces nouveaux TLV doivent suivre le format de la section 4.3 du RFC 6126.

Si on veut ajouter des données dans un TLV existant, en s'assurant qu'il restera correctement analysé par les anciennes mises en œuvre, il faut jouer sur la différence entre la taille explicite (explicit length) et la taille effective (natural length) du TLV. La taille explicite est celle qui est indiqué dans le champ Length spécifié dans la section 4.3 du RFC 6126. La taille effective est celle déduite d'une analyse des données (plus ou moins compliquée selon le type de TLV). Comme les implémentations de Babel doivent ignorer les données situées après la taille naturelle, on peut s'en servir pour ajouter des données. Elles doivent être encodées sous forme de sous-TLV, chacun ayant type, longueur et valeur (leur format exact est décrit en section 3).

Babel a aussi six bits libres dans les TLV de type Update (champ Flags, RFC 6126, section 4.4.9). Notre RFC déconseille de les utiliser, pour l'instant.

Enfin, après le dernier TLV (Babel est transporté sur UDP, qui indique une longueur explicite), on peut encore ajouter des données. L'idée était d'y mettre une signature cryptographique mais le système d'authentification de Babel, spécifié dans le RFC 7298, se sert plutôt de nouveaux TLV. Cet espace potentiel est donc inutilisé pour l'instant.

Bon, mais alors quel mécanisme d'extension choisir ? La section 4 fournit des pistes aux développeurs. Le choix de faire une nouvelle version est un choix drastique. Il ne devrait être fait que si la nouvelle version est réellement incompatible avec la précédente.

Un nouveau TLV, ou bien un nouveau sous-TLV d'un TLV existant est la solution à la plupart des problèmes d'extension. Par exemple, si on veut mettre de l'information supplémentaire aux mises à jour de routes (TLV Update), on peut créer un nouveau TLV « Update enrichi » ou bien un sous-TLV de Update qui contiendra l'information supplémentaire. Attention, les conséquences de l'un ou l'autre choix ne seront pas les mêmes. Un TLV « Update enrichi » serait totalement ignoré par un Babel ancien, alors qu'un TLV Update avec un sous-TLV d'« enrichissement » verrait la mise à jour des routes acceptée, seules l'information supplémentaire serait perdue.

Il existe désormais, pour permettre le développement d'extensions, un registre IANA des types de TLV et un des sous-TLV (section 5 du RFC) et plusieurs extensions s'en servent déjà.


Téléchargez le RFC 7557


L'article seul

RFC 7513: SAVI Solution for DHCP

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : J. Bi, J. Wu, G. Yao (Tsinghua Univ.), F. Baker (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF savi
Première rédaction de cet article le 11 juin 2015


Le cadre SAVI (Source Address Validation Improvement), décrit dans le RFC 7039, vise à rendre plus difficile l'usurpation d'adresses IP. SAVI fournit un cadre général et plusieurs solutions techniques concrètes sont ensuite développées selon le type de réseau et selon le niveau de sécurité qu'on désire et qu'on est prêt à « payer ». Ainsi, le RFC 6620 décrivait un mécanisme où le réseau d'accès assurait que le premier titulaire d'une adresse IP puisse la garder. Ce nouveau RFC décrit un autre mécanisme, où c'est via l'utilisation de DHCP qu'on contrôle les adresses : le réseau d'accès va empêcher l'utilisation d'adresses qui n'ont pas été allouées par le serveur DHCP. (Ce mécanisme est largement déployé depuis des années, sous divers noms, comme « DHCP snooping », mais n'avait pas été formellement décrit dans un RFC.)

L'usurpation d'adresse IP est à la base de nombreuses attaques sur l'Internet, comme les attaques par réflexion. Il existe depuis longtemps des techniques pour limiter l'usurpation d'adresses IP (le RFC 2827 est un exemple classique, qui permet de protéger un réseau contre l'usurpation par un autre). Celles de SAVI visent surtout le réseau local (réseau d'accès pour un FAI) en limitant le risque d'usurpation interne (qu'un utilisateur du réseau local usurpe l'adresse d'un autre). Ici, dans ce RFC 7513, l'allocation d'une adresse IP via DHCP va créer un lien (binding) entre cette adresse et des informations qui permettront au réseau de filtrer les usurpateurs. Par exemple, en retenant le port physique du commutateur comme lien, le commutateur peut bloquer les paquets dont l'adresse IP source n'est pas celle qui a été allouée à la machine connectée à ce port. Un tel mécanisme est souvent présent dans les commutateurs existants, souvent sous le nom de DHCP snooping mais attention : parfois, ce DHCP snooping se limite à bloquer les réponses DHCP arrivant sur un port inattendu, et n'intégre pas forcément la protection contre l'usurpation d'adresses IP, le but principal de ce RFC. Vérifiez avec votre commutateur !

Ce mécanisme de lien (binding anchor) est décrit en section 3 du RFC 7039 et rappelé en section 3 de notre RFC. Un lien doit être un attribut caractéristique, et difficile à changer (un contre-exemple est l'adresse MAC, facile à changer sur beaucoup de systèmes, et pourtant citée par notre RFC). C'est le cas du port physique du commutateur Ethernet cité plus haut, ou bien d'une association de sécurité WiFi (la section 3.2 du RFC 7039 donne d'autres exemples).

SAVI-DHCP va donc surveiller le trafic DHCP, notant les requêtes et réponses DHCP et les associant aux liens. Notez que cela marche avec le DHCP avec état (RFC 2131 pour IPv4 et RFC 3315 pour IPv6), pas avec le DHCP sans état du RFC 3736, qui ne s'occupe pas d'allocation d'adresses IP. De même, SAVI-DHCP ne gère évidemment pas le cas des réseaux où les adresses IP sont obtenues par un autre moyen que DHCP, par exemple le SLAAC du RFC 4862. Idem pour les adresses locales au lien (RFC 4291, section 2.5.6). Dans ces deux derniers cas, il faut utiliser une autre technique SAVI, le FCFS du RFC 6620.

Bon, maintenant, les détails. La section 4 précise quels acteurs sont considérés : un serveur DHCP évidemment, des clients DHCP, et les machines SAVI, typiquement des commutateurs, qui vont faire respecter les règles SAVI (il y a aussi quelques commutateurs non-SAVI dans le réseau d'exemple, pour mieux refléter la réalité). La machine SAVI va avoir besoin d'une certaine configuration. Par exemple, si le réseau contient un serveur DHCP menteur, la machine SAVI ne peut pas le deviner, et il faut lui dire sur quel port est attaché le vrai serveur DHCP (attribut SAVI DHCP-trust, cf. par exemple cette documentation Cisco, la commande ip dhcp snooping trust indiquera qu'un serveur DHCP légitime opère sur cette interface). De même, certains ports physiques ne doivent pas valider les adresses IP (attribut SAVI Trust, par exemple un port attaché au routeur de sortie, port sur lequel on verra passer, et c'est normal, plusieurs adresses IP) et il faudra donc indiquer à la machine SAVI sur quels ports elle doit surveiller (ceux où ne se trouve normalement qu'une ou plusieurs machines obtenant des adresses par DHCP).

SAVI sépare le réseau en deux, la partie de confiance et le reste. Dans la partie de confiance, on peut être raisonnablement sûr que les adresses IP source sont authentiques : tous les commutateurs valident. SAVI ne prétend pas sécuriser tout l'Internet. Et, même dans le réseau local, une partie du réseau peut être non-SAVI et ne sera donc pas de confiance. Cette notion de périmètre (séparant la partie de confiance et le reste) est essentielle pour configurer SAVI, et pour savoir ce qu'on peut attendre de cette technique. Par exemple, des réponses DHCP venues d'un serveur situé en dehors du périmètre ne seront pas utilisées par SAVI : puisque cette zone n'est pas de confiance, il peut parfaitement s'agir d'un serveur pirate (section 4.3.3 du RFC, un bon exemple de l'utilisation de la notion de périmètre, avec un schéma d'exemple).

La sécurité de SAVI-DHCP dépend évidemment de la sécurité des liens. Il faut notamment s'assurer que les attributs utilisés pour construire le lien sont difficiles à usurper. Un port physique du commutateur est un bon exemple. A contrario, une adresse MAC est un mauvais attribut (trop facile à changer) et même un attribut fort peut être affaibli par certains usages. Par exemple, si on utilise le port physique du commutateur Ethernet comme binding anchor, mais que ce dernier est connecté à des commutateurs non-SAVI en cascade, les nombreuses machines qui partagent ce port physique peuvent encore usurper leurs adresses IP entre elles.

Ces liens et les adresses IP associées doivent être stockées dans la mémoire de la machine SAVI, dans un structure de données dite BST (Binding State Table, section 5). Chaque ligne de cette table stocke également la durée de vie du lien et l'état du lien (établi, en cours d'établissement, inconnu).

La BST se remplit en « espionnant » (snooping) le trafic DHCP (section 6). En résumant (beaucoup) : la machine SAVI voit passer une requête DHCP et la réponse arrive depuis un port marqué comme DHCP-trust. On stocke alors dans la BST le port d'où est venu la requête (le lien, le binding anchor), l'adresse IP dans la réponse, le fait que le lien est établi, et sa durée de vie (typiquement la durée du bail DHCP). Désormais, si on voit un paquet IP arriver par le port d'où venait la requête DHCP, on pourra regarder son adresse IP source, et jeter le paquet si elle ne correspond pas à ce qui est dans la BST (ce filtrage est décrit en section 8). Sur un Juniper, on peut afficher cette BST avec show dhcp snooping binding. Cet exemple est tiré d'une documentation Juniper :

user@switch> show dhcp snooping binding
DHCP Snooping Information:
MAC Address             IP Address Lease   Type     VLAN    Interface
-----------------       ---------- -----   -------  ----    ---------
00:00:01:00:00:03       192.0.2.0  640     dynamic  guest    ge-0/0/12.0
00:00:01:00:00:04       192.0.2.1  720     dynamic  guest    ge-0/0/12.0
00:00:01:00:00:05       192.0.2.5  800     dynamic  guest    ge-0/0/13.0

Attention, il y a quelques pièges. Par exemple, s'il existe plusieurs chemins entre le client et le serveur DHCP, et que la machine SAVI n'est que sur un seul de ces chemins, elle risque de rater le dialogue DHCP. Autre cas problématique si une machine se déplace d'un port à un autre sans refaire une requête DHCP.

La section 7 propose des solutions à ces problèmes de faux positifs. L'idée est de noter le trafic rejeté par SAVI-DHCP et de vérifier activement si le paquet a été rejeté à tort (le mal nommé « Data Snooping Process »). Par exemple, en IPv4, on peut envoyer des requêtes ARP (RFC 826 et RFC 5227) pour déterminer si deux machines (la vraie et l'usurpatrice) utilisent la même adresse IP (s'il n'y a qu'une machine, la vraie, on ne recevra qu'une réponse). En IPv6, on peut utiliser un message DAD (Duplicate Address Detection, cf. RFC 4862, section 5.4) pour faire le même test.

On peut aussi, si on a raté ou qu'on pense avoir raté le dialogue DHCP, demander directement au serveur DHCP, avec un message DHCPLEASEQUERY (RFC 4388) en IPv4 et LEASEQUERY (RFC 5007) en IPv6.

Bref, comme toujours en sécurité, on n'a pas de repas gratuit : SAVI-DHCP protège contre bien des usurpations mais, comme toute technique de filtrage, il peut mener au rejet de messages légitimes.

Le mécanisme de SAVI-DHCP nécessite de mémoriser un état, la BST (Binding State Table, décrite en section 5). Si elle est gardée en RAM et qu'on redémarre, la liste des liens est perdue et tous les paquets seront rejetés (c'est pourquoi, en général, IP déconseille de garder de l'état dans le réseau). La section 9 rappelle ce problème et demande donc que la BST soit stockée dans une mémoire qui survit aux redémarrages. (On pourrait récupérer un bon bout de la BST par les méthodes de la section 7 mais ça prendrait un temps fou.) À noter que, sur un Juniper, ce n'est pas fait par défaut (il faut la directive dhcp-snooping-file pour stocker la BST).

Terminons ce résumé du RFC avec la section 11, consacrée aux questions de sécurité. D'abord, les risques que crée le Data Snooping process de la section 7. Comme ce processus est coûteux en nombre de paquets envoyés, un attaquant pourrait être tenté de le déclencher afin de réaliser une attaque par déni de service. Pour cela, il aurait juste à envoyer quelques paquets usurpés. Le processus doit donc avoir une limitation de trafic.

Plusieurs autres attaques sont possibles contre ce mécanisme de sécurité complexe qu'est SAVI-DHCP (réutiliser l'adresse d'un client qui est parti et ne peut donc plus se défendre en cas de détection d'adresse dupliquée, créer de nombreux liens pour remplir la BST et faire une attaque par déni de service, etc). Il y a aussi un risque sur la vie privée, puisque la BST stocke de nombreuses informations sur l'arrivée et le départ des machines des utilisateurs. Elle ne doit donc pas être archivée. L'idée est qu'aucune information ne devrait être gardée sur les machines qui n'usurpent jamais d'adresse IP (ne pas fliquer les gens honnêtes).

À noter que Cisco prétend avoir inventé la technique et a un brevet sur l'idée, mais propose une licence (avec clause de représailles).

Merci à Cécile Grange pour des indications sur les solutions Juniper.


Téléchargez le RFC 7513


L'article seul

RFC 7564: PRECIS Framework: Preparation, Enforcement, and Comparison of Internationalized Strings in Application Protocols

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : P. Saint-Andre (&yet), M. Blanchet (Viagenie)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF precis
Première rédaction de cet article le 7 juin 2015


Dans la longue marche vers une plus grande internationalisation de l'Internet, la question des identificateurs (comme par exemple les noms de domaine) a toujours été délicate. Ce sont en effet à la fois des éléments techniques, traités automatiquement par les programmes, et des marqueurs d'identité, vus par les humains (par exemple sur des cartes de visite) et manipulés par eux. Jusqu'à présent, chaque protocole internationalisait ses identificateurs comme il le souhaitait. Ce RFC du groupe de travail PRECIS tente une approche unificatrice, en élaborant des règles qui peuvent servir à de larges classes d'identificateurs, pour de nombreux protocoles différents.

Cette opposition entre « éléments techniques » et « textes prévus pour l'utilisateur » est au cœur du RFC 2277 qui pose comme principe politique qu'on internationalise les seconds, mais pas les premiers. Cet excellent principe achoppe souvent sur la question des identificateurs, qui sont les deux à la fois. D'un côté, les programmes doivent les traiter (les identificateurs doivent donc être clairement définis, sans ambiguité), de l'autre les humains les voient, les communiquent, les échangent (les identificateurs doivent donc permettre, sinon toutes les constructions du langage humain, en tout cas un sous-ensemble d'Unicode qui parait raisonnable aux humains ordinaires : pas question d'imposer stephane comme nom de login à un utilisateur nommé Stéphane, avec un accent sur le E). C'est cette double nature des identificateurs (ainsi, il est vrai, que l'énorme couche de bureaucratie qui gère les noms de domaine) qui explique la durée et la vivacité des discussions sur les IDN.

Maintenant que ces IDN existent (depuis plus de douze ans, RFC 3490), que faire avec les autres identificateurs ? Une possibilité aurait été que chaque protocole se débrouille avec ses propres identificateurs, comme l'a fait le DNS avec les noms de domaine. Mais cela menait à une duplication du travail (et tous les auteurs de protocole ne sont pas des experts Unicode) et surtout à un risque de choix très différents : certains protocoles autoriseraient tel caractère Unicode et d'autres pas, sans que l'utilisateur ordinaire puisse comprendre clairement les raisons de cette différence. L'idée de base du groupe PRECIS est donc d'essayer de faire des règles qui s'appliqueraient à beaucoup de protocoles, épargnant aux concepteurs de ces protocoles de les concevoir eux-mêmes, et offrant à l'utilisateur une certaine homogénéité. Le premier RFC de PRECIS était la description du problème, dans le RFC 6885. Le second est la normalisation du cadre de définition des identificateurs internationalisés, dans ce RFC 7564. Ce cadre permet la manipulation d'identificateurs internationalisés (par exemple leur comparaison, comme lorsqu'un utilisateur tape son nom et son mot de passe, et qu'il faut les vérifier). Il remplace complètement l'ancien système stringprep du RFC 3454.

Le nom du groupe de travail PRECIS reflète les trois fonctions essentielles que vont faire les programmes qui manipulent les identificateurs internationalisés :

  • PRE pour la préparation des identificateurs, les opérations préliminaires comme la conversion depuis un jeu de caractères local non-Unicode,
  • E pour la vérification (enforcement) des règles, afin de déterminer si une chaîne de caractères Unicode est légale ou pas pour un usage donné,
  • C pour la comparaison entre les identificateurs, afin de déterminer leur égalité (« cette ressource n'est accessible qu'à l'utilisateur Thérèse or elle est connectée avec le nom therese »),
  • Le IS final étant pour Internationalized Strings.

A priori, les serveurs Internet seront responsables de la vérification, les clients n'ayant à faire qu'une préparation. Ayant souvent moins de ressources, les clients pourraient en effet avoir du mal à faire certaines opérations Unicode complexes (section 3).

Stringprep (RFC 3454) avait été développé pour le système IDN (RFC 3490) mais était conçu pour être généraliste, et certaines applications n'ayant rien à voir avec les noms de domaine avaient utilisé stringprep. Ce dernier avait des limites, certaines font l'objet d'un consensus, comme le fait que stringprep était lié à une version particulière d'Unicode, ce qui l'empêchait d'évoluer automatiquement lorsque le consortium Unicode publiait une nouvelle version (la version actuelle est la version 7, la plus récente est toujours à l'URL http://www.unicode.org/versions/latest/). D'autres limites étaient plus contestées (RFC 4690). IDN n'utilise plus stringprep depuis le RFC 5890.

Les principes du travail de PRECIS sont :

  • Définir un petit nombre (deux, actuellement) de classes spécifiant un jeu de caractères autorisés, classes applicables à un grand nombre d'usages.
  • Définir le contenu de ces classes en fonction d'un algorithme, reposant sur les propriétés Unicode (contrairement à stringprep où le contenu des classes était énuméré dans le RFC). Ainsi, lorsqu'une nouvelle version d'Unicode sort, il suffit de refaire tourner l'algorithme et on obtient le contenu à jour de la classe.
  • Spécifier les classes par une inclusion : tout caractère non explicitement listé comme membre de la classe est automatiquement exclu.
  • Permettre aux protocoles applicatifs de définir un profil d'une classe, à savoir une restriction de ses membres, ou bien d'autres précisions sur des sujets comme la normalisation Unicode. Il y aura ainsi probablement un profil pour les noms d'utilisateurs, un profil pour les mots de passe, etc. Notez qu'il est prévu que le nombre de profils reste limité, pour ne pas réintroduire l'excessive variété que voulait justement éviter PRECIS.

Si tout va bien, ces principes permettront l'indépendance vis-à-vis des versions d'Unicode (ou, plus exactement, la possibilité de passer à une nouvelle version d'Unicode sans faire une nouvelle norme incompatible), le partage des tables et du logiciel entre applications (par exemple par le biais de bibliothèques communes, utilisables si toutes les applications reposent sur PRECIS), et moins de surprises pour les utilisateurs, qui auraient été bien embêtés si chaque protocole Internet avait eu une manière complètement différente de prévoir l'internationalisation.

Bien, quelles sont donc les classes prévues par PRECIS (section 4) ? L'idée est de faire un compromis entre expressivité et sécurité. Qu'est-ce que la sécurité vient faire là dedans ? Personne ne le sait trop (le RFC utilise plusieurs fois safe et safety sans expliquer face à quels risques) mais Unicode fait souvent peur aux informaticiens anglo-saxons et il est donc courant d'estimer qu'il existe des caractères dangereux.

Il y a donc deux classes en tout et pour tout dans PRECIS : IdentifierClass et FreeformClass. La première classe servira à identifier utilisateurs, machines, pièces de discussions en messagerie instantanée, fichiers, etc, et ne permettra que les lettres, les nombres et quelques symboles (comme le ! ou le +). C'est contraignant mais l'idée est qu'on veut des désignations simples et sans ambiguïté, pas écrire des romans. La seconde classe servira à tout le reste (mots de passe, textes affichés comme la description d'une pièce XMPP, nom complet d'une machine, etc). Par exemple, une imprimante sera imprimante-jean-et-thérèse pour les protocoles qui demandent un nom de la classe IdentifierClass et Imprimante de Jean & Thérèse lorsqu'on pourra utiliser un nom FreeformClass.

Les classes sont définies par les caractères inclus et exclus. Plus précisément, un caractère peut être, pour une classe donnée (voir aussi la section 8) :

  • Valide (ou PVALID pour Protocol Valid),
  • Interdit,
  • Autorisé dans certains contextes seulement, c'est-à-dire que l'autorisation dépendra des caractères voisins (pas facile de trouver un exemple dans l'alphabet latin, cela sert surtout à d'autres écritures),
  • Pas encore affecté dans Unicode.

La classe IdentifierClass se définit donc par :

  • Caractères valides : les lettres et chiffres (rappelons qu'on définit des identificateurs internationalisés : on ne se limite donc pas aux lettres et chiffres latins), et les symboles traditionnels, ceux d'ASCII (comme le tiret ou le tilde).
  • Caractères valides dans certains contextes : ceux de la rare catégorie JoinControl du RFC 5892, section 2.8.
  • Caractères interdits : tout le reste (espaces, ponctuation, la plupart des symboles...).
  • Les caractères non encore affectés sont également interdits.

La classe Freeform Class se définit, elle, par :

  • Caractères valides : les lettres et chiffres (rappelons qu'on définit des identificateurs internationalisés : on ne se limite donc pas aux lettres et chiffres latins), les espaces, la ponctuation, les symboles.
  • Caractères valides dans certains contextes : ceux de la catégorie JoinControl plus quelques exceptions.
  • Caractères interdits : tout le reste, ce qui fait surtout les caractères de contrôle comme U+0007 (celui qui fait sonner votre ordinateur).
  • Les caractères non encore affectés sont également interdits.

Ces listes de caractères autorisés ou interdits ne sont pas suffisantes. Il y a d'autres points à régler (section 5), ce qui se fait typiquement dans les profils. Ainsi, un profil doit définir :

  • Normalisation Unicode à utiliser. NFC est recommandé.
  • La correspondance entre les caractères et leur version large (width mapping). Est-ce que FULLWIDTH DIGIT ZERO (U+FF10) doit être considéré comme équivalent au zéro traditionnel, de largeur « normale », U+0030 ? Notez que certaines normalisations (mais qui ne sont pas celle recommandée), comme NFKC, règlent le problème. Autrement, la recommandation du RFC est « oui, il faut rendre ces caractères équivalents » car l'utilisateur serait certainement surpris que target0 et target0 soient considérés différents (le fameux POLA).
  • D'autres correspondances peuvent être spécifiées par le profil (comme de transformer tous les espaces Unicode en l'espace traditionnel ASCII U+0020).
  • Changement de la casse des caractères, par exemple pour tout mettre en minuscules. Si c'est décidé pour un profil, le RFC recommande que cela soit fait avec la méthode Unicode standard, « Default case folding » (section 3 de la norme Unicode). Attention, cette méthode Unicode ne gère pas des cas qui dépendent de la langue, dont le plus fameux est le i sans point du turc (U+0131 c'est-à-dire ı). Le changement de casse est évidemment déconseillé pour les mots de passe (puisqu'il diminue l'entropie).
  • Interdiction de certains mélanges de caractères de directionnalité différentes. Il y a des écritures qui vont de gauche à droite et d'autres de droite à gauche, et leur combinaison peut entrainer des surprises à l'affichage. Dans certains cas, un profil peut vouloir limiter ce mélange de directionnalités.

Un profil peut également interdire certains caractères normalement autorisés (mais pas l'inverse).

Au passage, pour la comparaison, le RFC (section 7) impose un ordre à ces opérations. Par exemple, la mise en correspondance de la version large sur la version normale doit se faire avant l'éventuel changement de casse. C'est important car ces opérations ne sont pas commutatives entre elles.

Les profils sont enregistrés à l'IANA. Le RFC met bien en garde contre leur multiplication : toute l'idée de PRECIS est d'éviter que chaque protocole ne gère l'internationalisation des identificateurs de manière différente, ce qui empêcherait la réutilisation de code, et perturberait les utilisateurs. Si on avait un cadre commun mais des dizaines de profils différents, on ne pourrait pas dire qu'on a atteint cet objectif. Par exemple, en matière d'interface utilisateur, PRECIS essaie de s'en tenir au POLA (Principle of Least Astonishment) et ce principe serait certainement violé si chaque application trouvait rigolo d'interdire un caractère ou l'autre, sans raison apparente. Le RFC estime d'ailleurs (section 5.1) qu'il ne devrait y avoir idéalement que deux ou trois profils. Mais ce n'est pas possible puisque les protocoles existent déjà, avec leurs propres règles, et qu'on ne peut pas faire table rase de l'existant (tous les protocoles qui ont déjà définis des caractères interdits, comme IRC, NFS, SMTP, XMPP, iSCSI, etc).

Un petit point en passant, avant de continuer avec les applications : vous avez noté que la classe IdentifierClass interdit les espaces (tous les espaces Unicode, pas seulement le U+0020 d'ASCII), alors que certaines applications acceptent les espaces dans les identificateurs (par exemple, Unix les accepte sans problèmes dans les noms de fichier, Apple permet depuis longtemps de les utiliser pour nommer Macintoshes et imprimantes, etc). La section 5.3 explique pourquoi :

  • Il est très difficile de distinguer tous ces espaces entre eux,
  • Certains interfaces utilisateurs risquent de ne pas les afficher, menant à confondre françoise durand avec françoisedurand.

C'est embêtant (toute contrainte est embêtante) mais le compromis a semblé raisonnable au groupe PRECIS.

Passons maintenant aux questions des développeurs d'applications (section 6 du RFC). Que doivent-ils savoir pour utiliser PRECIS correctement ? Idéalement, il suffirait de lier son code aux bonnes bibliothèques bien internationalisées et tout se ferait automatiquement. En pratique, cela ne se passera pas comme ça : sans être obligé de lire et de comprendre tout le RFC, le développeur d'applications devra quand même réflechir un peu à l'internationalisation de son programme :

  • Il est très déconseillé de créer son propre profil. Non seulement c'est plus compliqué que ça n'en a l'air, mais ça risque de dérouter les utilisateurs, si votre application a des règles légèrement différentes des règles des autres applications analogues.
  • Précisez bien quel partie de l'application va être responsable pour la préparation, la vérification et la comparaison. Par exemple, le travail de vérification sera-t-il fait par le client ou par le serveur ? Demandez-vous aussi à quel stade les applications devront avoir fait ce travail (par exemple, en cas de login, avant de donner un accès).
  • Définissez bien, pour chaque utilisation d'un identificateur (chaque slot, dit le RFC), quel profil doit être utilisé. Par exemple, « le nom du compte doit être conforme au profil UsernameCaseMapped de la classe IdentifierClass ».
  • Dressez la liste des caractères interdits (en plus de ceux déjà interdits par le profil) en fonction des spécificités de votre application. Par exemple, un @ est interdit dans la partie gauche d'une adresse de courrier électronique.

Sur ce dernier point, il faut noter que la frontière est mince entre « interdire plusieurs caractères normalement autorisés par le profil » et « définir un nouveau profil ». La possibilité d'interdire des caractères supplémentaires est surtout là pour s'accomoder des protocoles existants (comme dans l'exemple du courrier ci-dessus), et pour éviter d'avoir un profil par application existante.

Votre application pourra avoir besoin de constructions au dessus des classes existantes. Par exemple, si un nom d'utilisateur, dans votre programme, peut s'écrire « Prénom Nom », il ne peut pas être une instance de la classe IdentifierClass, qui n'accepte pas les espaces pour la raison indiquée plus haut. Il faudra alors définir un concept « nom d'utilisateur », par exemple en le spécifiant comme composé d'une ou plusieurs instances de IdentifierClass, séparées par des espaces. En ABNF :

username   = userpart *(1*SP userpart)
userpart   = ... ; Instance d'IdentifierClass

La même technique peut être utilisée pour spécifier des identificateurs qui ne seraient normalement pas autorisés par IdentifierClass comme stéphane@maçonnerie-générale.fr ou /politique/séries/Game-of-Thrones/saison05épisode08.mkv.

On a vu plus haut qu'un des principes de PRECIS était de définir les caractères autorisés de manière algorithmique, à partir de leur propriétés Unicode, et non pas sous la forme d'une liste figée (qu'il faudrait réviser à chaque nouvelle version d'Unicode). Les catégories de caractères utilisées par cet algorithme sont décrites en section 9. Par exemple, on y trouve :

  • LettersDigits qui rassemble les chiffres et les lettres. (Rappelez-vous qu'on utilise Unicode : ce ne sont pas uniquement les lettres et les chiffres d'ASCII.)
  • ASCII7, les caractères d'ASCII, à l'exception des caractères de contrôle,
  • Spaces, tous les espaces possibles (comme le U+200A, HAIR SPACE, ainsi appelé en raison de sa minceur),
  • Symbols, les symboles, comme U+20A3 (FRENCH FRANC SIGN, ₣) ou U+02DB (OGONEK, ˛),
  • Etc.

Plusieurs registres IANA sont nécessaires pour stocker toutes les données nécessaires à PRECIS. La section 11 les recense tous. Le plus important est le PRECIS Derived Property Value, qui est recalculé à chaque version d'Unicode. Il indique pour chaque caractère s'il est autorisé ou interdit dans un identificateur PRECIS. Voici sa version pour Unicode 6.3. (La version 7 est retardée par une tempête dans un verre d'eau.)

Les deux autres registres stockent les classes et les profils (pour l'instant, aucun). Les règles d'enregistrement dans le premier sont strictes (un RFC est nécessaire) et celles dans le second bien plus ouvertes (un examen par un expert est nécessaire).

La section 12 est consacrée aux problèmes de sécurité qui, comme toujours lorsqu'il s'agit d'Unicode, sont plus imaginaires que réels. Un des problèmes envisagés est celui du risque de confusion entre deux caractères qui sont visuellement proches. Le problème existe déjà avec le seul alphabet latin (vous voyez du premier coup la différence entre google.com et goog1e.com ?) mais est souvent utilisé comme prétexte pour retarder le déploiement d'Unicode. PRECIS se voulant fidèle au principe POLA, le risque de confusion est considéré comme important. Notez que le risque réel dépend de la police utilisée. Unicode normalisant des caractères et non pas des glyphes, il n'y a pas de solution générale à ce problème dans Unicode (les écritures humaines sont compliquées : c'est ainsi). Si le texte ᏚᎢᎵᎬᎢᎬᏒ ressemble à STPETER, c'est que vous utilisez une police qui ne distingue pas tellement l'alphabet cherokee de l'alphabet latin. Est-ce que ça a des conséquences pratiques ? Le RFC cite le risque accru de hameçonnage, sans citer les nombreuses études qui montrent le contraire (cf. le Unicode Technical Report 36, section 2, « the use of visually confusable characters in spoofing is often overstated », et la FAQ de sécurité d'Unicode).

Quelques conseils aux développeurs concluent cette partie : limiter le nombre de caractères ou d'écritures qu'on accepte, interdire le mélange des écritures (conseil inapplicable : dans la plupart des alphabets non-latins, on utilise des mots entiers en alphabet latin)... Le RFC conseille aussi de marquer visuellement les identificateurs qui utilisent plusieurs écritures (par exemple en utilisant des couleurs différentes), pour avertir l'utilisateur.

C'est au nom de ce principe POLA que la classe IdentifierClass est restreinte à un ensemble « sûr » de caractères (notez que ce terme « sûr » n'est jamais expliqué ou défini dans ce RFC). Comme son nom l'indique, FreeformClass est bien plus large et peut donc susciter davantage de surprises.

PRECIS gère aussi le cas des mots de passe en Unicode. Un bon mot de passe doit être difficile à deviner ou à trouver par force brute (il doit avoir beaucoup d'entropie). Et il faut minimiser les risques de faux positifs (un mot de passe accepté alors qu'il ne devrait pas : par exemple, des mots de passe insensibles à la casse seraient agréables pour les utilisateurs mais augmenteraient le risque de faux positifs). L'argument de l'entropie fait que le RFC déconseille de créer des profils restreints de FreeformClass, par exemple en excluant des catégories comme la ponctuation. Unicode permet des mots de passe vraiment résistants à la force brute, comme « 𝃍🐬ꢞĚΥਟዶᚦ⬧ »... D'un autre côté, comme le montre l'exemple hypothétique de mots de passe insensibles à la casse, il y a toujours une tension entre la sécurité et l'utilisabilité. Laisser les utilisateurs choisir des mots de passe comportant des caractères « exotiques » peut poser bien des problèmes par la suite lorsqu'utilisateur tentera de les taper sur un clavier peu familier. Il faut noter aussi que les mots de passe passent parfois par des protocoles intermédiaires (comme SASL, RFC 4422, ou comme RADIUS, RFC 2865) et qu'il vaut donc mieux que tout le monde utilise les mêmes règles pour éviter des surprises (comme un mot de passe refusé par un protocole intermédiaire).

Enfin, la section 13 de notre RFC se penche sur l'interopérabilité. Elle rappele qu'UTF-8 est l'encodage recommandé (mais PRECIS est un cadre, pas un protocole complet, et un protocole conforme à PRECIS peut utiliser un autre encodage). Elle rappelle aussi qu'il faut être prudent si on doit faire circuler ses identificateurs vers d'autres protocoles : tous ne savent pas gérer Unicode, hélas.


Téléchargez le RFC 7564


L'article seul

Qualité des clés cryptographiques

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


A priori, une clé cryptographique en vaut une autre, non ? Ce sont toutes des chaînes de bits incompréhensibles ? Mais non : une clé peut, sous une apparence normale, avoir des caractéristiques qui la rendent plus ou moins vulnérable à certaines attaques cryptanalytiques. Deux analyses récentes ont testé des grands ensembles de clés et ont parfois trouvé des failles.

La première porte sur les clés PGP stockées dans les serveurs de clé. Ces serveurs sont utilisés pour distribuer les clés publiques. Étant librement accessibles, ils permettent d'analyser par la suite la qualité des clés. C'est ce qu'a fait l'étude « A look at the PGP ecosystem through the key server data ». L'auteur télécharge les clés depuis les serveurs qui fournissent un moyen d'accès en masse, puis les analyse. Il a développé pour cela un analyseur en Python. (J'ai déjà parlé du manque regrettable d'outil de test automatique de la qualité d'une clé PGP.)

Je vous préviens tout de suite, cette analyse n'a montré aucun grave problème (tant mieux ! À moins que les problèmes n'aient pas été détectés... ) Par exemple, une faiblesse connue de DSA (et ECDSA) est la nécessité d'utiliser une valeur imprévisible (et pas forcément aléatoire, contrairement à ce qu'on lit souvent, cf. RFC 6979) à chaque signature. Le non-respect de cette règle a permis, par exemple, le libre accès à la PlayStation. L'auteur a donc cherché des exemples de plusieurs signatures (les serveurs de clés stockent des clés signées par d'autres clés, donc on a aussi un lot de signatures) faites avec le même paramètre. Les deux seuls cas trouvés concernaient des signatures incorrectes (les serveurs de clés ne testent pas les données soumises et on peut donc trouver des données corrompues) ou bien les clés de PrimeFactors, une société qui commercialise des solutions cryptographiques (!) et qui a répondu à l'alerte de sécurité de l'auteur par une explication montrant qu'ils n'avaient pas compris le problème. Bon rappel que les seules solutions de sécurité sérieuses sont en logiciel libre.

D'autres tests faits sur les clés PGP ont également été des échecs (du point de vue du chercheur : pour la sécurité, c'est une bonne chose !) Par exemple, deux clés RSA partageaient un facteur premier mais l'adresse associée à la clé, alice@example.com donne à penser qu'il ne s'agissait pas d'une vraie clé, avec une vraie utilisatrice, mais plutôt d'une expérimentation avec des clés délibérement vulnérables.

Bref, chou blanc, pas de problème sensationnel noté pendant l'analyse des clés PGP.

Une autre étude a donné des résultats plus inquiétants. « Auditing GitHub users’ SSH key quality » est le récit d'un audit des clés SSH utilisés sur GitHub (dont j'ai découvert à cette occasion qu'elles sont publiques, voir par exemple les miennes en https://github.com/bortzmeyer.keys). L'auteur a pu faire des statistiques, par exemple sur le type de clés (nette domination de RSA, DSS loin derrière et les courbes elliptiques encore plus).

Mais il a aussi trouvé des choses plus inquiétantes comme des clés RSA de seulement 256 bits (!) Une telle clé se factorise en 25 minutes sur un vieux processeur. Plus étonnant, GitHub stocke encore plusieurs clés qui ont été générées par la bogue Debian. Et ces clés « protègent » (cela a été corrigé depuis) des dépôts logiciels importants comme les bibliothèques cryptographiques de Python (!).

C'est donc l'occasion de rappeler que la cryptographie ne fait pas de miracles : il ne suffit pas d'utiliser PGP ou SSH pour être en sécurité, il faut aussi s'assurer de la solidité des clés. Il faudrait vraiment que des programmeurs courageux développent un site Web où on pourrait soumettre ses clés privées (non, je rigole, ses clés publiques) SSH ou PGP et avoir des diagnostics, du genre « clé privée prévisible suite à la bogue Debian » ou bien « clé trop courte » ou encore « facteur premier déjà vu ».


L'article seul

RFC 7526: Deprecating Anycast Prefix for 6to4 Relay Routers

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : O. Troan (Cisco), B. Carpenter (Univ. of Auckland)
Réalisé dans le cadre du groupe de travail IETF v6ops
Première rédaction de cet article le 4 juin 2015


6to4 en anycast, c'est fini ! Cette technique de transition entre IPv4 et IPv6, reposant sur des tunnels établis automatiquement, a pu être utile à un moment pour faciliter l'accès à IPv6 depuis les opérateurs qui étaient en retard pour le déploiement. Mais elle a plein de défauts techniques, qui ont contribué à donner une mauvaise image d'IPv6. Elle est donc marquée par ce RFC comme officiellement abandonnée.

C'est dans le RFC 3068 que 6to4+anycast était normalisé (il existe plein d'autres techniques de transition). Le principe était d'avoir des relais anycast qui recevaient les paquets IPv6 encapsulés dans de l'IPv4, tunnelant ainsi le trafic IPv6 au-dessus d'opérateurs restés en IPv4. Pour éviter d'avoir à configurer manuellement ces relais, une correspondance existait entre les adresses IPv4 des machines, et des adresses IPv6 attribuées dans un préfixe spécifique à 6to4, le 2002::/16 (le réseau IPv6 associé à une adresse IPv4 était 2002:adresse-IPv4::/48). Des outils comme whois connaissaient ce préfixe et savaient donc faire une recherche « intelligente » (ici, d9ae:c921 = 217.174.201.33) :

% whois 2002:d9ae:c921::1

Querying for the IPv4 endpoint 217.174.201.33 of a 6to4 IPv6 address.
...
[affichage des informations au sujet de 217.174.201.33]

Un autre préfixe, en IPv4, était attribué aux relais, pour que les mécanismes de l'anycast trouvent ensuite le relais le plus proche. C'est ce second préfixe, 192.88.99.0/24, qui est retiré du service par ce RFC. En outre, le RFC 3068 est désormais marqué comme « intérêt historique seulement ».

La première version de ces tunnels automatiques, spécifiée dans le RFC 3056, utilisait un adressage unicast. C'est avec le RFC 3068 que 6to4 est passé à l'anycast. Les relais étaient gérés par des tas de volontaires situés sur la planète mais, en pratique, beaucoup marchaient mal ou pas du tout et l'anycast ne permettait pas de garantir qu'on tombe sur un relais valide, encore moins sur un relais proche et rapide. L'étude « Flailing IPv6 » a montré la quantité de problèmes que posait 6to4. Un test avec les sondes RIPE Atlas montre 23 % de timeout sur un serveur 6to4, 2002:d9ae:c921::1, contre 10 % pour une adresse IPv6 native. En test DNS, 343 sondes Atlas sur 470 répondent pour l'adresse 2002:d9ae:c921::1, contre 490 sur 500 pour l'adresse IPv4 du même serveur, 217.174.201.33.

Un résultat tragique de cette mauvaise qualité a été de ralentir le déploiement d'IPv6, bien des utilisateurs coupant IPv6 lorsqu'ils découvraient la lenteur et les pannes de 6to4, bien des gérants de serveurs ne fournissant pas IPv6 de peur que cela entraine une dégradation de la qualité de service.

Le RFC 6343 analysait le problème et faisait des recommandations pour améliorer 6to4. Il recommandait que 6to4 soit coupé par défaut (un scénario commun, avant, était que 6to4 était activé sans demande explicite, le trafic IPv6 passait par un relais lointain, et l'utilisateur en concluait qu'IPv6 était lent) : « it should always be a conscious decision by a user to enable 6to4 ». Le RFC 6343 recommandait aussi de suivre l'algorithme des « globes oculaires heureux » du RFC 6555, afin de masquer les défaillances éventuelles d'une des familles, IPv4 ou IPv6.

Mais ces conseils, quoique assez largement mis en œuvre, ne suffisent pas, et les serveurs accessibles en IPv6 voient toujours du trafic 6to4.

À noter que la technologie 6rd, normalisée dans le RFC 5969, est très proche de 6to4 mais s'en distingue par l'utilisation d'un préfixe IPv6 lié au fournisseur d'accès. Les relais, au lieu d'être gérés un peu partout par des volontaires inconnus, sont donc forcément sous la houlette du FAI qui utilise 6rd, et il peut donc garantir une voie de retour. 6rd n'est donc pas concerné par les critiques de notre RFC.

La section 3 revient en détail sur les problèmes rencontrés avec 6to4. Elle rappelle que les routes peuvent être asymétriques (un relais différent à l'aller et au retour). Si le choix du relais aller peut être contrôlé (par exemple par des préférences BGP pour telle ou telle annonce du préfixe 192.88.99.0/24), le chemin de retour échappe complètement au nœud 6to4, qui ne peut pas être sûr que ses pairs utiliseront un « bon » relais. C'est le cœur du problème de 6to4. (Notez bien que cela ne concerne que le mode anycast, avec le prefixe standard. Des variantes de 6to4, avec un préfixe contrôlé par le FAI, ou avec de l'unicast vers des relais connus, ne sont pas concernées par ce RFC. C'est par exemple le cas de 6rd, cité plus haut)

La section 4 du RFC contient les décisions formellement prises :

  • Le mécanisme d'anycast de 6to4 du RFC 3068 est abandonné,
  • Le préfixe 192.88.99.0/24 est marqué comme abandonné (dans le registre IANA),
  • Le 6to4 en unicast du RFC 3056 reste utilisable, tout comme le préfixe 2002::/16, c'est uniquement son annonce en anycast qui est abandonnée,
  • Les règles de sélection de l'adresse source du RFC 6724 ne sont pas modifiées (elles donnent la priorité à IPv4 sur 6to4, contrairement aux règles de son prédécesseur, le RFC 3484).

Comme indiqué dans la section 5, il est déconseillé d'inclure 6to4+anycast dans les mises en œuvre d'IPv6 et, si on le fait, il faut qu'il soit désactivé par défaut. (Bien des CPE IPv6 avaient imprudemment activé ce mécanisme par défaut, pour fournir une connectivité IPv6 dans tous les cas, même au-dessus d'un opérateur resté uniquement à IPv4.)

En revanche, contrairement à ce qui avait parfois été proposé, notre RFC ne formule pas de recommandations sur le filtrage des annonces de route 6to4 (un tel filtrage bloquerait 6to4 chez l'opérateur qui le ferait). Il conseille par contre aux actuels opérateurs de relais 6to4 de se poser sérieusement la question « est-ce que c'est vraiment la peine de continuer ? » Ces recommandations (ou absence de recommandations) avaient fait l'objet des plus vigoureuses discussions au sein du groupe de travail à l'IETF.


Téléchargez le RFC 7526


L'article seul

RFC 7516: JSON Web Encryption (JWE)

Date de publication du RFC : Mai 2015
Auteur(s) du RFC : M. Jones (Microsoft), J. Hildebrand (Cisco)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF jose
Première rédaction de cet article le 3 juin 2015


L'ensemble de normes de cryptographie JOSE, qui permet de sécuriser des textes JSON comprend plusieurs RFC, dont ce RFC 7516, qui normalise le chiffrement, permettant d'assurer la confidentialité des documents JSON.

Un document chiffré est baptisé JWE (pour JSON Web Encryption). Il peut exister sous deux formes (deux sérialisations), une compacte (en Base64, cf. section 3.1), qui peut notamment être utilisée dans les URL, et une en JSON, qui permet de passer par les programmes de traitement du JSON (sections 3.2 et 7.2.1). Elles utilisent les mêmes mécanismes cryptographiques sous-jacents. Les algorithmes utilisables sont normalisés dans le RFC 7518. Il est recommandé de lire également le RFC sur les signatures JOSE (RFC 7515) car beaucoup de règles applicables à la fois à la signature et au chiffrement ne sont décrites que dans ce RFC 7515 (comme la comparaison des chaînes de caractères de la section 5.3).

Les principes de base de JWE sont exposés dans la section 3 du RFC (en s'appuyant que la terminologie de la section 2). Quelle que soit la sérialisation choisie, un JWE peut comprendre :

  • L'en-tête JOSE, lui-même composé d'une partie protégée et d'une ou plusieurs parties non protégées,
  • La clé cryptographique, chiffrée,
  • Le vecteur d'initialisation,
  • L'AAD (Additional Authenticated Data), protégée en intégrité mais pas chiffrée, qui sert lorsqu'on fait de l'AEAD,
  • Le texte chiffré (et donc illisible par un indiscret),
  • L'authentication tag.

Dans la sérialisation en JSON, les composants binaires (comme le texte chiffré) sont encodés en Base64, JSON n'ayant pas de mécanisme pour les données binaires.

Un JWE en sérialisation compacte est la concaténation des différents composants cités ci-dessus, chacun encodé en Base64 (un exemple figure en section 3.3). Un JWE en sérialisation JSON est un objet JSON comportant un membre par composant, par exemple iv pour le vecteur d'initialisation, ciphertext pour le texte chiffré, recipients pour des informations sur les destinataires (optionnel : s'il n'y a qu'un seul destinataire, on peut mettre ces informations dans l'objet JWE, cf. section 7.2.2).

L'en-tête JOSE est détaillé dans la section 4. Il inclut la plupart des paramètres cryptographiques. On le représente par un objet JSON (qui sera ensuite encodé en Base64). Cet objet a des membres comme alg (l'algorithme de chiffrement utilisé pour la clé, en général un algorithme de chiffrement asymétrique) ou enc (l'algorithme de chiffrement utilisé pour le contenu, en général un algorithme de chiffrement symétrique), etc. Les algorithmes possibles sont décrits dans le RFC 7518. De nombreux autres membres sont possibles comme zip pour indiquer l'éventuel algorithme de compression utilisé (par exemple celui du RFC 1951).

Le mécanisme complet de chiffrement et de déchiffrement (ce dernier est l'inverse du chiffrement) est décrit dans la section 5. Voici un exemple, tiré de l'annexe A.4 : il y a deux destinataires, le premier utilisera RSA et le second AES pour chiffrer la clé :

"recipients":[
       {"header":
         {"alg":"RSA1_5","kid":"2011-04-29"},
       {"header":
         {"alg":"A128KW","kid":"7"},
	 ...

Le texte sera chiffré avec AES en mode CBC avec du HMAC sur SHA-256 pour produire l'authentication tag :

  {"enc":"A128CBC-HS256"}

(Cet objet formera l'en-tête protégé.) En utilisant cette valeur pour le vecteur d'initialisation :

  "iv":       "AxY8DCtDaGlsbGljb3RoZQ",

et cette clé de chiffrement :

  {"kty":"oct",
      "k":"GawgguFyGrWKav7AX4VKUg"
      }

Et le message en clair « Live long and prosper. », on arrive à ce JWE complet :

  {
      "protected":
       "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0",
      "unprotected":
       {"jku":"https://server.example.com/keys.jwks"},
      "recipients":[
       {"header":
         {"alg":"RSA1_5","kid":"2011-04-29"},
        "encrypted_key":
         "UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-
          kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKx
          GHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3
          YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPh
          cCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPg
          wCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A"},
       {"header":
         {"alg":"A128KW","kid":"7"},
        "encrypted_key":
         "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ"}],
      "iv":
       "AxY8DCtDaGlsbGljb3RoZQ",
      "ciphertext":
       "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY",
      "tag":
       "Mz-VPPyU4RlcuYv1IwIvzw"
       }

Pour du code qui met en œuvre le chiffrement JOSE, voir mon article général.


Téléchargez le RFC 7516


L'article seul

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

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