Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

Les RFC (Request For Comments) sont les documents de référence de l'Internet. Produits par l'IETF pour la plupart, ils spécifient des normes, documentent des expériences, exposent des projets...

Leur gratuité et leur libre distribution ont joué un grand rôle dans le succès de l'Internet, notamment par rapport aux protocoles OSI de l'ISO organisation très fermée et dont les normes coûtent cher.

Je ne tente pas ici de traduire les RFC en français (un projet pour cela existe mais je n'y participe pas, considérant que c'est une mauvaise idée), mais simplement, grâce à une courte introduction en français, de donner envie de lire ces excellents documents. (Au passage, si vous les voulez présentés en italien...)

Le public visé n'est pas le gourou mais l'honnête ingénieur ou l'étudiant.


RFC 9755: IMAP Support for UTF-8

Date de publication du RFC : Mars 2025
Auteur(s) du RFC : P. Resnick (Episteme Technology Consulting), J. Yao (CNNIC), A. Gulbrandsen (ICANN)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF extra
Première rédaction de cet article le 18 mars 2025


Successeur du RFC 6855, voici la normalisation de la gestion d'Unicode par le protocole IMAP (dans sa version 4rev1) d'accès aux boîtes aux lettres.

Normalisé dans le RFC 3501, IMAP version 4rev1 permet d'accéder à des boîtes aux lettres situées sur un serveur distant. Ces boîtes peuvent avoir des noms en Unicode, les utilisateurs peuvent utiliser Unicode pour se nommer et les adresses gérées peuvent être en Unicode. L'encodage utilisé est UTF-8 (RFC 3629). C'est donc une des composantes d'un courrier électronique complètement international (RFC 6530). (Il existe un RFC équivalent pour POP le RFC 6856. Pour IMAP 4rev2, normalisé dans le RFC 9051, UTF-8 est prévu dès le début.)

Tout commence par la possibilité d'indiquer le support d'UTF-8. Un serveur IMAP, à l'ouverture de la connexion, indique les extensions d'IMAP qu'il gère et notre RFC normalise UTF8=ACCEPT (section 3). En l'utilisant, le serveur proclame qu'il sait faire de l'UTF-8. Par le biais de l'extension ENABLE (RFC 5161), le client peut à son tour indiquer qu'il va utiliser UTF-8. Une fois que cela sera fait, client et serveur pourront faire de l'IMAP UTF-8. Cette section 3 détaille la représentation des chaînes de caractères UTF-8 sur le réseau.

Les nouvelles capacités sont toutes décrites dans la section 10 et enregistrées dans le registre IANA.

On peut donc avoir des boîtes aux lettres qui ne peuvent être manipulées qu'en UTF-8. Les noms de ces boîtes doivent se limiter au profil « Net-Unicode » décrit dans le RFC 5198, avec une restriction supplémentaire : pas de caractères de contrôle.

Il n'y a bien sûr pas que les boîtes, il y a aussi les noms d'utilisateurs qui peuvent être en Unicode, et la section 5 spécifie ce point. Elle note que le serveur IMAP s'appuie souvent sur un système d'authentification externe (comme /etc/passwd sur Unix) et que, de toute façon, ce système n'est pas forcément UTF-8. Prudence, donc.

Aujourd'hui, encore rares sont les serveurs IMAP qui gèrent l'UTF-8. Mais, dans le futur, on peut espérer que l'internationalisation devienne la norme et la limitation à US-ASCII l'exception. Pour cet avenir radieux, la section 7 du RFC prévoit une capacité UTF8=ONLY. Si le serveur l'annonce, cela indique qu'il ne gère plus l'ASCII seul, que tout est forcément en UTF-8.

Outre les noms des boîtes et ceux des utilisateurs, cette norme IMAP UTF-8 permet à un serveur de stocker et de distribuer des messages dont les en-têtes sont en UTF-8, comme le prévoit le RFC 6532.

La section 8 expose le problème général des clients IMAP très anciens. Un serveur peut savoir si le client accepte UTF-8 ou pas (par le biais de l'extension ENABLE) mais, si le client ne l'accepte pas, que peut faire le serveur ? Le courrier électronique étant asynchrone, l'expéditeur ne savait pas, au moment de l'envoi si tous les composants, côté réception, étaient bien UTF-8. Le RFC n'impose pas une solution unique. Le serveur peut dissimuler le message problématique au client archaïque. Il peut générer un message d'erreur. Ou il peut créer un substitut, un ersatz du message originel, en utilisant les algorithmes du RFC 6857 ou du RFC 6858. Ce ne sera pas parfait, loin de là. Par exemple, de tels messages « de repli » auront certainement des signatures invalides. Et, s'ils sont lus par des logiciels différents (ce qui est un des avantages d'IMAP), certains gérant l'Unicode et d'autres pas, l'utilisateur sera probablement très surpris de ne pas voir le même message, par exemple entre son client traditionnel et depuis son webmail. C'est affreux, mais inévitable : bien des solutions ont été proposées, discutées et même décrites dans des RFC (RFC 5504) mais aucune d'idéale n'a été trouvée.

Je n'ai pas testé les implémentations en logiciel libre mais, apparemment, la bibliothèque standard de Python est déjà conforme à ce RFC (cherchez "UTF" dans la documentation), ainsi que celle de Java. Si vous connaissez des utilisateurices du courrier électronique en Unicode, demandez leur quel serveur IMAP ielles utilisent.

Le résumé des différences (peu importantes) avec son prédécesseur, le RFC 6855 est dans l'annexe B. UTF8=APPEND disparait, et FETCH BODYSTRUCTURE voit sa sémantique modifiée.


Téléchargez le RFC 9755


L'article seul

RFC 9745: The Deprecation HTTP Header Field

Date de publication du RFC : Mars 2025
Auteur(s) du RFC : S. Dalal, E. Wilde
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpapi
Première rédaction de cet article le 17 mars 2025


Ce nouveau champ de l'en-tête HTTP sert à indiquer que la ressource demande va être (ou a été) abandonné et qu'il faut penser à migrer. Il sert surtout pour les API HTTP.

(Et si vous ne savez pas ce qu'est une ressource, dans le monde HTTP, voyez la section 3.1 du RFC 9110.)

L'idée de ce champ est de permettre aux clients HTTP d'être informés, de préférence à l'avance, du fait qu'une ressource est considérée comme abandonnée et qu'ils devraient donc aller voir ailleurs. Par exemple, si on a une API avec une fonction d'URL https://api.example.com/v1/dosomething et que cette fonction est finalement jugée inutile, on pourra faire en sorte que tout appel à cet URL renvoie un champ Deprecation: dans l'en-tête, que les clients HTTP comprendront. (Ce champ a été ajouté dans le registre des champs de l'en-tête HTTP.) Deprecation: est juste une information, la ressource continue à fonctionner.

Un exemple est disponible sur ce blog (je n'en ai pas trouvé de « vraies »), qui a quelques API :


% curl -i https://www.bortzmeyer.org/apps/limit    
HTTP/1.1 200 OK
Date: Sat, 22 Feb 2025 15:50:23 GMT
Server: Apache/2.4.62 (Debian)
Deprecation: @2147483648
Link: <https://www.bortzmeyer.org/9745.html>; rel="deprecation"; type="text/html"
Content-Type: text/plain

Will be deprecated on 2038-01-19T03:14:08Z.

  

Que veut dire « @2147483648 » ? Le champ Deprecation: indique le nombre de secondes depuis l'epoch Unix. La commande GNU date vous permet de voir facilement cet instant :

% date --date=@2147483648
mar. 19 janv. 2038 03:14:08 UTC
  

C'est, dans cet exemple, au moment de la bogue de 2038 que cette ressource ne sera plus maintenue. La syntaxe utilisée est celle des objets de type Date des champs HTTP structurés (RFC 9651, section 3.3.7). D'ailleurs, cette question de syntaxe avait fait l'objet d'une intéressante discussion à l'IETF, d'autres champs HTTP, comme Sunset:, mentionné plus loin, utilisent une autre syntaxe pour les dates. Et vous trouverez, par exemple sur Stack Overflow, d'innombrables articles qui utilisent pour le champ Deprecation:, la syntaxe qui avait été initialement proposée (et qui était la même que celle de Sunset:).

Cette indication d'un futur abandon ne s'applique qu'à la ressource demandée. Si vous retirez un ensemble de ressources (par exemple votre API avait plusieurs ressources commençant par https://api.example.com/v1/ et désormais vous êtes passé à une nouvelle version, avec le préfixe https://api.example.com/v2/), vous devrez le spécifier dans la documentation associée (continuez la lecture, on va parler de cette documentation).

Vous avez sans doute remarqué dans l'exemple plus haut le champ Link:. Il sert à donner des détails, sous forme d'un URL où vous trouverez davantage d'informations. Au passage, le moment indiqué dans le champ Deprecation: peut être dans le passé indiquant que, quoi que la ressource fonctionne encore, elle est déjà considérée comme abandonnée (et donc sans doute plus maintenue). Les liens sont normalisés dans le RFC 8288 et le type de lien deprecation est désormais dans le registre des types de liens.

Arrivés à ce stade, si vous connaissez bien HTTP, vous vous demandez sans doute « Et Sunset: (RFC 8594), alors, il sert à quoi ? » Je dois dire qu'il n'est pas évident d'expliquer pourquoi les deux existent, mais notez quand même que Deprecation: est toujours plus tôt que Sunset:, qui représente donc la fin effective (Deprecation: pouvant être simplement une reclassification de la ressource, sans qu'elle cesse de fonctionner). Un exemple donné par le RFC :

Deprecation: @1688169599
Sunset: Sun, 30 Jun 2024 23:59:59 UTC   
  

Dans cet exemple, la ressource cesse d'être officiellement disponible le 1 juillet 2023 mais n'est réellement retirée que le 30 juin 2024. Après cette deuxième date, on peut supposer qu'à cet URL, on récupèrera un code de retour 404 ou, mieux, 410 (RFC 9110, section 15.5.11).

Quelques articles qui peuvent être utiles lors d'une stratégie de retrait d'une ressource :

Et le champ Expires: (RFC 9111, section 5.3) ? Rien à voir, Expires: concerne le contenu, mais l'URL reste stable et fonctionnel.

Un petit mot sur la sécurité (section 7 du RFC). Le champ Deprecation: n'est qu'une indication et il ne faut sans doute pas agir automatiquement sur la base de ce champ. Toujours vérifier la documentation !

Pour traiter ce champ, ainsi que le Sunset: du RFC 8594, regardez ce script Python. Quelques exemples d'utilisation dans le monde :

  • L'entreprise de mode Zalando a un guide de la conception d'API qui recommande ce champ.
  • La mise en œuvre dans la bibliothèque Requests a été discutée mais le consensus a plutôt été que c'était à l'application utilisatrice de gérer cela.
  • Mon client pour l'API RIPE Atlas, Blaeu, a ce code pour tester si l'API utilisée ne va pas être abandonnée, tiré de l'exemple Python cité plus haut.
  • Et bien plus encore qui ont le concept mais avec une autre syntaxe, choisie avant ce RFC.

Téléchargez le RFC 9745


L'article seul

RFC 9743: Specifying New Congestion Control Algorithms

Date de publication du RFC : Mars 2025
Auteur(s) du RFC : M. Duke (Google), G. Fairhurst (University of Aberdeen)
Réalisé dans le cadre du groupe de travail IETF ccwg
Première rédaction de cet article le 14 mars 2025


La lutte contre la congestion du réseau est une tâche permanente des algorithmes utilisés dans l'Internet. Si les émetteurs de données envoyaient des octets aussi vite qu'ils le pouvaient, sans jamais réfléchir, l'Internet s'écroulerait vite. Des protocoles comme TCP ou QUIC contiennent donc des algorithmes de contrôle de la congestion. Il y en a plusieurs, certains peuvent être néfastes, et ce RFC, qui remplace le RFC 5033, explique comment de nouveaux algorithmes doivent être évalués avant d'être déployés en vrai. Bref, la prudence est nécessaire.

Le RFC 2914 expose les principes généraux du contrôle de congestion du réseau. Notre RFC 9743 a un autre but : créer un cadre d'évaluation des algorithmes de contrôle de la congestion. Car c'est très difficile de concevoir et de spécifier un tel algorithme. Songez qu'il doit fonctionner sur des types de liens très différents, des réseaux à énorme capacité sur les courtes distance d'un centre de données (RFC 8257) à des liaisons radio à grande distance et avec un fort taux de perte de paquets. Il doit fonctionner en Wifi, sur la fibre, sur des liens surchargés, bien exploiter des liens à forte capacité, supporter des liens à forte latence, etc. Et l'efficacité de ces algorithmes dépend aussi de l'application qui va les utiliser, la vidéoconférence ne produisant pas les mêmes effets que le transfert de fichiers, le visionnage de vidéos haute définition, les connexions interactives type SSH, l'accès à des sites Web, etc).

La plupart des protocoles de transport normalisés par l'IETF ont du contrôle de congestion. Quand le RFC 5033 a été publié, cela concernait surtout TCP (RFC 9293), avec des outsiders comme DCCP (RFC 4340) ou SCTP (RFC 9260). Mais il y a aussi désormais QUIC (RFC 9000) et RMCAT (RFC 8836).

Parmi les algorithmes de contrôle de la congestion développés pour l'Internet, on peut citer CUBIC RFC 9438, Reno RFC 5681, BBR (pas encore de RFC mais il y a un brouillon, draft-ietf-ccwg-bbr), et autres.

Le RFC 5033 ne dit pas clairement si on a « le droit » de déployer un nouvel algorithme de contrôle de la congestion sans l'avoir normalisé dans un RFC. En tout cas, en pratique, comme le montre le déploiement de CUBIC et BBR, on n'attend pas le RFC (l'Internet est sans permission), on publie le code, sous une licence libre dans le cas ci-dessus (CUBIC a été surtout porté par sa mise en œuvre dans Linux) et on y va. Pourtant, avoir une spécification écrite et disponible, revue par l'IETF, serait certainement bénéficiaire pour tout le monde, permettant un examen large du nouvel algorithme et de certaines de ses conséquences imprévues.

(Le RFC cite un très bizarre argument comme quoi, dans certaines entreprises, les développeurs ont le droit de lire les RFC mais pas le code source publié sous une licence libre. Je ne suis pas juriste mais cela ressemble à un disjonctage sérieux de la part du juriste qui a prétendu cela.)

Notre RFC 9743 est donc un guide pour les gens qui vont faire cette très souhaitable évaluation des algorithmes de lutte contre la congestion, dans le prolongement du RFC 2914.

Donc, place au guide, en section 3, le centre de ce RFC. Premier objectif, qu'il existe plusieurs mises en œuvre de l'algorithme, et sous une licence libre. Ce n'est pas une obligation (surtout si le RFC décrivant l'algorithme a le statut « Expérimental ») mais c'est souhaité.

En parlant d'algorithmes expérimentaux, le RFC rappelle que la spécification d'un tel algorithme doit indiquer quels résultats on attend de l'expérience, et ce qu'il faudrait pour progresser. La section 12 du RFC 6928 et la section 4 du RFC 4614 sont de bons exemples en ce sens.

Un algorithme expérimental ne doit pas être activé par défaut et doit être désactivable s'il a des comportements désagréables. Mais il faut quand même le tester sinon il ne progressera jamais et ce test peut, au début, être fait dans un simulateur (RFC 8869) mais il doit, à un moment, être fait en vrai grandeur, dans l'Internet réel. Le RFC ajoute donc que tout déploiement ne doit être fait qu'accompagné de mesures qui permettront d'obtenir des informations.

Comme résultat de l'évaluation, tout RFC décrivant un algorithme de contrôle de congestion doit indiquer explicitement, dès le début, s'il est sûr et peut être déployé massivement sans précautions particulières. (Un exemple d'expérimentation figure dans le RFC 3649.)

Une exception est faite par notre RFC sur les « environnements contrôlés » (section 4). Il s'agit de réseaux qui sont sous le contrôle d'une seule organisation, qui maitrise tout ce qui s'y passe, sans conséquences pour des tiers (RFC 8799), et peuvent donc utiliser des algorithmes de contrôle de la congestion qu'on ne voudrait pas voir déployés dans l'Internet public. Un exemple typique d'un tel « environnement contrôlé » est un centre de données privé, avec souvent des commutateurs qui signalent aux machines terminales l'état du réseau, leur permettant d'ajuster leur débit (sur les centres de données, voir aussi la section 7.11).

Une fois passé ce cas particulier, allons voir la section 5, qui est le cœur de ce RFC ; elle liste les critères d'évaluation d'un algorithme de contrôle de la congestion. D'abord, dans le cas relativement simple où plusieurs flux de données sont en compétition sur un même lien mais que tous utilisent l'algorithme évalué. Est-ce que chaque flux a bien sa juste part (qui est une part égale aux autres, lorsque les flux veulent transmettre le plus possible) ? En outre, est-ce que l'algorithme évite l'écroulement qui se produit lorsque, en raison de pertes de paquets, les émetteurs ré-émettent massivement, aggravant le problème ? Pour cela, il faut regarder si l'algorithme ralentit en cas de perte de paquets, voire arrête d'émettre lorsque le taux de pertes devient trop important (cf. RFC 3714). Lire aussi les RFC 2914 et RFC 8961, qui posent les principes de cette réaction à la perte de paquets. Ce critère d'évaluation n'impose pas que le mécanisme d'évitement de la congestion soit identique à celui de TCP.

Une façon d'éviter de perdre les paquets est de les mettre dans une file d'attente, en attendant qu'ils puissent être transmis. Avec l'augmentation de la taille des mémoires, on pourrait penser que cette solution est de plus en plus bénéfique. Mais elle mène à de longues files d'attente, où les paquets séjourneront de plus en plus longtemps, au détriment de la latence, un phénomène connu sous le nom de bufferbloat. Le RFC demande donc qu'on évalue les mécanismes de contrôle de la congestion en regardant comment ils évitent ces longues files d'attente (RFC 8961 et RFC 8085, notez que Reno et CUBIC ne font rien pour éviter le bufferbloat).

Il est bien sûr crucial d'éviter les pertes de paquets ; même si les protocoles comme TCP savent les rattraper (en demandant une réémission des paquets manquants), les performances en souffrent, et c'est du gaspillage que d'envoyer des paquets qui seront perdus en route. Un algorithme comme la première version de BBR (dans draft-cardwell-iccrg-bbr-congestion-control-00) avait ce défaut de mener à des pertes de paquets. Mais cette exigence laisse quand même pas mal de marge de manœuvre aux protocoles de contrôle de la congestion.

Autre exigence importante, l'équité (ou la justice). On la décrit souvent en disant que tous les flux doivent avoir le même débit. Mais c'est une vision trop simple : certains flux n'ont pas grand'chose à envoyer et il est alors normal que leur débit soit plus faible. L'équité se mesure entre des flux qui sont similaires.

En parlant de flux, il faut noter que, comme les algorithmes de contrôle de congestion n'atteignent leur état stable qu'au bout d'un certain temps, les flux courts, qui peuvent représenter une bonne partie du trafic (songez à une connexion TCP créée pour une seule requête HTTP d'une page de petite taille) n'auront jamais leur débit théorique. Les auteurs d'un protocole de contrôle de la congestion doivent donc étudier ce qui se passe lors de flux courts, qui n'atteignent pas le débit asymptotique.

La question de l'équité ne concerne pas que les flux utilisant tous le même algorithme de contrôle de la congestion. Il faut aussi penser au cas où plusieurs flux se partagent la capacité du réseau, tout en utilisant des algorithmes différents (section 5.2). Le principe, lorsqu'on envisage un nouveau protocole, est que les flux qui l'utilisent ne doivent pas obtenir une part de la capacité plus grande que les flux utilisant les autres protocoles (RFC 5681, RFC 9002 et RFC 9438). Les algorithmes du nouveau protocole doivent être étudiés en s'assurant qu'ils ne vont pas dégrader la situation, et ne pas supposer que le protocole sera le seul, il devra au contraire coexister avec les autres protocoles. (Dans un réseau décentralisé comme l'Internet, on ne peut pas espérer que tout le monde utilise le même protocole de contrôle de la congestion.)

