A test request is a real request

“I tested it and it worked” is one of the most reliable sentences in operations, and one of the least informative. A filtering resolver has no simulation layer: the query you send is a query, the answer is a policy decision, and whether it is the one your users get depends on who you were when you asked.

There is no test mode

A filtering resolver has exactly one execution path. A request to allow a name — here, a client proposing a whitelist entry from the portal — proceeds down it as production traffic would: the submission becomes a pull request on nix-config-private appending one line to modules/adguard/allowlist.txt, that line reaches main, the deploy renders it into the resolvers, and the request mails the address on record.

The review procedure for those PRs says it in one line: the submit path has no test mode — whatever you submit becomes a PR, reaches the fleet policy on main, is deployed, and mails the address on the request. Hence the reserved host, whitelist-test.ymrtech.com, already in the allowlist, instead of a name you would refuse.

An exemption hides the policy from the tester

A filtering resolver applies policy per client. That is a feature: the tier a device runs on decides which lists answer it. It is also the trap. If the client you test from is exempt from the rule you are testing — a different tier, an allowlisted source, a bypass the operator added — your test cannot observe the rule at all. It observes the exemption.

This is not specific to DNS. Any test performed by an actor privileged relative to the production path is evidence about the test, not about production. The operator’s own machine is the classic privileged actor: it sits on a different resolver address, may carry settings no customer has, and is the client an ad-adjacent domain is most likely to have been allowlisted for by hand.

So “the client told me it is broken, I checked and it works” usually means you asked from a position where the answer is different.

The cache is a third party

A resolver cache serves whatever it already holds, and those entries outlive the change you are verifying. This fleet’s loopback resolvers carry cache-min-ttl = 60. AdGuard Home also rewrites its own config in place and reloads its filter lists from the URL declared in the policy file before it serves them, so a retry loop against a resolver mid-reload produces a spurious empty answer that reads as “blocked”.

A name that fails right after a policy change may be failing from cache; a name that resolves may be resolving from cache from before the policy existed. Either way you measured a cache, or an exemption, and called it the policy.

How this class of request should be reviewed

An allowlist entry is a lasting, reviewable change to a security control, so it deserves the scrutiny any policy edit gets. The procedure attached to these PRs asks four things:

The rule underneath all four: a request is a policy proposal, judged on the host and the reason, never on the fact that someone tested it and it worked.

What you can check

How to tell whether your own test request was privileged — three questions, where any “yes” invalidates the result:

  1. Which client did you ask from? If it was not the device whose experience you care about — a laptop in the same tier, a phone on the same resolver — you tested a neighbour. Ask from the failing client.
  2. Which resolver answered? Print the address your client actually queries. A machine pointed at the operator’s resolver is a different question from a client on the tier in question.
  3. Was caching in play? Ask for a name that cannot already be in any cache, and re-run after the policy settles rather than while the resolver is still loading rules.

Then record the response code: “blocked” and “not found” are different failures, and only a recorded code keeps them apart later. This is the same discipline as the audit page: a check that runs from the client’s position and publishes its own result beats any number of successful probes from somewhere convenient.

For a related case of the same mistake — a green status that measured the test harness — see the green deploy that deployed nothing.

󰔟 Running the same kind of stack?
The tunnel this site is written from is the one I sell: WireGuard to a gateway in Montréal, three DNS postures, one price — and the same "check it yourself" habit as everything above.
[ CREATE ACCOUNT ] [ WHAT IS THE VPN ]
󰣨 ymrtech@ymrtech | 󰌠 NixOS | 󰍢 UTF-8