Set Up Your Own DNS Resolver on Debian with BIND9

This tutorial will be showing you how to set up a local DNS resolver on Debian, with the widely-used BIND9 DNS software. There are many synonyms for DNS resolver, some of which are listed below. They all refer to the same thing.

  • full resolver (in contrast to stub resolver)
  • DNS recursor
  • recursive DNS server
  • recursive resolver

Also be aware that A DNS server can also called a name server. Examples of DNS resolver are 8.8.8.8 (Google public DNS server) and 1.1.1.1 (Cloudflare public DNS server). The OS on your PC also has a resolver, although it’s called stub resolver due to its limited capability. A stub resolver is a small DNS client on the end-user’s computer that receives DNS requests from applications such as Firefox and forwards requests to a recursive resolver. Almost every resolver can cache DNS response to improve performance, so they are also called caching DNS server.

Why Run Your Own DNS Resolver

Normally, your computer or router uses your ISP’s DNS resolver to query domain names in order to get an IP address. Running your own local DNS resolver can speed up DNS lookups, because

  1. The local DNS resolver only listens to your DNS requests and does not answer other people’s DNS requests, so you have a much higher chance of getting DNS responese directly from the cache on the resolver.
  2. The network latency between your computer and DNS resolver is eliminated (almost zero), so DNS queries can be sent to root DNS servers more quickly.

If you run a mail server and use DNS blacklists (DNSBL) to block spam, then you are advised to run a local DNS resolver to speed up DNS lookups. If you run your own VPN server on a VPS (Virtual Private Server), it’s also a good practice to install a DNS resolver on the same VPS.

You may also want to run your own DNS resolver if you don’t like your Internet browsing history being stored on a third-party server.

If you own a website and want your own DNS server to handle name resolution for your domain name instead of using your domain registrar’s DNS server, then you will need to set up an authoritative DNS server, which is different than a DNS resolver. BIND can act as an authoritative DNS server and a DNS resolver at the same time, but it’s a good practice to separate the two roles on different boxes. This tutorial shows how to set up a local DNS resolver and because it will be used on local host/local network, no encryption (DNS over TLS or DNS over HTTPS) is needed. Setting up a DoT or DoH server will be discussed in a future article.

Please note that you need to have root privilege when installing software on Debian. You can add sudo at the beginning of a command, or use su - command to switch to root user.

Install BIND9 on Debian

BIND (Berkeley Internet Name Domain) is an open-source DNS server software widely used on Unix/Linux due to it’s stability and high quality. It’s originally developed by UC Berkeley, and later in 1994 its development was moved to Internet Systems Consortium, Inc (ISC).

Run the following command to install BIND 9 on Debian from the default repository. BIND 9 is the current version and BIND 10 is a dead project.

sudo apt update
sudo apt install bind9 bind9utils bind9-doc bind9-host dnsutils

Check version information.

sudo named -v

Sample output:

BIND 9.11.5-P4-5.1-Debian (Extended Support Version) <id:998753c>

To check the version number and build options, run

sudo named -V

debian 10 buster bind9

By default, BIND automatically starts after installation. You can check its status with:

systemctl status bind9

Hint: If the above command doesn’t quit immediately, press Q.

If it’s not running, then start it with:

sudo systemctl start bind9

And enable auto start at boot time:

sudo systemctl enable bind9

The BIND server will run as the bind user, which is created during installation, and listens on TCP and UDP port 53, as can be seen by running the following command:

sudo netstat -lnptu | grep named

debian 10 bind dns resolver

Usually DNS queries are sent to the UDP port 53. The TCP port 53 is for responses size larger than 512 bytes.

The BIND daemon is called named. (A daemon is a piece of software that runs in the background.) The named binary is installed by the bind9 package and there’s another important binary: rndc, the remote name daemon controller, which is installed by the bind9utils package. The rndc binary is used to reload/stop and control other aspects of the BIND daemon. Communication is done over TCP port 953.

For example, we can check the status of the BIND name server.

sudo rndc status

debian 10 buster bind caching dns server

Configurations for a Local DNS Resolver

/etc/bind/ is the directory that contains configurations for BIND.

  • named.conf: the primary config file which includes configs of three other files.
  • db.127: localhost IPv4 reverse mapping zone file.
  • db.local: localhost forward IPv4 and IPv6 mapping zone file.
  • db.empty: an empty zone file

