Setup BIND DNS Server in Rocky Linux 8 [Step-by-Step]


Rocky Linux, DNS

In this guide, we shall demonstrate how to install and configure BIND DNS server running in a chroot environment. BIND, also known as named, is the widely used DNS server application across the internet. BIND however when installed with the default method poses some vulnerabilities such as exposing the root filesystem in case of a security breach. In this guide, we shall be configuring BIND in a chroot environment. What this mechanism does is to "Jail" a program to a certain path and configure it as the root directory. This in turn prevents the process to access other parts of the system. This makes running the application more secure since you are assured that in case of a breach, the attacker will not be able to access the rest of the filesystem.

 

Lab Environment

I am using my existing Rocky Linux setup to demonstrate this article. Following are the details of my Lab Environment:

Server Machine:
OS: Rocky Linux release 8.4 (Green Obsidian)
Hostname: rockylinux
IP Address: 172.29.10.4/24

Client Machine:
OS: Rocky Linux release 8.4 (Green Obsidian)
Hostname: rockylinux-lab
IP Address: 172.29.10.6/24

 

Step-1: Install BIND Chroot

On Rocky Linux 8, install BIND Chroot with the command below:

[root@rockylinux ~]# dnf install -y bind bind-chroot
Rocky Linux 8 - AppStream                                                 3.5 kB/s | 4.8 kB     00:01    
Rocky Linux 8 - AppStream                                                 262 kB/s | 8.2 MB     00:31    
Rocky Linux 8 - BaseOS                                                    3.8 kB/s | 4.3 kB     00:01    
Rocky Linux 8 - BaseOS                                                    2.2 MB/s | 4.5 MB     00:01    
Rocky Linux 8 - Extras                                                    2.5 kB/s | 3.1 kB     00:01    
Rocky Linux 8 - Extras                                                    2.7 kB/s | 3.8 kB     00:01    
...
Total download size: 2.2 M
Installed size: 4.5 M
Downloading Packages:
(1/2): bind-chroot-9.11.26-4.el8_4.x86_64.rpm                            48 kB/s | 103 kB     00:02    
(2/2): bind-9.11.26-4.el8_4.x86_64.rpm                                   419 kB/s | 2.1 MB     00:05    

...
Installed:
  bind-32:9.11.26-4.el8_4.x86_64                                bind-chroot-32:9.11.26-4.el8_4.x86_64                                                                      

Complete!

Verify that the packages are installed as below:

[root@rockylinux ~]# rpm -qa| grep bind
bind-9.11.26-4.el8_4.x86_64
bind-export-libs-9.11.26-4.el8_4.x86_64
bind-libs-lite-9.11.26-4.el8_4.x86_64
bind-chroot-9.11.26-4.el8_4.x86_64
bind-libs-9.11.26-4.el8_4.x86_64
bind-license-9.11.26-4.el8_4.noarch
python3-bind-9.11.26-4.el8_4.noarch
bind-utils-9.11.26-4.el8_4.x86_64

The directories below will be created once you successfully install bind-chroot

[root@rockylinux ~]# ls -l /var/named/chroot/
total 0
drwxr-x---. 2 root named  6 Jun 11 03:18 dev
drwxr-x---. 5 root named 53 Aug  7 10:35 etc
drwxr-x---. 3 root named 19 Aug  7 10:35 run
drwxr-xr-x. 4 root root  32 Aug  7 10:35 usr
drwxr-x---. 5 root named 52 Aug  7 10:35 var

 

Step-2: Turn ON BIND-Chroot Environment

To turn on the bind-chroot environment, run the initialization script located at  /usr/libexec/setup-named-chroot.sh then specify the directory at which you want to jail the bind process.

[root@rockylinux ~]# /usr/libexec/setup-named-chroot.sh /var/named/chroot on

The command above mounts all BIND configuration files into the chroot location. This means that you don't have to copy any files to the chroot directory.

Verify that the paths have been mounted at /var/named/chroot

[root@rockylinux-lab network-scripts]# mount | grep chroot
/dev/mapper/rl-root on /var/named/chroot/etc/localtime type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/named.root.key type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/named.conf type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/named.rfc1912.zones type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/crypto-policies/back-ends/bind.config type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/protocols type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/services type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/named type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/usr/lib64/bind type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/usr/share/GeoIP type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)
tmpfs on /var/named/chroot/run/named type tmpfs (rw,nosuid,nodev,seclabel,mode=755)
/dev/mapper/rl-root on /var/named/chroot/var/named type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota)

 

Step-3: Configure DNS Server (named.conf)

