Set Up Your Own BIND9 DNS Resolver on CentOS 8/RHEL 8/Rocky Linux 8/Alma Linux 8

This tutorial will be showing you how to set up a local DNS resolver on CentOS 8/RHEL 8, 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 CentOS/RHEL. You can add sudo at the beginning of a command, or use su - command to switch to root user.

Install BIND9 on CentOS 8/RHEL 8

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 CentOS 8/RHEL 8 from the default repository. BIND 9 is the current version and BIND 10 is a dead project.

sudo dnf update
sudo dnf install bind

Check version information.

named -v

Sample output:

BIND 9.11.4-P2-RedHat-9.11.4-17.P2.el8_0.1 (Extended Support Version) <id:7107deb>

To check the version number and build options, run

named -V

centos 8 rhel 8 bind9

Now we can start BIND 9 with:

sudo systemctl start named

And enable auto start at boot time:

sudo systemctl enable named

You can check its status with:

systemctl status named

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

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

sudo dnf install net-tools
sudo netstat -lnptu | grep named

centos 8 rhel 8 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 bind package and there’s another important binary: rndc, the remote name daemon controller. 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

centos 8 caching dns server

Configurations for a Local DNS Resolver

The named daemon on CentOS 8/RHEL 8 uses the root hints file at /var/named/named.ca. 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 CentOS/RHEL provides recursive service for localhost only. Outside queries will be denied. Edit the BIND main configuration file /etc/named.conf.

sudo nano /etc/named.conf

In the options clause, you can find the following two lines.

listen-on port 53 { 127.0.0.1; };
listen-on-v6 port 53 { ::1; };

This makes named listen on localhost only. If you want to allow clients in the same network to query domain names, then comment out these two lines. (add double slashes at the beginning of each line)

// listen-on port 53 { 127.0.0.1; };
// listen-on-v6 port 53 { ::1; };

Find the following line.

allow-query { localhost; };

Add the network range from which clients can query domain names like below.

allow-query { localhost; 192.168.0.0/24; 10.10.10.0/24; };

The following line enables recursion service, which is fine.

recursion yes;

I also recommend adding the following directives in the options clause.

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

 // enable the query log
 querylog yes;

centos 8 bind enable recursion service

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 named.

sudo systemctl restart named

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.

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.0.0/24" port protocol="udp" port="53" accept'

Reload firewall for the change to take effect.

sudo systemctl reload firewalld

This will open 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.101 with the IP address of your BIND resolver.

dig A google.com @192.168.0.101

Note: On CentOS/RHEL, you need to install the bind-utils package in order to use the dig command.

sudo dnf install bind-utils

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

sudo journalctl -eu named

This will show the latest log message of the named 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.101)

Setting the Default DNS Resolver on CentOS 8/RHEL 8 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 CentOS 8/RHEL 8 with the following command.

cat /etc/resolv.conf

Sample output:

# Generated by NetworkManager
nameserver 192.168.0.1
nameserver 8.8.8.8

If you run the following command on the BIND server,

dig A facebook.com

This DNS query can’t be found in BIND log. Instead, you need to explicitly tell dig to use BIND.

dig A facebook.com @127.0.0.1

To set BIND as the default resolver, first you need to find the name of your main network interface with the following command.

ip addr

Mine is ens3. Next, run the following command to edit the network interface configuration file. Replace ens3 with your own interface name. If the BIND resolver is running on a laptop connected using Wi-Fi, then you need to edit the ifcfg-wireless-network-name file.

sudo nano /etc/sysconfig/network-scripts/ifcfg-ens3

Find the DNS1 parameter and change its value to 127.0.0.1. Note that if values for other parameters in this file are wrapped in double-quotes, then you also need to wrap 127.0.0.1 with double-quotes.

DNS1="127.0.0.1"

If you can’t find the DNS1 parameter, then add the above line at the bottom. Save and close the file. Then restart NetworkManager for the change to take effect.

sudo systemctl restart NetworkManager

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 CentOS 8/RHEL 8.

change name server on centos 8

Troubleshooting

Some hosting providers may have a different mechanism to update DNS resolver. If the /etc/resolv.conf file doesn’t show 127.0.0.1 as the resolver, it could be that this file isn’t managed by NetworkManager. You can manually edit this file.

sudo nano /etc/resolv.conf

And change the name server to 127.0.0.1.

nameserver 127.0.0.1

Save and close the file.

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 uses 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 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 CentOS/RHEL, simply open the /etc/sysconfig/named file

sudo nano /etc/sysconfig/named

And add the following line at the end of the file.

OPTIONS="-4"

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

sudo systemctl restart named

Now run the following command. You can see that BIND is not listening on IPv6 address anymore.

sudo netstat -lnptu | grep named

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 was 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.

