DNS Resolution and Troubleshooting¶
"It's always DNS" is a joke because it's usually true. This article covers how a Linux host actually resolves a hostname to an address, and the tools to find out where that process broke.
How it works¶
The resolution chain¶
When an application calls getaddrinfo("example.com") (what every DNS-aware tool uses under the hood), the C library consults /etc/nsswitch.conf:
This means: check /etc/hosts first, then fall back to DNS. A stale or wrong entry in /etc/hosts silently shadows real DNS and is a surprisingly common cause of "but DNS is configured correctly!" Your line may carry extra entries (on Ubuntu, for example, resolve or mdns4_minimal [NOTFOUND=return]); what matters is that files comes before dns.
On most modern systems, actual DNS queries go through systemd-resolved, not directly to the nameservers configured by your network:
$ resolvectl status
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (eth0)
Current Scopes: DNS
Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 192.0.2.53
DNS Servers: 192.0.2.53 203.0.113.53
"resolv.conf mode: stub" means /etc/resolv.conf actually points at 127.0.0.53 — a local stub resolver run by systemd-resolved — rather than listing your real upstream DNS servers directly. This is normal and by design, but it means editing /etc/resolv.conf directly often has no lasting effect on these systems; it gets regenerated. Use resolvectl or your network manager's DNS settings instead.
Querying DNS directly, bypassing the OS resolver¶
dig example.com # full, verbose output
dig +short example.com # just the answer
dig example.com @8.8.8.8 # query a specific server directly, bypassing /etc/resolv.conf
dig -x 203.0.113.10 # reverse lookup (PTR record)
dig example.com MX # a different record type
dig <name> @<server> is the single most useful DNS debugging technique: it tells you definitively whether the problem is the DNS server's answer (wrong even when queried directly) or your local resolution path (works fine against @8.8.8.8 but not through the system's normal resolver).
Reading a dig answer¶
With the verbose form (dig example.com, no +short), look at the ANSWER SECTION:
The 300 is the TTL in seconds — how long resolvers are allowed to cache this answer. A DNS change that "isn't taking effect" for a while after you made it is very often just caching behaving exactly as designed, up to the old record's TTL.
Ubuntu/Debian vs. RHEL-family differences¶
| Ubuntu/Debian (modern) | RHEL-family | |
|---|---|---|
| Local resolver | systemd-resolved (stub at 127.0.0.53) by default | NetworkManager-managed /etc/resolv.conf, often without a local stub |
| Inspect config | resolvectl status | nmcli dev show <iface> \| grep DNS or check /etc/resolv.conf directly |
On RHEL-family systems without systemd-resolved, /etc/resolv.conf usually does reflect the real upstream nameservers directly, and editing it manually works — but may be overwritten by NetworkManager on the next network event unless marked otherwise.
Practical exercise¶
- Compare
dig +short example.comagainst your system's default resolver vs.dig +short example.com @8.8.8.8— confirm they return the same address (or figure out why they don't). - Check the TTL of the answer with plain
dig example.com(without+short). - Deliberately add a wrong entry to
/etc/hostsfor a real domain, confirm it overrides DNS (getent hosts <domain>reflects the hosts-file entry), then remove it.
How to verify you did it correctly¶
- Step 3:
getent hosts <domain>should return your fake IP while the entry exists in/etc/hosts, and the real DNS-resolved IP again immediately after you remove it (no caching —/etc/hostsis re-read on every lookup, unlike DNS answers).
Common mistakes¶
- Flushing the wrong cache.
resolvectl flush-cachesonly clears systemd-resolved's cache — if your application has its own DNS cache (some runtimes/browsers do), this won't touch that. - Troubleshooting with
ping's DNS resolution instead ofdig.pingdoes a resolution and immediately tells you if it worked, but gives none of the diagnostic detail (which server answered, the TTL, the actual record type) thatdigdoes. - Forgetting
/etc/hostsexists at all and spending time investigating "broken" DNS servers when a stale hosts-file entry is silently shadowing them.
⚠ Dangerous commands / cautions¶
- Changing
/etc/nsswitch.conf'shosts:line incorrectly (e.g., removingdnsentirely) can break all hostname resolution on the host system-wide, affecting package managers, monitoring agents, and anything else that resolves names — not just your application.
Related articles¶
Review questions¶
- Why might editing
/etc/resolv.confdirectly have no effect on a system running systemd-resolved? - What does
dig example.com @8.8.8.8let you determine that a plaindig example.comdoesn't? - Why would a DNS record change seem to "not take effect" immediately even after you've confirmed the authoritative server has the new value?
- In what order does
/etc/nsswitch.conf's defaulthosts: files dnsconsult sources, and what does that mean for a stale/etc/hostsentry?