Hvorfor interne vertsnavn løses med dig, men feiler med curl på en VPN
dig svarer, men curl rapporterer at den ikke kan slå opp verten. Sammenlign de to oppslagskjedene, og rett deretter nsswitch, DNS per lenke eller et feil søkesuffiks.
Bærbaren din er på VPN-en, dig service.internal.example svarer med en 10.x-adresse, og curl avslutter fortsatt med Could not resolve host. Tunnelen er ikke problemet: den fraktet dig-spørringen uten klager. Det som er forskjellig, er hvem som stiller spørsmålet. dig sender én spørring til én server du navngir, mens curl går gjennom operativsystemets oppslagskjede, og den kjeden har egne regler for hvilken server som blir spurt.
To oppslag for samme navn
dig er sin egen stub-resolver. Den leser /etc/resolv.conf, velger en navneserver, sender én enkelt A- eller AAAA-spørring og skriver ut svaret. Den hopper helt over nsswitch og vet ingenting om tilstanden per lenke som systemd-resolved eller NetworkManager holder utenfor den filen, og derfor kan et dig-svar være riktig og likevel ikke si deg noe om hva applikasjonen din vil se.
Applikasjoner kaller getaddrinfo, og getaddrinfo går gjennom en lengre kjede: modulrekkefølgen i nsswitch, deretter modulen som håndterer navnet, og så resolveren som bygges fra den gjeldende lenkekonfigurasjonen. På en systemd-maskin går spørringen til 127.0.0.53, og systemd-resolved velger en oppstrøms server per lenke basert på rutingsdomenet som er knyttet til tun-grensesnittet.
To kommandoer skiller disse lagene uten å gjette:
getent ahosts service.internal.example
resolvectl query service.internal.example
getent bruker samme vei som curl, så en getent-feil ved siden av en fungerende dig lokaliserer feilen til oppslagspolicyen og ikke til pakkerutingen. resolvectl query skriver også ut grensesnittet og oppstrømsen som ga svaret, noe som viser om tunnellenken eller den fysiske lenken vant avgjørelsen.
Les resolveren applikasjonen faktisk bruker
/etc/resolv.conf genereres på de fleste skrivebord, og en VPN-klient har tre måter å forholde seg til den på: sette en navneserver først, overskrive filen eller overlate serverne sine til NetworkManager og la daemonen skrive den på nytt. Bare det tredje mønsteret bevarer DNS per lenke, fordi serverne forblir knyttet til et grensesnitt i stedet for å bli flatet ut til én global liste.
På NetworkManager-systemer avhenger resultatet av backenden i /etc/NetworkManager/NetworkManager.conf:
[main]
dns=systemd-resolved
Med dns=default flettes klientens servere inn i resolv.conf i den rekkefølgen som vinner, og et privat oppslag kan fortsatt sendes til den offentlige resolveren. Med en backend som forstår lenker, systemd-resolved eller dnsmasq, forblir tunnelens servere begrenset til tunnelen, og bare navn som samsvarer med rutingsdomenet går dit. Den begrensningen er hva split DNS betyr i praksis, og det er den brikken som oftest mangler når en klient hevder å støtte det.
Les tilstanden før du endrer noe:
resolvectl status
resolvectl dns tun0
Du vil se tun-grensesnittet listet med en DNS-server og et rutingsdomene for det private suffikset, vist som ~internal.example. Ingen server på lenken betyr at klienten ikke sendte noe. En server uten domene betyr at oppslag enten alle sendes dit eller ingen, avhengig av klienten, og ingen av delene er split DNS.
Der nsswitch avslutter oppslaget for tidlig
En standardlinje på et skrivebord ser slik ut:
hosts: files mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns myhostname
mdns4_minimal håndterer multicast-DNS og gjør krav på alle navn som slutter på .local. En Kubernetes-tjeneste som api.infra.svc.cluster.local slutter også på .local. Når mDNS-modulen rapporterer NOTFOUND, avslutter handlingen [NOTFOUND=return] hele oppslaget i stedet for å fortsette til dns-modulen, så navnet blir aldri sendt til VPN-resolveren. dig omgår filen fullstendig, og det er nettopp derfor de to verktøyene er uenige.
Det er den skarpeste kontrasten i dette problemet, og det koker ned til ett ord i en konfigurasjonsfil som er eldre enn VPN-en din. Endrer du handlingen til [NOTFOUND=continue], beholdes mDNS for skrivere og lokale enheter mens DNS kan se navnet. Å erstatte linjen med hosts: files dns fungerer også og er grovere: det dropper .local-oppslaget for skriveren du faktisk bruker.
Navn som bare finnes i ett nettverk
Private soner er autoritative på nøyaktig ett sted. Et AWS-navn som ip-10-0-4-31.eu-west-1.compute.internal besvares via VPC-resolveren i den regionen, og bare så lenge VPN-endepunktet ditt er i samme region som ressursen. Koble til et endepunkt i Frankfurt, slå opp et compute.internal-navn fra Irland, og ingen lokal innstilling hjelper: sonen som holder posten, er ikke tilgjengelig derfra.
Søkedomener gir speilbildet. Et bart service fylles ut med suffikset resolveren mener gjelder, og med en VPN-lenke kan det lokale domenet vinne over bedriftens. Slå opp med et punktum til slutt for å fjerne gjettingen, getent ahosts service.internal.example., og hvis det virker mens det korte navnet feiler, er rettelsen søkedomenet på tunnelen, ikke serveradressen.
Administrerte klienter legger et tredje lag over operativsystemets resolver. En Windows-VPN-profil kan bære sin egen navneoppløsningspolicy, regler per app og en NRPT-tabell som gjelder selv når tunnelen er nede. Applikasjoner med egen DNS-cache, vanlig i .NET- og Java-runtimes, beholder en foreldet feil lenge etter at kjeden er rettet. Apple-klienter konfigurerer split DNS via match-domener i DNS-innstillingene i stedet for via resolv.conf, og Chromium eller Firefox i secure-DNS-modus kan omgå systemets resolver for offentlige navn. Microsofts referanse for VPN-navneoppløsning beskriver Windows-siden av det policylaget.
Bestem hvilket lag som skal rettes
Arbeid fra symptomet til laget i stedet for å prøve rettelser i rekkefølge:
| Symptom | What it means | Check first |
|---|---|---|
| dig answers, getent fails | lookup chain, not the packet path | nsswitch line and resolvectl status |
| Timeout rather than NXDOMAIN | private resolver unreachable through the tunnel | resolvectl dns tun0, route to that address |
| NXDOMAIN | an authority answered and does not know the name | zone owner, endpoint region |
| FQDN works, short name fails | search suffix mismatch | resolvectl domain on the tun link |
| getent works, app fails | app cache or its own resolver | restart the app, check secure DNS |
To rader bærer det meste. En timeout er et tilgjengelighetsproblem: den private resolveren svarer ikke gjennom tunnelen, så kontroller ruten til adressen og om DNS-serveren på lenken er den du tror. NXDOMAIN er et autoritetsproblem: noe svarte, og det kjenner ikke navnet, noe som peker på sonen, regionen eller en resolver som aldri skulle ha mottatt spørringen.
Den siste raden er den folk overser fordi begge halvdeler ser ut som suksess. Et kort navn som løses annerledes enn FQDN-en, er en suffiks-mismatch, og å koble til tunnelen på nytt endrer ikke hvilket suffiks klienten sender.
Ta vare på tilstanden før du redigerer en konfigurasjonsfil, så du kan se om endringen gjorde noe:
resolvectl status > before.txt
getent ahosts service.internal.example >> before.txt
Kjør kontrollene i denne rekkefølgen og stopp ved den første som feiler. getent og resolvectl query må stemme overens; hvis getent feiler mens dig svarer, bli i oppslagskjeden og la rutingen være. resolvectl status må vise en DNS-server og et rutingsdomene på tun-grensesnittet. nsswitch må ikke returnere tidlig på NOTFOUND for suffikset du tester. Navnet må være autoritativt i nettverket endepunktet ditt er knyttet til, testet med et punktum til slutt. Applikasjonen må ikke holde egen cache eller en secure-DNS-overstyring.
Rett bare det første laget som feiler, og kjør deretter de samme kommandoene igjen. To endringer samtidig gjør at du ikke kan si hvilken som betydde noe, og neste avbrudd starter undersøkelsen fra null.