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.
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
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.
This zone file which will resolve any domain @ and subdomains * to the addresses shown in the A record.
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:
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.
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.
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.
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.