dig Explained: Diagnosing DNS From the Command Line

dig Explained: Diagnosing DNS From the Command Line

Networking problems have a running joke attached: it is always DNS. The joke persists because DNS failures are indirect. A service is unreachable, a certificate fails to validate, an email bounces, and the cause is a record three delegations up that nobody has looked at.

dig is the tool for looking.

sudo apt install dnsutils      # Debian and Ubuntu
sudo dnf install bind-utils    # Fedora
sudo pacman -S bind            # Arch

Basic queries

dig example.com                    # A record, verbose output
dig +short example.com             # just the answer
dig example.com MX                 # mail servers
dig example.com TXT                # text records, SPF, verification
dig example.com NS                 # nameservers
dig example.com AAAA               # IPv6
dig example.com ANY                # everything, often refused now

+short is what you want in scripts. Full output is what you want when investigating.

Reading the output

;; QUESTION SECTION:
;example.com.			IN	A

;; ANSWER SECTION:
example.com.		3600	IN	A	93.184.216.34

;; Query time: 24 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)

The number before IN is the TTL, in seconds, and it is the single most useful field for understanding why a change has not propagated. A TTL of 3600 means resolvers may hold this answer for an hour.

SERVER tells you who answered. 127.0.0.53 means systemd-resolved, which is a local cache rather than an authority.

The status line matters too:

  • NOERROR with an answer: fine
  • NOERROR with no answer: the name exists but has no record of that type
  • NXDOMAIN: the name does not exist
  • SERVFAIL: the resolver failed, often DNSSEC validation or an unreachable authority
  • REFUSED: the server declined to answer

The distinction between NXDOMAIN and an empty NOERROR catches people out. Asking for an AAAA record on a domain with only IPv4 gives you NOERROR and nothing, which is correct and looks like a failure.

Querying a specific server

This is the technique that resolves most disputes:

dig @8.8.8.8 example.com           # what Google's resolver sees
dig @1.1.1.1 example.com           # what Cloudflare sees
dig @ns1.example.com example.com   # what the authority actually holds

Querying the authoritative server bypasses every cache. If the authority has the new record and your ISP resolver does not, the record is correct and you are waiting on TTL expiry. That is a completely different problem from a record that was never updated.

Find the authoritative servers first:

dig +short example.com NS

Tracing from the root

dig +trace example.com

This performs the whole resolution yourself: query a root server, follow the delegation to the TLD servers, follow that to the domain’s nameservers, and get the final answer. Each step is printed.

It is the right tool when a domain resolves for some people and not others, because it shows exactly which delegation is broken or inconsistent.

Reverse lookups

dig -x 93.184.216.34
dig +short -x 93.184.216.34

Reverse DNS matters more than people expect for mail servers, where a missing or mismatched PTR record is a common reason messages are rejected.

Checking propagation

After changing a record:

for ns in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
  echo -n "$ns: "; dig @$ns +short example.com
done

Different answers mean caches at different stages of expiry, which is expected. Identical old answers everywhere while the authority has the new value means you are simply waiting.

Plan ahead where you can: lower the TTL to 300 a day before a planned change, make the change, then raise it again.

Records worth knowing

dig +short example.com MX          # mail
dig +short _dmarc.example.com TXT  # DMARC policy
dig +short example.com CAA         # which CAs may issue certificates
dig +short _acme-challenge.example.com TXT   # ACME validation

That last one is how you debug a failing DNS-01 certificate challenge: if the TXT record is not visible here, certbot will not get its certificate either.

CAA records are worth checking if certificate issuance fails for no obvious reason, since a restrictive CAA record blocks CAs not listed in it.

When dig disagrees with your system

dig talks to the resolver in /etc/resolv.conf directly. Applications go through the C library, which also consults /etc/hosts, nsswitch.conf, and local caches.

So dig can fail while an application succeeds, or the reverse. To see what the system actually does:

resolvectl query example.com
resolvectl status
getent hosts example.com

getent uses the same path applications do, which makes it the honest comparison.

Our DNS explainer covers the concepts, and network troubleshooting commands covers the layer beneath.

Frequently Asked Questions

Why use dig instead of nslookup or ping?

dig shows the full response including the record type, TTL, which section each answer came from, and which server replied. nslookup is older and gives less detail, and ping only tells you whether a name resolved at all, not how or from where.

What does dig +trace do?

It performs the resolution yourself, starting at the root nameservers and following delegations down to the authoritative server, showing each step. This is how you find out where in the chain a lookup is going wrong rather than just that it failed.

How do I check what the authoritative server says?

Query it directly with dig @ns1.example.com example.com. This bypasses every cache between you and the origin, which is how you tell whether a record has actually been updated or whether you are seeing a stale cached answer.

Why does my DNS change not take effect?

Caching, almost always. Resolvers hold records for the TTL, and if that was set to 86400 seconds you may wait a day. Lower the TTL before making a planned change, then raise it afterwards.

What is the difference between a CNAME and an A record?

An A record maps a name to an IPv4 address directly. A CNAME maps a name to another name, which then has to be resolved in turn. CNAMEs cannot coexist with other records at the same name, which is why they are not allowed at a domain apex.

Why does my system resolve differently to dig?

dig queries the resolver in /etc/resolv.conf directly and ignores nsswitch, /etc/hosts, and systemd-resolved caching. Applications go through the C library, so they see hosts entries and local caches that dig does not. Use resolvectl query to see what the system actually does.