Вашият лаптоп е във VPN, dig service.internal.example отговаря с адрес 10.x, а curl все още завършва с Could not resolve host. Тунелът не е проблемът: той пренесе dig заявката без оплаквания. Разликата е кой задава въпроса. dig изпраща една заявка до един сървър, който вие посочвате, докато curl минава през веригата за търсене на операционната система, а тази верига има собствени правила кой сървър се пита.

Две търсения за едно и също име

dig е собствен stub resolver. Чете /etc/resolv.conf, избира сървър за имена, изпраща една A или AAAA заявка и отпечатва отговора. Напълно пропуска nsswitch и не знае нищо за състоянието по връзка, което systemd-resolved или NetworkManager държат извън този файл, и затова dig отговор може да е правилен и въпреки това да не ви каже нищо за това, което ще види приложението ви.

Приложенията извикват getaddrinfo, а getaddrinfo минава по-дълга верига: редът на модулите в nsswitch, после модулът, който обработва името, и накрая resolver, изграден от текущата конфигурация на връзката. На systemd машина заявката отива до 127.0.0.53 и systemd-resolved избира горен сървър за всяка връзка според домейна за маршрутизиране, прикачен към интерфейса tun.

Две команди разделят тези слоеве без гадаене:

getent ahosts service.internal.example
resolvectl query service.internal.example

getent използва същия път като curl, така че getent грешка до работещ dig локализира дефекта в политиката за търсене, а не в маршрутизирането на пакети. resolvectl query отпечатва също интерфейса и горния сървър, който е дал отговора, което показва дали връзката на тунела или физическата връзка е спечелила решението.

Прочетете resolver-а, който приложението действително използва

/etc/resolv.conf се генерира на повечето настолни системи, а VPN клиентът има три начина да взаимодейства с него: да добави сървър за имена отпред, да презапише файла или да предаде своите сървъри на NetworkManager и да остави демона да го презапише. Само третият модел запазва DNS по връзка, защото сървърите остават прикачени към интерфейс, вместо да бъдат сплескани в един глобален списък.

В системи с NetworkManager резултатът зависи от backend-а в /etc/NetworkManager/NetworkManager.conf:

[main]
dns=systemd-resolved

С dns=default сървърите на клиента се сливат в resolv.conf в реда, който победи, и частна заявка все още може да бъде изпратена до публичния resolver. С backend, който разбира връзките, systemd-resolved или dnsmasq, сървърите на тунела остават ограничени до тунела и там отиват само имената, съответстващи на неговия домейн за маршрутизиране. Това ограничение е това, което split DNS означава на практика, и то е частта, която най-често липсва, когато клиент твърди, че го поддържа.

Прочетете състоянието, преди да промените нещо:

resolvectl status
resolvectl dns tun0

Искате да видите интерфейса tun изброен със DNS сървър и домейн за маршрутизиране за частния суфикс, показани като ~internal.example. Липсата на сървър на връзката означава, че клиентът не е изпратил нищо. Сървър без домейн означава, че заявките или всички отиват там, или нито една, в зависимост от клиента, и нито едно от двете не е split DNS.

Къде nsswitch прекратява търсенето твърде рано

Стандартен ред на настолна система изглежда така:

hosts: files mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns myhostname

mdns4_minimal обработва multicast DNS и предявява претенции за всяко име, завършващо на .local. Kubernetes услуга като api.infra.svc.cluster.local също завършва на .local. Когато mDNS модулът отчете NOTFOUND, действието [NOTFOUND=return] прекратява цялото търсене, вместо да продължи към модула dns, така че името никога не се изпраща до VPN resolver-а. dig заобикаля файла напълно, и точно затова двата инструмента не са съгласни.

