HardStacked
Partager :

systemd-resolved · netplan

Qu'est-ce qui change /etc/resolv.conf ? Trouver qui impose ton DNS (Ubuntu 24.04)

Publié le · HardStacked · 10 min

Ton serveur Ubuntu 24.04 interroge un serveur DNS qui n'existe plus. Tu ouvres /etc/resolv.conf et il dit 127.0.0.53, ou, si tu as changé le lien, une liste avec le mauvais serveur dedans et la ligne # Too many DNS servers configured, the following entries may be ignored. Tu édites, ça revient. La question traîne sur askubuntu depuis le 2024-07-26 (question 1521666, 43 902 vues au 2026-10-28, trois réponses, aucune acceptée), et la personne qui la pose la résume en une phrase :

« How can I remove whatever is setting this DNS server, incorrectly? » (« Comment retirer ce qui impose ce serveur DNS, à tort ? »)

Personne n'édite ton /etc/resolv.conf. C'est un lien vers un fichier que systemd-resolved remplace en entier, à chaque changement de DNS sur une interface. Demande-toi donc quelle interface apporte ce DNS, et d'où elle le tient. ls -l nomme l'écrivain, resolvectl dns nomme l'interface, le bail DHCP nomme le serveur qui l'a donné. Si le bail ne correspond pas, le DNS a été posé à chaud, par une personne ou un script, et il survit à un renouvellement du bail et à un redémarrage de systemd-resolved, jusqu'à resolvectl revert. Le correctif : refuser le DNS du DHCP sur cette interface. Ajouter un DNS global ne retire rien.

Mesuré sur une machine virtuelle Ubuntu 24.04.5 LTS (arm64, image cloud officielle), systemd-resolved 255.4, netplan.io 1.1.2, le 2026-10-28. Pareil sur Ubuntu 26.04.1 LTS (systemd 259.5), sauf DHCPv4 via au lieu de DHCP4 via.

01. Rien n'édite le fichier : le labo et le piège

Tu peux le reproduire sans toucher à ton vrai réseau. On crée une interface virtuelle, demo0, reliée à un faux routeur : un espace de noms réseau où dnsmasq fait du DHCP et rien d'autre, et distribue trois DNS morts, 198.51.100.112 à .114. Personne n'a ces adresses, comme le vieux serveur de la question (les plages 198.51.100.x et 192.0.2.x sont réservées à la documentation, RFC 5737). Sûr : pas de passerelle (--dhcp-option=3 est vide), seul demo0 est touché, tout est retiré à la fin. 10.0.2.3 est le DNS normal de la VM (interface enp0s1) ; chez toi ce sera le tien. On a coupé les lignes debconf et needrestart d'apt-get.

le labo
$ sudo apt-get install -y -qq dnsmasq-base inotify-tools >/dev/null
$ sudo ip netns add demo-router
$ sudo ip link add demo0 type veth peer name demo0-r
$ sudo ip link set demo0-r netns demo-router
$ sudo ip -n demo-router addr add 198.51.100.1/24 dev demo0-r
$ sudo ip -n demo-router link set demo0-r up
$ sudo ip netns exec demo-router dnsmasq --conf-file=/dev/null --port=0 --interface=demo0-r --bind-interfaces --dhcp-range=198.51.100.50,198.51.100.99,12h --dhcp-option=3 --dhcp-option=6,198.51.100.112,198.51.100.113,198.51.100.114 --pid-file=/run/demo-dnsmasq.pid --dhcp-leasefile=/run/demo-dnsmasq.leases
$ printf 'network:\n version: 2\n ethernets:\n demo0:\n dhcp4: true\n' | sudo tee /etc/netplan/60-demo.yaml
network: version: 2 ethernets: demo0: dhcp4: true
$ sudo chmod 600 /etc/netplan/60-demo.yaml
$ sudo netplan apply && sleep 5

