Miksi sisäiset isäntänimet ratkeavat digissä mutta epäonnistuvat curlissa VPN-yhteydellä
dig vastaa, mutta curl ilmoittaa, ettei se pysty ratkaisemaan isäntää. Vertaa kahta hakuketjua ja korjaa sitten nsswitch, linkkikohtainen DNS tai väärä hakusuffiksi.
Kannettavasi on VPN:ssä, dig service.internal.example vastaa 10.x-osoitteella ja curl päättyy yhä Could not resolve host. Tunneli ei ole ongelma: se kuljetti dig-kyselyn valittamatta. Ero on siinä, kuka kysymyksen esittää. dig lähettää yhden kyselyn yhdelle itse nimeämällesi palvelimelle, kun taas curl kulkee käyttöjärjestelmän hakuketjun läpi, ja tuolla ketjulla on omat sääntönsä siitä, miltä palvelimelta kysytään.
Kaksi hakua samalle nimelle
dig on oma stub-resolverinsa. Se lukee /etc/resolv.conf-tiedoston, valitsee nimipalvelimen, lähettää yhden A- tai AAAA-kyselyn ja tulostaa vastauksen. Se ohittaa nsswitchin kokonaan eikä tiedä mitään siitä linkkikohtaisesta tilasta, jota systemd-resolved tai NetworkManager pitävät kyseisen tiedoston ulkopuolella, ja siksi dig-vastaus voi olla oikea ja silti kertoa sinulle mitään siitä, mitä sovelluksesi näkee.
Sovellukset kutsuvat getaddrinfoa, ja getaddrinfo kulkee pidemmän ketjun: nsswitchin moduulijärjestys, sitten nimen käsittelevä moduuli ja lopuksi nykyisestä linkkikonfiguraatiosta rakennettu resolver. systemd-koneella kysely menee 127.0.0.53:lle ja systemd-resolved valitsee linkkikohtaisen ylävirran palvelimen tun-rajapintaan liitetyn reititystoimialueen perusteella.
Kaksi komentoa erottavat nämä kerrokset arvaamatta:
getent ahosts service.internal.example
resolvectl query service.internal.example
getent käyttää samaa polkua kuin curl, joten getent-virhe toimivan digin rinnalla paikantaa vian hakukäytäntöön eikä pakettireititykseen. resolvectl query tulostaa myös rajapinnan ja ylävirran, joka vastauksen antoi, mikä näyttää, voittiko ratkaisun tunnelilinkki vai fyysinen linkki.
Lue resolveri, jota sovellus todella käyttää
/etc/resolv.conf luodaan useimmilla työpöydillä, ja VPN-asiakkaalla on kolme tapaa käsitellä sitä: lisätä nimipalvelin eteen, korvata tiedosto tai antaa palvelimensa NetworkManagerille ja antaa daemonin kirjoittaa se uudelleen. Vain kolmas malli säilyttää linkkikohtaisen DNS:n, koska palvelimet pysyvät rajapintaan kiinnitettyinä sen sijaan, että ne litistettäisiin yhdeksi globaaliksi listaksi.
NetworkManager-järjestelmissä tulos riippuu /etc/NetworkManager/NetworkManager.conf-tiedoston backendistä:
[main]
dns=systemd-resolved
Asetuksella dns=default asiakkaan palvelimet sulautetaan resolv.conf-tiedostoon voittavassa järjestyksessä, ja yksityinen haku voi silti päätyä julkiselle resolverille. Linkit ymmärtävällä backendillä, systemd-resolved tai dnsmasq, tunnelin palvelimet pysyvät tunneliin rajattuina ja vain sen reititystoimialueeseen sopivat nimet menevät sinne. Tämä rajaus on se, mitä split DNS käytännössä tarkoittaa, ja se on osa, joka useimmin puuttuu, kun asiakas väittää tukevansa sitä.
Lue tila ennen kuin muutat mitään:
resolvectl status
resolvectl dns tun0
Haluat nähdä tun-rajapinnan listattuna DNS-palvelimella ja yksityisen suffiksin reititystoimialueella, näytettynä muodossa ~internal.example. Ei palvelinta linkillä tarkoittaa, ettei asiakas työntänyt mitään. Palvelin ilman toimialuetta tarkoittaa, että haut menevät joko kaikki sinne tai ei yhtään, asiakkaasta riippuen, eikä kumpikaan ole split DNS.
Missä nsswitch lopettaa haun liian aikaisin
Tavallinen työpöytärivi näyttää tältä:
hosts: files mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns myhostname
mdns4_minimal hoitaa multicast-DNS:n ja vaatii jokaisen .local-loppuisen nimen. Kubernetes-palvelu kuten api.infra.svc.cluster.local päättyy myös .localiin. Kun mDNS-moduuli raportoi NOTFOUND, toiminto [NOTFOUND=return] lopettaa koko haun sen sijaan, että jatkaisi dns-moduuliin, joten nimeä ei koskaan lähetetä VPN:n resolverille. dig ohittaa tiedoston kokonaan, ja juuri siksi kaksi työkalua ovat eri mieltä.
Tämä on tämän ongelman terävin vastakohta, ja se tiivistyy yhteen sanaan konfiguraatiotiedostossa, joka on vanhempi kuin VPN:si. Toiminnon muuttaminen muotoon [NOTFOUND=continue] säilyttää mDNS:n tulostimille ja paikallisille laitteille samalla kun DNS voi nähdä nimen. Rivin korvaaminen muodolla hosts: files dns toimii myös ja on karkeampi: se pudottaa .local-ratkaisun siltä tulostimelta, jota todella käytät.
Nimet, jotka elävät täsmälleen yhdessä verkossa
Yksityiset vyöhykkeet ovat valtuutettuja täsmälleen yhdessä paikassa. AWS-nimi kuten ip-10-0-4-31.eu-west-1.compute.internal vastataan kyseisen alueen VPC-resolverin kautta, ja vain niin kauan kuin VPN-päätepisteesi on samalla alueella kuin resurssi. Yhdistä Frankfurtin päätepisteeseen, kysy irlantilaista compute.internal-nimeä, eikä mikään paikallinen asetus auta: tietueen sisältävään vyöhykkeeseen ei pääse sieltä.
Hakutoimialueet tuottavat peilikuvan. Paljas service täydennetään suffiksilla, jota resolver pitää soveltuvana, ja VPN-linkillä paikallinen toimialue voi voittaa yrityksen toimialueen. Kysy loppupisteellä arvailun poistamiseksi, getent ahosts service.internal.example., ja jos se toimii lyhyen nimen epäonnistuessa, korjaus on tunnelin hakutoimialue, ei palvelimen osoite.
Hallinnoidut asiakkaat lisäävät kolmannen kerroksen järjestelmän resolverin päälle. Windows-VPN-profiili voi kantaa oman nimiratkaisukäytäntönsä, sovelluskohtaiset sääntönsä ja NRPT-taulukon, joka on voimassa myös silloin, kun tunneli on alas. Sovellukset, joilla on oma DNS-välimuisti, yleisiä .NET- ja Java-ajoympäristöissä, pitävät vanhentunutta virhettä kauan sen jälkeen, kun ketju on korjattu. Apple-asiakkaat määrittävät split DNS:n DNS-asetusten vastaavuustoimialueilla resolv.confin sijaan, ja Chromium tai Firefox suojatun DNS:n tilassa voivat ohittaa järjestelmän resolverin julkisille nimille. Microsoftin VPN-nimiratkaisun viite kuvaa tämän käytäntökerroksen Windows-puolen.
Päätä, mikä kerros korjata
Etene oireesta kerrokseen sen sijaan, että kokeilisit korjauksia järjestyksessä:
| 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 |
Kaksi riviä kantaa suurimman osan painosta. Aikakatkaisu on tavoitettavuusongelma: yksityinen resolver ei vastaa tunnelin kautta, joten tarkista reitti sen osoitteeseen ja se, onko linkin DNS-palvelin se, mitä luulet. NXDOMAIN on valtuusongelma: jokin vastasi eikä tunne nimeä, mikä viittaa vyöhykkeeseen, alueeseen tai resolveriin, jonka ei koskaan pitänyt saada kyselyä.
Viimeinen rivi on se, jonka ihmiset ohittavat, koska molemmat puolet näyttävät menestykseltä. Lyhyt nimi, joka ratkeaa eri tavalla kuin FQDN, on suffiksin epäsopivuus, eikä tunnelin uudelleenyhdistäminen muuta sitä, minkä suffiksin asiakas lähettää.
Tallenna tila ennen kuin muokkaat konfiguraatiotiedostoa, jotta voit sanoa, tekikö muokkaus mitään:
resolvectl status > before.txt
getent ahosts service.internal.example >> before.txt
Suorita tarkistukset tässä järjestyksessä ja pysähdy ensimmäiseen, joka epäonnistuu. getentin ja resolvectl queryn on oltava samaa mieltä; jos getent epäonnistuu digin vastatessa, pysy hakuketjussa äläkä koske reititykseen. resolvectl statusin on näytettävä DNS-palvelin ja reititystoimialue tun-rajapinnalla. nsswitch ei saa palata aikaisin NOTFOUNDilla testattavalle suffiksille. Nimen on oltava valtuutettu verkossa, johon päätepisteesi on liitetty, testattuna loppupisteellä. Sovellus ei saa pitää omaa välimuistiaan tai suojatun DNS:n ohitusta.
Korjaa vain ensimmäinen epäonnistuva kerros ja suorita sitten samat komennot uudelleen. Kaksi muutosta kerralla jättää sinut sanomaan, mikä niistä merkitsi, ja seuraava katkos aloittaa tutkinnan nollasta.