Building a caching/forwarding DNS with bind9
Whenever you connect to a website, the computer needs to exchange the URL with the actual IP address of the remote server. In this article, I tell you why it is a good idea to cache this request.
Why do it?
As you have already read, computer URLs, or more specific the host name (ex.: tuxdstash.de), need to be translated into IP numbers. That is because networking only works with those. It can be either IPV4 or IPV6 . To do that, any computer has an important information in the network section, called a DNS resolver, often written as “Nameserver”.
Now, if you are a single like me, it probably makes not as much sense to cache that request. But, if you live in a household of 3 and more, it makes more sense. Family members may visit the same site at the same time, with each computer requesting the same IP. If you don’t have a device in your network that caches this request, it needs to be pulled off the internet only once. It makes even more sense if you live country side and don’t have a very speedy connection. Or in companies with a lot more users, campus etc.
If you want to see the Domain Name System in action, you can use
nslookup to test it.
On Linux it is often not installed by default, but
nslookup can be installed on Linux via
apt install dnsutils.
Here is an example with
As you can see, Windows used the IPV6 local-link address (those are like APIPA addresses, but actually useable) of my Raspberry to get the answer off the internet. The funny thing is, you actually can’t use those to connect to my website directly, because my hoster runs Virtual Hosts on Apache and only identifies requests by server alias. But that is a topic for another day.
Ok, so what are our tools?
I am using a Raspberry Pi as a device for services in my network. It is small and reasonably fast for this kind of thing.
As DNS server, we are going to use
bind9. It comes directly from the Internet Consortium
You can install it via
How do I get started?
Since a networked device always needs to know where your Nameserver is located without relying on one, the Pi needs a static IP address. On Raspbian, this is done via the file
The Raspberry has the IP 192.168.1.252/24 in our scenario.
Of course, you need to adjust it to your IP setup in your home, it should be in the same network as your home router,
unless you are running a big network with professional routers. Your network interface might also have a different name,
especially if friendly names are enabled, but you can find that out via
What you might notice, is that it also includes an IPV6 address.
Addresses beginning with
fc00 are so called unique local address
and corresponds to the private IPV4 addresses, such as
This is important on Windows, because Windows will always prefer IPV6, especially when you test with
Generally, the config files we are looking for are inside of
We have lots of files there, but are only interested in one:
Without further ado, here is the code you need for this file:
Let’s have a look at it, step by step, shall we?
acl means “access list”. So what we are doing here, is telling bind9 to see those addresses as trusted addresses. In our case, the Raspberry (identified by localhost) and the private address space we use, both in IPV4 and IPV6.
localnets tells bind to match all IP that are in the same subnet as bind is. In my case, it is a bit redundant, because I only have one net at home, but in a bigger network this may be quite significant.
The first one is self-explanatory. It sets the data directory for the service. The second one requires a bit more explanation and the good folks over at zytrak have done a fine job at that. You may also choose no, default is yes, so I am going to leave it at that.
This puts our access-list from above into effect. It tells our service to accept all clients on this list.
Here we tell bind on which interfaces to listen. This is also quite important. As you can see, I have told bind to only listen on the
fc00:: IPV6 addresses. But since my phones do not get such an address and only use the equivalent of APIPA, you may choose to use
any in the IPV6 section. But, it is up to you.
Now comes the magic:
This is where bind9 get’s the DNS records then, which it cashes internally, until the caching time has expired. That time is set by the domain owner and we have no control over it. In my case, I have used Cloudflare
18.104.22.168) as my primary DNS and Google
22.214.171.124) as my secondary. You may choose different name servers, but that is up to you. I am comfortable with my choice.
To bring this into effect, the best way is to reboot your Pi, especially if you connect over SSH only, since you don’t want to have your network interface down without any ability to bring it back up. Or having to plug in a monitor and a keyboard. Generally, you can also restart bind with
service bind9 restart. If there are any errors, you can see them with a quick
journalctl -xe, after a restart. You can also use
named-checkconf /etc/bind/filename to check a specific file’s syntax, before you attempt to restart the service.
The last thing you have to do, is to force the devices in your network to use those name server by default. That is done via DHCP and we are going to cover this in our next tutorial. You can assign it manually as well, for V4 and V6 in the network properties of Windows.
So, now you have learned how to configure a caching DNS. If you have a public WiFi or administrating a large office, your patrons will be very thankful for you having that, it can speed up the networking experience significantly. Have fun and keep a lookout for more tutorials. Send any comments or errata to firstname.lastname@example.org.
Thanks for reading.
Come join the discussion and write something nice. You will have to confirm your comment by mail, so make sure it is legit and not a throwaway. Only the name part of it will be displayed, so don't worry about spam. If it does not show up after confirming it, it may be considered spam, but I curate them manually, so don't worry. Please read the privacy statement for more.