🔎 How to check a resolver
Your resolver is the server your machine asks when it needs to turn a name into an address. It is the first thing in the path and the most common place for the path to go wrong.
Step 1: which resolver are you even using?#
Most people are wrong about this. The setting you configured is not always the one in use.
On Linux:
resolvectl status | grep -A2 "Current DNS"On older Linux systems, or inside a container:
cat /etc/resolv.confLook for the nameserver lines. That is who your machine asks.
On macOS:
scutil --dns | grep nameserver | head -5On Windows, in PowerShell:
Get-DnsClientServerAddress -AddressFamily IPv4A common surprise: on modern Linux you will often see 127.0.0.53. That is not a real remote server, it is a local stub on your own machine that forwards to the real one. resolvectl status shows you what sits behind it.
Another surprise: your browser may not use this at all. Firefox and Chrome can be configured with their own encrypted DNS, DoH (RFC 8484) or DoT (RFC 7858), which bypasses your system setting entirely. If a name works in the terminal but not the browser, or the other way around, that difference is the first thing to check. See dot-doh.
Step 2: does it answer?#
Ask it something simple:
dig @1.1.1.1 isitdns.net A +shortSwap 1.1.1.1 for your own resolver's IP. Real output:
104.21.56.211
172.67.155.242Reading it: two IPv4 addresses, so the name resolves. Two is normal; many services publish several addresses so clients can try another if one fails.
If nothing comes back, work through the header line instead, which +short hides. Run it again without +short and read the status: word:
| Status | Means |
|---|---|
NOERROR with answers | working |
NOERROR, ANSWER: 0 | the name exists but has no record of that type |
NXDOMAIN | the name does not exist |
SERVFAIL | the resolver tried and failed, often DNSSEC, see dnssec-troubleshooting |
REFUSED | the resolver will not serve you, usually an access list |
timed out | nothing reachable at that address |
Step 3: is it telling you the truth?#
A resolver that answers is not necessarily a resolver that is honest. The test is to ask several and compare.
for r in 1.1.1.1 8.8.8.8 9.9.9.9; do
echo "$r -> $(dig @"$r" +short isitdns.net A | tr '\n' ' ')"
doneWhat you want: the same set of addresses from each, allowing for order changes and for large services that legitimately vary by location.
If one differs sharply, especially by returning a single address on a private range like 192.168.x.x or 10.x.x.x when the others return public addresses, that resolver is rewriting answers. That can be deliberate (split horizon, parental filtering, enterprise blocking) or hostile.
If all three agree with each other but disagree with what you get without @, the thing rewriting answers is between you and all of them. See the interception check on the troubleshooting index.
Step 4: is it a resolver at all?#
Two different jobs get confused constantly. A resolver does the lookup work for you: RFC 1034 §5 defines it as the agent that extracts information from name servers on the client's behalf. An authoritative server owns a zone and answers only for that zone. Pointing at the wrong kind produces confusing failures.
dig @1.1.1.1 isitdns.net SOACheck the flags line:
rapresent means recursion available: this is a resolver and it will do work for youaapresent means authoritative: this server owns the zone, and it is not doing general lookups for you
A machine configured to use an authoritative-only server as its resolver can look up names in that one zone and nothing else. It is a strange, memorable failure once you have seen it. Details in query-types.
Step 5: is it caching something stale?#
Caching is why "it works for me" and "it is broken for me" can both be true at the same moment.
Ask twice and watch the TTL:
dig @1.1.1.1 isitdns.net A | grep -E "^isitdns"Run it again a few seconds later. The number in the second column is the TTL, in seconds.
- counting down between runs: you are being served from cache, and the answer is that many seconds from expiring
- back at its full value: the cache expired and the resolver went and got a fresh copy
If you just changed a record and are still seeing the old value, compare against the authority directly, which has no cache in front of it. That is check-an-auth.
Quick reference#
| Symptom | Where to look |
|---|---|
| nothing resolves at all | step 1, you may be pointed at the wrong server |
| one name is wrong, others fine | step 5, caching, then check-an-auth |
| answers differ between resolvers | step 3, something is rewriting |
| works in terminal, not in browser | browser has its own DNS, see dot-doh |
| only names in one zone resolve | step 4, that is an authoritative server |
SERVFAIL on one specific name | dnssec-troubleshooting |
See also#
- query-types: recursive versus authoritative, and what
rdandramean - check-a-forwarder: when your resolver hands queries onward
- nslookup-and-dig: tool comparison
- anatomy-of-a-query: the full journey of one lookup