Policy evaluation order
For each query the resolver walks this list and stops at the first match
(internal/policy/engine.go):
| Step | Check | Outcome |
|---|---|---|
| 0 | Operator-level blocks (legal, abuse) | block, EDE 15 |
| 1 | Your rewrites (exact name, then wildcard) | your records |
| 2 | Your allowlist | allow; but SafeSearch and YouTube restricted mode still rewrite |
| 3 | Your denylist | block, EDE 17 |
| 4 | Security lists | block, EDE 17 |
| 5 | Parental: blocked services and categories, then SafeSearch and YouTube restricted mode | block, EDE 17, or rewrite to the safe endpoint |
| 6 | Blocklists (ads, trackers) | block, EDE 17 |
| – | nothing matched | resolved by Unbound |
Consequences worth knowing:
- An allowlisted name skips security checks. Allowlist narrowly.
- An allowlisted name skips parental categories and services, but not SafeSearch or YouTube restricted mode.
- Your own rewrite beats everything but operator blocks, including SafeSearch for that name.
- The public path (no profile) applies step 0 only.
After resolution
Section titled “After resolution”Two checks run on the answer of an allowed query, and can turn it into a block:
- CNAME uncloaking: every name in the answer’s CNAME chain goes through the same policy.
- DNS rebinding protection: a private address in the answer of a public
name blocks it (extra text
rebinding: <address>).
Matching
Section titled “Matching”A rule matches the queried name and its parents: for ads.example.com the
resolver checks ads.example.com, example.com and com. =name matches
exactly, *.name matches children only. List compilers reject bare
top-level domains for that reason. See Rules.