REFUSED (DNS rcode 5) is a deliberate policy decision: BIND received the query, parsed it, and chose not to answer. The server is alive, listening, and processing queries. It is configured to reject this particular query from this particular source.
The actionable scenario: legitimate client subnets that previously resolved names or queried your zones suddenly start receiving REFUSED, typically after a configuration change. The fix is almost always an ACL or view mismatch, not a restart.
Background REFUSED from random Internet hosts hitting a public authoritative server is normal noise. Open-recursion probes, amplification reconnaissance, and scanner traffic generate REFUSED continuously. A public authoritative server with recursion no; correctly returns REFUSED for queries outside its zones. These are not incidents.
What it means
BIND evaluates ACLs early in the query pipeline, before cache lookup or zone lookup. When a query fails an ACL check, BIND returns an empty response with RCODE set to REFUSED. No records, no additional section, no recursion attempted.
Three ACL directives control who gets REFUSED:
allow-querycontrols which sources can send any query at all. If a client fails this check, it gets REFUSED for everything, including zones the server is authoritative for. Default:{ any; }. This is the broadest gate.allow-recursioncontrols which sources can trigger recursive resolution. Default:{ localnets; localhost; }. Clients outside this ACL who send recursive queries get REFUSED instead of resolution.allow-query-cachecontrols which sources can receive answers from the cache. If not explicitly set, it inherits fromallow-recursion. Default whenrecursion no;is set:{ none; }.
Key inheritance rule: allow-query-cache inherits from allow-recursion when not explicitly set. The reverse is not true. If you set allow-recursion { 10.0.0.0/8; }; without setting allow-query-cache, cache access inherits { 10.0.0.0/8; } and both match. But if you set allow-query-cache without allow-recursion, recursion stays at the default { localnets; localhost; } while cache access is restricted. This asymmetry produces unexpected REFUSED from clients that can reach the cache but not recurse, or vice versa.
Views add another layer. If your configuration uses views and a client matches a view that does not contain the requested zone, the response is REFUSED, even if the zone exists in another view. Every zone that needs to be visible to a client must exist in the view that client matches.
REFUSED is also the response when a zone fails to load. If named starts or reloads successfully but a zone file has a syntax error or is missing, that specific zone is not served. Queries to it return REFUSED or SERVFAIL, while all other zones continue working. rndc status shows “running” with no indication of the failure.
Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
allow-query too restrictive | Client gets REFUSED for all queries, including authoritative zones they should see | named-checkconf -p | grep allow-query |
allow-recursion / allow-query-cache mismatch | Client gets REFUSED only for recursive queries; authoritative queries work | Compare both ACLs in the config |
Client outside localnets after network change | Subnet that moved or was re-IP’d suddenly gets REFUSED on recursion | Check localnets value and client source IP |
| View without the requested zone | Client gets REFUSED for a zone that exists in another view | List zones in the matching view |
| Zone failed to load | REFUSED or SERVFAIL for one zone only, after reload | rndc zonestatus <zone> and logs |
recursion no; on a server clients expect to recurse | All recursive queries get REFUSED; authoritative still works | Check whether the server role changed |
Quick checks
# Reproduce the REFUSED from the affected client's perspective
dig +time=2 +tries=1 @<server-ip> example.com A
# Look for: status: REFUSED
# Check the effective ACL configuration (includes defaults)
named-checkconf -p /etc/named.conf | grep -i "allow-query\|allow-recursion\|allow-query-cache\|recursion"
# Check REFUSED counts in the statistics channel
# NOTE: The statistics channel has no default port. It must be explicitly
# configured with 'statistics-channels'. Adjust the port to match your config.
<!-- TODO: verify JSON field names/structure across BIND versions. The JSON
format changed between 9.10, 9.16, and 9.18. These snippets assume a dict-style
layout; some versions return arrays of {name,value} objects. -->
curl -s http://localhost:8653/json/v1/server | \
python3 -c "import sys,json; d=json.load(sys.stdin); \
[print(f'{k}: {v}') for k,v in sorted(d.get('rcodes',{}).items())]"
# Check query rejection counters in nsstats
curl -s http://localhost:8653/json/v1/server | \
python3 -c "import sys,json; d=json.load(sys.stdin); \
[print(f'{k}: {v}') for k,v in d.get('nsstats',{}).items() if 'Rej' in k]"
# Check zone load status for a specific zone
rndc zonestatus example.com
# Check for REFUSED or denied entries in BIND security logs
# Common paths: /var/log/named/security.log (Debian/Ubuntu)
# /var/named/data/named.security.log (RHEL/CentOS)
grep -i "refused\|denied" /var/log/named/security.log | tail -20
How to diagnose it
flowchart TD
A["Client gets REFUSED"] --> B{"Known client subnet?"}
B -- "No" --> C["Normal background noise"]
B -- "Yes" --> D{"Authoritative query also REFUSED?"}
D -- "Yes" --> E["Check allow-query and views"]
D -- "No: recursive only" --> F["Check allow-recursion / allow-query-cache"]
E --> G["Verify zone loaded: rndc zonestatus"]
F --> GConfirm the response code. Run
digfrom the affected client (or simulate its source IP) and verify the status line readsREFUSED. A timeout looks different. SERVFAIL looks different. NXDOMAIN looks different. REFUSED means BIND saw the query and rejected it by policy.Determine the query type. Is the client querying a zone the server is authoritative for, or requesting recursion? If authoritative queries also get REFUSED,
allow-queryor a view mismatch is the culprit. If only recursive queries fail, the problem is inallow-recursionorallow-query-cache.Check the effective ACLs. Run
named-checkconf -pto print the parsed configuration, including defaults. Verify that the affected client’s source IP or subnet appears in the relevant ACL. Pay attention tolocalnets, which is derived from the server’s interface addresses and netmasks. A network re-IP or interface change silently shifts whatlocalnetscovers.Check for view mismatch. If your config uses views, identify which view the client matches based on
match-clientsand confirm the requested zone exists in that view. A zone present in the “external” view but not the “internal” view produces REFUSED for internal clients.Check zone load health. Run
rndc zonestatus <zone>for the affected zone. If the zone is not loaded, check logs for load errors. A zone that failed to load afterrndc reloadproduces REFUSED with no obvious ACL cause.Distinguish from SERVFAIL. REFUSED is a policy rejection. SERVFAIL means BIND tried to process the query but encountered a deeper failure: upstream timeout, DNSSEC validation failure, zone data corruption, recursive client exhaustion. If clients report “DNS is broken” and you see both REFUSED and SERVFAIL, investigate them separately. See BIND SERVFAIL responses for the SERVFAIL diagnostic path.
Correlate with recent changes. REFUSED from legitimate clients almost always follows a configuration change. Check for recent
rndc reloadevents,named.confedits, or network changes that shiftedlocalnets.
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
REFUSED count in rcodes section | Direct measure of REFUSED responses served | Sudden increase above baseline |
AuthQryRej in nsstats | Authoritative queries rejected by ACL | Increase from known client subnets |
RecQryRej in nsstats | Recursive queries rejected by ACL | Increase from known client subnets |
| Per-view resolver REFUSED | Outbound queries refused by upstream | Can cascade into SERVFAIL for clients |
| Zone load status | Zones that fail to load produce REFUSED | Missing zones after reload |
| Config change events | REFUSED spikes correlate with config edits | Temporal proximity to rndc reload |
There is no QryREFUSED counter in nsstats. The REFUSED response code count lives in the top-level rcodes section of the statistics channel. The per-view resolver REFUSED counter tracks outbound recursive queries that received REFUSED from upstream nameservers, which is a different signal entirely. Confusing these two leads to misdiagnosis.
Fixes
allow-query too restrictive
If legitimate clients get REFUSED for all queries including authoritative zones, allow-query is excluding them. Either widen the ACL to include their subnet or verify that allow-query is not inadvertently set to something narrower than intended.
The default is { any; }. Most authoritative servers should leave this at default unless they have a specific reason to restrict query sources.
allow-recursion / allow-query-cache mismatch
If recursive queries fail but authoritative queries work, check both ACLs. Remember the inheritance: allow-query-cache inherits from allow-recursion, not the reverse.
Set both explicitly to the same ACL if you intend them to match. If you set only allow-query-cache, allow-recursion stays at the default { localnets; localhost; }, creating a mismatch where cache access is restricted but recursion is not.
Client outside localnets
If a client subnet that should have recursion access gets REFUSED, check whether the subnet is covered by localnets. The localnets ACL is automatically derived from the server’s network interface configuration. A server that was re-IP’d, moved to a different VLAN, or had interfaces added or removed will have a different localnets scope.
Fix: explicitly list the client subnet in allow-recursion and allow-query-cache rather than relying on localnets alone.
View without zone
If the client matches a view that does not contain the requested zone, add the zone to that view. Every zone that needs to be visible to clients matching a particular view must be declared within that view’s configuration block.
Zone failed to load
Check the BIND logs for zone load errors after the last reload. Validate the zone file with named-checkzone before reloading. If the zone file has a syntax error, fix it and reload that specific zone with rndc reload <zone>.
Always run named-checkconf and named-checkzone before production reloads.
Prevention
- Validate before reload. Run
named-checkconf /etc/named.confandnamed-checkzone <zone> <zonefile>before everyrndc reload. This catches syntax errors, path mismatches, and ACL typos before they affect production. - Verify after reload. After any reload, check
rndc zonestatusfor production zones and scan logs for load failures. - Explicit ACLs over implicit. Do not rely solely on
localnetsfor recursion access. Explicitly list client subnets inallow-recursionandallow-query-cacheso that network changes do not silently lock out clients. - Monitor REFUSED as a ratio. Track REFUSED as a percentage of total responses and alert on sustained increases from known client subnets. Background REFUSED from random Internet sources is expected and should not trigger alerts.
- Use canary probes. Deploy synthetic queries from known-authorized source IPs that exercise both authoritative and recursive paths. A REFUSED from a canary probe is an unambiguous signal of an ACL or view regression.
How Netdata helps
- Per-second RCODE distribution including REFUSED lets you pinpoint the exact moment a spike begins and correlate it with config change timestamps or deployment events.
- Query rejection counters (
AuthQryRej,RecQryRej) are collected from the statistics channel and trended, making it visible when rejections shift from background noise to a legitimate-client problem. - Per-view resolver statistics including outbound REFUSED are collected separately from inbound rcodes, helping distinguish “my clients are locked out” from “my upstream is refusing me.”
- Zone load health correlation with REFUSED spikes after reload events helps identify the “zone didn’t load” failure pattern without manual log diving.
- ML anomaly detection on REFUSED rates learns the normal background noise level for your authoritative servers and surfaces deviations that represent real ACL regressions.






