VPN पर आंतरिक होस्टनाम dig में क्यों हल होते हैं लेकिन curl में विफल रहते हैं
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 मल्टीकास्ट 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 क्लाइंट DNS सेटिंग्स में मैच डोमेन से split DNS सेट करते हैं, resolv.conf से नहीं, और Chromium या Firefox सुरक्षित DNS मोड में सार्वजनिक नामों के लिए सिस्टम resolver को बायपास कर सकते हैं। VPN नाम-हल पर Microsoft का संदर्भ उस नीति-परत का 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 को tun इंटरफ़ेस पर DNS सर्वर और रूटिंग डोमेन दिखाना चाहिए। nsswitch परीक्षण किए जा रहे सफ़िक्स के लिए NOTFOUND पर जल्दी न लौटे। नाम उस नेटवर्क में आधिकारिक होना चाहिए जिससे आपका एंडपॉइंट जुड़ा है, अंत में बिंदु के साथ जाँचा गया। एप्लिकेशन अपना कैश या सुरक्षित DNS का ओवरराइड न रखे।
सिर्फ़ पहली विफल परत ठीक करें, फिर वही कमांड दोबारा चलाएँ। एक साथ दो बदलाव आपको यह बताने से रोकते हैं कि कौन-सा मायने रखता था, और अगली खराबी जाँच शून्य से शुरू करती है।