RFC 8482: Providing Minimal-Sized Responses to DNS Queries that have QTYPE=ANY

Stephane Bortzmeyer <[email protected]> Fri, 11 Jan 2019 10:10:31 +0100
Newsgroups gmane.network.dns.french
Organization NIC France
Message-ID <[email protected]>
Comme vous le savez, on ne peut pas compter sur les requêtes
ANY. Maintenant, c'est officiel. Désormais, si vous voyez un HINFO
bizarre en réponse à une requête ANY, ne vous inquiétez pas.

RFC 8482 : Providing Minimal-Sized Responses to DNS Queries that have QTYPE=ANY

https://www.bortzmeyer.org/8482.html

----------------------------

Auteur(s) du RFC: J. Abley (Afilias), O. Gudmundsson, M. Majkowski (Cloudflare), E. Hunt (ISC)

Chemin des normes

----------------------------


     Lorsqu'un client DNS envoie une requête à un serveur DNS, le client 
indique le *type* de données souhaité. Contrairement à ce qu'on lit 
souvent, le DNS ne sert pas à « traduire des noms de domaine en 
adresses IP ». Le DNS est une base de données généraliste, qui sert 
pour de nombreux types de données. Outre les types (AAAA pour les 
adresses IP, SRV pour les noms de serveurs assurant un service donné, 
SSHFP ou TLSA pour les clés cryptographiques, etc), le DNS permet de 
demander *tous* les types connus du serveur pour un nom de domaine 
donné ; c'est ce qu'on appelle une requête ANY. Pour différentes 
raisons, l'opérateur du serveur DNS peut ne pas souhaiter répondre à 
ces requêtes ANY. Ce nouveau RFC spécifie ce qu'il faut faire dans ce 
cas.

     Les requêtes comme ANY, qui n'utilisent pas un type spécifique, sont 
souvent informellement appelées « méta-requêtes ». Elles sont 
spécifiées (mais de manière un peu ambigue) dans le RFC 1035, section 
3.2.3. On note que le terme « ANY » n'existait pas à l'époque, il est 
apparu par la suite.

     Pourquoi est-ce que ces requêtes ANY défrisent certains opérateurs de 
serveurs DNS ? La section 2 de notre RFC explique ce choix. D'abord, 
quelle était l'idée derrière ces requêtes ANY ? La principale 
motivation était de déboguage : ANY n'est pas censé être utilisé dans 
la cadre du fonctionnement normal du DNS, mais lorsqu'on veut creuser 
un problème, vérifier l'état d'un serveur. Voici un exemple de requête 
ANY envoyée au serveur faisant autorité pour le nom de domaine 
anna.nic.fr :

       
% dig +nodnssec @ns1.nic.fr ANY anna.nic.fr
...
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 5, ADDITIONAL: 10
...
;; ANSWER SECTION:
anna.nic.fr.		600 IN A 192.134.5.10
anna.nic.fr.		172800 IN TXT "EPP prod"
anna.nic.fr.		600 IN AAAA 2001:67c:2218:e::51:41
...
;; Query time: 2 msec
;; SERVER: 2001:67c:2218:2::4:1#53(2001:67c:2218:2::4:1)
...

     
     Le serveur 2001:67c:2218:2::4:1 a renvoyé
     les données pour trois types, A (adresse IPv4), AAAA (adresse
     IPv6) et TXT (un commentaire).
     

     Certains programmeurs comprenant mal le DNS ont cru qu'ils pouvaient 
utiliser les requêtes ANY pour récupérer à coup sûr toutes les données 
pour un nom (ce fut par exemple une bogue de qmail). Voyons d'abord si 
ça marche, en essayant le même nom avec un autre serveur DNS :

    
       
