Warum resolv.conf Ihren VPN-DNS anzeigt, Abfragen ihn aber ignorieren
Auf einem Host mit resolved ist die Datei eine Ansicht, nicht der Zustand. Folgen Sie dem Stub, den Servern pro Verbindung und der nsswitch-Zeile, um zu sehen, was eine Abfrage wirklich nutzt.
In den Protokollen sieht nichts falsch aus: Das Interface ist oben, der Resolver meldet den DNS-Server des VPN, und die Datei auf der Platte listet ihn. Trotzdem wird ein interner Hostname weiterhin über den lokalen Router aufgelöst. Die drei Aussagen widersprechen sich nicht, denn die Datei, der Zustand pro Verbindung und der Abfrageweg sind verschiedene Objekte, die zufällig denselben Namen teilen. Was folgt, ist der Weg, den eine Abfrage auf einem Host mit systemd-resolved tatsächlich nimmt.
Drei Objekte namens resolv.conf
Auf einem Host mit resolved ist /etc/resolv.conf meist ein symbolischer Link auf /run/systemd/resolve/stub-resolv.conf. Dieses Ziel enthält die Adresse eines lokalen Stub-Listeners, 127.0.0.53, sowie die Suchdomains, die resolved berechnet hat. Es ist eine Ansicht des Zustands, nicht der Zustand selbst.
Der Zustand lebt in der Konfiguration von resolved pro Verbindung, weshalb resolvectl status der Datei widersprechen und dennoch recht haben kann. Eine Verbindung trägt ihre eigenen Server und ihre eigenen Routing-Domains, und der Stub zieht diese Daten heran, wenn eine Abfrage eintrifft. Das Handbuch zu systemd-resolved beschreibt die erzeugten Dateien und das Modell pro Verbindung; die Trennung von Ansicht und Zustand ist der Teil, den man sich merken sollte. Das Ziel des symbolischen Links zu ändern ändert, was traditionelle Clients lesen, nicht was der Resolver weiß.
Ein drittes Objekt, /run/systemd/resolve/resolv.conf, flacht jede Verbindung zu einer einzigen Serverliste ab. Ein Programm, das auf diese Datei zeigt, schickt Abfragen direkt an die gelisteten Server und überspringt den Stub, sodass die Richtlinie pro Verbindung für es nicht mehr gilt. Zwei Programme auf derselben Maschine können daher denselben Namen unterschiedlich beantworten, und keines davon ist defekt.
Eine Abfrage durch NSS verfolgen
glibc liest /etc/nsswitch.conf, um zu entscheiden, wer einen Namen beantwortet. Eine hosts-Zeile mit resolve leitet die Frage an nss-resolve weiter, das resolved über D-Bus fragt und die Antwort pro Verbindung erhält. Eine Zeile nur mit files dns schickt die Abfrage an die Adresse, die /etc/resolv.conf enthält.
Diese eine Zeile erklärt die meisten Meinungsverschiedenheiten zwischen einem Browser und dig. dig liest resolv.conf direkt und berührt NSS nie, prüft also den Stub oder einen vorgelagerten Server statt den Weg, den die Anwendung nutzt. getent hosts internal.example geht durch NSS, und dessen Antwort mit der von dig zu vergleichen ist die erste brauchbare Messung.
Anwendungen, die einen eigenen Resolver mitbringen oder DNS über HTTPS mit einem festen Endpunkt sprechen, umgehen beide Wege. Nichts in resolv.conf oder im Zustand von resolved beschränkt sie.
Prüfen, wem die Datei gehört und wohin sie zeigt
Lesen Sie die Linkkette, bevor Sie etwas ändern, denn der Besitz entscheidet, welche Datei maßgeblich ist. Jeder Befehl unten liest nur Zustand.
stat -c '%N' /etc/resolv.conf
resolvectl status --no-pager
grep '^hosts' /etc/nsswitch.conf
ls -l /run/systemd/resolve/
Die erste Zeile gibt den Link und sein Ziel gemeinsam aus, und eine gewöhnliche Datei, die einem VPN-Skript gehört, bedeutet, dass der Resolver diesen Schreibvorgang nie als Eingabe behandelt. Die Statusausgabe listet Server pro Verbindung sowie die Routing-Domains, die entscheiden, wohin jede Abfrage geht. Die nsswitch-Zeile sagt, ob der Stub überhaupt herangezogen wird, eine Stub-Adresse in der Datei ohne resolve dort bedeutet also, dass Abfragen den lokalen Listener erreichen, während nichts die Aufteilung verwaltet. Auch die letzte Auflistung zählt, denn ein Host ohne stub-resolv.conf betreibt die hier beschriebene Anordnung nicht.
Endet die Kette in einer Datei, die ein anderes Paket verwaltet, sind der VPN-Client und dieses Paket die beiden Eigentümer, die in Einklang gebracht werden müssen. Den Link zu ersetzen verwirft die Arbeit des einen Eigentümers und lässt die des anderen stehen.
Beim Eigentümer des Links reparieren
Eine VPN-Verbindung sollte ihre Server und ihre Domains auf ihrer eigenen Verbindung registrieren und sie beim Trennen wieder zurückziehen. Die resolved-Integration von NetworkManager und der eigene Helfer eines Clients arbeiten genau so; ein Skript, das nur resolv.conf umschreibt, nicht.
Auf einer bereits bestehenden Verbindung zeigt die Laufzeitkonfiguration den Mechanismus. resolvectl dns tun0 10.40.0.53 hängt einen Server an, und resolvectl domain tun0 '~corp.example' hängt eine Routing-Domain an. Die Tilde ist das tragende Zeichen: Sie beschränkt Abfragen für dieses Suffix auf diese Verbindung und lässt alles andere in Ruhe, während derselbe Wert ohne sie zu einer Suchdomain wird und die Aufteilung verdampft. Diese Adressen sind Laborbeispiele, keine dauerhafte Konfiguration. Bestätigen Sie mit resolvectl query host.corp.example und lesen Sie, welche Verbindung geantwortet hat.
Ein registrierter Server braucht trotzdem eine Route. Wenn die Abfrage die richtige Verbindung erreicht und dann ausläuft, liegt der Fehler in der Erreichbarkeit durch den Tunnel und nicht im Besitz des Resolvers.
Wie ein funktionierender Zustand aussieht
Ein gesundes Ergebnis ist in allen drei Ansichten stimmig: Die Server pro Verbindung entsprechen dem, was das VPN ausgegeben hat, die Routing-Domains decken nur interne Suffixe ab, und die wichtige Anwendung löst einen internen Namen auf, während ein öffentlicher Name weiterhin dem lokalen Weg folgt. Eine erfolgreiche Abfrage beweist weniger als diese Übereinstimmung.
Trennen Sie dann die Verbindung und wiederholen Sie beide Abfragen. Ein Client, der seine Domains nach dem Abbau registriert lässt, erzeugt eine Maschine, die Stunden später interne Auflösungen verfehlt, ohne offenen Tunnel und ohne erkennbare Ursache.