Ce blog n'a d'autre prétention que de me permettre de mettre à la disposition de tous des petits textes que j'écris. On y parle surtout d'informatique mais d'autres sujets apparaissent parfois.
Première rédaction de cet article le 20 février 2025
Le 18 février, le CEA a annoncé avoir battu un record de durée de confinement pour du plasma. Aussitôt, des dizaines de personnes ont écrit des messages techno-béats et anti-écologistes, sans prendre la mesure de ce qui avait été réalisé et de ce qui reste à faire. Petite discussion sur cette réactivité des technosolutionnistes, ces gens qui espèrent résoudre tous les problèmes de l'humanité par une invention technique spectaculaire.
Je n'ai pas l'impression qu'il y ait eu une publication un peu détaillée du résultat obtenu le 12 février (à part un tweet et un article qui explique le contexte mais pas tellement le résultat obtenu). Si vous avez trouvé, les détails m'intéressent. Bon, en très bref, les chercheur·ses (et technicien·nes et ouvrier·ères) ont réussi à garder dans un tokamak un plasma très chaud (vraiment très chaud) pendant une durée plus longue que le record précédent, et ce résultat est une étape dans l'obtention, à très long terme, d'un réacteur de production d'énergie par fusion thermonucléaire. C'est très cool du point de vue scientifique.
Mais ce qui m'a frappé, ce sont les réactions de certains. Bon,
d'accord, c'était sur Twitter, qui n'est pas
connu pour l'intelligence et la sensibilité de ses
utilisateurices. Pour ceux et celles qui ne connaissent pas, voici
le genre de tweets de réponse qu'on voit quand une journaliste
experte en géopolitique écrit une analyse sérieuse (sur un autre
sujet) :
Cela donne une bonne idée du niveau moyen du débat sur
Twitter. Compte-tenu de cela, ne soyons pas trop étonné de voir
arriver des tweets chauvins :
Ou bien très techno-béats :
Mais, surtout, il y a des gens qui jettent le masque ; le succès
du CEA n'est pour eux qu'un prétexte pour dire leur haine des
écologistes :
Idem ici :
Évidemment, ce que disent les écologistes, et tous les scientifiques est gênant. Alors, il est tentant de défendre son confort intellectuel en attaquant violemment le messager plutôt que de lire le message. C'est puéril, mais fréquent, comme par exemple chez les gens qui disent qu'ils ne veulent pas d'« écologie punitive » ; ce n'est pas l'écologie qui est punitive, c'est la physique ! (Ou, pour citer le proverbe breton, « Le capitaine qui ne veut pas obéir à la carte finira par obéir aux récifs. ».)
Outre ces tweets haineux contre tout ce qui pourrait menacer leur
droit sacré à rouler en voiture tant qu'ils veulent, on voit aussi
des tweets technosolutionnistes, de gens qui
espèrent qu'un progrès scientifique leur évitera de changer leur
mode de vie :
Le plus amusant est que ces gens qui se réclament de la science et accusent les écologistes d'obscurantisme font preuve d'une grande ignorance de la science. Cela fait des dizaines d'années qu'on nous affirme que la recherche sur la fusion thermonucléaire va déboucher sur une énergie grauite, illimitée et non-polluante, et à court terme. Et il n'y a toujours rien d'opérationnel (le tokamak du record n'a pas du tout produit d'énergie ; ce n'est pas son rôle). Le problème est très complexe (et je ne blâme donc pas les chercheur·ses, technicien·nes et ouvrier·ères, leur tâche est vraiment difficile) et il s'agit de recherche fondamentale bien plus que d'ingéniérie. Le calendrier est donc impossible à prévoir. Il est à noter que les gens qui se sont félicités de la disponibilité prochaine de l'énergie de fusion n'ont même pas fait l'effort de lire le court article du CEA, qui disait très bien, et très honnêtement, « Pour autant, compte-tenu des infrastructures nécessaires pour produire cette énergie à grande échelle, il est peu probable que les technologies de fusion contribuent significativement à l’atteinte du net 0 d’émissions de CO2 en 2050. Il faudra pour cela lever plusieurs verrous technologiques, mais aussi démontrer la faisabilité économique d’une telle production d’électricité. »
Notons qu'une telle avalanche de messages anti-écologistes et de style trumpiste avait déjà eu lieu en 2023, avec le LK-99, soi-disant à supraconducteur à température ambiante. Les techno-béats n'ont rien appris de cette bavure.
Date de publication du RFC : Février 2024
Auteur(s) du RFC : S. Gössner (Fachhochschule Dortmund), G. Normington, C. Bormann (Universität Bremen TZI)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF jsonpath
Première rédaction de cet article le 14 février 2025
Le langage JSONPath sert à désigner une partie d'un document JSON. Il est donc utile pour, par exemple, extraire des valeurs qui nous intéressent.
Il existe de nombreux langages pour cela (une liste partielle figure à la fin de l'article), pas forcément normalisés mais mis en œuvre dans tel ou tel logiciel (dont, évidemment, jq). Ce RFC est, je crois, la première normalisation formelle d'un tel langage. Voici tout de suite un exemple, utilisant le logiciel jpq, sur la la base des arbres parisiens :
% jpq '$[*].libellefrancais' arbres.json [ "Marronnier", "Aubépine", "Cerisier à fleurs", …
Cela se lit « affiche les noms d'espèce
[libellefrancais
, dans le fichier] de tous
[vous avez vu l'astérisque] les
arbres ». (Avec jq, on aurait écrit jq
'.[].libellefrancais' arbres.json
.) Voyons maintenant les
détails.
JSONPath travaille sur des
documents JSON, JSON étant normalisé dans le RFC 8259. Il n'est sans doute pas utile de
présenter JSON, qui est utilisé partout aujourd'hui. Notons
simplement que l'argument d'une requête JSONPath, écrit en JSON, est
ensuite modélisé comme un arbre, composé de
nœuds. Le JSON {"foo": 3, "bar": 0}
a ainsi une
racine de l'arbre sous laquelle se trouvent deux nœuds, avec comme
valeur 3 et 0 (les noms des membres JSON, foo
et bar
, ne sont pas sélectionnables par
JSONPath et donc pas considérés comme nœuds).
Vous êtes impatient·e de vous lancer ? On va utiliser le logiciel jpq cité plus haut. Pensez à installer un Rust très récent puis :
cargo install jpq
Ou bien, si vous voulez travailler à partir des sources :
git clone https://codeberg.org/KMK/jpq.git cd jpq cargo install --path .
Puis pensez à modifier votre chemin de recherche d'exécutables si ce n'est pas déjà fait (notez que l'excellente Julia Evans vient justement de faire un très bon article sur ce sujet). Testez :
% echo '["bof"]' | jpq '$[0]' [ "bof" ]
Les choses utiles à savoir pour écrire des expressins JSONPath :
[0]
est un segment sélectionnant
le premier élément d'un tableau, ici, le seul).La grammaire complète (en ABNF, RFC 5234) figure dans l'annexe A du RFC.
Allez, passons aux exemples, avec les arbres parisiens comme document JSON. Le quatrième arbre du document (on part de zéro) :
% jpq '$[3]' arbres.json [ { "idbase": 143057, "typeemplacement": "Arbre", "domanialite": "CIMETIERE", "arrondissement": "PARIS 20E ARRDT", "complementadresse": null, "numero": null, "adresse": "CIMETIERE DU PERE LACHAISE / DIV 41", "idemplacement": "D00000041050", "libellefrancais": "Erable", …
Tous les genres (dans la classification de Linné) :
% jpq '$[*].genre' arbres.json [ "Aesculus", "Crataegus", "Prunus", …
Les sélecteurs par nom peuvent s'écrire avec un point, comme ci-dessus, ou bien entre crochets avec des apostrophes (notez comme c'est moins pratique pour le shell Unix) :
% jpq "\$[*]['genre']" arbres.json [ "Aesculus", "Crataegus", "Prunus", …
La forme avec les crochets est la forme canonique pour une expression JSONPath. La notation avec un point n'est acceptée que pour les noms, pas pour les indices :
% echo '[1, 2, 3]' | jpq '$[1]' [ 2 ] % echo '[1, 2, 3]' | jpq '$.1' Error: × Invalid JSONPath: at position 2, in dot member name, must start with lowercase alpha or '_' ╭──── 1 │ $.1 · ▲ · ╰── in dot member name, must start with lowercase alpha or '_' ╰────
Tous les arbres qui font plus de 50 mètres de haut :
% jpq '$[?@.hauteurenm > 50].hauteurenm' < arbres.json [ 120, 69, 100, 67, 58, 74, 911 ]
L'arobase indique le nœud en cours d'évaluation. Et, oui, l'arbre de 911 mètres de haut est une erreur, chose courante dans les données ouvertes.
Comme vous avez vu, la requête JSONPath renvoie toujours une liste de nœuds, affichée par jpq dans la syntaxe des tableaux JSON.
Vous avez vu, dans l'exemple où on cherchait les plus grands arbres, que JSONPath permet de faire des comparaisons. Vous avez droit à tous les opérateurs booléens classiques. Ici, l'identificateur de tous les arbres situés dans un cimetière :
% jpq '$[?@.domanialite == "CIMETIERE"].idbase' < arbres.json [ 143057, 165296, 166709, …
JSONPath permet d'ajouter des fonctions, qui ne sont utilisables
que pour les comparaisons (je ne crois pas qu'on puisse mettre leur
résultat dans la valeur retournée par JSONPath). Plusieurs d'entre
elles sont définies par ce RFC, comme length()
,
mais pas forcément mises en œuvre dans tous les programmes. Et pour
compliquer les choses, des implémentations de JSONPath ajoutent
leurs propres fonctions non enregistrées et qui rendent l'expression
non portable.
Deux de ces fonctions,
search()
et match()
,
prennent en paramètre une expression
rationnelle, à la syntaxe du RFC 9485.
Les expressions JSONPath, quand on les envoie via l'Internet,
peuvent être marquées avec le type application/jsonpath
,
désormais enregistré
(section 3 du RFC). En plus, un
nouveau registre IANA est créé, pour stocker les fonctions
mentionnées au paragraphe précédent. Pour ajouter des fonctions à ce
registre, il faut passer par la procédure « Examen par un expert »
du RFC 8126.
La section 4, sur la sécurité, est très détaillée. JSONPath était souvent mis en œuvre en passant directement l'expression ou une partie d'entre elle au langage sous-jacent (typiquement JavaScript). Inutile de détailler les énormes problèmes de sécurité que cela pose si l'expression évaluée est, en tout ou en partie, fournie par un client externe (par exemple via un formulaire Web), permettant ainsi l'injection de code. Une validation de ces expressions avant de les passer étant irréaliste, le RFC insiste sur le fait qu'une mise en œuvre de JSONPath doit avoir son propre code et ne pas compter sur une évaluation par le langage de programmation sous-jacent.
Même ainsi, une expression JSONPath peut permettre une attaque par déni de service, si une expression mène à une consommation de ressources excessive. (Cf. la section 10 du RFC 8949 et la section 8 du RFC 9485.)
La section 1.2 de notre RFC décrit l'histoire un peu
compliquée de JSONPath. (Une des raisons pour lesquelles il
existe plusieurs langages de requête dans JSON est que JSONPath a
mis du temps à être terminé.) L'origine de JSONPath date de
2007, dans cet article de
Gössner (un des auteurs du RFC). L'interprétation de ce premier
JSONPath était souvent déléguée au langage sous-jacent (le
eval()
de JavaScript…)
avec les problèmes de sécurité qu'on imagine. Le JSONPath actuel se
veut portable, au sens où il ne dépend pas d'un langage
d'implémentation particulier, ni d'un moteur
d'expressions rationnelles
particulier. L'inconvénient est qu'il n'est pas forcément compatible
avec l'ancien JSONPath.
JSONPath a aussi été inspiré par le XPath de XML (cf. annexe B de notre RFC, qui détaille cette inspiration, et compare les deux langages). On peut aussi comparer JSONPath à JSON Pointer (RFC 6901), ce qui est fait dans l'annexe C.
Il existe bien sûr d'autres mises en œuvre de JSONPath que jpq. Mais attention : certaines sont très anciennes (comme Python JSONPath RW) et ne correspondent pas à ce qui est normalisé dans le RFC. Essayons Python JSONPath Next-Generation :
% python Python 3.13.2 (main, Feb 5 2025, 01:23:35) [GCC 14.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from jsonpath_ng.ext import filter, parse >>> import json >>> data = json.load(open("arbres.json")) >>> expr = parse("$[?@.hauteurenm > 50].hauteurenm") >>> result = expr.find(data) >>> for r in result: ... print(r.value) ... 120 69 100 67 58 74 911
D'autres langages de requête dans le JSON existent, chacun avec sa syntaxe :
Date de publication du RFC : Février 2025
Auteur(s) du RFC : P. Koch (DENIC
eG), M. Larson, P. Hoffman
(ICANN)
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 12 février 2025
Un résolveur DNS ne connait au début, rien du contenu du DNS. Rien ? Pas tout à fait, il connait une liste des serveurs de noms faisant autorité pour la racine, car c'est par eux qu'il va commencer le processus de résolution de noms. Cette liste est typiquement en dur dans le code du serveur, ou bien dans un de ses fichiers de configuration. Mais peu d'administrateurs système la maintiennent à jour. Il est donc prudent, au démarrage du résolveur, de chercher une liste vraiment à jour, et c'est le priming (amorçage, comme lorsqu'on amorce une pompe pour qu'elle fonctionne seule ensuite), opération que décrit ce RFC, qui remplace l'ancienne version, le RFC 8109 (les changements sont nombreux mais sont surtout des points de détail).
Le problème de départ d'un résolveur est un problème d'œuf et de
poule. Le résolveur doit interroger le DNS pour avoir
des informations mais comment trouve-t-il les serveurs DNS à
interroger ? La solution est de traiter la racine du DNS de manière
spéciale : la liste de ses serveurs est connue du résolveur au
démarrage. Elle peut être dans le code du serveur lui-même, ici un
Unbound qui contient les adresses IP des
serveurs de la racine (je ne montre que les trois premiers,
A.root-servers.net
,
B.root-servers.net
et
C.root-servers.net
) :
% strings /usr/sbin/unbound | grep -i 2001: 2001:503:ba3e::2:30 2001:500:84::b 2001:500:2::c ...
Ou bien elle est dans un fichier de configuration (ici, sur un Unbound) :
server: directory: "/etc/unbound" root-hints: "root-hints"
Ce fichier peut être téléchargé via
l'IANA, il peut être spécifique au logiciel résolveur, ou bien fourni
par le système d'exploitation (cas du
paquetage dns-root-data
chez
Debian). Il contient la liste des serveurs
de la racine et leurs adresses :
. 3600000 NS A.ROOT-SERVERS.NET. . 3600000 NS B.ROOT-SERVERS.NET. ... A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4 A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:ba3e::2:30 B.ROOT-SERVERS.NET. 3600000 A 192.228.79.201 B.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:84::b ...
Tous les résolveurs actuels mettent en œuvre le priming. En effet, les configurations locales tendent à ne plus être à jour au bout d'un moment. (Sauf dans le cas où elles sont dans un paquetage du système d'exploitation, mis à jour avec ce dernier, comme dans le bon exemple Debian ci-dessus.)
Les changements des serveurs racines sont rares. Si on regarde sur le site des opérateurs des serveurs racine, on voit :
Bref, peu de changements. Ils sont en général annoncés sur les listes de diffusion opérationnelles (comme ici). Mais les fichiers de configuration ayant une fâcheuse tendance à ne pas être mis à jour et à prendre de l'âge, les anciennes adresses des serveurs racine continuent à recevoir du trafic des années après (comme le montre cette étude de J-root). Notez que la stabilité de la liste des serveurs racine n'est pas due qu'au désir de ne pas perturber les administrateurs système : il y a aussi des raisons politiques (aucun mécanisme en place pour choisir de nouveaux serveurs, ou pour retirer les « maillons faibles »). C'est pour cela que la liste des serveurs (mais pas leurs adresses) n'a pas changé depuis 1997 ! (Une histoire - biaisée - des serveurs racine a été publiée par l'ICANN.)
Notons aussi que l'administrateur système d'un résolveur peut changer la liste des serveurs de noms de la racine pour une autre liste, par exemple s'ielle veut utiliser une racine alternative.
Le priming, maintenant. Le principe du priming est, au démarrage, de faire une requête à un des serveurs listés dans la configuration et de garder sa réponse (certainement plus à jour que la configuration) :
% dig +bufsize=4096 +norecurse +nodnssec @i.root-servers.net . NS ; <<>> DiG 9.18.28-0ubuntu0.24.04.1-Ubuntu <<>> +bufsize +norecurse +nodnssec @i.root-servers.net . NS ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54419 ;; flags: qr aa; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 27 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ; COOKIE: c0a47c1200bf6bfc0100000067377b40981cc05cdb33b736 (good) ;; QUESTION SECTION: ;. IN NS ;; ANSWER SECTION: . 518400 IN NS k.root-servers.net. . 518400 IN NS h.root-servers.net. . 518400 IN NS m.root-servers.net. . 518400 IN NS l.root-servers.net. . 518400 IN NS b.root-servers.net. . 518400 IN NS e.root-servers.net. . 518400 IN NS d.root-servers.net. . 518400 IN NS f.root-servers.net. . 518400 IN NS g.root-servers.net. . 518400 IN NS i.root-servers.net. . 518400 IN NS a.root-servers.net. . 518400 IN NS j.root-servers.net. . 518400 IN NS c.root-servers.net. ;; ADDITIONAL SECTION: m.root-servers.net. 518400 IN A 202.12.27.33 l.root-servers.net. 518400 IN A 199.7.83.42 k.root-servers.net. 518400 IN A 193.0.14.129 j.root-servers.net. 518400 IN A 192.58.128.30 i.root-servers.net. 518400 IN A 192.36.148.17 h.root-servers.net. 518400 IN A 198.97.190.53 g.root-servers.net. 518400 IN A 192.112.36.4 f.root-servers.net. 518400 IN A 192.5.5.241 e.root-servers.net. 518400 IN A 192.203.230.10 d.root-servers.net. 518400 IN A 199.7.91.13 c.root-servers.net. 518400 IN A 192.33.4.12 b.root-servers.net. 518400 IN A 170.247.170.2 a.root-servers.net. 518400 IN A 198.41.0.4 m.root-servers.net. 518400 IN AAAA 2001:dc3::35 l.root-servers.net. 518400 IN AAAA 2001:500:9f::42 k.root-servers.net. 518400 IN AAAA 2001:7fd::1 j.root-servers.net. 518400 IN AAAA 2001:503:c27::2:30 i.root-servers.net. 518400 IN AAAA 2001:7fe::53 h.root-servers.net. 518400 IN AAAA 2001:500:1::53 g.root-servers.net. 518400 IN AAAA 2001:500:12::d0d f.root-servers.net. 518400 IN AAAA 2001:500:2f::f e.root-servers.net. 518400 IN AAAA 2001:500:a8::e d.root-servers.net. 518400 IN AAAA 2001:500:2d::d c.root-servers.net. 518400 IN AAAA 2001:500:2::c b.root-servers.net. 518400 IN AAAA 2801:1b8:10::b a.root-servers.net. 518400 IN AAAA 2001:503:ba3e::2:30 ;; Query time: 6 msec ;; SERVER: 192.36.148.17#53(i.root-servers.net) (UDP) ;; WHEN: Fri Nov 15 17:48:00 CET 2024 ;; MSG SIZE rcvd: 851
(Les raisons du choix des trois options données à dig sont indiquées plus loin.)
La section 3 de notre RFC décrit en détail à quoi ressemblent les
requêtes de priming. Le type de données demandé
(QTYPE) est NS (Name Servers,
type 2) et le nom demandé (QNAME) est « . » (oui,
juste la racine). D'où le dig . NS
ci-dessus. Le bit RD (Recursion Desired) est
typiquement mis à zéro (d'où le +norecurse
dans
l'exemple avec dig). La taille de la réponse dépassant les 512
octets (limite très ancienne du DNS), il faut utiliser
EDNS (cause du
+bufsize=4096
dans l'exemple). On peut utiliser
le bit DO (DNSSEC OK) qui indique qu'on demande
les signatures DNSSEC mais ce n'est pas habituel (d'où le
+nodnssec
dans l'exemple). En effet, si la
racine est signée, permettant d'authentifier l'ensemble
d'enregistrements NS, la zone root-servers.net
,
où se trouvent actuellement tous les serveurs de la racine, ne l'est
pas, et les enregistrements A et AAAA ne peuvent donc pas être
validés avec DNSSEC.
Cette requête de priming est envoyée lorsque le résolveur démarre, et aussi lorsque la réponse précédente a expiré (regardez le TTL dans l'exemple : six jours). Si le premier serveur testé ne répond pas, on essaie avec un autre. Ainsi, même si le fichier de configuration n'est pas parfaitement à jour (des vieilles adresses y trainent), le résolveur finira par avoir la liste correcte.
Et comment choisit-on le premier serveur qu'on interroge ? Notre RFC recommande (section 3.2) un tirage au sort, pour éviter que toutes les requêtes de priming ne se concentrent sur un seul serveur (par exemple le premier de la liste). Une fois que le résolveur a démarré, il peut aussi se souvenir du serveur le plus rapide, et n'interroger que celui-ci, ce qui est fait par la plupart des résolveurs, pour les requêtes ordinaires (mais n'est pas conseillé pour le priming).
Et les réponses au priming ? Il faut bien
noter que, pour le serveur racine, les requêtes
priming sont des requêtes comme les autres, et ne
font pas l'objet d'un traitement particulier. Normalement, la
réponse doit avoir le code de retour NOERROR
(c'est bien le cas dans mon exemple). Parmi les
flags, il doit y avoir AA (Authoritative
Answer). La section de réponse doit évidemment contenir
les NS de la racine, et la section additionnelle les adresses IP. Le
résolveur garde alors cette réponse dans son cache, comme il le
ferait pour n'importe quelle autre réponse. Notez que là aussi, il
ne faut pas de traitement particulier. Par exemple, le résolveur ne
doit pas compter sur le fait qu'il y aura exactement 13 serveurs,
même si c'est le cas depuis longtemps (ça peut changer).
Normalement, le serveur racine envoie la totalité des adresses IP
(deux par serveur, une en IPv4 et une en
IPv6). S'il ne le fait pas (par exemple par
manque de place parce qu'on a bêtement oublié
EDNS), le résolveur va devoir envoyer des
requêtes A et AAAA explicites pour obtenir les adresses IP (ici, on
interroge k.root-servers.net
) :
% dig @2001:7fd::1 g.root-servers.net AAAA ; <<>> DiG 9.18.33-1~deb12u2-Debian <<>> @2001:7fd::1 g.root-servers.net AAAA ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10640 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 1232 ;; QUESTION SECTION: ;g.root-servers.net. IN AAAA ;; ANSWER SECTION: g.root-servers.net. 3600000 IN AAAA 2001:500:12::d0d ;; Query time: 3 msec ;; SERVER: 2001:7fd::1#53(2001:7fd::1) (UDP) ;; WHEN: Thu Feb 13 17:26:51 CET 2025 ;; MSG SIZE rcvd: 75
Vous pouvez voir ici les requêtes et réponses de priming d'un Unbound. D'abord, décodées par tcpdump :
17:57:14.439382 IP (tos 0x0, ttl 64, id 26437, offset 0, flags [none], proto UDP (17), length 56) 10.10.156.82.51893 > 198.41.0.4.53: [bad udp cksum 0x6cbf -> 0x49dc!] 63049% [1au] NS? . ar: . OPT UDPsize=1232 DO (28) 17:57:14.451715 IP (tos 0x40, ttl 52, id 45305, offset 0, flags [none], proto UDP (17), length 1125) 198.41.0.4.53 > 10.10.156.82.51893: [udp sum ok] 63049*- q: NS? . 14/0/27 . [6d] NS l.root-servers.net., . [6d] NS j.root-servers.net., . [6d] NS f.root-servers.net., . [6d] NS h.root-servers.net., . [6d] NS d.root-servers.net., . [6d] NS b.root-servers.net., . [6d] NS k.root-servers.net., . [6d] NS i.root-servers.net., . [6d] NS m.root-servers.net., . [6d] NS e.root-servers.net., . [6d] NS g.root-servers.net., . [6d] NS c.root-servers.net., . [6d] NS a.root-servers.net., . [6d] RRSIG ar: l.root-servers.net. [6d] A 199.7.83.42, l.root-servers.net. [6d] AAAA 2001:500:9f::42, j.root-servers.net. [6d] A 192.58.128.30, j.root-servers.net. [6d] AAAA 2001:503:c27::2:30, f.root-servers.net. [6d] A 192.5.5.241, f.root-servers.net. [6d] AAAA 2001:500:2f::f, h.root-servers.net. [6d] A 198.97.190.53, h.root-servers.net. [6d] AAAA 2001:500:1::53, d.root-servers.net. [6d] A 199.7.91.13, d.root-servers.net. [6d] AAAA 2001:500:2d::d, b.root-servers.net. [6d] A 170.247.170.2, b.root-servers.net. [6d] AAAA 2801:1b8:10::b, k.root-servers.net. [6d] A 193.0.14.129, k.root-servers.net. [6d] AAAA 2001:7fd::1, i.root-servers.net. [6d] A 192.36.148.17, i.root-servers.net. [6d] AAAA 2001:7fe::53, m.root-servers.net. [6d] A 202.12.27.33, m.root-servers.net. [6d] AAAA 2001:dc3::35, e.root-servers.net. [6d] A 192.203.230.10, e.root-servers.net. [6d] AAAA 2001:500:a8::e, g.root-servers.net. [6d] A 192.112.36.4, g.root-servers.net. [6d] AAAA 2001:500:12::d0d, c.root-servers.net. [6d] A 192.33.4.12, c.root-servers.net. [6d] AAAA 2001:500:2::c, a.root-servers.net. [6d] A 198.41.0.4, a.root-servers.net. [6d] AAAA 2001:503:ba3e::2:30, . OPT UDPsize=4096 DO (1097)
Et ici par tshark :
1 0.000000 10.10.156.82 → 198.41.0.4 DNS 70 Standard query 0xf649 NS <Root> OPT 2 0.012333 198.41.0.4 → 10.10.156.82 DNS 1139 Standard query response 0xf649 NS <Root> NS l.root-servers.net NS j.root-servers.net NS f.root-servers.net NS h.root-servers.net NS d.root-servers.net NS b.root-servers.net NS k.root-servers.net NS i.root-servers.net NS m.root-servers.net NS e.root-servers.net NS g.root-servers.net NS c.root-servers.net NS a.root-servers.net RRSIG A 199.7.83.42 AAAA 2001:500:9f::42 A 192.58.128.30 AAAA 2001:503:c27::2:30 A 192.5.5.241 AAAA 2001:500:2f::f A 198.97.190.53 AAAA 2001:500:1::53 A 199.7.91.13 AAAA 2001:500:2d::d A 170.247.170.2 AAAA 2801:1b8:10::b A 193.0.14.129 AAAA 2001:7fd::1 A 192.36.148.17 AAAA 2001:7fe::53 A 202.12.27.33 AAAA 2001:dc3::35 A 192.203.230.10 AAAA 2001:500:a8::e A 192.112.36.4 AAAA 2001:500:12::d0d A 192.33.4.12 AAAA 2001:500:2::c A 198.41.0.4 AAAA 2001:503:ba3e::2:30 OPT
Et un décodage plus détaillé de tshark dans ce fichier.
Enfin, la section 6 de notre RFC traite des problèmes de sécurité du priming. Évidemment, si un attaquant injecte une fausse réponse aux requêtes de priming, il pourra détourner toutes les requêtes ultérieures vers des machines de son choix. À part le RFC 5452, et l'utilisation de cookies (RFC 7873, mais seuls les serveurs racine C, F, G et I les gèrent aujourd'hui), la seule protection est DNSSEC : si le résolveur valide (et a donc la clé publique de la racine), il pourra détecter que les réponses sont mensongères (voir aussi la section 3.3). Cela a l'avantage de protéger également contre d'autres attaques, ne touchant pas au priming, comme les attaques sur le routage.
Notez que DNSSEC est recommandé pour valider les réponses
ultérieures mais, comme on l'a vu, n'est pas important pour valider
la réponse de priming elle-même, puisque
root-servers.net
n'est pas signé. Si un
attaquant détournait, d'une manière ou d'une autre, vers un faux
serveur racine, servant de fausses données, ce ne serait qu'une
attaque par déni de
service, puisque le résolveur validant pourrait détecter
que les réponses sont fausses.
L'annexe A du RFC liste les changements depuis le RFC 8109. Rien de vraiment crucial, juste une longue liste de clarifications et de précisions.
Auteur(s) du livre : Jennifer Lesieur
Éditeur : Robert Laffont
978-2-253-24937-5
Publié en 2023
Première rédaction de cet article le 10 février 2025
Rose Valland n'est évidemment plus une inconnue. Néanmoins, son nom et son activité m'avaient échappé et c'est grâce à ce petit livre que j'ai appris son rôle, pendant et après la guerre, pour documenter les pillages d'œuvres d'art, et essayer d'en récupérer le plus grand nombre.
Grâce au film Monuments Men, ce pillage d'œuvres d'art par les nazis en Europe occupée, et le travail de récupération des œuvres est bien connu. Mais Hollywood se focalise sur le rôle des États-Unis, alors que des pays qui n'ont pas la même puissance médiatique sont moins mentionnés. En France, Rose Valland, conservatrice de musée, a joué pourtant un rôle important. Pendant l'Occupation, elle notait tout, les œuvres d'art enlevées, les noms des voleurs, les destinations des trains qui pouvaient permettre d'identifier les dépôts en Allemagne. À la Libération, elle a accompagné les troupes alliées en Allemagne et ses notes ont beaucoup contribué à retrouver un grand nombre de tableaux ou de sculptures et à les rapporter au bon endroit.
Ce court livre raconte la vie de Rose Valland, de conservatrice de musée binoclarde et réservée, à aventurière en jeep dans une Allemagne dévastée, à chercher des milliers d'œuvres d'art. Une vie passionnante, face à d'innombrables difficultés. Toustes les résistant·es n'avaient pas forcément une arme à feu…
Première rédaction de cet article le 9 février 2025
Plusieurs organisations françaises viennent de signer un appel critique vis-à-vis de l'IA, dans le contexte du sommet IA du gouvernement. Alors que je suis en général d'accord avec ces organisations, cet appel me semble frapper à côté de la cible, car il attribue à l'IA un rôle excessif.
À l'approche du sommet IA, les discours technobéats se multiplient, affirmant que l'IA va tout résoudre et qu'il faut vite y investir des milliards de gigawatts pour rester compétitif. Les injonctions à passer à l'IA, à accélérer le déploiement de l'IA jusque dans nos brosses à dent, évidemment connectées, sont répétés sans cesse. Face à ce délire marketing et politicien, on comprend l'agacement des gens qui tiennent à garder un regard critique sur le numérique. (Rappel : « critique » au sens de « penser par soi-même, sans forcément suivre le discours dominant », pas au sens de « jamais d'accord ».) Cet agacement peut mener à passer complètement de l'autre côté et à dire que l'IA ne sert à rien, voire qu'elle est 100 % néfaste.
Mais l'appel dont je parlais a un autre défaut : il met l'IA à toutes les sauces. Par exemple quand il dit que « elle [l'IA] est le plus souvent imposée sans réelle prise en compte de ses impacts délétères sur les droits humains » comme si ce n'était pas le cas de tout le numérique (cf. par exemple le RFC 8280), et même de toutes les innovations techniques. À lire l'appel, on a l'impression que les choses allaient plus ou moins bien avant mais que l'IA a entrainé une rupture qualitative. Ce qui est, paradoxalement, exactement le discours des techno-béats qui promeuvent l'IA à tout prix.
Qu'on attribue à l'IA des miracles ou au contraire qu'on l'accuse de tous les maux, dans les deux cas, on fait l'erreur de croire qu'il existe bien quelque chose qui s'appelerait « l'IA » et qui aurait des caractéristiques qui en feraient quelque chose de très distinct du reste du monde numérique. En réalité, « IA » est un terme surtout marketing, sans définition précise, et qui a surtout une longue histoire dans la communication plus que dans la technique. (Notons qu'« algorithme » est également souvent utilisé mal à propos mais ce mot, au moins, a une définition rigoureuse.) Alors, oui, les LLM existent, oui, les logiciels de génération de textes ou d'images ont fait des très gros progrès depuis quelques années, des nouvelles techniques et des nouveaux outils sont développés par les chercheur·ses, mais il n'est pas du tout évident que cela change fondamentalement les questions qu'on se posait déjà avant que ChatGPT ne remette l'IA à la mode.
Par exemple, quand l'appel de Hiatus dit « dans l’action publique, elle [l'IA] agit en symbiose avec les politiques d’austérité qui sapent la justice socio-économique », c'est très discutable alors qu'on n'a pas attendu l'IA pour casser les services publics, souvent au nom de la dématérialisation (je recommande par exemple l'excellent rapport de la Défenseure des Droits sur l'ANEF).
Bref, autant la critique du numérique est indispensable, autant je pense que c'est une mauvaise idée que d'ériger « l'IA » en phénomène spécifique.
Première rédaction de cet article le 5 février 2025
Le FOSDEM est sans doute le plus grand rassemblement de développeurs (et quelques développeuses) de logiciel libre en Europe. L'édition 2025, qui marquait le vingt-cinquième anniversaire de la création du FOSDEM, vient de se tenir à Bruxelles, les 1 et 2 février.
Impossible de tout raconter. Le FOSDEM, ce sont des milliers de
participants (et 950 kg de frites servies) et
presque un millier d'orateurices. (Il y avait 2 064 propositions,
955 ont été acceptées.) Personne ne peut tout suivre, sans compter
la difficulté à rentrer dans les salles les plus populaires. Malgré
la générosité de l'ULB, qui prête ses locaux,
il n'y a jamais assez de salles, ni assez de place dans les
salles. Je vais donc me contenter de quelques points.
Saluons d'abord l'exploit de l'équipe technique : l'accès à l'Internet via le WiFi a parfaitement marché, de partout, tout le week-end. On est en 2025, donc il était évidemment en IPv6 seul. 8 846 machines ont été vues.
Vous pouvez regarder tout le programme et les vidéos.
J'ai suivi la salle sur le courrier électronique. Vieille technologie que cet ancien réseau social (bien plus social que ce que vendent les entreprises privées aujourd'hui) ? Mais le courrier reste la seule solution de communication ouverte, reposant sur des protocoles normalisés et du logiciel libre, et largement accessible. Il y avait un excellent exposé de Robin Jarry sur le logiciel client >aerc (un concurrent de mutt et autres logiciels tournant dans un terminal). Il gère même JMAP (RFC 8621). Et, via w3m, peut afficher les messages marketing en HTML. Mais il n'a pas encore de langage de filtrage. L'auteur n'envisage pas d'utiliser le langage normalisé Sieve (RFC 5228).
Autre client de courrier, très différent, Parula. Lui est graphique, et se veut un concurrent crédible des grosses usines à gaz tout-en-un utilisées dans le monde corporate. Si le grand public utilise Gmail, les entreprises en interne sont plutôt Microsoft. Ce souci d'être enterprise-ready pousse les développeurs de Parula à déprioritiser le chiffrement « très peu de gens l'utilisent ». (Le FOSDEM a toujours été partagé entre ceux qui veulent adapter le logiciel libre au monde corporate, pour qu'il y gagne succès et respectabilité, et ceux qui préfèrent rester différents.)
Et côté serveurs et pas clients ? Il y a eu deux présentations de serveurs tout-en-un. Installer un serveur de messagerie aujourd'hui nécessite l'installation et la configuration de nombreux logiciels différents, par exemple Postfix, Dovecot, SpamAssassin et les logiciels qui font faire du SPF, du DKIM et du DMARC, sans parler du greylisting (RFC 6647). Sur mon serveur, qui utilise Postfix, les trois logiciels SPF, DKIM et DMARC utilisent trois façons différentes de s'interfacer à Postfix… Bref, il est tentant de remplacer cette ménagerie par un logiciel qui fait tout et le café. C'est ce que proposent Stalwart (écrit en Rust) et mox (écrit en Go, l'autre langage qui concurrence Rust pour les serveurs Internet), présentés ici. Stalwart inclut même l'analyse des rapports DMARC…
Je n'ai pas aimé le côté trop marketing de la présentation de Stalwart (cf. ma remarque plus haut sur le partage du FOSDEM entre corporate-compatibles et libristes pur·es et dur·es). L'orateur abusait de intuitive, enterprise-ready et autres red flags du discours marketing. En outre, il semble que bien des fonctions de base soient uniquement dans la version payante.
Personnellement, je ne compte pas utiliser ces logiciels car j'ai déjà une configuration qui fonctionne mais, si je devais monter un serveur de messagerie en partant de zéro, cela vaudrait sans doute un essai.
Le présentateur de mox, Mechiel Lukkien, insistait sur tous les problèmes qui sont de toute façon en dehors du contrôle du serveur de messagerie et rendent donc le « tout-en-un complet » illusoire. Ainsi, notait-il, il faut quinze enregistrements DNS pour un domaine (je n'ai pas vérifié le chiffre ; peut-être comptait-il DNSSEC jugé, à juste titre, indispensable en 2025), et le serveur de messagerie ne peut pas les ajouter lui-même. Pas de norme, des API privatrices partout. En attendant une éventuelle normalisation, mox utilise un relais, dnsclay, avec qui il parle en mise à jour dynamiques (RFC 2136), charge à lui de relayer via différents dorsaux vers les API de l'hébergeur DNS.
La réunion a aussi été l'occasion de parler du projet Structured email à l'IETF, projet visant à normaliser des messages structurés et donc facilement compréhensibles par un programme (par exemple des confirmations de commande). Le groupe de travail a plusieurs documents sur le feu.
J'ai bien sûr suivi la réunion
DNS. Valentin Gosu,
de Mozilla, a présenté la difficulté de
faire des résolutions DNS depuis une application typique. D'accord,
il y a getaddrinfo
qui, en gros,
marche, et partout, mais qui a plein de limites, par exemple il ne
donne pas le TTL (rappel,
car l'orateur ne l'a pas mentionné : la résolution de noms en
adresses IP n'utilise pas forcément le DNS). Il n'indique pas si la
réponse a été validée par DNSSEC. Et il ne permet de
récupérer que les adresses IP, alors qu'on voudrait, par exemple,
les enregistrements HTTPS (RFC 9460). Il
existe des API spécifiques à une plate-forme donnée
(DNSQuery_A
sur Windows)
pour avoir ces informations, mais qui sont plus ou moins
documentées, et marchent plus ou moins bien (par exemple selon les
versions de Windows). Bref, on l'oublie souvent, mais une des
motivations de DoH
(RFC 8484) était de permettre à une
application comme Firefox de faire de la résolution DNS
proprement.
Alexey Milovidov a fait un amusant exposé sur sa mesure systématique des enregistrements PTR pour tout l'Internet IPv4. Vous pouvez en voir une jolie visualisation. Chaque bloc d'une même couleur concerne des adresses IP proches et résolvant vers des noms de domaine proches. N'hésitez pas à zoomer et à cliquer, c'est amusant. (Défi : réfléchir à comment cela pourrait se faire en IPv6.)
Peter van Dijk (remplaçant Rémi Gacogne, empêché) a présenté le travail (qui n'a pas été un échec mais n'a pas complètement marché) pour réduire l'empreinte de dnsdist et le rendre ainsi utilisable sur de petits routeurs utilisant OpenWrt. (Au passage, dnsdist est le logiciel derrière mon résolveur DNS public.) Beaucoup de choses ont été essayées (options du compilateur, retrait d'une partie du code…) sans trop de résultat. Changer de bibliothèque (remplacer OpenSSL par wolfSSL) n'a pas beaucoup aidé non plus, d'autant plus que le code de ces bibliothèques peut quand même être chargé par une autre application (il faudrait qu'elles changent toutes en même temps).
Ah, et comme le DNS est très politique, Farzaneh Badiei (Digital Medusa) a présenté le travail en cours d'analyse de l'utilisation des résolveurs DNS publics. Ils sont utilisés pour des raisons diverses. Par exemple, dans plusieurs pays (dont la France), ils servent entre autre à contourner la censure faite via des résolveurs menteurs. Digital Medusa a déjà produit un rapport préliminaire dont je vous recommande la lecture.
La réunion Retrocomputing est comme d'habitude une des plus pittoresques du FOSDEM. C'est ainsi que Raphaël Zumer a expliqué comment casser les mots de passe écrits en japonais pour pouvoir jouer à un ancien jeu vidéo japonais. (La devise de Retrocomputing pourrait être « si c'est utile, ça n'a pas sa place ici ».)
Hans Hübner a présenté son travail sur le Bildschirmtext, le « Minitel allemand ». En raison du peu de matériels fabriqués, il n'avait pas accès à un vrai terminal (et encore moins à ses serveurs) et donc a tout reconstitué en logiciel. Il a réussi à trouver certaines documentations (épaisses couches de papier mal imprimé à partir d'un texte tapé à la machine), notamment auprès de musées. Le logiciel original semble perdu (Software Heritage n'existait pas encore, cela permet de comprendre son importance).
Les auteurs (pas les simples lecteurs) de pages Bildschirmtext devaient utiliser un clavier spécial. La part la plus importante de son exposé était consacrée à la reproduction de ce clavier en Javascript, pour que cela puisse tourner dans un navigateur Web (avec une description en XML et un programme XSLT pour produire du SVG…). Beaucoup de hacks ont enchanté l'audience comme le travail pour fabriquer une police de caractères qui ressemble à celle du Bildschirmtext, uniquement à partir des copies d'écran existantes. Le code du « serveur » a été refait en Common Lisp.
Le résultat de son travail est visible en ligne (page d'accueil du CCC en 1987). Il faut cliquer sur le clavier (pas sur l'écran).
Un autre exposé, celui de Dmitriy Kostiuk, portait sur l'histoire des souris. Nous avons vu plein de jolies images de vieilles souris, qu'on peut retrouver sur le site de l'auteur.
Un des meilleurs exposés était celui de Rodrigo Arias Mallo (dans
Minimalistic
computing) sur le navigateur Web
Dillo. Dillo existe depuis
1999. C'est un navigateur graphique
minimaliste (HTML et CSS mais pas JavaScript,
il est donc parfait pour les sites Web avec du contenu, de
l'information, mais pas pour les applications). Si vous vous
préoccupez de l'empreinte environnementale du
numérique, commencez par regarder si votre site Web est visible avec
Dillo (celui de l'ADEME n'est pas visible, en
raison d'un problème TLS ; la sécurité et l'écologie peuvent être
difficiles à concilier). Le projet a été abandonné de 2017 à 2024
(le domaine dillo.org
étant même perdu) mais
Rodrigo Arias Mallo l'a relancé, avec un nouveau
domaine. Dillo a un système de
greffons et il existe des greffons pour voir
des pages de manuel, des fichiers
locaux ou bien des capsules Gemini.
Bien sûr, le logiciel libre est très politique, son utilisation et son développement posent de nombreuses questions politiques. J'ai apprécié la keynote sur l'utilisation d'infrastructures privatrices pour développer du logiciel libre. Karen Sandler et Denver Gingerich ont commencé en demandant de lever la main à ceux qui utilisaient Slack. Discord ? Confluence ? Teams ? Jira ? GitHub ? À la fin, la grande majorité des mains dans l'amphi étaient levées. (Personnellement, j'ai quitté GitHub il y a des années.) Comme dit en conclusion, « GitHub is free. Free as in free cocaine. ». La discussion après l'exposé a beaucoup porté sur la connexion des forges libres entre elles ; une des critiques les plus souvent entendues sur l'utilisation de forges libres, comme un gitlab auto-hébergé, est qu'il faut se créer un compte dans chaque forge, ne serait-ce que pour créer un ticket. Des solutions techniques sont envisageables (ActivityPub ? Le courrier électronique ?) mais aucune ne s'est encore imposée.
Le FOSDEM, ce sont aussi d'innombrables stands (comme celui d'Haiku, toujours très suivi et très fréquenté). J'ai eu une longue discussion avec les gens de Qubes OS. Je croyais le projet mort mais, si sa fondatrice, Joanna Rutkowska, est bien partie, le projet est toujours vivant. L'idée de base est d'avoir un système d'exploitation qui soit « raisonnablement sécurisé » (un système « parfaitement sécurisé » serait un système sur un ordinateur éteint). Il faut qu'il soit sécurisé mais qu'on puisse quand même faire des trucs et des machins. (Au contraire des approches compliance, où on ne se soucie que de cocher des cases pour être en conformité et où on se moque de si les gens pourront travailler ou pas.) Pour atteindre cet objectif, Qubes OS partitionne le système en plusieurs machines virtuelles (utilisant Xen, qui est toujours un projet actif). Par exemple, l'une est dédiée au travail sur un projet très confidentiel, et n'a pas accès à l'Internet, une autre sert à regarder Pornhub (non, je plaisante, mais vous avez l'idée). De même, une machine virtuelle est dédiée à USB, pour limiter le risque d'une attaque type Stuxnet. Qubes OS fait tourner des applications non modifiées, avec toutes leurs bogues, donc, mais les isole les unes des autres pour limiter les conséquences d'une faille de sécurité. Le gestionnaire de fenêtres décore les machines virtuelles de couleurs différentes pour limiter le risque de confusion. Par défaut, les machines virtuelles ne communiquent pas (par exemple, le copier-coller ne marche qu'entre fenêtres d'une même machine virtuelle) mais rappelez-vous que le but est de faire de la sécurité raisonnable et utilisable donc la communication reste possible, mais explicite, et donc un peu plus compliquée pour que l'utilisateurice soit bien conscient de franchir des frontières.
Juste à côté, il y avait un autre projet de sécurité, qui partait sur une démarche très différente. Genode est un noyau écrit en partant de zéro (alors que Qubes OS utilise Linux+Xen), qui fait tourner des machines virtuelles bien isolées. Pour pouvoir gérer le maximum de matériel, Genode peut utiliser les pilotes de Linux en mode utilisateur (pas dans le noyau).
L'allée des food trucks, ici celui de Mozilla :
Première rédaction de cet article le 29 janvier 2025
Il vient d'y avoir 3 000 articles sur ce blog.
Aujourd'hui, 29 janvier 2025, où le trois millième article a été atteint, il y a 21,5 millions de caractères et 1,194 million de mots. La qualité des 3 000 articles, et leur taille, sont évidemment très variables… Vous pouvez trouver d'autres statistiques (utiles ?).
Voici le rythme de publication d'articles sur ce
blog, depuis qu'il a été lancé sous sa forme
actuelle en juillet 2005 :
On y voit bien une nette baisse en quantité (et en qualité ?) depuis le début, l'effet des mois précédant la sortie de mon livre (il y a du travail pour tout relire), guère d'effet de la pandémie de Covid-19, et, par contre, une nette baisse de régime en 2023.
Le graphique a été fait par l'excellent gnuplot, avec ce fichier de commandes :
set terminal png size 1800, 900 set xlabel "Month" set xdata time set timefmt "%Y-%m" set format x "%m/%Y" set xtics rotate by 90 right set xrange ["2005-07":] # Increment must be in seconds :-( set xtics "07/2005", 10540800 set ylabel "Published articles" set title "My blog's activity" plot "blog.dat" using 1:2 with lines title ""
Le fichier de données a été produit par ce script Python :
#!/usr/bin/python import Utils import time import re start = time.time() files = Utils.entries(thedir="../entries") + Utils.entries(thedir="../RFC") data = {} for thefile in files: match = re.match("^([0-9]+-[0-9]+)-", thefile[1]) if not match: raise Exception("Invalid date %s" % thefile[1]) month = match.group(1) if month in data: data[month] = data[month] + 1 else: data[month] = 1 months = sorted(data.keys()) print("# Gnuplot data file for my blog") for month in months: print("%s %i" % (month, data[month]))
Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : T. Li (Juniper Networks)
Pour information
Première rédaction de cet article le 29 janvier 2025
Tout le monde connait aujourd'hui l'utilisation de constellations de satellites en orbite basse pour les télécommunications et, par exemple, pour l'accès à l'Internet. Contrairement à l'ancienne technique de communication via des satellites en orbite géostationnaire, la communication directe entre satellites y joue un rôle important. Les satellites se déplacent les uns par rapport aux autres, changeant en permanence la topologie de ce réseau. Alors, comment se fait le routage ? Ce RFC décrit une méthode possible, reposant largement sur le protocole IS-IS.
Ce n'est pas forcément la technique réellement utilisée. Les constellations existantes, dont la plus connue est Starlink, sont des entreprises privées, très secrètes, et qui ne décrivent pas leur configuration interne. Ce RFC est donc un travail de réflexion, mené à partir des rares informations publiques. Il ne peut pas spécifier une solution complète. Si vous envisagez de créer une constellation, il vous restera du travail pour avoir une solution de routage.
D'abord, il faut voir les particularités de ce réseau de satellites. Il est bien moins fiable qu'un réseau terrestre (l'espace est agité, un satellite en panne n'est pas facile à réparer) et il est tout le temps en mouvement. Ce rythme important de changement est un défi pour les protocoles de routage. Sauf si les satellites sont exactement sur la même orbite, leur mouvement relatif fait qu'on a une possibilité de communiquer à certains moments seulement, voire quasiment jamais. Si deux satellites se déplacent en direction opposée, leur vitesse relative, de l'ordre de dizaines de milliers de km/h, ne permettra guère de communication entre eux.
Par contre, un point qui va faciliter les choses est que ces mouvements, et donc l'établissement et la coupure du lien, sont prévisibles. On peut compter sur Kepler et Newton !
La section 1.2 du RFC rappelle le vocabulaire important. Notons le sigle ISL, pour Inter-Satellite Link, la liaison directe entre satellites, typiquement via un faisceau laser. (Le RFC cite ce très vieil article de Bell, « On the Production and Reproduction of Sound by Light ».) Si vous ne le connaissez pas, il faut aussi apprendre le sigle LEO, pour Low Earth Orbit, désignant les satellites qui orbitent à moins de 2 000 km de la surface de la Terre. On utilisera aussi SR (Segment Routing), la technique du routage par segments, décrite dans le RFC 8402 et SID (Segment IDentifier), qui vient de cette technique. Et IS-IS (Intermediate System to Intermediate System ) ? Ce protocole de routage est normalisé par l'ISO (et donc la spécification n'est normalement pas librement disponible) mais il est aussi décrit dans le RFC 1142 et le RFC 1195 explique comment s'en servir pour IP. Attention : c'est un vieux RFC, datant d'une époque où on pensait encore que les protocoles OSI avaient peut-être un avenir (aujourd'hui, ils n'ont même pas de page Wikipédia). Le RFC 1195 se concentre donc sur la possibilité d'utiliser IS-IS pour router à la fois OSI et TCP/IP. Aujourd'hui, il ne sert plus qu'aux protocoles Internet.
La section 2 de notre RFC rappelle les points essentiels des satellites LEO, qui vont impacter les choix techniques. Quand deux satellites se parlent via un ISL (Inter-Satellite Link), la liaison ne peut avoir qu'une durée limitée, les deux satellites ne restant pas visibles l'un par l'autre éternellement, s'ils sont sur des orbites différentes. Par contre, les périodes de visibilité et de non-visibilité peuvent être calculées à l'avance, on peut compter sur les lois de la physique.
Les constellations peuvent être de grande taille. En 2021, déjà, celle du milliardaire d'extrême-droite représentait un tiers du total des satellites en orbite. Aujourd'hui, des constellations de dizaines de milliers de satellites sont prévues (occupant l'espace public et bloquant la visibilité sans vergogne). Les protocoles de routage traditionnels peuvent gérer des réseaux de grande taille mais à condition qu'ils soient relativement statiques, avec juste une panne ou une addition d'un lien de temps en temps, ce qui n'est pas le cas pour des réseaux de satellites en mouvement. L'IETF a sous la main deux protocoles de routage normalisés pour les réseaux mono-organisation, OSPF (RFC 2328 et RFC 5340) et IS-IS (RFC 1195). (Il existe d'autres protocoles pour ces réseaux mais convenant plutôt à des réseaux plus petits.) Tous les deux sont à état des liaisons et, pour passer à l'échelle, tous les deux permettent de partitionner le réseau en zones (areas) à l'intérieur desquelles l'information de routage est complète, alors qu'entre zones, on ne passe qu'une partie de l'information. Dans OSPF, il y a forcément une zone spéciale, l'épine dorsale (backbone, la zone de numéro 0). Rien que pour cela, le RFC estime qu'OSPF ne serait pas un bon choix : contrairement aux réseaux terrestres, les constellations n'ont rien qui pourrait servir d'épine dorsale. IS-IS repose sur un système différent, où des zones dites « L1 » (de niveau 1) regroupent des parties du réseau qui ne servent pas au transit entre zones, qui est assuré par des zones « L2 ». La machine individuelle peut aussi bien être dans L1 que dans L2 ou même dans les deux. Si on adoptait le système simple de mettre chaque satellite dans une zone L2 (puisque tout satellite peut servir au transit), on perdrait tous les avantages du partitionnement. L'utilisation de IS-IS va donc nécessiter des ajustements.
La section 3 du RFC expose le mécanisme de transmission des paquets choisi. Elle propose d'utiliser MPLS (RFC 3031), en raison de sa souplesse (puisque la topologie change tout le temps), avec le SR (Segment Routing) du RFC 8402 (et RFC 8660 pour son adaptation à MPLS). Dans cette vision, il n'y a pas de transmission au niveau IP et donc un traceroute ne montrerait pas le trajet entre les satellites.
Reste le choix de l'IGP. La section 4 décrit la préférence de l'auteur pour IS-IS. Dans cette hypothèse, tous les satellites seraient des nœuds L1L2 (appartement aux deux types de zones). Le passage à l'échelle serait assuré grâce au système des relais, normalisé dans le RFC 9666. Un réseau de 1 000 zones L1, chacune comportant 1 000 satellites, n'aurait besoin que de mille entrées (et pas un million) dans ses tables de routage, aussi bien L1 que L2. Idem pour la table des étiquettes MPLS.
La section 5 introduit le concept de bande (stripe). La bande est un ensemble de satellites dont les orbites sont suffisamment proches pour que la connectivité entre eux change peu.
On l'a dit,
une particularité importante des réseaux de satellites est la
prévisibilité des coupures. Un calcul de mécanique
céleste permet de dire quand deux satellites
ne pourront plus communiquer. On peut bien sûr router comme s'il
s'agissait de pannes imprévues, mais on améliorera certainement la
qualité du routage (et on diminuera le nombre de pertes de paquets
lorsque la topologie change) si on prévient les satellites à
l'avance. Par exemple, une fois informés d'un changement proche, les
routeurs peuvent annoncer une métrique très élevée pour les ISL qui
vont bientôt être coupés, comme on le fait sur les réseaux
terrestres quand une maintenance est prévue. Il y a une proposition
concrète d'un mécanisme d'information dans le brouillon
draft-ietf-tvr-schedule-yang
.
Quelques lectures recommandées par notre RFC :
Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : K. Fujiwara (JPRS), P. Vixie (AWS
Security)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 28 janvier 2025
Les requêtes et réponses DNS peuvent voyager sur divers transports, mais le plus fréquent est UDP. Une réponse de grande taille sur UDP peut dépasser la MTU et donc devoir être fragmentée. La fragmentation crée divers problèmes et ce RFC décrit les problèmes, et comment éviter la fragmentation.
Un peu de rappel : avec UDP (RFC 768), il n'y a pas de négociation de la taille des paquets et un émetteur UDP peut donc, en théorie, envoyer ce qu'il veut, jusqu'à la limite maximum de 65 536 octets. Bon, en pratique, on voit rarement un paquet aussi grand. Déjà, la norme originelle du DNS mettait une limite à 512 octets. Cette limite a disparu depuis longtemps, grâce à EDNS (RFC 6891) et, désormais, le logiciel DNS peut indiquer la taille maximale qu'il est prêt à recevoir. Pendant longtemps, on voyait souvent une taille de 4 096 octets, ce qui excède la MTU de la plupart des liens Internet. Un paquet aussi grand devait donc être fragmenté (que cela soit en IPv4 ou en IPv6). Voici un exemple de réponse plus grande que la MTU typique :
% dig oracle.com TXT … ;; MSG SIZE rcvd: 3242
Si cette réponse était transmise dans un seul datagramme UDP, elle serait fragmentée, ce qui ne marcherait pas toujours, comme l'explique le RFC 8900 et créerait des risques de sécurité.
TCP (RFC 9293) évite le problème grâce à la négociation de la MSS (Maximum Segment Size, section 3.7.1 du RFC 9293) et au découpage en paquets plus petits que la MTU. La requête DNS ci-dessus ne poserait aucun problèmes avec TCP :
% dig +tcp oracle.com TXT … ;; SERVER: 192.168.2.254#53(192.168.2.254) (TCP) ;; MSG SIZE rcvd: 3242
Mais UDP, plus rigide, n'a pas un tel mécanisme. On pourrait tout faire en TCP (le RFC 7766 rappelle opportunément qu'il n'est pas en option : tout serveur DNS doit l'accepter) mais cela a d'autres inconvénients donc restons avec UDP pour l'instant.
Donc, il est recommandé d'éviter la fragmentation. La section 3
traduit cela en recommandations concrètes : ne pas fragmenter au
départ (IPv6) et mettre le bit DF (Don't fragment,
pour IPv4, cf. RFC 791) car, sinon, un paquet
IPv4 pourra être fragmenté en route (cf. section 7.1). Malheureusement, tous
les systèmes
d'exploitation ne donnent pas un accès facile à ce
bit. Sur Linux, par
exemple, il faut passer (ce qui n'est pas très intuitif) par
l'option IP_MTU_DISCOVER
, ce qui mène à
d'autres problèmes (cf. annexe C du RFC).
Le logiciel qui répond à une requête DNS doit la maintenir sous une taille qui est le miminum de ces quatre tailles :
Si on ne peut pas fabriquer une réponse de taille inférieure à ce minimum, il faut mettre le bit TC (TrunCated) dans la réponse DNS.
Ça, c'était pour les répondeurs (les serveurs DNS). Et pour les
demandeurs (les clients) ? Ils ne devraient pas indiquer en EDNS une
taille supérieure au minimum des trois dernières valeurs citées plus
haut. Ici, vue par tshark,
la requête faite par dig avec l'option
+dnssec
mais sans autre mention, notamment de
taille. dig indique une taille maximale de 1 232 octets, conforme
aux recommandations du RFC :
Domain Name System (query) Flags: 0x0120 Standard query 0... .... .... .... = Response: Message is a query … Queries re: type NS, class IN Name: re [Name Length: 2] [Label Count: 1] Type: NS (2) (authoritative Name Server) Class: IN (0x0001) Additional records <Root>: type OPT Name: <Root> Type: OPT (41) UDP payload size: 1232 Higher bits in extended RCODE: 0x00 EDNS0 version: 0 Z: 0x8000 1... .... .... .... = DO bit: Accepts DNSSEC security RRs .000 0000 0000 0000 = Reserved: 0x0000 Data length: 12 Option: COOKIE Option Code: COOKIE (10) Option Length: 8 Option Data: 83d7d3e78b76b45d Client Cookie: 83d7d3e78b76b45d Server Cookie: <MISSING>
Le RFC demande également aux clients DNS de refuser les réponses fragmentées, compte tenu de certains risques de sécurité (risque de ne pas pouvoir valider les réponses), et de ne pas hésiter à essayer avec d'autres protocoles de transport, comme TCP.
La section 4, elle, rassemble les recommandations pour les hébergeurs DNS. Comme ils contrôlent les zones publiées, ils peuvent faire en sorte que les réponses ne soient pas trop longues, rendant la fragmentation inutile. Par exemple, ils devraient faire attention à ne pas lister « trop » de serveurs de noms, ne pas mettre « trop » d'enregistrements d'adresses à ces serveurs, etc. Un conseil DNSSEC : certains algorithmes cryptographiques ont des clés et des signatures plus courtes que d'autres. Utilisez-les. (Et, donc, ECDSA ou EdDSA, plutôt que RSA.)
Le RFC note aussi que certains logiciels ne sont pas conformes à la norme. Par exemple, la taille maximale indiquée dans la requête est ignorée et une réponse plus grande que cette taille renvoyée. Et, bien sûr, on trouve encore des serveurs qui n'acceptent pas TCP.
Mais quel était le problème de sécurité avec la fragmentation, au juste ? Comme détaillé en section 7.3, qui cite le papier « Fragmentation Considered Poisonous », de Amir Herzberg et Haya Shulman, l'empoisonnement de la mémoire d'un résolveur est plus facile lorsqu'il y a fragmentation, puisque certains des éléments dans le paquet qui peuvent être utilisés pour juger de la légitimité d'une réponse peuvent se retrouver dans un autre fragment. (Voir aussi cet exposé au RIPE.) Ces attaques permettent ensuite plein d'autres attaques, par exemple contre les autorités de certification.
DNSSEC résout évidemment ces problèmes mais attention, les délégations ne sont pas signées donc DNSSEC ne protège que si les victimes ont signé leur zone et, en prime, DNSSEC permet de détecter la tentative d'empoisonnement et de la refuser, mais pas d'obtenir la bonne réponse.
L'annexe A du RFC détaille les observations quantitatives sur la taille des réponses et les raisons qui peuvent guider le choix des tailles maximum. La section 5 du RFC 8200 garantit que 1 280 octets passeront partout en IPv6, c'est la MTU minimale (mais elle est bien plus basse dans l'ancienne version d'IP). Le RFC 4035 (section 3) impose 1 220 octets minimums pour DNSSEC. Le DNS flag day 2020 proposait 1 232 octets comme taille maximale acceptée (MTU de 1 280 octets, moins 48 octets d'en-têtes). La MTU typique dans l'Internet est de 1 500 octets et, au moins dans le cœur, il n'y a pratiquement pas de liens avec une MTU plus basse. Une taille de 1 452 octets (la MTU moins les en-têtes) est donc réaliste mais, pour tenir compte de certaines techniques qui abaissent la MTU effective, comme les tunnels, notre RFC arrive finalement aux 1 400 octets cités plus haut (section 3).
L'annexe B, elle, décrit le concept de « réponses minimisées ». Certaines mises en œuvre du DNS ont une option qui permet de dire « essaie de réduire la taille de la réponse, en n'incluant pas certaines informations non indispensables ». Attention, des informations comme la colle (les adresses IP des serveurs nommés dans la zone qu'ils servent) sont indispensables (RFC 9471).
Par exemple, pour un serveur faisant autorité qui fait tourner BIND, qui envoie des réponses minimales par défaut, si on lui demande de ne pas être si économe :
options { minimal-responses no; };
Il va alors renvoyer des informations qu'on n'avait pas demandé et dont l'utilité se discute (ici, les deux enregistrements NS) :
% dig @::1 -p 8053 under.michu.example … ;; ANSWER SECTION: under.michu.example. 600 IN A 192.0.2.56 ;; AUTHORITY SECTION: michu.example. 600 IN NS ns2.nic.fr. michu.example. 600 IN NS ns1.nic.fr. …
Par défaut, BIND, conformément aux recommandations de notre RFC, n'enverra pas ces deux NS. Ici, il s'agissait d'un serveur faisant autorité mais cette option s'applique aussi aux résolveurs. (Notez que, pour d'autres logiciels, le fait d'envoyer des réponses minimales est par défaut, et pas modifiable.)
En parlant de logiciels, l'annexe C liste un certain nombre de serveurs DNS libres (BIND, Knot, Knot resolver, Unbound, PowerDNS, PowerDNS recursor et dnsdist) en regardant quelles recommandations de ce RFC sont appliquées.
Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : J. Daley, S. Turner (IETF
Administration LLC)
Première rédaction de cet article le 27 janvier 2025
L'IETF utilise, pour le cœur de son travail de normalisation, l'Internet : listes de diffusion, forge de documents, outils divers de travail en groupe. Mais il y a quand même des réunions physiques, trois par an, rien ne remplaçant à 100 % le contact direct. Les discussions sur les lieux de ces réunions sont un des sujets favoris à l'IETF et ce RFC résume les règles actuelles de sélection d'un lieu. Pour savoir pourquoi il n'y a jamais eu de réunion en Inde, une seule en Chine et une seule en Amérique du Sud, lisez-le.
La politique officielle est documentée dans les RFC 8718 et RFC 8719. Ce nouveau RFC 9712 vise à détailler ces RFC et à expliquer certains points, d'autant plus que des choses ont pu changer depuis ces RFC (écrits avant la pandémie de Covid-19…). Pas de changements radicaux de la politique, surtout des clarifications (la section 2 de notre RFC les résume).
Ainsi, le RFC explique que ce sera toujours l'IASA (IETF Administration Support, RFC 8711), qui décidera, pas l'IETF dans son ensemble. Il y a déjà eu des cas d'enthousiasme de l'IETF pour un lieu de réunion… qui ne se traduisaient pas par un grand nombre de participants, bien au contraire (je me souviens que ce fut le cas de la réunion de Buenos Aires).
Le RFC 8718 énonçait que les hôtels devaient être « proches » du lieu de la réunion. Certains avaient interprété cela comme imposant un seul lieu (la one-roof policy). Notre nouveau RFC clarifie donc que « proche » veut dire « moins de dix minutes à pied », pas forcément sous le même toit.
L'IASA réservait traditionnellement un grand nombre de chambres dans les hôtels proches mais cela a toujours fait courir un risque financier en cas d'annulation, comme cela s'est produit pendant la pandémie de Covid-19. Depuis cette pandémie, les hôtels sont d'ailleurs bien plus prudents, demandant des paiements en avance. Bref, notre RFC n'impose plus de chiffre minimal de réservation, contrairement à ce que disait la section 3.2.4 du RFC 8718.
Une ancienne tradition disparait avec ce RFC : dans les réunions professionnelles d'informaticiens·nes, il y avait toujours une terminal room, ainsi appelée car elle était autrefois équipée de terminaux pour se connecter à ses ordinateurs distants. L'évolution de l'informatique fait que cette salle n'a plus de terminaux, mais juste tables, chaises et prises de courant. Désormais, elle n'est même plus obligatoire dans les réunions IETF (où on voyait de toute façon souvent des gens ouvrir leur ordinateur portable assis par terre dans le couloir, ou au bistrot d'à côté).
Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : J. Abley (Cloudflare), J. Schlyter
(Kirei AB), G. Bailey
(Independent), P. Hoffman (ICANN)
Pour information
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 25 janvier 2025
Le mécanisme d'authentification des informations DNS nommé DNSSEC repose sur la même structure arborescente que le DNS : une zone publie un lien sécurisé vers les clés de ses sous-zones. Un résolveur DNS validant n'a donc besoin, dans la plupart des cas, que d'une seule clé publique, celle de la racine. Elle lui servira à vérifier les clés des TLD, qui serviront à valider les clés des domaines de deuxième niveau et ainsi de suite. Reste donc à configurer la clé de la racine dans le résolveur : c'est évidemment crucial, puisque toute la sécurité du système en dépend. Si un résolveur est configuré avec une clé fausse pour la racine, toute la validation DNSSEC est menacée. Comment est-ce que l'ICANN, qui gère la clé principale de la racine, publie cette clé cruciale ? C'est documenté dans ce RFC qui remplace le RFC 7958, avec plusieurs changements, comme l'abandon des signatures PGP.
Notez que ce nouveau RFC documente l'existant, déjà mis en œuvre, et ne prétend pas décrire la meilleure méthode. Notez aussi que ce format et cette méthode de distribution pourraient encore changer à l'avenir, comme ils l'ont fait depuis la sortie du RFC 7958.
Si vous voulez réviser DNSSEC d'abord, outre les RFC de base sur ce système (RFC 4033, RFC 4034, RFC 4035...), notez surtout le RFC 6781, qui décrit les questions opérationnelles liées au bon fonctionnement de DNSSEC.
Les clés publiques configurées dans les résolveurs qui valident avec DNSSEC, sont appelées « points de départ de la confiance » (trust anchors). Un point de départ de la confiance est une clé dont l'authenticité est admise, et non pas dérivée d'une autre clé, via une chaîne de signatures. Il en faut au moins un, celui de la racine, bien que certains résolveurs en ajoutent parfois deux ou trois pour des zones qu'ils veulent vérifier indépendamment. Lorsque le résolveur recevra une réponse de la racine, signée, il l'authentifiera avec la clé publique de la racine (le point de départ de la confiance). S'il veut vérifier une réponse d'un TLD, il l'authentifiera avec la clé publique du TLD, elle-même signée (et donc authentifiée) par la clé de la racine. Et ainsi de suite même pour les zones les plus profondes.
(Notez qu'il existe deux clés pour la plupart des zones, la KSK - Key Signing Key, et la ZSK - Zone Signing Key, mais on ne s'intéresse ici qu'aux KSK, c'est elles qui sont signées par la zone parente, et configurées comme points de départ de la confiance.)
La gestion de la clé de la racine par l'ICANN (via sa filiale PTI) est décrite dans leur DPS (DNSSEC Practice Statement).
Le RFC rappelle aussi qu'il y a d'autres possibilités d'installation d'un point de départ de la confiance. Par exemple, si un tel point a été configuré une fois, ses remplacements éventuels peuvent être faits via le RFC 5011.
La section 2 du RFC décrit le format des clés publiées par l'IANA. Il s'agit d'un fichier XML contenant les condensats des clés, utilisant le format de présentation du RFC 4034. Leur syntaxe formelle est exprimée en Relax NG, le schéma est en section 2.1 du RFC (copie locale). Une vérification du fichier avec rnv fonctionne :
% rnv dnssec-root-trust-anchors.rnc root-anchors.xml root-anchors.xml
Voici un exemple du fichier XML (à ne pas prendre comme s'il faisait autorité, évidemment) :
<TrustAnchor id="0C05FDD6-422C-4910-8ED6-430ED15E11C2" source="http://data.iana.org/root-anchors/root-anchors.xml"> <Zone>.</Zone> <KeyDigest id="Klajeyz" validFrom="2017-02-02T00:00:00+00:00"> <KeyTag>20326</KeyTag> <Algorithm>8</Algorithm> <DigestType>2</DigestType> <Digest>E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D</Digest> <PublicKey>AwEAAaz/…</PublicKey> <Flags>257</Flags> </KeyDigest> </TrustAnchor>
L'élément <KeyTag>
indique
l'identifiant de la clé, actuellement 20326, comme on peut le
voir avec dig :
% dig +multi +nodnssec . DNSKEY ... ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ... ;; ANSWER SECTION: . 86254 IN DNSKEY 257 3 8 ( AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTO … ) ; KSK; alg = RSASHA256 ; key id = 20326 ...
L'attribut id
de l'élément
<TrustAnchor>
est un UUID. L'attribut
id
de l'élément
<KeyDigest>
sert à identifier un
condensat particulier. Le fichier peut également comporter des
commentaires XML (mais ce n'est pas le cas actuellement). Le fichier
indique aujourd'hui le condensat de la clé et la clé mais cette
dernière est optionnelle (on ne s'en sert pas par la suite).
Pour produire un enregistrement DS à partir de
ce fichier XML, il suffit de mettre
<KeyTag>
,
<Algorithm>
,
<DigestType>
et
<Digest>
bout à bout. Par exemple, avec
le fichier XML ci-dessus, cela donnerait :
. IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
(Des résolveurs comme Unbound acceptent ce format, pour le point de confiance de départ.)
Ici, je n'ai montré qu'une clé mais il peut y en avoir plusieurs,
donc plusieurs <KeyDigest>
. En novembre
2024, le fichier comportait trois clés, l'ancienne 19036, abandonnée
il y a des années, l'actuelle 20326 et la future 38696 (qui n'était pas encore
publiée dans le DNS mais qui l'a été en janvier 2025).
Comment récupérer le fichier XML de
manière à être sûr de son authenticité ? C'est ce que spécifie la
section 3 du RFC : on utilise HTTPS (ou HTTP tout court mais ce n'est pas
forcément une bonne idée et, de toute façon, aujourd'hui, une
politique HSTS le rend difficile). L'URL est
https://data.iana.org/root-anchors/root-anchors.xml
. Si
on fait confiance à l'AC utilisée par
l'ICANN, on peut être sûr de l'authenticité du fichier. (Mais notez,
comme le fait remarquer gregR, que
data.iana.org
et iana.org
n'ont pas d'enregistrement CAA, RFC 8659.)
Une
autre solution est de le récupérer en HTTP et de le vérifier avec la
signature fournie, en CMS (RFC 5652) - son URL est
https://data.iana.org/root-anchors/root-anchors.p7s
. (Non,
je ne sais pas comment la vérifier.)
Bien sûr, un résolveur
validant n'est pas obligé d'utiliser ces points de départ de la
confiance. Cela reste une décision locale. La très grande majorité
des résolveurs utiliseront sans doute plutôt un
paquetage fourni par leur système
d'exploitation, comme dns-root-data
sur Debian.
Pour les amateurs d'histoire, l'annexe B rappelle que la clé 19036 (également appelée KSK-2010) avait été générée au cours d'une cérémonie à Culpeper, le 16 juin 2010. Elle avait été publiée dans le DNS pour la première fois le 15 juillet 2010. La clé actuelle, la 20326 (également nommée KSK-2017), a été également générée à Culpeper le 27 octobre 2016 et publiée le 11 novembre 2018. La liste des cérémonies de création de clés est en ligne.
L'annexe A de notre RFC contient les changements depuis le RFC 7958. Notamment :
Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : T. Pauly (Apple), B. Trammell (Google Switzerland), A. Brunstrom (Karlstad University), G. Fairhurst (University of Aberdeen), C. Perkins (University of Glasgow)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF taps
Première rédaction de cet article le 23 janvier 2025
Ce RFC s'inscrit dans un projet IETF datant de quelques années : formaliser davantage les services que rend la couche Transport aux applications. Le but est de permettre de développer des applications en indiquant ce qu'on veut de la couche Transport, en rentrant le moins possible dans les détails. Ce RFC décrit l'architecture générale, le RFC 9622 spécifiant quant à lui une API plus concrète.
Des API pour les applications parlant à la couche Transport, il y en a beaucoup. La plus connue est bien sûr l'interface « socket », qui a pour principal avantage d'être ancienne et très documentée, dans des livres (comme le génial Stevens) et dans d'innombrables logiciels libres à étudier (mais, par contre, la norme POSIX qui la spécifie officiellement, n'est toujours pas disponible publiquement). C'est d'ailleurs cette multiplicité d'API, donc beaucoup sont solidement installées dans le paysage, qui fait que je doute du succès du projet et de sa TSAPI (Transport Services API) : la base installée à déplacer est énorme.
Pourtant, ces API traditionnelles ont de nombreux défauts. Le RFC
cite par exemple l'incohérence : pour envoyer des données sur une
prise qui utilise du TCP en clair, on
utilise send()
mais quand
la communication est chiffrée avec TLS, c'est une autre
fonction (non normalisée). Pourtant, pour l'application, c'est la
même chose.
Toujours question cohérence, la terminologie n'est pas fixée et des termes comme flow, stream, connection et message ont des sens très différents selon les cas.
Le but de la nouvelle architecture est donc de permettre le développement d'une API (normalisée dans le RFC 9622) qui unifiera tout cela. (Notez que l'IETF, habituellement, normalise des protocoles et pas des API. Mais il y a déjà eu des exceptions à cette règle.) Un autre objectif est de permettre de mettre dans les bibliothèques du code qui autrefois était souvent dupliqué d'une application à l'autre, comme la mise en œuvre de l'algorithme des « globes oculaires heureux » (RFC 8305).
J'avais déjà présenté le projet TAPS, qui était alors nettement moins avancé, dans un exposé à la conférence MiXiT (dont voici le support).
L'architecture présentée ici est dérivée de l'analyse des protocoles de transport du RFC 8095 et de leur synthèse dans le RFC 8923. Pour les questions de sécurité, il est également conseillé de lire le RFC 8922.
L'interface pour les applications (TSAPI : Transport Services Application Programming Interface) sera fondée sur l'asynchronicité, en mode programmation par évènements. (Opinion personnelle : c'est une mauvaise idée, excessivement favorable aux langages sans vrai parallélisme, comme C. J'aurais préféré un modèle synchrone, fondé sur des fils d'exécution parallèle, plus simple pour la·e programmeur·se.)
Une des idées de base du projet est de développer une API qui soit indépendante du langage de programmation. C'est à mon avis fichu dès le départ. Outre cette question du parallélisme, la gestion des erreurs est très variable d'un langage à l'autre : codes de retour (en C), exceptions, valeurs mixtes comme en Haskell ou en Zig… L'API du RFC 9622 ne plaira donc pas à tout le monde.
La section 2 du RFC expose le modèle utilisé par l'API. D'abord, un résumé de la traditionnelle API « socket » :
SOCK_STREAM
mais, en pratique, son
utilisation nécessite de connaitre le protocole de transport utilisé),La nouvelle API généralisera ce modèle : l'application utilise l'API Transport Services (TSAPI), en indiquant les propriétés souhaitées pour la connexion, et la mise en œuvre de l'API parlera à tous les protocoles de transport (et de chiffrement) possibles, qu'ils soient placés dans le noyau ou pas. La résolution de noms est intégrée dans ce cadre, entre autres parce que certains services sous-jacents, notamment TLS, nécessitent de connaitre le nom du service auquel on accède (ce qui n'est pas le cas avec l'API socket, qui ne manipule que des adresses IP).
Pendant qu'on en parle, cette idée d'intégrer la résolution de
noms est également dans des projets comme Connect by
Name, qui vise à permettre aux applications de juste
demander connect(domain-name, port, tls=true)
et que tout soit fait proprement par l'API, notamment les fonctions
de sécurité (vérifier le nom dans le
certificat, par exemple, ce qui n'est pas
trivial à faire proprement).
On l'a dit plus haut, TSAPI est asynchrone. Le RFC estime que ce mode d'interaction avec le réseau, fondé sur des évènements, est plus fréquent et même « plus naturel ». C'est un des reproches que je ferais au projet. Je préfère le modèle d'interactions synchrone, notamment pour des langages de programmation ayant la notion de fils d'exécution séparés (les goroutines en Go, les processus en Erlang ou Elixir, les tâches d'Ada…), dans l'esprit des Communicating sequential processes (et j'en profite pour recommander le génial livre de Hoare, bien qu'il soit assez abstrait et d'un abord austère). Rien n'est naturel en programmation (ou ailleurs : « la seule interface utilisateur naturelle est le téton ; tout le reste est appris ») et le RFC se débarrasse un peu vite du choix effectué et ne cherche pas vraiment à le justifier.
Donc, l'application qui veut, par exemple, recevoir des données, va appeler l'API pour demander une lecture et l'API préviendra l'application quand des données seront prêtes. Au contraire, dans un modèle synchrone, le fil qui veut lire sera bloqué tant qu'il n'y aura rien à lire, les autres fils continuant leur travail.
Dans l'API socket, on peut avoir des messages séparés lorsqu'on utilise UDP mais, avec TCP, c'est forcément une suite d'octets, sans séparation des éventuels messages. Chaque protocole applicatif doit donc, s'il en a besoin, inventer sa méthode de découpage en messages : DNS et EPP indiquent la longueur du message avant d'envoyer le message, HTTP/1 l'indique dans l'en-tête mais a un mécanisme de découpage fondé sur des délimiteurs (cf. RFC 9112, sections 6.1 et 7), HTTP/2 et HTTP/3 ont leurs ruisseaux (une requête par ruisseau), TLS utilise également une indication de longueur. Au contraire, avec TSAPI, il y a toujours un découpage en messages, qui seront encodés en utilisant les capacités du protocole de transport sous-jacent (par un mécanisme nommé cadreur - framer).
TSAPI permet des choses qui n'étaient pas possibles avec les API classiques, comme d'avoir plusieurs paires d'adresses IP entre les machines qui communiquent, avec changement de la paire utilisée pendant une connexion.
Un des intérêts de cette nouvelle API est de permettre aux applications de fonctionner de manière plus déclarative et moins impérative. Au lieu de sélectionner tel ou tel protocole précis, l'application déclare ses exigences, et TSAPI se débrouillera pour les lui fournir (section 3.1).
Bon, c'est bien joli, de vouloir que les applications ne connaissent pas les protocoles (ce qui permet de les faire évoluer plus facilement) mais, quand même, parfois, il existe des fonctions très spécifiques d'un protocole particulier qu'il serait bien sympa d'utiliser. La section 3.2 de notre RFC couvre donc cette question. Par exemple, l'option User Timeout de TCP (RFC 5482) est bien pratique, même si elle est spécifique à TCP. Donner accès à ces spécificités soulève toutefois un problème : parfois, l'application souhaite une certaine fonction, et peut donc s'en passer, et parfois elle l'exige et la connexion doit échouer si elle n'est pas disponible pour un certain protocole. L'API devra donc distinguer les deux cas.
Une fois que l'application a indiqué ses préférences et ses exigences, l'API devra sélectionner un protocole de transport. Parfois, plusieurs protocoles conviendront. Si l'application demande juste un transport fiable d'une suite d'octets, TCP, SCTP et QUIC conviendront tous les trois (alors qu'UDP serait exclu).
Comme rien n'est gratuit en ce bas monde, le progrès de l'abstraction, et une relative indépendance de l'application par rapport aux particularités des protocoles de transport, ont un inconvénient : le système devient plus complexe. Les développeureuses d'application lorsqu'il faut déboguer, et les administrateurices système qui vont installer (et essuyer les plâtres !) les applications vont avoir des difficultés nouvelles. Des fonctions de déboguage devront donc être intégrées. (Personnellement, je pense aussi à la nécessité que la bibliothèque qui mette en œuvre TSAPI coopère au déboguage pour les protocoles chiffrés, qui ne permettront pas tellement d'utiliser Wireshark. Voir mon exposé à Capitole du Libre.)
Et enfin, après ces généralités, passons aux concepts qui devront être visibles par l'application, rapprochons-nous de la future API (section 4 du RFC). D'abord, la Connexion. Non, ce n'est pas une erreur d'avoir capitalisé le mot. Le RFC utilise la même méthode pour montrer qu'il s'agit d'un concept abstrait, qui ne correspond pas forcément parfaitement aux connexions du protocole de transport (pour ceux qui ont ce concept). La Connexion est donc au cœur de l'API Transport Services. Elle se fait entre deux points, le local et le distant, chacun identifié par un Endpoint Identifier. Elle a un certain nombre de propriétés, qui peuvent s'appliquer avant (et influenceront la sélection du protocole de transport, et/ou des machines auxquelles ont se connecte), juste avant ou pendant la Connexion, par exemple l'utilisation du 0-RTT (RFC 9622, section 6.2.5) ou l'exigence du chiffrement (cf. RFC 8922), mais il y a aussi des propriétés pour chaque message individuel. Ensuite, on va :
Close
ou salement avec Abort
).
Un écoutant va créer une Pré-Connexion et attendre les demandes, ce
n'est pas lui qui va établir les connexions. L'entité active, elle,
va se connecter (fonctions Listen
et
Initiate
). Et le
pair-à-pair ? Il sera également possible via
la fonction Rendezvous
. Ce sera à l'API de
gérer les services comme STUN (RFC 8489),
souvent indispensables en pair-à-pair.
Le transfert de données a les classiques fonctions
Send
et Receive
(qui n'est
pas synchrone, rappelons-le, donc qui ne bloque pas). Mais il y a
aussi un nouveau concept, le cadreur (traduction peu imaginative de
framer). C'est la couche logicielle qui va ajouter et/ou modifier les
données du message pour mettre en œuvre des exigences du protocole,
par exemple indiquer les frontières entre messages dans un protocole
de transport qui n'a pas ce concept (comme TCP). Ainsi, les
protocoles EPP (RFC 5734) et
DNS (RFC 7766) nécessitent que chaque message soit
préfixé d'un seizet indiquant sa longueur. Un
cadreur peut faire cela automatiquement pour chaque message,
simplifiant la tâche de l'application (par exemple la bibliothèque
standard d'Erlang a cette
option - cf. packet
).
Enfin, un peu de sécurité et de vie privée (section 6). D'abord, les implémentations devront faire attention aux risques pour la vie privée si on réutilise l'état des connexions passées. C'est le cas des sessions TLS (RFC 8446, section 2.2) ou des gâteaux HTTP (RFC 6265), qui peuvent permettre de relier deux connexions entre elles, lien qu'on ne souhaite peut-être pas.
Et puis, en sécurité, le RFC rappelle qu'on ne doit pas se replier sur des solutions non sécurisées si la technique sécurisée échoue. Ainsi, si une application demande du chiffrement, mais que la connexion chiffrée échoue, il ne faut pas se rabattre sur une connexion en clair.
Notez que l'ensemble du projet TAPS a bénéficié de divers financements publics, par exemple de l'UE.
Une opinion personnelle sur ce projet ? Outre des critiques sur tel ou tel choix, comme l'asynchronisme, je suis malheureusement sceptique quant aux chances de réussite. Les API actuelles, avec tous leurs défauts, sont solidement installées, et dans le meilleur des cas, il faudra de nombreuses années pour que les formations s'adaptent et enseignent une API comme TSAPI.
Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : B. Trammell (Google Switzerland), M. Welzl (University of Oslo), R. Enghardt (Netflix), G. Fairhurst (University of Aberdeen), M. Kuehlewind (Ericsson), C. Perkins (University of Glasgow), P. Tiesel (SAP SE), T. Pauly (Apple)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF taps
Première rédaction de cet article le 23 janvier 2025
Voici un des RFC du projet TAPS, qui vise à proposer une vision cohérente des protocoles de transport aux applications. Ce RFC décrit (mais de manière assez abstraite) l'API de TAPS.
Avant de le lire, il est très fortement recommandé de réviser le RFC 9621, qui décrit les buts du projet TAPS, et les principes de l'API Transport Services (autrefois surnommée « post-sockets »). Mais le RFC 9621 restait assez abstrait, et notre RFC 9622 se fait un peu plus concret (sans aller jusqu'à une vraie API puisqu'il reste partiellement indépendant du langage de programmation utilisé).
Rappelons quelques principes de TSAPI (Transport Services API, l'API qui est le but final du projet TAPS). D'abord, l'API est asynchrone (ce qui n'est pas idéal pour les langages avec parallélisme comme Go ou Elixir). On crée des Connexions (la majuscule au début est là pour se distinguer du concept flou de connexion, et pour désigner un type d'objets particulier), voire des Préconnexions si on veut les configurer avant, on leur définit des propriétés (en indiquant si elles sont impératives ou facultatives), on peut ensuite activer les Connexions (ou écouter passivement que l'autre machine les active), puis on envoie et on reçoit des Messages. La section 3 du RFC résume l'API, et, si vous êtes pressé·e, vous pouvez vous contenter de cette section. Elle contient quelques exemples pratiques, en pseudo-code.
À propos de pseudo-code, le RFC note que les conventions de nommage de l'API ne pourront pas forcément être suivies religieusement par toutes les mises en œuvre puisque certains langages de programmation ont des règles différentes. Mais c'est un détail.
Parmi les points dignes d'intérêt dans le RFC, on note que les applications peuvent indiquer le domaine d'avitaillement (PvD, ProVisioning Domain, défini dans le RFC 7556) qu'elles veulent utiliser. Elles peuvent par exemple l'identifier par son nom de domaine (RFC 8801).
Autre point intéressant, les cadreurs (framers). Décrits dans la section 9.1.2, ce sont des couches logicielles qui vont mettre en œuvre les exigences du protocole sous-jacent. Lors d'une opération d'envoi ou de réception d'un Message, les cadreurs vont tenir compte du protocole pour transformer un Message en flux d'octets et réciproquement. (Le RFC suggère de regarder le RFC 9329, pour un exemple.)
Pour mettre en œuvre cette API assez abstraite dans un langage de programmation spécifique, l'annexe A du RFC donne quelques conseils. Il y a des mises en œuvre de TAPS (plusieurs sont listées dans le RFC 9623, annexe C). On peut citer :
Notez un point positif dans le RFC : l'annexe C du RFC 9623, qui décrit les mises en œuvre existantes donne non
seulement les URL « normaux » du projet, et ceux sur
GitHub mais aussi un lien
Software Heritage, pour la pérennité. C'est
une très bonne chose, car certains RFC ont une longue durée de
vie). Par exemple, NEAT est
mais aussi
https://github.com/NEAT-project/neat
.
https://archive.softwareheritage.org/swh:1:dir:737820840f83c4ec9493a8c0cc89b3159e2e1a57;origin=https://github.com/NEAT-project/neat;visit=swh:1:snp:bbb611b04e355439d47e426e8ad5d07cdbf647e0;anchor=swh:1:rev:652ee991043ce3560a6e5715fa2a5c211139d15c
Date de publication du RFC : Janvier 2025
Auteur(s) du RFC : P. Hoffman (ICANN), H. Flanagan
(Spherical Cow Consulting)
Pour information
Première rédaction de cet article le 18 janvier 2025
Vous le savez, les RFC ne sont plus en texte brut depuis des années, leur format officiel est du XML. Le système était décrit dans le RFC 7990, que ce nouveau RFC remplace. Il y a beaucoup de changements sur la forme et aussi sur le fond, notamment la possibilité de modifier un fichier déjà publié (sans changer sa sémantique, bien sûr).
La section 2 de notre RFC décrit ce qu'est la « version définitive » d'un RFC. Écrite dans le format RFCXML spécifié dans le RFC 7991, elle peut donc comporter des images en SVG (voir le RFC 7996) et des caractères non-ASCII (cf. RFC 7997). Cette version définitive contient tout ce qui est nécessaire pour produire le RFC publié. (Les versions de développement, avant la publication, peuvent utiliser des références externes, qui devront être résolues dans la version définitive, qui sera auto-suffisante.)
Mais le changement le plus spectaculaire de notre RFC 9720 est que cette version « définitive » peut désormais changer. Si on découvre un problème dans le fichier XML, il pourra être modifié, si cela ne change pas le sens, bien sûr. La section 2.1 décrit précisément les règles de changement. En cas de modification, les versions antérieures devront être gardées, avec leurs métadonnées (comme la date) et accessibles publiquement, comme les RFC l'ont toujours été (section 4), ce qui a beaucoup contribué au succès de l'Internet.
De nouvelles versions de publication, produites à partir de la version définitive, seront produites, soit parce que la version définitive a changé, soit parce que les outils ont évolué et permettent un meilleur rendu (section 3). (La re-publication pour corriger des erreurs de rendu existait déjà et la liste des cas est en ligne.)
Notez que ce RFC ne s'applique qu'au produit final. L'élaboration des RFC, via les Internet drafts, n'est pas concernée, même si elle va sans doute s'aligner. (Si vous en écrivez et que vous voulez utiliser le format XML, ce que je recommande, une page Web dédiée est là pour vous aider.)
La section 1.1 résume les changements depuis le RFC 7990. On garde le format XML normalisé dans le RFC 7991 mais on change le concept de « format canonique », qui mélangeait plusieurs choses. Il y a désormais :
Notre RFC spécifie dans quelles conditions on peut désormais changer la version finale (contrairement à la règle du RFC 9280). En gros, il faut que la sémantique reste inchangée. Cela permet d'effectuer les changements suite à des erreurs de format XML ou bien lorsqu'une évolution des logiciels ne permet plus de traiter l'ancien fichier. Mais cela pose peut-être des problèmes de sécurité et la section 6 appelle à la vigilance face au risque d'utiliser une version non-officielle.
Et, sinon, le RFC Editor » devient le « RFC Production Center » (mais je parie que l'ancien terme, chargé d'histoire, va rester encore longtemps).
On sait que le premier RFC publié sous le nouveau système (format de référence en XML) était le RFC 8651. Depuis, tous les autres RFC ont suivi ce système.
Date de publication du RFC : Février 2024
Auteur(s) du RFC : A. Backman (Amazon), J. Richer (Bespoke Engineering), M. Sporny (Digital Bazaar)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF httpbis
Première rédaction de cet article le 17 janvier 2025
Ce RFC spécifie comment on peut signer cryptographiquement et vérifier des messages HTTP, afin de s'assurer de leur authenticité. Des signatures HTTP conceptuellement proches, mais syntaxiquement différentes sont notamment utilisées par le fédivers.
Alors, attention, vous allez me dire « mais tout le monde utilise HTTPS, de toute façon » mais ce n'est pas tout à fait la même chose. Comme l'explique la section 1 de notre RFC, TLS protège une connexion mais ne fonctionne pas de bout en bout, s'il y a sur le trajet des relais qui terminent une session TLS et ouvrent une autre connexion (la section 7.1.2 détaille les limites de TLS pour les scénarios envisagés). Et TLS ne permet pas d'authentifier le client, sauf à utiliser des certificats client, que beaucoup trouvent peu pratique, et qui dépendent d'un système centralisé, les AC. En prime, dans un contexte d'utilisation serveur-serveur, comme dans le fédivers, on n'a pas envie de confier sa clé privée à son serveur. Donc, il y a un besoin pour une signature des messages (TLS n'est pas inutile pour autant, il fournit notamment la confidentialité, cf. section 8.2 de notre RFC). Voilà pourquoi Mastodon, par exemple, a commencé à utiliser des signatures HTTP pour la sécurité. Le format ActivityPub ne prévoyait en effet aucune sécurité, d'où la nécessité de développer des techniques ad hoc. Mais notez que la technique de Mastodon, non normalisée et même pas spécifiée quelque part, sauf dans le code source, n'est pas compatible avec celle du RFC. Un travail est en cours pour documenter cela.
Notons qu'il existe aussi des solutions pour signer le corps d'un message HTTP, comme JWS (RFC 7515) si le corps est en JSON (RFC 8259). Mais les signatures HTTP de notre RFC 9421 protègent non seulement le corps (quel que soit son format) mais aussi une partie des champs de l'en-tête. Il n'y a pas de solution générale de protection des contenus en HTTP, juste une protection du canal de communication, avec HTTPS.
Donc, le principe est simple : le signeur canonicalise certains champs de l'en-tête (et, indirectement, le corps, via la condensation du RFC 9530), les signe et met la signature dans l'en-tête. Par exemple, avec ce message HTTP (une simple demande de lecture, qui n'a donc probablement pas besoin d'être authentifiée mais c'est juste un exemple) :
GET /9421.html HTTP/1.1 Host: www.bortzmeyer.org Date: Fri, 17 Jan 2025 10:53:17 +0100 Content-Type: text/plain Content-Digest: sha-256=:591b6607e9e257e26808e2ccf3984c23a5742b78defad9ec7b2966ddcef29909=: Hello, HTTP
La signature ajoutera ces deux champs :
Signature-Input: sig=("date" "host";sf "content-type";sf "content-digest" "@method" "@target-uri" "@authority" "@scheme" "@request-target" "@path" "@query");alg="ecdsa-p256-sha256" Signature: sig=:0dnCVeCDOJ9fQiLqUXLE8hwBDNpAVlO3TJZgqm/FBJ1x2h5/g5qU20UM87BkJt0iK9vpRRgPF9fmWobf6Y5iYQ==:
(« sig » est un identificateur arbitraire, qui sert à faire la correspondance entre une signature et ses paramètres, dans le cas où il y a plusieurs signatures.) Le vérificateur devra récupérer la clé publique (notez que le RFC ne précise pas comment : chaque application utilisant les signatures HTTP devra décrire sa méthode de récupération des clés), canonicaliser et refaire les calculs cryptographiques, validant (ou non) la signature.
Voilà, vous connaissez l'essentiel du RFC, maintenant, place aux
détails. D'abord, un peu de terminologie : en dépit de leur nom, les
signatures HTTP peuvent être aussi bien de « vraies » signatures, faites avec de la
cryptographie asymétrique que des
MAC incluant une clé secrète (avec de la
cryptographie symétrique, donc). Ensuite,
relisez bien le RFC 9651 : les champs
structurés dans l'en-tête sont un cas particulier, en raison de la
canonicalisation qu'ils vont subir. (Vous
avez remarqué le sf
dans le champ
Signature-Input:
plus haut ? Il veut dire
Structured Field et indique un traitement
particulier.)
Ensuite, la question évidemment compliquée de la
canonicalisation. HTTP permet et même parfois impose des
transformations du message faites par des intermédiaires (la section
1.3 donne une liste partielle des transformations possibles). Il est
très difficile, voire impossible, de définir quels champs de
l'en-tête vont être respectés et lesquels vont être modifiés. Il n'y
a donc pas de liste officielle des champs à signer, chaque
application va indiquer les siens. Dans l'exemple ci-dessus, on
signe les quatre champs présents, et on l'indique dans le
Signature-Input:
. Si un intermédiaire ajoute un
champ quelconque (par exemple le Forwarded:
du
RFC 7239), la signature restera valide. Le
récepteur ne devra donc pas considérer ce champ comme
authentifié. Même chose pour le corps si on ne signe pas son
condensat (RFC 9530). La section 7.2.8 du RFC
rappelle l'importance de signer le corps, pour la plupart des
cas. Notez également que le Signature-Input:
plus haut incluait aussi des composants qui ne sont pas des champs
de l'en-tête mais qu'on veut signer, comme la méthode (GET
) ou
les composants de l'URL. Leur nom est précédé d'un arobase.
Autre problème du monde réel : les programmes n'ont pas un contrôle complet du message HTTP produit. Par exemple, le programme va utiliser une bibliothèque qui va formater les champs à sa manière, en ajouter, etc. C'est pour cela qu'il est important de laisser ouverte la question de la liste des champs à signer. Chaque application choisira.
Les signatures HTTP ne sont pas une solution complète prête à l'emploi : bien des points sont délibérément laissés vides dans le RFC. Une solution complète de sécurité doit donc spécifier :
Date:
soit présent et signé, pour détecter
les messages trop anciens que quelqu'un essaierait de rejouer,
cf. la section 7.2.2),Les noms des composants signés (champs de l'en-tête et autres)
sont décrits dans la section 2 de notre RFC. Pour un champ, c'est
simplement son nom en minuscules (comme "date"
dans le Signature-Input:
plus haut). Autrement,
les noms commencent par un arobase par exemple
@method
indique la méthode HTTP
utilisée. Les méthodes de canonicalisation (complexes, surtout pour
les champs structurés !) sont dans la même section.
Les différents paramètres de la signature, comme un
identificateur pour la clé utilisée, ou comme la date de signature,
peuvent également être inclus dans le
Signature-Input:
.
Tous ces paramètres forment ce qu'on appelle la base (section 2.5). Celle du message donné comme exemple plus haut est :
"date": Fri, 17 Jan 2025 10:53:17 +0100 "host";sf: www.bortzmeyer.org "content-type";sf: text/plain "content-digest": sha-256=:591b6607e9e257e26808e2ccf3984c23a5742b78defad9ec7b2966ddcef29909=: "@method": GET "@target-uri": https://www.bortzmeyer.org/9421.html "@authority": www.bortzmeyer.org "@scheme": https "@request-target": /9421.html "@path": /9421.html "@query": ? "@signature-params": ("date" "host";sf "content-type";sf "content-digest" "@method" "@target-uri" "@authority" "@scheme" "@request-target" "@path" "@query");alg="ecdsa-p256-sha256"
Ici, elle est relativement courte, la plupart des métadonnées n'étant pas mentionnée.
Une fois la signature générée, le signeur ajoute deux champs à l'en-tête (section 4 du RFC) :
Signature-Input:
qui indique les
paramètres de la signature (liste des champs signés, et
optionnellement métadonnées sur la signature),Signature:
, qui contient la
signature elle-même.
Les deux champs sont structurés selon la syntaxe du RFC 9651. (Notez que ces deux champs sont une des différences
avec l'ancienne version des signatures HTTP, utilisée dans le
fédivers. Cette ancienne version n'avait qu'un champ,
Signature:
. Un vérificateur qui veut gérer les
deux versions peut donc utiliser la présence du champ
Signature-Input:
comme indication que la
version utilisée est celle du RFC. L'annexe A expose cette
heuristique, qui figure également dans le
projet d'intégration avec ActivityPub.)
Voici un exemple de signature avec des métadonnées (date de signature et identifiant de la clé :
Signature-Input: reqres=("@status" "content-digest" "content-type" \ "@authority";req "@method";req "@path";req "content-digest";req)\ ;created=1618884479;keyid="test-key-ecc-p256" Signature: reqres=:dMT/A/76ehrdBTD/2Xx8QuKV6FoyzEP/I9hdzKN8LQJLNgzU\ 4W767HK05rx1i8meNQQgQPgQp8wq2ive3tV5Ag==:
Notez que notre RFC décrit aussi une méthode pour demander qu'un
correspondant signe ses messages : inclure un champ
Accept-Signature:
(section 5 du RFC).
Les signatures HTTP nécessitent la modification ou la création de plusieurs registres IANA :
Accept-Signature:
,
Signature:
et Signature-Input:
ont été ajoutés au registre des champs
d'en-tête HTTP.ecdsa-p256-sha256
, que j'ai
utilisé dans mon exemple (algorithme
ECDSA). On peut y ajouter des algorithmes
via la politique « Spécification nécessaire » du RFC 8126. created
(la date de signature) ou
keyid
(l'identificateur de la clé, selon un
schéma de nommage spécifique à l'application). On peut y ajouter des valeurs
via la politique « Examen par un expert » du RFC 8126.@method
.
On peut y ajouter des noms
via la politique « Examen par un expert » du RFC 8126.sf
, par exemple, qui
indique qu'un champ de l'en-tête est un champ structuré et doit
donc être traité de manière spéciale.
On peut y ajouter des noms
via la politique « Examen par un expert » du RFC 8126.Si vous voulez un article d'introduction :
Questions mises en œuvre, on dispose désormais de bibliothèques pour de nombreux langages de programmation (je ne les ai pas testées) :
https://github.com/superseriousbusiness/httpsig
,https://imrannazar.com/articles/http-signatures-in-php
,https://docs.rs/crate/http-signatures/latest
,https://pypi.org/project/http-message-signatures/
.
Une discussion est en
cours pour ajouter ces signatures à
curl.
Si vous programmez, pour tester votre code, je recommande fortement le service en ligne
.
Notez qu'il ne vérifie pas
le condensat du corps du message. Pour fabriquer les clés
pour ce service, si
vous voulez faire de l'ECDSA, vous pouvez
utiliser les commandes OpenSSL suivantes
(oui, il doit y avoir une version plus simple) :
https://httpsig.org/
openssl ecparam -out server.pem -name prime256v1 -genkey openssl req -new -key server.pem -nodes -days 1000 -out server.csr openssl x509 -in server.csr -out server.crt -req -signkey server.pem -days 2001
La clé privée sera dans server.pem
et la
publique dans server.crt
.
Concernant l'ancienne version des signatures HTTP, vous pouvez consulter :
https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/
et https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/
.Mobilizon.Federation.HTTPSignatures.Signature
et il vient à l'origine de Pleroma.Cette technique des signatures HTTP a eu une histoire longue et
compliquée. Née chez Amazon, elle avait d'abord été
décrite dans un Internet draft, draft-cavage-http-signatures
en 2013, et déployée, notamment dans le secteur financier. En 2017,
Mastodon avait utilisé la technique telle que décrite dans ce
document (forçant le reste du fédivers à s'aligner sur « ce que fait
Mastodon »). C'est après l'adoption par le groupe de travail
httpbis que le projet avait pris sa forme finale. (Regardez
les
supports de présentation à l'IETF en 2019 et la vidéo de la
réunion.) L'auteur du projet initial avait écrit un
bon résumé en 2020, décrivant de l'intérieur comment se passe
la normalisation dans l'Internet. Les différences principales avec ce que fait le fédivers :
Signature-Input:
et
Signature:
,Date de publication du RFC : Juillet 2022
Auteur(s) du RFC : D. Eastlake 3rd (Futurewei Technologies)
Chemin des normes
Première rédaction de cet article le 14 janvier 2025
Il existe tout un ensemble de normes pour assurer la sécurité de documents XML, par exemple les protéger contre la lecture non autorisée, ou bien permettre leur authentification. Ces normes dépendent d'algorithmes cryptographiques identifiés par un URI. Ce RFC met à jour la liste précédente de ces URI (qui était dans le RFC 6931) avec les nouveaux algorithmes et corrige quelques erreurs du précédent RFC.
Ces normes de sécurité de XML étaient à l'origine un travail conjoint de l'IETF et du W3C. C'était par exemple le cas des signatures XML du RFC 3275, du XML canonique des RFC 3076 ou RFC 3741. Elles sont désormais maintenues par le W3C qui a produit des versions plus récentes (par exemple pour les signatures XML, le XML canonique ou le chiffrement XML).
Dans un monde dynamique comme celui de la
cryptographie, où les progrès de la
cryptanalyse nécessitent des changements
d'algorithmes, les normes ne sont pas liées à un algorithme
particulier. Elles permettent l'agilité cryptographique (le
changement d'algorithme) et il faut donc pouvoir indiquer quel
algorithme est utilisé pour signer ou chiffrer un document
donné. Pour une norme W3C, on ne s'étonnera pas que l'indication
se fait par le biais d'un URI (RFC 3986). Les
nouveaux algorithmes commencent désormais par le préfixe
http://www.w3.org/2021/04/xmldsig-more#
(les
anciens algorithmes pouvant avoir d'autres préfixes). Ces nouveaux
algorithmes (avec 2021/04
dans leur
identificateur) sont relativement rares dans ce RFC : on n'invente
quand même pas un bon algorithme de cryptographie tous les jours et
la plupart des exemples dans cet article utilisent donc le vieux
préfixe. Un exemple récent ? EdDSA (RFC 8032) a l'URI
http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519
. Rappelez-vous
qu'il s'agit d'URI, pas forcément d'URL et que vous
n'obtiendrez donc pas forcément un résultat en pointant votre
navigateur Web vers
http://www.w3.org/2001/04/xmlenc#sha256
(cf. section 5.1).
Notons que notre RFC 9231 ne prend pas position sur la qualité cryptographique des algorithmes : il fournit un moyen de les désigner sans ambiguïté, c'est tout. Si on veut étudier cette qualité cryptographique, il faut lire d'autres documents (comme le RFC 6194 pour SHA-1).
Un exemple d'un ancien algorithme est
SHA-1 pour calculer les condensats
cryptographiques. Son URI est
http://www.w3.org/2000/09/xmldsig#sha1
. Sa
sécurité est aujourd'hui sérieusement battue en brèche (cf. RFC 6194). Autre exemple d'un algorithme qui était
déjà dans le RFC 6931, SHA-512,
identifié par http://www.w3.org/2001/04/xmlenc#sha512
.
Il existe aussi des identificateurs pour les MAC combinés
avec une condensation, par exemple
http://www.w3.org/2001/04/xmldsig-more#hmac-sha512
(RFC 6234).
Et pour les signatures avec un système à clé publique ?
L'identificateur indique l'algorithme de cryptographie asymétrique
et celui de condensation, par exemple
http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
(voir aussi le RFC 3447). Si on trouve RSA ennuyeux, il existe
aussi des identificateurs pour un algorithme à courbes
elliptiques (RFC 6090 mais notez
ses
errata), ECDSA, par exemple
http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512
.
Enfin, il y a les algorithmes de chiffrement symétrique. Par exemple,
Camellia (RFC 3713) sera identifié par
http://www.w3.org/2001/04/xmldsig-more#camellia256-cbc
. Le
plus récent SEED (RFC 4269) sera
http://www.w3.org/2007/05/xmldsig-more#seed128-cbc
.
Un exemple d'utilisation donné par notre RFC, pour de la cryptographie symétrique :
<EncryptionMethod Algorithm="http://www.w3.org/2021/04/xmldsig-more#chacha20"> <Nonce>0123456789abcdef01234567</Nonce> <Counter>fedcba09</Counter> </EncryptionMethod>
Voici pour la cryptographie. Mais les normes de sécurité XML
prévoient aussi une étape de canonicalisation avant chiffrement ou
signature, et là aussi, il y a plusieurs algorithmes, identifiés par
des URI comme
http://www.w3.org/2000/09/xmldsig#minimal
ou
http://www.w3.org/2006/12/xmlc14n11#WithComments
.
Quelle est la politique d'allocation dans le registre ? La
section 5 décrit celle du W3C (le préfixe
http://www.w3.org/2007/05/xmldsig-more#
est
figé, a priori, on n'y mettra pas de nouveaux algorithmes) et celle
de l'IETF : comme il est facile d'obtenir un URI (n'importe qui peut
en créer un), la seule question est celle de leur enregistrement. Il
se fera après un examen par un expert (voir le RFC 8126 pour les politiques d'allocation IETF) après
publication d'un texte décrivant le nouvel algorithme.
Quels changements depuis la version précédente de ce RFC, le RFC 6931 ? L'annexe A les liste. Les principaux, à mon avis, sont :
First publication of this article on 11 January 2025
If you use the fediverse, you know that
the main bot-hosting instance,
botsin.space
, closed recently. I document here
one or two things about the new hosting of two bots I maintain, one
answering BGP
requests and one for DNS information.
These two bots are documented in the
articles "A Fediverse/Mastodon bot for
DNS" and "A
Fediverse/Mastodon bot for BGP queries". They were hosted on
a dedicated-for-bots instance,
botsin.space
. This one is now
closed so I had to move elsewhere.
This proved to be surprisingly difficult. Many instances no longer accept new inscriptions, or are subject to a (sometimes long) process of registration. Some have policies against bots (or mention they are just "tolerated", something I did not want) or against the use of some specific vocabulary (and I did not want the DNS bot to filter words used in domain names).
But there were also technical issues. Some instances never hosted
a bot (more specifically a read-write bot, which will need the
ability to read notifications; many bots are write-only) and
therefore have surprising issues (one accepted the connections but
never sent the heartbeats that the Mastodon API uses to
check liveness, another replied with 404 to all requests of the
streaming API). And I had no experience with debugging
these issues (but now I do). In the end, while I would have
prefer to try another instance, I used the instance where my main
acount is hosted, mastodon.gougere.fr
.
As usual on the fediverse, no instance is perfect
(botsin.space
was blocking a big instance,
mamot.fr
, for instance) but at least this time
it works. You can now resume sending DNS and BGP queries.
Thanks to the people who maintain instances (it is often an unrewarding task) and let's toot.
Auteur(s) du livre : Rémi Boulle
Éditeur : Dunod
978-2-10-087133-9
Publié en 2024
Première rédaction de cet article le 26 décembre 2024
Vous le savez tous et toutes, la cryptographie est une composante essentielle de la sécurité de l'Internet. Si tout le monde ne va pas devenir expert·e en cryptographie, en revanche, il est utile de connaitre les principes de base. Ce livre, destiné à des étudiant·es plutôt qu'au grand public, est une approche très concrète de la cryptographie, avec des exemples pratiques. J'ai beaucoup apprécié cette approche terre-à-terre.
Le livre commence par rappeler l'enjeu de la cryptographie, indispensable pour protéger l'utilisateurice de l'Internet des nombreuses activités de surveillance qui s'exercent contre lui ou elle. Les révélations d'Edward Snowden, par exemple, ont montré que la surveillance massive par les États est une réalité. La cryptographie soulève de nombreuses questions politiques, ce livre les mentionne mais parle surtout de technique.
Vous aurez en effet ensuite une explication des principes de la cryptographie, puis des différents algorithmes. Il faudra accepter un peu de mathématique, mais c'est nécessaire dans ce domaine.
Pour les exemples de code, le livre utilise Python, et commence par une
introduction (ou un rappel) de ce langage, si vous ne le connaissez
pas bien. Il dépend ensuite de plusieurs bibliothèques qu'il
présente, dont cryptography
et,
comme le titre l'indique, OpenSSL. La
cryptographie nécessite des opérations de bas niveau, comme des
décalages de bits mais ne vous inquiétez pas, tout cela est
rappelé.
On commence par un exemple trivial et d'intérêt purement historique, l'algorithme de César :
import sys KEY=3 def chiffre_Cesar_texte(texte_clair, k): texte_chiffre = "" for lettre in texte_clair: code_lettre = ord(lettre)-65 chiffre = (code_lettre + k) % 26 lettre_chiffre = chr(chiffre + 65) texte_chiffre = texte_chiffre + lettre_chiffre return texte_chiffre for texte in sys.argv[1:]: print(chiffre_Cesar_texte(texte, KEY))
Mais vous aurez d'innombrables exemples de codes plus sérieux, utilisant des services réels, par exemple récupérer des données sur la chaine de blocs Bitcoin, l'analyser, la vérifier et même faire du minage de bitcoins. Même un·e connaisseur·se en cryptographie y découvrira certainement quelque chose, par exemple qu'il existe une courbe elliptique souveraine en France.
Conçu comme livre de classe, il contient de nombreux exercices. Si vous voulez récupérer l'intégralité des exemples et des solutions, allez sur le site officiel (on vous demande votre adresse de courrier mais mettez n'importe quoi, ça marche).
Le livre ne se contente pas de généralités sur la cryptographie mais explique aussi les détails de certains protocoles de communication sécurisés, très utilisés sur l'Internet, comme HTTPS et SSH, ou bien dans le contexte de l'Internet des objets, comme LoRaWAN, avec décorticage de paquets. Bref, si vous êtes prêt à vous plonger dans la cryptographie, voici un excellent guide.
La photo du livre, ci-dessous, contient une autre image,
cachée. Lisez le chapitre sur la
stéganographie et vous pourrez récupérer
cette image cachée (les quatre bits de poids faible contiennent les
bits de poids fort de l'image cachée, cf. section 4.5.2, p. 43 et
44).
Première rédaction de cet article le 22 décembre 2024
Si vous êtes en vacances dans les prochains jours, cela peut être l'occasion de lire des articles scientifiques riches. Par exemple, si vous voulez en apprendre davantage sur la robustesse des connexions Internet face aux coupures de câbles, regardez le cas du Pakistan dans cet article (en anglais).
Régulièrement, la question de la vulnérabilité des câbles qui forment l'infrastructure physique de l'Internet est posée. Souvent, elle est traitée de manière sensationnaliste (« les russechinoicoréeniraniens vont couper notre Internet, on ne pourra plus voir Netflix »), par exemple par des politiciens qui veulent jouer au chef de temps de guerre. Si on veut traiter le sujet plus sérieusement, il faut analyser en détail, et ça prend davantage de temps que de faire un titre putaclic. C'est ce que font Nowmay Opalinski, Zartash Uzmi et Frédérick Douzet pour le cas du Pakistan. Leur article « The Quest for a Resilient Internet Access in a Constrained Geopolitical Environment » étudie en détail la connectivité d'un pays. Combien de câbles vers l'extérieur ? Par où passent-ils ? (Je vous laisse lire l'article pour voir leur méthodologie, mais notez qu'il ne suffit pas d'étudier l'infrastructure physique, leur article décortique aussi l'infrastructure logicielle.) Cela donne une bonne idée de la robustesse de la connectivité d'un pays, de ses chances de résister à des coupures de câble, qu'elles soient volontaires ou accidentelles (et je rappelle qu'il y a davantage de maladroits que de malveillants).
Si vous regardez la carte, vous pouvez vous dire que le Pakistan n'a pas trop besoin de câbles sous-marins, il peut passer par des connexions terrestres avec ses voisins. Mais la question n'est évidemment pas purement technique, il faut prendre en question la géopolitique. Pas question de passer par l'Inde, par exemple. Et, avec l'Iran, ce n'est pas beaucoup mieux. Il reste l'Afghanistan… Et il y a même un lien avec la Chine, avec qui les relations sont bien plus cordiales, mais, ici, c'est la géographie qui n'est pas d'accord (le câble, dont l'utilisation n'est pas claire, passe par un col difficile).
Bref, les connexions internationales du Pakistan passent pour l'essentiel par des liaisons sous-marines depuis Karachi, vers des pays plus lointains. Une panne dans cette région met donc en péril toute la connectivité extérieure du pays.
Ce ne serait pas trop grave si les Pakistanais·es pouvaient encore dialoguer entre ielles. Mais, comme dans beaucoup de pays, les communications, même locales, sont souvent médiées par les GAFA. Et ceux-ci n'ont souvent pas d'infrastructure dans le pays, suggérant parfois de passer par l'Inde, ce qui est évidemment irréaliste vu les relations entre les deux pays. Une coupure des liens avec l'extérieur pourrait donc avoir de sérieuses conséquences. Si on utilisait davantage les liaisons pair-à-pair et l'auto-hébergement, il y aurait davantage de robustesse.
Un exemple (j'ai pris le DNS parce que c'est ce que je connais mais lisez l'article, il y aura d'autres exemples), l'instance de Google Public DNS qu'on peut joindre depuis le Pakistan, vue par les sondes RIPE Atlas, est aux Émirats, de l'autre côté du golfe :
% blaeu-resolve --requested 100 --country PK --nameserver 8.8.8.8 \ --nsid --type A lums.edu.pk Nameserver 8.8.8.8 [110.93.234.24 111.68.103.174 203.135.62.24 NSID: gpdns-fjr;] : 3 occurrences Test #85285321 done at 2024-12-22T13:48:31Z
(Voir mon autre article sur l'utilisation des sondes Atlas. Regardez le NSID - RFC 5001 de l'instance, qui pointe vers les EAU.)
En parlant d'histoire-géographie, notez aussi que l'article met en évidence que les liaisons intérieures du pays sont très concentrées dans la vallée de l'Indus. La technologie moderne utilise la même voie de communication qu'il y a cinq mille ans.
Quelques autres références :
Date de publication du RFC : Décembre 2024
Auteur(s) du RFC : M.Q.C. van
Beurden, A. Weaver
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF cellar
Première rédaction de cet article le 19 décembre 2024
Le format FLAC, normalisé dans ce RFC, permet de stocker et de transmettre du son sans perte (contrairement à des mécanismes de compression comme MP3). Il est donc utile, par exemple pour l'archivage à long terme (mais aussi pour la haute fidélité).
Le multimédia, c'est compliqué. Le RFC fait près de 100 pages, pour un format audio qui se veut pourtant simple. FLAC fait de la compression pour limiter l'espace de stockage nécessaire mais en prenant soin de permettre une décompression qui redonne exactement le fichier originel (d'où le « sans perte » dans son nom, qu'il partage avec d'autres formats, comme le FFV1 du RFC 9043). Je ne connais pas assez le domaine de l'audio pour faire un résumé intelligent du RFC donc je vous invite à le lire si vous voulez comprendre comment FLAC fonctionne (les sections 4 à 6 vous font une description de haut niveau).
Si on prend un fichier FLAC, un programme comme file peut le comprendre :
% file Thélème.flac Thélème.flac: FLAC audio bitstream data, 24 bit, stereo, 44.1 kHz, length unknown
Le fait que l'échantillonage soit à 44,1 kHz est encodé dans les métadonnées (cf. section 9.1.2 du RFC), que file a pu lire (section 9.1.3 pour le fait que le fichier soit en stéréo).
Il y a quelques fichiers FLAC sur Wikimedia Commons. Mais un bon exemple de l'utilisation de FLAC est donné par l'enregistrement des Variations Goldberg par Kimiko Ishizaka, que vous pouvez télécharger en FLAC et sous une licence libre (CC0).
La mise en œuvre de référence de FLAC est en logiciel libre et se nomme libFLAC. Mais il existe beaucoup d'autres programmes qui savent gérer FLAC (j'ai écouté plusieurs fichiers FLAC avec vlc pour cet article), le lire, l'écrire, l'analyser, etc. Une liste est disponible sur le site du groupe de travail IETF. Il faut dire que FLAC, bien qu'il vienne seulement d'être normalisé, est un format ancien, dont le développement a commencé en 2000, et il n'est donc pas étonnant que les programmeur·ses aient eu le temps de travailler.
Si vous voulez ajouter du code à cette liste, lisez bien la section 11 du RFC, sur la sécurité. Un programme qui lit du FLAC doit être paranoïaque (comme avec n'importe quel autre format, bien sûr) et se méfier des cas pathologiques. Ainsi, le RFC note qu'on peut facilement créer un fichier FLAC de 49 octets qui, décomprimé, ferait 2 mégaoctets, ce qui pourrait dépasser la mémoire qui avait été réservée. Ce genre de surprises peut arriver à plusieurs endroits. L'annexe D du RFC contient plusieurs fichiers FLAC intéressants (et vous pouvez les retrouver en ligne) et il existe également une collection de fichiers FLAC, dont certains sont délibérément anormaux, pour que vous puissiez tester la robustesse de votre programme. Autre piège (mais lisez toute la section 11, il y en a beaucoup), FLAC permet de mettre des URL dans les fichiers, URL qu'il ne faut évidemment pas déréférencer bêtement.
Ce RFC est également la documentation pour l'enregistrement
du type MIME audio/flac
(section 12.1).
Pour une analyse technique de la prétention « sans perte » de FLAC, voir cet article de Guillaume Seznec.
Articles des différentes années : 2025 2024 2023 2022 2021 2020 2019 Précédentes années
Syndication : Flux Atom avec seulement les résumés et Flux Atom avec tout le contenu.