Pour compliquer la chose, il y a aussi des algorithmes qui visent à satisfaire les besoins spécifiques des applications « temps réel ». Leur débit attendu est faible mais ils sont par contre très exigeants sur la latence maximale (cf. RFC 8836). La question est étudiée dans les RFC 8868 et RFC 8867 ainsi que, pour le cas spécifique de RTP, dans le RFC 9392. Si on prétend déployer un nouveau protocole de contrôle de la congestion, il doit coexister harmonieusement avec ces protocoles temps réel. La tâche est d'autant plus difficile, note notre RFC, que ces protocoles sont souvent peu ou mal documentés.

Bon, quelques autres trucs à garder en tête. D'abord, il faut évidemment que tout nouveau protocole soit déployable de manière incrémentale. Pas question d'un flag day où tout l'Internet changerait de mécanisme de contrôle de la congestion du jour au lendemain (section 5.3.2). Si le protocole est conçu pour des environnements très spécifiques (comme l'intérieur d'un centre de données privé), il peut se permettre d'être plus radical dans ses choix mais le RFC insiste sur l'importance, dans ce cas, de décrire les mesures par lesquelles on va s'assurer que le protocole n'est réellement utilisé que dans ces environnements. Un exemple de discussion sur le déploiement incrémental figure dans les sections 10.3 et 10.4 du RFC 4782.

La section 6 de notre RFC rappelle que le protocole doit être évalué dans des environnements différents qu'on peut rencontrer sur l'Internet public. Ainsi, les liaisons filaires se caractérisent par une très faible quantité de perte de paquets, sauf dans les routeurs, lorsque leur file d'attente est pleine. Et leurs caractéristiques sont stables dans le temps. En revanche, les liens sans fil ont des caractéristiques variables (par exemple en fonction d'évènements météorologiques) et des pertes de paquets en route, pas seulement dans les routeurs. Le RFC 3819 et le brouillon draft-irtf-tmrg-tools (dans sa section 16) discutent ce problème, que l'algorithme de contrôle de congestion doit prendre en compte.

Tout cela est bien compliqué, vous allez me dire ? Mais ce n'est pas fini, il reste les « cas spéciaux » de la section 7. D'abord, si le routeur fait de l'AQM, c'est-à-dire jette des paquets avant que la file d'attente ne soit pleine. Des exemples de tels algorithmes sont Flow Queue CoDel (RFC 8290), PIE (Proportional Integral Controller Enhanced, RFC 8033) ou L4S (Low Latency, Low Loss, and Scalable Throughput, RFC 9332). L'évaluation doit donc tenir compte de ces algorithmes.

Certains réseaux disposent de disjoncteurs (breakers, RFC 8084), qui surveillent le trafic et coupent ou réduisent lorsque la congestion apparait. Là encore, tout nouvel algorithme de contrôle de la congestion qu'on utilise doit gérer le cas où de tels disjoncteurs sont présents.

Autre cas qui complique les choses, les réseaux à latence variable. Avec un réseau simple, la latence dans les câbles est fixe et la latence vue par les flux ne varie qu'avec l'occupation des files d'attentes du routeur. Mais un chemin à travers l'Internet n'est pas simple, et la latence peut varier dans le temps, par exemple parce que les routes changent et qu'on passe par d'autres réseaux. (Voir par exemple les conséquences d'une coupure de câble.) Bref, le protocole de contrôle de la congestion ne doit pas supposer une latence constante. En parlant de latence, il y a aussi des liens qui ont une latence bien plus élevée que ce que qu'attendent certains protocoles simples. C'est par exemple le cas des liens satellite (RFC 2488 et RFC 3649). Et en parlant de variations, l'Internet voit souvent des brusques changements, par exemple un brusque afflux de paquets, et notre protocole devra gérer cela (section 9.2 du RFC 4782). J'avais dit que l'Internet était compliqué !

Et pour ajouter à cette complication, il y a des réseaux qui changent l'ordre des paquets. Oui, vous savez cela. Tout le monde sait qu'IP ne garantit pas l'ordre d'arrivée des paquets. Tout le monde le sait mais notre RFC juge utile de le rappeler car c'est un des défis que devra relever un protocole de contrôle de la congestion : bien fonctionner même en cas de sérieux réordonnancement des paquets, comme discuté dans le RFC 4653.

L'algorithme utilisé pour gérer la congestion ne doit pas non plus être trop subtil, car il faudra qu'il puisse être exécuté par des machines limitées (en processeur, en mémoire, etc, cf. RFC 7228).