Edit the /etc/named.conf file and make the changes at listen-on port 53, allow-query and allow-query-cache. This is as shown below:

[root@rockylinux ~]# cat /etc/named.conf

options {
        listen-on port 53 { 127.0.0.1; any; };
        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";
        recursing-file  "/var/named/data/named.recursing";
        secroots-file   "/var/named/data/named.secroots";
        allow-query     { localhost; any; };
        allow-query-cache { localhost; any; };

        recursion yes;

        dnssec-enable yes;
        dnssec-validation yes;

        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.iscdlv.key";

        managed-keys-directory "/var/named/dynamic";

        pid-file "/run/named/named.pid";
        session-keyfile "/run/named/session.key";
};

logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};

zone "." IN {
        type hint;
        file "named.ca";
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
NOTE:
Make sure that the configuration file includes named.rfc1912.zones as this is where we will define our zones

 

Step-4: Configure DNS Zones

We need to create the DNS zone for our environment. To achieve this, we need to edit the file /etc/named.rfc1912.zones.Before that, we need to check our network interfaces and choose the IP that will be used for the DNS configuration. This IP should be a static IP.

In my setup, I'll use 172.29.10.4/24 IP for DNS configuration.

To check the IP, run the ip a command and obtain the output.
Setup BIND DNS Server in Rocky Linux 8 [Step-by-Step]

Add the following lines to  /etc/named.rfc1912.zones to create the forward and reverse zones;

zone "example.com" IN {
        type master;
        file "example.com.zone";
        allow-update { none; };
};

zone "10.29.172.in-addr.arpa" IN {
        type master;
        file "example.com.rzone";
        allow-update { none; };
};

In the above config, example.comis the forward zone while 10.29.172.in-addr.arpais the reverse zone.  Make sure you use the correct details for your environment.

NOTE:
For the reverse zone, since our IP is 172.29.10.4, we have used 10.29.172.in-addr.arpa. Make sure you use the same syntax in your environment. For example, if your IP is 192.168.100.X, you should use 100.168.192.in-addr.arpa. If you have more than one subnets then create multiple entries for individual subnet and respective reverse zone files.

 

4.1: Configure Forward DNS Zone File

We need to configure the forward DNS zone files where we shall be adding entries for domain name resolution.

Navigate to /var/named/.This is where we shall configure the DNS zone files.

[root@rockylinux ~]# cd /var/named

Verify that there exist DNS files;

# ls -l
total 16
drwxr-x---. 7 root  named   61 Aug  7 10:35 chroot
drwxrwx---. 2 named named    6 Jun 11 03:18 data
drwxrwx---. 2 named named    6 Jun 11 03:18 dynamic
-rw-r-----. 1 root  named 2253 Jun 11 03:18 named.ca
-rw-r-----. 1 root  named  152 Jun 11 03:18 named.empty
-rw-r-----. 1 root  named  152 Jun 11 03:18 named.localhost
-rw-r-----. 1 root  named  168 Jun 11 03:18 named.loopback
drwxrwx---. 2 named named    6 Jun 11 03:18 slaves

Copy the named.loopback contents to example.com.zoneto create the forward zone file.

[root@rockylinux named]# cp named.loopback  example.com.zone

Assign the correct permissions to the file created

[root@rockylinux named]# chmod 644 example.com.zone
[root@rockylinux named]# chown root:named example.com.zone

Edit the forward zone file created to update the entries. In this file, you will be required to configure the A records for your hosts and their respective IPs. A sample entry as shown below:

[root@rockylinux named]# cat example.com.zone 
$TTL 1D
@	IN SOA	example.com     root (
					0	; serial
					1D	; refresh
					1H	; retry
					1W	; expire
					3H )	; minimum
		IN  NS	localhost
localhost	IN A	127.0.0.1
ns-master       IN A    172.29.10.4
server1         IN A    172.29.10.5
server2         IN A    172.29.10.6
NOTE:
Update the serial with a new value every time you do any modification to this file.

 

4.2: Create a Reverse DNS Zone File

Create a reverse DNS zone file using named.localhost

[root@rockylinux named]# cat named.localhost > example.com.rzone

Grant the correct permissions to the file created

[root@rockylinux named]# chmod 644 example.com.rzone
[root@rockylinux named]# chown root:named example.com.rzone

Update the reverse DNS records, increasing the serial number for every record you modify this file. Provide the last octet or the last number of the IP address as shown the below examples. In the below file I have added PTR record for 172.29.10.4, 172.29.10.5, 172.29.10.6 which will resolve to ns-master.example.com, server1.example.com and server2.example.com respectively.

[root@rockylinux named]# cat example.com.rzone 
$TTL 1D
@	IN SOA	example.com. root.example.com. (
				  20220521 	; serial
					1D	; refresh
					1H	; retry
					1W	; expire
					3H )	; minimum
        IN NS   localhost.
4      IN PTR  ns-master.example.com.
5      IN PTR  server1.example.com.
6      IN PTR  server2.example.com.


 

Step-5: Verify BIND chroot configuration

Verify bind configuration and confirm that you don't have any syntax errors.

[root@rockylinux named]# named-checkconf -t /var/named/ /etc/named.conf

If you get an error such as open: /etc/named.conf: file not found, verify that the contents of /var/namedare mounted at /var/named/chroot. Below is how to check and the sample output;

[root@rockylinux named]# mount | grep chroot
/dev/mapper/rl-root on /var/named/chroot/etc/named type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/usr/lib64/bind type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
tmpfs on /var/named/chroot/run/named type tmpfs (rw,nosuid,nodev,mode=755)
/dev/mapper/rl-root on /var/named/chroot/etc/localtime type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/named.root.key type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/named.conf type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/named.rfc1912.zones type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/rndc.key type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/crypto-policies/back-ends/bind.config type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/protocols type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/services type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/etc/named type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/usr/lib64/bind type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
/dev/mapper/rl-root on /var/named/chroot/usr/share/GeoIP type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
tmpfs on /var/named/chroot/run/named type tmpfs (rw,nosuid,nodev,mode=755)
/dev/mapper/rl-root on /var/named/chroot/var/named type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)

