Konfigurasi DNS Masih Sering Bikin Production Down
DNS terlihat sederhana sampai rusak. Simak bagaimana update OS, resolv.conf, mDNS, dan TLD .internal bisa memicu outage production yang tak terduga.

Rilis macOS terbaru dari Apple merusak pengaturan DNS kustom milik ribuan developer. Secara spesifik, sistem mulai mencegat query untuk TLD .internal — yang dipakai banyak perusahaan untuk resource jaringan privat — lalu mengarahkannya ke mDNS (multicast DNS), bukan ke resolver DNS yang sudah dikonfigurasi. Layanan yang sudah bertahun-tahun berjalan normal tiba-tiba tidak bisa diakses. Solusinya tidak langsung kelihatan. Pesan errornya pun tidak membantu. Dan seperti biasa pada masalah DNS, gejalanya terlihat seperti apa saja kecuali DNS.
Ini cerita tentang konfigurasi DNS — topik yang pasti pernah dihadapi setiap developer, jarang benar-benar dipahami, dan selalu diremehkan sampai akhirnya merusak sesuatu di production jam 2 pagi.
Insiden TLD .internal
Banyak organisasi memakai .internal sebagai TLD privat untuk layanan internal: api.internal, db.staging.internal, grafana.internal. Pilihan ini kelihatannya aman — bukan TLD publik, jelas menandakan ‘ini internal’, dan sudah dipakai begitu selama puluhan tahun.
Lalu OS baru Apple memutuskan bahwa .internal harus ditangani oleh mDNS — protokol yang sama yang meresolve myprinter.local di jaringan rumahmu. Saat Mac kamu mencoba meresolve api.internal, alih-alih bertanya ke DNS server yang sudah dikonfigurasi, ia malah menyiarkan query mDNS di jaringan lokal. DNS server kamu tidak pernah melihat query itu. Responsnya bisa berupa tidak ada sama sekali (timeout) atau alamat yang salah (kalau ada perangkat di jaringan lokal yang kebetulan merespons nama tersebut).
Gejalanya: curl api.internal menggantung 5 detik lalu gagal. Koneksi SSH ke host internal timeout. Pengguna VPN tidak bisa mengakses resource internal. Container Docker tidak bisa meresolve nama service. Dan karena kegagalannya tampil sebagai connection timeout generik, kebanyakan developer langsung mengecek VPN, firewall, atau aplikasinya — apa saja kecuali DNS.
Cara Kerja Resolusi DNS di Sistem Modern
Model mental ‘DNS itu sederhana’ — komputer bertanya ke DNS server untuk mendapatkan IP, server menjawab — sudah tidak akurat selama bertahun-tahun. Sistem modern punya pipeline resolusi dengan beberapa tahap, dan setiap tahap bisa mencegat, memodifikasi, atau mengalihkan query.
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
Di setiap tahap, bisa saja ada yang salah. Resolver sistem mungkin mencegat query sebelum sampai ke DNS server yang sudah kamu atur. VPN bisa menimpa pengaturan DNS. DHCP bisa membawa DNS server yang mengalahkan konfigurasi manual kamu. Dan caching di setiap level berarti perbaikan yang kamu lakukan belum tentu langsung berlaku.
Kebohongan /etc/resolv.conf
Di Linux, /etc/resolv.conf dulunya adalah satu-satunya sumber kebenaran untuk konfigurasi DNS. Atur nameserver di sana, dan sistem akan memakainya. Sederhana.
Distro Linux modern membuat hal ini jauh lebih rumit. Jika kamu menjalankan systemd-resolved (yang default di Ubuntu, Fedora, dan sebagian besar distro berbasis systemd), /etc/resolv.conf adalah symlink ke stub resolver di 127.0.0.53. Konfigurasi DNS yang sebenarnya tersimpan di state systemd-resolved dan dikelola lewat resolvectl. Mengedit /etc/resolv.conf secara langsung akan tertimpa saat ada perubahan jaringan berikutnya, atau malah merusak 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 menambah satu lapisan lagi. Container Docker punya /etc/resolv.conf sendiri, biasanya disalin dari konfigurasi host saat container dijalankan. Kalau DNS host berubah (VPN terhubung, jaringan berganti), container yang sudah berjalan tetap memakai konfigurasi DNS lama sampai di-restart. Ini sering jadi sumber bug ‘berfungsi setelah restart tapi gagal lagi setelah beberapa waktu’.
Split DNS dan Konflik VPN
Split DNS — memakai DNS server berbeda untuk domain yang berbeda — sudah jadi standar di lingkungan korporat. VPN kamu mengarahkan query *.corp.internal ke DNS server perusahaan, sementara query publik tetap ke resolver biasa. Ini bekerja dengan baik kalau dikonfigurasi dengan benar, dan gagal dengan cara membingungkan kalau tidak.
Mode kegagalan yang umum:
- VPN mendorong DNS server sebagai default global. Beberapa klien VPN menjadikan DNS server VPN sebagai resolver default untuk semua query, bukan hanya yang internal. Semua query DNS kamu — termasuk browsing pribadi — jadi lewat DNS server perusahaan. Ini lambat (karena DNS perusahaan ada di datacenter lain) dan juga menjadi masalah privasi.
- Konflik urutan DNS server. Saat beberapa DNS server dikonfigurasi, sistem mencobanya secara berurutan. Kalau server pertama lambat atau tidak terjangkau (VPN sudah putus tapi konfigurasi DNS-nya masih ada), setiap query DNS harus menunggu timeout dulu sebelum mencoba server kedua. Hasilnya, setiap koneksi tertambah delay 5 detik.
- Search domain menambahkan sufiks diam-diam. Search domain
corp.internalberarti query untukapijuga akan dicoba sebagaiapi.corp.internal. Ini berguna (cukup ketikssh apialih-alihssh api.corp.internal) sampai suatu saat tidak lagi — ketika hostname pendek bentrok dengan nama service internal, query malah resolve ke IP yang salah. - mDNS mencegat domain internal. Seperti yang ditunjukkan insiden
.internal, resolver sistem bisa mencegat query untuk TLD tertentu sebelum sampai ke DNS server mana pun yang sudah dikonfigurasi. Ini sangat licik karena intersepsinya terjadi diam-diam — tanpa pesan error, hanya timeout atau respons yang salah.
Debugging DNS: Perangkatnya
Saat DNS bermasalah, kamu butuh tools yang menunjukkan persis apa yang terjadi di setiap tahap pipeline resolusi.
# 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
Langkah diagnosis paling penting: query DNS server secara langsung dengan dig @server hostname. Kalau itu berhasil tapi resolusi normal gagal, masalahnya ada di antara aplikasi dan DNS server — intersepsi resolver sistem, caching, atau routing. Kalau query langsung juga gagal, masalahnya ada di DNS server itu sendiri atau konektivitas jaringan ke sana.
Memilih TLD Privat Kamu
Insiden .internal memunculkan pertanyaan praktis: TLD apa yang sebaiknya dipakai untuk layanan internal? Tidak ada jawaban yang benar-benar aman, tapi sebagian pilihan lebih baik dari yang lain.
- .internal — RFC 6762 memang mencadangkannya untuk penggunaan internal, tapi penanganan mDNS dari Apple membuatnya bermasalah di macOS. Mungkin baik-baik saja di Linux.
- .local — Dicadangkan untuk mDNS (RFC 6762). Memakainya untuk layanan yang diresolve lewat DNS akan bentrok dengan Bonjour/Avahi. Jangan dipakai.
- .corp, .home, .mail — Tidak dicadangkan. ICANN bisa menetapkannya sebagai TLD publik kapan saja, dan itu akan merusak resolusi internal kamu. Jangan dipakai.
- Subdomain dari domain milikmu.
internal.yourcompany.com— ini pilihan paling aman. Kamu mengontrol domain induknya, jadi tidak ada risiko bentrok. Kekurangannya: lebih panjang untuk diketik. - .test, .example, .invalid, .localhost — Dicadangkan oleh RFC 6761 dan dijamin tidak akan pernah ditetapkan sebagai TLD publik.
.testadalah pilihan paling bersih untuk layanan internal yang bukan production.
Jawaban yang membosankan tapi benar: pakai subdomain dari domain milikmu. api.internal.yourcompany.com tidak ambigu, tidak akan bentrok dengan apa pun, dan berfungsi dengan benar di setiap OS dan resolver DNS. Memang lebih panjang, tapi masalah DNS jam 2 pagi jauh lebih menyebalkan daripada mengetik beberapa karakter tambahan.
Pelajaran untuk Sistem Production
Setiap outage DNS mengajarkan pelajaran yang sama, dan kita terus mempelajarinya ulang.
- Monitor resolusi DNS, bukan cuma DNS server. DNS server yang sehat tidak berarti resolusinya berjalan. Monitor seluruh jalurnya: apakah aplikasi kamu benar-benar bisa meresolve hostname yang dibutuhkan? Pengecekan sintetis yang meresolve hostname kritis setiap 30 detik lebih cepat mendeteksi masalah dibanding monitoring server saja.
- Pasang TTL pendek untuk DNS internal. Saat kamu perlu mengubah record DNS internal, TTL yang panjang berarti data lama tersimpan di cache. TTL 60 detik untuk layanan internal memberi failover yang cepat dengan beban resolver yang minimal.
- Uji update OS terhadap setup DNS kamu. Kerusakan
.internalhanya berdampak pada pengguna macOS. Uji environment development setelah update OS besar — perubahan perilaku resolusi DNS jarang tercantum di release notes. - Dokumentasikan arsitektur DNS kamu. DNS server mana yang menangani domain apa? Di mana titik pemisahnya? Apa yang terjadi saat VPN putus? Dokumentasi ini adalah hal pertama yang kamu butuhkan saat outage, dan hal terakhir yang biasanya ditulis siapa pun.
- Siapkan fallback. Kalau resolusi DNS gagal untuk layanan internal, bisakah aplikasi kamu memakai IP hardcoded? Ini memang tidak elegan, tapi IP hardcoded yang berfungsi lebih baik daripada nama DNS yang tidak bisa diresolve.
DNS adalah layanan fundamental yang tak terlihat saat bekerja dan bencana saat tidak. Insiden .internal jadi pengingat bahwa konfigurasi DNS lebih rapuh dari kelihatannya — satu update OS bisa mengubah perilaku resolusi untuk jutaan pengguna. Bangun sistemmu dengan asumsi bahwa DNS akan rusak, dan kamu tidak akan terlalu kaget saat itu terjadi.