Le piège : le fichier dit 127.0.0.53, rien d'anormal. C'est le résolveur local de systemd-resolved, et il cache les vrais serveurs, gardés par interface. resolvectl dns demo0 en montre trois morts. tcpdump sur demo0 pendant une recherche montre des requêtes ARP pour 198.51.100.112 : le serveur mort est interrogé, et example.net se résout quand même.

le piège
$ grep nameserver /etc/resolv.conf
nameserver 127.0.0.53
$ resolvectl dns demo0
Link 12 (demo0): 198.51.100.112 198.51.100.113 198.51.100.114
$ sudo timeout 8 tcpdump -tlni demo0 -c 3 arp and host 198.51.100.112 2>/dev/null & sleep 1; sudo resolvectl flush-caches; getent hosts example.net >/dev/null && echo 'example.net resolves'; wait
ARP, Request who-has 198.51.100.112 tell 198.51.100.72, length 28 example.net resolves ARP, Request who-has 198.51.100.112 tell 198.51.100.72, length 28 ARP, Request who-has 198.51.100.112 tell 198.51.100.72, length 28

Le manuel : une requête sans domaine de routage part vers tous les DNS des interfaces avec DefaultRoute=, plus le DNS global (systemd-resolved(8)), et le mort n'a pas retardé la réponse. Un serveur mort ne casse donc pas les noms publics, il casse ce que lui seul connaissait : les noms internes d'un labo. (example.net resolves s'intercale entre les lignes ARP : deux programmes écrivent en même temps.)

02. Qui l'écrit, et la ligne « Too many DNS servers »

Le lien pointe vers stub-resolv.conf. systemd-resolved(8) décrit quatre modes pour /etc/resolv.conf, détectés selon la cible du lien, et dit que resolved maintient stub-resolv.conf et resolv.conf dans /run/systemd/resolve/. Tout le dossier appartient à systemd-resolve : l'écrivain est nommé. On a coupé les deux lignes de sockets.

qui l'écrit
$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Oct 17 12:58 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
$ ls -l /run/systemd/resolve/
total 8 -rw-r--r-- 1 systemd-resolve systemd-resolve 934 Oct 28 18:44 resolv.conf -rw-r--r-- 1 systemd-resolve systemd-resolve 920 Oct 28 18:38 stub-resolv.conf

Ce resolv.conf est le fichier uplink : les vrais serveurs, sans stub, la liste que lisait la personne de la question. Ici : les trois morts, l'avertissement, notre DNS sain en 4ᵉ.

le fichier uplink
$ grep -E '^nameserver|^# Too' /run/systemd/resolve/resolv.conf
nameserver 198.51.100.112 nameserver 198.51.100.113 nameserver 198.51.100.114 # Too many DNS servers configured, the following entries may be ignored. nameserver 10.0.2.3

glibc lit trois serveurs au plus (resolv.conf(5), MAXNS = 3), donc le 4ᵉ est ignoré. Lequel tombe 4ᵉ n'est pas stable : sur cinq relevés en 24.04 et 26.04, le DNS sain quatre fois et un mort une fois, les deux vus sur le même 24.04. Ne lis pas cette ligne comme « ton bon DNS est ignoré ».

Éditer à la main ne tient pas : ta ligne disparaît au prochain renouvellement de bail, même si le DNS est le même (grep -c a donné 1, puis 0), parce que le fichier est remplacé (son inode change). L'autre piste de la personne qui pose la question :

« Other posts that I have read said that /etc/resolv.conf will get fed from: /etc/resolvconf/resolv.conf.d/tail , that file does not exist. » (« D'autres messages disaient que /etc/resolv.conf serait alimenté par /etc/resolvconf/resolv.conf.d/tail, ce fichier n'existe pas. »)

Ce dossier appartient au paquet resolvconf (celui de Debian y livre les fichiers head et base ; tail, c'est toi qui le crées), et sur ce 24.04, apt n'a aucun paquet resolvconf à installer. Ici, l'écrivain est celui que ls -l nomme.

03. Quel serveur DHCP a donné ce DNS

Interroge networkd. Le fichier de bail porte le numéro de l'interface.

le bail
$ networkctl status demo0 --no-pager | grep -E '^ *(Address|DNS):'
Address: 198.51.100.72 (DHCP4 via 198.51.100.1) DNS: 198.51.100.112
$ grep -E '^(SERVER_ADDRESS|DNS)=' /run/systemd/netif/leases/$(cat /sys/class/net/demo0/ifindex)
SERVER_ADDRESS=198.51.100.1 DNS=198.51.100.112 198.51.100.113 198.51.100.114

SERVER_ADDRESS est le coupable : un serveur DHCP, nommé par son adresse. Si le routeur a été corrigé et que l'ancien DNS traîne, networkctl renew demo0 demande un nouveau bail.

04. Le DNS que personne n'a écrit

Cas où le bail est innocent : on pose un DNS sur demo0 à la main, on renouvelle, on redémarre systemd-resolved, on relit le bail.

un DNS posé à la main
$ sudo resolvectl dns demo0 198.51.100.200
$ sudo networkctl renew demo0 && sleep 4 && resolvectl dns demo0
Link 12 (demo0): 198.51.100.200
$ sudo systemctl restart systemd-resolved && sleep 2 && resolvectl dns demo0
Link 12 (demo0): 198.51.100.200
$ grep '^DNS=' /run/systemd/netif/leases/$(cat /sys/class/net/demo0/ifindex)
DNS=198.51.100.112 198.51.100.113 198.51.100.114
$ sudo resolvectl revert demo0 && sleep 2 && resolvectl dns demo0
Link 12 (demo0): 198.51.100.112 198.51.100.113 198.51.100.114

Le DNS posé à la main survit au renouvellement et au redémarrage. Le bail dit toujours .112 à .114 : il ne dit pas ce qui est actif. resolvectl revert retire le DNS posé à la main. resolvectl(1) dit que ces commandes informent « systemd-resolved or systemd-networkd », et networkd le garde bien : dans nos essais, networkctl status demo0 affichait alors DNS: 198.51.100.200. Il survit aussi à netplan apply (mesuré sur 26.04).

05. Surveille le dossier, pas le fichier

Pour voir le changement au moment où il arrive : inotifywait sur le fichier, puis sur le dossier. Deux changements chacun.

fichier, puis dossier
$ sudo timeout 6 inotifywait -mq -e modify,attrib,move_self,delete_self /run/systemd/resolve/resolv.conf & sleep 1; sudo resolvectl dns demo0 198.51.100.201; sleep 1; sudo resolvectl dns demo0 198.51.100.202; wait
/run/systemd/resolve/resolv.conf ATTRIB /run/systemd/resolve/resolv.conf DELETE_SELF
$ sudo timeout 6 inotifywait -mq -e create,moved_to /run/systemd/resolve/ & sleep 1; sudo resolvectl dns demo0 198.51.100.203; sleep 1; sudo resolvectl dns demo0 198.51.100.204; wait
/run/systemd/resolve/ CREATE .#resolv.conf22c36321bad9fea2 /run/systemd/resolve/ CREATE .#stub-resolv.conf3152481f6abd0d30 /run/systemd/resolve/ MOVED_TO resolv.conf /run/systemd/resolve/ CREATE .#resolv.confe9d8f0efdac74324 /run/systemd/resolve/ CREATE .#stub-resolv.conf0d3055593eb59b9e /run/systemd/resolve/ MOVED_TO resolv.conf
$ sudo resolvectl revert demo0 && sleep 2 && resolvectl dns demo0
Link 12 (demo0): 198.51.100.112 198.51.100.113 198.51.100.114

Sur le fichier : ATTRIB, DELETE_SELF, puis rien au deuxième changement, parce que la surveillance suit l'ancien fichier, supprimé. Sur le dossier, chaque changement donne CREATE .#resolv.conf… puis MOVED_TO resolv.conf : écrit à côté, puis renommé par-dessus. Deux outils n'ont rien vu, mesuré sur 26.04 : une règle auditd sur /etc/resolv.conf, même pour une écriture à travers le lien (une règle sur le fichier cible, elle, l'a attrapée), et fatrace 0.19 dans /run.

06. Le correctif : refuser le DNS du DHCP sur cette interface

La deuxième réponse de la question commence par « I didn't find what is changing… » et propose DNS= dans /etc/systemd/resolved.conf. On l'essaie, avec une adresse de documentation.

un DNS= global
$ sudo mkdir -p /etc/systemd/resolved.conf.d
$ printf '[Resolve]\nDNS=192.0.2.53\n' | sudo tee /etc/systemd/resolved.conf.d/demo-global.conf
[Resolve] DNS=192.0.2.53
$ sudo systemctl restart systemd-resolved && sleep 2 && resolvectl dns
Global: 192.0.2.53 Link 2 (enp0s1): 10.0.2.3 Link 12 (demo0): 198.51.100.112 198.51.100.113 198.51.100.114
$ sudo rm /etc/systemd/resolved.conf.d/demo-global.conf && sudo systemctl restart systemd-resolved

Global: 192.0.2.53 s'ajoute, et demo0 garde ses trois serveurs morts. Ça ajoute, ça ne retire rien. Le correctif est sur l'interface. Netplan documente use-dns : « When true, the DNS servers received from the DHCP server will be used and take precedence over any statically configured ones. Currently only has an effect on the networkd back end. »

le correctif
$ printf 'network:\n version: 2\n ethernets:\n demo0:\n dhcp4: true\n dhcp4-overrides:\n use-dns: false\n' | sudo tee /etc/netplan/60-demo.yaml
network: version: 2 ethernets: demo0: dhcp4: true dhcp4-overrides: use-dns: false
$ sudo netplan apply && sleep 5 && resolvectl dns demo0
Link 12 (demo0):
$ (sudo timeout 8 tcpdump -tlni demo0 arp and host 198.51.100.112 2>/dev/null | grep -c who-has) & sleep 1; sudo resolvectl flush-caches; getent hosts example.net >/dev/null && echo 'example.net resolves'; wait
example.net resolves 0
$ grep -E '^nameserver|^# Too' /run/systemd/resolve/resolv.conf
nameserver 10.0.2.3

demo0 n'a plus de DNS, le compte de requêtes ARP vers le serveur mort est 0, et le fichier uplink ne contient que le sain. Portée : le back end networkd, le défaut serveur. Ubuntu Desktop (NetworkManager) : pas couvert, pas mesuré. Si dhcp4 et dhcp6 sont tous deux à true, networkd veut les mêmes clés dans les deux overrides.

Les trois réponses. La première (score 5) dit de renouveler le bail et de remettre le mode stub : juste si le serveur DHCP a été corrigé entre-temps, mais elle ne trouve rien si le DHCP redonne le même DNS, et un DNS posé à la main survit au renouvellement (section 04). La deuxième (score 1) : le DNS= global ci-dessus. La troisième (score 0) dit que /etc/resolv.conf est géré par « systemd-dnsmasq » : ni paquet ni page de manuel de ce nom en 24.04 ou 26.04.

07. Ménage

Garde dnsmasq-base s'il était installé avant (Ubuntu Desktop l'installe avec NetworkManager) et saute le dernier apt-get remove dans ce cas. tcpdump reste : Ubuntu le livre.

démontage
$ sudo rm /etc/netplan/60-demo.yaml
$ sudo netplan apply
$ sudo kill $(cat /run/demo-dnsmasq.pid)
$ sudo ip netns del demo-router
$ sudo rm /run/demo-dnsmasq.pid /run/demo-dnsmasq.leases
$ ip link show demo0
Device "demo0" does not exist.
$ sudo apt-get remove -y -qq dnsmasq-base inotify-tools >/dev/null

Pas mesuré : NetworkManager, resolvconf, Debian.

Partager :