Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

RFC 9250: DNS over Dedicated QUIC Connections

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


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

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

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

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

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

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

En revanche, DoQ n'esssaie pas de :

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

% ./quicdoq_app -p 8053 -d 9.9.9.9
  

Puis le client :

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

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

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

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

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

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


Téléchargez le RFC 9250

Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)

Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)