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";
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]](/setup-bind-dns-server-rocky-linux-8/rocky-3.webp)
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.
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-masterIN A172.29.10.4
server1 IN A 172.29.10.5
server2 IN A 172.29.10.6
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 PTRns-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.

![Setup BIND DNS Server in Rocky Linux 8 [Step-by-Step]](/setup-bind-dns-server-rocky-linux-8/setup_dns_server.jpg)
