Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

Ce blog n'a d'autre prétention que de me permettre de mettre à la disposition de tous des petits textes que j'écris. On y parle surtout d'informatique mais d'autres sujets apparaissent parfois.


RFC 9969: IAB AI-CONTROL Workshop Report

Date de publication du RFC : Mai 2026
Auteur(s) du RFC : M. Nottingham, S. Krishnan
Pour information
Première rédaction de cet article le 20 mai 2026


Ah, l'IA… Vaste sujet, et d'actualité. Une des questions qui reviennent souvent est celle de l'utilisation du contenu qu'on trouve sur le Web pour entrainer les grands modèles, sa légitimité, la charge qu'elle induit pour les serveurs, les moyens de la contrôler, etc. Un colloque avait été organisé par l'IAB en septembre 2024 sur ces questions et ce RFC en est le compte-rendu. Ce colloque avait lancé le projet IETF aipref.

Une petite précision politique d'abord : le RFC précise bien qu'il s'agit d'un compte-rendu et que l'IAB n'approuve pas forcément tout ce qui a été dit à ce colloque (section 1.2 du RFC). Je rajoute que j'ai aussi des opinions sur le sujet, donc je mettrais [entre crochets] ce qui est mon opinion, et ne vient pas du RFC. Le reste n'est donc pas de moi, j'en rends compte, c'est tout, ne me tapez pas.

Ce colloque fait partie de la série de colloques qu'organise régulièrement l'IAB pour explorer des tendances à plus ou moins long terme, sans les obligations de l'IETF de produire normes et documents.

