esc
move open

Access control and blocking

Who may query, how fast, and which names never resolve.

Who may query

accesslist = ["127.0.0.1/32", "::1/128", "192.168.0.0/16"]

CIDR ranges allowed to query this resolver. Queries from anywhere else are refused before any resolution work happens — the access list runs near the front of the middleware chain, ahead of the cache and the resolver.

The shipped default is ["0.0.0.0/0", "::0/0"], which allows everyone. That is right for a resolver on loopback and wrong for one on a public address. An open recursive resolver on the internet will be found and used for reflection attacks, so narrow this before you bind to a reachable address.

Watch dns_accesslist_denied_total to see whether anything is being refused.

Rate limits

ratelimit       = 0     # queries per second, whole server; 0 disables
clientratelimit = 0     # queries per minute, per client IP; 0 disables

Both are off by default. clientratelimit is the more useful of the two on a resolver serving known clients — it contains one misbehaving host without capping the server. ratelimit is a blunt ceiling on everything.

Refusals increment dns_ratelimit_exceeded_total.

Reflection and amplification defence

reflexenabled      = false
reflexblockmode    = true
reflexlearningmode = false
# reflexthreshold  = 0.7

Tracks per-IP behaviour to identify spoofed sources being used for reflection. Off by default.

The two modes matter. With reflexlearningmode = true detections are logged and nothing is blocked, which is how you calibrate the threshold against your own traffic. reflexblockmode = false also only logs. Turn on blocking after you have watched the detections for a while and are satisfied they are not your own clients — the threshold is a score between 0 and 1, and lower is more aggressive.

Blocking names

blocklists = [
    "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts",
]
blocklist  = ["ads.example.com"]
whitelist  = ["important.example.com"]
nullroute   = "0.0.0.0"
nullroutev6 = "::0"

blocklists are URLs downloaded and refreshed periodically; blocklist is a manual list in the configuration file; whitelist bypasses all blocking and wins over both. A blocked A query answers nullroute and a blocked AAAA answers nullroutev6.

Entries can also be managed at runtime through the API without a restart:

curl http://127.0.0.1:8080/api/v1/block/set/ads.example.com
curl http://127.0.0.1:8080/api/v1/block/exists/ads.example.com
curl http://127.0.0.1:8080/api/v1/block/remove/ads.example.com

For policy that goes beyond a name list — rewriting to a CNAME, matching on the client’s address or on the address in the answer, vendor feeds over AXFR, or a shadow mode that counts what enforcement would do — use Response Policy Zones instead. RPZ runs after the blocklist in the chain and is the richer of the two.

blocklistdir is deprecated; the directory is created under directory automatically.

Local answers from a hosts file

hostsfile = "/etc/hosts"

Serves entries from a hosts file directly. Empty disables it. For answers scoped to particular client networks rather than served to everyone, use views.

Per-domain metrics

domainmetrics      = false
domainmetricslimit = 1000

Tracks query counts per domain, exported as dns_domain_queries_total. Off by default because the cardinality is unbounded on a public resolver — that is what the limit is for. 0 means unlimited, which on a busy resolver will consume memory until something gives.