Waarom resolv.conf je VPN-DNS toont maar lookups hem negeren
Op een host met resolved is het bestand een weergave, niet de status. Volg de stub, de servers per link en de nsswitch-regel om te zien welke een lookup echt gebruikt.
Niets in de logs ziet er verkeerd uit: de interface is up, de resolver meldt de DNS-server van de VPN en het bestand op schijf vermeldt hem. Toch wordt een interne hostnaam nog steeds via de lokale router opgelost. Die drie uitspraken spreken elkaar niet tegen, want het bestand, de status per link en het zoekpad zijn verschillende objecten die toevallig dezelfde naam delen. Wat volgt is het pad dat een query op een host met systemd-resolved werkelijk aflegt.
Drie objecten die resolv.conf heten
Op een host met resolved is /etc/resolv.conf meestal een symbolische link naar /run/systemd/resolve/stub-resolv.conf. Dat doel bevat het adres van een lokale stub-listener, 127.0.0.53, plus de zoekdomeinen die resolved heeft berekend. Het is een weergave van de status, niet de status zelf.
De status leeft in de configuratie van resolved per link, en daarom kan resolvectl status het oneens zijn met het bestand en toch gelijk hebben. Elke link draagt zijn eigen servers en zijn eigen routingdomeinen, en de stub raadpleegt die gegevens wanneer een query binnenkomt. De handleiding van systemd-resolved beschrijft de gegenereerde bestanden en het model per link; de scheiding tussen weergave en status is het deel dat de moeite waard is. Het doel van de symbolische link wijzigen verandert wat traditionele clients lezen, niet wat de resolver weet.
Een derde object, /run/systemd/resolve/resolv.conf, vlakt elke link af tot één serverlijst. Een programma dat naar dat bestand wijst, stuurt queries rechtstreeks naar de vermelde servers en slaat de stub over, dus het beleid per link geldt er niet meer voor. Twee programma's op dezelfde machine kunnen daardoor dezelfde naam verschillend beantwoorden, en geen van beide is stuk.
Volg één lookup door NSS
glibc leest /etc/nsswitch.conf om te bepalen wie een naam beantwoordt. Een hosts-regel met resolve stuurt de vraag naar nss-resolve, dat resolved via D-Bus vraagt en het antwoord per link krijgt. Een regel met alleen files dns stuurt de query naar het adres dat /etc/resolv.conf heeft.
Die ene regel verklaart de meeste meningsverschillen tussen een browser en dig. dig leest resolv.conf rechtstreeks en raakt NSS nooit aan, dus test het de stub of een upstream-server in plaats van het pad dat de toepassing gebruikt. getent hosts internal.example gaat door NSS, en het antwoord ervan vergelijken met dat van dig is de eerste nuttige meting.
Toepassingen die hun eigen resolver meebrengen, of DNS over HTTPS spreken met een vast eindpunt, omzeilen beide paden. Niets in resolv.conf of in de status van resolved beperkt ze.
Controleer wie het bestand bezit en waar het naartoe wijst
Lees de linkketen voordat je iets wijzigt, want eigendom bepaalt welk bestand gezaghebbend is. Elk commando hieronder leest alleen status.
stat -c '%N' /etc/resolv.conf
resolvectl status --no-pager
grep '^hosts' /etc/nsswitch.conf
ls -l /run/systemd/resolve/
De eerste regel drukt de link en zijn doel samen af, en een gewoon bestand in bezit van een VPN-script betekent dat de resolver die schrijfactie nooit als invoer behandelt. De statusuitvoer vermeldt servers per link plus de routingdomeinen die bepalen waar elke query heen gaat. De nsswitch-regel zegt of de stub überhaupt wordt geraadpleegd, dus een stub-adres in het bestand zonder resolve daar betekent dat queries de lokale listener bereiken terwijl niets de splitsing beheert. Die laatste lijst doet er ook toe, want een host zonder stub-resolv.conf draait de hier beschreven regeling niet.
Als de keten eindigt bij een bestand dat een ander pakket beheert, zijn de VPN-client en dat pakket de twee eigenaren die verzoend moeten worden. De link vervangen gooit het werk van de ene eigenaar weg en laat dat van de andere staan.
Repareer bij de eigenaar van de link
Een VPN-verbinding hoort zijn servers en zijn domeinen op zijn eigen link te registreren en ze bij verbreken weer in te trekken. De resolved-integratie van NetworkManager en de eigen helper van een client werken allebei zo; een script dat alleen resolv.conf herschrijft, niet.
Op een link die al bestaat, laat de runtime-instelling het mechanisme zien. resolvectl dns tun0 10.40.0.53 koppelt een server, en resolvectl domain tun0 '~corp.example' koppelt een routingdomein. De tilde is het dragende teken: hij beperkt queries voor dat achtervoegsel tot deze link en laat al het andere met rust, terwijl dezelfde waarde zonder tilde een zoekdomein wordt en de splitsing verdampt. Die adressen zijn laboratoriumvoorbeelden, geen blijvende configuratie. Bevestig met resolvectl query host.corp.example en lees welke link antwoordde.
Een geregistreerde server heeft nog steeds een route nodig. Als de query de juiste link bereikt en dan verloopt, zit de fout in bereikbaarheid door de tunnel en niet in het eigendom van de resolver.
Hoe een werkende status eruitziet
Een gezond resultaat is consistent in alle drie de weergaven: de servers per link komen overeen met wat de VPN uitdeelde, de routingdomeinen dekken alleen interne achtervoegsels, en de toepassing die ertoe doet, lost een interne naam op terwijl een openbare naam nog steeds het lokale pad volgt. Eén geslaagde query bewijst minder dan die overeenstemming.
Verbreek daarna de verbinding en herhaal beide queries. Een client die zijn domeinen na het afbreken geregistreerd laat, produceert een machine die uren later interne lookups mist, zonder open tunnel en zonder duidelijke oorzaak.