# How DNS works

**Every agent connection begins with a name lookup — and almost nobody can explain what actually happens during it, which is exactly why cache poisoning and silent spoofing still work in 2026.**

You type a hostname, a socket opens a few milliseconds later, and in between a whole delegation tree — root, TLD, authoritative — was walked, the answer was cached at three layers, and unless someone turned on DNSSEC, nothing you got back was ever cryptographically proven to come from the zone owner. If you're going to trust the name an agent resolves, you need to know where that trust does — and doesn't — come from. This page walks the query end to end, then shows the gap plain DNS leaves open.

## The delegation walk

DNS is a tree, not a database. There is no single server that "knows" `agents.whisper.online` — there's a chain of **referrals**, each one narrower than the last, defined in [RFC 1034](https://www.rfc-editor.org/rfc/rfc1034) / [RFC 1035](https://www.rfc-editor.org/rfc/rfc1035):

```
.                              (root — 13 letter-named server clusters, anycast)
 └── online.                   (TLD — delegated via NS + glue at the root)
      └── whisper.online.      (our zone — delegated via NS at the .online TLD)
           └── agents.whisper.online.   (subdelegated zone, own NS records)
```

Each level hands you a **referral**, not an answer: "I don't know, but here's who does." A **full resolver** (recursive) walks the whole chain on your behalf and hands back one final answer; a **stub** just asks a recursive resolver to do that work. When you run `dig` against `1.1.1.1` or your OS resolver, you're doing recursive resolution. When you trace it yourself, you're doing **iterative** resolution — exactly what the recursive resolver does internally, one referral at a time.

### With stock tools — walk it yourself

```bash
$ dig +trace AAAA acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online

;; global options: +cmd
.                       7181  IN  NS   a.root-servers.net.
;; Received 239 bytes from 127.0.0.53#53(127.0.0.53) in 0 ms

online.               172800  IN  NS   ns01.trs-dns.com.
online.               172800  IN  NS   ns01.trs-dns.net.
online.               172800  IN  NS   ns10.trs-dns.info.
online.                86400  IN  DS   30961 13 2 9292C8B1...78ACD47E
online.                86400  IN  RRSIG DS 8 1 86400 ...
;; Received 734 bytes from 199.7.91.13#53(d.root-servers.net) in 23 ms

whisper.online.          900  IN  NS   ns1.whisper.online.
whisper.online.          900  IN  NS   ns2.whisper.online.
whisper.online.          900  IN  DS   50855 13 2 3B33E999...47E247D3
whisper.online.          900  IN  RRSIG DS 13 2 900 ...
;; Received 418 bytes from 2620:57:4002::1#53(ns01.trs-dns.net) in 22 ms

acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online. 60 IN AAAA 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
acef2002a323d40d4...agents.whisper.online. 60 IN RRSIG AAAA 13 5 60 ...
;; Received 247 bytes from 2001:19f0:5000:15f6::fe45:110#53(ns2.whisper.online) in 91 ms
```

Four steps, four different servers, one final authoritative answer — served by `ns2.whisper.online`, the authoritative server for the `agents.whisper.online` zone that names every agent on the Whisper network (`AS219419`, `2a04:2a01::/32`). Notice the `DS`/`RRSIG` records riding along at every hop — that's DNSSEC's chain of trust, covered below.

### With Whisper — the equivalent, DNSSEC-aware by default

`kdig` (from `knot-dnsutils`) is the tool of choice for validators and protocol work — it prints the same trace with clearer DNSSEC bookkeeping:

```bash
kdig +trace +dnssec AAAA acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online
```

And the `whisper` CLI wraps the whole walk plus the identity checks (below) into one call — no manual trace needed for the common case:

```bash
whisper verify acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online
# → resolves AAAA, walks PTR, checks TLSA/DANE, reports pass/fail — see /docs/verify
```

## Iterative vs. recursive, precisely

