DNS RPZ with PowerDNS

Domain Name Service Response Policy Zones

from PowerDNS Recursor documentation :

Response Policy Zone is an open standard developed by Paul Vixie (ISC and Farsight) and Vernon Schryver (Rhyolite), to modify DNS responses based on a policy loaded via a zonefile.

Sometimes it is called: DNS Firewall

Reading Material

aka useful links:


An example scheme to get a a better understanding on the concept behind RPZ.



The main purposes of implentanting DNS RPZ in your DNS Infrastructure are to dynamicaly DNS sinkhole:

  • Malicious domains,
  • Implement goverment regulations,
  • Prevent users to visit domains that are blocked via legal reasons.

by maintaining a single RPZ zone (or many) or even getting a subscription from another cloud provider.

Althouth for SOHO enviroments I suggest reading this blog post: Removing Ads with your PowerDNS Resolver and customize it to your needs.

RPZ Policies

These are the RPZ Policies we can use with PowerDNS.

  • Policy.Custom (default policy)
  • Policy.Drop
  • Policy.NXDOMAIN
  • Policy.NODATA
  • Policy.Truncate
  • Policy.NoAction


Will return a NoError, CNAME answer with the value specified with
defcontent, when looking up the result of this CNAME, RPZ is not taken into account

Use Case

Modify the DNS responces with a list of domains to a specific sinkhole dns record.


  thisismytestdomain.com.org ---> sinkhole.example.net.
*.thisismytestdomain.com.org ---> sinkhole.example.net.
  example.org                ---> sinkhole.example.net.
*.example.org                ---> sinkhole.example.net.
  example.net                ---> sinkhole.example.net.
*.example.net                ---> sinkhole.example.net.

DNS sinkhole record

Create an explicit record outside of the DNS RPZ scheme.

A type A Resource Record to a domain zone that points to is okay, or use an explicit host file that the resolver can read. In the PowerDNS Recursor the configuration for this, are these two lines:



$ echo " sinkhole.example.net" >> /etc/pdns-recursor/hosts.blocked

and reload the service.


RPZ functionality is set by reading a bind dns zone file, so create a simple file:


; Time To Live
$TTL 86400

; Start Of Authorite
@       IN  SOA authns.localhost. hostmaster. 2018042901 14400 7200 1209600 86400

; Declare Name Server
@                    IN  NS      authns.localhost.


RPZ support configuration is done via our Lua configuration mechanism

In the pdns-recursor configuration file: /etc/pdns-recursor/recursor.conf we need to declare a lua configuration file:


Lua-RPZ Configuration file

that points to the rpz.zone file. In this example, we will use Policy.Custom to send every DNS query to our default content: sinkhole.example.net


rpzFile("/etc/pdns-recursor/rpz.zone", {defpol=Policy.Custom, defcontent="sinkhole.example.net."})

Restart PowerDNS Recursor

At this moment, restart the powerdns recusor

# systemctl restart pdns-recursor


# service pdns-recursor restart

and watch for any error log.

Domains to sinkhole

Append to the rpz.zone all the domains you need to sinkhole. The defcontent="sinkhole.example.net." will ignore the content of the zone, but records must be valid, or else pdns-recursor will not read the rpz bind zone file.

; Time To Live
$TTL 86400

; Start Of Authorite
@   IN  SOA authns.localhost. hostmaster. 2018042901 14400 7200 1209600 86400

; Declare Name Server
@                    IN  NS      authns.localhost.

; Domains to sinkhole
thisisatestdomain.org.  IN  CNAME    sinkhole.example.net.
thisisatestdomain.org.  IN  CNAME    sinkhole.example.net.
example.org.            IN  CNAME    sinkhole.example.net.
*.example.org.          IN  CNAME    sinkhole.example.net.
example.net.            IN  CNAME    sinkhole.example.net.
*.example.net.          IN  CNAME    sinkhole.example.net.

When finished, you can reload the lua configuration file that read the rpz.zone file, without restarting the powerdns recursor.

# rec_control reload-lua-config

Verify with dig

testing the dns results with dig:

$ dig example.net.

;example.net.           IN  A

example.net.        86400   IN  CNAME   sinkhole.example.net.
sinkhole.example.net.   86261   IN  A

$ dig thisisatestdomain.org

;thisisatestdomain.org.     IN  A

thisisatestdomain.org.  86400   IN  CNAME   sinkhole.example.net.
sinkhole.example.net.   86229   IN  A


test the wildcard record in rpz.zone:

$ dig example.example.net.

;example.example.net.       IN  A

example.example.net.    86400   IN  CNAME   sinkhole.example.net.
sinkhole.example.net.   86400   IN  A

Tag(s): dns, rpz, PowerDNS
PowerDNS Remote Backend

One of the great features that PowerDNS has, is the concepts of ‘backends’.

Backends give you the ability to choose the datastore you would like to save (or not) your dns data. If you are looking to migrate from another dns server (lets say bind ics) with bind zone files support, then you can choose the bind backend, copy the files and voila !

PowerDNS can also support multiple backends. So you can build/test your “new” infrastructure without compromise any existing data structure or as the consultants love to say: “With no-downtime!” Another approach is that you can add support for provisioning automate mechanism or whatever else you can think of !