% dig @::1 ANY anna.nic.fr
...
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
anna.nic.fr.		595 IN AAAA 2001:67c:2218:e::51:41
...
;; Query time: 0 msec
;; SERVER: ::1#53(::1)


     On n'a cette fois récupéré que l'adresse IPv6 et pas les trois enregistrements. C'est parce que
     cette fois, le serveur interrogé était un résolveur, pas un
     serveur faisant autorité. Il a bien répondu en donnant toutes les
     informations qu'il avait. Simplement, il ne connaissait pas tous
     les types possibles. Ce comportement est le comportement normal
     de ANY ; ANY (n'importe lesquelles) ne veut pas dire ALL
     (toutes). Il veut dire « donne-moi tout ce que
     *tu* connais ». Il n'y a jamais eu de garantie
     que la réponse à une requête ANY contiendrait toutes les données
     (c'est la bogue fondamentale de l'usage DNS de qmail). Si la
     réponse, comme dans l'exemple précédent, n'a pas de données de
     type A, est-ce que cela veut dire qu'il n'y a pas de telles
     données, ou simplement que le serveur ne les connaissait pas ? On
     ne peut pas savoir. Bref, il ne faut pas utiliser les requêtes
     ANY vers un résolveur ou, plus exactement, il ne faut pas compter
     sur le fait que cela vous donnera toutes les données pour ce
     nom. ANY reste utile pour le déboguage (savoir ce que le
     résolveur a dans le cache) mais pas plus.

     Et vers un serveur faisant autorité, est-ce que là, au moins, on a une 
garantie que cela va marcher ? Même pas car certains serveurs faisant 
autorité ne donnent qu'une partie des données, voire rien du tout, pour 
les raisons exposées au paragraphe suivant.

     En effet, les requêtes ANY ont des inconvénients. D'abord, elles 
peuvent être utilisées pour des attaques par réflexion, avec 
amplification <https://www.bortzmeyer.org/attaques-reflexion.html>. La 
réponse, si le serveur envoie toutes les données possibles, va être 
bien plus grosse que la question, assurant une bonne amplification 
<https://www.bortzmeyer.org/amplification-dns-combien.html> (cf. RFC 
5358, et section 8 de notre nouveau RFC). Bien sûr, ANY n'est pas le 
seul type de requête possible pour ces attaques (DNSKEY ou NS donnent 
également de « bons » résultats.)

     Ensuite, les requêtes ANY peuvent permettre de récupérer facilement 
toutes les données sur un nom de domaine, ce que certains opérateurs 
préféreraient éviter. C'est à mon avis l'argument le plus faible, le 
même effet peut être obtenu avec des requêtes multiples (i y a 65 536 
types possibles, mais beaucoup moins en pratique) ou via le "passive 
DNS <https://www.bortzmeyer.org/dnsdb.html>".

     Enfin, avec certaines mises en œuvre des serveurs DNS, récupérer toutes 
les informations peut être coûteux. C'est par exemple le cas si le 
dorsal du serveur est un SGBD où les données sont accessibles 
uniquement via la combinaison {nom, type}.

     Bref, il est légitime que le gérant d'un serveur DNS veuille bloquer 
les requêtes ANY. Mais que doit-il répondre dans ce cas ? Ne pas 
répondre du tout, comme le font certains pare-feux programmés et 
configurés avec les pieds n'est pas une solution, le client réémettra, 
gaspillant des ressources chez tout le monde. Notre RFC suggère un 
choix de trois méthodes (section 4) :
* Envoyer un sous-ensemble non-vide des données connues. Le client ne 
saura jamais si on lui a envoyé toutes les données, seulement celles 
connues du serveur, ou bien un sous-ensemble. Mais rappelez-vous qu'il 
n'y a jamais eu aucune garantie qu'ANY renvoie tout. Cette technique ne 
change donc rien pour le client.
* Variante du précédent, essayer de deviner ce que veut le client et le 
lui envoyer. Par exemple, en renvoyant tous les A, AAAA, MX et CNAME 
qu'on a et en ignorant les autres types d'enregistrement, on satisfera 
sans doute la grande majorité des clients.
* Envoyer un enregistrement HINFO, solution décrite en détail plus 
loin.
Toutes ces réponses sont compatibles avec le protocole existant. Le RFC 
1035, section 3.2.3, est relativement clair à ce sujet : ANY n'est pas 
la même chose que ALL (section 7 de notre RFC). Notez que notre nouveau 
RFC n'impose pas une politique particulière ; ce RFC ne dit pas qu'il 
faut renvoyer la réponse courte, il dit « si vous le faites, faites-le 
avec une des trois méthodes indiquées ».

     Notez que le comportement du serveur peut dépendre de si la question 
était posée sur UDP ou sur TCP (section 4.4 du RFC). En effet, avec 
TCP, le risque d'attaque par réflexion est très faible.

     Voici un exemple chez Cloudflare, la société qui a le plus « poussé » 
pour ce RFC 
<https://blog.cloudflare.com/what-happened-next-the-deprecation-of-any/>
 :

       
% dig +nodnssec @ns5.cloudflare.com. ANY cloudflare.com
...
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 54605
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
...
;; ANSWER SECTION:
cloudflare.com.		3789 IN	HINFO "ANY obsoleted" "See draft-ietf-dnsop-refuse-any"

;; Query time: 4 msec
;; SERVER: 2400:cb00:2049:1::a29f:209#53(2400:cb00:2049:1::a29f:209)
;; WHEN: Wed Dec 19 16:05:12 CET 2018
;; MSG SIZE  rcvd: 101

     

     Le client recevant ces réponses les mémorise de la manière classique. 
S'il trouve un HINFO, il peut décider de l'utiliser pour répondre aux 
requêtes ANY ultérieures. (C'est un changement de la sémantique du type 
HINFO mais pas grave, ce type étant très peu utilisé.)

     Mais pourquoi HINFO, type qui était normalement prévu pour donner des 
