summaryrefslogtreecommitdiff
path: root/RFC_8020_NXDOMAIN_There_Really_Is_Nothing_Underneath.txt
diff options
context:
space:
mode:
Diffstat (limited to 'RFC_8020_NXDOMAIN_There_Really_Is_Nothing_Underneath.txt')
-rw-r--r--RFC_8020_NXDOMAIN_There_Really_Is_Nothing_Underneath.txt210
1 files changed, 210 insertions, 0 deletions
diff --git a/RFC_8020_NXDOMAIN_There_Really_Is_Nothing_Underneath.txt b/RFC_8020_NXDOMAIN_There_Really_Is_Nothing_Underneath.txt
new file mode 100644
index 0000000..02a36b8
--- /dev/null
+++ b/RFC_8020_NXDOMAIN_There_Really_Is_Nothing_Underneath.txt
@@ -0,0 +1,210 @@
+Titre: RFC 8020: NXDOMAIN: There Really Is Nothing Underneath
+Auteur:
+Date: Wed 09 Nov 2016 01:00:00 +0100
+Lien: https://www.bortzmeyer.org/8020.html
+
+Tout le monde apprend à l'école que les noms de domaine sont organisés en un
+arbre. (Et j'invite tout le monde à lire la section 3.1 du RFC 1034, pour dire
+moins de bêtises[1] sur les noms de domaine.) Il en découle logiquement que, si
+un nœud de l'arbre n'existe pas, les nœuds situés en dessous n'existent pas non
+plus. C'est évident ? Hélas, non. En pratique, bien des résolveurs DNS sont
+prudents et, lorsqu'ils reçoivent une réponse négative pour un nom, mettons
+foo.example, ils n'enregistrent pas pour autant le fait que les sous-domaines
+comme bar.foo.example n'existent pas non plus, et, si un client leur demande
+des informations sur ce sous-domaine, ils vont relayer la question aux serveurs
+faisant autorité, alors qu'ils auraient parfaitement pu répondre à partir de
+leur cache. Ce nouveau RFC remet les choses en place : les noms de domaine sont
+organisés en arbre, ce comportement traditionnel est donc bel et bien erroné,
+et un résolveur devrait, lorsqu'il reçoit une réponse négative, mémoriser le
+fait qu'il n'y a pas non plus de sous-domaines de ce nom. Cela améliorera les
+performances du DNS et, dans certains cas, sa résistance à des attaques par
+déni de service.
+
+Voyons d'abord ce que fait un résolveur actuel. J'ai choisi Unbound. Il vient
+de démarrer, on lui demande foobar56711.se, qui n'existe pas :
+
+% dig MX foobar56711.se.
+
+...
+;; ->>HEADER<><>- opcode: QUERY, status: NXDOMAIN, id: 56324
+
+On a logiquement un NXDOMAIN (No Such Domain, ce nom n'existe pas ; cette
+erreur se nommait autrefois Name Error, et a le code 3). Où le résolveur a-t-il
+trouvé cette information ? Il a demandé aux serveurs faisant autorité, comme
+nous le montre tcpdump :
+
+14:57:14.488196 IP (tos 0x0, ttl 57, id 52537, offset 0, flags [none], proto UDP (17), length 1063)
+ 130.239.5.114.53 > 10.10.86.133.44861: [udp sum ok] 64329 NXDomain*- q: MX? foobar56711.se. 0/6/1 ...
+Le serveur d'IIS[2] (le registre de .se), 130.239.5.114 lui a bien dit NXDOMAIN
+. Maintenant, demandons au même résolveur xyz.foobar56711.se, sous-domaine du
+précédent :
+
+% dig MX xyz.foobar56711.se.
+
+...
+;; ->>HEADER<><>- opcode: QUERY, status: NXDOMAIN, id: 64776
+
+Et, si on regarde le trafic avec tcpdump, on voit que le résolveur a demandé
+encore au serveur faisant autorité, alors que c'était inutile !
+
+15:00:32.929219 IP (tos 0x0, ttl 64, id 42641, offset 0, flags [none], proto UDP (17), length 75)
+ 10.10.86.133.40616 > 130.239.5.114.53: [bad udp cksum 0x8d98 -> 0xd7df!] 10643% [1au] MX? xyz.foobar56711.se. ar: . OPT UDPsize=4096 OK (47)
+15:00:32.939437 IP (tos 0x0, ttl 57, id 14256, offset 0, flags [none], proto UDP (17), length 1067)
+ 130.239.5.114.53 > 10.10.86.133.40616: [udp sum ok] 10643 NXDomain*- q: MX? xyz.foobar56711.se. 0/6/1 ...
+
+Pourquoi le résolveur est-il si prudent, et pose-t-il au serveur faisant
+autorité une question dont il aurait déjà dû connaitre la réponse ? Il y a
+plusieurs raisons mais la principale est que le RFC originel sur le DNS, le RFC
+1034, est ambigu. Il ne décrivait pas de manière parfaitement claire ce qu'il
+faut faire lorsqu'un nom de domaine est un ENT, un Empty Non-Terminal,
+c'est-à-dire un nom de domaine qui n'a pas d'enregistrements mais qui a des
+sous-domaines. Certains ont pensé que cela autorisait à répondre NXDOMAIN
+lorsque le nom demandé est un ENT. Ce comportement a été clairement noté comme
+incorrect dans les RFC ultérieurs (section 7.16 du RFC 2136 et sections 2.2.2
+et 2.2.3 du RFC 4592) mais tout le monde n'en avait pas forcément tiré les
+conséquences. Autre RFC qui contribuait au comportement erroné, le RFC 2308
+(dans sa section 5) faisait l'erreur de dire qu'un résolveur ne pouvait
+renvoyer un NXDOMAIN que si la question portait sur exactement le même nom que
+celui qui avait été mis en cache. Notre nouveau RFC 8020 corrige cette erreur :
+un résolveur doit également renvoyer NXDOMAIN si la question est un
+sous-domaine d'un domaine inexistant.
+
+La règle qui forme le cœur de ce nouveau RFC tient en une phrase (section 2) :
+« si un résolveur reçoit un NXDOMAIN, il peut et il devrait mémoriser le fait
+que ce nom et tous ceux en dessous n'existent pas ». Logiquement, les questions
+ultérieures portant sur un sous-domaine de ce nom devraient recevoir
+immédiatement un NXDOMAIN, sans déranger les serveurs faisant autorité. C'est
+d'ailleurs ce que fait Unbound, si on active l'option harden-below-nxdomain[3]
+ainsi :
+
+server:
+ harden-below-nxdomain: yes
+On voit alors qu'Unbound, face aux deux requêtes successives pour
+foobar56711.se et xyz.foobar56711.se, n'écrit qu'une seule fois aux serveurs de
+.se. (Si cela ne marche pas pour vous, c'est peut-être que votre Unbound ne
+valide pas, vérifiez sa configuration DNSSEC, ou que le domaine est signé avec
+l'option opt-out.) Unbound suit donc le bon comportement mais, malheureusement,
+pas par défaut. (C'est déjà mieux que BIND, qui a toujours le mauvais
+comportement de demander systématiquement aux serveurs faisant autorité, ce qui
+annule partiellement l'intérêt d'avoir un cache.)
+
+Voilà, vous savez maintenant l'essentiel sur le principe du NXDOMAIN cut.
+Voyons quelques détails, toujours en section 2 du RFC. D'abord, il faut noter
+que la règle n'est pas absolue : un résolveur, s'il y tient, peut continuer à
+renvoyer des réponses positives à une question sur un sous-domaine, même si le
+domaine parent n'existe pas, si le cache (la mémoire) du résolveur contenait
+des réponses pour ces sous-domaines. En terme d'implémentation, cela veut dire
+que le mode préféré est de supprimer tout le sous-arbre du cache lorsqu'on
+reçoit un NXDOMAIN, mais que ce n'est pas obligatoire.
+
+D'autre part, rien n'est éternel dans le monde du DNS. Les informations reçues
+par le résolveur ne sont valables que pendant une période donnée, le TTL.
+Ainsi, une information positive (ce domaine existe) n'est vraie que jusqu'à
+expiration du TTL (après, il faut revalider auprès des serveurs faisant
+autorité). Même chose pour une information négative : la non-existence d'un
+domaine (et de tout le sous-arbre qui part de ce domaine) est établie pour un
+TTL donné (qui est celui du champ Minimum du SOA, cf. RFC 2308).
+
+Dernier petit piège, s'il y a une chaîne d'alias menant au nom de domaine
+canonique, le NXDOMAIN s'applique au dernier nom de la chaîne (RFC 6604), et
+pas au nom explicitement demandé.
+
+La section 4 de notre RFC détaille les bénéfices attendus du NXDOMAIN cut. Le
+principal est la diminution de la latence des réponses, et celle de la charge
+des serveurs faisant autorité. On aura moins de requêtes, donc un bénéfice pour
+tout l'écosystème. Cela sera encore plus efficace avec la QNAME minimisation du
+RFC 7816, puisque le résolveur pourra arrêter son traitement dès qu'il y aura
+un domaine absent.
+
+Cela sera aussi utile dans le cas de certaines attaques par déni de service,
+notamment les attaques random QNAMEs avec un suffixe un peu long (comme dans le
+cas de l'attaque dafa888[4]).
+
+Mais tout n'est pas idéal dans cette vallée de larmes. Le NXDOMAIN cut peut
+aussi poser des problèmes, ce qu'examine la section 5. Le principal risque est
+celui que pose des serveurs faisant autorité bogués, comme ceux d'Akamai.
+Regardons le domaine de l'Université de Pennsylvanie, www.upenn.edu :
+
+% dig A www.upenn.edu
+www.upenn.edu. 300 IN CNAME www.upenn.edu-dscg.edgesuite.net.
+C'est un alias pour un nom Edgesuite (une marque d'Akamai). Mais les serveurs
+de edgesuite.net sont bogués, ils répondent NXDOMAIN pour un ENT (Empty
+Non-Terminal, comme edu-dscg.edgesuite.net :
+
+
+% dig @ns1-2.akam.net A edu-dscg.edgesuite.net
+...
+;; ->>HEADER<><>- opcode: QUERY, status: NXDOMAIN, id: 659
+...
+
+La réponse correcte aurait dû être NODATA (c'est-à-dire le code NOERROR et une
+section Answer de taille nulle). Tant qu'Akamai n'aura pas réparé ses serveurs,
+des problèmes subsisteront.
+
+Au fait, pourquoi ne pas se servir de l'enregistrement SOA, qui est renvoyé en
+cas de réponse négative, pour trouver un NXDOMAIN cut situé encore plus haut,
+et qui sera donc plus efficace pour limiter les requêtes ultérieures ? L'annexe
+A du RFC explique pourquoi c'est une fausse bonne idée. Prenons l'exemple d'un
+nom non existant, anything.which.does.not.exist.gouv.fr :
+
+
+% dig AAAA anything.which.does.not.exist.gouv.fr
+...
+;; ->>HEADER<><>- opcode: QUERY, status: NXDOMAIN, id: 35377
+...
+;; AUTHORITY SECTION:
+fr. 5400 IN SOA nsmaster.nic.fr. hostmaster.nic.fr. (
+ 2224131472 ; serial
+...
+Le SOA renvoyé indique fr. Il ne faut pas en déduire que les noms plus
+spécifiques n'existent pas (gouv.fr existe, mais ce n'est pas une zone séparée,
+voilà pourquoi le SOA indiquait son parent fr).
+
+La section 6 du RFC contient quelques conseils pour les implémenteurs.
+Rappelez-vous que les exigences de ce RFC concernent le comportement extérieur
+du résolveur, pas la façon dont il est mis en œuvre. Cette réalisation concrète
+va donc dépendre de comment sont représentés les domaines dans la mémoire du
+résolveur. La représentation la plus évidente est d'utiliser un arbre puisque
+c'est le modèle des noms de domaine. Mais ce n'est pas obligatoire. Un autre
+choix pourrait être celui d'un dictionnaire, plus rapide (pour un nom de
+domaine très profond, il y aura moins de lectures dans la structure de données)
+mais qui rend certaines opérations plus difficiles (toutes celles définies par
+rapport au modèle d'arbre, et elles sont nombreuses dans le DNS). Et il existe
+des implémentations intermédiaires, par exemple avec un arbre augmenté d'un
+index. Bref, le programmeur a le choix. S'il a opté pour un arbre, la façon la
+plus simple de respecter les exigences du RFC et, en recevant un NXDOMAIN, de
+supprimer tout sous-arbre qui partirait du nom ainsi nié.
+
+Un petit mot de sécurité, maintenant qu'on approche de la fin. Si un résolveur
+accepte un NXDOMAIN mensonger (attaque par empoisonnement), les conséquences
+risquent d'être sérieuses puisque c'est un sous-arbre entier qui serait
+« détruit ». C'est pour cela que le RFC autorise un résolveur prudent à ne
+pratiquer le NXDOMAIN cut que si le NXDOMAIN a été validé avec DNSSEC. C'est ce
+que fait Unbound, cité plus haut.
+
+Notez que, si on a DNSSEC, une technique encore plus puissante consiste à
+synthétiser des réponses NXDOMAIN en utilisant les enregistrements NSEC. Elle
+est décrite dans un Internet-Draft actuellement en cours de discussion.
+
+Quels sont les résolveurs qui gèrent aujourd'hui le NXDOMAIN cut ? Outre
+Unbound, déjà cité, il y a PowerDNS Recursor, mais qui est, curieusement,
+limité au cas particulier de la racine[5].
+
+Un peu d'histoire pour finir : la prise de conscience du problème que pose le
+manque d'agressivité des caches des résolveurs est ancienne. Voici par exemple
+une partie d'un rapport de Paul Mockapetris à la réunion IETF n° 4 en 1986 :
+
+Mais le projet concret qui a mené à ce RFC est bien plus récent. Il a été lancé
+(cf. les supports[6]) à la réunion IETF[7] de Yokohama, à peine plus d'un an
+avant la publication du RFC (on peut voir ici l'histoire des différents
+brouillons[8]). On voit que l'IETF peut agir vite.
+
+Liens:
+[1]: http://www.bortzmeyer.org/parties-nom-domaine.html (lien)
+[2]: https://www.iis.se/ (lien)
+[3]: https://www.unbound.net/documentation/unbound.conf.html (lien)
+[4]: https://indico.dns-oarc.net/event/20/session/3/contribution/37 (lien)
+[5]: https://doc.powerdns.com/md/recursor/settings/#root-nx-trust (lien)
+[6]: https://www.ietf.org/proceedings/94/slides/slides-94-dnsop-9.pdf (lien)
+[7]: https://www.ietf.org/meeting/94/ (lien)
+[8]: https://datatracker.ietf.org/doc/draft-ietf-dnsop-nxdomain-cut/ (lien)