If you can't see any path mounted, re-run the named-chroot script as shown below:

[root@rockylinux ~]# /usr/libexec/setup-named-chroot.sh /var/named/chroot off
[root@rockylinux ~]# /usr/libexec/setup-named-chroot.sh /var/named/chroot on

 

Step-6: Start named-chroot service

The named-chroot service runs the same way as the default bind service, other than the fact that it is running in a jail environment. Before we can start the named-chroot service, make sure you have stopped and disabled the default named service.

[root@rockylinux named]# systemctl stop named
[root@rockylinux named]# systemctl disable named

Start and enable the named-chroot service

[root@rockylinux named]# systemctl enable --now named-chroot

Verify that the service has started successfully and is running

[root@rockylinux-lab named]# systemctl status named-chroot
● named-chroot.service - Berkeley Internet Name Domain (DNS)
   Loaded: loaded (/usr/lib/systemd/system/named-chroot.service; disabled; vendor preset: disabled)
   Active: active (running) since Sat 2021-08-07 12:53:50 EAT; 14s ago
  Process: 1726 ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} -t /var/named/chroot $OPTIONS (code=exited, status=0/SUCCESS)
  Process: 1721 ExecStartPre=/bin/bash -c if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -t /var/named/chroot -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi (cod>
 Main PID: 1728 (named)
    Tasks: 7 (limit: 4942)
   Memory: 64.0M
   CGroup: /system.slice/named-chroot.service
           └─1728 /usr/sbin/named -u named -c /etc/named.conf -t /var/named/chroot

Aug 07 12:53:50 rockylinux-lab named[1728]: network unreachable resolving './NS/IN': 2001:7fd::1#53
Aug 07 12:53:50 rockylinux-lab named[1728]: network unreachable resolving './DNSKEY/IN': 2001:503:c27::2:30#53
Aug 07 12:53:50 rockylinux-lab named[1728]: network unreachable resolving './NS/IN': 2001:503:c27::2:30#53
Aug 07 12:53:50 rockylinux-lab named[1728]: network unreachable resolving './DNSKEY/IN': 2001:500:9f::42#53
Aug 07 12:53:50 rockylinux-lab named[1728]: network unreachable resolving './NS/IN': 2001:500:9f::42#53
Aug 07 12:53:50 rockylinux-lab named[1728]: network unreachable resolving './DNSKEY/IN': 2001:500:a8::e#53
Aug 07 12:53:50 rockylinux-lab named[1728]: network unreachable resolving './DNSKEY/IN': 2001:dc3::35#53
Aug 07 12:53:50 rockylinux-lab named[1728]: managed-keys-zone: Key 20326 for zone . acceptance timer complete: key now trusted
Aug 07 12:53:50 rockylinux-lab named[1728]: network unreachable resolving './DNSKEY/IN': 2001:500:9f::42#53
Aug 07 12:53:51 rockylinux-lab named[1728]: resolver priming query complete

 

Step-7: Configure Rocky Linux 8 node as DNS Client

We can now configure the DNS server on Rocky Linux to verify domain resolution.

Add a DNS entry to /etc/resolv.conf file as shown below:

[root@rockylinux-lab named]# echo "nameserver 172.29.10.4" >> /etc/resolv.conf

Remember to use the IP of the DNS server we configured above.

 

Step-8: Test DNS Configuration from Client

8.1: Test forward lookup zone

We can now check domain name resolution using our DNS server as shown below:

[root@rockylinux-lab named]# nslookup server1.example.com
Server:		172.29.10.4
Address:	172.29.10.4#53

Name:	server1.example.com
Address: 172.29.10.5

 

8.2: Test reverse lookup zone

We can also use the dig command to get the reverse DNS information about the domain name as below. Look out for ANSWER section:

[root@rockylinux-lab ~]# dig -x 172.29.10.5

; <<>> DiG 9.11.26-RedHat-9.11.26-4.el8_4 <<>> -x 172.29.10.5
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23231
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: db03e58df53932aa0d10867c610e842dd8934fbd301f97fb (good)
;; QUESTION SECTION:
;5.10.29.172.in-addr.arpa.	IN	PTR

;; ANSWER SECTION:
5.10.29.172.in-addr.arpa. 86400	IN	PTR	server1.example.com.

;; AUTHORITY SECTION:
10.29.172.in-addr.arpa.	86400	IN	NS	localhost.

;; ADDITIONAL SECTION:
localhost.		86400	IN	A	127.0.0.1
localhost.		86400	IN	AAAA	::1

;; Query time: 1 msec
;; SERVER: 172.29.10.4#53(172.29.10.4)
;; WHEN: Sat Aug 07 16:01:33 EAT 2021
;; MSG SIZE  rcvd: 181

As we can see, name resolution is working, just as expected.

 

Conclusion

I hope this article has been elaborate enough, we have configured bind-chroot DNS server on Rocky Linux 8. Feel free to reach out in the comment section in case you have any concerns.

 

Deepak Prasad

Deepak Prasad

Deepak Prasad is the founder of GoLinuxCloud, bringing over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, Networking, and Security. His extensive experience spans development, DevOps, networking, and security, ensuring robust and efficient solutions for diverse projects.

Certifications and Credentials:

  • Certified Kubernetes Application Developer (CKAD)
  • Go Developer Certification
  • Linux Foundation Certified System Administrator (LFCS)
  • Certified Ethical Hacker (CEH)
  • Python Institute PCAP (Certified Associate in Python Programming)
You can connect with him on his LinkedIn profile and join his Facebook and LinkedIn page.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

4 thoughts on “Setup BIND DNS Server in Rocky Linux 8 [Step-by-Step]”

  1. You could have saved me hours of googling if you used the words “last octet” or last number of the IP address” instead of “serial” in step 4.2. Although to be fair, after said hours and hundreds of pages of blogs and other versions of this procedure, not one soul until user1686 on superuser dot com hinted me into finally realizing it is the last octet!
    If you could add a little diagram or strong indicator that that number is not a serial number nor index, but rather the last part of the IP address corresponding directly to the named server IP and that it alone belongs squarely in the left column of the reverse lookup zone file, this procedure will be 100% perfect.

    My sleep deprived self thought the parenthesis line counted as one line and thus the line with the 4 was the 4th entry and it was just a counting correlating to some serial mandated by a config rule…until I saw others counting with different numbers, although always incrementing by one from where they started. As I found out, the numbers can be completely out of order, which frankly, one example of that would have clued me in too.

    Seriously, usually I see you have a procedure for something I want to do and I’m like “yes, this will make my life easier.”

    Oh, also Step 5 should be named-checkconf -t /var/named/ /etc/named.conf. Minor, but I did confirm with the man pages. Threw me for a much smaller loop, that one. Take care!

    Reply
    • Thank you for your detailed feedback and I am sorry for the extra effort you had to spent. I completely agree that I should have added those hints but somehow I missed. I have updated the article based on your feedback and added some hints in other places as well. Let me know if anything further can be added to improvise the quality here.

      Reply
      • You’re very welcome!

        Update: I think this is what is needed at the beginning of step 5:

        [root@server1 named]# # named-checkconf -t /var/named/chroot/ /etc/named.conf

        or

        [root@server1 named]# # named-checkconf -t /var/named/chroot /etc/named.conf

        Works with our without the trailing ‘/‘ on /var/named/chroot.

        Kind Regards!

        Reply

Leave a Comment