← Back to Learning Hub

DNS • Intermediate • 5 min read

RPZ Response Policy Zones: The DNS Firewall Explained

RPZ turns a recursive resolver into a DNS firewall. Learn the QNAME, IP, and NSDNAME triggers, actions such as NXDOMAIN and PASSTHRU, and writing policy zones.

Response Policy Zones (RPZ) turn a recursive DNS resolver into a programmable filter, often called a DNS firewall. Instead of faithfully returning whatever an authoritative server says, a resolver with RPZ checks each query and answer against a set of policy rules and can rewrite, block, or pass it through. RPZ was introduced by Paul Vixie and Vernon Schryver and is implemented in BIND, Unbound, Knot Resolver, PowerDNS, and commercial platforms. It is the mechanism behind most malware-blocking and content-filtering DNS services. This guide explains the trigger types, the available actions, how precedence works, and how to author and load a policy zone.

Why filter at the resolver

DNS is the first step of almost every connection, which makes the resolver an efficient and low-cost place to stop bad traffic. If a device never resolves the name of a command-and-control server or a phishing host, it never connects to it. RPZ lets you subscribe to threat-intelligence feeds (distributed as ordinary zones) and apply them without touching endpoints or the network firewall. Because policy is expressed as a normal DNS zone, it can be transferred and updated with the same AXFR/IXFR machinery you already run.

Triggers: what a rule matches on

An RPZ rule fires when some part of the query or its resolution matches a trigger. Each trigger type uses a naming convention inside the policy zone so the resolver knows what to compare against.

TriggerMatches onExample owner name in the policy zone
QNAMEThe name being queriedevil.example.com.rpz.example.
IP (response)An address in the answer RDATA32.10.0.113.203.rpz-ip.rpz.example.
NSDNAMEThe name of an authoritative nameserver usedns.badhost.net.rpz-nsdname.rpz.example.
NSIPThe IP of an authoritative nameserver used32.5.0.0.198.rpz-nsip.rpz.example.
CLIENT-IPThe IP of the client asking32.50.0.2.192.rpz-client-ip.rpz.example.

QNAME is by far the most common: block a domain and, with a wildcard, all of its subdomains. The IP trigger is powerful for catching hosts that keep changing domain names but reuse address space, and the NSDNAME and NSIP triggers let you take out an entire malicious nameserver and everything it serves in one rule.

Actions: what happens on a match

The action a rule takes is encoded in the records it holds inside the policy zone. The main actions are:

  • NXDOMAIN: answer as if the name does not exist. Encoded with a CNAME to the root (CNAME .).
  • NODATA: answer that the name exists but has no records of that type. Encoded with a CNAME to the wildcard (CNAME *.).
  • Local data (redirect): return a substitute answer, for example point a blocked site at a walled-garden warning page.
  • PASSTHRU: explicitly allow, creating an exception that stops any other policy from applying. This is how you whitelist.
  • DROP: silently discard the query so the client simply times out.
  • TCP-only: force the client to retry over TCP, useful against spoofed UDP floods.

Precedence when rules overlap

Within a single policy zone, trigger types are evaluated in a fixed order so results are predictable: QNAME is preferred over IP, IP over NSDNAME, and NSDNAME over NSIP. When you load more than one policy zone, they are consulted in the order listed in the configuration, and the first zone to produce a non-PASSTHRU action wins. Put your allow-list (PASSTHRU) zone first so an explicit exception can override a later block.

Writing a policy zone

A policy zone is just a zone file with an SOA, NS, and the policy records. Here is a small example that blocks a domain, returns NODATA for another, redirects a third to a warning host, and whitelists a partner that would otherwise be caught by a feed:

$TTL 60
@   IN  SOA  localhost. admin.rpz.example. (
            2026101401  ; serial
            3600        ; refresh
            600         ; retry
            86400       ; expire
            60 )        ; negative TTL
    IN  NS   localhost.

; QNAME -> NXDOMAIN (domain and all subdomains)
malware-c2.example          CNAME   .
*.malware-c2.example        CNAME   .

; QNAME -> NODATA
tracker.ads.example         CNAME   *.

; QNAME -> local data redirect to a warning page
phishing-login.example      A       192.0.2.200

; PASSTHRU exception (allow this one even if a feed lists it)
partner-cdn.example         CNAME   rpz-passthru.

; IP trigger: block any answer pointing at 203.0.113.66
32.66.0.113.203.rpz-ip      CNAME   .

Then tell the resolver to use it. In BIND, reference the zone in the response-policy statement and define it like any secondary or local zone:

// named.conf
options {
    response-policy {
        zone "allow.rpz.example";    // whitelist first, highest priority
        zone "rpz.example";          // block/redirect rules
    } qname-wait-recurse no
      break-dnssec no;
};

zone "rpz.example" {
    type primary;
    file "/etc/bind/db.rpz.example";
};

Most real deployments do not hand-edit these. They subscribe to a threat feed published as an RPZ zone and transfer it continuously with IXFR, so new malicious domains appear in the policy within seconds of the feed updating.

Testing and observing RPZ

After loading a policy, confirm a blocked name returns your chosen action and a passthru name resolves normally:

# Blocked via NXDOMAIN
dig @127.0.0.1 malware-c2.example A
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 18822

# Redirected via local data
dig @127.0.0.1 phishing-login.example A +short
192.0.2.200

# Whitelisted despite appearing in a feed
dig @127.0.0.1 partner-cdn.example A +short
203.0.113.9

BIND logs each policy hit in the rpz logging category, which is how you audit what the firewall is actually blocking and catch false positives quickly.

Operational cautions

ConcernGuidance
DNSSECRewriting an answer breaks its signature; validating clients may see failures unless you set break-dnssec deliberately and understand the tradeoff.
False positivesKeep a fast path to add PASSTHRU exceptions; a bad feed entry can block a critical service.
PerformanceNSIP and NSDNAME triggers require tracking delegations and cost more than QNAME; use them judiciously.
TransparencyDROP causes confusing timeouts; redirect to a warning page when users need to understand why a site is blocked.

RPZ is a precise, auditable way to apply security and policy at the exact layer every connection depends on. If you run a resolver with RPZ, verify that the names you intend to allow still resolve correctly from multiple networks using the Valla DNS propagation checker, and browse the Valla DNS learning hub for companion guides on zone transfers, DNSSEC, and TTL strategy that all interact with how your policy zones load and behave.

Troubleshooting box

If results look inconsistent, compare authoritative nameservers first, then recursive resolvers by region. Capture snapshots every 10 minutes for deterministic incident timelines.

Try VallaDNS free →