A very good example of Pipe Backend is the PowerDNS Dynamic Reverse script that @kargig has modified to support reverse ipv6 responses (amazing, right ?).

I have a few (half–baked) ideas that I would like to implement with PowerDNS and I was looking on Remote Backend. It took me some time to understand the logic behind this (as I am not a developer, nor I will ever be!) and create a proof of concept script.

So this is my initial script, that I would like to share:
pdns remote - pipe

It doesnt do anything (yet), just sends everything to your syslog (/var/log/messages) for debugging.

The key to success is this quote:

You must always reply with JSON hash with at least one key, ‘result’

Tag(s): PowerDNS
Removing Ads with your PowerDNS Resolver

In my previous post , I documented my notes on setting up a new PowerDNS Recursor for our own clients.

In this post, I will present a simple way to reduce unnecessary traffic by blocking every FQDN you dont want.



Download a well known custom HOSTS file:

# curl -s -L http://winhelp2002.mvps.org/hosts.txt -o /etc/pdns-recursor/hosts.blocked

Add your FQDNs you want to block,

# echo " facebook.com" >> /etc/pdns-recursor/hosts.blocked

be very careful not to block something you need.
Reminder: No support for wildcards, only FQDNs


Edit your /etc/pdns-recursor/recursor.conf to support the new hosts file:


restart your pdns and test it

# dig www.facebook.com @localhost

www.facebook.com.   86400   IN  A

Once you have done that, you can edit your hosts.blocked when ever you want!
But dont forget to reload:

# rec_control reload-zones

Tag(s): PowerDNS
Build your own DNS Recursor with PowerDNS in five minutes

First rule of DNS: Always keep in separted machines your authoritative and recursor DNS server.

Disclaimer: The below notes are made on a fresh centos7 server. This is not an openresolver, is just for personal use. You need to adjust your settings.



PowerDNS is an amazing product. Has two flavors, one for Authoritative NS and one for Recursor. I always use @KeesMonshouwer RPMs for two reasons:

a. Works perfectly
b. I trust his work


  • Installation

    Let’s start, by installing the pdns-recursor:

    # rpm -ivh https://www.monshouwer.eu/download/3rd_party/pdns-recursor/el7/x86_64/pdns-recursor-3.7.2-1.el7.MIND.x86_64.rpm
  • User/Group

    Verify that you have the pdns User/Group, if not create them:

    # grep pdns /etc/group
    # grep pdns /etc/passwd
    pdns-recursor:x:996:996:PowerDNS Recursor:/dev/null:/sbin/nologin
  • root hint

    Create the hint (root NS) zone:

    # dig NS . @a.root-servers.net. | grep -vE '^;|^$'  | sort -V > /etc/pdns-recursor/root.hint

    I prefer to use and work with the opennicproject cause it’s an amazing community open DNS project. They also provide their own gTLDs and the majority of them dont have any logs at all or they anonymize the dns logs. In the times we are living, I prefer my DNS queries NOT to be obtained and recorded by companies.

    I strongly suggest to participate to this amazing community project.

    So my root.hint file is the result of this:

    # dig . NS @ | grep -v '^;' | sort -u -V  > /etc/pdns-recursor/root.hint

    Dont forget to edit your /etc/pdns-recursor/recursor.conf so that you tell pdns where is your root hint file:

  • ACL

    As i mentioned above, I dont want (at the current moment) to create an openresolver. So I need to create an ACL.

    That can be done by two ways (combined or separated).

  • iptables

    The first one is via iptables. My iptables default policy is DROP, so I need to ACCEPT tcp/udp traffic from the networks I want to provide dns recursion. The below example are for a specific IP and a class C (/24) network

    # TCP
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 53 -s XXX.XXX.XXX.XXX -j ACCEPT
    -A INPUT -p tcp -m state --state NEW -m tcp --dport 53 -s YYY.YYY.YYY.0/24 -j ACCEPT
    # UDP
    -A INPUT -p udp -m state --state NEW -m udp --dport 53 -s XXX.XXX.XXX.XXX -j ACCEPT
    -A INPUT -p udp -m state --state NEW -m udp --dport 53 -s YYY.YYY.YYY.0/24 -j ACCEPT

    Dont forget to restart your iptable service.

  • ACL in pdns

    The second way is by configure the allow-from pdns setting accordingly:

    # vim /etc/pdns-recursor/recursor.conf
    allow-from=, XXX.XXX.XXX.XXX, YYY.YYY.YYY.0/24
  • Listen IP address

    PowerDNS Recursor will start on your local IP address. To change it to your public IP, you need to edit the below entry:

    # vim /etc/pdns-recursor/recursor.conf
    local-address=, XXX.XXX.XXX.XXX

    At this point you are ready to start and use your own DNS recursor.

    # systemctl status pdns-recursor.service
    # systemctl enable pdns-recursor.service
  • Testing

    Before you exit your machine, you need to test your DNS server.

    # dig soa powerdns.com @

    and from a machine inside your ACL:

    # dig soa powerdns.com @XXX.XXX.XXX.XXX

    Everything must work just fine.