DNS Response Policy Zone (RPZ) is a method to modify or block the DNS requests of end clients. It was developed as a standard to block end users from accessing malicious domains. The RPZ is implemented as an authoritative zone configured in DNS Authoritative Server. The RPZ is transferred into the recursive servers (AXFR/IXFR) which can control the behavior of the DNS responses sent to end customers.
The following guide outlines the setup of PowerDNS Authoritative Server which will be loaded with the RPZ zone. The recursive DNS servers (PowerDNS and BIND) will be configured to load the RPZ from the Primary Auth Server.
PowerDNS Auth Server Installation
Configure the PowerDNS repositories. Create the file ‘/etc/apt/sources.list.d/pdns.list’ and add following content to the file:
deb [arch=amd64] http://repo.powerdns.com/ubuntu focal-auth-46 main
Change the package installation preference to the PowerDNS repository for the pdns packages. Create and add following content in the file /etc/apt/preferences.d/pdns:
Package: pdns-* Pin: origin repo.powerdns.com Pin-Priority: 600
Install the PowerDNS Authoritative server with Sqlite3 backend.
curl https://repo.powerdns.com/FD380FBB-pub.asc | sudo apt-key add - sudo apt-get update sudo apt-get install pdns-server pdns-backend-sqlite3 sqlite3
Create the Database directory for the PowerDNS Sqlite backend. Import the DB schema and set proper File/Directory permissions.
$ sudo mkdir /var/lib/powerdns $ $ sudo sqlite3 /var/lib/powerdns/pdns.sqlite3 < /usr/share/doc/pdns-backend-sqlite3/schema.sqlite3.sql $ $ sudo chown -R pdns:pdns /var/lib/powerdns
Configuration of PowerDNS Auth Server
The configurations need to be done in the configuration file /etc/pdns/pdns.conf. The Primary Authoritative server needs to be defined as Primary in the configuration file. The IPs to which zone transfer is allowed and which IP subnets to send notifications for zone updates needs to be configured.
Auth Server Configuration
################################# # primary Act as a primary # primary=yes ################################# # slave Act as a secondary secondary=no ################################# # allow-axfr-ips Allow zonetransfers only to these subnets # allow-axfr-ips=192.168.10.0/24,192.168.20.0/24 ################################# # daemon Operate as a daemon # daemon=no ################################# # edns-subnet-processing If we should act on EDNS Subnet options # edns-subnet-processing=yes ################################# # guardian Run within a guardian process # guardian=no ################################# # launch Which backends to launch and order to query them in # launch=gsqlite3 gsqlite3-database=/var/lib/powerdns/pdns.sqlite3 ################################# # local-address Local IP addresses to which we bind # local-address=0.0.0.0, :: ################################# # only-notify Only send AXFR NOTIFY to these IP addresses or netmasks # only-notify=192.168.10.0/24,192.168.20.0/24 ################################# # loglevel Amount of logging. Higher is more. Do not set below 3 # loglevel=6 ################################# # lua-health-checks-interval LUA records health checks monitoring interval in seconds # lua-health-checks-interval=20 ################################# # prevent-self-notification Don't send notifications to what we think is ourself # prevent-self-notification=yes ################################# # allow-notify-from Allow AXFR NOTIFY from these IP ranges. If empty, drop all incoming notifies. # allow-notify-from= ################################# # receiver-threads Default number of receiver threads to start # receiver-threads=2 ################################# # reuseport Enable higher performance on compliant kernels by using SO_REUSEPORT allowing each receiver thread to open its own socket # reuseport=yes ################################# # setgid If set, change group id to this gid for more security # setgid=pdns ################################# # setuid If set, change user id to this uid for more security # setuid=pdns ################################# # webserver Start a webserver for monitoring (api=yes also enables the HTTP listener) # webserver=yes webserver-address=0.0.0.0 webserver-allow-from=127.0.0.1,192.168.30.0/27 webserver-password=secure-pass webserver-port=8081 ################################# # consistent-backends Assume individual zones are not divided over backends. Send only ANY lookup operations to the backend to reduce the number of lookups # consistent-backends=yes ################################# # enable-lua-records Process LUA records for all zones (metadata overrides this) # enable-lua-records=yes
Creation of Response Policy Zone
Create two RPZ zones on the Auth server. One zone will be created for domains which should never be blocked. The second RPZ will be used for domain blocking.
Create zone which will be configured for pass-through records.
$ sudo pdnsutil create-zone arpz.domain.com $ sudo pdnsutil set-kind arpz.domain.com primary
Create a zone file which will be imported. The response “rpz-passthru” will make sure the DNS requests passes without any modification.
$ORIGIN arpz.domain.com. @ 3600 SOA ns1.arpz.domain.com. hostmaster.domain.com 10 600 3600 604800 3600 arpz.domain.com. NS ns1.arpz.domain.com. ns1.arpz.domain.com. A 172.16.17.18 good-domain.com CNAME rpz-passthru. *.good-domain.com CNAME rpz-passthru.
Import the zone:
$ sudo pdnsutil load-zone arpz.domain.com arpz.zone
Create second zone which will be used for DNS blocking.
$ sudo pdnsutil create-zone brpz.domain.com $ sudo pdnsutil set-kind brpz.domain.com primary
Create a zone file which will be imported into the blocking zone. The “CNAME .” response will return an NXDOMAIN response for the queried domain name.
$ORIGIN brpz.domain.com. @ 3600 SOA ns1.brpz.domain.com. hostmaster.domain.com 10 600 3600 604800 3600 brpz.domain.com. NS ns1.brpz.domain.com. ns1.brpz.domain.com. A 172.16.17.18 bad-domain.com CNAME . *.bad-domain.com CNAME .
Import the blocking zone
$ sudo pdnsutil load-zone brpz.domain.com brpz.zone
Command Line Zone Modifications
The zone records in PowerDNS can be added or removed using command line.
To add add a record to the a zone:
# Syntax: pdnsutil add-record ZONE name type [ttl] "content" ["content"...] $ sudo pdnsutil add-record brpz.domain.com example.com CNAME "."
To remove a record from zone:
# Syntax: pdnsutil delete-rrset ZONE name type $ sudo pdnsutil delete-rrset brpz.domain.com example.net CNAME
After making changes to zone the serial number needs to be increase so that the secondary servers can pick up the changes:
$ sudo pdnsutil increase-serial brpz.domain.com
PowerDNS Recursor RPZ Configuration
The Response Policy Zones in PowerDNS Recursor are configured using LUA. In the main configuration file /etc/powerdns/recursor.conf make sure you have following:
# lua-config-file More powerful configuration options lua-config-file=/etc/powerdns/recursor.lua
In the LUA file /etc/powerdns/recursor.lua configure the RPZs. The order of the zones matter so we will place the always allow zone to be configured first and then the RPZ for blocked domains.
. . . . . . . . rpzPrimary("172.16.17.18", "arpz.domain.com", {refresh=600, axfrTimeout=60, dumpFile="/var/lib/powerdns/arpz.domain.com", seedFile="/var/lib/powerdns/arpz.domain.com"}) rpzPrimary("172.16.17.18", "brpz.domain.com", {refresh=600, zoneSizeHint=800000, axfrTimeout=60, dumpFile="/var/lib/powerdns/brpz.domain.com", seedFile="/var/lib/powerdns/brpz.domain.com"})
BIND Recursor RPZ Configuration
The Response Policy Zones in Bind are defined in within the options in the named.conf.options file. The order of the zones listed in important.
options { . . . . . . . . //enable response policy zone. response-policy { zone "arpz.domain.com"; zone "brpz.domain.com"; }; }; zone "arpz.domain.com" { type slave; file "db.arpz.domain.com"; masters { 172.16.177.83;}; allow-notify { 172.16.177.83; }; allow-transfer { none; }; allow-query { localhost; }; }; zone "brpz.domain.com" { type slave; file "db.brpz.domain.com"; masters { 172.16.177.83;}; allow-notify { 172.16.177.83; }; allow-transfer { none; }; allow-query { localhost; }; };
References
https://www.dnsrpz.info/
https://doc.powerdns.com/recursor/lua-config/rpz.html
https://bind9.readthedocs.io/en/latest/reference.html?#response-policy-zone-rpz-rewriting