I once had another interesting situation. My BIND server had the SERVFAIL problem. My server can only query the Google public DNS resolver (8.8.8.8 and 8.8.4.4). DNS queries to all other IP addresses are blocked. I certainly did not set such a firewall rule on my own server. If you are in the same situation, it could mean that your hosting provider doesn’t want you to run a DNS resolver, because some folks don’t block public DNS queries coming to their DNS resolver and so they become open DNS resolvers, which can be used by bad actors to launch DNS amplification attack.

In this case, you can configure your BIND to forward DNS queries to Google public DNS resolver, so DNS clients can continue to use your BIND resolver.

Add a fowarders directive like below in the options clause in the /etc/named.conf file, then your BIND resolver becomes a forwarder, which will forward DNS requests to an upstream DNS resolver like 8.8.8.8.

options {
//      listen-on port 53 { 127.0.0.1; };
//      listen-on-v6 port 53 { ::1; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        secroots-file   "/var/named/data/named.secroots";
        recursing-file  "/var/named/data/named.recursing";
        allow-query { localhost; 192.168.0.0/24; 10.10.10.0/24; };

        ...
        ...

        forwarders {
              8.8.8.8;
              8.8.4.4;
        };

        ...
        ...
};

Save and close the file. Then restart BIND for the changes to take effect.

sudo systemctl restart named

Named Automatic Restart

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

sudo systemctl restart named

Instead of manually typing this command, we can make Named 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/named.service.d/

Then create a file under this directory.

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

Add the following lines in the file, which will make Named 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 Named with:

sudo pkill named

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

systemctl status named

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 named) 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 main configuration file /etc/named.conf.

sudo nano /etc/named.conf

Add the following directive in the options clause (below the allow-query directive). Change 50% to your preferred value.

max-cache-size 50%;

Restart BIND for the change to take effect.

sudo systemctl restart named

No servers could be reached

If you see the following error when using the dig command on client computers

;; connection timed out; no servers could be reached

It could be that

  • Your firewall rule is wrong.
  • The BIND resolver isn’t running.
  • BIND isn’t listening on a network interface.

Conclusion

I hope this tutorial helped you set up a local DNS resolver on CentOS 8/RHEL 8 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: 8 Average: 5]

10 Responses to “Set Up Your Own BIND9 DNS Resolver on CentOS 8/RHEL 8/Rocky Linux 8/Alma Linux 8

  • i have used this guide and installed bind9, its works like a charm 🙂
    but I need a web tool or web access for this software to maintain DNS records.
    more user friendly software for some users.
    please help me 🙂

    thanks in advance

    • Xiao Guoan (Admin)
      4 years ago

      This article is for running a local DNS resolver. It’s not for domain name owners to create DNS records.

      PS: I have already pointed this out in the article.

  • Piter yong
    4 years ago

    How to setup authoritive dns in centos 8

  • i get this

    ; <> DiG 9.11.20-RedHat-9.11.20-5.el8 <> A facebook.com @127.0.0.1
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 31892
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 4096
    ; COOKIE: XXXX deleted XXXX (good)
    ;; QUESTION SECTION:
    ;facebook.com. IN A

    ;; Query time: 420 msec
    ;; SERVER: 127.0.0.1#53(127.0.0.1)
    ;; WHEN: Mon Oct 26 09:17:22 EET 2020
    ;; MSG SIZE rcvd: 69

    • Xiao Guoan (Admin)
      3 years ago

      “SERVFAIL” indicates your BIND resolver has a problem querying DNS records. It can be difficult to troubleshoot “SERVFAIL” error.

      You can restart BIND.

      sudo systemctl restart named

      And check the BIND log to see if there are other errors.

      sudo journalctl -eu named

      For example, it might tell you that it can’t reach IPv6 address, and you need to disable IPv6 in BIND, which is explained at the end of this article.

  • Jose Pascoal
    3 years ago

    I notice that you don’t define ips forwarders, how can this local dns answer a query that he doesn’t know?

    • Xiao Guoan (Admin)
      3 years ago

      Yes, BIND can forward DNS queries, but BIND is a full DNS recusive resolver that can work on its own without forwading queries to another resolver. If a recursive resolver must forward queries in order to work, then the upstream resolver also needs to forward queries to another resolver, and there will never be an end to this forward chain.

      When do you must forward DNS queries? When you use a DNS software that doesn’t support recursive queries, like dnsmasq, which is just a DNS forwader that needs to send queries to a real recursive resolver.

      A recursive resolver can automatically find the authoritative DNS servers for a given domain via the root DNS servers and TLD DNS servers. Authoritative DNS servers store the master copy of zone file for a given domain and it will respond to the DNS queries sent from recursive resolvers, which then sends the DNS response to end-users.

    • Jose Pascoal
      3 years ago

      I didn’t know this. When I don’t config forwarders in my bind configuration I have no network, if I use nslookup for google.com, my DNS don’t answer the query. Probably is a problem in my company network, it doesn’t allow my DNS to use recursion. I will test in my own network. Thank you for your clarification and your tutorials, help me a lot.

  • Wow, this is a super useful and well written guide. Many thanks.

    I’ll be popping a donation to you next payday 🙏

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