The bind9 package on Debian doesn’t ship with a db.root file, it now uses the root hints file at /usr/share/dns/root.hints. The root hints file is used by DNS resolvers to query root DNS servers. There are 13 groups of root DNS servers, from a.root-servers.net to m.root-servers.net.

Out of the box, the BIND9 server on Debian provides recursive service for localhost and local network clients only. Outside queries will be denied. So you don’t have to edit the configuration files. To get you familiar with BIND 9 configurations, I will show you how to enable recursion service anyway.

The main BIND configuration file /etc/bind/named.conf sources the settings from 3 other files.

  • /etc/bind/named.conf.options
  • /etc/bind/named.conf.local
  • /etc/bind/named.conf.default-zones

To enable recursion service, edit the first file.

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

In the options clause, add the following lines. Replace IP addresses in the allow-recursion statement with your own local network addresses.

 // hide version number from clients for security reasons.
 version "not currently available";

 // optional - BIND default behavior is recursion
 recursion yes;

 // provide recursion service to trusted clients only
 allow-recursion { 127.0.0.1; 192.168.0.0/24; 10.10.10.0/24; };

 // enable the query log
 querylog yes;

install bind9 dns recursor debian 10 buster

Save and close the file. Then test the config file syntax.

sudo named-checkconf

If the test is successful (indicated by a silent output), then restart BIND9.

sudo systemctl restart bind9

If you have a firewall running on the BIND server, then you need to open port 53 to allow LAN clients to send DNS queries. If you use UFW firewall, you can run the following command.

sudo ufw allow in from 192.168.0.0/24 to any port 53

This will open TCP and UDP port 53 to the private network 192.168.0.0/24. Then from another computer in the same LAN, we can run the following command to query the A record of google.com. Replace 192.168.0.102 with the IP address of your BIND resolver.

dig A google.com @192.168.0.102

Now on the BIND resolver, check the query log with the following command.

sudo journalctl -eu bind9

This will show the latest log message of the bind9 service unit. I can find the following line in the log, which indicates that a DNS query for google.com’s A record has been received from port 57806 of  IP address 192.168.0.103.

named[1162]: client @0x7f4d2406f0f0 192.168.0.103#57806 (google.com): query: google.com IN A +E(0)K (192.168.0.102)

Setting the Default DNS Resolver on Debian Server

On the BIND server, we need to set 127.0.0.1 as the default DNS resolver. You can check the current DNS resolver on Debian with the following command.

cat /etc/resolv.conf

Sample output:

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#      DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 2001:19f0:300:1704::6
nameserver 108.61.10.10

The bind9 package on Debian ships with a Systemd service unit bind9-resolvconf.service, which will help us set BIND as default DNS resolver on Debian server. By default, this service is disabled, we need to start it and enable auto-start at boot time.

sudo systemctl start bind9-resolvconf

sudo systemctl enable bind9-resolvconf

You can now check the content of /etc/resolv.conf again. As you can see, 127.0.0.1 (BIND) is now the default DNS resolver on Debian.

change name server on debian 10 buster

If your DNS resolver isn’t 127.0.0.1, it might be that your system doesn’t have the resolvconf binary, which causes the bind9-resolvconf service to fail. You need to install the resolvconf package and restart the service.

sudo apt install resolvconf

sudo systemctl restart bind9-resolvconf

Setting Default DNS Resolver on Client Computers

Now you can configure other computes on the LAN to use the BIND server as DNS resolver. For Windows and MacOS computers, you can search on Google to find out how to set default DNS resolvers. Here I will show you how to set DNS resolver on Linux desktop computers. The following method works on any Linux distro that use NetworkManager.

Click on the Network Manager icon on your Linux desktop to find the Edit connections. (On Some Linux distros, you need to right-click the Network Manager.)

network-manager-change-DNS-server

Then select the current connection and click the cog icon to edit this connection.

dns server bind9

Select IPv4 settings tab, change method from Automatic(DHCP) to Automatic(DHCP) addresses only, which will prevent your Ubuntu system from getting DNS server address from your router. Then specify a DNS server. Here I enter the BIND server’s IP address in my LAN.

bind local dns server lan

Save your changes. Then restart NetworkManager for the changes to take effect.

sudo systemctl restart NetworkManager

