भविष्य को आकार देने वाली तकनीक पर गहन लेख।

DNS कॉन्फ़िगरेशन अब भी Production तोड़ रहा है

DNS सरल लगता है, जब तक टूट न जाए। OS updates, resolv.conf, mDNS और .internal TLD कैसे ऐसे production outages लाते हैं जिनकी डेवलपर्स को भनक नहीं होती।

सॉर्टिंग रूम में गलत न्यूमैटिक ट्यूब में भेजे जा रहे पत्र

Apple के नवीनतम macOS रिलीज़ ने हज़ारों डेवलपर्स की कस्टम DNS सेटिंग्स तोड़ दीं। खास तौर पर, इसने .internal TLD के लिए आने वाली queries को पकड़ना शुरू कर दिया — जिसे कई कंपनियाँ निजी नेटवर्क संसाधनों के लिए इस्तेमाल करती हैं — और उन्हें कॉन्फ़िगर किए गए DNS resolver के बजाय mDNS (multicast DNS) की ओर भेजने लगा। जो services सालों से ठीक चल रही थीं, वे अचानक पहुँच से बाहर हो गईं। समाधान आसान नहीं था। Error messages भी कुछ काम के नहीं थे। और जैसा DNS की समस्याओं में अक्सर होता है, लक्षण हर चीज़ जैसे दिख रहे थे — सिवाय DNS के।

यह कहानी DNS कॉन्फ़िगरेशन की है — ऐसा विषय जिससे हर डेवलपर का वास्ता पड़ता है, जिसे बहुत कम लोग गहराई से समझते हैं, और जिसे तब तक कोई गंभीरता से नहीं लेता जब तक रात 2 बजे production में कुछ टूट न जाए।

.internal TLD घटना

कई संगठन आंतरिक services के लिए .internal को निजी TLD के रूप में इस्तेमाल करते हैं: api.internal, db.staging.internal, grafana.internal। यह एक सुरक्षित चुनाव लगता था — यह कोई public TLD नहीं है, साफ़ संकेत देता है कि 'यह internal है', और दशकों से इसी तरह इस्तेमाल होता आया है।

फिर Apple के नए OS ने तय किया कि .internal को mDNS से संभाला जाए — वही protocol जो आपके होम नेटवर्क में myprinter.local को resolve करता है। जब आपका Mac api.internal को resolve करने की कोशिश करता है, तो वह कॉन्फ़िगर किए गए DNS server से पूछने के बजाय लोकल नेटवर्क पर mDNS query broadcast करता है। आपका DNS server यह query कभी देखता ही नहीं। जवाब या तो कुछ नहीं आता (timeout), या फिर गलत address मिलता है (अगर लोकल नेटवर्क पर कोई और डिवाइस उस नाम पर जवाब दे दे)।

लक्षण: curl api.internal 5 सेकंड अटकता है और फिर fail हो जाता है। Internal hosts के लिए SSH connections timeout हो जाते हैं। VPN उपयोगकर्ता internal resources तक नहीं पहुँच पाते। Docker containers service names resolve नहीं कर पाते। और क्योंकि failure एक आम connection timeout जैसा दिखता है, ज़्यादातर डेवलपर्स अपना VPN, firewall, application — सब कुछ debug करने लगते हैं, बस DNS को छोड़कर।

आधुनिक सिस्टम्स पर DNS resolution असल में कैसे काम करता है

'DNS तो सरल है' वाला मानसिक मॉडल — कंप्यूटर DNS server से IP पूछता है, server जवाब देता है — कई सालों से सही नहीं रहा। आधुनिक सिस्टम्स में कई चरणों वाली resolution pipeline होती है, और उनमें से हर चरण query को रोक सकता है, बदल सकता है या redirect कर सकता है।

