Soon to be released, PowerDNS Recursor 4.0.0 includes a lot of exciting features. We have already blogged about some of them, but apart from a post on our mailing-list, the new Response Policy Zone support has not received much love.
Response Policy Zone
First of all, what is RPZ? It’s a way to provide policies to a recursive name server, allowing the use of large, quickly changing data feeds to provide custom responses to queries. RPZ data is supplied as a DNS zone, and can be loaded from a file or retrieved over the network by AXFR/IXFR.
While RPZ was first implemented by the ISC BIND name server, it’s an open and vendor neutral mechanism. You can read more about it on dnsrpz.info.
Why use RPZ?
The most common use case of RPZ is to implement security measures based on a reputation feed provided by another party, such as:
- protect customers from accessing known malware-infected hosts
- prevent known spam sources from reaching your infrastructure
RPZ feeds
While some users are building their own RPZ feed using internal data, the greatest strength of RPZ is the capacity to use an external feed. Several providers are already offering interesting feeds, for example:
- Farsight
- Spamhaus
- ThreatSTOP
Setting it up in Recursor 4.0.0
PowerDNS Recursor has the capability to get RPZ data from two sources:
- a local file
- a remote server, using IXFR
While the first option is great for mostly static data and testing purposes, the second one is particularly suited for large and rapidly changing feeds.
RPZ support configuration is done via our Lua configuration mechanism, and as such requires a Recursor compiled with Lua support.
First, let’s set up a very basic RPZ zone in a local file, basic.rpz:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$TTL 2h; | |
$ORIGIN domain.example.com. | |
@ SOA powerdns.example.net. hostmaster.example.com ( 1 12h 15m 3w 2h) | |
NS powerdns.example.net. | |
; begin RPZ RR definitions | |
example.net A 192.168.2.5 | |
*.example.net A 192.168.2.5 |
This file declares a simple zone, and instructs PowerDNS to respond to queries for example.net with the address 192.168.2.5. To be valid, the zone needs to have a SOA record and at least one NS one at its apex. A more complex example can be found here.
We now need to setup a Lua configuration file for PowerDNS, using the lua-config-file
setting:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
lua-config-file=/etc/powerdns/recursorconf.lua |
Finally, in the Lua configuration file, we use the rpzFile() directive to load the RPZ zone:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rpzFile("basic.rpz", {}) |
As soon as the Recursor is started with this configuration, we can check whether it has been correctly loaded:
Loading RPZ from file ‘/etc/powerdns/basic.rpz’
Done loading RPZ from file ‘/etc/powerdns/basic.rpz’
Everything is fine. As expected, a query for http://www.example.net returns 192.168.2.5:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ dig http://www.example.net @::1 +short | |
192.168.2.5 |
It’s time to try a setup a bit more complicated. To retrieve a RPZ zone rpz.example.net from a remote provider at 192.0.2.1 via IXFR, we would instead use:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rpzMaster("192.0.2.1", "rpz.example.net", {policyName="example"}) |
The additional parameter policyName has no impact on the response the Recursor will send, but it sets the appliedPolicy of the protobuf message it will output, if configured to. This allows keeping track of the queries that have been modified because of a RPZ policy, for example to be able to detect and act on infected hosts.
This time, the Recursor is a bit more verbose on startup:
Loading RPZ zone ‘rpz.example.net.’ from 192.0.2.1:53
Loaded & indexed 375 policy records so far
Done: 375 policy records active, SOA: need.to.know.only. hostmaster.example.net. 1467033991 60 60 432000 60
We will also be able to check later that IXFR updates are correctly received:
Getting IXFR deltas for rpz.example.net. from 192.0.2.1:53, our serial: 1467033991
Processing 1 delta for RPZ rpz.example.net.
Had 23 RPZ removals, 1 addition for rpz.example.net. New serial: 1467034591
That’s it, we are all set!
Digging deeper
We only covered so far the very basic possibilities offered by RPZ. In addition to altering the response, PowerDNS Recursor 4.0.0 is capable of the following actions:
- Forcing the query to TCP by sending a response with TC set
- Sending a NOData response
- Sending a NXDomain response
- Sending a custom CNAME
- Silently dropping the query
It also supports defining a default policy that will use the data found in the RPZ zone, but will override the action, making it possible to use a feed from a provider while customizing the recursor’s behavior.
The rpzMaster example above did not use TSIG to authenticate the server, but of course PowerDNS Recursor 4.0.0 supports that too.
The corresponding documentation can be found in the Response Policy Zone (RPZ) part of our documentation.