Vue d’ensemble

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 a 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 c’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 fichierresolv.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

Wikipedia

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 c’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 !