Once you are reconnected, click the Network Manager icon again and select connection information. You can see that your Linux desktop computer is now using your BIND DNS server.

change dns server on linux

How to Disable IPv6 in BIND

If you don’t use IPv6 in your network, then it’s a good idea to turn off IPv6 in BIND, otherwise, there will be a lot of errors about IPv6 in BIND log like below.

network unreachable resolving 'mirrors.fedoraproject.org/A/IN': 2001:4178:2:1269:dead:beef:cafe:fed5#53
network unreachable resolving 'mirrors.fedoraproject.org/AAAA/IN': 2001:4178:2:1269:dead:beef:cafe:fed5#53
network unreachable resolving 'mirrors.fedoraproject.org/A/IN': 2610:28:3090:3001:dead:beef:cafe:fed5#53
network unreachable resolving 'mirrors.fedoraproject.org/AAAA/IN': 2610:28:3090:3001:dead:beef:cafe:fed5#53

To disable IPv6 in BIND on Ubuntu, simply open the /etc/default/bind9 file

sudo nano /etc/default/bind9

Add -4 to the OPTIONS.

OPTIONS="-u bind -4"

Save and close the file. Then restart BIND and you are done.

sudo systemctl restart bind9

BIND SERVFAIL

If your BIND resolver can’t answer DNS queries (SERVFAIL), and you see the following line in the BIND log.

dnssec: warning: managed-keys-zone: Unable to fetch DNSKEY set '.': timed out

It’s probably because your server doesn’t have a working IPv6 connectivity. This happened to one of my servers. I thought IPv6 connectivity is working as usual, but it’s suddenly broken for reasons I didn’t know. Once I disabled IPv6 in BIND, DNS resolution is working again.

Broken Trust Chain

If you found the following error in the BIND log, it’s probably because your server time is wrong.

Aug 06 02:16:13 bookworm named[962]: broken trust chain resolving '1.debian.pool.ntp.org/AAAA/IN': 10.0.0.254#53
Aug 06 02:16:14 bookworm named[962]: validating youtube-ui.l.google.com/A: bad cache hit (google.com/DS)
Aug 06 02:16:14 bookworm named[962]: broken trust chain resolving 'youtube-ui.l.google.com/A/IN': 10.0.0.254#53
Aug 06 02:16:15 bookworm named[962]: validating youtube-ui.l.google.com/A: bad cache hit (google.com/DS)
Aug 06 02:16:15 bookworm named[962]: broken trust chain resolving 'youtube-ui.l.google.com/A/IN': 10.0.0.254#53

Follow the tutorial below to configure time zone and system clock.

BIND Automatic Restart

If for any reason your Bind process is killed, you need to run the following command to restart it.

sudo systemctl restart bind9

Instead of manually typing this command, we can make bind automatically restart by editing the named.service systemd service unit. To override the default systemd service configuration, we create a separate directory.

sudo mkdir -p /etc/systemd/system/bind9.service.d/

Then create a file under this directory.

sudo nano /etc/systemd/system/bind9.service.d/restart.conf

Add the following lines in the file, which will make Bind automatically restart 5 seconds after a failure is detected.

[Service]
Restart=always
RestartSec=5s

Save and close the file. Then reload systemd.

sudo systemctl daemon-reload

To check if this would work, kill Bind with:

sudo pkill named

Then check Bind status. You will find Bind automatically restarted.

systemctl status bind9

BIND max-cache-size

BIND can cache DNS results on the server to speed up DNS lookup for clients. BIND assumes you are running a dedicated DNS resolver, i.e, no other web services are running on the same host, so the default cache size (defined by max-cache-size) is set to 90% of the total RAM to achieve best performance. You can see a line like below in the BIND log (sudo journalctl -eu bind9) when BIND starts.

none:100: 'max-cache-size 90%' - setting to 7165MB (out of 7961MB)

Note that BIND will not use 90% of your RAM immediately. If there are only a few DNS requests, BIND uses only a small amount of RAM, because there’s not many DNS results to cache. If there are lots of DNS requests, then it will use lots of RAM to store the DNS cache.

If your RAM is limited, you might not want BIND to use 90% of your RAM for cache. Edit the BIND configuration file /etc/bind/named.conf.options.

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

Add the following directive in the options clause. Change 50% to your preferred value.

max-cache-size 50%;

