Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

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


RFC 9184: BGP Extended Community Registries Update

Date de publication du RFC : Janvier 2022
Auteur(s) du RFC : C. Loibl (next layer Telekom)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 21 janvier 2022


Les « communautés étendues » de BGP, des attributs d'une annonce de route avec BGP, sont enregistrées dans des registres IANA, décrits par le RFC 7153. Notre nouveau RFC 9184 met légèrement à jour les procédures d'enregistrement dans ces registres.

Le principal changement est simple : les types 0x80, 0x81 et 0x82 du registre des communautés étendues transitives sont désormais utilisables selon une politique d'enregistrement « premier arrivé, premier servi » (cf. RFC 8126 sur ces politiques d'enregistrement à l'IANA). Ils sont en effet utilisés par le RFC 8955 alors qu'ils étaient dans une plage prévue pour les expérimentations. L'erreur est donc désormais rectifiée.


Téléchargez le RFC 9184


L'article seul

Amusant problème DNS Orange/Oléane/Google

Première rédaction de cet article le 19 janvier 2022


Les résolveurs DNS utilisés entre autres par Orange Business Services renvoient l'adresse locale localhost (127.0.0.1) pour des noms chez Google.

Cela ne concerne apparemment que les résolveurs 194.2.0.20 et 194.2.0.50, qui ne semblent pas utilisés par tout le monde chez Orange (comme l'indique leur nom, ce sont des anciennes machines d'Oléane, société rachetée par Orange). Vu avec les sondes RIPE Atlas :

% blaeu-resolve -r 100 --as 3215  --nameserver 194.2.0.20 --type A www.google.com
Nameserver 194.2.0.20
[142.250.179.68] : 20 occurrences 
[216.58.213.164] : 14 occurrences 
[127.0.0.1] : 13 occurrences 
[216.58.214.164] : 6 occurrences 
[216.58.206.228] : 11 occurrences 
[216.58.213.68] : 11 occurrences 
[142.250.179.100] : 11 occurrences 
[216.58.213.132] : 5 occurrences 
[172.217.18.196] : 8 occurrences 
Test #34858799 done at 2022-01-19T14:07:44Z
  

La ligne importante est celle avec 127.0.0.1. Notez donc que ce résolveur ne répond pas toujours avec cette adresse. Un problème analogue existe en IPv6 :

% blaeu-resolve -r 100 --as 3215  --nameserver 194.2.0.20 --type AAAA www.google.com
Nameserver 194.2.0.20
[2a00:1450:4007:80e::2004] : 12 occurrences 
[2a00:1450:4007:813::2004] : 29 occurrences 
[2a00:1450:4007:811::2004] : 11 occurrences 
[2a00:1450:4007:810::2004] : 11 occurrences 
[2a00:1450:4007:806::2004] : 14 occurrences 
[::1] : 11 occurrences 
[2a00:1450:4007:817::2004] : 11 occurrences 
Test #34858911 done at 2022-01-19T14:35:32Z
  

Pourquoi est-ce que la même adresse IP, 194.2.0.20, donne des résultats différents aux sondes, le tout dans un intervalle de temps très court ? Probablement parce que derrière cette adresse, il y a plusieurs machines physiques, avec des configurations différentes.

Plusieurs personnes ont signalé ce problème par exemple sur Twitter (ici ou ), sans réponse d'Orange. Le problème est bien du côté de ces résolveurs, pas des serveurs faisant autorité pour google.com. (Notez qu'aucun autre domaine ne semble avoir été touché, par exemple google.fr n'a pas eu de problème.) En dehors de ces résolveurs, on ne voit pas de problème :

% blaeu-resolve -c FR -r 100 - -type A alt2.gmail-smtp-in.l.google.com.
[142.250.150.27] : 53 occurrences 
[74.125.200.27] : 1 occurrences 
[142.250.150.26] : 43 occurrences 
[74.125.200.26] : 2 occurrences 
[173.194.202.27] : 1 occurrences 
Test #34858791 done at 2022-01-19T14:05:34Z
  

Les signalements à DownDetector sont réels mais trompeurs, Google n'y étant apparemment pour rien : downdetector-google-oleane-dns.png

Quelques heures plus tard, le problème était apparemment réparé :

%   blaeu-resolve -r 100 --as 3215  --nameserver 194.2.0.20 --type A www.google.com 
Nameserver 194.2.0.20
[216.58.206.228] : 17 occurrences 
[216.58.213.164] : 30 occurrences 
[142.250.179.68] : 24 occurrences 
[142.250.74.228] : 12 occurrences 
[142.250.186.36] : 1 occurrences 
[216.58.214.164] : 16 occurrences 
Test #34861409 done at 2022-01-19T20:08:59Z

La réponse d'Orange à ses clients : « ORANGE INFO INCIDENT xxxxxx Il y avait un problème de résolution sur le service Cache DNS. Nous avons fait un changement au niveau de nos serveurs. Le service est rétabli depuis hier soir 18H . Nous passons à la cloture du ticket. »

Quelle est la cause de la panne ? On l'ignore et il est certain qu'Orange ne communiquera rien. Rappelons juste que le DNS est un service critique de l'Internet et qu'il est donc essentiel de ne pas vouloir le bricoler à des fins, par exemple, de censure. (La panne est peut-être due à une erreur dans la configuration d'un résolveur menteur. Tout bricolage augmente les risques de panne, comme on l'a déjà vu chez Orange et comme le rapport du Conseil Scientifique de l'Afnic avait déjà alerté à ce sujet.)


L'article seul

Fiche de lecture : Vivre libre au 21e siècle

Auteur(s) du livre : Thierry Bayoud, Léa Deneuville
Éditeur : Xérographes
978-2-917717-56-1
Publié en 2021
Première rédaction de cet article le 18 janvier 2022


Ce petit livre a comme sous-titre « Le leurre du progrès technologique ». Mais il ne parle pas que du progrès technique, il explore les absurdités et les problèmes de la société actuelle.

Ce livre examine une grande variété de sujets : le logiciel libre, la publicité, la consommation, la langue, le travail, l'argent, la mondialisation et d'autres encore. Le regard est critique : notre société a vraiment beaucoup de problèmes. Bien des chapitres sont justes mais pas forcément originaux (sa critique de la publicité est tout à fait correcte mais ne me semble pas apporter de nouveaux arguments). Moins communs, son plaidoyer pour une « monnaie libre » (il conseille Ğ1, tout en notant ses limites) ou sa défense bien argumentée de la langue française (sujet rarement abordé dans son camp politique). De même, le chapitre sur le numérique ne cède pas, contrairement à tant de livres qui critiquent notre société, à l'anti-numérisme primaire. Et l'auteur (les auteurs) proposent de nombreuses pistes d'amélioration.

Le livre est bien écrit, clair et sans jargon. Si vous avez déjà lu beaucoup de livres critiquant la société capitaliste, vous n'y lirez sans doute pas beaucoup de nouveautés. Mais ce livre peut être utilisé avec profit pour un début de réflexion.

Petite déclaration de conflit d'intérêts : j'ai reçu un exemplaire gratuit de ce livre.

Il y a eu une recension plus détaillée sur LinuxFr.


L'article seul

RFC 9124: A Manifest Information Model for Firmware Updates in Internet of Things (IoT) Devices

Date de publication du RFC : Janvier 2022
Auteur(s) du RFC : B. Moran, H. Tschofenig (Arm Limited), H. Birkholz (Fraunhofer SIT)
Pour information
Réalisé dans le cadre du groupe de travail IETF suit
Première rédaction de cet article le 15 janvier 2022


On le sait, la sécurité des gadgets nommés « objets connectés » est abyssalement basse. Une de raisons (mais pas la seule, loin de là !) est l'absence d'un mécanisme de mise à jour du logiciel, mécanisme qui pourrait permettre de corriger les inévitables failles de sécurité. Le problème de la mise à jour de ces machins, souvent contraints en ressources, est très vaste et complexe. Le groupe de travail SUIT de l'IETF se focalise sur un point bien particulier : un format de manifeste permettant de décrire une mise à jour. Ce RFC décrit le modèle de données des informations qui seront placées dans ce manifeste.

Donc, que faut-il indiquer pour permettre une mise à jour du logiciel (et des réglages) d'un objet connecté ? Le groupe de travail est parti des expériences concrètes, de scénarios et de menaces, pour arriver à la liste que contient ce RFC. Certes, cette liste n'est pas exhaustive (cela serait impossible) mais donne quand même un bon point de départ. Attention, ce RFC décrit le modèle d'information (cf. RFC 3444), pas le format du manifeste (qui sera en CBOR, et fera l'objet d'un futur RFC).

Pour suivre le contenu de ce RFC, il vaut mieux avoir déjà lu le premier RFC du groupe de travail, le RFC 9019, qui explique l'architecture générale du système, ainsi que le RFC 8240, qui était le compte-rendu d'un atelier de réflexion sur cette histoire de mise à jour des objets connectés..

La (longue) section 3 du RFC est consacrée à énumérer tous les éléments à mettre dans le manifeste. Je ne vais pas reproduire toute la liste, juste quelques éléments intéressants. Notez que pour chaque élément, le RFC précise s'il doit être présent dans le manifeste ou bien s'il est facultatif. Le premier élément listé est l'obligatoire identificateur de version de la structure du manifeste, qui permettra de savoir à quel modèle ce manifeste se réfère.

Autre élément obligatoire, un numéro de séquence, croissant de façon monotone, et qui permettra d'éviter les reculs accidentels (« mise à jour » avec une version plus ancienne que celle installée). On peut utiliser pour cela une estampille temporelle (si on a une horloge sûre).

Ensuite, le RFC recommande (mais, contrairement aux deux précédents éléments, ce n'est pas obligatoire) de placer dans le manifeste un identificateur du fournisseur de la mise à jour. Il n'est pas prévu pour d'autres comparaisons que la simple égalité. Le format recommandé pour cet identificateur est un UUID (RFC 4122) de « version 5 », c'est-à-dire formé à partir d'un nom de domaine, qui est forcément unique. L'avantage des UUID (surtout par rapport au texte libre) est leur taille fixe, qui simplifie analyse et comparaison. Si on veut un identificateur de fournisseur qui soit lisible par des humains, il faut le placer dans un autre élément.

L'identificateur de la classe (class ID), indique un type de machines, les machines d'une même classe acceptant le même logiciel (cette acceptation dépend du matériel mais aussi d'autres facteurs comme la version du microcode). Il doit être unique par identificateur de fournisseur (et, en cas de vente en marque blanche, il doit être fourni par le vrai fournisseur, pas par le vendeur). Là aussi, un UUID de « version 5 » est recommandé. Il ne doit pas dépendre juste du nom commercial, un même nom commercial pouvant recouvrir des produits qui n'acceptent pas les mêmes mises à jour. Si un objet peut recevoir des mises à jour indépendantes, pour différents composants de l'objet, il faut des identificateurs de classe différents (surtout si certains objets du fournisseur utilisent une partie des mêmes composants, mais pas tous ; l'identificateur doit identifier le composant, pas l'objet).

Le manifeste contient aussi (mais ce n'est pas obligatoire), une date d'expiration, indiquant à partir de quand il cesse d'être valable.

Le manifeste peut (mais ce n'est pas obligatoire) contenir directement l'image utilisée pour la mise à jour du logiciel de l'objet. Cela peut être utile pour les images de petite taille ; plus besoin d'une étape supplémentaire de téléchargement.

Par contre, l'indication du format de l'image, qu'elle soit directement incluse ou non, est obligatoire, ainsi que celle de la taille de la dite image.

Question sécurité, le RFC impose également la présence d'une signature du manifeste. Le manifeste peut aussi contenir des éléments qui vont servir à établir si on a une délégation sûre depuis une autorité reconnue : des Web Tokens en CBOR (RFC 8392), avec peut-être des preuves du RFC 8747.

La sécurité est au cœur des problèmes que traite ce RFC. Après cette liste d'élements facultatifs ou obligatoires dans un manifeste, la section 4 de notre RFC expose le modèle des menaces auxquelles il s'agit de faire face. Le RFC rappelle que la mise à jour elle-même peut être une menace : après tout, mettre à jour du logiciel, c'est exécuter du code distant. Juste répéter « il faut mettre à jour le logiciel de sa brosse à dents connectée » ne suffit pas, si le mécanisme de mise à jour permet d'insérer du code malveillant. (Et encore, le RFC est gentil, tendance bisounours, il ne rappelle pas que l'attaquant peut être le fournisseur, envoyant du code nouveau pour désactiver certaines fonctions ou pour espionner l'utilisateur, voir les exemples de Hewlett-Packard et de Sony. Sans même parler de la possibilité d'une attaque contre la chaine de développement comme celle contre SolarWinds.)

L'analyse part du modèle STRIDE. Je ne vais pas citer toutes les menaces possibles (il y en a beaucoup !), lisez le RFC pour avoir une vue complète. Notez que les attaques physiques contre les objets (ouvrir la boite et bricoler à l'intérieur) ne sont pas incluses.

Évidemment, la première menace est celle d'une mise à jour qui serait modifiée par un attaquant. Le code correspondant serait exécuté, avec les conséquences qu'on imagine. La signature prévient cette attaque.

Ensuite, le cas d'une vieille mise à jour, qui était honnête et signée, mais n'est plus d'actualité. Si elle a une faiblesse connue, un attaquant pourrait essayer de faire réaliser une « mise à jour » vers cette vieille version. Le numéro de séquence dans le manifeste, qui est strictement croissant, est là pour protéger de cette attaque.

Autre risque, celui d'une mise à jour signée mais qui concerne en fait un autre type d'appareil. Appliquer cette mise à jour pourrait mener à un déni de service. La protection contre ce risque est assurée par l'identificateur du type d'objet.

Le RFC liste la menace d'une rétro-ingénierie de l'image. Outre que cela ne s'applique qu'au logiciel privateur, du point de vue de la sécurité, cela n'est pas crucial, puisqu'on ne compte pas sur la STO. Si on y tient quand même, le chiffrement de l'image (qui n'est pas obligatoire) pare ce risque.

Sinon la section 4.4 contient des scénarios typiques d'utilisation, où une histoire décrit les acteurs, les menaces, les solutions possibles, rendant ainsi plus vivants et plus concrets les problèmes de sécurité étudiés dans ce RFC.


Téléchargez le RFC 9124


L'article seul

Fiche de lecture : The orphan tsunami of 1700

Auteur(s) du livre : Brian Atwater, Musumi-Rokkaku Satoko, Satake Kenji, Tsuji Yoshinobu, Ueda Kazue, David Yamaguchi
Éditeur : US Geological Survey / University of Washington Press
978-0-295-99808-4
Publié en 2015
Première rédaction de cet article le 12 janvier 2022


Le 26 janvier 1700, un tsunami a frappé le Japon et a été dûment enregistré dans les textes de l'époque. Mais ceux-ci se sont également étonnés de l'absence de tremblement de terre qui normalement précède les tsunamis (d'où le titre du livre, « Le tsunami orphelin »). Ce livre raconte l'enquête, et ses résultats ; on sait désormais d'où venait le tsunami.

Le principal intérêt du livre est qu'il plonge vraiment profondément dans les détails techniques : ce n'est pas écrit comme un roman, mais comme une étude détaillée de tous les aspects de l'enquête. De nombreuses illustrations, avec leurs légendes, des textes japonais de l'époque, des graphiques, des photos et des dessins, de quoi étudier pendant des heures. Il y a même une discussion des problèmes de calendrier, toujours difficiles pour les historiens quand il faut identifier une date du passé (les textes japonais de l'époque ne disaient pas « 26 janvier 1700 »…).

Un rapport de l'époque, avec son analyse : orphan-tsunami-text.png

Donc, à gauche du Pacifique, un tsunami orphelin. Pourrait-il venir d'un tremblement de terre lointain ? A-t-on des candidats ? Je vous le divulgâche tout de suite (mais c'est sur la couverture du livre), oui, des tremblements de terre de l'autre côté du Pacifique peuvent provoquer un tsunami au Japon et cela s'est produit, par exemple, lors du plus gros tremblement de terre connu, souvent mentionné dans le livre, car bien étudié. Mais à l'époque, dans la région du supposé tremblement de terre, on ne prenait pas de notes écrites. (Alors qu'au Japon de la période Edo, tout était noté et archivé, la bureaucratie était florissante.) Il faut donc faire parler les sols et les arbres, puis les dater pour être sûr qu'on a trouvé le coupable. Et le livre fait même de l'ethnologie, en interrogeant les traditions orales des Makahs.

Explication de ce qui arrive aux arbres : orphan-tsunami-trees.png

Un livre collectif qui couvre plein d'aspects : une telle enquête est un travail d'équipe. Il est rare d'avoir une enquête aussi totale sur un phénomène naturel.

Notez que le livre est vendu sous forme papier, mais qu'il est aussi en ligne, et dans le domaine public, comme toutes les publications des organismes du gouvernement fédéral étatsunien. Sinon, ce livre a été longuement présenté dans l'excellente émission de radio « Sur les épaules de Darwin ».


L'article seul

Fiche de lecture : Internet aussi, c'est la vraie vie

Auteur(s) du livre : Lucie Ronfaut-Hazard, Mirion Malle
Éditeur : La ville brûle
978-2-36012-134-2
Publié en 2022
Première rédaction de cet article le 11 janvier 2022


Ce livre explique l'Internet (bon, en pratique, plutôt les usages de l'Internet que le réseau lui-même) à un lectorat jeune.

Ce n'est pas une tâche facile : il faut être pédagogique sans être simplificateur, il faut être exact techniquement tout en étant compréhensible, il faut donner des conseils aux jeunes sans les prendre pour des imbéciles… Je trouve le résultat réussi et c'est un livre qu'on peut recommander à un public adolescent (ceci dit, je ne prétends pas bien connaitre ce public, donc prenez mon avis avec prudence).

Le titre résume bien le livre : contrairement à un discours conservateur courant, il n'y a pas « la vraie vie » d'un côté et le monde numérique de l'autre. Communiquer en étant physiquement proches et en se parlant, ou bien via une lettre en papier, ou bien via un logiciel de messagerie instantanée, c'est toujours communiquer, et ça a des conséquences, bonnes ou mauvaises. Les activités humaines se faisant très souvent via l'Internet, considérer qu'il ne serait pas de « la vraie vie » serait stupide. Donc, Internet, c'est la vraie vie. Mais, justement à cause de cela, il faut l'utiliser intelligemment. L'auteure et l'illustratrice vont parler successivement des GAFA, des données personnelles, des algorithmes de recommandation, du mensonge en ligne, de harcèlement, d'écologie, du Bitcoin, du sexisme, etc. (J'ai été étonné de la mention des cryptomonnaies : dans le public visé par ce livre, il y a des adolescent·es tenté·es par le Bitcoin ?)

L'auteure réussit bien à parler des sujets « à la mode » sans pour autant reprendre forcément tel quel le discours dominant. Par exemple, la section sur les mensonges en ligne (ce que les médias appelent fake news pour essayer de faire croire que c'est un phénomène spécifique au Web) traite ce sujet compliqué avec nuance. Et celle sur l'écologie essaie d'aller plus loin que les stupides recommandations « envoyez moins de messages » pour analyser plus en détail l'empreinte environnementale de nos usages du numérique. (Les caricatures qui illustrent le livre sont nettement plus… caricaturales que le texte.)

Par contre, en matière de harcèlement, il est à noter que les exemples citent de nombreux cas (le phénomène étant hélas répandu) mais ne mentionnent jamais les islamistes (comme dans le cas des attaques contre Mila), comme s'il y avait des bons harceleurs et des mauvais harceleurs. C'est d'autant plus ennuyeux que le dessin p. 39 semble un appel direct au harcèlement (oui, des méchants, mais c'est quand même glaçant, surtout que le texte met au contraire en garde contre les comportements de meute).