informations sur le modèle d'ordinateur et sur son système 
d'exploitation (RFC 1035, section 3.3.2) ? La section 6 du RFC traite 
cette question. Le choix de réutiliser (en changeant sa sémantique) un 
type existant était dû au fait que beaucoup de boitiers intermédiaires 
bogués refusent les types DNS qu'ils ne connaissent pas (un nouveau 
type NOTANY avait été suggéré), rendant difficile le déploiement d'un 
nouveau type. HINFO est très peu utilisé, donc considéré comme 
« récupérable ». Ce point a évidemment fait l'objet de chaudes 
discussions à l'IETF, certains étant choqués par cette réutilisation 
sauvage d'un type existant. Le type NULL avait été proposé comme 
alternative mais l'inconvénient est qu'il n'était pas affiché de 
manière lisible par les clients DNS actuels, contrairement à HINFO, qui 
permet de faire passer un message, comme dans l'exemple Cloudflare 
ci-dessus.

     Un HINFO réel dans une réponse peut être mémorisé par le résolveur et 
empêcher certaines requêtes ANY ultérieures. De la même façon, le HINFO 
synthétique généré en réponse à une requête ANY peut masquer des vrais 
HINFO. Attention, donc, si vous avez des HINFO réels dans votre zone, à 
ne pas utiliser ce type dans les réponses aux requêtes ANY.

     Mais les HINFO réels sont rares. En janvier 2017, en utilisant la base 
DNSDB <https://www.bortzmeyer.org/dnsdb.html>, je n'avais trouvé que 54 
HINFO sur les trois millions de noms de .fr, et la plupart n'étaient 
plus dans le DNS. Les meilleurs étaient :

iiel.iie.cnam.fr. IN HINFO "VS3100" "VMS-6.2"
wotan.iie.cnam.fr. IN HINFO "AlphaServer-1000" "OSF"
     
     Il y a peu de chance qu'une VaxStation
     3100 soit encore en service en 2017 :-) Autres HINFO utilisés de
     façon créative :
     

www-cep.cma.fr. IN HINFO "bat. B" ""
syndirag.dirag.meteo.fr. IN HINFO "VM Serveur Synergie 1 operationnel" "RHEL 5.4"
www.artquid.fr. IN HINFO "Artquid" "ArtQuid, La place de marche du Monde de l'Art (Antiquites, Objets d'art, Art contemporain et Design)"
     
     Le HINFO de syndirag.dirag.meteo.fr est
     toujours en ligne et illustre très bien une raison pour laquelle
     les HINFO sont peu utilisés : il est pénible de les maintenir à
     jour (la machine n'est probablement plus en
     RHEL 5.4).
     

     Notons que d'autres solutions avaient été étudiées à l'IETF pendant la 
préparation de ce RFC (section 3) :
* Créer un nouveau code de retour (au lieu de l'actuel NOERROR). Le 
nommer, par exemple, NOTALL. Mais les résolveurs actuels, recevant un 
code inconnu, auraient simplement renvoyé la question à d'autres 
serveurs.
* Utiliser une option EDNS, mais l'expérience prouve que les options 
EDNS inconnues ont du mal à passer les boitiers intermédiaires.
* Simplement décider que ANY devenait un type d'enregistrement comme 
les autres, au lieu de rester un « méta-type » avec traitement spécial. 
Dans ce cas, comme il n'y a pas de données de type ANY dans la zone, la 
réponse aurait été NODATA (code de retour NOERROR mais une section de 
réponse vide). Cela s'intégre bien avec DNSSEC par exemple. Mais cela 
casserait les attentes des logiciels clients, et cela ne leur 
laisserait rien à mémoriser (à part la réponse négative).
Le choix a donc été fait de renvoyer quelque chose, afin que le client 
s'arrête là, et qu'il puisse garder quelque chose dans sa mémoire 
(cache).

     On notera que cela laisse entier le problème du client qui voudrait 
récupérer, par exemple, adresse IPv4 (A) et IPv6 (AAAA) avec une seule 
requête. Plusieurs approches ont été proposées mais aucune adoptée.

     
   Les techniques de ce RFC sont-elles disponibles ? NSD a depuis sa 
version 4.1 une option refuse-any, mais pas conforme au RFC (elle 
répond avec le bit TC indiquant la troncature, ce que le RFC refuse 
explicitement). BIND a depuis la version 9.11 une option minimal-any 
qui, elle, est conforme. En mettant minimal-any yes; dans la 
configuration, BIND répondre aux requêtes ANY avec un seul 
enregistrement. BIND n'utilise donc pas la solution « HINFO » mais le 
RFC permet ce choix.