say my name

DNS – Part 3 – Use Bind9 as your local DNS server

Let’s do this!


I don’t want smart match, i.e. when a DNS server is unable to find a match to the submitted URL:

  1. it corrects it and returns an approximation, or
  2. returns a Google Search of the queried URL to the client.

I particularly don’t want machines recording my activity. I search how to build dirty bombs, how to torture children and where would I go to eat human flesh. The shit I would have to put up with, if that got recorded and somehow someone got a hold of that information… not to mention searching for snuff films, child pornography and murder footage… I could be in serious trouble. Don’t even get me started on 6 year old chat rooms… I’ll have a colourful traffic graph this month…

Dying DNS servers are a thing of the past. Redundancy isn’t an issue – it’s nice to have – unless the world is ending. In that case, forget about DNS servers, build a fire and a spear – they’re coming.

I definitely want to be able to access ALL.If you care that domains are/get blocked/censored by your ISP through DNS, this is also for you.

If all the above can be done, it is important that all nodes in my private networks are able to use the server to query outside domain names. Outsiders will not be allowed to use it that way. Outsiders can only do authoritative queries on my domain. Even if they were allowed to…dynamic IP suckers!! …I guess it could be done … with lasers and magnets!!!

Wubba lubba dub dub witches!
Wubba lubba dub dub witches!

Getting reliable results and giving reliable results are interesting topics. To the DeLorean on that one!


Picking up from my last post, this is fairly easy to do – not.

The Theory behind Bind9 Access Control

It’s important to know what you’re doing to maximize fun.

With that in mind, ignoring DNS Zones, this section contains what you need to know to have the most fun – in my view – setting up access control in Bind9. The following are a series of quotes [ISC, ZYTRAX, Wikipedia] that explain how Bind9’s access control mechanisms work.

The information presented below covers keywords that can be added to the configuration files of Bind9. Knowing their purpose can help with setting up the case described, as well as any other case you might be interested in.

allow-query governs who can send any query to the server, not just  queries against authoritative data. If a query is blocked by this ACL, the response sent back is empty (no records), with the RCODE set to REFUSED.

allow-query-cache was added in BIND 9.4 (previously, the only access control on cached data was allow-query).  It is used to restrict who has access to records that are in cache (i.e. that have been learned by the recursive server via recursion).

If a query is blocked by allow-query-cache, the response is REFUSED,  as with allow-query. If it passes allow-query-cache but is blocked by allow-recursion (an unusual situation these days), the query is  handled as if it were not recursive.

allow-recursion and allow-query-cache default to behave like each other. In other words, if one is set but not the other, the behaviour is as if both were set to the same ACL. Therefore, there’s almost  never any reason to set allow-query-cache – just use allow-recursion  for both, unless you truly have a use for allowing someone access to the cache who does not also have permission to send recursive queries
to the server.

The defaults if no values are set at all:

allow-query { any; };
allow-query-cache { localhost; localnets; };
allow-recursion { localhost; localnets; };

So basically, by default, Bind seems to be set-up for my purpose, but it isn’t because:

The following special acl-name values are built into BIND:

  1. “none” – matches no hosts
  2. “any” – matches all hosts
  3. “localhost” – matches all the IP address(es) of the server on which BIND is running e.g. if the server has a single interface with an IP address of then localhost will match and (the loopback address is always present).
  4. “localnets” – matches all the IP address(es) and subnetmasks of the server on which BIND is running i.e. if the server has a single interface with an IP address of and a netmask of (or then localnets will match to and (the loopback is assumed to be a single address). Some systems do not provide a way to determine the prefix lengths of local IPv6 addresses. In such a case, localnets only matches the local IPv6 addresses, just like localhost.

If you look carefully to number 4 and remember…

The Internet Engineering Task Force (IETF) has directed the Internet Assigned Numbers Authority (IANA) to reserve the following IPv4 address ranges for private networks, as published in RFC 1918:[1]

RFC1918 name IP address range number of addresses largest CIDR block (subnet mask) host id size mask bits classful description[Note 1]
24-bit block – 16,777,216 ( 24 bits 8 bits single class A network
20-bit block – 1,048,576 ( 20 bits 12 bits 16 contiguous class B networks
16-bit block – 65,536 ( 16 bits 16 bits 256 contiguous class C networks

Users can randomly assign networks and subnets from the above ranges…

… you’ll notice there are some privatenets not included in localnets for the localnets to contain all privatenets.

Security-wise, it makes a lot of sense to restrict, although in this case – not a professional grade solution – I’m to lazy to ever want to mess around with access control on the bind service again so… I’ll just open the flood gates and allow any origin within all possible private network to be able to query Bind9 for cached results, recursively.

The Configuration

First I’ll need a new Access Contol List (ACL) where all privatenets are included. I’ll call it privatenets to minimize consistency – not.

acl privatenets {;;;

Second I add it to the options file and include it in the default configuration. Open the file:

sudo nano /etc/bind/named.conf.options

The new lines, in comparison to the previous post, are maked as orange. Make it look like this:

acl privatenets {;;;
options {
    directory "/var/cache/bind";
    allow-query { any; };
    allow-query-cache { localhost; localnets; privatenets; };
    allow-recursion { localhost; localnets; privatenets; };

    forwarders {

    dnssec-validation auto;

    auth-nxdomain no;    # conform to RFC1035
    listen-on-v6 { any; };

    listen-on port 53 { any; };

Third I just need to restart Bind9:

sudo service bind9 restart


Leave a Reply