Donc, les LLM (qui ne sont qu'une partie des techniques qu'on regroupe sous le terme marketing d'« IA ») fonctionnent en deux phases : on entraine le modèle en lui faisant ingérer une grande quantité de contenu (textes, images ou autres), puis il va pouvoir inférer du contenu à partir de ce qu'il a digéré pendant la phase d'entrainement, et d'une demande (dite prompt). Le contenu inféré n'est jamais tout à fait identique à celui utilisé pour l'entrainement (autrement, cela serait du plagiat, potentiellement illégal). Les LLM ne marchant bien, à l'heure actuelle, que si le corpus d'entrainement était énorme, ils sont très gourmands en données et une source évidente de contenu en grande quantité est le Web. Des bots ou crawlers parcourent donc le Web, ramassant du contenu. Voici par exemple un extrait du journal du serveur qui héberge ce blog, montrant le bot de Perplexity récoltant du contenu :

18.210.92.235:64884 - - [09/Jan/2026:07:26:15 +0000] "GET /images/TCP_state_diagram.jpg HTTP/1.1" 200 96551 "-" "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)" www.bortzmeyer.org TLS
18.97.9.103:64398 - - [09/Jan/2026:08:31:39 +0000] "GET /bitcoin-metamorphoses.html HTTP/1.1" 200 8982 "-" "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)" www.bortzmeyer.org TLS
18.97.9.101:57493 - - [09/Jan/2026:08:31:39 +0000] "GET /robots.txt HTTP/1.1" 404 3250 "-" "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)" www.bortzmeyer.org TLS
18.97.9.103:48122 - - [09/Jan/2026:08:47:36 +0000] "GET /nist-pq.pdf HTTP/1.1" 200 84543 "-" "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)" www.bortzmeyer.org TLS
18.97.9.96:25157 - - [09/Jan/2026:08:51:37 +0000] "GET /files/capitole-libre-2019-quic-pour-impression.pdf HTTP/1.1" 200 212507 "-" "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)" www.bortzmeyer.org TLS

Une des questions soulevées par cette récolte de données est qu'elle n'était pas prévue à l'origine. Certains webmestres qui mettent du contenu en ligne estiment donc qu'un nouvel usage (l'entrainement des LLM) justifie de nouvelles règles et de nouvelles possibilités de contrôle par le serveur Web. C'est par exemple ce que prévoit l'AI Act européen.

Le colloque (ou atelier) de l'IAB s'est tenu les 19 et 20 septembre 2024 (oui, le RFC met trop longtemps à sortir) et prévoyait de travailler sur tous les aspects liés à cette récolte de données (cf. l'appel à participation). Le colloque regroupait des personnes de divers horizons, experts techniques, entreprises d'IA, fournisseurs de contenu, décideurs politiques, etc. La liste figure dans l'annexe A.2. La règle suivie était celle de Chatham House (tout ce qui se dit est public mais sans le lier à un·e participant·e particulier·ère). D'ailleurs, le RFC note qu'au moins un participant n'a pas voulu que son identité soit dévoilée, juste qu'il était un représentant officiel d'un gouvernement. Et, comme déjà dit, le RFC rend compte des discussions, cela ne signifie pas que l'IAB approuve tout ce qui a été dit.

La section 2 du RFC résume les discussions (la totalité des soumissions sont en ligne). Aujourd'hui, les fournisseurs de contenu, les webmestres, peuvent exprimer leurs choix quant à la récolte de données par divers moyens. Il y a par exemple une solution technique existante, c'est le robots.txt, qui est décrit dans le RFC 9309. Notez que, en l'absence du fichier robots.txt, les bots peuvent tout récolter. C'est donc une solution opt-out. Il y a aussi des solutions non-techniques par exemple les conditions d'utilisation (ainsi, ce blog est sous licence GFDL et les contenus peuvent donc être réutilisés, à la condition que les destinataires jouissent des mêmes droits de réutilisation). Tiens, par contre, il n'y a pas de licence CC-BY-NoAI ? Pour revenir à la technique, le webmestres peuvent aussi bloquer les crawlers par leur adresse IP, ou leur User-Agent (RFC 9110, section 10.1.5), ou carrément tout mettre derrière un paywall.

Comme indiqué plus haut, ces solutions sont en général opt-out, donc par défaut, la récolte est autorisée. (Sur ce blog, et c'est apparemment le cas de la plupart des serveurs HTTP, plus de la moitié des requêtes sont faites par des bots, mais pas forcément liés à l'IA, c'était déjà le cas avant les LLM.) On constate (cf. l'exposé « Consent in Crisis: The Rapid Decline of the AI Data Commons ») une tendance à la fermeture : la récolte devient de plus en plus difficile car de nombreux serveurs bloquent les accès qu'ils pensent dûs à un bot. Le Web tend donc à se fermer.

[Le RFC n'est pas clair sur ce point mais, pour moi, il est important de faire la différence entre les problèmes techniques et opérationnels posés par certains bots qui, qu'ils travaillent pour l'IA ou pas, « matraquent » avec excès les serveurs, et les problèmes politiques et financiers liés à l'utilisation qui est faite des données récoltées. Les problèmes techniques et opérationnels causés par des « bots fous » existaient bien avant les LLM. Par contre, les problèmes politiques (légitimité à réutiliser le contenu) et financiers (perte de revenus pour les ayant-droits, comme mentionné dans le RFC) sont plus spécifiques de l'IA. Le RFC ne parle pas vraiment des problèmes opérationnels posés par l'agressivité de certains bots - pas forcément liés à l'IA, d'ailleurs - mais la réunion IETF 123 à Madrid avait vu de très intéressants exposés à ce sujet.]

À l'heure actuelle, il est difficile de savoir ce qui est permis, au delà des simples consignes du robots.txt. Les gérants des serveurs n'ont pas de moyen standard et automatiquement analysable de faire connaitre leurs conditions d'utilisation, et les bots n'ont donc pas non plus de moyen de savoir ce qui est permis. [Il va de soi qu'il y a des bots qui, de toute façon, s'en foutent. Le travail de normalisation à l'IETF ne pourra concerner que les bots honnêtes et ne dispensera pas de mesurs de sécurité contre les malhonnêtes.]

Le RFC creuse certain aspects de la question. Par exemple, en section 2.1, le problème de la différence entre le moment du ramassage des données et celui de leur utilisation. Les consignes du serveur (comme le robots.txt) sont lues au moment du ramassage mais certains responsables de contenu voudraient exprimer des choix concernant l'utilisation, or celle-ci se fait à un autre moment, décorrélé du premier. Certaines récoltes, comme celle faite par Common Crawl, peuvent servir à de multiples usages et des consignes concernant le ramassage ne sont donc pas appropriées. Autre exemple que Common Crawl, on peut avoir une organisation qui gère un moteur de recherche du Web et développe un LLM, et qui utilise le même crawler pour les deux usages. Certains webmestres estiment que la première utilisation ne pose pas de problème (au bout du compte, cela ramènera du trafic sur leur site Web) mais s'opposent à la seconde car elle n'apportera pas de trafic, le LLM donnant des réponses qui suffiront à l'utilisateur.

Du point de vue technique, il faut aussi noter que le principe d'entrainement d'un LLM fait qu'on utilise toutes les données et, qu'une fois le modèle créé, il n'y a pas d'étiquetage spécifique de la source de telle ou telle réponse du LLM. (C'est pour cela que les LLM ont du mal à indiquer leurs sources.) Un webmestre qui souhaiterait dire « d'accord pour servir à l'entrainement des IA mais pas pour que ces IA aient un usage militaire, ou bien pas un usage commercial » ne le peut pas, en raison de cette limite technique. Et même si ce moyen existait, le gérant du LLM serat obligé de faire N modèles, pour toutes les permutations des différents critères (ou tout simplement d'exclure tous les contenus ayant une licence restrictive, ce qui limiterait la représentativité du corpus d'entrainement du modèle).

Enfin, les préférences changent dans le temps et celles exprimées au moment de la récolte des données peuvent ne pas être à jour lorsque les données seront utilisées pour l'entrainement d'un LLM.

Le problème est déjà compliqué si on suppose que tous les acteurs sont de bonne foi et respectent les règles. Mais, évidemment, la confiance ne règne pas, et pour de bonnes raisons. [Les entreprises capitalistes trichent, que ce soit celles qui entrainent les LLM ou bien celles des ayant-droits.] Il n'y a pas de moyen facile de vérifier le respect des préférences exprimées par les gérants du contenu. Et c'est d'autant plus inquiétant que les entreprises de l'IA n'ont pas vraiment de motivation pour respecter les règles : aucun risque de sanction [surtout compte-tenu des déclarations de Trump contre tout projet de régulation de l'IA]. Cette absence de confiance entraine l'utilisation importante de moyens techniques de blocage, comme de bloquer les adresses IP des bots connus. Il y a même un bot qui suggère cette solution :

119.28.89.249:58834 - - [21/Jan/2026:15:32:02 +0000] "GET /5153.xml HTTP/1.1" 200 6891 "-" "Mozilla/5.0 (compatible; Thinkbot/0.5.8; +In_the_test_phase,_if_the_Thinkbot_brings_you_trouble,_please_block_its_IP_address._Thank_you.)" www.bortzmeyer.org TLS
  

L'atelier de l'IAB a passé du temps sur la question de l'attachement des préférences au contenu (section 2.3). Le robots.txt (RFC 9309) est très bien, très déployé et largement reconnu. Mais il manque de souplesse pour les gros sites qui souhaitent un système plus granulaire. Par exemple, si un site de vidéos souhaitait restreindre l'accès à certaines vidéos, la seule solution est de les placer dans un espace particulier (par exemple un répertoire distinct), et donc de devoir changer l'URL si la classification change. Et, comme le robots.txt est à la racine du site Web, il n'est pas sous le contrôle des créateurs de contenu qui ont accès à un espace dédié mais pas à la totalité du site. Si le CMS que vous utilisez permet des créations de contenu et des mises à jour décentralisées, où certaines personnes peuvent modifier une partie du site, regardez s'il permet à ces personnes d'influencer le robots.txt. Je suis preneur d'exemples.

Une autre solution (qui ne serait pas forcément exclusive du robots.txt mais complémentaire) serait d'inclure les préférences d'utilisation dans le contenu lui-même. C'est ce que permet l'élément HTML <meta> ou le format XMP pour les images. Des formats comme XML ou JSON permettraient certainement d'ajouter ces préférences d'utilisation, qui ont l'avantage de forcément voyager avec le contenu, contrairement au robots.txt. Évidemment, cela ne marchera pas si ces méta-données sont retirées par le programme de collecte (pas forcément pour des raisons malveillantes, cela peut être pour diminuer la taille des données). Et certains formats ne se prêtent pas à cette inclusion des préférences d'utilisation, comme le texte brut, ou comme les contenus qui ont plusieurs auteurs (pensez à un fil de discussion sur les réseaux sociaux).

Une autre solution serait de placer les préférences d'utilisation dans un registre, extérieur aux œuvres, comme cela se fait souvent pour, par exemple, la musique ou les photographies. C'est plus robuste que l'inclusion de métadonnées mais ça passe mal à l'échelle de l'Internet (les registres existants avaient été conçus pour des écosystèmes plus petits et relativement fermés).

Enfin, parmi les difficultés, il faut noter qu'exprimer préférences et conditions d'utilisation un peu fines nécessite de disposer d'un vocabulaire (par exemple pour décrire les différentes techniques qui sont regroupées sous le terme marketing et flou d'« IA ») et qu'il n'existe pas de vocabulaire standard. Ce serait un tâche difficile que d'en établir un (un travail est en cours, dans draft-ietf-aipref-vocab). Je me souviens d'une réunion IETF où il y avait eu un long débat sur la question de savoir si la traduction rentrait dans la catégorie « IA générative » (après tout, elle génère des textes…).

La section 3 du RFC, en conclusion, essaie de synthétiser et d'identifier les points sur lesquels l'IETF pourrait travailler. L'atelier avait un relatif consensus sur le fait que la situation actuelle est mauvaise et que le principal outil technique disponible, robots.txt, ne convient pas. Les pistes de travail discutées ont été :

  • Améliorer robots.txt ou bien développer un meilleur système d'attachement aux sites Web,
  • Définir des attachements pour les protocoles IETF (par exemple dans l'en-tête HTTP, HTML ou XML dépendant d'un autre organisme),
  • Définition d'un vocabulaire commun (le groupe de travail IETF aipref y travaille),
  • Description de comment les différentes techniques (attachées au site Web ou bien attachées au contenu) se combinent.

Par contre, le consensus était que les points suivants n'étaient pas du ressort de l'IETF ou ne pouvaient pas, pour l'instant, faire l'objet d'un travail concret :

Notez qu'un résumé de l'atelier avait été publié juste après. Et, sinon, vous pouvez regarder l'intéressant site Web « Dealing With Bots » et, sur les projets de contrôle de l'accès aux ressources et leurs risques, l'excellent article « No One Should Control the Internet After AI: Freedom to Build Cleopatra GPT ».


Téléchargez le RFC 9969


L'article seul

RFC 9991: Domain-Based Message Authentication, Reporting, and Conformance (DMARC) Failure Reporting

Date de publication du RFC : Mai 2026
Auteur(s) du RFC : S. Jones (DMARC.org), A. Vesely (Tana)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dmarc
Première rédaction de cet article le 20 mai 2026


DMARC (RFC 9989) permet de demander l'envoi, par les destinataires des messages, de rapports indiquant les éventuels problèmes notés, afin de diminuer le nombre de faux positifs (messages légitimes incorrectement considérés comme invalides). Cette demande de rapports se fait en ajoutant l'option ruf à l'enregistrement DMARC. Ce RFC décrit ces rapports.

Il y a au moins deux raisons de demander ces rapports :

  • Comprendre pourquoi certains des messages qu'on envoie sont classés comme invalides alors qu'ils ne devraient pas l'être. On va donc analyser des rapports concernant des messages qu'on a réellement envoyés.
  • Détecter les tentatives d'usurpation du domaine. On va donc analyser des rapports concernant des messages qu'on ne connaissait pas, et qu'un méchant a envoyés.

Notez qu'il existe aussi des rapports agrégés (RFC 9990, avec un format très différent, fondé sur XML) et qu'on demande parfois des rapports individuels parce qu'on note dans les rapports agrégés qu'il y a beaucoup d'erreurs et qu'on voudrait comprendre leur origine.

Le format normalisé ici dérive du format ARF (Abuse Reporting Format, RFC 6591), qui décrivait les rapports pour les problèmes SPF et DKIM. L'option ruf dans l'enregistrement DMARC (RFC 9989, section 4.7) indique à quelle adresse de courrier le rapport doit être envoyé. Voici par exemple l'enregistrement DMARC de afnic.fr :

dig +short _dmarc.afnic.fr TXT
"v=DMARC1; p=quarantine; pct=100; ruf=mailto:dmarc-feedback@afnic.fr; rua=mailto:dmarc-feedback@afnic.fr; fo=1"

Vous voyez le ruf ? Il indique que les rapports doivent être envoyés à dmarc-feedback@afnic.fr. Attention, j'ai écrit « doivent » mais, évidemment, les récepteurs de courrier ne sont pas obligés d'envoyer ces rapports, qui peuvent leur coûter des ressources et poser des problèmes de vie privée.

Pour DMARC, notre RFC ajoute au format du RFC 6591 les champs (section 4, ils sont listés dans un registre IANA) :

  • Identity-Alignment:, qui liste les mécanismes d'authentification où il n'y a pas d'alignement avec l'expéditeur,
  • Delivery-Result:,
  • DKIM-Domain:, et quelques autres au sujet de DKIM,
  • SPF-DNS:.

Il y a un autre piège avec les rapports, c'est la possibilité d'indiquer dans ruf l'adresse de quelqu'un d'autre, pour l'embêter avec beaucoup de rapports qui ne le concernent pas. La section 4 du RFC 9990 explique les précautions que devrait prendre un receveur de courrier avant d'envoyer un rapport vers une adresse qui n'est pas dans le domaine concerné, comme de tester le sous-domaine _report._dmarc. (Dans l'exemple afnic.fr plus haut, il n'y avait pas de problème, le destinataire des rapports est dans le domaine concerné.)

J'ai mentionné un peu plus haut la question de la vie privée. Les rapports détaillés, contrairement à leurs copains agrégés du RFC 9990, peuvent être très indiscrets, notamment parce qu'ils contiennent souvent des données personnelles, par exemple dans les champs indiquant l'expéditeur et le destinataire. Et il ne suffit pas de se dire « Bon, de toute façon, le gestionnaire du système envoyeur avait accès au message quand il est parti de son système » car le message a pu être transmis et re-transmis et le rapport donnera des informations sur des destinataires finaux. Une section 7, trés détaillée, couvre donc ce problème. Elle note par exemple que beaucoup de gros receveurs de courrier n'envoient pas du tout de rapport individuel, seulement des rapports agrégés. Et elle recommande que, même si on envoie les rapports, on en supprime les éléments les plus sensibles (voir le RFC 6590).

Enfin, à envoyer un rapport par message, on noiera l'expéditeur supposé sous des rapports qui concerneront des spams envoyés en nombre. Donc, prudence.

Un point amusant, que je vois pour la première fois dans un RFC : ce RFC 9991 recommande de modifier les URL présents dans les rapports en remplaçant http par hxxp. Cette convention est assez courante dans le monde de la sécurité Internet, pour éviter qu'un humain ne clique trop vite sur un lien malveillant.

L'annexe A du RFC donne un exemple de rapport, je ne montre ici que la partie MIME qui concerne le rapport proprement dit¸:

   --=_mime_boundary_
   Content-Type: message/feedback-report
   Content-Transfer-Encoding: 7bit

   Feedback-Type: auth-failure
   Version: 1
   User-Agent: DMARC-Filter/1.2.3
   Auth-Failure: dmarc
   Authentication-Results: gen.example;
     dmarc=fail header.from=consumer.example
   Identity-Alignment: dkim
   DKIM-Domain: consumer.example
   DKIM-Identity: @consumer.example
   DKIM-Selector: epsilon
   Original-Envelope-Id: 65E1A3F0A0
   Original-Mail-From: author=gen.example@forwarder.example
   Source-IP: 192.0.2.2
   Source-Port: 12345
   Reported-Domain: consumer.example
  

Le message prétend venir de consumer.example mais aucune signature DKIM n'est valide, sans doute suite à des modifications chez forwarder.example ou bien parce que la clé DKIM n'a pu être récupérée dans le DNS.

Apparemment, OpenDKIM est capable de générer ces rapports, mais je n'ai pas testé.


Téléchargez le RFC 9991


L'article seul

RFC 9989: Domain-based Message Authentication, Reporting, and Conformance (DMARC)

Date de publication du RFC : Mai 2026
Auteur(s) du RFC : T. Herr (Valimail), J. Levine (Standcore)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dmarc
Première rédaction de cet article le 20 mai 2026


DMARC est une technique d'authentification du courrier électronique qui permet à un domaine d'indiquer quelle est sa politique de sécurité vis-à-vis des messages dont l'expéditeur (le champ From: de l'en-tête) indique ce domaine. Il donne au gérant du domaine la possibilité d'annoncer sa politique de sécurité « tous les messages de ce domaine sont authentifiés (via SPF ou DKIM) ». Typiquement, DMARC est le couronnement d'une démarche de sécurité du courrier, ce qu'on annonce quand on a bien tout authentifié. Par contre, attention, en authentifiant la donnée visible par les utilisateurs et pas les données techniques, il casse certains usages du courrier. DMARC était à l'origine normalisé dans le RFC 7489, que ce nouveau RFC remplace. Mais rassurez-vous si vous avez déjà déployé DMARC : les changements ne sont pas radicaux. Le principal est le nouvel algorithme pour trouver l'enregistrement DMARC pertinent (celui à l'apex du domaine enregistré).

Revenons sur les problèmes de sécurité du courrier électronique. Un message typique, tel que normalisé par le RFC 5322, comprend dans son en-tête ce genre d'informations :


Date: Wed, 18 Mar 2026 17:28:36 +0800
From: Jiankang Yao <yaojk@cnnic.cn>
To: 125attendees@ietf.org
Subject: [125attendees] Wednesday 8:00 pm, Shenzhen light show for IETF 125
X-Mailer: iPhone Mail (21D61)
[et bien d'autres]    

  

Une qui nous intéresse particulièrement est l'expéditeur. Cette notion est plus compliquée qu'il n'y parait (il y a plusieurs définitions possibles de « expéditeur ») mais pour DMARC, c'est simple : le champ qui nous intéresse est uniquement le From: (section 3.6.2 du RFC 5322). C'est en effet celui qui est typiquement affiché par les MUA, et c'est celui que DMARC va protéger. On l'appelle souvent RFC5322-From pour le distinguer de celui qui apparait dans l'enveloppe du courrier, le RFC5321-From (et qui n'est pas montré dans mon exemple).

Les techniques d'authentification existantes avant DMARC, SPF (RFC 7208) et DKIM (RFC 6376), n'authentifient pas ce champ mais d'autres (le RFC5321-From pour SPF et le domaine indiqué dans la signature pour DKIM), qui ne sont pas en général affichés à l'utilisateurice final·e. DMARC va permettre d'utiliser ces deux techniques, SPF et DKIM, pour les appliquer à l'expéditeur (RFC5322-From). Un test DMARC réussi signifie que SPF ou DKIM a réussi mais aussi que le domaine authentifié par SPF ou DKIM est le même que celui présent dans le From: ; on parle d'alignement du nom de domaine. Cela ne va pas de soi car il y a de nombreux usages légitimes du courrier où ces domaines ne sont pas alignés, et DMARC casse donc ces usages.

Dans les exemples de messages reçus après traitement par DMARC, on va regarder les champs Authentication-Results. Normalisés dans le RFC 8601, ils sont ajoutés par le récepteur et indiquent le résultat d'une technique d'authentification. Ici, un exemple où SPF et DKIM ont marché (tous les exemples ici sont réels, issus de mes boites aux lettres):


Authentication-Results: mail.bortzmeyer.org; dmarc=pass (p=quarantine dis=none) header.from=afnic.fr
Authentication-Results: mail.bortzmeyer.org;
        dkim=pass (2048-bit key; secure) header.d=afnic.fr header.i=@afnic.fr header.a=rsa-sha256 header.s=afnic-20240601
        header.b=bdGM6W8o;
        dkim-atps=neutral
Authentication-Results: mail.bortzmeyer.org; spf=pass (sender SPF authorized) smtp.mailfrom=afnic.fr
        (client-ip=2001:67c:2218:10::51:1; helo=mx1.nic.fr; envelope-from=quelqu.un@afnic.fr; receiver=bortzmeyer.org)

Le domaine afnic.fr a bien été authentifié, à la fois par SPF et par DKIM, et DMARC passe donc (le champ From: n'est pas montré ici mais il indiquait bien une adresse @afnic.fr).

Il est également important de se souvenir que DMARC ne fait qu'authentifier le domaine, il ne garantit pas que le message soit sincère, sûr, utile ou quoi que ce soit d'autre. Si on reçoit un message de Trump, on peut prouver qu'il vient bien de whitehouse.gov mais il sera quand même certainement mensonger. C'est pour cela qu'il est absurde, comme on le lit dans certains forums, de dire « je ne comprends pas, j'ai bien mis un enregistrement DMARC et mes messages finissent quand même dans la boite Spam » : les spammeurs font du DMARC, eux-aussi.

L'inverse est vrai aussi, un message légitime et désiré peut parfaitement échouer au test DMARC, d'autant plus, que, comme indiqué plus haut, DMARC casse plusieurs usages légitimes du courrier. Il vaut donc mieux ne pas refuser un message uniquement sur la base d'un échec DMARC mais traiter cet échec comme une indication parmi d'autres. Ce RFC 9989 insiste sur ce point (notamment sa section 7), en mentionnant également le RFC 7960, qui détaille les problèmes venant de l'utilisation de DMARC.

La section 2 du RFC détaille le cahier des charges de DMARC. Comme avec toutes les solutions de sécurité, il faut garder en tête ce cahier des charges lorsqu'on évalue DMARC. Aucune solution de sécurité n'est parfaite : elles collent simplement plus ou moins bien à leur cahier des charges. Celui-ci, en résumé, est :

  • Permettre aux gérants de noms de domaine d'annoncer leur politique d'authentification du courrier et leurs souhaits quant au traitement du courrier qui ne passerait pas cette authentification.
  • Fonctionner dans le contexte de l'Internet (donc, sans autorité centrale).
  • Traiter uniquement les cas où le message malveillant copie exactement un nom de domaine qu'on gère. En d'autres termes, les usurpations utilisant des noms qui ressemblent (goog1e.com au lieu de google.com) sont hors-sujet.
  • Authentifier uniquement le nom de domaine qui est dans l'adresse (RFC 5322, section 3.4). En d'autres termes, dans un From: « Emmanuel Macron <emmanuel5561@gmail.com>, DMARC ne se préoccupe que du gmail.com, pas du emmanuel5561.
  • Authentifier uniquement l'adresse, pas le nom affiché (« Emmanuel Macron » dans l'exemple ci-dessus). La section 11.4 rappelle ce point très important.

Un bon cahier des charges a une autre section très importante : celle des non-objectifs, des choses qu'on n'essaie pas de faire. (Regardez les documents commerciaux : ils n'ont jamais l'honnêteté de lister ce qu'ils ne font pas.) Pour DMARC :

  • Il ne dit évidemment rien sur les domaines qui ont choisi de ne pas avoir d'enregistrement DMARC dans le DNS. Dit autrement, DMARC est opt-in.
  • Il n'essaie pas de s'occuper des autres informations présentes dans l'en-tête (comme Reply-To: ou Date:).
  • Il ne s'occupe pas des tricheries sur le nom affiché, comme dans l'exemple « Emmanuel Macron » plus haut (ou bien, tiré de ma boite Spam From: "amendes.gouv.fr" <amendes-gouv-nepasrepondre.C9717A5D-EA39-D865-765A6C98B4A0BB03@therugest.com>). Tant pis pour ceux et celles qui s'obstinent à utiliser un logiciel qui, par défaut, n'affiche que ce nom (Outlook fait encore ça). Relisez la section 11.4 du RFC.
  • Et naturellement, DMARC ne s'occupe pas du contenu du message, qu'il soit mensonger (« je suis l'ex-ministre des finances du Nigéria ») ou malveillant (logiciel qui va tenter d'exploiter une faille de sécurité pour prendre le contrôle de votre ordinateur).

Par exemple, voici un spam, prétendant venir de l'ANTAI mais qui passe tous les tests (le nom de domaine dans l'adresse n'a rien à voir avec l'ANTAI mais beaucoup d'utilisateurs n'y feront pas attention, et ce nom avait bien un enregistrement DMARC) :


Authentication-Results: mail.bortzmeyer.org; dmarc=pass (p=quarantine dis=none) header.from=rtm.gov.my
Authentication-Results: mail.bortzmeyer.org;
        dkim=pass (2048-bit key; secure) header.d=rtm.gov.my header.i=@rtm.gov.my header.a=rsa-sha256 header.s=rtm
        header.b=MaKApt+s;
        dkim-atps=neutral
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=rtm.gov.my; s=rtm; t=1775231898; x=1775836698; darn=bortzmeyer.org;
        h=content-transfer-encoding:mime-version:subject:message-id:to:from
        :date:from:to:cc:subject:date:message-id:reply-to;
        bh=L6c3f6fDBrQyBjkO1RiiF3vHHNmYjLDd4A1urn+cNJg=;
        b=MaKApt+s0vgkVsgh3VoFE0/MgCt8ilWkghyQKUbj2NnhgInADkR8G3aW0UbklkuDDV
	…
Authentication-Results: mail.bortzmeyer.org; spf=pass (sender SPF authorized) smtp.mailfrom=rtm.gov.my
        (client-ip=2607:f8b0:4864:20::f64; helo=mail-qv1-xf64.google.com; envelope-from=antai.gouv.fr@rtm.gov.my;
        receiver=bortzmeyer.org)
Subject: ACTION REQUISE SOUS 24H
From: "Antai.gouv.fr" <Antai.gouv.fr@rtm.gov.my>

La section 3 du RFC décrit les termes utilisés par DMARC, entre autres :

  • Domaine de l'auteur : ce qui est après l'arobase dans l'adresse indiquée par le champ From: de l'en-tête (rappel : pas celui de l'enveloppe).
  • Domaine DKIM : celui indiqué par le paramètre d= dans la signature DKIM (rappel : le domaine DKIM peut n'avoir aucun rapport avec l'adresse de l'en-tête ou avec celle de l'enveloppe).
  • Domaine SPF : ce qui est après l'arobase dans l'adresse indiquée par le champ From de l'enveloppe (rappel : pas celui de l'en-tête). Dans le contexte de DMARC, ce terme ne s'applique pas au domaine indiqué dans la commande EHLO (ou HELO) de SMTP.
  • Titulaire du domaine : la personne physique ou morale qui décidé d'enregistrer un nom de domaine et qui le gère ensuite.
  • Domaine organisationnel : le domaine au sommet du sous-arbre qui a la même administration (le RFC 5598 est une bonne lecture ici). Ainsi, bortzmeyer.org est le domaine organisationnel de mail.bortzmeyer.org. En pratique, c'est souvent le domaine enregistré du RFC 9499, domaine qui a été enregistré auprès d'un registre.
  • Suffixe public : domaine où le public peut enregistrer un sous-domaine, par exemple .fr ou eu.org. Ainsi, dans mail.foobar.eu.org, foobar.eu.org est le domaine organisationnel et eu.org le suffixe public, ou domaine d'enregistrement.

Armé de cela (mais il y a d'autres termes, que je présenterai au fur et à mesure), on peut passer à la section 4, qui explique les concepts importants.

DMARC permet à un titulaire de domaine d'annoncer sa politique d'authentification d'un domaine de l'auteur d'un courrier. On n'authentifie donc que le domaine, pas toute l'adresse (je l'ai déjà dit mais c'est important). Et DMARC ne s'intéresse qu'à ce qu'il appelle le domaine de l'auteur, donc le From: dans l'en-tête (également appelé « RFC5322.From »). DMARC annonce juste une politique, l'authentification est faite avec SPF (RFC 7208) ou DKIM (RFC 6376).

Un concept essentiel dans DMARC est celui d'alignement. Il y a alignement quand le domaine authentifié par SPF (celui de l'enveloppe, le « RFC5321.From ») ou par DKIM (celui indiqué dans le d= de la signature) coïncide avec le domaine de l'auteur (celui du From: de l'en-tête). Plus précisément, il peut y avoir un alignement strict (les deux noms de domaine sont identiques) ou relâché (les deux noms sont dans le même domaine organisationnel). Le choix se fait dans l'enregistrement DMARC publié.

Justement, on le publie où ? Via le DNS, dans un enregistrement de type TXT, publié dans le sous-domaine _dmarc, par exemple :

% dig +short _dmarc.proton.me TXT
"v=DMARC1; p=quarantine; fo=1; aspf=s; adkim=s;"
  

On bénéficie ainsi de toute l'infrastructure, très fiable et éprouvée, du DNS. Ce sous-domaine _dmarc figure dans le registre IANA des noms commençant par un trait bas, créé par le RFC 8552.

Au passage, si vous voulez voir (ou enregistrer), sur un serveur DNS faisant autorité, uniquement les requêtes DNS pour le sous-domaine _dmarc, dnscap permet de le faire facilement :

% dnscap -g -x _dmarc   
  

(Je triche un peu, le -x attrape en effet davantage que cela mais ça suffit en première approximation.)

Le format exact de l'enregistrement DMARC utilise des doublets clé=valeur, comme celui de DKIM. (Sa description formelle, en ABNFRFC 5234 - est dans la section 4.8.) Les clés possibles figurent dans un registre IANA. Les plus courantes sont :

  • v : c'est obligatoirement le premier doublet clé=valeur et il indique la version de DMARC, actuellement DMARC1.
  • p : c'est la clé la plus importante, celle qui indique la politique à appliquer aux messages qui ne passent pas la validation DMARC. Une valeur reject indique que le titulaire du domaine recommande le rejet des messages invalides (cela ne peut être qu'une recommandation, car le récepteur du courrier reste évidemment libre de sa politique). quarantine recommande une mise en attente quelque part (un dossier « peut-etre-spam » par exemple). Enfin, none indique qu'on recommande de ne rien faire. Cela peut être utilisé quand on craint les conséquences de DMARC sur certains usages (cf. RFC 7960) mais qu'on pense que certains récepteurs vont mal traiter les messages des domaines sans DMARC. Ou bien cela peut être utile dans certains audits « de sécurité » qui demandent un enregistrement DMARC, n'importe lequel. Enfin, un p=none peut être utilisé lors d'un déploiement progressif de DMARC, quand on veut juste tester, avant de publier une politique plus fasciste. Comme DMARC permet de solliciter l'envoi de rapports d'erreur, un p=none peut être accompagné d'une telle sollicitation.
  • sp : comme p mais pour les sous-domaines du domaine qui a l'enregistrement DMARC. Les valeurs possibles sont les mêmes que pour p.
  • np : nouveauté, initialement décrite dans le RFC 9091. C'est le traitement à appliquer aux sous-domaines non-existants du domaine pour lequel une politique DMARC est publiée. Les valeurs possibles sont les mêmes que pour p.
  • ruf : c'est ainsi qu'on sollicite l'envoi de rapports d'erreur. On indique les URI où envoyer ces rapports (souvent des URI de plan mailto:, pour demander des rapports par courrier). Le format des rapports est spécifié dans les RFC 9991, RFC 6651 et RFC 6552. ruf demande un rapport par message invalide, rua permet de demander des rapports agrégés. Leur format figure dans le RFC 9990.
  • psd : nouveauté de notre RFC, s'il a la valeur y, il indique que le domaine est un suffixe public (PSD : Public Suffix Domain), c'est-à-dire un domaine dont les sous-domaines peuvent être délégués à d'autres entités (comme c'est le cas de .re ou eu.org).
  • fo : diverses options pour la génération de rapports d'erreur.
  • adkim et adpf : tous les deux peuvent prendre la valeur s (strict) ou r (relâché, ou laxiste). Ils indiquent si l'alignement avec l'identificateur authentifié par DKIM ou SPF doit être strict (les deux identificateurs sont rigoureusement identiques) ou relâché (l'identificateur authentifié peut se contenter d'être dans le même domaine enregistré que celui qui a un enregistrement DMARC). Par défaut, DMARC est laxiste. Notez que cela permet à quelqu'un qui peut utiliser un sous-domaine de se faire authentifier comme étant dans l'apex (section 11.8 du RFC). Demander un alignement strict résout ce problème (mais impose que vous controliez bien les sous-domaines).