Restart BIND for the change to take effect.

sudo systemctl restart bind9

Conclusion

I hope this tutorial helped you set up a local DNS resolver on Debian with BIND9. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care 🙂

Rate this tutorial
[Total: 4 Average: 5]

23 Responses to “Set Up Your Own DNS Resolver on Debian with BIND9

  • Hello
    and thanks a lot for this guide
    i wanna ask you please is it possible to install DNS Resolver and openvpn server on the same server?

    • Xiao Guo An (Admin)
      5 years ago

      Yes, you can.

      • what i need to do is just download and install DNS Resolver in another directory right?
        i’m so new on linux excuse my (bad English) and my stupidity ^_^

    • Xiao Guo An (Admin)
      5 years ago

      You just need to follow this tutorial to install BIND9 as your DNS resolver. It won’t interfere with OpenVPN.

  • Hello!

    Many thanks for this.
    I found a problem on the debian server that I had and it may be useful to add it to the tutorial as well.
    When I wanted to start bind9-resolvconf I got this:

    ● bind9-resolvconf.service - local BIND via resolvconf
       Loaded: loaded (/lib/systemd/system/bind9-resolvconf.service; enabled; vendor preset: enabled)
       Active: inactive (dead)
    Condition: start condition failed at Sun 2020-10-25 18:05:10 CET; 4s ago
               └─ ConditionFileIsExecutable=/sbin/resolvconf was not met
         Docs: man:named(8)
               man:resolvconf(8)
    
    Oct 25 17:57:33 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    Oct 25 17:57:50 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    Oct 25 17:58:39 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    Oct 25 18:00:38 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    Oct 25 18:00:59 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    Oct 25 18:01:08 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    Oct 25 18:02:05 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    Oct 25 18:03:50 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    Oct 25 18:04:21 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    Oct 25 18:05:10 x.com systemd[1]: Condition check resulted in local BIND via resolvconf being skipped.
    

    All I needed to do is to install resolvconf through:

    sudo apt install resolvconf
    • Xiao Guoan (Admin)
      4 years ago

      Thanks for the tip. It’s been added to this article.

  • Another small issue.

    At this:
    > sudo ufw allow in from 192.168.0.0/24 to any port 53
    If you want to create your own VPN you should also add the rule for the vpn network.
    > sudo ufw allow in from 10.10.10.0/24 to any port 53

  • Cyberian
    4 years ago

    Hi, Great work! A small typo needs to be corrected.
    Instead of
    sudo systemctl restart bind9-resolvconf
    Please use
    sudo systemctl restart bind9 resolvconf

    • Xiao Guoan (Admin)
      4 years ago

      systemctl status bind9-resolvconf
      systemctl status bind9-resolvconf

      Content of /lib/systemd/system/bind9-resolvconf.service
      local BIND via resolvconf

  • Cyberian
    4 years ago

    (Note to clarify: Using Debian 11 Testing here)

    • Xiao Guoan (Admin)
      4 years ago

      I can’t update my article for a testing operating system.

      • Tiger lilly
        1 year ago

        Hi – the command

        sudo systemctl restart bind9-resolvconf

        does not work for Debian 11, The command to use should be

        sudo systemctl restart named-resolvconf.service
  • in this package “bind9utils” there is no ” dig ” you need to put “dnsutils”

  • Rob Fantini
    3 years ago

    Hello,
    we currently use dnsmasq only because we can read in our sitewide lan host file. to do so we have this line in /etc/dnsmasq.conf:

    addn-hosts=/opt/lan-hosts-file

    # that file is recreated automatically when we had hosts, which we maintain using this excellent software: https://github.com/opennetadmin/ona

    Question – is there a way to use a local hosts file in bind9?

    PS : thank you for these articles, I’ve been a subscriber for years, and find them well written

  • Rob Fantini
    3 years ago

    thank you Xiao Fuoan. it is good to know there is a way to use a LAN hosts file with bind.

  • Hello,

    How can I increase tcp clients?

    root@xx:/etc/bind# rndc status
    (…)
    recursive clients: 0/0/1000
    tcp clients: 100/100

    Thank you in advance

  • Great Job. Thanks a lot! Very good Teaching.

  • How can I connect to while I’m away (for example using hotel wifi). Port forward Port 53 right? And does the server cache other DNS entries of sites you haven’t visited yet?

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here