- **Iterative query**: the resolver asks a server "do you know the full answer for X?" and accepts a *referral* (a list of closer NS records) if the server doesn't. The resolver itself walks every hop. This is what `+trace` simulates locally.
- **Recursive query**: the resolver asks a server to do the *entire* walk and return only the final answer (or a definitive negative). Set with the `RD` (Recursion Desired) header bit — [RFC 1035 §4.1.1](https://www.rfc-editor.org/rfc/rfc1035#section-4.1.1). Public recursive resolvers (`1.1.1.1`, `8.8.8.8`, your ISP's resolver, or a dedicated Whisper per-tenant `:53` resolver) do this on your behalf and cache the result for every other client behind them.

Root and TLD servers **never** do recursion for you — they only answer authoritatively for their own zone and refer you onward. Only a recursive resolver walks the whole tree; that's the load-bearing distinction between "the 13 root server letters" (which handle enormous query volume by being purely iterative and heavily cached/anycast) and your laptop's resolver (which does the walking).

## TTL and caching — three layers deep

Every RRset carries a **TTL** (Time To Live, seconds) set by the zone's authoritative server — the fourth field in the wire format, an unsigned 32-bit integer per [RFC 1035 §3.2.1](https://www.rfc-editor.org/rfc/rfc1035#section-3.2.1). It bounds how long *any* resolver, at *any* layer, may reuse the answer without re-asking:

```
acef2002a323d40d4...agents.whisper.online.  60  IN  AAAA  2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
                                             ^^
                                             TTL: 60 seconds
```

A 60-second TTL on an agent identity is deliberate — it's short enough that revocation (an agent's `/128` being torn down) propagates fast, without paying a full round-trip on every single connection. Compare `whisper.online.`'s own `A` record TTL of 300s, or the zone's `SOA` (`refresh 7200 / retry 3600 / expire 1209600 / minimum 300`) that governs secondary-to-primary sync and negative caching ([RFC 2308](https://www.rfc-editor.org/rfc/rfc2308)).

Caching happens at every hop: your OS stub resolver, your recursive resolver (`1.1.1.1`, corporate resolver, or Whisper's per-tenant `:53` resolver), and often an application-level cache in the HTTP client or SDK. A `dig` immediately after another `dig` for the same name will show the TTL counting down (`59`, `58`, ...) instead of resetting — proof you hit a cache, not the authoritative server.

```bash
dig +noall +answer AAAA acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online
# 60 IN AAAA ...
dig +noall +answer AAAA acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online
# 47 IN AAAA ...   ← same data, counting down = served from cache
```

## The record types that matter for an agent identity

| Type | RFC | Carries | Example (this page) |
|---|---|---|---|
| `A` | 1035 | IPv4 address | `whisper.online. 300 IN A 78.141.218.153` |
| `AAAA` | 3596 | IPv6 address | `acef2002...agents.whisper.online. AAAA 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4` |
| `PTR` | 1035 | reverse mapping, under `.ip6.arpa` for v6 | `4.d.0.4...ip6.arpa. PTR acef2002a323d40d4.t7af9242c44554e0f8e183ac8e6fbf645.agents.whisper.online.` |
| `CNAME` | 1035 | alias to another name | not used on agent leaves — an agent's forward name is canonical, never aliased, so the identity a client sees is never one indirection away from the signed answer |
| `TLSA` | 6698 | a DANE pin: cert-usage / selector / matching-type + hash | `_443._tcp.acef2002...agents.whisper.online. TLSA 3 1 1 b653a4ef...fcb82d1d` |
| `SOA` | 1035 | zone metadata: primary, serial, refresh/retry/expire/minimum | `agents.whisper.online. SOA ns1.whisper.online. hostmaster.whisper.online. 1783326316 7200 3600 1209600 300` |
| `NS` | 1035 | delegation — who is authoritative | `agents.whisper.online. NS ns1.whisper.online. / ns2.whisper.online.` |

The forward (`AAAA`) and reverse (`PTR`) records for a Whisper agent are kept **consistent by construction** — the same authoritative zone answers both directions for every `/128` in `2a04:2a01::/32`, so `dig -x <addr>` and `dig AAAA <name>` always agree. That two-way binding is what makes "the address is the identity" a claim you can check yourself, from any stub resolver, with no API key. See [`/docs/identity`](/docs/identity) for how the name itself is derived from the address.

## The gap plain DNS leaves open

Everything above is **unauthenticated**. A referral, an `A`/`AAAA` record, even the delegation itself — none of it is signed by default. A resolver has no way to tell a genuine authoritative answer from one injected by a spoofed UDP packet on the wire (the class of attack [Dan Kaminsky demonstrated in 2008](https://www.kb.cert.org/vuls/id/800113)) or a compromised recursive resolver. `dig` will happily print a forged answer with the same confidence as a real one — there is no field in a plain DNS response that proves authenticity.

That's the entire reason DNSSEC exists: `RRSIG`, `DNSKEY`, and `DS` records — visible in the `+trace` output above at every hop, from the root's `DS` for `.online` down to `agents.whisper.online.`'s own signed `AAAA` — build a cryptographic chain from the root zone's trust anchor down to the exact record you received, so a validating resolver can set the `AD` (Authentic Data) bit and you can *prove* nothing was substituted in flight. Whisper signs every zone it's authoritative for, and layers DANE `TLSA` on top so a TLS certificate can be pinned the same way — no certificate authority required. That's the next page.

## Next

Continue to [DANE & DNSSEC](/docs/dane) for the signature chain, `TLSA` validation mechanics, and how to verify an agent's identity without trusting anyone but the DNS root — or see [Graph-first resolution](/docs/resolver) for how Whisper's resolver layers policy on top of this same standard DNS path.
