dig and DNS Debugging
DNS bugs are notorious for showing up as "it works for me" - the same name
resolving differently on two machines, or a change that took effect for some
users and not others. dig is the tool for pulling apart exactly what a
resolver answered and why; see DNS in Practice
for the record types and TTL/caching concepts this page assumes.
The basic query
The parts that matter for debugging:
- status: NOERROR - the query succeeded;
NXDOMAINmeans the name does not exist,SERVFAILmeans the authoritative or recursive server errored. - ANSWER SECTION - the actual record(s) returned, with their TTL
(
86400seconds here) - how much longer this answer will be cached. - AUTHORITY SECTION - present instead of an answer on an
NXDOMAIN, or alongside a referral; shows which nameservers are authoritative for the zone. Useful for confirming delegation is set up correctly. - SERVER - which resolver actually answered. This is the first thing to check when two machines disagree.
"Works on one machine, not another"
This symptom is almost always one of two things, and dig distinguishes
them directly:
-
Stale cache - one machine (or its resolver) cached an old answer before a record changed, and its TTL has not yet expired. Query the same name against a few different resolvers and compare:
If the local resolver disagrees with public ones, it is very likely serving a cached answer from before the record was updated, or split-horizon (see below). Waiting out the TTL, or flushing the local resolver's cache, resolves it.
-
Split-horizon DNS - the two machines are genuinely supposed to get different answers, because they are asking from different networks (e.g. one is on the office VPN, one is not) and the authoritative server is intentionally serving an internal address to one and a public address to the other.
dig @<resolver>from each network, pointed at the same authoritative server, confirms whether the difference is deliberate zone config rather than a caching bug.
Comparing dig output from two machines is meaningless if you don't also
compare which resolver answered (the SERVER line). Two machines using
two different resolvers can legitimately show different TTLs remaining, or
different answers under split-horizon, without either being "wrong."
Tracing the full delegation path
dig +trace walks the resolution from the root down, exactly the way a
recursive resolver would, instead of trusting a single resolver's cached
answer:
This is the tool for diagnosing delegation problems - a missing or wrong NS
record at the registrar, a zone that lost its glue records, or a nameserver
that is unreachable. A plain dig only shows you the recursive resolver's
final answer (or cached failure); +trace shows you exactly which step in
the chain broke.
Querying a specific resolver directly
dig @<resolver> <name> bypasses whatever resolver your OS is configured to
use and asks a specific one - essential for the "works on one machine" case
above, and for checking whether a change has propagated to a particular public
resolver yet:
Reverse lookups
dig -x <ip> asks for the PTR record - the hostname associated with an IP,
the reverse of a normal lookup. Useful for identifying an unfamiliar IP in a
log file, or confirming that a mail server's reverse DNS matches its forward
DNS (many mail providers reject mail from IPs that fail this check):
nslookup: the older alternative
nslookup predates dig and is still installed everywhere (including
Windows, where dig often is not), but its output is less detailed and its
interactive mode is clunkier to script against:
Reach for nslookup only when dig genuinely is not available (stock
Windows, some minimal containers). Everywhere else, dig gives you the
TTL, the full ANSWER/AUTHORITY/ADDITIONAL sections, and +trace/+short
flags that nslookup cannot match.
dig +short strips everything but the answer data itself - the fastest way
to get a value into a shell variable or script without parsing the full
output.