Чаму ўнутраныя імёны хастоў вырашаюцца ў dig, але не ўдаюцца ў curl на VPN
dig адказвае, але curl паведамляе, што не можа вырашыць хост. Параўнайце абодва ланцугі пошуку, а потым выпраўце nsswitch, DNS па злучэнні або няправільны суфікс пошуку.
Ваш ноўтбук у 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, таму імя ніколі не дасылаецца resolver тунеля. dig цалкам абыходзіць файл, і менавіта таму два інструменты не пагаджаюцца.
Гэта найвастрэйшы кантраст у гэтай праблеме, і ён зводзіцца да аднаго слова ў канфігурацыйным файле, старэйшым за ваш VPN. Змена дзеяння на [NOTFOUND=continue] захоўвае mDNS для прынтараў і лакальных прылад, дазваляючы DNS бачыць імя. Замена радка на hosts: files dns таксама працуе і больш грубая: яна адмаўляецца ад развязання .local для прынтара, якім вы насамрэч карыстаецеся.
Імёны, што жывуць роўна ў адной сетцы
Прыватныя зоны аўтарытэтныя роўна ў адным месцы. Імя AWS накшталт ip-10-0-4-31.eu-west-1.compute.internal адказваецца праз resolver VPC таго рэгіёна, і толькі пакуль ваша канчатковая кропка VPN у тым жа рэгіёне, што і рэсурс. Падключыцеся да канчатковай кропкі ў Франкфурце, запытайцеся пра імя compute.internal з Ірландыі, і ніякая лакальная налада не дапаможа: зона, што трымае запіс, адтуль недасяжная.
Домены пошуку даюць люстраны адбітак. Голае service дапаўняецца суфіксам, які resolver лічыць прыдатным, і з злучэннем VPN лакальны домен можа перамагчы карпаратыўны. Запытайцеся з канчатковай кропкай, каб прыбраць здагадкі, getent ahosts service.internal.example., і калі гэта працуе, пакуль кароткае імя не ўдаецца, выпраўленне — домен пошуку на тунелі, а не адрас сервера.
Кіраваныя кліенты дадаюць трэці пласт над сістэмным resolver. Профіль VPN Windows можа несці ўласную палітыку развязання імёнаў, правілы для асобных праграм і табліцу NRPT, якая дзейнічае нават калі тунель выключаны. Праграмы з уласным кэшам DNS, звычайныя ў асяроддзях .NET і Java, доўга трымаюць састарэлы збой пасля выпраўлення ланцуга. Кліенты Apple наладжваюць split DNS праз супадальныя домены ў наладах DNS, а не праз resolv.conf, а Chromium або Firefox у рэжыме бяспечнага DNS могуць абыходзіць сістэмны resolver для публічных імёнаў. Даведка Microsoft пра развязанне імёнаў VPN апісвае бок Windows гэтага пласта палітыкі.
Вырашыце, які пласт выпраўляць
Ідзіце ад сімптому да пласта, замест каб спрабаваць выпраўленні па чарзе:
| 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 |
Два радкі нясуць большую частку вагі. Час чакання — гэта праблема дасяжнасці: прыватны 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.
Выпраўце толькі першы пласт, што не ўдаецца, а потым зноў выканайце тыя ж каманды. Дзве змены адразу не дазваляюць сказаць, якая мела значэнне, і наступны збой пачынае расследаванне з нуля.