Comprendre la résolution DNS sous Debian
Dans mon article précédent, j’expliquais comment configurer une connexion VPN pour une Freebox afin d’être partout chez soi. Une fois que j’ai réussi à me connecter, j’ai voulu accéder à mes machines par leur petit nom. Je ne me rappelle pas par cœur de leurs IPs ! Et c’est là qu’a commencé la vraie galère : la Résolution DNS !
TL;DR
Sur les Debians récentes, la résolution DNS est prioritairement assurée par systemd-resolved
qui s’initialise depuis le fichier /etc/resolv.conf
, mais qui l’ignore ensuite. Donc si l’on modifie le fichier systemd-resolved
ne tiens pas compte des modifications. dig
qui ne lit que le fichier /etc/resolv.conf
utilise alors un DNS différent de ping
qui passe par la glibc, qui passe par NSS, qui passe par systemd-resolved
.
Au commencement
J’ai passé un temps infini sur le net à comprendre pourquoi ping
et nslookup
ne répondent pas la même IP pour un nom de domaine. Voilà ce que j’en ai compris.
À la base, cela n’est pas censé être compliqué, un fichier /etc/resolv.conf
qui contient des enregistrements nameserver x.x.x.x
et un système qui demande à ces “nameserver” de résoudre l’adresse IP pour un domaine donné.
Mais il y a aussi un fichier /etc/hosts
qui contient des enregistrements de type x.x.x.x nom.de.domain
. Il faut en tenir compte. C’est le travail de NSS
, j’y reviendrai plus tard. Mais déjà on voit que nslookup
et ping
ont des méthodes de résolution qui diffèrent.
NetworkManager, l’ami qui vous veut du bien
Il est la depuis longtemps, NetworkManager
est l’outil qui s’occupe de configurer votre réseau plus ou moins de manière automatique. C’est lui qui génère le fichier resolv.conf
, on peut d’ailleurs voir la ligne suivante dans le fichier :
# Generated by NetworkManager
Il prend les informations d’un peu partout, de la configuration des interfaces, de sa propre configuration, … Puis il mixe le tout et sort un fichier resolv.conf
.
Puis on a commencé à vouloir faire des choses plus compliquer et avoir des DNS en fonction de la connexion ou de l’interface utilisée. C’est là qu’est apparue la commande resolvconf
. On rentre alors dans un niveau de complexité plus élevé. La commande resolvconf
s’occupe de gérer le fichier resolv.conf
et ne fait que ça. Il est donc possible de spécifier au NetworkManager qu’il doit déléguer la gestion du fichier resolv.conf
à la commande resolvconf
via l’option dns
du fichier /etc/NetworkManager/NetworkManager.conf
.
Le fichier resolv.conf
contient maintenant cette ligne
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
Jusque-là, ça va encore, tout passe par le fichier de configuration.
Systemd-resolved, le fauteur de trouble
La gestion par fichier, c’est bien, mais ce n’est pas très dynamique. resolvconf
passe son temps à changer le fichier resolv.conf
au gré des connexions/dé-connexions, et il n’est pas vraiment possible de gérer les DNS à la volée selon l’interface. De plus, l’arrivée de systemd offre de nouvelles perspectives.
Et c’est là que se pointe systemd-resolved
.
Il faut savoir que sur les dernières versions de Debian, c’est lui qui gère le DNS, pas le fichier resolv.conf
, enfin il est prioritaire en tout cas.
Il a plusieurs modes de fonctionnement, il peut soit ne plus tenir compte du tout du fichier resolv.conf
, soit lancer son propre DNS et le mettre dans le fichier resolv.conf
(127.0.0.53
). Cela permet une migration plus en douceur vers la solution. Cela se règle au niveau du fichier /etc/NetworkManager/NetworkManager.conf
.
On peut tester la résolution de ce service avec la commande resolvectl query blog.ght1pc9kc.fr
.
ping vs nslookup, dig
Revenons en au problème initial, pourquoi la commande dig
ou nslookup
ne me retournent pas la même chose que ping
?
C’est là qu’intervient NSS .
C’est un service qui autorise le remplacement des traditionnels fichiers Unix de configuration (par exemple /etc/passwd, /etc/group, /etc/hosts) par une ou plusieurs bases de données centralisées
Si on regarde la configuration de ce service avec la commande cat /etc/nsswitch.conf | grep hosts
(on ne s’intéresse qu’a la partie hosts
), on voit la ligne suivante :
hosts: files mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns myhostname
Quelques explications :
- files: Représente les fichiers de configuration comme
/etc/hosts
- mdns4_minimal: Est le service mDNS ou DNS Multicast fourni par Avahi. C’est le service qui découvre les noms des machines de votre réseau local en fonction de leur hostname sans avoir besoin de DNS central.
- resolve: C’est le service
systemd-resolved
- dns: C’est la résolution DNS classique par
resolv.conf
- myhostname: C’est la commande
hostname
. En gros il regarde si ce n’est pas le nom de la machine locale.
Cette ligne donne dans l’ordre des bases dans lesquelles le système cherche l’ip d’un nom de domaine. On voit donc que resolve
est présent AVANT dns
.
C’est de là que vient la différence. nslookup
comme dig
lisent le fichier resolv.conf
, en sortent l’IP du DNS et lui demandent la résolution, ni plus ni moins. Ils ignorent NSS. ping
quant à lui, comme la plupart des applications web (navigateurs, …) utilise la glibc qui passe par NSS pour résoudre les noms d’hôtes. Comme resolve
est prioritaire à dns
, s’il n’utilise pas les mêmes DNS que ceux présents dans le fichier resolv.conf
le résultat des deux commandes est différent.
CQFD !