Recursive DNS

Recursive resolver configuration. How resolution works, root hints, security hardening, and rate limiting.

What Recursive Resolution Means

A recursive resolver does the full work of walking the DNS tree on behalf of the client. The client sends one query; the resolver contacts root servers, TLD servers, and authoritative servers as needed, then returns the final answer. The client never sees the intermediate steps.

Contrast with iterative resolution: the server returns referrals ("ask this other server") and the client does the walking. In practice, clients always request recursion; servers do iterative resolution internally.

Configuring Recursive Resolution in BIND

Enable recursion for internal networks only
acl "trusted" { 10.50.0.0/16; 172.16.0.0/12; 127.0.0.0/8; };

options {
    recursion yes;
    allow-recursion { trusted; };
    allow-query-cache { trusted; };
};

An open recursive resolver is a DDoS amplification vector. Attackers send spoofed queries with the victim’s source IP; the resolver sends amplified responses to the victim. Always restrict recursion to trusted networks.

Disable recursion entirely — authoritative-only mode
options {
    recursion no;
};

Use this for servers that only answer queries for their own zones. Returns REFUSED for any query outside their authority.

Testing Recursion

Check if a server performs recursion — look for the RA flag
dig @10.50.1.90 google.com A | grep "flags"

The ra (Recursion Available) flag means the server will perform recursive resolution for you. If ra is absent, the server either has recursion disabled or you’re outside the allow-recursion ACL.

Send a query with recursion desired — the RD flag
dig example.com +recurse

The rd (Recursion Desired) flag is set by default in dig. The server only honors it if recursion is enabled for the querier.

Send a query without recursion — test authoritative knowledge
dig @10.50.1.90 example.com +norecurse

Forces the server to answer only from its own data or cache. No walking the tree. Useful for testing what a server knows directly.

How Recursive Resolution Works

Trace the full resolution path — root to answer
dig example.com +trace

Shows every step:

  1. Query root (.) for com. — returns referral to .com TLD servers

  2. Query .com TLD for example.com. — returns referral to authoritative NS

  3. Query authoritative NS for example.com. — returns the answer

Each step is an iterative query performed by the recursive resolver on your behalf.

Measure resolution time — first query vs cached query
# Flush cache first
sudo rndc flush

# First query — full recursive resolution
dig example.com +stats +noall | awk '/Query time/'

# Second query — served from cache
dig example.com +stats +noall | awk '/Query time/'

The first query takes tens or hundreds of milliseconds (full tree walk). The second takes <1ms (cache hit). This demonstrates why caching matters.

Root Hints

Root hints file — the bootstrap for recursive resolution
cat /var/named/named.ca

Contains the IP addresses of the 13 root server clusters (a.root-servers.net through m.root-servers.net). Without this file, a recursive resolver cannot start the resolution chain.

Update root hints — they change rarely but do change
dig NS . @a.root-servers.net > /var/named/named.ca

Root hints should be updated annually or when IANA announces changes. Stale hints still work (root IPs are very stable) but best practice is to keep them current.

Recursion Security

Rate limiting — protect against recursive abuse
options {
    rate-limit {
        responses-per-second 10;
        window 5;
    };
};

Response Rate Limiting (RRL) throttles identical responses. Mitigates amplification attacks even if recursion is properly ACL’d.

Minimal exposure — separate authoritative and recursive roles
# Recursive resolver (internal-facing)
view "recursive" {
    match-clients { trusted; };
    recursion yes;
};

# Authoritative (public-facing)
view "authoritative" {
    match-clients { any; };
    recursion no;
    zone "inside.domusdigitalis.dev" { type master; file "inside.domusdigitalis.dev.zone"; };
};

A single BIND instance can serve both roles via views, but production best practice is separate servers. If the recursive resolver is compromised, it doesn’t expose your zone data.

See Also