Skip to content
Networking
Lab 3 of 7·35mBeginner

Follow a name to an address, end to end

Trace a lookup from the root servers down, read the record types that matter, and reproduce the classic "dig works but the app does not" bug.

You need

  • A Linux system with internet access
  • dnsutils (apt-get install -y dnsutils)

Do first

DNS causes more outages than routing does, and almost all of them are one of three things: a stale cache, a resolver that is not the one you think, or /etc/hosts.

1. The short answer, and the long one

dig +short example.com
dig example.com

The full output has sections worth knowing. QUESTION is what you asked. ANSWER is the records returned. The status: in the header is the result — NOERROR means it worked, NXDOMAIN means the name does not exist, SERVFAIL means the resolver broke trying.

That distinction matters: NXDOMAIN is an answer, SERVFAIL is a failure. Treating them the same sends you debugging the wrong thing.

Verify

dig example.com | grep -o "status: [A-Z]*" # status: NOERROR

2. Watch the delegation from the root down

dig +trace example.com | grep -E "^(\.|com\.|example\.com\.)" | head -n 12

Read the hops: the root servers delegate com. to the TLD servers, which delegate example.com. to its authoritative nameservers, which finally answer with an address. Nothing in DNS is a single lookup; it is a walk down a tree, cached at every level.

+trace bypasses your resolver's cache and asks each level itself, which makes it the tool for "the record is updated but I still see the old value" — if +trace shows the new value and a plain dig shows the old one, you are looking at a cache, not a DNS problem.

Verify

dig +trace example.com 2>/dev/null | grep -c "NS" # several — one line per nameserver at each delegation

3. The record types you will actually use

dig +short example.com A
dig +short example.com AAAA
dig +short google.com MX
dig +short google.com TXT | head -n 3
dig +short www.github.com CNAME
dig +short example.com NS
dig +short example.com SOA
TypeAnswers
AIPv4 address
AAAAIPv6 address
CNAMEan alias to another name, resolved recursively
MXwhere mail for this domain goes
TXTarbitrary text — SPF, DKIM, domain validation
NSthe authoritative nameservers
SOAthe zone's serial number and timing

The one rule that trips people up: a CNAME cannot coexist with other records at the same name, which is why you cannot put a CNAME on a bare apex domain like example.com. Cloud providers work around this with ALIAS or ANAME records that are not real DNS types.

Verify

dig +short google.com MX | wc -l # 1 or more mail exchangers

4. Ask a specific server, and read the TTL

dig @1.1.1.1 +short example.com
dig @8.8.8.8 +short example.com
dig @1.1.1.1 example.com | grep -A1 "ANSWER SECTION"

@server bypasses your configured resolver entirely. When a name resolves on your laptop and not on the server, asking both from the same public resolver tells you immediately whether the record or the resolver is at fault.

The number before IN A in the answer is the TTL in seconds — how long a cache may keep it. Ask twice in a row and watch it count down: the second answer comes from cache. This is also why you lower a record's TTL _before_ a migration, not during one.

Verify

dig @1.1.1.1 example.com | grep -E "^example.com" | awk '{print $2}' | head -n 1 # a TTL in seconds

5. Reproduce the classic bug

dig talks to DNS. Your application talks to the _resolver stack_, which checks /etc/hosts first. Make them disagree:

echo "127.0.0.1 example.com" | sudo tee -a /etc/hosts
dig +short example.com
getent hosts example.com
curl -s -o /dev/null -w "%{remote_ip}\n" -m 5 http://example.com || true

dig still returns the real address. getent hosts returns 127.0.0.1. So does your app. This is the bug: someone added a hosts entry for testing months ago and nobody looked at that file since.

The lesson is which tool to trust. dig answers "what does DNS say". getent hosts answers "what will my application get" — and that is the one that matters when an app is misbehaving.

Verify

getent hosts example.com | awk '{print $1}' # 127.0.0.1 — the hosts file wins over DNS

Undo it now, before you forget:

sudo sed -i.bak '/^127\.0\.0\.1 example\.com$/d' /etc/hosts
getent hosts example.com | awk '{print $1}'

Verify

getent hosts example.com | awk '{print $1}' # a public address again, not 127.0.0.1

6. Reverse lookups

dig +short -x 1.1.1.1
dig +short -x 8.8.8.8

-x looks up PTR records, mapping an address back to a name. Forward and reverse are separate records maintained by different parties, so they frequently disagree — a reverse lookup that returns nothing is normal and not a fault. Mail servers are the notable exception: many reject mail from an address with no matching PTR.

Verify

dig +short -x 1.1.1.1 # one.one.one.one.

Clean up

sudo rm -f /etc/hosts.bak
grep -c "example.com" /etc/hosts || echo "hosts file is clean"

Where this goes next

You can turn a name into an address. Next: connecting to a port on it, and telling the three failure modes apart.