DNS Firewalling with BIND: Performance of Approaches
Part 1: an Anti-Guide
I once received an email from a hosting provider telling me that my DNS server was participating in an amplification attack. BIND is a tricky piece of software which can be configured to cause problems. My server was resolving queries without the necessary safeguards to do so publically, to a global network. I recently decided to self-host a BIND instance again. A simple instance which will
- Resolve lookups for clients on internal private networks
- Block ads, malware or any unwanted domains
Solving the right problem the wrong way
It's tempting to escape the complexity of ISC's documentation by looking at finished solutions. There are numerous guides and automation scripts found online aimed at implementing a DNS firewall with BIND and everyone is different.
After introducing some basics, I'll outline two approaches that accomplish DNS firewalling.
- Using DNS spoofing – similar to hosts blocking – by defining multiple zones.
- Later: using a Request Policy Zone (RPZ), a security feature designed with access-control in mind.
The first method is more frequent in earlier and dated documents. In BIND's 35 year history, RPZ is a "recent" feature so it makes sense that earlier approaches are there to find. Note that this isn't an exhaustive list by any means.
Primer
Let's walk through a few points about BIND and the structure used to manipulate domains. The basics are always there, informing us how we might solve a higher level problems.
etc
└── bind
├── bind.keys
├── db.0 # zone file
├── db.127 # zone file
├── db.255 # zone file
├── db.empty # zone file
├── db.local # zone file
├── named.conf # configuration
├── named.conf.default-zones # configuration
├── named.conf.local # configuration
├── named.conf.options # configuration
├── rndc.key
└── zones.rfc1918
Zone files
BIND uses zone files to define DNS Resource Records (RR). An RR describe how a domain should resolve to some resource. A zone file can state what IP address will be returned when asking for imdb.com or peach.cool.
$TTL 60
@ IN SOA localhost. hostmaster.localhost. (
4 ; serial
3H ; refresh
1H ; retry
1W ; expiry
1H) ; minimum
IN NS localhost.
@ IN A 10.100.100.198
* IN A 10.100.100.198
This zone file which will resolve any domain @ and subdomains * to the addresses shown in the A record.
Zone statement
For a domain to point to the records in db.custom
we create a zone in BIND's settings. The zone include it's configuration and location of the zone file. Most importantly, the name of the zone will be interpreted by BIND as an actual domain*. For example zone "example.tld"
means that example.tld will be used in place of @ found in the zone file.
BIND will do this for us as long as there is no $ORIGIN described in the zone file
There are several named.conf
files but we'll add zones to named.conf.local
. The new zone entry for example.tld looks like so:
zone "example.tld" {
type master;
file "/etc/bind/db.custom";
};
BIND can now link the dots and resolve example.tld to the addresses in our zone file. An adig
from the client-side can confirm that the domain resolves to the wanted address.
user@mbpro:~|⇒ adig example.tld
id: 24487
flags: qr aa rd ra
opcode: QUERY
rcode: NOERROR
Questions:
example.tld . A
Answers:
example.tld . 3600 A 10.100.100.198
NS records:
Additional records:
Firewalling with Multiple zones
☠ This method is not recommended
With the ability to serve arbitrary records, we can (1) make a list of unwanted domains and (2) turn them into zones. Each will point to the same zone file.

zone "ads.nytimes.com" {
type master;
file "/etc/bind/db.blocked";
};
zone "ads.snapchat.com" {
type master;
file "/etc/bind/db.blocked";
};
zone "zzzrtrcm2.com" {
type master;
file "/etc/bind/db.blocked";
};
zone "secure.webconnect.net" {
type master;
file "/etc/bind/db.blocked";
};
Building these zones from a blocklist such as hosts yields close to 90,000 entries. The resulting named.conf.local
grows to over 6MB after conversion to zone formatting. All zones point to db.blocked
which consists of some bare essentials. Note that the A records can be left out.
$TTL 86400
@ IN SOA localhost. hostmaster.localhost. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
86400 ) ; Negative Cache TTL
;
@ IN NS localhost.
@ IN A 0.0.0.0
* IN A 0.0.0.0
The zone file will resolve to an unusable address and should break the domain. Testing from a client again, shows that this domain has been spoofed and is now pointing to a non-routable 0.0.0.0.
user@mbpro:~|⇒ adig secure.webconnect.net
id: 64487
flags: qr aa rd ra
opcode: QUERY
rcode: NOERROR
Questions:
secure.webconnect.net. A
Answers:
secure.webconnect.net. 3600 A 0.0.0.0
NS records:
Additional records:
Performance issues with Multiple zones
Degraded performance is noticed after implementing this approach.
- Start and restart times consistently much longer
- Memory consumption consistently too high
In normal circumstances when starting the service, it's up and answering lookups in a couple of seconds. During this test, BIND startup required close to a minute to complete as it loaded the zones. Memory consumption was high, putting BIND consistently in the top. Running with this configuration became unsustainable as BIND would be die off as it maxed out the system.
CPU[| 1.3%] Tasks: 67, 135 thr; 1 running
Mem[|||||||||||||||||||||||||||||||||||||||||||||||||1.67G/1.94G] Load average: 0.06 0.01 0.00
Swp[||||||||||||||||||||||||||||||||||||||||| 688M/1024M] Uptime: 24 days, 12:21:54
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
133237 bind 20 0 1821M 1414M 5316 S 0.0 71.2 0:00.19 /usr/sbin/named -f -u bind
133238 bind 20 0 1821M 1414M 5316 S 0.0 71.2 0:27.43 /usr/sbin/named -f -u bind
133239 bind 20 0 1821M 1414M 5316 S 0.0 71.2 0:02.19 /usr/sbin/named -f -u bind
133240 bind 20 0 1821M 1414M 5316 S 0.0 71.2 0:00.02 /usr/sbin/named -f -u bind
133226 bind 20 0 1821M 1414M 5316 S 0.0 71.2 0:29.88 /usr/sbin/named -f -u bind
131545 ***** 20 0 1879M 101M 16496 S 0.0 5.1 0:00.00 /usr/bin/node current/index.js
None of these issues are experienced when implementing the equivalent blocklist using a Response Policy Zone. Using RPZ also provides other benefits in shaping the DNS service. A later walkthrough will cover RPZ in BIND.
