Ինչու են ներքին հոսթանունները լուծվում 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-ը, ուստի աշխատող dig-ի կողքին getent-ի ձախողումը թերությունը տեղորոշում է որոնման քաղաքականության մեջ, ոչ թե փաթեթների երթուղավորման մեջ։ resolvectl query-ն նաև տպում է ինտերֆեյսը և այն վերին սերվերը, որը տվել է պատասխանը, ինչը ցույց է տալիս՝ արդյոք որոշումը հաղթել է թունելի կապը, թե ֆիզիկական կապը։
Կարդացեք այն resolver-ը, որն իրականում օգտագործում է ծրագիրը
/etc/resolv.conf-ը գեներացվում է աշխատասեղանների մեծ մասում, և VPN հաճախորդն ունի դրա հետ փոխազդելու երեք եղանակ. անվանասերվեր ավելացնել սկզբում, վերագրել ֆայլը կամ իր սերվերները տալ NetworkManager-ին և թույլ տալ դեմոնին վերագրել այն։ Միայն երրորդ ձևն է պահպանում կապի մակարդակի DNS-ը, որովհետև սերվերները մնում են կցված ինտերֆեյսին՝ մեկ գլոբալ ցանկի մեջ հարթեցվելու փոխարեն։
NetworkManager համակարգերում արդյունքը կախված է /etc/NetworkManager/NetworkManager.conf-ի backend-ից.
[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-ով ավարտվող ցանկացած անվան։ api.infra.svc.cluster.local-ի նման Kubernetes ծառայությունը նույնպես ավարտվում է .local-ով։ Երբ mDNS մոդուլը հաղորդում է NOTFOUND, [NOTFOUND=return] գործողությունը ավարտում է ամբողջ որոնումը՝ dns մոդուլին անցնելու փոխարեն, ուստի անունը երբեք չի ուղարկվում VPN resolver-ին։ dig-ը ամբողջությամբ շրջանցում է ֆայլը, և հենց դրա համար է, որ երկու գործիքները համաձայն չեն։
Սա այս խնդրի ամենասուր հակադրությունն է, և այն հանգում է մեկ բառի VPN-իցդ հին կոնֆիգուրացիոն ֆայլում։ Գործողությունը [NOTFOUND=continue]-ի փոխելը պահպանում է mDNS-ը տպիչների և տեղական սարքերի համար, միաժամանակ թույլ տալով DNS-ին տեսնել անունը։ Տողը hosts: files dns-ով փոխարինելը նույնպես աշխատում է և ավելի կոպիտ է. այն հանում է .local լուծումը այն տպիչի համար, որն իրականում օգտագործում եք։
Անուններ, որոնք ապրում են ուղիղ մեկ ցանցում
Մասնավոր զոնաները հեղինակավոր են ուղիղ մեկ տեղում։ ip-10-0-4-31.eu-west-1.compute.internal-ի նման AWS անունը պատասխանվում է այդ տարածաշրջանի 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 կողմը։
Որոշեք, թե որ շերտն ուղղել
Աշխատեք ախտանիշից դեպի շերտը՝ ուղղումները հերթով փորձելու փոխարեն.
| 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-ի վերագրանցում։
Ուղղեք միայն առաջին ձախողված շերտը, ապա նորից կատարեք նույն հրամանները։ Միաժամանակ երկու փոփոխությունը թույլ չի տալիս ասել, թե որն էր կարևոր, և հաջորդ խափանումը հետաքննությունը սկսում է զրոյից։