Le livre est court (probablement pour ne pas effrayer les lecteurs et lectrices potentiel·les avec un gros pavé) et ne peut donc pas tout traiter. Mais il est prévu pour des débutants, qui n'ont eu comme éducation au numérique que de vagues « c'est dangereux ». Parmi les points qui auraient pu être ajoutés (mais je comprends bien que le livre, vu son cahier des charges, se focalise sur ce qui existe aujourd'hui), on peut noter tout ce qui concerne la possibilité d'« alternatives » aux usages dominants. Par exemple, les algorithmes de recommandation sont discutés, mais sans remettre en cause l'existence même de ces algorithmes.


L'article seul

Portable Tuxedo Pulse 14

Première rédaction de cet article le 10 janvier 2022


Je viens d'acheter un nouvel ordinateur portable, et ce court article est là pour raconter deux ou trois choses.

Un des éléments de mon cahier des charges était la nécessité que ce PC fonctionne avec du logiciel libre, notamment pour le système d'exploitation. Cela ne va pas de soi car un certain nombre de fabricants d'ordinateurs mettent des composants (carte graphique, ACPI, UEFI) qui ne marchent qu'avec Windows et, si cela arrive, aucune chance de pouvoir obtenir de l'aide du vendeur (en dépit du discours traditionnel comme quoi « avec un produit qu'on achète, on a du support »). C'est scandaleux, mais fréquent, surtout avec les ordinateurs portables. Pour limiter les risques, j'ai donc acheté la machine chez Tuxedo, qui vend des PC pré-installés avec un système libre. Ainsi, normalement, tout fonctionne sans devoir bricoler et passer un temps fou sur des forums divers. J'ai choisi un Tuxedo Pulse 14 - Gen1. C'est un peu plus cher, à matériel équivalent, mais il est bon d'encourager ce genre de fournisseurs.

La machine à l'arrivée : tuxedo-pulse-14-arrival.jpg(Image en grand)

Un des intérêts de ce vendeur est que les machines ont un système d'exploitation pré-installé (un dérivé d'Ubuntu et vous avez bien sûr la possibilité de commander une machine nue et d'installer ce que vous voulez). Mais, vous allez me dire, comment ça marche si on veut un disque dur chiffré, ce qui est clairement indispensable pour un portable ? L'astuce est que le PC arrive avec un tel disque, et le mot de passe sur un papier inclus. Ce mot de passe n'est utilisé qu'une fois (et attention, au moment du démarrage, le clavier est encore en QWERTY, ce qui ne facilite pas sa saisie), on le remplace par un mot de passe que vous choisissez. (Les paranoïaques réinstalleront tout, de toute façon. Comme le fait remarquer FuraxFox, le risque le plus réaliste n'est pas celui de Tuxedo gardant les clés privées, mais celui d'une bogue dans le processus d'avitaillement qui mène à utiliser la même clé pour plusieurs machines.)

L'installation : tuxedo-pulse-14-install.jpg(Image en grand)

L'environnement graphique par défaut est GNOME, avec le bureau Budgie. Pour l'instant, j'ai quelques petits problèmes de ce côté-là (pas de clic droit avec le pavé tactile - il faut taper avec deux doigts sur le pavé pour avoir le même effet, pas trouvé comment modifier la barre en bas du bureau, couleurs très saturées quand j'envoie les vidéos sur un écran externe en HDMI, etc). Les joies d'un environnement nouveau… Il va falloir chercher un peu. (Il ne semble pas exister de forum des utilisateurs de Tuxedo.)

Les logiciels spécifiques à Tuxedo sont pré-installés et leur source est disponible sur GitHub.

Une des caractéristiques les plus importantes d'un portable est évidemment sa robustesse mais je ne peux pas encore en juger. Pour l'instant, tout va bien, tout le matériel marche.

Sinon, si le principe d'un PC déjà équipé avec un système d'exploitation libre vous plait, il y a aussi PCW (vendeur de Clevo) et, une liste de possibilités.


L'article seul

Tester les performances d'un service REST

Première rédaction de cet article le 5 janvier 2022


J'ai eu récemment à tester un service REST, pour ses performances mais aussi pour sa robustesse, et ça a été l'occasion de faire un rapide tour des outils libres existants. Voici quelques notes.

Précisons bien le cahier des charges : le service à tester était du REST. Certes, il tournait sur HTTP mais ce n'était pas un site Web avec plein de traqueurs, de JavaScript, de vidéos ou de fenêtres polichinelles à faire disparaitre avant de voir quelque chose. Il n'utilisait que HTTP 1.1, je n'ai donc pas regardé ce que ces outils donnaient avec HTTP/2. Et je voulais des outils libres, fonctionnant autant que possible en ligne de commande.

On peut tester les performances d'un serveur HTTP simplement avec curl (et sa très pratique option --write-out) mais on voudrait ici des tests répétés, qui matraquent le serveur.

J'ai trouvé six outils différents, et voici mon expérience. Mais d'abord quelques notes générales si vous n'avez pas l'habitude de ce genre d'outils de test :

  • Les résultats dépendent évidemment du réseau entre le client (le logiciel de test) et le serveur testé. On obtient évidemment des meilleures performances lorsqu'ils sont sur la même machine, mais c'est moins réaliste. Dans mon cas, le testeur était chez Free et le testé sur Nua.ge, ce qui veut dire entre autres que je ne maitrisais pas complètement les fluctations du réseau. (Mais j'ai aussi fait des tests en local.)
  • Le parallélisme compte : une machine même lente peut saturer un serveur HTTP si elle fait de nombreuses requêtes en parallèle. Typiquement, le nombre de requêtes par seconde augmente lorsqu'on augmente le parallélisme, puis diminue au-delà d'un certain seuil.
  • Pour atteindre un bon niveau de parallélisme, le client de test doit ouvrir beaucoup de fichiers (en fait, de descripteurs de fichiers), et des erreurs comme « socket: Too many open files (24) » seront fréquentes. Sur Unix, vous pouvez augmenter la limite du nombre de descripteurs ouverts avec limit descriptors 65535 (mais attention, cela va dépendre de plusieurs choses, options du noyau, être root ou pas, etc). Comme le dit un message du logiciel Locust  « It's [la limite] not high enough for load testing, and the OS didn't allow locust to increase it by itself. ». Les différents logiciels de test ont souvent une section entière de leurs documentation dédiée à ce problème (voir par exemple celle de Locust ou bien celle de Gatling).
  • Le goulet d'étranglement qui empêche d'avoir davantage de requêtes par seconde peut parfaitement être dans la machine de test, trop lente ou mal connectée. (C'est pour cela qu'il est sans doute préférable que les programmes de test soient écrits dans un langage de bas niveau.)
  • Même avec la plus rapide des machines et le meilleur programme de test, une seule machine peut être insuffisante pour tester une charge importante du serveur. Plusieurs logiciels de test ont un mécanisme pour répartir le programme de test sur plusieurs machines (voir par exemple dans la documentation de Locust).
  • Enfin, d'une manière générale, la mesure de performances est un art difficile et il y a plein de pièges. Au minimum, quand vous publiez des résultats, indiquez bien comment ils ont été obtenus (dire « le serveur X peut traiter N requêtes/seconde » sans autre détail n'a aucune valeur).

Maintenant, les différents outils. On commence par le vénérable ApacheBench (alias ab). Largement disponible, son utilisation de base est :

ab -n 5000 -c 100 http://tested.example.org/
  

Le -n permet de spécifier le nombre de requêtes à faire et le -c le nombre de requêtes en parallèle. ApacheBench produit un rapport détaillé :

Time taken for tests:   8.536 seconds
Complete requests:      5000
Failed requests:        0
Requests per second:    585.74 [#/sec] (mean)
Time per request:       170.724 [ms] (mean)
Time per request:       1.707 [ms] (mean, across all concurrent requests)

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        5   93 278.9     39    3106
Processing:     5   65 120.1     43    1808
Waiting:        4   64 120.2     43    1808
Total:         14  158 307.9     87    3454

Percentage of the requests served within a certain time (ms)
  50%     87
  66%    104
  75%    123
  80%    130
  90%    247
  95%   1027
  98%   1122
  99%   1321
 100%   3454 (longest request)
  

Le serveur a bien tenu, aucune connexion n'a échoué. D'autre part, on voit une forte dispersion des temps de réponse (on passe par l'Internet, ça va et ça vient ; en local - sur la même machine, la dispersion est bien plus faible). Le taux de requêtes obtenu (586 requêtes par seconde) dépend fortement du parallélisme. Avec -c 1, on n'atteint que 81 requêtes/seconde.

ab affiche des messages d'erreur dès que le serveur HTTP en face se comporte mal, par exemple en fermant la connexion tout de suite (« apr_socket_recv: Connection reset by peer (104) » ou bien « apr_pollset_poll: The timeout specified has expired (70007) » et, dans ces cas, n'affiche pas du tout les statistiques. Ce manque de robustesse est regrettable pour un logiciel qui doit justement pousser les serveurs à leurs limites.

Par défaut, ab ne réutilise pas les connexions HTTP. Si on veut des connexions persistentes, il existe une option -k.

Deuxième logiciel testé, Siege (j'en profite pour placer le mot de poliorcétique, que j'adore) :

%  siege -c 100 -r 50 http://tested.example.org/ 
Transactions:		        5000 hits
Availability:		      100.00 %
Elapsed time:		        5.09 secs
Response time:		        0.07 secs
Transaction rate:	      982.32 trans/sec
Concurrency:		       66.82
Successful transactions:        5000
Failed transactions:	           0
Longest transaction:	        3.05
Shortest transaction:	        0.00

(Le nombre de requêtes, donné avec -r est par fil d'exécution et non pas global comme avec ab. Ici, 50*100 nous redonne 5 000 comme dans le test avec ab.) On voit qu'on a même pu obtenir un taux de requêtes plus élevé qu'avec ab alors que, comme lui, il crée par défaut une nouvelle connexion HTTP par requête. En éditant le fichier de configuration pour mettre connection = keep-alive (pas trouvé d'option sur la ligne de commande pour cela), on obtient cinq fois mieux :

Transactions:		        5000 hits
Availability:		      100.00 %
Elapsed time:		        0.92 secs
Response time:		        0.02 secs
Transaction rate:	     5434.78 trans/sec
Concurrency:		       85.12
Successful transactions:        5000
Failed transactions:	           0
Longest transaction:	        0.46
Shortest transaction:	        0.00

Si vous augmentez le niveau de parallélisme, vous aurez peut-être le message d'erreur :

WARNING: The number of users is capped at 255.  To increase this
         limit, search your .siegerc file for 'limit' and change
         its value. Make sure you read the instructions there...
  

Il faut alors éditer le fichier de configuration (qui ne s'appelle pas .siegerc, sur ma machine, c'était ~/.siege/siege.conf) et changer la valeur. (Rappelez-vous l'avertissement au début sur les limites imposées par le système d'exploitation.)

Siege a aussi des problèmes de robustesse et vous sort des messages comme « [alert] socket: select and discovered it's not ready sock.c:351: Connection timed out » ou « [alert] socket: read check timed out(30) sock.c:240: Connection timed out ».

Notons que Siege permet d'analyser le HTML reçu et de lancer des requêtes pour les objets qu'il contient, comme le CSS, mais je n'ai pas essayé (rappelez-vous, je testais un service REST, pas un site Web).

Troisième logiciel testé, JMeter. Contrairement à ApacheBench et Siege où tout était sur la ligne de commande et où on pouvait démarrer tout de suite, JMeter nécessite de d'abord définir un Test Plan, listant les requêtes qui seront faites. Cela permet de tester Et, apparemment, on ne peut écrire ce plan qu'avec l'outil graphique de JMeter (« GUI mode should only be used for creating the test script, CLI mode (NON GUI) must be used for load testing »). J'étais de mauvaise humeur, je ne suis pas allé plus loin.

Quatrième logiciel, Cassowary. Contrairement aux trois précédents, il n'était pas en paquetage tout fait pour mon système d'exploitation (Debian), donc place à la compilation. Cassowary est écrit en Go et la documentation disait qu'il fallait au moins la version 1.15 du compilateur mais, apparemment, ça marche avec la 1.13.8 que j'avais :

git clone https://github.com/rogerwelin/cassowary.git
cd cassowary 
go build ./cmd/cassowary   
  

Et on y va :

% ./cassowary run -u http://tested.example.org/   -n 5000 -c 100    

 TCP Connect.....................: Avg/mean=17.39ms 	Median=16.00ms	p(95)=36.00ms
 Server Processing...............: Avg/mean=15.27ms 	Median=13.00ms	p(95)=22.00ms
 Content Transfer................: Avg/mean=0.02ms 	Median=0.00ms	p(95)=0.00ms

Summary: 
 Total Req.......................: 5000
 Failed Req......................: 0
 DNS Lookup......................: 8.00ms
 Req/s...........................: 5903.26
  

Par défaut, Cassowary réutilise les connexions HTTP, d'où le taux de requêtes élevé (on peut changer ce comportement avec --disable-keep-alive). Lui aussi affiche de vilains messages d'erreur (« net/http: request canceled (Client.Timeout exceeded while awaiting headers) ») si le serveur HTTP, ayant du mal à répondre, laisse tomber certaines requêtes. Et, ce qui est plus grave, Cassowary n'affiche pas les statistiques s'il y a eu ne serait-ce qu'une erreur.

Cinquième logiciel utilisé, k6. Également écrit en Go, je n'ai pas réussi à le compiler :

% go get go.k6.io/k6 
package hash/maphash: unrecognized import path "hash/maphash" (import path does not begin with hostname)
package embed: unrecognized import path "embed" (import path does not begin with hostname)

Les deux derniers logiciels sont, je crois, les plus riches et aussi les plus complexes. D'abord, le sixième que j'ai testé, Gatling. On le télécharge, on unzip gatling-charts-highcharts-bundle-3.7.3-bundle.zip et on va dans le répertoire ainsi créé. On doit d'abord enregistrer les tests à faire. Pour cela, on lance l'enregistreur de Gatling. L'interface principale est graphique (je n'ai pas vu s'il y avait une interface en ligne de commande) :

%  ./bin/recorder.sh

Il fait tourner un relais HTTP qu'on doit ensuite utiliser depuis son client HTTP. Par exemple, si j'utilise curl :

% export http_proxy=http://localhost:8000/
% curl http://tested.example.org/

Et Gatling enregistrera une requête HTTP vers http://tested.example.org/. Le plan est écrit sous forme d'un programme Scala (d'autres langages sont possibles) que Gatling exécutera. Il se lance avec :

% ./bin/gatling.sh
  

Et on a une jolie page HTML de résultats. Après, les choses se compliquent, Gatling est très riche, mais il faut écrire du code, même pour une tâche aussi simple que de répéter une opération N fois.

Enfin, le septième et dernier, Locust. (Après le champ lexical de la guerre, avec Siege et Gatling, celui d'une plaie d'Égypte…) Locust est écrit en Python et il a été simple à installer avec pip3 install locust. Il dispose d'une documentation détaillée. Comme JMeter, il faut écrire un plan de test mais, contrairement à JMeter, on peut le faire avec un éditeur ordinaire. Ce plan est écrit lui-même en Python et voici un exemple très simple où le test sollicitera deux chemins sur le serveur :

from locust import HttpUser, task
import requests

class HelloWorldUser(HttpUser):
        @task
        def hello_world(self):
            self.client.get("/")
            self.client.get("/hello")
  

Une fois le plan écrit, on peut lancer Locust en ligne de commande :

% locust --host http://tested.example.org --headless --users 100 --spawn 10
  

On ne peut pas indiquer le nombre maximal de requêtes (seulement le temps maximal), il faut interrompre le programme au bout d'un moment. Il affiche alors :

  Name                                                              # reqs      # fails  |     Avg     Min     Max  Median  |   req/s failures/s
------------------------------------------------------------------------------------------------------------------------------------------------
 GET /                                                              20666     0(0.00%)  |      87       7     541      94  |  736.70    0.00
  

On voit que le nombre de requêtes par seconde est faible. Une des raisons est que Locust est très consommateur de temps de processeur : celui-ci est occupé à 100 % pendant l'exécution, et est le facteur limitant. Locust avertit, d'ailleurs, « CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements!  ». Bref, il ne pousse pas le serveur à ses limites. Locust réutilise les connexions HTTP, et je n'ai pas trouvé comment faire si on voulait tester sans cela. Cette réponse sur StackOverflow ne marche pas pour moi, les requêtes sont bien faites, mais pas comptées dans les statistiques.

Mais l'intérêt de Locust est de lancer un serveur Web qui permet d'obtenir de jolis graphes : locust-stats.png

On peut aussi utiliser cette interface Web pour piloter les tests.

En conclusion ? Je ne crois pas qu'il y ait un de ces logiciels qui fasse tout ce que je voulais et comme je voulais. Donc, j'en garde plusieurs.


L'article seul

Fiche de lecture : Le Minitel

Auteur(s) du livre : Valérie Schafer, Benjamin Thierry
Éditeur : Cigref - Nuvis
978-2-36367-014-4
Publié en 2012
Première rédaction de cet article le 3 janvier 2022


Ah, le Minitel… Disparu complètement juste avant la parution de ce livre, il continue à susciter des discussions, des nostalgies et à servir de référence (positive ou négative) pour beaucoup de discussions autour des réseaux informatiques. Ce livre raconte l'histoire du Minitel, de ses débuts à sa fin. Une lecture nécessaire que l'on soit « pro » ou « anti », vu l'importance qu'a joué et joue encore le Minitel dans les réflexions.

C'est que l'histoire du Minitel a été longue et que certaines réflexions sur le Minitel oublient de prendre en compte cette durée. Ainsi, à la fin des années 1990, il est exact que le Minitel était très en retard sur les ordinateurs de l'époque. Mais ce n'était pas le cas au moment de sa création, où il avait des caractéristiques matérielles qu'on juge ridicules aujourd'hui, mais qui étaient raisonnables pour l'époque.

Ce livre peut aider à traiter des questions délicates comme « le Minitel fut-il un échec ? » La réponse dépend évidemment de l'angle choisi. Techniquement, beaucoup de choix erronés ont été faits. (Mais il ne faut pas faire d'anachronisme : des erreurs qui sont évidentes aujourd'hui, étaient bien plus difficiles à détecter à la fin des années 1970, au moment de sa conception.) Le réseau Transpac sous-jacent avait aussi de bonnes idées mais avait fait aussi plusieurs erreurs fondamentales, comme de rejeter le datagramme. Économiquement, l'idée très originale du Minitel était la distribution gratuite du terminal. Cela avait permis de casser le cercle vicieux « pas de services car pas de clients → pas de clients car pas de services » en amorçant la pompe. (Les auteurs rappellent toutefois qu'il n'y a jamais eu qu'une minorité de la population française à avoir un Minitel à la maison.) Et le Minitel a rapporté énormément d'argent à l'État, et a été à l'origine de certaines fortunes comme celle de Xavier Niel. (Par contre, je trouve que le livre passe trop vite sur le scandale qu'était la « pompe à fric » des tarifications à la durée, avec ses factures surprenantes, même s'ils rappellent que certains serveurs étaient délibérement mal conçus pour que la session dure plus longtemps.) Stratégiquement, le Minitel a permis à la France de partir plus vite dans les réseaux informatiques, puis l'a empêché d'aller plus loin. Politiquement, le Minitel est resté le symbole d'un système centralisé (cf. la fameuse conférence de Benjamin Bayart « Internet libre ou Minitel 2.0 »). Mais la situation est plus complexe que cela. Si l'asymétrie du Minitel n'est pas, sauf erreur, mentionnée dans le livre (1 200 b/s du serveur vers le client et 75 b/s, oui, SOIXANTE-QUINZE BITS PAR SECONDE, du client vers le serveur), le Minitel avait quand même généré une activité plus symétrique, par exemple avec les fameuses « messageries ». Enfin, artistiquement, le Minitel a quand même été l'inspiration d'une belle chanson.

Si vous voulez mon avis, je pense que le Minitel était utile au début, mais ensuite, assis sur le tas d'or que rapportait la tarification à la durée, piloté par des aveugles volontaires qui avaient nié jusqu'au bout l'intérêt de l'Internet, et qui étaient enfermés dans leur auto-satisfaction (« on est les meilleurs »), il a trop duré. Le Minitel aurait laissé un bien meilleur souvenir si son arrêt avait été engagé dès le début des années 1990.

Au fait, si vous lisez ce livre (ce que je recommande), vous pouvez sauter sans mal la préface de Pascal Griset et surtout, surtout, la ridicule postface de Dominique Wolton, caricaturalement nostalgique, chauvine (la France patrie de la culture, opposée au « libéralisme », comme si la France n'était pas un pays capitaliste comme les autres) et présentant le Minitel comme fondé sur une logique égalitaire, « éducative et d'émancipation » ! Il présente même le Minitel comme opposé au marché, ce qui va faire rire jaune tous ceux qui se souviennent de leur facture 3615.

Le livre rappelle tout un ensemble de faits peu connus ou oubliés sur le Minitel. Ainsi, ce qu'on appelait à l'époque « ergonomie » et qu'on dirait aujourd'hui UX, avait fait l'objet de nombreuses réflexions, et d'essais avec des vrais utilisateurs et utilisatrices. Alors que la conception globale du projet était très technocratique de haut en bas, l'UX avait été travaillée sur un mode bien plus interactif. Parmi les idées amusantes, celle d'un clavier alphabétique (ABCDEF au lieu d'AZERTY), supposé plus « intuitif ». Bien sûr, l'idée était mauvaise (et a été vite abandonnée) mais elle rappelle que très peu de gens avaient tapé sur un clavier d'ordinateur à l'époque (mais beaucoup plus avaient tapé sur un clavier de machine à écrire, ce qui explique la victoire finale du clavier Azerty).

Comme avec tout livre d'histoire, on est étonné de trouver des débats du passé qui sont toujours d'actualité. Les auteurs rappellent qu'une bonne partie de la presse s'était vigoureusement opposée au Minitel, l'accusant de détourner le marché de la publicité (la presse ne vit pas de ses lecteurs…).

Ce livre ne considère pas non plus que le phénomène était purement français (contrairement à un certain discours chauvin pro-Minitel). Prestel et le Bildschirmtext sont ainsi discutés en détail. (Tous les deux avaient en commun qu'il fallait un investissement initial de l'utilisateur, précisément le cercle vicieux que le Minitel a cassé avec sa distribution gratuite, une leçon importante pour l'innovation.)


L'article seul

RFC 9170: Long-term Viability of Protocol Extension Mechanisms

Date de publication du RFC : Décembre 2021
Auteur(s) du RFC : M. Thomson (Mozilla), T. Pauly (Apple)
Pour information
Première rédaction de cet article le 1 janvier 2022


Après des années de déploiement d'un protocole sur l'Internet, lorsqu'on essaie d'utiliser des fonctions du protocole parfaitement standards et légales, mais qui avaient été inutilisées jusqu'à présent, on découvre souvent que cela ne passe pas : des programmes bogués, notamment dans les middleboxes, plantent de manière malpropre lorsqu'ils rencontrent ces (toutes relatives) nouveautés. C'est ce qu'on nomme l'ossification de l'Internet. Ce RFC de l'IAB fait le point sur le problème et sur les solutions proposées, par exemple le graissage, l'utilisation délibérée et précoce de variations, pour ne pas laisser d'options inutilisées.

Lorsqu'un protocole a du succès (cf. RFC 5218, sur cette notion de succès), on va vouloir le modifier pour traiter des cas nouveaux. Cela n'est pas toujours facile, comme le note le RFC 8170. Tout protocole a des degrés de liberté (extension points) où on pourra l'étendre. Par exemple, le DNS permet de définir de nouveaux types de données (contrairement à ce qu'on lit souvent, le DNS ne sert pas qu'à « trouver des adresses IP à partir de noms ») et IPv6 permet de définir de nouvelles options pour la destination du paquet, voire de nouveaux en-têtes d'extension. En théorie, cela permet d'étendre le protocole. Mais en pratique, utiliser ces degrés de liberté peut amener des résultats imprévus, par exemple, pour le cas du DNS, un pare-feu programmé avec les pieds qui bloque les paquets utilisant un type de données que le pare-feu ne connait pas. Ce RFC se focalise sur des couches relativement hautes, où tout fonctionne de bout en bout (et où, en théorie, les intermédiaires doivent laisser passer ce qu'ils ne comprennent pas). Les couches basses impliquent davantage de participants et sont donc plus problématiques. Ainsi, pour IPv6, l'en-tête « options pour la destination » doit normalement être ignoré et relayé aveuglément par les routeurs alors que l'en-tête « options pour chaque saut » doit (enfin, devait, avant le RFC 8200) être compris et analysé par tous les routeurs du chemin, ce qui complique sérieusement son utilisation.

Notre RFC a été développé par l'IAB dans le cadre du programme « Evolvability, Deployability, & Maintainability (EDM) ».

Déployer une nouvelle version d'un protocole, ou simplement utiliser des options qui n'avaient pas été pratiquées avant, peut donc être très frustrant. Prenons le cas imaginaire mais très proche de cas réels d'un protocole qui a un champ de huit bits inutilisé et donc le RFC d'origine dit que l'émetteur du paquet doit mettre tous ces bits à zéro, et le récepteur du paquet, en application du principe de robustesse, doit ignorer ces bits. Un jour, un nouveau RFC sort, avec une description du protocole où ces bits ont désormais une utilité. Les premiers logiciels qui vont mettre en œuvre cette nouvelle version, et mettre certains bits à un, vont fonctionner lors de tests puis, une fois le déploiement sur l'Internet fait, vont avoir des problèmes dans certains cas. Un pare-feu programmé par des incompétents va jeter ces paquets. Dans son code, il y a un test que le champ vaut zéro partout, car le programmeur n'a jamais lu le RFC et il a juste observé que ce champ était toujours nul. Cette observation a été mise dans le code et bonne chance pour la corriger. (Les DSI qui déploient ce pare-feu n'ont pas regardé s'il était programmé correctement, ils ont juste lu la brochure commerciale.) À partir de là, les programmeurs qui mettent en œuvre le protocole en question ont le choix de foncer et d'ignorer les mines, acceptant que leur programme ne marche pas si les paquets ont le malheur de passer par un des pare-feux bogués (et seront donc perdus), ou bien de revenir à l'ancienne version, ce second choix étant l'ossification : on n'ose plus rien changer de peur que ça casse quelque chose quelque part. Comme les utilisateurs ignorants attribueraient sans doute les problèmes de timeout à l'application, et pas au pare-feu mal écrit, le choix des programmeurs est vite fait : on ne déploie pas la nouvelle version. C'est d'autant plus vrai si le protocole est particulièrement critique pour le bon fonctionnement de l'Internet (BGP, DNS…) ou bien s'il y a de nombreux acteurs non coordonnés (cf. section 2.3). Bien sûr, le blocage de certains paquets peut être volontaire mais, bien souvent, il résulte de la négligence et de l'incompétence des auteurs de middleboxes (cf. section 5).

Les exemples de tels problèmes sont innombrables (l'annexe A du RFC en fournit plusieurs). Ainsi, TLS a eu bien des ennuis avec des nouvelles valeurs de l'extension signature_algorithms.

Si le protocole en question était conçu de nos jours, il est probable que ses concepteurs prendraient la précaution de réserver quelques valeurs non nulles pour le champ en question, et de demander aux programmes d'utiliser de temps en temps ces valeurs, pour être sûr qu'elles sont effectivement ignorées. C'est ce qu'on nomme le graissage et c'est une technique puissante (mais pas parfaite) pour éviter la rouille, l'ossification. (Notez que les valeurs utilisées pour le graissage ne doivent pas être consécutives, pour limiter les risques qu'un programmeur de middlebox paresseux ne les teste facilement. Et qu'il faut les réserver pour que, plus tard, l'utilisation de vraies valeurs pour ce champ ne soit pas empêchée par les valeurs de graissage.) Le graissage ne résout pas tous les problèmes puisqu'il y a toujours le risque que les valeurs utilisées pour graisser finissent par bénéficier d'un traitement de faveur, et soient acceptées, alors que les valeurs réelles poseront des problèmes.

On pourrait penser qu'une meilleure conception des protocoles éviterait l'ossification. (C'est le discours des inventeurs géniaux et méconnus qui prétendent que leur solution magique n'a aucun inconvénient et devrait remplacer tout l'Internet demain.) Après tout, le RFC 6709 contient beaucoup d'excellents conseils sur la meilleure façon de concevoir des protocoles pour qu'ils puissent évoluer. Par exemple, il insiste sur le fait que le mécanisme de négociation qui permet aux deux parties de se mettre d'accord sur une option ou une version doit être simple, pour qu'il y ait davantage de chances qu'il soit mis en œuvre correctement dans tous les programmes. En effet, en l'absence de graissage, ce mécanisme ne sera testé en vrai que lorsqu'on introduira une nouvelle version ou une nouvelle option et, alors, il sera trop tard pour modifier les programmes qui n'arrivent pas à négocier ces nouveaux cas, car leur code de négociation est bogué. Le RFC 6709 reconnait ce problème (tant qu'on n'a pas utilisé un mécanisme, on ne sait pas vraiment s'il marche) et reconnait que le conseil d'un mécanisme simple n'est pas suffisant.

Notre RFC 9170 contient d'ailleurs une petite pique contre QUIC en regrettant qu'on repousse parfois à plus tard le mécanisme de négociation de version, pour arriver à publier la norme décrivant le protocole (exactement ce qui est arrivé à QUIC, qui n'a pas de mécanisme de négociation des futures versions). Le problème est que, une fois la norme publiée et le protocole déployé, il sera trop tard…

Bref, l'analyse du RFC (section 3) est qu'il faut utiliser tôt et souvent les mécanismes d'extension. Une option ou un moyen de négocier de nouvelles options qui n'a jamais été utilisé depuis des années est probablement ossifié et ne peut plus être utilisé. C'est très joli de dire dans le premier RFC d'un protocole « cet octet est toujours à zéro dans cette version mais les récepteurs doivent ignorer son contenu car il pourra servir dans une future version » mais l'expérience prouve largement qu'une telle phrase est souvent ignorée et que bien des logiciels planteront, parfois de façon brutale, le jour où on commencer à utiliser des valeurs non nulles. Il faut donc utiliser les mécanismes ou bien ils rouillent. Par exemple, si vous concevez un mécanisme d'extension dans votre protocole, il est bon que, dès le premier jour, au moins une fonction soit mise en œuvre via ce mécanisme, pour forcer les programmeurs à en tenir compte, au lieu de simplement sauter cette section du RFC. Les protocoles qui ajoutent fréquemment des options ou des extensions ont moins de problèmes que ceux qui attendent des années avant d'exploiter leurs mécanismes d'extension. Et plus on attend, plus c'est pire. C'est pour cela que, par exemple, il faut féliciter le RIPE NCC d'avoir tenté l'annonce de l'attribut BGP 99, même si cela a cassé des choses, car si on ne l'avait pas fait (comme l'avaient demandé certaines personnes qui ne comprenaient pas les enjeux), le déploiement de nouveaux attributs dans BGP serait resté quasi-impossible.

Tester tôt est d'autant plus important qu'il peut être crucial, pour la sécurité, qu'on puisse étendre un protocole (par exemple pour l'agilité cryptographique, cf. RFC 7696). L'article de S. Bellovin et E. Rescorla, « Deploying a New Hash Algorithm » montre clairement que les choses ne se passent pas aussi bien qu'elles le devraient.

Comme dit plus haut, la meilleure façon de s'assurer qu'un mécanisme est utilisable est de l'utiliser effectivement. Et pour cela que ce mécanisme soit indispensable au fonctionnement normal du protocole, qu'on ne puisse pas l'ignorer. Le RFC cite l'exemple de SMTP : le principal mécanisme d'extension de SMTP est d'ajouter de nouveaux en-têtes (comme le Archived-At: dans le RFC 5064) or, SMTP dépend d'un traitement de ces en-têtes pour des fonctions mêmes élémentaires. Un MTA ne peut pas se permettre d'ignorer les en-têtes. Ainsi, on est sûr que toute mise en œuvre de SMTP sait analyser les en-têtes. Et, comme des en-têtes nouveaux sont assez fréquemment ajoutés, on sait que des en-têtes inconnus des vieux logiciels ne perturbent pas SMTP. Ce cas est idéal : au lieu d'un mécanisme d'extension qui serait certes spécifié dans le RFC mais pas encore utilisé, on a un mécanisme d'extension dont dépendent des fonctions de base du protocole.

Le RFC cite également le cas de SIP, qui est moins favorable : les relais ne transmettent en général pas les en-têtes inconnus, ce qui ne casse pas la communication, mais empêche de déployer de nouveaux services tant que tous les relais n'ont pas été mis à jour.

Bien sûr, aucune solution n'est parfaite. Si SMTP n'avait pas ajouté de nombreux en-têtes depuis sa création, on aurait peut-être des programmes qui certes savent analyser les en-têtes mais plantent lorsque ces en-têtes ne sont pas dans une liste limitée. D'où l'importance de changer souvent (ici, en ajoutant des en-têtes).

Souvent, les protocoles prévoient un mécanisme de négociation de la version utilisée. On parle de version différente lorsque le protocole a suffisamment changé pour qu'on ne puisse pas interagir avec un vieux logiciel. Un client SMTP récent peut toujours parler à un vieux serveur (au pire, le serveur ignorera les en-têtes trop récents) mais une machine TLS 1.2 ne peut pas parler à une machine TLS 1.3. Dans le cas le plus fréquent, la machine récente doit pouvoir parler les deux versions, et la négociation de version sert justement à savoir quelle version utiliser. Le problème de cette approche est que, quand la version 1 est publiée en RFC, avec son beau mécanisme de négociation de version, il n'y a pas encore de version 2 pour tester que cette négociation se passera bien. Celle-ci ne sortira parfois que des années plus tard et on s'apercevra peut-être à ce moment que certains programmes ont mal mis en œuvre la négociation de version, voire ont tout simplement négligé cette section du RFC…

Première solution à ce problème, utiliser un mécanisme de négociation de version située dans une couche plus basse. Ainsi, IP a un mécanisme de négociation de version dans l'en-tête IP lui-même (les quatre premiers bits indiquent le numéro de version, cf. RFC 8200, section 3) mais ce mécanisme n'a jamais marché en pratique. Ce qui marche, et qui est utilisé, c'est de se servir du mécanisme de la couche 2. Par exemple, pour Ethernet (RFC 2464), c'est l'utilisation du type de protocole (EtherType), 0x800 pour IPv4 et 0x86DD pour IPv6. Un autre exemple est l'utilisation d'ALPN (RFC 7301) pour les protocoles au-dessus de TLS. (Le RFC cite aussi la négociation de contenu de HTTP.)

Une solution récente au problème de l'ossification est le graissage, présenté en section 3.3. Décrit à l'origine pour TLS, dans le RFC 8701, il est désormais utilisé dans d'autres protocoles comme QUIC. Son principe est de réserver un certain nombre de valeurs utilisant des extensions du protocole et de s'en servir, de façon à forcer les différents logiciels, intermédiaires ou terminaux, à lire tout le RFC et à gérer tous les cas. Dans l'exemple cité plus haut d'un protocole qui aurait un champ de huit bits « cet octet est toujours à zéro dans cette version mais les récepteurs doivent ignorer son contenu car il pourra servir dans une future version », on peut réserver les valeurs 3, 21, 90 et 174 comme valeurs de graissage et l'émetteur les mettra de temps en temps dans le champ en question. Dans le cas de TLS, où le client propose des options et le serveur accepte celles qu'il choisit dans ce lot (oui, je sais, TLS est plus compliqué que cela, par exemple lorsque le serveur demande une authentification), le client annonce au hasard des valeurs de graissage. Ainsi, une middlebox qui couperait les connexions TLS serait vite détectée et, on peut l'espérer, rejetée par le marché. Le principe du graissage est donc « les extensions à un protocole s'usent quand on ne s'en sert pas ». Cela évoque les tests de fuzzing qu'on fait en sécurité, où on va essayer plein de valeurs inhabituelles prises au hasard, pour s'assurer que le logiciel ne se laisse pas surprendre. On voit aussi un risque du graissage : si les programmes bogués sont nombreux, le premier qui déploie un mécanisme de graissage va essuyer les plâtres et se faire parfois rejeter. Il est donc préférable que le graissage soit utilisé dès le début, par exemple dans un nouveau protocole.

Évidemment, la solution n'est pas parfaite. On peut imaginer un logiciel mal fait qui reconnait les valeurs utilisées pour le graissage (et les ignore) mais rejette quand même les autres valeurs pourtant légitimes. (La plupart du temps, les valeurs réservées pour le graissage ne sont pas continues, comme dans les valeurs 3, 21, 90 et 174 citées plus haut, pour rendre plus difficile un traitement spécifique au graissage.)

Bien sûr, même sans valeurs réservées au graissage, un programme pourrait toujours faire à peu près l'équivalent, en utilisant les valeurs réservées pour des expérimentations ou bien des usages privés. Mais le risque est alors qu'elles soient acceptées par l'autre partie, ce qui n'est pas le but.

Tous les protocoles n'ont pas le même style d'interaction que TLS, et le graissage n'est donc pas systématiquement possible. Et puis il ne teste qu'une partie des capacités du protocole, donc il ne couvre pas tous les cas possibles. Le graissage est donc utile mais ne résout pas complètement le problème.

Parfois, des protocoles qui ne permettaient pas facilement l'extensibilité ont été assez sérieusement modifiés pour la rendre possible. Ce fut le cas du DNS avec EDNS (RFC 6891). Son déploiement n'a pas été un long fleuve tranquille et, pendant longtemps, les réactions erronées de certains serveurs aux requêtes utilisant EDNS nécessitaient un mécanisme de repli (re-essayer sans EDNS). Il a ensuite fallu supprimer ce mécanisme de repli pour être sûr que les derniers systèmes erronés soient retirés du service, le tout s'étalant sur de nombreuses années. Un gros effort collectif a été nécessaire pour parvenir à ce résultat, facilité, dans le cas du DNS, par le relativement petit nombre d'acteurs et leur étroite collaboration.

La section 4 du RFC cite d'autres techniques qui peuvent être utilisées pour lutter contre l'ossification. D'abord, ne pas avoir trop de possibilités d'étendre le protocole car, dans ce cas, certaines possibilités seront fatalement moins testées que d'autres et donc plus fragiles si on veut s'en servir un jour.

Le RFC suggère aussi l'utilisation d'invariants. Un invariant est une promesse des auteurs du protocole, assurant que cette partie du protocole ne bougera pas (et, au contraire, que tout le reste peut bouger et qu'il ne faut pas compter dessus). Si les auteurs de logiciels lisent les RFC (une supposition audacieuse, notamment pour les auteurs de middleboxes), cela devrait éviter les problèmes avec les évolutions futures. (Il est donc toujours utile de graisser les parties du protocole qui ne sont pas des invariants.) Le RFC 5704, dans sa section 2.2, définit plus rigoureusement ce que sont les invariants. Deux exemples d'utilisation de ce concept sont le RFC 8999 (décrivant les invariants de QUIC) et la section 9.3 du RFC 8446 sur TLS. Notre RFC conseille aussi de préciser explicitement ce qui n'est pas invariant (comme le fait l'annexe A du RFC 8999), ce que je trouve contestable (il y a un risque que cette liste d'exemples de non-invariants soit interprétée comme limitative, alors que ce ne sont que des exemples).

Une autre bonne technique, que recommande notre RFC, est de prendre des mesures techniques pour empêcher les intermédiaires de tripoter la communication. Moins il y a d'entités qui analysent et interprètent les paquets, moins il y aura de programmes à vérifier et éventuellement à modifier en cas d'extension du protocole. Un bon exemple de ces mesures techniques est évidemment la cryptographie. Ainsi, chiffrer le fonctionnement du protocole, comme le fait QUIC, ne sert pas qu'à préserver la vie privée de l'utilisateur, cela sert aussi à tenir à l'écart les intermédiaires, ce qui limite l'ossification. Le RFC 8558 est une bonne lecture à ce sujet.

Bien sûr, si bien conçu que soit le protocole, il y aura des problèmes. Le RFC suggère donc aussi qu'on crée des mécanismes de retour, permettant d'être informés des problèmes. Prenons par exemple un serveur TLS qui refuserait des clients corrects, mais qui utilisent des extensions que le serveur ne gère pas correctement. Si le serveur ne journalise pas ces problèmes, ou bien que l'administrateur système ne lit pas ces journaux, le problème pourra trainer très longtemps. Idéalement, ces retours seront récoltés et traités automatiquement, et envoyés à celles et ceux qui sont en mesure d'agir. C'est plus facile à dire qu'à faire, et cela dépend évidemment du protocole utilisé. Des exemples de protocoles ayant un tel mécanisme sont DMARC (RFC 7489, avec son étiquette rua, section 7), et SMTP (avec le TLSRPT du RFC 8460).

Enfin, pour terminer, l'annexe A du RFC présente quelques exemples de protocoles et comment ils ont géré ce problème. Elle commence par le DNS (RFC 1034 et RFC 1035). Le DNS a une mauvaise expérience avec le déploiement de nouveaux types d'enregistrement qui, par exemple, provoquaient des rejets violents des requêtes DNS par certains équipements. C'est l'une des raisons pour lesquelles SPF (RFC 7208) a finalement renoncé à utiliser son propre type d'enregistrement, SPF (cf. RFC 6686) et pour lesquelles tout le monde se sert de TXT. Le problème s'est heureusement amélioré depuis la parution du RFC 3597, qui normalise le traitement des types inconnus. (Mais il reste d'autres obstacles au déploiement de nouveaux types, comme la mise à jour des interfaces « conviviales » d'avitaillement d'une zone DNS, interfaces qui mettent de nombreuses années à intégrer les nouveaux types.)

HTTP, lui, a plutôt bien marché, question extensibilité mais il a certains mécanismes d'extension que personne n'ose utiliser et qui ne marcheraient probablement pas, comme les extensions des chunks (RFC 7230, section 4.1.1) ou bien comme l'utilisation d'autres unités que les octets dans les requêtes avec intervalles (RFC 7233, section 2.2).

Et IP lui-même ? Par exemple, IP avait un mécanisme pour permettre aux équipements réseau de reconnaitre la version utilisée, permettant donc de faire coexister plusieurs versions d'IP, le champ Version (les quatre premiers bits du paquet). Mais il n'a jamais réellement fonctionné, les équipements utilisant à la place les indications données par la couche inférieure (l'« ethertype », dans le cas d'Ethernet, cf. RFC 2464). D'autres problèmes sont arrivés avec IP, par exemple l'ancienne « classe E ». Le préfixe 224.0.0.0/3 avait été réservé par le RFC 791, section 3.2, mais sans précisions (« The extended addressing mode is undefined. Both of these features are reserved for future use. »). Le RFC 988 avait ensuite pris 224.0.0.0/4 pour le multicast (qui n'a jamais été réellement déployé sur l'Internet), créant la « classe D », le reste devenant la « classe E », 240.0.0.0/4 dont on ne sait plus quoi faire aujourd'hui, même si certains voudraient la récupérer pour prolonger l'agonie d'IPv4. Son traitement spécial par de nombreux logiciels empêche de l'affecter réellement. Une solution souvent utilisée pour changer la signification de tel ou tel champ dans l'en-tête est la négociation entre les deux parties qui communiquent, mais cela ne marche pas pour les adresses (la communication peut être unidirectionnelle).

SNMP n'a pas eu trop de problèmes avec le déploiement de ses versions 2 et 3. La norme de la version 1 précisait clairement (RFC 1157) que les paquets des versions supérieures à ce qu'on savait gérer devaient être ignorés silencieusement, et cela était vraiment fait en pratique. Il a donc été possible de commencer à envoyer des paquets des versions 2, puis 3, sans casser les vieux logiciels qui écoutaient sur le même port.

TCP, par contre, a eu bien des problèmes avec son mécanisme d'extension. (Lire l'article de Honda, M., Nishida, Y., Raiciu, C., Greenhalgh, A., Handley, M., et H. Tokuda, « Is it still possible to extend TCP? ».) En effet, de nombreuses middleboxes se permettaient de regarder l'en-tête TCP sans avoir lu et compris le RFC, jetant des paquets qui leur semblaient anormaux, alors qu'ils avaient juste des options nouvelles. Ainsi, le multipath TCP (RFC 6824) a été difficile à déployer (cf. l'article de Raiciu, C., Paasch, C., Barre, S., Ford, A., Honda, M., Duchêne, F., Bonaventure, O., et M. Handley, «  How Hard Can It Be? Designing and Implementing a Deployable Multipath TCP »). TCP Fast Open (RFC 7413) a eu moins de problèmes sur le chemin, mais davantage avec les machines terminales, qui ne comprenaient pas ce qu'on leur demandait. Comme le but de TCP Fast Open était d'ouvrir une connexion rapidement, ce problème était fatal : on ne peut pas entamer une négociation lorsqu'on veut aller vite.

Et enfin, dernier protocole étudié dans cette annexe A, TLS. Là, la conclusion du RFC est que le mécanisme de négociation et donc d'extension de TLS était correct, mais que la quantité de programmes mal écrits et qui réagissaient mal à ce mécanisme l'a, en pratique, rendu inutilisable. Pour choisir une version de TLS commune aux deux parties qui veulent communiquer de manière sécurisée, la solution était de chercher la plus haute valeur de version commune (HMSV pour highest mutually supported version, cf. RFC 6709, section 4.1). Mais les innombrables bogues dans les terminaux, et dans les middleboxes (qui peuvent accéder à la négociation TLS puisqu'elle est en clair, avant tout chiffrement) ont fait qu'il était difficile d'annoncer une version supérieure sans que les paquets soient rejetés. (Voir l'expérience racontée dans ce message.)

TLS 1.3 (RFC 8446) a donc dû abandonner complètement le mécanisme HMSV et se présenter comme étant du 1.2, pour calmer les middleboxes intolérantes, dissimulant ensuite dans le ClientHello des informations qui permettent aux serveurs 1.3 de reconnaitre un client qui veut faire du 1.3 (ici, vu avec tshark) :

    TLSv1 Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 665
        Handshake Protocol: Client Hello
            Handshake Type: Client Hello (1)
            Length: 661
            Version: TLS 1.2 (0x0303)

[Ce champ Version n'est là que pour satisfaire les middleboxes.]
	    
            Extension: supported_versions (len=9)
                Type: supported_versions (43)
                Length: 9
                Supported Versions length: 8
                Supported Version: TLS 1.3 (0x0304)
                Supported Version: TLS 1.2 (0x0303)
                Supported Version: TLS 1.1 (0x0302)
                Supported Version: TLS 1.0 (0x0301)

[La vraie liste des versions acceptées était dans cette extension.]
  

Toujours à propos de TLS, SNI (Server Name Indication, cf. RFC 6066, section 3) est un autre exemple où la conception était bonne mais le manque d'utilisation de certains options a mené à l'ossification et ces options ne sont plus, en pratique, utilisables. Ainsi, SNI permettait de désigner le serveur par son nom de domaine (host_name dans SNI) mais aussi en utilisant d'autres types d'identificateurs (champ name_type) sauf que, en pratique, ces autres types n'ont jamais été utilisés et ne marcheraient probablement pas. (Voir l'article de A. Langley, « Accepting that other SNI name types will never work ».)


Téléchargez le RFC 9170


L'article seul

RFC 9154: Extensible Provisioning Protocol (EPP) Secure Authorization Information for Transfer

Date de publication du RFC : Décembre 2021
Auteur(s) du RFC : J. Gould, R. Wilhelm (VeriSign)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF regext
Première rédaction de cet article le 31 décembre 2021


Le protocole EPP d'avitaillement des noms de domaine permet, entre autres opérations, de transférer un domaine d'un client (typiquement un BE) à un autre. Cette opération ouvre de sérieux problèmes de sécurité, le transfert pouvant être utilisé pour détourner un nom de domaine. En général, la sécurisation de ce transfert est faite par un mot de passe stocké en clair. Notre RFC décrit une méthode pour gérer ces mots de passe qui évite ce stockage, et qui gêne sérieusement les transferts malveillants.

EPP est normalisé dans le RFC 5730 et c'est ce document qui décrit le cadre général d'autorisation d'un transfert de domaines. La forme exacte que prend l'autorisation dépend du type d'objets qu'on gère avec EPP. Pour les domaines (RFC 5731), c'est un élément <authInfo>, qui peut contenir divers types de sous-élements mais le plus fréquent est un simple mot de passe (parfois appelé « code de transfert » ou « code d'autorisation », ou simplement « authinfo »), comme dans cet exemple, une réponse à une commande EPP <info>, où le mot de passe est « 2fooBAR » :

    
<domain:infData>
     <domain:name>example.com</domain:name>
...
     <domain:crDate>1999-04-03T22:00:00.0Z</domain:crDate>
...
     <domain:authInfo>
       <domain:pw>2fooBAR</domain:pw>
     </domain:authInfo>
</domain:infData>

  

L'utilisation typique de ce mot de passe est que le client (en général un BE) le crée, le stocke en clair, l'envoie au serveur, qui le stocke. Lors d'un transfert légitime, le BE gagnant recevra ce mot de passe (typiquement via le titulaire de l'objet, ici un nom de domaine) et le transmettra au registre (RFC 5731, section 3.2.4). Ici, le BE gagnant demande à son client le code d'autorisation qu'il a normalement obtenu via le BE perdant (si le client est vraiment le titulaire légitime) : gandi-winning-registrar.png Et ici le BE perdant indique à son client le code d'autorisation : gandi-losing-registrar.png (registar = BE)

Notez que la façon d'autoriser les transferts, et d'accéder aux informations d'autorisation, dépend de la politique du registre. Les RFC sur EPP normalisent la technique mais pas la politique. Par exemple, lorsqu'un BE demande un transfert sans fournir d'information d'autorisation, certains registres refusent immédiatement le transfert, tandis que d'autres le mettent en attente d'une acceptation ou d'un refus explicite. De même, certains registres permettent de récupérer l'information d'autorisation, comme dans l'exemple ci-dessus, alors que d'autres (comme CentralNic) refusent.

Même chose pour d'autres types d'objets comme les contacts (RFC 5733) même si en pratique la pratique du transfert est plus rare pour ces types. Le mot de passe étant typiquement stocké en clair chez le client, pour pouvoir être donné en cas de transfert, on voit les risques que cela pose en cas d'accès à la base du BE. Aujourd'hui, stocker un mot de passe en clair est nettement considéré comme une mauvaise pratique de sécurité.

À la place, notre RFC décrit, non pas une modification du protocole EPP, mais une nouvelle procédure, une façon créative de se servir du protocole existant pour gérer ces informations d'autorisation de manière plus sérieuse : l'objet (par exemple le nom de domaine) est créé sans information d'autorisation, le serveur EPP (par exemple le registre de noms de domaine) doit refuser le transfert si cette information est manquante. Lors d'un transfert légitime, le client (par exemple un BE) perdant va générer un mot de passe, le transmettre au registre et à son client (typiquement le titulaire du nom de domaine) et ne pas le stocker. Le registre stockera le mot de passe uniquement sous forme condensée et, lorsqu'il recevra la demande de transfert accompagnée d'un mot de passe, il pourra condenser ce mot et vérifier qu'il correspond bien à celui stocké. Le mot ne servira qu'une fois et l'information d'autorisation est détruite après le succès du transfert. Tout ceci ne nécessite pas de modification du protocole, mais, dans certains cas, une modification des pratiques des différents acteurs (par exemple, le serveur EPP doit accepter qu'un objet soit créé sans information d'autorisation, et doit considérer que cela vaut refus de tout transfert).

Le RFC note que la norme EPP ne décrit, logiquement, que le protocole, c'est-à-dire l'interaction entre les deux machines, mais pas ce que fait chaque machine de son côté. Ainsi, la nécessité de stocker les mots de passe de manière sécurisée n'est pas imposée par EPP (mais est néanmoins une bonne pratique).

D'autre part, EPP ne prévoit pas explicitement de durée de vie pour les mots de passe (mais n'interdit pas non plus de les supprimer au bout d'un temps donné, ce qui va être justement la technique de notre RFC).

Petite révision sur les acteurs de l'avitaillement de noms de domaine en section 2 du RFC. La norme EPP parle de client et de serveur, notions techniques, mais du point de vue business, il y a trois acteurs (cf. la terminologie dans le RFC 8499), le registre (qui gère le serveur EPP), le bureau d'enregistrement (BE, qui gère le client EPP) et le titulaire (qui se connecte à son BE via une interface Web ou une API). Dans beaucoup de domaines d'enregistrement, il n'y a aucun lien direct entre le titulaire et le registre, tout devant passer par le BE.

Maintenant, place à la description de la nouvelle manière de faire des transferts. Bien qu'elle ne change pas le protocole, qu'elle ne soit qu'une nouvelle façon d'utiliser ce qui existe déjà dans EPP, elle doit se signaler lors de la connexion EPP, avec l'espace de noms urn:ietf:params:xml:ns:epp:secure-authinfo-transfer-1.0 (enregistré à l'IANA). En effet, la nouvelle manière a besoin que le serveur accepte des choses qui sont autorisées par EPP mais pas obligatoires, notamment :

  • une information d'autorisation vide (représentée par exemple par le NULL dans une base SQL),
  • la possibilité de supprimer l'information d'autorisation avec la commande EPP <update>,
  • la possibilité de valider l'information d'autorisation avec la commande EPP <info>,
  • le refus de tout transfert si l'information d'autorisation est vide,
  • la remise à zéro de l'information d'autorisation lorsque le transfert a été réalisé (mot de passe à usage unique).

Le serveur, lui, en recevant urn:ietf:params:xml:ns:epp:secure-authinfo-transfer-1.0, peut compter que le client EPP saura :

  • générer une information d'autorisation forte (aléatoire, par exemple),
  • ne le faire que lorsqu'un transfert est demandé.

L'autorisation d'information dans l'élement XML <domain:pw> (RFC 5731, section 3.2.4) est un mot de passe qui doit être difficile à deviner par un attaquant. Idéalement, il doit être aléatoire ou équivalent (RFC 4086). Le RFC calcule que pour avoir 128 bits d'entropie, avec uniquement les caractères ASCII imprimables, il faut environ 20 caractères.

Pour compenser l'absence de la notion de durée de vie de l'information d'autorisation dans EPP, le client ne doit définir une information d'autorisation que lorsqu'un transfert est demandé, et supprimer cette information ensuite. La plupart du temps, le domaine n'aura pas d'information d'autorisation, et les transferts seront donc refusés.

L'information d'autorisation, comme tout mot de passe, ne doit plus être stockée en clair, mais sous forme d'un condensat. Le BE perdant ne doit pas la stocker (il la génère, la passe au titulaire et l'oublie ensuite). Le BE gagnant ne doit la stocker que le temps de finaliser le transfert. Évidemment, toute la communication EPP doit être chiffrée (RFC 5734). Lors d'une demande de transfert, le registre va vérifier qu'un condensat de l'information d'autorisation transmise par le BE gagnant correspond à ce que le BE perdant avait envoyé. L'information vide est un cas particulier, le registre ne doit pas tester l'égalité mais rejeter le transfert.

La section 4 explique en détail le processus de transfert avec cette nouvelle méthode :

  • Quand le domaine est créé, l'information d'autorisation est vide (pas de « authinfo »),
  • quand le titulaire veut transférer le nom à un nouveau BE, il demande au BE perdant l'information d'autorisation,
  • le BE perdant génère un mot de passe, qu'il transmet au titulaire et au registre (qui peut répondre avec le code d'erreur EPP 2202 si ce mot de passe ne lui semble pas assez fort), puis qu'il oublie aussitôt,
  • le titulaire donne le mot de passe au BE gagnant,
  • le BE gagnant demande le transfert au registre, en fournissant le mot de passe, ce qui permet au transfert d'être accepté immédiatement,
  • le registre (ou bien le BE perdant), efface le mot de passe.

Voici en EPP quelques messages pour réaliser ces différentes opérations. D'abord, la création d'un nom (notez le mot de passe vide) :


<create>
  <domain:create
    xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
    <domain:name>example.test</domain:name>
    <domain:authInfo>
      <domain:pw/>
    </domain:authInfo>
  </domain:create>
</create>

  

Ici, la mise à jour de l'information d'autorisation par le BE perdant, lorsque le titulaire lui a annoncé le départ du domaine ; le mot de passe est LuQ7Bu@w9?%+_HK3cayg$55$LSft3MPP (le RFC rappelle fortement l'importance de générer un mot de passe fort, par exemple en utilisant des sources bien aléatoires, comme documenté dans le RFC 4086) :


<update>
  <domain:update
    xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
    <domain:name>example.test</domain:name>
    <domain:chg>
      <domain:authInfo>
        <domain:pw>LuQ7Bu@w9?%+_HK3cayg$55$LSft3MPP</domain:pw>
      </domain:authInfo>
    </domain:chg>
  </domain:update>
</update>

    

Le BE perdant devra peut-être également supprimer l'état clientTransferProhibited, si le domaine était protégé contre les transferts.

Le BE gagnant peut également vérifier l'information d'autorisation sans déclencher un transfert, avec une requête <info>, qui lui renverra l'information d'autorisation. Pour plusieurs exemples par la suite, j'ai utilisé le logiciel Cocca. Cocca, par défaut, ne stocke pas l'autorisation d'information en clair et ne peut donc pas la renvoyer. Ou bien le client EPP peut envoyer une commande <info> en indiquant l'information d'autorisation. S'il obtient une erreur EPP 2202 (RFC 5730, section 3), c'est que cette information n'était pas correcte. Ici, la réponse EPP de Cocca lorsqu'on lui envoie un <info> avec information d'autorisation correcte :


Client : <info xmlns="urn:ietf:params:xml:ns:epp-1.0"><info xmlns="urn:ietf:params:xml:ns:domain-1.0"><name>foobar.test</name><authInfo xmlns="urn:ietf:params:xml:ns:domain-1.0"><pw xmlns="urn:ietf:params:xml:ns:domain-1.0">tropfort1298</pw></authInfo></info></info>

Serveur : ... <ns1:authInfo><ns1:pw>Authinfo Correct</ns1:pw></ns1:authInfo> ...

  

Et si cette information est incorrecte :


Serveur : ... <ns1:authInfo><ns1:pw>Authinfo Incorrect</ns1:pw></ns1:authInfo>

  

(Mais Cocca répond quand même avec un code EPP 1000, ce qui n'est pas correct.)

Et enfin, bien sûr, voici la demande de transfert elle-même :


<transfer op="request">
  <domain:transfer
    xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
    <domain:name>example1.com</domain:name>
    <domain:authInfo>
      <domain:pw>LuQ7Bu@w9?%+_HK3cayg$55$LSft3MPP</domain:pw>
    </domain:authInfo>
  </domain:transfer>
</transfer>

  

Et si c'est bon :

    
<ns0:response xmlns:ns0="urn:ietf:params:xml:ns:epp-1.0" xmlns:ns1="urn:ietf:params:xml:ns:domain-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><ns0:result code="1000"><ns0:msg>Command completed successfully</ns0:msg></ns0:result><ns0:msgQ count="2" id="3" />
<ns1:trStatus>serverApproved</ns1:trStatus> ...

  

Et avec une mauvaise information d'autorisation :


<ns0:response xmlns:ns0="urn:ietf:params:xml:ns:epp-1.0"><ns0:result code="2202"><ns0:msg>Invalid authorization information; (T07) Auth Info Password incorrect</ns0:msg></ns0:result>...

  

La section 6 du RFC décrit le problème de la transition depuis l'ancien modèle d'autorisation vers le nouveau. Notez que certains registres peuvent avoir une partie du nouveau système déjà en place. Le registre qui désire transitionner doit d'abord s'assurer que l'information d'autorisation absente ou vide équivaut à un rejet. Il doit ensuite permettre aux BE de mettre une information d'autorisation vide, permettre que la commande <info> puisse tester une information d'autorisation, s'assurer que l'acceptation d'un transfert supprime l'information d'autorisation, etc.

L'extension à EPP décrite dans ce RFC a été enregistrée dans le registre des extensions EPP. Quelles sont les mises en œuvre de ce RFC ? Cocca, déjà cité, le fait partiellement (par exemple en ne stockant pas les mots de passe en clair). Je n'ai pas testé avec ce logiciel ce qui se passait avec une information d'autorisation vide. Sinon, CentralNic a déjà ce mécanisme en production. Et Verisign l'a mis dans son SDK.


Téléchargez le RFC 9154


L'article seul

RFC 9167: Registry Maintenance Notification for the Extensible Provisioning Protocol (EPP)

Date de publication du RFC : Décembre 2021
Auteur(s) du RFC : T. Sattler, R. Carney, J. Kolker (GoDaddy)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF regext
Première rédaction de cet article le 26 décembre 2021


Un registre, par exemple un registre de noms de domaine, utilise parfois le protocole EPP pour la communication avec ses clients. Ce RFC décrit comment utiliser ce protocole pour informer les clients des périodes d'indisponibilité du registre, par exemple lors d'une opération de maintenance.

Aujourd'hui, un registre prévient de ses periodes d'indisponibilité prévues par divers moyens : courriers aux BE, messages sur des réseaux sociaux, page Web dédiée comme : afnic-maintenances.png

Chaque registre le fait de façon différente, il n'existe pas de règles communes, et le côté non-structuré de ces annonces fait qu'il faut une interventon humaine pour les analyser et les mettre dans un agenda. Et un BE peut devoir interagir avec de nombreux registres ! Notre RFC propose d'utiliser EPP (RFC 5730) pour ces annonces.

Donc, premier principe, puisqu'on va souvent manipuler des dates, les dates et heures seront toutes représentées en UTC et dans le format du RFC 3339. Ensuite, les annonces seront dans un élément XML <item>, de l'espace de noms urn:ietf:params:xml:ns:epp:maintenance-1.0 (enregistré à l'IANA). Parmi les sous-éléments de cet élément :

  • id, un identificateur de l'évènement,
  • systems, qui permettra de désigner les systèmes affectés,
  • environment, pour dire si l'évènement concerne la production ou bien un banc de test,
  • start et end, qui indiquent le début et la fin (prévue…) de l'évènement,
  • et plusieurs autres éléments.

Un exemple d'évènement, une intervention sur le serveur EPP epp.registry.example de production, peut être :


<maint:item>
  <maint:id>2e6df9b0-4092-4491-bcc8-9fb2166dcee6</maint:id>
  <maint:systems>
    <maint:system>
      <maint:name>EPP</maint:name>
      <maint:host>epp.registry.example</maint:host>
      <maint:impact>full</maint:impact>
    </maint:system>
  </maint:systems>
  <maint:environment type="production"/>
  <maint:start>2021-12-30T06:00:00Z</maint:start>
  <maint:end>2021-12-30T07:00:00Z</maint:end>
  <maint:reason>planned</maint:reason>
  <maint:detail>
    https://www.registry.example/notice?123
  </maint:detail>
  <maint:tlds>
    <maint:tld>example</maint:tld>
    <maint:tld>test</maint:tld>
  </maint:tlds>
</maint:item>
    
  

On voit que le serveur EPP sera arrêté pendant une heure (<impact>full</impact> indiquant une indisponibilité totale) et que cela affectera les TLD .example et .test. Une telle information, étant sous une forme structurée, peut être analysée par un programme et automatiquement insérée dans un agenda, ou un système de supervision.

Les commandes EPP exactes, maintenant (section 4 du RFC). La commande <info> peut renvoyer maintenant un élément <maint:info> qui contient l'information de maintenance. Voici l'exemple du RFC. D'abord, la question du client, qui veut de l'information sur l'évènement 2e6df9b0-4092-4491-bcc8-9fb2166dcee6 :


<info>
  <maint:info
    xmlns:maint="urn:ietf:params:xml:ns:epp:maintenance-1.0">
    <maint:id>2e6df9b0-4092-4491-bcc8-9fb2166dcee6</maint:id>
  </maint:info>
</info>

  

Puis la réponse du serveur :

    
 <response>
    <result code="1000">
       <msg>Command completed successfully</msg>
    </result>
    <resData>
      <maint:infData
        xmlns:maint="urn:ietf:params:xml:ns:epp:maintenance-1.0">
        <maint:item>
          <maint:id>2e6df9b0-4092-4491-bcc8-9fb2166dcee6
          </maint:id>
          <maint:type lang="en">Routine Maintenance</maint:type>
          <maint:systems>
            <maint:system>
              <maint:name>EPP</maint:name>
              <maint:host>epp.registry.example
              </maint:host>
              <maint:impact>full</maint:impact>
            </maint:system>
          </maint:systems>
          <maint:environment type="production"/>
          <maint:start>2021-12-30T06:00:00Z</maint:start>
          <maint:end>2021-12-30T07:00:00Z</maint:end>
          <maint:reason>planned</maint:reason>
          <maint:detail>
            https://www.registry.example/notice?123
          </maint:detail>
          <maint:description lang="en">free-text
          </maint:description>
          <maint:description lang="de">Freitext
          </maint:description>
          <maint:tlds>
            <maint:tld>example</maint:tld>
            <maint:tld>test</maint:tld>
          </maint:tlds>
          <maint:intervention>
            <maint:connection>false</maint:connection>
            <maint:implementation>false</maint:implementation>
          </maint:intervention>
          <maint:crDate>2021-11-08T22:10:00Z</maint:crDate>
        </maint:item>
      </maint:infData>
    </resData>
    ...

  

Ici, le client connaissait l'identificateur d'une opération de maintenance particulière. S'il ne le connait pas et veut récupérer une liste d'événements :


<info>
  <maint:info
    xmlns:maint="urn:ietf:params:xml:ns:epp:maintenance-1.0">
    <maint:list/>
  </maint:info>
</info>

  

Il récupérera alors une <maint:list>, une liste d'opérations de maintenance.

Le client EPP peut également être prévenu des maintenances par la commande <poll>, qui dote EPP d'un système de messagerie (RFC 5730, section 2.9.2.3). Ainsi, un message dans la boite aux lettres du client pourra être :


<response>
  <result code="1301">
    <msg>Command completed successfully; ack to dequeue</msg>
  </result>
<msgQ count="1" id="12345">
  <qDate>2021-11-08T22:10:00Z</qDate>
  <msg lang="en">Registry Maintenance Notification</msg>
</msgQ>
<resData>
  <maint:infData
    xmlns:maint="urn:ietf:params:xml:ns:epp:maintenance-1.0">
    <maint:item>
      <maint:id>2e6df9b0-4092-4491-bcc8-9fb2166dcee6</maint:id>
      <maint:pollType>create</maint:pollType>
      <maint:systems>
        <maint:system>
          <maint:name>EPP</maint:name>
          <maint:host>epp.registry.example
          </maint:host>
          <maint:impact>full</maint:impact>
...

  

La section 5 du RFC décrit la syntaxe formelle de cette extension (en XML Schema). Elle est dans le registre IANA des extensions à EPP.

Et question mises en œuvre ? Apparemment, les registres gérés par GoDaddy et Tango envoient déjà ces informations de maintenance.


Téléchargez le RFC 9167


L'article seul

Clé PGP inutilisable ?

Première rédaction de cet article le 25 décembre 2021


Décembre 2021, des correspondants m'informent que ma clé PGP n'est plus utilisable pour m'envoyer des messages chiffrés. Unusable public key ou autres messages peu parlants. Alors que ça marchait avant.

% gpg --encrypt --recipient CCC66677 toto.txt 
gpg: CCC66677: skipped: Unusable public key
gpg: toto.txt: encryption failed: Unusable public key
    

C'était un simple oubli idiot de ma part : la clé a plusieurs sous-clés, ayant des rôles différents (chiffrement, signature…). Lors de la précédente expiration de la clé, j'avais bien re-signé mais en oubliant une des sous-clés, celle de chiffrement (une grosse bêtise). Au lieu d'un message clair du genre « cette clé a expiré » (ce qui se produit quand toutes les clés sont expirées), le logiciel, ne voyant que la clé de signature, n'arrivait pas à produire un message d'erreur intelligent. (Au passage, le format de clés PGP ou, plus exactement, OpenPGP, est normalisé dans le RFC 4880).

La clé et ses sous-clés, dont une (tout à la fin) était expirée :

sec  rsa4096/555F5B15CCC66677
     created: 2014-02-08  expires: 2023-12-21  usage: SC  
     trust: unknown       validity: undefined
ssb  rsa4096/3FA836C996A4A254
     created: 2014-02-09  expires: 2023-12-21  usage: S   
ssb* rsa4096/9045E02757F02AA1
     created: 2014-02-09  expired: 2021-12-19  usage: E   
  

(Usage: E = encryption - chiffrement, alors que Usage: S désigne la possibilité de signer.)

Une fois tout re-signé proprement :

sec  rsa4096/555F5B15CCC66677
     created: 2014-02-08  expires: 2023-12-25  usage: SC  
     trust: unknown       validity: undefined
ssb* rsa4096/3FA836C996A4A254
     created: 2014-02-09  expires: 2023-12-25  usage: S   
ssb* rsa4096/9045E02757F02AA1
     created: 2014-02-09  expires: 2023-12-25  usage: E   
  

Vous pouvez récupérer ma clé publique sur les serveurs de clés PGP habituels, ou bien directement sur ce site Web. Les raisons pour lesquelles j'ai mis une date d'expiration à ma clé (ce n'est pas obligatoire et, vous avez vu, ça peut entrainer des problèmes), sont détaillées dans un autre article.

Merci à André Sintzoff pour le signalement et à Kim Minh Kaplan pour la solution.


L'article seul

RFC 9165: Additional Control Operators for Concise Data Definition Language (CDDL)

Date de publication du RFC : Décembre 2021
Auteur(s) du RFC : C. Bormann (Universität Bremen TZI)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF cbor
Première rédaction de cet article le 25 décembre 2021


Le langage CDDL (Concise Data Definition Language) est un langage de description de schémas de données, notamment pour le format CBOR. Ce nouveau RFC étend CDDL avec de nouveaux opérateurs, permettant entre autres l'addition d'entiers et la concaténation de chaines de caractères.

CDDL est normalisé dans le RFC 8610 (et le format CBOR dans le RFC 8949). Il permet l'ajout de nouveaux opérateurs pour étendre le langage, possibilité utilisée par notre nouveau RFC. Notez que, comme les modèles de données de JSON et CBOR sont très proches, les schémas CDDL peuvent également être utilisés pour JSON, ce que je fais ici pour les exemples car le JSON est plus facile à lire et à écrire.

D'abord, l'opérateur .plus. Il permet par exemple, dans la spécification d'un schéma, de faire dépendre certains nombres d'autres nombres. L'exemple ci-dessous définit un type « intervalle » où la borne supérieure doit être supérieure de 5 à la borne inférieure :

    
top = interval<3>

interval<BASE> = BASE .. (BASE .plus 5)

  

Avec un tel schéma, la valeur 4 sera acceptée mais 9 sera refusée :

% cddl tmp.cddl validate tmp.json
CDDL validation failure (nil for 9):
[9, [:range, 3..8, Integer], ""]
  

Deuxième opérateur, la concaténation, avec le nouvel opérateur .cat :

s = "foo" .cat "bar"
  

Dans cet exemple, évidemment, .cat n'est pas très utile, on aurait pu écrire la chaine complète directement. Mais .cat est plus pertinent quand on veut manipuler des chaines contenants des sauts de ligne :

s = "foo" .cat '
 bar
 baz
'
  

Ce schéma acceptera la chaine de caractère "foo\n bar\n baz\n".

Dans l'exemple ci-dessus, bar et baz seront précédés des espaces qui apparaissaient dans le code source. Souvent, on souhaite mettre ces espaces en début de ligne dans le code source, pour l'indenter joliment, mais les supprimer dans le résultat final. Cela peut se faire avec l'opérateur pour lequel notre RFC invente le joli mot de détentation (dedending), .det, qui fonctionne comme .cat mais « dédente » les lignes :

s = "foo" .det '
 bar
 baz
'
  

Cette fois, le schéma n'acceptera que la chaine "foo\nbar\nbaz\n".

Le RFC note que, comme .det est l'abréviation de dedending cat, on aurait pu l'appeler .dedcat mais cela aurait chagriné les amis des chats.

CDDL est souvent utilisé dans les normes techniques de l'Internet et celles-ci contiennent souvent des grammaires en ABNF (RFC 5234). Pour permettre de réutiliser les règles ABNF dans CDDL, et donc se dispenser d'une ennuyeuse traduction, un nouvel opérateur fait son apparition, .abnf. Le RFC donne l'exemple de la grammaire du RFC 3339, qui normalise les formats de date : abnf-rfc3339.cddl. Avec ce fichier, on peut accepter des chaines comme "2021-12-15" ou "2021-12-15T15:52:00Z". Notons qu'il reste quelques difficultés car les règles d'ABNF ne sont pas parfaitement compatibles avec celles de CDDL. Si .abnf va traiter l'ABNF comme de l'Unicode encodé en UTF-8, un autre opérateur, .abnfb, va le traiter comme une bête suite d'octets. D'autre part, comme ABNF exige souvent des sauts de ligne, les opérateurs .cat et .det vont être très utiles.

Quatrième et dernier opérateur introduit par ce RFC, .feature. À quoi sert-il ? Comme le langage CDDL peut ếtre étendu au-delà de ce qui existait dans le RFC 8610, on court toujours le risque de traiter un schéma CDDL avec une mise en œuvre de CDDL qui ne connait pas toutes les fonctions utilisées dans le schéma. Cela produit en général un message d'erreur peu clair et, surtout, cela mènerait à considérer des données comme invalides alors qu'elles sont parfaitement acceptables pour le reste du schéma. .feature sert donc à marquer les extensions qu'on utilise. Le programme qui met en œuvre CDDL pourra ainsi afficher de l'information claire. Par exemple, si on définit une personne :

person = {
     ? name: text
     ? organization: text
}
  

puis qu'on veut rajouter son groupe sanguin :

{"name": "Jean", "bloodgroup": "O+"}
  

Cet objet sera rejeté, en raison du champ bloodgroup. On va faire un schéma plus ouvert, avec .feature :

person = {
     ? name: text
     ? organization: text
     * (text .feature "further-person-extension") => any
}
  

Et, cette fois, l'objet est accepté avec un message d'avertissement clair :

% cddl person-new-feature.cddl validate tmp.json
** Features potentially used (tmp.json): further-person-extension: ["bloodgroup"]
  

Comme le schéma est assez ouvert, la fonction de génération de fichiers d'exemple de l'outil donne des résultats amusants :

% cddl person-new-feature.cddl generate
{"name": "plain", "dependency's": "Kathryn's", "marvelous": "cleavers"}
  

Les nouveaux opérateurs ont été placés dans le registre IANA. Ils sont mis en œuvre dans l'outil de référence de CDDL (le cddl utilisé ici). Écrit en Ruby, on peut l'installer avec la méthode Ruby classique :

% gem install cddl
  

Il existe une autre mise en œuvre de CDDL (qui porte malheureusement le même nom). Elle est en Rust et peut donc s'installer avec :

% cargo install cddl

Elle n'inclut pas encore les opérateurs de ce RFC :

% /home/stephane/.cargo/bin/cddl validate --cddl plus.cddl plus.json  
Validation of "plus.json" failed

error parsing CDDL: error: lexer error
  ┌─ input:8:12
  │
8 │      (BASE .plus 1) => int   ; upper bound
  │            ^^^^^ invalid control operator
  

Mais un travail est en cours pour cela.


Téléchargez le RFC 9165


L'article seul

RFC 0810: DoD Internet host table specification

Date de publication du RFC : Mars 1982
Auteur(s) du RFC : Elizabeth Feinler, Ken Harrenstien, Zaw-Sing Su, Vic White (SRI International, Network Information Center)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 22 décembre 2021


Un peu d'histoire, avec ce RFC 810, qui mettait à jour le format du fichier géant qui, à l'époque, contenait la liste de toutes les machines de l'Internet. Il remplaçait le RFC 608.

Par rapport à son prédécesseur, ce RFC marquait le début de la fin de ce fichier géant : ses limites étaient désormais bien comprises, et le DNS était en cours d'élaboration, quoique encore dans le futur. En attendant ce système décentralisé et réparti, notre RFC mettait à jour la syntaxe du fichier HOSTS.TXT, aussi appelé « hosts » ou « host table ». Il s'appliquait à l'Internet mais aussi à son prédécesseur Arpanet qui, à l'époque, vivait encore, une vie séparée. Le fichier était ensuite distribué par un serveur centralisé, décrit dans le RFC 811. Si vous vouliez le fichier entier, notre RFC rappelait les instructions, à l'époque où les URL n'existaient pas encore : « Connectez-vous à 10.0.0.73 en FTP, en utilisant le compte ANONYMOUS et le mot de passe GUEST, puis utilisez la commande get pour le fichier <NETFINFO>HOSTS.TXT ». (On notera qu'à l'époque, le FTP anonyme était réellement anonyme, la convention d'utiliser son adresse comme mot de passe n'existait pas encore.)

Bon, quelle était la syntaxe de ce fichier ? Les noms étaient composés de lettres ASCII, de chiffres, de traits d'union et de points, en 24 caractères maximum. Ils étaient insensibles à la casse. Il existait des conventions de nommage : un routeur devait avoir un nom se terminant en -GATEWAY ou -GW. Un TAC devait se nommer quelquechose-TAC. (Le RFC ne prend pas la peine d'expliquer ce qu'est un TAC. Un TAC, Terminal Access Controller était un ordinateur spécialisé dans le service de terminaux, qui n'avait pas de compte local et ne servait qu'à se connecter à des ordinateurs distants.)

Le RFC décrit ensuite le format des adresses. Loin des débuts de l'Arpanet, elles étaient déjà sur 32 bits à l'époque (cela avait été normalisé par le RFC 796 en 1981). La longueur du préfixe dépendait de la valeur des premiers bits de l'adresse (le système des classes, qui a été abandonné en 1993).

Le fichier contenait aussi les noms des réseaux. Pour les machines, le fichier ne contenait pas que noms et adresses. À cette époque sans Web et sans moteur de recherche, il servait aussi à publier les services disponibles sur chaque machine. Et il indiquait aussi le système d'exploitation des machines, information utile quand on voulait se connecter avec telnet. (D'autres protocoles nécessitaient de connaitre ce système d'exploitation. L'utilisation de FTP en dépendait, sans compter les problèmes d'encodage des caractères, dans un monde sans Unicode.) Voici quelques exemples de machines, datant de 1983 :

HOST : 10.0.0.4, 192.5.12.21 : UTAH-CS : VAX-11/750 : UNIX : TCP/TELNET,TCP/FTP,TCP/SMTP :
HOST : 10.0.0.6 : MIT-MULTICS,MULTICS : HONEYWELL-DPS-8/70M : MULTICS : TCP/TELNET,TCP/SMTP,TCP/FTP,TCP/FINGER,TCP/ECHO,TCP/DISCARD,ICMP :
HOST : 10.0.0.9 : HARV-10,ACL : DEC-10 : TOPS10 ::
HOST : 32.2.0.42 : UCL-TAC,LONDON-TAC : H-316 : TAC : TCP :
HOST : 26.4.0.73 : SRI-F4 : FOONLY-F4 : TENEX ::
HOST : 10.0.0.51, 26.0.0.73 : SRI-NIC,NIC : DEC-2060 : TOPS20 : TCP/TELNET,TCP/SMTP,TCP/TIME,TCP/FTP,TCP/ECHO,ICMP :
  

Vous noterez que l'université d'Utah utilise toujours, en 2021, le même préfixe 192.5.12.0/24… Par contre, le MIT n'a plus de service ECHO… (Ce service était normalisé dans le RFC 862.) La machine de l'UCL était une des rares étrangères aux USA. Le Foonly qu'on voit au SRI était une machine connue pour avoir fait les CGI des films Tron et, come le note John Shaft, Looker : « première fois qu'il était possible de voir de la 3D avec ombrage dans un film, de mémoire. Un corps humain de surcroît. ». Quant à la machine SRI-NIC, c'est elle qui distribuait ce fichier (son adresse avait changé depuis la publication du RFC).

L'internet était encore assez centralisé à l'époque, et il était possible de décider d'un « jour J », où on fait changer tout le monde en même temps : ce RFC fixait la date au 1er mai 1982, où tout le monde devait utiliser le nouveau format, l'ancien, celui du RFC 608, étant abandonné.

Une copie du fichier de 1983 est en ligne (merci à Patrick Mevzek pour l'avoir trouvée) et j'en ai fait une copie locale.


Téléchargez le RFC 0810


L'article seul

RFC 9155: Deprecating MD5 and SHA-1 signature hashes in (D)TLS 1.2

Date de publication du RFC : Décembre 2021
Auteur(s) du RFC : L.V. Velvindron (cyberstorm.mu), K.M. Moriarty (CIS), A.G. Ghedini (Cloudflare)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tls
Première rédaction de cet article le 20 décembre 2021


Vous le savez certainement déjà, car toutes les lectrices et tous les lecteurs de ce blog sont très attentif·ves et informé·es, mais les algorithmes de condensation MD5 et SHA-1 ont des failles connues et ne doivent pas être utilisés dans le cadre de signatures. Vous le savez, mais tout le monde ne le sait pas, ou bien certain·es ont besoin d'un document « officiel » pour agir donc, le voici : notre RFC dit qu'on ne doit plus utiliser MD5 et SHA-1 dans TLS.

Si vous voulez savoir pourquoi ces algorithmes sont mauvais, le RFC 6151 vous renseignera (et la section 1 de notre RFC 9155 vous donnera une bibliographie récente).

La section 2 à 5 sont le cœur du RFC et elle est sont très simples : pas de MD5, ni de SHA-1 pour les signatures. Dans le registre IANA, ces algorithmes sont désormais marqués comme déconseillés.

Les fanas de cryptographie noteront qu'on peut toujours utiliser SHA-1 pour HMAC (où ses faiblesses connues n'ont pas de conséquences).


Téléchargez le RFC 9155


L'article seul

Log4Shell, et le financement du logiciel libre

Première rédaction de cet article le 14 décembre 2021


Vous avez sans doute suivi l'affaire de la faille de sécurité Log4Shell. Elle a souvent été utilisée comme point de départ pour des discussions à propos du financement du logiciel libre, en mode « de nombreuses grosses entreprises utilisent tel logiciel libre et en dépendent mais ne contribuent pas à son financement ». Ce point de vue mérite d'être nuancé.

La faille concerne le logiciel Log4j, très utilisé (ce qui explique en partie l'intérêt porté à la faille Log4Shell). Comme beaucoup de logiciels libres très utilisés, il ne bénéficie pas d'une équipe de développeurs payés à temps plein pour le maintenir. Je cite tout de suite le dessin de XKCD que tout le monde mentionne tout le temps. Face à cela, on lit souvent des affirmations comme quoi les grosses entreprises (par exemple les GAFA) devraient financer ces logiciels cruciaux. Je pense que c'est plus compliqué que cela, et je voudrais présenter ici deux faits et une opinion.

Premier fait, un ou une développeureuse de logiciel libre n'est pas forcément bénévole. Le logiciel libre n'est pas synonyme de gratuité et, de toute façon, la gratuité du logiciel ne veut pas dire que les développeureuses n'ont pas été payé·es. Il y a beaucoup de logiciels libres cruciaux qui sont maintenus par des salarié·es. (Dans le domaine du DNS, c'est le cas de tous les serveurs libres, comme BIND ou NSD, maintenus par les employé·es de l'ISC, de NLnet Labs, de PowerDNS, etc.) D'affirmer comme je l'ai lu souvent qu'il faut s'inquiéter des logiciels libres car leurs développereuses sont bénévoles est donc absurde. La question du financement du logiciel libre est une question très intéressante (il est parfaitement normal que les programmeureuses soient payé·es pour leur travail) mais elle a de nombreuses réponses.

Deuxième fait, si le logiciel est libre, par définition, personne n'est obligé de payer pour l'utiliser. Du point de vue moral, on peut trouver que ce n'est pas beau qu'Amazon ou Google ne dépensent pas un centime pour des logiciels qu'ils utilisent mais c'est le principe du logiciel libre. Un·e auteur·e de logiciel peut toujours mettre son logiciel sous une licence non-libre, imposant par exemple un paiement pour un usage commercial (ce qui est en général une mauvaise idée) mais ce n'est plus du logiciel libre.

Enfin, mon opinion. À défaut d'imposer un paiement, ce qui n'est pas possible pour un logiciel libre, ne faudrait-il pas au moins exercer une pression morale pour que les entreprises qui gagnent de l'argent avec une infrastructure composée en (bonne) partie de logiciel libre mettent la main sur l'interface Web de leur banque et envoient de l'argent ?

Ce point soulève de nombreuses questions. D'abord, si la programmeuse ou le programmeur a choisi le logiciel libre (et donc de ne pas forcément toucher de l'argent des utilisateurs), c'est qu'il y a une raison. Souvent, c'était pour être elle-même ou lui-même plus libre, pour ne pas dépendre de product owners, de commerciaux ou de décideurs qui lui diraient qu'ils veulent telle ou telle jolie fonction dans l'interface. Si le financement des logiciels libres est assuré par des grosses entreprises, elles exigeront sans doute du reporting, des process formalisés, elles demanderont un pouvoir de décision, et tou·tes les auteur·es de logiciel libre n'ont pas envie de travailler dans un tel cadre. Même si Amazon voulait payer, tout le monde ne le voudrait pas. (En outre, se faire payer pour développer du logiciel libre est parfois compliqué, du point de vue administratif, même si quelqu'un veut le faire.)

C'est d'autant plus vrai que ces grosses entreprises ont souvent un rôle très néfaste dans l'Internet. Je me souviens d'une discussion il y a quelques années avec la responsable d'un gros projet libre, financé en grande partie par des contrats avec des entreprises de l'Internet qui payaient pour que telle ou telle fonction soit développée. Je lui suggérai des améliorations pour préserver la vie privée des utilisateurices. Elle m'avait répondu « Stéphane, tu nous demandes toujours des trucs pour mieux protéger la vie privée, mais les clients qui paient nous paient pour, au contraire, trouver des moyens de récolter davantage de données. »

Bien sûr, une solution possible serait d'isoler les programmeuses ou programmeurs des financeurs via, par exemple, une fondation qui recevrait l'argent et le distribuerait (un certain nombre de gros logiciels libres fonctionnent ainsi, et c'est d'ailleurs le cas de Log4j). Mais cela ne convient pas non plus à tout le monde. (Ces fondations ne sont pas forcément innocentes.)

Et la sécurité n'y gagnerait pas forcément. Dans le cas de Log4Shell, les auteurs ont commis une bogue, c'est sûr. Mais tous les logiciels peuvent avoir des bogues, que leurs auteurs soient payés ou pas. Et, une fois la bogue signalée, tout semble indiquer que les auteurs de Log4j ont réagi vite et bien. Tout n'est pas une question de financement, et, en matière de sécurité, la conscience professionnelle et la réactivité comptent davantage. Rajouter des règles, des procédures et de la bureaucratie, sous couvert d'avoir des dévelopements logiciels « plus sérieux » ne serait pas un progrès en sécurité, probablement plutôt le contraire. (Sans compter que les grosses entreprises sont les premières à réclamer davantage de fonctions, donc davantage de failles de sécurité, et à prioriser l'apparence sur la qualité.)

[Ne me faites pas dire ce que je n'ai pas dit ; je n'ai pas proposé que les développeur·ses de logiciels soient forcément pauvres et grelottant de froid dans une mansarde non chauffée. Qu'ielles soient payé·es est normal. Mais, vu l'actuel marché de l'emploi dans la programmation, celles et ceux qui ne s'intéressent qu'à l'argent n'ont en général pas de problème. La question du financement et de la maintenance des logiciels essentiels est importante, mais elle ne se résoudra pas en demandant simplement aux GAFA de mettre la main à la poche.]

Quelques lectures sur ce sujet délicat :

  • Un appel à financer les développeurs dont on utilise le travail (appel qui n'est pas destiné qu'aux « grosses entreprises »).
  • Un rappel de la situation dans Next Inpact.
  • Un avis d'un employé de Google, qui pointe entre autres les contraintes liées aux grandes entreprises, et qui illustre parfaitement les dangers dont je parle plus haut (en disant explicitement que de payer les développeureuses permettra de leur donner des ordres).
  • Un article de Numérama décrit bien l'opinion dominante (« il faut faire payer les grosses entreprises »).
  • Au contraire, cet article pointe les dangers du financement par les grosses entreprises.
  • Un excellent article de Daniel Stenberg sur le sujet, pointant entre autres les difficultés paperassières à toucher de l'argent, même quand une entreprise ou l'État veut vous en donner, et également le fait que ce n'est pas un hasard si les logiciels touchés sont souvent des logiciels d'infrastructure, sans jolie interface que les décideurs peuvent admirer.
  • Un développeur qui pointe la paperasserie nécessaire pour se faire payer.
  • Dans le débat, des gens disent souvent open source au lieu de logiciel libre, par snobisme, parce que c'est mieux en anglais (ou bien parce qu'ils ne comprennent pas le sujet). C'est pareil.

L'article seul

RFC 9164: Concise Binary Object Representation (CBOR) Tags for IPv4 and IPv6 Addresses

Date de publication du RFC : Décembre 2021
Auteur(s) du RFC : M. Richardson (Sandelman Software Works), C. Bormann (Universität Bremen TZI)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF cbor
Première rédaction de cet article le 14 décembre 2021


Ce nouveau RFC normalise deux étiquettes CBOR pour représenter des adresses IP et des préfixes d'adresses.

Le format de données CBOR, normalisé dans le RFC 8949, a une liste de types prédéfinis mais on peut en créer d'autres, en étiquetant la donnée avec un entier qui permettre de savoir comment interpréter la donnée en question. Notre RFC introduit les étiquettes 52 (pour les adresses IPv4) et 54 (pour les adresses IPv6). Ah, pourquoi 52 et 54 ? Je vous laisse chercher, la solution est à la fin de l'article

La section 3 de notre RFC décrit le format. Pour chaque famille (IPv4 ou IPv6), il y a trois formats (tous avec la même étiquette) :

  • Les adresses à proprement parler, représentées sous forme d'une byte string CBOR (suite d'octets, cf. RFC 8949, section 3.1, type majeur 2) et donc pas sous la forme textuelle (celle avec les points pour IPv4 et les deux-points pour IPv6),
  • Les préfixes, représentés par un tableau de deux éléments, un entier pour la longueur du préfixe et une suite d'octets pour le préfixe lui-même (les octets nuls à la fin doivent être omis),
  • L'interface, sous forme d'un tableau de deux ou trois éléments, qui comporte une adresse IP, la longueur du préfixe sur cette interface et éventuellement un identificateur d'interface (genre eth0 sur Linux, voir la section 6 du RFC 4007 pour IPv6, et les RFC 4001 et RFC 6991 pour IPv4, mais cela peut aussi être un entier), identificateur qui est local à la machine.

La section 5 du RFC contient une description en CDDL (RFC 8610) de ces données.

J'ai écrit une mise en œuvre en Python de ce RFC, qui renvoie à un client HTTP son adresse IP, et le préfixe annoncé dans la DFZ en BGP (en utilisant pour cela les données du RIS, via le programme WhichASN). Le service est accessible à l'adresse https://www.bortzmeyer.org/apps/addresses-in-cbor, par exemple :

% curl -s https://www.bortzmeyer.org/apps/addresses-in-cbor > tmp.cbor

Le CBOR est du binaire, on peut regarde avec le programme read-cbor :

% read-cbor tmp.cbor                               
Array of 3 items
	String of length 165: Your IP address in CBOR [...]
	Tag 54
		Byte string of length 16
	Tag 54
		Array of 2 items
			Unsigned integer 32
			Byte string of length 4

On voit que le service renvoie un tableau CBOR de trois entrées :

  • Une chaine de caractères de documentation,
  • l'adresse IP (ici, de l'IPv6, d'où l'étiquette 54 et les 16 octets),
  • le préfixe routé, sous la forme d'une longueur (ici, 32 bits) et des octets non nuls dudit préfixe (ici, au nombre de 4).

Vu avec le programme cbor2diag, le même fichier :

% cbor2diag.rb tmp.cbor
["Your IP address in CBOR, done with Python 3.9.2 [...]", 
    54(h'200141D0030222000000000000000180'), 
    54([32, h'200141D0'])]

(Le préfixe du client HTTP était en effet bien 2001:41d0::/32.) Le code source de service est dans les sources du moteur de ce blog, plus précisement en wsgis/dispatcher.py.

Sinon, la raison du choix des étiquettes est que, en ASCII, 52 est le chiffre 4 et 54 est 6. Les deux étiquettes sont désormais dans le registre IANA. À noter que la représentation des adresses IP en CBOR avait été faite initialement avec les étiquettes 260 et 261, en utilisant un encodage complètement différent. 260 désignait les adresses (v4 et v6), 261, les préfixes. (Ces deux étiquettes sont marquées comme abandonnées, dans le registre IANA.) Au contraire, dans notre nouveau RFC, l'étiquette identifie la version d'IP, la distinction entre adresse et préfixe se faisant par un éventuel entier initial pour indiquer la longueur.


Téléchargez le RFC 9164


L'article seul

RFC 9162: Certificate Transparency Version 2.0

Date de publication du RFC : Décembre 2021
Auteur(s) du RFC : B. Laurie, A. Langley, E. Kasper, E. Messeri (Google), R. Stradling (Sectigo)
Expérimental
Réalisé dans le cadre du groupe de travail IETF trans
Première rédaction de cet article le 10 décembre 2021


Le système de gestion de certificats PKIX (dérivé des certificats X.509) a une énorme faiblesse. N'importe quelle AC peut émettre un certificat pour n'importe quel nom de domaine. Il ne suffit donc pas de bien choisir son AC, votre sécurité dépend de toutes les AC. Ce RFC propose une approche pour combler cette faille de sécurité : encourager/obliger les AC à publier « au grand jour » les certificats qu'elles émettent. Un titulaire d'un certificat qui craint qu'une AC n'émette un certificat à son nom sans son autorisation n'a alors qu'à surveiller ces publications. (Il peut aussi découvrir à cette occasion que sa propre AC s'est fait pirater ou bien est devenue méchante et émet des certificats qu'on ne lui a pas demandés. L'idée est aussi d'empêcher l'émission « discrète » de vrais/faux certificats qui seraient ensuite utilisés uniquement à certains endroits.) Ce système, dit « Certificate Transparency » (CT) avait initialement été normalisé dans le RFC 6962, que notre RFC remplace, le protocole passant à une nouvelle version, la v2 (toujours considérée comme expérimentale).

Le principe est donc de créer des journaux des certificats émis. Le journal doit être public, pour que n'importe qui puisse l'auditer (section 4 du RFC). Il doit être en mode « ajout seulement » pour éviter qu'on puisse réécrire l'histoire. Les certificats sont déjà signés mais le journal a ses propres signatures, pour prouver son intégrité. Conceptuellement, ce journal est une liste de certificats dans l'ordre de leur création. Toute AC peut y ajouter des certificats (la liste ne peut pas être ouverte en écriture à tous, de crainte qu'elle ne soit remplie rapidement de certificats bidons). En pratique, le RFC estime que la liste des AC autorisées à écrire dans le journal sera l'union des listes des AC acceptées dans les principaux navigateurs Web (voir aussi les sections 4.2 et 5.7, chaque journal est responsable de ce qu'il accepte ou pas comme soumissions).

À chaque insertion, le journal renvoie à l'AC une estampille temporelle signéee (SCT, pour Signed Certificate Timestamp), permettant à l'AC de prouver qu'elle a bien enregistré le certificat. Si on a cette signature mais que le certificat est absent du journal, l'observateur aura la preuve que le journal ne marche pas correctement. Le format exact de cette estampille temporelle est décrit en section 4.8. Idéalement, elle devra être envoyée au client par les serveurs TLS, dans l'extension TLS transparency_info (désormais enregistrée à l'IANA), comme preuve de la bonne foi de l'AC (cf. section 6 et notamment 6.5, car c'est plus compliqué que cela). Bien sûr, cette validation de l'insertion dans un journal ne dispense pas de la validation normale du certificat (un certificat peut être journalisé et mensonger à la fois). Notez aussi que, si le serveur TLS n'envoie pas toutes les données au client, celui-ci peut les demander au journal (opérations /get-proof-by-hash et get-all-by-hash) mais, ce faisant, il informe le journal des certificats qui l'intéressent et donc, par exemple, des sites Web qu'il visite.

De même, une extension à OCSP (RFC 6960) peut être utilisée pour appuyer les réponses OCSP. On peut même inclure les preuves d'inclusion dans le journal dans le certificat lui-même, ce qui permet d'utiliser des serveurs TLS non modifiés.

Les titulaires de certificats importants, comme Google, mais aussi des chercheurs, des agences de sécurité, etc, pourront alors suivre l'activité de ces journaux publics (section 8.2 du RFC). Ce qu'ils feront en cas de détection d'un certificat anormal (portant sur leur nom de domaine, mais qu'ils n'ont pas demandé) n'est pas spécifié dans le RFC : cela dépend de la politique de l'organisation concernée. Ce RFC fournit un mécanisme, son usage n'est pas de son ressort. Ce journal n'empêchera donc pas l'émission de vrais/faux certificats, ni leur usage, mais il les rendra visibles plus facilement et sans doute plus vite.

Notons que les certificats client, eux, ne sont typiquement pas journalisés (rappelez-vous que les journaux sont publics et que les certificats client peuvent contenir des données personnelles). Le serveur TLS ne peut donc pas utiliser Certificate Transparency pour vérifier le certificat du client. (Le RFC estime que le principal risque, de toute façon, est celui d'usurpation du serveur, pas du client.)

Pour que cela fonctionne, il faudra que les clients TLS vérifient que le certificat présenté est bien dans le journal (autrement, le méchant n'aurait qu'à ne pas enregistrer son vrai/faux certificat, cf. section 8.3 du RFC).

En pratique, la réalisation de ce journal utilise un arbre de Merkle, une structure de données qui permet de mettre en œuvre un système où l'ajout de certificats est possible, mais pas leur retrait, puisque chaque nœud est un condensat de ses enfants (voir aussi le RFC 8391). La section 2 du RFC détaille l'utilisation de ces arbres et la cryptographie utilisée. (Et les exemples en section 2.1.5 aident bien à comprendre comment ces arbres de Merkle sont utilisés.)

Le protocole utilisé entre les AC et le journal, comme celui utilisé entre les clients TLS et le journal, est HTTP et le format des données du JSON (section 5, qui décrit l'API). Ainsi, pour ajouter un certificat nouvellement émis au journal géré sur sunlight-log.example.net, l'AC fera :

POST https://sunlight-log.example.net/ct/v2/submit-entry

et le corps de la requête HTTP sera un tableau JSON de certificats encodés en Base64. La réponse contiendra notamment l'estampille temporelle (SCT pour Signed Certificate Timestamp). S'il y a un problème, le client recevra une des erreurs enregistrées. Pour récupérer des certificats, le programme de surveillance fera par exemple :

GET https://sunlight-log.example.net/ct/v2/get-entries

D'autres URL permettront de récupérer les condensats cryptographiques contenus dans l'arbre de Merkle, pour s'assurer qu'il est cohérent.

Comme il n'existe (en octobre 2021) aucune mise en œuvre de la version 2 du protocole, voici quelques exemples, utilisant des journaux réels, et la version 1 du protocole (notez le v1 dans l'URL). Pour trouver les coordonnées des journaux, j'ai utilisé la liste « officielle » du projet. Notez que tous les journaux qui y figurent ne fonctionnent pas correctement. Notez aussi que, comme pour les AC ou les serveurs de clés PGP, il n'y a pas de « journal de référence », c'est à chacun de choisir les journaux où il va écrire, et qu'il va lire. Le script test-ct-logs-v1.py teste la liste, et trouve :

50 logs are OK, 54 are currently broken
  

Si vous vous demandez pourquoi un même opérateur a plusieurs journaux, c'est en partie parce qu'il n'est pas possible de faire évoluer les algorithmes cryptographiques au sein d'un même journal (cf. section 9 du RFC) et qu'il faut donc de temps en temps créer un nouveau journal. Un journal est identifié par son URL, sa clé publique et (en v2) par son OID. Par exemple, le journal « Nimbus 2021 » de Cloudflare est en https://ct.cloudflare.com/logs/nimbus2021/ et a la clé MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExpon7ipsqehIeU1bmpog9TFo4Pk8+9oN8OYHl1Q2JGVXnkVFnuuvPgSo2Ep+6vLffNLcmEbxOucz03sFiematg== (je ne donne pas l'OID, il n'existe pas encore de journaux qui utilisent la version 2 du protocole). Voici un exemple d'utilisation (le STH est le Signed Tree Head, la valeur de la racine de l'arbre de Merkle, cf. section 4.2.10) :

% curl -s https://ct.cloudflare.com/logs/nimbus2021/ct/v1/get-sth | jq .                   
{
  "tree_size": 408013312,
  "timestamp": 1634739692384,
  "sha256_root_hash": "7GnGjI7L6O5fn8kQKTdJG2riShNTTbcjRP2WbLoZrvQ=",
  "tree_head_signature": "BAMARjBEAiAQ0gb6udc9e28ykUGUzl0HV8U5NlJhPVSTUF4JtXGSeQIgcSbZ9kRgttGzpFETFem4eCv7GgUYPUUnl7lTGGFZSHM="
}
  

Plus de quatre cents millions de certificats, fichtre. Si on veut récupérer les deux premiers certificats journalisés :

% curl -s https://ct.cloudflare.com/logs/nimbus2021/ct/v1/get-entries\?start=0\&end=1 | jq .
{
  "entries": [
    {
      "leaf_input":
    [L'exemple est fait avec un journal v1, l'objet JSON renvoyé est
    différent en v2.]
  

Mais vous pouvez aussi utiliser Certificate Transparency (CT) sans aller regarder du JSON. Un service en ligne comme https://crt.sh vous permet de scruter un journal. Voici par exemple l'actuel certificat de ce blog, ou bien tous les certificats au nom de la Banque Postale (CT est utile pour le renseignement).

On a vu que plusieurs acteurs intervenaient, le gérant du journal, les AC, les gens qui regardent le journal, par exemple pour l'auditer, etc. Une utilisation courante de CT est pour surveiller l'émission de certificats au nom de son entreprise ou de son organisation, pour repérer les AC qui créent des certificats incorrects. Pour éviter de programmer tout cela de zéro en partant du RFC, on peut utiliser le service Certstream, qui sert d'intermédiaire avec plusieurs journaux, et sa bibliothèque Python. Ainsi, le petit script test-certstream.py permet de détecter tous les certificats émis pour les noms de domaine en .fr :

% pip3 install certstream
  
% ./test-certstream.py
...
[2021-10-23T13:21:46] pimpmydrone.fr (SAN: www.pimpmydrone.fr)
[2021-10-23T13:21:51] pascal-goldbach.fr (SAN: www.pascal-goldbach.fr)
[2021-10-23T13:21:52] leginkobiloba.fr (SAN: www.leginkobiloba.fr)
[2021-10-23T13:21:52] promabat-distribution.fr (SAN: www.promabat-distribution.fr)
[2021-10-23T13:21:53] maevakaliciak.fr (SAN: mail.maevakaliciak.fr, www.maevakaliciak.fr)
[2021-10-23T13:21:55] pascal-goldbach.fr (SAN: www.pascal-goldbach.fr)
[2021-10-23T13:21:56] maevakaliciak.fr (SAN: mail.maevakaliciak.fr, www.maevakaliciak.fr)
[2021-10-23T13:21:57] blog.nicolas-buffart.itval.fr (SAN: euromillions-generator.itval.fr, itval.fr, loto-generator.itval.fr, password-generator.itval.fr, www.blog.nicolas-buffart.itval.fr, www.euromillions-generator.itval.fr, www.itval.fr, www.loto-generator.itval.fr, www.password-generator.itval.fr)
...

Bien sûr, cela fait beaucoup (regardez les intervalles entre deux messages). En pratique, on modifierait sans doute ce script pour ne regarder que les noms de son organisation. Ainsi, vous pouvez détecter les certificats et chercher ensuite s'ils sont légitimes (ce qui, dans certaines organisations très cloisonnées n'ira pas de soi…).

À part Certstream, Samuel Bizien Filippi me suggère CertSpotter mais qui me semble uniquement payant. Il a une API. Elle peut être utilisée par le programme check_ct_logs, qui peut être utilisé comme script de test pour les programmes de supervision comme Icinga.

Le projet « Certificate Transparency » (largement impulsé par Google) a un site officiel (lecture recommandée) et, une liste de diffusion (sans compter le groupe de travail IETF TRANS, mais qui se limitait à la normalisation, il ne parle pas des aspects opérationnels, et il a de toute façon été clos en août 2021). Questions logiciels, si vous voulez créer votre propre journal, il y a le programme de Google.

Aujourd'hui, on peut dire que « Certificate Transparency » est un grand succès. La plupart (voire toutes ?) des AC y participent, il existe de nombreux journaux publics, et ils sont fréquemment utilisés pour l'investigation numérique (voire pour le renseignement, puisqu'on peut savoir, via les journaux, les noms de domaine pas encore annoncés, ce qui a parfois été cité comme une objection contre CT). Un bon exemple est celui de l'attaque « moyen-orientale » de 2018 (mais il y a aussi l'affaire du certificat révoqué de la Poste). Par contre, un client TLS ne peut pas encore être certain que tous les certificats seront dans ces journaux, et ne peut donc pas encore refuser les serveurs qui ne signalent pas la journalisation du certificat. Et le navigateur Firefox ne teste pas encore la présence des certificats dans le sjournaux.

Un point amusant : le concept de « Certificate Transparency » montre qu'il est parfaitement possible d'avoir un livre des opérations publiquement vérifiable sans chaine de blocs. La chaine de blocs reste nécessaire quand on veut autoriser l'écriture (et pas juste la lecture) au public.

La section 1.3 du RFC résume les principaux changements entre les versions 1 (RFC 6962) et 2 du protocole :

  • Les algorithmes cryptographiques utilisés sont désormais dans des registres IANA,
  • certains échanges utilisent désormais le format CMS (RFC 5652),
  • les journaux qui étaient auparavant idenfiés par un condensat de leur clé publique le sont désormais par un OID, enregistrés à l'IANA (aucun n'est encore attribué),
  • nouvelle fonction get-all-by-hash dans l'API,
  • remplacement de l'ancienne extension TLS signed_certificate_timestamp (valeur 18) par transparency_info (valeur 52, et voir aussi le nouvel en-tête HTTP Expect-CT: d'un futur RFC,
  • et d'autres changements, dans les structures de données utilisées.

CT ne change pas de statut avec la version 2 : il est toujours classé par l'IETF comme « Expérimental » (bien que largement déployé). La sortie de cette v2 n'est pas allée sans mal (le premier document étant sorti en février 2014), avec par exemple aucune activité du groupe pendant la deuxième moitié de 2020.

Une des plus chaudes discussions pour cette v2 avait été la proposition de changer l'API pour que les requêtes, au lieu d'aller à <BASE-URL>/ct/v2/ partent du chemin /.well-known/ du RFC 8615. Cette idée a finalement été rejetée, malgré le RFC 8820, qui s'oppose à cette idée de chemins d'URL en dur.


Téléchargez le RFC 9162


L'article seul

Saisie de noms de domaine par Microsoft

Première rédaction de cet article le 9 décembre 2021


Il y a quelques jours, la justice étatsunienne a saisi, sur demande de Microsoft, un certain nombre de domaines, et les a transférés à cette société. Quelques informations techniques concrètes suivent pour celles et ceux qui seraient intéressé·es.

D'abord, le jugement du 2 décembre (trouvé par Rayna Stamboliyska, merci beaucoup) : une copie en ligne. En gros, Microsoft a identifié des noms de domaine utilisés par un groupe de délinquants nommé Nickel (apparemment entre autres pour contrôler des botnets composés de machines Microsoft Windows). La société a donc demandé à la justice de saisir ces noms. Cela marche car ces domaines étaient dans les TLD .com et .org, TLD gérés par des registres étatsuniens (alors que beaucoup de gens croient qu'ils ont un statut « international »). La justice a donné raison à Microsoft et ordonné le transfert des noms. Techniquement, c'est l'équivalent d'un détournement de nom de domaine ; Microsoft, ayant désormais le contrôle du nom, peut changer les informations associées et, par exemple, envoyer le trafic vers un serveur qu'ils contrôlent. La liste de ces noms figure dans l'annexe A du jugement.

Prenons un de ces noms au hasard, optonlinepress.com. Une requête whois nous montre le nouveau titulaire (on admire la célérité de l'opération, effectuée le lendemain du jugement) :

% whois optonlinepress.com
...
Updated Date: 2021-12-03T21:42:26Z
...
Registrant Name: Digital Crimes Unit Digital Crimes Unit
Registrant Organization: Microsoft Corporation
Registrant Street: One Microsoft Way, 
Registrant City: Redmond
Registrant State/Province: WA
Registrant Postal Code: 98052
Registrant Country: US
...
  

(Attention, .com est un registre mince, et les informations au registre peuvent être différentes de celles au BE, notamment si l'injonction judiciaire a visé le registre sans prévenir le BE. Mais, ici, tout est cohérent.)

Le domaine est désormais délégué aux serveurs DNS faisant autorité de Microsoft (ici, avec l'outil check-soa) :

% check-soa optonlinepress.com
NS104A.microsoftinternetsafety.net.
	13.107.222.41: OK: 1
NS104B.microsoftinternetsafety.net.
	13.107.206.41: OK: 1
ns001.microsoftinternetsafety.net.
	13.107.222.41: OK: 1
ns002.microsoftinternetsafety.net.
	13.107.206.41: OK: 1
  

(On notera que la liste des serveurs n'est pas la même dans la zone parente, .com et dans la zone optonlinepress.com. C'est une erreur de configuration fréquente et Zonemaster proteste à juste titre. Ici, encore plus rigolo, les serveurs supplémentaires ont la même adresse IP.)

DNSDB nous montre l'ancienne configuration :

;;  bailiwick: com.
;;      count: 136
;; first seen: 2020-06-17 19:04:12 -0000
;;  last seen: 2021-12-01 16:37:44 -0000
optonlinepress.com. IN NS ns67.domaincontrol.com.
optonlinepress.com. IN NS ns68.domaincontrol.com.
  

La nouvelle étant :

;;  bailiwick: com.
;;      count: 4
;; first seen in zone file: 2021-12-04 22:50:22 -0000
;;  last seen in zone file: 2021-12-07 22:50:26 -0000
optonlinepress.com. IN NS ns104a.microsoftinternetsafety.net.
optonlinepress.com. IN NS ns104b.microsoftinternetsafety.net.
  

L'adresse IP pour le nom optonlinepress.com est désormais 40.83.198.93 (chez Microsoft) alors qu'elle était auparavant 172.105.98.76 (chez le gros hébergeur Linode), qui ne répond plus aujourd'hui. D'ailleurs, les anciens serveurs faisant autorité répondent toujours pour ce nom (ce qui est courant en cas de saisie judiciaire, l'ancien hébergeur n'ayant pas été prévenu) :


%  dig +norecurse @ns67.domaincontrol.com. ANY optonlinepress.com

; <<>> DiG 9.16.22-Debian <<>> +norecurse @ns67.domaincontrol.com. ANY optonlinepress.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1600
;; flags: qr aa; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1472
;; QUESTION SECTION:
;optonlinepress.com.	IN ANY

;; ANSWER SECTION:
optonlinepress.com.	600 IN A 172.105.98.76
optonlinepress.com.	3600 IN	NS ns67.domaincontrol.com.
optonlinepress.com.	3600 IN	NS ns68.domaincontrol.com.
optonlinepress.com.	3600 IN	SOA ns67.domaincontrol.com. dns.jomax.net. (
				2020111802 ; serial
				28800      ; refresh (8 hours)
				7200       ; retry (2 hours)
				604800     ; expire (1 week)
				600        ; minimum (10 minutes)
				)

;; Query time: 12 msec
;; SERVER: 2603:5:2174::2c#53(2603:5:2174::2c)
;; WHEN: Thu Dec 09 10:53:43 CET 2021
;; MSG SIZE  rcvd: 164

  

L'affaire a fait l'objet d'un article sur ArsTechnica qui semble essentiellement reprendre l'article officiel de Microsoft, qui est très médiocre (utilisant au hasard des termes comme server et website, et mélangeant tout).


L'article seul

Articles des différentes années : 2022  2021  2020  2019  2018  2017  2016  Précédentes années

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

Un article de ce blog au hasard.