DNS Firewall or Bind9 Response Policy Zones (RPZ)

Using piHole for a while at home, i feeld that i wanted to bring things back to my already running bind9 name servers.
Please do not misunderstand me PiHole is really a great solution.

Bind has the option to build up a DNS Firewall.

  1. Enable the RPZ Zone
  2. load the zone file
  3. the zone file
  4. Build a tool chain to support Open Block Lists
  5. Links

Enable the RPZ Zone

options {...}
//enable response policy zone. 
response-policy { 
  zone "rpz.local"; 
};

more policies (Spamhaus)

load the zone file

include "/var/named/etc/zones/rpz.local";
zone "rpz.local" { 
  type master; 
  file "/var/named/etc/db/rpz.local"; 
  allow-transfer {none; };
  allow-query (localhost; };
};

The reason for allow-query being set to localhost is so only the resolver will be able to access the zones defined.

the zone file

$TTL 300

@               IN SOA  localhost. need.to.know.only. (
                       201702121 ; Serial number
                       60        ; Refresh every minute
                       60        ; Retry every minute
                       432000    ; Expire in 5 days
                       60 )      ; negative caching ttl 1 minute
                IN NS   LOCALHOST.

deteque.com                     IN CNAME rpz-passthru.
*.deteque.com                   IN CNAME rpz-passthru.
spamhaus.org                    IN CNAME rpz-passthru.
*.spamhaus.org                  IN CNAME rpz-passthru.
32.25.195.194.32.rpz-ip         IN CNAME rpz-passthru.          ; whitelist 34.194.195.25/32
32.71.219.156.35.rpz-ip         IN CNAME rpz-passthru.          ; whitelist 35.156.219.71/32

example.com                     IN CNAME .                      ; local block against example.com
*.example.com                   IN CNAME .                      ; local block against example.com

Build a tool chain to support Open Block Lists

Thanks to circuitshelter for writing Using BIND 9 RPZ as DNS firewall

Source from circuitshelter

#!/usr/bin/env python3

from urllib import request
    
rpz_file         = 'rpz-filter.db'
hosts_file_url   = 'https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts'

comment_char  = '#'
local         = ('127.0.0.1', '255.255.255.255', '::1', 'f')
default_route = '0.0.0.0'

zone_header = """$TTL 2w
@ IN SOA localhost. root.localhost. (
       2   ; serial 
       2w  ; refresh 
       2w  ; retry 
       2w  ; expiry 
       2w) ; minimum 
    IN NS localhost.

"""

def generate_rpz_file():
    hosts = 0
    file = open(rpz_file, 'w')
    file.write(zone_header)

    with request.urlopen(hosts_file_url) as f:
        for bytes in f:
            line = bytes.decode('utf-8').strip()
            if (not line or line.startswith(comment_char) or line.startswith(local)):
                continue

            domain = line[8:].split(' ')[0]
            
            if domain == default_route:
                continue

            file.write(f'{domain} CNAME .\n')
            file.write(f'*.{domain} CNAME .\n')
            hosts += 1

    file.close()
    print(f'Total hosts in filter: {hosts}')

if __name__ == '__main__':
    generate_rpz_file()

https://www.shellandco.net/import-dns-zone-file-bind-python/

Photo by Taylor Vick on Unsplash