Diagnose a DNS problem

3 min read07 November 2026

When a name fails to resolve, four layers may be involved: the client, the resolver, delegation and the zone. Query closer and closer to the source, and read the response code instead of guessing.

Qualify the failure

Separate a resolution failure from a connection failure:

Bash
getent hosts your-domain.com
curl -v https://your-domain.com/ 2>&1 | head -n 20

"Could not resolve host" points to DNS; "connection timed out" after resolution points to the network or service; HTTP 502 or 504 points to the application behind the web server.

Query DNS properly

Bash
dig your-domain.com A
dig your-domain.com AAAA
dig your-domain.com NS
dig your-domain.com MX
dig your-domain.com TXT

Add +short for a readable answer and query a specific server with @:

Bash
dig @1.1.1.1 A your-domain.com +short
dig @ns1.provider.com A your-domain.com +short
dig +trace your-domain.com

If the authority answers but a public resolver does not, you face caching or delegation. dig +trace shows where the chain stops.

dig prints status, flags and the authority section, essential for diagnosis; nslookup is just a quick check.

Read response codes

Status Meaning Lead
NOERROR with answer record found check service or firewall
NOERROR without answer name exists, not this type NODATA: missing AAAA or MX
NXDOMAIN name does not exist typo, deleted domain, wrong zone
SERVFAIL server could not answer broken DNSSEC, unreachable authority, bad zone
REFUSED query refused DNS server access list
Timeout no answer unreachable NS, filtered UDP 53

Flags help: aa marks an authoritative answer, ad a successful DNSSEC validation. A missing ad is not an error if the resolver skips validation.

Local and zone issues

  • /etc/hosts can bypass DNS: check it first.
  • /etc/resolv.conf or resolvectl status shows the resolvers actually used. With systemd-resolved, 127.0.0.53 is a normal local stub.
  • A VPN or Docker (127.0.0.11) may impose its own resolver.
  • A misconfigured search domain turns my-site into my-site.internal: use a trailing dot for an absolute name.
  • Flush the local cache before concluding.

To bypass DNS and test the server:

Bash
curl -sI --resolve your-domain.com:443:[YOUR_IPV6] https://your-domain.com/ | head -n 5

On the zone side, confirm you edit the right zone: dig NS your-domain.com +short must return your current DNS provider's servers. If they belong to a former provider, your changes do not apply.

Then look for classic errors: CNAME at the apex, two SPF records, MX pointing to a name without A, an overly strict CAA, a stale AAAA. For DNSSEC, a DS at the extension without a matching DNSKEY causes a global SERVFAIL: remove the DS or complete the chain.

Confirm the fix

Query the authority, then two public resolvers, then the application. A fixed record with a 24-hour cache means waiting up to a day: lower the TTL before the next change.

Advertisement

Was this article helpful?

Read next