Les clés inconnues doivent être ignorées, ce qui permet d'en ajouter de nouvelles sans tout casser. La politique pour un éventuel ajout est « Spécification nécessaire » (RFC 8126).

On a parlé du domaine organisationnel, l'apex du domaine testé par DMARC. C'est en fait une notion administrative, pas technique, ce qui fait que ce domaine organisationnel n'est pas évident à identifier dans le DNS. Pour le trouver, l'ancien RFC, le RFC 7489, suggérait de faire appel à une liste de suffixes publics, comme la PSL (rappel : il n'existe pas de liste officielle). Notre nouveau RFC suggère une autre méthode, en remontant l'arbre des noms de domaine. On commence par le domaine qu'on veut authentifier, et, si on n'y trouve pas de politique DMARC, on essaie son domaine parent et ainsi de suite, jusqu'à ce qu'on trouve un enregistrement DMARC. Ainsi, pour truc.machin.example.com, on essaiera successivement _dmarc.truc.machin.example.com, _dmarc.machin.example.com, _dmarc.example.com et enfin _dmarc.com. La dernière requête permet donc au registre de .com de définir une politique DMARC qui s'appliquera à tous les domaines sans politique DMARC. C'est très dangereux, pour les raisons expliquées dans le RFC 1535 mais cela permet de se passer de liste de suffixes publics, et c'est plus souple pour le cas des grosses organisations, qui peuvent avoir des politiques DMARC dans des sous-domaines qui ne sont pas délégués.

Notez que l'éventuelle présence de la clé psd va compliquer les choses mais je n'ai pas vraiment le courage de détailler ici l'algorithme complet.

Maintenant, voyons quels sont les acteurs d'un déploiement de DMARC. D'abord, le titulaire du domaine qui envoie des messages. Il doit publier un enregistrement SPF à l'apex du domaine. Il doit signer les courriers sortants avec DKIM (ce qui implique de publier les clés publiques DKIM dans le DNS). Notez que DMARC n'a pas besoin de SPF et de DKIM, un seul des deux suffit mais, bon, autant tout faire. Il a intérêt à créer une boite dédiée pour recevoir les rapports sur les messages invalides. Le titulaire doit enfin publier dans le DNS l'enregistrement DMARC (celui qui commence par _dmarc). Au début, on utilise typiquement une politique indulgente (p=none). Puis on teste.

Comment teste t-on ? En lisant les rapports indiquant des messages invalides (RFC 9990 et RFC 9991). Les rapports agrégés sont du XML, assez lisibles par un humain mais, en pratique, on préférera typiquement utiliser un programme qui les synthétisera dans une forme plus lisible. (Je n'utilise pas actuellement un tel programme, car je n'en ai pas trouvé. Il faut qu'il tourne en local - pas question de confier les rapports à un tiers - et ne nécessite pas d'installer toute une batterie de cuisine PHP et MariaDB.) Une fois qu'on a trouvé les problèmes (une application oubliée dans un coin qui envoie des courriers sans passer par les serveurs centraux…) et qu'on les a corrigés, on peut durcir la politique (p=quarantine, par exemple). Il est raisonnable d'attendre plusieurs semaines, voire mois, pour être sûr d'avoir vu tous les problèmes.

(Et si vous êtes gérant d'un suffixe public - - un domaine sous lequel d'autres entités peuvent enregistrer des noms, demandez-vous si vous devez publier du DMARC avec psd=y. Ce n'est pas obligatoire, cf. section 5.2.)

Et le récepteur du courrier, que doit-il faire ? Il extrait du message le domaine de l'auteur. Il cherche s'il y a un enregistrement DMARC. Il exécute les tests SPF et DKIM. S'il récupère un ou plusieurs domaines authentifiés, il vérifie l'alignement (strict ou relâché). Si au moins un domaine authentifié est aligné avec le domaine de l'auteur, le test DMARC est un succès. Sinon, c'est un échec. Notez bien qu'il n'est pas nécessaire que SPF et DKIM réussissent tous les deux. Si le test DMARC se termine en échec, on applique un traitement, qui dépend de la politique suggérée dans l'enregistrement DMARC, et de la politique propre du receveur. Voici un exemple où DMARC dit que tout s'est bien passé :


From: "Projet Arcadie" <admin@projetarcadie.com>
Authentication-Results: mail.bortzmeyer.org; dmarc=pass (p=none dis=none) header.from=projetarcadie.com
Authentication-Results: mail.bortzmeyer.org;
        dkim=pass (2048-bit key; unprotected) header.d=projetarcadie.com header.i=@projetarcadie.com header.a=rsa-sha256 header.s=alternc
        header.b=plrnZlsJ;
        dkim=pass (2048-bit key) header.d=projetarcadie.com header.i=@projetarcadie.com header.a=rsa-sha256 header.s=alternc
        header.b=m84VgM5U;
        dkim-atps=neutral
Authentication-Results: mail.bortzmeyer.org; spf=pass (sender SPF authorized) smtp.mailfrom=projetarcadie.com (client-ip=91.194.60.11;
        helo=arcadieweb01.octopuce.fr; envelope-from=admin@projetarcadie.com; receiver=bortzmeyer.org)

  

Ici, il y avait un enregistrement SPF (qui autorise l'émetteur SMTP donc cela suffit), deux signatures DKIM, toutes les deux corrects, il y a alignement strict, et donc DMARC passe, il n'y a aucun doute que le domaine émetteur était bien projetarcadie.com. (La politique DMARC était p=none donc un éventuel échec n'aurait sans doute pas eu beaucoup de conséquences.)

Ici, DKIM a échoué (pourquoi ? mystère mais c'est peut-être la faute de SpamAssassin qui a modifié le sujet, il faudrait que je vérifie ma configuration) mais SPF réussit (le message vient bien de Gmail) donc DMARC est content (il s'agissait bien d'un spam, tentative d'escroquerie financière) :


Authentication-Results: mail.bortzmeyer.org;
        dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com
        header.a=rsa-sha256 header.s=20230601 header.b=K6F+sj7y;
        dkim-atps=neutral
Authentication-Results: mail.bortzmeyer.org; dmarc=pass (p=none dis=none) header.from=gmail.com
Authentication-Results: mail.bortzmeyer.org; spf=pass (sender SPF authorized) smtp.mailfrom=gmail.com
        (client-ip=2a00:1450:4864:20::133; helo=mail-lf1-x133.google.com; envelope-from=mrsbalex@gmail.com;
        receiver=sources.org)
From: "Mr. Mike Christopher" <mrsbalex@gmail.com>

Et ici, un échec, SPF est correct, il n'y a pas de signature DKIM et il n'y a pas d'alignement des domaines, la tentative du spammeur pour se faire passer pour saison.co.jp échoue :


From: 株式会社クレディセゾン <admin@saison.co.jp>
Authentication-Results: mail.bortzmeyer.org; dmarc=fail (p=none dis=none) header.from=saison.co.jp
Authentication-Results: mail.bortzmeyer.org; spf=pass (sender SPF authorized) smtp.mailfrom=zh-cht-jjb.com (client-ip=34.130.185.194;
        helo=zh-cht-jjb.com; envelope-from=admin@zh-cht-jjb.com; receiver=bortzmeyer.org)

  

Et ici, l'émetteur tente de faire croire qu'il vient de Gmail mais l'enregistrement SPF de Gmail se termine par un ~all, son adresse IP n'y est pas listée et il n'y a pas de signature DKIM dans le message. Même pas besoin de tester l'alignement puisqu'il n'y a pas de domaine authentifié du tout :


From: Axel.Bouvier <mailrmicro+Axel.Bouvier@gmail.com>
Authentication-Results: mail.internatif.org; dmarc=fail (p=none dis=none) header.from=gmail.com
Authentication-Results: mail.internatif.org; spf=softfail (domain owner discourages use of this host)
        smtp.mailfrom=gmail.com (client-ip=78.246.109.210; helo=gmail225.com;
        envelope-from=mailrmicro+axel.bouvier@gmail.com; receiver=internatif.org)

  

De nombreux autres exemples, avec succès ou échec, figurent dans l'annexe B du RFC.

C'est pas mal si le récepteur de courrier qui fait tourner DMARC en profite pour générer les rapports (RFC 9991), s'ils sont demandés (par un ruf ou un rua dans l'enregistrement DMARC de l'envoyeur). Néanmoins, le RFC note qu'il peut ne pas le faire, s'il craint pour la vie privée (cf. section 10) ou tout simplement si ça lui consomme trop de ressources.

D'ailleurs, le RFC insiste bien sur un point que j'avais déjà mentionné : la décision finale (de livrer le message, ou de le mettre dans le dossier Spam ou de le jeter) revient toujours au destinataire (section 5.4). Celui-ci applique la politique qu'il veut. Il serait ridicule de croire que, parce qu'on a SPF, DKIM et DMARC bien configurés, nos messages seraient systématiquement livrés. Après tout, un spammeur peut en faire autant.

À l'inverse, un récepteur peut parfaitement décider d'acheminer jusqu'à ses utilisateurices un message qui échoue aux testes DMARC, par exemple parce qu'il a lu le RFC 7960 (et la section 7.4 de notre RFC) et qu'il sait que DMARC échoue dans des cas d'usage pourtant légitimes, notamment les listes de diffusion. DMARC fournit de la traçabilité et de la responsabilité, il n'est pas un oracle tout-puissant sur l'authenticité du message.

La section 7 du RFC est surtout intéressante pour les historien·nes et pour les technicien·nes qui veulent comprendre les choix faits par DMARC. C'est un pot-pourri de diverses discussions.

D'abord, SPF. SPF a été conçu pour être utilisable pendant la session SMTP, parfois avant même que l'en-tête du message ait été transmis. Une politique SPF « dure » (se terminant en -all) peut amener au rejet du message avant que DMARC n'ait été évalué. Ainsi, si un message échoue en SPF mais réussit en DKIM, normalement, DMARC réussirait. Mais, si le test SPF mène à un rejet dès la session SMTP, le message n'arrivera pas. Attention donc en configurant vos enregistrements SPF. (Relisez les « M3AAWG Best Practices for Managing SPF Records » et « M3AAWG Email Authentication Recommended Best Practices ».)

Et à propos de rejet précoce (dans le cours de la session SMTP, avant d'avoir accepté le message) : le RFC recommande cette méthode car elle évite la génération d'un avis de non-remise (RFC 3464), avis qui irait sans doute à un innocent si l'adresse était usurpée. Deux façons de mettre en œuvre ce rejet précoce, en renvoyant un code d'erreur (commençant par 5 RFC 5321, section 4.2.5) au client SMTP, qui saura ainsi que son message a été refusé, ou, plus méchamment, en prétendant que le message a bien été reçu (code commençant par 2) mais en le jetant silencieusement. La deuxième solution est évidemment horrible (le serveur SMTP ment, l'émetteur ne sait pas ce qui s'est passé, le déboguage devient très difficile) mais elle est parfois nécessaire pour éviter le backscatter, l'envoi de messages d'erreur à un innocent, une des plaies du spam qui usurpe votre adresse. Et elle évite de donner des informations à quelqu'un qu'on estime être un usurpateur.

Contrairement à ce qu'on voit dans certains articles pro-DMARC imprudents qui promeuvent DMARC sans insister sur ses limites et ses faiblesses, notre RFC précise bien qu'il y a des cas où DMARC pose problème (sections 7.3 et 7.4). Par exemple, citant le RFC 7960, il rappelle que DMARC peut casser des cas d'usage légitimes comme les adresses d'anciens élèves que certaines universités fournissent (en faisant suivre automatiquement le courrier à l'adresse actuelle), comme des alias où le courrier vers une même adresse est distribuée à plusieurs personnes, qui ne sont pas forcément dans le même domaine, ou comme les listes de diffusion. Pour les deux premiers cas, des solutions relativement simples existent (réécrire l'enveloppe pour ne pas casser SPF, ce qui est de toute façon une bonne pratique car l'envoyeur du message ne saurait pas quoi faire si la vraie adresse finale ne marcherait pas) et ne pas du tout toucher au message, pour éviter de casser DKIM), pour les listes de diffusion, c'est plus délicat. En pratique, plusieurs gestionnaires de liste adoptent la solution très intrusive de réécrire le champ From: comme ici dans ce message envoyé à une liste de l'OARC (le vrai From: a été reporté en Reply-To:) :


Authentication-Results: nic.fr;
        spf=pass smtp.mailfrom=dns-operations-bounces@dns-oarc.net;
        dmarc=pass header.from=dns-oarc.net
Reply-To: Walter Russo <walter@secureme.it>
From: Walter Russo via dns-operations <dns-operations@dns-oarc.net>

Le problème est évidemment particulièrement sérieux si on a une politique DMARC restrictive (p=reject) et le RFC conseille fortement dans ce cas de systématiquement signer avec DKIM, pour éviter de compter sur le seul SPF (qui sera cassé par les serveurs qui font suivre un message sans réécrire l'enveloppe). Et il rappelle aux récepteurs de courrier qu'il est très imprudent de rejeter un message sur la seule base de DMARC. Ces consignes, qui ne sont pas toujours respectées par les serveurs actuels, sont cruciales pour le bon fonctionnement du courrier. Le RFC note bien ce problème de filtrage excessif et explique que c'est ce qui a mené plusieurs gestionnaires de liste à tripoter le champ From:, par exemple en changeant le vrai champ bob@example.com en un bob=example.com@user.somelist.example, où on peut toujours retrouver la vraie adresse. (On ajoute également parfois un Reply-To: indiquant la vraie adresse de l'expéditeur, comme dans l'exemple ci-dessus.) Le RFC n'approuve pas cette modification mais note qu'elle est répandue et qu'il faut faire avec. Il existe des solutions techniquement plus propres comme le ARC du RFC 8617 mais que presque personne n'utilise.

En résumé, pour faire du DMARC complet, l'émetteur du courrier devrait idéalement :

  • Produire des messages qui auront un identificateur SPF aligné avec le domaine de l'auteur (une exigence qui me parait très excessive),
  • produire des messages avec une signature DKIM valide et alignée,
  • configurer une boite aux lettres qui recevra les rapports,
  • publier l'enregistrement DMARC (je rajoute : après avoir soigneusement testé les trois points précédents),
  • ne pas compter sur le seul SPF.

Et le receveur devrait idéalement :

  • Tester s'il y a un enregistrement DMARC pour le domaine de l'auteur,
  • tester s'il y a des identificateurs authentifiés par SPF ou DKIM,
  • tester si au moins l'un d'entre eux est aligné avec le domaine de l'auteur,
  • déterminer ainsi si le résultat final est pass ou fail,
  • envoyer des rapports, si demandé,
  • ne pas rejeter des messages juste parce qu'il y a eu un échec DMARC, même si la politique de l'émetteur est p=reject.

La section 11 du RFC creuse les questions de sécurité. Que faut-il savoir pour utiliser DMARC de manière sûre ? D'abord, DMARC est évidemment dépendant des mécanismes d'authentification utilisés, SPF et DKIM (le groupe de travail IETF avait même envisagé de supprimer SPF, considéré comme trop permissif). Si vous publiez votre clé privée DKIM, DMARC ne pourra rien pour vous. Et SPF, DKIM et DMARC dépendent tous les trois du DNS donc il est crucial de gérer ses serveurs DNS sérieusement. Malheureusement, les RFC sur ces trois techniques n'imposent pas DNSSEC (RFC 9364) mais ils devraient : sans DNSSEC, l'envoi de fausses informations dans le DNS est plus facile. Compter sur SPF, DKIM et DMARC sans avoir DNSSEC me semble peu sérieux mais, bon, le vrai but de la cybersécurité est de réussir l'audit de conformité, pas d'améliorer la sécurité concrète. D'autre part, l'examen du trafic DNS (qui n'est pas limité aux deux parties qui s'envoient du courrier) donne des informations sur le trafic. Utiliser DoT (RFC 7858) ou DoH (RFC 8484) peut donc être une bonne idée.

Comme toujours en ingéniérie, d'autres solutions techniques auraient été possibles. L'annexe A de notre RFC examine certaines de ces alternatives et explique pourquoi elles n'ont pas été retenues. Ainsi, on aurait pu utiliser S/MIME (RFC 8551) pour signer le message, ajoutant cette technique à SPF et DKIM. Mais S/MIME a un cahier des charges différent de celui de DMARC, il vise plutôt à une authentification de bout en bout du message entier. Et puis il faut bien constater qu'en dehors de quelques environnements bureaucratiques fermés, personne n'utilise S/MIME. C'est en partie dû à la nécessité d'une PKI, dont le RFC note qu'elle a été souvent promise mais ne s'est jamais matérialisée. (Curieusement, le RFC ne cite pas OpenPGPRFC 9580 - qui est pourtant nettement plus utilisé que S/MIME.)

Une autre décision de conception cruciale de DMARC est le fait d'accepter n'importe quelle technique d'authentification ; SPF ou DKIM, c'est pareil pour lui. Il a pourtant été souvent proposé de permettre au titulaire du domaine de spécifier, dans l'enregistrement DMARC, de préciser qu'on ne veut que SPF, ou que DKIM. Mais DMARC est assez compliqué comme cela et la décision a finalement été de permettre l'une ou l'autre des méthodes d'authentification. Débrouillez-vous pour qu'au moins une (et de préférence les deux) fonctionne.

Un point essentiel de DMARC est qu'il authentifie l'expéditeur (plus exactement son alignement) en considérant que l'expéditeur est indiqué par le champ From: de l'en-tête. Cela casse bien des usages légitimes (comme les listes de diffusion). Ne serait-il pas préférable d'authentifier un champ plus technique comme Sender: (RFC 5322, section 3.6.2) ? Cela avait même été spécifié dans le RFC 4870, puis retiré. Finalement, le choix a été de se concentrer sur From: puisqu'il est le seul à être toujours montré à l'utilisateur. (SPF, comme DKIM, peuvent authentifier un identificateur que l'utilisateur ordinaire ne voit pas.)

Notre RFC 9989 introduit une nouvelle clé, np, qui spécifie la politique à appliquer aux sous-domaines non-existants du domaine authentifié. Cela soulève le problème de la définition de non-existant. Le RFC dit que cela inclut les réponses NXDOMAIN (No Such Domain), évidemment, mais pas forcément les réponses NOERROR où la section Réponses est vide, car le nom existe mais ne contient ni enregistrement MX, ni enregistrement d'adresse (A ou AAAA). Ce test de la présence de certains types d'enrgeistrement est déjà couramment utilisé en pratique (il n'y a aucune raison d'accepter du courrier d'un domaine qui ne permettrait pas les réponses) mais le RFC ne l'impose pas. Et, sinon, le RFC rappelle que, si une requête pour un domaine renvoie NXDOMAIN, tous ses sous-domaines n'existent pas non plus (RFC 8020).

Évidemment, un débat ancien et récurrent pour DMARC est celui des frontières organisationnelles. Comment sait-on si cis.cnrs.fr dépend de la même autorité que cnrs.fr (ou bien pick.eu.org et eu.org). Il n'y a pas de réel moyen de trouver cette information dans le DNS. (On peut trouver les frontières techniques en demandant l'enregistrement de type SOA. Mais cela ne donne pas les frontières administratives. gouv.fr n'est pas géré par la même organisation que fr, même s'ils sont dans la même zone.) Des efforts ont été faits à l'IETF pour résoudre ce problème mais sans résultat. L'ancien RFC DMARC, le RFC 7489 suggérait d'utiliser une liste de suffixes d'enregistrement mais notre RFC 9989 a finalement préféré une autre méthode, la « montée à l'arbre » (on grimpe l'arbre des noms de domaine, cherchant des enregistrements DMARC).

Passons à la pratique, maintenant. OpenDMARC est aujourd'hui très répandu, aussi bien côté envoyeur que côté récepteur, et apparait souvent dans les articles de marketing « comment s'assurer que votre spam pardon votre newsletter sera bien livrée partout ». Sur mon serveur de messagerie personnel, j'annonce une politique DMARC et, pour valider les messages entrants, j'utilise OpenDMARC (notez que son développement semble bien avoir stoppé et qu'il y a donc peu de chances qu'il prenne en compte les nouveautés de ce RFC). Ma configuration est très proche de celle par défaut :


Socket inet:54321
# Les autres ont leur valeur par défaut	 

  

Et Postfix le lance ainsi, juste après DKIM :

smtpd_milters = unix:run/opendkim.sock, inet:localhost:54321
  

Et c'est ainsi que sont produits les champs Authenticated-Results: que vous avez vus.

Pour apprendre DMARC, je recommande l'excellent et interactif https://www.learndmarc.com/. Pour tester votre configuration, comme d'habitude, il existe de nombreux services.

Le chemin vers ce RFC a été très long (plusieurs années). L'annexe C du RFC résume les changements depuis le précédent RFC, le RFC 7489. Les principaux sont :

  • Nouvel algorithme (« montée dans l'arbre » pour trouver le domaine organisationnel, au lieu de l'utilisation d'une liste de suffixes publics). C'est la suite du RFC 9091.
  • Introduction de nouveaux concepts comme le PSD (Public Suffix Domain) et le PSO (Public Suffix Operator).
  • Le RFC n'est plus seulement « Pour information », il passe sur le chemin des normes.
  • Plusieurs nouvelles clés sont possibles dans l'enregistrement DMARC : np, psd et t.
  • Mise à l'écart de certaines clés comme pct (partiellement remplacé par t).
  • Résolution des erreurs du précédent RFC.

Les articles suivants sont de bonnes lectures pour les nouveautés de DMARC :


Téléchargez le RFC 9989


L'article seul

RFC 15: Network Subsystem for Time Sharing Hosts

Date de publication du RFC : Septembre 1969
Auteur(s) du RFC : C. Stephen Carr (UTAH)
Statut inconnu, probablement trop ancien
Première rédaction de cet article le 15 mai 2026


Faisons un peu un tour dans le passé avec ce vieil RFC, que j'ai lu pour préparer une intervention consacrée à l'Arpanet. Il normalise le protocole de connexion à distance qui est l'ancêtre de telnet.

La seule utilisation prévue de l'Arpanet, à ses débuts, était la connexion à un ordinateur distant, avec éventuellement un peu de transfert de fichiers. On pensait même que l'avenir était aux ordinateurs ultra-spécialisés, chaque université en hébergeant un, et Arpanet permettant un accès facile depuis les autres campus. Arpanet étant prévu dès le début pour des ordinateurs hétérogènes, il fallait un protocole standard pour cette connexion. En cinq pages (les RFC étaient courts, à l'époque), c'était fait.

Comme tout les RFC de l'époque, il peut être difficile à lire car la terminologie a changé. Un subsystem est tout simplement un programme généraliste, distinct des programmes « métiers » écrits par l'utilisateur. C'est le cas de telnet. Et un teletype est un terminal pas intelligent. Quant au time sharing, c'est du multi-tâches, auquel on est tellement habitués aujourd'hui qu'on ne pense plus à lui donner un nom. Et en ce temps, le RFC ne spécifiait pas seulement le protocole mais aussi le mode d'emploi du programme (telnet) qui le mettait en œuvre. Et encore, ici, le protocole n'est défini que par un exemple, où un programme tournant sur un PDP-10 se connecte sur un SDS 940. Il utilise les fonctions de base définies par le RFC 11 (ouvrir une connexion principale, une connexion auxiliaire, envoyer des données, etc). Le protocole n'a quasiment aucune des fonctions du futur « vrai » telnet (annoncé en conclusion du RFC et qui sera normalisé dans le RFC 764, bien des années après). Il se contente de faire passer des données entre les deux machines. Ici, les deux premières commandes sont des commandes locales au PDP-10, et la dernière une commande locale au 940. Les commandes préfixées par un astérisque sont celles de telnet :

.LOGIN
.R TELNET

*ESCAPE CHARACTER IS #
*CONNECT TO SRI

@LOGIN CARR.

Notez que notre RFC 15 inclut même un mécanisme de transfert de fichiers (FTP n'existait pas à l'époque), profitant du fait que le protocole de base de l'Arpanet (celui décrit dans le RFC 11) permettait d'ouvrir, en plus de la connexion principale, une connexion auxiliaire.

J'aurais bien aimé lire le code source de programmes mettant en œuvre ce RFC 15 mais je n'ai pas trouvé (j'ai très peu cherché donc, si vous avez une idée…).


Téléchargez le RFC 15


L'article seul

La faille de sécurité Linux Fragnesia

Première rédaction de cet article le 13 mai 2026


Ah, contrairement à CopyFail et DirtyFrag, la faille de sécurité Linux Fragnesia ne semble pas marcher sur mes machines.

Sur une Debian 13 (évidemment une machine sacrifiable), à jour donc ayant un noyau protégé contre DirtyFrag, mais sans le contournement consistant à bloquer le chargement des modules via un /etc/modprobe.d/dirtyfrag.conf :

toto@s55827:~$  git clone https://github.com/v12-security/pocs.git
toto@s55827:~$ cd pocs/fragnesia/
[Lire le code source, renoncer car il est trop compliqué.]
toto@s55827:~/pocs/fragnesia$ gcc -o fragnesia fragnesia.c
toto@s55827:~/pocs/fragnesia$ ./fragnesia
[*] uid=1000 euid=1000 gid=1000 egid=1000
[*] mode=xfrm_espintcp_pagecache_replace collateral=after

[*] target=/usr/bin/su size=84360
outer_write_open_denied=1 errno=13 (Permission denied)
userns_setup: outer_uid=1000 outer_gid=1000 ns_uid=0 ns_gid=0
netns_setup=1
loopback_up=1
namespace_gate_failed: XFRM_MSG_NEWSA ack errno=22 (Invalid argument)
toto@s55827:~/pocs/fragnesia$ su
Password:
    

Les modules sont bien chargés :

toto@s55827:~/pocs/fragnesia$ lsmod | egrep esp\|xfr
esp6                   32768  0
esp4                   28672  0
xfrm_user              69632  0
xfrm_algo              16384  3 esp6,esp4,xfrm_user
    

Donc, le programme d'exploitation de la faille ne marche pas sur Debian. Reste à savoir si c'est juste une bogue du POC (peut-être spécifique à Debian), qu'on pourrait corriger, ou bien si Fragnesia n'est pas si universelle que ça. En attendant, j'ai quand même réactivé ce contournement sur toutes mes machines, à tout hasard (et parce qu'il n'a pas trop d'inconvénients si on ne fait pas d'IPsec) :

sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; true"
  

D'autant plus que le POC de Fragnesia semble marcher sur Ubuntu, Fedora et Arch.

decio a testé sur Kali, même « problème ». Cela semble dû au fait que l'ESP dans TCP ne soit pas activé du tout :

root@s55827 ~ # grep ESPINTCP /boot/config-$(uname -r)  
# CONFIG_INET_ESPINTCP is not set
# CONFIG_INET6_ESPINTCP is not set
  

L'article seul

RFC 9959: Convergence of Congestion Control from Retained State

Date de publication du RFC : Mai 2026
Auteur(s) du RFC : N. Kuhn (Thales Alenia Space), E. Stephan (Orange), G. Fairhurst, R. Secchi (University of Aberdeen), C. Huitema (Private Octopus)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF tsvwg
Première rédaction de cet article le 12 mai 2026


Traditionnellement, les protocoles de transport comme QUIC ou TCP partaient de zéro à chaque connexion. On se connecte, on démarre prudemment (ne pas envoyer trop de données pour éviter de congestionner le réseau), puis on augmente le débit petit à petit. Mais c'est dommage de ne pas tenir compte des connexions précédentes, où on avait déjà suivi ce processus. Ne pourrait-on pas se souvenir des mesures précédentes pour aller plus vite la prochaine fois ? C'est justement ce que propose ce RFC.

Évidemment, si l'idée est simple, la réalisation soulève plein de problèmes, d'autant plus qu'on touche ici à une activité dangereuse : si on se trompe, on risque d'aggraver la congestion. Le RFC détaille donc plus précisément comment réutiliser ces mesures passées, pour ne pas faire s'écrouler le réseau. Tout protocole de transport doit utiliser un algorithme de contrôle de la congestion (RFC 2914) ou bien s'auto-modérer (RFC 8085). Mais concevoir un bon algorithme de contrôle de la congestion n'est pas trivial et, par exemple, le RFC 5783 notait que les algorithmes existants marchaient mal pour les liaisons avec un BDP élevé et/ou très variable, comme les liaisons satellite.

Pour comprendre pourquoi, revenons un peu au fonctionnement typique d'un algorithme de contrôle de la congestion. Il a typiquement deux phases. D'abord, au début de la connexion, on envoie moins de données que ce qu'on pourrait, afin de ne pas congestionner le réseau. Puis on augmente le débit, jusqu'au moment où des indicateurs comme la perte de paquets ou le rythme des accusés de réception (RFC 9406) signalent qu'on a atteint la capacité maximale pour ce flux de données. La dépasser (overshoot) congestionnerait le réseau ou, si les autres flux qui se partagent le réseau sont mieux élevés, entrainerait des diminutions de ressources pour ces autres, voire un écroulement du réseau sous la charge. Voilà pourquoi il faut démarrer lentement.

Au passage, le RFC note que, bien sûr, la connexion TCP ou QUIC qui réutiliserait les mesures d'une précédente connexion doit s'assurer qu'on compare ce qui est comparable : mêmes adresses IP source et destination, et peut-être même DSCP (Differentiated Services Code Point, cf. RFC 2474). On verra plus loin que ce n'est pas suffisant (les choses peuvent changer, le passé peut ne pas être un bon indicateur du présent), mais patientez encore un peu.

La méthode de notre RFC se nomme « reprise prudente » (careful resume) ou, en plus joli « partage temporel » (temporal sharing), puisqu'on reprend des mesures passées (mesures de la capacité, du RTT, etc). Ces mesures pouvant ne plus être d'actualité (trop vieilles et/ou le chemin suivi a changé), il faut en effet être prudent (cf. RFC 9000 et RFC 9040).

Dans quels cas cette reprise (prudente) de données d'une connexion précédente peut être utile ? La section 1.4 du RFC liste un certain nombre de cas d'usages. Entre autres, il y a le cas d'une application qui utilise plusieurs connexions, les connexions peuvent alors utiliser les données récupérées par la première d'entre elles. Ou bien lorsqu'une connexion a été violemment interrompue et repart tout de suite après. Et il y a aussi une autre utilisation, lorsque la latence du chemin utilisé est bien plus importante que dans une liaison Internet typique, ce qui est le cas des satellites lorsqu'ils ne sont pas en orbite basse. L'article « Google QUIC performance over a public SATCOM access  » note ainsi que sur une liaison via un satellite géostationnaire, avec l'algorithme classique, transférer 5,3 Mo prendra 9 secondes alors que le partage temporel, si on peut réutiliser les mesures d'une connexion précédente, prendra 4 secondes. (Si les 9 secondes vous semblent trop, compte-tenu de la capacité du lien, rappelez-vous que la capacité n'est pas le seul facteur limitant ; TCP, surtout au démarrage, n'utilise pas toute la capacité, et il met longtemps à converger si la latence est élevée.) Une autre présentation, à l'IETF « Feedback from using QUIC's 0- RTT-BDP extension over SATCOM public access », calcule une réduction du temps de transfert de 62 % pour faire voyager 1 Mo. Enfin, le RFC recommande la lecture de la synthèse « Careful Resumption of Internet Congestion Control from Retained Path State ».

Le récepteur des données peut avoir des informations que l'envoyeur n'a pas, et cela peut le pousser à vouloir désactiver la reprise que l'envoyeur croit prudente. Par exemple, le récepteur sait peut-être quelle quantité de données va être envoyée, ou bien il sait que le chemin sur le réseau a changé.

Toujours pour compliquer les choses, il faut aussi se souvenir que d'autres facteurs peuvent limiter la quantité de données qu'on envoie, par exemple le contrôle de flux, donc les fenêtres de TCP (RFC 9293, section 3.8.6) ou le système de crédit de QUIC (RFC 9000, section 4).

Prenant en compte tout cela, la section 1.5 du RFC résume les principes de la « reprise prudente » :

  • D'abord, s'assurer que les conditions n'ont pas changé depuis la dernière connexion ; le chemin est-il le même ? (La mesure du RTT donne une première bonne idée.) À l'issue de cette phase de reconnaissance, si les conditions ont changé, on utilise la méthode classique, on ne tient pas compte des mesures qui ont été sauvegardées.
  • Ensuite, OK, on va plus vite qu'avec la méthode classique mais pas aussi vite que ne l'indiquent les mesures sauvegardées. Après tout, la reconnaissance ne permet pas toujours d'identifier un changement dans les conditions.
  • Enfin, on se prépare à faire marche arrière, et à revenir à la méthode classique, si on s'aperçoit qu'on est en train de créer de la congestion. (Le RFC note qu'il faut la détecter rapidement, avant que les autres flots de données n'aient détecté la congestion et réduit leur débit.)

Un peu de terminologie avant de continuer (section 2) : le partenaire distant (remote endpoint) est l'ensemble des informations qui identifie à qui on envoie des données, typiquement l'identificateur d'une interface réseau locale couplé à l'adresse IP de la machine avec qui on parle et peut-être (c'est une décision locale, et forcément très dépendante du système d'exploitation utilisé) des informations comme DSCP. Si le partenaire distant change, on en déduit que le chemin a changé (l'inverse n'est pas vrai : le chemin peut changer alors que le partenaire distant est le même). Si on a une indication que le chemin a changé, on revient au mécanisme traditionnel, on n'utilise pas les paramètres gardés des précédentes connexions.

Le mécanisme de notre RFC a donc plusieurs phases (section 3, mais regardez aussi le joli tableau de l'annexe A, qui est peut-être plus clair) : celle de reconnaissance, où on cherche si les caractéristiques du chemin correspondent à un chemin connu, puis , selon son résultat, on passe à la phase dite normale, si on a reconnu un chemin déjà vu, ou bien à la phase non validée (chemin inconnu, on démarre prudemment), puis à la phase de validation (y a t-il un indicateur de congestion ou bien tout est-il beau et propre ?), ou bien à celle de retraite (on jette les informations enregistrées, la situation a changé, on retourne en mode traditionnel), avant de passer à la phase normale. (Des exemples détaillés figurent dans l'annexe B.)

La section 4 du RFC fournit des détails sur la mise en œuvre des principes de ce RFC. Par exemple, la détermination pratique d'un changement du chemin. Un bon indicateur est le RTT. Cette section conseille aussi, même en l'absence d'indications que le chemin a changé, de ne pas garder les paramètres sauvegardés trop longtemps : comme la détection d'un éventuel changement n'est pas parfaite, il vaut mieux avoir une durée de vie maximale pour les paramètres enregistrés. Le RFC suggère quelques heures, voire moins si on sait que le chemin est très dynamique.

Enfin, l'annexe B détaille à l'octet près des exemples de fonctionnement de l'algorithme de reprise prudente, pour différents cas.

Vous pouvez aussi avoir une introduction aux principes de ce RFC dans l'exposé d'un des auteurs à la Journée du Conseil Scientifique de l'Afnic en 2021 (avec les supports).

Merci à Nicolas Kuhn pour sa relecture.


Téléchargez le RFC 9959


L'article seul

Utiliser son propre nom de domaine sur l'ATmosphère

Première rédaction de cet article le 10 mai 2026


Ça y est, j'ai réussi à utiliser mon propre nom de domaine pour m'identifier sur l'ATmosphère, le réseau social utilisant le protocole AT. Je suis désormais @at.bortzmeyer.fr.

Je ne vais pas essayer d'expliquer le protocole ou comment ça se passe, l'ATmosphère, c'est compliqué et il y a plein de composants dont le rôle n'est pas du tout clair pour moi. Je vais simplement décrire la vision « utilisateur ordinaire, paresseux et pas très malin ».

Si vous utilisez Bluesky, vous allez me dire « mais c'est très simple d'avoir son propre nom de domaine sur Bluesky et c'est documenté ». Mais, justement, je ne veux pas du tout utiliser Bluesky, je veux voir si l'ATmosphère est réellement décentralisé, comme le prétendent ses fanboys.

Mon compte est sur Eurosky et l'interface Web de gestion du compte ne semble proposer aucun moyen d'utiliser un domaine qui ne soit pas un sous-domaine d'eurosky.social. Le truc est donc de passer par une interface analogue à celle de Bluesky comme celle dont je me sers, Blacksky. Donc, avec Blacksky, dans Paramètres → Compte → Pseudo, cliquer sur « j'ai mon propre domaine », et vous arrivez là : blacksky-own-domain.png

Pour prouver que vous contrôlez réellement le domaine, vous aller devoir publier un enregistrement TXT dans le DNS. Cela se fait chez votre hébergeur DNS (et non pas, comme on le lit dans certaines documentations, chez le registrar). Le sous-domaine du nom choisi (que l'interface, curieusement, appelle « Hébergeur ») est _atproto. Comme je suis mon propre hébergeur DNS, j'ai ajouté cette ligne dans le fichier de zone :

_atproto.at IN TXT "did=did:plc:5q7z7bsjozd5bl7dghurywmm" 
  

Puis les manœuvres habituelles (recharger la zone, etc) et vous pouvez voir le résultat :

% dig +short _atproto.at.bortzmeyer.fr TXT
"did=did:plc:5q7z7bsjozd5bl7dghurywmm"

Vous pouvez alors cliquer sur « Vérifier l'enregistrement DNS » et poursuivre le changement d'identité. Attention si vous avez fait une erreur dans le DNS et que vous la corrigez, Blacksky ne verra pas la correction avant la fin du TTL et continuera donc à vous dire que ça ne marche pas.


L'article seul

Test de DirtyFrag et d'un contournement

Première rédaction de cet article le 8 mai 2026
Dernière mise à jour le 9 mai 2026


Aujourd'hui, vous avez probablement entendu parler de la faille de sécurité du noyau Linux nommée CopyFail. Une nouvelle faille a été publiée hier, DirtyFrag (CVE-2026-43284 et CVE-2026-43500) et elle est aussi dangereuse et facile à exploiter que CopyFail.

Comme avec CopyFail, testons sur une machine sacrifiable, en l'occurrence une VM chez xTom. On crée la VM, sous Debian 13 (la dernière version stable). Par souci de complétude, on commence par tester CopyFail :

toto@s55827:~$ python copyfail
Password: 
  

Ouf, CopyFail échoue ; comme avec tous les hébergeurs sérieux, les VM sont créées avec un noyau insensible à cette faille, et ce bien que le module qui était bogué soit chargé :

toto@s55827:~$ lsmod|grep aea
algif_aead             12288  0
af_alg                 36864  1 algif_aead

toto@s55827:~$ uname -a
Linux s55827 6.12.85+deb13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.85-1 (2026-04-30) x86_64 GNU/Linux
  

Maintenant, essayons DirtyFrag :

toto@s55827:~$ git clone https://github.com/V4bel/dirtyfrag.git
…
toto@s55827:~$ cd dirtyfrag/

toto@s55827:~/dirtyfrag$ more exp.c
  

On regarde le code C, il est difficilement compréhensible, c'est bien pour cela qu'il ne faut le tester que sur une machine sacrifiable. Compilons-le :

toto@s55827:~/dirtyfrag$ gcc -O0 -Wall -o exp exp.c

toto@s55827:~/dirtyfrag$ ./exp 
#
# id
uid=0(root) gid=0(root) groups=0(root)

# touch /P0wned
# ls -l /P0wned
-rw-rw-r-- 1 root root 0 May  8 08:53 /P0wned
# 
  

Aussi simple et aussi efficace que CopyFail. Comme lui, il marche à tous les coups et tourne sur de très nombreux systèmes. su a été modifié en mémoire (pas sur le disque et cela ne survivra donc pas au démarrage) :

toto@s55827:~/dirtyfrag$ ls -l /usr/bin/su
-rwsr-xr-x 1 root root 84360 May  9  2025 /usr/bin/su

toto@s55827:~/dirtyfrag$ su
# 
  

La page officielle propose un contournement, en attendant une vraie correction (qui existe déjà chez Debian, pour les autres systèmes, voir ici) :

root@s55827 ~ # sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; true"    

root@s55827 ~ # cat /etc/modprobe.d/dirtyfrag.conf
install esp4 /bin/false
install esp6 /bin/false
install rxrpc /bin/false
  

Et une fois ce contournement appliqué (et la machine redémarrée pour annuler l'effet du test précédent) :

toto@s55827:~/dirtyfrag$ ./exp
dirtyfrag: failed (rc=1)

toto@s55827:~/dirtyfrag$ su
Password: 

 

Ouf, on est en sécurité (jusqu'à la prochaine faille). Si vous avez plusieurs machines où appliquer ce contournement, vous pouvez utiliser Ansible (sur Ansible, voir aussi cet article). Attention, ce contournement empêche apparemment d'utiliser IPsec (mais ce n'est pas grave, tout le monde utilise Wireguard, de toute façon). Si c'est un problème, une autre solution (que je n'ai pas testée) est sysctl -w kernel.unprivileged_userns_clone=0.

Un autre contournement possible est d'utiliser eBPF pour empêcher l'attaque (je n'ai pas testé). Voyez copyfail-dirtyfrag-blocker. Et une solution encore plus radicale (et qui crée probablement pas mal d'inconvénients) est de suspendre le chargement des modules après le démarrage.

Évidemment, la meilleure solution est quand même l'installation d'un noyau corrigé et la redémarrage. Ici, sur une Debian 13 (l'actuelle version stable) :

toto@s55827:~/dirtyfrag$ uname -a
Linux s55827 6.12.86+deb13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.86-1 (2026-05-08) x86_64 GNU/Linux

toto@s55827:~/dirtyfrag$ ./exp 
dirtyfrag: failed (rc=1)

toto@s55827:~/dirtyfrag$ lsmod |grep esp
esp4                   28672  0
xfrm_algo              16384  2 esp4,xfrm_user
  

Malgré le chargement du module, on est en sécurité.

Si vous voulez tous les détails techniques sur DirtyFrag, outre la page officielle, vous avez cet article en anglais et celui-ci en français (et un autre en français mais moins détaillé).


L'article seul

Test de copy.fail et d'un contournement

Première rédaction de cet article le 30 avril 2026
Dernière mise à jour le 2 mai 2026


Petit test de la faille de sécurité du noyau Linux copy.fail (CVE-2026-31431) sur une VM neuve.

La faille CVE-2026-31431 est très sérieuse (ainsi que DirtyFrag, qui l'a suivie d'une semaine). Premier avertissement : la sécurité, c'est compliqué et ne croyez donc pas aveuglément ce que j'écris ou ce que vous avez compris de cet article. Deuxième avertissement : les manipulations effectuées dans cet article sont dangereuses. Réservées aux adultes consentants.

J'ai créé une VM neuve chez xTom, avec le système Debian 13. Aucune modification de mon côté, c'est une Debian pure.

Le compte normal est toto. Il ne peut pas utiliser su sans le mot de passe de root :

toto@s55486:~$ id
uid=1000(toto) gid=1000(toto) groups=1000(toto),100(users)

toto@s55486:~$ su
Password: 
  

On télécharge le POC d'exploitation de la faille :

toto@s55486:~$ curl https://copy.fail/exp > copyfail
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   731    0   731    0     0   3458      0 --:--:-- --:--:-- --:--:--  3448

toto@s55486:~$ more copyfail 
#!/usr/bin/env python3
…
  

On l'examine mais, de toute façon, il est peu compréhensible. On le fait tourner (et je me répète, ne faites pas ça sur une machine de production !!!) :

toto@s55486:~$ python3 copyfail
# id
uid=0(root) gid=1000(toto) groups=1000(toto),100(users)

toto@s55486:~$ su
# 
  

Et voilà, on est root. (Il y a aussi une exploitation en C mais que je n'ai pas testée. Et une plus simple et plus analysable en Python.)

Pour empêcher cela, le mieux est d'installer un noyau réparé, s'il est disponible. C'est le cas dans Arch Linux, Debian, sur Ubuntu, Suse, Fedora… Si on n'a pas un tel noyau, on désactive le module noyau bogué :

root@s55486 ~ # echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
root@s55486 ~ # rmmod algif_aead
  

toto@s55486:~$ python3 copyfail
Traceback (most recent call last):
  File "/home/toto/copyfail", line 9, in <module>
    while i<len(e):c(f,i,e[i:i+4]);i+=4
                   ~^^^^^^^^^^^^^^
  File "/home/toto/copyfail", line 5, in c
…
FileNotFoundError: [Errno 2] No such file or directory


toto@s55486:~$ su
Password: 
  

Et voilà, on est normalement en sécurité. (Il faut évidemment se protéger aussi contre DirtyFrag.) C'est par exemple ce qu'a fait NLNOG sur les machines du RING. Et Evolix nous donne une recette Ansible pour le faire sur toutes vos machines.

Si vous obtenez ceci :

% python copyfail
% 
  

C'est que vous utilisez un noyau non vulnérable (par exemple la version 7.0.2 qui dans Arch Linux).

Sinon, si vous préférez un POC en Go, ça existe (en C aussi).

Alain Thivillon me dit que sur les systèmes d'exploitation Red Hat comme Fedora le module est lié statiquement au noyau et il faut redémarrer avec ça sur la ligne de commande du noyau :

initcall_blacklist=algif_aead_init

(Ou utiliser seccomp. Mais je n'ai testé aucun des deux contournements sur une Red Hat. )


L'article seul

Détournement du nom de domaine eth.limo

Première rédaction de cet article le 20 avril 2026


Le 18 avril, le nom de domaine eth.limo a été victime d'un détournement (une attaque où le méchant prend le contrôle du nom et change les informations).

Les détournements sont le deuxième plus gros problème de sécurité des noms de domaine, avec les attaques par déni de service. Des articles de bilan sur celui-ci ont été produits aussi bien par le titulaire du nom (nom qui est utilisé en rapport avec la cryptomonnaie Ethereum) que par le revendeur EasyDNS (dont on notera la franchise « nous avons merdé »). On ne sait pas exactement comment s'est fait le détournement (l'article d'EasyDNS parle juste d'« ingénierie sociale). Mais voyons les changements faits dans le DNS, et quelques leçons à tirer.

Le domaine a été enregistré via EasyDNS, un revendeur du BE Tucows. Il est hébergé sur AWS. Voici l'information obtenue via RDAP :

% rdap eth.limo
…
Nameserver: ns-814.awsdns-37.net
Nameserver: ns-1689.awsdns-19.co.uk
Nameserver: ns-48.awsdns-06.com
Nameserver: ns-1382.awsdns-44.org
Delegation Signed: yes
…
Last Changed: 2026-04-18T15:31:54.163Z
…
Role: registrar
Name: Tucows Domains Inc.
  

(Notez qu'on ne peut pas utiliser whois, celui-ci n'est plus obligatoire dans les TLD ICANN et, en effet, .limo ne semble plus en avoir.)

Enregistrés par DNSDB, voici la délégation DNS normale de eth.limo :

;;  bailiwick: limo.
;;      count: 1371
;; first seen in zone file: 2022-07-15 00:15:27 -0000
;;  last seen in zone file: 2026-04-19 00:11:22 -0000
eth.limo. IN NS ns-48.awsdns-06.com.
eth.limo. IN NS ns-814.awsdns-37.net.
eth.limo. IN NS ns-1382.awsdns-44.org.
eth.limo. IN NS ns-1689.awsdns-19.co.uk.
  

Et pendant le détournement (deux jeux de serveurs de noms utilisés, comme noté par le tweet du titulaire) :

;;  bailiwick: limo.
;;      count: 495
;; first seen: 2026-04-18 06:31:38 -0000
;;  last seen: 2026-04-18 08:06:34 -0000
eth.limo. IN NS joan.ns.cloudflare.com.
eth.limo. IN NS garrett.ns.cloudflare.com.

;;  bailiwick: limo.
;;      count: 1363
;; first seen: 2026-04-18 08:06:57 -0000
;;  last seen: 2026-04-18 11:59:02 -0000
eth.limo. IN NS dns1.namecheaphosting.com.
eth.limo. IN NS dns2.namecheaphosting.com.
  

Il est amusant de constater que deux jours après, Cloudflare (et Namecheap) continuent à servir la mauvaise information :


% dig @joan.ns.cloudflare.com. eth.limo NS
…
;; ANSWER SECTION:
eth.limo.		86400 IN NS garrett.ns.cloudflare.com.
eth.limo.		86400 IN NS joan.ns.cloudflare.com.
…
;; WHEN: Mon Apr 20 14:02:13 BST 2026
	     
  

Qu'est-ce que le méchant a changé dans la zone ? Il a modifié l'adresse IP, pointant vers un hébergement Web chez Namecheap. On le voit aussi avec DNSDB :

;;      count: 206
;; first seen: 2026-04-18 07:36:35 -0000
;;  last seen: 2026-04-18 11:50:19 -0000
eth.limo. IN A 162.213.253.76
  

Mais notez que les serveurs faisant autorité de Cloudflare et Namecheap continuent de servir la mauvaise info. Comparez avec la vraie :

    
% dig eth.limo A
…
;; ANSWER SECTION:
eth.limo.		60 IN A	35.71.142.77
eth.limo.		60 IN A	52.223.52.2
…
;; WHEN: Mon Apr 20 13:18:39 UTC 2026

% dig @dns1.namecheaphosting.com eth.limo A 
…
;; ANSWER SECTION:
eth.limo.		14400 IN A 162.213.253.76
…
;; WHEN: Mon Apr 20 13:19:06 UTC 2026

  

Et en mettant 162.213.253.76 eth.limo dans son /etc/hosts, on peut voir le site « pirate », qui n'a pas été supprimé. Il ressemble tout à fait au vrai, sauf qu'il n'a pas de HTTPS. Puisqu'on parle de HTTPS, notons que l'attaquant ne semble pas avoir demandé de certificat (il aurait pu). Le dernier certificat alloué date du 11 avril. C'est en tout cas ce qu'on voit en regardant les journaux Certificate Transparency.

Le domaine était signé et l'attaquant, bêtement, n'a pas changé l'enregistrement DS, ce qui fait que tous les gens utilisant (à raison) un résolveur validant n'ont pas pu voir le site pirate. (Personne ne semble avoir testé le domaine avec DNSviz pendant le détournement mais les tests anciens montrent que le DS était là depuis bien avant.)

Il ne semble pas (mais ce n'est pas visible de l'extérieur) que eth.limo était protégé par un verrou au registre (je ne sais pas si .limo a un tel service, l'équivalent du FR lock de .fr ; Patrick Mevzek a cherché et n'a pas trouvé trace de ce service en .limo). C'est pourtant une très bonne protection contre les détournements mais aucun des deux articles n'en parle.


L'article seul

Fiche de lecture : Assaut contre la frontière

Auteur(s) du livre : Leïla Slimani
Éditeur : Gallimard
978-2-07-315293-0
Publié en 2026
Première rédaction de cet article le 20 avril 2026


Dans ce court mais très percutant essai, Leïla Slimani commence par se demander pourquoi elle ne parle pas arabe, puis s'attaque aux politiques identitaires et défend la pluralité et l'égalité des langues (ainsi que la liberté de leurs locuteurs et locutrices).

Petite, l'auteure, dans son Maroc natal, parlait darija. Mais à la maison (famille assez riche et éduquée), c'était le français. Et les cours d'arabe classique, donnés par des enseignants rétrogrades et ennuyeux, n'attiraient pas. Résultat, aujourd'hui (elle vit en France), elle ne peut plus parler arabe et le regrette.

Slimani dénonce donc la hiérarchisation des langues, le fait que certaines langues étaient vues comme inférieures, moins intéressantes et donc pas ou mal enseignées. Et elle en profite pour défendre l'idée de langues vivantes, qui changent et ne sont pas tenues aux oukases (tiens, est-ce un mot français ?) d'institutions réactionnaires. C'est ainsi qu'elle défend les textes d'Aya Nakamura ou, plus exactement, le droit de la chanteuse à écrire comme elle le souhaite.

Mais surtout, l'auteure lance un « assaut contre la frontière » en dénonçant les politiques identitaires ou l'assignation à une identité unique, et en prônant l'universalité, que permet le pluralisme des langues. « Combien de fois m'a-t-on demandé si je me sentais plus arabe ou plus française. »

PS : la question de l'enseignement de l'arabe en France est un vieux sujet et je retrouve un article que j'avais fait en 2020.


L'article seul

Fiche de lecture : Un empire des sens

Auteur(s) du livre : Alberto Angela
Éditeur : Payot
9-782228-934367
Publié en 2023
Première rédaction de cet article le 19 avril 2026


Le titre original « Amour et sexe dans la Rome antique » résume mieux ce livre que la ridicule traduction française. Mais ne lisant pas l'italien, j'ai dû passer par cette traduction. Donc, ce livre est un récit de plusieurs aspects de la sexualité dans la Rome de l'Antiquité.

Comme dans les précédents livres de cet excellent vulgarisateur qu'est Alberto Angela, le récit est très vivant, les personnages attachants et, vu le sujet choisi (amour et sexe…), le livre a certainement de quoi capter l'attention. Comment embrassait-on à Rome ? Comment draguait-on ? Quelles étaient les positions utilisées ? D'un côté, il y avait une certaine liberté des mœurs (davantage qu'avec le christianisme ultérieur), de l'autre, c'était quand même une société très machiste (et violente)… D'autant plus qu'on la connait surtout par des textes d'auteurs masculins. Mais, bon, j'en profite pour placer une image récupérée sur Wikimedia Commons car il n'y a pas assez d'images érotiques sur ce blog : nymphe-satyre.jpg

Mais je suis un peu resté sur ma faim : plusieurs des éléments des précédents livres de cet auteur ont été réutilisés, et il n'y a pas assez de nouveautés pour moi. Je conseillerai aux lecteurices potentiel·les, qui s'intéressent aux différents aspects de la vie des Romains de l'Antiquité, de lire d'abord « Empire » (son meilleur livre) ou « Une journée dans la Rome antique ».


L'article seul

Je me lance dans l'ATmosphère

Première rédaction de cet article le 17 avril 2026


Non, il n'y a pas de coquille dans le titre de cet article, l'ATmosphère (avec un A majuscule et un T majuscule) est le terme parfois utilisé pour désigner le réseau social bâti autour du protocole AT. J'y ai maintenant un compte, @bortzmeyer.eurosky.social (depuis changé en @at.bortzmeyer.fr).

Alors, je vous préviens tout de suite, je ne connais pas grand'chose au fonctionnement du protocole AT. J'ai un point de vue d'utilisateur. Au moins, cela me permet de parler de mon expérience, pas juste de répéter des arguments marketing. Mais, si vous connaissez bien AT, n'hésitez pas à signaler des erreurs (mais en étant rigoureux, pas juste en répétant des slogans).

Donc, pour écrire des choses intéressantes sur l'ATmosphère, on peut se demander pourquoi ne pas simplement aller sur son service le plus connu, Bluesky. Pour moi, la raison est simple : un autre réseau centralisé, propriété d'une entreprise états-unienne à but lucratif n'a pas d'intérêt. Ce n'est pas différent de Twitter et ça finira peut-être de la même façon, racheté par un milliardaire quasi-nazi. Les thuriféraires d'AT répètent tout le temps qu'AT est décentralisé, je ne voulais pas l'utiliser sans profiter de cette décentralisation (une Nième panne de Bluesky avait été l'élément déclencheur). Or, c'est compliqué, bien plus en pratique qu'en théorie.

D'abord, il y a un obstacle intellectuel : la quasi-totalité des documentations et articles supposent qu'on utilise Bluesky. La décentralisation est parfois invoquée pour faire joli mais rarement pratiquée. Ainsi, dans certains cas, pour utiliser un service ATmosphère, il faut bien chercher pour trouver l'option sans Bluesky. Ensuite, les choses changent (lentement). Des services qui, il y a encore quelques mois, n'affichaient que la possibilité d'utiliser Bluesky, s'ouvrent petit à petit.

Bon, quel service utiliser si on ne veut pas tout centraliser sur Bluesky ? C'est là que les difficultés commencent car le monde AT est complexe (bien plus que d'autres réseaux décentralisés comme le courrier, Matrix ou comme le fédivers). Il y a en effet plusieurs services à actionner. Il faut un compte, un PDS (c'est l'endroit où sont stockées les données, comme les messages qu'on a écrit), un PLC (qui permet de trouver les utilisateurs) et une appview (la partie visible à l'utilisateur, donc l'interface utilisateur en dépend). Le PLC, on n'a apparemment pas le choix, il est choisi par les services (trouver le PDS se fait en passant par le PLC). Et des systèmes comme Eurosky fournissent à la fois le compte et le PDS. J'ai donc commencé par me créer un compte sur Eurosky (une possibilité récente, il y a encore quelques mois, il fallait un compte Bluesky) et c'est pour cela que vous voyez eurosky.social dans mon identificateur (on peut aussi utiliser son propre nom de domaine, ce que j'ai fait depuis). La création du compte est classique (identificateur, mot de passe, données personnelles…), je peux me connecter.

Ensuite, selon le service qu'on veut utiliser, il faut choisir une appview (mais on pourra en utiliser plusieurs, c'est essentiellement une interface avec le service). Pour le microblogging, j'ai testé Blacksky (mais vous n'avez pas besoin de savoir cela, c'est juste l'interface que j'utilise, via un navigateur Web). Et voilà, je peux écrire des messages.

Il me reste encore des choses amusantes à tester :

  • Changer mon identificateur pour utiliser mon nom de domaine (fait),
  • Tester des applications permettant de se passer du navigateur Web, par exemple sur mon ordiphone (et de préférence pas l'application « officielle » Bluesky, je rappelle que le but est l'indépendance par rapport à cette entreprise) ; je teste pour l'instant Flare,
  • Regarder ce qui existe en termes d'API pour faire des robots (la documentation ne décrit pas l'API mais uniquement le code Typescript),
  • (Plus tard) Comprendre ce que veulent dire PDS, PLC et autres trucs. Notamment, le PLC utilise des DID et c'est l'occasion de s'instruire, d'autant plus qu'il semble être toujours centralisé, les DID utilisant par exemple une DHT (cf. le projet) n'étant pas utilisés (idem pour le toujours-futur IPFS).

Merci à aeris pour les nombreux renseignements.


L'article seul

Fiche de lecture : Comment cuire un ours

Auteur(s) du livre : Mikael Niemi
Éditeur : Le livre de poche
978-2-253-10728-6
Publié en 2021
Première rédaction de cet article le 17 avril 2026


Un curieux roman policier suédois mais qui ne ressemble pas aux « polars scandinaves » habituels. D'abord, ça se passe au XIXe siècle, ensuite le héros n'est pas alcoolique (et même tout le contraire).

Le livre est inspiré d'un personnage réel, Lars Levi Læstadius, un pasteur intégriste qui faisait également de la botanique et, mais dans le roman seulement, de l'enquête policière. Dans une partie de la Finlande dominée par la Suède, où règne une stricte hiérarchie des langues (d'abord le suédois, puis le finnois, puis tout en bas le same), dans une région secouée par le mouvement de l'Éveil (ce qui perturbe pas mal l'enquête), le héros doit trouver le coupable d'une série de meurtres que certains attribuent à un ours. Le quatrième de couverture de l'édition français cite évidemment Le nom de la rose, pour le personnage du religieux-enquêteur mais Læstadius est bien plus rigide religieusement que Guillaume.

Croyez-moi, vous allez probablement être accroché rapidement si vous aimez les enquêtes policières. L'enquêteur ne traine pas sa dépression tout au long du livre, au contraire, il a une énergie débordante, qui contraste avec le calme de son assistant.


L'article seul

Fiche de lecture : La politique dans les réseaux

Auteur(s) du livre : Francesca Musiani
Éditeur : C&F éditions
978-2-37662-107-2
Publié en 2026
Première rédaction de cet article le 17 avril 2026


Il y en a des livres, qui parlent d'Internet et, dans le lot, certains parlent de politique. Mais la plupart se limitent aux services visibles (YouTube, TikTok, ce que connait l'auteur) alors que ce livre de Francesca Musiani parle bien de l'Internet : en quoi son infrastructure est-elle politique ?

Ce livre est tiré de son HDR et, donc, si vous avez déjà lu ses autres articles, vous n'aurez pas de révélations radicales. Mais même dans ce cas, il est agréable de pouvoir lire un livre qui, en français, rassemble de manière cohérente et bien intégrée, des années de recherche. L'auteure explique bien la façon dont l'Internet est géré (ou pas géré, justement), et en quoi il est à la fois un outil et un enjeu de pouvoir.

Cinq passionnantes études de cas forment l'essentiel du livre : la « gouvernance de l'Internet » (sujet battu et rebattu, oui, mais ici traité de façon sérieuse), le DNS, Bitcoin, Signal et le cas de la Russie. Même si vous connaissez bien l'Internet, vous apprendrez certainement quelque chose. Et cela vous donnera peut-être envie d'agir pour que le futur de l'Internet soit celui que nous voulons.


L'article seul

La conférence UndoneCS de 2026

Première rédaction de cet article le 3 avril 2026


Du 23 au 25 mars 2026, à l'université du Luxembourg s'est tenue la deuxième édition de UndoneCS (Undone in Computer Science), la conférence scientifique sur les recherches qui n'ont pas été faites.

L'idée de base est que la recherche scientifique ne se fait pas au hasard : il y a des sujets sur lesquels on travaille car ils sont passionnants, ou bien financés, ou demandés par les autorités supérieures, et il y a les sujets négligés, ou pas financés, ou qui passent « sous le radar ». L'appel à présentations demandait donc des exposés sur des sujets qui sont a priori utiles mais qui n'ont pas fait l'objet de recherches approfondies.

L'angle était bien sur la science, pas les applications. En informatique, il est facile de citer d'innombrables sujets qui ont fait l'objet d'une recherche scientifique sérieuse, mais où cette recherche n'a pas été suivie de déploiements effectifs. Et c'était un peu, à mon avis, un point faible de cette conférence, plusieurs exposés, pourtant très intéressants, portaient sur des sujets qui avaient été étudiés par la recherche, parfois au point d'être overdone. On ne peut pas dire, par exemple, que les questions sur l'empreinte environnementale du numérique, ou sur le pair-à-pair n'ont pas fait l'objet de recherche, même si, sur le terrain, ça n'a pas eu tellement de conséquences. Vous pouvez consulter tout le programme de la conférence.

Hop, assez de critiques, quelques mots sur les exposés qui m'ont le plus intéressé. D'abord, Viktoriia Makovska a travaillé sur un excellent sujet, la mémoire, et la résistance des systèmes informatiques à l'oubli. Tout le monde sait qu'il est difficile de supprimer réellement une donnée qu'on a enregistrée. Même si on applique un droit à l'oubli, la donnée va rester dans les sauvegardes, dans les journaux, etc. Sans compter les malhonnêtetés comme celle d'Ashley Madison, qui ne supprimait pas réellement les comptes (alors qu'il fallait payer pour cela !) mais les marquait juste comme supprimés, ce qui n'a été dévoilé qu'après qu'un piratage a fait fuiter le fichier. Mais l'oratrice est allée plus loin en observant qu'avec tous les systèmes d'apprentissage automatique, supprimer une donnée utilisée pour l'entrainement d'une machine ne lui fait pas oublier la donnée. Ainsi, si on a entrainé le système avec des messages envoyés sur un réseau social, et que certains messages étaient agressifs, cette agressivité va se retrouver dans les textes générés (memory ghosts). Il ne s'agit donc pas seulement d'effacer mais aussi de désapprendre (machine unlearning). Si on veut vraiment permettre de supprimer, par exemple des informations fausses, il va falloir chercher des solutions (autre que de recommencer tout l'entrainement).

Si vous avez déjà utilisé des LLM (il existe encore des gens qui ne l'ont pas fait ?), vous savez qu'une de leurs grosses faiblesses est l'explicabilité. Le générateur affirme des choses mais a le plus grand mal à expliquer pourquoi il a dit cela, ce qui le rend inutilisable pour de nombreux usages, tous ceux où il faut pouvoir remettre en cause l'affirmation. Clément Arlotti a demandé à ce que la recherche se penche sur cette question, qui est très difficile puisque l'explicabilité demande de la séparabilité alors que le LLM, pendant son entrainement, a tout digéré et mélangé. Les marketeux qui vendent de l'IA se contentent d'affirmer que le progrès des LLM résoudra ce problème mais c'est un acte de foi, pas un résultat scientifique.

Comme exemple de la recherche guidée par les intérêts financiers de certains acteurs, Ryan Lahfa a cité le cas des systèmes de fichiers. Les travaux sur ce sujet sont typiquement financés par les grandes entreprises du Web, alors que leurs besoins ne sont pas forcément ceux des petits acteurs ou de l'auto-hébergement.

Baptiste Jonglez et Lucien Astié, qui travaillent pour le chaton Deuxfleurs (la page la plus frugale du Web) ont plutôt parlé des recherches sur la gouvernance des communs, qui pourraient tirer profit des communs réellement existants, comme ceux des hébergeurs Internet associatifs.

Nikolas Melissaris a fait remarquer qu'il n'y avait jamais de recherches faites sur l'efficacité des lois, par exemple celles de restrictions aux libertés sur l'Internet. On ne se soucie pas de savoir si la loi atteint ses buts ou pas. Négligence ? (Lisez son article.)

Et, sinon, le discours principal était fait par Payal Arora qui, entre autres, a estimé que pas mal de critiques de l'IA venaient de privilégiés qui, eux, n'avaient en effet pas forcément besoin de l'IA (par exemple parce qu'ils rédigeaient bien en anglais), mais négligeaient les besoins des autres. Par exemple, dans beaucoup de pays d'Afrique, les gens sont bien plus enthousiastes vis-à-vis de l'IA que dans les pays riches. Je n'ai pas lu son livre « From Pessimism to Promise », il faudrait que je regarde s'il n'y a pas également des critiques de ce techno-enthousiasme dans les pays du Sud.

On a parlé de bien d'autres choses (même de Plan 9 et de Forth), je ne peux pas tout raconter. Voilà, prochaine édition dans deux ans, commencez à réfléchir aux sujets « non faits » !


L'article seul

Mon expérience avec les paiements en Chine

Première rédaction de cet article le 1 avril 2026


Ayant récemment passé quelques jours en Chine, j'ai eu quelques problèmes à payer mes achats donc je profite de mon blog pour donner quelques conseils aux voyageurs (y compris à moi si je repars).

Ceci n'est pas une étude détaillée et scientifique. Je n'ai pas tout compris, loin de là, et je raconte juste ce que j'ai vu. Ne vous fiez pas aveuglément à ce que je dis. En outre, les choses peuvent changer vite et, si vous lisez cet article en 2027 ou 2028, il sera peut-être ridiculement dépassé.

Donc, la raison pour laquelle je fais un article sur le paiement en Chine et pas sur, par exemple, le paiement au Luxembourg ou même en Australie, c'est que la Chine a deux particularités : les cartes « occidentales » comme Visa ne marchent pas, ou très peu, et l'argent liquide est de plus en plus rare. Si certains commerçants l'acceptent encore, il est rare qu'ils rendent la monnaie (puisqu'ils n'en ont pas en caisse).

Comment font les Chinois ? Ils utilisent des applications de paiement sur leur ordiphone, les deux plus connues étant WeChat Pay et Alipay. Et ceux et celles qui n'ont pas d'ordiphone ? Je suppose qu'ils disparaissent rapidement.

Le Chinois typique adosse son application WeChat ou Alipay à son compte en banque local. Mais que peut faire l'étranger qui séjourne pour une courte durée ? La solution, pour laquelle vous trouvez de nombreux articles en ligne et de nombreuses vidéos sur YouTube est de lier sa carte Visa ou autre à ces applications. Et c'est là que les ennuis commencent. Je vous donne tout de suite deux conseils utiles : préparez les choses très à l'avance, et prévoyez des plans B. (Le mien était de taper les collègues à la réunion IETF.)

Déjà, ces applications sont très intrusives et demandent beaucoup de permissions. Comme, de toute façon, on ne voyage pas en Chine avec des machines qui portent des informations confidentielles, j'avais un téléphone Android vierge (et qui est effacé après). Donc, OK, on installe WeChat et Alipay. (Vous avez intérêt à les configurer en anglais ; en français, il y a moins de choses traduites, et moins bien.) On se crée un compte via l'application. Ensuite, on se crée sur sa banque des cartes virtuelles et on les ajoute à son compte (toujours via l'application sur l'ordiphone, je n'ai pas l'impression qu'il existe des sites Web pour gérer son compte). Et on demande la vérification d'identité, en montrant une photo de son passeport. Ici, l'application WeChat, qui est en fait une « super-app » qui peut héberger des « mini-apps », par exemple pour trouver un taxi : wechat.jpg

Pour tester avant de partir, vous pouvez essayer de payer sur https://testchinapay.com/. On numérise le QR code présenté par le site Web, on tape le mot de passe et hop.

J'ai aussi essayé de mettre de l'argent sur mes comptes WeChat et Alipay avant de partir, avec des services comme Western Union ou Panda Remit mais cela a été refusé à chaque fois, cela ne marche apparemment que si l'application est adossée à un compte en banque chinois.

Voilà, avec tout ça, est-ce que ça marche ? Eh bien, oui et non. J'avais prévenu ma banque avant de partir. Mais les paiements marchent parfois et sont parfois refusés, sans explications. Je ne sais même pas si cela vient du côté chinois ou de ma banque. En payant avec WeChat (mais ça n'est jamais arrivé avec Alipay), j'ai même eu parfois des demandes de vérification 3-D Secure, qui échouaient puisque je n'avais pas apporté mon ordiphone habituel. Acceptations et refus me semblent assez aléatoires e-carte-chine.png

Si vous êtes dans une boutique pour acheter des objets, vous pouvez encore rendre les objets, mais c'est plus embêtant quand vous êtes au restaurant et que vous avez fini de manger. D'où l'importance des plans B (du liquide, en espérant que vous aurez le bon montant, ou un collègue généreux). Ou alors, espérer que tout marche (ici, sur Alipay) : paiements-alipay.jpg

Notez qu'il existe deux façons de payer, en numérisant le QR code que le commerçant vous présente, ou bien en présentant votre QR code, puis en tapant le montant demandé. Scan pour le premier cas, Pay/Receive pour le second, qui marche bien plus souvent, ici sur Alipay : alipay.jpg

La vérification d'identité est resté « en cours » sur Alipay jusqu'à mon retour en France, ce qui n'a pas dû aider.

Merci beaucoup à Antoine Fressancourt pour son aide et ses explications.


L'article seul

RFC 9953: DNS over the Constrained Application Protocol (DoC)

Date de publication du RFC : Mars 2026
Auteur(s) du RFC : M. S. Lenders (TU Dresden), C. Amsüss, C. Gündoğan (NeuralAgent GmbH), T. C. Schmidt (HAW Hamburg), M. Wählisch (TU Dresden & Barkhausen Institut)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF core
Première rédaction de cet article le 1 avril 2026


Le protocole CoAP est un protocole léger, conçu pour les objets connectés. Ce RFC décrit comment faire du DNS au-dessus de CoAP. Si votre brosse à dents a besoin de faire du DNS, c'est ce RFC qu'il faut lire.

CoAP, normalisé dans le RFC 7252, ressemble à HTTP mais en plus simple. Il vise le marché des objets contraints (en mémoire, énergie, en capacité réseau, en puissance de calcul…, voir le RFC 7228). CoAP permet à un client d'envoyer des requêtes à un serveur, et notre tout neuf RFC 9953 explique comment utiliser CoAP pour faire des requêtes DNS et recevoir des réponses DNS. Comme CoAP peut être vu, de manière simplifiée, comme une variante légère de HTTP, ce DNS sur CoAP, alias DoC (DNS over CoAP), est très proche dans ses principes de DoH (RFC 8484). Les contraintes de l'Internet des objets empêchent votre tournevis ou votre ampoule électrique de faire du DoH (qui implique HTTPS), d'où ce DoC. Bien sûr, il y avait toujours la possibilité de faire du DNS sur DTLS, comme le décrit le RFC 8094, mais CoAP a plein de fonctions sympas pour les objets contraints (transferts par blocs - RFC 7959, qui résout les problèmes de MTU, relais CoAP, etc).

L'architecture générale de DoC est très proche de celle de DoH : le client DoC interroge un serveur DoC qui est lui-même un client DNS, parlant typiquement à un résolveur DNS. La communication entre le client DoC et le serveur DoC utilise CoAP, celle entre le serveur DoC et le résolveur utilise le DNS normal, sur UDP, TCP, TLS, etc.

Le serveur DoC sera a priori désigné par le chemin /. Le but est que les messages soient plus courts (DoH utilise souvent le chemin /dns-query). Au fait, comment le client DoC trouve-t-il le serveur (section 3 du RFC) ? Plusieurs méthodes sont admises, de la configuration manuelle (« le serveur DoC est en coaps://doc.foobar.example/ ») aux répertoires CORE (RFC 9176) en passant par les classiques DHCP ou RA ou bien par la découverte de résolveurs du RFC 9462. Ces différentes solutions sont plus ou moins sûres, et plus ou moins pratiques pour l'administrateur/utilisateur (et en général les plus pratiques sont les moins sûres).

Mais ce n'est pas tout : le serveur DoC peut aussi être trouvé via le DNS, avec un enregistrement SVCB (RFC 9460 et RFC 9461), si l'objet contraint a déjà un moyen d'interroger le DNS (la clé SVCB est docpath, numéro 10).

Une fois qu'on connait le serveur, on peut lui parler. La section 4 décrit les messages CoAP échangés. Ils sont étiquetés avec le type application/dns-message (valeur numérique 553).

La méthode CoAP utilisée est FETCH (RFC 8132), qui n'a pas d'équivalent HTTP, contrairement à la plupart des méthodes CoAP. DoC utilise le principe REST (RFC 6690). Le RFC recommande de ne pas oublier le champ Accept: pour indiquer le type de données accepté. Le type recommandé est application/dns-message. Dans la requête, le Query ID DNS devrait être à 0, CoAP se charge de mettre en correspondance requêtes et réponses donc cet identificateur n'est pas utile (c'est pareil pour DoH).

Et les réponses ? Là encore, comme pour DoH, les codes de retour CoAP indiquent si le serveur DoC a pu être joint et a pu faire son travail, pas si la requête DNS a eu une réponse satisfaisante. Autrement dit, tant que le serveur DoC fonctionne bien, il renvoie le code 2.05 (RFC 7252, section 5.9.1.5.) et c'est dans le message DNS qu'on saura si la résolution DNS a renvoyé NOERROR, SERVFAIL, NXDOMAIN, etc.

La mémorisation des réponses joue un rôle plus grand en CoAP qu'en HTTP (rappelez-vous que CoAP sert à des objets contraints). Le RFC demande donc que les TTL dans la réponse DNS soient constants, afin que l'ETag (RFC 7252, section 5.10.6), s'il est calculé via un condensat, ne change pas. Le serveur DoC doit par contre mettre un champ Max-Age: dans sa réponse (section 4.3.2).

Voici, tiré du RFC, un exemple de réponse CoAP, formaté en texte :


2.05 Content
Content-Format: 553 (application/dns-message)
Max-Age: 58719
Payload (human-readable):
    ;; ->>Header<<- opcode: QUERY, status: NOERROR, id: 0
    ;; flags: qr rd ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

    ;; QUESTION SECTION:
    ;example.org.                 IN      AAAA
    ;; ANSWER SECTION:
    ;example.org.         79689   IN      AAAA    2001:db8:1:0:1:2:3:4

  

Et la sécurité ? Le RFC recommande de sécuriser la communication avec le système OSCORE du RFC 8613 (ou, sinon, le DTLS du RFC 9147, ce qui donne du CoAPS). Le RFC note que cela assure la sécurité de la communication entre le client DoC et le serveur DoC mais que, après, on ne sait pas ce que fait le serveur (la section 8 recommande évidemment que le serveur DoC valide avec DNSSEC).

Questions mises en œuvre de DoC, on trouve (mais je ne les ai pas testées, je ne fais pas d'Internet des Objets), par les auteurs du RFC, dans RIOT, un client en C (source sur Github) et un serveur en Python.

Si vous voulez allez plus loin que ce résumé sommaire, une bonne lecture est le papier de 2023 des auteurs, « Securing Name Resolution in the IoT: DNS over CoAP ».


Téléchargez le RFC 9953


L'article seul

Ma configuration WireGuard (client et serveur) avec IPv6 NATé

Première rédaction de cet article le 25 mars 2026


Si vous connaissez déjà, même superficiellement, WireGuard, vous n'apprendrez rien dans cet article, je n'ai rien fait d'original avec WireGuard mais, comme je l'ai récemment utilisé intensivement, voici mon expérience et ma configuration.

WireGuard est un logiciel permettant de créer un VPN, ce qui permet plein de choses, comme d'échapper à certains types de censure, ou comme dissimuler vos activités au fournisseur d'accès Internet que vous utilisez. Par exemple, en ce moment, j'écris cet article depuis le Wifi gratuit, non sécurisé, d'un aéroport dans un pays étranger, donc le risque est important. Bien sûr, je ne fais que des communications chiffrées de bout en bout (SSH, HTTPS, etc) mais le FAI voit quand même les machines avec lesquelles je communique. Autant lui dissimuler un peu plus de choses.

Il y a plusieurs façons de faire du VPN. Déjà, il faut choisir qui ou quoi va être à l'autre extrémité du réseau virtuel ainsi créé. Dans un cadre professionnel, on va se connecter au VPN de son employeur. Il y a aussi des fournisseurs de VPN commerciaux (comme celui qui est cité dans la moitié des vidéos YouTube parce que les youtubeur·ses ont des factures à payer). Et on peut aussi être son propre fournisseur de VPN, via une machine qu'on loue quelque part. Du point de vue de la sécurité, attention, le VPN dissimule votre activité à votre FAI mais le fournisseur de VPN devient votre vrai FAI et lui voit tout le trafic. Le VPN ne dispense donc pas de faire du chiffrement de bout en bout, et il faut bien choisir son fournisseur de VPN, sans se fier à l'influenceur payé pour cela qui va vanter son sponsor dans sa vidéo, avec des arguments malhonnêtes (« personne ne pourra voir ce que vous visitez »).

Moi, j'ai choisi d'être mon propre fournisseur de VPN et j'ai loué pour cela (c'était un projet temporaire) une machine chez V.PS. J'ai choisi cet hébergeur car la même entreprise a un résolveur DNS sympa. Et surtout ils louent des VPS dans de nombreux pays, ce qui m'a permis de placer le serveur VPN pas trop loin du client VPN (pour éviter que les paquets ne fassent le tour du monde), mais quand même dans un autre pays. J'ai choisi Debian comme système d'exploitation car ça juste marche.

Une fois ce choix fait, quel logiciel choisir ? Il existe de nombreuses techniques pour faire un VPN, IPsec (RFC 4301), OpenVPN, WireGuard… Les mises en œuvre d'IPsec sont complexes, et j'ai pris WireGuard car j'en avais entendu dire du bien (et il parait qu'il est plus rapide qu'OpenVPN mais je n'ai pas mesuré).

Effectivement, la configuration est simplissime. Côté serveur, on installe WireGuard (il y a un paquetage Debian), on vérifie qu'il est bien là :

server% wg version
wireguard-tools v1.0.20210914 - https://git.zx2c4.com/wireguard-tools/

WireGuard protège toute la communication avec de la cryptographie asymétrique. On va donc générer des clés, d'abord la clé privée (que je ne vous montre pas en entier) :

server% wg genkey
E….

(En vrai, on va sans doute rediriger vers un fichier, car il faut garder cette clé. Pensez à donner à ce fichier des permissions bien strictes.)

Il reste à calculer la clé publique à partir de la privée (ici, la privée a été mise dans private.key). Elle, on peut la montrer :

server% wg pubkey < private.key
t0Bjw+XGBE1PI81vmhx+bBEIeoWO1f6JWthwi1vYHBk=

Ensuite, le gérant du serveur de VPN (moi, en l'occurrence) va devoir choisir un plan d'adressage. Ici, avec seulement un client, je ne me suis pas embêté. Comme V.PS ne me donne qu'une seule adresse IPv4 publique et, hélas, une seule adresse IPv6 publique, on va donner des adresses privées au client VPN, et faire du NAT. Le VPN aura donc des adresses dans 10.66.0.0/24 (RFC 1918) et fd00:666:ab::1/64 (ce sont les ULA - Universal Local Address du RFC 4193, je détaille plus loin les choix pour IPv6). Le serveur aura une adresse se terminant par 1 et le client par 2.

WireGuard fonctionne au-dessus d'UDP, pour maximiser ses chances de passer dans un réseau mal fichu qui bloquerait d'autres protocoles de couche 4 (le problème de l'ossification). J'ai choisi un port UDP inhabituel, 41834 car les VPN sont souvent bloqués par les FAI, surtout dans certains pays, un port inhabituel a un petit peu plus de chances d'avoir été oublié par le censeur. Voici la configuration du serveur (clé privée masquée) :

server% cat /etc/wireguard/wg0.conf
[Interface]
Address = 10.66.0.1/24,fd00:666:ab::1/64
ListenPort = 41834
PrivateKey = E…Y=

[Peer]
PublicKey = xwVsq/MqwhqUxCRk5KeU0h8nLVCmBRPV3PFgRoay3VA=
AllowedIPs = 10.66.0.2/32,fd00:666:ab::2/128

# Ajouter d'autres pairs si vous avez d'autres clients.
  

(Pourquoi wg0 ? C'est le nom de l'interface réseau couramment utilisé mais vous pouvez en mettre un autre.) Le premier groupe indique les préfixes IP du VPN, les adresses du serveur et son port. Le deuxième indique les caractéristiques du client, dont sa clé publique, qu'il nous a communiqué.

Car il faut faire pareil chez le client (Ubuntu, dans mon cas). Il a aussi une clé privée (qu'il garde pour lui), une clé publique (qu'il communique au gérant du serveur) et la clé publique du serveur, que le fournisseur de VPN lui a communiquée.

[Interface]
Address = 10.66.0.2/32,fd00:666:ab::2/128
PrivateKey = y…Q=

[Peer]
PublicKey = t0Bjw+XGBE1PI81vmhx+bBEIeoWO1f6JWthwi1vYHBk=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = wg-server.bortzmeyer.org:41834
  

Vous noterez qu'on a indiqué le serveur par son nom mais on aurait aussi pu utiliser son adresse IP, ce qui peut être nécessaire si le résolveur DNS par défaut est menteur. Sinon, il y a aussi dans le NetworkManager d'Ubuntu un cliquodrome pour configurer le client WireGuard mais je ne l'ai pas utilisé.

La directive AllowedIPs veut dire qu'on va utiliser le VPN pour toutes les destinations, IPv4 et IPv6. (Attention à ne pas mettre une directive pareille sur le serveur, ou vous déclencherez une boucle sans fin, empêchant tout accès par le réseau. Croyez-moi. J'ai essayé.)

Il reste à configurer le routage, et la traduction d'adresses puisque, aussi bien en IPv4 qu'en IPv6, on a des adresses IP privées, qui ne seront pas routées sur l'Internet. Déjà, activer le routage sur le serveur :

server% sysctl net.ipv4.ip_forward=1 
server% sysctl   net.ipv6.conf.all.forwarding=1
  

Si vous voulez que le routage soit activé systématiquement, vous devez éditer /etc/sysctl.conf pour y mettre :

net.ipv4.ip_forward=1 
net.ipv6.conf.all.forwarding=1 

Notez que ces paramètres ne sont pas forcément appliqués au démarrage, pour des raisons complexes (façon polie de dire que c'est une bogue). Si ce n'est pas le cas (vérifiez avec sysctl -a | grep forward), ajoutez @reboot /usr/bin/sleep 5 && /usr/sbin/sysctl --system dans la crontab de root.

Maintenant, la traduction d'adresses, en IPv4 (RFC 3424) et en IPv6 (notez que ce n'est pas du NAT66, RFC 6296, qui se ferait avec SNPT et pas SNAT, car NAT66 nécessite un préfixe routé) :

server% iptables -t nat -A POSTROUTING -s 10.66.0.0/24 -o eth0 -j SNAT --to-source 149.62.44.9

server% ip6tables -t nat -A POSTROUTING -s fd00:666:ab::1/64 -o eth0 -j SNAT --to-source 2a12:a301:2010::10eb
  

Pour rendre ces règles systématiques à chaque démarrage, vous pouvez utiliser le paquetage iptables-persistent :

server% iptables-save -f /etc/iptables/rules.v4
server% ip6tables-save -f /etc/iptables/rules.v6
  

Une autre solution, pour ne pas retaper les commandes à chaque démarrage, est de les mettre dans des directives PostUp et PostDown de wg0.conf, qui sont exécutées lorsque le VPN est activé ou désactivé :

PostUp = ip6tables -t nat -A POSTROUTING -s fd00:666:ab::1/64 -o eth0 -j SNAT --to-source 2a12:a301:2010::10eb  ; sysctl -q -w net.ipv6.conf.all.forwarding=1; iptables -t nat -A POSTROUTING -s 10.66.0.0/24 -o eth0 -j SNAT --to-source 149.62.44.9 ; sysctl -q -w net.ipv4.ip_forward=1
PostDown = ip6tables -t nat -D POSTROUTING -s fd00:666:ab::1/64 -o eth0 -j SNAT --to-source 2a12:a301:2010::10eb ; sysctl -q -w net.ipv6.conf.all.forwarding=0 ; iptables -t nat -D POSTROUTING -s 10.66.0.0/24 -o eth0 -j SNAT --to-source 149.62.44.9 ; sysctl -q -w net.ipv4.ip_forward=0
  

Enfin, on peut démarrer le service, ici en utilisant systemd puisque c'est ce que prévoit le paquetage Debian :

server% systemctl start wg-quick@wg0

client% systemctl start wg-quick@wg0

(Si on veut que ce soit fait automatiquement au démarrage, on systemctl enable wg-quick@wg0.) À partir de là, un examen du trafic avec tcpdump va montrer qu'on utilise bien le VPN. Ici, je pingue 1.1.1.1 :

22:27:42.017959 IP 10.253.203.139.59473 > 149.62.44.9.41834: UDP, length 128
22:27:42.086272 IP 149.62.44.9.41834 > 10.253.203.139.59473: UDP, length 128
22:27:43.020249 IP 10.253.203.139.59473 > 149.62.44.9.41834: UDP, length 128
22:27:43.390246 IP 149.62.44.9.41834 > 10.253.203.139.59473: UDP, length 128

Et ici mon blog :

22:32:13.428890 IP 149.62.44.9.41834 > 10.253.203.139.59473: UDP, length 1452
22:32:13.428891 IP 149.62.44.9.41834 > 10.253.203.139.59473: UDP, length 1452
22:32:13.428891 IP 149.62.44.9.41834 > 10.253.203.139.59473: UDP, length 1452
22:32:13.429001 IP 10.253.203.139.59473 > 149.62.44.9.41834: UDP, length 96
22:32:13.429028 IP 10.253.203.139.59473 > 149.62.44.9.41834: UDP, length 96
22:32:13.564711 IP 149.62.44.9.41834 > 10.253.203.139.59473: UDP, length 80
22:32:13.564712 IP 149.62.44.9.41834 > 10.253.203.139.59473: UDP, length 80

Dans les deux cas, le FAI qui regarderait le trafic ne verrait pas 1.1.1.1 ou mon blog mais uniquement qu'il y a de la communication UDP chiffrée avec 149.62.44.9 (le serveur VPN). Notez aussi que l'utilisation du VPN permet au client de faire de l'IPv6 même si son réseau d'accès est bloqué au XXe siècle et ne connait qu'IPv4 :

client%  traceroute 2a09::
traceroute to 2a09:: (2a09::), 30 hops max, 80 byte packets
 1  2a12:a301:2010::1 (2a12:a301:2010::1)  0.923 ms  0.851 ms  0.842 ms
 2  * * *
 3  * * *
 4  * * *
 5  public-dns-a.dns.sb (2a09::)  0.148 ms  0.125 ms  0.133 ms
  

Voilà, configurer WireGuard prend moins de temps que lire entièrement cet article. La documentation que j'ai suivie était celle de Hetzner.

Si vous observez que ping passe bien mais que les connexions TCP (par exemple pour le Web, ou pour SSH) s'établissent, mais sans pouvoir transférer de données, c'est sans doute un problème de MTU (la taille compte). Dans ce cas, un ip link set wg0 mtu 1200 va sans doute régler le problème, le temps d'investiguer plus sérieusement (vous pouvez aussi utiliser la directive MTU dans le wg0.conf, ou bien mettre en PostUp quelque chose comme iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wg0 -j TCPMSS --clamp-mss-to-pmtu, et idem en IPv6).

Ah, je n'ai pas encore parlé de la résolution DNS. Par défaut, le résolveur n'est pas changé. S'il est distant, le trafic DNS passera par le VPN. S'il est local (ce qui est le cas par défaut avec systemd-resolved), il n'est pas affecté mais le trafic du résolveur local, quand il parle aux serveurs faisant autorité (ou bien à son forwarder), passe par le VPN. Mais si vous êtes dans un pays où il y a un résolveur menteur, votre résolveur local a pu être empoisonné par de fausses réponses avant que vous ne démarriez le VPN. Bref, la configuration idéale dépend de beaucoup de choses. Quelques notes techniques : si vous utilisez systemd-resolved, la directive DNS dans le wg0.conf du client va changer le forwarder utilisé. Vous pouvez aussi mettre :

PostUp = resolvectl dns %i 2a09::0

Et ça donnera le même résultat. Le résolveur (celui indiqué dans /etc/resolv.conf) ne change pas mais il transmettra (forward) désormais toutes les requêtes à 2a09::. Trois points à retenir :

  • Le résolveur utilisé ici, 2a09:: est celui de xTom puisqu'il est sur le même réseau que le serveur VPN,
  • La forme canonique de cette adresse IP est 2a09::, pas 2a09::0 (RFC 5952), mais il y a une stupide bogue dans systemd qui affiche resolvectl[19427]: Failed to parse DNS server address: 2a09: resolvectl[19427]: Failed to set DNS configuration: Invalid argument,
  • Rappelez-vous que le VPN configuré route IPv6 donc que ce résolveur DNS est joignable même si votre réseau d'accès local n'a pas IPv6.

Revenons un peu à l'adressage et au routage IPv6. Tout dépend de ce qu'offre l'hébergeur du serveur VPN. S'il vous délègue un préfixe (sans doute un /64), et vous route tous les paquets vers ce préfixe, vous avez juste à activer le routage (et peut-être à traduire le préfixe, si vous utilisez des adresses privées en interne, cf. RFC 6296), c'est la situation idéale (mais extrêmement rare sur un hébergement bon marché). Si vous avez un préfixe mais qu'il n'y a pas de route chez l'hébergeur vers votre machine, vous devrez le configurer en proxy NDP (je vous laisse faire l'exercice). Et si vous n'avez pas un préfixe, juste une adresse IP, ce qui était mon cas, il fallait utiliser les ULA. Les ULA sont des adresses privées, comme on peut le vérifier en demandant au RIR :

client% whois -h whois.ripe.net fd00:666:ab::1
…
inet6num:       fc00::/7
netname:        IANA-BLK
descr:          Unique Local Addresses (ULAs)
country:        EU # Country is really world wide
remarks:        This network should never be routed outside an enterprise
remarks:        See RFC4193 for further information

Deux points techniques pour finir, notamment sur la comparaison avec d'autres solutions de VPN :

  • Je n'ai pas vraiment regardé la cryptographie de Wireguard. J'ai l'impression qu'il n'a pas d'agilité cryptographique (RFC 7696), ce qui sera peut-être embêtant dans le futur.
  • La configuration manuelle présentée ici ne passe évidemment pas à l'échelle si on a une centaine de clients, avec les clés à gérer. Peut-être qu'il faut alors utiliser Headscale au-dessus de WireGuard mais je n'ai pas testé.

Amusez-vous bien avec le VPN et n'en profitez pas pour regarder des sites Web illégaux.


L'article seul

RFC 9935: Internet X.509 Public Key Infrastructure - Algorithm Identifiers for the Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM)

Date de publication du RFC : Mars 2026
Auteur(s) du RFC : S. Turner (sn3rd), P. Kampanakis, J. Massimo (AWS), 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 7 mars 2026


Ce RFC spécifie comment mettre des clés ML-KEM dans un certificat X.509. Vous allez me dire « Mais ML-KEM est un algorithme d'échange de clés, pas de signature, que fait-il dans un certificat ? » Et je vous répondrai que vous avez raison, d'ailleurs le RFC restreint sérieusement ce qu'on peut faire avec cet algorithme.

ML-KEM a l'intéressante propriété d'être résistant aux calculateurs quantiques. Il est normalisé dans FIPS 203. Ce RFC permet de l'utiliser dans les certificats normalisés dans le RFC 5280, et il décrit trois variantes, ML-KEM-512, ML-KEM-768 et ML-KEM-1024.

Comme indiqué plus haut, autant il était normal de permettre ML-DSA dans les certificats (RFC 9881), autant cela peut sembler surprenant pour ML-KEM. La section 1.1 de notre RFC explique les usages (limités) d'un algorithme d'échange de clés dans un certificat. C'est par exemple utile pour un protocole où vous avez besoin d'une clé publique, que vous allez tirer du certificat. Mais vous ne pourrez pas utiliser les certificats de ce RFC pour faire du TLS sur l'Internet public, aucune AC ne vous en produira, même si TLS le permet un jour. Pour la même raison, vous n'en trouverez pas dans les journaux Certificate Transparency.

Les trois algorithmes sont identifiés en suivant le RFC 5912, par un OID via le NIST ; Ce sont id-alg-ml-kem-512 (2.16.840.1.101.3.4.4.1), id-alg-ml-kem-768 (2.16.840.1.101.3.4.4.2) et id-alg-ml-kem-1024 (2.16.840.1.101.3.4.4.3).

La section 5 du RFC précise que les bits indiquant les utilisations possibles de ces certificats (RFC 5280, section 4.2.1.3) doivent indiquer uniquement le chiffrement d'une clé (et pas l'authentification, comme avec les certificats habituels).

Le module ASN.1 figure dans l'annexe A, si vous voulez implémenter ce RFC (il faut aussi importer les modules des RFC 5912 et RFC 9629). Le module est identifié par id-mod-x509-ml-kem-2025 et a l'OID 1.3.6.1.5.5.7.0.121. Le gros du RFC est constitué d'exemples de clés et de certificats ML-KEM (annexe C), dans l'encodage en texte du RFC 7468.

Allez, un peu de pratique avec OpenSSL 3.5 :

% openssl genpkey -algorithm ML-KEM-512 -out ml-kem-key.pem -outform PEM

% cat ml-kem-key.pem
-----BEGIN PRIVATE KEY-----
MIIGvgIBADALBglghkgBZQMEBAEEggaqMIIGpgRAOwWCnP71SklfOIuwiLrIddsm
Up4AlOMwvwjqCy4PHr8fSq5jRjFoP6XYXnl8IQCR9HhzSRVffI09hBezOUrmxgSC
…

# Analysons cette clé :
% openssl pkey -text -in ml-kem-key.pem 

# Demandons une signature du certificat :
% openssl req -new -key ml-kem-key.pem  -provider default -out req.csr 
…
40E7CEC0027F0000:error:03000096:digital envelope routines:do_sigver_init:operation not supported for this keytype:../crypto/evp/m_sigver.c:305:

Ah, là, c'est raté, et c'est logique. OpenSSL n'accepte pas de fabriquer un CSR pour ces clés « operation not supported for this keytype » puisque ML-KEM ne permet pas de signer. La solution :

# Extraire la clé publique :
% openssl pkey -in ml-kem-key.pem -pubout   -out mlkem.pub

# Fabriquer une clé ECDSA pour signer :
% openssl ecparam -out ec_key.pem -name secp256r1 -genkey 

# Signer :
% openssl x509 -new \
  -subj "/CN=test-mlkem" \
  -force_pubkey mlkem.pub \
  -signkey ec_key.pem \
  -days 365 \
    -out mlkem-cert.pem
Warning: Signature key and public key of cert do not match

L'avertissement est normal, puisqu'on a effectivement utilisé une autre clé, d'un autre algorithme, pour signer le certificat contenant notre clé publique ML-KEM. Mais tout s'est bien passé :

% openssl x509 -text -in mlkem-cert.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            69:33:f9:1e:e5:34:64:84:d9:f4:b2:15:3b:50:ec:36:db:0b:71:5c
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: CN=test-mlkem
        Validity
            Not Before: Feb 16 15:30:02 2026 GMT
            Not After : Feb 16 15:30:02 2027 GMT
        Subject: CN=test-mlkem
        Subject Public Key Info:
            Public Key Algorithm: ML-KEM-512
                ML-KEM-512 Public-Key:
                ek:
                    d8:d2:6c:c4:9b:96:48:23:0d:ce:f7:0d:b3:0b:85:
                    …
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                E7:B2:03:92:37:EC:C6:35:E4:F0:2E:AC:4E:1C:F2:81:67:F7:95:29
            X509v3 Authority Key Identifier: 
                15:E5:2A:5E:B1:C3:50:69:7E:E4:48:EA:0F:DD:3C:5C:90:4B:7C:CC
    Signature Algorithm: ecdsa-with-SHA256
  

Téléchargez le RFC 9935


L'article seul

Articles des différentes années : 2026  2025  2024  2023  2022  2021  2020  Précédentes années

Syndication : Flux Atom avec seulement les résumés et Flux Atom avec tout le contenu.

Un article de ce blog au hasard.