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.
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.)
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 :
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 :
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),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 :
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 :
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) :
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 :
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.
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 :
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 :
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 |
+------------------------------+
<----- PLPMTU ----->
<---------- PMTU -------------->
</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
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.
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.
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 :
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 ».
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.
À 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 :
Un peu de terminologie avant d'attaquer les détails, notamment (section 3) :
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) :
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 :
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.
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
et le
programme de test est kangarootwelve.py). Si on prend ce vecteur
de test dans le RFC :
test-kangarootwelve.py
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).
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 , qui utilise l'excellente
bibliothèque ldns. Compiler
et exécuter :
generalized-notify.c
% 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.
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).
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).
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.
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) :
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.
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).
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, à
(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).
https://sjnrk23rmcl4ie5atmz664v7o7k5nkk4jh7mm6lor2n4hxz2tos3eyid.onion/
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.
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 :
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.
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.
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 vous fait le
calcul. Utilisons-le sur l'actuel certificat de ce blog :
ari-make-path.py
% 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.
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 :
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.
RFC des différentes séries : 0 1000 2000 3000 4000 5000 6000 7000 8000 9000