HOWTO setup your own caching nameserver using Unbound
The best alternative for setting up a caching nameserver on your LAN or personal machine today is Unbound. It's written with that purpose in mind which makes it faster and simpler to setup than more full-featured alternatives such as named (called "BIND") or KNOT-resolver and such.
Basic installation and configuration
Start off by installing unbound with
dnf install unbound or
apt-get install unbound depending on distribution. On Arch you also have to manually install the
Now it's time to make a configuration file for it. Here is a most basic example of what you need:
The first few lines define who can query the server with
access-control directives. They we define what to listen on with
interface. The above example is very liberal and makes unbound listen on all interfaces.
Refer to the unbound.conf manual page for further details.
It is a good idea to run
unbound-checkconf to check if it is valid once you are happy with your configuration.
Now you need to ensure that
systemd-resolved is not occupying the DNS port. You can do this by giving it the following configuration file:
DNSStubListener directive is essential to ensure it does not listen for DNS queries. You may actually want
MulticastDNS if you do not use
avahi-daemon for multicast-DNS purposes.
Restart systemd-resolved with
systemctl restart systemd-resolved.service or stop it with
systemctl stop systemd-resolved.service - Do be aware that it doesn't really matter if you stop it or re-start it. systemd will happily start it when applications make API requests for it even if you masked it.
systemctl start unbound.service
to start it and
systemctl enable unbound.service
to make it start on every boot.
Validating your queries
Once you have a basic unbound setup you will want to add validation. First, install the
bind-utils package and copy the
/etc/trusted-key.key to where unbound can read it with
cp /etc/trusted-key.key /etc/unbound
Now add this line to your unbound.conf:
And restart unbound. Now you should test using this command:
unbound-host -C /etc/unbound/unbound.conf -v sigok.verteiltesysteme.net
which should output
sigok.verteiltesysteme.net has address 188.8.131.52 (secure)<br data-attributes="class=%22mw_emptyline%22">sigok.verteiltesysteme.net has IPv6 address 2001:638:501:8efc::139 (secure)<br data-attributes="class=%22mw_emptyline%22">sigok.verteiltesysteme.net has no mail handler record (secure)
sigok.verteiltesysteme.net has address 184.108.40.206 (insecure)<br data-attributes="class=%22mw_emptyline%22">sigok.verteiltesysteme.net has IPv6 address 2001:638:501:8efc::139 (insecure)<br data-attributes="class=%22mw_emptyline%22">sigok.verteiltesysteme.net has no mail handler record (insecure)
If get "secure" as in the first output then you're good, if you get "insecure" as in the last example then it is not working.
Maintaining a root "hints" file
A DNS query will first go to the DNS root and then the nameservers responsible for the top domain (.com/.org/etc) and then the server which is responsible for the domain you are querying. Thus; you need to know where to start. Unbound comes with a built-in list of root servers. That's great, but if your Unbound version gets wildly outdated and the root servers change those hints may no longer apply. It is considered "good practice" to keep a updated local copy of the hints. A simple way to do this is to create a good old
make the file executable
chmod a+x /etc/cron.monthly/update-unbound-hints.sh
and run it
Then add the following line to
Asking a botnet DNS server ran by either CloudFlare or Google may actually be faster than doing your own recursive lookups depending on your network, location and distance to those.
If you would like to forward DNS queries to another nameserver on your LAN you need to add
forward-zone:<br data-attributes="class=%22mw_emptyline%22"> name: "."<br data-attributes="class=%22mw_emptyline%22"> forward-addr: 192.168.0.1@53<br data-attributes="class=%22mw_emptyline%22">
That is good enough on your LAN but you may want to add more if your DNS queries will be leaving your local network and going to the botnet. For this you would want to add the following:
tls-upstream: yes tls-cert-bundle: /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem forward-zone: name: "." # Cloudflare DNS forward-addr: 2606:4700:4700::1111@853#cloudflare-dns.com forward-addr: 220.127.116.11@853#cloudflare-dns.com forward-addr: 2606:4700:4700::1001@853#cloudflare-dns.com forward-addr: 18.104.22.168@853#cloudflare-dns.com
Here we tell unbound to use TLS for queries leaving the LAN with
tls-upstream: yes. Then we tell it what certificate package to check against with
tls-cert-bundle. The file referred to should be installed by the
ca-certificates package which you should have gotten installed as a dependency for unbound. Next we specify a set of
forward-addr and here there is one detail one might get wrong: The names of those servers after the
# are not comments. Those are used for the TLS certificate validation and must be present.
Combining the above a complete unbound configuration file which forwards DNS queries to the CloudFlare botnet looks like this:
Ensuring there is no systemd or networkmanager interference
This section is not for everyone. You may want to ensure that a local or LAN Unbound nameserver is always used regardless of systemd or networkmanager opinion. To accomplish this you first need to tell networkmanager to not interfere with your DNS settings, ever. This can be accomplished by changing the configuration file
/etc/NetworkManager/NetworkManager.conf to only contain the following content:
Now NetworkManager will not touch or overwrite or destroy your
/etc/resolv.conf. By default that file is now a symbolic link on most distributions. You can remove that link and demand that only localhost, where you now have unbound, is (ab)used with these fine commands:
rm -f /etc/resolv.conf<br data-attributes="class=%22mw_emptyline%22">echo 'nameserver 127.0.0.1' > /etc/resolv.conf<br data-attributes="class=%22mw_emptyline%22">
Note that you are now relying entirely on unbound running on localhost. That is fine if you are starting Unbound on boot and you want it to handle DNS regardless of what network you are using.
systemd-resolved will however be a pain to configure in this situation.