DNS resolution pipeline on a typical macOS/Linux system:
Application calls getaddrinfo("api.internal")
↓
1. /etc/hosts — checked first. Static overrides.
↓
2. NSSwitch / resolver configuration
- Linux: /etc/nsswitch.conf controls lookup order
- macOS: /etc/resolver/* for per-domain DNS servers
↓
3. System resolver (systemd-resolved, mDNSResponder)
- May intercept .local, .internal, or other special TLDs
- May apply DNSSEC validation
- May cache responses
↓
4. DNS server (from DHCP, VPN, or manual config)
- Queries sent to configured upstream resolver
- May go through a corporate DNS proxy
↓
5. Recursive resolver (8.8.8.8, 1.1.1.1, corporate)
- Walks the DNS hierarchy: root → TLD → authoritative
↓
Response flows back up the chain

हर चरण पर कुछ गलत हो सकता है। System resolver शायद query को कॉन्फ़िगर किए गए DNS server तक पहुँचने से पहले ही रोक ले। VPN DNS settings को override कर सकता है। DHCP ऐसे DNS servers भेज सकता है जो आपकी manual configuration से ऊपर माने जाते हैं। और हर स्तर पर caching का मतलब है कि कोई fix तुरंत असर न करे।

/etc/resolv.conf वाला झूठ

Linux पर /etc/resolv.conf ऐतिहासिक रूप से DNS configuration का एकमात्र स्रोत था। वहाँ nameserver लिख दो, सिस्टम उसे इस्तेमाल करता है। सीधा-सादा।

आधुनिक Linux distributions ने इसे काफ़ी जटिल बना दिया है। अगर आप systemd-resolved चला रहे हैं (जो Ubuntu, Fedora और ज़्यादातर systemd-based distros में डिफ़ॉल्ट है), तो /etc/resolv.conf 127.0.0.53 पर मौजूद stub resolver का symlink होता है। आपकी असली DNS configuration systemd-resolved की state में रहती है, जिसे resolvectl से मैनेज किया जाता है। /etc/resolv.conf को सीधे edit करने पर वह अगले network बदलाव में overwrite हो जाती है, या stub resolver को तोड़ देती है।

# What you THINK your DNS config is:
$ cat /etc/resolv.conf
nameserver 127.0.0.53  # This is systemd-resolved's stub
# What your DNS config ACTUALLY is:
$ resolvectl status
Global:
DNS Servers: 8.8.8.8 8.8.4.4
DNS Domain: ~.
Link 2 (eth0):
DNS Servers: 10.0.0.1  # From DHCP — this takes precedence
DNS Domain: corp.internal
Link 5 (wg0):  # WireGuard VPN
DNS Servers: 10.100.0.1
DNS Domain: ~internal  # VPN claims the .internal domain
# Three different DNS servers, each handling different domains.
# /etc/resolv.conf shows none of this.

Docker एक और परत जोड़ता है। Docker containers को अपना /etc/resolv.conf मिलता है, जो आम तौर पर container शुरू होते समय host की configuration से कॉपी होता है। अगर host का DNS बदल जाए (VPN कनेक्ट हो, network switch हो), तो चल रहे containers तब तक पुरानी DNS configuration इस्तेमाल करते रहते हैं जब तक उन्हें restart न किया जाए। 'restart करने पर चलता है, पर कुछ देर बाद फेल हो जाता है' वाले bugs का यह आम कारण है।

Split DNS और VPN के टकराव

Split DNS — अलग-अलग domains के लिए अलग DNS servers इस्तेमाल करना — कॉर्पोरेट वातावरण में आम बात है। आपका VPN *.corp.internal queries को corporate DNS server की ओर भेजता है, जबकि public queries आपके सामान्य resolver के पास जाती हैं। सही तरीके से configure हो तो यह बढ़िया काम करता है, और गलत होने पर उलझाने वाली तरह से फेल होता है।

आम failure modes:

  • VPN DNS servers को global default बना देता है। कुछ VPN clients सभी queries के लिए VPN का DNS server default resolver बना देते हैं, सिर्फ़ internal के लिए नहीं। अब आपकी हर DNS query — निजी browsing सहित — corporate DNS server से होकर जाती है। यह धीमा होता है (क्योंकि corporate DNS किसी और data center में है) और privacy की चिंता भी है।
  • DNS server का क्रम टकराता है। जब कई DNS servers configured हों, तो सिस्टम उन्हें क्रम से आज़माता है। अगर पहला server धीमा है या पहुँच से बाहर है (VPN डिस्कनेक्ट हो गया पर DNS config बची है), तो हर DNS query दूसरे server को आज़माने से पहले timeout का इंतज़ार करती है। इससे हर connection में 5 सेकंड की देरी जुड़ जाती है।
  • Search domains चुपचाप जुड़ जाते हैं। corp.internal वाला search domain होने पर api की query api.corp.internal को भी आज़माती है। यह सुविधाजनक है (ssh api.corp.internal की जगह ssh api लिख सकते हैं) जब तक यह काम करना बंद न कर दे — जब कोई छोटा hostname किसी internal service के नाम से टकराए, तो queries गलत IP पर resolve हो जाती हैं।
  • mDNS internal domains को पकड़ लेता है। जैसा .internal घटना दिखाती है, सिस्टम resolver कुछ TLDs की queries को किसी भी कॉन्फ़िगर किए गए DNS server तक पहुँचने से पहले ही रोक सकता है। यह खास तौर पर खतरनाक है क्योंकि यह interception चुपचाप होता है — कोई error message नहीं, बस timeout या गलत जवाब।

DNS की डीबगिंग: टूलकिट

जब DNS टूटे, तो आपको ऐसे tools चाहिए जो resolution pipeline के हर चरण पर असली स्थिति दिखाएँ।

# 1. Check what your system actually resolves:
$ dig api.internal
# Shows: query sent to which server, response received
# The 'SERVER' line tells you which DNS server answered
# 2. Query a specific DNS server directly:
$ dig @10.100.0.1 api.internal
# Bypasses the system resolver — goes directly to the specified server
# If this works but 'dig api.internal' doesn't, the problem is
# in the system resolver, not the DNS server
# 3. Check systemd-resolved state (Linux):
$ resolvectl query api.internal
# Shows which interface/server handled the query
# 4. Check macOS DNS routing:
$ scutil --dns
# Shows per-domain DNS configuration on macOS
# Look for your .internal domain — is it being routed correctly?
# 5. Monitor DNS queries in real time:
$ sudo tcpdump -i any port 53
# See actual DNS packets. If no packets go out for your query,
# the system resolver is intercepting it locally.
# 6. Flush DNS cache (when fixing config):
$ sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder  # macOS
$ resolvectl flush-caches  # Linux with systemd-resolved

सबसे ज़रूरी diagnostic कदम: dig @server hostname से सीधे अपने DNS server से query करें। अगर यह काम करे पर सामान्य resolution न करे, तो समस्या आपकी application और DNS server के बीच है — system resolver का interception, caching, या routing। अगर सीधी queries भी फेल हों, तो समस्या DNS server में या उसके नेटवर्क कनेक्शन में है।

अपना निजी TLD चुनना

.internal घटना एक व्यावहारिक सवाल खड़ा करती है: internal services के लिए कौन सा TLD इस्तेमाल करें? कोई सार्वभौमिक रूप से सुरक्षित जवाब नहीं है, लेकिन कुछ विकल्प दूसरों से बेहतर हैं।

  • .internal — RFC 6762 इसे internal उपयोग के लिए आरक्षित करता है, पर Apple का mDNS हैंडलिंग macOS पर इसे समस्याग्रस्त बनाता है। Linux पर शायद ठीक चले।
  • .local — mDNS के लिए आरक्षित (RFC 6762)। DNS से resolve होने वाली services के लिए इसका इस्तेमाल Bonjour/Avahi से टकराएगा। इसका इस्तेमाल न करें।
  • .corp, .home, .mail — आरक्षित नहीं हैं। ICANN इन्हें किसी भी समय public TLD के रूप में दे सकता है, जिससे आपका internal resolution टूट जाएगा। इनका इस्तेमाल न करें।
  • आपके स्वामित्व वाले domain का subdomain। internal.yourcompany.com — यह सबसे सुरक्षित विकल्प है। पैरेंट domain आपके नियंत्रण में है, इसलिए टकराव का कोई खतरा नहीं। कमी यह है कि टाइप करने में थोड़ा लंबा है।
  • .test, .example, .invalid, .localhost — RFC 6761 द्वारा आरक्षित, और गारंटीशुदा कि इन्हें कभी public TLD नहीं दिया जाएगा। जो internal services production नहीं हैं, उनके लिए .test सबसे साफ़ विकल्प है।

सीधा-सादा लेकिन सही जवाब: अपने स्वामित्व वाले domain का subdomain इस्तेमाल करें। api.internal.yourcompany.com बिल्कुल स्पष्ट है, किसी से नहीं टकराता, और हर OS व हर DNS resolver पर सही काम करता है। यह लंबा है, पर 2 बजे रात की DNS समस्या कुछ अतिरिक्त अक्षर टाइप करने से कहीं ज़्यादा महंगी पड़ती है।

Production सिस्टम्स के लिए सबक

हर DNS outage एक ही सबक सिखाता है, और हम उसे बार-बार दोबारा सीखते हैं।

  1. सिर्फ़ DNS servers नहीं, DNS resolution की निगरानी करें। आपका DNS server स्वस्थ होने का मतलब यह नहीं कि resolution काम कर रहा है। पूरे रास्ते की निगरानी करें: क्या आपकी application वास्तव में वे hostnames resolve कर पा रही है जिनकी उसे ज़रूरत है? हर 30 सेकंड में महत्वपूर्ण hostnames resolve करने वाला synthetic check server monitoring से तेज़ी से समस्या पकड़ता है।
  2. Internal DNS के लिए छोटे TTL रखें। जब internal DNS record बदलना हो, तो लंबे TTL का मतलब पुराना cached डेटा है। Internal services के लिए 60 सेकंड का TTL कम resolver load के साथ तेज़ failover देता है।
  3. OS updates को अपने DNS setup पर टेस्ट करें। .internal की समस्या सिर्फ़ macOS उपयोगकर्ताओं पर आई। बड़े OS updates के बाद अपना development environment टेस्ट करें — DNS resolution में बदलाव शायद ही कभी release notes में लिखे जाते हैं।
  4. अपना DNS architecture दस्तावेज़ित करें। कौन से DNS servers कौन से domains संभालते हैं? Split points कहाँ हैं? VPN डिस्कनेक्ट होने पर क्या होता है? यह दस्तावेज़ outage के दौरान सबसे पहले चाहिए होगा, और इसे सबसे कम लोग लिखते हैं।
  5. एक fallback रखें। अगर किसी internal service के लिए DNS resolution फेल हो, तो क्या आपकी application hardcoded IP इस्तेमाल कर सकती है? यह सुंदर तरीका नहीं है, पर काम करने वाला hardcoded IP उस DNS नाम से बेहतर है जो resolve ही नहीं होता।

DNS उन बुनियादी सेवाओं में से है जो काम करते समय दिखती ही नहीं, और टूटते ही तबाही मचा देती है। .internal की समस्या याद दिलाती है कि DNS configuration दिखने से ज़्यादा नाज़ुक है — एक OS update लाखों उपयोगकर्ताओं के resolution व्यवहार को बदल सकता है। अपने systems को इस मान्यता के साथ बनाएँ कि DNS टूटेगा, और जब टूटेगा तो आप कम चौंकेंगे।