Това е най-острия контраст в този проблем и се свежда до една дума в конфигурационен файл, по-стар от вашия VPN. Промяната на действието на [NOTFOUND=continue] запазва mDNS за принтери и локални устройства, като същевременно позволява на DNS да види името. Замяната на реда с hosts: files dns също работи и е по-груба: премахва разрешаването на .local за принтера, който действително използвате.

Имена, които живеят в точно една мрежа

Частните зони са авторитетни на точно едно място. AWS име като ip-10-0-4-31.eu-west-1.compute.internal се отговаря чрез VPC resolver-а на този регион и само докато вашата VPN крайна точка е в същия регион като ресурса. Свържете се с крайна точка във Франкфурт, попитайте за compute.internal име от Ирландия и никаква локална настройка няма да помогне: зоната, която държи записа, не е достъпна оттам.

Домейните за търсене дават огледалния образ. Голо service се допълва със суфикса, който resolver-ът смята за приложим, а с VPN връзка локалният домейн може да победи корпоративния. Питайте със завършваща точка, за да премахнете гадането, getent ahosts service.internal.example., и ако това работи, докато краткото име се проваля, поправката е домейнът за търсене на тунела, а не адресът на сървъра.

Управляваните клиенти добавят трети слой над системния resolver. Windows VPN профил може да носи собствена политика за разрешаване на имена, правила за отделни приложения и NRPT таблица, която важи дори когато тунелът е изключен. Приложенията със собствен DNS кеш, обичайни в .NET и Java среди, задържат остарял провал дълго след като веригата е поправена. Apple клиентите конфигурират split DNS чрез съвпадащи домейни в DNS настройките, а не чрез resolv.conf, а Chromium или Firefox в режим на защитен DNS могат да заобиколят системния resolver за публични имена. Справката на Microsoft за разрешаване на VPN имена описва Windows страната на този слой политика.

Решете кой слой да поправите

Работете от симптома към слоя, вместо да пробвате поправки по ред:

SymptomWhat it meansCheck first
dig answers, getent failslookup chain, not the packet pathnsswitch line and resolvectl status
Timeout rather than NXDOMAINprivate resolver unreachable through the tunnelresolvectl dns tun0, route to that address
NXDOMAINan authority answered and does not know the namezone owner, endpoint region
FQDN works, short name failssearch suffix mismatchresolvectl domain on the tun link
getent works, app failsapp cache or its own resolverrestart the app, check secure DNS

Два реда носят по-голямата част от тежестта. Времето за изчакване е проблем на достъпност: частният resolver не отговаря през тунела, затова проверете маршрута до адреса му и дали DNS сървърът на връзката е този, който мислите. NXDOMAIN е проблем на авторитет: нещо е отговорило и не знае името, което сочи към зоната, региона или resolver, който никога не е трябвало да получи заявката.

Последният ред е този, който хората пропускат, защото и двете половини изглеждат като успех. Кратко име, което се разрешава различно от FQDN, е несъответствие на суфикса, а повторното свързване на тунела няма да промени кой суфикс изпраща клиентът.

Запишете състоянието, преди да редактирате конфигурационен файл, за да можете да кажете дали редакцията е направила нещо:

resolvectl status > before.txt
getent ahosts service.internal.example >> before.txt

Изпълнете проверките в този ред и спрете на първата, която се провали. getent и resolvectl query трябва да съвпадат; ако getent се провали, докато dig отговаря, останете във веригата за търсене и не пипайте маршрутизирането. resolvectl status трябва да покаже DNS сървър и домейн за маршрутизиране на интерфейса tun. nsswitch не трябва да се връща рано с NOTFOUND за суфикса, който тествате. Името трябва да е авторитетно в мрежата, към която е прикачена вашата крайна точка, тествано със завършваща точка. Приложението не трябва да държи собствен кеш или презаписване на защитения DNS.

Поправете само първия провалил се слой и след това отново изпълнете същите команди. Две промени наведнъж ви оставят без възможност да кажете коя е имала значение, а следващата повреда започва разследването от нула.

Подобни статии