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

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.