Resolver Policy
The fields that decide which names your account answers, which it refuses, and who is allowed to ask.
Resolver Policy Documentation
One policy per account. It applies to every agent and every device on the account, so there is no per-agent copy to keep in step. Read the current policy back by passing no arguments:
whisper policy
CALL whisper.agents({op: 'policy', args: {}})
The read returns key and value rows. Only the fields you send on a write are changed;
anything you leave out keeps the value it had.
default
allow or deny. It decides what happens to a name that neither the graph nor your own
lists have an opinion about. deny turns the resolver into an allow-list for the names the
graph has not judged.
whisper policy --default deny
block
Domain names, and nothing else. An entry covers the domain and every name under it, so
evil.example already covers a.evil.example. The *.evil.example spelling is accepted
and means the same rule.
whisper policy --block ads.example.com --block telemetry.example.net
Categories and geography are not list entries. An entry of tor-exit here blocks a domain
literally named tor-exit and nothing more. Those rules live in bundles, below.
allow
Same shape as block, and an explicit allow wins over a block. It cannot reopen a name the
graph places in a top band: policy narrows a verdict and never widens it, as
How Resolution Works sets out.
whisper policy --allow api.example.com
mode
How names are resolved once the verdict is in.
| Value | Behaviour |
|---|---|
hybrid | Ask the graph, then fall through to ordinary recursive resolution for anything it has no opinion on. |
graph-only | Answer from the graph alone, and return REFUSED with extended DNS error 17 when it has nothing. |
always-forward | Forward the lookup to ordinary recursive resolution. |
whisper policy --mode hybrid
allow_sources
Which source addresses or prefixes may use your account's dedicated resolver address on port 53. With no list, any source may. A source that is not on the list gets the same answer an address with no account would get, so adding the list is a narrowing change and worth testing from one of your own hosts first. There is no CLI flag; send it on the call.
CALL whisper.agents({op: 'policy', args: {allow_sources: ['203.0.113.0/24', '2001:db8:1::/48']}})
retention
How long ordinary query logs are kept for the account, in days. Set it when you mint an agent or a device, or change it later here.
whisper policy --retention <days>
bundles
Category and geography rules travel in their own argument, with a fixed catalogue. The CLI has no flag for them, so they are set on the control-plane call.
| Bundle | What it covers |
|---|---|
block:tor-exits | names that resolve to anonymising exit infrastructure |
block:bulletproof | names hosted in networks that will not act on abuse |
block:rpki-invalid | names whose addresses are routed with an invalid origin authorisation |
block:sanctions | names associated with sanctioned parties |
block:newly-registered | names registered very recently |
geo:deny:<CC>,<CC> | names resolving into the listed countries |
geo:allow:<CC>,<CC> | names resolving only into the listed countries |
A deny wins over an allow when both could apply.
CALL whisper.agents({op: 'policy', args: {bundles: ['block:tor-exits', 'block:sanctions', 'geo:allow:NL,DE']}})
Writing it in one call
Everything above can go on a single write, which is the form to put in a deployment script:
CALL whisper.agents({op: 'policy', args: {default: 'deny', block: ['ads.example.com'], allow: ['api.example.com'], mode: 'hybrid'}})
The envelope this returns, and the key that is allowed to send it, are on Set Policy and Keys and Scopes.