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 9567: DNS Error Reporting

Date de publication du RFC : Avril 2024
Auteur(s) du RFC : R. Arends (ICANN), M. Larson (ICANN)
Chemin des normes
Première rédaction de cet article le 27 avril 2024


Lorsqu'un résolveur DNS détecte un problème avec une zone, l'empêchant de résoudre les noms dans cette zone, il n'avait pas de moyen simple et automatique de prévenir les gérants des serveurs faisant autorité pour cette zone. Leur envoyer un message en utilisant l'information dans l'enregistrement SOA ou les adresses classiques du RFC 2142 ? Mais, justement, si la zone ne marche pas, le courrier ne partira pas forcément. Ce nouveau RFC propose un nouveau système. Les serveurs faisant autorité annoncent un domaine (qui marche, espérons-le), qui acceptera des requêtes DNS spéciales signalant le problème.

Cela dépend évidemment du problème pratique qui se pose. Si la zone n'a aucun serveur faisant autorité qui marche, il n'y a évidemment rien à faire. Mais s'ils marchent, tout en servant des données problématiques (par exemple des signatures DNSSEC expirées), alors, le résolveur pourra agir. Les serveurs faisant autorité mettent dans leurs réponses une option EDNS qui indique le domaine qui recevra les rapports (cela doit être un autre domaine, qui n'a pas de problème), le résolveur fera alors une requête DNS se terminant par le nom du domaine de signalement, et encodant le problème. L'agent, le domaine de signalement, pourra alors récolter ces requêtes et savoir qu'il y a un problème. Cela ne traite pas tous les cas (il faudra toujours utiliser RDAP ou whois pour récolter des informations sur les contacts du domaine erroné, puis leur écrire depuis un autre réseau) mais c'est simple, léger et automatisable. Les gérants de domaine sérieux, qui prennent au sérieux les signalements de problèmes techniques (soit 0,00001 % des domaines) pourront alors agir. (Note si vous gérez un résolveur et que vous constatez un problème avec un domaine et que les contacts ne répondent pas : un message méchant sur Twitter est souvent plus efficace.)

Donc, les détails techniques : le domaine qui veut recevoir les éventuels signalements va devoir configurer ses serveurs faisant autorité pour renvoyer une option EDNS, de numéro 18 (section 5 du RFC), indiquant l'agent, c'est-à-dire le domaine qui va recevoir les signalements (il faut évidemment veiller à ce qu'il n'ait pas de point de défaillance commun avec le domaine surveillé). Notez que cette option est systématiquement envoyée, le client (le résolveur) n'a pas à dire quoi que ce soit (la question avait fait l'objet d'un sérieux débat à l'IETF).

En cas de problème, notamment DNSSEC, le résolveur qui a noté le problème va alors construire un nom de domaine formé, successivement (section 6.1.1) par :

  • Le composant _er,
  • Le type de données qui posait problème (adresse IP, enregistrement de service, etc),
  • Le nom de domaine qui était initialement demandé par le résolveur,
  • L'erreur étendue (EDE, RFC 8914),
  • Le composant _er (oui, encore),
  • Le nom de domaine de l'agent.

Par exemple, si le domaine dyn.bortzmeyer.fr annonce comme agent report.dyn.sources.org, et qu'un résolveur découvre des signatures DNSSEC expirées (EDE 7) en cherchant à résoudre hello.dyn.bortzmeyer.fr / TXT (TXT a la valeur 16), la requête de signalement du résolveur sera _er.16.hello.dyn.bortzmeyer.fr.7._er.report.dyn.sources.org (ouf). Le type demandé est TXT. Lorsque cette requête arrivera au serveur faisant autorité pour report.dyn.sources.org, il pourra enregistrer qu'il y a eu un problème, et mettre cette information à la disposition de son administrateur système.

Ce serveur faisant autorité est censé répondre au signalement avec une réponse de type TXT comme ici :


% dig _er.16.hello.dyn.bortzmeyer.fr.7._er.report.dyn.sources.org TXT
…
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12032
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
…
;; ANSWER SECTION:
_er.16.hello.dyn.bortzmeyer.fr.7._er.report.dyn.sources.org. 30	IN TXT "Thanks for the report of error 7 on hello.dyn.bortzmeyer.fr"
…

  

L'agent peut ensuite être interrogé, par des méthodes propres à la mise en œuvre utilisée :

% echo report | socat - UNIX-CONNECT:/home/drink/drink.sock
REPORT state:
hello.dyn.bortzmeyer.fr, 7
ip.dyn.bortzmeyer.fr, 7
  

