Skip to content

16. Cheat sheet

Everything worth having to hand, in one place.

1. NOTHING PROPAGATES. an old answer expires
out of each cache independently. the wait
is bounded by the OLD TTL, not the new one.
2. A ZONE IS NOT A DOMAIN. a zone starts at
an SOA and ends at every delegation below
it.
3. A CNAME CANNOT COEXIST WITH ANYTHING,
therefore it cannot sit at the apex.
4. NXDOMAIN ≠ NODATA. "does not exist" is
not "exists with no record of this type".
5. SERVFAIL MEANS TWO THINGS. `dig +cd`
tells you which.
6. ONE BROKEN DNSSEC LINK = TOTAL OUTAGE for
every validating resolver (~30–40% of
queries).
7. NS, GLUE AND DS LIVE AT THE REGISTRAR.
everything else lives in your zone.
8. DNS FAILOVER TAKES MINUTES. a load
balancer takes milliseconds. know which
problem you have.
A IPv4 address
AAAA IPv6 address
CNAME alias; exclusive at its name
DNAME alias for a whole subtree
MX mail exchange + preference
(lower first; hostname, never
an IP, never a CNAME)
TXT arbitrary strings; ≤255 per
string
SRV _svc._proto; priority weight
port target
HTTPS /
SVCB alpn, ipv4hint, ech — and an
ALIAS form legal at the apex
NS delegation / authority
SOA one per zone, at the apex
PTR reverse mapping
CAA which CAs may issue
TLSA DANE certificate pinning
DNSKEY public key
RRSIG signature over an RRset
DS hash of a child's key, in the
parent
NSEC /
NSEC3 proof of non-existence
CDS /
CDNSKEY child's signal for DS updates
ANY a meta-query, widely refused
FLAGS
qr response aa authoritative
tc truncated rd recursion
desired
ra recursion ad DNSSEC
available validated
cd checking disabled
RCODES
0 NOERROR (zero answers = NODATA)
1 FORMERR
2 SERVFAIL server broke OR DNSSEC
bogus
3 NXDOMAIN
5 REFUSED not my zone / not allowed
16 BADVERS / BADSIG
READING FLAGS
aa present → you reached authority
aa absent → a resolver or a referral
tc present → size problem; retry TCP
ad present → validated
Terminal window
dig example.com A # the basics
dig +short example.com A
dig +noall +answer example.com
dig @1.1.1.1 example.com # a specific resolver
dig @ns1.example.com example.com # a specific authority
dig +norecurse @ns1.example.com example.com # no recursion: see referrals
dig +trace example.com # walk from the root (no cache)
dig +dnssec example.com # ask for signatures
dig +cd example.com # bypass validation
dig +tcp example.com
dig +bufsize=1232 example.com
dig +subnet=203.0.113.0/24 example.com # EDNS Client Subnet
dig +nsid @k.root-servers.net . SOA # which anycast instance?
dig -x 192.0.2.15 # reverse
dig @ns1.example.com example.com AXFR # zone transfer
dig +short example.com SOA | awk '{print $3}' # the serial
dig example.com | awk '/^example/ {print $2}' # remaining TTL
Terminal window
# other tools
delv example.com # validating lookup (BIND)
delv +rtrace example.com
kdig +tls @1.1.1.1 example.com # DoT
kdig +https @1.1.1.1 example.com # DoH
dog example.com @1.1.1.1
dnsviz probe example.com | dnsviz print
named-checkzone example.com db.example.com
named-checkconf
nsupdate -k key.conf
resolvectl query example.com
resolvectl status
resolvectl flush-caches
getent hosts example.com
whois example.com
example.com. 3600 IN SOA
ns1.example.com. ; MNAME primary
admin.example.com. ; RNAME admin@…
2024061503 ; SERIAL higher =
; newer
7200 ; REFRESH check
; interval
900 ; RETRY after a
; failure
1209600 ; EXPIRE secondaries
; STOP SERVING
; after this
300 ; MINIMUM negative
; cache TTL
apex / www A, AAAA 300
behind a CDN or LB 60
MX 3600
SPF / DKIM / DMARC 3600
NS at the apex 86400
SOA minimum 300
_acme-challenge 60
mid-migration 60
LOWER THE TTL THREE DAYS BEFORE A
PLANNED CHANGE, THEN WAIT OUT THE OLD
TTL, THEN CHANGE THE RECORD.
WHO IGNORES YOUR TTL
nscd its own, 3600
browsers their own, ~60 s
the JVM FOREVER by default
connection pools never re-resolve
some ISPs floor low TTLs
MX example.com. MX 10 mail.example.com.
SPF example.com. TXT
"v=spf1 include:_spf.google.com -all"
ONE record. 10-lookup limit.
DKIM sel._domainkey.example.com. TXT
"v=DKIM1; k=rsa; p=…"
DMARC _dmarc.example.com. TXT
"v=DMARC1; p=none;
rua=mailto:dmarc@example.com"
deploy p=none FIRST. read reports.
then tighten.
PTR set by whoever owns the IP block.
mail receivers check it.
MTA-STS _mta-sts.example.com. TXT
+ an HTTPS policy file
/etc/resolv.conf
nameserver 127.0.0.1
search example.com
options timeout:1 attempts:2 rotate
single-request-reopen ndots:1
edns0
timeout default is 5 — change it.
ndots:5 in Kubernetes costs 5 wasted
NXDOMAINs per external lookup. use a
trailing dot, a per-pod dnsConfig, or
NodeLocal DNSCache.
Do53 udp/tcp 53 plaintext
DoT 853 TLS; easy to permit,
easy to block
DoH 443 indistinguishable
from HTTPS
DoQ 853/udp QUIC
ODoH relay + target,
non-collusion
assumed
DDR/DNR RFC 9462/9463 a network advertises
its own encrypted
resolver
STILL VISIBLE: the destination IP, the
SNI (unless ECH), timing, your choice of
resolver.
use-application-dns.net → NXDOMAIN
disables Firefox auto-DoH.
CHAIN root KSK → root ZSK → child DS →
child KSK → child ZSK → the RRset
ALGORITHM 13 (ECDSA P-256) for anything
new — RSA pushes DNSKEY answers past
1232 bytes.
NSEC signs the gaps; allows zone walking
NSEC3 hashes names; RFC 9276 says
0 iterations, no salt
WHITE LIES synthesised NSEC, online key,
no enumeration
TO DISABLE: REMOVE THE DS AT THE PARENT
FIRST, WAIT OUT ITS TTL, THEN UNSIGN.
dig +cd does it work without
validation?
delv why not?
dig +dnssec … | grep EDE the specific
reason
AXFR full transfer, over TCP.
RESTRICT IT.
IXFR delta from a serial
NOTIFY primary tells secondaries
immediately
TSIG shared-secret HMAC for
transfers, notifies and
updates. signs a timestamp —
clock skew gives BADTIME.
RFC 2136 dynamic update (nsupdate, DHCP,
AD, certbot)
THE SERIAL CHECK, RUN IT HOURLY:
Terminal window
for ns in $(dig +short example.com NS); do
printf '%-28s %s\n' "$ns" \
"$(dig +short @"$ns" example.com SOA | awk '{print $3}')"
done
.arpa infrastructure; in-addr,
ip6
.internal the reserved private TLD —
use this
.home.arpa home / lab networks
.local mDNS ONLY. never unicast.
.localhost always loopback
.invalid never exists
.example documentation
.test testing
.corp .home
.mail PERMANENTLY BLOCKED from
the root
$ORIGIN example.com.
$TTL 3600
@ IN SOA ns1.example.com. admin.example.com. (
2024061503 7200 900 1209600 300 )
IN NS ns1.example.com.
IN MX 10 mail.example.com.
IN A 192.0.2.1
IN CAA 0 issue "letsencrypt.org"
ns1 IN A 192.0.2.1
www 300 IN CNAME cdn.example.net.
* IN A 192.0.2.99
@ the current $ORIGIN
blank owner repeats the previous one
— INSERTING A LINE CHANGES
THE OWNER OF EVERYTHING
BELOW
no trailing
dot $ORIGIN is appended
\# len hex an unknown record type
(RFC 3597)
Terminal window
named-checkzone example.com db.example.com
dig @ns1.example.com example.com AXFR > exported.zone
Terminal window
sudo resolvectl flush-caches # systemd-resolved
sudo unbound-control flush www.example.com
sudo rndc flushname www.example.com # BIND
sudo killall -HUP dnsmasq
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder # macOS
ipconfig /flushdns # Windows
# browsers: chrome://net-internals/#dns, about:networking#dns
AND THE CACHES YOU CANNOT REACH:
every other resolver, every browser,
every JVM, every connection pool.
*.example.com A 192.0.2.99
matches anything.example.com
NOT example.com (the apex)
NOT any name that EXISTS with any
record of any type
IF a.b.example.com EXISTS THEN
b.example.com EXISTS WITH NO DATA
→ NODATA, not NXDOMAIN
1. IS IT A CACHE?
dig @ns1.yourdomain … vs dig @1.1.1.1 …
read the remaining TTL. if authority is
right, you are waiting. stop.
2. IS IT DNSSEC?
dig +cd. one command.
3. IS THE DELEGATION RIGHT?
dig +norecurse @a.gtld-servers.net …
compare the parent's NS set with yours.
4. DO ALL NAMESERVERS AGREE?
the SOA serial loop above.
5. IS IT THE CLIENT?
resolv.conf, ndots, nsswitch,
/etc/hosts, resolvectl status, the JVM.
6. IS IT THE NETWORK?
TCP/53 open? dig +tcp. dig +bufsize=512.
fragmentation?
7. IS IT THE REGISTRAR?
whois: expiry, status, NS, DS.
✗ a missing trailing dot in a zone file
✗ a CNAME at the apex
✗ a CNAME as an MX or NS target
✗ two SPF records, or more than 10 SPF
lookups
✗ DMARC p=reject before SPF and DKIM work
✗ an SOA minimum of 86400
✗ changing a record and its TTL together
and expecting speed
✗ publishing a DS without the matching
DNSKEY
✗ changing NS and DS in one operation
✗ decommissioning old nameservers
immediately after an NS change
✗ a made-up internal TLD (.corp, .lan)
✗ a dangling CNAME to a deleted service
✗ an open AXFR
✗ an open recursive resolver
✗ relying on round-robin DNS for failover
✗ treating an internal-only name as an
access control
✗ monitoring your own DNS through your
own resolver
label ≤63 octets
full name ≤255 octets
TXT string ≤255 octets
classic UDP message 512 octets
recommended EDNS size 1232 octets
root zone size ~2 MB
top-level domains ~1,500
root server names 13
root server instances 1,900+
root key ceremonies 4 per year
validating resolvers ~30–40% of
queries
signed .com domains ~5%
cold lookup, 3 round trips ~80 ms
warm lookup ~1 ms
local cache hit ~0.05 ms
stub timeout, default 5 s
DNS failover, realistic 1–3 min
DS TTL at .com 2 days

Read alongside: Consul for DNS as a read interface onto a registry with real health data, Kubernetes for CoreDNS, ndots and the conntrack race, HAProxy for the sub-second failover DNS cannot provide, Envoy for endpoint discovery that replaces DNS inside a mesh, Vault for issuing the certificates whose names all of this resolves, and Terraform for the reviewable diff that zone-as-code is after.

Written by Sepuri Sai Krishna

© 2026CC BY 4.0Source