Module 01 — Names, Resolvers & Your First Query
Updated 20 August 2026
This module assumes zero DNS knowledge. It takes you from "what is a name" to reading a dig response line by line and telling four different kinds of failure apart — which is most of what DNS troubleshooting actually is.
🧠 concept → 🧪 exercise → ✅ expected result (hidden) → 🎯 interview questions (answers hidden)
Prerequisite: none. A Linux shell and an internet connection.
Part A · What a name actually is
A1 · The problem DNS solves
That paper book is /etc/hosts. DNS is the shared, always-current contacts app that replaced it.
A network moves packets between IP addresses. Nothing in the network layer understands the word example.com — a router has never heard of it. So something has to turn the name a human types into the address a packet needs. That something is DNS.
The first solution was not DNS. It was one text file, HOSTS.TXT, maintained by hand at the Stanford Research Institute, which every machine on the ARPANET downloaded periodically. Your /etc/hosts file is the direct descendant of it, and it still works exactly the same way.
That design died of three separate diseases, and each one explains a feature of DNS:
| Problem with one file | What went wrong | What DNS does instead |
|---|---|---|
| Load | Every host on the network fetching the same file from one machine | Distributed — the data lives on thousands of independent servers |
| Name collisions | One flat list, so two organisations could not both have a machine called mail | Hierarchical — mail.a.com and mail.b.com are different names |
| Staleness | Your copy was wrong from the moment someone else changed theirs | Delegated + cached with a TTL — the owner changes it, caches expire on a timer |
🧪 Exercise A1.1 — Look at the file DNS replaced
cat /etc/hosts✅ Expected result — click to reveal
127.0.0.1 localhost
127.0.1.1 dev-box
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allroutersWhat to read out of it. Each line is address then name then optional aliases. That is the entire data model of the pre-DNS internet, and it is still consulted on every lookup your machine makes.
Notice what is missing, because the missing things are precisely what DNS adds:
- No expiry. Nothing tells the machine when this information goes stale. It is right until a human edits it.
- No authority. Nothing records who is entitled to say what dev-box means. Whoever can write the file wins.
- No sharing. This file is true on this machine only. The machine next to it can disagree, and neither will ever know.
Now imagine this at 500 hosts. One IP change means pushing a file to 500 machines. Any host that misses the push is silently, confidently wrong — and "silently wrong" is far more expensive to debug than "loudly broken". That single sentence is the reason DNS exists.
🎯 Interview questions — What DNS is
Q. What is DNS and what problem does it solve?
DNS is a distributed, hierarchical, delegated and cached database. Its best-known job is translating human-readable names into IP addresses, but it is a general-purpose lookup system — the same machinery carries mail routing, service discovery, certificate issuance policy and text-based ownership proofs.
The problem it solves is not just "names are nicer than numbers". It is decentralised administration at scale: it lets the owner of a name change what that name points to, without coordinating with anyone else, and without any central authority holding the data.
The detail that separates a strong candidate: pointing out that DNS is a database, not a connection. It returns data and stops. It performs no health checking of the address it returns, so a correct DNS answer and a dead service are entirely compatible states. Candidates who understand this stop blaming DNS first.
Q. Why was a single hosts file not good enough?
Three independent failures, and it is worth naming all three because each maps to a DNS feature.
Load — one server distributing one file to every host on the network does not scale, which is why DNS data is spread over many independent servers.
Collisions — a flat namespace means one global mail. Hierarchy fixes this: mail.a.com and mail.b.com coexist because the name includes the administrative path to its owner.
Consistency — with copies everywhere and no expiry, every copy is wrong between edits. DNS replaces "copy the file" with "ask the owner, then cache the answer for a stated TTL", which bounds how wrong you can be.
Worth adding: /etc/hosts did not disappear. It is still consulted first on most Linux systems, which is why it is a standard debugging and incident tool — and a standard cause of "it works on my machine".
A2 · The namespace is an inverted tree
A domain name is exactly that: www.example.com means "the machine called www, inside example, inside com". And just like the post office, each level only has to know about the level below it — the country's sorting office doesn't need to know your house number.
The namespace is a tree, drawn upside down: the root at the top, branching downwards. Every node in the tree has a short text label. A domain name is simply the list of labels on the path from a node back up to the root, written left to right, separated by dots.
Diagram source
flowchart TD
ROOT["root<br>label is empty<br>written as a bare dot"]
ROOT --> COM["com"]
ROOT --> ORG["org"]
ROOT --> UK["uk"]
COM --> EX["example<br>= example.com"]
COM --> OTHER["acme"]
UK --> CO["co"]
CO --> BBC["bbc<br>= bbc.co.uk"]
EX --> WWW["www<br>= www.example.com"]
EX --> ENG["eng"]
ENG --> API["api<br>= api.eng.example.com"]
style ROOT fill:#8b5cf6,color:#fff
style EX fill:#22c55e,color:#fff
style API fill:#22c55e,color:#fffRead the diagram from the bottom up, not the top down. api.eng.example.com is api inside eng inside example inside com inside the root. The name is a path, and it is written in the opposite order to a filesystem path — which is the first thing that trips people up.
| Term | What it means, precisely |
|---|---|
| Label | One node's name. www, example, com. The root's label is the empty string |
| Domain name | The full path of labels from a node to the root, dot-separated |
| Root | The top of the tree. Written as a single dot . and served by 13 named root server identities |
| TLD | Top-level domain — a label directly under the root. com, org, uk, dev |
| Subdomain | A relative term, not an absolute one. eng.example.com is a subdomain of example.com, which is itself a subdomain of com |
🧪 Exercise A2.1 — Walk three names of different depths, one of which does not exist
ping -c 1 example.com
ping -c 1 www.example.com
ping -c 1 definitely-not-real.example.com✅ Expected result — click to reveal
PING example.com (23.215.0.136) 56(84) bytes of data.
64 bytes from 23.215.0.136: icmp_seq=1 ttl=54 time=11.9 ms
--- example.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
PING www.example.com (23.215.0.138) 56(84) bytes of data.
64 bytes from 23.215.0.138: icmp_seq=1 ttl=54 time=12.1 ms
--- www.example.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
ping: definitely-not-real.example.com: Name or service not knownYour addresses will differ from these — example.com is served from many locations and the addresses change. That is normal and is itself the point: the name is stable, the address behind it is not.
Three things to read out of this.
1. example.com and www.example.com are different names, and here they resolve to different addresses. They are two separate nodes in the tree. There is no rule anywhere in DNS that makes www.x behave like x — that is a convention people set up by hand, and forgetting to set it up is a common outage.
2. The third failure is a different kind of failure. Look at the wording: Name or service not known. Not Destination Host Unreachable, not Request timed out. ping never sent a packet, because it never got an address to send it to. Resolution failed before the network was involved at all.
3. That distinction is the single most useful reflex in this whole subject. "Name or service not known" means take the network off the suspect list and look at DNS. "Destination Host Unreachable" means DNS did its job and something downstream is wrong. Engineers who cannot tell these apart spend hours on the wrong half of the stack.
What ping will not tell you is why resolution failed — whether the name genuinely does not exist, whether your resolver was unreachable, or whether the name was malformed. Those look identical here. Getting that detail is exactly what dig is for, and that is Part C.
🎯 Interview questions — The namespace
Q. Describe the structure of the DNS namespace.
An inverted tree with an unnamed root at the top. Each node carries a label; a domain name is the path of labels from a node up to the root, written left to right and separated by dots — so it reads most-specific-first, the opposite of a filesystem path.
Directly under the root are the top-level domains, then registrable domains beneath those, then whatever structure the owner chooses.
The point worth making explicitly: the hierarchy is not cosmetic, it is the administrative boundary. Because the tree is nested, authority can be handed downwards one branch at a time, which is what lets the database be maintained by millions of unrelated parties with no central coordination.
Q. How many root servers are there?
Thirteen root server identities, a through m under root-servers.net, operated by twelve independent organisations. Thirteen because that many addresses fitted inside the original 512-byte UDP response limit.
But thirteen identities is not thirteen machines. Each identity is served by many physical instances in many countries, all announcing the same address, so the practical count is over a thousand servers.
The trap in this question is answering "13" and stopping. The interviewer is usually checking whether you know the difference between a name, an address, and a server — three things this question deliberately blurs.
A3 · Absolute names, relative names, and the trailing dot
A name without a trailing dot is the short version, and something may quietly fill in the rest for you. The trailing dot is the "… Malaysia" — it says "this is the complete address, do not add anything".
Because the root's label is empty, the truly complete form of a name ends in a dot:
www.example.com.
│ │ │ └── the root, whose label is empty
│ │ └───── com
│ └───────────── example
└───────────────── wwwA name written with that final dot is absolute — it is anchored at the root and means exactly one thing everywhere in the world. The formal term is FQDN, fully qualified domain name.
A name written without the final dot is relative, and something is entitled to add labels to it before looking it up.
The rules that govern that expansion — the search list and ndots — are the subject of Module 06. What matters now is only this: the trailing dot means "do not touch this name, send it as written".
🧪 Exercise A3.1 — Prove the trailing dot is legal, then break the name deliberately
ping -c 1 example.com.
ping -c 1 example.com..✅ Expected result — click to reveal
PING example.com (23.215.0.136) 56(84) bytes of data.
64 bytes from 23.215.0.136: icmp_seq=1 ttl=54 time=12.0 ms
--- example.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
ping: example.com..: Name or service not knownThe first command works and most people are surprised by that. The trailing dot is not a typo and not decoration — it is the root label, and it is the more correct way to write a name. ping strips or ignores it and resolves normally.
The second fails because it contains an empty label in the middle. example.com.. asks for a label between the two final dots, and that label is the empty string — which is reserved for the root and cannot appear anywhere else. This one is not a network failure; the name itself is invalid.
Where you will actually meet the trailing dot. In zone files, where a name without a trailing dot silently gets the zone name appended — so writing www.example.com inside the example.com zone produces www.example.com.example.com.. That is one of the most common zone-file mistakes there is, it produces a valid file that loads without complaint, and Module 02 makes you commit it on purpose so you recognise it.
🎯 Interview questions — FQDNs
Q. What is an FQDN, and what does the trailing dot mean?
A fully qualified domain name specifies the complete path to the root, so it is unambiguous globally. The trailing dot is the root — the root's label is the empty string, so example.com. has labels example, com, and empty.
A name without the trailing dot is relative and may have a search domain appended before it is queried.
Where this earns you credit: naming the two places it bites. In zone files, an unqualified name silently gets the origin appended, producing www.example.com.example.com. from a file that loads cleanly. In resolver configuration, the trailing dot is how you force a single absolute query and skip search-list expansion — which is the standard trick for proving that a slow or failing lookup is a search-domain problem rather than a server problem.
A4 · What is legal in a name
Same here — and the twist worth remembering: "valid DNS name" and "valid host name" are two different forms with two different rule sets. Something can pass one and fail the other.
| Rule | Detail, and why it exists |
|---|---|
| A label is at most 63 octets | The length is encoded on the wire in a byte whose top two bits are reserved, leaving six bits — and six bits counts to 63 |
| A whole name is at most 255 octets | Counting the length byte in front of every label plus the final zero byte. In practice this caps you at roughly 253 printable characters |
| Host names: letters, digits, hyphen | The "LDH" rule from RFC 1035, relaxed by RFC 1123 to allow a leading digit. A hyphen may not start or end a label |
| Comparison is case-insensitive | Example.COM and example.com are the same name. Case is preserved on output but never affects matching |
| The wire is 8-bit clean | DNS itself can carry arbitrary bytes in a label. The LDH restriction is a host name rule, not a DNS rule — which is why _dmarc and _sip._tcp are perfectly valid DNS labels |
🧪 Exercise A4.1 — Prove case does not matter, then build an illegal label
ping -c 1 ExAmPlE.cOm
# a 64-character label - one octet over the limit
ping -c 1 $(printf 'a%.0s' {1..64}).example.com✅ Expected result — click to reveal
PING ExAmPlE.cOm (23.215.0.136) 56(84) bytes of data.
64 bytes from 23.215.0.136: icmp_seq=1 ttl=54 time=11.8 ms
--- ExAmPlE.cOm ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
ping: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.example.com: Name or service not knownThe mixed-case lookup succeeds and the tool echoes back your capitalisation. Case is preserved for display and ignored for matching — those are two different behaviours and both are in RFC 4343.
Now the important part, and it is about what you cannot see. The 64-character label failed with Name or service not known — the exact same message you got in Exercise A2.1 for a name that simply did not exist. But these are completely different events:
- In A2.1 a query was sent and the network answered "no such name"
- Here no query was ever sent — the resolver library rejected the name locally, because 64 does not fit in six bits
ping collapses both into one message, and that is its fatal weakness as a DNS tool. It tells you that resolution failed and never why. Every incident where the answer is "we spent two hours on the wrong thing" starts here.
You will repeat this exact command with dig in Exercise C6.2 and watch it name the real cause in one line.
🎯 Interview questions — Name syntax
Q. What are the length limits on a DNS name?
63 octets per label, 255 octets for the whole name on the wire — which works out to about 253 characters once you account for the length byte before each label and the terminating zero byte.
The answer that shows you understand the format rather than the trivia: 63 is not arbitrary. Each label on the wire is preceded by a length byte, and the top two bits of that byte are reserved as a flag for message compression. Six bits remain, and six bits counts to 63. Knowing why the number is 63 signals that you have read the wire format, which Module 04 covers in full.
Q. Is DNS case sensitive?
No for matching, yes for storage. Lookups and comparisons fold ASCII case, so EXAMPLE.com and example.com are the same name. Case is meant to be preserved when a name is echoed back.
The senior-level addition: because case is preserved but ignored, resolvers can randomise the case of the name they query and require the response to echo it back exactly. That is 0x20 encoding, and it is a cheap defence against off-path spoofing — the attacker has to guess the capitalisation pattern as well as everything else. It comes up again in Module 09.
Q. Is an underscore allowed in a DNS name?
In DNS, yes. In a host name, no. They are separate rule sets and conflating them is the mistake the question is fishing for.
DNS labels are 8-bit clean; the letters-digits-hyphen restriction comes from host name syntax in RFC 1035 and RFC 1123. That is exactly why the underscore prefix was chosen for service and metadata records — _dmarc, _acme-challenge, _sip._tcp — since a label starting with an underscore can never collide with a legitimate machine name.
The practical trap worth mentioning: some validating tools, load balancers and certificate authorities apply host-name rules where DNS rules apply, and reject underscore labels that are perfectly valid. Knowing which layer is complaining saves an afternoon.
Part B · Who answers the question
B1 · The three roles
You are the stub resolver. The concierge is the recursive resolver. The restaurant is the authoritative server — it knows its own opening hours and nothing about anyone else's.
There are only three roles a piece of software can play in a DNS lookup. Almost every confusing DNS conversation comes from someone using the word "DNS server" for two of them at once.
Diagram source
flowchart LR
APP["your application<br>curl, browser, ping"]
STUB["STUB RESOLVER<br>a library inside your OS<br>knows almost nothing<br>asks one server and waits"]
REC["RECURSIVE RESOLVER<br>a real server, often your ISP<br>or 1.1.1.1 / 8.8.8.8<br>does the work, keeps a cache"]
AUTH["AUTHORITATIVE SERVER<br>holds the real data for a zone<br>never asks anyone else<br>keeps no cache"]
APP --> STUB
STUB -->|"one question<br>please do the work"| REC
REC -->|"many questions<br>walking down the tree"| AUTH
style STUB fill:#f59e0b,color:#fff
style REC fill:#8b5cf6,color:#fff
style AUTH fill:#22c55e,color:#fff| Role | What it does | Where it lives |
|---|---|---|
| Stub resolver | Asks one configured server the whole question and waits for the whole answer. Has no cache of its own and no knowledge of the tree | A library inside your OS — code, not a service you can log in to |
| Recursive resolver | Accepts "tell me everything about this name", does whatever work is needed, caches what it learns, returns one final answer | Your ISP, your router, your company, or a public service such as 1.1.1.1 |
| Authoritative server | Holds the actual configured data for a zone and answers only about that zone. Never asks anyone else on your behalf | Run by the domain owner, or by their DNS provider |
🧪 Exercise B1.1 — Predict the traffic before you can measure it
No commands for this one. Decide your answer for each case out loud before opening the toggle. Assume a normal laptop using a normal ISP resolver.
- You look up example.com. Nobody on your network has asked for it in days.
- Immediately afterwards, your colleague on the same office network looks up example.com.
- You look up does-not-exist-at-all.example.com.
- You look up a name in /etc/hosts.
For each: does a DNS packet leave your laptop, and does one leave your resolver?
✅ Expected result — click to reveal
1. Cold lookup. A packet leaves your laptop. Your resolver has nothing cached, so it does real work out on the internet and packets leave it too. This is the slow case — typically tens to hundreds of milliseconds.
2. Your colleague, seconds later. A packet leaves their laptop — the stub resolver has no cache, so it always asks. But nothing leaves the resolver: it answers from cache, usually in single-digit milliseconds. Your colleague benefits from your lookup and has no idea.
3. A name that does not exist. A packet leaves your laptop, and the resolver does real work to establish the name is absent. The "no" is then cached too — that is negative caching, and it is why a name you have just created can stay "missing" for minutes after you create it. Module 03 explains where the timer for that comes from.
4. A name in /etc/hosts. No DNS packet at all. The lookup is satisfied locally before DNS is consulted. This is why dig can return a perfectly good answer while your application connects somewhere completely different — dig speaks DNS directly and skips /etc/hosts entirely. That divergence is one of the most confusing things in this subject and Module 06 is dedicated to it.
The pattern to take away: the stub asks every single time; the resolver is where caching happens; and the highest-value thing a cache stores is often the negative answer.
🎯 Interview questions — The three roles
Q. What is the difference between a recursive resolver and an authoritative server?
A recursive resolver answers "what is the address of X" by doing whatever work is required — it queries other servers, follows the hierarchy down, caches every step, and hands back one final answer. It owns no data.
An authoritative server holds the configured data for the zones it serves and answers only for those. It does not chase answers for anyone and normally keeps no cache, because it is the source.
The framing interviewers respond to: the resolver is optimised for reads and lives or dies on its cache hit rate; the authoritative server is the source of truth and lives or dies on correctness and availability. They have opposite failure modes — a resolver failure affects everyone who uses that resolver, an authoritative failure affects everyone in the world looking up that zone once caches drain.
Q. What is a stub resolver?
The minimal DNS client built into the operating system — for most Linux systems, code inside glibc rather than a running daemon. It knows how to format a question, send it to the servers listed in its configuration, and read the reply. It cannot walk the hierarchy itself and traditionally holds no cache.
Why it matters operationally: because it holds no cache, every lookup by every process crosses the network to the resolver. That is why an unreachable resolver hangs applications rather than degrading them, and it is why local caching layers such as systemd-resolved, dnsmasq or NodeLocal DNSCache exist. Those layers change the picture significantly, and they are Module 06 and Module 08.
Q. What is an open resolver and why is it a problem?
A recursive resolver that will do work for any client on the internet rather than only its own users.
It is a problem for two reasons. It lets strangers consume your capacity, and — far worse — it makes you a reflector and amplifier: an attacker sends a small query with a forged source address, and your server sends a much larger response to the victim. The response can be many times the size of the query, so the attacker multiplies their bandwidth.
What separates a strong answer: naming the fix rather than just the risk. Split the roles onto different servers or different addresses, restrict recursion to known client ranges, and enable response rate limiting on the authoritative side. Module 05 sets this up and Module 09 covers the attack in detail.
B2 · Where your machine gets its resolver from
The catch: sometimes the number on the note is an internal extension, not the real outside line — so reading the note tells you who picks up first, not who actually answers.
The stub resolver has to be told which server to ask. On Linux that comes from /etc/resolv.conf.
The file has three kinds of line. Only one of them matters in this module:
| Directive | Meaning |
|---|---|
| nameserver <ip> | A recursive resolver to ask. Up to three are used by default, in order, as failover — not as load balancing |
| search <domains> | Suffixes that may be appended to relative names. Introduced properly in Module 06 |
| options ... | Resolver tuning, including ndots, timeout and attempts. Also Module 06 |
🧪 Exercise B2.1 — Find out who your machine actually asks
cat /etc/resolv.conf✅ Expected result — click to reveal
You will see one of roughly three shapes. All three are normal.
Shape 1 — a real resolver on your network:
nameserver 192.168.1.1
search homeShape 2 — a public resolver, common on a cloud VM:
nameserver 8.8.8.8
nameserver 8.8.4.4Shape 3 — a local stub listener, the default on modern Ubuntu and Fedora:
# This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8).
# Do not edit.
nameserver 127.0.0.53
options edns0 trust-ad
search .If you got shape 3, read this carefully, because it is the single most misleading line in Linux networking. 127.0.0.53 is on your own machine. It is a local caching stub listener run by systemd-resolved, and the real upstream resolvers are configured somewhere else entirely and are not shown in this file.
The practical consequence: on such a machine, cat /etc/resolv.conf cannot answer the question "which resolver is my traffic actually going to". Editing the file usually does nothing either, because it is regenerated. Module 06 shows the command that gives the true answer.
Now imagine this at 500 hosts. Half your fleet reads its upstream from this file and half does not. Any runbook step that says "check /etc/resolv.conf" is correct on some hosts and quietly wrong on the others — which is exactly how an incident ends up with two engineers looking at the same output and reaching opposite conclusions.
🎯 Interview questions — Resolver configuration
Q. How does a Linux machine know which DNS server to use?
From the nameserver lines in /etc/resolv.conf, which the stub resolver reads. The file is usually generated — by DHCP, by NetworkManager, by cloud-init, or by systemd-resolved — rather than hand-edited, so editing it directly is often undone on the next network event.
The detail that matters in production: multiple nameserver lines are sequential failover, not load balancing. The resolver uses the first and only moves on after a timeout, five seconds by default. So a dead primary does not cost you nothing, it costs you five seconds on every lookup until the configuration changes.
And if the file says 127.0.0.53, it is not telling you the upstream at all — that is a local systemd-resolved listener and the real servers are configured elsewhere.
Part C · Installing the tools and asking the question yourself
C1 · Installing dig
dig lives in a package whose name has nothing to do with the word "dig", and production containers usually ship with no tools at all — so the moment you need it is the moment you cannot install it.
dig — domain information groper — is the tool. It ships as part of BIND, the reference DNS implementation, which is why it is not always installed by default: it lives in a package whose name has nothing to do with the word dig.
| Distribution | Install command |
|---|---|
| Debian, Ubuntu | sudo apt update && sudo apt install -y bind9-dnsutils |
| RHEL, Rocky, Alma, Fedora | sudo dnf install -y bind-utils |
| Alpine | sudo apk add bind-tools |
| Arch | sudo pacman -S bind |
| macOS | Already present. brew install bind if you want a newer version |
🧪 Exercise C1.1 — Meet the failure first, in a container that has nothing
# a deliberately bare image - this is what your CI runners and
# slim application images actually look like
docker run --rm -it ubuntu:24.04 bash
# inside the container:
dig example.com
ping -c 1 example.com✅ Expected result — click to reveal
root@3f9c1a2b4d5e:/# dig example.com
bash: dig: command not found
root@3f9c1a2b4d5e:/# ping -c 1 example.com
bash: ping: command not foundBoth tools are missing, and this is the single most common wasted hour in container debugging. You are trying to establish whether DNS works inside a pod, and the image contains no DNS tooling at all — so every diagnostic you reach for reports command not found, which looks alarmingly like a broken system.
Read the error precisely. bash: dig: command not found is your shell speaking, not DNS. Compare it with ping: example.com: Name or service not known, which is a resolution failure. Same feeling of "it's broken", completely different cause. Getting fast at classifying error messages by who emitted them is most of what troubleshooting skill actually is.
What to do instead in a bare container, before installing anything — because the ability to resolve is already there even when the tools are not:
apt update && apt install -y bind9-dnsutils iputils-pingNow imagine this at 500 hosts. You cannot apt install inside a production pod on a locked-down cluster, and you should not want to. This is why teams keep a purpose-built debug image with dig, ping, curl and ss in it, and attach that to a running pod instead of mutating the application container. Module 08 shows the exact pattern.
🧪 Exercise C1.2 — Install it and confirm which version you have
sudo apt update && sudo apt install -y bind9-dnsutils # or dnf install bind-utils
dig -v✅ Expected result — click to reveal
DiG 9.18.30-0ubuntu0.24.04.2-UbuntuNote the version, because dig output has changed over the years. Two differences you will actually trip over when comparing your output against a blog post or a colleague's terminal:
- BIND 9.16 and later print an OPT PSEUDOSECTION by default. Older output does not have it
- Recent versions append the transport to the SERVER: line, as (UDP) or (TCP). Older versions do not
dig -v writes to standard error, not standard output, which surprises people scripting it. Use dig -v 2>&1 if you are capturing it.
🎯 Interview questions — Tooling
Q. Which command-line tools do you use for DNS, and which do you reach for first?
dig first, essentially always. It shows the complete response — the header, the flags, every section, the TTL, which server answered and how long it took — and it lets me target a specific server, which is the thing that actually isolates a fault.
host for a quick one-line check in a script. nslookup only when I am on a machine that has nothing else, typically Windows.
getent hosts when the question is not "what does DNS say" but "what will the application see", because that goes through the full system resolution path including /etc/hosts — and those two answers differing is a real and common failure mode.
The addition that lands well: naming what you would avoid. ping is not a DNS tool. It collapses every possible resolution failure into one message and tells you nothing about which one you hit.
C2 · Your first query
It does not summarise and it does not tidy up. That is the point: everything you need to diagnose a problem is on the slip.
The simplest possible form is dig followed by a name.
dig example.comdig builds a DNS question, sends it to the first server in /etc/resolv.conf, waits, and prints the entire response in a fixed layout. It does not interpret anything for you and it does not consult /etc/hosts — it speaks DNS and only DNS.
🧪 Exercise C2.1 — Run it, and do not try to understand the output yet
dig example.com✅ Expected result — click to reveal
; <<>> DiG 9.18.30-0ubuntu0.24.04.2-Ubuntu <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47823
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 277 IN A 23.215.0.136
example.com. 277 IN A 96.7.128.175
example.com. 277 IN A 23.192.228.80
example.com. 277 IN A 23.215.0.138
example.com. 277 IN A 96.7.128.198
example.com. 277 IN A 23.192.228.84
;; Query time: 4 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Mon Aug 17 13:41:02 +08 2026
;; MSG SIZE rcvd: 128Three quick observations before the detailed reading in C3.
1. You asked for a name and got six addresses. You did not ask for six. The zone owner published six, and every one of them is a valid answer. Whatever connects next will pick one — and which one it picks is decided by the client, not by DNS.
2. You never said A, and yet the QUESTION SECTION says A. dig's default query type is A, the IPv4 address record. Nothing about the name implied that. Record types are Module 02.
3. dig added the trailing dot for you — you typed example.com and the question reads example.com.. It qualified the name into an absolute one before sending it. How it decided to do that, and when it decides differently, is Module 06.
C3 · Reading the response, line by line
Those are two different things — a slip can honestly say delivered, no problems while the box is empty. In DNS, status: tells you the counter staff were happy; the ANSWER: count tells you whether you actually got anything. Read both, every time.
This is the most valuable skill in the module. Every DNS response has the same five parts, and knowing what each one is for turns a wall of text into four facts.
| Line or section | What it tells you |
|---|---|
| ->>HEADER<<- | status: is the verdict. NOERROR means the server answered successfully — it does not mean you got data |
| flags: | Who did what. qr = this is a response · rd = recursion was requested · ra = the server offers recursion · aa = the answer came from an authoritative server |
| The counters | ANSWER: 6 is the number to read first. ANSWER: 0 with status: NOERROR is a distinct and very common situation, covered in Part D |
| QUESTION SECTION | The question as the server understood it. Always check this — it is where you discover a search domain was appended, or that you typo'd the name |
| ANSWER SECTION | The data. Five columns: name, TTL, class, type, value |
| AUTHORITY / ADDITIONAL | Supporting records. Empty here; they carry real weight in Module 03 |
| Query time: | Round trip in milliseconds. Single digits means a cache hit; tens or hundreds means real work happened |
| SERVER: | Which server actually answered. The first thing to check when an answer is not what you expect |
One answer line, decomposed:
example.com. 277 IN A 23.215.0.136
│ │ │ │ └── RDATA - the value
│ │ │ └────────── TYPE - what kind of record
│ │ └────────────────── CLASS - always IN in practice
│ └────────────────────────── TTL - seconds this may be cached
└────────────────────────────────────────────── NAME - what this record is about🧪 Exercise C3.1 — Strip the output down to just the data
dig example.com +noall +answer
dig example.com +short✅ Expected result — click to reveal
$ dig example.com +noall +answer
example.com. 241 IN A 23.192.228.80
example.com. 241 IN A 23.215.0.138
example.com. 241 IN A 96.7.128.198
example.com. 241 IN A 23.192.228.84
example.com. 241 IN A 23.215.0.136
example.com. 241 IN A 96.7.128.175
$ dig example.com +short
23.192.228.84
23.215.0.136
96.7.128.198
23.215.0.138
23.192.228.80
96.7.128.175+noall +answer is the form to build a habit around. It reads as "turn off every section, then turn the answer section back on". You keep the TTL, the type and the record name — which is almost always the information you actually need — and lose the noise.
+short is for scripts, and it is lossy in a way that matters. It prints values only. No TTL, no type, no status. Which means an empty result from +short is ambiguous: it could be NXDOMAIN, it could be NOERROR with no records, it could be SERVFAIL, it could be a timeout. Four completely different problems, one identical empty output.
Notice the order changed between the two commands. The resolver rotated the records. That is deliberate — it is the crudest form of DNS load balancing, and it is why you must never assume "the first address" is stable. Module 09 covers what this technique can and cannot do.
Now imagine this at 500 hosts. A monitoring check written as dig +short myservice.internal and tested against "is the output empty" will report the same failure for a deleted record, a broken resolver and a network partition. On-call gets one alert that means four things. Check status: in automation, never emptiness.
🎯 Interview questions — Reading a response
Q. Walk me through the output of dig example.com.
Top down: the header line gives the status — the RCODE — and the flags; then the counters for each section; then the question as the server understood it; then the answer records; then metadata about the transaction itself.
In the flags I read qr for response, rd for recursion desired, ra for recursion available, and aa if the answer was authoritative. Each answer record is name, TTL, class, type, then the value.
At the bottom, Query time tells me whether it was a cache hit, and SERVER tells me who answered.
The two lines a strong candidate says they check first: SERVER, because a surprising answer is very often the right answer from the wrong server; and the QUESTION SECTION, because that is where you see that a search domain was appended or that the name was not what you thought you typed. Junior candidates read the answer section and nothing else.
Q. What does the aa flag mean, and why would you care?
Authoritative answer — the response came from a server that holds the zone itself rather than from a cache.
You care because it is how you separate "the record is wrong" from "the record is right and something is serving a stale copy". If the authoritative server has the new value and a resolver still returns the old one, the change is fine and you are simply waiting out a TTL. If the authoritative server itself has the old value, the change never landed.
That single check is the correct first step in any "I updated DNS and nothing happened" investigation, and it saves you from waiting on a TTL for a change that was never made.
C4 · Choosing which server to ask
That is what @server gives you: the ability to ask the same question of different people and compare.
Prefixing a server with @ sends the query there instead of to your configured resolver. This is the feature that makes dig a diagnostic tool rather than a lookup tool: it lets you ask the same question of different servers and compare, which is how you find out where a wrong answer is coming from.
dig @1.1.1.1 example.com # ask Cloudflare's public resolver
dig @8.8.8.8 example.com # ask Google's public resolver
dig @a.root-servers.net example.com # ask a root server🧪 Exercise C4.1 — Watch the recursion bits change, and meet a server that refuses to work for you
dig @1.1.1.1 example.com | head -6
dig +norecurse @1.1.1.1 example.com | head -6
dig @a.root-servers.net example.com | head -8✅ Expected result — click to reveal
$ dig @1.1.1.1 example.com | head -6
; <<>> DiG 9.18.30 <<>> @1.1.1.1 example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12045
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1
$ dig +norecurse @1.1.1.1 example.com | head -6
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33871
;; flags: qr ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1
$ dig @a.root-servers.net example.com | head -8
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59102
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 13, ADDITIONAL: 27Compare the three flags: lines. That is the whole exercise.
Query 1 — qr rd ra. You asked for recursion (rd) and the server told you it provides recursion (ra). You got six answers. Normal.
Query 2 — qr ra, and rd is gone. +norecurse cleared the request. ra is still set because the server still offers recursion — it just was not asked to use it. You still got six answers, because they were already in Cloudflare's cache. Ask for a name nobody has looked up recently and this query returns ANSWER: 0 — you have asked a cache for something it does not have and forbidden it from finding out. That is exactly how you inspect a cache without warming it.
Query 3 — qr rd and no ra. You asked for recursion and the root server declined to offer it. This is the concrete meaning of "authoritative servers do not do the work for you", the policy point from B1, visible as one missing two-letter flag.
Also note query 3 returned ANSWER: 0 but AUTHORITY: 13. It did not fail and it did not answer — it pointed you somewhere else. That is a referral, and following referrals is the entire subject of Module 03.
Why this is the most useful dig feature in an incident. "The site is broken for some users." Ask your resolver, ask 1.1.1.1, ask 8.8.8.8. If they disagree, you are looking at a caching or propagation problem, and you already know which resolvers are affected. If they all agree and the answer is wrong, the data at the source is wrong. One command, and the search space halves.
🎯 Interview questions — Targeting servers
Q. Users report a site is unreachable but it works for you. How do you use DNS to narrow it down?
I would ask several resolvers the same question and compare — my own, 1.1.1.1, 8.8.8.8, and ideally a resolver on the affected users' network — using dig @server name.
If the answers differ, it is a cache or propagation issue and the differing resolvers tell me the blast radius. If every resolver agrees, DNS is consistent and the fault is downstream: routing, TLS, the application, or a health check.
What makes this a strong answer rather than a list of commands: saying explicitly that I check the authoritative source too, so I can tell "the record is wrong" apart from "the record is right and a cache is stale". Those two have completely different remedies — one is a fix, the other is patience or a TTL change — and confusing them is how teams end up making a second wrong change on top of the first.
Q. What does +norecurse do and when is it genuinely useful?
It clears the recursion-desired bit, so the server answers only from what it already holds.
Its real use is inspecting a cache without disturbing it. A normal query makes the resolver go and fetch the record, which destroys the evidence — after that you can no longer tell whether it was cached before you asked. +norecurse answers "was this already in the cache, and with what remaining TTL" without warming anything.
Where it earns its keep: confirming that a specific resolver is the one holding a stale record during a migration, and checking whether a resolver you do not control is still serving an old address after a cutover.
C5 · The TTL is a live countdown
Two different shops stock their fridges at different times, so their cartons have different dates left, even though it is the same milk. That is why two DNS resolvers show different TTLs for the same record: they fetched it at different moments and each is counting down its own copy.
The TTL in an answer is not a fixed property of the record. It is the remaining lifetime of that particular cached copy, and it is decremented by the cache as it ages. The authoritative server always states the full value; every cache in between counts it down and discards the record at zero.
🧪 Exercise C5.1 — Watch a cache age in real time
dig +noall +answer example.com
sleep 10
dig +noall +answer example.com
sleep 10
dig +noall +answer example.com✅ Expected result — click to reveal
example.com. 298 IN A 23.215.0.136
example.com. 288 IN A 23.215.0.136
example.com. 278 IN A 23.215.0.136Only the first of six records shown for brevity — you will see all six each time.
The TTL dropped by exactly 10 each time, because you slept 10 seconds. You are watching a cache entry expire. This is worth doing once with your own eyes because it converts TTL from a number in a config file into a thing that is visibly happening.
What to read out of it.
- A TTL below the configured maximum means you are talking to a cache, and it tells you how long ago that cache fetched the record
- A TTL that resets to the full value means the entry expired and was re-fetched
- A TTL that is always the full value means you are talking to the authoritative server, or to something that is not caching
The operational consequence, and it is the reason TTL comes up in every DNS interview. A record with a 300-second TTL means that after you change it, some clients keep using the old value for up to 300 more seconds. Nothing you can do makes them stop — you do not control their cache. So the standard migration procedure is: lower the TTL first, wait for the old high TTL to fully expire everywhere, then make the change, then raise the TTL again afterwards. Lowering the TTL at the same time as making the change achieves nothing, because the clients that need to see the low TTL are exactly the ones still holding the old record.
Now imagine this at 500 hosts behind a resolver with a 24-hour TTL on the record. A rollback is not a rollback for a day. That is why TTL planning is part of change planning, not an afterthought.
🧪 Exercise C5.2 — Make two resolvers disagree
dig +noall +answer @1.1.1.1 example.com
dig +noall +answer @8.8.8.8 example.com✅ Expected result — click to reveal
$ dig +noall +answer @1.1.1.1 example.com
example.com. 112 IN A 23.215.0.136
$ dig +noall +answer @8.8.8.8 example.com
example.com. 267 IN A 23.215.0.136Same record, same value, different TTL — and neither is wrong. The two resolvers fetched the record at different moments, so their copies are at different points in their lifetimes. Cloudflare fetched about 3 minutes ago; Google about 30 seconds ago.
This is the concrete mechanism behind the phrase "DNS propagation", and it is why the phrase is misleading. Nothing propagates. No update is pushed anywhere. Each cache independently discovers the new value when its own copy of the old one expires — which is why a change appears to roll out gradually and unevenly across the world, and why "it works for me" and "it doesn't work for me" are both true at the same time. Module 03 takes this apart properly.
If the two resolvers had shown different values, you would be looking at a change in flight, and the TTLs would tell you roughly how much longer the stale one has to live.
🎯 Interview questions — TTL and caching
Q. What is TTL in DNS and why does it matter?
Time to live, in seconds — how long a resolver may cache a record before it must fetch it again. The authoritative server publishes the full value; each cache counts it down and evicts at zero.
It is a direct trade-off. High TTL means fewer queries, faster responses and more resilience if the authoritative servers become unreachable, but slower change. Low TTL means agility at the cost of query volume and a harder dependency on your authoritative servers being up.
The operational detail that separates candidates: the ordering of a TTL change. You must lower the TTL and then wait out the old TTL before making the change, because caches holding the old record never see the new low value until their copy expires. Lowering it at the same time as the change is a no-op for exactly the clients you were worried about. Typical practice is to drop to 60 seconds a day ahead of a planned cutover, and raise it again once the change has settled.
Q. What is DNS propagation, and how long does it take?
Strictly speaking there is no such thing — the word implies a push, and DNS has none. Authoritative data changes in one place, and every cache independently picks up the new value when its own cached copy expires.
So the honest answer to "how long" is: up to the TTL that was in effect on the record before you changed it, per cache, plus the time your own provider takes to distribute the change across its authoritative servers.
What marks out a strong candidate: refusing the premise politely, then naming the two things that actually make it take longer than the TTL suggests. First, intermediate resolvers that clamp or extend TTLs to their own minimums and maximums regardless of what you published. Second, application-level caches — a JVM caching DNS forever by default is a genuinely notorious case, and no amount of TTL tuning touches it.
C6 · host, nslookup, and what dig tells you that ping cannot
ping is "I feel unwell" — it reports that a name did not work, and gives the same message whether the name was mistyped, does not exist, or your resolver is down. dig is the thermometer.
| Tool | Use it for | Why it is not your default |
|---|---|---|
| dig | Everything diagnostic | — |
| host | A quick, readable one-liner | Hides the flags, the TTL and the status. Fine for a yes/no, useless for a diagnosis |
| nslookup | Windows, or a box with nothing else | Its "Non-authoritative answer" and "server can't find" wording actively misleads people, and it reports some errors identically |
| delv | Checking DNSSEC validation | Not needed until Module 07 |
🧪 Exercise C6.1 — The same question through three tools
dig +short example.com
host example.com
nslookup example.com✅ Expected result — click to reveal
$ dig +short example.com
23.215.0.136
96.7.128.175
...
$ host example.com
example.com has address 23.215.0.136
example.com has address 96.7.128.175
example.com has IPv6 address 2600:1408:ec00:36::1736:7f24
example.com mail is handled by 0 .
$ nslookup example.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: example.com
Address: 23.215.0.136
Address: 96.7.128.175host quietly asked three questions, not one. With no type specified it looks up addresses and mail routing, which is why you got lines you did not ask for. Convenient interactively, surprising in a script.
nslookup's "Non-authoritative answer" is not a warning. It means "this came from a cache", which is the normal and expected case for essentially every lookup you will ever do. It is phrased like a problem and is not one, and it has sent a great many engineers looking for a fault that does not exist. This wording alone is a good reason to prefer dig, where the same fact is one flag — aa present or absent.
Neither host nor nslookup shows you the TTL by default, so neither can tell you whether you are looking at a fresh record or a stale one — which is the question you most often actually have.
🧪 Exercise C6.2 — Revisit the illegal label, and finally see the real reason
# the same 64-character label that failed in Exercise A4.1
dig $(printf 'a%.0s' {1..64}).example.com
# and a name that is merely absent
dig definitely-not-real.example.com +noall +comments✅ Expected result — click to reveal
$ dig aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.example.com
dig: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.example.com' is not a legal name (label too long)
$ dig definitely-not-real.example.com +noall +comments
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 8842
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1This is the payoff for Part A. In Exercise A4.1 both of these produced the identical message Name or service not known and you could not tell them apart. Now they are obviously two different events:
- is not a legal name (label too long) — dig rejected the name locally. No packet was ever sent. The problem is in your input, not in the network, not in the zone, not in the resolver
- status: NXDOMAIN — a packet was sent, a server answered, and the answer was an authoritative "that name does not exist". The system worked perfectly; the name genuinely is not there
The generalisable lesson, which is worth more than either fact. When a tool gives you one message for many causes, replace the tool — do not start guessing. ping merges local rejection, NXDOMAIN, SERVFAIL, REFUSED and timeout into a single sentence. dig distinguishes all five, and Part D is about telling them apart.
🎯 Interview questions — Tool differences
Q. nslookup says "Non-authoritative answer". Is that a problem?
No. It means the answer came from a cache rather than from a server that holds the zone, which is the normal case for almost every lookup on the internet.
The wording is unfortunate — it reads like a warning and is merely a statement of fact. In dig the same information is the presence or absence of the aa flag, with no editorial.
Where it does matter: when you are verifying a change you just made. Then you specifically want an authoritative answer, so you query the zone's own servers directly rather than a resolver — and there you would expect aa to be set. Otherwise, non-authoritative is exactly what you should see.
Part D · Reading failure
D1 · There are five ways a lookup can fail, and they are not interchangeable
· Nobody answers at all — you don't even know if anyone lives there
· "No such address" — the street number does not exist
· "He lives here, but he has no phone" — right person, thing you asked for isn't there
· "I tried to check and our system is down" — something is broken on their side
· "I'm not allowed to tell you" — nothing is broken; you are just not on the list
Five situations, five different people to go and see next. The whole skill is telling them apart.
Almost all DNS debugging comes down to correctly classifying the failure in front of you. There are five distinct outcomes, they have five different causes, and five different people fix them.
| What you see | What it means | Who fixes it |
|---|---|---|
| status: NOERROR ANSWER: 0 | The name exists. It has no record of the type you asked for. Often called NODATA | The zone owner — a record is missing, or you asked for the wrong type |
| status: NXDOMAIN | The name does not exist at all, and an authoritative server said so | Whoever typed the name, or the zone owner |
| status: SERVFAIL | The resolver tried and could not complete the job. A failure on the answering side | The resolver operator, or the zone's authoritative servers |
| status: REFUSED | The server understood you perfectly and declined by policy | The server operator — you are asking the wrong server, or you are not allowed |
| connection timed out or connection refused | No DNS-level answer at all. This is a network or process problem, not a DNS answer | Networking, firewall, or whoever should be running the daemon |
Diagram source
flowchart TD
Q["you run dig"] --> GOT{"did a DNS<br>response come back?"}
GOT -->|"no"| NET["timed out or refused<br>NETWORK PROBLEM<br>firewall, routing,<br>nothing listening"]
GOT -->|"yes"| RC{"read status:"}
RC -->|"NOERROR<br>ANSWER greater than 0"| OK["success<br>you have data"]
RC -->|"NOERROR<br>ANSWER 0"| NODATA["NODATA<br>name exists,<br>wrong record type"]
RC -->|"NXDOMAIN"| NX["name does not exist<br>check spelling,<br>check the zone"]
RC -->|"SERVFAIL"| SF["the answering side broke<br>try another resolver<br>to localise it"]
RC -->|"REFUSED"| RF["policy<br>wrong server, or<br>you are not permitted"]
style NET fill:#ef4444,color:#fff
style OK fill:#22c55e,color:#fff
style NODATA fill:#f59e0b,color:#fff
style NX fill:#f59e0b,color:#fff
style SF fill:#ef4444,color:#fff
style RF fill:#8b5cf6,color:#fffD2 · NXDOMAIN versus NOERROR with no data
· "There is nobody by that name here" — that is NXDOMAIN. You probably have the name wrong
· "She works here, but she has no mobile number listed" — that is NODATA. The person is real; the detail you asked for is missing
On screen these two look almost identical. In practice one sends you back to check the spelling, and the other sends you to whoever maintains the directory.
These two look almost identical on screen and mean opposite things.
- NXDOMAIN — there is no node at that point in the tree. Nothing of any type exists there.
- NOERROR with ANSWER: 0 — the node exists and has records, just not of the type you asked for.
🧪 Exercise D2.1 — Produce both, deliberately, and compare them side by side
# a name that does not exist -> NXDOMAIN
dig definitely-not-real.example.com +noall +comments +authority
# a name that DOES exist, asked for a record type it does not have.
# MX records carry mail routing - Module 02 covers the types; all you
# need here is that this particular name has none.
dig MX www.example.com +noall +comments +authority✅ Expected result — click to reveal
$ dig definitely-not-real.example.com +noall +comments +authority
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 21044
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; AUTHORITY SECTION:
example.com. 900 IN SOA ns.icann.org. noc.dns.icann.org. 2025011653 7200 3600 1209600 3600
$ dig MX www.example.com +noall +comments +authority
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39517
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; AUTHORITY SECTION:
example.com. 900 IN SOA ns.icann.org. noc.dns.icann.org. 2025011653 7200 3600 1209600 3600Look at how similar these are. Both have ANSWER: 0. Both have one AUTHORITY record. Both return the same SOA record. The only difference in the entire output is the word after status: — and that one word is the difference between "you typed the wrong name" and "the zone is missing a record".
This is exactly why dig +short is dangerous in scripts. Run either of these with +short and you get an empty line for both. Two different problems, one indistinguishable output.
Why is there an SOA record in a negative answer? Because a "no" needs an expiry date just as much as a "yes" does. There is no record to attach a TTL to, so the server sends the zone's SOA record instead, and one of the numbers inside it states how long this "no" may be cached. That is why a name you have just created can keep returning NXDOMAIN for minutes after you create it — you are being served a cached "no". The SOA fields and negative caching are Module 02 and Module 03; the reflex to learn now is: if I get NXDOMAIN for something I just created, suspect a cached negative answer before suspecting my change.
Now imagine this at 500 hosts. A new service name is added and half the fleet reports NXDOMAIN for the next hour because they queried it once, a second too early, and cached the "no". Every one of those hosts is behaving correctly. The mistake was querying before publishing.
🎯 Interview questions — NXDOMAIN and NODATA
Q. What is the difference between NXDOMAIN and an empty NOERROR response?
NXDOMAIN means no node exists at that name — nothing of any type is there. NOERROR with a zero answer count, sometimes called NODATA, means the name does exist and has records, just none of the type requested.
Practically: NXDOMAIN points at the name, NODATA points at the record set.
The detail worth adding, because it shows you have read the response and not just the summary line: both come back with the zone's SOA in the AUTHORITY section, and that SOA is what makes the negative answer cacheable. So both can be served from cache, and a name you just created can keep returning NXDOMAIN until that cached negative expires. Checking the authoritative server directly is how you tell "my change didn't land" from "my change landed and I'm reading a cached no".
Q. You add a DNS record and it still returns NXDOMAIN. Walk me through it.
First, query the authoritative servers directly rather than a resolver. If they return the record, the change landed and I am looking at a cached negative answer — then I wait out the negative caching TTL, which comes from the zone's SOA rather than from the record I just added.
If the authoritative servers also say NXDOMAIN, the change did not take effect: I would check that I edited the zone I think I did, that the serial number was incremented, that the zone reloaded, and that secondaries actually transferred it.
The subtlety that impresses: the negative TTL is a property of the zone, not of the record you created, so it is often much longer than the TTL you carefully set on the new record. People set a 60-second TTL on a new record and are baffled that it takes an hour to appear — because the thing being cached is the absence, governed by the SOA.
D3 · SERVFAIL and REFUSED
· "Sorry, our system is down, I can't look that up" — SERVFAIL. Something really is broken, and it is on their side
· "I'm not allowed to give out that information" — REFUSED. Nothing is broken at all. You called the wrong department, or you are not authorised
Treating the second one as an outage is how teams spend an afternoon hunting a fault that does not exist.
| RCODE | What it actually means, and the usual causes |
|---|---|
| SERVFAIL | "I tried and I could not finish." The answering server failed on your behalf. Usual causes: every authoritative server for the zone is unreachable; the delegation points at servers that do not serve the zone; a DNSSEC validation failure; or the resolver itself is broken or overloaded |
| REFUSED | "I understood you and I decline." A policy decision, not a failure. Usual causes: you asked an authoritative-only server about a zone it does not host; you asked a resolver that restricts recursion to certain client ranges; or an ACL blocks the query type |
🧪 Exercise D3.1 — Earn a REFUSED on purpose
# a.iana-servers.net is one of the authoritative servers for example.com.
# Taking that as given for now - Module 02 shows you how to find it yourself.
# Ask it about example.com -> it will answer authoritatively
dig @a.iana-servers.net example.com +noall +comments
# now ask that same server about a zone it does not serve
dig @a.iana-servers.net google.com +noall +comments✅ Expected result — click to reveal
$ dig @a.iana-servers.net example.com +noall +comments
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5512
;; flags: qr aa rd; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1
$ dig @a.iana-servers.net google.com +noall +comments
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 46108
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1Two things changed between those two responses, and both are worth naming.
1. The first response has aa set. This is the first time in this module you have seen it. The answer came from a server that holds the zone, not from a cache — and notice the TTLs on those records would be the full published values, not counted down. aa plus full TTLs is the signature of an authoritative answer.
2. The second response is REFUSED, and there is no ra flag anywhere. You asked an authoritative-only server to go and find something for you. It does not do that for anybody, so rather than fail, it declines. Nothing is broken here. The server is working exactly as designed and you asked the wrong question of the right server.
Where you will meet this for real. Someone points an application's resolv.conf at an authoritative server — often because "it's our DNS server" — and everything inside that one zone works while everything else in the world returns REFUSED. The symptom looks bizarre and random until you notice the pattern: only one domain resolves. That pattern is the diagnosis.
The other common source is an ACL. A company resolver that only serves the office ranges will REFUSE a VPN client whose new subnet was never added to the allow-list. Same code, same reasoning: policy, not fault.
🧪 Exercise D3.2 — Two ways of getting nothing at all, which mean different things
# 192.0.2.1 is reserved for documentation and is not routed anywhere.
# Nothing will ever answer. Expect this to take about 15 seconds.
dig @192.0.2.1 example.com
# your own machine, on a port where almost certainly nothing is listening
dig @127.0.0.1 -p 5399 example.com✅ Expected result — click to reveal
$ dig @192.0.2.1 example.com
;; communications error to 192.0.2.1#53: timed out
;; communications error to 192.0.2.1#53: timed out
;; communications error to 192.0.2.1#53: timed out
; <<>> DiG 9.18.30 <<>> @192.0.2.1 example.com
; (1 server found)
;; global options: +cmd
;; no servers could be reached
$ dig @127.0.0.1 -p 5399 example.com
;; communications error to 127.0.0.1#5399: connection refused
;; communications error to 127.0.0.1#5399: connection refused
;; communications error to 127.0.0.1#5399: connection refused
; <<>> DiG 9.18.30 <<>> @127.0.0.1 -p 5399 example.com
;; global options: +cmd
;; no servers could be reachedNeither of these has a status: line, and that absence is the most important thing on the screen. There is no RCODE because there is no response. DNS did not answer you — so DNS has told you nothing, and every DNS-level theory you were forming should be set aside.
But the two error words point in different directions, and this distinction is genuinely valuable:
- timed out — your packet went out and nothing came back. Either it never arrived, or the reply never made it home. Suspect routing, or a firewall silently dropping the packet. Note dig tried three times before giving up: that is the default, and it is why a dead resolver costs you seconds rather than milliseconds
- connection refused — you reached the host and it actively rejected the port, via an ICMP port-unreachable. The network is fine. Nothing is listening on that port. Suspect a stopped daemon, a service bound to the wrong address, or the wrong port
"Timed out" versus "refused" is the same distinction as an unanswered phone versus a disconnected number, and it routes the ticket to a different team. A silent drop is a network conversation; a refused connection is a process conversation.
Now imagine this at 500 hosts. A security group change removes UDP/53 egress. Every host now waits the full timeout on every lookup, three times, before falling back — so nothing reports as "DNS down", everything reports as "the application is slow". Latency, not errors, is how DNS failures usually present at scale, and that is why they are hard to spot.
🎯 Interview questions — SERVFAIL, REFUSED and timeouts
Q. What does SERVFAIL mean and how do you troubleshoot it?
It means the server answering you could not complete the resolution — it is a failure on the answering side, not a statement about whether the name exists.
My first move is always to ask a different resolver the identical question. If only one resolver fails, the fault is that resolver. If all of them fail, the fault is the zone: unreachable authoritative servers, a delegation pointing at servers that do not host the zone, or a DNSSEC validation failure.
Then I query the zone's authoritative servers directly to see whether they answer at all.
The specific cause worth naming, because it is the one people miss: DNSSEC validation failures surface as SERVFAIL and nothing else. An expired signature produces a plain SERVFAIL that looks like a network problem, and the way to confirm it is to re-query with validation disabled — if it succeeds without validation and fails with it, you have your answer. That is Module 07.
Q. What is the difference between SERVFAIL and REFUSED?
SERVFAIL is "I tried and failed". REFUSED is "I understood and I won't". The first is a malfunction somewhere, the second is a policy decision and means nothing is broken.
REFUSED usually means you are querying an authoritative-only server for a zone it does not host, or a resolver whose ACL does not include your source address.
The reason getting this right matters: the two codes route to different teams. SERVFAIL starts an investigation; REFUSED starts a configuration review. Escalating a REFUSED as an outage burns credibility, and every DNS server operator has watched it happen.
Q. dig reports "connection timed out; no servers could be reached". What do you check?
The absence of a status: line tells me this is not a DNS answer at all — nothing responded — so I stop reasoning about records and start reasoning about reachability.
I would check that I am querying the address I intended, that UDP/53 and TCP/53 egress is permitted, and that something is actually listening — from the server side, ss -ulnp | grep :53.
The distinction I would draw explicitly: timed out means the packet was silently dropped, which is firewall or routing. Connection refused means the host was reached and rejected the port, which means the daemon is not running or is bound to the wrong address. Those are different teams and different fixes, and the two words in the error message are the only clue you get.
And the scale point: at fleet scale this failure mode usually presents as latency rather than errors, because the stub waits out its full timeout and then succeeds against a secondary. You get "the app is slow", not "DNS is down".
Part E · Putting it together
E1 · How this all fits — the complete picture
Diagram source
flowchart TD
subgraph LOCAL["🖥️ YOUR MACHINE"]
APP["curl / browser / ping<br>wants an address"]
HOSTS["/etc/hosts<br>checked first,<br>DNS never consulted"]
STUB["stub resolver in libc<br>no cache of its own"]
CONF["/etc/resolv.conf<br>nameserver lines<br>tried in order, 5s each"]
DIG["dig<br>bypasses hosts and libc<br>speaks DNS directly"]
end
APP --> HOSTS
HOSTS -->|"no match"| STUB
CONF --> STUB
STUB -->|"one query<br>rd bit set"| REC
DIG -->|"@server lets you<br>choose the target"| REC
REC["🌐 RECURSIVE RESOLVER<br>does the work<br>CACHES the result<br>counts the TTL down<br>sets ra"]
REC -->|"only on a cache miss"| AUTH["📗 AUTHORITATIVE SERVERS<br>hold the zone<br>set aa<br>full TTL, no cache"]
REC -->|"NOERROR + data<br>NODATA · NXDOMAIN<br>SERVFAIL · REFUSED<br>or silence"| STUB
style HOSTS fill:#ef4444,color:#fff
style REC fill:#8b5cf6,color:#fff
style AUTH fill:#22c55e,color:#fff
style DIG fill:#f59e0b,color:#fffThree things in this diagram cause most of the confusion in DNS, and all three are now things you have seen with your own eyes.
- dig and your application do not take the same path. dig skips /etc/hosts and skips the libc resolution logic. A dig that works while curl fails is not a contradiction — it is a clue.
- The cache is the only place TTLs count down. Full TTL plus aa means authoritative; a reduced TTL and no aa means you are reading a cache.
- Silence is not an RCODE. If there is no status: line, DNS has told you nothing at all.
E2 · Production practice
| Habit | Why |
|---|---|
| Read status: and the ANSWER: counter before reading anything else | NOERROR with zero answers is a completely different problem from NXDOMAIN, and they look nearly identical |
| Check the SERVER: line on every surprising result | A wrong answer is very often the right answer from the wrong server — a local stub, a VPN resolver, or a split-horizon view |
| Never use dig +short in automation or alerting | It collapses NXDOMAIN, NODATA, SERVFAIL, REFUSED and timeout into one empty string. One alert, five meanings |
| On SERVFAIL, immediately re-query a second resolver | It splits the search space in half: one resolver failing is a resolver fault, all of them failing is a zone or delegation fault |
| Query the authoritative servers directly when verifying a change | Separates "my change did not land" from "my change landed and I am reading a cache" — two problems with opposite responses |
| Lower TTLs before a planned change, not during it | Caches holding the old record never see the new low TTL until the old one expires, so a simultaneous change buys nothing |
| Treat REFUSED as a configuration review, not an incident | It is a policy decision by a healthy server. Escalating it as an outage sends a team hunting a fault that does not exist |
| Keep a debug image with dig, ping, curl and ss in it | Production and CI images have no DNS tools, and installing packages into a running production container is not a plan |
| Distinguish timed out from connection refused before escalating | A silent drop means firewall or routing; refused means the daemon is not listening. Different teams, different fixes |
| Never rely on the second nameserver line as real redundancy | Failover costs a full 5-second timeout per lookup, which users and health checks experience as an outage, not as resilience |
| Add the trailing dot when you want certainty about what was queried | It disables search-list expansion, which is the fastest way to rule out a whole class of resolver-side problem |
E3 · Capstone exercise
Brief. Using only dig, cat and sleep, produce a short written report that answers all six of the following. Capture the exact line of output that proves each one.
- Which resolver does this machine send queries to, and is that a local stub listener or a real remote server? State how you can tell.
- Trigger all five failure outcomes on purpose — NODATA, NXDOMAIN, SERVFAIL, REFUSED, and no-response — and for each, quote the single line that identifies it. If one of them will not reproduce reliably, say which and why.
- Prove that a particular answer came from a cache rather than from the authoritative source, and state how many more seconds that cached copy has to live.
- Prove that two different public resolvers are holding copies of the same record that were fetched at different times.
- Establish whether example.com and www.example.com are the same node in the namespace, and justify your conclusion from the output rather than from convention.
- Write a four-line decision procedure you would hand to a junior engineer on call, taking them from dig output to the name of the team that owns the problem.
✅ Model answer — attempt it first, then click
1. Which resolver.
cat /etc/resolv.confIf it shows nameserver 127.0.0.53, that is a local stub listener — systemd-resolved on this machine — and the real upstream servers are configured elsewhere and are not visible in this file. Any other address, particularly a private range or a public resolver, is a real remote server.
The confirming evidence is in dig itself: the ;; SERVER: line reports who actually answered.
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)2. All five failures.
# NODATA - name exists, no record of that type
dig MX www.example.com +noall +comments
# PROOF: status: NOERROR together with ANSWER: 0
# NXDOMAIN - no such name
dig definitely-not-real.example.com +noall +comments
# PROOF: status: NXDOMAIN
# REFUSED - policy
dig @a.iana-servers.net google.com +noall +comments
# PROOF: status: REFUSED, and no ra flag
# NO RESPONSE, silently dropped
dig @192.0.2.1 example.com
# PROOF: ";; communications error ... timed out" and NO status: line at all
# NO RESPONSE, actively rejected
dig @127.0.0.1 -p 5399 example.com
# PROOF: ";; communications error ... connection refused"SERVFAIL is the one that will not reproduce reliably, and saying so is part of the correct answer. It requires something to actually be broken — an unreachable authoritative server, a lame delegation, or a DNSSEC validation failure — and you cannot break somebody else's zone to order. Public test domains for it exist but come and go. You will generate one deterministically in Module 07, on a zone you control.
3. Cached, not authoritative.
dig +noall +answer example.com
# example.com. 241 IN A 23.215.0.136Two independent pieces of evidence, and you should cite both:
- The aa flag is absent from the header, so this did not come from a server holding the zone
- The TTL is not a round configured number — 241 rather than 300 — so it has been counted down. It has 241 seconds left
Contrast it with the authoritative source, where aa is set and the TTL is the full published value:
dig @a.iana-servers.net example.com +noall +comments +answer4. Two caches, fetched at different times.
dig +noall +answer @1.1.1.1 example.com
dig +noall +answer @8.8.8.8 example.comSame name, same value, different TTLs — for example 112 against 267. Neither is wrong. Each resolver fetched the record at a different moment and is counting down its own copy independently. This is the actual mechanism behind the phrase "DNS propagation", and it is why a change appears to roll out unevenly rather than everywhere at once.
5. Are they the same node?
dig +noall +answer example.com
dig +noall +answer www.example.comThey are different nodes. The proof is that each response's answer records carry their own owner name in the first column — example.com. in one and www.example.com. in the other — so two distinct record sets exist at two distinct points in the tree. They may or may not hold the same values; that is a choice the zone owner made, not a rule of DNS. Nothing in the protocol links www.x to x, and assuming otherwise causes a recognisable class of outage.
6. The four-line on-call procedure.
1. No "status:" line? -> nobody answered. Networking / firewall team.
"timed out" = silent drop. "refused" = nothing listening.
2. status: REFUSED? -> healthy server, wrong server or missing ACL.
Configuration review, not an incident.
3. status: SERVFAIL? -> re-ask a second resolver NOW.
One fails -> resolver operator. All fail -> zone owner / delegation.
4. status: NOERROR or NXDOMAIN? -> DNS is working correctly.
NXDOMAIN = wrong name.
NOERROR + ANSWER: 0 = right name, missing record -> zone owner.
NOERROR + data = DNS is fine, the fault is downstream.The five things most people miss on this capstone:
- Admitting SERVFAIL cannot be reproduced to order. Inventing a command that "produces" it is worse than explaining why you cannot.
- Using the absent aa flag as evidence, not just the TTL. The TTL alone is suggestive; aa is decisive.
- Noticing that requirement 5 is answered by the owner name column, not by comparing addresses. Two names sharing an address proves nothing about the tree.
- Putting "no status: line" first in the procedure. It is the only check that removes DNS from the investigation entirely, so it belongs at the top.
- Ending line 4 with "the fault is downstream". A successful lookup is a result, and the most valuable thing DNS troubleshooting often produces is the conclusion that DNS is not the problem.
E4 · Official documentation
| Link | Covers |
|---|---|
| RFC 1034 — Concepts and Facilities | The whole of Part A and Part B: the namespace, the tree, zones, resolvers and their roles. The readable one of the two founding RFCs |
| RFC 1035 — Implementation and Specification | §2.3.1 and §2.3.4 for name syntax and the 63/255 limits · §3.2.1 for the TTL field · §4.1.1 for the header and RCODEs |
| RFC 9499 — DNS Terminology (BCP 219) | The authoritative dictionary. Read this whenever two sources seem to use a word differently — usually one of them is wrong |
| RFC 1123 §2.1 — Requirements for Internet Hosts | Host name syntax, and the relaxation that allows a name to begin with a digit |
| RFC 4343 — DNS Case Insensitivity Clarification | Exactly what "case insensitive" means: folded for matching, preserved on output |
| RFC 2308 — Negative Caching of DNS Queries | The formal definitions of NXDOMAIN and NODATA, and why an SOA appears in a negative answer |
| dig manual — BIND 9 ARM | Every query option and display option, including +short, +noall, +norecurse, +comments |
| host manual · nslookup manual | The two alternatives, and what each one hides from you |
| resolv.conf(5) · hosts(5) | Stub resolver configuration, and the local override file that bypasses DNS entirely |
| IANA DNS Parameters | The live registries: every RCODE, every record type, every EDNS option. Definitive, and always current |
| IANA Root Servers · IANA Root Zone Database | The 13 root identities and their operators; every TLD and who runs it |
| BIND 9 Administrator Reference Manual · Troubleshooting chapter | The reference you will live in from Module 05 onwards |
Start with RFC 9499, not RFC 1034. It is a dictionary, it is recent, and it settles the vocabulary. Most DNS confusion is vocabulary confusion.
Check the banner of any RFC before trusting it. The header tells you whether it has been Obsoleted by or Updated by something newer. RFC 1034 and 1035 date from 1987 and have been updated many times — they remain correct on concepts and are out of date on specifics.
Search for MUST, MUST NOT and SHOULD. Those keywords mark the actual requirements; everything between them is explanation you can skim.
Prefer the IANA registries over any RFC for lists. Record types, RCODEs and EDNS options are added over time. The registry is current; an RFC is a snapshot of the year it was written.
The offline route. man dig gives you the complete manual with no browser, and dig -h prints every option in one screen — the fastest reference there is once you know what you are looking for. Both work on a locked-down bastion with no internet access, which is exactly where you will need them.
E5 · Self-assessment
Answer each one out loud before opening it.
1. Why is the DNS namespace hierarchical rather than flat, and what does that hierarchy actually buy you?
Two things, and the second matters more.
It removes name collisions: mail.a.com and mail.b.com can coexist because the name carries its administrative path.
More importantly it enables delegation — the operator of com can say "for anything under example.com, ask these other servers instead". That is what lets the database be maintained by millions of unrelated parties, with no central coordination and no central copy.
2. What is the trailing dot, and name one place where forgetting it causes a real bug.
It is the root, whose label is the empty string. A name ending in a dot is absolute; a name without one is relative and may have a suffix appended before it is queried.
The classic bug is in a zone file, where an unqualified name silently gets the zone origin appended — writing www.example.com inside the example.com zone produces www.example.com.example.com.. The file loads without complaint and the name simply does not work.
Its diagnostic use is the mirror image: adding the dot forces a single absolute query and skips search-list expansion, which rules out a whole class of resolver-side problem in one command.
3. Why is the maximum label length 63 octets rather than a rounder number?
Because the length is encoded in a single byte on the wire and the top two bits of that byte are reserved as a flag for message compression. Six bits remain, and six bits counts to 63.
The whole-name limit of 255 octets counts every label plus its length byte plus the terminating zero, which works out at roughly 253 printable characters.
4. Distinguish a stub resolver, a recursive resolver and an authoritative server.
The stub is library code inside your OS. It asks one configured server the whole question and waits. No cache, no knowledge of the tree.
The recursive resolver accepts the whole question, does whatever work is required, caches every step, and returns one final answer. It owns no data.
The authoritative server holds the configured data for its zones, answers only about those, and does not chase answers on anyone else's behalf.
The difference between the last two is expressed as a single bit — recursion available — not as a difference in capability.
5. Your /etc/resolv.conf says nameserver 127.0.0.53. What does that tell you, and what does it not tell you?
It tells you there is a local stub listener on this machine, almost certainly systemd-resolved, and that your queries go there first.
It tells you nothing whatsoever about the real upstream resolvers, which are configured elsewhere and do not appear in this file. Editing the file is also usually pointless, because it is regenerated.
Practically: on such a host, cat /etc/resolv.conf cannot answer the question "where is my DNS traffic actually going".
6. What do the flags qr, rd, ra and aa each mean?
qr — this message is a response rather than a query.
rd — recursion desired; the client asked the server to do the work.
ra — recursion available; the server is willing to do that work for clients.
aa — authoritative answer; this came from a server holding the zone rather than from a cache.
rd is set by the asker; ra and aa are set by the answerer. An authoritative-only server never sets ra.
7. Why is status: NOERROR not the same as "I found it"?
NOERROR means the server processed the question without malfunctioning. It says nothing about whether any records came back.
NOERROR with ANSWER: 0 is NODATA: the name exists but has no record of the requested type. That is a completely different problem from NXDOMAIN and it is frequently misread as "not found".
So you always read two things — status: for whether the server is happy, and the ANSWER: counter for whether you got data.
8. A TTL comes back as 241 when the zone publishes 300. What does that tell you?
That you are talking to a cache, that this copy was fetched 59 seconds ago, and that it has 241 seconds left before it is discarded.
A TTL that is always the full published value means you are talking to the authoritative server, or to something that is not caching at all — and in that case aa should be set too.
9. You must repoint a name that has a 24-hour TTL. Describe the procedure and its ordering.
Lower the TTL first — to 60 seconds, say — then wait a full 24 hours, because every cache currently holding the record keeps its old copy with the old 24-hour lifetime until it expires. Only once that has drained does the low TTL actually apply everywhere.
Then make the change, verify against the authoritative servers and against several public resolvers, and raise the TTL back up once it has settled.
Lowering the TTL at the same moment as making the change achieves nothing for exactly the clients you were worried about.
10. You get SERVFAIL. What is your very next command, and why that one?
The same query against a different resolver — dig @1.1.1.1 name, then dig @8.8.8.8 name.
Because SERVFAIL means "the answering side could not complete the job" and deliberately does not say which side. One resolver failing while others succeed makes it that resolver's fault. Every resolver failing makes it the zone's or the delegation's fault. One command, and the search space halves.
And if the cause is DNSSEC, it will present as a plain SERVFAIL with no other clue — which is why re-querying with validation disabled is the follow-up.
11. dig says "connection timed out" against one server and "connection refused" against another. What differs in the cause?
Neither produced a DNS response at all — there is no status: line, so DNS has told you nothing.
Timed out means the packet was silently dropped in one direction or the other: firewall or routing.
Connection refused means you reached the host and it rejected the port with an ICMP port-unreachable: the network is fine and nothing is listening — a stopped daemon, or one bound to the wrong address or port.
Different teams, different fixes, and the only clue is which of those two words appears.
12. Why should dig +short never appear in a monitoring check?
Because it prints values only and discards the status. An empty result from +short could be NXDOMAIN, NODATA, SERVFAIL, REFUSED, or no response at all — five different problems owned by four different teams, all producing one identical empty string.
A check should read status: and the ANSWER: counter explicitly, so the alert carries the classification instead of making on-call rediscover it at three in the morning.
You have seen the shape of a record — name, TTL, class, type, value — and used exactly one type, A. Module 02 fills in the rest: AAAA, CNAME, NS, MX, TXT, PTR, SRV, CAA, and the SOA record you have already met twice in negative answers without being told what it was. It then has you write a zone file by hand — including committing the trailing-dot mistake from A3 on purpose, and meeting the CNAME-at-the-apex rule that no vendor can engineer around.
📚 Sources for the interview questions
The technical content is taken from the primary specifications and was verified against them: RFC 1034, RFC 1035, RFC 1123, RFC 2308, RFC 4343, RFC 9499, the IANA DNS Parameters registry, and the BIND 9 Administrator Reference Manual.
Question selection was cross-referenced against publicly published 2026 DNS and networking interview question sets:
- Top 25 DNS Interview Questions and Answers for 2026 — nitizsharma.com
- Top 30 Most Common DNS Interview Questions You Should Prepare For — Verve AI
- Interview Questions & Answers for DNS — DevOpsSchool
- DNS Interview Questions & Answers for Network Engineers & Software Developers — Level Up Coding
- 75+ Network Engineer Interview Questions for 2026 — Taggd
- 50 Must-Prepare Networking Interview Questions for DevOps Engineers
Answers were rewritten and deepened rather than reproduced. The published versions are usually correct but shallow — they state the rule and stop. The added operational detail, and the explicit notes on what separates a strong candidate from an average one, are the part that actually matters in the room.