Le cas où un flux emprunte plusieurs chemins (Multipath TCP, RFC 8684, mais lisez aussi le RFC 6356) est délicat. Par exemple, on peut avoir un seul des chemins qui est congestionné (le protocole de gestion des chemins peut alors décider d'abandonner ce chemin) mais aussi plusieurs chemins qui partagent le même goulet d'étranglement.

Et, bien sûr, l'Internet est une jungle. On ne peut pas compter que toutes les machines seront gérées par des gentilles licornes arc-en-ciel bienveillantes. Tout protocole de contrôle de la congestion déployé dans l'Internet public doit donc tenir compte des méchants. (Il y a aussi, bien plus nombreux, les programmes bogués et les administrateurs système incompétents. Mais, si un protocole tient le coup en présence d'attaques, a fortiori, il résistera aux programmes non conformes.) Une lecture intéressante est le RFC 4782, dans ses sections 9.4 à 9.6.

L'annexe A résume les changements depuis le RFC 5033. Il y a notamment :

  • L'ajout de QUIC,
  • un texte plus précis sur le bufferbloat,
  • le cas des machines contraintes (pour l'IoT),
  • des discussions sur l'AQM, les flux courts, le temps réel…

Téléchargez le RFC 9743


L'article seul

RFC 9741: Concise Data Definition Language (CDDL): Additional Control Operators for the Conversion and Processing of Text

Date de publication du RFC : Mars 2025
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 5 mars 2025


Le langage CDDL, qui permet de créer un schéma formel pour des formats comme CBOR, peut s'étendre via l'ajout d'« opérateurs de contrôle ». Ce RFC en spécifie quelques uns, notamment pour agir sur du texte ou convertir d'une forme dans une autre.

CDDL est normalisé dans le RFC 8610. Sa principale utilisation est pour fournir des schémas afin de valider des données encodées en CBOR (RFC 8949). Du fait de l'extensibilité de CDDL (voir notamment RFC 8610, section 3.8), le RFC 9165 a pu ajouter l'addition, la concaténation, etc. Notre nouveau RFC 9741 ajoute encore d'autres opérateurs, surtout de conversion d'une représentation dans une autre.

Je ne vais pas tous les citer ici (lisez le RFC), juste donner quelques exemples. D'abord, .b64u, qui va convertir une chaine d'octets en sa représentation en Base64 (RFC 4648 et, rassurez-vous, il y a aussi des opérateurs pour Base32 et les autres).

Voici un exemple. Mais d'abord, on installe l'outil cddl. Écrit en Ruby, il s'installe avec :

% gem install cddl
  

Ensuite, on écrit un schéma CDDL utilisant l'opérateur .b45 (Base45 est normalisé dans le RFC 9285) :

%    cat base.cddl
encoded = text .b45 "Café ou thé ?"
  

En utilisant les fonctions de génération de l'outil cddl, on trouve :

% cddl base.cddl generate
"EN8R:C6HL34ES44:AD6HLI1"
  

C'est bien l'encodage en Base45 de la chaine de caractères utilisée (évidemment, dans un vrai schéma, on utiliserait une variable, pas une chaine fixe).

Ensuite, .printf va formater du texte, en utilisant les descriptions de format du printf de C.


% cat printf.cddl 
my_alg_19 = hexlabel<19>
hexlabel<K> = text .printf (["0x%04x", K])

% cddl printf.cddl generate 
"0x0013"

  

Bien sûr, ce n'est pas la méthode la plus simple pour convertir le 19 décimal en 13 hexadécimal. Mais le but est simplement d'illustrer le fonctionnement des nouveaux opérateurs.

Enfin, .join va transformer un tableau en chaine d'octets. Voici l'exemple du RFC, avec des adresses IPv4 :


% cat address.cddl

legacy-ip-address = text .join legacy-ip-address-elements
legacy-ip-address-elements = [bytetext, ".", bytetext, ".",
                                 bytetext, ".", bytetext]
bytetext = text .base10 byte
byte = 0..255

% cddl address.cddl generate
"108.58.234.211"
% cddl address.cddl generate
"42.65.53.156"
% cddl address.cddl generate
"77.233.49.115"
 

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 :

% ~/.cargo/bin/cddl validate --cddl schema.cddl --json person.json
Error: "error: lexer error\n  ┌─ input:7:26\n  │\n7 │ legacy-ip-address = text .join legacy-ip-address-elements\n  │                          ^^^^^ invalid control operator\n\n"
  

Téléchargez le RFC 9741


L'article seul

RFC 9724: Randomized and Changing MAC Address State of Affairs

Date de publication du RFC : Mars 2025
Auteur(s) du RFC : JC. Zúñiga (CISCO), CJ. Bernardos (UC3M), A. Andersdotter (Safespring AB)
Pour information
Réalisé dans le cadre du groupe de travail IETF madinas
Première rédaction de cet article le 20 mars 2025


Dans le contexte de la surveillance massive qui s'exerce contre les utilisateurices de l'Internet, tout identifiant un peu stable peut être utilisé pour pister quelqu'un. On en laisse, des traces ! C'est par exemple le cas avec l'adresse MAC. Ce nouveau RFC décrit les mécanismes existants pour diminuer le risque de pistage par l'adresse MAC. Il ne spécifie pas un protocole, il liste les solutions.

Ne croyez donc pas les médias et les politiciens qui vous diraient que le problème de l'Internet, c'est l'anonymat. C'est tout le contraire : il est extrêmement difficile d'utiliser l'Internet sans laisser de traces partout, traces qui peuvent être corrélées si on réutilise un identifiant, comme l'adresse MAC (dite également adresse Ethernet ou bien adresse physique).

(Au passage, le RFC contient une remarque très désagréable comme quoi l'une des causes des problèmes de vie privée serait « le manque d'éducation [des utilisateurices ?] ». S'il est vrai que la littératie numérique en matière de sécurité est très perfectible, il ne faudrait pas pour autant tout rapporter à l'ignorance. Les utilisateurices ne sont pas responsables de la surveillance massive, dont l'ubiquité et la sophistication font qu'il est difficile de se défendre, même pour un·e expert·e. Et les innombrables entreprises et États qui pistent les utilisateurices ne le font pas par ignorance mais cherchent en toute conscience à récolter le maximum de données.)

Le problème du pistage se place à tous les niveaux du modèle en couches ; les adresses MAC en couche 2, les adresses IP en couche 3, les cookies pour le Web en couche 7, etc. Pour la couche 2, sujet de notre RFC, voyez par exemple l'analyse « Wi-Fi internet connectivity and privacy: Hiding your tracks on the wireless Internet » (comme l'IEEE fait partie de ces organisations de normalisation réactionnaires qui ne permettent pas l'accès libre à leurs documents, prenez une copie), ou bien cet article décrivant comment les poubelles vous pistent.

Le problème est d'autant plus sérieux qu'aujourd'hui, plein d'équipements électroniques ont la WiFi (en termes plus techniques, IEEE 802.11) et donc une adresse MAC unique, qui peut servir au pistage. On ne pense pas forcément à ces équipements comme étant des ordinateurs, susceptibles d'émettre et donc de révéler leur présence. Quiconque écoute le réseau va voir ces adresses, il n'y a pas besoin d'être actif, une écoute passive suffit. Même sans association avec la base, la machine se signale par les Probe Request qu'elle envoie. Dans le cas typique, l'adresse 802.11 est composée de deux parties, l'OUI (Organizationally Unique Identifier), qui identifie le fournisseur, et le Network Interface Controller Specific, qui identifie une des machines (en toute rigueur, plutôt une des interfaces réseau) dudit fournisseur. La combinaison des deux fait une adresse unique (au moins en théorie), traditionnellement attribuée à la fabrication et pas changée ensuite. Cette adresse unique est donc, malheureusement pour la vie privée, un bon identificateur stable. Mais une adresse MAC peut aussi être localement gérée (elle n'est alors plus forcément unique), et, contrairement à ce que croient certaines personnes, l'adresse globale par défaut n'est pas obligatoire. (Un bit dans l'adresse indique si elle est globale ou locale. Le RFC 8948 définit même un plan d'adressage pour ces adresses locales.) On peut donc échapper au pistage en changeant d'adresse de temps en temps (cf. l'article de Gruteser et D. Grunwald, « Enhancing location privacy in wireless LAN through disposable interface identifiers: a quantitative analysis »). Ces questions de vie privée liées à l'adresse MAC sont décrites plus en détail dans l'article « Privacy at the Link Layer », de Piers O'Hanlon, Joss Wright et Ian Brown, présenté à l'atelier STRINT, dont le compte-rendu a été le RFC 7687. Notre RFC rappelle aussi que, bien sûr, la protection de la vie privée ne dépend pas uniquement de cette histoire d'adresse MAC et que les surveillants ont d'autres moyens de pistage, qu'il faut combattre également, cf. section 9.

Un peu d'histoire : l'IEEE, qui normalise 802.11 et donc les adresses MAC, avait pour la première fois traité le problème lors d'un tutoriel en 2014, qui avait suivi l'atelier STRINT (celui dont le compte-rendu est dans le RFC 7687). Suite à ce tutoriel, l'IEEE avait créé l'IEEE 802 EC Privacy Recommendation Study Group, ce qui avait finalement donné naissance à des documents IEEE comme IEEE 802E-2020 - IEEE Recommended Practice for Privacy Considerations for IEEE 802 Technologies et 802c-2017 - IEEE Standard for Local and Metropolitan Area Networks:Overview and Architecture--Amendment 2: Local Medium Access Control (MAC) Address Usage. Les idées documentées avaient été testées lors de réunions plénières de l'IEEE et de l'IETF. Ces tests ont montré que les collisions (deux adresses MAC identiques) étaient extrêmement rares. Elles ont aussi permis de constater que certains identificateurs visibles (comme celui envoyé en DHCP, cf. RFC 7819) restent stables et qu'il ne suffit donc pas de changer l'adresse MAC. Je recommande la lecture du rapport « IEEE 802E Privacy Recommendations & Wi-Fi Privacy Experiment @ IEEE 802 & IETF Networks> », présenté à l'IETF 96 à Berlin en 2016.

Depuis, l'aléatoirisation des adresses MAC a été largement déployée, sur iOS, sur Android, sur Microsoft Windows, sur Fedora, etc. Il n'y a évidemment pas de solution parfaite et des chercheurs ont déjà trouvé comment contourner l'aléatoirisation. Cela a mené à une nouvelle norme IEEE, 802.11aq.

Ce changement de l'adresse MAC a ensuite posé problème à certains opérateurs de réseaux mobiles. (Voir aussi « IEEE 802.11 Randomized And Changing MAC Addresses Topic Interest Group Report » et « RCM A PAR Proposal ».)

La question de la vie privée s'est beaucoup posée à l'IETF dans le contexte de l'auto-affectation des adresses IPv6 (SLAAC : Stateless Address Autoconfiguration). Le RFC 1971 et ses successeurs (le dernier en date est le RFC 4862) prévoyaient que la partie spécifique à la machine de l'adresse IPv6 soit fondée sur l'adresse MAC, ce qui permettait le pistage. Cette méthode, qui a fait couler beaucoup d'encre, est désormais déconseillée (RFC 8064). La méthode recommandée maintenant est celle du RFC 8981, avec ses adresses aléatoires et temporaires. (Elles ont d'autres avantages, comme de limiter la durée pendant laquelle on peut se connecter à une machine depuis l'extérieur.) Évidemment, ces adresses temporaires ne conviennent pas aux serveurs (qui doivent être joignables) ni aux cas où l'administrateur réseau veut pouvoir garder trace des adresses IP des machines (dans ce dernier cas, le RFC 7217, avec ses adresses stables tant qu'on reste dans le même réseau, est la solution recommandée).

On l'a dit, l'adresse MAC n'est pas le seul moyen qu'on a de suivre une machine à la trace. Les identifiants qui figurent dans la requête DHCP en sont un autre. Le RFC 7844 rassemble les recommandations faites aux auteur·es de logiciels DHCP pour limiter ce pistage.

On a donc vu qu'on pouvait changer son adresse MAC et que c'était une bonne chose pour la protection de sa vie privée. Mais la changer pour quoi ? La section 6 de notre RFC résume toutes les politiques possibles :

  • Adresse MAC fixe déterminée par le fournisseur (c'est la politique ancienne et traditionnelle) et enregistrée en dur dans l'interface réseau.
  • Adresse permanente mais générée localement, sur la machine, typiquement au premier démarrage. On parle de PDGM (Per-Device Generated MAC).
  • Adresse temporaire générée localement, au démarrage de la machine. On parle de PBGM (Per-Boot Generated MAC). Plus besoin de mémoire stable.
  • Adresse fixe générée localement, pour chaque réseau. L'adresse est stockée dans une mémoire stable, indexée par un identificateur du réseau (le SSID pour le Wifi, et diverses heuristiques utilisant par exemple STP pour les réseaux fixes). Cette politique empêche le pistage trans-réseau mais permet une stabilité utile pour l'administrateur du réseau. On parle de PNGM (Per-Network Generated MAC).
  • Adresse temporaire renouvelée régulièrement, par exemple toutes les douze heures. On parle de PPGM (Per-Period Generated MAC).
  • Adresse temporaire par « session ». La session étant par exemple une connexion via le portail captif. On parle de PSGM (Per-Session Generated MAC).

Que font les systèmes d'exploitation d'aujourd'hui ? La section 7 détaille les pratiques actuelles. Un point important est que, depuis longtemps, tous ces systèmes mettent en œuvre une forme ou l'autre d'aléatoirisation, pour les questions de vie privée citées ici. Comme la situation évolue, plutôt que de lire cette section du RFC, vous avez peut-être intérêt à suivre en ligne. Au moment de la rédaction de cet article, les versions actuelles d'Android et d'iOS étaient en PNGM (adresse choisie aléatoirement mais liée au SSID). Idem pour Debian et Windows. Mais lisez les détails, qui peuvent dépendre de points subtils. config-mac-address.png


Téléchargez le RFC 9724


L'article seul

RFC 9720: RFC Formats and Versions

Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : P. Hoffman (ICANN), H. Flanagan (Spherical Cow Consulting)
Pour information
Première rédaction de cet article le 18 janvier 2025


Vous le savez, les RFC ne sont plus en texte brut depuis des années, leur format officiel est du XML. Le système était décrit dans le RFC 7990, que ce nouveau RFC remplace. Il y a beaucoup de changements sur la forme et aussi sur le fond, notamment la possibilité de modifier un fichier déjà publié (sans changer sa sémantique, bien sûr).

La section 2 de notre RFC décrit ce qu'est la « version définitive » d'un RFC. Écrite dans le format RFCXML spécifié dans le RFC 7991, elle peut donc comporter des images en SVG (voir le RFC 7996) et des caractères non-ASCII (cf. RFC 7997). Cette version définitive contient tout ce qui est nécessaire pour produire le RFC publié. (Les versions de développement, avant la publication, peuvent utiliser des références externes, qui devront être résolues dans la version définitive, qui sera auto-suffisante.)

Mais le changement le plus spectaculaire de notre RFC 9720 est que cette version « définitive » peut désormais changer. Si on découvre un problème dans le fichier XML, il pourra être modifié, si cela ne change pas le sens, bien sûr. La section 2.1 décrit précisément les règles de changement. En cas de modification, les versions antérieures devront être gardées, avec leurs métadonnées (comme la date) et accessibles publiquement, comme les RFC l'ont toujours été (section 4), ce qui a beaucoup contribué au succès de l'Internet.

De nouvelles versions de publication, produites à partir de la version définitive, seront produites, soit parce que la version définitive a changé, soit parce que les outils ont évolué et permettent un meilleur rendu (section 3). (La re-publication pour corriger des erreurs de rendu existait déjà et la liste des cas est en ligne.)

Notez que ce RFC ne s'applique qu'au produit final. L'élaboration des RFC, via les Internet drafts, n'est pas concernée, même si elle va sans doute s'aligner. (Si vous en écrivez et que vous voulez utiliser le format XML, ce que je recommande, une page Web dédiée est là pour vous aider.)

La section 1.1 résume les changements depuis le RFC 7990. On garde le format XML normalisé dans le RFC 7991 mais on change le concept de « format canonique », qui mélangeait plusieurs choses. Il y a désormais :

  • le format final, forcément en XML, donc, c'est le format de référence, qui s'appelait « xml2rfc version 3 » et se nomme désormais RFCXML,
  • la version finale qui, en dépit de son nom, peut désormais changer,
  • le format de publication (texte brut, HTML ou PDF),
  • la version de publication, c'est-à-dire un document dans un format de publication, fait à partir de la version finale.

Notre RFC spécifie dans quelles conditions on peut désormais changer la version finale (contrairement à la règle du RFC 9280). En gros, il faut que la sémantique reste inchangée. Cela permet d'effectuer les changements suite à des erreurs de format XML ou bien lorsqu'une évolution des logiciels ne permet plus de traiter l'ancien fichier. Mais cela pose peut-être des problèmes de sécurité et la section 6 appelle à la vigilance face au risque d'utiliser une version non-officielle.

Et, sinon, le RFC Editor » devient le « RFC Production Center » (mais je parie que l'ancien terme, chargé d'histoire, va rester encore longtemps).

On sait que le premier RFC publié sous le nouveau système (format de référence en XML) était le RFC 8651. Depuis, tous les autres RFC ont suivi ce système.


Téléchargez le RFC 9720


L'article seul

RFC 9718: DNSSEC Trust Anchor Publication for the Root Zone

Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : J. Abley (Cloudflare), J. Schlyter (Kirei AB), G. Bailey (Independent), P. Hoffman (ICANN)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 25 janvier 2025


Le mécanisme d'authentification des informations DNS nommé DNSSEC repose sur la même structure arborescente que le DNS : une zone publie un lien sécurisé vers les clés de ses sous-zones. Un résolveur DNS validant n'a donc besoin, dans la plupart des cas, que d'une seule clé publique, celle de la racine. Elle lui servira à vérifier les clés des TLD, qui serviront à valider les clés des domaines de deuxième niveau et ainsi de suite. Reste donc à configurer la clé de la racine dans le résolveur : c'est évidemment crucial, puisque toute la sécurité du système en dépend. Si un résolveur est configuré avec une clé fausse pour la racine, toute la validation DNSSEC est menacée. Comment est-ce que l'ICANN, qui gère la clé principale de la racine, publie cette clé cruciale ? C'est documenté dans ce RFC qui remplace le RFC 7958, avec plusieurs changements, comme l'abandon des signatures PGP.

Notez que ce nouveau RFC documente l'existant, déjà mis en œuvre, et ne prétend pas décrire la meilleure méthode. Notez aussi que ce format et cette méthode de distribution pourraient encore changer à l'avenir, comme ils l'ont fait depuis la sortie du RFC 7958.

Si vous voulez réviser DNSSEC d'abord, outre les RFC de base sur ce système (RFC 4033, RFC 4034, RFC 4035...), notez surtout le RFC 6781, qui décrit les questions opérationnelles liées au bon fonctionnement de DNSSEC.

Les clés publiques configurées dans les résolveurs qui valident avec DNSSEC, sont appelées « points de départ de la confiance » (trust anchors). Un point de départ de la confiance est une clé dont l'authenticité est admise, et non pas dérivée d'une autre clé, via une chaîne de signatures. Il en faut au moins un, celui de la racine, bien que certains résolveurs en ajoutent parfois deux ou trois pour des zones qu'ils veulent vérifier indépendamment. Lorsque le résolveur recevra une réponse de la racine, signée, il l'authentifiera avec la clé publique de la racine (le point de départ de la confiance). S'il veut vérifier une réponse d'un TLD, il l'authentifiera avec la clé publique du TLD, elle-même signée (et donc authentifiée) par la clé de la racine. Et ainsi de suite même pour les zones les plus profondes.

(Notez qu'il existe deux clés pour la plupart des zones, la KSK - Key Signing Key, et la ZSK - Zone Signing Key, mais on ne s'intéresse ici qu'aux KSK, c'est elles qui sont signées par la zone parente, et configurées comme points de départ de la confiance.)

La gestion de la clé de la racine par l'ICANN (via sa filiale PTI) est décrite dans leur DPS (DNSSEC Practice Statement).

Le RFC rappelle aussi qu'il y a d'autres possibilités d'installation d'un point de départ de la confiance. Par exemple, si un tel point a été configuré une fois, ses remplacements éventuels peuvent être faits via le RFC 5011.

La section 2 du RFC décrit le format des clés publiées par l'IANA. Il s'agit d'un fichier XML contenant les condensats des clés, utilisant le format de présentation du RFC 4034. Leur syntaxe formelle est exprimée en Relax NG, le schéma est en section 2.1 du RFC (copie locale). Une vérification du fichier avec rnv fonctionne :

% rnv  dnssec-root-trust-anchors.rnc root-anchors.xml
root-anchors.xml
    

Voici un exemple du fichier XML (à ne pas prendre comme s'il faisait autorité, évidemment) :


<TrustAnchor id="0C05FDD6-422C-4910-8ED6-430ED15E11C2" 
             source="http://data.iana.org/root-anchors/root-anchors.xml">
    <Zone>.</Zone>
    <KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00">
        <KeyTag>20326</KeyTag>
        <Algorithm>8</Algorithm>
        <DigestType>2</DigestType>
        <Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest>
        <PublicKey>AwEAAaz/…</PublicKey>
        <Flags>257</Flags>
    </KeyDigest>
</TrustAnchor>

    

L'élément <KeyTag> indique l'identifiant de la clé, actuellement 20326, comme on peut le voir avec dig :

      
% dig +multi +nodnssec . DNSKEY 
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
.			86254 IN DNSKEY	257 3 8 (
				AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTO
                                …
				) ; KSK; alg = RSASHA256 ; key id = 20326
...

    

L'attribut id de l'élément <TrustAnchor> est un UUID. L'attribut id de l'élément <KeyDigest> sert à identifier un condensat particulier. Le fichier peut également comporter des commentaires XML (mais ce n'est pas le cas actuellement). Le fichier indique aujourd'hui le condensat de la clé et la clé mais cette dernière est optionnelle (on ne s'en sert pas par la suite).

Pour produire un enregistrement DS à partir de ce fichier XML, il suffit de mettre <KeyTag>, <Algorithm>, <DigestType> et <Digest> bout à bout. Par exemple, avec le fichier XML ci-dessus, cela donnerait :

    
.  IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D

(Des résolveurs comme Unbound acceptent ce format, pour le point de confiance de départ.)

Ici, je n'ai montré qu'une clé mais il peut y en avoir plusieurs, donc plusieurs <KeyDigest>. En novembre 2024, le fichier comportait trois clés, l'ancienne 19036, abandonnée il y a des années, l'actuelle 20326 et la future 38696 (qui n'était pas encore publiée dans le DNS mais qui l'a été en janvier 2025).

Comment récupérer le fichier XML de manière à être sûr de son authenticité ? C'est ce que spécifie la section 3 du RFC : on utilise HTTPS (ou HTTP tout court mais ce n'est pas forcément une bonne idée et, de toute façon, aujourd'hui, une politique HSTS le rend difficile). L'URL est https://data.iana.org/root-anchors/root-anchors.xml. Si on fait confiance à l'AC utilisée par l'ICANN, on peut être sûr de l'authenticité du fichier. (Mais notez, comme le fait remarquer gregR, que data.iana.org et iana.org n'ont pas d'enregistrement CAA, RFC 8659.)

Une autre solution est de le récupérer en HTTP et de le vérifier avec la signature fournie, en CMS (RFC 5652) - son URL est https://data.iana.org/root-anchors/root-anchors.p7s. (Non, je ne sais pas comment la vérifier.)

Bien sûr, un résolveur validant n'est pas obligé d'utiliser ces points de départ de la confiance. Cela reste une décision locale. La très grande majorité des résolveurs utiliseront sans doute plutôt un paquetage fourni par leur système d'exploitation, comme dns-root-data sur Debian.

Pour les amateurs d'histoire, l'annexe B rappelle que la clé 19036 (également appelée KSK-2010) avait été générée au cours d'une cérémonie à Culpeper, le 16 juin 2010. Elle avait été publiée dans le DNS pour la première fois le 15 juillet 2010. La clé actuelle, la 20326 (également nommée KSK-2017), a été également générée à Culpeper le 27 octobre 2016 et publiée le 11 novembre 2018. La liste des cérémonies de création de clés est en ligne.

L'annexe A de notre RFC contient les changements depuis le RFC 7958. Notamment :


Téléchargez le RFC 9718


L'article seul

RFC 9717: A Routing Architecture for Satellite Networks

Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : T. Li (Juniper Networks)
Pour information
Première rédaction de cet article le 29 janvier 2025


Tout le monde connait aujourd'hui l'utilisation de constellations de satellites en orbite basse pour les télécommunications et, par exemple, pour l'accès à l'Internet. Contrairement à l'ancienne technique de communication via des satellites en orbite géostationnaire, la communication directe entre satellites y joue un rôle important. Les satellites se déplacent les uns par rapport aux autres, changeant en permanence la topologie de ce réseau. Alors, comment se fait le routage ? Ce RFC décrit une méthode possible, reposant largement sur le protocole IS-IS.

Ce n'est pas forcément la technique réellement utilisée. Les constellations existantes, dont la plus connue est Starlink, sont des entreprises privées, très secrètes, et qui ne décrivent pas leur configuration interne. Ce RFC est donc un travail de réflexion, mené à partir des rares informations publiques. Il ne peut pas spécifier une solution complète. Si vous envisagez de créer une constellation, il vous restera du travail pour avoir une solution de routage.

D'abord, il faut voir les particularités de ce réseau de satellites. Il est bien moins fiable qu'un réseau terrestre (l'espace est agité, un satellite en panne n'est pas facile à réparer) et il est tout le temps en mouvement. Ce rythme important de changement est un défi pour les protocoles de routage. Sauf si les satellites sont exactement sur la même orbite, leur mouvement relatif fait qu'on a une possibilité de communiquer à certains moments seulement, voire quasiment jamais. Si deux satellites se déplacent en direction opposée, leur vitesse relative, de l'ordre de dizaines de milliers de km/h, ne permettra guère de communication entre eux.

Par contre, un point qui va faciliter les choses est que ces mouvements, et donc l'établissement et la coupure du lien, sont prévisibles. On peut compter sur Kepler et Newton !

La section 1.2 du RFC rappelle le vocabulaire important. Notons le sigle ISL, pour Inter-Satellite Link, la liaison directe entre satellites, typiquement via un faisceau laser. (Le RFC cite ce très vieil article de Bell, « On the Production and Reproduction of Sound by Light ».) Si vous ne le connaissez pas, il faut aussi apprendre le sigle LEO, pour Low Earth Orbit, désignant les satellites qui orbitent à moins de 2 000 km de la surface de la Terre. On utilisera aussi SR (Segment Routing), la technique du routage par segments, décrite dans le RFC 8402 et SID (Segment IDentifier), qui vient de cette technique. Et IS-IS (Intermediate System to Intermediate System ) ? Ce protocole de routage est normalisé par l'ISO (et donc la spécification n'est normalement pas librement disponible) mais il est aussi décrit dans le RFC 1142 et le RFC 1195 explique comment s'en servir pour IP. Attention : c'est un vieux RFC, datant d'une époque où on pensait encore que les protocoles OSI avaient peut-être un avenir (aujourd'hui, ils n'ont même pas de page Wikipédia). Le RFC 1195 se concentre donc sur la possibilité d'utiliser IS-IS pour router à la fois OSI et TCP/IP. Aujourd'hui, il ne sert plus qu'aux protocoles Internet.

La section 2 de notre RFC rappelle les points essentiels des satellites LEO, qui vont impacter les choix techniques. Quand deux satellites se parlent via un ISL (Inter-Satellite Link), la liaison ne peut avoir qu'une durée limitée, les deux satellites ne restant pas visibles l'un par l'autre éternellement, s'ils sont sur des orbites différentes. Par contre, les périodes de visibilité et de non-visibilité peuvent être calculées à l'avance, on peut compter sur les lois de la physique.

Les constellations peuvent être de grande taille. En 2021, déjà, celle du milliardaire d'extrême-droite représentait un tiers du total des satellites en orbite. Aujourd'hui, des constellations de dizaines de milliers de satellites sont prévues (occupant l'espace public et bloquant la visibilité sans vergogne). Les protocoles de routage traditionnels peuvent gérer des réseaux de grande taille mais à condition qu'ils soient relativement statiques, avec juste une panne ou une addition d'un lien de temps en temps, ce qui n'est pas le cas pour des réseaux de satellites en mouvement. L'IETF a sous la main deux protocoles de routage normalisés pour les réseaux mono-organisation, OSPF (RFC 2328 et RFC 5340) et IS-IS (RFC 1195). (Il existe d'autres protocoles pour ces réseaux mais convenant plutôt à des réseaux plus petits.) Tous les deux sont à état des liaisons et, pour passer à l'échelle, tous les deux permettent de partitionner le réseau en zones (areas) à l'intérieur desquelles l'information de routage est complète, alors qu'entre zones, on ne passe qu'une partie de l'information. Dans OSPF, il y a forcément une zone spéciale, l'épine dorsale (backbone, la zone de numéro 0). Rien que pour cela, le RFC estime qu'OSPF ne serait pas un bon choix : contrairement aux réseaux terrestres, les constellations n'ont rien qui pourrait servir d'épine dorsale. IS-IS repose sur un système différent, où des zones dites « L1 » (de niveau 1) regroupent des parties du réseau qui ne servent pas au transit entre zones, qui est assuré par des zones « L2 ». La machine individuelle peut aussi bien être dans L1 que dans L2 ou même dans les deux. Si on adoptait le système simple de mettre chaque satellite dans une zone L2 (puisque tout satellite peut servir au transit), on perdrait tous les avantages du partitionnement. L'utilisation de IS-IS va donc nécessiter des ajustements.

La section 3 du RFC expose le mécanisme de transmission des paquets choisi. Elle propose d'utiliser MPLS (RFC 3031), en raison de sa souplesse (puisque la topologie change tout le temps), avec le SR (Segment Routing) du RFC 8402 (et RFC 8660 pour son adaptation à MPLS). Dans cette vision, il n'y a pas de transmission au niveau IP et donc un traceroute ne montrerait pas le trajet entre les satellites.

Reste le choix de l'IGP. La section 4 décrit la préférence de l'auteur pour IS-IS. Dans cette hypothèse, tous les satellites seraient des nœuds L1L2 (appartement aux deux types de zones). Le passage à l'échelle serait assuré grâce au système des relais, normalisé dans le RFC 9666. Un réseau de 1 000 zones L1, chacune comportant 1 000 satellites, n'aurait besoin que de mille entrées (et pas un million) dans ses tables de routage, aussi bien L1 que L2. Idem pour la table des étiquettes MPLS.

La section 5 introduit le concept de bande (stripe). La bande est un ensemble de satellites dont les orbites sont suffisamment proches pour que la connectivité entre eux change peu.

On l'a dit, une particularité importante des réseaux de satellites est la prévisibilité des coupures. Un calcul de mécanique céleste permet de dire quand deux satellites ne pourront plus communiquer. On peut bien sûr router comme s'il s'agissait de pannes imprévues, mais on améliorera certainement la qualité du routage (et on diminuera le nombre de pertes de paquets lorsque la topologie change) si on prévient les satellites à l'avance. Par exemple, une fois informés d'un changement proche, les routeurs peuvent annoncer une métrique très élevée pour les ISL qui vont bientôt être coupés, comme on le fait sur les réseaux terrestres quand une maintenance est prévue. Il y a une proposition concrète d'un mécanisme d'information dans le brouillon draft-ietf-tvr-schedule-yang.

Quelques lectures recommandées par notre RFC :


Téléchargez le RFC 9717


L'article seul

RFC 9715: IP Fragmentation Avoidance in DNS over UDP

Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : K. Fujiwara (JPRS), P. Vixie (AWS Security)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 28 janvier 2025


Les requêtes et réponses DNS peuvent voyager sur divers transports, mais le plus fréquent est UDP. Une réponse de grande taille sur UDP peut dépasser la MTU et donc devoir être fragmentée. La fragmentation crée divers problèmes et ce RFC décrit les problèmes, et comment éviter la fragmentation.

Un peu de rappel : avec UDP (RFC 768), il n'y a pas de négociation de la taille des paquets et un émetteur UDP peut donc, en théorie, envoyer ce qu'il veut, jusqu'à la limite maximum de 65 536 octets. Bon, en pratique, on voit rarement un paquet aussi grand. Déjà, la norme originelle du DNS mettait une limite à 512 octets. Cette limite a disparu depuis longtemps, grâce à EDNS (RFC 6891) et, désormais, le logiciel DNS peut indiquer la taille maximale qu'il est prêt à recevoir. Pendant longtemps, on voyait souvent une taille de 4 096 octets, ce qui excède la MTU de la plupart des liens Internet. Un paquet aussi grand devait donc être fragmenté (que cela soit en IPv4 ou en IPv6). Voici un exemple de réponse plus grande que la MTU typique :


% dig oracle.com TXT
…
;; MSG SIZE  rcvd: 3242

Si cette réponse était transmise dans un seul datagramme UDP, elle serait fragmentée, ce qui ne marcherait pas toujours, comme l'explique le RFC 8900 et créerait des risques de sécurité.

TCP (RFC 9293) évite le problème grâce à la négociation de la MSS (Maximum Segment Size, section 3.7.1 du RFC 9293) et au découpage en paquets plus petits que la MTU. La requête DNS ci-dessus ne poserait aucun problèmes avec TCP :


% dig +tcp oracle.com TXT
…
;; SERVER: 192.168.2.254#53(192.168.2.254) (TCP)
;; MSG SIZE  rcvd: 3242

Mais UDP, plus rigide, n'a pas un tel mécanisme. On pourrait tout faire en TCP (le RFC 7766 rappelle opportunément qu'il n'est pas en option : tout serveur DNS doit l'accepter) mais cela a d'autres inconvénients donc restons avec UDP pour l'instant.

Donc, il est recommandé d'éviter la fragmentation. La section 3 traduit cela en recommandations concrètes : ne pas fragmenter au départ (IPv6) et mettre le bit DF (Don't fragment, pour IPv4, cf. RFC 791) car, sinon, un paquet IPv4 pourra être fragmenté en route (cf. section 7.1). Malheureusement, tous les systèmes d'exploitation ne donnent pas un accès facile à ce bit. Sur Linux, par exemple, il faut passer (ce qui n'est pas très intuitif) par l'option IP_MTU_DISCOVER, ce qui mène à d'autres problèmes (cf. annexe C du RFC).

Le logiciel qui répond à une requête DNS doit la maintenir sous une taille qui est le miminum de ces quatre tailles :

  • la taille indiquée par le demandeur, via EDNS,
  • la MTU de l'interface réseau par laquelle partira la réponse,
  • la MTU du chemin (si on la connait),
  • 1 400 octets (la valeur sûre : aller au-delà serait risqué).

Si on ne peut pas fabriquer une réponse de taille inférieure à ce minimum, il faut mettre le bit TC (TrunCated) dans la réponse DNS.

Ça, c'était pour les répondeurs (les serveurs DNS). Et pour les demandeurs (les clients) ? Ils ne devraient pas indiquer en EDNS une taille supérieure au minimum des trois dernières valeurs citées plus haut. Ici, vue par tshark, la requête faite par dig avec l'option +dnssec mais sans autre mention, notamment de taille. dig indique une taille maximale de 1 232 octets, conforme aux recommandations du RFC :


Domain Name System (query)
    Flags: 0x0120 Standard query
        0... .... .... .... = Response: Message is a query
…
    Queries
        re: type NS, class IN
            Name: re
            [Name Length: 2]
            [Label Count: 1]
            Type: NS (2) (authoritative Name Server)
            Class: IN (0x0001)
    Additional records
        <Root>: type OPT
            Name: <Root>
            Type: OPT (41) 
            UDP payload size: 1232
            Higher bits in extended RCODE: 0x00
            EDNS0 version: 0
            Z: 0x8000
                1... .... .... .... = DO bit: Accepts DNSSEC security RRs
                .000 0000 0000 0000 = Reserved: 0x0000
            Data length: 12
            Option: COOKIE
                Option Code: COOKIE (10)
                Option Length: 8
                Option Data: 83d7d3e78b76b45d
                Client Cookie: 83d7d3e78b76b45d
                Server Cookie: <MISSING>

  

Le RFC demande également aux clients DNS de refuser les réponses fragmentées, compte tenu de certains risques de sécurité (risque de ne pas pouvoir valider les réponses), et de ne pas hésiter à essayer avec d'autres protocoles de transport, comme TCP.

La section 4, elle, rassemble les recommandations pour les hébergeurs DNS. Comme ils contrôlent les zones publiées, ils peuvent faire en sorte que les réponses ne soient pas trop longues, rendant la fragmentation inutile. Par exemple, ils devraient faire attention à ne pas lister « trop » de serveurs de noms, ne pas mettre « trop » d'enregistrements d'adresses à ces serveurs, etc. Un conseil DNSSEC : certains algorithmes cryptographiques ont des clés et des signatures plus courtes que d'autres. Utilisez-les. (Et, donc, ECDSA ou EdDSA, plutôt que RSA.)

Le RFC note aussi que certains logiciels ne sont pas conformes à la norme. Par exemple, la taille maximale indiquée dans la requête est ignorée et une réponse plus grande que cette taille renvoyée. Et, bien sûr, on trouve encore des serveurs qui n'acceptent pas TCP.

Mais quel était le problème de sécurité avec la fragmentation, au juste ? Comme détaillé en section 7.3, qui cite le papier « Fragmentation Considered Poisonous », de Amir Herzberg et Haya Shulman, l'empoisonnement de la mémoire d'un résolveur est plus facile lorsqu'il y a fragmentation, puisque certains des éléments dans le paquet qui peuvent être utilisés pour juger de la légitimité d'une réponse peuvent se retrouver dans un autre fragment. (Voir aussi cet exposé au RIPE.) Ces attaques permettent ensuite plein d'autres attaques, par exemple contre les autorités de certification.

DNSSEC résout évidemment ces problèmes mais attention, les délégations ne sont pas signées donc DNSSEC ne protège que si les victimes ont signé leur zone et, en prime, DNSSEC permet de détecter la tentative d'empoisonnement et de la refuser, mais pas d'obtenir la bonne réponse.

L'annexe A du RFC détaille les observations quantitatives sur la taille des réponses et les raisons qui peuvent guider le choix des tailles maximum. La section 5 du RFC 8200 garantit que 1 280 octets passeront partout en IPv6, c'est la MTU minimale (mais elle est bien plus basse dans l'ancienne version d'IP). Le RFC 4035 (section 3) impose 1 220 octets minimums pour DNSSEC. Le DNS flag day 2020 proposait 1 232 octets comme taille maximale acceptée (MTU de 1 280 octets, moins 48 octets d'en-têtes). La MTU typique dans l'Internet est de 1 500 octets et, au moins dans le cœur, il n'y a pratiquement pas de liens avec une MTU plus basse. Une taille de 1 452 octets (la MTU moins les en-têtes) est donc réaliste mais, pour tenir compte de certaines techniques qui abaissent la MTU effective, comme les tunnels, notre RFC arrive finalement aux 1 400 octets cités plus haut (section 3).

L'annexe B, elle, décrit le concept de « réponses minimisées ». Certaines mises en œuvre du DNS ont une option qui permet de dire « essaie de réduire la taille de la réponse, en n'incluant pas certaines informations non indispensables ». Attention, des informations comme la colle (les adresses IP des serveurs nommés dans la zone qu'ils servent) sont indispensables (RFC 9471).

Par exemple, pour un serveur faisant autorité qui fait tourner BIND, qui envoie des réponses minimales par défaut, si on lui demande de ne pas être si économe :

options {
	minimal-responses no;
};
  

Il va alors renvoyer des informations qu'on n'avait pas demandé et dont l'utilité se discute (ici, les deux enregistrements NS) :


% dig @::1 -p 8053 under.michu.example
…
;; ANSWER SECTION:
under.michu.example.	600 IN A 192.0.2.56

;; AUTHORITY SECTION:
michu.example.		600 IN NS ns2.nic.fr.
michu.example.		600 IN NS ns1.nic.fr.
…

  

Par défaut, BIND, conformément aux recommandations de notre RFC, n'enverra pas ces deux NS. Ici, il s'agissait d'un serveur faisant autorité mais cette option s'applique aussi aux résolveurs. (Notez que, pour d'autres logiciels, le fait d'envoyer des réponses minimales est par défaut, et pas modifiable.)

En parlant de logiciels, l'annexe C liste un certain nombre de serveurs DNS libres (BIND, Knot, Knot resolver, Unbound, PowerDNS, PowerDNS recursor et dnsdist) en regardant quelles recommandations de ce RFC sont appliquées.


Téléchargez le RFC 9715


L'article seul

RFC 9712: IETF Meeting Venue Requirements Review

Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : J. Daley, S. Turner (IETF Administration LLC)
Première rédaction de cet article le 27 janvier 2025


L'IETF utilise, pour le cœur de son travail de normalisation, l'Internet : listes de diffusion, forge de documents, outils divers de travail en groupe. Mais il y a quand même des réunions physiques, trois par an, rien ne remplaçant à 100 % le contact direct. Les discussions sur les lieux de ces réunions sont un des sujets favoris à l'IETF et ce RFC résume les règles actuelles de sélection d'un lieu. Pour savoir pourquoi il n'y a jamais eu de réunion en Inde, une seule en Chine et une seule en Amérique du Sud, lisez-le.

La politique officielle est documentée dans les RFC 8718 et RFC 8719. Ce nouveau RFC 9712 vise à détailler ces RFC et à expliquer certains points, d'autant plus que des choses ont pu changer depuis ces RFC (écrits avant la pandémie de Covid-19…). Pas de changements radicaux de la politique, surtout des clarifications (la section 2 de notre RFC les résume).

Ainsi, le RFC explique que ce sera toujours l'IASA (IETF Administration Support, RFC 8711), qui décidera, pas l'IETF dans son ensemble. Il y a déjà eu des cas d'enthousiasme de l'IETF pour un lieu de réunion… qui ne se traduisaient pas par un grand nombre de participants, bien au contraire (je me souviens que ce fut le cas de la réunion de Buenos Aires).

Le RFC 8718 énonçait que les hôtels devaient être « proches » du lieu de la réunion. Certains avaient interprété cela comme imposant un seul lieu (la one-roof policy). Notre nouveau RFC clarifie donc que « proche » veut dire « moins de dix minutes à pied », pas forcément sous le même toit.

L'IASA réservait traditionnellement un grand nombre de chambres dans les hôtels proches mais cela a toujours fait courir un risque financier en cas d'annulation, comme cela s'est produit pendant la pandémie de Covid-19. Depuis cette pandémie, les hôtels sont d'ailleurs bien plus prudents, demandant des paiements en avance. Bref, notre RFC n'impose plus de chiffre minimal de réservation, contrairement à ce que disait la section 3.2.4 du RFC 8718.

Une ancienne tradition disparait avec ce RFC : dans les réunions professionnelles d'informaticiens·nes, il y avait toujours une terminal room, ainsi appelée car elle était autrefois équipée de terminaux pour se connecter à ses ordinateurs distants. L'évolution de l'informatique fait que cette salle n'a plus de terminaux, mais juste tables, chaises et prises de courant. Désormais, elle n'est même plus obligatoire dans les réunions IETF (où on voyait de toute façon souvent des gens ouvrir leur ordinateur portable assis par terre dans le couloir, ou au bistrot d'à côté).


Téléchargez le RFC 9712


L'article seul

RFC 9707: IAB Barriers to Internet Access of Services (BIAS) Workshop Report

Date de publication du RFC : Février 2025
Auteur(s) du RFC : M. Kühlewind, D. Dhody, M. Knodel
Pour information
Première rédaction de cet article le 26 février 2025


L'Internet est aujourd'hui un service indispensable à toutes les activités humaines. Un accès correct à ce réseau est donc crucial. Mais plusieurs problèmes limitent l'accès à l'Internet ou à plusieurs de ses services. L'IAB avait organisé en janvier 2024 un atelier sur cette question, atelier dont ce RFC est le compte-rendu.

Trois thèmes principaux étaient à l'agenda de cet atelier, qui s'est tenu entièrement en ligne : l'état de la fracture numérique, le rôle des réseaux communautaires et la question de la censure. Oui, il y aurait eu plein d'autres thèmes possibles (comme les difficultés d'accès aux services en ligne, par exemple parce que leur utilisation est anormalement difficile) mais en trois jours d'atelier, ce n'est déjà pas mal.

Comme tous les ateliers de l'IAB, celui-ci a fonctionné en demandant aux participants des position papers expliquant leur point de vue. Ne participent à l'atelier que des gens ayant écrit un de ces articles, ce qui garantit que tout le monde a dû travailler le sujet. Ces articles sont disponibles en ligne.

Le RFC commence en rappelant que, dans une société où tout se fait via l'Internet, ne pas avoir accès à l'Internet, ou bien n'avoir un accès que dans de mauvaises conditions, est une discrimination inacceptable. Le RFC insiste sur ce deuxième point : aujourd'hui, le problème n'est plus uniquement l'absence totale d'accès Internet, c'est souvent l'accès de mauvaise qualité (liaison trop lente, intermittente, ordinateur trop lent pour les sites Web modernes surchargés de gadgets, censure, etc). L'atelier de l'IAB visait à :

  • récolter des informations sur les diverses inégalités d'accès,
  • mieux comprendre les différentes façons dont les gens accèdent à l'Internet (et pas uniquement dans les pays riches),
  • et ce que veut dire « être connecté à l'Internet » pour les utilisateurs, quels sont leurs usages et leurs exigences.

Le premier jour, l'atelier a surtout travaillé sur les réseaux dits « communautaires » (terminologie très étatsunienne, je m'excuse mais c'est celle du RFC). Ces réseaux bâtis localement par leurs utilisateurices, sans but lucratif, sont décrits plus en détail dans le RFC 7962 et un groupe de recherche IRTF existe, GAIA. Le plus connu et le plus souvent cité est Guifi. Ces réseaux communautaires souffrent de divers problèmes, dont bien sûr le coût élevé du transit, qui est nécessaire pour joindre le reste de l'Internet. Une des pistes évoquées était l'installation des CDN dans ces réseaux communautaires, pour limiter l'utilisation du transit. Cette piste était par exemple citée dans cette intervention, dont on notera qu'un des auteurs travaille pour un CDN, qui a par ailleurs un projet caritatif pour les réseaux communautaires. Opinion personnelle : c'est très discutable, les CDN ne servent qu'à la consommation passive de contenu et, pire, renforcent le contenu déjà très populaire.

L'accès au transit peut se faire par liaison terrestre fixe mais aussi par satellite, les satellites en orbite basse (LEO) étant actuellement en plein développement. Notez que cela ne résout pas les problèmes de contrôle, comme l'a montré la coupure de l'Ukraine par Starlink.

Le RFC note aussi un problème social : les opérateurs des réseaux communautaires sont peu présents à l'IETF et donc leurs questions et problèmes ne sont pas forcément bien pris en compte dans la normalisation technique.

Autre sujet, le deuxième jour, la fameuse fracture numérique. Comme dit plus haut, elle ne se réduit pas au fait de ne pas avoir d'accès du tout, problème qu'on pourrait régler en posant de la fibre optique. Il y a aussi une fracture entre celleux qui accèdent à l'Internet dans de bonnes conditions et celleux qui sont du mauvais côté de la fracture. Des bonnes conditions, cela concerne à la fois la technique (liaison rapide et fiable) mais aussi la maitrise de son activité en ligne (ne pas être dépendant des GAFA, par exemple, ce que le RFC ne mentionne guère).

À l'atelier, Holz a par exemple étudié les serveurs DNS faisant autorité pour divers domaines australiens et montré que les organisations indigènes étaient nettement moins bien servies.

Les différentes personnes vivant sur Terre parlant de nombreuses langues différentes, la question de la possibilité de chacun·e d'utiliser sa langue a toute sa place dans toute discussion sur les inégalités d'accès. D'où l'exposé de Hussain sur le projet Universal Acceptance de l'ICANN, qui vise à faire en sorte que, par exemple, les noms de domaine en Unicode soient acceptés partout. Actuellement, si le travail de normalisation est largement fini, le déploiement effectif est loin d'être complet. (Opinion personnelle : cette question de l'acceptation universelle des TLD ICANN en Unicode n'est qu'une toute petite partie de la question des langues sur l'Internet.)

Il y a aussi le problème des performances : bien des sites Web modernes sont développées par une personne riche et bien connectée, munie d'un ordinateur rapide. Ils sont souvent pénibles à utiliser lorsque la liaison est lente et/ou la machine de l'utilisateur un peu ancienne. (Et, dans mon expérience, les remarques aux développeurs Web sur ce point sont souvent accueillies par des remarques méprisantes.) L'étude de Habib et al. analyse très bien ce problème, notamment pour les pays « du Sud » (et propose une solution technique mais, quoi qu'on pense de cette solution, l'étude reste très pertinente). Sinon, le RFC n'en parle pas, mais ce problème est une des motivations du projet Gemini.

Gros morceau pour la troisième session, la censure. C'est évidemment un des principaux obstacles sur la route des utilisateurices. Ainsi, le projet iMAP (rien à voir avec IMAP) a documenté la censure dans plusieurs pays asiatiques, notamment en utilisant les sondes OONI. De nombreuses techniques différentes sont utilisées, par exemple des résolveurs DNS menteurs, ou bien, plus sophistiqué, une interférence avec les connexions HTTPS, utilisant le SNI pour repérer le site visité. Parfois, l'utilisateurice est redirigé·e vers une page expliquant le blocage (comme je l'avais vu il y a déjà seize ans à Dubaï, la censure n'est pas une invention récente). Parfois, la censure est plus hypocrite et ne s'avoue pas comme telle.

Une autre étude détaillée est celle de Grover, portant notamment sur l'Inde et le Pakistan. Il insiste notamment sur le caractère inégal de la mise en œuvre de la censure, bien des ressources n'étant bloquées que par certains FAI.

Évidemment, en Russie, la guerre avec l'Ukraine est le prétexte pour un durcissement considérable de la censure. Basso l'a étudié avec OONI. Notez que son étude montre des domaines bloqués sans être pour autant sur la liste officielle de blocage.

Comme la censure, comme dans ce cas russe, est souvent hypocrite, voire dissimulée, il y a beaucoup de travail à faire du point de vue technique pour l'analyser. C'est ainsi que Wang et al ont présenté les solutions utilisables pour cela. (Et le problème est complexe !)

Tous les intervenants sur la question de la censure ont insisté sur l'importance de l'information des utilisateurices, souvent laissé·es délibèrement dans le noir sur les raisons d'un blocage ou même sur sa simple existence. Les solutions normalisées existantes pour cela incluent le code de retour 451 de HTTP (normalisé dans le RFC 7725) ou les codes EDE, notamment le code 16, pour le DNS (normalisés dans le RFC 8914). Voici deux exemples, respectivement par Google et par Cloudflare, vus en juillet 2024, à propos de la censure en France de sites qui diffusent des spectacles sportifs en violation des intérêts financiers des entreprises comme Canal+ :


% dig @8.8.8.8 tarjetarojatvlive.net
…
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 7912
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; EDE: 16 (Censored): (The requested domain is on a court ordered copyright piracy blocklist for FR (ISO country code). To learn more about this specific removal, please visit https://lumendatabase.org/notices/41939614.)
…
;; SERVER: 8.8.8.8#53(8.8.8.8) (UDP)
;; WHEN: Wed Jul 03 10:34:44 CEST 2024

  

% curl -v jokersportshd.net         
…
* Connected to jokersportshd.net (2606:4700:3034::6815:5b9) port 80 (#0)
> GET / HTTP/1.1
> Host: jokersportshd.net
> User-Agent: curl/7.81.0
> Accept: */*
…
< HTTP/1.1 451 
< Date: Wed, 03 Jul 2024 08:36:59 GMT
< Content-Type: text/html
…
<!DOCTYPE html><html class="no-js" lang="en-US"> <head>
<title>Unavailable For Legal Reasons</title> 
…
<p>This website is unavailable for legal reasons.</p><p>Please see <a
rel="noopener noreferrer"
href="https://lumendatabase.org/notices/42038946"
target="_blank">https://lumendatabase.org/notices/42038946</a> for
more details.</p>
..

  

(Il y aurait aussi le RFC 6108, mais il est aujourd'hui techniquement dépassé.) Les mécanismes standardisés pour signaler une censure sont peu utilisés aujourd'hui, et les explications sont rares.

Notons que rediriger les utilisateurs vers une page Web d'information leur annonçant qu'ils ont été bloqués (comme le fait en France la Main Rouge) est dangereux : cela permet au gestionnaire de la page en question de voir l'adresse IP (et d'autres informations envoyées par le navigateur) du visiteur ou de la visiteuse. En France, le ministère de l'Intérieur avait ainsi supprimé les données récoltées… après avoir juré qu'il n'en récoltait pas !

Qui dit censure dit évidemment contournement, car les utilisateurices ne vont pas rester les bras ballants face aux mesures de blocage. Ont été discutés à l'atelier les VPN, par exemple, y compris leurs problèmes actuels (cf. l'excellente étude de Ramesh sur les VPN et leurs limites, à lire la prochaine fois qu'un youtubeur vous fera la pub de NordVPN).

Voilà, maintenant, il y a du travail pour des groupes IRTF comme GAIA, HRPC, PEARG, et MAPRG (section 2.4 du RFC, sur le travail à faire).


Téléchargez le RFC 9707


L'article seul

RFC 9695: The 'haptics' Top-level Media Type

Date de publication du RFC : Mars 2025
Auteur(s) du RFC : Y. K. Muthusamy, C. Ullrich
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF mediaman
Première rédaction de cet article le 19 mars 2025


L'enregistrement d'un nouveau type de média de premier niveau est plutôt rare (le dernier avait été font/ en 2017). Notre RFC introduit le type haptics/, pour les formats de fichier des interfaces haptiques, celles qu'on touche et qui vous touchent (une manette de jeu vidéo à retour d'effort, par exemple).

De telles interfaces se trouvent dans de nombreux secteurs, le jeu vidéo, bien sûr, mais aussi la simulation (simulateurs de vol, par exemple), la robotique, des trucs pour adultes, etc. Contrairement à l'audio et à la vidéo, qui s'affichent directement, l'haptique est une réaction à votre toucher. (Enfin, c'est ce que dit le RFC mais les fauteuils de cinéma haut de gamme qui vous secouent pendant les scènes d'action sont aussi de l'haptique.) Les interfaces haptiques peuvent être mises en œuvre de diverses façons, par exemple des petits moteurs ou des matériaux piézoélectriques.

Il existe divers formats pour représenter des actions haptiques et il est donc nécessaire de les étiqueter proprement pour quand les fichiers voyagent sur l'Internet. Le mécanisme des types de médias est décrit dans le RFC 6838. Il est complété par le RFC 9694 pour la création de nouveaux types de premier niveau, comme haptics/, créé par notre RFC.

On trouve des dispositifs haptiques dans un certain nombre de machines (PlayStation, Switch, etc) et le W3C a une norme pour les vibrations (et même deux).

À noter que les données haptiques peuvent être combinées avec des données audio et vidéo, par exemple pour une simulation plus réussie. La norme ISOBMFF (ISO 14496) est un exemple mais on trouve aussi des instructions haptiques transportées, par exemple, dans RTP. Je n'ai pas 216 francs suisses pour vérifier mais le RFC dit que la première mention d'un type de médias haptics/ vient de cette norme ISO. On pourra donc avoir, par exemple, dans le futur, haptics/mp4.

haptics/ ne concerne pas que le toucher au sens strict. Outre les effects tactiles, il y a aussi la kinésthésique (des forces plus importantes), la friction, l'utilisation de sons qu'on n'entend pas (par exemple ultrasons) mais qui ont quand même un effet sur le corps et même la température. Vous voyez que cela ne pouvait pas rentrer dans audio/ ou video/.

Il existe déjà plusieurs formats pour les données haptiques :

Les trois premiers ont déjà été mis dans le registre : haptics/ivs, haptics/hjif et haptics/hmpg.

Le type application/ aurait pu convenir mais haptics/ est plus spécifique et, surtout, ce sont des données, pas du code. En parlant de cela, la section 3 du RFC détaille quelques points de sécurité. Outre les problèmes classiques d'analyser des données venues de l'extérieur (les formats complexes mènent souvent à des failles de sécurité dans l'analyseur), les actuateurs peuvent être dangereux (un actuateur thermique qui brûle, un actuateur à retour de force qui brutalise) et il ne faut donc pas exécuter aveuglément toutes les instructions que contient un fichier de type haptics/.


Téléchargez le RFC 9695


L'article seul

RFC 9694: Guidelines for the Definition of New Top-Level Media Types

Date de publication du RFC : Mars 2025
Auteur(s) du RFC : M.J. Dürst (Aoyama Gakuin University)
Réalisé dans le cadre du groupe de travail IETF mediaman
Première rédaction de cet article le 19 mars 2025


Vous savez que les types de médias comportent un type de premier niveau et un sous-type. Dans image/gif, image est le type de premier niveau et gif le sous-type. On crée des sous-types tout le temps mais les types, l'identificateur qui est au premier niveau, c'est bien plus rare. La création du type haptics (données haptiques), qui a été faite dans le RFC 9695, a été l'occasion de formaliser un peu plus le processus de création de types de médias.

Vous voulez créer un nouveau type de médias (également appelé type MIME) ? Les types existants comme text, image et application ne vous suffisent pas ? Alors, il vaut mieux lire ce RFC 9694, qui explique les principes. Le RFC 6838, qui spécifie les types de médias est assez vague sur la création de nouveaux types de premier niveau (cf. sa section 4.2.7), sans doute parce qu'on ne comptait pas en voir arriver beaucoup. Notre RFC 9694 comble ce manque, devenu évident avec la création du type haptics dans le RFC 9695.

Attention, ne pas confondre les types de médias de premier niveau avec les arbres qui permettent d'étiqueter les sous-types, comme vnd (abréviation de vendor), pour les sous-types spécifiques à un fournisseur, comme application/vnd.adobe.flash.movie pour un format qu'on ne regrettera pas.

Donc, contrairement aux sous-types, qui apparaissent tout le temps et ne font pas forcément l'objet d'un RFC, la création de types est plus rare. Le dernier créé, avant haptics/, était font/, par le RFC 8081. L'une des raisons de la séparation type/sous-type est que, dans certains cas, le type peut indiquer, au logiciel qui lit un fichier, une application générique (si on tombe sur un image/sous-type-inconnu, lancer un logiciel de visualisation d'imges qui gère beaucoup de formats est une solution raisonnable ; si on tombe sur un text/sous-type-inconnu, on sait qu'un humain pourra à peu près le lire avec un éditeur générique). Le RFC note qu'autrefois il était même prévu que cet aiguillage puisse se faire vers différents matériels (envoyer image/nimporte-quoi à l'imprimante, video/nimporte-quoi à la télé) mais qu'aujourd'hui, où les machines sont bien plus généralistes, cela n'a plus trop de sens.

Donc, si vous voulez enregistrer un nouveau type de médias de premier niveau, la section 2 de notre RFC liste les critères obligatoires d'évaluation :

  • Le type doit être décrit dans un RFC qui est sur le chemin des normes (Standards Track, cf. la politique « Action de normalisation », RFC 8126, section 4.9) donc approuvé par l'IETF.
  • La spécification doit citer, dans sa section IANA considerations l'ajout au registre des types de premier niveau,
  • Elle doit bien indiquer les critères d'évaluation pour les sous-types (qu'est-ce qui est acceptable et qu'est-ce qui ne l'est pas).
  • Il faut qu'au moins un sous-type soit décrit, pour bien montrer qu'il y a un usage réel, pas juste théorique. (haptics/ a commencé avec trois sous-types.)

Moins cruciaux sont d'autres critères, comme :

Il y a aussi des anti-critères.

  • Un type de premier niveau ne doit pas être juste un pointeur vers un autre registre (le RFC cite le cas fictif d'un type oid/ qui pointerait vers des object identifiers).
  • Les types de médias sont prévus pour aider les applications qui lisent des ressources Internet à les faire traiter par le logiciel approprié. Ce ne sont pas un mécanisme de typage générique, on ne va pas faire une ontologie avec.
  • Un éventuel nouveau type ne doit pas marcher sur les plate-bandes d'un type existant. On ne pourrait sans doute pas créer un code/ pour le code source puisqu'il existe déjà text/ (même si peu de langages de programmation ont eu un sous-type enregistré, le RFC 9239 est plutôt une exception).
  • Et pas question de commencer un nom de type par x-, le RFC 6648 explique pourquoi.

La section 3 du RFC est pour les féru·es d'histoire. Elle documente l'évolution de ces types de médias. Leur apparition date du RFC 1341 en 1992, qui créait les « classiques » text/, image/, audio/… Le premier type de premier niveau créé par la suite a été matter-transport/ (pour indiquer que le message contient de la matière, pas juste de l'information) en 1993 dans le RFC 1437 (mais regardez la date du RFC avant de critiquer). Le premier « sérieux » type de premier niveau en dehors des « classiques », model/, n'a été créé qu'en 1997 par le RFC 2077. example/ date de 2006 (RFC 4735) et font/ de 2017 (RFC 8081). Enfin, le dernier, haptics/, date de cette année, avec le RFC 9695.

Il existe aussi des types utilisés mais pas enregistrés. Wikipédia parle d'un type chemical/, décrit dans un article mais jamais passé par le mécanisme d'enregistrement que décrit notre RFC, et donc absent du registre.

La section 4 de notre RFC synthétise les règles et procédures pour l'enregistrement d'un nouveau type (rappel : politique « Action de normalisation », RFC 8126) et crée formellement le registre des types de premier niveau.

Si vous voulez créer un nouveau type de médias de premier niveau, je signale que scent/ (pour distribuer des odeurs sur l'Internet) n'a pas été enregistré. Il faut dire qu'à ma connaissance, il n'existe pas de format pour les odeurs, qui permettrait d'avoir le premier sous-type. Et ce manque de format vient probablement du fait qu'on n'a pas de synthétiseur d'odeurs qui serait capable de rendre le contenu du fichier de manière perceptible par notre odorat. (Trois autres sens sont couverts par image/, audio/ et haptics/ mais on n'a rien non plus pour le goût.)


Téléchargez le RFC 9694


L'article seul

RFC 9687: Border Gateway Protocol 4 (BGP-4) Send Hold Timer

Date de publication du RFC : Novembre 2024
Auteur(s) du RFC : J. Snijders (Fastly), B. Cartwright-Cox (Port 179), Y. Qu (Futurewei)
Chemin des normes
Première rédaction de cet article le 8 novembre 2024


Que doit faire un routeur BGP lorsque le pair en face ne traite manifestement plus ses messages ? Ce n'était pas précisé avant mais la réponse est évidente : raccrocher (mettre fin à la communication).

Un problème classique lors d'une connexion réseau, par exemple sur TCP, est de détecter si la machine en face est toujours là. Par défaut, TCP ne fournit pas ce service : s'il n'y a aucun trafic, vous ne pouvez pas savoir si votre partenaire est mort ou simplement s'il n'a rien à dire. Une coupure de réseau, par exemple, ne sera pas détectée tant que vous n'avez pas de trafic à transmettre (avec attente d'une réponse). Et BGP ne transmet que les changements donc l'absence de trafic ne signale pas forcément un problème. Il existe des solutions, comme d'envoyer périodiquement des messages même quand on n'a rien à dire (RFC 4271, section 4.4), mais aucune n'est parfaite : un programme qui utilise TCP ne sait typiquement pas immédiatement si ses messages sont vraiment partis (et l'alarme actuelle ne couvre que la réception des messages, pas leur envoi). Et BGP n'a pas de fonction « ping », qui exigerait une réponse.

Quand la coupure est franche et détectée, aucun problème, la session BGP (RFC 4271) s'arrête et les routes correspondantes sont retirées de la table de routage. Mais ce RFC traite le cas de où le routeur BGP d'en face a un problème mais qu'on ne détecte pas. Un exemple : si ce routeur en face a complètement fermé sa fenêtre TCP de réception (RFC 9293, notamment la section 3.8.6), on ne pourra pas lui envoyer de messages, mais la session BGP ne sera pas coupée et les paquets continueront à être transmis selon des annonces de routage dépassées, alors qu'ils finiront peut-être dans un trou noir (le problème des « zombies BGP »).

La solution (section 3 de notre RFC) est de modifier l'automate de BGP (RFC 4271, section 8), en ajoutant une alarme (RFC 4271, section 10), SendHoldTimer. Quand elle expire, on coupe la connexion TCP et on retire les routes qu'avait annoncé le pair dont on n'a plus de nouvelles. Le RFC recommande une configuration par défaut de huit minutes de patience avant de déclencher l'alarme.

L'erreur « Send Hold Timer Expired » est désormais dans le registre IANA des erreurs BGP et tcpdump sait l'afficher. Il existe plusieurs mises en œuvre de ce RFC :

Si les processus IETF vous passionnent, il y a une documentation des discussions autour de ce RFC.


Téléchargez le RFC 9687


L'article seul

RFC 9682: Updates to the CDDL grammar of RFC 8610

Date de publication du RFC : Novembre 2024
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 19 novembre 2024


Voici une légère mise à jour de la grammaire du langage de description de schéma CDDL (Concise Data Definition Language), originellement normalisé dans le RFC 8610. Pas de gros changement.

Il y avait juste quelques errata à traiter, et des ambiguités concernant notamment les chaines de caractères. Il était devenu nécessaire de modifier l'ABNF. CDDL a été décrit dans le RFC 8610, puis étendu par le RFC 9165. Il vise à décrire un schéma pour des fichiers CBOR ou JSON. Depuis quatre ans qu'il est normalisé, plusieurs erreurs ont été relevées dans la norme. (Dont une, c'est amusant, causée par le traitement du source du RFC, traitement qui avait fait disparaitre accidentellement des barres obliques inversées.)

Donc, notre RFC 9682 modifie l'ABNF qui décrit les littéraux pour les chaines de caractères, ABNF qui était trop laxiste (section 2 du RFC). Il change également la grammaire générale (section 3) pour autoriser (au niveau syntaxique) des schémas vides (ils restent interdits au niveau sémantique). Ainsi, l'ancienne règle :

cddl = S 1*(rule S)
  

devient :

cddl = S *(rule S)        
  

Téléchargez le RFC 9682


L'article seul

RFC 9680: Antitrust Guidelines for IETF Participants

Date de publication du RFC : Octobre 2024
Auteur(s) du RFC : J. M. Halpern (Ericsson), J. Daley (IETF Administration LLC)
Pour information
Première rédaction de cet article le 31 octobre 2024


Les normes publiées par l'IETF ne sont pas que des documents techniques à seule destination des techniciens. L'Internet et, de manière plus générale, les protocoles TCP/IP sont aussi une grosse industrie qui brasse beaucoup d'argent. Il y a donc un risque que des acteurs de cette industrie essaient d'influencer les normes à leur profit, par exemple en formant des alliances qui, dans certains pays, seraient illégales au regard des lois antitrust. Ce court RFC administratif explique aux participant·es IETF ce que sont ces lois et comment éviter de les violer.

En effet, les organisations, notamment les entreprises à but lucratif, qui participent à l'IETF peuvent être concurrentes sur leurs marchés. Or, le développement de normes nécessite de la collaboration entre ces concurrents. Pour maintenir une concurrence et pour éviter les ententes, plusieurs pays ont des lois, dites « antitrust », lois que des participant·es à l'IETF ne connaissent pas forcément bien. La justification idéologique de ces lois est rappelée par le RFC, dans le cas étatsunien mais d'autres pays capitalistes ont des principes similaires : « Competition in a free market benefits consumers through lower prices, better quality and greater choice. Competition provides businesses the opportunity to compete on price and quality, in an open market and on a level playing field, unhampered by anticompetitive restraints. » Que ce soit vrai ou pas, peu importe, les lois antitrust doivent être respectées. Ce RFC n'édicte pas de règles pour l'IETF (« respectez la loi » est de toute façon déjà obligatoire), mais il explique des subtilités juridiques aux participant·es à l'IETF.

Il y a en effet deux risques pour l'IETF, qu'un·e représentant officiel de l'IETF soit accusé de comportement anti-concurrentiel, engageant la responsabilité de l'organisation, ou que des participant·es soient accusés de comportement anti-concurrentiel, ce qui n'engagerait pas la responsabilité de l'IETF mais pourrait affecter sa réputation.

Les participant·es à l'IETF sont censés suivre des règles dont certaines limitent déjà le risque de comportement anti-concurrentiel, entre autres :

Maintenant, s'y ajoutent les questions spécifiques au respect des lois sur la concurrence. La section 4, le cœur de ce RFC, attire l'attention sur :

  • La nécessité d'éviter de parler de certains sujets comme les prix des produits, les marges bénéficiaires, les accords avec des tiers, les analyses marketing, bref tout ce qui concerne le business, auquel le RFC ajoute les salaires et avantages divers (allez au bistrot le plus proche si vous voulez en parler librement). Des discussions sur ces sujets ne violent pas forcément les lois antitrust mais, dans le doute, mieux vaut être prudent.
  • L'importance de consulter un·e expert·e juridique en cas de doute. (L'IETF ne fournit pas de conseils juridiques.)
  • Le fait que les problèmes peuvent être signalés à l'équipe juridique de l'IETF (legal@ietf.org) ou via le service spécifique pour les lanceurs d'alerte.

Téléchargez le RFC 9680


L'article seul

RFC 9673: IPv6 Hop-by-Hop Options Processing Procedures

Date de publication du RFC : Octobre 2024
Auteur(s) du RFC : R. Hinden (Check Point Software), G. Fairhurst (University of Aberdeen)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 31 octobre 2024


Parmi les différentes options qui peuvent être placées dans un en-tête d'un paquet IPv6, certaines sont à traiter par chaque routeur situé sur le trajet. On les appelle les options « par saut » (hop-by-hop). Elles sont très peu utilisées en pratique, entre autres parce que leur traitement, tel que spécifié dans le RFC 8200, est trop contraignant pour les routeurs. Ce nouveau RFC change donc les règles, dans le sens d'un plus grand pragmatisme.

À part l'en-tête « Hop-by-hop Options » (RFC 8200, section 4.3), tous les en-têtes IPv6 ne concernent que les machines terminales. « Hop-by-hop Options », lui, concerne les routeurs et, avant le RFC 8200, tous les routeurs sur le trajet avaient l'obligation de le lire et d'agir en fonction des options qu'il contenait (la liste complète des options possibles est dans un registre IANA). Bien trop coûteuse pour les routeurs, cette obligation a été supprimée par le RFC 8200. Ce nouveau RFC 9673 modifie le traitement des options de cet en-tête (et donc le RFC 8200) dans l'espoir qu'il voit enfin un vrai déploiement dans l'Internet (actuellement, cet en-tête par saut - hop-by-hop - est quasiment inutilisé). Si vous concevez des routeurs, et êtes pressé·e, sautez directement à la section 5 du RFC, qui décrit les nouvelles règles, mais ce serait dommage.

Petite révision sur l'architecture des routeurs (section 3 du RFC). Les routeurs de haut de gamme ont une voie rapide (fast path) pour le traitement des paquets, lorsque ceux-ci n'ont pas de demande particulière. Mise en œuvre en dehors du processeur principal du routeur, cette voie rapide est traitée par des circuits spécialisés, typiquement des ASIC. Si le paquet nécessite des opérations plus complexes, on passe par une voie plus lente, utilisant des méthodes et du matériel plus proches de ceux d'un ordinateur classique. (Les RFC 6398 et RFC 6192 sont des lectures recommandées ici.) D'autre part, on distingue souvent, dans le routeur, la transmission (forwarding plane) et le contrôle (control plane). La transmission est le travail de base du routeur (transmettre les paquets reçus sur une interface via une autre interface, et le plus vite possible), le contrôle regroupe notamment les opérations de manipulation de la table de routage, par exemple lors de mises à jour reçues via des protocoles comme OSPF ou BGP. Contrairement à la transmission, le contrôle n'est pas en « temps réel ».

Aujourd'hui, un paquet IPv6 utilisant des options par saut risque fort de ne même pas arriver à destination, sacrifié par des routeurs qui ne veulent pas le traiter. (Voir le RFC 7872, l'exposé « Internet Measurements: IPv6 Extension Header Edition » ou l'article « Is it possible to extend IPv6? ».)

Que disent donc les nouvelles procédures (section 5) ?

  • Un routeur ne devrait pas jeter un paquet uniquement parce que celui-ci contient l'en-tête par saut (voir aussi RFC 9288). Même si le routeur ne traite pas les options de cet en-tête, il devrait transmettre le paquet.
  • Il est très recommandé que les routeurs disposent d'une option de configuration permettant d'indiquer s'il faut ou non traiter les options par saut. Et d'une autre pour indiquer quelles options dans l'en-tête doivent être gérées, que cela ne soit pas du tout ou rien.
  • IPv6 dispose de deux bits dans chaque option par saut pour indiquer le traitement souhaité du paquet si le routeur ne connait pas l'option. La nouvelle procédure permet d'être plus indulgent et, par exemple, de ne pas jeter un paquet même si l'émetteur le demandait, si le routeur ne veut pas traiter cette option (cf. le premier item de cette liste de règles).
  • Les émetteurs qui mettent l'en-tête par saut dans les paquets doivent être bien conscients que tous les routeurs ne le traiteront pas (c'est le cas depuis longtemps, le RFC ne fait que décrire cet état de fait).
  • Les machines terminales devraient examiner cet en-tête et le traiter, il ne concerne pas que les routeurs.

Pour faciliter la tâche des routeurs, et toujours dans l'espoir que les options par saut deviennent enfin une possibilité réaliste, la section 6 du RFC encadre la définition de nouveaux en-têtes (le RFC 8200 recommandait carrément de ne plus en définir, tant qu'on n'avait pas mieux défini leur utilisation). Les éventuelles futures options doivent être simples à traiter et conçues en pensant au travail qu'elles imposeront au routeur. Le protocole qui les utilise doit intégrer le fait que le routeur est autorisé à ignorer cette option, voire qu'il puisse jeter le paquet.

Ah, et un mot sur la sécurité (section 8). Plusieurs RFC ont déjà documenté les problèmes de sécurité que peuvent poser les options par saut, notamment le risque qu'elles facilitent une attaque par déni de service sur le routeur : RFC 6398, RFC 6192, RFC 7045 et RFC 9098.

Est-ce que le déploiement de ce RFC va améliorer les choses pour l'en-tête par saut, qui est jusqu'à présent un exemple d'échec ? Je suis assez pessimiste, étant donné la difficulté à changer des comportements bien établis.

Un peu d'histoire pour terminer (section 4 du RFC) : les premières normes IPv6 (RFC 1883, puis RFC 2460) imposaient à tous les routeurs d'examiner et de traiter les options par saut. Le RFC 7045 avait été le premier à constater que cette règle n'était pas respectée et ne pouvait pas l'être vu l'architecture des routeurs modernes. Le problème de performance dans le traitement des options était d'autant plus grave que les options n'avaient pas toutes le même format (cela a été résolu par le RFC 6564, qui imposait un format unique). Le résultat, comme vu plus haut, était que les routeurs ignoraient les options par saut ou, pire, jetaient le paquet qui les contenait. (Le RFC 9288 et l'article « Threats and Surprises behind IPv6 Extension Headers » expliquent pourquoi c'est une mauvaise idée. L'Internet Draft draft-ietf-v6ops-hbh discute également cette question.)


Téléchargez le RFC 9673


L'article seul

RFC 9669: BPF Instruction Set Architecture (ISA)

Date de publication du RFC : Octobre 2024
Auteur(s) du RFC : D. Thaler
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF bpf
Première rédaction de cet article le 1 novembre 2024


On a souvent envie de faire tourner des programmes à soi dans le noyau du système d'exploitation, par exemple à des fins de débogage ou d'observation du système. Cela soulève plein de problèmes (programmer dans le noyau est délicat) et la technique eBPF permet, depuis de nombreuses années, de le faire avec moins de risques. Ce RFC spécifie le jeu d'instructions eBPF. Programmeureuses en langage d'assemblage, ce RFC est pour vous.

eBPF désigne ici un jeu d'instructions (comme ARM ou RISC-V). Programmer en eBPF, c'est donc programmer en langage d'assemblage et, en général, on ne le fait pas soi-même, on écrit dans un langage de plus haut niveau (non spécifié ici mais c'est souvent un sous-ensemble de C) et on confie à un compilateur le soin de générer les instructions. Ce jeu d'instructions a plusieurs particularités. Notamment, il est délibérément limité, puisque toute bogue dans le noyau est particulièrement sérieuse, pouvant planter la machine ou pire, permettre son piratage. Vous ne pouvez pas faire de boucles générales, par exemple. eBPF est surtout répandu dans le monde Linux (et c'est là où vous trouverez beaucoup de ressources) où il est une alternative aux modules chargés dans le noyau. Pas mal du code réseau d'Android est ainsi en eBPF. Normalisé ici, eBPF peut être mis en œuvre sur d'autres noyaux (il tourne sur Windows, par exemple). Le monde eBPF est très riche, il y a plein de logiciels (pas toujours faciles à utiliser), plein de tutoriels (pas toujours à jour et qui ne correspondent pas toujours à votre système d'exploitation) mais cet article se focalise sur le sujet du RFC : le jeu d'instructions.

On trouve de nombreux exemples d'utilisation en production par exemple le répartiteur de charge Katran chez Facebook, via lequel vous êtes certainement passé, si vous utilisez Facebook. En plus expérimental, j'ai trouvé amusant qu'on puisse modifier les réponses DNS en eBPF.

Passons tout de suite à la description de ce jeu d'instructions (ISA = Instruction Set Architecture). D'abord, les types (section 2.1) : u32 est un entier non signé sur 32 bits, s16, un signé sur 16 bits, etc. eBPF fournit des fonctions de conversions utiles (section 2.2) comme be16 qui convertit en gros boutien (le RFC cite IEN137…). Au passage, une mise en œuvre d'eBPF n'est pas obligée de tout fournir (section 2.4). La norme décrit des groupes de conformité et une implémentation d'eBPF doit lister quels groupes elle met en œuvre. Le groupe base32 (qui n'a rien à voir avec le Base32 du RFC 4648) est le minimum requis dans tous les cas. Par exemple, divmul32 ajoute multiplication et division. Tous ces groupes figurent dans un registre IANA.

Les instructions eBPF sont encodées en 64 ou 128 bits (section 3). On y trouve les instructions classiques de tout jeu, les opérations arithmétiques (comme ADD), logiques (comme AND), les sauts (JA, JEQ et autrs), qui se font toujours vers l'avant, pour, je suppose, ne pas permettre de boucles (souvenez-vous du problème de l'arrêt, qui n'a pas de solution avec un jeu d'instructions plus étendu), l'appel de fonction, etc.

En parlant de fonctions, eBPF ne peut pas appeler n'importe quelle fonction. Il y a deux sortes de fonctions utilisables, les fonctions d'aide (section 4.3.1), pré-définies par la plateforme utilisée, et non normalisées (pour celles de Linux, voir la documentation, qui est sous Documentation/bpf si vous avez les sources du noyau). Il y a aussi les fonctions locales (section 4.3.2), définies par le programme eBPF.

Il y a enfin des instructions pour lire et écrire dans la mémoire (LD, ST, etc). Pour mémoriser plus facilement, eBPF utilise des dictionnaires (maps, cf. section 5.4.1).

La section 6 concerne la sécurité, un point évidemment crucial puisque les programmes eBPF tournent dans le noyau, où les erreurs ne pardonnent pas. Un programme eBPF malveillant peut provoquer de nombreux dégâts. C'est pour cela que, sur Linux, seul root peut charger un tel programme dans le noyau. Le RFC recommande de faire tourner ces programmes dans un environnement limité (bac à sable), de limiter les ressources dont ils disposent et de faire tourner des vérifications sur le programme avant son exécution (par exemple, sur Linux, regardez cette documentation ou bien l'article « Simple and Precise Static Analysis of Untrusted Linux Kernel Extensions »).

Enfin, section 7, les registres (pas les registres du processeur, ceux où on enregistre les codes utilisés). Deux registres IANA sont créés, celui des groupes de conformité et celui du jeu d'instructions. L'annexe A du RFC donne les valeurs actuelles. Les registres sont extensibles et la politique d'enregistrement est « Spécification nécessaire » et « Examen par un expert », cf. RFC 8126. (J'avoue ne pas savoir pourquoi, si les opcodes sont enregistrés, les mnémoniques ne le sont pas, cela rend les registres difficiles à lire.)

Un peu d'histoire, au passage. eBPF est dérivé de BPF, ce qui voulait dire Berkeley Packet Filter, et était spécifique au filtrage des paquets réseau. Cet usage a été notamment popularisé par tcpdump. D'ailleurs, ce programme a une option pour afficher le code BPF produit :


% sudo tcpdump -d port 53
(000) ldh      [12]
(001) jeq      #0x86dd          jt 2    jf 10
(002) ldb      [20]
(003) jeq      #0x84            jt 6    jf 4
(004) jeq      #0x6             jt 6    jf 5
(005) jeq      #0x11            jt 6    jf 23
(006) ldh      [54]
…
(021) jeq      #0x35            jt 22   jf 23
(022) ret      #262144
(023) ret      #0

  

Si vous voulez vous mettre à eBPF (attention, la courbe d'apprentissage va être raide), man 4 bpf est utile. Typiquement, vous écrirez vos programmes dans un sous-ensemble de C et vous compilerez en eBPF, par exemple avec clang, après avoir installé tous les outils et bibliothèques nécessaires (il faut souvent des versions assez récentes) :


% cat count.c
…
int count_packets(struct __sk_buff *skb) {
    __u32 key = 0;
    __u64 *counter;

    counter = bpf_map_lookup_elem(&pkt_counter, &key);
    if (counter) {
        (*counter)++;
    }

    return 0;
}
…

% clang  -target bpf -c count.c

% file count.o
count.o: ELF 64-bit LSB relocatable, eBPF, version 1 (SYSV), not stripped

% objdump -d count.o
…
0000000000000000 <count_packets>:
   0:	7b 1a f8 ff 00 00 00 00 	stxdw [%r10-8],%r1
   8:	b7 01 00 00 00 00 00 00 	mov %r1,0
  10:	63 1a f4 ff 00 00 00 00 	stxw [%r10-12],%r1
  18:	18 01 00 00 00 00 00 00 	lddw %r1,0
  20:	00 00 00 00 00 00 00 00 
  28:	bf a2 00 00 00 00 00 00 	mov %r2,%r10
  30:	07 02 00 00 f4 ff ff ff 	add %r2,-12

  

(Notez l'utilisation du désassembleur objdump.) Vous pouvez alors charger le code eBPF dans votre noyau, par exemple avec bpftool (et souvent admirer de beaux messages d'erreur comme « libbpf: elf: legacy map definitions in 'maps' section are not supported by libbpf v1.0+ »). Si tout fonctionne, votre code eBPF sera appelé par le noyau lors d'événements particuliers que vous avez indiqués (par exemple la création d'un processus, ou bien l'arrivée d'un paquet par le réseau) et fera alors ce que vous avez programmé. Comme me le fait remarquer Pierre Lebeaupin, il y a une bogue dans le source ci-dessus : l'incrémentation du compteur n'est pas atomique et donc, si on a plusieurs CPU, on risque de perdre certaines incrémentations. La solution de ce problème est laissé à la lectrice.

Un exemple d'utilisation d'eBPF pour observer ce que fait le noyau (ici avec un outil qui fait partie de bcc), on regarde les exec :


% sudo /usr/sbin/execsnoop-bpfcc
PCOMM            PID     PPID    RET ARGS
check_disk       389622  1628      0 /usr/lib/nagios/plugins/check_disk -c 10% -w 20% -X none -X tmpfs -X sysfs -X proc -X configfs -X devtmpfs -X devfs -X 
check_disk       389623  1628      0 /usr/lib/nagios/plugins/check_disk -c 10% -w 20% -X none -X tmpfs -X sysfs -X proc -X configfs -X devtmpfs -X devfs -X 
check_swap       389624  1628      0 /usr/lib/nagios/plugins/check_swap -c 25% -w 50%
check_procs      389625  1628      0 /usr/lib/nagios/plugins/check_procs -c 400 -w 250
ps               389627  389625    0 /bin/ps axwwo stat uid pid ppid vsz rss pcpu etime comm args
sh               389632  389631    0 /bin/sh -c   [ -x /usr/lib/php/sessionclean ] && if [ ! -d /run/systemd/system ]; then /usr/lib/php/sessionclean; fi
sessionclean     389633  1         0 /usr/lib/php/sessionclean
sort             389635  389633    0 /usr/bin/sort -rn -t: -k2,2
phpquery         389638  389634    0 /usr/sbin/phpquery -V
expr             389639  389638    0 /usr/bin/expr 2 - 1
sort             389642  389638    0 /usr/bin/sort -rn

Le code eBPF est interprété par une machine virtuelle ou bien traduit à la volée en code natif.

De nombreux exemples se trouvent dans le répertoire samples/bpf des sources du noyau Linux. (Le fichier README.rst explique comment compiler mais seulement dans le cadre de la compilation d'un noyau. En gros, c'est make menuconfig , cd samples/bpf puis make -i.) Un bon exemple, relativement simple, pour commencer avec le réseau est tcp_clamp_kern.c.

Si vous préférez travailler en Go (là aussi, avec un Go récent…), il existe un bon projet. Si vous suivez bien la documentation, vous pourrez compiler des programmes et les charger :


% go mod init ebpf-test
% go mod tidy
% go get github.com/cilium/ebpf/cmd/bpf2go
% go generate
% go build 
% sudo ./ebpf-test
2024/08/20 15:21:43 Counting incoming packets on veth0..
…
2024/08/20 15:22:03 Received 25 packets
2024/08/20 15:22:04 Received 26 packets
2024/08/20 15:22:05 Received 27 packets 
2024/08/20 15:22:06 Received 502 packets    <- ping -f
2024/08/20 15:22:07 Received 57683 packets
2024/08/20 15:22:08 Received 75237 packets
^C2024/08/20 15:22:09 Received signal, exiting..

Vous trouverez beaucoup de ressources eBPF sur https://ebpf.io/. Et si vous voulez plonger dans les détails précis des choix de conception d'eBPF, je recommande ce document.

Ce RFC avait fait l'objet de pas mal de débats à l'IETF car, normalement, l'IETF ne normalise pas de langages de programmation ou de jeux d'instructions. (La première réunion était à l'IETF 116 en mars 2023 donc c'est quand même allé assez vite.)


Téléchargez le RFC 9669


L'article seul

RFC 9660: The DNS Zone Version (ZONEVERSION) Option

Date de publication du RFC : Octobre 2024
Auteur(s) du RFC : H. Salgado (NIC Chile), M. Vergara (DigitalOcean), D. Wessels (Verisign)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 13 octobre 2024


Cette nouvelle option du DNS permet au client d'obtenir du serveur le numéro de version de la zone servie. (Et, non, le numéro de série dans l'enregistrement SOA ne suffit pas, lisez pour en savoir plus.)

Cela permettra de détecter les problèmes de mise à jour des serveurs faisant autorité si, par exemple, un des secondaires ne se met plus à jour. C'est surtout important pour l'anycast, qui complique le déboguage. En combinaison avec le NSID du RFC 5001, vous trouverez facilement le serveur qui a un problème. Cette nouvelle option ressemble d'ailleurs à NSID et s'utilise de la même façon.

Vous le savez, le DNS ne garantit pas que tous les serveurs faisant autorité d'une zone servent la même version de la zone au même moment. Si je regarde la zone .com à cet instant (14 juillet 2024, 09:48 UTC) avec check-soa, je vois :

% check-soa com
a.gtld-servers.net.
	2001:503:a83e::2:30: OK: 1720950475
	192.5.6.30: OK: 1720950475
b.gtld-servers.net.
	192.33.14.30: OK: 1720950475
	2001:503:231d::2:30: OK: 1720950475
c.gtld-servers.net.
	2001:503:83eb::30: OK: 1720950475
	192.26.92.30: OK: 1720950475
d.gtld-servers.net.
	2001:500:856e::30: OK: 1720950475
	192.31.80.30: OK: 1720950475
e.gtld-servers.net.
	2001:502:1ca1::30: OK: 1720950475
	192.12.94.30: OK: 1720950475
f.gtld-servers.net.
	2001:503:d414::30: OK: 1720950475
	192.35.51.30: OK: 1720950475
g.gtld-servers.net.
	192.42.93.30: OK: 1720950475
	2001:503:eea3::30: OK: 1720950475
h.gtld-servers.net.
	192.54.112.30: OK: 1720950475
	2001:502:8cc::30: OK: 1720950475
i.gtld-servers.net.
	2001:503:39c1::30: OK: 1720950460
	192.43.172.30: OK: 1720950475
j.gtld-servers.net.
	2001:502:7094::30: OK: 1720950475
	192.48.79.30: OK: 1720950475
k.gtld-servers.net.
	192.52.178.30: OK: 1720950460
	2001:503:d2d::30: OK: 1720950475
l.gtld-servers.net.
	192.41.162.30: OK: 1720950475
	2001:500:d937::30: OK: 1720950475
m.gtld-servers.net.
	2001:501:b1f9::30: OK: 1720950475
	192.55.83.30: OK: 1720950475

On observe que, bien que le numéro de série dans l'enregistrement SOA soit 1720950475, certains serveurs sont restés à 1720950460. Le DNS est « modérement cohérent » (RFC 3254, sur ce concept).

Dans l'exemple ci-dessus, check-soa a simplement fait une requête pour le type de données SOA (section 4.3.5 du RFC 1034). Une limite de cette méthode est que, si on observe des données d'autres types qui ne semblent pas à jour et que, pour vérifier, on fait une requête de type SOA, on n'a pas de garantie de tomber sur le même serveur, notamment en cas d'utilisation d'anycast (RFC 4786) ou bien s'il y a un répartiteur de charge avec plusieurs serveurs derrière. (D'ailleurs, dans l'exemple ci-dessus, vous avez remarqué que vous n'avez pas la même réponse en IPv4 et IPv6, probablement parce que vous arriviez sur deux instances différentes du nuage anycast.) Il faut donc un mécanisme à l'intérieur même de la requête qu'on utilise, comme pour le NSID. C'est le cas du ZONEVERSION de ce RFC, qui permet d'exprimer la version sous forme d'un numéro de série (comme avec le SOA) ou par d'autres moyens dans le futur, puisque toutes les zones n'utilisent pas le mécanisme de synchronisation habituel du DNS. On peut par exemple avoir des zones entièrement dynamiques et tirées d'une base de données, ou bien d'un calcul.

Notez aussi que certaines zones, comme .com, changent très vite, et que donc, même si on tombe sur le même serveur, le numéro de série aura pu changer entre une requête ordinaire et celle pour le SOA. C'est une raison supplémentaire pour avoir le mécanisme ZONEVERSION.

Bref, le nouveau mécanisme (section 2 du RFC), utilise EDNS (section 6.1.2 du RFC 6891). La nouvelle option EDNS porte le numéro 19. Encodée en TLV comme toutes les options EDNS, elle comprend une longueur et une chaine d'octets qui est la version de la zone. La longueur vaut zéro dans une requête (le client indique juste qu'il souhaite connaitre la version de la zone) et, dans la réponse, une valeur non nulle. La version est elle-même composée de trois champs :

  • Le nombre de composants dans le nom de domaine pour la zone concernée. Si la requête DNS portait sur le nom de domaine foo.bar.example.org et que le serveur renvoie la version de la zone example.org, ce champ vaudra deux.
  • Le type de la version. Différents serveurs faisant autorité utiliseront différentes méthodes pour se synchroniser et auront donc des types différents. Pour l'instant, un seul est normalisé, le 0 (alias SOA-SERIAL), qui est le numéro de série, celui qu'on trouverait dans le SOA, cf. section 3.3.13 du RFC 1035. La longueur sera donc de 6, les 4 octets de ce numéro, le type et le nombre de composants, un octet chacun. Un nouveau registre IANA accueillera peut-être d'autres types dans le futur, suivant la procédure « spécification nécessaire » du RFC 8126. (Cette procédure nécessite un examen par un expert, et la section 7.2.1 guide l'expert pour ce travail.)
  • La valeur à proprement parler.

Si vous voulez voir dans un pcap, regardez zoneversion.pcap.

L'option ZONEVERSION n'est renvoyée au client qui si celui-ci l'avait demandé, ce qu'il fait en mettant une option ZONEVERSION vide dans sa requête (section 3 du RFC). Si le serveur fait autorité pour la zone concernée (ou une zone ancêtre), et qu'il gère cette nouvelle option, il répond avec une valeur. Même si le nom demandé n'existe pas (réponse NXDOMAIN), l'option est renvoyée dans la réponse.

Comme les autres options EDNS, elle n'est pas signée par DNSSEC (section 8). Il n'y a donc pas de moyen de vérifier son authenticité et elle ne doit donc être utilisée qu'à titre informatif, par exemple pour le déboguage. (En outre, elle peut être modifiée en route, sauf si on utilise un mécanisme comme DoTRFC 7858.)

Question mises en œuvre de cette option, c'est surtout du code expérimental pour l'instant, voir cette liste (pas très à jour ?). Personnellement, j'ai ajouté ZONEVERSION à Drink, et écrit un article sur l'implémentation d'options EDNS (mais notez que l'option a changé de nom et de format depuis). Notez que, contrairement à presque toutes les options EDNS, ZONEVERSION est par zone, pas par serveur, ce qui est une contrainte pour le ou la programmeureuse, qui ne peut pas choisir la valeur avant de connaitre le nom demandé. Du côté des autres logiciels, NSD a vu un patch (mais apparemment abandonné). Voici ce que voit dig actuellement (en attendant une intégration officielle de l'option) :


% dig +ednsopt=19 @ns1-dyn.bortzmeyer.fr dyn.bortzmeyer.fr SOA 
…
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64655
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
…
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1440
; OPT=19: 03 00 78 a5 08 cc ("..x...")
…

;; ANSWER SECTION:
dyn.bortzmeyer.fr.	0 IN SOA ns1-dyn.bortzmeyer.fr. stephane.bortzmeyer.org. (
				2024081612 ; serial
…

Vous noterez que "03" indique trois composants (dyn.bortzmeyer.fr), "00" le SOA-SERIAL, et "78 a5 08 cc" égal 2024081612. Vous pouvez aussi tester ZONEVERSION avec le serveur de test 200.1.122.30 (un NSD modifié), avec le domaine example.com.


Téléchargez le RFC 9660


L'article seul

RFC 9651: Structured Field Values for HTTP

Date de publication du RFC : Septembre 2024
Auteur(s) du RFC : M. Nottingham (Cloudflare), P-H. Kamp (The Varnish Cache Project)
Chemin des normes
Première rédaction de cet article le 6 octobre 2024


Plusieurs en-têtes HTTP sont structurés, c'est-à-dire que le contenu n'est pas juste une suite de caractères mais est composé d'éléments qu'un logiciel peut analyser. C'est par exemple le cas de Accept-Language: ou de Content-Disposition:. Mais chaque en-tête ainsi structuré a sa propre syntaxe, sans rien en commun avec les autres en-têtes structurés, ce qui en rend l'analyse pénible. Ce nouveau RFC (qui remplace le RFC 8941) propose donc des types de données et des algorithmes que les futurs en-têtes qui seront définis pourront utiliser pour standardiser un peu l'analyse d'en-têtes HTTP. Les en-têtes structurés anciens ne sont pas changés, pour préserver la compatibilité. De nombreux RFC utilisent déjà cette syntaxe (RFC 9209, RFC 9211, etc).

Imaginez : vous êtes un concepteur ou une conceptrice d'une extension au protocole HTTP qui va nécessiter la définition d'un nouvel en-tête. La norme HTTP, le RFC 9110, section 16.3.2, vous guide en expliquant ce à quoi il faut penser quand on conçoit un en-tête HTTP. Mais même avec ce guide, les pièges sont nombreux. Et, une fois votre en-tête spécifié, il vous faudra attendre que tous les logiciels, serveurs, clients, et autres (comme Varnish, pour lequel travaille un des auteurs du RFC) soient mis à jour, ce qui sera d'autant plus long que le nouvel en-tête aura sa syntaxe spécifique, avec ses amusantes particularités. Amusantes pour tout le monde, sauf pour le programmeur ou la programmeuse qui devra écrire l'analyse.

La solution est donc que les futurs en-têtes structurés réutilisent les éléments fournis par notre RFC, ainsi que son modèle abstrait, et la sérialisation proposée pour envoyer le résultat sur le réseau. Le RFC recommande d'appliquer strictement ces règles, le but étant de favoriser l'interopérabilité, au contraire du classique principe de robustesse, qui mène trop souvent à du code compliqué (et donc dangereux) car voulant traiter tous les cas et toutes les déviations. L'idée est que s'il y a la moindre erreur dans un en-tête structuré, celui-ci doit être ignoré complètement.

La syntaxe est malheureusement spécifiée sous forme d'algorithmes d'analyse. L'annexe C fournit toutefois aussi une grammaire en ABNF (RFC 5234).

Voici un exemple fictif d'en-tête structuré très simple (tellement simple que, si tous étaient comme lui, on n'aurait sans doute pas eu besoin de ce RFC) : Foo-Example: est défini comme ne prenant qu'un élément comme valeur, un entier compris entre 0 et 10. Voici à quoi il ressemblera en HTTP :

Foo-Example: 3
  

Il accepte des paramètres après un point-virgule, un seul paramètre est défini, foourl dont la valeur est un URI. Cela pourrait donner :

Foo-Example: 2; foourl="https://foo.example.com/"    
  

Donc, ces solutions pour les en-têtes structurés ne serviront que pour les futurs en-têtes, pas encore définis, et qui seront ajoutés au registre IANA. Imaginons donc que vous soyez en train de mettre au point une norme qui inclut, entre autres, un en-tête HTTP structuré. Que devez-vous mettre dans le texte de votre norme ? La section 2 de notre RFC vous le dit :

  • Inclure une référence à ce RFC 9651.
  • J'ai parlé jusqu'à présent d'en-tête structuré mais en fait ce RFC 9651 s'applique aussi aux pieds (trailers) (RFC 9110, section 6.5 ; en dépit de leur nom, les pieds sont des en-têtes eux aussi). La norme devra préciser si elle s'applique seulement aux en-têtes classiques ou bien aussi aux pieds.
  • Spécifier si la valeur sera une liste, un dictionnaire ou juste un élément (ces termes sont définis en section 3). Dans l'exemple ci-dessus Foo-Example:, la valeur était un élément, de type entier.
  • Penser à définir la sémantique.
  • Et ajouter les règles supplémentaires sur la valeur du champ, s'il y en a. Ainsi, l'exemple avec Foo-Example: imposait une valeur entière entre 0 et 10.

Une spécification d'un en-tête structuré ne peut que rajouter des contraintes à ce que prévoit ce RFC 9651. S'il en retirait, on ne pourrait plus utiliser du code générique pour analyser tous les en-têtes structurés.

Rappelez-vous que notre RFC est strict : si une erreur est présente dans l'en-tête, il est ignoré. Ainsi, s'il était spécifié que la valeur est un élément de type entier et qu'on trouve une chaîne de caractères, on ignore l'en-tête. Idem dans l'exemple ci-dessus si on reçoit Foo-Example: 42, la valeur excessive mène au rejet de l'en-tête.

Les valeurs peuvent inclure des paramètres (comme le foourl donné en exemple plus haut), et le RFC recommande d'ignorer les paramètres inconnus, afin de permettre d'étendre leur nombre sans tout casser.

On a vu qu'une des plaies du Web était le laxisme trop grand dans l'analyse des données reçues (c'est particulièrement net pour HTML). Mais on rencontre aussi des cas contraires, des systèmes (par exemple les pare-feux applicatifs) qui, trop fragiles, chouinent lorsqu'ils rencontrent des cas imprévus, parce que leurs auteurs avaient mal lu le RFC. Cela peut mener à l'ossification, l'impossibilité de faire évoluer l'Internet parce que des nouveautés, pourtant prévues dès l'origine, sont refusées. Une solution récente est le graissage, la variation délibérée des messages pour utiliser toutes les possibilités du protocole. (Un exemple pour TLS est décrit dans le RFC 8701.) Cette technique est recommandée par notre RFC.

La section 3 du RFC décrit ensuite les types qui sont les briques de base avec lesquelles on va pouvoir définir les en-têtes structurés. La valeur d'un en-tête peut être une liste, un dictionnaire ou un élément. Les listes et les dictionnaires peuvent à leur tour contenir des listes. Une liste est une suite de termes qui, dans le cas de HTTP, sont séparés par des virgules :

ListOfStrings-Example: "foo", "bar", "It was the best of times."    
  

Et si les éléments d'une liste sont eux-mêmes des listes, on met ces listes internes entre parenthèses (et notez la liste vide à la fin, et l'espace comme séparateur) :

ListOfListsOfStrings-Example: ("foo" "bar"), ("baz"), ("bat" "one"), ()    
  

Un en-tête structuré dont la valeur est une liste a toujours une valeur, la liste vide, même si l'en-tête est absent.

Un dictionnaire est une suite de termes nom=valeur. En HTTP, cela donnera :

Dictionary-Example: en="Applepie", fr="Tarte aux pommes"
  

Et nous avons déjà vu les éléments simples dans le premier exemple. Les éléments peuvent être de type entier, chaîne de caractères, booléen, identificateur, valeur binaire, date, et un dernier type plus exotique (lisez le RFC pour en savoir plus). L'exemple avec Foo-Example: utilisait un entier. Les exemples avec listes et dictionnaires se servaient de chaînes de caractères. Ces chaînes sont encadrées de guillemets (pas d'apostrophes). Compte-tenu des analyseurs HTTP existants, les chaînes de caractères ordinaires doivent être en ASCII (RFC 20). Si on veut envoyer de l'Unicode, il faut utiliser un autre type, Display String. Quant aux booléens, notez qu'il faut écrire 1 et 0 (pas true et false), et préfixé d'un point d'interrogation.

Toutes ces valeurs peuvent prendre des paramètres, qui sont eux-mêmes une suite de couples clé=valeur, après un point-virgule qui les sépare de la valeur principale (ici, on a deux paramètres) :

ListOfParameters: abc;a=1;b=2    
  

J'ai dit au début que ce RFC définit un modèle abstrait, et une sérialisation concrète pour HTTP. La section 4 du RFC spécifie cette sérialisation, et son inverse, l'analyse des en-têtes (pour les programmeur·ses seulement).

Ah, et si vous êtes fana de formats structurés, ne manquez pas l'annexe A du RFC, qui répond à la question que vous vous posez certainement depuis plusieurs paragraphes : pourquoi ne pas avoir tout simplement décidé que les en-têtes structurés auraient des valeurs en JSON (RFC 8259), ce qui évitait d'écrire un nouveau RFC, et permettait de profiter du code JSON existant ? Le RFC estime que le fait que les chaînes de caractères JSON soient de l'Unicode est trop risqué, par exemple pour l'interopérabilité. Autre problème de JSON, les structures de données peuvent être emboîtées indéfiniment, ce qui nécessiterait des analyseurs dont la consommation mémoire ne peut pas être connue et limitée. (Notre RFC permet des listes dans les listes mais cela s'arrête là : on ne peut pas poursuivre l'emboîtement.)

Une partie des problèmes avec JSON pourrait se résoudre en se limitant à un profil restreint de JSON, par exemple en utilisant le RFC 7493 comme point de départ. Mais, dans ce cas, l'argument « on a déjà un format normalisé, et mis en œuvre partout » tomberait.

Enfin, l'annexe A note également qu'il y avait des considérations d'ordre plutôt esthétiques contre JSON dans les en-têtes HTTP.

Toujours pour les programmeur·ses, l'annexe B du RFC donne quelques conseils pour les auteur·es de bibliothèques mettant en œuvre l'analyse d'en-têtes structurés. Pour les aider à suivre ces conseils, une suite de tests est disponible. Quant à une liste de mises en œuvre du RFC, vous pouvez regarder celle-ci.

Actuellement, il y a dans le registre des en-têtes plusieurs en-têtes structurés, comme le Accept-CH: du RFC 8942 (sa valeur est une liste d'identificateurs), le Cache-Status: du RFC 9211 ou le Client-Cert: du RFC 9440.

Si vous voulez un exposé synthétique sur ces en-têtes structurés, je vous recommande cet article par un des auteurs du RFC.

Voyons maintenant un peu de pratique avec une des mises en œuvre citées plus haut, http_sfv, une bibliothèque Python. Une fois installée :

  
% python3
>>> import http_sfv
>>> my_item=http_sfv.Item()
>>> my_item.parse(b"2")
>>> print(my_item)
2

On a analysé la valeur « 2 » en déclarant que cette valeur devait être un élément et, pas de surprise, ça marche. Avec une valeur syntaxiquement incorrecte :

     
>>> my_item.parse(b"2, 3")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/stephane/.local/lib/python3.12/site-packages/http_sfv/util.py", line 61, in parse
    raise ValueError("Trailing text after parsed value")
ValueError: Trailing text after parsed value

   

Et avec un paramètre (il sera accessible après l'analyse, via le dictionnaire Python params) :

     
>>> my_item.parse(b"2; foourl=\"https://foo.example.com/\"")
>>> print(my_item.params['foourl'])
https://foo.example.com/

   

Avec une liste :

     
>>> my_list=http_sfv.List()
>>> my_list.parse(b"\"foo\", \"bar\", \"It was the best of times.\"")
>>> print(my_list)
"foo", "bar", "It was the best of times."

   

Et avec un dictionnaire :

     
>>> my_dict=http_sfv.Dictionary()
>>> my_dict.parse(b"en=\"Applepie\", fr=\"Tarte aux pommes\"")
>>> print(my_dict)
en="Applepie", fr="Tarte aux pommes"
>>> print(my_dict["fr"])
"Tarte aux pommes"

  

L'annexe D résume les principaux changements depuis le RFC 8941. Rien de trop crucial, à part le fait que l'ABNF est reléguée à une annexe. Sinon, il y a deux nouveaux types de base, pour les dates et les chaines de caractères en Unicode (Display Strings).


Téléchargez le RFC 9651


L'article seul

RFC des différentes séries : 0  1000  2000  3000  4000  5000  6000  7000  8000  9000