Ici, on voit que deux domaines ont été signalés comme ayant des signatures expirées (rassurez-vous, c'était juste des tests). Le nombre de signalements n'est pas indiqué, ni la source des signalements (travail futur).

Quelques petits points de sécurité à garder en tête (section 9 du RFC) :

  • Le fait de signaler va, par définition, donner au serveur faisant autorité des informations sur le résolveur (par exemple, un résolveur menteur qui signalerait les blocages informerait sur sa politique, ce que les censeurs ne font en général pas).
  • Il en donnera aussi aux serveurs des zones parentes du domaine agent, et il est donc très recommandé de minimiser le nom (RFC 9156).
  • Il n'y a pas spécialement d'authentification donc tous ces rapports doivent être traités avec prudence. Un méchant peut facilement fabriquer de faux rapports, de toute façon. Ils doivent donc toujours être vérifiés.

Cette technique a été mise en œuvre dans Drink lors d'un hackathon IETF. Drink peut à la fois signaler un domaine agent, et être serveur pour un domaine agent.

Un exemple de signalisation EDNS de cette option, vu la version de développement de Wireshark (merci à Alexis La Goutte) : wireshark-domain-report.jpeg


Téléchargez le RFC 9567


L'article seul

RFC 9562: Universally Unique IDentifiers (UUIDs)

Date de publication du RFC : Mai 2024
Auteur(s) du RFC : K. Davis (Cisco Systems), B. Peabody (Uncloud), P. Leach (University of Washington)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF uuidrev
Première rédaction de cet article le 12 mai 2024


Ce RFC normalise les UUID, une famille d'identificateurs uniques, obtenus sans registre central. Il remplace l'ancienne norme, le RFC 4122, avec pas mal de nouveautés et un RFC complètement refait.

Les UUID, également connus autrefois sous le nom de GUID (Globally Unique IDentifiers), sont issus à l'origine du système des Apollo, adopté ensuite dans la plate-forme DCE. Les UUID ont une taille fixe, 128 bits, et sont obtenus localement, par exemple à partir d'un autre identificateur unique comme un nom de domaine, ou bien en tirant au hasard, la grande taille de leur espace de nommage faisant que les collisions sont très improbables (section 6.7 du RFC). Ce RFC reprend la spécification (bien oubliée aujourd'hui) de DCE de l'Open Group (ex-OSF) et ajoute la définition d'un espace de noms pour des URN (sections 4 et 7). (Il existe aussi une norme ITU sur les UUID et un registre des UUID, pour ceux qui y tiennent.)

Les UUID peuvent donc convenir pour identifier une entité sur le réseau, par exemple une machine mais aussi, vu leur nombre, comme identificateur unique pour des transactions (ce qui était un de leurs usages dans DCE). En revanche, ils ne sont pas résolvables, contrairement aux noms de domaine. Mais ils sont présents dans beaucoup de logiciels (Windows, par exemple, les utilise intensivement). On les utilise comme clé primaire dans les bases de données, comme identificateur de transaction, comme nom de machine, etc.

Les UID peuvent se représenter sous forme d'un nombre binaire de 128 bits (la section 5 du RFC décrit les différents champs qui peuvent apparaitre) ou bien sous forme texte. Sur Unix, on peut fabriquer un UUID avec la commande uuidgen, qui affiche la représentation texte standard que normalise notre RFC (section 4) :

% uuidgen 
317e8ed3-1428-4ef1-9dce-505ffbcba11a

% uuidgen
ec8638fd-c93d-4c6f-9826-f3c71436443a

Sur une machine FreeBSD, un UUID de la machine est automatiquement généré (par le script /etc/rc.d/hostid) et stocké dans le fichier /etc/hostid.

Pour l'affichage sous forme d'URN (RFC 8141), on ajoute juste l'espace uuid par exemple urn:uuid:ec8638fd-c93d-4c6f-9826-f3c71436443a. Il a été ajouté au registre IANA des espaces de noms des URN.

La section 4 du RFC détaille le format de l'UUID. En dépit des apparences, l'UUID n'est pas plat, il a une structure, mais il est très déconseillé aux applications de l'interpréter (section 6.12). Un des champs les plus importants est le champ Version (qui devrait plutôt s'appeler Type) car il existe plusieurs types d'UUID :

  • UUID version 1, fondé sur le temps (notez tout de suite que les versions 6 et 7 sont recommandées à sa place).
  • UUID version 2, réservé, non utilisé.
  • UUID version 3, fondé sur un espace de noms (par exemple le DNS) et un nom qui est condensé en MD5 (la version 5 est préférable).
  • UUID version 4, aléatoire.
  • UUID version 5, fondé sur un espace de noms et un nom qui est condensé en SHA-1.
  • UUID version 6, fondé sur le temps, avec les mêmes champs que la version 1, mais avec un format différent.
  • UUID version 7, fondé sur le temps, avec une autre définition, et des champs différents.
  • UUID version 8, pour les usages expérimentaux, si vous voulez jouer localement avec un nouveau mécanisme de génération.

Ces différents types / versions figurent dans un registre IANA. Ce registre ne peut être modifié que par une action de normalisation (cf. RFC 8126).

uuidgen, vu plus haut, peut générer des UUID de version 1 option -t, de version 3 (-m), de version 4 (c'est son comportement par défaut, mais on peut utiliser l'option -r si on veut être explicite) ou de version 5 (-s). Ici, on voit les UUID fondés sur une estampille temporelle (version 1) augmenter petit à petit :

% uuidgen -t
42ff1626-0fc7-11ef-8162-49e9505fb2f3

% uuidgen -t
4361fae8-0fc7-11ef-8162-49e9505fb2f3

% uuidgen -t
45381d02-0fc7-11ef-8162-49e9505fb2f3
  

Ici, dans le cas d'un UUID fondé sur un nom (version 3), l'UUID est stable (essayez chez vous, vous devriez obtenir le même résultat que moi), une propriété importante des UUID de version 3 et 5 :

 
% uuidgen -m -n @dns -N foobar.example
8796bf1a-793c-3c44-9ec5-a572635cd3d4

% uuidgen -m -n @dns -N foobar.example
8796bf1a-793c-3c44-9ec5-a572635cd3d4
  

Les espaces de noms sont enregistrés dans un registre IANA, d'autres peuvent être ajoutés si on écrit une spécification (cf. RFC 8126). Notez que chaque espace a son UUID (6ba7b810-9dad-11d1-80b4-00c04fd430c8 pour l'espace DNS).

Les UUID de version 6 et 7, nouveautés de ce RFC 9562, ne sont pas mis en œuvre par uuidgen, ni d'ailleurs par beaucoup d'autres programmes.

Les sections 6.1 et 6.2, elles, décrivent le processus de génération d'un UUID à base temporelle. Idéalement, il faut utiliser une graine enregistrée sur le disque (pour éviter de générer des UID identiques) ainsi que l'instant de la génération. Mais lire sur le disque prend du temps (alors qu'on peut vouloir générer des UUID rapidement, par exemple pour identifier des transactions) et l'horloge de la machine n'a pas toujours une résolution suffisante pour éviter de lire deux fois de suite le même instant. Ces sections contiennent donc également des avis sur la génération fiable d'UUID, par exemple en gardant en mêmoire le nombre d'UUID générés, pour les ajouter à l'heure.

La section 8, consacrée à la sécurité, rappelle qu'un UUID ne doit pas être utilisé comme capacité (car il est trop facile à deviner) et qu'il ne faut pas demander à un humain de comparer deux UUID (ils se ressemblent trop pour un œil humain).

Il est évidemment recommandé d'utiliser les UUID de version 5 plutôt que de version 3 (RFC 6151) mais SHA-1 a aussi ses problèmes (RFC 6194) et, de toute façon, pour la plupart des utilisations des UUID, les faiblesses cryptographiques de MD5 et de SHA-1 ne sont pas gênantes.

La section 2.1 du RFC détaille les motivations pour la mise à jour du RFC 4122 et quels sont les changements effectués. Certaines utilisations des UUID ont remis en cause des suppositions originales. Ainsi, les UUID sont souvent utilisés dans un contexte réparti, où leur capacité à être uniques sans registre central est très utile. Mais quelques points manquaient au RFC 4122 :

  • UUID version 4 (aléatoire) avait une mauvaise localité : deux UUID créés l'un après l'autre en un temps très court n'ont aucun rapport, ce qui est gênant pour certains usages (par exemple comme étiquette dans un B-tree).
  • UUID version 1 (fondé entre autre sur le temps écoulé depuis l'epoch) utilise un incrément peu pratique (cent nanosecondes).
  • Certaines méthodes fabrication des UUID posaient des gros problèmes de vie privée, par exemple l'utilisation des adresses MAC dans UUID version 1, désormais déconseillée.
  • Le RFC 4122 descendait trop dans les détails de mise en œuvre.
  • Le RFC 4122 ne séparait pas les exigences pour la génération d'UUID et celles pour leur stockage.

Seize mises en œuvre des UUID ont été étudiées pour préparer le nouveau RFC (vous avez la liste dans la section 2.1), menant aux constations suivantes :

  • Beaucoup d'errata dans le RFC 4122.
  • Spécification du format qui mélangeait trop les diverses versions d'UUID.
  • Absence de vecteurs de test (ils figurent désormais dans l'annexe A).

En Python, il existe un module UUID qui offre des fonctions de génération d'UUID de différentes versions (mais pas les plus récentes) :

import uuid

myuuid = uuid.uuid1() # Version 1, Time-based UUID
heruuid = uuid.uuid3(uuid.NAMESPACE_DNS, "foo.bar.example") # Version
            # 3, Name-based ("hash-based") UUID, a name hashed by MD5
otheruuid = uuid.uuid4() # Version 4, Random-based UUID
yetanotheruuid = uuid.uuid5(uuid.NAMESPACE_DNS,
                            "www.example.org")
                      # Version 5, a name hashed by SHA1
if (myuuid == otheruuid or \
    myuuid == heruuid or \
    myuuid == yetanotheruuid or \
    otheruuid == yetanotheruuid):
    raise Exception("They are equal, PANIC!")

print(myuuid)
print(heruuid) # Will always be the same
print(otheruuid)
print(yetanotheruuid) # Will always be the same

Et comme le dit la documentation, Note that uuid1() may compromise privacy since it creates a UUID containing the computer’s network address. (méthode de génération des UUID version 1 qui est désormais déconseillée).

Le SGBD PostgreSQL inclut un type UUID. Cela évite de stocker les UUID sous leur forme texte, ce qui est techniquement absurde et consomme 288 bits au lieu de 128 (section 6.13 du RFC).

essais=> CREATE TABLE Transactions (id uuid, value INT);
CREATE TABLE
essais=> INSERT INTO Transactions VALUES 
           ('74738ff5-5367-5958-9aee-98fffdcd1876', 42);
INSERT 0 1
essais=> INSERT INTO Transactions VALUES 
            ('88e6441b-5f5c-436b-8066-80dca8222abf', 6);
INSERT 0 1
essais=> INSERT INTO Transactions VALUES ('Pas correct', 3);
ERROR:  invalid input syntax for type uuid: "Pas correct"
LINE 1: INSERT INTO Transactions VALUES ('Pas correct', 3);
                                         ^
-- PostgreSQL peut seulement générer la version 4, les aléatoires
essais=> INSERT INTO Transactions VALUES (gen_random_uuid () , 0);
INSERT 0 1
essais=> SELECT * FROM Transactions;
                  id                  | value 
--------------------------------------+-------
 74738ff5-5367-5958-9aee-98fffdcd1876 |    42
 88e6441b-5f5c-436b-8066-80dca8222abf |     6
 41648aef-b123-496e-8a4c-52e573d17b6a |     0
(3 rows)

Attention, le RFC (section 6.13) déconseille l'utilisation des UUID fondés sur un nom pour servir de clé primaire dans la base de données, sauf si on est absolument certain (mais c'est rare) que les noms ne changeront pas.

Il existe plusieurs exemples d'utilisation des UUID. Par exemple, Linux s'en sert pour identifier les disques attachés à la machine, de préférence à l'ancien système où l'ajout d'un nouveau disque pouvait changer l'ordre des numéros sur le bus et empêcher le système de trouver un disque. Un /etc/fstab typique sur Linux contient donc des :

UUID=da8285a0-3a70-413d-baed-a1f48d7bf7b2       /home   ext3 defaults ...

plutôt que les anciens :

/dev/sda3       /home           ext3    defaults  

car sda3 n'est pas un identificateur stable. L'UUID, lui, est dans le système de fichiers et ne changera pas avec les changements sur le bus. On peut l'afficher avec dumpe2fs :


# dumpe2fs -h /dev/sda3
...
Filesystem UUID:          da8285a0-3a70-413d-baed-a1f48d7bf7b2
...

Un exemple d'utilisation de la nouvelle version 7 est décrit dans l'excellent article « Goodbye integers. Hello UUIDv7! ».

La section 6 décrit les bonnes pratiques de génération d'un UUID. Ainsi :

  • Pour tous les UUID fondés sur le temps, si vous avez besoin d'unicité des UUID, attention aux cas où l'horloge peut changer, en raison d'une modification manuelle, d'une seconde intercalaire ou d'un ajustement fait par NTP.
  • Si vous générez des UUID de manière répartie, sur plusieurs machines, ce qui est un des points forts des UUID, mais que vous voulez quand même de l'unicité, vous pouvez préfixer vos UUID avec un identificateur de la machine, ou bien compter sur un registre central (mais, en général, c'est justement ce qu'on veut éviter avec des UUID).
  • UUID rend les collisions (génération de deux UUID identiques) peu probables mais pas impossibles. Lorsque vous concevez une application, demandez vous si une collision est juste un petit inconvénient ou bien si elle est inacceptable (le RFC cite l'exemple fictif d'un système de contrôle aérien où chaque avion serait identifié par un UUID ; l'attribution du même UUID à deux avions différents serait clairement catastrophique). Dans ce cas, vous devez trouver un moyen de ne pas avoir de collision.
  • Si vous voulez des UUID qui ne soient pas prévisibles par un observateur extérieur, utilisez la version 4 et assurez vous que votre générateur de nombres aléatoires suit bien les prescriptions des RFC 4086 et RFC 8937, ainsi que « Random Number Generator Recommendations for Applications ».
  • Les versions 6 et 7 (nouveautés de ce RFC 9562) sont prévues pour que les UUID soient triables chronologiquement, sans avoir besoin d'analyse, uniquement en triant la version binaire. Un des avantages est que des UUID générés à des moments proches ont des valeurs proches, ce qui peut être utile dans certaines applications.

Téléchargez le RFC 9562


L'article seul

RFC 9557: Date and Time on the Internet: Timestamps with Additional Information

Date de publication du RFC : Avril 2024
Auteur(s) du RFC : U. Sharma (Igalia, S.L.), C. Bormann (Universität Bremen TZI)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sedate
Première rédaction de cet article le 29 avril 2024


Ce RFC modifie légèrement le format des estampilles temporelles du RFC 3339, changeant à la marge une définition et, surtout, permettant d'y attacher des informations supplémentaires.

Le RFC 3339 décrit un des formats d'estampilles temporelles possibles sur l'Internet (car, malheureusement, toutes les normes Internet ne l'utilisent pas). Un exemple, sur Unix :

% date --rfc-3339=seconds 
2024-04-29 06:22:33+00:00
  

Le format du RFC 3339 est du type « YYYY-MM-DD HH:MM:SS » avec, à la fin, ajout d'une information sur le décalage avec le temps de référence (on verra que notre nouveau RFC 9557 change un peu cette dernière information). Un format gros boutien, donc, qui permet notamment de trier les dates-et-heures uniquement en suivant l'ordre lexicographique des caractères.

Mais certaines applications voudraient en savoir plus, et ajouter à ce format des détails. D'ailleurs, c'est déjà fait dans des solutions non normalisées, comme le format de Java, très populaire, qui permet des estampilles comme 2011-12-03T10:15:30+01:00[Europe/Paris] (fuseau horaire, ajouté après la date au format du RFC 3339 ; lisez le RFC 6557 pour en savoir davantage sur les fuseaux horaires).

Ce nouveau RFC prévoit donc une extension optionnelle (les dates-et-heures qui suivaient le format de l'ancien RFC restent parfaitement valdies), compatible avec celle de Java, et généraliste (on pourra indiquer autre chose que le fuseau horaire). Ce format étendu est baptisé IXDTF pour Internet Extended Date/Time Format. En revanche, le nouveau format ne gère pas des cas compliqués (la gestion du temps en informatique est toujours compliquée) comme les dates futures lorque la définition du fuseau horaire changera, par exemple en supprimant l'heure d'été, ou des échelles de temps différentes, comme TAI (le format IXDTF ne marche que pour l'échelle d'UTC).

Donc, concrètement, notre RFC commence par changer un peu la définition du décalage à la fin des estampilles. Dans le RFC 3339, il y avait trois cas subtilement différents pour une estampille indiquant l'absence de décalage :

  • Une lettre Z indiquait qu'on utilisait UTC comme référence,
  • Un +00:00 indiquait qu'on utilisait UTC comme référence (identique au cas précédent),
  • Un -00:00 indiquait qu'on n'avait aucune idée sur la référence (typiquement parce qu'on voudrait connaitre l'heure locale mais qu'on ne la connait pas).

(Au passage, si vous ne connaissiez pas ces trois cas et leurs différences, ne vous inquiétez pas, vous n'étiez pas seul·e.) Notre RFC change cela (section 2) en décidant que Z est désormais synonyme de -00:00 plutôt que de +00:00, un changement qui aura sans doute peu d'importance en pratique.

L'autre nouveauté de ce RFC 9557 est plus marquante, c'est le format étendu IXDTF (section 3). Il consiste à ajouter à la fin de l'estampille une série (facultative) de couples {clé, valeur}, entre crochets. Si la clé est absente, c'est que la valeur est un fuseau horaire, suivant la syntaxe de la base TZ. Voici un exemple :

2022-07-08T12:14:37+02:00[Europe/Paris][u-ca=hebrew]
  

Cet exemple indique que le fuseau horaire était celui de Paris (cf. le format de ces noms de fuseaux) et que le calendrier préféré (clé u-ca), pour afficher cette date, serait le calendrier hébreu (ce qui indiquera 9 Tammouz 5782, sauf erreur).

Un point d'exclamation avant la clé indiquerait que la clé doit être comprise par le lecteur, sinon, il faut qu'il ignore l'estampille temporelle (la plupart du temps, l'application peut ignorer les clés et leurs valeurs). Un trait bas indique une clé expérimentale, non officiellement enregistrée.

Car notre RFC crée aussi un registre des clés. Pour l'instant, il ne compte qu'une seule clé, u-ca, pour indiquer le calendrier préféré. Pour enregistrer une nouvelle clé, il faut une spécification écrite (cf. RFC 8126), mais il y a aussi des enregistrements temporaires, plus légers.

Et on termine par un petit mot sur la sécurité (section 7). Le RFC rappelle que plus on donne d'informations, plus on risque d'en donner trop. Ainsi, l'indication du calendrier préféré peut indiquer une origine ethnique ou religieuse, qui peut être considérée comme privée, surtout s'il y a des risques d'attaques racistes.


Téléchargez le RFC 9557


L'article seul

RFC 9547: Report from the IAB Workshop on Environmental Impact of Internet Applications and Systems, 2022

Date de publication du RFC : Février 2024
Auteur(s) du RFC : J. Arkko, C. S. Perkins, S. Krishnan
Pour information
Première rédaction de cet article le 24 avril 2024


La question de l'empreinte environnementale du numérique suscite beaucoup de débats. L'IAB avait organisé en décembre 2022 un atelier sur le cas de l'empreinte environnementale de l'Internet dont ce RFC est le compte-rendu (tardif, oui, je sais, mais mon propre article de résumé du RFC est aussi en retard).

Le sujet est très complexe, relativement nouveau, et surtout noyé sous beaucoup d'approximations, voire de franches bêtises (l'ADEME s'en est fait une spécialité, avec des chiffres tirés du chapeau et à la méthodologie inconnue). Il y a donc du travail sur la planche. L'IAB commence par estimer que l'Internet a certes une empreinte environnementale mais peut aussi servir à diminuer l'empreinte environnementale globale, ce qui n'est franchement pas étayé (le RFC cite l'exemple de réunions physiques remplacées par des réunions en ligne, sans citer de calcul détaillé qui permettrait de voir s'il y a vraiment un gain, et en oubliant que de toute façon une réunion en ligne ne rend pas les mêmes services). Mais l'IAB note aussi que l'Internet a des effets indirects, et pas forcément positifs : il cite l'exemple de l'augmentation de la consommation de biens matériels que produit le commerce en ligne.

Clairement, l'Internet n'est pas virtuel, contrairement à ce que prétend le marketing qui abuse de termes comme cloud pour faire croire que le numérique est immatériel. A contrario, l'Internet dépend de machines, de l'électricité (et des humains qui font fonctionner ces machines). Que peut-on faire pour diminuer l'empreinte environnementale de l'Internet ? (Sans pour autant suivre les conseils débiles de l'ADEME, comme de supprimer ses messages.)

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, plus exactement à cet endroit. (Tous les documents liés à cet atelier sont également disponibles.) Parmi les papiers acceptés :

La section 2 du RFC détaille les sujets qui étaient dans le programme de l'atelier :

  • Les impacts environnementaux directs de l'Internet (consommation électrique des machines, des routeurs aux serveurs en passant par les machines terminales, refroidissement, fabrication des machines, et leur traitement final, souvent oublié dans les études),
  • Les impacts indirects de l'Internet, provenant des effets qu'il a sur la société,
  • Les métriques (souvent très maltraitées dans les artcles parlant de l'empreinte environnementale du numérique, par exemple en confondant énergie et puissance), un sujet crucial puisqu'on ne peut pas améliorer ce qu'on ne peut pas mesurer,
  • Les questions non techniques, comme les enjeux financiers ou comme la régulation,
  • Les questions techniques où l'IETF pourrait travailler pour améliorer les choses (par exemple, mais non cité par le RFC, annoncer dans les réponses HTTP le coût environnemental de la requête),
  • Mais aussi les questions liées aux usages et aux utilisateurices, qui sont souvent sollicités, mais en général de manière culpabilisatrice (« regardez les vidéos en basse définition et pas de porno »).

Ah et, si vous vous le demandez, l'atelier a été entièrement en ligne (section 2.1 du RFC).

La première des quatre sessions de l'atelier essayait d'aborder le problème de manière générale. Le problème du réchauffement climatique est évidemment bien plus vaste que l'Internet seul et n'a pas de solution simple et unique. Et les solutions ne sont pas toutes techniques, donc il y a des limites à ce que l'IETF peut faire (ce qui ne veut pas dire qu'il ne faut rien faire !). Même la publicité est mentionnée dans cette section du RFC, avec un très prudent « davantage d'études sont nécessaires » (opinion personnelle : son attitude au sujet de la publicité est un bon moyen de savoir si votre interlocuteur veut sérieusement lutter contre le réchauffement climatique, ou bien s'il veut juste faire des discours).

Ensuite, deuxième session sur les mesures et la récolte des faits. Par exemple, où sont les gros postes de consommation électrique dans le numérique ? Les serveurs ? Les routeurs ? Les terminaux ? C'est d'autant plus important que le RFC note la quantité de fausses informations qui circulent (citant par exemple un article qui confondait MB/s et Mb/s, soit un facteur 8 de différence). De même, contrairement à ce qui est encore souvent dit, la session a mis en évidence le fait que la consommation électrique n'est pas du tout proportionnelle au trafic. Des phrases comme « envoyer un courrier dégage autant de dioxyde de carbone qu'un vol Paris-Quelquepart » n'ont donc aucun sens. (Un des papiers acceptés, « Towards a power-proportional Internet » expliquait pourquoi il fallait changer cela et comment le faire.) Par contre, les usages impactent la consommation car ils peuvent nécessiter des mises à jour du réseau.

La troisième session regardait du côté des pistes d'amélioration, plus précisement de celles sur lesquelles l'IETF pouvait agir. Le premier point est celui des mesures (insuffisantes et parfois contradictoires). Le deuxième point concernait l'influence de phénomènes comme la gigue (RFC 4689) ou l'élongation du trajet (RFC 7980) sur la consommation énergétique (si on réduit ces phénomènes grâce à de meilleurs protocoles, est-ce qu'on diminue la consommation ?). Parmi les autres optimisations possibles, le choix de meilleurs formats, plus optimisés (CBORRFC 8949 - est cité). Notez qu'un des articles acceptés pour l'atelier faisait le point sur toutes les activités de l'IETF liées à l'énergie, draft-eckert-ietf-and-energy-overview.

Et la quatrième et dernière session portait sur les étapes suivantes du travail ; en résumé, il y a du travail et, même si l'IETF ne peut pas tout, elle doit en prendre sa part. Il faut toujours garder en tête que le but n'est pas de réduire l'empreinte environnementale de l'Internet mais de réduire celle de l'ensemble de la société. Éteindre l'Internet diminuerait certainement son empreinte environnementale mais pourrait avoir des effets négatifs sur d'autres secteurs, comme les transports. Pour améliorer l'Internet sans le supprimer, plusieurs axes ont été mis en avant :

  • Mesurer, toujours mesurer, on manque d'informations,
  • Pouvoir diminuer la consommation quand il n'y a pas de travail en cours, voire hiberner, serait utile (comme dans beaucoup de cas, le problème est complexe : un routeur ne peut pas hiberner car il ne sait pas quand arrivera le prochain paquet, et il ne peut pas se réveiller instantanément),
  • Adopter de meilleurs formats de données. Comme le disait un des articles présentés, « CBOR est plus vert ».

Et les actions concrètes (section 2.4.3) ?

  • Faut-il imposer dans chaque RFC une section Environmental considerations comme il y a déjà une Security considerations obligatoire ? (La question s'était déjà posée pour une éventuelle Human rights considerations.) Pour l'instant, ce n'est pas prévu notamment parce que, dans l'état actuel des choses, la plupart des auteurs de RFC n'ont pas de connaissances suffisamment approfondies ur le sujet pour écrire une section utile.
  • Plusieurs groupes à l'IETF sont déjà au travail sur ce sujet environnemental : NMRG travaille sur les métriques (et a, par exemple, un Internet-Draft « Challenges and Opportunities in Management for Green Networking »), même chose à OPSAWG et le nouveau groupe TVR (Time-Variant Routing), comme il travaille sur le routage intermittent, a également un rôle, par exemple lorsqu'on coupe des liens pour économiser de l'énergie. Là, on est pile dans le rôle de l'IETF.
  • Curieusement, le RFC parle aussi d'éviter les NFT, qui ne sont pourtant plus guère à la mode (et n'ont jamais suscité beaucoup d'intérêt à l'IETF, de toute façon). En outre, la plupart d'entre eux tournent sur Ethereum, qui n'utilise plus la preuve de travail et n'est donc pas crucial du point de vue environnemental.

Si vous voulez participer au nouveau programme de l'IAB E-IMPACT, tout est là.

Puisqu'on parlait de la section sur la sécurité qui est obligatoire dans les RFC, notre RFC en a une, qui rappelle que :

  • Tout mécanisme par lequel on donne des pénalités (financières ou bien en terme de diminution des ressources allouées) en fonction de métriques d'empreinte environnementale doit se préparer à ce qu'il y ait des tricheurs (cf. P. McDaniel, « Sustainability is a Security Problem », à la conférence SIGSAC en 2022), qui faussent les mesures pour échapper à ces pénalités.
  • De même, tout mécanisme qui va agir sur le réseau, par exemple pour diminuer l'empreinte environnementale, peut être détourné pour une attaque par déni de service, et doit donc prévoir le problème.

Téléchargez le RFC 9547


L'article seul

RFC 9499: DNS Terminology

Date de publication du RFC : Mars 2024
Auteur(s) du RFC : P. Hoffman (ICANN), K. Fujiwara (JPRS)
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 3 mai 2024


Comme beaucoup de protocoles très utilisés sur l'Internet, le DNS est ancien. Très ancien (la première norme, le RFC 882, date de 1983). Les normes techniques vieillissent, avec l'expérience, on comprend mieux, on change les points de vue et donc, pour la plupart des protocoles, on se lance de temps en temps dans une révision de la norme. Mais le DNS est une exception : la norme actuelle reste fondée sur des textes de 1987, les RFC 1034 et RFC 1035. Ces documents ne sont plus à jour, modifiés qu'ils ont été par des dizaines d'autres RFC. Bref, aujourd'hui, pour comprendre le DNS, il faut s'apprêter à lire de nombreux documents. En attendant qu'un courageux et charismatique participant à l'IETF se lance dans la tâche herculéenne de faire un jeu de documents propre et à jour, ce RFC 9499, successeur du RFC 8499 (il y a peu de modifications), se limite à une ambition plus modeste : fixer la terminologie du DNS. Ce n'est pas un tutoriel : vous n'y apprendrez pas le DNS. C'est plutôt une encyclopédie.

En effet, chacun peut constater que les discussions portant sur le DNS sont difficiles : on manque de terminologie standard, et celle des RFC officielles ne suffit pas, loin de là. Souvent, le DNS a tellement changé que le RFC officiel est même trompeur : les mots ne veulent plus dire la même chose. D'autres protocoles ont connu des mises à jour de la norme. Cela a été le cas de SMTP, passé successivement du RFC 772 à l'actuel RFC 5321, en passant par plusieurs révisions successives. Ou de XMPP, qui a vu sa norme originale mise à jour dans le RFC 6120. Et bien sûr de HTTP, qui a connu plusieurs toilettages complets (cf. RFC 9110). Mais personne n'a encore osé faire pareil pour le DNS. Au moins, ce RFC 9499, comme son prédécesseur RFC 8499, traite l'un des problèmes les plus criants, celui du vocabulaire. Le RFC est évidemment en anglais, les traductions proposées dans cet article, et qui n'ont pas de valeur « officielle » sont de moi seul.

Notre RFC 9499 rassemble donc des définitions pour des termes qui étaient parfois précisément définis dans d'autres RFC (et il fournit alors un lien vers ce RFC original), mais aussi qui n'étaient définis qu'approximativement ou parfois qui n'étaient pas définis du tout (et ce RFC fournit alors cette définition). Du fait du flou de certains RFC anciens, et des changements qui ont eu lieu depuis, certaines définitions sont différentes de l'original. Le document a fait l'objet d'un consensus relatif auprès des experts DNS mais quelques termes restent délicats. Notez aussi que d'autres organisations définissent des termes liés au DNS par exemple le WHATWG a sa définition de ce qu'est un domaine, et le RSSAC a développé une terminologie.

Ironiquement, un des termes les plus difficiles à définir est « DNS » lui-même (section 1 de notre RFC). D'accord, c'est le sigle de Domain Name System mais ça veut dire quoi ? « DNS » peut désigner le schéma de nommage (les noms de domaine comme signal.eu.org, leur syntaxe, leurs contraintes), la base de données répartie (et faiblement cohérente) qui associe à ces noms des informations (comme des certificats, des adresses IP, etc), ou le protocole requête/réponse (utilisant le port 53) qui permet d'interroger cette base. Parfois, « DNS » désigne uniquement le protocole, parfois, c'est une combinaison des trois éléments indiqués plus haut (personnellement, quand j'utilise « DNS », cela désigne uniquement le protocole, un protocole relativement simple, fondé sur l'idée « une requête => une réponse »).

Bon, et ces définitions rigoureuses et qui vont mettre fin aux discussions, ça vient ? Chaque section du RFC correspond à une catégorie particulière. D'abord, en section 2, les noms eux-même, ces fameux noms de domaine. Un système de nommage (naming system) a plusieurs aspects, la syntaxe des noms, la gestion des noms, le type de données qu'on peut associer à un nom, etc. D'autres systèmes de nommage que celui présenté dans ce RFC existent, et sont distincts du DNS sur certains aspects. Pour notre système de nommage, le RFC définit :

  • Nom de domaine (domain name) : la définition est différente de celle du RFC 7719, qui avait simplement repris celle du RFC 1034, section 3.1. Elle est désormais plus abstraite, ce qui permet de l'utiliser pour d'autres systèmes de nommage. Un nom de domaine est désormais simplement une liste (ordonnée) de composants (labels). Aucune restriction n'est imposée dans ces composants, simplement formés d'octets (tant pis pour la légende comme quoi le DNS serait limité à ASCII). Comme on peut représenter les noms de domaine sous forme d'un arbre (la racine de l'arbre étant à la fin de la liste des composants) ou bien sous forme texte (www.madmoizelle.com), le vocabulaire s'en ressent. Par exemple, on va dire que com est « au-dessus de madmoizelle.com » (vision arborescente) ou bien « à la fin de www.madmoizelle.com » (vision texte). Notez aussi que la représentation des noms de domaine dans les paquets IP n'a rien à voir avec leur représentation texte (par exemple, les points n'apparaissent pas). Enfin, il faut rappeler que le vocabulaire « standard » n'est pas utilisé partout, même à l'IETF, et qu'on voit parfois « nom de domaine » utilisé dans un sens plus restrictif (par exemple uniquement pour parler des noms pouvant être résolus avec le DNS, pour lesquels il avait été proposé de parler de DNS names).
  • FQDN (Fully Qualified Domain Name, nom de domaine complet) : apparu dans le RFC 819, ce terme désigne un nom de domaine où tous les composants sont cités (par exemple, ldap.potamochère.fr. est un FQDN alors que ldap tout court ne l'est pas). En toute rigueur, un FQDN devrait toujours s'écrire avec un point à la fin (pour représenter la racine) mais ce n'est pas toujours le cas. (Notre RFC parle de « format de présentation » et de « format courant d'affichage » pour distinguer le cas où on met systématiquement le point à la fin et le cas où on l'oublie.)
  • Composant (label) : un nœud de l'arbre des noms de domaine, dans la chaîne qui compose un FQDN. Dans www.laquadrature.net, il y a trois composants, www, laquadrature et net.
  • Nom de machine (host name) : ce n'est pas la même chose qu'un nom de domaine. Utilisé dans de nombreux RFC (par exemple RFC 952) mais jamais défini, un nom de machine est un nom de domaine avec une syntaxe plus restrictive, définie dans la section 3.5 du RFC 1035 et amendée par la section 2.1 du RFC 1123 : uniquement des lettres, chiffres, points et le tiret. Ainsi, brienne.tarth.got.example peut être un nom de machine mais www.&#$%?.example ne peut pas l'être. Le terme de « nom de machine » est parfois aussi utilisé pour parler du premier composant d'un nom de domaine (brienne dans brienne.tarth.got.example).
  • TLD (Top Level Domain, domaine de premier niveau ou domaine de tête) : le dernier composant d'un nom de domaine, celui juste avant (ou juste en dessous) de la racine. Ainsi, fr ou name sont des TLD. N'utilisez surtout pas le terme erroné d'« extension ». Et ne dites pas que le TLD est le composant le plus à droite, ce n'est pas vrai dans l'alphabet arabe. La distinction courante entre gTLD, gérés par l'ICANN, et ccTLD, indépendants de l'ICANN, est purement politique et ne se reflète pas dans le DNS.
  • DNS mondial (Global DNS), nouveauté du RFC 8499, désigne l'ensemble des noms qui obéissent aux règles plus restrictives des RFC 1034 et RFC 1035 (limitation à 255 octets, par exemple). En outre, les noms dans ce « DNS mondial » sont rattachés à la racine officiellement gérée par l'ICANN, via le service Public Technical Identifiers (PTI). Une racine alternative, si elle sert un contenu différent de celui de PTI, n'est donc pas le « DNS mondial » mais ce que le RFC nomme « DNS privé » (private DNS). Évidemment, un système de nommage qui n'utilise pas le DNS du tout mais qui repose, par exemple, sur le pair-à-pair, ne doit pas être appelé DNS (« DNS pair-à-pair » est un oxymore, une contradiction dans les termes.)
  • IDN (Internationalized Domain Name, nom de domaine internationalisé) : un nom de domaine en Unicode, normalisé dans le RFC 5890, qui définit des termes comme U-label (le nom Unicode) et A-label (sa représentation en Punycode). Sur l'internationalisation des noms, vous pouvez aussi consulter le RFC de terminologie RFC 6365.
  • Sous-domaine (subdomain) : domaine situé sous un autre, dans l'arbre des noms de domaines. Sous forme texte, un domaine est sous-domaine d'un autre si cet autre est un suffixe. Ainsi, www.cl.cam.ac.uk est un sous-domaine de cl.cam.ac.uk, qui est un sous-domaine de cam.ac.uk et ainsi de suite, jusqu'à la racine, le seul domaine à n'être sous-domaine de personne. Quand le RFC parle de suffixe, il s'agit d'un suffixe de composants, pas de caractères : foo.example.net n'est pas un sous-domaine de oo.example.net.
  • Alias (alias) : attention, il y a un piège. Le DNS permet à un nom d'être un alias d'un autre, avec le type d'enregistrement CNAME (voir la définition suivante). L'alias est le terme de gauche de l'enregistrement CNAME. Ainsi, si on met dans un fichier de zone vader IN CNAME anakin, l'alias est vader (et c'est une erreur de dire que c'est « le CNAME »).
  • CNAME (Canonical Name, nom canonique, le « vrai » nom) : le membre droit dans l'enregistrement CNAME. Dans l'exemple de la définition précédente, anakin est le CNAME, le « nom canonique ».

Fini avec les noms, passons à l'en-tête des messages DNS et aux codes qu'il peut contenir. Cet en-tête est défini dans le RFC 1035, section 4.1. Il donne des noms aux champs mais pas forcément aux codes. Ainsi, le code de réponse 3 indiquant qu'un domaine demandé n'existe pas est juste décrit comme name error et n'a reçu son mnémonique de NXDOMAIN (No Such Domain) que plus tard. Notre RFC définit également, dans sa section 3 :

  • NODATA : un mnémonique pour une réponse où le nom de domaine demandé existe bien mais ne contient aucun enregistrement du type souhaité. Le code de retour est 0, NOERROR, et le nombre de réponses (ANCOUNT pour Answer Count) est nul.
  • Réponse négative (negative answer) : le terme recouvre deux choses, une réponse disant que le nom de domaine demandé n'existe pas (code de retour NXDOMAIN), ou bien une réponse indiquant que le serveur ne peut pas répondre (code de retour SERVFAIL ou REFUSED). Voir le RFC 2308.
  • Renvoi (referral) : le DNS étant décentralisé, il arrive qu'on pose une question à un serveur qui ne fait pas autorité pour le domaine demandé, mais qui sait vous renvoyer à un serveur plus proche. Ces renvois sont indiqués dans la section Authority d'une réponse.

Voici un renvoi depuis la racine vers .fr :


% dig @l.root-servers.net A blog.imirhil.fr 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16572
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 5, ADDITIONAL: 11
...
;; AUTHORITY SECTION:
fr.			172800 IN NS d.ext.nic.fr.
fr.			172800 IN NS d.nic.fr.
fr.			172800 IN NS e.ext.nic.fr.
fr.			172800 IN NS f.ext.nic.fr.
fr.			172800 IN NS g.ext.nic.fr.

    

La section 4 s'intéresse aux transactions DNS. Un des termes définis est celui de QNAME (Query NAME), nouveauté du RFC 8499. Il y a trois sens possibles (le premier étant de très loin le plus commun) :

  • Le sens original, le QNAME est la question posée (le nom de domaine demandé),
  • Le sens du RFC 2308, la question finale (qui n'est pas la question posée s'il y a des CNAME sur le trajet),
  • Un sens qui n'apparait pas dans les RFC mais est parfois présent dans les discussions, une question intermédiaire (dans une chaîne de CNAME).

Le RFC 2308 est clairement en tort ici. Il aurait dû utiliser un terme nouveau, pour le sens nouveau qu'il utilisait.

Passons maintenant aux enregistrements DNS, stockés dans cette base de données répartie (section 5 du RFC) :

  • RR (Resource Record) : un enregistrement DNS.
  • Enregistrements d'adresses (Address records) : enregistrements DNS A (adresses IPv4) et AAAA (adresses IPv6). Beaucoup de gens croient d'ailleurs que ce sont les seuls types d'enregistrements possibles (« le DNS sert à traduire les noms en adresses IP » est une des synthèses erronées du DNS les plus fréquentes).
  • Ensemble d'enregistrements (RRset pour Resource Record set) : un ensemble d'enregistrements ayant le même nom (la même clé d'accès à la base), la même classe, le même type et le même TTL. Cette notion avait été introduite par le RFC 2181. Notez que la définition originale parle malheureusement de label dans un sens incorrect. La terminologie du DNS est vraiment compliquée !
  • Fichier maître (master file) : un fichier texte contenant des ensembles d'enregistrement. Également appelé fichier de zone, car son utilisation la plus courante est pour décrire les enregistrements que chargera le serveur maître au démarrage. (Ce format peut aussi servir à un résolveur quand il écrit le contenu de sa mémoire sur disque.)
  • EDNS (Extension for DNS, également appelé EDNS0) : normalisé dans le RFC 6891, EDNS permet d'étendre l'en-tête du DNS, en spécifiant de nouvelles options, en faisant sauter l'antique limitation de taille de réponses à 512 octets, etc.
  • OPT (pour Option) : une astuce d'EDNS pour encoder les informations de l'en-tête étendu. C'est un enregistrement DNS un peu spécial, défini dans le RFC 6891, section 6.1.1.
  • Propriétaire (owner ou owner name) : le nom de domaine d'un enregistrement. Ce terme est très rarement utilisé, même par les experts.
  • Champs du SOA (SOA field names) : ces noms des enregistrements SOA (comme MNAME ou RNAME) sont peu connus et malheureusement peu utilisés (RFC 1035, section 3.3.13). Notez que la sémantique du champ MINIMUM a complètement changé avec le RFC 2308.
  • TTL (Time To Live) : la durée de vie maximale d'un enregistrement dans les caches des résolveurs. C'est un entier non signé (même si le RFC 1035 dit le contraire), en secondes.

Voici un ensemble d'enregistrements (RRset), comptant ici deux enregistrements :


rue89.com.		600 IN MX 50 mx2.typhon.net.
rue89.com.		600 IN MX 10 mx1.typhon.net.	       
	       
    

(Depuis, ça a changé.)

Et voici un pseudo-enregistrement OPT, tel qu'affiché par dig, avec une indication de la taille maximale et l'option client subnet (RFC 7871) :

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
; CLIENT-SUBNET: 13.176.144.0/24/0
    

Ensuite, un sujet chaud où le vocabulaire est particulièrement peu défini, et très mal utilisé (voir les forums grand public sur le DNS où les discussions prennent un temps fou car les gens utilisent mal les mots) : les différents types de serveurs et clients DNS (section 6). Pour commencer, il est crucial de se méfier quand un texte parle de « serveur DNS » tout court. Si le contexte ne permet pas de savoir de quel genre de serveur DNS on parle, cela indique un manque de compréhension du DNS par l'auteur du texte. Serveurs faisant autorité et serveurs résolveurs, quoique utilisant le même protocole, sont en effet très différents.

  • Résolveur (resolver) : un client DNS qui va produire une réponse finale (pas juste un renvoi, pas juste une information ponctuelle comme le fait dig). Il existe plusieurs types de résolveurs (voir ci-dessous) et, en pratique, quand on dit « résolveur » tout court, c'est en général un « résolveur complet ».
  • Résolveur minimum (stub resolver) : un résolveur qui ne sait pas suivre les renvois et qui dépend donc d'un ou de plusieurs résolveurs complets pour faire son travail. Ce type est défini dans la section 6.1.3.1 du RFC 1123. C'est ce résolveur minimum qu'appellent les applications lorsqu'elles font un getaddrinfo() ou getnameinfo(). Sur Unix, le résolveur minimum fait en général partie de la libc et trouve l'adresse du ou des résolveurs complets dans /etc/resolv.conf.
  • Résolveur complet (full resolver) : un résolveur qui sait suivre les renvois et donc fournir un service de résolution complet. Des logiciels comme Unbound ou PowerDNS Resolver assurent cette fonction. Le résolveur complet est en général situé chez le FAI ou dans le réseau local de l'organisation où on travaille, mais il peut aussi être sur la machine locale. On le nomme aussi « résolveur récursif ». Notez que « résolveur complet » fait partie de ces nombreux termes qui étaient utilisés sans jamais avoir été définis rigoureusement.
  • Resolveur complet avec mémoire (full-service resolver) : un résolveur complet, qui dispose en plus d'une mémoire (cache) des enregistrements DNS récoltés.
  • Serveur faisant autorité (authoritative server et traduire ce terme par « serveur autoritaire » montre une grande ignorance de l'anglais ; un adjudant est autoritaire, un serveur DNS fait autorité) : un serveur DNS qui connait une partie des données du DNS (il « fait autorité » pour une ou plusieurs zones) et peut donc y répondre (RFC 2182, section 2). Ainsi, au moment de l'écriture de cet article, f.root-servers.net fait autorité pour la racine, d.nic.fr fait autorité pour pm, etc. Des logiciels comme NSD ou Knot assurent cette fonction. Les serveurs faisant autorité sont gérés par divers acteurs, les registres, les hébergeurs DNS (qui sont souvent en même temps bureaux d'enregistrement), mais aussi parfois par M. Michu. La commande dig NS $ZONE vous donnera la liste des serveurs faisant autorité pour la zone $ZONE. Ou bien vous pouvez utiliser un service sur le Web en visitant https://dns.bortzmeyer.org/DOMAIN/NS où DOMAIN est le nom de domaine qui vous intéresse.
  • Serveur mixte : ce terme n'est pas dans ce RFC. Autrefois, il était courant que des serveurs DNS fassent à la fois résolveur et serveur faisant autorité. Cette pratique est fortement déconseillée depuis de nombreuses années (entre autres parce qu'elle complique sérieusement le débogage, mais aussi pour des raisons de sécurité parce qu'elle mène à du code plus complexe) et n'est donc pas dans ce RFC.
  • Initialisation (priming) : le processus par lequel un résolveur complet vérifie l'information sur les serveurs de la racine. Ce concept est décrit en détail dans le RFC 8109. Au démarrage, le résolveur ne sait rien. Pour pouvoir commencer la résolution de noms, il doit demander aux serveurs de la racine. Il a donc dans sa configuration leur liste. Mais ces configurations ne sont pas forcément mises à jour souvent. La liste peut donc être trop vieille. La première chose que fait un résolveur est donc d'envoyer une requête « NS . » à un des serveurs de sa liste. Ainsi, tant qu'au moins un des serveurs de la vieille liste répond, le résolveur est sûr d'apprendre la liste actuelle.
  • Indications de la racine (root hints) : la liste des noms et adresses des serveurs racine, utilisée pour l'initialisation. L'administrateur d'un résolveur utilisant une racine alternative changera cette liste.
  • Mémorisation des négations (negative caching, ou « cache négatif ») : mémoriser le fait qu'il n'y a pas eu de réponse, ou bien une réponse disant qu'un nom de domaine n'existe pas.
  • Serveur primaire (primary server mais on dit aussi serveur maître, master server) : un serveur faisant autorité qui a accès à la source des données (fichier de zone, base de données, etc). Attention, il peut y avoir plusieurs serveurs primaires (autrefois, ce n'était pas clair et beaucoup de gens croient qu'il y a un serveur primaire, et qu'il est indiqué dans l'enregistrement SOA). Attention bis, le terme ne s'applique qu'à des serveurs faisant autorité, l'utiliser pour les résolveurs (« on met en premier dans /etc/resolv.conf le serveur primaire ») n'a pas de sens.
  • Serveur secondaire (secondary server mais on dit aussi « serveur esclave », slave server) : un serveur faisant autorité qui n'est pas la source des données, qui les a prises d'un serveur primaire (dit aussi serveur maître), via un transfert de zone (RFC 5936).
  • Serveur furtif (stealth server) : un serveur faisant autorité mais qui n'apparait pas dans l'ensemble des enregistrements NS. (Définition du RFC 1996, section 2.1.)
  • Maître caché (hidden master) : un serveur primaire qui n'est pas annoncé publiquement (et n'est donc accessible qu'aux secondaires). C'est notamment utile avec DNSSEC : s'il signe, et donc a une copie de la clé privée, il vaut mieux qu'il ne soit pas accessible de tout l'Internet (RFC 6781, section 3.4.3).
  • Transmission (forwarding) : le fait, pour un résolveur, de faire suivre les requêtes à un autre résolveur (probablement mieux connecté et ayant un cache partagé plus grand). On distingue parfois (mais ce n'est pas forcément clair, même dans le RFC 5625) la transmission, où on émet une nouvelle requête, du simple relayage de requêtes sans modification.
  • Transmetteur (forwarder) : le terme est parfois utilisé confusément. Il désigne tantôt la machine qui transmet une requête et tantôt celle vers laquelle on transmet (c'est dans ce sens qu'il est utilisé dans la configuration de BIND, avec la directive forwarders). La définition de notre RFC est le premier sens.
  • Résolveur politique (policy-implementing resolver) : un résolveur qui modifie les réponses reçues, selon sa politique. On dit aussi, moins diplomatiquement, un « résolveur menteur ». C'est ce que permet, par exemple, le système RPZ. Sur l'utilisation de ces « résolveurs politiques » pour mettre en œuvre la censure, voir entre autres mon article aux RIPE Labs. Notez que le résolveur politique a pu être choisi librement par l'utilisateur (par exemple comme élément d'une solution de blocage des publicités) ou bien qu'il lui a été imposé.
  • Résolveur ouvert (open resolver) : un résolveur qui accepte des requêtes DNS depuis tout l'Internet. C'est une mauvaise pratique (cf. RFC 5358) et la plupart de ces résolveurs ouverts sont des erreurs de configuration. Quand ils sont délibérement ouverts, comme Google Public DNS ou Quad9, on parle plutôt de résolveurs publics.
  • Collecte DNS passive (passive DNS) : désigne les systèmes qui écoutent le trafic DNS, et stockent tout ou partie des informations échangées. Le cas le plus courant est celui où le système de collecte ne garde que les réponses (ignorant donc les adresses IP des clients et serveurs), afin de constituer une base historique du contenu du DNS (c'est ce que font DNSDB ou le système de PassiveDNS.cn).
  • Serveur protégeant la vie privée (privacy-enabled server) : ce terme désigne un serveur, typiquement un résolveur, qui permet les requêtes DNS chiffrées, avec DNS-sur-TLS (RFC 7858) ou avec DoH (RFC 8484).
  • Anycast : le fait d'avoir un service en plusieurs sites physiques, chacun annonçant la même adresse IP de service (RFC 4786). Cela résiste mieux à la charge, et permet davantage de robustesse en cas d'attaque par déni de service. Les serveurs de la racine, ceux des « grands » TLD, et ceux des importants hébergeurs DNS sont ainsi « anycastés ». Chaque machine répondant à l'adresse IP de service est appelée une instance.
  • DNS divisé (split DNS) : le fait de donner des réponses différentes selon que le client est interne à une organisation ou externe. Le but est, par exemple, de faire en sorte que www.organisation.example aille sur le site public quand on vient de l'Internet mais sur un site interne de la boîte quand on est sur le réseau local des employés.

Voici, vu par tcpdump, un exemple d'initialisation d'un résolveur BIND utilisant la racineYeti (RFC 8483) :

15:07:36.736031 IP6 2a01:e35:8bd9:8bb0:21e:8cff:fe76:29b6.35721 > 2001:6d0:6d06::53.53: \
       21476% [1au] NS? . (28)
15:07:36.801982 IP6 2001:6d0:6d06::53.53 > 2a01:e35:8bd9:8bb0:21e:8cff:fe76:29b6.35721: \
       21476*- 16/0/1 NS yeti-ns.tisf.net., NS yeti-ns.lab.nic.cl., NS yeti-ns.wide.ad.jp., NS yeti.ipv6.ernet.in., NS yeti-ns.as59715.net., NS ns-yeti.bondis.org., NS yeti-dns01.dnsworkshop.org., NS dahu2.yeti.eu.org., NS dahu1.yeti.eu.org., NS yeti-ns.switch.ch., NS bii.dns-lab.net., NS yeti.bofh.priv.at., NS yeti-ns.conit.co., NS yeti.aquaray.com., NS yeti-ns.ix.ru., RRSIG (619)
    

La question était « NS . » (quels sont les serveurs de la racine) et la réponse contenait les noms des seize serveurs racine qu'avait Yeti à l'époque.

Voici aussi des exemples de résultats avec un résolveur ou bien avec un serveur faisant autorité. Si je demande à un serveur faisant autorité (ici, un serveur racine), avec mon client DNS qui, par défaut, demande un service récursif (flag RD, Recursion Desired) :


% dig @2001:620:0:ff::29 AAAA www.iab.org 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54197
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 9, ADDITIONAL: 13
;; WARNING: recursion requested but not available
...
;; AUTHORITY SECTION:
org.			172800 IN NS b0.org.afilias-nst.org.	       
...
	       
    

C'est pour cela que dig affiche WARNING: recursion requested but not available. Notez aussi que le serveur, ne faisant autorité que pour la racine, n'a pas donné la réponse mais juste un renvoi aux serveurs d'Afilias. Maintenant, interrogeons un serveur récursif (le service de résolveur public Yandex DNS) :


% dig @2a02:6b8::feed:0ff AAAA www.iab.org           
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63304
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
...
;; ANSWER SECTION:
www.iab.org.		1800 IN	AAAA 2001:1900:3001:11::2c
	       
    

Cette fois, j'ai obtenu une réponse, et avec le flag RA, Recursion Available. Si je pose une question sans le flag RD (Recursion Desired, avec l'option +norecurse de dig) :


% dig +norecurse @2a02:6b8::feed:0ff AAAA www.gq.com  
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59438
;; flags: qr ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
...
;; ANSWER SECTION:
www.gq.com.		293 IN CNAME condenast.map.fastly.net.
	       
    

J'ai obtenu ici une réponse car l'information était déjà dans le cache (la mémoire) de Yandex DNS (on le voit au TTL, qui n'est pas un chiffre rond, il a été décrémenté du temps passé dans le cache). Si l'information n'est pas dans le cache :

    
% dig +norecurse @2a02:6b8::feed:0ff AAAA blog.keltia.net
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19893
;; flags: qr ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
...
	       
    

Je n'obtiens alors pas de réponse (ANSWER: 0, donc NODATA). Si je demande au serveur faisant autorité pour cette zone :


% dig +norecurse @2a01:e0d:1:3:58bf:fa61:0:1 AAAA blog.keltia.net  
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62908
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 6, ADDITIONAL: 15
...
;; ANSWER SECTION:
blog.keltia.net.	86400 IN AAAA 2a01:240:fe5c:1::2
...
	       
    

J'ai évidemment une réponse et, comme il s'agit d'un serveur faisant autorité, elle porte le flag AA (Authoritative Answer, qu'un résolveur ne mettrait pas). Notez aussi le TTL qui est un chiffre rond (et qui ne change pas si on rejoue la commande).

Passons maintenant à un concept relativement peu connu, celui de zones, et le vocabulaire associé (section 7) :

  • Zone : un groupe de domaines contigus dans l'arbre des noms, et gérés ensemble, par le même ensemble de serveurs de noms (ma définition, celle du RFC étant très abstraite). Beaucoup de gens croient que tout domaine est une zone, mais c'est faux. Ainsi, au moment de la publication de ce RFC, gouv.fr n'est pas une zone séparée, il est dans la même zone que fr (cela se teste facilement : gouv.fr n'a pas d'enregistrement NS ou de SOA).
  • Parent : le domaine « du dessus ». Ainsi, le parent de wikipedia.org est org, le parent de .org est la racine.
  • Apex : le sommet d'une zone, là où on trouve les enregistrements NS et SOA. Si la zone ne comprend qu'un domaine, l'apex est ce domaine. Si la zone est plus complexe, l'apex est le domaine le plus court. (On voit parfois des gens utiliser le terme erroné de racine pour parler de l'apex.)
  • Coupure de zone (zone cut) : l'endroit où on passe d'une zone à l'autre. Au-dessus de la coupure, la zone parente, en dessous, la zone fille.
  • Délégation (delegation) : un concept évidemment central dans le DNS, qui est un système décentralisé. En ajoutant un ensemble d'enregistrements NS pointant vers les serveurs de la zone fille, une zone parente délègue une partie de l'arbre des noms de domaine à une autre entité. L'endroit où se fait la délégation est donc une coupure de zone.
  • Colle (glue records) : lorsqu'une zone est déléguée à des serveurs dont le nom est dans la zone fille, la résolution DNS se heurte à un problème d'œuf et de poule. Pour trouver l'adresse de ns1.mazone.example, le résolveur doit passer par les serveurs de mazone.example, qui est déléguée à ns1.mazone.example et ainsi de suite... On rompt ce cercle vicieux en ajoutant, dans la zone parente, des données qui ne font pas autorité sur les adresses de ces serveurs (RFC 1034, section 4.2.1). Il faut donc bien veiller à les garder synchrones avec la zone fille. (Tanguy Ortolo me suggère d'utiliser « enregistrement de raccord » plutôt que « colle ». Cela décrit bien leur rôle, en effet.)
  • Délégation boiteuse (lame delegation) : un ou plusieurs des serveurs à qui la zone est déléguée ne sont pas configurés pour servir cette zone. La délégation peut avoir été boiteuse depuis le début (parce que le titulaire a indiqué des noms un peu au hasard) ou bien l'être devenue par la suite. C'est certainement une des erreurs techniques les plus courantes. Mais le RFC note que l'usage du terme a dérivé et qu'aujourd'hui, il est devenu plus flou, désignant hélas des erreurs très variées.
  • Dans le bailliage (in bailiwick) : terme absent des textes DNS originaux et qui peut désigner plusieurs choses. (La définition du RFC 8499, embrouillée, a été heureusement remplacée.) « Dans le bailliage » est (très rarement, selon mon expérience) parfois utilisé pour parler d'un serveur de noms dont le nom est dans la zone servie (et qui nécessite donc de la colle, voir la définition plus haut), mais le sens le plus courant désigne des données pour lesquelles le serveur qui a répondu fait autorité, soit pour la zone, soit pour un ancêtre de cette zone. L'idée est qu'il est normal dans la réponse d'un serveur de trouver des données situées dans le bailliage et, par contre, que les données hors-bailliage sont suspectes (elles peuvent être là suite à une tentative d'empoisonnement DNS). Un résolveur DNS prudent ignorera donc les données hors-bailliage.
  • ENT (Empty Non-Terminal pour nœud non-feuille mais vide) : un domaine qui n'a pas d'enregistrements mais a des sous-domaines. C'est fréquent, par exemple, sous ip6.arpa ou sous les domaines très longs de certains CDN. Cela se trouve aussi avec les enregistrements de service : dans _sip._tcp.example.com, _tcp.example.com est probablement un ENT. La réponse correcte à une requête DNS pour un ENT est NODATA (code de réponse NOERROR, liste des répoonses vide) mais certains serveurs bogués, par exemple, à une époque, ceux d'Akamai, répondaient NXDOMAIN.
  • Zone de délégation (delegation-centric zone) : zone composée essentiellement de délégations vers d'autres zones. C'est typiquement le cas des TLD et autres suffixes publics. Il est amusant de noter que les RFC 4956 et RFC 5155 utilisaient ce terme sans le définir.
  • Changement rapide (fast flux) : une technique notamment utilisée par les botnets pour mettre leur centre de commande à l'abri des filtrages ou destructions. Elle consiste à avoir des enregistrements d'adresses IP avec des TTL très courts et à en changer fréquemment.
  • DNS inverse (reverse DNS) : terme qui désigne en général les requêtes pour des enregistrements de type PTR, permettant de trouver le nom d'une machine à partir de son adresse IP. À ne pas confondre avec les vraies requêtes inverses, qui avaient été normalisées dans le RFC 1035, avec le code IQUERY, mais qui, jamais vraiment utilisées, ont été abandonnées dans le RFC 3425.

Voyons ici la colle retournée par un serveur faisant autorité (en l'occurrence un serveur de .net) :


% dig @a.gtld-servers.net AAAA labs.ripe.net 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18272
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 9
...
;; AUTHORITY SECTION:
ripe.net.		172800 IN NS ns3.nic.fr.
ripe.net.		172800 IN NS sec1.apnic.net.
ripe.net.		172800 IN NS sec3.apnic.net.
ripe.net.		172800 IN NS tinnie.arin.net.
ripe.net.		172800 IN NS sns-pb.isc.org.
ripe.net.		172800 IN NS pri.authdns.ripe.net.
...
;; ADDITIONAL SECTION:
sec1.apnic.net.		172800 IN AAAA 2001:dc0:2001:a:4608::59
sec1.apnic.net.		172800 IN A 202.12.29.59
sec3.apnic.net.		172800 IN AAAA 2001:dc0:1:0:4777::140
sec3.apnic.net.		172800 IN A 202.12.28.140
tinnie.arin.net.	172800 IN A 199.212.0.53
tinnie.arin.net.	172800 IN AAAA 2001:500:13::c7d4:35
pri.authdns.ripe.net.	172800 IN A 193.0.9.5
pri.authdns.ripe.net.	172800 IN AAAA 2001:67c:e0::5
	     
    

On notera :

  • La section ANSWER est vide, c'est un renvoi.
  • Le serveur indique la colle pour pri.authdns.ripe.net : ce serveur étant dans la zone qu'il sert, sans son adresse IP, on ne pourrait jamais le joindre.
  • Le serveur envoie également les adresses IP d'autres machines comme sec1.apnic.net. Ce n'est pas strictement indispensable (on pourrait l'obtenir par une nouvelle requête), juste une optimisation.
  • Les adresses de ns3.nic.fr et sns-pb.isc.org ne sont pas renvoyées. Le serveur ne les connait probablement pas et, de toute façon, elles seraient hors-bailliage, donc ignorées par un résolveur prudent.

Voyons maintenant, un ENT, gouv.fr (notez que, depuis, ce domaine n'est plus un ENT) :

   
% dig @d.nic.fr ANY gouv.fr 
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42219
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1

    

Le serveur fait bien autorité pour ce domaine (flag AA dans la réponse), le domaine existe (autrement, le status aurait été NXDOMAIN, pas NOERROR) mais il n'y a aucun enregistrement (ANSWER: 0).

Et, ici, une délégation boiteuse, pour .ni :

% check-soa ni   
dns.nic.cr.
	2001:13c7:7004:1::d100: ERROR: SERVFAIL
	200.107.82.100: ERROR: SERVFAIL
ns.ideay.net.ni.
	186.1.31.8: OK: 2013093010
ns.ni.
	165.98.1.2: ERROR: read udp 10.10.86.133:59569->165.98.1.2:53: i/o timeout
ns.uu.net.
	137.39.1.3: OK: 2013093010
ns2.ni.
	200.9.187.2: ERROR: read udp 10.10.86.133:52393->200.9.187.2:53: i/o timeout
    

Le serveur dns.nic.cr est déclaré comme faisant autorité pour .ni mais il ne le sait pas, et répond donc SERVFAIL.

Les jokers ont une section à eux, la section 8 du RFC. S'appuyant sur le RFC 4592, elle définit, entre autres :

  • Joker (wildcard) : une source de confusion considérable depuis les débuts du DNS. Si on pouvait refaire le DNS en partant de zéro, ces jokers seraient la première chose à supprimer. Pour les résumer, le nom * dans une zone déclenche la synthèse automatique de réponses pour les noms qui n'existent pas dans la zone. Si la zone foo.example contient bar.foo.example et *.foo.example, une requête pour thing.foo.example renverra le contenu de l'enregistrement avec le joker, une requête pour bar.foo.example donnera les données de bar.foo.example. Attention, l'astérisque n'a son rôle particulier que s'il est le composant le plus spécifique (le premier). Dans foo.*.bar.example, il n'y a pas de joker.
  • Ancêtre le plus proche (closest encloser) : c'est le plus long ancêtre existant d'un nom. Si foo.bar.baz.example n'existe pas, que bar.baz.example n'existe pas non plus, mais que baz.example existe, alors baz.example est l'ancêtre le plus proche de foo.bar.baz.example. Ce concept est nécessaire pour le RFC 5155.

Allez courage, ne faiblissons pas, il reste encore la question de l'enregistrement des noms de domaine (section 9) :

  • Registre (registry) : l'organisation ou la personne qui gère les délégations d'une zone. Le terme est parfois employé uniquement pour les gérants de grandes zones de délégation, mais ce n'est pas obligatoire. Je suis à moi tout seul le registre de bortzmeyer.org 😁. C'est le registre qui décide de la politique d'enregistrement, qui peut être très variable selon les zones (sauf dans celles contrôlées par l'ICANN, où une certaine uniformité est imposée). Mes lecteurs français noteront que, comme le terme « registre » est court et largement utilisé, le gouvernement a inventé un nouveau mot, plus long et jamais vu auparavant, « office d'enregistrement ».
  • Titulaire (registrant, parfois holder) : la personne ou l'organisation qui a enregistré un nom de domaine.
  • Bureau d'enregistrement (registrar) : dans le modèle RRR (Registry-Registrar-Registrant, mais ce modèle n'est pas obligatoire et pas universel), c'est un intermédiaire entre le titulaire et le registre.
  • Hébergeur DNS (DNS operator) : la personne ou l'organisation qui gère les serveurs DNS. Cela peut être le titulaire, son bureau d'enregistrement, ou encore un acteur spécialisé dans cette gestion.
  • Suffixe public (public suffix) : ce terme pas très officiel est parfois utilisé pour désigner un suffixe de noms de domaine qui est contrôlé par un registre public (au sens où il accepte des enregistrements du public). Mais le terme est trompeur car, par exemple, .aquarelle se trouve dans la Public Suffix List alors qu'il s'agit d'un « .marque », un de ces TLD où une seule entreprise peut enregistrer des noms. Le terme est ancien mais est apparu pour la première fois dans un RFC avec le RFC 6265, section 5.3. com, co.uk et eu.org sont des suffixes publics. Rien dans la syntaxe du nom n'indique qu'un nom de domaine est un suffixe public, puisque ce statut ne dépend que d'une politique d'enregistrement (qui peut changer). Il est parfaitement possible qu'un domaine, et un de ses enfants, soient tous les deux un suffixe public (c'est le cas de .org et eu.org).
  • EPP (Extensible Provisioning Protocol) : normalisé dans le RFC 5730, c'est le protocole standard entre bureau d'enregistrement et registre. Ce protocole n'a pas de lien avec le DNS, et tous les registres ne l'utilisent pas.
  • Whois (nommé d'après la question Who Is?) : un protocole réseau, sans lien avec le DNS, normalisé dans le RFC 3912. Il permet d'interroger les bases de données du registre pour trouver les informations dites « sociales », informations qui ne sont pas dans le DNS (comme le nom du titulaire, et des moyens de le contacter). Les termes de « base Whois » ou de « données Whois » sont parfois utilisés mais ils sont erronés puisque les mêmes bases peuvent être interrogées par d'autres protocoles que Whois, comme RDAP (voir définition suivante).
  • RDAP (Registration Data Access Protocol) : un protocole concurrent de Whois, mais plus moderne. RDAP est décrit notamment dans les RFC 9082 et RFC 9083.

Prenons par exemple le domaine eff.org. Au moment de la publication du RFC :

Enfin, pour terminer, les sections 10 et 11 de notre RFC couvrent DNSSEC. Pas grand'chose de nouveau ici, DNSSEC étant plus récent et donc mieux défini.

L'annexe A de notre RFC indique quelles définitions existaient dans de précédents RFC mais ont été mises à jour par le nôtre. (C'est rare, puisque le but de ce RFC de terminologie est de rassembler les définitions, pas de les changer.) Par exemple, la définition de QNAME du RFC 2308 est corrigée ici.

L'annexe B liste les termes dont la première définition formelle se trouve dans ce RFC (ou dans un de ses prédécesseurs, les RFC 7719 et "RFC 8499). Cette liste est bien plus longue que celle de l'annexe A, vu le nombre de termes courants qui n'avaient jamais eu l'honneur d'une définition stricte.

Notre RFC ne contient pas une liste exhaustive des changements depuis son prédécesseur, le RFC 8499, mais ils sont peu importants. Parmi les changements sérieux :

  • DoT (RFC 7858), DoH (RFC 8484) et DoQ (RFC 9250) ont maintenant une définition complète.
  • Par contraste, le DNS traditionnel (Classic DNS), celui qui tourne directement sur UDP ou TCP, et en clair, a sa définition.
  • L'importance de TLS se traduit aussi par l'arrivée des définitions de DoT vers le résolveur (RDoT, pour Recursive DNS over TLS), de DoT vers le serveur faisant autorité (ADoT pour Authoritative DNS over TLS) et XoT (zone transfer over TLS, normalisé dans le RFC 9103).
  • Le RFC prend également acte du fait que le terme désignant les délégations invalides, lame delegation, a beaucoup dérivé.

Téléchargez le RFC 9499


L'article seul

RFC 9490: Report from the IAB Workshop on Management Techniques in Encrypted Networks (M-TEN)

Date de publication du RFC : Janvier 2024
Auteur(s) du RFC : M. Knodel, W. Hardaker, T. Pauly
Pour information
Première rédaction de cet article le 9 mai 2024


Aujourd'hui, l'essentiel du trafic sur l'Internet est chiffré, et pour d'excellentes raisons. Pas question de revenir là-dessus, mais, ceci dit, il va falloir adapter certaines pratiques de gestion des réseaux. L'IAB a organisé en 2022 un atelier sur ce sujet, dont ce RFC est le compte-rendu.

Comme les autres ateliers de l'IAB, il s'agit de faire s'exprimer diverses personnes, pas forcément d'arriver à une position commune (surtout sur un sujet… sensible). Tenu entièrement en ligne, cet atelier commençait par la soumission d'articles, qui devaient être lus d'abord, et discutés lors de l'atelier. La liste des articles figure dans l'annexe A du RFC, et les articles sont disponibles en ligne.

D'abord, notre RFC réaffirme que la cryptographie est absolument nécessaire à la protection de la vie privée. Les difficultés réelles qu'elle peut poser ne doivent jamais être un prétexte pour réduire ou affaiblir le chiffrement. Qu'il y ait une tension entre l'impératif du chiffrement et certaines méthodes de gestion du réseau, OK, mais la priorité reste la lutte contre la surveillance (RFC 7258).

Ensuite (section 1), le RFC pose le paysage : le trafic étant largement chiffré, des méthodes traditionnelles de gestion du réseau ne fonctionnent plus. tcpdump ne montre plus les données, on ne peut donc pas distinguer différentes méthodes HTTP, par exemple. Avec QUIC (RFC 9000), c'est même une partie de la couche transport qui est chiffrée donc un observateur extérieur ne peut plus, par exemple, évaluer le RTT d'une session qu'il observe (ce qui était possible avec TCP). Il va donc falloir s'adapter notamment en coopérant davantage avec les applications qui, elles, ont accès à tout. Pour l'instant, on a vu surtout passer des récriminations d'acteurs habitués à surveiller le trafic et qui se plaignent que le chiffrement les en empêchent (le RFC 8404 est un bon exemple de ces récriminations). Au contraire, il faut chercher à résoudre une contradiction : permettre aux réseaux d'appliquer leur politique sans céder d'un millimètre sur le principe du chiffrement.

Outre le cas des opérateurs réseau qui veulent examiner le trafic, à des fins louables (améliorer le réseau) ou critiquables (défavoriser certains usages), on peut aussi citer, parmi les intermédiaires qui voudraient observer et/ou interférer avec le trafic réseau, les réseaux d'entreprise qui veulent, par exemple, empêcher les employés d'accéder à certains services, ou bien les mécanismes de contrôle des enfants (appelés à tort « contrôle parental », alors que leur but est justement de remplacer les parents).

Trois thèmes importants étaient discutés à l'atelier : la situation actuelle, les futures techniques et la façon dont on pourrait arriver à déployer ces futures techniques.

Pour la situation actuelle, on sait que, depuis longtemps, les administrateurices réseau comptent sur de l'observation passive, par exemple pour classer le trafic (tant de HTTP, tant de SSH, etc). C'est à la base de techniques comme IPFIX (RFC 7011), qui permet de produire de beaux camemberts. Outre la production de rapports, cette observation passive peut (mais n'est pas forcément) être utilisée pour prévoir les évolutions futures, prioriser certains types de trafic, détecter des comportements malveillants, etc. Les protocoles Internet étaient en effet traditionnellement trop bavards, faisant fuiter des informations vers des observateurs passifs (cf. le concept de « vue depuis le réseau », RFC 8546).

La lutte de l'épée et de la cuirasse étant éternelle, il y a évidemment eu des travaux sur des mécanismes pour empêcher ce genre d'analyses comme l'article soumis pour l'atelier « WAN Traffic Obfuscation at Line Rate ». (Au passage, sur cette idée d'obfuscation, je recommande le livre de Brunton et Nissenbaum.) Le RFC mentionne aussi une discussion sur l'idée d'exiger une permission explicite des utilisateurs pour les analyses du trafic (je ne vous dis pas les difficultés pratiques…). Voir l'Internet-Draft draft-irtf-pearg-safe-internet-measurement.

Dans un monde idéal, le réseau et les applications coopéreraient (et, dans un monde idéal, licornes et bisounours s'embrasseraient tous les jours) mais on voit plutôt une lutte, le réseau essayant d'en savoir plus, les applications de préserver leur intimité. Pourtant, le RFC note qu'une coopération pourrait être dans leur intérêt réciproque. Bien sûr, des applications comme Tor refuseraient certainement toute coopération puisque leur but est de laisser fuiter le moins d'information possible, mais d'autres applications pourraient être tentées, par exemple en échange d'informations du réseau sur la capacité disponible. Après tout, certaines techniques sont justement conçues pour cela, comme ECN (RFC 3168).

OK, maintenant, quelles sont les techniques et méthodes pour résoudre le problème de la gestion des réseaux chiffrés (section 2.2) ? Le RFC exprime bien le fait que le but du chiffrement est d'empêcher tout tiers d'accéder aux informations. Donc, sauf faille de sécurité, par exemple suite à une faiblesse du chiffrement, tout accès à l'information impose la coopération d'une des deux parties qui communiquent. Cette question du consentement est cruciale. Si on n'a pas le consentement d'une des deux extrémités de la communication, on n'a pas le droit d'accéder aux données, point. Cf. la contribution « What’s In It For Me? Revisiting the reasons people collaborate ». Comme le répète souvent Eric Rescorla « Sur l'Internet, tout ce qui n'est pas une des extrémités est un ennemi. » (Cela inclut donc tous les équipements réseaux et les organisations qui les contrôlent.) Bref, les utilisateurs doivent pouvoir donner un consentement éclairé, et juger si les bénéfices de la visibilité l'emportent sur les risques. Évidemment, ce principe correct va poser de sérieuses difficultés d'application, car il n'est pas évident d'analyser proprement les bénéfices, et les risques (songez aux bandeaux cookies ou aux permissions des application sur votre ordiphone). Développer des nouveaux mécanismes de communication avec l'utilisateurice sont nécessaires, sinon, comme le note le RFC, « les ingénieurs devront choisir pour les utilisateurs ». Le RFC estime que les utilisateurs donneront toujours la priorité à leur vie privée (notamment parce qu'ils ne comprennent pas l'administration de réseaux et ses exigences), mais cela ne me semble pas si évident que cela. Personnellement, il me semble que le choix par défaut est crucial, car peu d'utilisateurices le modifieront.

Une des techniques qui permettent d'avoir accès à de l'information sans avoir toute l'information est celle des relais (cf. « Relying on Relays: The future of secure communication ». Le principe est de séparer les fonctions : l'utilisateur parle à un relais qui parle au serveur final. Le relais ne connait pas le contenu de la demande, le serveur ne connait pas le demandeur. C'est utilisé dans des techniques comme Oblivious HTTP (RFC 9458) ou Oblivious DNS (RFC 9230). La préservation de la vie privée est donc bien meilleure qu'avec, par exemple, un VPN, où l'opérateur du VPN voit tout, le demandeur et la demande (contrairement à ce que prétendent les publicités pour NordVPN que de nombreux youtubeurs transmettent avec leurs vidéos). Le relais permet donc un accès à une information limitée, ce qui permet d'assurer certaines fonctions (comme le filtrage de contenu malveillant) sans avoir un accès complet.

Un exemple souvent cité par les opérateurs de l'intérêt d'accéder à la communication et de la modifier est celui de l'optimisation des flux TCP. Des PEP (Performance Enhancing Proxies) violant le modèle en couches (car, normalement, TCP est de bout en bout) sont souvent déployés, notamment sur les liaisons satellites, dont les performances sont plus mauvaises, et les caractéristiques techniques très spéciales. (Cf. l'exposé de Nicolas Kuhn, « QUIC for satellite communications » à la Journée du Conseil Scientifique de l'Afnic en 2021.) Le PEP va modifier les en-têtes TCP, voire parfois boucler la connexion TCP et en faire une autre lui-même. Cette technique ne marche évidemment plus avec QUIC, qui chiffre même la couche transport. Et elle mène à l'ossification de l'Internet puisqu'elle rend plus difficile de faire évoluer TCP, car toute évolution risque de perturber les PEP. QUIC avait en partie été explicitement développé pour empêcher ces intermédiaires de bricoler la session. Une autre approche est celle proposée dans « The Sidecar: "Opting in" to PEP Functions ».

Bon, maintenant, comment arriver à déployer de meilleures méthodes ? Dans un environnement fermé ou semi-fermé, cela doit être possible de faire en sorte que, par exemple, toutes les machines mettent en œuvre telle fonction (cf. RFC 8520 pour un exemple). Mais cela ne marche clairement pas pour l'Internet.

Parmi les moyens proposés de résolution de la contradiction entre visibilité par le réseau et protection de la vie privée, le RFC mentionne les Zero-Knowledge Middleboxes. Décrites dans l'article du même nom, cette méthode utilise les preuves à divulgation nulle de connaissance pour prouver à l'intermédiaire qui fait le filtrage qu'on a bien respecté sa politique de filtrage, sans lui dire ce qu'on a fait. L'article détaille par exemple comment cela peut s'appliquer au DNS, qui est le principal outil de censure de l'Internet dans l'Union européenne. Ces preuves à divulgation nulle de connaissance ayant toujours été mystérieuses pour moi, je ne vous expliquerai pas comment elles marchent, mais notez que les auteurs ont fait un article pédagogique.

Enfin, le RFC mentionne la proposition Red Rover, qui propose encore un arrangement bisounours où les utilisateurs et les opérateurs collaboreraient pour un filtrage géré en commun. Les auteurs disent que ça marcherait car les utilisateurs « ne veulent probablement pas violer les CGU » (ben si : ils veulent utiliser Sci-Hub même si c'est censuré).

En conclusion, le RFC note en effet qu'on peut être sceptique quant aux chances d'une solution négociée. Mais il met aussi en avant le fait qu'il va être très difficile de trouver une solution qui marche pour toute la variété des réseaux. Et que l'expérience prouve largement que toute nouvelle technique va avoir des effets inattendus et que, par exemple, une solution qui visait à donner aux opérateurs des informations utiles pour la gestion de réseaux, va parfois être détournée pour d'autres buts.

Sinon, sur la question du déboguage des applications dans un monde où tout est chiffré, j'avais fait un exposé à Capitole du Libre.


Téléchargez le RFC 9490


L'article seul

RFC 9476: The .alt Special-Use Top-Level Domain

Date de publication du RFC : Septembre 2023
Auteur(s) du RFC : W. Kumari (Google), P. Hoffman (ICANN)
Chemin des normes
Première rédaction de cet article le 30 septembre 2023


Le TLD .alt a été réservé pour les utilisations non-DNS. Si demain je crée une chaine de blocs nommée Catena et que j'enregistre des noms dessus, il est recommandé qu'ils se terminent par catena.alt (mais comme toujours sur l'Internet, il n'y a pas de police mondiale chargée de faire respecter les RFC).

Ce nouveau RFC est l'occasion de rappeler que noms de domaine et DNS, ce n'est pas pareil. Les noms de domaine existaient avant le DNS et, même aujourd'hui, peuvent être résolus par d'autres techniques que le DNS (par exemple votre fichier local /etc/hosts ou équivalent).

Mais le DNS est un tel succès que cette « marque » est utilisée partout. On voit ainsi des systèmes de résolution de noms n'ayant rien à voir avec le DNS se prétendre « DNS pair-à-pair » ou « DNS sur la blockchain », ce qui n'a aucun sens. Ce nouveau RFC, lui, vise clairement uniquement les systèmes non-DNS. Ainsi, des racines alternatives ou des domaines privés comme le .local du RFC 6762 ne rentrent pas dans son champ d'application. De plus, il ne s'applique qu'aux noms de domaine ou en tout cas aux identificateurs qui leur ressemblent suffisamment. Si vous créez un système complètement disruptif où les identificateurs ne ressemblent pas à des noms de domaine, ce RFC ne vous concerne pas non plus. Mais si, pour des raisons techniques (être compatible avec les applications existantes) ou marketing (les noms de domaine, c'est bien, tout le monde les reconnait), vous choisissez des noms de domaine comme identificateurs, lisez ce RFC.

En effet, il existe plusieurs de ces systèmes. Ils permettent, en indiquant un nom de domaine (c'est-à-dire une série de composants séparés par des points comme truc.machin.chose.example) d'obtenir des informations techniques, permettant, par exemple, de trouver un serveur ou de s'y connecter. Un exemple d'un tel système est le mécanisme de résolution utilisé par Tor. Les identificateurs sont construits à partir d'une clé cryptographique et suffixés d'un .onion (réservé par le RFC 7686). Ainsi, ce blog est en http://sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion/. N'essayez pas ce nom dans le DNS : vous ne le trouverez pas, il se résout via Tor.

Pendant longtemps, cette pratique de prendre, un peu au hasard, un nom et de l'utiliser comme TLD a été la façon la plus courante de créer des noms de domaine dans son espace à soi. C'est ainsi que Namecoin a utilisé le .bit, ENS (Ethereum Name Service) le .eth et GNUnet le .gnu. Chacun prenait son nom comme il voulait, sans concertation (il n'existe pas de forum ou d'organisation pour discuter de ces allocations). Cela entraine deux risques, celui de collision (deux systèmes de nommage utilisent le même TLD, ou bien un système de nommage utilise un TLD qui est finalement alloué dans le DNS, ce qui est d'autant plus probable qu'il n'existe pas de liste de ces TLD non-DNS). Il y a plusieurs solutions à ce problème, et l'IETF en a longuement discuté (cf. par exemple l'atelier EName de 2017, ou bien le très contestable RFC 8244). Ce RFC a donc mis des années à sortir. L'ICANN, par exemple, a essayé de diaboliser ces noms, attirant surtout l'attention sur leurs dangers. Autre méthode, il a été suggéré de créer un mécanisme de concertation pour éviter les collisions, création qui n'a jamais eu lieu, et pas pour des raisons techniques. Ce RFC 9476 propose simplement de mettre les noms non-DNS sous un TLD unique, le .alt. Ce TLD est réservé dans le registre des noms spéciaux (créé par le RFC 6761). Ainsi, si le système de résolution de Tor était créé aujourd'hui, on lui proposerait d'être en .onion.alt. Est-ce que les concepteurs de futurs systèmes de résolution non-DNS se plieront à cette demande ? Je suis assez pessimiste à ce sujet. Et il serait encore plus utopique de penser que les TLD non-DNS existants migrent vers .alt.

Comme .alt, par construction, regroupe des noms qui ne sont pas résolvables dans le DNS, un résolveur purement DNS ne peut que répondre tout de suite NXDOMAIN (ce nom n'existe pas) alors qu'un résolveur qui parle plusieurs protocoles peut utiliser le suffixe du nom comme une indication qu'il faut utiliser tel ou tel protocole. Si jamais des noms sous .alt sont réellement utilisés, ils ne devraient jamais apparaitre dans le DNS (par exemple dans les requêtes aux serveurs racine) mais, compte-tenu de l'expérience, il n'y a aucun doute qu'on les verra fuiter dans le DNS. Espérons que des techniques comme celles du RFC 8020, du RFC 8198 ou du RFC 9156 réduiront la charge sur les serveurs de la racine; et préserveront un peu la vie privée (section 4 du RFC).

Le nom .alt est évidemment une référence à alternative mais il rappelera des souvenirs aux utilisateurs d'Usenet. D'autres noms avaient été sérieusement discutés comme de préfixer tous les TLD non-DNS par un tiret bas. Mon catena.alt aurait été _catena :-) Tout ce qui touche à la terminologie est évidemment très sensible, et le RFC prend soin de souligner que le terme de « pseudo-TLD », qu'il utilise pour désigner les TLD non-DNS n'est pas péjoratif…

On note que le risque de collision existe toujours, mais sous .alt. Notre RFC ne prévoit pas de registre des noms sous .alt (en partie parce que l'IETF ne veut pas s'en mêler, son protocole, c'est le DNS, et en partie parce que ce milieu des mécanismes de résolution différents est très individualiste et pas du tout organisé).


Téléchargez le RFC 9476


L'article seul

RFC 9460: Service Binding and Parameter Specification via the DNS (SVCB and HTTPS Resource Records)

Date de publication du RFC : Novembre 2023
Auteur(s) du RFC : B. Schwartz (Meta Platforms), M. Bishop, E. Nygren (Akamai Technologies)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 8 avril 2024


Ces deux nouveaux types d'enregistrement DNS, SVCB et sa variante HTTPS, permettent de donner des informations supplémentaires à un client réseau avant qu'il ne tente de se connecter à un serveur. On peut envoyer ainsi des indications sur les versions des protocoles gérées, des clés cryptographiques ou des noms de serveurs supplémentaires.

Un client d'un service réseau a en effet plein de questions à se poser avant de tenter une connexion. Quelle adresse IP utiliser ? Quel port ? Chiffrement ou pas ? Les anciens mécanismes traitent la question de l'adresse IP (on la trouve par une requête DNS) et celle du port, si on se limite aux ports bien connus (comme 43 pour whois). Mais cela ne dit pas, par exemple, si le serveur HTTP distant accepte ou non HTTP/3 (RFC 9114). Par contre, cet enregistrement HTTPS de Cloudflare va bien nous dire que ce serveur accepte HTTP/2 et 3 :


% dig cloudflare.com HTTPS
…
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28399
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
…
;; ANSWER SECTION:
cloudflare.com.		300 IN HTTPS 1 . alpn="h3,h2" ipv4hint=104.16.132.229,104.16.133.229 ipv6hint=2606:4700::6810:84e5,2606:4700::6810:85e5
…
;; WHEN: Mon Apr 08 09:27:01 CEST 2024
;; MSG SIZE  rcvd: 226

  

Bon, en quoi consiste cet enregistrement SVCB ? Il a deux modes de fonctionnement, alias et service. Le premier mode sert à faire d'un nom une version canonique d'un autre, un peu comme le CNAME mais en étant utilisable à l'apex d'une zone. Le second mode sert à indiquer les paramètres techniques de la connexion. Un enregistrement SVCB (ou HTTPS) a trois champs dans ses données :

  • SvcPriority : quand il vaut zéro, il indique le mode alias. Autrement (par exemple dans le cas ci-dessus), il indique la priorité de ces paramètres.
  • TargetName : en mode alias, il indique le nom canonique, ou autrement un nom alternatif (pour un service accessible via plusieurs noms). Dans l'exemple Cloudflare ci-desssus, il valait la racine (un point) ce qui indique l'absence de nom alternatif (section 2.5).
  • SvcParams : une liste de couples {clé,valeur} pour les paramètres de connexion (uniquement en mode service). Dans le cas avec Cloudflare, c'était alpn="h3,h2" ipv4hint=104.16.132.229,104.16.133.229 ipv6hint=2606:4700::6810:84e5,2606:4700::6810:85e5. (Si vous vous intéressez aux débats à l'IETF, la question de la syntaxe de ces paramètres avait suscité une longue discussion.)

Les enregistrements SVCB ont le type 64 (enregistré à l'IANA) et les HTTPS, qui ont la même syntaxe et le même contenu, mais sont spécifiques à HTTP, ont le 65 (SVCB est générique). Les enregistrements HTTPS (et de futurs enregistrements pour d'autres protocoles) sont dits « compatibles avec SVCB » car ils ont la même syntaxe et la même sémantique.

Notre RFC définit (section 7) une liste de paramètres possibles mais d'autres peuvent être ajoutés dans un registre IANA, via la procédure « Examen par un expert » (RFC 8126). Pour l'instant, il y a, entre autres :

  • alpn : indique l'ALPN (RFC 7301).
  • ech : il servira à indiquer la clé à utiliser pour chiffrer le SNI.
  • port : comme son nom l'indique.
  • ipv4hint et ipv6hint : les adresses IP du service.

L'enregistrement peut (cela dépend des protocoles qui l'utilisent, HTTP ne le fait pas) être placé sur un sous-domaine indiquant le service, par exemple _8765._baz.api.example.com (section 10.4.5).

Idéalement, un serveur faisant autorité devrait renvoyer les SVCB et les HTTPS, s'ils sont présents, dans la section additionnelle de la réponse, lorsque le type demandé était une adresse IP. Mais ceux de Cloudflare ne semblent pas le faire actuellement. (PowerDNS le fait.)

Si vous vous intéressez aux questions opérationnelles, et que vous voulez mettre des enregistrements SVCB/HTTPS dans votre zone, la section 10 du RFC est faite pour vous. J'ai des enregistrements HTTPS pour ce blog :


# Un alias à l'apex (la priorité 0 indique le mode alias)
% dig +short +nodnssec bortzmeyer.org HTTPS
0 www.bortzmeyer.org.

# J'ai HTTP/2 (mais pas encore HTTP/3)
% dig +short +nodnssec www.bortzmeyer.org HTTPS
1 . alpn="h2"

Pour cela, j'ai mis dans le fichier de zone :

; Enregistrements SVCB (HTTPS).     

; HTTP/2 (mais pas encore - au 2024-04-08 - de HTTP/3)               
www IN HTTPS 1 . alpn="h2"

; alias                               
@ IN HTTPS 0 www.bortzmeyer.org.

Les clients HTTP récents, qui gèrent SVCB/HTTPS vont alors se connecter directement en HTTP/2 à https://www.bortzmeyer.org/ même si l'utilisateur demandait originellement http://bortzmeyer.org/ (le type d'enregistrement HTTPS, comme son nom l'indique, sert aussi à annoncer qu'on accepte HTTPS, ce qui permettra d'abandonner HSTS). Les clients HTTP plus anciens, évidemment, ne connaissent pas le système SVCB/HTTPS et il faut donc garder une configuration pour eux (par exemple des adresses IP à l'apex). Il y a aussi les autres méthodes, comme le Alt-Svc: du RFC 7838. La section 9.3 du RFC décrit le comportement attendu lorsque les différentes méthodes coexistent.

Faites attention toutefois, lorsque vous mettez ce type d'enregistrements dans votre zone, je ne connais pas encore d'outils de test permettant de vérifier la syntaxe des enregistrements, encore moins leur correspondance avec la réalité (par exemple, SSLLabs ne semble pas le faire). C'est un problème général de la signalisation sur l'Internet, quand on signale (notamment via le DNS) les capacités d'un serveur : le logiciel client doit de toute façon être prêt à tout, car il ne peut jamais être sûr que le signal est conforme aux faits.

En parlant d'anciens logiciels (clients et serveurs), vous pouvez trouver une liste de mises en œuvre de SVCB/HTTPS. Attention, elle est incomplète et pas à jour. Notez qu'il y a parfois des contraintes particulières, ainsi, il semble que Firefox ne demande des enregistrements HTTPS que s'il utilise DoH. iOS envoie des requêtes HTTPS depuis iOS 14, publié en septembre 2020, ce qui avait étonné, à l'époque.

En parlant de Firefox, s'il est assez récent, et s'il est configuré pour faire du DoH, vous pouvez tester le SVCB/HTTPS en allant dans about:networking#dnslookuptool. En entrant un nom de domaine, le champ « RR HTTP » doit renvoyer l'enregistrement HTTPS.

Avec un tcpdump récent, voici le trafic DNS utilisant le nouvel enregistrement DNS, qu'on peut observer sur un serveur faisant autorité pour bortzmeyer.org :

09:49:23.354974 IP6 2a04….31362 > 2001:4b98:dc0:41:216:3eff:fe27:3d3f.53: 13024% [1au] HTTPS? www.bortzmeyer.org. (47)
09:52:06.094314 IP6 2a00….56551 > 2001:4b98:dc0:41:216:3eff:fe27:3d3f.53: 40948% [1au] HTTPS? wWw.bOrTZmEyER.ORg. (62)
10:06:21.501437 IP6 2400….11624 > 2001:4b98:dc0:41:216:3eff:fe27:3d3f.53: 59956 [1au] HTTPS? doh.bortzmeyer.fr. (46)
10:06:21.999608 IP6 2400….36887 > 2001:4b98:dc0:41:216:3eff:fe27:3d3f.53: 17231 [1au] HTTPS? radia.bortzmeyer.org. (49)
10:25:53.947096 IP6 2001….54476 > 2001:4b98:dc0:41:216:3eff:fe27:3d3f.53: 26123% [1au] HTTPS? www.bortzmeyer.org. (47)
  

Si votre tcpdump est plus ancien, vous verrez Type65 au lieu de HTTPS.

Sinon, si vous aimez les bricolages (et celui-ci sera de moins en moins utile avec le temps, au fur et à mesure que les serveurs géreront ce type), pour fabriquer les enregistrements, vous pouvez utiliser cet outil, qui va fabriquer la forme binaire, directement chargeable par les serveurs faisant autorité :

% perl type65_https.pl 'example.net HTTPS 1 . alpn="h3,h2" ipv4hint="192.0.2.42" ipv6hint="2001:db8::42"'
example.net. TYPE65 ( \# 41 00010000010006026833026832000400
	04c000022a0006001020010db8000000 000000000000000042 )
  

(Il faut un Net::DNS récent sinon « unknown type "HTTPS" at /usr/share/perl5/Net/DNS/RR.pm line 671. in new Net::DNS::RR( www.bortzmeyer.org HTTPS 1 . alpn="h2" ) at type65_https.pl line 30. ».)

Quelques articles pas mal :


Téléchargez le RFC 9460


L'article seul

RFC 9432: DNS Catalog Zones

Date de publication du RFC : Juillet 2023
Auteur(s) du RFC : P. van Dijk (PowerDNS), L. Peltan (CZ.NI), O. Sury (Internet Systems Consortium), W. Toorop (NLnet Labs), C.R. Monshouwer, P. Thomassen (deSEC, SSE - Secure Systems Engineering), A. Sargsyan (Internet Systems Consortium)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 29 mars 2024


L'idée de base de ces « zones catalogue » est d'automatiser la configuration d'une nouvelle zone DNS sur les serveurs secondaires, en publiant dans le DNS les caractéristiques des zones qu'ils devront servir. Cela concerne donc surtout les gros hébergeurs qui ont beaucoup de zones.

Petit rappel : une zone, dans le DNS, est une partie contigüe de l'arbre des noms de domaine, gérée comme un tout (mêmes serveurs faisant autorité). Ainsi, si vous venez de louer le nom machin.example, un hébergeur DNS va configurer ses serveurs pour faire autorité pour ce nom. Par exemple, avec le logiciel NSD, sur le primaire (serveur maitre) :

zone:
        name: "machin.example"
        zonefile: "primary/machin.example"
        # Les serveurs secondaires :
        notify: 2001:db8:1::53
        provide-xfr: 2001:db8:1::53
        …

Et, sur un serveur secondaire (serveur esclave), qui transférera la zone depuis le primaire (RFC 5936) :

zone:
   name: "machin.example"
   # Le primaire :
   allow-notify: 2001:db8:cafe::1 NOKEY
   request-xfr: AXFR 2001:db8:cafe::1 NOKEY

Si on gère beaucoup de zones, avec des ajouts et des retraits tout le temps, l'avitaillement manuel est long et risqué (et si on oublie un serveur ?). Éditer ces fichiers sur tous les serveurs secondaires devient vite pénible. Et si les logiciels sur les secondaires sont différents les uns des autres (ce qui est recommandé, pour la robustesse), il faut se souvenir des différentes syntaxes. Pourquoi faire manuellement ce qu'on peut automatiser ? C'est le principe des zones catalogue.

Le principe est simple : une zone catalogue est une zone comme une autre, produite par les mêmes mécanismes (par exemple emacs) et qui sera servie par un serveur primaire à tous les secondaires, qui changeront alors automatiquement leur configuration en fonction du contenu de la zone catalogue. Chaque zone à configurer est un enregistrement de type PTR, dont la partie gauche est une étiquette interne et la partie droite indique le nom de la zone. Ici, on configure la zone rutaba.ga, l'étiquette (qui doit être unique) label1 est à usage interne (section 4.1 du RFC) :

label1.zones.catalog.example. IN PTR rutaba.ga.

Le reste est listé sous forme de propriétés (section 4.2). Une propriété évidente est l'adresse IP du primaire. Pour l'instant, elle doit être indiquée via le composant ext qui désigne les propriétés pas encore normalisées :

primaries.ext.catalog.example.    IN AAAA 2001:db8:bad:dcaf::42

La liste des propriétés figure dans un registre IANA.

À l'heure actuelle, de nombreux logiciels gèrent ces zones catalogues. Le site Web du projet (pas mis à jour depuis très longtemps) en liste plusieurs.

Voici un exemple complet de zone catalogue :

; -*- zone -*-
catalog.example.    IN SOA ns4.bortzmeyer.org. stephane.bortzmeyer.org. 2023120902 900 600 86400 1
catalog.example.    IN NS invalid.   ; Le NS est inutile mais
                         ; obligatoire et "invalid" est la valeur
                         ; recommandée (section 4).
version.catalog.example.    IN TXT "2"  ; Obligatoire, section 4.2.1

label1.zones.catalog.example. IN PTR rutaba.ga.
primaries.ext.catalog.example.    IN AAAA 2001:db8:bad:dcaf::42

La configuration de BIND pour l'utiliser :

# La zone catalogue se charge comme n'importe quelle zone. Ceci dit,
# vu le caractère critique de la zone catalogue, la section 7 du RFC
# insiste sur l'importance de sécuriser ce transfert, par exemple avec
# TSIG (RFC 8945) :
zone "catalog.example" {
        type slave;
        file "catalog.example";
        masters {
              2001:db8:666::;
        };            

};

# Et, ici, on la désigne comme spéciale :
options {
   ...      
   catalog-zones {
     zone "catalog.example"
              in-memory no;
   };
};

Naturellement, comme toujours lorsque on automatise, on risque le syndrome de l'apprenti sorcier. Attention donc en générant la zone catalogue. Comme le note le RFC (section 6) : « Great power comes with great responsibility. Catalog zones simplify zone provisioning by orchestrating zones on secondary name servers from a single data source: the catalog. Hence, the catalog producer has great power and changes must be treated carefully. For example, if the catalog is generated by some script and this script generates an empty catalog, millions of member zones may get deleted from their secondaries within seconds, and all the affected domains may be offline in a blink of an eye. »


Téléchargez le RFC 9432


L'article seul

RFC 9340: Architectural Principles for a Quantum Internet

Date de publication du RFC : Mars 2023
Auteur(s) du RFC : W. Kozlowski, S. Wehner (QuTech), R. Van Meter (Keio University), B. Rijsman, A. S. Cacciapuoti, M. Caleffi (University of Naples Federico II), S. Nagayama (Mercari)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF qirg
Première rédaction de cet article le 3 avril 2024


Voici un RFC assez futuriste qui explore à quoi pourrait ressembler un futur « Internet » quantique. Je divulgâche tout de suite : ce ne sera pas de si tôt.

Quelques avertissements s'imposent d'abord. Avant tout, rappelez-vous que la quantique produit des résultats qui sont parfaitement cohérents théoriquement et très bien vérifiés expérimentalement mais qui sont hautement non-intuitifs. Avant d'aborder le monde merveilleux de la quantique, n'oubliez pas d'oublier tout ce que vous croyez savoir sur le monde physique. Et ne comptez pas trop sur moi comme guide, on sort nettement ici de mon domaine de compétence. Ensuite, « quantique » est un terme à très forte charge marketing (moins que « IA » mais davantage que « métavers » ou même « blockchain », qui semblent bien passés de mode). Il faut donc être prudent chaque fois qu'un commercial ou un éditorialiste va dire que « c'est quantique » ou que « la quantique va bouleverser tel ou tel domaine ». Enfin, il y a loin de la coupe aux lèvres : de même qu'on n'a pas encore d'ordinateur quantique utile, on n'a pas encore de réseau quantique. Le RFC est à juste titre prudent, pointant les différents obstacles qui restent sur le chemin de l'Internet quantique.

Bon, ces précautions étant posées, qu'est-ce qu'un réseau quantique et pourquoi y consacrer un RFC ? La section 1 du RFC le résume : un réseau quantique est un réseau qui ferait communiquer des dispositifs quantiques pour faire des choses inimaginables avec un réseau classique. Il s'appuierait sur des propriétés spécifiques au monde quantique, notamment l'intrication, propriétés qui n'ont pas d'équivalent dans le monde classique. Attention, et le RFC insiste bien là-dessus, personne n'envisage de remplacer l'Internet classique par un Internet quantique (de la même façon que les futurs ordinateurs quantiques, étant loin d'être généralistes, ne remplaceront pas les ordinateurs classiques). Au contraire, le scénario envisagé est celui d'un réseau hybride, partiellement quantique. (Une lecture recommandée par le RFC est « The quantum internet ».)

Un exemple typique qui ne serait pas possible avec un réseau classique est celui de la distribution quantique de clés (parfois appelée du terme erroné de « cryptographie quantique »), dont l'utilité pratique est douteuse mais qui est assez spectaculaire et, contrairement à d'autres applications, est assez avancée techniquement. D'autres applications sont envisageables à plus long terme. C'est le cas par exemple du blind quantum computation, qui n'a pas encore d'article Wikipédia mais est expliqué dans cet article.

En laboratoire, beaucoup de résultats ont été obtenus. Les chercheurs et chercheuses ont déjà mis au point bien des dispositifs physiques étonnants. Mais à l'échelle du réseau, il n'y a pas encore eu beaucoup de travaux. Le RFC compare cette situation à celle d'un réseau classique où on aurait des fibres optiques et des lasers pour les illuminer mais aucun protocole de transport, aucun mécanisme de routage, encore moins de moyens de gérer le réseau. Développer une application pour un réseau quantique revient à toucher directement au matériel, comme, pour un réseau classique, s'il fallait que chaque application parle aux interfaces physiques, sans avoir d'interface de plus haut niveau comme les prises.

La section 2 du RFC est un rappel sur la quantique. Comme dit plus haut, c'est un domaine riche et complexe, où l'intuition ordinaire ne sert pas à grand'chose. Donc, lire ce rappel est une bonne idée mais n'espérez pas tout comprendre si vous n'êtes pas spécialiste de la question. Cette section est conçue pour des gens qui ne connaissent rien à la physique quantique, elle recommande, pour aller plus loin, le livre de Sutor Dancing with Qubits ou bien celui de Nielsen et Chuang, Quantum Computation and Quantum Information.

Le rappel commence avec la notion d'état quantique. Vous avez sans doute déjà entendu dire qu'un bit classique peut prendre deux valeurs, 0 ou 1, alors que son équivalent quantique, le qubit, a un état qui est une superposition de valeurs possibles, avec des probabilités. Lorsqu'on le mesure, on trouve un 0 ou un 1. (Oui, comme le célèbre chat qui est à la fois vivant et mort.) Attention, ces non-certitudes ne sont pas la conséquence d'un manque d'information mais sont une propriété fondamentale du monde quantique (Alain Aspect a eu un prix Nobel pour avoir prouvé cela). Notez que les versions HTML ou PDF du RFC sont recommandées ici, car il y a quelques équations. Comme un qubit est dans un état qui superpose les deux valeurs possibles, les opérations quantiques agissent sur tout l'état, par exemple l'équivalent quantique d'une porte NOT va inverser les probabilités du 0 et du 1 mais pas transformer un 0 en 1.

Le terme « qubit » (et cette distinction revient souvent dans le RFC) peut désigner aussi bien le concept abstrait que le truc physique qui va le mettre en œuvre (il existe plusieurs techniques pour fabriquer un engin qui gérera des qubits).

On peut ensuite assembler des qubits et, très vite, le nombre de possibilités croît. Mais l'intérêt de mettre des qubits ensemble est qu'on peut les intriquer et ce concept est au cœur de beaucoup de solutions quantiques, notamment du réseau quantique. Une fois intriqués, les deux qubits verront leur sort lié. Une mesure sur l'un affectera l'autre. (Rappel : la quantique n'est pas intuitive et l'intrication n'a pas d'équivalent dans le monde non-quantique, celui sur lequel a été bâtie notre intuition.) La mesure, comme toujours en quantique, est « destructive » au sens où elle ramène à un système classique (le qubit vaut 0 ou 1 quand on le mesure, pas un mélange des deux, et le chat est vivant ou mort quand on ouvre la boite).

Cette intrication est au cœur des réseaux quantiques (section 3 du RFC). Tous les projets de réseaux quantiques utilisent cette propriété (qui, rappelons-le, n'a pas d'équivalent non-quantique). L'intrication permet de corréler deux nœuds du réseau. Par exemple, pour se mettre d'accord sur une valeur, deux machines n'ont pas besoin de faire tourner des algorithmes de consensus, elles peuvent utiliser deux qubits intriqués, chacune en gardant un. Quand une machine lira la valeur de son qubit, elle sera certaine de la valeur lue par l'autre. Et l'intrication ne peut pas être partagée : un tiers ne peut pas s'intriquer avec une intrication existante, ce qui peut avoir des applications en sécurité.

Un réseau quantique est donc défini par notre RFC comme un ensemble de nœuds qui peuvent échanger des qubits intriqués.

Bon, tout ça, c'est très joli, mais comment on le réalise, ce réseau quantique ? La section 4 se penche sur les défis :

  • Comme toute mesure détruit le caractère quantique du qubit et le transforme en un bit ordinaire, des opérations banales dans le monde classique, comme la copie d'un bit, deviennent non triviales.
  • Et copier un qubit sans le mesurer ? On ne peut pas (c'est le théorème d'impossibilité du clonage).
  • Tout cela rend très difficile la correction d'erreurs. Un réseau réel, reposant sur des objets physiques, va forcément voir des erreurs (un rayon cosmique passe et paf, un 0 est transformé en 1) et de nombreuses techniques existent pour gérer ce problème dans le monde classique. Mais elles ne peuvent en général pas s'appliquer dans le monde quantique, qui va donc avoir un problème de fidélité : la fidélité est la conformité à ce qu'on souhaitait (elle va de 0 à 1), et les applications doivent en tenir compte.

Distribuer sur le réseau des qubits quelconques n'est pas forcément facile, donc le RFC suggère de plutôt distribuer des paires de Bell. On peut alors plus facilement (tout est relatif) faire de la téléportation, c'est-à-dire « transporter » un qubit d'un point à un autre. Ce n'est pas une violation du théorème d'impossibilité du clonage puisque le qubit n'est pas copié (il disparait de son point de départ). Notez que le terme de « téléportation » est surtout marketing : vous ne pourrez pas déplacer votre chat ou vous-même de cette façon.

Dernier problème, amplifier le signal (sans le copier !) pour tenir compte de sa dégradation avec la distance. Il existe une astuce, l'échange d'intrication, que je ne vais pas essayer d'expliquer, mais qui permet des réseaux quantiques sur des distances importantes.

Revenons à la correction d'erreurs. Les réseaux quantiques ne sont pas complètement démunis, et ont des solutions possibles, comme les codes quantiques.

OK, on a vu que le monde quantique était très spécial. Donc, le réseau quantique va être bizarre aussi, aux yeux de quelqu'un qui a l'habitude des réseaux classiques (section 5 du RFC). Par exemple, il fera face à ces problèmes :

  • C'est bien joli, les paires de Bell, mais ce n'est pas l'équivalent d'un paquet portant une charge utile. Il n'y a pas l'équivalent de l'en-tête du paquet, et le réseau quantique va donc devoir utiliser un réseau classique pour l'information de contrôle. On ne fera pas un réseau purement quantique.
  • Toute action sur des qubits intriqués doit être coordonnée entre les nœuds puisque l'action sur un qubit va déterminer le résultat d'une action sur les autres (il faut donc que chaque nœud sache contacter les autres).

Répétons-le, chaque nœud du réseau quantique devra également être relié à un réseau classique. Le réseau sera donc complexe et son administration pas évidente.

Une fois qu'on a accepté cela, le réseau classique pourra s'occuper d'opérations comme la construction des tables de routage, pour laquelle les algorithmes et méthodes classiques semblent suffire. On n'aura donc peut-être qu'un seul plan de contrôle (le classique) mais deux plans de données, le classique et le quantique.

Que faut-il construire comme machines pour le plan de données quantique ? D'abord, des répéteurs quantiques qui vont pouvoir créer les intrications, les échanger et contrôler la fidélité. Ensuite :

  • Des routeurs quantiques, qui, en plus des fonctions ci-dessus, participeront au routage.
  • Les nœuds ordinaires, des répéteurs qui ne participent pas au routage.
  • Les nœuds terminaux, qui pourront émettre et recevoir des qubits mais pas faire d'échange d'intrication. C'est là que tourneront les applications.

Facile, me direz-vous ? Non, construire ces machines va nécessiter de s'attaquer à quelques problèmes physiques :

  • Stocker un qubit est un défi ! Le monde classique n'aime pas les objets quantiques et essaie régulièrement de les rappeler à ses lois. Les bruits divers de l'environnement font rapidement perdre aux qubits leurs propriétés quantiques. (C'est d'ailleurs pour cela que vous ne rencontrez pas de chats de Schrödinger dans la vraie vie.) Cela se nomme la décohérence et c'est l'un des principaux obstacles sur la route des réseaux quantiques (ou des calculateurs quantiques). Les durées de vie qu'on atteint étaient, lors de la rédaction du RFC, de l'ordre de la seconde (ou de la minute si on n'est pas connecté au réseau, source de perturbations).
  • La capacité des liens quantiques est un autre problème. Générer des qubits intriqués prend du temps. Quand on en fabrique dix par seconde, on est contents. Bien sûr, la technique progresse sans cesse (pas mal des références du RFC sont un peu datées, car il a mis du temps à sortir) mais pas assez.
  • On l'a dit, on peut réaliser des qubits intriqués par différentes méthodes physiques, avec des performances différentes selon la métrique utilisée. Mais ces méthodes ne communiquent pas entre elles, ce qui veut dire que tous les nœuds du réseau doivent utiliser la même.

Si vous n'êtes pas découragé·e (mais il ne faut pas l'être : même si les difficultés sont colossales, le chemin est rigolo), il faut maintenant, en supposant qu'on aura les composants de base d'un réseau, les assembler. (À moins que le choix décrit dans le RFC des paires de Bell et de l'échange d'intrication ne soit remis en cause par les futurs progrès…) La section 6 se penche sur la question. Elle démarre par un bel excès d'optimisme, en expliquant que, contrairement à ce qui s'est passé avec l'Internet classique, on a de l'expérience sur la construction de réseau, et qu'on pourra donc ne pas faire d'erreur comme la taille trop réduite des adresses IPv4.

Des services essentiels pour un réseau réel seront difficiles à assurer sur un réseau quantique. Par exemple, l'impossibilité du clonage interdira d'utiliser un logiciel équivalent à tcpdump (remarquez, pour la sécurité, c'est un plus). Le RFC liste les principes de base d'un réseau quantique :

  • Le service de base sera l'intrication.
  • La fidélité est aussi un service (contrairement au réseau classique où on peut espérer une fidélité parfaite).
  • Le temps va être un facteur crucial, compte tenu de la décohérence. Pas question de faire patienter des qubits trop longtemps dans une file d'attente, par exemple.
  • Il faudra être flexible, notamment parce que le matériel va continuer à évoluer.

Et le RFC se termine par une exploration d'une architecture de réseau quantique possible, inspirée de MPLS. Dans ce réseau (pour l'instant) imaginaire, tout fonctionne en mode connecté (comme MPLS) : on doit d'abord créer un circuit virtuel (car créer les paires de Bell et les utiliser va nécessiter de la coordination, donc il vaut mieux établir d'abord une connexion). Ce QVC (Quantum Virtual Circuit) a des caractéristiques comme une qualité de service choisie, qui se décline en, par exemple, une capacité mesurée en nombre de paires de Bell par seconde et bien sûr une fidélité (toutes les applications des réseaux quantiques n'ont pas les mêmes exigences en terme de fidélité). La signalisation peut être décentralisée (comme avec RSVP) ou centralisée (comme avec OpenFlow). Comme vous le verrez en lisant cette conclusion du RFC, les détails sont encore approximatifs.

Ce RFC a mis longtemps à être écrit, vous pouvez trouver une description ancienne du projet sur le blog de l'IETF. Notez que l'écriture de ce RFC a été en partie financée par la Quantum Internet Alliance européenne.

N'hésitez pas à vous plonger dans la bibliographie très détaillée de ce RFC, vous y trouverez beaucoup de lectures passionnantes. Il y a même déjà des livres entiers sur les réseaux quantiques comme celui de Van Meter.


Téléchargez le RFC 9340


L'article seul

RFC 9309: Robots Exclusion Protocol

Date de publication du RFC : Septembre 2022
Auteur(s) du RFC : M. Koster, G. Illyes, H. Zeller, L. Sassman (Google)
Chemin des normes
Première rédaction de cet article le 14 septembre 2022


Quand vous gérez un serveur Internet (pas forcément un serveur Web) prévu pour des humains, une bonne partie du trafic, voire la majorité, vient de robots. Ils ne sont pas forcément malvenus mais ils peuvent être agaçants, par exemple s'ils épuisent le serveur à tout ramasser. C'est pour cela qu'il existe depuis longtemps une convention, le fichier robots.txt, pour dire aux robots gentils ce qu'ils peuvent faire et ne pas faire. La spécification originale était très limitée et, en pratique, la plupart des robots comprenait un langage plus riche que celui du début. Ce nouveau RFC documente plus ou moins le format actuel.

L'ancienne spécification, qui date de 1996, est toujours en ligne sur le site de référence (qui ne semble plus maintenu, certaines informations ont des années de retard). La réalité des fichiers robots.txt d'aujourd'hui est différente, et plus riche. Mais, comme souvent sur l'Internet, c'est assez le désordre, avec différents robots qui ne comprennent pas la totalité du langage d'écriture des robots.txt. Peut-être que la publication de ce RFC aidera à uniformiser les choses.

Donc, l'idée de base est la suivante : le robot qui veut ramasser des ressources sur un serveur va d'abord télécharger un fichier situé sur le chemin /robots.txt. (Au passage, si cette norme était faite aujourd'hui, on utiliserait le /.well-known du RFC 8615.) Ce fichier va contenir des instructions pour le robot, lui disant ce qu'il peut récupérer ou pas. Ces instructions concernent le chemin dans l'URI (et robots.txt n'a donc de sens que pour les serveurs utilisant ces URI du RFC 3986, par exemple les serveurs Web). Un exemple très simple serait ce robots.txt :

User-Agent: *
Disallow: /private
  

Il dit que, pour tous les robots, tout est autorisé sauf les chemins d'URI commençant par /private. Un robot qui suit des liens (RFC 8288) doit donc ignorer ceux qui mènent sous /private.

Voyons maintenant les détails pratiques (section 2 du RFC). Un robots.txt est composé de groupes, chacun s'appliquant à un robot ou un groupe de robots particulier. Les groupes sont composés de règles, chaque règle disant que telle partie de l'URI est interdite ou autorisée. Par défaut, tout est autorisé (même chose s'il n'y a pas de robots.txt du tout, ce qui est le cas de ce blog). Un groupe commence par une ligne User-Agent qui va identifier le robot (ou un astérisque pour désigner tous les robots) :

User-Agent: GoogleBot
  

Le robot va donc chercher le ou les groupes qui le concernent. En HTTP, normalement, l'identificateur que le robot cherche dans le robots.txt est une sous-chaine de l'identificateur envoyé dans le champ de l'en-tête HTTP User-Agent (RFC 9110, section 10.1.5).

Le robot doit combiner tous les groupes qui s'appliquent à lui, donc on voit parfois plusieurs groupes avec le même User-Agent.

Le groupe est composé de plusieurs règles, chacune commençant par Allow ou Disallow (notez que la version originale de la spécification n'avait pas Allow). Si plusieurs règles correspondent, le robot doit utiliser la plus spécifique, c'est-à-dire celle dont le plus d'octets correspond. Par exemple, avec :

Disallow: /private
Allow: /private/notcompletely
  

Une requête pour /private/notcompletely/foobar sera autorisée. L'ordre des règles ne compte pas (mais certains robots sont bogués sur ce point). C'est du fait de cette notion de correspondance la plus spécifique qu'on ne peut pas compiler un robots.txt en une simple expression rationnelle, ce qui était possible avec la spécification originelle. Si une règle Allow et une Disallow correspondent, avec le même nombre d'octets, l'accès est autorisé.

Le robot a le droit d'utiliser des instructions supplémentaires, par exemple pour les sitemaps.

En HTTP, le robot peut rencontrer une redirection lorsqu'il essaie de récupérer le robots.txt (code HTTP 301, 302, 307 ou 308). Il devrait dans ce cas la suivre (mais pas infinement : le RFC recommande cinq essais au maximum). S'il n'y a pas de robots.txt (en HTTP, code de retour 404), tout est autorisé (c'est le cas de mon blog). Si par contre il y a une erreur (par exemple 500 en HTTP), le robot doit attendre et ne pas se croire tout permis. Autre point HTTP : le robot peut suivre les instructions de mémorisation du robots.txt données, par exemple, dans le champ Cache-control de l'en-tête.

Avant de passer à la pratique, un peu de sécurité. D'abord, il faut bien se rappeler que le respect du robots.txt dépend de la bonne volonté du robot. Un robot malveillant, par exemple, ne tiendra certainement pas compte du robots.txt. Mais il peut y avoir d'autres raisons pour ignorer ces règles. Par exemple, l'obligation du dépôt légal fait que la BNF annonce explicitement qu'elle ignore ce fichier. (Et un programme comme wget a une option, -e robots=off, pour débrayer la vérification du robots.txt.) Bref, un robots.txt ne remplace pas les mesures de sécurité, par exemple des règles d'accès aux chemins définies dans la configuration de votre serveur HTTP. Le robots.txt peut même diminuer la sécurité, en indiquant les fichiers « intéressants » à un éventuel attaquant.

Passons maintenant à la pratique. On trouve plein de mises en œuvre de robots.txt un peu partout mais en trouver une parfaitement conforme au RFC est bien plus dur. Disons-le clairement, c'est le bordel, et l'auteur d'un robots.txt ne peut jamais savoir comment il va être interprété. Il ne faut donc pas être trop subtil dans son robots.txt et en rester à des règles simples. Du côté des robots, on a un problème analogue : bien des robots.txt qu'on rencontre sont bogués. La longue période sans spécification officielle est largement responsable de cette situation. Et tout n'est pas clarifié par le RFC. Par exemple, la grammaire en section 2.2 autorise un Disallow ou un Allow à être vide, mais sans préciser clairement la sémantique associée.

Pour Python, il y a un module standard, mais qui est loin de suivre le RFC. Voici un exemple d'utilisation :

import urllib.robotparser
import sys

if len(sys.argv) != 4:
    raise Exception("Usage: %s robotstxt-file user-agent path" % sys.argv[0])
input = sys.argv[1]
ua = sys.argv[2]
path = sys.argv[3]
parser = urllib.robotparser.RobotFileParser()
parser.parse(open(input).readlines())
if parser.can_fetch(ua, path):
    print("%s can be fetched" % path)
else:
    print("%s is denied" % path)

Et, ici, on se sert de ce code :

% cat ultra-simple.txt 
User-Agent: *
Disallow: /private

% python test-robot.py ultra-simple.txt foobot /public/test.html         
/public/test.html can be fetched

% python test-robot.py ultra-simple.txt foobot /private/test.html
/private/test.html is denied

Mais ce module ne respecte pas la précédence des règles :

% cat precedence.txt
User-Agent: *
Disallow: /
Allow: /bar.html

% python3 test-robot.py precedence.txt foobot /bar.html
/bar.html is denied

En application de la règle la plus spécifique, /bar.html aurait dû être autorisé. Si on inverse Allow et Disallow, on obtient le résultat attendu. Mais ce n'est pas normal, l'ordre des règles n'étant normalement pas significatif. Autre problème du module Python, il ne semble pas gérer les jokers, comme l'exemple *.gif$ du RFC. Il existe des modules Python alternatifs pour traiter les robots.txt mais aucun ne semble vraiment mettre en œuvre le RFC.

La situation n'est pas forcément meilleure dans les autres langages de programmation. Essayons avec Elixir. Il existe un module pour cela. Écrivons à peu près le même programme qu'en Python :

usage = "Usage: test robotstxtname useragent path"
filename =
  case Enum.at(System.argv(), 0) do
    nil -> raise RuntimeError, usage
    other -> other
  end
content =
  case File.read(filename) do
    {:ok, data} -> data
    {:error, reason} -> raise RuntimeError, "#{filename}: #{reason}"
  end
ua =
  case Enum.at(System.argv(), 1) do
    nil -> raise RuntimeError, usage
    other -> other
  end
statuscode = 200
{:ok, rules} = :robots.parse(content, statuscode) 
path =
  case Enum.at(System.argv(), 2) do
    nil -> raise RuntimeError, usage
    other -> other
  end
IO.puts(
  case :robots.is_allowed(ua, path, rules) do
    true -> "#{path} can be fetched"
    false -> "#{path} can NOT be fetched"
  end)
  

Et testons-le :

% mix run test-robot.exs ultra-simple.txt foobot /public/test.html   
/public/test.html can be fetched

% mix run test-robot.exs ultra-simple.txt foobot /private/test.html  
/private/test.html can NOT be fetched
  

Il semble avoir moins de bogues que le module Python mais n'est quand même pas parfait.

Comme dit plus haut, le robots.txt n'est pas réservé au Web. Il est utilisé par exemple pour Gemini. Ainsi, le robot de collecte Lupa lit les robots.txt et ne va pas ensuite récupérer les URI interdits. En septembre 2022, 11 % des capsules Gemini avaient un robots.txt.


Téléchargez le RFC 9309


L'article seul

RFC 9299: An Architectural Introduction to the Locator/ID Separation Protocol (LISP)

Date de publication du RFC : Octobre 2022
Auteur(s) du RFC : A. Cabellos (UPC-BarcelonaTech), D. Saucez (INRIA)
Pour information
Réalisé dans le cadre du groupe de travail IETF lisp
Première rédaction de cet article le 3 novembre 2022


Le protocole réseau LISP (Locator/ID Separation Protocol, rien à voir avec le langage de programmation du même nom) est normalisé dans le RFC 6830 et plusieurs autres qui l'ont suivi. Ce RFC 6830 est un peu long à lire et ce nouveau RFC propose donc une vision de plus haut niveau, se focalisant sur l'architecture de LISP. Cela peut donc être un bon point de départ vers les RFC LISP.

L'idée de base de LISP est de séparer l'identificateur du localisateur, comme recommandé par le RFC 4984. Un identificateur désigne une machine, un localisateur sa position dans l'Internet. Aujourd'hui, les adresses IP servent pour les deux, ne satisfaisant parfaitement aucun des deux buts : les identificateurs devraient être stables (une machine qui change de réseau ne devrait pas en changer), les localisateurs devraient être efficaces et donc être liés à la topologie, et agrégeables.

LISP a donc deux classes : les identificateurs, ou EID (End-host IDentifier) et les localisateurs, ou RLOC (Routing LOCators). Les deux ont la syntaxe des adresses IP (mais pas leur sémantique). Un système de correspondance permet de passer de l'un à l'autre (par exemple, je connais l'EID de mon correspondant, je cherche le RLOC pour lui envoyer un paquet). LISP est plutôt prévu pour être mis en œuvre dans les routeurs, séparant un cœur de l'Internet qui n'utilise que les RLOC, d'une périphérie qui utiliserait les EID (avec, entre les deux, les routeurs LISP qui feraient la liaison).

En résumé (accrochez-vous, c'est un peu compliqué) :

  • LISP peut être vu comme un réseau virtuel (overlay) au-dessus de l'Internet existant (underlay),
  • Les RLOC n'ont de sens que dans le réseau sous-jacent, l'underlay,
  • Les EID n'ont de sens que dans le réseau virtuel overlay,
  • Entre les deux, le système de correspondance,
  • Dans le réseau sous-jacent, les RLOC servent de localisateur et d'identificateur,
  • Dans un site à la périphérie, les EID servent d'identificateur et de localisateur pour les autres machines du site.

C'est ce côté « solution dans les routeurs » et donc le fait que les machines terminales ne savent même pas qu'elles font du LISP, qui distingue LISP des autres solutions fondées sur la séparation de l'identificateur et du localisateur, comme ILNP (RFC 6740).

Au passage, pourquoi avoir développé LISP ? Quel était le problème à résoudre ? Outre la beauté conceptuelle de la chose (il n'est pas esthétique de mêler les fonctions d'identificateur et de localisateur), le principal problème à traiter était celui du passage à l'échelle du système de routage de l'Internet, décrit dans le RFC 4984. En gros, le nombre de routes distinctes augmente trop vite et menace la stabilité des routeurs de la DFZ. Le but était donc, par une nouvelle architecture, de rendre inutile certains choix qui augmentent la taille de la table de routage (comme la désagrégation des préfixes IP, afin de faire de l'ingénierie de trafic). Le RFC 7215 décrit comment LISP aide dans ce cas.

La section 7 du RFC décrit les différents scénarios d'usage de LISP :

  • Ingénierie de trafic : aujourd'hui, dans l'Internet classique BGP, quand on veut orienter le trafic entrant, le faire passer par un chemin donné, on utilise souvent la désagrégation des préfixes. Comme indiqué plus haut, cela aggrave la pression sur la table de routage globale. L'indirection que permet LISP dispense de cette solution : on peut publier dans le système de correspondance les RLOC qu'on veut.
  • Transition vers IPv6 : les EID et les RLOC ont la forme syntaxique d'une adresse IP, v4 ou v6, et il n'y a pas d'obligation qu'EID et RLOC aient la même version. On peut avoir des EID IPv6 et des RLOC IPv4, et cela fournit un mécanisme de tunnel permettant de connecter deux sites LISP IPv6 au-dessus de réseaux qui seraient purement IPv4. L'avantage par rapport aux techniques de transition actuelles est l'intégration dans une solution plus générale et plus « propre ».
  • LISP permet également de faire des VPN, ou de gérer la mobilité de réseaux entiers (un réseau qui se déplace, et donc change de RLOC, c'est juste la correspondance dans le sous-système de contrôle qu'il faut changer, et tout les partenaires routeront vers les nouveaux RLOC).

La section 3 du RFC décrit en détail l'architecture de LISP (après, vous serez mûr·e·s pour lire les RFC LISP eux-mêmes, en commençant par le RFC 6830). Elle repose sur quatre principes :

  • La séparation entre l'identificateur (le EID) et le localisateur (le RLOC),
  • Deux sous-systèmes différents, le contrôle et les données, utilisant des protocoles différents, et pouvant évoluer séparement (enfin, dans une certaine mesure),
  • Une architecture overlay : LISP est déployé sur un réseau virtuel au-dessus de l'Internet existant, ce qui évite les approches « table rase », qui ont une probabilité de déploiement à peu près nulle,
  • Un protocole déployable de manière incrémentale, pas besoin d'attendre que tout le monde s'y mette, il y a des avantages à déployer LISP même pour les premiers à l'adopter (ce problème de déploiement est une des plaies de l'Internet actuel, comme on le voit avec IPv6).

La séparation entre identificateur et localisateur n'est pas faite au niveau de la machine individuelle, comme avec ILNP, mais à la frontière entre la périphérie de l'Internet (the edge) et son cœur (the core, en gros, la DFZ et quelques routeurs en plus). La périphérie travaille avec des EID (elle ne sait même pas que LISP est utilisé), le cœur avec des RLOC. Contrairement à ILNP, il n'y a donc pas une stricte séparation entre identificateurs et localisateurs : ils ont la même syntaxe (qui est celle d'une adresse IP, v4 ou v6) et, à part les routeurs d'entrée et de sortie des tunnels LISP, personne ne sait s'il utilise un EID ou un RLOC : les machines terminales manipulent des EID, les routeurs du cœur des RLOC, tout en croyant que ce sont des adresses IP ordinaires. Seuls les routeurs à la frontière entre les deux mondes connaissent LISP (et auront donc besoin d'un logiciel adapté).

Un Internet LISP est donc une série de « sites LISP » (des réseaux de périphérie accessibles par LISP) connectés par des tunnels entre eux, au-dessus du cœur actuel. Le routeur d'entrée du tunnel se nomme ITR (pour Ingress Tunnel Router) et celui de sortie ETR (pour Egress Tunnel Router). Le terme de xTR (pour « ITR ou bien ETR ») est parfois utilisé pour désigner un routeur LISP, qu'il soit d'entrée ou de sortie lisp-arch

Le sous-système des données (data plane) se charge d'encapsuler et de décapsuler les paquets, puis de les transmettre au bon endroit. (Sa principale qualité est donc la rapidité : il ne faut pas faire attendre les paquets.) Les ITR encapsulent un paquet IP qui vient d'un site LISP (dans un paquet UDP à destination du port 4341), puis l'envoient vers l'ETR. À l'autre bout du tunnel, les ETR décapsulent le paquet. Dans le tunnel, les paquets ont donc un en-tête intérieur (un en-tête IP normal, contenant les EID source et destination), qui a été placé par la machine d'origine, et un en-tête extérieur (contenant le RLOC source, celui de l'ITR, et le RLOC de destination, celui de l'ETR puis, après l'en-tête UDP, l'en-tête spécifique de LISP). Rappelez-vous que les routeurs du cœur ne connaissent pas LISP, ils font suivre ce qui leur semble un paquet IP ordinaire. Les routeurs LISP utilisent des tables de correspondance entre EID et RLOC pour savoir à quel ETR envoyer un paquet.

Ces tables ont été apprises du sous-système de contrôle (control plane, qui contient la fonction de correspondance - mapping), le routeur ayant un cache des correspondances les plus récentes. Cette fonction de correspondance, un des points les plus délicats de LISP (comme de tout système de séparation de l'identificateur et du localisateur) est décrite dans le RFC 6833. Son rôle peut être comparé à celui du DNS et de BGP dans l'Internet classique.

Une correspondance est une relation entre un préfixe d'identificateurs (rappelez-vous que les EID sont, syntaxiquement, des adresses IP ; on peut donc utiliser des préfixes CIDR) et un ensemble de localisateurs, les RLOC des différents routeurs possibles pour joindre le préfixe convoité.

Le RFC 6833 normalise une interface avec ce système de correspondance. Il y a deux sortes d'entités, le Map Server, qui connait les correspondances pour certains préfixes (car les ETR lui ont raconté les préfixes qu'ils servent), et le Map Resolver, qui fait les requêtes (il est typiquement dans l'ITR, ou proche). Quatre messages sont possibles (les messages de contrôle LISP sont encpasulés en UDP, et vers le port 4342) :

  • Map-Register : un ETR informe son Map Server des préfixes EID qu'il sait joindre,
  • Map-Notify : la réponse de l'ETR au message précédent,
  • Map-Request : un ITR (ou bien un outil de débogage comme lig, cf. RFC 6835) cherche les RLOC correspondant à un EID,
  • Map-Reply : un Map Server ou un ETR lui répond.

Un point important de LISP est qu'il peut y avoir plusieurs mécanismes de correspondance EID->RLOC, du moment qu'ils suivent les messages standard du RFC 6833. On pourra donc, dans le cadre de l'expérience LISP, changer de mécanisme pour voir, pour tester des compromis différents. Notre RFC rappele l'existence du système ALT (RFC 6836, fondé, comme BGP sur un graphe. Mais aussi celle d'un mécanisme utilisant une base « plate » (NERD, RFC 6837), un mécanisme arborescent nommé DDT (RFC 8111), des DHT, etc. On pourrait même, dans des déploiements privés et locaux, avoir une base centralisée avec un seul serveur.

ALT, normalisé dans le RFC 6836, est le système de correspondance « historique » de LISP, et il est souvent présenté comme le seul dans les vieux documents. Il repose sur BGP, protocole bien maitrisé par les administrateurs de routeurs, ceux qui auront à déployer LISP. L'idée de base est de connecter les serveurs ALT par BGP sur un réseau virtuel au-dessus de l'Internet.

DDT, dans le RFC 8111, lui, ressemble beaucoup plus au DNS, par sa structuration arborescente des données, et sa racine.

Évidemment, tout l'Internet ne va pas migrer vers LISP instantanément. C'est pour cela que notre RFC mentionne les problèmes de communication avec le reste du monde. Les EID ne sont typiquement pas annoncés dans la table de routage globale de l'Internet. Alors, comment un site pourra-t-il communiquer avec un site LISP ? Le mécanisme décrit dans le RFC 6832 utilise deux nouvelles sortes de routeurs : les PITR (Proxy Ingress Tunnel Router) et les PETR (Proxy Egress Tunnel Router). Le PITR annonce les EID en BGP vers l'Internet, en les agrégeant le plus possible (l'un des buts de LISP étant justement d'éviter de charger la table de routage globale). Il recevra donc les paquets envoyés par les sites Internet classiques et les fera suivre par les procédures LISP normales. A priori, c'est tout : le site LISP peut toujours envoyer des paquets vers l'Internet classiques en ayant mis un EID en adresse IP source. Mais cela peut échouer pour diverse raisons (uRPF, par exemple) donc on ajoute le PETR : il recevra le paquet du site LISP et le transmettra.

Voici pour les principes de LISP. Mais, si vous travaillez au quotidien comme administrateur d'un réseau, vous avez sans doute à ce stade plein de questions concrètes et opérationnelles. C'est le moment de lire la section 4 de ce RFC. Par exemple, la gestion des caches : un routeur LISP ne peut pas faire appel au système de correspondance pour chaque paquet qu'il a à transmettre. Le sous-système des données tuerait complètement le sous-système de contrôle, si un routeur s'avisait de procéder ainsi. Il faut donc un cache, qui va stocker les réponses aux questions récentes. Qui dit cache dit problèmes de cohérence des données, puisque l'information a pu changer entre la requête, et l'utilisation d'une réponse mise en cache. Pour gérer cette cohérence, LISP dispose de divers mécanismes, notamment un TTL (Time To Live) : l'ETR le définit, indiquant combien de temps les données peuvent être utilisées (c'est typiquement 24 h, aujourd'hui).

Autre problème pratique cruciale, la joignabilité des RLOC. C'est bien joli de savoir que telle machine a tel RLOC mais est-ce vrai ? Peut-on réellement lui parler ou bien tous les paquets vont-ils finir dans un trou noir ? Un premier mécanisme pour transporter l'information de joignabilité est les LSB (Locator Status Bits). Transportés dans les paquets LISP, ces bits indiquent si un RLOC donné est joignable par l'ETR qui a envoyé le paquet. Évidemment, eux aussi peuvent être faux, donc, s'il existe une communication bi-directionnelle, il est préférable d'utiliser le mécanisme des numniques. Quand un ITR écrit à un ETR, il met un numnique dans le paquet, que l'ETR renverra dans son prochain paquet. Cette fois, plus de doute, l'ETR est bien joignable. Si l'ITR est impatient et veut une réponse tout de suite, il peut tester activement la joignabilité, en envoyant des Map-Request.

LISP est souvent présenté avec un modèle simplifié où chaque site est servi par un seul ETR, qui connait les EID du site et les annonce au Map Server. Mais, dans la réalité, les sites sérieux ont plusieurs ETR, pour des raisons de résilience et de répartition de charge. Cela soulève le problème de leur synchronisation : ces ETR doivent avoir des configurations compatibles, pour annoncer les mêmes RLOC pour leurs EID. Pour l'instant, il n'existe pas de protocole pour cela, on compte sur une synchronisation manuelle par l'administrateur réseaux.

Enfin, comme LISP repose sur des tunnels, il fait face à la malédiction habituelle des tunnels, les problèmes de MTU. Du moment qu'on encapsule, on diminue la MTU (les octets de l'en-tête prennent de la place) et on peut donc avoir du mal à parler avec les sites qui ont une MTU plus grande, compte-tenu de la prévalence d'erreurs grossières de configuration, comme le filtrage d'ICMP. La section 4.4 de notre RFC décrit le traitement normal de la MTU dans LISP et ajoute que des mécanismes comme celui du RFC 4821 seront peut-être nécessaires.

Dans l'Internet d'aujourd'hui, une préoccupation essentielle est bien sûr la sécurité : d'innombrables menaces pèsent sur les réseaux (section 8 du RFC). Quelles sont les problèmes spécifiques de LISP en ce domaine ? Par exemple, certains systèmes de correspondance, comme DDT, sont de type pull : on n'a pas l'information à l'avance, on va la chercher quand on en a besoin. Cela veut dire qu'un paquet de données (sous-système des données) peut indirectement déclencher un événement dans le sous-système de contrôle (par la recherche d'une correspondance EID->RLOC afin de savoir où envoyer le paquet). Cela peut affecter la sécurité.

D'autant plus que le sous-système de contrôle sera typiquement mis en œuvre dans le processeur généraliste des routeurs, beaucoup moins rapide que les circuits électroniques spécialisés qui servent à la transmission des données. Un attaquant qui enverrait des tas de paquets vers des EID différents pourrait, à un coût très faible pour lui, déclencher plein de demandes à DDT, ralentissant ainsi sérieusement les routeurs LISP. Une mise en œuvre naïve de LISP où toute requête pour un EID absent du cache déclencherait systématiquement une MAP-Request serait très vulnérable. Une limitation du trafic est donc nécessaire.

En parlant du système de correspondance, il représente évidemment un talon d'Achille de LISP. Si son intégrité est compromise, si des fausses informations s'y retrouvent, les routeurs seront trahis et enverront les paquets au mauvais endroit. Et si le système de correspondance est lent ou en panne, par exemple suite à une attaque par déni de service, le routage ne se fera plus du tout (à part pour les EID encore dans les caches des routeurs). On peut donc comparer ce système de correspondance au DNS dans l'Internet classique, par son côté crucial pour la sécurité.

Il faut donc des « bons » Map Server, qui suivent bien le RFC 6833 (notamment sa section 6) et, peut-être dans le futur, des Map Servers qui gèrent l'extension de sécurité LISP-Sec (si son RFC est publié un jour).

Dernier point de sécurité, le fait que LISP puisse faire du routage asymétrique (le chemin d'Alice à Bob n'est pas le même que celui de Bob à Alice). Rien d'extraordinaire à cela, c'est pareil pour lee routage Internet classique, mais il faut toujours se rappeler que cela a des conséquences de sécurité : par exemple, un pare-feu ne verra, dans certains cas, qu'une partie du trafic.

On trouvera plus de détails sur les attaques qui peuvent frapper LISP dans le RFC 7835.

Pour ceux qui sont curieux d'histoire des technologies, l'annexe A du RFC contient un résumé de LISP. Tout avait commencé à Amsterdam en octobre 2006, à l'atelier qui avait donné naissance au RFC 4984. Un groupe de participants s'était alors formé, avait échangé, et le premier Internet-Draft sur LISP avait été publié en janvier 2007. En même temps, et dans l'esprit traditionnel de l'Internet (running code), la programmation avait commencé et les premiers routeurs ont commencé à gérer des paquets LISP en juin 2007.

Le groupe de travail IETF officiel a été ensuite créé, en mars 2009. Les premiers RFC sont enfin sortis en 2013.

LISP n'a pas toujours été comme aujourd'hui ; le protocole initial était plutôt une famille de protocoles, désignés par des numéros, chacun avec des variantes sur le concept de base. Cela permettait de satisfaire tous les goûts mais cela compliquait beaucoup le protocole. On avait LISP 1, où les EID étaient routables dans l'Internet normal (ce qui n'est plus le cas), LISP 1.5 où ce routage se faisait dans un réseau séparé, LISP 2 où les EID n'étaient plus routables, et où la correspondance EID->RLOC se faisait avec le DNS, et enfin LISP 3 où le système de correspondance était nouveau (il était prévu d'utiliser une DHT...). Le LISP final est proche de LISP 3.


Téléchargez le RFC 9299


L'article seul

RFC 9297: HTTP Datagrams and the Capsule Protocol

Date de publication du RFC : Août 2022
Auteur(s) du RFC : D. Schinazi (Google), L. Pardue (Cloudflare)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF masque
Première rédaction de cet article le 8 septembre 2022


Ce RFC est le premier du groupe de travail MASQUE qui développe des techniques pour relayer du trafic IP. Dans ce RFC, il s'agit de faire passer des datagrammes sur HTTP.

Pourquoi, sur HTTP ? Parce que c'est le seul protocole dont on est raisonnablement sûr qu'il passera partout. En bâtissant un service de datagrammes sur HTTP (et non pas directement sur IP), on arrivera à le faire fonctionner à tous les endroits où HTTP fonctionne.

En fait, ce RFC décrit deux mécanismes assez différents, mais qui visent le même but, la transmission de datagrammes sur HTTP. Le premier mécanisme est le plus simple, utiliser HTTP juste pour lancer une session qui utilisera les datagrammes de QUIC, normalisés dans le RFC 9221. (QUIC seul ne passe pas partout, d'où la nécessité d'insérer une couche HTTP.) Ce premier mécanisme dépend de QUIC donc ne marche qu'avec HTTP/3 (RFC 9114). Un second mécanisme est normalisé, dans notre RFC ; nommé Capsule, il permet de faire passer des datagrammes (ou à peu près) sur HTTP/2 (RFC 9113) et HTTP/1 (RFC 9112). Capsule est plus général, mais moins efficace.

Ces mécanismes ne sont pas vraiment prévus pour des utilisations par des applications, mais plutôt pour des extensions à HTTP (RFC 9110, section 16). Par exemple, le service CONNECT (RFC 9110, section 9.3.6) pourrait être doublé par un service équivalent, mais utilisant des datagrammes, au lieu du transfert fiable que fait CONNECT (cf. RFC 9298). Même chose pour les Web sockets du RFC 6455.

La section 2 de notre RFC explique de quels datagrammes on parle. Il s'agit de paquets de données dont l'ordre d'arrivée et l'acheminement ne sont pas garantis, et qui vont sans doute consommer moins de ressources. Sur HTTP/3 (qui utilise QUIC), ils vont utiliser les trames QUIC de type DATAGRAM (RFC 9221). Ce sont les « meilleurs » datagrammes HTTP, ceux qui collent le plus à la sémantique des datagrammes. Sur HTTP/2, tout acheminement de données est garanti. Si on veut faire des datagrammes, il va falloir utiliser le protocole Capsule, décrit dans la section 3. (Notez que HTTP/2 ne garantit pas l'ordre d'arrivée si les datagrammes sont transportés dans des ruisseaux différents.) Et pour HTTP/1 ? Le protocole ne convient guère puisqu'il garantit l'ordre d'arrivée et l'acheminement, justement les propriétés auxquelles on était prêt à renoncer. Là aussi, on se servira de Capsule.

HTTP utilise différentes méthodes pour faire ses requêtes (les deux plus connues sont GET et POST). Les datagrammes ne sont utilisables qu'avec des méthodes qui les acceptent explicitement. Donc, pas de GET ni de POST, plutôt du CONNECT.

Sur HTTP/3, le champ de données du datagramme QUIC aura le format :

HTTP/3 Datagram {
     Quarter Stream ID (i),
     HTTP Datagram Payload (..),
   }
  

Le quarter stream ID est l'identificateur du ruisseau QUIC du client où a été envoyée la requête HTTP, divisé par 4 (ce qu'on peut toujours faire, vu la façon dont sont générés ces identificateurs, RFC 9000, section 2.1).

Ah, et comme les datagrammes ne sont pas acceptés par défaut en HTTP/3, il faudra envoyer au début de la session un paramètre SETTINGS_H3_DATAGRAM (enregistré à l'IANA).

Les capsules, maintenant. Inutiles en HTTP/3, elles sont la seule façon de faire du datagramme en HTTP/1 et HTTP/2. Le protocole Capsule permet d'envoyer des données encodées en TLV sur une connexion HTTP. On indique qu'on va l'utiliser, en HTTP/1 avec le champ Upgrade: (RFC 9110, section 7.8) et en HTTP/2 avec un CONNECT étendu (cf. RFC 8441). Les upgrade tokens (les identificateurs de protocoles utilisés, enregistrés à l'IANA) sont décrits dans la section 16.7 du RFC 9110.

Le format des capsules est décrit en section 3.2 :

Capsule {
     Capsule Type (i),
     Capsule Length (i),
     Capsule Value (..),
   }
  

Les différents types possibles de capsules figurent dans un registre IANA. Une fois le protocole Capsule sélectionné via un upgrade token, on passe du HTTP classique au protocole Capsule. Un premier type de capsule est DATAGRAM (type 0) dont le nom indique bien la sémantique. D'autres types pourront être ajoutés en suivant la procédure « spécification nécessaire » du RFC 8126, sauf les valeurs basses du type (de 0 à 63) qui exigent une action de normalisation, ou bien une approbation par l'IESG.

Si on utilise Capsule, la requête HTTP est accompagnée du champ Capsule-Protocol (un champ structuré, cf. RFC 8941), champ désormais enregistré à l'IANA.

Il existe plusieurs mises en œuvre de ces datagramms HTTP. En logiciel libre, on a :

Notez que le protocole Capsule n'est a priori pas accessible au code JavaScript chargé dans le navigateur Web (il faut pouvoir accéder aux upgrade tokens). Mais rappelez-vous que tout ce mécanisme de datagrammes sur HTTP est conçu pour des extensions de HTTP, pas pour l'application finale.


Téléchargez le RFC 9297


L'article seul

RFC 9293: Transmission Control Protocol (TCP)

Date de publication du RFC : Août 2022
Auteur(s) du RFC : W. Eddy (MTI Systems)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 20 août 2022


Le protocole de transport TCP est l'un des piliers de l'Internet. La suite des protocoles Internet est d'ailleurs souvent appelée TCP/IP, du nom de ses deux principaux protocoles. Ce nouveau RFC est la norme technique de TCP, remplaçant l'antique RFC 793, qui était vieux de plus de quarante ans, plus vieux que la plupart des lecteurices de ce blog. Il était temps de réviser et de rassembler en un seul endroit tous les détails sur TCP.

TCP est donc un protocole de transport. Rappelons brièvement ce qu'est un protocole de transport et à quoi il sert. L'Internet achemine des paquets IP de machine en machine. IP ne garantit pas leur arrivée : les paquets peuvent être perdus (par exemple parce qu'un routeur n'avait plus de place dans ses files d'attente), peuvent être dupliqués, un paquet peut passer devant un autre, pourtant envoyé avant, etc. Pour la grande majorité des applications, ce n'est pas acceptable. La couche de transport est donc chargée de remédier à cela. Première (en partant du bas) couche à être de bout en bout (les routeurs et autres équipements intermédiaires n'y participent pas, ou plus exactement ne devraient pas y participer), elle se charge de suivre les paquets, de les remettre dans l'ordre, et de demander aux émetteurs de ré-émettre si un paquet s'est perdu. C'est donc un rôle crucial, puisqu'elle évite aux applications de devoir gérer ces opérations très complexes. (Certaines applications, par exemple de vidéo, n'ont pas forcément besoin que chaque paquet arrive, et n'utilisent pas TCP.) Le RFC 8095 contient une comparaison détaillée des protocoles de transport de l'IETF.

Avant de décrire TCP, tel que spécifié dans ce RFC 9293, un petit mot sur les normes techniques de l'Internet. TCP avait originellement été normalisé dans le RFC 761 en 1980 (les couches 3 - IP et 4 étaient autrefois mêlées en une seule). Comme souvent sur l'Internet, le protocole existait déjà avant sa normalisation et était utilisé. La norme avait été rapidement révisée dans le RFC 793 en 1981. Depuis, il n'y avait pas eu de révision générale, et les RFC s'étaient accumulés. Comprendre TCP nécessitait donc de lire le RFC 793 puis d'enchainer sur plusieurs autres. Un RFC, le RFC 7414, avait même été écrit dans le seul but de fournir un guide de tous ces RFC à lire. Et il fallait également tenir compte de l'accumulation d'errata. Désormais, la situation est bien plus simple, tout TCP a été consolidé dans un RFC central, notre RFC 9293. (Notez que ce travail de consolidation a été aussi fait pour HTTP et SMTP, qui ne sont plus décrits par les RFC d'origine mais par des versions à jour, mais pas pour le DNS, qui reste le principal ancien protocole qui aurait bien besoin d'une remise à jour complète des documents qui le spécifient.) Ne vous faites toutefois pas d'illusion : malgré ses 114 pages, ce RFC 9293 ne couvre pas tout, et la lecture d'autres RFC reste nécessaire. Notamment, TCP offre parfois des choix multiples (par exemple pour les algorithmes de contrôle de la congestion, une partie cruciale de TCP), qui ne sont pas décrits intégralement dans la norme de base. Voyez par exemple le RFC 7323, qui n'a pas été intégré dans le RFC de base, et reste une extension optionnelle.

Attaquons-nous maintenant à TCP. (Bien sûr, ce sera une présentation très sommaire, TCP est forcément plus compliqué que cela.) Son rôle est de fournir aux applications un flux d'octets fiable et ordonné : les octets que j'envoie à une autre machine arriveront dans l'ordre et arriveront tous (ou bien TCP signalera que la communication est impossible, par exemple en cas de coupure du câble). TCP découpe les données en segments, chacun voyageant dans un datagramme IP. Chaque octet est numéroté (attention : ce sont bien les octets et pas les segments qui sont numérotés) et cela permet de remettre dans l'ordre les paquets, et de détecter les pertes. En cas de perte, on retransmet. Le flux d'octets est bidirectionnel, la même connexion TCP permet de transmettre dans les deux sens. TCP nécessite l'établissement d'une connexion, donc la mémorisation d'un état, par les deux pairs qui communiquent. Outre les tâches de fiabilisation des données (remettre les octets dans l'ordre, détecter et récupérer les pertes), TCP fournit du démultiplexage, grâce aux numéros de port. Ils permettent d'avoir plusieurs connexions TCP entre deux machines, qui sont distinguées par ces numéros de port (un pour la source et un pour la destination) dans l'en-tête TCP. Le bon fonctionnement de TCP nécessite d'édicter un certain nombre de règles et le RFC les indique avec MUST-n où N est un entier. Par exemple, MUST-2 et MUST-3 indiqueront que la somme de contrôle est obligatoire, aussi bien en envoi qu'en vérification à la réception.

Après ces concepts généraux, la section 3 de notre RFC rentre dans les détails concrets, que je résume ici. D'abord, le format de cet en-tête que TCP ajoute derrière l'en-tête IP et devant les données du segment. Il inclut les numéros de port, le numéro de séquence (le rang du premier octet dans les données), celui de l'accusé de réception (le rang du prochain octet attendu), un certain nombre de booléens (flags, ou bits de contrôle, qui indiquent, par exemple, s'il s'agit d'une connexion déjà établie, ou pas encore, ou la fin d'une connexion), la taille de la fenêtre (combien d'octets peuvent être envoyés sans accusé de réception, ce qui permet d'éviter de surcharger le récepteur), une somme de contrôle, et des options, de taille variable (l'en-tête contient un champ indiquant à partir de quand commencent les données). Une option de base est MSS (Maximum Segment Size) qui indique quelle taille de segment on peut gérer. Il existe d'autres options comme les accusés de réception sélectifs du RFC 2018 ou comme le facteur multiplicatif de la taille de fenêtre du RFC 7323.

Avant d'expliquer la dynamique de TCP, le RFC définit quelques variables indispensables, qui font partie de l'état de la connexion TCP. Pour l'envoi de données, ce sont par exemple SND.UNA (ces noms sont là pour comprendre le RFC, mais un programme qui met en œuvre TCP peut évidemment nommer ces variables comme il veut), qui désigne le numéro de séquence du début des données envoyées, mais qui n'ont pas encore fait l'objet d'un accusé de réception, ou SND.NXT, le numéro de séquence du début des données pas encore envoyées ou encore SND.WND, la taille de la fenêtre d'envoi. Ainsi, on ne peut pas envoyer d'octets dont le rang serait supérieur à SND.UNA + SND.WND, il faut attendre des accusés de réception (qui vont incrémenter SND.UNA) ou une augmentation de la taille de la fenêtre. Pour la réception, on a RCV.NXT, le numéro de séquence des prochains paquets si tout est normal, et RCV.WND, la taille de la fenêtre de réception.

TCP est un protocole à état et il a donc une machine à états, décrite en section 3.3.2. Parmi les états, LISTEN, qui indique un TCP en train d'attendre un éventuel pair, ESTAB (ou ESTABLISHED), où TCP envoie et reçoit des données, et plusieurs états qui apparaissent lors de l'ouverture ou de la fermeture d'une connexion.

Et les numéros de séquence ? Un point important de TCP est qu'on ne numérote pas les segments mais les octets. Chaque octet a son numéro et les accusés de réception référencent ces numéros. On n'accuse évidemment pas réception de chaque octet individuel. Les accusés de réception sont cumulatifs ; ils désignent un octet et, implicitement, tous les octets précédents. Quand un récepteur prévient qu'il a bien reçu l'octet N, cela veut dire que tous ceux avant N ont aussi été reçus.

Les numéros ne partent pas de 1 (ni de zéro), ils sont relatifs à un ISN (Initial Sequence Number, rappelez-vous qu'il y a un glossaire, en section 4 du RFC) qui est choisi aléatoirement (pour des raisons de sécurité, cf. RFC 6528) au démarrage de la session. Des logiciels comme Wireshark savent cela et peuvent calculer puis afficher des numéros de séquence qui partent de 1, pour faciliter la lecture.

Les numéros de séquence sont stockés sur 32 bits et il n'y a donc que quatre milliards (et quelques) valeurs possibles. C'était énorme quand TCP a été créé mais cela devient de plus en plus petit, relativement aux capacités des réseaux modernes. Comme TCP repart de zéro quand il atteint le numéro de séquence maximum, il y a un risque qu'un « vieux » paquet soit considéré comme récent. À 1 Gb/s, cela ne pouvait se produire qu'au bout de 34 secondes. Mais à 100 Gb/s, il suffit d'un tiers de seconde ! Les extensions du RFC 7323 deviennent alors indispensables.

Tout le monde sait bien que TCP est un protocole orienté connexion. Cela veut dire qu'il faut pouvoir créer, puis supprimer, les connexions. La section 3.5 de notre RFC décrit cet établissement de connexion, via la fameuse « triple poignée de mains ». En gros, un des TCP (TCP n'est pas client-serveur, et la triple poignée de mains marche également quand les deux machines démarrent la connexion presque en même temps) envoie un paquet ayant l'option SYN (pour synchronization), le second répond avec un paquet ayant les options ACK (accusé de réception du SYN) et SYN, le premier TCP accuse réception. Avec trois paquets, les deux machines sont désormais d'accord qu'elles sont connectées. En d'autres termes (ici, machine A commence) :

  • Machine A ⇒ Machine B : je veux te parler,
  • B ⇒ A : j'ai noté que tu voulais me parler et je veux te parler aussi,
  • A ⇒ B : j'ai noté que tu voulais me parler.

Pour mettre fin à la connexion, un des deux TCP envoie un paquet ayant l'option FIN (pour finish), auquel l'autre répond de même.

Conceptuellement, TCP gère un flux d'octets sans séparation. TCP n'a pas la notion de message. Si une application envoie (en appelant print, write ou autre fonction du langage de programmation utilisé) les octets "AB" puis "CD", TCP transmettra puis livrera à l'application distante les quatre octets "ABCD" dans l'ordre, sans indiquer qu'il y avait eu deux opérations d'écriture sur le réseau. Mais, pour envoyer les données, TCP doit les segmenter en paquets IP distincts. La fragmentation IP n'étant pas bonne pour les performances, et étant peu fiable de toute façon, l'idéal est que ces paquets IP aient une taille juste inférieure à la MTU du chemin. Cela nécessite de découvrir cette MTU (section 3.7.2), ou bien d'adopter la solution paresseuse de faire des paquets de 1 280 octets (la MTU minimum, en IPv6). Comme la solution paresseuse ne serait pas optimale en performances, les mises en œuvre de TCP essaient toutes de découvrir la MTU du chemin. Cela peut se faire avec la méthode PMTUD, décrite dans les RFC 1191 et RFC 8201, mais qui a l'inconvénient de nécessiter qu'ICMP ne soit pas bloqué. Or, beaucoup de middleboxes programmées avec les pieds, ou configurées par des incompétents, bloquent ICMP, empêchant le fonctionnement de PMTUD. Une alternative est PLPMTUD, normalisée dans le RFC 4821, qui ne dépend plus d'ICMP.

Une fois la connexion établie, on peut envoyer des données. TCP va les couper en segments, chaque segment voyageant dans un paquet IP.

Une mise en œuvre de TCP n'envoie pas forcément immédiatement les octets qu'on lui a confiés. Envoyer des petits paquets n'est pas efficace : s'il y a peu de données, les en-têtes du paquet forment la majorité du trafic et, de toute façon, le goulet d'étranglement dans le réseau n'est pas forcément lié au nombre d'octets, il peut l'être au nombre de paquets. Un des moyens de diminuer le nombre de paquets contenant peu d'octets est l'algorithme de Nagle. Le principe est simple : quand TCP reçoit un petit nombre d'octets à envoyer, il ne les transmet pas tout de suite mais attend un peu pour voir si l'application ne va pas lui confier des octets supplémentaires. Décrit dans le RFC 896, et recommandé dans le RFC 1122, cet algorithme est aujourd'hui présent dans la plupart des mises en œuvres de TCP. Notre RFC 9293 le recommande, mais en ajoutant que les applications doivent pouvoir le débrayer. C'est notamment indispensable pour les applications interactives, qui n'aiment pas les délais, même courts. (Sur Unix, cela se fait avec l'option TCP_NODELAY passée à setsockopt.)

Un des rôles les plus importants de TCP est de lutter contre la congestion. Il ne faut pas envoyer le plus d'octets possible, ou alors on risque d'écrouler le réseau (RFC 2914). Plusieurs mécanismes doivent être déployés : démarrer doucement (au début de la connexion, TCP ne connait pas le débit que peut supporter le réseau et doit donc être prudent), se calmer rapidement si on constate que des paquets sont perdus (cela peut être un signe de congestion en aval), etc. Ces mesures pour éviter la congestion sont absolument obligatoires (comme tous les biens communs, l'Internet est vulnérables aux parasites, un TCP égoïste qui ne déploierait pas ces mesures anti-congestion serait un mauvais citoyen du réseau). Elles sont décrites plus précisément dans les RFC 1122, RFC 2581, RFC 5681 et RFC 6298. Notez qu'ils énoncent des principes, mais pas forcément les algorithmes exacts à utiliser, ceux-ci pouvant évoluer (et ils l'ont fait depuis la sortie du RFC 793, voir les RFC 5033 et RFC 8961).

Un point qui surprend souvent les programmeur·ses qui écrivent des applications utilisant TCP est que rien n'indique qu'une connexion TCP est coupée, par exemple si un câble est sectionné. C'est seulement lorsqu'on essaie d'écrire qu'on l'apprendra (ce comportement est une conséquence de la nature sans connexion d'IP ; pourquoi prévenir d'une coupure alors qu'IP va peut-être trouver un autre chemin ?). Si on veut être mis au courant tout de suite, on peut utiliser des keep-alives, des segments vides qui seront envoyés de temps en temps juste pour voir s'ils arrivent. Cette pratique est contestée (entre autre parce qu'elle peut mener à abandonner une connexion qui n'est que temporairement coupée, et aussi parce que, même si les keep-alives passent, cela ne garantit pas que la prochaine écriture de données passera). Notre RFC demande donc que les keep-alives soient désactivés par défaut, et que l'application puisse contrôler leur activation (sur Unix, c'est l'option SO_KEEPALIVE à utiliser avec setsockopt).

Pendant les quarante ans écoulés depuis la sortie du RFC 793, bien des choses ont changé. Des options ont été ajoutées mais on a vu aussi certaines options qui semblaient être des bonnes idées être finalement abandonnées. C'est le cas du mécanisme de données urgentes, qui n'a jamais vraiment marché comme espéré. Une mise en œuvre actuelle de TCP doit toujours le gérer, pour pouvoir parler avec les anciennes, mais on ne peut pas compter dessus (RFC 6093).

On a parlé plusieurs fois de l'utilisation de TCP par les applications. Pour cela, il faut que TCP offre une API à ces applications. Notre RFC ne décrit pas d'API concrète (cela dépend de toute façon du langage de programmation, et sans doute du système d'exploitation). Il se contente d'une description fonctionnelle de l'interface : les services qu'elle doit offrir à l'application. On y trouve :

  • L'ouverture de la connexion, en indiquant l'adresse et le port distant, mais aussi l'adresse locale (MUST-43), pour pouvoir choisir l'adresse si la machine en a plusieurs.
  • L'envoi de données, dont TCP garantit qu'elles arriveront toutes et dans l'ordre.
  • La lecture de données. Rappelez-vous que TCP fournit un flot continu d'octets, deux envois de données feront peut-être une seule lecture ou bien un envoi deux lectures. C'est une des erreurs les plus courante des programmeurs débutants que de penser que s'ils font un write d'un côté, un read de l'autre lira tout ce que le write a écrit et seulement cela.
  • La fermeture propre (avec envoi, et réémission si nécessaire, des données écrites) de la connexion.
  • Et quelques autres services auxiliaires que je ne détaille pas ici (voir la section 3.9.1).

Rappelez-vous que l'API « socket » n'est qu'un des moyens pour l'application de parler à TCP. Et, à propos de cette API, notez que le RFC utilise le terme de socket avec un sens très différent (cf. le glossaire en section 4).

Et l'autre interface, « sous » TCP, l'interface avec la couche réseau (section 3.9.2) ? TCP peut fonctionner avec des couches réseau variées mais, en pratique, c'est toujours IP, dans une de ses deux versions, v4 ou v6. Un des points délicats est le traitement des messages ICMP que TCP peut recevoir. Au minimum, ils doivent être assignés à une connexion existante. Mais cela ne veut pas dire qu'il faut systématiquement agir lors de la réception d'un de ces messages (RFC 5461). Par exemple, il faut ignorer les messages ICMP de répression de la source (RFC 6633). Et il ne faut pas fermer la connexion juste parce qu'on a reçu une erreur ICMP (MUST-56), car elles peuvent être temporaires.

TCP étant un protocole orienté connexion, la connexion va avoir un état, représenté par un automate fini. Ainsi, l'ouverture d'une connexion par le premier TCP va le faire passer par les états CLOSED, SYN-SENT puis enfin ESTABLISHED. Récupérée sur Wikimedia Commons, voici une représentation de cet automate : TCP_state_diagram.jpg

La section 5 de notre RFC décrit les changements depuis le RFC 793. TCP reste le même et des TCP d'« avant » peuvent interopérer avec ceux qui suivent notre RFC récent. Les principaux changements sont :

  • La résolution d'un grand nombre d'errata accumulés depuis quarante ans.
  • La « démobilisation » du mécanisme de données urgentes (cf. RFC 6093).
  • L'incorporation d'une bonne partie des RFC comme le RFC 1011 ou le RFC 1122.

Le RFC 793 avait été écrit par Jon Postel (comme tant de RFC de cette époque), et notre nouveau RFC 9293 lui rend hommage, en estimant que la longue durée de vie du RFC 793 montre sa qualité.

En application des changements de ce nouveau RFC sur TCP, un registre IANA, celui des bits de l'en-tête comme URG (dont on a vu qu'il était désormais démobilisé), a été mis à jour.

La section 7 de notre nouveau RFC 9293 n'avait pas d'équivalent dans l'ancien RFC 793. Elle concerne la sécurité de TCP. TCP, par lui-même, fournit peu de sécurité (il protège quand même un peu contre l'usurpation d'adresse IP et l'injection de trafic, surtout contre un attaquant qui n'est pas sur le chemin, cf. RFC 5961). Par exemple, il ne fournit pas de services cryptographiques, donc pas de confidentialité ou de vraie garantie d'intégrité. (Son concurrent QUIC, lui, intègre systématiquement la cryptographie.) Si on veut davantage de sécurité pour TCP, il faut mettre IPsec en dessous de TCP ou bien TLS au-dessus. TCP a aussi des mécanismes de sécurité qui lui sont propres, comme AO, normalisé dans le RFC 5925 (mais très peu déployé en pratique). Autre expérience qui n'a pas été un succès, tcpcrypt (RFC 8548).

Il reste des attaques contre lesquelles la cryptographie ne fournit pas vraiment de solution. C'est le cas du SYN flooding, ou d'autres attaques par déni de service.

Mëme si on chiffre les données applicatives avec TLS, TCP expose quand même au réseau tout son fonctionnement. Cette vue depuis le réseau (RFC 8546) soulève plusieurs problèmes (elle peut par exemple faciliter des actions contraires à la neutralité du réseau) et c'est pour cela que le plus récent QUIC masque une grande partie de son fonctionnement (ce qui n'a pas été sans entrainer des polémiques). Toujours côté vie privée, le comportement des mises en œuvre de TCP est suffisamment différent pour qu'il soit possible dans certains cas d'identifier le système d'exploitation d'une machine à distance (ce n'est pas forcément grave, mais il faut le savoir).

Pour les programmeurs et programmeuses, l'annexe A du RFC contient différentes observations utiles pour la mise en œuvre concrète de TCP. Par exemple, cette annexe explique que la validation des numéros de séquence des segments TCP entrants, validation qui est nécessaire pour empêcher un grand nombre d'attaques, peut rejeter des segments légitimes. Ce problème n'a pas de solution idéale.

Un autre point intéressant concerne l'algorithme de Nagle. Cet algorithme représente un compromis entre la réactivité de l'application (qui nécessite d'envoyer les données le plus vite possibles) et l'optimisation de l'occupation du réseau (qui justifie d'attendre un peu pour voir si on ne va pas recevoir de nouvelles données à envoyer). Une modification de l'algorithme de Nagle, décrite dans le document draft-minshall-nagle peut rendre le choix moins douloureux.

Enfin, l'annexe B résume sous forme d'un tableau quelles sont les parties de la norme TCP qui doivent être mises en œuvre et quelles sont celles qu'on peut remettre à plus tard.

Si vous voulez sérieusement apprendre TCP, vous pouvez bien sûr lire le RFC en entier, mais il est sans doute plus sage de commencer par un bon livre comme le CNP3.

Un pcap d'une connexion TCP typique est utilisé ici pour illustrer le fonctionnement de TCP (fichier tcp-typique.pcap). Vu par tshark, cela donne :

8.445772 2a01:4f8:c010:7eb7::106 → 2605:4500:2:245b::42 TCP 94 33672 → 443 [SYN] Seq=0 Win=64800 Len=0 MSS=1440 SACK_PERM=1 TSval=285818465 TSecr=0 WS=128
8.445856 2605:4500:2:245b::42 → 2a01:4f8:c010:7eb7::106 TCP 94 443 → 33672 [SYN, ACK] Seq=0 Ack=1 Win=64260 Len=0 MSS=1440 SACK_PERM=1 TSval=3778761402 TSecr=285818465 WS=128
8.534636 2a01:4f8:c010:7eb7::106 → 2605:4500:2:245b::42 TCP 86 33672 → 443 [ACK] Seq=1 Ack=1 Win=64896 Len=0 TSval=285818554 TSecr=3778761402
8.534897 2a01:4f8:c010:7eb7::106 → 2605:4500:2:245b::42 SSLv3 236 Client Hello
8.534989 2605:4500:2:245b::42 → 2a01:4f8:c010:7eb7::106 TCP 86 443 → 33672 [ACK] Seq=1 Ack=151 Win=64128 Len=0 TSval=3778761491 TSecr=285818554
8.548101 2605:4500:2:245b::42 → 2a01:4f8:c010:7eb7::106 TLSv1.2 1514 Server Hello
8.548111 2605:4500:2:245b::42 → 2a01:4f8:c010:7eb7::106 TCP 1514 443 → 33672 [PSH, ACK] Seq=1429 Ack=151 Win=64128 Len=1428 TSval=3778761504 TSecr=285818554 [TCP segment of a reassembled PDU]
8.548265 2605:4500:2:245b::42 → 2a01:4f8:c010:7eb7::106 TLSv1.2 887 Certificate, Server Key Exchange, Server Hello Done
8.636922 2a01:4f8:c010:7eb7::106 → 2605:4500:2:245b::42 TCP 86 33672 → 443 [ACK] Seq=151 Ack=2857 Win=63616 Len=0 TSval=285818656 TSecr=3778761504
8.636922 2a01:4f8:c010:7eb7::106 → 2605:4500:2:245b::42 TCP 86 33672 → 443 [ACK] Seq=151 Ack=3658 Win=62848 Len=0 TSval=285818656 TSecr=3778761504
8.649899 2a01:4f8:c010:7eb7::106 → 2605:4500:2:245b::42 TCP 86 33672 → 443 [FIN, ACK] Seq=151 Ack=3658 Win=64128 Len=0 TSval=285818669 TSecr=3778761504
8.650160 2605:4500:2:245b::42 → 2a01:4f8:c010:7eb7::106 TCP 86 443 → 33672 [FIN, ACK] Seq=3658 Ack=152 Win=64128 Len=0 TSval=3778761606 TSecr=285818669
8.739117 2a01:4f8:c010:7eb7::106 → 2605:4500:2:245b::42 TCP 86 33672 → 443 [ACK] Seq=152 Ack=3659 Win=64128 Len=0 TSval=285818758 TSecr=3778761606
  

Ici, 2a01:4f8:c010:7eb7::106 (une sonde RIPE Atlas) veut faire du HTTPS (donc, port 443) avec le serveur 2605:4500:2:245b::42. Tout commence par la triple poignée de mains (les trois premiers paquets, SYN, SYN+ACK, ACK). Une fois la connexion établie, tshark reconnait que les machines font du TLS mais, pour TCP, ce ne sont que des données applicatives (contrairement à QUIC, TCP sépare connexion et chiffrement). On note qu'il n'y a pas eu d'optimisation des accusés de réception. Par exemple, l'accusé de réception du ClientHello TLS voyage dans un paquet séparé, alors qu'il aurait pu être inclus dans la réponse applicative (le ServerHello), probablement parce que celle-ci a mis un peu trop de temps à être envoyée. À la fin de la connexion, chaque machine demande à terminer (FIN). Une analyse automatique plus complète, avec tshark -V figure dans tcp-typique.txt.

Ah, au fait, si vous avez pu lire cet article, c'est certainement grâce à TCP… (Ce blog ne fait pas encore de HTTP sur QUIC…).


Téléchargez le RFC 9293


L'article seul

RFC 9287: Greasing the QUIC bit

Date de publication du RFC : Août 2022
Auteur(s) du RFC : M. Thomson (Mozilla)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF quic
Première rédaction de cet article le 30 août 2022


Dans un monde idéal, nos flux de données sur l'Internet passeraient sans problème et sans être maltraitées par les éléments intermédiaires du réseau. Mais dans le monde réel, de nombreuses middleboxes examinent le trafic et interfèrent avec lui. Les machines émettrices de trafic doivent donc se protéger et une des techniques les plus courantes est le chiffrement : si la middlebox ne peut pas comprendre ce qui est envoyé, elle ne pourra pas interférer. Le protocole de transport QUIC chiffre donc le plus possible. Mais une partie du trafic reste non chiffrée. Une des techniques pour empêcher que les middleboxes ne le lisent et ne prennent des décisions déplorables fondées sur ces informations transmises en clair est le graissage : on fait varier les données le plus possible. Ce RFC normalise une possibilité de graisser un bit de l'en-tête QUIC qui était fixe auparavant.

L'un des principes de conception de QUIC est de diminuer le plus possible la vue depuis le réseau (RFC 8546) ; les éléments intermédiaires, comme les routeurs ne doivent avoir accès qu'à ce qui leur est strictement nécessaire, le reste étant chiffré, pour leur éviter toute tentation. QUIC définit (dans le RFC 8999) des invariants, des informations qui seront toujours vraies même pour les futures versions de QUIC (le RFC 9000 définit QUIC version 1, pour l'instant la seule version). En dehors de ces invariants, tout peut… varier et les équipements intermédiaires du réseau ne doivent pas en tenir compte. Si tous suivaient ce principe, on préserverait la neutralité du réseau, et on éviterait l'ossification (cf. RFC 9170). Mais, en pratique, on sait que ce n'est pas le cas et que toute information visible depuis le réseau sera utilisée par les middleboxes, ce qui peut rendre difficile les évolutions futures (TLS a par exemple beaucoup souffert de ce problème, d'où le RFC 8701, le premier à avoir formalisé ce concept de graissage).

Or, QUIC a un bit qui n'est pas cité dans les invariants du RFC 8999 mais qui est fixe et peur servir à différencier QUIC d'autres protocoles. On l'appele d'ailleurs souvent le « bit QUIC » (même si ça n'est pas son nom officiel, qui est fixed bit, cf. RFC 9000, sections 17.2 et 17.3). Si les middleboxes s'en servent pour appliquer un traitement particulier à QUIC, les futures versions de QUIC ne pourront pas utiliser ce bit pour autre chose (rappelez-vous qu'il ne fait pas partie des invariants).

Notre RFC ajoute donc à QUIC une option pour graisser ce bit, c'est-à-dire pour le faire varier au hasard, décourageant ainsi les middleboxes d'en tenir compte. Un nouveau paramètre de transport QUIC (ces paramètres sont définis dans le RFC 9000, section 7.4) est créé, grease_quic_bit (et ajouté au registre IANA). Lorsqu'il est annoncé à l'ouverture de la connexion QUIC, il indique que ce bit est ignoré et que le pair à tout intérêt à le faire varier.

Les paquets initiaux de la connexion (Initial et Handshake) doivent garder le bit QUIC à 1 (puisqu'on n'a pas encore les paramètres de la connexion), sauf si on reprend une ancienne connexion (en envoyant un jeton, cf. RFC 9000, section 19.7).

Tout le but de ce graissage est de permettre aux futures versions de QUIC (v2, 3, etc) d'utiliser ce bit qui était originellement fixe. Ces futures versions, ou tout simplement des extensions à QUIC négociées au démarrage de la connexion, pourront donc utiliser ce bit (lui donner une sémantique). Le RFC leur recommande d'annoncer quand même le paramètre grease_quic_bit, ce qui permettra de graisser même si la future extension n'est pas gérée par le partenaire.

Le RFC note enfin que ce graissage rend plus difficile d'identifier les flux de données QUIC au milieu de tout le trafic. C'est bien sûr le but, mais cela peut compliquer certains activités d'administration réseau. Un futur RFC explique plus en détail cette situation.

Apparemment, plusieurs mises en œuvre de QUIC gèrent déjà ce graissage.


Téléchargez le RFC 9287


L'article seul

RFC 9285: The Base45 Data Encoding

Date de publication du RFC : Août 2022
Auteur(s) du RFC : P. Faltstrom (Netnod), F. Ljunggren (Kirei), D. van Gulik (Webweaving)
Pour information
Première rédaction de cet article le 10 août 2022


Ce RFC décrit un encodage en texte de données binaires, l'encodage Base45. Proche conceptuellement d'encodages comme Base64, il est, par exemple, beaucoup utilisé pour le code QR.

Ces codes QR ne permettent pas de stocker directement des données binaires quelconques car le contenu sera toujours interprété comme du texte. Il est donc nécessaire d'encoder et c'est le rôle de Base45. Il existe bien sûr d'innombrables autres mécanismes d'encodage en texte, comme Base16, Base32 et Base64, spécifiés dans le RFC 4648 mais Base45 est plus efficace pour les codes QR, qui réencodent ensuite.

Base45 utilise un sous-ensemble d'ASCII, de 45 caractères (d'où son nom). Deux octets du contenu binaire sont encodés en trois caractères de ce sous-ensemble. Par exemple, deux octets nuls donneront la chaine de caractères "000". Regardons tout de suite avec le module Python base45 :


% pip3 install base45
% python3             
>>> import base45
>>> base45.b45encode(b'Bonjour, tout le monde')
b'.H86/D34ENJES4434ESUETVDL44-3E6VC'
>>> 

  

Et décodons avec le module Elixir base45 :

    
% iex -S mix
iex(1)> Base45.decode(".H86/D34ENJES4434ESUETVDL44-3E6VC")
"Bonjour, tout le monde"

C'est parfait, tout le monde est d'accord. Ici, évidemment, la chaine originale n'avait pas vraiment besoin d'être encodée donc on va essayer avec du binaire, les trois octets 42, 1 et 6, encodage en Elixir, décodage en Python :

    
iex(1)> Base45.encode(<<42, 1, 6>>)
"/D560"

>>> base45.b45decode("/D560")
b'*\x01\x06'

  

Encore une fois, tout va bien, Elixir a encodé les trois octets du binaire en quatre caractères, que Python a su décoder (l'astérisque est affiché car son code ASCII est 42).

Je vous laisse découvrir l'algorithme complet (il est assez simple) dans la section 3 du RFC. Si vous le programmez vous-même (ce qui n'est sans doute pas une bonne idée, il existe déjà de nombreuses mises en œuvre), attention aux cas limites comme un binaire d'un seul octet, ou comme une chaine à décoder qui compte des caractères invalides. Ici, un essai avec un caractère invalide, le signe égal :


% python3
>>> import base45
>>> base45.b45decode("AAAA=")
Traceback (most recent call last):
  File "/home/stephane/.local/lib/python3.8/site-packages/base45/__init__.py", line 30, in b45decode
    buf = [BASE45_DICT[c] for c in s.rstrip("\n")]
  File "/home/stephane/.local/lib/python3.8/site-packages/base45/__init__.py", line 30, in <listcomp>
    buf = [BASE45_DICT[c] for c in s.rstrip("\n")]
KeyError: '='

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/stephane/.local/lib/python3.8/site-packages/base45/__init__.py", line 54, in b45decode
    raise ValueError("Invalid base45 string")
ValueError: Invalid base45 string

  

Pensez à tester votre code avec de nombreux cas variés. Le RFC cite l'exemple des chaines "FGW" (qui se décode en une paire d'octets valant chacun 255) et "GGW" qui, quoique proche de la précédente et ne comportant que des caractères de l'encodage Base45 est néanmoins invalide (testez-la avec votre décodeur). Le code de test dans le module Elixir donne des idées de tests utiles (certains viennent de bogues détectées pendant le développement). Regardez test/base45_test.exs.

Et, comme toujours, lorsque vous recevez des données venues de l'extérieur, soyez paranoïaques dans le décodage ! Un code QR peut être malveillant et chercher à activer une bogue dans le décodeur (section 6 du RFC).

Enfin, le RFC rappelle qu'une chaine encodée n'est pas forcément directement utilisable comme URL, elle peut comporter des caractères qui ne sont pas sûrs, il faut donc encore une étape d'encodage si on veut en faire un URL.

Compte tenu de l'importance des codes QR, on trouve des mises en œuvre de Base45 un peu partout. J'ai par exemple cité celle en Python. Si vous programmez en Elixir, il y a une bibliothèque sur Hex (écrite en Erlang) mais aussi ma bibliothèque (aux performances très basses).

Sinon, si vous cherchez un bon article d'explication sur Base45, je recommande celui-ci.


Téléchargez le RFC 9285


L'article seul

RFC 9267: Common Implementation Anti-Patterns Related to Domain Name System (DNS) Resource Record (RR) Processing

Date de publication du RFC : Juillet 2022
Auteur(s) du RFC : S. Dashevskyi, D. dos Santos, J. Wetzels, A. Amri (Forescout Technologies)
Pour information
Première rédaction de cet article le 14 septembre 2022


Comme chacun·e sait, l'Internet est une jungle (les politiciens ajouteraient « une jungle Far-West de non-droit qu'il faut civiliser »). Par exemple, les logiciels qui parlent avec les vôtres ne sont pas toujours correctement écrits, voire ils sont franchement malveillants. Le code de votre côté doit donc être robuste, voire paranoïaque, et penser à tout. Ce RFC décrit quelques problèmes qui ont été observés dans des logiciels mettant en œuvre le DNS et explique comment ne pas refaire la même erreur.

Le RFC ne parle pas de failles DNS mais de failles dans les programmes DNS, ce qui est très différent (mais la différence est souvent oubliée dans les médias). Le protocole lui-même n'était pas en cause dans ces cas, ce sont juste les logiciels qui avaient des bogues. Les cas sont nombreux, par exemple SIGRed (CVE-2020-1350) ou DNSpooq (CVE-2020-25681 à CVE-2020-25687). Ces problèmes frappent notamment souvent dnsmasq (personnellement, je n'ai jamais compris pourquoi ce logiciel était si utilisé, mais c'est une autre histoire).

Plusieurs vulnérabilités ont concerné l'analyse des enregistrements DNS (RR = Resource Record). Les risques lors de cette analyse devraient être bien connus, la première faille documentée l'ayant été en 2000 (CVE-2000-0333) ! Tout logiciel qui analyse des enregistrements DNS (client, serveurs, mais aussi pare-feux, IDS, etc) peut tomber dans ces pièges, d'où l'importance de les documenter. C'était déjà fait dans l'Internet-Draft draft-ietf-dnsind-local-compression et dans le RFC 5625 mais c'était perdu au milieu d'autres choses donc notre RFC choisit d'enfoncer le clou.

Il commence par le grand classique des bogues de logiciels DNS : le traitement des pointeurs de compression. Pour gagner quelques octets, à l'époque où ça comptait, le DNS prévoit (RFC 1035, section 4.1.4) qu'on peut, dans un enregistrement DNS, remplacer tout ou partie d'un nom de domaine par un pointeur vers un autre endroit du paquet. Ainsi, si on a tous ses serveurs qui se terminent par les mêmes composants (comme c'est le cas, par exemple, de la racine), on peut ne mettre ces composants qu'une fois, et pointer vers eux partout ailleurs. Évidemment, si vous êtes programmeuse ou programmeur, vous avez déjà vu le piège : les pointeurs, c'est dangereux. Ils peuvent pointer en dehors du paquet, ou pointer vers eux-même, par exemple. Si on suit aveuglément un pointeur, un déni de service est possible, si on tape en dehors de la mémoire allouée ou bien si on se lance dans une boucle sans fin.

Rentrons dans les détails. Le RFC 1035 nous dit que l'octet qui indique la longueur d'un composant doit valoir moins de 64 (la taille maximale d'un composant), donc avoir les deux bits de plus fort poids à zéro. S'ils sont tous les deux à un, cela indique qu'on a un pointeur. Cet octet et le suivant (privés des deux bits de plus fort poids) sont alors un pointeur, le nombre d'octets depuis le début du message. On voit qu'on peut atteindre 16 383 octets (2 ** 14 - 1), largement assez pour sortir de la mémoire allouée pour le paquet, avec les conséquences qu'on imagine. Cela s'est produit en vrai (CVE-2020-25767, CVE-2020-24339 et CVE-2020-24335).

Autre exemple amusant cité par le RFC, le cas d'un pointeur pointant sur lui-même. Soit un message DNS minimal. Le premier composant est à 12 octets du début du message. Si on y met les octets 0xC0 et 0x0C, on aura un pointeur (0xC0 = 11000000, les deux bits de plus fort poids à un) qui vaut 12 (0xC0 0x0C moins les deux bits les plus significatifs = 0000000000001100 = 12). Le pointeur pointera alors sur lui-même, entrainant le logiciel DNS imprudent dans une boucle sans fin. Ça aussi, ça s'est déjà produit (CVE-2017-9345).

Dernier exemple amusant avec des pointeurs, le pointeur qui va mener à un nombre infini de composants. L'attaquant (ou le programmeur maladroit) met dans le message un composant suivi d'un pointeur qui revient au début de ce composant. Si le composant était test, un analyseur DNS imprudent va créer le nom de domaine test.test.test.test… avant de tomber à court de mémoire, ou bien, dans un langage de programmation comme C, d'écrire dans une autre zone de la mémoire, ce qui peut mener à un RCE. Notez que les pointeurs ne devraient pas pointer vers un pointeur : ça n'a aucun intérêt pratique et c'est dangereux, mais le RFC 1035 ne l'interdit pas explicitement. Une alternative est de tester le nombre de fois qu'on a suivi un pointeur ou, encore mieux, de vérifier que le pointeur ne pointe qu'en avant de lui-même.

Notez que le problème de la répétition infinie d'un composant pourrait également être évité en s'assurant que le nom de domaine reste en dessous de sa taille maximale, 255 octets (section 3 du RFC).

Mais il n'y a pas que les pointeurs. Un nom de domaine doit être terminé par un octet nul, indiquant la racine. Ainsi, le nom afnic.fr est encodé 0x05 0x61 0x66 0x6E 0x69 0x63 ("afnic") 0x02 0x66 0x72 ("fr") 0x00 (la racine). Que se passe-t-il si l'octet nul final manque ? Certains programmes en C ont été assez imprudents pour tenter de traiter le nom de domaine avec des routines comme strlen, qui comptent sur un octet nul pour terminer les données (section 4 de notre RFC). Le développeur qui ne veut pas refaire des failles comme CVE-2020-25107, CVE-2020-17440, CVE-2020-24383 ou CVE-2020-27736 devrait utiliser strnlen ou une autre méthode sûre.

On n'a pas terminé. Lorsqu'on traite une réponse DNS, les enregistrements incluent des données. Leur longueur est donné par un champ RDLENGTH de deux octets, qui précède les données (section 5). Si un analyseur DNS ne fait pas attention, la longueur indiquée peut être supérieure à la taille du paquet. Un programme qui, bêtement, lirait RDLENGTH puis ferait un read() de la longueur indiquée aurait de fortes chances de taper en dehors de la mémoire accessible (CVE-2020-25108, CVE-2020-24336 et CVE-2020-27009).

Ah, et le RFC n'en parle pas, mais l'analyse des options EDNS (RFC 6891) offre également ce genre de pièges. Une option est encodée en TLV et une longueur invalide peut mener à lire les valeurs en dehors du paquet.

Un problème du même genre est décrit dans la section 6 du RFC. Un message DNS comprend plusieurs sections (Question, Réponse, Autorité, Additionnelle) et le nombre d'enregistrements par section est indiqué au début du message DNS. Ces nombres (count) peuvent également être faux et ne doivent pas être utilisés aveuglément, sinon, on aura des malheurs du genre CVE-2020-25109, CVE-2020-24340, CVE-2020-24334 ou CVE-2020-27737.

C'est en raison de tous ces risques qu'il faut tester que ses programmes résistent bien à des messages DNS mal formés. Par exemple, le serveur faisant autorité Drink, écrit en Elixir, a dans ses jeux de tests de tels messages. Regardez par exemple drink_parsing_test.exs. Un exemple d'un tel test, pour le problème de boucle sans fin sur des pointeurs, décrit en section 2 du RFC, est :

    
  test "pointerloop1" do # RFC 9267, section 2
    result = Drink.Parsing.parse_request(<<@id::unsigned-integer-size(16),
      @request::unsigned-integer-size(16),
      1::unsigned-integer-size(16), # QDcount
      0::unsigned-integer-size(16), # ANcount
      0::unsigned-integer-size(16), # NScount
      0::unsigned-integer-size(16), # ARcount
      0xc0::unsigned-integer-size(8), # First label of the question
				      # section starts with a
				      # compression pointer to itself.
      0x0c::unsigned-integer-size(8),
      @mx::unsigned-integer-size(16),
      @in_class::unsigned-integer-size(16)
      >>, 
      false)
    assert result == {:error, :badDNS}    
  end

  

On fabrique un paquet DNS avec le pointeur invalide, et on l'analyse. Le sous-programme parse_request ne doit pas tourner sans fin, et doit renvoyer une erreur.

Un test du même genre en Python, où on envoie un message DNS avec un pointeur pointant sur lui-même (et on espère que ça n'aura pas tué le serveur qui le reçoit) :

id = 12345
misc = 0 # opcode 0, all flags zero 
data = struct.pack(">HHHHHHBB", id, misc, 1, 0, 0, 0, 0xc0, 0x0c)
s.sendto(data, sockaddr)
  

Téléchargez le RFC 9267


L'article seul

RFC 9260: Stream Control Transmission Protocol

Date de publication du RFC : Juin 2022
Auteur(s) du RFC : R. Stewart (Netflix), M. Tüxen (Münster Univ. of Appl. Sciences), K. Nielsen (Kamstrup A/S)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF twvwg
Première rédaction de cet article le 6 juin 2022


Une des particularités du protocole IP est que vous avez plusieurs protocoles de transport disponibles. TCP et UDP sont les plus connus mais SCTP, normalisé dans notre RFC, est également intéressant. C'est un protocole déjà ancien (il date de 2000) et ce RFC remplace son prédécesseur, le RFC 4960. Beaucoup de changements de détails, mais rien de crucial.

SCTP ressemble plutôt à TCP, notamment par le fait qu'il fournit un transport fiable. Mais il a plusieurs différences :

  • il ne gère pas un flot d'octets continu mais une série de messages, bien séparés,
  • il gère plusieurs flux de données séparés, qui partagent le même contrôle de congestion mais gèrent à part les pertes et retransmissions (un peu comme QUIC),
  • il gère le cas où la machine a plusieurs adresses IP, ce qui lui fournit normalement plus de redondance, si on est connecté à plusieurs réseaux.

Cette dernière possibilité le rapproche des protocoles qui séparent l'identificateur et le localisateur et lui permet de gérer proprement le multihoming. Cela se fait en indiquant, au début du contact, toutes les adresses IP (autrefois, il y avait même les noms de domaines, cf. la section 3.3.2.1.4) de la machine.

SCTP tient également compte de l'expérience acquise avec TCP. par exemple, l'établissement d'une connexion (que SCTP nomme association) se fait avec un échange de quatre paquets (et non pas trois comme avec TCP), pour offrir une meilleure protection contre les dénis de service. Les SYN cookies, un ajout plus ou moins bancal en TCP, sont ici partie intégrante du protocole.

SCTP est surtout issu des demandes du monde de la téléphonie sur IP, qui avait besoin d'un tel protocole pour la signalisation mais il peut être aussi utilisé dans d'autres domaines.

Un excellent article du Linux Journal explique bien SCTP.

SCTP est depuis longtemps mis en œuvre dans Linux et dans FreeBSD. De même, des programmes de débogage comme Wireshark sont capables de décoder et d'afficher le SCTP. Voici par exemple un pcap entre deux machines dont l'une a envoyé (trame 3) la chaîne de caractères « toto ». (Vous avez également la version texte de ce dialogue.) Des exemples de programmes de tests SCTP se trouvent dans mon article sur le RFC 3286.

Comme tout « nouveau » protocole de transport, SCTP est handicapé par des coupe-feux mal programmés et/ou mal configurés. L'Internet s'ossifiant de plus en plus, il devient très difficile de déployer un nouveau protocole de transport. D'où le RFC 6951, pour faire tourner SCTP sur UDP (comme ce que fait QUIC).

Les changements qu'introduit ce nouveau RFC ne modifient pas en profondeur le protocole mais corrigent les nombreux problèmes survenus pendant ses premières années d'utilisation. Le RFC 8540 donne la liste complète des problèmes corrigés.


Téléchargez le RFC 9260


L'article seul

RFC 9255: The 'I' in RPKI Does Not Stand for Identity

Date de publication du RFC : Juin 2022
Auteur(s) du RFC : R. Bush (Arrcus & IIJ Research), R. Housley (Vigil Security)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sidrops
Première rédaction de cet article le 15 juin 2022


Un très court RFC pour un simple rappel, qui ne devrait même pas être nécessaire : les identités utilisées dans la RPKI, la base des identités qui sert aux techniques de sécurisation de BGP, n'ont pas de lien avec les identités attribuées par l'État et ne doivent pas être utilisées pour, par exemple, signer des documents « officiels » ou des contrats commerciaux.

Le RFC 6480 décrit cette RPKI : il s'agit d'un ensemble de certificats et de signatures qui servent de base pour des techniques de sécurité du routage comme les ROA du RFC 6482 ou comme le BGPsec du RFC 8205. Les objets de la RPKI servent à établir l'autorité sur des ressources Internet (INR, Internet Number Resources, comme les adresses IP et les numéros d'AS). Le RFC 6480, section 2.1, dit clairement que cela ne va pas au-delà et que la RPKI ne prétend pas être la source d'identité de l'Internet, ni même une source « officielle ».

Prenons un exemple concret, un certificat choisi au hasard dans les données du RIPE-NCC (qu'on peut récupérer avec rsync en rsync://rpki.ripe.net/repository). Il est au format DER donc ouvrons-le :

%  openssl x509 -inform DER -text -in  ./DEFAULT/ztLYANxsM7afpHKR4vFbM16jYA8.cer
Certificate:
    Data:
        ...    
        Serial Number: 724816122963 (0xa8c2685453)
        Validity
            Not Before: Jan  1 14:04:04 2022 GMT
            Not After : Jul  1 00:00:00 2023 GMT
        Subject: CN = ced2d800dc6c33b69fa47291e2f15b335ea3600f
	...
        X509v3 extensions:
            ...
            sbgp-ipAddrBlock: critical
                IPv4:
                  51.33.0.0/16
                  ...
            sbgp-autonomousSysNum: critical
                Autonomous System Numbers:
                  206918
                  ...
  

Je n'ai pas tout montré, mais seulement les choses importantes :

  • Il n'y a pas de vraie identité dedans, le sujet a manifestement été généré automatiquement,
  • Il couvre un certain nombre de ressources (INR, Internet Number Resources), comme le préfixe IP 51.33.0.0/16, utilisant les extensions du RFC 3779.

Ce certificat dit simplement que l'entité qui a la clé privée (RFC 5280) correspondante (une administration britannique, dans ce cas) a autorité sur des ressources comme l'AS 206918. Rien d'autre.

Mais, apparemment, certaines personnes n'avaient pas bien lu le RFC 6480 et croyaient que cet attirail PKIesque leur permettait également de signer des documents sans lien avec les buts de la RPKI, voire n'ayant rien à voir avec le routage. Et d'autant plus que des gens croient que le I dans RPKI veut dire Identity (il veut en fait dire Infrastructure). Il a ainsi été suggéré que les clés de la RPKI pouvaient être utilisées pour signer des LOA demandant l'installation d'un serveur dans une baie.

Pourquoi est-ce que cela serait une mauvaise idée ? Il y a plusieurs raisons mais la principale est qu'utiliser la RPKI pour des usages en dehors du monde restreint du routage Internet est que cela exposerait les AC de cette RPKI à des risques juridiques qu'elles n'ont aucune envie d'assumer. Et cela compliquerait les choses, obligeant sans doute ces AC à déployer des processus bureaucratiques bien plus rigides. Si on veut connaitre l'identité officielle (que le RFC nomme à tort « identité dans le monde réel ») d'un titulaire de ressources Internet, on a les bases des RIR, qu'on interroge via RDAP ou autres protocoles. (C'est ainsi que j'ai trouvé le titulaire de 51.33.0.0/16.) Bien sûr, il y a les enregistrements Ghostbusters du RFC 6493 mais ils sont uniquement là pour aider à trouver un contact opérationnel, pas pour indiquer l'identité étatique du titulaire. Même les numéros d'AS ne sont pas l'« identité » d'un acteur de l'Internet (certains en ont plusieurs).

Notons qu'il y a d'autres problèmes avec l'idée de se servir de la RPKI pour signer des documents à valeur légale. Par exemple, dans beaucoup de grandes organisations, ce ne sont pas les mêmes personnes qui gèrent le routage et qui gèrent les commandes aux fournisseurs. Et, au RIPE-NCC, les clés privées sont souvent hébergées par le RIPE-NCC, pas par les titulaires, et le RIPE-NCC n'a évidemment pas le droit de s'en servir pour autre chose que le routage.

Bref, n'utilisez pas la RPKI pour autre chose que ce pour quoi elle a été conçue.


Téléchargez le RFC 9255


L'article seul

RFC 9250: DNS over Dedicated QUIC Connections

Date de publication du RFC : Mai 2022
Auteur(s) du RFC : C. Huitema (Private Octopus), S. Dickinson (Sinodun IT), A. Mankin (Salesforce)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dprive
Première rédaction de cet article le 22 mai 2022


Ce nouveau RFC complète la série des mécanismes de protection cryptographique du DNS. Après DoT (RFC 7858) et DoH (RFC 8484), voici DoQ, DNS sur QUIC. On notera que bien que QUIC ait été conçu essentiellement pour les besoins de HTTP, c'est le DNS qui a été la première application normalisée de QUIC.

Fonctionnellement, DoQ est très proche de ses prédécesseurs, et offre les mêmes services de sécurité, confidentialité, grâce au chiffrement, et authentification du serveur, via le certificat de celui-ci. L'utilisation du transport QUIC permet quelques améliorations, notamment dans le « vrai » parallélisme. Contrairement à DoT (RFC 7858) et DoH (RFC 8484), DoQ peut être utilisé pour parler à un serveur faisant autorité aussi bien qu'à un résolveur.

Notez que le terme de DoQ (DNS over QUIC) n'apparait pas dans le RFC de terminologie DNS, le RFC 8499. Il sera normalement dans son successeur.

Logiquement, DoQ devrait faire face aux mêmes problèmes politiques que ceux vécus par DoH (voir aussi mon article dans Terminal) mais cela n'a pas été encore le cas. Il faut dire qu'il y a peu de déploiements (ne comptez pas installer DoQ comme serveur ou client tout de suite, le code est loin d'être disponible partout).

Le cahier des charges de DoQ est (sections 1 et 3 du RFC) :

  • Protection contre les attaques décrites dans le RFC 9076.
  • Même niveau de protection que DoT (RFC 7858, avec notamment les capacités d'authentification variées du RFC 8310). Rappelez-vous que QUIC est toujours chiffré (actuellement avec TLS, cf. RFC 9001).
  • Meilleure validation de l'adresse IP source qu'avec le classique DNS sur UDP, grâce à QUIC.
  • Pas de limite de taille des réponses, quelle que soit la MTU du chemin.
  • Diminution de la latence, toujours grâce à QUIC et notamment ses possibilités de connexion 0-RTT (RFC 9000, section 5), ses procédures de récupération en cas de perte de paquets (RFC 9002) et la réduction du head-of-line blocking, chaque couple requête/réponse étant dans son propre ruisseau.

En revanche, DoQ n'esssaie pas de :

  • Contourner le blocage de QUIC que font certaines middleboxes (DoH est meilleur, de ce point de vue). La section 3.3 du RFC détaille cette limitation de DoQ : il peut être filtré trop facilement, son trafic se distinguant nettement d'autres trafics.
  • Ou de permettre des messages du serveur non sollicités (pour cela, il faut utiliser le RFC 8490).

DoQ utilise QUIC. QUIC est un protocole de transport généraliste, un concurrent de TCP. Plusieurs protocoles applicatifs peuvent utiliser QUIC et, pour chacun de ces protocoles, cela implique de définir comment sont utilisés les ruisseaux (streams) de QUIC. Pour HTTP/3, cela a été fait dans le RFC 9113, publié plus tard. Ironiquement, le DNS est donc le premier protocole à être normalisé pour une utilisation sur QUIC. Notez qu'une autre façon de faire du DNS sur QUIC est de passer par DoH et HTTP/3 (c'est parfois appelé DoH3, terme trompeur) mais cette façon n'est pas couverte dans notre RFC, qui se concentre sur DoQ, du DNS directement sur QUIC, sans HTTP.

La spécification de DoQ se trouve en section 4. Elle est plutôt simple, DoQ étant une application assez directe de QUIC. Comme DoQ utilise QUIC, il y a forcément un ALPN, en l'occurrence via l'identificateur doq.

Le port, quant à lui, est par défaut 853, également nommé domain-s. C'est donc le même que DoT, et aussi le même que le DNS sur DTLS (RFC 8094, protocole expérimental, jamais vraiment mis en œuvre et encore moins déployé, et qui est de toute façon distinguable du trafic QUIC, cf. section 17.2 du RFC 9000). Bien sûr, un client et un serveur DNS majeurs et vaccinés peuvent toujours se mettre d'accord sur un autre port (mais pas 53, réservé au DNS classique). Cette utilisation d'un port spécifique à DoQ est un des points qui le rend vulnérable au filtrage, comme vu plus haut. Utiliser 443 peut aider. (Le point a été chaudement discuté à l'IETF, entre défenseurs de la vie privée et gestionnaires de réseau qui voulaient pouvoir filtrer facilement les protocoles de leur choix. Si on utilise le port 443, il faut se rappeler que l'ALPN est pour l'instant en clair, la lutte de l'épée et de la cuirasse va donc continuer.)

Plus important, la question de la correspondance entre les messages DNS et les ruisseaux QUIC. La règle est simple : pour chaque requête DNS, un ruisseau est créé. La première requête sur une connexion donnée sera donc sur le ruisseau 0 (RFC 9000, section 2.1), la deuxième sur le ruisseau 4, etc. Si les connexions QUIC sont potentiellement de longue durée, en revanche, les ruisseaux ne servent qu'une fois. Le démultiplexage des réponses est assuré par QUIC, pas par le DNS (et l'identificateur de requête DNS est donc obligatoirement à zéro, puisqu'inutile). Le parallélisme est également fourni par QUIC, client et serveur n'ont rien de particulier à faire. Il est donc recommandé de ne pas attendre une réponse pour envoyer les autres questions. Les messages DNS sont précédés de deux octets indiquant leur longueur, comme avec TCP.

Comme avec TCP, client et serveur ont le droit de garder un œil sur les ruisseaux et les connexions inactifs, et de les fermer d'autorité. La section 5.5 donne des détails sur cette gestion de connexion, mais le RFC 7766 est également une bonne lecture (voir aussi le RFC 9103 pour le cas des transferts de zones).

DoQ introduit quelques codes d'erreur à lui (RFC 9000, section 20.2), comme DOQ_INTERNAL_ERROR (quelque chose s'est mal passé), DOQ_PROTOCOL_ERROR (quelqu'un n'a pas lu le RFC, par exemple l'identificateur de requête était différent de zéro) ou DOQ_EXCESSIVE_LOAD (trop de travail tue le travail).

Un des gros avantages de QUIC est le 0-RTT, où des données sont envoyées dès le premier paquet, ce qui réduit nettement la latence. Cela implique que le client ait déjà contacté le serveur avant, mémorisant les informations qui seront données au serveur pour qu'il retrouve la session à reprendre. C'est cool, mais cela pose d'évidents problèmes de vie privée (ces informations mémorisées sont une sorte de cookie, et permettent le suivi à la trace d'un client). D'ailleurs, en parlant de vie privée, le RFC signale aussi (section 5.5.4) que la possibilité de migrer une connexion QUIC d'une adresse IP à l'autre a également des conséquences pour la traçabilité.

Autre piège avec le 0-RTT, il ne protège pas contre le rejeu et il ne faut donc l'utiliser que pour des requêtes DNS idempotentes comme QUERY (le cas le plus courant) ou NOTIFY (qui change l'état du serveur, mais est idempotent). Bon, de toute façon, un serveur peut toujours être configuré pour ne pas accepter de 0-RTT, et répondre alors REFUSED (avec un code d'erreur étendu - RFC 8914 - Too Early).

La section 5 du RFC liste les exigences auxquelles doivent se soumettre les mises en œuvre de DoQ. Le client doit authentifier le serveur (cf. RFC 7858 et RFC 8310, mais aussi RFC 8932, sur les bonnes pratiques). Comme tous les serveurs ne géreront pas DoQ, en tout cas dans un avenir prévisible, les clients doivent être préparés à ce que ça échoue et à réessayer, par exemple en DoT.

QUIC ne dissimule pas forcément la taille des messages échangés, et celle-ci peut être révélatrice. Malgré le chiffrement, la taille d'une requête ou surtout d'une réponse peut donner une idée sur le nom demandé. Le RFC impose donc l'utilisation du remplissage, soit par la méthode QUIC générique de la section 19.1 du RFC 9000, soit par la méthode spécifique au DNS du RFC 7830. La première méthode est en théorie meilleure car elle dissimule d'autres métadonnées, et qu'elle tient compte de davantage d'éléments, mais les bibliothèques QUIC n'exposent pas forcément dans leur API de moyen de contrôler ce remplissage. Le RFC recommande donc aux clients et serveurs DoQ de se préparer à faire le remplissage eux-mêmes (en relisant bien le RFC 8467 avant).

Un petit retour sur la protection de la vie privée en section 7. Cette section rappele l'importance de lire et suivre le RFC 8932 si vous gérez un service de résolution DNS sécurisé (DoQ ou pas DoQ). Et elle insiste sur le fait que des fonctions de QUIC très pratiques pour diminuer la latence à l'établissement de la connexion, notamment le 0-RTT, ont des conséquences pour la vie privée, en permettant de suivre un même utilisateur (plus exactement une même machine). Et cela marche même si la machine a changé d'adresse IP entretemps. On peut aussi dire que le problème de QUIC est de permettre des sessions de très longue durée (que ce soit une vraie session unique, ou bien une « session virtuelle », formée en reprenant une session existante avec le 0-RTT) et que de telles sessions longues, excellentes pour les performances, le sont forcément moins pour l'intimité.

Les mises en œuvre de DoQ, maintenant. La société AdGuard a produit du code, dont un serveur et un client en Go, dnslookup. (Regardez l'exposé du directeur technique de cette société à l'OARC.) Voici un exemple de compilation, puis d'utilisation de dnslookup :


% git clone https://github.com/ameshkov/dnslookup.git
%  cd dnslookup
% make
% ./dnslookup www.bortzmeyer.org quic://dns.adguard.com

On utilisait le serveur DoQ public d'AdGuard. Officiellement, NextDNS en a également un mais je n'arrive pas à l'utiliser :

% ./dnslookup www.bortzmeyer.org quic://3e4935.dns.nextdns.io
...
2022/05/22 08:16:33 Cannot make the DNS request: opening quic session to quic://3e4935.dns.nextdns.io:853: timeout: no recent network activity
  

Notez que si vous voulez utiliser dnslookup avec un serveur dont le certificat n'est pas valide, il faut mettre la variable d'environnement VERIFY à 0 (cela ne semble pas documenté).

Il existe une autre mise en œuvre de DoQ, quicdoq, écrite en C. Elle dépend de la bibliothèque QUIC picoquic qui, à son tour, dépend de picotls, dont la compilation n'est pas toujours évidente. D'une manière générale, les bibliothèques QUIC sont souvent récentes, parfois expérimentales, et ne marchent pas toujours du premier coup. Mais si vous arrivez à compiler les dépendances de quicdoq, vous pouvez lancer le serveur ainsi :

% ./quicdoq_app -p 8053 -d 9.9.9.9
  

Puis le client :

% ./quicdoq_app ::1 8053 foobar:SOA bv:NS www.bortzmeyer.org:AAAA
  

Le logiciel de test de performances Flamethrower, écrit en C++ a une branche DoQ en cours de développement.

Le logiciel en Python aioquic ne semble pouvoir interagir qu'avec lui-même. Vu les messages d'erreur (quelque chose à propos de not enough bytes), je soupçonne qu'il utilise l'encodage des débuts de DoQ, quand il n'y avait pas encore le champ de deux octets au début des messages. Même avec lui-même, il a des exigences pénibles en matière de certificat (pas de certificats auto-signés, obligation que le nom du serveur soit dans le SAN - Subject Alternative Name, pas seulement dans le sujet).

Pour PowerDNS, il n'y a pour l'instant qu'un ticket. Et pour Unbound, c'est en cours, ainsi que pour Knot.

Dans les bibliothèques DNS, un travail est en cours pour go-dns.

Pour finir, vous pouvez regarder la présentation de DoQ par une des auteures du RFC au RIPE 84. Et un des premiers articles de recherche sur DoQ est « One to Rule them All? A First Look at DNS over QUIC ».


Téléchargez le RFC 9250


L'article seul

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