Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

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

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

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

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


RFC 9926: Prefix Registration for IPv6 Neighbor Discovery

Date de publication du RFC : Février 2026
Auteur(s) du RFC : P. Thubert
Chemin des normes
Première rédaction de cet article le 14 février 2026


Une addition sympa au mécanisme de découverte des voisins d'IPv6 (RFC 4861), utile pour les réseaux d'objets contraints, genre Internet des Objets mais aussi les réseaux à connectivité imparfaite, par exemple avec des hauts et des bas : la possibilité pour une machine qui est connectée à un réseau d'un préfixe donné d'enregistrer ce préfixe auprès des routeurs voisins. Ceux-ci sauront alors où envoyer les paquets pour ce préfixe. Cela ne remplace pas les protocoles de routage traditionnels, c'est plutôt une addition pour optimiser les protocoles spécialisés dans les réseaux contraints.

Le cœur de cible de ce RFC, ce sont les LLN (Low power and Lossy Networks, les réseaux « pauvres », avec pas beaucoup d'énergie et des liaisons pourries, cf. RFC 7102 et RFC 7228). La préoccupation principale est d'économiser l'énergie ; éviter de transmettre (la radio coûte cher) et s'endormir le plus souvent possible. Ces LLN utilisent des technologies comme 6LoWPAN (RFC 4919) et le protocole de routage RPL du RFC 6550. Les protocoles conçus pour les LLN n'utilisent donc pas d'émissions périodiques (comme le fait OSPF), qui consomment de l'énergie, et obligent tout le monde à écouter tout le temps, donc à ne pas dormir. L'idée de ce RFC est de compter sur quelques routeurs qui sont moins contraints (par exemple parce qu'ils sont connectés à une prise de courant) et que les autres signalent aux routeurs les préfixes connus, lorsqu'ils sont réveillés.

Autre exemple, les mécanismes IPv6 de découverte du voisin (RFC 4861 et RFC 4862) ont été conçus en pensant à des machines alimentées électriquement en permanence, sur des réseaux comme Ethernet, où diffuser à tout le monde est peu coûteux. Mais ils ne fonctionnent plus si, par exemple, certaines machines sont endormies, et ne répondent donc pas aux sollicitations. D'où des idées comme le RFC 6775, où une machine n'attend pas les sollicitations, elle profite de ses périodes d'éveil pour enregistrer son adresse auprès du routeur. Idem avec le projet draft-ietf-6man-ipv6-over-wireless. L'idée a ensuite été généralisée par le RFC 8505, sur lequel s'appuie notre nouveau RFC, qui permet d'enregistrer un préfixe IP entier. Notez bien que cette technique est indépendante de la manière dont la machine a reçu ce préfixe en allocation, et de la manière dont le routeur auprès duquel on s'enregistre va ensuite diffuser son préfixe dans son domaine de routage.

La section 3 du RFC donne une vision générale du nouveau mécanisme, je vous laisse la lire 😃.

Notez (section 11) que la machine qui enregistre un préfixe peut mentir et que cette technique doit donc être déployée en comprenant les caractéristiques spécifiques du réseau (par exemple, fermé ou au contraire ouvert sur l'Internet). Le RFC 8928 est ici une bonne lecture, ainsi que la section 9 de notre RFC.

Et merci à Pascal Thubert pour sa relecture. (Naturellement, je reste responsable des erreurs et approximations.)


Téléchargez le RFC 9926


L'article seul

RFC 9920: RFC Editor Model (Version 3)

Date de publication du RFC : Février 2026
Auteur(s) du RFC : P. Hoffman (ICANN), A. Rossi (RFC Series Consulting Editor)
Pour information
Réalisé dans le cadre de l'activité d'édition des RFC rswg
Première rédaction de cet article le 12 février 2026


Vous avez toujours voulu savoir qui s'occupait de publier les RFC et qu'est-ce que ce mystérieux « RFC Editor » ? Ce nouveau RFC décrit ce rôle et la façon dont il doit accomplir sa tâche. Il s'agit d'une légère mise à jour du RFC 9280, sans changement de version. (Parmi les nouveautés, la définition de la notion d'utilisateurice des RFC, avant, on ne parlait que des auteurices.)

Les RFC sont un ensemble de documents techniques au sujet de l'Internet, qui comprend notamment, mais pas uniquement, les normes TCP/IP. Les RFC sont librement accessibles en ligne et sont publiés depuis 1969 (cf. RFC 8700).

Il y a très longtemps, quand les dinosaures étaient petits, le rôle de RFC Editor s'incarnait bien dans une personne unique, Jon Postel. Aujourd'hui, c'est plus complexe et il n'y a plus, depuis la version 2 du modèle (qui était dans le RFC 8728), de RFC Editor unique. Ce rôle est désormais réparti en deux tâches principales, définir la politique, et la mettre en œuvre. La première tâche est du ressort du RSWG (RFC Series Working Group), pour discuter et proposer (tout le monde, et son chat, peut y participer), puis du RSAB (RFC Series Approval Board), pour décider (ce comité est plus fermé). La deuxième tâche, la mise en œuvre de la politique, est du ressort du RFC Production Center, typiquement une organisation privée sous contrat avec l'IETF LLC, l'organisation administrative derrière l'IETF (RFC 8711). Ce sont donc tous ces groupes ensemble qui composent le « RFC Editor ». Tout ceci, et quelques autres points, étaient déjà dans le RFC 9280, notre nouveau RFC 9920 n'apporte que des changements de détail.

Les RFC sont publiés par cinq voies (streams) différentes, dont une, la voie IETF, sert pour les normes (mais tous les RFC ne sont pas des normes). Chaque voie a une organisation ou une personne responsable du contenu des RFC (pour la voie IETF, le responsable est… l'IETF), la fonction RFC Editor ne gère pas le contenu (ou seulement la forme, mais pas le fond des documents) mais la publication. Le RFC 8729, dans sa section 5.1, décrit les quatre voies classiques (IETF, IRTF, IAB et indépendante). En plus, le RFC 9280 avait introduit la voie éditoriale, dédiée aux évolutions des RFC (les RFC parlant des RFC…). C'est via cette voie que seront publiés les propositions issues du RSWG et approuvées par le RSAB. Un exemple est le récent RFC 9896, dont vous pouvez suivre l'historique.

Dans les deux tâches décrites plus haut (la définition de la politique, et sa mise en œuvre), je n'ai pas mentionné un acteur supplémentaire (comme s'il n'y en avait pas déjà assez !), le RFC Series Consulting Editor, qui est un·e expert·e en édition, membre du RSAB.

Et donc, si vous avez des idées géniales pour améliorer les RFC, il faut faire comment pour qu'elles triomphent ? Lisez la section 3 et notamment la 3.2.2 :

  • Les propositions sont écrites (un Internet draft) et diffusées au RSWG (rappelez-vous : il est ouvert, tout le monde peut y participer),
  • Après un dernier appel dans le RSWG, puis plus large, s'il y a un consensus approximatif (RFC 2418),
  • Les propositions atterrissent au RSAB, qui décidera (avec des votes YES ou CONCERN, le second n'étant pas un NO mais une demande de discussion).

Chaque acteur est décrit ensuite plus en détail. Le RSWG est le groupe le plus ouvert du lot, vous vous abonnez à sa liste de diffusion et c'est parti, vous êtes membre. Et ceci que vous soyez déjà participant à l'IETF ou pas. Les développeur·ses qui mettent en œuvre les RFC, les auteurs de RFC, les auteurs de logiciels qui traitent les RFC, les gens qui citent les RFC dans leurs appels d'offres, tous ceux et toutes celles là sont les bienvenu·es. Les discussions sont publiques. Le RSWG peut aussi utiliser des outils en ligne comme MicrosoftHub (RFC 8874).

Le RSAB, lui, est relativement fermé, aussi bien dans sa composition (les membres avec droit de vote sont un représentant de chaque voie plus le RFC Series Consulting Editor, cf. section 5) que dans son travail (mais les comptes-rendus des réunions sont publics). Par contre, il n'est pas censé court-circuiter le RSWG : toutes les propositions doivent d'abord être discutées au RSWG.

Les boilerplates, ces textes rigides présents au début de chaque RFC et expliquant le statut de celui-ci, décrits dans le RFC 7841, sont décidés par chaque voie puis approuvés par le RSAB, le RFC Production Center et l'IETF Trust.

Le RPC (RFC Production Center) est décrit en section 4. C'est actuellement AMS. C'est ce RPC qui va écrire et maintenir le guide stylistique à respecter (RFC 7322 et documents en ligne), décider des formats acceptés (par exemple du profil restreint de SVG, cf. RFC 9896), et préciser les points que le RFC 7991 laissait libres. C'est aussi le RPC qui doit faire le travail de publication effectif :

  • Attribuer les numéros des RFC (qui sera le numéro 10 000 ?),
  • Relire et corriger les textes soumis, en respectant le sens technique,
  • Garder trace de toutes les modifications faites (des « corrections » peuvent accidentellement changer le fond du texte),
  • Assurer la communication avec les auteurs et avec des organisations comme l'IANA, quand le futur RFC leur donne un rôle, par exemple de créer un nouveau registre de paramètres, et archiver tous ces dialogues,
  • Demander le cas échéant au RSCE et/ou au RSAB, et leur faire des suggestions, fondées sur son expérience de publication des RFC,
  • Participer au RSWG,
  • Rendre compte à la communauté des auteurs et lecteurs de RFC, d'une part, et à l'IETF LLC d'autre part,
  • Mettre les RFC en ligne, veiller au serveur www.rfc-editor.org qui les distribue, archiver les RFC (RFC 8153), annoncer les publications (le RPC est sur le fédivers, voyez par exemple cette annonce, et il y a bien sûr un flux de syndication sur le site Web),
  • Maintenir le système d'errata (« Submit an issue »),
  • Et répondre aux demandes judiciaires car il y a parfois des procès impliquant un RFC.

Le RPC est choisi suite à un appel d'offres de l'IETF LLC, qui est chargée d'écrire le cahier des charges détaillé et de sélectionner le vainqueur. L'argent vient du budget de l'IETF LLC, qui paie le RPC (AMS, actuellement, comme indiqué plus haut).

Et le RSCE (RFC Series Consulting Editor) ? La section 5 le décrit plus en détail. C'est une personne expérimentée dans les questions d'édition. Il ou elle doit guider le RPC sur les questions techniques liées à la publication (la section 4 du RFC 8729 donne une liste complète de ces questions). La RSCE actuelle, depuis 2022, est Alexis Rossi, une des auteures de ce RFC.

Une des nouveautés du RFC 9280 était la voie éditoriale (Editorial Stream), la cinquième voie de création de RFC, consacrée aux RFC qui parlent des RFC. La section 6 de notre RFC la détaille. Cette voie est empruntée par les RFC discutés par le RSWG puis approuvés par le RSAB, comme ce RFC 9920 dont vous êtes en train de lire le résumé. Le statut de ces RFC est forcément « Pour information » (informational, cf. RFC 8729), mais ce sont bien des règles impératives pour les RFC qu'ils spécifient.

Et, pour finir, la section 7 de notre RFC liste les propriétés « historiques » des RFC qui, si elles n'ont pas forcément été mises par écrit, surtout au début, ont toujours été respectées et ne doivent pas être prises à la légère lors des propositions d'évolution :

  • Libre disponibilité des documents, que tout le monde peut télécharger, lire, redistribuer. (Ce n'est pas évident, puisque des organisations fermées comme l'AFNOR ou l'ISO ne fournissent toujours pas d'accès libre à leurs documents et, même si vous avez payé pour en avoir un, vous ne pouvez pas le redistribuer.)
  • Accessibilité (format texte d'abord, puis XML avec plusieurs formats de sortie), sans dépendance vis-à-vis de logiciels privateurs comme le font les organisations fermées.
  • En anglais (notez que la licence permet de faire une traduction sans demander d'autorisation). Opinion personnelle : ce n'est évidemment pas génial mais il n'y pas d'alternative réaliste : traduire des documents normatifs en N autres langues est très coûteux (chaque virgule compte et, par exemple, un texte en français tend facilement à être plus directif que le texte en anglais).
  • Diversité : tous les RFC ne sont pas des normes, il y a des informations, des discussions, de l'humour
  • Qualité des documents.
  • Stabilité et longévité : le contenu sémantique des RFC n'est jamais modifié, et les formats sont choisis pour garantir qu'ils seront toujours lisibles dans des dizaines d'années (formats standards, acceptés par de nombreux logiciels). À part le cas particulier du RFC 20, le RFC le plus ancien et qui est toujours applicable est le RFC 768, qui a presque un demi-siècle. L'archivage à long terme est un point crucial des RFC, à la fois pour les RFC anciens mais toujours d'actualité, et aussi pour les historien·nes de l'informatique.

La section 1.1 de notre RFC résume les changements depuis le RFC 9280, qui avait spécifié la version 3 du modèle « RFC Editor ». On reste en version 3 et les changements sont peu importants :

  • Précisions des responsabilités de développement des outils informatiques nécessaires. C'est au RFC Production Center de s'en occuper. Cela implique des choses comme les choix de formats ou bien les grammaires XML.
  • Définition de la notion d'utilisateur des RFC (consumer of RFCs, section 3.3), en se référant au RFC 3935, qui décrit la mission de l'IETF mais qui n'expliquait pas clairement cette notion. Les utilisateurs des RFC sont un ensemble plus large que celui des participants à l'IETF, et un RFC doit être utilisable par des gens qui ne connaissent rien à l'IETF.
  • En cohérence avec le RFC 9720, on précise désormais qu'un RFC, une fois publié, peut être modifié (sa forme, mais pas son fond).

La section 9, quant à elle, raconte les changements qu'il y avait eu depuis la version 2 du modèle (la version 1 du modèle était dans le RFC 5620 en 2009 et la version 2 dans le RFC 6635 en 2012) :

  • Éclatement de la fonction de RFC Editor en plusieurs acteurs (RSWG, RSAB, etc).
  • Fusion des fonctions RFC Production Center et RFC Publisher.
  • Suppression du RSOC (RFC Series Oversight Commitee).
  • Création de la voie éditoriale pour les RFC parlant des RFC.

Téléchargez le RFC 9920


L'article seul

RFC 9915: Dynamic Host Configuration Protocol for IPv6 (DHCPv6)

Date de publication du RFC : Janvier 2026
Auteur(s) du RFC : T. Mrugalski (ISC), B. Volz (Individual Contributor), M. Richardson (SSW), S. Jiang (BUPT), T. Winters (QA Cafe)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dhc
Première rédaction de cet article le 11 février 2026


IPv6 dispose de trois mécanismes principaux pour l'allocation d'une adresse IP à une machine. L'allocation statique, « à la main », le système d'« autoconfiguration » SLAAC du RFC 4862 et DHCP. DHCP pour IPv6 était normalisé dans le RFC 8415, que notre RFC met à jour. Le protocole n'a guère changé, le principal changement est la suppression de certaines fonctions peu utilisées.

DHCP permet à une machine (qui n'est pas forcément un ordinateur, ou plus exactement qui n'est pas perçue comme telle) d'obtenir une adresse IP (ainsi que plusieurs autres informations de configuration) à partir d'un serveur DHCP du réseau local. C'est donc une configuration « avec état », du moins dans son mode d'utilisation le plus connu. (Notre RFC documente également un mode sans état.) DHCP nécessite un serveur, par opposition à l'autoconfiguration du RFC 4862 qui ne dépend pas d'un serveur (cette autoconfiguration sans état peut être utilisée à la place de ou bien en plus de DHCP). Deux utilisations typiques de DHCP sont le SoHo où le routeur est également serveur DHCP pour les trois PC connectés et le réseau local d'entreprise où deux ou trois machines Unix distribuent adresses IP et informations de configuration à des centaines de machines.

Le principe de base de DHCP (IPv4 ou IPv6) est simple : la nouvelle machine annonce à la cantonade qu'elle cherche une adresse IP, le serveur lui répond, l'adresse est allouée pour une certaine durée, le bail, la machine cliente devra renouveler le bail de temps en temps.

L'administrateur d'un réseau IPv6 se pose souvent la question « DHCP ou SLAAC » ? Notez que les deux peuvent coexister, ne serait-ce que parce que certaines possibilités n'existent que pour un seul des deux protocoles. Ainsi, DHCP seul ne peut indiquer l'adresse du routeur par défaut. Pour le reste, c'est une question de goût.

Le DHCP spécifié par notre RFC ne fonctionne que pour IPv6, les RFC 2131 et RFC 2132 traitant d'IPv4. Les deux protocoles restent donc complètement séparés, le RFC 4477 donnant quelques idées sur leur coexistence. Il a parfois été question de produire une description unique de DHCPv4 et DHCPv6, ajoutant ensuite les spécificités de chacun, mais le projet n'a pas eu de suite (section 1.2 de ce RFC), les deux protocoles étant trop différents.

DHCP fonctionne par diffusion restreinte. Un client DHCP, c'est-à-dire une machine qui veut obtenir une adresse, diffuse (DHCP fonctionne au-dessus d'UDP, RFC 768, le port source est 546, le port de destination, où le serveur écoute, est 547) sa demande à l'adresse multicast locale au lien ff02::1:2. Le serveur se reconnait et lui répond. S'il n'y a pas de réponse, c'est, comme dans le DNS, c'est au client de réémettre (section 15). L'adresse IP source du client est également une adresse locale au lien.

(Notez qu'une autre adresse de diffusion restreinte est réservée, ff05::1:3 ; elle inclut également tous les serveurs DHCP mais, contrairement à la précédente, elle exclut les relais, qui transmettent les requêtes DHCP d'un réseau local à un autre.)

Le serveur choisit sur quels critères il alloue les adresses IP. Il peut les distribuer de manière statique (une même machine a toujours la même adresse IP) ou bien les prendre dans un pool d'adresses et chaque client aura donc une adresse « dynamique ». Le fichier de configuration du serveur DHCP Kea ci-dessous montre un mélange des deux approches.

Il faut bien noter (et notre RFC le fait dans sa section 22) que DHCP n'offre aucune sécurité. Comme il est conçu pour servir des machines non configurées, sur lesquelles on ne souhaite pas intervenir, authentifier la communication est difficile. Un serveur DHCP pirate, ou, tout simplement, un serveur DHCP accidentellement activé, peuvent donc être très gênants.

Outre l'adresse IP, DHCP peut indiquer des options comme les adresses des serveurs DNS à utiliser (RFC 3646).

Notre version IPv6 de DHCP est assez différente de la version IPv4 (et le RFC est plus de trois fois plus long). Par exemple, l'échange « normal » entre client et serveur prend quatre paquets IP (section 5) et non pas deux. (Mais il y a aussi un échange simplifié à deux paquets, cf. section 5.1.) L'encodage des messages est très différent, et il y a des différences internes comme l'IA (Identity Association) de la section 12. Il y a aussi des différences visibles à l'utilisateur comme le concept de DUID (DHCP Unique IDentifier), section 11, qui remplace les anciens client identifier et server identifier de DHCP v4. Les différences sont telles que le RFC précise que leur intégration avec DHCP pour IPv4 n'est pas envisagée.

À l'heure actuelle, il existe plusieurs mises en œuvre de DHCPv6, comme Kea (serveur seulement) et dhcpcd (client seulement). (Notez qu'une liste complète figurait dans le brouillon du RFC.) Pour celles et ceux qui utilisent une Freebox comme serveur DHCP, il semble qu'elle ait DHCPv6 depuis 2018 (je n'ai pas testé). Il parait que la Livebox le fait également. Je n'ai pas non plus essayé pour la Turris Omnia mais cela devrait marcher puisqu'elle utilise le serveur odhcpd, qui sait faire du DHCPv6 (ceci dit, je ne vois pas comment l'activer depuis les menus de Luci). Et il y a bien sûr des implémentations non-libres dans des équipements comme les Cisco. Notez que ces mises en œuvre de DHCPv6 n'ont pas forcément déjà intégré les modifications de notre RFC 9915.

Il existe aussi des programmes qui ne sont plus maintenus comme Dibbler (client et serveur), l'ancien programme de l'ISC (le nouveau est Kea), etc.

Voici un exemple d'utilisation de Dibbler, face à Kea, qui nous affiche les quatre messages (Solicit - Advertise - Request - Reply) :


% sudo dibbler-client run 
...
2026.02.11 08:28:04 Client Notice    DUID creation: Generating 14-bytes long link-local+time (duid-llt) DUID.
2026.02.11 08:28:04 Client Notice    DUID creation: generated using wlan0/4 interface.
2026.02.11 08:28:04 Client Info      My DUID is 00:01:00:01:31:1e:fa:14:f6:fc:69:10:65:09.
...
2026.02.11 08:28:04 Client Info      Creating SOLICIT message with 1 IA(s), no TA and 0 PD(s) on eth1/3 interface.
2026.02.11 08:28:04 Client Debug     Sending SOLICIT(opts:1 3 39 8 6 ) on eth1/3 to multicast.
2026.02.11 08:28:04 Client Info      Received ADVERTISE on eth1/3,trans-id=0x5ded1b, 5 opts: 1 2 3 23 39
2026.02.11 08:28:05 Client Info      Processing msg (SOLICIT,transID=0x5ded1b,opts: 1 3 39 8 6)
2026.02.11 08:28:05 Client Info      Creating REQUEST. Backup server list contains 1 server(s).
2026.02.11 08:28:05 Client Debug     Advertise from Server ID=00:01:00:01:31:19:db:68:38:f7:cd:ce:22:c6, preference=0.[using this]
2026.02.11 08:28:05 Client Debug     Sending REQUEST(opts:1 3 39 6 2 8 ) on eth1/3 to multicast.
2026.02.11 08:28:05 Client Info      Received REPLY on eth1/3,trans-id=0x6eb008, 5 opts: 1 2 3 23 39
2026.02.11 08:28:05 Client Notice    Address fc00:cafe:1234:4321:5678::2/128 added to eth1/3 interface.
2026.02.11 08:28:05 Client Debug     RENEW(IA_NA) will be sent (T1) after 1000, REBIND (T2) after 2000 seconds.
2026.02.11 08:28:08 Client Notice    FQDN: About to perform DNS Update: DNS server=2001:db8:2::dead:beef, IP=fc00:cafe:1234:4321:5678::2 and FQDN=grace
...

   

Le serveur en face était un Kea ainsi configuré :

"subnet6": [
        {
           "interface": "eth0",  // Ce n'est pas bien documenté mais
	   // cette option est cruciale, autrement le client reçoit
	   // des « Server could not select subnet for this client ».
           "subnet": "fc00:cafe:1234:4321::/64",
           "pools": [ { "pool": "fc00:cafe:1234:4321:5678::/80" } ],
...

Si vous voulez, le pcap de l'échange est disponible (capture faite avec tcpdump -w /tmp/dhcpv6-bis.pcap udp and \(port 546 or port 547\)). tcpdump voit le trafic ainsi :

09:28:04.624687 IP6 fe80::606d:ad11:58ca:6cab.546 > ff02::1:2.547: dhcp6 solicit
09:28:04.639479 IP6 fe80::6ee4:5672:da95:1018.547 > fe80::606d:ad11:58ca:6cab.546: dhcp6 advertise
09:28:05.652900 IP6 fe80::606d:ad11:58ca:6cab.546 > ff02::1:2.547: dhcp6 request
09:28:05.667843 IP6 fe80::6ee4:5672:da95:1018.547 > fe80::606d:ad11:58ca:6cab.546: dhcp6 reply
   

La requête est émise depuis une adresse lien-local (ici fe80::606d:ad11:58ca:6cab) pas depuis une adresse « tout zéro » comme en IPv4 (section 17 du RFC). On voit bien les quatre messages (Solicit - Advertise - Request - Reply), décrits section 5.2 (et la liste des types possibles est en section 7.3). Le serveur n'a pas répondu directement avec un Reply, parce que le client n'a pas inclut l'option Rapid Commit (section 21.14). Dans l'échange à quatre messages, le client demande à tous (Solicit), un(s) serveur(s) DHCP répond(ent) (Advertise), le client envoie alors sa requête au serveur choisi (Request), le serveur donne (ou pas) son accord (Reply). Avec l'option -vvv, tcpdump est plus bavard et montre qu'il analyse bien DHCPv6 :

09:28:04.624687 IP6 (flowlabel 0x51d28, hlim 1, next-header UDP (17) payload length: 99) fe80::606d:ad11:58ca:6cab.546 > ff02::1:2.547: [udp sum ok] dhcp6 solicit (xid=5ded1b (client-ID hwaddr/time type 1 time 824113684 f6fc69106509) (IA_NA IAID:1 T1:4294967295 T2:4294967295 (IA_ADDR :: pltime:4294967295 vltime:4294967295)) (Client-FQDN) (elapsed-time 0) (option-request DNS-server Client-FQDN))
09:28:04.639479 IP6 (flowlabel 0xf6846, hlim 64, next-header UDP (17) payload length: 140) fe80::6ee4:5672:da95:1018.547 > fe80::606d:ad11:58ca:6cab.546: [udp sum ok] dhcp6 advertise (xid=5ded1b (client-ID hwaddr/time type 1 time 824113684 f6fc69106509) (server-ID hwaddr/time type 1 time 823778152 38f7cdce22c6) (IA_NA IAID:1 T1:1000 T2:2000 (IA_ADDR fc00:cafe:1234:4321:5678::2 pltime:3000 vltime:4000)) (DNS-server 2001:db8:2::dead:beef 2001:db8:2::cafe:babe) (Client-FQDN))
09:28:05.652900 IP6 (flowlabel 0x51d28, hlim 1, next-header UDP (17) payload length: 117) fe80::606d:ad11:58ca:6cab.546 > ff02::1:2.547: [udp sum ok] dhcp6 request (xid=6eb008 (client-ID hwaddr/time type 1 time 824113684 f6fc69106509) (IA_NA IAID:1 T1:4294967295 T2:4294967295 (IA_ADDR fc00:cafe:1234:4321:5678::2 pltime:3000 vltime:4000)) (Client-FQDN) (option-request DNS-server Client-FQDN) (server-ID hwaddr/time type 1 time 823778152 38f7cdce22c6) (elapsed-time 0))
09:28:05.667843 IP6 (flowlabel 0xf6846, hlim 64, next-header UDP (17) payload length: 140) fe80::6ee4:5672:da95:1018.547 > fe80::606d:ad11:58ca:6cab.546: [udp sum ok] dhcp6 reply (xid=6eb008 (client-ID hwaddr/time type 1 time 824113684 f6fc69106509) (server-ID hwaddr/time type 1 time 823778152 38f7cdce22c6) (IA_NA IAID:1 T1:1000 T2:2000 (IA_ADDR fc00:cafe:1234:4321:5678::2 pltime:3000 vltime:4000)) (DNS-server 2001:db8:2::dead:beef 2001:db8:2::cafe:babe) (Client-FQDN))
   

Mais si vous préférez tshark, l'analyse de cet échange est également disponible.

Notez que certains clients DHCP dépendent de la présence d'un routeur qui envoie des RA (RFC 4861) avec le bit M - Managed - à 1 (RFC 4861, section 4.2). En l'absence de ces annonces, le client se contente de demander des informations diverses au serveur DHCP, mais pas d'adresse IP.

Et si vous voulez compiler dhcpcd vous-même, c'est simple :

wget https://github.com/NetworkConfiguration/dhcpcd/releases/download/v10.3.0/dhcpcd-10.3.0.tar.xz
dhcpcd-10.3.0.tar.xz 
tar xvf dhcpcd-10.3.0.tar 
dhcpcd-10.3.0
./configure
make
sudo make install
 

L'échange à deux messages (Solicit - Reply) est, lui, spécifié dans la section 5.1. Il s'utilise si le client n'a pas besoin d'une adresse IP, juste d'autres informations de configuration comme l'adresse du serveur NTP, comme décrit dans le RFC 4075. Même si le client demande une adresse IP, il est possible d'utiliser l'échange à deux messages, via la procédure rapide avec l'option Rapid Commit.

Tout client ou serveur DHCP v6 a un DUID (DHCP Unique Identifier, décrit en section 11). Le DUID est opaque et ne devrait pas être analysé par la machine qui le reçoit. La seule opération admise est de tester si deux DUID sont égaux (indiquant qu'en face, c'est la même machine). Il existe plusieurs façons de générer un DUID (dans l'exemple plus haut, Dibbler avait choisi la méthode duid-llt, adresse locale et heure) et de nouvelles pourront apparaitre dans le futur. Par exemple, un DUID peut être fabriqué à partir d'un UUID (RFC 6355).

Mais l'utilisation exclusive du DUID, au détriment de l'adresse MAC, n'est pas une obligation du RFC (le RFC, section 11, dit juste « DHCP servers use DUIDs to identify clients for the selection of configuration parameters », ce qui n'interdit pas d'autres méthodes). On peut utiliser l'adresse Ethernet. En combinaison avec des commutateurs qui filtrent sur l'adresse MAC, cela peut améliorer la sécurité.

Puisqu'on peut aussi attribuer des adresses statiquement à une machine, en la reconnaissant, par exemple, à son adresse MAC ou à son DUID, voici comment on peut configurer Kea pour donner une adresse IP fixe au client d'un certain DUID :

"reservations": [
  {
    "duid": "00:01:00:01:31:1e:fa:14:f6:fc:69:10:65:09",
    "ip-addresses": [ "fc00:cafe:1234:4321:b0f:1111::1" ]
  }
   

La section 6 de notre RFC décrit les différentes façons d'utiliser DHCPv6. On peut se servir de DHCPv6 en mode sans état (section 6.1), lorsqu'on veut juste des informations de configuration, ou avec état (section 6.2, qui décrit la façon historique d'utiliser DHCP), lorsqu'on veut réserver une ressource (typiquement l'adresse IP) et qu'il faut alors que le serveur enregistre (et pas juste dans sa mémoire, car il peut redémarrer) ce qui a été réservé. On peut aussi faire quelque chose qui n'a pas d'équivalent en IPv4, se faire déléguer un préfixe d'adresses IP entier (section 6.3). Un client DHCP qui reçoit un préfixe, mettons, /60, peut ensuite redéléguer des bouts, par exemple ici des /64. (Le RFC 7084 est une utile lecture au sujet des routeurs installés chez M. Toutlemonde.)

Le format détaillé des messages est dans la section 8. Le début des messages est toujours le même, un type d'un octet (la liste des types est en section 7.3) suivi d'un identificateur de transaction de trois octets. Le reste est variable, dépendant du type de message.

On a déjà parlé du concept de DUID plus haut, donc sautons la section 11 du RFC, qui parle du DUID, et allons directement à la section 12, qui parle d'IA (Identity Association). Une IA est composée d'un identifiant numérique, l'IAID (IA IDentifier) et d'un ensemble d'adresses et de préfixes. Le but du concept d'IA est de permettre de gérer collectivement un groupe de ressources (adresses et préfixes). Pour beaucoup de clients, le concept n'est pas nécessaire, on n'a qu'une IA, d'identificateur égal à zéro. Pour les clients plus compliqués, on a plusieurs IA, et les messages DHCP (par exemple d'abandon d'un bail) indiquent l'IA concernée.

Comme pour DHCPv4, une bonne partie des informations est transportée dans des options, décrites dans la section 21. Certaines options sont dans ce RFC, d'autres pourront apparaitre dans des RFC ultérieurs. Toutes les options commencent par deux champs communs, le code identifiant l'option (deux octets), et la longueur de l'option. Ces champs sont suivis par des données, spécifiques à l'option. Ainsi, l'option Client Identifier a le code 1, et les données sont un DUID (cf. section 11). Autre exemple, l'option Vendor Class (code 16) permet d'indiquer le fournisseur du logiciel client (notez qu'elle pose des problèmes de sécurité, cf. RFC 7824, et section 23 de notre RFC). Notez qu'il peut y avoir des options dans les options, ainsi, l'adresse IP (code 5) est toujours dans les données d'une option IA (les IA sont décrites en section 12).

Puisqu'on a parlé de sécurité, la section 22 du RFC détaille les questions de sécurité liées à DHCP. Le fond du problème est qu'il y a une profonde incompatibilité entre le désir d'une autoconfiguration simple des clients (le but principal de DHCP) et la sécurité. DHCP n'a pas de chiffrement et tout le monde peut donc écouter les échanges de messages, voire les modifier. Et, de toute façon, le serveur n'est pas authentifié, donc le client ne sait jamais s'il parle au serveur légitime. Il est trivial pour un méchant de configurer un serveur DHCP « pirate » et de répondre à la place du vrai, indiquant par exemple un serveur DNS que le pirate contrôle. Les RFC 7610 et RFC 7513 décrivent des solutions possibles à ce problème.

Des attaques par déni de service sont également possibles, par exemple via un client méchant qui demande des ressources (comme des adresses IP) en quantité. Un serveur prudent peut donc limiter la quantité de ressources accessible à un client.

Maintenant, les questions de vie privée. La section 23 rappelle que DHCP est très indiscret. Le RFC 7824 décrit les risques que DHCP fait courir à la vie privée du client (et le RFC 7844 des solutions possibles).

Les registres IANA ne changent pas par rapport à l'ancien RFC. Les différents paramètres sont en ligne.

L'annexe A de notre RFC décrit les changements depuis l'ancien RFC 8415. Rien d'essentiel n'a été changé. On notera :

  • Suppression de certains mécanismes optionnels (comme ils étaient de toute façon optionnels, cela n'affecte pas l'interopérabilité) qui étaient complexes et peu mis en œuvre : les adresses temporaires (IA_TA), il faut désormais relâcher explicitement celles qu'on veut temporaires, la possibilité de faire de l'unicast, et donc, logiquement, l'option qui forçait le multicast.
  • Correction de plusieurs erreurs signalées (certaines n'ont pas été corrigées puisqu'elles s'appliquaient à des options supprimées).
  • Texte plus précis sur les ports UDP utilisés.
  • Progression du RFC au statut de norme Internet complète (alors que le RFC 8415 était officiellement une proposition de norme).

Téléchargez le RFC 9915


L'article seul

RFC 9910: Registration Data Access Protocol (RDAP) Regional Internet Registry (RIR) Search

Date de publication du RFC : Janvier 2026
Auteur(s) du RFC : T. Harrison (APNIC), J. Singh (ARIN)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF regext
Première rédaction de cet article le 8 janvier 2026


Le protocole RDAP, successeur de whois, n'est pas utilisé que par les registres de noms de domaine. Il sert aussi chez les RIR, pour obtenir des informations sur les entités qui sont derrière une adresse IP (ou un AS). RDAP dispose dès le début de fonctions de recherche (regardez le RFC 9082) mais ce nouveau RFC ajoute des choses en plus.

Traditionnellement, les serveurs whois des RIR disposaient de fonction de recherche « avancées » comme la possibilité de chercher par valeur (« quels sont tous les préfixes IP de tel titulaire ? »). L'idée de ce RFC est de permettre la même chose en RDAP. RDAP de base permet les recherches des informations associées à une adresse IP :

% curl -s https://rdap.db.ripe.net/ip/2001:41d0:302:2200::180 | jq . 
{
  "handle": "2001:41d0::/32",
  "name": "FR-OVH-20041115",
  "country": "FR",
  "parentHandle": "2001:4000::/23",
  …
  "status": [
    "active"
  ],
  "entities": [
    {
      "handle": "OK217-RIPE",
      …
            "text",
            "Octave Klaba"
      …
  

En plus de ip, ce RFC ajoute ips (section 2.1) qui permet une recherche sur tous les préfixes dont le nom correspond à un certain motif (ici, tous ceux d'OVH) :

% curl -s https://rdap.db.ripe.net/ips\?name="FR-OVH-*" | jq '.ipSearchResults.[].handle'
"109.190.0.0 - 109.190.255.255"
"135.125.0.0 - 135.125.255.255"
"137.74.0.0 - 137.74.255.255"
"141.94.0.0 - 141.95.255.255"
"145.239.0.0 - 145.239.255.255"
"147.135.128.0 - 147.135.255.255"
"149.202.0.0 - 149.202.255.255"
"152.228.128.0 - 152.228.255.255"
"159.173.0.0 - 159.173.255.255"
"162.19.0.0 - 162.19.255.255"
…
  

J'ai utilisé ici curl et jq mais, évidemment, l'avantage de RDAP est que vous pouvez utiliser un client dédié ou bien n'importe quel logiciel qui sait faire du HTTP et du JSON (voyez plus loin un exemple en Python).

Et chez un autre RIR :

% curl -s https://rdap.arin.net/registry/ips\?name='CLOUDFLARE*' | \
       jq '.ipSearchResults.[].handle'
"NET-104-16-0-0-1"
"NET-108-162-192-0-1"
"NET-156-146-101-152-1"
"NET-162-158-0-0-1"
"NET-172-64-0-0-1"
"NET-173-245-48-0-1"
"NET-198-41-128-0-1"
"NET-199-27-128-0-1"
"NET6-2606-4700-1"
  

De la même façon, vous pouvez chercher par numéro d'AS :

% curl -s https://rdap.db.ripe.net/autnums\?name="*NIC-FR*" | \
          jq '.autnumSearchResults.[].handle'
"AS2483"
"AS2484"
"AS2485"
"AS2486"
  

La section 3 décrit ensuite des moyens de trouver les objets parents et enfants (puisque l'allocation des adresses IP est hiérarchique, toute adresse est dans un préfixe plus général et contient des préfixes plus spécifiques, cf. la section 3.2.1 du RFC) :

% curl -s https://rdap.db.ripe.net/ips/rirSearch1/rdap-up/2001:41d0:302:2200::180 | \
       jq '.handle'                   
"2001:41d0::/32"
  
% curl -s https://rdap.db.ripe.net/ips/rirSearch1/rdap-down/2001:4000::/23 | \
          jq '.ipSearchResults.[].handle'
"2001:4000::/32"
"2001:4010::/32"
"2001:4018::/29"
"2001:4020::/32"
…
  

Notez la relation (rdap-up et rdap-down). Notez aussi que rdap-up renvoie au maximum un objet alors que rdap-down peut en renvoyer plusieurs (cf. section 4.2), et c'est pour cela qu'il a fallu itérer en jq (le .[] parcourt le tableau). Quant au rirSearch1, le 1 indique la version de cette extension de recherche chez les RIR (désormais enregistrée à l'IANA).

Et en Python, ça donnerait :

#!/usr/bin/python

# Example of using search extensions to RDAP (RFC 9910)

# https://requests.readthedocs.io
import requests

# Standard library
import json
import sys

# Yes, we should use the registry documented in RFC 7484…
BASE_URL = "https://rdap.db.ripe.net/ips/rirSearch1/rdap-down"

if len(sys.argv) != 2:
    raise Exception("Usage: %s ip-prefix-at-ripe" % sys.argv[0])
arg = sys.argv[1]

response = requests.get("%s/%s" % (BASE_URL, arg))
if response.status_code != 200:
    raise Exception("Wrong HTTP return code from %s: %s" % (BASE_URL, response.status_code))
data = json.loads(response.text)
for prefix in data["ipSearchResults"]:
    print(prefix["handle"])
  

Et les recherches inverses, telles que décrites dans le RFC 9536 ? La section 5 du RFC les présente et voici un exemple qui marche (trouver tous les préfixes de Webflow) :

% curl -s 'https://rdap.arin.net/registry/ips/reverse_search/entity?handle=WEBFL' | \
            jq '.ipSearchResults.[].handle'
"NET-198-202-211-0-1"
"NET6-2620-CB-2000-1"
  

Un serveur RDAP qui gère les extensions de ce RFC doit le signaler dans ses réponses (section 6) :

…    
"rdapConformance" : [ "geofeed1", "rirSearch1", "ips", "cidr0",
       "rdap_level_0", "nro_rdap_profile_0", "redacted" ],
…
  

Mais aussi dans les liens donnés dans les réponses (ici, en réponse à une requête traditionnelle ip) :

  "links": [
    {
      "value": "https://rdap.db.ripe.net/ip/2001:41d0:302:2200::180",
      "rel": "rdap-up",
      "href": "https://rdap.db.ripe.net/ips/rirSearch1/rdap-up/2001:41d0::/32",
      "type": "application/rdap+json"
    },
  

Et bien sûr dans les réponses d'aide :

% curl -s https://rdap.arin.net/registry/help 
{
  "rdapConformance" : [ "nro_rdap_profile_0", "rdap_level_0", "cidr0", "nro_rdap_profile_asn_flat_0", "arin_originas0", "rirSearch1", "ips", "ipSearchResults", "autnums", "autnumSearchResults", "reverse_search" ],
  "notices" : [ {
    "title" : "Terms of Service",
    "description" : [ "By using the ARIN RDAP/Whois service, you are agreeing to the RDAP/Whois Terms of Use" ],
    "links" : [ {
      "value" : "https://rdap.arin.net/registry/help",
      "rel" : "terms-of-service",
      "type" : "text/html",
      "href" : "https://www.arin.net/resources/registry/whois/tou/"
    } ]
…
  

Les fonctions de recherche, c'est très bien mais c'est, par construction, indiscret. La section 8 de notre RFC détaille les risques de ces extensions de recherche pour la vie privée (relire le RFC 7481 est une bonne idée).

Les extensions de ce RFC, rirSearch1, ips, autnums, ipSearchResults et autnumSearchResults ont été enregistrées à l'IANA (section 10 du RFC). Les relations rdap-up, rdap-down, rdap-top et rdap-bottom sont dans le registre des liens (RFC 8288). Et le registre des recherches inverses inclut désormais fn, handle, email et role, avec leur correspondance en JSONPath.

Et question mise en œuvre et déploiement, on a quoi ? ARIN et RIPE ont annoncé avoir programmé les extensions de ce RFC mais elles ne sont pas forcément accessibles via le serveur RDAP public, entre autre pour les raisons de vie privée discutées dans la section 8. Aujourd'hui, comme vous le voyez dans les exemples ci-dessus, au moins ARIN et RIPE rendent une partie de ces extensions utilisables.


Téléchargez le RFC 9910


L'article seul

RFC 9896: SVG in RFCs

Date de publication du RFC : Janvier 2026
Auteur(s) du RFC : A. Rossi (RFC Series Consulting Editor), N. Brownlee, J. Mahoney (RFC Production Center), M. Thomson
Pour information
Réalisé dans le cadre de l'activité d'édition des RFC rswg
Première rédaction de cet article le 5 février 2026


Le RFC 7996 avait introduit la possibilité de mettre des images dans les RFC. Ce nouveau document le remplace, il décrit les règles pour inclure du SVG. Il est très court, se limitant aux principes, il n'a plus de mention d'un profil SVG particulier.

On peut donc mettre des images vectorielles car, a priori, dans un RFC, il y aura beaucoup plus de schémas que de photos. Donc, pas de bitmap.

Au fait, c'est quoi, SVG ? Il s'agit d'une norme d'un format d'images vectoriel, gérée par le W3C, et fondée sur XML. Voici un exemple d'un simple dessin en SVG :


<svg xmlns="http://www.w3.org/2000/svg" version="1.2">
  <rect x="25" y="25" width="200" height="200" fill="white" stroke-width="4" stroke="black" />
  <circle cx="125" cy="125" r="75" fill="black" />
  <polyline points="50,150 50,200 200,200 200,100" stroke="black" stroke-width="4" fill="none" />
  <line x1="50" y1="50" x2="200" y2="200" stroke="white" stroke-width="4" />
</svg>

  

Et voici son rendu : simple-rfc-picture

Ce RFC décrit des objectifs, une politique. Contrairement à son prédécesseur, le RFC 7996, il ne décrit pas de profil de SVG, il fixe des buts, pas les moyens de les atteindre. Ces buts sont :

  • Le schéma en SVG ne doit jamais être la seule représentation. Le RFC doit être compréhensible sans les schémas.
  • Le SVG ne doit pas inclure d'animations et ne doit pas être trop réactif (pas question de changer quand on tourne le téléphone).
  • Le but étant d'être vu et compris par le public le plus large possible, il ne faut pas utiliser les fonctions de SVG qui ne sont pas largement mises en œuvre. Pas de pointeurs vers des ressources externes, pas de script exécutable (pas de JavaScript actif dans un RFC…), attention portée à l'accessibilité, en suivant WAI. Pour la même raison, il ne faut pas de dépendance vis-à-vis des couleurs (RFC 6949, section 3.2) et pas de choix arbitraire de police.

Il est crucial que les RFC soient accessibles à tou·te·s, non seulement quel que soit le matériel utilisé, mais également quels que soient les handicaps dont souffre leur propriétaire. C'est bien joli de vouloir ajouter des tas de choses dans les RFC mais encore faut-il ne pas creuser ainsi davantage le fossé entre les utilisateurs. Ainsi, accepter de la couleur (le RFC 6949 limite les futurs RFC au noir et blanc) fait courir le risque que les daltoniens ne puissent pas comprendre un RFC. De même, les graphiques, qui ont l'air comme ça d'être une bonne idée, peuvent aggraver la situation des malvoyants. Le texte seul peut toujours être lu à voix haute par un synthétiseur de parole mais pas le graphique.

La traduction de ces principes en conseils techniques concrets, et l'application de ces règles seront du ressort du RFC Production Center. Il suivra peut-être les nombreux détails pratiques décrits dans le RFC 7996 mais il n'y est pas obligé.

Comment on écrit du SVG ? S'il est évidemment possible de le faire entièrement à la main avec un éditeur ordinaire, gageons que peu de gens le tenteront. Le RFC 7996 citait des éditeurs graphiques, produisant du SVG, comme les logiciels libres Inkscape et Dia. (Et, si on aime programmer en Python, il y a svgwrite, que je présente plus en détail à la fin.) Attention, Inkscape et Dia produisent du SVG généraliste, qui peut inclure des fonctions de SVG qui ne suivent pas les principes de notre RFC.

Autre solution, utiliser la bibliothèque Fletcher de Typst :

% typst compile --format svg essai-fletcher.typ
  

Le texte « Tips for Creating Accessible SVG » donne des bons conseils pour faire du SVG accessible. Et il y a bien sûr la norme ARIA, dont il existe une introduction et de bons exemples. (Désolé, je n'ai pas suivi ces excellents principes dans les exemples ci-dessous, mais j'accepte les patches.)

Avec Inkscape, il faut veiller à sauver le fichier en Plain SVG (autrement, on a des ennuis avec les éléments spécifiques d'Inkscape, ex-Sodipodi). Mais il reste malgré cela deux ou trois trucs à corriger manuellement, avant que le document produit par Inkscape soit accepté. Pour Dia, il faut utiliser l'action Export (par défaut, Dia n'enregistre pas en SVG), mais Dia produit alors un document avec une DTD. Si on la retire (manuellement, ou bien avec xmllint --dropdtd), tout se passe bien.

Si vous voulez voir des exemples concrets de RFC utilisant SVG, vous avez entre beaucoup d'autres, le RFC 8899, le RFC 9869 ou encore le RFC 9750. Ainsi, le RFC 8899 inclut un schéma qui a deux formes alternatives, en art ASCII :


<artwork type="ascii-art" name="" alt="" align="left" pn="section-4.4-2.1.2">
Any additional
  headers         .--- MPS -----.
         |        |             |
         v        v             v
  +------------------------------+
  | IP | ** | PL | protocol data |
  +------------------------------+

             &lt;----- PLPMTU -----&gt;
  &lt;---------- PMTU --------------&gt;
</artwork>

  

Et en SVG, que vous pouvez admirer dans le rendu HTML du RFC et son rendu en PDF.

Une alternative, pour tester les SVG est svgcheck. Ici avec le vrai source du RFC 9750 :

% svgcheck rfc9750.xml  
INFO: File conforms to SVG requirements.
  

Et si je tente de mettre des couleurs vives en modifiant le XML :

% svgcheck rfc9750.xml      
rfc9750.xml:438: The attribute 'stroke' does not allow the value 'red', replaced with 'black'
ERROR: File does not conform to SVG requirements
  

Autre solution que j'aime bien pour faire du SVG, dès qu'on a des éléments répétitifs et qu'on veut donc automatiser (en Python), svgwrite. Ce schéma en art ASCII :

 +--------------+				     +----------------+
 |  Alice       |------------------------------------|      Bob	      |
 | 2001:db8::1  |                                    |   2001:db8::2  |
 +--------------+				     +----------------+

aurait pu être créé avec svgwrite avec network-schema-svgwrite.py, qui donne network-schema-svgwrite

Bien sûr, pour un schéma aussi simple, le gain n'est pas évident, mais il le devient pour les schémas comportant beaucoup d'éléments récurrents. Mais notez que svgwrite, par défaut, peut donc produire des SVG non conformes aux règles du RFC (par exemple avec de la couleur). Le programmeur doit donc faire attention.


Téléchargez le RFC 9896


L'article seul

RFC 9881: Internet X.509 Public Key Infrastructure -- Algorithm Identifiers for the Module-Lattice-Based Digital Signature Algorithm (ML-DSA)

Date de publication du RFC : Octobre 2025
Auteur(s) du RFC : J. Massimo, P. Kampanakis (AWS), S. Turner (sn3rd), B. E. Westerbaan (Cloudflare)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF lamps
Première rédaction de cet article le 18 février 2026


Vous reprendrez bien un peu de post-quantique ? Ce RFC normalise l'utilisation de signatures ML-DSA dans les certificats X.509.

ML-DSA est un des premiers gagnants du concours du NIST (il se nommait Dilithium à l'époque). Il est normalisé dans FIPS-204. Il utilise les réseaux euclidiens. C'est un algorithme de signature et il a donc toute sa place dans les certificats X.509, aux côtés des plus classiques RSA et ECDSA. Petit rappel de cryptographie post-quantique au passage : contrairement à RSA, ML-DSA ne sait faire que les signatures, pas l'échange de clés. Vous pouvez donc mettre des clés publiques ML-DSA dans un certificat, le signer avec ML-DSA mais, pour un protocole comme TLS, il faudra utiliser autre chose pour l'échange de clés (par exemple ML-KEM, autre vainqueur du concours NIST).

Mettre du post-quantique dans les certificats était moins urgent que dans l'échange de clés : ici, pas de risque qu'un attaquant prévoyant stocke des communications chiffrées, en attendant d'avoir un calculateur quantique pour les décrypter. Avec TLS, le risque est nul car la signature est au moment de la connexion, les calculateurs quantiques ne pourront usurper que les communications futures. Mais, bon, les certificats sont utilisés pour autre chose que TLS, et, comme il faut se préparer à un lent déploiement, il vaut mieux s'y prendre tout de suite.

Notez aussi qu'il n'y a pas que les certificats qui sont signés, les CRL le sont aussi, et ce RFC s'applique aussi à ces listes.

Des deux variantes normalisées dans FIPS-204, « pure » et « HashML-DSA », seule la première est utilisée dans notre RFC, pour les raisons qu'explique la section 8.3.

Le RFC utilise trois niveaux de sécurité différents, et les identificateurs pour les trois niveaux sont id-ml-dsa-44 (OID 2.16.840.1.101.3.4.3.17), id-ml-dsa-65 (OID 2.16.840.1.101.3.4.3.18) et id-ml-dsa-87 (OID 2.16.840.1.101.3.4.3.19). (Ces OID sont enregistrés par le NIST.) D'autre part, l'IANA a enregistré l'identificateur id-mod-x509-ml-dsa-2025 (OID 1.3.6.1.5.5.7.0.119) pour le module ML-DSA (annexe A).

Un certificat X.509 contient des indications sur les utilisations permises (section 4.2.1.3 du RFC 5280). Comme ML-DSA sait faire des signatures mais pas des échanges de clés, un certificat avec ML-DSA aura les utilisations de signature, comme keyCertSign mais pas celles d'échange de clés comme keyEncipherment.

Le format de la clé privée (section 6) a été un des sujets de discussions chauds à l'IETF (et chez les implémenteurs). Dans la norme FIPS-204, on peut définir une clé privée de deux façons, une optimisée (section 4 de la norme) où on ne stocke que la graine (notée ξ) ou bien une forme longue avec la graine, les éléments de la clé secrète, etc. On peut déduire la clé de la graine (section 6.1 de la norme), mais pas l'inverse donc si vous ne gardez pas la graine, vous pourrez toujours signer mais pas retrouver la graine. Le RFC permet de stocker la clé privée de trois façons, la graine seule (la méthode recommandée, cf. section 8.1), la clé seule (déconseillé) ou les deux (voir un exemple plus loin).

Je n'ai pas trouvé de certificat utilisant ML-DSA dans la nature. crt.sh ne permet pas de chercher par algorithme, même dans ses fonctions avancées. Il faudrait écrire son propre client d'examen des journaux Certificate Transparency (RFC 9162) et j'avais la flemme. Donc, on va utiliser OpenSSL 3.5 pour fabriquer des certificats (je n'ai pas testé pour voir s'ils étaient parfaitement conformes au RFC…).

% openssl req -new -newkey mldsa44 -keyout mldsa.key -out mldsa.csr -nodes -subj "/CN=test"
% openssl x509 -in mldsa.csr -out mldsa.crt -req -signkey mldsa.key -days 2001 
Certificate request self-signature ok
subject=CN=test
  

Et hop, nous voilà avec un beau certificat :

% openssl x509 -text -in mldsa.crt 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            54:5b:c0:5d:0e:85:83:43:90:77:93:4f:53:83:e1:38:a2:12:9f:61
        Signature Algorithm: ML-DSA-44
        Issuer: CN=test
        Validity
            Not Before: Feb 17 15:01:53 2026 GMT
            Not After : Aug 11 15:01:53 2031 GMT
        Subject: CN=test
        Subject Public Key Info:
            Public Key Algorithm: ML-DSA-44
                ML-DSA-44 Public-Key:
                pub:
                    15:10:02:cc:d6:ec:53:12:bb:6d:34:23:82:65:ec:
                    …
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                6E:F9:AD:56:9C:AA:60:EF:ED:B7:A1:7B:70:F6:71:55:74:B8:68:B9
    Signature Algorithm: ML-DSA-44
…
  

Autre solution, de plus bas niveau, en découpant les étapes :

# Créer la clé privée
openssl genpkey -algorithm ML-DSA-44 -out private.pem

# Extraire la clé publique (mais on ne s'en servira pas ici)
openssl pkey -in private.pem -pubout -out public.pem

# Créer la demande de signature du certificat
openssl req -new -subj /CN=Test -key private.pem -out cert.csr

# (Auto-)Signer
openssl x509 -req -in cert.csr -signkey private.pem -out cert.pem
Certificate request self-signature ok
subject=CN=Test

# Vérifier
openssl x509 -text -in cert.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            7c:65:cb:17:5b:ed:ee:08:c9:1a:6b:a5:97:da:ac:b8:0e:6e:df:cd
        Signature Algorithm: ML-DSA-44
        Issuer: CN=Test
        Validity
            Not Before: Feb 18 13:24:05 2026 GMT
            Not After : Mar 20 13:24:05 2026 GMT
        Subject: CN=Test
        Subject Public Key Info:
            Public Key Algorithm: ML-DSA-44
                ML-DSA-44 Public-Key:
   …
   Signature Algorithm: ML-DSA-44
…

Et si vous voulez utiliser des extensions comme la restriction d'utilisation du certificat (ici, on se limite à la signature), remplacez la demande de signature et la signature par :

openssl req -new -subj /CN=Test -key private.pem -out cert.csr -addext "keyUsage=digitalSignature"
openssl x509 -req -in cert.csr -signkey private.pem -out cert.pem  -copy_extensions copy
  

Si vous voulez regarder ce qu'il y a dans la clé privée :

%  openssl pkey -text -in private.pem  
…
ML-DSA-44 Private-Key:
seed:
    48:c8:e4:e3:63:16:c0:e4:57:da:22:31:94:36:98:
    ..
priv:
    d9:0b:5b:8d:18:4f:61:8d:c0:8f:85:6c:97:28:46:
    …
  

Vous voyez que sont stockées graine et clé (et la clé publique, plus loin).

Pour wolfSSL, vous pouvez regarder ici.

Pour des « vrais » certificats, notez que Digicert en fait apparemment, ainsi que l'AC pour usage privé d'AWS. Vous connaissez d'autres AC qui permettraient ML-DSA ?

Sinon, l'annexe C du RFC comprend de nombreux exemples de clés et de signatures.


Téléchargez le RFC 9881


L'article seul

RFC 9874: Best Practices for Deletion of Domain and Host Objects in the Extensible Provisioning Protocol (EPP)

Date de publication du RFC : Septembre 2025
Auteur(s) du RFC : S. Hollenbeck (Verisign Labs), W. Carroll (Verisign), G. Akiwate (Stanford University)
Réalisé dans le cadre du groupe de travail IETF regext
Première rédaction de cet article le 5 octobre 2025


Dans un registre de noms de domaine, il existe une classe d'objets pour les domaines et parfois une pour les serveurs de noms (hosts). C'est en se basant sur les objets de ces classes que des informations sont ensuite publiées dans le DNS. Que se passe-t-il si on retire un objet de ces classes, alors que d'autres objets en dépendaient ? Va-t-on scier une branche sur laquelle quelqu'un est assis ? Ce RFC fait le point sur les solutions existantes, notant que certaines sont moins bonnes que d'autres, notamment pour la sécurité.

Prenons un exemple simple : le domaine monbeaudomaine.example est enregistré auprès du registre du TLD .example. Ses serveurs de noms sont ns1.domaine-d-un-copain.example et ns1.hébergeur.example et on va supposer que le registre de .example traite les serveurs de noms comme une classe distincte dans sa base de données. Maintenant, supposons que le domaine domaine-d-un-copain.example soit supprimé parce que son titulaire n'en voit plus l'utilité. Que va devenir le serveur de noms ns1.domaine-d-un-copain.example ? Il existe de nombreuses façons de traiter ce problème, et c'est le rôle de ce RFC de les analyser toutes.

Ainsi, la section 3.2.2 du RFC 5731 dit que ce n'est pas bien de détruire un domaine si des objets de type serveur de noms sont sous ce domaine. Dans l'exemple précédent, le registre de .example aurait refusé la suppression de domaine-d-un-copain.example. Mais cela laisse le problème entier : si le titulaire ne veut plus payer et donc veut supprimer le domaine, que faire ?

Un cas similaire se produit si on veut supprimer un serveur de noms. Si le client EPP demande au serveur EPP du registre de .example la suppression de l'objet ns1.domaine-d-un-copain.example, que doit faire le registre, sachant que ce serveur de noms est utilisé par monbeaudomaine.example ? La section 3.2.2 du RFC 5732 dit que le registre devrait refuser la suppression. C'est d'autant plus gênant que, dans le modèle RRR (Registrant-Registrar-Registry), domaine et serveur(s) peuvent être gérés par des BE différents, n'ayant pas le droit de toucher aux objets des autres BE.

Vous pouvez trouver des bonnes explications et des exemples réels dans les supports d'une présentation qui avait été faite à l'IETF.

Quelles sont donc les recommandations concrètes de ce RFC ? La section 6 les résume. Au choix :

  • Renommer les serveurs de noms vers le nom d'un serveur maintenu par le client EPP (le BE), comme décrit dans la section 5.1.3.4.
  • Demander au client EPP de supprimer les serveurs de noms mais avec possibilité de rétablissement (RFC 3915) comme décrit en section 5.2.2.3.
  • Renommer les serveurs de noms dans un nom de domaine spécial, dont il est garanti qu'il ne sera jamais utilisé, comme décrit en section 5.1.4.3. Pour éviter d'avoir à créer une nouvelle entrée dans le registre des noms de domaine spéciaux, le nom sacrificial.invalid, utilisant un TLD existant, est recommandé.

Le protocole EPP permet de changer le nom d'un serveur de noms (section 3.2.5 du RFC 5732). Une pratique déjà observée est donc de renommer les serveurs de noms. Dans l'exemple ci-dessus, recevant la demande de suppression de domaine-d-un-copain.example, le registre (ou le BE s'il le peut) renommerait ns1.domaine-d-un-copain.example en, mettons, ns1.domaine-d-un-copain.renamed.invalid. Ici, .invalid, TLD réservé par le RFC 6761, ne poserait pas vraiment de problème mais renommer dans un domaine ouvert à l'enregistrement pourrait créer un risque de sécurité, si le domaine de destination n'existe pas, un méchant pouvant alors l'enregistrer et être ainsi en mesure de répondre aux requêtes DNS.

La section 3 du RFC explique brièvement pourquoi les RFC 5731 et RFC 5732 déconseillent fortement de permettre la suppression d'un domaine tant que des serveurs de noms dans ce domaine existent. Il y a deux risques de sécurité si on détruisait le domaine en laissant les serveurs de noms tels quels dans la base de données du registre : un de déni de service (le nom ne se résout plus et le serveur va donc être inutile) et un de détournement (si un méchant peut ré-enregistrer le nom de domaine supprimé). Il y a aussi le problème de la colle orpheline, décrit dans le rapport du SSAC, « Comment on Orphan Glue Records in the Draft Applicant Guidebook ».

Si la clé qui identifie un serveur de noms est un numéro quelconque et pas son nom, on peut renommer le serveur sans changer les délégations, ce qui est particulièrement utile si le client EPP n'a pas le droit de changer des délégations qui appartiennent à un autre client du registre. Le nouveau nom ne va en général pas être associé à un serveur opérationnel : on sacrifie un serveur pour pouvoir supprimer le domaine parent. Mais cela entraine quelques risques (section 4 du RFC et l'article d' Akiwate, G., Savage, S., Voelker, G., et K. Claffy, « Risky BIZness: Risks Derived from Registrar Name Management »). Si on renomme vers un nom actuellement inexistant, le domaine peut être détourné si un malveillant enregistre ensuite ce domaine.

Compte tenu de tout cela, la section 5 du RFC étudie les différentes pratiques possibles, leurs avantages et leurs inconvénients. Pour les illustrer, je vais utiliser une base de données simple, décrite en SQL (les essais ont été faits avec PostgreSQL). Voici par exemple une création d'une telle base :

CREATE TABLE Domains (name TEXT UNIQUE);

-- Ici, la table Nameservers n'offre aucune valeur ajoutée par rapport
-- au fait de tout mettre dans Domains. Mais ce ne sera pas le cas par
-- la suite. 
CREATE TABLE Nameservers (name TEXT UNIQUE);

CREATE TABLE Delegation (domain TEXT REFERENCES Domains(name),
                         server TEXT REFERENCES Nameservers(name));

INSERT INTO Domains VALUES ('monbeaudomaine.example');
INSERT INTO Domains VALUES ('domaine-d-un-copain.example');

INSERT INTO Nameservers VALUES ('ns1.domaine-d-un-copain.example');
INSERT INTO Nameservers VALUES ('ns1.hébergeur.example');

INSERT INTO Delegation VALUES ('monbeaudomaine.example', 'ns1.domaine-d-un-copain.example');
INSERT INTO Delegation VALUES ('monbeaudomaine.example', 'ns1.hébergeur.example');
  

Dans ce premier cas très simple, la suppression du domaine domaine-d-un-copain.example est triviale :

registry=> DELETE FROM Domains WHERE name='domaine-d-un-copain.example';
DELETE 1
  

Mais elle laisse la possibilité de colle orpheline et surtout d'un détournement de monbeaudomaine.example si quelqu'un ré-enregistre domaine-d-un-copain.example. Ce premier essai n'est pas conforme aux exigences des RFC 5731 et RFC 5732. On va essayer de faire mieux.

Si on interdit (à juste titre) la suppression d'un domaine lorsque des serveurs de noms sont nommés dans ce domaine, on peut arriver à supprimer un domaine en supprimant d'abord les serveurs de noms qui sont nommés dans ce domaine (section 5.2) :

CREATE TABLE Domains (name TEXT UNIQUE);

-- Ajout d'une dépendance au domaine parent, pour éviter les suppressions. 
CREATE TABLE Nameservers (name TEXT UNIQUE, parent TEXT REFERENCES Domains(name));

CREATE TABLE Delegation (domain TEXT REFERENCES Domains(name),
                         server TEXT REFERENCES Nameservers(name));

INSERT INTO Domains VALUES ('monbeaudomaine.example');
INSERT INTO Domains VALUES ('domaine-d-un-copain.example');
INSERT INTO Domains VALUES ('hébergeur.example');

-- Pour une vraie base, on écrirait du code SQL qui extrait le parent
-- automatiquement.
INSERT INTO Nameservers VALUES ('ns1.domaine-d-un-copain.example', 'domaine-d-un-copain.example');
INSERT INTO Nameservers VALUES ('ns1.hébergeur.example', 'hébergeur.example');

INSERT INTO Delegation VALUES ('monbeaudomaine.example', 'ns1.domaine-d-un-copain.example');
INSERT INTO Delegation VALUES ('monbeaudomaine.example', 'ns1.hébergeur.example');

registry=> DELETE FROM Domains WHERE name='domaine-d-un-copain.example';
ERROR:  update or delete on table "domains" violates foreign key constraint "nameservers_parent_fkey" on table "nameservers"
DETAIL:  Key (name)=(domaine-d-un-copain.example) is still referenced from table "nameservers".
-- Ce comportement est ce que recommandent les RFC 5731 et 5732.

-- Cela oblige le client à supprimer les serveurs de noms d'abord, ce qui à
-- son tour nécessite potentiellement de changer les délégations :

registry=> DELETE FROM Delegation WHERE server = 'ns1.domaine-d-un-copain.example';
DELETE 1
registry=>  DELETE FROM Nameservers WHERE name='ns1.domaine-d-un-copain.example';
DELETE 1
registry=>  DELETE FROM Domains WHERE name='domaine-d-un-copain.example';
DELETE 1
  

Ici, il y a eu suppression explicite des serveurs de noms par le client (section 5.2.2.1). Cela peut poser des problèmes de permission, dans le cadre du système RRR, si tous les objets ne sont pas chez le même BE. Mais la suppression explicite est une des trois solutions recommandées, notamment si on ajoute la possibilité de rétablir l'état précédent (commande EPP <restore>, RFC 3915).

On peut aussi envisager une suppression implicite (section 5.2.1.1), le registre se chargeant du nettoyage (c'est le rôle de la directive SQL ON DELETE CASCADE) :

CREATE TABLE Domains (name TEXT UNIQUE);

CREATE TABLE Nameservers (name TEXT UNIQUE,
                          parent TEXT REFERENCES Domains(name) ON DELETE CASCADE);

CREATE TABLE Delegation (domain TEXT REFERENCES Domains(name) ON DELETE CASCADE,
                         server TEXT REFERENCES Nameservers(name) ON DELETE CASCADE);

INSERT INTO Domains VALUES ('monbeaudomaine.example');
INSERT INTO Domains VALUES ('domaine-d-un-copain.example');
INSERT INTO Domains VALUES ('hébergeur.example');

-- Pour une vraie base, on écrirait du code SQL qui extrait le parent
-- automatiquement.
INSERT INTO Nameservers VALUES ('ns1.domaine-d-un-copain.example', 'domaine-d-un-copain.example');
INSERT INTO Nameservers VALUES ('ns1.hébergeur.example', 'hébergeur.example');

INSERT INTO Delegation VALUES ('monbeaudomaine.example', 'ns1.domaine-d-un-copain.example');
INSERT INTO Delegation VALUES ('monbeaudomaine.example', 'ns1.hébergeur.example');

registry=> SELECT Domains.name,Nameservers.name FROM Domains,Delegation,Nameservers WHERE Delegation.domain=Domains.name AND Delegation.server=Nameservers.name;
          name          |              name               
------------------------+---------------------------------
monbeaudomaine.example | ns1.domaine-d-un-copain.example
monbeaudomaine.example | ns1.hébergeur.example
(2 rows)

registry=>  DELETE FROM Domains WHERE name='domaine-d-un-copain.example';
DELETE 1

-- Serveur de noms et délégation ont été détruits en cascade. Ce n'est
-- pas déraisonnable mais c'est quand même un peu effrayant.

registry=> SELECT Domains.name,Nameservers.name FROM Domains,Delegation,Nameservers WHERE Delegation.domain=Domains.name AND Delegation.server=Nameservers.name;
          name          |         name          
------------------------+-----------------------
monbeaudomaine.example | ns1.hébergeur.example
(1 row)
  

Cette solution est simple et efficace mais détruire implicitement des objets de la base de données peut inquiéter les responsables de cette base. Et cela peut laisser un domaine avec trop peu de serveurs de noms pour assurer sa continuité de service voire, dans le pire des cas, sans serveurs du tout. Et il serait bon de prévenir le client de cette suppression implicite, par exemple par le mécanisme de poll d'EPP (RFC 8590).

Si on interdit (à juste titre, le RFC le recommande) la suppression d'un domaine lorsque des serveurs de noms sont nommés dans ce domaine, une solution possible est de renommer les serveurs avant de supprimer le domaine (section 5.1). Le nouveau nom permet d'indiquer clairement la raison du renommage. Mais ce renommage laisse dans la base des « déchets » qu'il faudra nettoyer un jour. Cette catégorie contient de nombreuses variantes. Par exemple, on peut renommer dans un TLD spécial (RFC 6761), ici, .invalid :

CREATE TABLE Domains (name TEXT UNIQUE);

-- On introduit un identificateur du serveur de noms qui n'est *pas*
-- son nom, pour permettre le renommage.
CREATE TABLE Nameservers (id SERIAL UNIQUE, name TEXT UNIQUE,
                                 parent TEXT REFERENCES Domains(name));

CREATE TABLE Delegation (domain TEXT REFERENCES Domains(name),
                         server INTEGER REFERENCES Nameservers(id));

INSERT INTO Domains VALUES ('monbeaudomaine.example');
INSERT INTO Domains VALUES ('domaine-d-un-copain.example');
INSERT INTO Domains VALUES ('hébergeur.example');
-- Pour le renommage, un nom qui indique clairement le but :
INSERT INTO Domains VALUES ('renamed.invalid');

-- Pour une vraie base, on écrirait du code SQL qui extrait le parent
-- automatiquement.
INSERT INTO Nameservers (name, parent) VALUES ('ns1.domaine-d-un-copain.example', 'domaine-d-un-copain.example');
INSERT INTO Nameservers (name, parent) VALUES ('ns1.hébergeur.example', 'hébergeur.example');

INSERT INTO Delegation VALUES ('monbeaudomaine.example',
     (SELECT id FROM Nameservers WHERE name='ns1.domaine-d-un-copain.example'));
INSERT INTO Delegation VALUES ('monbeaudomaine.example',
     (SELECT id FROM Nameservers WHERE name='ns1.hébergeur.example'));

registry=> SELECT Domains.name,Nameservers.name FROM Domains,Delegation,Nameservers WHERE Delegation.domain=Domains.name AND Delegation.server=Nameservers.id;
          name          |              name               
------------------------+---------------------------------
monbeaudomaine.example | ns1.domaine-d-un-copain.example
monbeaudomaine.example | ns1.hébergeur.example
(2 rows)

registry=> UPDATE Nameservers SET name='ns1.domaine-d-un-copain.example.renamed.invalid', parent='renamed.invalid' WHERE id=1;
UPDATE 1
registry=> DELETE FROM Domains WHERE name='domaine-d-un-copain.example';
DELETE 1

registry=> SELECT Domains.name,Nameservers.name FROM Domains,Delegation,Nameservers WHERE Delegation.domain=Domains.name AND Delegation.server=Nameservers.id;
          name          |                      name                       
------------------------+-------------------------------------------------
monbeaudomaine.example | ns1.domaine-d-un-copain.example.renamed.invalid
monbeaudomaine.example | ns1.hébergeur.example
(2 rows)

Par contre, il ne faut pas utiliser .alt, qui est explicitement réservé aux protocoles non-DNS (RFC 9476). Notez que certains serveurs EPP peuvent tester le nom des serveurs de noms et refuser des TLD « inconnus ».

Dans la nature, on a pu observer d'autres pratiques, comme de renommer dans un sous-domaine de as112.arpa, nom garanti ne pas exister (RFC 7535), mais qui n'est pas censé servir à cela (RFC 6305). On a vu aussi des renommages vers des résolveurs DNS publics, ce qui est également une horreur, la délégation doit être faite vers des serveurs faisant autorité, pas des résolveurs.

Certains clients EPP maintiennent des serveurs de noms actifs qui servent pour le renommage. Cela fait davantage de travail mais cela protège contre le détournement. Le DNS va continuer à fonctionner normalement. On pourrait aussi imaginer des serveurs de noms actifs, répondant NXDOMAIN (« ce domaine n'existe pas »), qui soient gérés collectivement (section 5.1.4.4) ; un tel service serait certainement utile. On pourrait même créer un nom de domaine pour ce service (sacrificial.arpa ?) mais personne ne l'a encore fait. Pour l'instant, la solution des serveurs maintenus par le client EPP (section 5.1.3.4) fait partie des trois solutions recommandées. Le client prudent doit bien verrouiller le domaine dans lequel ces serveurs sont nommés (enregistrement multi-années, verrouillage par le registre, etc).

On peut aussi renommer les serveurs de noms vers un nom non-existant dans un TLD existant. Ça s'est déjà vu mais il ne faut surtout pas faire cela : un attaquant pourrait enregistrer le nom et capter ainsi le trafic (.invalid n'a pas ce problème). Idem si le nom n'est pas sous votre contrôle. Un exemple est donné par le domaine lenvol.re : ses serveurs de noms étaient ns.hostin.io, ns.hostin.mu et ns.hostin.re. Lors de la suppression de hostin.re en octobre 2024, le dernier serveur de noms a été renommé host1.renamedbyregistry.com (et, en dépit du nom, pas par le registre). Ce domaine renamedbyregistry.com étant enregistré, et par un autre BE, on voit le risque.

%  whois lenvol.re
domain:                        lenvol.re
status:                        ACTIVE
…
nserver:                       host1.renamedbyregistry.com
nserver:                       ns.hostin.io
nserver:                       ns.hostin.mu
  

D'autres noms qui utilisaient ce même serveur ont également le problème :

% dig @d.nic.fr savanna.re. NS       
…
;; AUTHORITY SECTION:
savanna.re.		3600	IN	NS	host1.renamedbyregistry.com.
savanna.re.		3600	IN	NS	ns.hostin.mu.
savanna.re.		3600	IN	NS	ns.hostin.io.

;; Query time: 8 msec
;; SERVER: 2001:678:c::1#53(d.nic.fr) (UDP)
;; WHEN: Tue Jun 24 14:33:32 CEST 2025

En lecture supplémentaire, notre RFC recommande le rapport « SSAC 125 "Report on Registrar Nameserver Management" », ainsi que l'article « Risky BIZness: Risks Derived from Registrar Name Management ».


Téléchargez le RFC 9874


L'article seul

RFC 9868: Transport Options for UDP

Date de publication du RFC : Octobre 2025
Auteur(s) du RFC : J. Touch, C. Heard
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 5 décembre 2025


Des protocoles de transport, comme TCP, ont le concept d'options, ajoutées à l'en-tête et permettant de régler divers paramètres. Ce RFC ajoute ce concept à UDP et standardise quelques options. Désormais, il y a des moyens standards de faire du « ping » en UDP.

Mais comment ajouter des options à un vénérable protocole (UDP a été normalisé en 1980, dans le RFC 768), qui n'a pas de place pour cela dans son en-tête très minimal ? L'astuce est que UDP indique une taille de paquet qui peut être différente de celle indiquée par IP. Si elle est supérieure, les octets ainsi disponibles peuvent stocker des options, à la fin du paquet. Ce sera donc un pied (trailer) et pas un en-tête.

Voici un paquet UDP simplifié (j'ai aussi mis une partie de l'en-tête IP) analysé par tshark :

Internet Protocol Version 6, Src: 2a04:cec0:10fc:5bd8:efd1:79bb:7356:4583, Dst: 2001:db8::1
    0110 .... = Version: 6
…
    Payload Length: 56
    Next Header: UDP (17)
    Hop Limit: 64
    Source Address: 2a04:cec0:10fc:5bd8:efd1:79bb:7356:4583
    Destination Address: 2001:db8::1
User Datagram Protocol, Src Port: 57560 (57560), Dst Port: domain (53)
    Source Port: 57560 (57560)
    Destination Port: domain (53)
    Length: 56
…
    UDP payload (48 bytes)
  

Vous avez vu ? Il y a deux champs qui indiquent la longueur du paquet UDP, un dans l'en-tête IP (Payload length) et un dans l'en-tête UDP (Length). Ici, les deux sont identiques, ce qui est le cas « normal ». Mais s'ils sont différents ? C'est le point de départ de ce RFC. Les options se nicheront dans la différence entre la longueur du paquet UDP et celle du paquet IP qui l'encapsule, dans une zone connue sous le nom de surplus (surplus area). Normalement, elles seront ainsi ignorées de tous les vieux programmes (mais il y a parfois eu des bogues).

Comme TCP (RFC 9293), les protocoles de transport SCTP (RFC 9260) et DCCP (RFC 4340) ont dans leur en-tête un espace réservé pour d'éventuelles options. Pas UDP. C'est ce manque que comble notre RFC. Comme UDP est un protocole sans connexion, ces options ne serviront que pour un seul paquet (alors que TCP peut les garder pour toute la connexion). Des options, dans les autres protocoles de transport, il y en a plein. Pour TCP, le RFC cite par exemple, la dilatation de fenêtres (RFC 7323), l'authentification (RFC 5925) et d'autres. On en trouve pour des protocoles avec état (comme TCP, où elles vont s'appliquer à toute la connexion) ou sans état (comme IP, où elles ne s'appliquent qu'au paquet qui les porte). Comme vu plus haut, seul UDP (RFC 768) n'avait pas le moyen d'ajouter des options.

(Notez que TeredoRFC 4380 - utilisait déjà un truc analogue.)

À quoi vont servir ces options (section 5 du RFC) ? À court terme, à permettre des mécanismes de fragmentation, de test (« ping UDP »), etc. À plus long terme (mais ce n'est pas encore normalisé), elles rendront possible d'ajouter de l'authentification ou du chiffrement à UDP (DTLS, RFC 9147 chiffre mais ne protège pas l'en-tête de la couche Transport). On pourra aussi faire de la découverte de la MTU du chemin, comme spécifié dans le RFC 9869. Et enfin, cela pourra permettre d'augmenter la taille des paquets DNS comme proposé dans draft-heard-dnsop-udp-opt-large-dns-responses.

La section 6 du RFC spécifie le cahier des charges de ces options UDP :

  • UDP est sans état (sans connexion) et doit le rester.
  • UDP est unidirectionnel et doit le rester. Les protocoles requête/réponse (comme le DNS) sont bâtis sur UDP mais doivent s'occuper de faire correspondre requêtes et réponses sans l'aide d'UDP.
  • Les options UDP n'ont pas de taille maximale (à part celle du paquet UDP lui-même, 65 536 octets).
  • Les options UDP ne visent pas à remplacer des protocoles existants. Le « ping UDP » ne cherche pas à être équivalent au ping utilisant ICMP. Après tout, UDP est fait pour être minimal, et il doit le rester.
  • Les options UDP ne constituent pas un protocole à elles seules : un protocole situé au-dessus d'UDP va devoir spécifier bien des détails (par exemple le RFC 9869 qui décrit le protocole PLPMTUD).
  • Tout le mécanisme est conçu pour qu'un logiciel ancien, qui ne connaisse pas ces options, fonctionne comme aujourd'hui.

Un peu de terminologie avant d'attaquer les détails, notamment (section 3) :

  • Option sûre (SAFE option) : option qui pourra être ignorée par un receveur qui ne la comprend pas. Elle ne modifie pas la compréhension du paquet.
  • Option non sûre (UNSAFE option) : option qui ne doit pas être ignorée, car elle modifie la compréhension du paquet (par exemple car elle indique qu'il est chiffré).

La description technique de l'emplacement des options figure en section 7 du RFC. Le champ Longueur de l'en-tête UDP, qui a toujours été redondant avec celui d'IP, peut désormais prendre une valeur inférieure à celle du champ dans IP (mais supérieure à huit, la taille de l'en-tête UDP). La différence entre les deux longueurs est la taille du surplus, la zone à la fin du paquet où se logent les options (qui ne sont donc pas dans l'en-être mais dans le pied). Notez qu'il n'y a pas d'obligation que le surplus soit aligné sur des multiples (2 ou 4) d'octets. Si les longueurs IP et UDP sont identiques, c'est qu'il n'y a pas d'options.

La structuration du surplus en options est dans la section 8. Le surplus commence avec un champ de deux octets qui est une somme de contrôle. Cet OCS (Option CheckSum) est une somme de contrôle Internet traditionnelle (RFC 791, section 3.1, et RFC 1071). Pourquoi cette somme de contrôle alors qu'UDP en a déjà une ? Pour détecter les cas où un autre mécanisme jouerait avec la différence des champs Longueur d'IP et d'UDP et aurait son propre pied, distinct de celui normalisé dans notre RFC. Simple somme de contrôle, l'OCS ne joue pas un rôle en sécurité, il ne sert qu'à vérifier que le surplus est bien utilisé conformément à la norme sur les options UDP. (Les options sont ignorées si l'OCS n'est pas correcte, voir la section 14.) La section 18 insiste sur ce point : comme cette distinction entre deux champs Longueur est ancienne, il est possible que certains s'en servaient et il faut donc faire face à la possibilité que des paquets UDP aient des champs Longueur différents sans pour autant avoir des options telles que normalisées ici. L'OCS est donc aussi une sorte de nombre magique mais en plus fort, puisqu'il n'est pas statique.

Comme toujours, il faut prévoir le cas de middleboxes boguées qui calculeraient la somme de contrôle UDP sur tout le paquet IP, au lieu de s'arrêter à la longueur indiquée dans l'en-tête UDP. L'OCS est conçu pour annuler l'effet d'une telle bogue (merveille des sommes de contrôle, qui n'ont pas de dispersion des résultats). La somme de contrôle UDP étant optionnelle (mais c'est évidemment très déconseillé), l'OCS l'est aussi (et peut donc valoir zéro). Rappelez-vous que ce qui marchait avant en UDP doit encore marcher avec les options donc, par défaut, même si l'OCS est incorrect, le paquet doit être transmis aux applications réceptrices.

À propos de middleboxes, le RFC précise aussi (section 16) que les options sont de bout en bout et ne doivent pas être modifiées par les équipements intermédiaires (mais cela risque de rester un vœu pieux). Des tests effectués ont montré que des systèmes d'exploitation courants (Linux, macOS, Windows) n'avaient pas de problème en recevant des paquets UDP contenant des options (section 18). Ils n'envoient à l'application que la partie du paquet indiquée par le champ Longueur d'UDP, et ignorent donc les options, qu'on peut donc envoyer sans craindre de perturber les systèmes pré-existants. Toutefois, au moins un objet connecté (non nommé par le RFC) passe tout le datagramme (y compris, donc, le surplus contenant les options) à l'application. Et au moins un IDS, l'Alcatel-Lucent Brick considère les paquets UDP ayant des options comme des attaques (les IDS sont un des facteurs importants de l'ossification de l'Internet car ils interprètent tout ce qui ne colle pas à leur vision étroite comme une attaque).

Les options suivent la somme de contrôle et la plupart sont encodées selon un classique schéma TLV, comme pour la plupart des options TCP (RFC 9293, section 3.1). Les deux exceptions à cet encodage TLV sont les options NOP (un seul octet, qui vaut un, cette option, comme son nom l'indique, ne sert à rien, à part éventuellement à aligner les données) et EOL (End Of Options, un seul octet, qui vaut zéro, elle indique la fin de la liste d'options). Autrement, les options sont en TLV, le premier octet indiquant le type, la longueur faisant un octet (un mécanisme existe pour des options faisant plus de 255 octets). Les options sûres ont un type de 0 à 191, les autres sont non sûres. Parmi les options sûres enregistrées par notre RFC, outre EOL et NOP, on trouve entre autres (section 11) :

  • APC (Additional Payload Checksum), type 2, qui ajoute une somme de contrôle plus forte (CRC32c, la même que celle utilisée dans iSCSI, RFC 3385 et SCTP).
  • FRAG (Fragmentation), type 3, qui permet une fragmentation au niveau UDP. Peut se combiner avec MDS (Maximum Datagram Size, type 4), qui indique la taille maximale qu'un récepteur peut accepter sans que le datagramme soit fragmenté.
  • REQ (Echo Request, type 6) et RES (Echo Response, type 7) permettent de faire un « ping UDP ». (Plus propre que les trucs abusivement baptisés « ping UDP » comme cet exemple ou celui-ci.)
  • TIME, type 8, permet d'envoyer et de recevoir l'heure, sous forme d'une estampille temporelle de quatre octets. C'est l'analogue de l'option TCP Timestamp (RFC 7323, section 3). UDP ne garantit pas que ces estampilles correspondent à l'heure officielle, juste qu'elles seront monotones (toujours croissantes).
  • AUTH (Authentication), n'est pas réellement spécifiée. Son type, 9, est réservé mais les autres points sont repoussés à un futur RFC, peut-être à partir de l'Internet-Draft draft-touch-tsvwg-udp-auth-opt.

Les options EOL, NOP et quelques autres doivent normalement être reconnues par toutes les mises en œuvres des options UDP (cf. section 14).

Et les options non sûres ? Rappelons que ce sont celles qui modifient l'interprétation du contenu du paquet. On y trouve (section 12 du RFC) entre autres :

  • UCMP (Unsafe Compression), type 192, pour des contenus comprimés.
  • UENC (Unsafe Encryption), type 193, pour des contenus chiffrés.

Ces deux options ne sont pas autrement spécifiées, seul un type est réservé. Le reste devra être précisé dans un RFC ultérieur.

De nouvelles options seront peut-être rajoutées dans le futur au registre des options (section 13 du RFC). La politique IANA (section 26) est « action de normalisation » ou « approbation par l'IESG », donc des procédures assez lourdes (RFC 8126) : il ne sera pas facile d'ajouter des options.

Question mise en œuvre, ce n'est pas forcément trivial à faire soi-même. Pour pouvoir lire et à plus forte raison écrire des options UDP, il faut actuellement court-circuiter UDP et écrire directement au-dessus d'IP (raw sockets) ou pire, dans certains cas, directement sur le réseau. Notre RFC propose des extensions à l'API socket pour lire et écrire les options (avec aussi des variables sysctl) mais je ne connais pas encore de système d'exploitation qui les intègre. Notez que ces API ne permettent pas d'influencer l'ordre des options, et c'est exprès.

Une difficulté supplémentaire vient du fait qu'UDP est sans état, sans connexion. D'une part, les options ne peuvent pas être négociées lors de l'établissement de la connexion (puisqu'il n'y a pas de connexion), d'autre part, elles doivent être répétées dans chaque paquet (puisqu'il n'y a pas d'état). Le RFC précise donc (section 19) qu'il faut ignorer les options qu'on ne connait pas (du moins celles marquées comme sûres). D'autre part il impose qu'on passe les données à l'application même si on ne comprend pas les options. Ah, et aussi, les options UDP sont conçues pour l'unicast essentiellement.

Et leurs conséquences pour la sécurité (section 25 du RFC) ? Fondamentalement, les options UDP ne posent pas plus (ou pas moins…) de problèmes de sécurité que les options TCP, qui sont normalisées depuis longtemps. Comme pour TCP, elles ne sont pas sécurisées par TLS (ici, DTLS, RFC 9147), TLS qui protège uniquement les données applicatives. Si vous voulez les protéger, il faudra attendre la spécification des futures options AUTH (qui fournira à peu près le même service que le AO de TCP, normalisé dans le RFC 5925) et UENC. Ou alors, protégez toute la couche transport avec IPsec (RFC 4301).

Mais il y a un autre danger, dans la façon dont vont être traitées les options UDP par le récepteur. Si celui-ci boucle imprudemment, en attendant juste l'option EOL, le risque de débordement est élevé. Ou si le récepteur alloue de la mémoire en utilisant le champ Longueur d'UDP puis y copie tout le paquet, les options faisant alors déborder son tampon.

Voilà, je n'ai pas tout détaillé, la section 25 est longue, lisez-la.

Un petit point d'histoire (section 4) : pourquoi diable UDP a-t-il ce champ Longueur, alors que celui d'IP suffisait, d'autant plus que l'en-tête UDP est de taille fixe ? Aucun autre protocole de transport ne fait cela (à part peut-être Teredo, RFC 6081). Le RFC note que des historiens de l'Internet ont été consultés mais sans résultat. Les raisons de ce choix (qu'on apprécie aujourd'hui mais qui est resté sans utilité pratique pendant 45 ans) restent mystérieuses. Permettre de placer plusieurs paquets UDP dans un seul datagramme IP ? Pour remplir les paquets de manière à ce qu'ils soient alignés sur des multiples d'octets ? Aucune explication ne semble satisfaisante et les archives sont muettes.

Notez aussi que d'autres propositions avaient été faites pour ajouter des options à UDP, comme celle décrite dans l'Internet Draft draft-hildebrand-spud-prototype.

Autre question que vous vous posez peut-être : et UDP-Lite (RFC 3828) ? Lui aussi jouait avec la différence des champs Longueur d'IP et d'UDP, pour indiquer la partie du paquet couverte par la somme de contrôle. De ce fait, le mécanisme d'options ne peut pas être utilisé pour UDP-Lite (section 17).

Et les mises en œuvre concrètes ? Il n'existe pas, à ma connaissance, de serveurs de test publics sur l'Internet. Mais vous avez une liste des programmes existants (je n'en ai pas vu en Python utilisant Scapy, ce qui serait pourtant une expérience intéressante).

D'autres lectures sur ces options UDP ? Vous avez l'article de Raffaele Zullo et les supports d'un de ses exposés, qui expliquent bien la question. Et, sinon ChatGPT, consulté s'en ne s'en est pas trop mal tiré, inventant un mécanisme qui ressemble à celui de TCP.


Téléchargez le RFC 9868


L'article seul

RFC 9861: KangarooTwelve and TurboSHAKE

Date de publication du RFC : Octobre 2025
Auteur(s) du RFC : B. Viguier (ABN AMRO Bank), D. Wong (zkSecurity), G. Van Assche (STMicroelectronics), Q. Dang (NIST), J. Daemen (Radboud University)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF cfrg
Première rédaction de cet article le 13 octobre 2025


Vous trouvez qu'il n'y a pas assez d'algorithmes en cryptographie ? En voici quatre de plus, ici pour condenser cryptographiquement des données, plus rapidement que les algorithmes existants.

Il s'agit de quatre fonctions, TurboSHAKE128 et TurboSHAKE256 (variantes de TurboSHAKE) ainsi que de KT128 et KT256 (variantes de Kangaroo Twelve qui est décrit dans cet article). Toutes sont des XOF (eXtendable Output Function), des fonctions dont le résultat peut être infiniment long (comme ce que produit un générateur pseudo-aléatoire), mais qu'on tronque à la valeur souhaitée (cf. section 2.1). Kangaroo Twelve (section 3) est bâti sur TurboSHAKE et apporte le parallélisme : il permet de répartir le travail sur plusieurs processeurs alors que SHA-3 et TurboSHAKE sont strictement séquentiels. TurboSHAKE (section 2), lui, est bâti sur Keccak (qui est aussi la base de SHA-3, la cryptographie, c'est compliqué). D'ailleurs, le logiciel qui met en œuvre les algorithmes de ce RFC est développé par l'équipe de Keccak.

Ne comptez pas sur moi pour des explications cryptographiques détaillées, je n'y connais rien, lisez les sections 2 et 3 du RFC. Mais Sakura, le système utilisé par Kangaroo Twelve pour répartir le travail semble intéressant (cf. l'article original).

En section 4 du RFC, vous trouverez comment utiliser Kangaroo Twelve pour faire un MAC (on condense le message puis on condense la concaténation de la clé et du résultat de la première condensation).

Et si vous voulez mettre en œuvre Kangaroo Twelve vous-même, la section 5 vous offre de nombreux vecteurs de test. Mais, avant, regardez l'annexe A qui vous offre du pseudo-code et rappelle qu'il y a une implémentation en C, XKCP (par l'équipe Keccak) et une en Python, décrite dans l'article «  KangarooTwelve: fast hashing based on Keccak-p » (les vecteurs de test du RFC viennent de là, normal, ce sont les mêmes auteurs). Enfin, une troisième est en Zig. Commençons en Python (j'ai fait une copie du code de l'article dans kangarootwelve.py et le programme de test est test-kangarootwelve.py). Si on prend ce vecteur de test dans le RFC :

  
      KT128(M=ptn(17 bytes), C=`00`^0, 32):
       `6B F7 5F A2 23 91 98 DB 47 72 E3 64 78 F8 E1 9B
        0F 37 12 05 F6 A9 A9 3A 27 3F 51 DF 37 12 28 88`

Le programme affiche :

% python test-kangarootwelve.py
6b f7 5f a2 23 91 98 db 47 72 e3 64 78 f8 e1 9b 0f 37 12 05 f6 a9 a9 3a 27 3f 51 df 37 12 28 88 

Ce qui est bien la bonne valeur.

Et avec XKCP, compilons la bibliothèque et le programme de test test-kangarootwelve.c :

git submodule update --init
make generic64/libXKCP.so
gcc -I ./bin/generic64/libXKCP.so.headers  -L ./bin/generic64   test-kangarootwelve.c -lXKCP
# ou
# gcc -I ./bin/generic64/libXKCP.so.headers test-kangarootwelve.c ./bin/generic64/libXKCP.so
LD_LIBRARY_PATH=./bin/generic64 ./a.out 
  

Et le programme affiche bien le vecteur de test indiqué dans le RFC.

Kangaroo Twelve a été ajouté au registre IANA, et les quatre algorithmes sont dans le registre de COSE (RFC 8152).


Téléchargez le RFC 9861


L'article seul

RFC 9859: Generalized DNS Notifications

Date de publication du RFC : Septembre 2025
Auteur(s) du RFC : J. Stenstam (The Swedish Internet Foundation), P. Thomassen (deSEC, Secure Systems Engineering), J. Levine (Standcore LLC)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 5 octobre 2025


Vous le savez, le protocole DNS permet plusieurs sortes de messages, identifiés par un code d'opération. Si le classique QUERY, pour demander à résoudre un nom en informations pratiques, est le plus connu, il y a aussi le UPDATE (modifier les données), le DSO (DNS Stateful Operations) et quelques autres. Et puis il y a le NOTIFY, qui sert à indiquer à un serveur DNS qu'il y a quelque chose de nouveau et d'intéressant. NOTIFY est surtout connu pour son utilisation afin de… notifier un serveur secondaire que le primaire a une nouvelle version de la zone (c'est dans le RFC 1996). Ce nouveau RFC généralise le concept et permet d'utiliser NOTIFY pour d'autres choses comme un changement dans la liste des serveurs faisant autorité ou un changement de clé DNSSEC.

Si vous avez oublié à quoi servait initialement NOTIFY, relisez le RFC 1996. Il permettait de donner une indication (uniquement une indication, le NOTIFY ne fait pas autorité) comme quoi il faudrait envisager un nouveau transfert de zone (RFC 5936) pour mettre à jour un serveur. Cela permettait des mises à jour plus rapides qu'avec le système traditionnel où chaque serveur esclave devait de temps en temps demander à son maître s'il y avait du nouveau. Mais il y a d'autres cas où un serveur DNS voudrait dire à un autre qu'il y a quelque chose à regarder, par exemple si une nouvelle clé doit être utilisée. D'où l'extension d'utilisation que permet notre RFC 9859. Elle ne change pas le protocole, elle se contente d'utiliser plus largement une fonction existante.

Bon, mais c'est bien joli de dire qu'on peut notifier pour bien des choses mais on notifie qui ? Dans le cas traditionnel d'une nouvelle version de la zone, le primaire savait qu'il devait notifier ses secondaires, qu'il connait (après tout, il doit leur autoriser le transfert de zone et, dans le pire des cas, il peut toujours regarder l'ensemble d'enregistrements NS de sa zone). Mais si on généralise le NOTIFY, on peut ne pas savoir qui notifier (les autres mécanismes de notification, comme une API ou comme la mise à jour dynamique du RFC 2136, ont d'ailleurs le même problème). La section 3 du RFC couvre ce problème. La méthode recommandée est de publier un enregistrement de type DSYNC, normalisé dans notre RFC, section 2. Il se place sous le nom _dsync de la zone :

sousdomaine._dsync  IN DSYNC  CDS   NOTIFY 5359 cds-scanner.example.net.
  

Notez qu'un joker est possible, par exemple :

*._dsync  IN DSYNC  CDS   NOTIFY 5359 cds-scanner.example.net.
*._dsync  IN DSYNC  CSYNC NOTIFY 5359 cds-scanner.example.net.
  

Ce nom _dsync a été ajouté dans le registre des noms précédés d'un trait bas (RFC 8552). Voici un autre exemple d'enregistrement DSYNC :

_dsync.example.net.   IN DSYNC  CDS   NOTIFY 5359 cds-scanner.example.net.
  

Que dit-il ? Qu'example.net, a priori un hébergeur DNS, voudrait que ses clients, lorsqu'ils ont un nouvel enregistrement CDS (indiquant l'activation d'une nouvelle clé DNSSEC, cf. RFC 8078), notifient cds-scanner.example.net sur le port 5359. Ce nouveau type DSYNC a été ajouté au registre des types, avec la valeur 66.

La section 4.1 détaille comment on trouve le serveur à qui envoyer la notification en utilisant _dsync. Imaginons qu'on gère extra.sub.exodus-privacy.eu.org et qu'on veuille notifier la zone parente. On insère le composant _dsync après le premier composant (cela donne extra._dsync.sub.exodus-privacy.eu.org) et on fait une requête pour ce nom et le type DSYNC. Si ça marche, c'est bon, sinon, on utilise le SOA dans la réponse pour trouver la zone parente, et on met le _dsync devant. Si ça ne donne toujours rien, on retire les composants avant la zone parente et on recommence. Donc, on interrogera successivement (jusqu'au premier succès), extra._dsync.sub.exodus-privacy.eu.org, extra.sub._dsync.exodus-privacy.eu.org et _dsync.exodus-privacy.eu.org.

Et le NOTIFY dans l'enregistrement DSYNC d'exemple plus haut ? C'est le plan (scheme, à ne pas confondre avec le code d'opération - opcode - NOTIFY) car DSYNC, dans le futur, pourra servir à autre chose que les notifications. Pour l'instant, dans le nouveau registre des plans, il n'y a que NOTIFY mais dans le futur, d'autres pourront être ajoutés (suivant la politique « Examen par un expert » du RFC 8126).

Comment utiliser ce mécanisme de notification généralisé pour traiter les enregistrements CDS et CDNSKEY des RFC 7344, RFC 8078 et RFC 9615 ? Ces enregistrements servent à signaler à la zone parente la disponibilité de nouvelles clés DNSSEC. La section 4 de notre RFC détaille comment le mécanisme de notification permet d'indiquer qu'un CDS ou un CDNSKEY a changé. Cela évite au gestionnaire de la zone parente de balayer toute la zone ce qui, pour un TLD de plusieurs millions de noms comme .fr serait long et pénible. La solution de ce RFC 9859 est donc de chercher les DSYNC puis d'envoyer les NOTIFY, au moins deux, un pour le type CDS et un pour le type CDNSKEY (on ne sait pas forcément à l'avance lesquels utilisent la zone parente). La zone parente doit effectuer les mêmes vérifications que lorsqu'elle a détecté un nouveau CDS (ou CDNSKEY) : RFC 9615 si on active une zone signée pour la première fois et RFC 7344 et RFC 8078 autrement.

Les messages utilisant le code d'opération NOTIFY sont censés produire une réponse (RFC 1996, section 4.7). Si aucune réponse n'arrive avant l'expiration du délai de garde, on réessaie. Si on a trop réessayé, on peut signaler le problème avec la technique du RFC 9567.

Il est important de se souvenir qu'une notification n'est pas sérieusement authentifiée, et que le récepteur doit donc, s'il choisit d'agir sur une notification, être prudent. Dans le RFC 1996, rien de grave ne pouvait arriver, le récepteur du NOTIFY demandait juste le SOA de la zone puis, si nécessaire, un transfert de zone. Mais avec les CDS et CDNSKEY, des attaques plus sérieuses sont possibles et le destinataire de la notification doit donc effectuer davantage de vérifications (par exemple, si la zone est déjà signée, faire une requête pour le CDS ou le CDNSKEY et vérifier que la réponse est valide et sécurisée, si elle ne l'est pas, faire tous les contrôles du RFC 9615). La notification elle-même n'est pas un problème de sécurité (elle dit juste « tu devrais regarder cela »), c'est l'action qui en résulte qui doit être bien réfléchie. Voilà pourquoi les notifications, même généralisées, ne sont pas plus sécurisées que cela. (Voir aussi la section 5 du RFC, qui insiste sur ce point ; la notification peut accélérer les choses mais ne doit pas à elle-même changer quelque chose.) Il est quand même préférable de limiter le nombre de notifications qu'on traite, au cas où un client malveillant vous bombarde de notifications.

Ces notifications généralisées pourront aussi s'utiliser pour les CSYNC du RFC 7477.

Qui met en œuvre ce RFC à l'heure actuelle ? Des opérateurs comme deSEC ont annoncé que c'était en cours, côté client. Côté serveur, les registres de .ch et .se ont annoncé que c'était en cours, ou bien prévu.

Voici un exemple d'un client en Python (utilisant dnspython) qui notifie pour un nouveau CDS :

import dns.message
import dns.query    
import dns.opcode

notify = dns.message.make_query("bortzmeyer.fr", "CDS")
notify.set_opcode(dns.opcode.NOTIFY)
response = dns.query.udp(notify, "192.0.2.211")
print(response)
  

Et en C ? Vous pouvez utiliser le programme d'exemple generalized-notify.c, qui utilise l'excellente bibliothèque ldns. Compiler et exécuter :

% gcc -o generalized-notify -Wall generalized-notify.c -lldns 

% ./generalized-notify bortzmeyer.fr 192.0.2.211
Reply code: NOERROR
  

Je note à ce sujet que certains serveurs faisant autorité, lorsqu'ils ne font pas autorité pour le domaine signalé, répondent REFUSED, ce qui est logique, mais on voit aussi des FORMERR ou NXDIOMAIN (!), sans doute parce que le type CDS ne leur plait pas.

L'annexe A du RFC prend de la hauteur et décrit plus en détail le problème du balayage DNS. Comment savoir qu'il y a du nouveau, sans tout examiner (dans le cas du SOA, au rythme indiqué par le champ Refresh ; mais il n'y a pas de telle solution pour les CDS et CDNSKEY). Le DNS traditionnel ne marchait que sur un modèle pull (et c'est pour cela qu'il est faux de parler de propagation DNS) mais les NOTIFY du RFC 1996 introduisaient un peu de push. Heureusement car balayer .com à la recherche de nouveaux enregistrements serait lent (et attirerait probablement l'attention des IDS). Pour les CDS et CDNSKEY, cela serait d'autant plus agaçant qu'ils seront a priori peu nombreux et que la plupart des requêtes ne donneront donc rien.


Téléchargez le RFC 9859


L'article seul

RFC 9844: Entering IPv6 Zone Identifiers in User Interface

Date de publication du RFC : Août 2025
Auteur(s) du RFC : B. Carpenter (Univ. of Auckland), R. Hinden (Check Point Software)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF 6man
Première rédaction de cet article le 17 février 2026


Ce très court RFC normalise la façon d'indiquer la zone quand il faut écrire une adresse IPv6 locale. Il remplace le RFC 6874, et est très différent, notamment parce qu'il ne s'applique plus aux URI.

Les zones sont définies et expliquées dans le RFC 4007. En gros, une adresse IPv6 n'est pas forcément globale, elle peut avoir une signification limitée à une seule zone, une zone étant un ensemble de sous-réseaux contigus, souvent composé d'un seul lien Ethernet. Les adresses locales au lien, par exemple, celles qui sont dans le préfixe fe80::/10, sont dans ce cas, le lien qui les relie forme une zone. Une zone n'a de signification que locale, elle n'a pas de sens sur l'Internet public. Comment préciser la zone dans une interface qui accepte les adresses IPv6 ? La syntaxe de celles-ci est normalisée dans le RFC 4291 et le RFC 5952 mais ne prévoit rien pour la zone. C'est surtout ennuyeux pour les réseaux purement IPv6 (RFC 8925) ou essentiellement IPv6 (draft-ietf-v6ops-6mops). Notre RFC impose donc (section 5) que toute interface qui permet d'indiquer des adresses IP permette également d'indiquer la zone.

Indiquer la zone est utile pour les applications de déboguage (cf. l'exemple avec ping plus loin) ou pour configurer une machine (« ton serveur pour le service XXX est à l'adresse YYY »).

Pour indiquer cette zone, ce RFC normalise l'utilisation d'un %, puis l'identificateur de la zone, après l'adresse. La convention du % est décrite en section 11 du RFC 4007. Si l'interface utilisée pour entrer des adresses IP a un problème spécifique avec le %, le RFC autorise à utiliser le tiret à la place. Et si même cela est impossible, le RFC recommande deux champs, un pour l'adresse seule et un pour la zone. Ici, sur une machine Linux, avec le % :

% ping -c 3 fe80::f437:ded0:7b2:1241%enp1s0 
PING fe80::f437:ded0:7b2:1241%enp1s0 (fe80::f437:ded0:7b2:1241%enp1s0) 56 data bytes
64 bytes from fe80::f437:ded0:7b2:1241%enp1s0: icmp_seq=1 ttl=64 time=68.0 ms
64 bytes from fe80::f437:ded0:7b2:1241%enp1s0: icmp_seq=2 ttl=64 time=13.2 ms
64 bytes from fe80::f437:ded0:7b2:1241%enp1s0: icmp_seq=3 ttl=64 time=15.6 ms

--- fe80::f437:ded0:7b2:1241%enp1s0 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 13.175/32.268/68.015/25.296 ms

On teste la machine fe80::f437:ded0:7b2:1241 reliée au réseau identifié par enp1s0 (dans le cas de Linux, c'est le nom d'une interface réseau mais d'autres systèmes d'exploitation peuvent utiliser une syntaxe différente, par exemple identifier les zones par un simple numéro comme le fait Microsoft Windows).

Notez que ce n'est pas ping qui a reconnu et traité l'indication de la zone mais le sous-programme getaddrinfo (RFC 3493). Autrement, on aurait pu utiliser un bricolage pour se connecter à une adresse lien local via une bibliothèque LD_PRELOAD, où l'application n'a pas besoin de connaitre cette syntaxe. Notez que la fonction inet_pton ne va pas accepter les adresses avec indication de zone, il faut utiliser getaddrinfo ou bien, séparement, inet_pton et if_nametoindex.

Autre exemple d'utilisation, comme indiqué plus haut, la configuration d'un équipement, par exemple pour lui indiquer « ton résolveur DNS est fe80::f437:ded0:7b2:1241%enp1s0 ». Ou bien les filtres utilisés pour ne capturer que le trafic d'une machine. Mais tcpdump (ou Wireshark) ne reconnaissent pas actuellement cette syntaxe :

 % tcpdump -n host fe80::f437:ded0:7b2:1241%enp1s0
tcpdump: can't parse filter expression: syntax error
  

(Pour tcpdump, il faudrait faire tcpdump -n -i enp1s0 host fe80::f437:ded0:7b2:1241.)

Plus pittoresque, le système OneNet Marine IPv6 Ethernet Networking Standard de la NMEA utilise uniquement des adresses locales au lien et doit donc absolument utiliser un mécanisme permettant d'indiquer la zone.

Le RFC ne liste pas les différences avec son prédécesseur RFC 6874 car elles sont trop nombreuses. Le principal changement est certainement l'abandon d'une standardisation des zones dans les URI, qui n'avait jamais vraiment marché (cf. draft-schinazi-httpbis-link-local-uri-bcp).


Téléchargez le RFC 9844


L'article seul

RFC 9824: Compact Denial of Existence in DNSSEC

Date de publication du RFC : Septembre 2025
Auteur(s) du RFC : S. Huque (Salesforce), C. Elmerot (Cloudflare), O. Gudmundsson
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsop
Première rédaction de cet article le 12 décembre 2025


Plus fort que le chat de Schrödinger qui était à la fois mort et vivant, ce RFC permet à un nom de domaine d'être à la fois existant et non-existant. Plus précisément, il permet de fournir une preuve cryptographique avec DNSSEC, prouvant que le nom existe (alors qu'il n'existe pas) mais n'a pas les données demandées. Cette technique (autrefois connue sous le nom de « black lies », et largement déployée) est particulièrement adaptée au cas des signatures générées dynamiquement, mais a l'inconvénient de « mentir » sur l'existence du nom.

Pour comprendre, il faut revenir à un problème agaçant pour DNSSEC : le déni d'existence. Ce terme désigne le fait de prouver qu'un nom, ou qu'un certain type de données pour un nom, n'existe pas. Car DNSSEC fonctionne en signant les données. Mais en cas de non-existence, il n'y a rien à signer. DNSSEC a donc ajouté un type d'enregistrement nommé NSEC qui encadre le nom manquant. Et ces enregistrements, eux, sont signés. Un enregistrement NSEC affirme « ce nom n'existe pas » en donnant le nom précédent et le nom suivant (ici, la réponse d'un serveur racine à qui on a demandé www.trump alors que le TLD .trump n'existe pas) :


;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 65362
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1
…
travelersinsurance.	86400	IN	NSEC	trust. NS DS RRSIG NSEC

On obtient un NXDOMAIN (ce nom n'existe pas), zéro réponse (la section Answer est vide) et l'enregistrement NSEC nous dit qu'il n'y a rien entre travelersinsurance et trust. Comme il est signé (je n'ai pas montré les signatures), nous avons une preuve de non-existence.

Et si le nom existe, mais n'a pas de données du type demandé ? J'interroge mon résolveur sur la localisation associée au nom www.iis.se :


% dig +dnssec www.iis.se LOC
…
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39872
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
…
www.iis.se.		480	IN	NSEC	xmpp01.iis.se. A AAAA RRSIG NSEC
…

  

Le NOERROR est normal (le nom existe) mais la section Answer est vide (puisqu'il n'y a pas d'enregistrement de type LOC) et le NSEC nous dit que le nom existe bien (le nom suivant étant xmpp01.iis.se.) mais n'a comme type d'enregistrement que A, AAAA, RRSIG et NSEC. On a donc prouvé que le LOC n'existe pas.

Bon, tout ça, c'est du DNSSEC classique, tel que normalisé dans les RFC 4034 et RFC 4035. Ça marche, mais cela a des inconvénients, notamment pour les signatures générées dynamiquement. Cela nécessite plusieurs NSEC (il faut aussi montrer qu'il n'y a pas de joker), avec leurs signatures.

CDE (Compact Denial of Existence, alias black lies) fonctionne (section 3 du RFC) en calculant un intervalle minimal entre les noms, comme le faisaient les white lies du RFC 4470. Mais, contrairement à eux, CDE fait partir cet intervalle du nom demandé. Par exemple, si on demande foobar.example et que ce nom n'existe pas, les white lies fabriqueront un NSEC allant de ~.foobaq~.example à foobar!.example alors que les black lies de notre RFC feront un NSEC allant de foobar.example à \000.foobar.example. Cet intervalle démarrant au nom de domaine demandé, il ne faut plus jamais renvoyer de NXDOMAIN, uniquement des NODATA (NOERROR mais avec une section Answer vide).

Voici un exemple de black lie chez Cloudflare (qui a déployé CDE il y a longtemps) :


% dig +dnssec doesnotexistcertainly.cloudflare.com                           
…
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43853
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
…
;; AUTHORITY SECTION:
doesnotexistcertainly.cloudflare.com. 300 IN NSEC \000.doesnotexistcertainly.cloudflare.com. RRSIG NSEC TYPE128
…
;; Query time: 14 msec
;; SERVER: 192.168.2.254#53(192.168.2.254) (UDP)
;; WHEN: Fri Dec 12 14:10:39 CET 2025
;; MSG SIZE  rcvd: 400

  

Mais puisqu'on ne renvoie jamais de NXDOMAIN, comment distinguer un nom qui n'existe pas d'un nom qui n'a simplement pas le type demandé ? La section 2 du RFC présente le type NXNAME (enregistré avec le numéro 128, d'où le TYPE128 ci-dessus). Sa présence dans le NSEC indique que le nom n'existe pas. Comparez la réponse ci-dessus avec celle-ci, où le nom existe, mais pas le type (hex.pm est chez Cloudflare et n'a pas d'adresse IPv6 associée à son nom) :


% dig +dnssec hex.pm AAAA
…
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5431
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
…
hex.pm.			1800	IN	NSEC	\000.hex.pm. A NS SOA HINFO MX TXT LOC SRV NAPTR CERT SSHFP RRSIG NSEC DNSKEY TLSA SMIMEA HIP CDS CDNSKEY OPENPGPKEY SVCB HTTPS URI CAA

  

La longue liste de types dans le NSEC (mais sans le NXNAME/TYPE128) est due au fait que le serveur, qui génère des NSEC (et des signatures) dynamiquement ne connait pas la vraie liste donc il met tout ce qu'il connait.

Un résolveur qui connait les NXNAME peut donc refabriquer un code de retour NXDOMAIN et l'envoyer à ses clients (section 5 du RFC). Un nouveau booléen dans la question envoyée aux serveurs faisant autorité, le CO (Compact Answers OK) peut être utilisé pour dire au serveur faisant autorité qu'il peut répondre avec un NXDOMAIN, le client DNS qui met le CO indique qu'il saura lire et interpréter le NXNAME. (Le CO a été enregistré à l'IANA, le premier booléen d'une requête EDNS à être enregistré depuis DO il y a vingt-quatre ans.) Cette possibilité de rétablissement du NXDOMAIN ne semble pas très souvent mise en œuvre actuellement.

Notez (section 4) qu'on peut utiliser CDE avec NSEC3 mais que cela n'a aucun intérêt, vu que la compacité de l'intervalle des noms empêche déjà l'énumération des noms.

Enfin, si vous aimez les détails, l'annexe A du RFC discute des raisons des choix faits, et des alternatives étudiées (et même testées dans la nature), mais non retenues.

CDE est largement déployé aujourd'hui, notamment chez Cloudflare, déjà cité, mais aussi chez d'autres hébergeurs utilisant la signature dynamique, comme NS1. En logiciel libre, Knot permet le CDE. Il y a aussi une implémentation (mais qui n'a pas été maintenue synchrone avec le RFC) dans mon serveur Drink. Elle fut développée lors d'un hackathon IETF. Elle n'est pas activée par défaut, il faut changer un paramètre dans le source (lib/drink/dnssec.ex).


Téléchargez le RFC 9824


L'article seul

RFC 9816: Usage and Applicability of BGP Link-State Shortest Path Routing (BGP-SPF) in Data Centers

Date de publication du RFC : Juillet 2025
Auteur(s) du RFC : K. Patel (Arrcus), A. Lindem (LabN Consulting), S. Zandi, G. Dawra (Linkedin), J. Dong (Huawei Technologies)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF lsvr
Première rédaction de cet article le 27 janvier 2026


Le RFC 9815 normalise l'utilisation de l'algorithme de routage SPF avec BGP. Dans quels cas est-ce que ça peut s'appliquer à l'intérieur d'un centre de données ? Ce RFC 9816 donne des éléments de réponse.

Il s'agit donc d'un court complément au RFC 9815 pour un cas courant, le centre de données qui suit la topologie décrite par Charles Clos dans son article de 1952, « A study of non-blocking switching networks ». (On trouve aussi cet article sur Sci-Hub ou à divers endroits sur le Web.) Pour que le trafic circule de n'importe quel nœud d'entrée vers n'importe quel nœud de sortie, on peut connecter tous les nœuds d'entrée à tous les nœuds de sortie mais cela fait beaucoup de connexions, qui coûtent cher. Ou bien on peut connecter tous les nœuds d'entrée à un dispositif de commutation qui ira vers tous les nœuds de sortie. Mais le trafic risque d'être bloqué si ce dispositif est surchargé. Dans un réseau Clos, on met des nœuds intermédiaires, avec une connectivité suffisante pour qu'on ne soit pas bloqué dans la plupart des cas. Il y a donc plusieurs chemins possibles d'un bout à l'autre du tissu ainsi formé (ce qui fait qu'un algorithme de routage comme le spanning tree n'est pas optimal puisqu'il ne trouve qu'un seul chemin). Dans un centre de données moderne, il y a en général une épine dorsale formée des commutateurs rapides et, dans chaque baie, un commutateur ToR (Top of Rack, rien à voir avec Tor). Tous les commutateurs ToR sont connectés à l'épine dorsale (liaison dite Nord-Sud, l'épine dorsale étant représentée en haut, le Nord) alors qu'il n'y a pas forcément de liaison entre les commutateurs ToR (liaison dite Est-Ouest).

Dans un centre de données non public (où toutes les machines appartiennent à la même entité), quel protocole de routage utiliser ? A priori, un IGP, non, puisqu'il s'agit de routage interne ? Mais pour diverses raisons, entre autres pour se simplifier la vie avec un seul protocole pour tout, certains utilisent BGP (RFC 7938) et même EBGP (External BGP), où les routeurs sont dans des AS différents (regardez la section 5 du RFC 7938 pour comprendre ce choix). Mais avec EBGP, les sessions BGP correspondent au chemin des données, ce qui empêche d'utiliser des réflecteurs de route. Et puis l'algorithme de routage classique de BGP ne converge pas assez vite en cas de changement, ce qui n'est pas grave sur l'Internet public mais est plus gênant à l'intérieur du centre de données. C'est là que le BGP-SPF du RFC 9815 devient intéressant, en remplaçant l'algorithme de routage traditionnel par SPF.

Utiliser BGP permet aussi de simplifier l'authentification, en se reposant sur les mécanismes existants comme celui du RFC 5925.

Autre avantage, les équipements réseau de ce centre de données aiment bien avoir de l'information détaillée sur la topologie et c'est justement ce que fournit l'extension BGP Link State, normalisée dans le RFC 9552, et dont BGP-SPF dépend. Il n'y a plus qu'à écouter le trafic BGP pour tout apprendre du réseau et bâtir ainsi divers services.

Plusieurs topologies d'appairage sont possibles entre les routeurs, collant à la topologie physique ou bien s'en écartant. Les routeurs peuvent utiliser BFD (RFC 5880) pour vérifier en permanence qu'ils arrivent bien à se joindre.

Même si le vieux protocole IPv4 est présent, on peut ne s'appairer qu'en IPv6 (cf. le RFC 8950) voire qu'avec des adresses locales (RFC 7404).

Et si un routeur veut jouer à BGP avec les autres routeurs mais sans être utilisé pour transmettre des paquets ? (Par exemple parce qu'il héberge des services applicatifs qui doivent être joignables.) Le TLV SPF status (RFC 9815, section 5.2.1.1) sert à cela : s'il est présent, avec une valeur de 2, le nœud ne sera pas utilisé pour le transit des paquets.


Téléchargez le RFC 9816


L'article seul

RFC 9815: BGP Link-State Shortest Path First (SPF) Routing

Date de publication du RFC : Juillet 2025
Auteur(s) du RFC : K. Patel (Arrcus), A. Lindem (LabN Consulting), S. Zandi (LinkedIn), W. Henderickx (Nokia)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF lsvr
Première rédaction de cet article le 27 janvier 2026


Vous le savez (peut-être), le protocole de routage BGP est du type « vecteur de chemin ». Mais il peut aussi transporter des états des liens, si on souhaite faire des choses plus proches des protocoles à état des liens. Ce RFC décrit comment, avec ces informations sur l'état des liens, décider du routage par l'algorithme SPF (Shortest Path First) plutôt que par la méthode traditionnelle de BGP.

Pour simplifier, un protocole à état des liens (comme OSPF ou IS-IS) permet à chaque routeur d'avoir l'état complet du réseau, et donc de faire tourner des algorithmes comme SPF, qui nécessite justement cette connaissance totale. Par contre, un protocole à vecteur de distance comme RIP ou à vecteur de chemin comme BGP n'a pas besoin de cette information et consomme donc moins de mémoire (pour BGP, stocker l'état de tous les liens de l'Internet serait évidemment impossible). Mais le protocole doit développer des mécanismes pour éviter, par exemple, les boucles de routage, qui pourraient arriver puisque chaque routeur décide sur la base d'une information incomplète.

Les deux types de protocole ont des avantages et des inconvénients et il est donc tentant de les combiner. Le RFC 9552 normalise justement un moyen de transporter l'état des liens avec BGP. Cela permet des prises de décision plus « intelligentes », comme dans le cas du RFC 9107 pour un réflecteur ou du RFC 7971 pour le mécanisme de décision ALTO. Pour transporter cet état, le RFC 9552 normalise un AFI (Address Family Identifier, RFC 4760, section 3) et un SAFI (Sub-address Family Identifier, même référence). Ce sont l'AFI 16388 et le SAFI 71. Ce BGP-LS (Border Gateway Protocol - Link State) sert de base à ce nouveau RFC, qui décrit une des manières d'utiliser cette information sur l'état des liens. (Cette technique a plusieurs années mais le développement du RFC a été long.)

Beaucoup de gros centres de données utilisent en interne BGP (RFC 4271) pour distribuer l'information de routage, car la densité des équipements créerait trop de trafic, avec les protocoles plus bavards comme OSPF (c'est documenté dans le RFC 7938 et RFC 9816). (Ces gros centres sont parfois appelés MSDC pour Massively Scaled Data Centers.) En outre, BGP repose sur TCP, ce qui élimine les problèmes de gestion des paquets perdus qu'ont les IGP traditionnels. Et puis cela permet de n'utiliser qu'un seul protocole comme IGP et EGP. Il ne restait qu'à étendre BGP pour pouvoir utiliser l'algorithme SPF de certains IGP, ce que fait notre RFC. Le principal avantage (section 1.2 du RFC) de cet ajout est que tous les routeurs auront désormais une vue complète de tout le réseau, sans qu'il y ait besoin de multiplier les sessions BGP. C'est utile pour des services comme ECMP, le calcul à l'avance de routes de secours (RFC 5286), etc.

Un peu de terminologie s'impose pour suivre ce RFC (section 1.1) :

  • Domaine de routage BGP SPF : un ensemble de routeurs sous la même administration (cf. section 10.1) qui échangent de l'information sur l'état des liens via BGP, et calculent la table de routage avec SPF.
  • NLRI (Network Layer Reachability Information) BGP-LS-SPF (LS = Link State, état des liens) : les NLRI (RFC 4271, section 3.1) sont les données envoyées dans les messages BGP. Ce type particulier de NLRI sert à transmettre les informations sur l'état des liens. Il a le numéro 80 et est encodé exactement comme le NLRI BGP-LS (tout court) du RFC 9552.
  • Algorithme de Dijkstra : un autre nom de SPF (Shortest Path First), la grande nouveauté de notre RFC.

Bon, maintenant, le protocole lui-même. C'est bien sûr le bon vieux BGP du RFC 4271, avec l'extension LS du RFC 9552 et « juste » en plus l'utilisation de SPF pour le mécanisme de décision (« quelle route choisir ? »). Autrement, le RFC insiste, c'est du BGP normal, avec son automate, son format de paquets, ses signalements d'erreurs (RFC 7606), etc. Du fait du nouveau mécanisme de décision, les attributs optionnels des chemins annoncés n'ont pas à être transmis (les attributs obligatoires, comme leur nom l'indique, sont toujours transmis, même si SPF ne les utilise pas). Comme le calcul des routes se fait sur la base de l'information sur l'état des liens, un routeur BGP-LS-SPF n'attend pas d'avoir fait son calcul local avant de transmettre une annonce, il envoie tout (section 2). Le traditionnel mécanisme de décision de BGP (celui de la section 9.1 du RFC 4271) disparait et est remplacé par celui décrit en section 6. Cela implique, entre autres, que le chemin d'AS n'est plus utilisé pour empêcher les boucles.

On l'a dit, BGP-LS-SPF s'appuie sur le BGP-LS du RFC 9552 mais, avec un nouveau SAFI (Subsequent Address Family Identifier), le 80, puisque le SAFI du RFC 9552 supposait le processus de décision traditionnel de BGP (SPF ne doit être utilisé qu'avec les informations obtenues via les NLRI BGP-LS-SPF, cf. section 5.1). Par contre, les autres paramètres de BGP-LS sont utilisés tels quels (section 5.1.1). Il y a aussi des ajouts, par exemple pour indiquer qu'un lien ou un préfixe doit être considéré comme inutilisable par BGP-LS-SPF.

Les messages peuvent être gros, vu qu'on doit transporter l'information au sujet de tout le domaine de routage. Il est donc recommandé de mettre en œuvre le RFC 8654, qui permet d'avoir des messages BGP de plus de 4 096 octets.

La section 4 du RFC explique comment s'appairer pour échanger des informations sur les états des liens. En gros, rien de spécial, appairage direct ou passage par un réflecteur (RFC 4456) sont possibles comme avant.


Téléchargez le RFC 9815


L'article seul

RFC 9803: Extensible Provisioning Protocol (EPP) mapping for DNS Time-To-Live (TTL) values

Date de publication du RFC : Juin 2025
Auteur(s) du RFC : G. Brown (ICANN)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF regext
Première rédaction de cet article le 14 juin 2025


Traditionnellement, les registres de noms de domaine publiaient toutes les informations des sous-domaines avec la même durée de vie maximale (TTL : Time To Live). Certain·es client·es demandent à pouvoir choisir un TTL plus court (ou, parfois, plus long) et ce RFC décrit comment faire cela avec le protocole EPP.

Cet EPP, normalisé dans les RFC 5730 et suivants, est aujourd'hui le plus utilisé par les gros registres pour recevoir les commandes de leurs BE. (Cf. cet article de l'Afnic.) Tel que normalisé dans le RFC 5731, EPP ne permet pas, lors de la création d'un nom de domaine, de spécifier le TTL des enregistrements NS (NameServer) qui seront publiés. Prenons l'exemple de l'enregistrement d'un .fr. Le ou la titulaire va sur l'interface Web de son BE, réserve le nom cyberstructure.fr, le BE transmet la demande de création en utilisant EPP et le registre publie ensuite dans le DNS les informations de délégation, ici récupérées avec dig :

% dig @d.nic.fr cyberstructure.fr NS    
…
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 9, ADDITIONAL: 1
…
;; AUTHORITY SECTION:
cyberstructure.fr.	3600 IN	NS puck.nether.net.
cyberstructure.fr.	3600 IN	NS fns2.42.pl.
cyberstructure.fr.	3600 IN	NS ns2.bortzmeyer.org.
cyberstructure.fr.	3600 IN	NS ns4.bortzmeyer.org.
cyberstructure.fr.	3600 IN	NS ns2.afraid.org.
cyberstructure.fr.	3600 IN	NS fns1.42.pl.
cyberstructure.fr.	3600 IN	NS ns1.bortzmeyer.org.
…
  

À aucun moment, la·e titulaire ou le BE n'a spécifié de TTL (les 3 600 secondes), il a été choisi par le registre seul. Certain·es titulaires peuvent pourtant avoir des préférences différentes. (Je rappelle que la notion de TTL est définie rigoureusement dans le RFC de terminologie DNS, le RFC 9499, voir sa section 5.)

Si vous voulez creuser ce concept de délégation, l'article de l'Afnic sur DELEG l'explique dans sa première partie.

L'exemple ci-dessus montrait les enregistrements NS (NameServer) mais ce problème concerne aussi les DS (RFC 9364), la colle et les éventuels DNAME (par exemple pour mettre en œuvre le RFC 6927).

Ce RFC normalise une extension à EPP pour permettre au client (le BE) d'indiquer le TTL souhaité pour la délégation. (Ce qui ne signifie pas que le registre satisfera ce souhait, lisez plus loin.) Plus précisément, il étend les classes (mappings) EPP pour les noms de domaine (RFC 5731) et pour les serveurs de noms (RFC 5732), les seules classes dont les données se retrouveront dans le DNS (rappelez-vous qu'EPP n'est pas limité aux noms de domaine, c'est un protocole d'avitaillement générique).

La section 1.2 du RFC contient les informations essentielles. D'abord, l'espace de noms urn:ietf:params:xml:ns:epp:ttl-1.0 (enregistré à l'IANA), qui identifie cette extension (le RFC utilise l'alias ttl mais rappelez-vous qu'en XML, c'est l'espace de noms qui compte, l'alias est choisi par l'auteur du document XML). Ensuite, l'élément <ttl:ttl> (donc, en complet, {urn:ietf:params:xml:ns:epp:ttl-1.0}ttl), qui peut être ajouté aux demandes EPP ou aux réponses. Parmi ses attributs :

  • for (le seul qui soit obligatoire) indique le type de données DNS auxquelles l'élément s'applique (uniquement des types qui jouent un rôle dans la délégation, NS, DS, DNAME, A et AAAA, ainsi que la valeur spéciale custom, qu'il faut compléter avec un attribut custom qui suit l'expression rationnelle de la section 3.1 du RFC 6895, et évidemment utilise un type enregistré),
  • min (uniquement dans les réponses) qui indique la valeur minimale que le serveur (donc le registre) accepte (le registre est toujours libre de sa politique et peut refuser une valeur trop basse ou trop haute, répondant avec le code d'erreur EPP 2004, Parameter value range error),
  • max, la contrepartie de min, avec les mêmes propriétés,
  • default, qu'on ne trouve également que dans les réponses, et qui permet de connaitre la valeur qu'utiliserait le serveur si le client ne demande rien de spécifique.

L'élément <ttl:ttl> a pour contenu une valeur en secondes. Si cette valeur est vide, le serveur prendra la valeur par défaut (mais autant ne pas mettre d'élément <ttl:ttl> dans ce cas).

L'extension de ce RFC décrit des possibilités mais le registre, qui gère le serveur EPP, reste libre de ne pas tout accepter. Par exemple, il peut refuser l'utilisation de l'attribut custom, ou bien la restreindre à certains types (et, si le client demande quand même, répondre avec le code d'erreur EPP 2306 Parameter value policy error). Les types qui ont une syntaxe privilégiée (pas besoin de l'attribut XML custom) sont ceux qu'on peut actuellement trouver au-dessus de la coupure de zone (section 7 du RFC 9499).

Vous avez noté que, dans les types qui ont une syntaxe privilégiée dans ce RFC, il y a les types pour les adresses IP. Ils sont utilisés pour la colle DNS (section 7 du RFC 9499), si le serveur EPP met en œuvre la classe EPP pour les serveurs de noms (RFC 5732).

Un deuxième élément XML est spécifié par ce RFC, <ttl:info>, qui sert à demander ou à indiquer des informations sur la politique du serveur (voir des exemples plus loin).

La section 2 décrit dans quelles commandes EPP on peut ajouter les nouveaux éléments. Je ne vais pas toutes les détailler, juste montrer quelques exemples du XML envoyé et des réponses. Ainsi, ici, le client va utiliser la commande <epp:info> pour se renseigner sur la politique du serveur :


…
   C:     <info>
   C:       <domain:info
   C:        xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
   C:         <domain:name>example.com</domain:name>
   C:       </domain:info>
   C:     </info>
   C:     <extension>
   C:       <ttl:info
   C:         xmlns:ttl="urn:ietf:params:xml:ns:epp:ttl-1.0"
   C:         policy="false"/>
   C:     </extension>
   …

  

Et la réponse du serveur :


…
   S:   <response>
   S:     <result code="1000">
   S:       <msg>Command completed successfully</msg>
   S:     </result>
   S:     <resData>
…
   S:         <domain:name>example.com</domain:name>
   S:         <domain:status s="ok"/>
…
   S:     </resData>
   S:     <extension>
   S:       <ttl:infData
   S:         xmlns:ttl="urn:ietf:params:xml:ns:epp:ttl-1.0">
   S:         <ttl:ttl for="NS">172800</ttl:ttl>
   S:         <ttl:ttl for="DS">300</ttl:ttl>
   S:       </ttl:infData>
…
   S:   </response>
…

  

Le serveur indique que le TTL des enregistrements NS sera de deux jours. Sinon, vous avez repéré le policy="false" ? S'il avait été à true, le serveur aurait renvoyé l'information sur sa politique pour tous les types d'enregistrements DNS (section 2.1.1.2).

Créons maintenant un nom de domaine en spécifiant un TTL :


   C:   <command>
   C:     <create>
   C:       <domain:create
   C:         xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
   C:         <domain:name>example.com</domain:name>
   C:         <domain:ns>
   C:           <domain:hostObj>ns1.example.com</domain:hostObj>
   C:           <domain:hostObj>ns1.example.net</domain:hostObj>
   C:         </domain:ns>
   C:       </domain:create>
   C:     </create>
   C:     <extension>
   C:       <ttl:create
   C:         xmlns:ttl="urn:ietf:params:xml:ns:epp:ttl-1.0">
   C:         <ttl:ttl for="NS">172800</ttl:ttl>
   C:         <ttl:ttl for="DS">300</ttl:ttl>
   C:       </ttl:create>
   C:     </extension>
   C:   </command>
   C: </epp>

    

Cela marcherait aussi dans un <domain:update>, pour changer les TTL.

Je l'ai déjà dit plusieurs fois, la demande du client ne va pas forcément être honorée par le serveur. La section 3 de notre RFC détaille l'interaction entre cette demande et la politique du serveur (donc du registre). Ainsi, le serveur peut limiter les types d'enregistrement DNS auxquels ces commandes s'appliquent, par exemple en n'acceptant de changer le TTL que pour les DS (d'où l'intérêt des demandes avec policy=…, pour savoir à l'avance).

D'autre part, le TTL des enregistrements publiés peut changer en dehors d'EPP, par une action du registre. Auquel cas, le registre (section 4) peut gentiment prévenir ses clients par le système de messagerie du RFC 8590.

La possibilité pour le client d'indiquer un TTL souhaité a aussi des conséquences opérationnelle (section 5). Ainsi, des TTL courts vont accroitre la charge sur les serveurs faisant autorité puisque les résolveurs auront besoin de demander plus souvent, les expirations se rapprochant. Souvent, les utilisateurs veulent des TTL courts, pour la réactivité, et n'ont pas conscience des conséquences, notamment en terme d'accroissement du trafic, d'autant plus que l'utilisation des serveurs DNS faisant autorité est gratuite pour eux. C'est pour cela que le registre peut fixer des valeurs minimales (et maximales, pour traiter d'autres problèmes) aux TTL souhaités par le client.

Une erreur parfois commise est de penser qu'un changement du TTL (via une commande EPP <epp:update>) va se voir instantanément. Mais, en fait, les informations, avec l'ancien TTL, sont encore dans la mémoire de plusieurs résolveurs. Il est donc recommandé de planifier les changements à l'avance, en tenant compte de cette mémorisation (section 5.2 du RFC). D'ailleurs, la politique du registre aussi peut changer, et les TTL par défaut, ainsi que les valeurs maximales et minimales, sont susceptibles d'être modifiées (un registre sérieux va informer ses utilisateurices de ces changements mais parfois, c'est oublié).

Un gros morceau de notre RFC est consacré à la sécurité (section 6) car les TTL ont une influence sur ce sujet. Premièrement, le fast flux (changement rapide des données de délégation DNS, cf. RFC 9499, section 7). Des malveillants utilisent cette technique pour rendre l'investigation numérique plus difficile et pour échapper à certaines règles de filtrage (voir le rapport SAC-025 du SAAC). Un TTL court peut faciliter ce changement rapide. Le rapport du SAAC suggère un TTL minimum de 30 minutes et/ou de limiter le nombre de changements qu'on peut faire par jour.

Si un malveillant réussit à obtenir les secrets qui lui permettent de soumettre des demandes de modification (au passage, pensez à activer l'authentification à plusieurs facteurs), il mettra sans doute des TTL très élevés pour que son détournement dure plus longtemps. D'où l'intérêt d'une valeur maximale pour les TTL.

Notre extension à EPP pour les TTL figure désormais dans le registre IANA des extensions et sa syntaxe complète, si vous êtes curieux·se, figure dans la section 8 (au format des schémas XML). Question mises en œuvre, vous en trouverez au moins deux, dans le SDK de Verisign et dans le logiciel Pepper (plus exactement dans la bibliothèque qu'il utilise, Net::EPP).


Téléchargez le RFC 9803


L'article seul

RFC 9799: Automated Certificate Management Environment (ACME) Extensions for ".onion" Special-Use Domain Names

Date de publication du RFC : Juin 2025
Auteur(s) du RFC : Q. Misell (AS207960)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF acme
Première rédaction de cet article le 27 juin 2025


Le protocole ACME, normalisé dans le RFC 8555, permet d'automatiser le processus de création et de renouvellement de certificats utilisables, par exemple, pour TLS. L'extension normalisée dans ce nouveau RFC permet d'obtenir et de renouveler des certificats pour un service utilisant le .onion de Tor. Si vous voulez passer à la télévision en disant « j'ai obtenu un certificat pour le Dark Web », ce RFC est la bonne lecture.

Ces services en .onion sont décrits dans la spécification de Tor. Le nom .onion a été enregistré comme « nom spécial » (RFC 6761) par le RFC 7686. Ces noms en .onion ne sont pas résolvables via le DNS et on ne peut donc pas utiliser les défis ACME (RFC 8555, section 8) classiques avec une AC habituelle.

La norme ACME, le RFC 8555, définit dans sa section 9.7.7 des types d'identificateurs. Pour les .onion, ce sera le type dns, même si Tor n'utilise pas le DNS. J'aurais préféré que ce type se nomme domainname, ça aurait été plus cohérent (voir l'annexe A du RFC, qui discute ce choix, qui prend place dans un cadre très embrouillé, avec beaucoup de gens qui confondent noms de domaine et DNS). L'identificateur est le nom dans .onion, éventuellement avec des sous-domaines. Par exemple, le JSON envoyé par ACME, pour la version en .onion de ce blog, serait :

{
  "type": "dns",
  "value": "sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion"
}
  

Reste à permettre au serveur ACME (l'AC) de le valider. Le forum AC/Navigateur permet les .onion (annexe B.2 de ses « Baseline Requirements for the Issuance and Management of Publicly-Trusted Certificates »). ACME utilise le concept de défi pour ces validations. Le client ACME demande un certificat pour un certain identificateur, le serveur lui renvoie un défi, une tâche à accomplir, du genre « prouve-moi que tu peux mettre ces données que je t'envoie dans un endroit accessible en HTTP via le nom pour lequel tu veux un certificat ». Il existe plusieurs défis utilisables avec les .onion :

  • http-01 (section 8.3 du RFC 8555), notre RFC dit qu'il faut suivre les redirections HTTP, même si elles mènent à un serveur HTTP qui n'est pas en .onion ; c'est ce défi que j'ai utilisé pour mon blog.
  • tls-alpn-01 (RFC 8737).
  • onion-csr-01, qui, contrairement aux deux précédents, est spécifique aux .onion et normalisé dans ce RFC 9799. C'est aussi le seul des trois défis utilisables qui permettre des jokers dans l'identificateur (*.bbcweb3hytmzhn5d532owbu6oqadra5z3ar726vq5kgwwn6aucdccrad.onion). Je le décris en détail plus loin. Cette méthode de validation figure désormais dans le registre des types de défis.
  • dns-01 (section 8.4 du RFC 8555), par contre, ne peut pas être utilisé pour les .onion, ceux-ci ne se servant pas du DNS.

Le défi onion-csr-01 consiste à demander au client de générer une CSR (RFC 2986) signée avec la clé privée du nom en .onion (je rappelle qu'un nom en .onion est une clé publique, plus exactement est dérivé d'une clé publique). Pour cela, le serveur ACME envoie un numnique et sa clé publique Ed25519, qu'il utilise pour Tor. Le client doit répondre avec le CSR, signé avec sa clé privée, CSR contenant parmi ses attributs le numnique choisi par le serveur, et un autre choisi par le client. Le serveur vérifie alors ce CSR (le nom en .onion, et bien sûr la signature).

Notez qu'on peut imaginer une AC qui ne soit elle-même accessible que via un nom en .onion, ce qui serait cohérent (section 5 du RFC). Par contre, en sortie, une AC doit utiliser Tor pour se connecter aux .onion (je veux dire l'utiliser directement, pas en passant par une passerelle, cf. section 8.8) mais une AC ne doit pas utiliser Tor pour se connecter à des domaines non-onion (section 8.4) car il y a des nœuds de sortie méchants.

Et les enregistrements de type CAA, normalisés dans le RFC 8659, et qui augmentent la sécurité du système en indiquant à quelles AC le client ACME a recours ? On ne peut pas utiliser le CAA traditionnel puisqu'il dépend du DNS. La solution, décrite dans la section 6 du RFC, est de mettre cette information dans le descripteur de service Tor (celui que le serveur en .onion envoie aux serveurs d'annuaire Tor).

Passons à la pratique. Il existe une AC expérimentale (et qui ne prétend pas offrir les garanties de sécurité d'une « vraie »), par l'auteure du RFC, documentée sur le site Web du projet. Je m'en suis servi pour obtenir un certificat pour mon blog. Vous pouvez donc désormais vous connecter en HTTPS, à https://sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion/ (votre navigateur va sans doute râler car il ne connait pas cette AC). Attention, l'AC a enregistré ce certificat via Certificate Transparency (RFC 9162) et est donc publiquement visible. Ne demandez pas de certificat à une AC qui utilise Certificate Transparency si ça vous dérange (section 8.9 du RFC).

Quelle est la marche à suivre pour obtenir un tel certificat ? D'abord, configurer Tor pour accepter le port de HTTPS :

  
  HiddenServiceDir /var/lib/tor/blogv2/
  HiddenServicePort 80 127.0.0.1:80
  HiddenServicePort 443 127.0.0.1:443

Ensuite, configurer son serveur HTTP, Apache dans mon cas :

  
# Pour le client ACME (qui écoutera sur le port 8080) :
ProxyPass /.well-known/acme-challenge http://localhost:8080/.well-known/acme-challenge
ProxyPassReverse /.well-known/acme-challenge http://localhost:8080/.well-known/acme-challenge
ProxyPreserveHost on
# Ne pas oublier d'activer mod_proxy *et* mod_proxy_http.

# HTTPS :
<VirtualHost _default_:443>
   ServerName sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion

   # Liens symboliques vers les certificats obtenus par ACME, dans mon
   # cas /etc/letsencrypt/live/sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion/…
   SSLCertificateFile	/etc/apache2/server.pem
   SSLCertificateKeyFile /etc/apache2/server.key

On lance ensuite le client ACME. J'ai utilisé certbot :

% sudo certbot certonly -v --server https://acme.api.acmeforonions.org/directory \
             --standalone --http-01-port 8080 --http-01-address 127.0.0.1 \
             -d sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion
…
Performing the following challenges:
http-01 challenge for sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion
Waiting for verification...
Cleaning up challenges
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion/privkey.pem
This certificate expires on 2025-05-28.
…

(Et pensez à configurer le renouvellement automatique du certificat, normalement, certbot l'a fait tout seul, mais vérifiez.)

Un tcpdump montre le trafic échangé entre Apache (qui a reçu le défi de l'AC, via Tor) et certbot (qui avait envoyé la demande et stocké le défi du serveur ACME), sur ma machine :

    
127.0.0.1.60978 > 127.0.0.1.8080: Flags [P.] … HTTP, length: 376
	GET /.well-known/acme-challenge/G4JwaWsRDG42H_FAESGCQrY7ZYk3D3mY9Ob_j458z6M HTTP/1.1
	Host: sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion
	X-Forwarded-For: 127.0.0.1
	X-Forwarded-Host: sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion
	X-Forwarded-Server: sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion
	
127.0.0.1.8080 > 127.0.0.1.60978: Flags [P.] … HTTP, length: 92
	HTTP/1.0 200 OK
	Server: BaseHTTP/0.6 Python/3.11.2
	Date: Thu, 27 Feb 2025 17:04:53 GMT

  

Si vous voulez ajouter cette AC (mais rappelez-vous qu'elle est expérimentale et sans garanties de sécurité) au Tor Browser, vous devrez sans doute, dans about:config, configurer, avant d'importer l'AC :

security.nocertdb false
browser.privatebrowsing.autostart false
security.ssl.enable_ocsp_stapling false
  

Mais je répète mon avertissement : cela peut affecter votre vie privée. Ne le faites pas si vous ne comprenez pas en détail les conséquences.

J'ai utilisé le défi http-01, avec un certbot ordinaire. Le défi onion-01 nécessite un certbot modifié (du code est disponible).

Petite anecdote : l'auteure du RFC travaille pour l'AS 207960, dont l'objet RIPE annonce :

aut-num:        AS207960
as-name:        AS-TRANSRIGHTS
descr:          Trans Rights! Hell Yeah!

Et le site Web montre d'ailleurs le drapeau correspondant. Il est assez rare de voir des prises de position politiques dans la base des RIR.


Téléchargez le RFC 9799


L'article seul

RFC 9794: Terminology for Post-Quantum Traditional Hybrid Schemes

Date de publication du RFC : Juin 2025
Auteur(s) du RFC : F. Driscoll, M. Parsons (UK National Cyber Security Centre), B. Hale (Naval Postgraduate School)
Pour information
Réalisé dans le cadre du groupe de travail IETF pquip
Première rédaction de cet article le 14 juin 2025


La cryptographie post-quantique vise à développer des algorithmes de cryptographie qui résistent à des ordinateurs quantiques. Mais ces algorithmes sont relativement récents et peuvent avoir des faiblesses, voire des failles, que la cryptanalyse classique pourra exploiter. La tendance actuelle est donc aux protocoles et formats hybrides, combinant algorithmes classiques et post-quantiques. Ce RFC spécifie la terminologie de ces protocoles hybrides.

On peut aussi dire AQ, pour après-quantique car le sigle anglophone PQ de post-quantum peut faire drôle en France. D'ailleurs, les termes à utiliser (post-quantique ? résistant au quantique ?) ont fait l'objet de chaudes discussions dans le groupe de travail IETF.

Le point de départ de tout le tintouin autour de l'après-quantique, c'est l'algorithme de Shor. Conçu pour les calculateurs quantiques, et donc inutilisable encore aujourd'hui, il permet de résoudre des problèmes mathématiques qu'on croyait difficiles, comme la décomposition en facteurs premiers (qui est derrière RSA) ou le logarithme discret (qui est derrière ECDSA). Le jour, qui n'est pas encore arrivé, où on aura des CRQC (Cryptographically-Relevant Quantum Computer, un calculateur quantique qui puisse s'attaquer à des problèmes de taille réelle, et pas juste faire des démonstrations), ce jour-là, la cryptographie classique, ou traditionnelle, aura un problème.

Les CRQC sont loin dans le futur, un lointain dont il est très difficile d'estimer la distance. Comme on ne sait pas quand les CRQC seront disponibles, et que certains secrets qu'on chiffre maintenant devront rester secrets pendant de nombreuses années, il est prudent de travailler dès maintenant aux algorithmes AQ, après-quantique, ceux pour lesquels on ne connait pas d'algorithme (quantique ou classique) pour les casser. Ce travail a effectivement commencé depuis des années et on a déjà des algorithmes AQ normalisés comme ML-KEM (ex-Kyber). Notez toutefois qu'aucune norme IETF n'a encore été publiée en intégrant ces algorithmes, mais le travail est en cours, entre autres au sein du groupe de travail pquip.

Mais remplacer complètement les algorithmes traditionnels par les algorithmes AQ n'est pas forcément satisfaisant. Au contraire de RSA et ECDSA, testés au feu depuis longtemps et qui ont toujours résisté, les algorithmes AQ peuvent sembler un peu jeunes. Que se passerait-il si un·e cryptanalyste cassait un de ces algorithmes ? Pour limiter les dégâts, on envisage d'utiliser des mécanismes hybrides, combinant cryptographie classique (pré-quantique) et après-quantique. Ainsi, un chiffrement hybride verrait le texte en clair chiffré par un mécanisme classique puis par un mécanisme après-quantique. Une signature hybride se ferait en mettant deux signatures et en vérifiant ensuite que les deux sont valides. Cette méthode « ceinture et bretelles » est utilisée par exemple dans le RFC 9370 ou dans les Internet-Drafts draft-ietf-tls-hybrid-design, draft-ietf-lamps-pq-composite-kem ou draft-ietf-lamps-cert-binding-for-multi-auth. On peut aussi consulter la FAQ du NIST (« A hybrid key-establishment mode is defined here to be a key establishment scheme that is a combination of two or more components that are themselves cryptographic key-establishment schemes. ») ou bien le document ETSI TS 103 744 nommé « Quantum-safe Hybrid Key Exchanges ». Attention toutefois avec cette terminologie car l'adjectif « hybride » est également souvent utilisé en cryptographie pour désigner la combinaison d'un algorithme de cryptographie asymétrique avec un algorithme de cryptographie symétrique (quand on crée une clé de session échangée via de la cryptographie asymétrique puis qu'on chiffre les données avec cette clé et de la cryptographie symétrique ; c'est ce que font TLS et OpenPGP, par exemple). C'est le sens qu'utilisent les RFC 4949 et RFC 9180, par exemple. Notre RFC 9794 note que ces deux usages du terme « hybride » vont certainement prêter à confusion mais qu'il n'y avait pas trop le choix : chaque usage était déjà solidement installé dans un milieu particulier. Essayer de promouvoir un autre terme pour la cryptographie après-quantique, comme « double algorithme » ou « multi algorithme » était sans doute voué à l'échec.

Passons maintenant aux définitions. Je ne vais pas les reprendre toutes mais donner quelques exemples. La section 2 du RFC commence par les mécanismes de base et d'abord, mécanisme hybride traditionnel / post-quantique (post-quantum traditional hybrid scheme, ou PQ/T), un mécanisme qui combine la cryptographie existante et celle du futur. On peut aussi simplifier en disant juste mécanisme hybride. Il y a aussi :

  • Multi-algorithme, qui est plus large qu'hybride puisqu'il inclut les mécanismes ayant deux algorithmes traditionnels ou deux algorithmes après-quantique.
  • Composé (composite), qui désigne les mécanismes hybrides où le mécanisme est exposé aux couches supérieures sous forme d'une interface unique (ce qui est évidemment plus simple et plus sûr pour le ou la programmeur·se).

Ensuite, on grimpe d'un niveau (section 3 du RFC), avec les éléments, qui sont les données en entrée ou en sortie d'un processus cryptographique. Quand on dit « l'algorithme X prend en entrée un texte en clair et une clé secrète et produit un texte chiffré », le texte en clair, la clé et le texte chiffré sont des éléments. Dans le mécanisme hybride décrit dans draft-ietf-tls-hybrid-design, il y a deux clés publiques, qui sont deux éléments. Un élément peut à son tour être composé de plusieurs éléments.

On peut maintenant utiliser tout cela pour faire des protocoles (section 4). Un protocole hybride PQ/T est, comme vous vous en doutez, un protocole qui utilise au moins deux algorithmes, un classique et un après-quantique. C'est ce qui est proposé dans draft-ietf-tls-hybrid-design. Ce dernier est même composé (dans le mécanisme de désignation de la clé, le KEM). Alors que le mécanisme du RFC 9370 est hybride mais pas composé (on fait un échange de clés classique et un KEM après-quantique).

Les noms des services de sécurité qu'on souhaite utiliser vont de soi (section 5) : confidentialité hybride PQ/T (confidentialité assurée par un mécanisme hybride traditionnel/après-quantique) et authentification hybride PQ/T.

Idem pour les certificats (section 6). Un « certificat hybride PQ/T » contient au moins deux clés publiques, une pour un algorithme traditionnel et une pour un algorithme après-quantique (alors que le certificat traditionnel et le certificat après-quantique ne contiennent qu'un seul type de clé publique, comme c'est le cas du certificat décrit dans draft-ietf-lamps-dilithium-certificates).

Et merci à Magali Bardet pour sa relecture mais, bien sûr, les erreurs sont de moi et moi seul.


Téléchargez le RFC 9794


L'article seul

RFC 9774: Deprecation of AS_SET and AS_CONFED_SET in BGP

Date de publication du RFC : Mai 2025
Auteur(s) du RFC : W. Kumari (Google), K. Sriram, L. Hannachi (USA NIST), J. Haas (Juniper Networks)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF idr
Première rédaction de cet article le 22 mai 2025


Dans le protocole de routage BGP, les annonces de routes sont marquées avec l'AS d'origine et avec les AS qui ont relayé l'annonce. Dans ce chemin des AS, on pouvait indiquer un ensemble d'AS, l'AS_SET (ainsi que l'AS_CONFED_SET). C'était déconseillé depuis le RFC 6472 et ce nouveau RFC 9774 l'interdit désormais. Le but est de simplifier BGP et notamment ses mécanismes de sécurité. Il faut maintenant forcément indiquer une suite ordonnée d'AS, une AS_SEQUENCE.

Ces AS_SET (et les AS_CONFED_SET du RFC 5065 mais je vais passer rapidement sur les confédérations) sont spécifiés par le RFC 4271, sections 4.3 et 5.1.2. Attention à ne pas confondre avec les objets de type as-set des bases des RIR comme, par exemple, celui de l'Afnic.

Un des inconvénients de ces AS_SET est que, puisqu'un ensemble n'est pas ordonné, il n'est pas évident de déterminer l'AS d'origine, le premier AS, ce qui est pourtant nécessaire pour la sécurité (ROV ou Route Origin Validation, cf. RFC 6811).

Pourquoi mettait-on des AS_SET alors ? Parce que c'est utile lorsqu'on effectue de l'agrégation de routes. L'agrégation, spécifiée dans les sections 9.1.2.2 et 9.1.4 du RFC 4271 est le mécanisme par lequel un routeur rassemble plusieurs routes en une route plus générale. Si les routes originales venaient de plusieurs AS, on pouvait les rassembler en un AS_SET. Mais, évidemment, cela brouille l'information sur la vraie origine d'une route. C'est pour cela que les techniques de sécurisation de BGP, comme le BGPsec du RFC 8205 ne s'entendent pas bien avec les AS_SET.

La section 3 est la partie normative du RFC : désormais, une machine qui parle BGP ne doit plus utiliser d'AS_SET ou d'AS_CONFED_SET dans les chemins d'AS de ses messages de mise à jour de routes. Une machine qui reçoit ce genre de messages doit les traiter comme une erreur et retirer les routes (cf. RFC 7606). Les techniques de sécurisation comme ROV (RFC 6811) ou BGPsec (RFC 8205) considèrent toute annonce incluant des AS_SET comme invalide.

Sur l'agrégation, voyez par exemple cette réponse sur StackExchange. La procédure désormais suggérée pour en faire (section 5) est d'indiquer comme AS d'origine du préfixe agrégé l'AS qui a fait l'agrégation (en s'assurant bien qu'il y a un ROA - RFC 6482). Les annexes A et B donnent des exemples détaillés.

Il est frappant de constater que la majorité des documentations BGP des routeurs continue à mettre AS_SET et AS_SEQUENCE sur un pied d'égalité, alors que le RFC 6472 date de déjà 14 ans.

Le RFC note que les AS_SET sont peu utilisés, et parfois mal (un AS_SET ne comportant qu'un seul AS, ou bien ayant des numéros d'AS spéciaux…). Cherchons un peu. Je prends une RIB (Routing Information Base) complète sur RouteViews. Elle est au format MRT (Multi-Threaded Routing Toolkit, RFC 6396). Passons là à travers bgpdump, produisant un fichier texte. Comment trouver les AS_SET ? J'ai simplement lu le code source de bgpdump :

 if (space)
	    {
	      if (segment->type == AS_SET
		  || segment->type == AS_CONFED_SET)
		as->str[pos++] = ',';
	      else
		as->str[pos++] = ' ';
		}
  

OK, il y a des virgules entre les AS (et une autre partie du code montre que les AS_SET sont placés entre accolades). On peut alors chercher le fichier texte et trouver, par exemple, cette annonce :

TIME: 04/16/25 12:00:02
TYPE: TABLE_DUMP_V2/IPV4_UNICAST
PREFIX: 45.158.28.0/23
FROM: 12.0.1.63 AS7018
ORIGINATED: 04/15/25 06:11:28
ASPATH: 7018 3356 3223 {8262,34224} 201200
NEXT_HOP: 12.0.1.63
COMMUNITY: 7018:5000 7018:37232
  

L'annonce du préfixe 45.158.28.0/23, dont l'origine est l'AS 201200, est passée par l'AS 8262 ou bien le 34224, ou bien il y a eu agrégation de deux routes, chacune passée par un de ces deux AS (mais cela n'a pas été marqué). Sur un looking glass, on voit le passage par le 8262 uniquement :

Mon Apr 21 10:30:34.855 CEST
BGP routing table entry for 45.158.28.0/23
Paths: (3 available, best #2, not advertised to any peer)
  Path #1: Received by speaker 0
  174 3356 3223 8262 201200, (received-only)
    149.6.34.5 from 149.6.34.5 (38.28.1.70)
      Origin IGP, metric 17060, localpref 100, valid, external
      Community: 174:21100 174:22009
      Origin-AS validity: not-found
      …
    

Soit ce looking glass a reçu une autre annonce, soit son code n'affiche que l'un des AS de l'AS_SET.

Autre exemple, où l'AS_SET est à l'origine :

TIME: 04/16/25 12:00:04
TYPE: TABLE_DUMP_V2/IPV4_UNICAST
PREFIX: 67.204.16.0/22
FROM: 89.149.178.10 AS3257
ORIGINATED: 04/10/25 00:44:05
ASPATH: 3257 13876 {15255,396519,396895}
NEXT_HOP: 89.149.178.10
MULTI_EXIT_DISC: 10
AGGREGATOR: AS13876 67.204.31.4
COMMUNITY: 3257:4000 3257:8118 3257:50002 3257:50120 3257:51100 3257:51110

Là, il y a eu agrégation, par l'AS 13876, qui a placé un AS_SET. Vu par le looking glass :

   
Mon Apr 21 10:39:46.348 CEST
BGP routing table entry for 67.204.16.0/22
Paths: (3 available, best #2, not advertised to any peer)
  Path #1: Received by speaker 0
  174 3356 13876 {15255,396519,396895}, (aggregated by 13876 67.204.31.4), (received-only)
    149.6.34.5 from 149.6.34.5 (38.28.1.70)
      Origin IGP, metric 17060, localpref 100, valid, external
      Community: 174:21100 174:22009
      Origin-AS validity: not-found
    

Je ne suis pas sûr que tous les looking glass affichent correctement les AS_SET. Mais étant donné que notre nouveau RFC met les AS_SET à la poubelle, il ne servirait à rien de demander au développeur d'ajouter ce service. Ah, et mon bot fédivers qui lit la table BGP gère ça bien.


Téléchargez le RFC 9774


L'article seul

RFC 9773: ACME Renewal Information (ARI) Extension

Date de publication du RFC : Juin 2025
Auteur(s) du RFC : A. Gable (Internet Security Research Group)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF acme
Première rédaction de cet article le 18 juin 2025


Si vous utilisez Let's Encrypt (et tout le monde l'utilise, de nos jours), vous avez sans doute reçu les messages « Let's Encrypt Expiration Emails Update » qui vous préviennent que cette AC n'enverra plus de rappels que vos certificats vont bientôt expirer. C'est parce qu'un meilleur système est maintenant disponible, ARI (ACME Renewal Information). ARI permet à une AC utilisant le protocole ACME d'indiquer à ses clients des suggestions sur le renouvellement des certificats. Il est décrit dans ce RFC.

ACME est normalisé dans le RFC 8555 et est surtout connu via le succès de Let's Encrypt. Les certificats sont de courte durée (aujourd'hui trois mois mais ça va diminuer) et il faut donc les renouveler souvent. On peut le faire automatiquement via cron, ou bien analyser le certificat et renouveler quand sa date d'expiration approche. L'un des problèmes est que cela peut mener à ce que plusieurs demandes de renouvellement arrivent en même temps sur l'AC. Le pic d'activité qui en résulterait pourrait charger l'AC inutilement. L'idée est donc que ce soit le serveur ACME, l'AC, qui planifie les renouvellements, et pas le client ACME. Cela permettrait aussi des changements de planning, comme une réduction des durées de validité, ou bien une révocation.

Donc, ARI ajoute un nouvel URL à la description d'une AC, renewalInfo. Voici celui de Let's Encrypt (qui met en œuvre ARI depuis deux ans) :

% curl https://acme-v02.api.letsencrypt.org/directory
{
  "keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change",
  "meta": {
    "caaIdentities": [
      "letsencrypt.org"
    ],
    "profiles": {
          …
    },
    "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf",
    …
  },
  "newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct",
  "newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce",
  "newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order",
  "renewalInfo": "https://acme-v02.api.letsencrypt.org/draft-ietf-acme-ari-03/renewalInfo",
  "revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert"
  

Ce nouveau membre a été ajouté au registre IANA.

Et comment on obtient quelque chose à cet URL https://acme-v02.api.letsencrypt.org/draft-ietf-acme-ari-03/renewalInfo ? On doit passer un identificateur du certificat. Il est formé par la concaténation de l'identifiant de l'AC et du numéro de série du certificat (pour garantir qu'il soit unique). Je passe sur les détails de construction (lisez la section 4 du RFC pour cela) mais ce petit script Python ari-make-path.py vous fait le calcul. Utilisons-le sur l'actuel certificat de ce blog :

% openssl x509 -text -in cert.pem
[Notez les valeurs]

% python ari-make-path.py 93:27:46:98:03:A9:51:68:8E:98:D6:C4:42:48:DB:23:BF:58:94:D2 00:06:7d:03:91:c6:49:b8:83:ba:e5:c6:da:8a:dc:be:4d:33:78
kydGmAOpUWiOmNbEQkjbI79YlNI.AAZ9A5HGSbiDuuXG2orcvk0zeA

% curl -i https://acme-v02.api.letsencrypt.org/draft-ietf-acme-ari-03/renewalInfo/kydGmAOpUWiOmNbEQkjbI79YlNI.AAZ9A5HGSbiDuuXG2orcvk0zeA
…
retry-after: 21600
…
{
  "suggestedWindow": {
    "start": "2025-06-23T03:50:00Z",
    "end": "2025-06-24T23:00:50Z"
  }
}
  

Voilà, on a fait un URL en concaténant la valeur de renewalInfo avec celle obtenue à partir du certificat et on sait désormais quand est-ce que Let's Encrypt suggère de renouveler ce certificat. Le format de sortie est clair mais vous avez les détails dans la section 4.2. Les dates sont évidemment au format du RFC 3339. Au passage, la date d'expiration est le 24 juillet 2025 donc Let's Encrypt n'attend pas le dernier moment. (Comme le dit un commentaire dans le code source du serveur, « calculate a point 2/3rds of the way through the validity period (or halfway through, for short-lived certs) ».)

Le RFC précise qu'un membre explanationURL peut être ajouté mais Let's Encrypt ne le fait pas. Les membres possibles figurent dans un nouveau registre IANA, auquel on pourra ajouter de nouveaux membres, en fournissant une spécification (« Spécification nécessaire » du RFC 8126).

Et on utilise cet intervalle entre deux dates comment ? Le RFC recommande de choisir une date au hasard dans l'intervalle. Le client ACME ne doit pas dormir jusqu'à la date sélectionnée, il doit réessayer de temps en temps car l'AC a pu changer la date (c'est tout le principe d'ARI). Mais attention à respecter le Retry-After: (six heures, ici), cf. RFC 9110, section 10.2.3.

Notre RFC ajoute également un membre à la description d'une commande de certificat : replaces indique quel certificat on est censé remplacer. (En utilisant le même identificateur de certificat qu'indiqué plus haut.) Il a été ajouté au registre IANA.

ARI est mis en œuvre dans le serveur ACME de Let's Encrypt, Boulder. Regardez core/objects.go et notamment la fonction RenewalInfoSimple. Côté client, Lego, acmez et le CertMagic de Caddy ont ARI mais certbot ou dehydrated ne gèrent pas ARI. Si vous voulez vous y mettre, Let's Encrypt a écrit un guide d'intégration d'ARI.


Téléchargez le RFC 9773


L'article seul

RFC 9771: Properties of AEAD Algorithms

Date de publication du RFC : Mai 2025
Auteur(s) du RFC : A. Bozhko (CryptoPro)
Pour information
Réalisé dans le cadre du groupe de recherche IRTF cfrg
Première rédaction de cet article le 8 mai 2025


Aujourd'hui, sur l'Internet, on n'utilise plus (ou, en tout cas, cela devrait être le cas) que des algorithmes de chiffrement AEAD (Authenticated Encryption with Associated Data). Ils assurent confidentialité et intégrité des données. Mais on peut être gourmand et vouloir en plus d'autres propriétés. Ce nouveau RFC classe ces propriétés et définit la terminologie.

Les algorithmes de chiffrement anciens, non-AEAD, assuraient la confidentialité, mais pas l'intégrité. Un méchant (ou un accident) pouvait modifier les données sans que ce soit détectable et le déchiffrement produisait ensuite un texte qui n'était pas le texte original. Bien sûr, s'il s'agissait d'un texte en langue naturelle, ou bien d'un texte dans un format structuré, l'utilisateurice pouvait parfois voir qu'il y avait eu un problème, puisque, avec certains modes de chiffrement, ielle ne récupérait que du n'importe quoi. Mais il serait souhaitable de détecter l'attaque (ou le problème) le plus tôt possible. Et il y a aussi des raisons de sécurité pour assurer confidentialité et intégrité en même temps. Sinon, certaines attaques (comme Poodle) sont possibles. Et il faut aussi compter avec le fait que les programmeurs peuvent se tromper s'ils doivent appliquer confidentialité et intégrité séparément (cf. RFC 7366).

Vérifier l'intégrité peut se faire avec une somme de contrôle avec clé (MAC), ou une technique équivalente mais l'AEAD fait mieux, en intégrant chiffrement et vérification de l'intégrité. Cela a plusieurs avantages, dont les performances (plus besoin de chiffrer et de calculer un MAC successivement) et, comme indiqué plus haut, la sécurité.

Dans la famille des normes de l'Internet, l'AEAD est décrit plus en détail dans le RFC 5116. À partir de la version 1.3 (normalisée dans le RFC 8446), TLS impose l'utilisation d'algorithmes AEAD. Même chose pour QUIC (RFC 9000). Parmi les algorithmes AEAD courants, on trouve AES-GCM et ChaCha20-Poly1305 (RFC 8439) mais aussi Aegis ou OCB (RFC 7253).

Au passage, je trouve que le terme en anglais, authenticated encryption et sa traduction en français, chiffrement authentifié, sont trompeurs. Le service qu'ils assurent n'est pas l'authentification telle qu'on peut la faire avec RSA ou ECDSA. Je préférerais qu'on parle de chiffrement intègre.

Tout cela est bien connu depuis des années. Mais l'appétit vient en mangeant et certaines utilisations bénéficieraient de services supplémentaires. Les algorithmes existants sont sûrs par rapport aux modèles de menace « traditionnels » mais il en existe d'autres, auxquels tous les algorithmes AEAD ne répondent pas forcément. Ces services supplémentaires, pour répondre à ces modèles de menace, existaient parfois, et parfois ont déjà été développés, mais des équipes différentes leur donnent des noms différents. D'où le projet d'unification de la terminologie de ce RFC 9771. Il présente les propriétés supplémentaires (en plus de la confidentialité et de l'intégrité, que tout algorithme AEAD fournit), des noms d'algorithmes qui les fournissent et des cas d'usage. Le but est que les futurs RFC normalisant des protocoles qui dépendent de ces propriétés utilisent le vocabulaire de notre RFC.

Les propriétés supplémentaires, au-delà de la confidentialité et de l'intégrité basiques, sont listées dans la section 4. Il y a deux catégories :

  • Propriétés de sécurité, lorsque la propriété permet de parer certaines attaques,
  • propriétés de mise en œuvre, lorsqu'elles permettent de meilleures implémentations,
  • et, pour, voir si vous savez compter jusqu'à deux, il y a aussi une catégorie un peu fourre-tout, pour les propriétés qui ajoutent de nouvelles fonctions, mais je n'en parlerai pas plus ici (consultez l'annexe A du RFC).

Avant d'exposer les propriétés additionnelles, le RFC présente les traditionnelles, en suivant le même schéma (définition, exemples, éventuels synonymes, cas d'usage, lectures pour approfondir) : confidentialité et intégrité sont ainsi exposées. Passons ensuite aux choses sérieuses, avec les propriétés de sécurité supplémentaires.

D'abord, la sécurité face aux changements (blockwise security) : c'est le fait d'être sûr même quand un adversaire particulièrement puissant peut modifier le texte en clair en fonction de ce qui a déjà été chiffré. Tous les adversaires n'ont heureusement pas ce pouvoir mais cela peut arriver, par exemple lors du streaming. Ainsi, la famille Deoxys résiste à ce type d'attaque.

Ensuite, l'engagement complet (full commitment). C'est l'extrême difficulté à trouver deux jeux {clé, numnique, données en clair} qui donneront le même texte chiffré. Cela sert dans le message franking mais ne me demandez pas ce que c'est, lisez cet article. Ascon a cette propriété. Et, au passage, le AD de AEAD veut dire « données associées » (associated data, des méta-données ajoutées au message) et les « données en clair » incluent donc ces données associées.

La résistance aux fuites (leakage resistance) est une propriété des algorithmes cryptographiques (pas seulement AEAD) dont la sécurité ne diminue pas même si l'attaquant obtient des informations via un canal secondaire. Un exemple d'un tel canal secondaire est le temps de calcul (si l'attaquant peut le chronométrer et si l'algorithme n'est pas résistant aux fuites, l'attaquant pourra obtenir des informations sur la clé) ou bien la consommation électrique. Bien sûr, cela dépend de l'implémentation (essayer de faire tous les calculs en un temps constant, quelle que soit la clé) mais un algorithme résistant aux fuites est un algorithme qui ne dépend pas trop (mild requirement, dit le RFC) de son implémentation concrète pour être sûr. Cette propriété est particulièrement importante pour les machines que l'attaquant peut contrôler physiquement (cartes à puce, objets connectés) alors que mesurer le temps de calcul, et a fortiori la consommation électrique, d'un serveur Internet distant est une autre affaire. (Mais ça reste possible dans certains cas, notamment si l'attaquant est proche, par exemple chez le même hébergeur : voir l'article « Remote Timing Attacks Are Practical » ou bien la faille Hertzbleed.)

La sécurité multi-utilisateurs (multi-user security) est atteinte quand la sécurité décroit moins vite que linéairement avec le nombre d'utilisateurs (les algorithmes ont des limites quantitatives, cf. draft-irtf-cfrg-aead-limits). C'est indispensable pour des protocoles comme TLS, où plusieurs « utilisateurs » peuvent se retrouver sur la même session TLS. Des algorithmes comme AES-GCM ou ChaCha20-Poly1305 ont cette sécurité (si on ne dépasse pas les limites). Vous pouvez lire « The Multi-user Security of Authenticated Encryption: AES-GCM in TLS 1.3 » pour les détails.

Bien sûr, il fallait mentionner la propriété de résistance aux calculateurs quantiques (Quantum security). AEAD ou pas, un algorithme est résistant au quantique si on ne connait pas d'algorithme pour calculateur quantique capable de casser cet algorithme. Les algorithmes comme AES-GCM ou ChaCha20-Poly1305 sont ainsi résistants (au prix parfois d'une augmentation raisonnable de la taille de la clé). Cette résistance permet de faire face au cas où un indiscret stocke aujourd'hui des messages qu'il ne sait pas déchiffrer, en attendant qu'il dispose d'un calculateur quantique. Notez que si on fait face à un adversaire mieux armé, qui n'a pas seulement un calculateur quantique mais peut en plus accéder à l'état quantique de votre système de chiffrement, ça devient plus compliqué. Dans ce cas très futuriste, il faut passer à des algorithmes comme QCB (cf. « QCB: Efficient Quantum-Secure Authenticated Encryption »).

Tout cela, c'étaient les propriétés de sécurité des algorithmes, liés à la définition de ces algorithmes. Mais, en pratique, on n'utilise pas un algorithme mais une mise en œuvre de l'algorithme, réalisée dans un programme. La section 4.4 du RFC liste des propriétés souhaitables des mises en œuvre (en plus de la propriété évidente que le programme soit rapide), propriétés qui n'affectent pas la sécurité (que ce soit en bien ou en mal). Par exemple, on souhaite que le programme soit léger, au sens où il tourne sur des machines contraintes (en mémoire, en processeur, en énergie, etc). Le rapport du NIST « NISTIR 8114 - Report on Lightweight Cryptography » est une lecture intéressante à ce sujet.

On souhaite ensuite un programme qui puisse exploiter le parallélisme de la machine qui l'exécute. Si celle-ci a plusieurs processeurs et/ou plusieurs cœurs, il serait bon que le travail puisse être réparti entre ces cœurs. Des algorithmes comme le mode CBC ne permettent pas le parallélisme lors du chiffrement.

Autres propriétés souhaitables citées par le RFC : ne pas nécessiter un travail supplémentaire ou de nouvelles ressources quand on introduit une nouvelle clé, fonctionner en une passe unique sur les données, permettre de chiffrer un flux de données continu, sans attendre sa fin…

Merci beaucoup à Manuel Pégourié-Gonnard et Florian Maury pour une relecture détaillée avec plein de bonnes remarques. Comme toujours, les erreurs et approximations sont de moi, pas des relecteurs.


Téléchargez le RFC 9771


L'article seul

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