The bind DNS server is massive, so we’re only going to cover some basic necessities commonly found for it today.
As previously mentioned, the most common use for the bind DNS server is for forwarding and caching:
Configuring BIND as a caching DNS server
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/managing_networking_infrastructure_services/assembly_setting-up-and-configuring-a-bind-dns-server_networking-infrastructure-services#proc_configuring-bind-as-a-caching-dns-server_assembly_setting-up-and-configuring-a-bind-dns-server
However, in most situations there are 5 typical “Needs” for a DNS server to fulfill:
Need 1: client machines need to be able to resolve each other’s hostnames (resolve local network hostnames within the internal business domain both forward and reverse)
Need 2: client machines need to be able to resolve the internal webserver’s subdomain and/or IP (resolve web application subdomain within the internal business domain both forward and reverse)
Need 3: client machines need to be able to resolve internet domains as well (resolve external internet domains)
Need 4: client machines need DNS caching (cache all DNS query results for faster DNS performance)
Need 5: We’re paranoid, we want our DNS server to run in a chroot (run our DNS server in a chrooted environment)
Let’s set up an example.
- We have 3 servers on our network, all under the internal domain fakedomain.dev
- One is our DNS server (rhel92)
- One is a webserver hosting a custom subdomain used for an internal web application (rhel89)
- One is just a desktop machine used by the office staff to perform work on the internal web application (rhel88)
You’re going to want to do two things here.
1. Setup caching + forwarding locally on the 2 servers that are -not- the DNS server with something lightweight like dnsmasq or unbound.
Set the forward nameserver to your BIND dns server. In our example our BIND server’s IP is 192.168.0.66
rhel89, rhel88:
# dnf install dnsmasq
# systemctl enable --now dnsmasq
# echo 'nameserver 127.0.0.1' > /etc/resolv.conf
# echo 'options edns0' >> /etc/resolv.conf
# echo 'resolv-file=/etc/resolv.dnsmasq' >> /etc/dnsmasq.conf
# echo 'cache-size=1000' >> /etc/dnsmasq.conf
# echo 'interface=lo' >> /etc/dnsmasq.conf
# echo 'bind-interfaces' >> /etc/dnsmasq.conf
# echo 'nameserver 192.168.0.66' > /etc/resolv.dnsmasq
# systemctl restart dnsmasq
We didn’t use all of the options required for dnsmasq in our example, just a few for basic functionality. It’s advised to follow along here for proper configuration:
How to configure DNS caching server with dnsmasq in RHEL
https://access.redhat.com/solutions/2189401
Alternatively you could just point all of the servers to the DNS server IP, but then you would be missing per-machine DNS caching. Having something like DNS or unbound running on each machine before it forwards to the DNS server allows each machine to have their own personal cache on the client side. The BIND DNS nameserver itself will also have caching itself for the server side.
☑ This resolves “Need 4” in the list. (cache all DNS query results for faster DNS performance)
When each server queries for another server’s hostname, we also need to search under the domain ‘fakedomain.dev’
So we need to add these additional /etc/resolv.conf lines to all machines:
# echo 'search .fakedomain.dev' >> /etc/resolv.conf
All 3 machines should have an /etc/resolv.conf that looks like this:
nameserver 127.0.0.1
options edns0
search fakedomain.dev
And on each server we need to make sure to set the fqdn:
# hostname rhel88.fakedomain.dev
# hostname rhel89.fakedomain.dev
# hostname rhel92.fakedomain.dev
These steps are part of the requirements for “Need 1” and “Need 2“.
2. By default, the BIND DNS server has caching, we just need to configure two things:
- Configure forwarding external internet queries
- Configure our internal domain and hostnames (and webserver subdomain)
This will allow our bind dns server to answer queries from the other four systems for both internal and external domains.
On the bind dns server (rhel92):
# dnf install bind bind-chroot bind-utils
# echo 'nameserver 127.0.0.1' > /etc/resolv.conf
And enable dns access in our firewall:
# firewall-cmd --permanent --add-service=dns
# firewall-cmd --reload
First, let’s edit our configuration file to allow caching and forwarding of external internet domain queries:
Configuring BIND as a caching DNS server
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/managing_networking_infrastructure_services/assembly_setting-up-and-configuring-a-bind-dns-server_networking-infrastructure-services#proc_configuring-bind-as-a-caching-dns-server_assembly_setting-up-and-configuring-a-bind-dns-server
Note in the example below ‘….’ is just to show skipping of unrelated configurations. They are not part of the configuration file.
# vim /etc/named.conf
options {
....
listen-on port 53 { 127.0.0.1;192.168.0.66; };
allow-query { localhost; 192.168.0/24; };
allow-recursion { localhost; 192.168.0/24; };
forwarders { 8.8.8.8;8.8.4.4; }; # forward unknown domains to google dns servers
....
}
This tells our nameserver:
- Listen on localhost and on IP 192.168.0.66
- Allow queries and recursion only from localhost and any IP address in the 192.168.0.* range.
- Forward unknown queries to google
So, with this we should be able to resolve something like www.redhat.com from all 3 machines:
rhel88, rhel89 dnsmasq caching -> bind dns server:
[root@rhel88 ~]# nslookup redhat.com
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
Name: redhat.com
Address: 52.200.142.250
Name: redhat.com
Address: 34.235.198.240
[root@rhel89 ~]# nslookup redhat.com
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
Name: redhat.com
Address: 52.200.142.250
Name: redhat.com
Address: 34.235.198.240
and our bind server rhel92 directly:
[root@rhel92 ~]# nslookup redhat.com
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
Name: redhat.com
Address: 34.235.198.240
Name: redhat.com
Address: 52.200.142.250
☑ Great! This resolves “Need 3” in the list. (resolve external internet domains)
3. Now, we need them to be able to resolve eachother’s hostnames within fakedomain.dev
The RHEL admin manual tells you how to create records for new zones:
4.6.2. Setting up a forward zone on a BIND primary server
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/deploying_different_types_of_servers/assembly_setting-up-and-configuring-a-bind-dns-server_deploying-different-types-of-servers#proc_setting-up-a-forward-zone-on-a-bind-primary-server_assembly_configuring-zones-on-a-bind-dns-server
Once again, let’s open up /etc/named.conf.
This time we’re going to go to the bottom and add another zone:
# vim /etc/named.conf
zone "fakedomain.dev" {
type master;
file "fakedomain.dev.zone";
};
Save and close the file. Next we need to create ‘fakedomain.dev.zone’ and fill it with records. Again — continue following the ‘4.6.2. Setting up a forward zone on a BIND primary server’ directions, step 3:
Create the /var/named/fakedomain.dev.zone file, for example, with the following content:
$TTL 8h
@ IN SOA ns1.fakedomain.dev. fakedomain.dev. (
2022070601 ; serial number
1d ; refresh period
3h ; retry period
3d ; expire time
3h ) ; minimum TTL
IN NS ns1.fakedomain.dev.
ns1 IN A 192.168.0.66
rhel92 IN A 192.168.0.66
We have to add the ns1 entry for our nameserver because as noted in the admin manual to be functional, a zone requires at least one name server (NS) record.
We also add the A record so that our DNS server IP resolves to it’s hostname (rhel92.fakedomain.dev)
After that, reload named:
# systemctl reload named
And NOW — verify our hostname lookup works locally on the bind server:
[root@rhel92 ~]# nslookup rhel92
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: rhel92.fakedomain.dev
Address: 192.168.0.66
Now we need to map the other two servers and the subdomain for our webapp to our records:
Once again open the zone file, and add our entries:
# vim /var/named/fakedomain.dev.zone
.....
$TTL 8h
@ IN SOA ns1.fakedomain.dev. fakedomain.dev. (
2022070601 ; serial number
1d ; refresh period
3h ; retry period
3d ; expire time
3h ) ; minimum TTL
IN NS ns1.fakedomain.dev.
ns1 IN A 192.168.0.66
rhel92 IN A 192.168.0.66
rhel89 IN A 192.168.0.63
webapp IN A 192.168.0.63
rhel88 IN A 192.168.0.67
.....
Remember, our rhel89 system is a webserver, which hosts a custom webapp within our organization’s subdomain, this is why both the ‘rhel89.fakedomain.dev’ and ‘webapp.fakedomain.dev’ both point to the same IP.
Save and close the file, reload the service:
# systemctl reload named
And now, magically all of our systems should be able to resolve any of those addresses:
rhel92:
[root@rhel92 ~]# nslookup rhel88
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: rhel88.fakedomain.dev
Address: 192.168.0.67
[root@rhel92 ~]# nslookup rhel89
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: rhel89.fakedomain.dev
Address: 192.168.0.63
[root@rhel92 ~]# nslookup webapp
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: webapp.fakedomain.dev
Address: 192.168.0.63
rhel89:
[root@rhel89 ~]# nslookup rhel92
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: rhel92.fakedomain.dev
Address: 192.168.0.66
[root@rhel89 ~]# nslookup rhel89
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: rhel89.fakedomain.dev
Address: 192.168.0.63
[root@rhel89 ~]# nslookup webapp
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: webapp.fakedomain.dev
Address: 192.168.0.63
rhel88:
[root@rhel88 ~]# nslookup rhel92
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: rhel92.fakedomain.dev
Address: 192.168.0.66
[root@rhel88 ~]# nslookup rhel89
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: rhel89.fakedomain.dev
Address: 192.168.0.63
[root@rhel88 ~]# nslookup webapp
Server: 127.0.0.1
Address: 127.0.0.1#53
Name: webapp.fakedomain.dev
Address: 192.168.0.63
That handles forward lookups for “Need 1” and “Need 2” but we still need reverse lookups for looking up domains based on IP address.
Again, RHEL admin manual has you covered:
4.6.3. Setting up a reverse zone on a BIND primary server
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/deploying_different_types_of_servers/assembly_setting-up-and-configuring-a-bind-dns-server_deploying-different-types-of-servers#proc_setting-up-a-reverse-zone-on-a-bind-primary-server_assembly_configuring-zones-on-a-bind-dns-server
Open /etc/named.conf again and:
# vim /etc/named.conf
....
zone "0.168.192.in-addr.arpa" {
type master;
file "0.168.192.in-addr.arpa.zone";
};
....
Save and close the file.
This will add a reverse lookup entry for addresses starting with 192.168.0.*.
Now just like our forward zone, we need to make a zone record file for our reverse lookups:
# vim /var/named/0.168.192.in-addr.arpa.zone
....
$TTL 8h
@ IN SOA ns1.fakedomain.dev. fakedomain.dev. (
2022070601 ; serial number
1d ; refresh period
3h ; retry period
3d ; expire time
3h ) ; minimum TTL
IN NS ns1.fakedomain.dev.
66 IN PTR ns1.fakedomain.dev.
66 IN PTR rhel92.fakedomain.dev.
63 IN PTR rhel89.fakedomain.dev.
63 IN PTR webapp.fakedomain.dev.
67 IN PTR rhel88.fakedomain.dev.
....
Again, save and reload named.service:
# systemctl reload named.service
Voila, now any of our servers can do reverse lookups via IP:
[root@rhel92 ~]# nslookup 192.168.0.63
63.0.168.192.in-addr.arpa name = webapp.fakedomain.dev.
63.0.168.192.in-addr.arpa name = rhel89.fakedomain.dev.
[root@rhel92 ~]# nslookup 192.168.0.67
67.0.168.192.in-addr.arpa name = rhel88.fakedomain.dev.
[root@rhel92 ~]# nslookup 192.168.0.66
66.0.168.192.in-addr.arpa name = ns1.fakedomain.dev.
66.0.168.192.in-addr.arpa name = rhel92.fakedomain.dev.
These are now covered:
☑ Need 1: (resolve local network hostnames within the internal business domain both forward and reverse)
☑ Need 2: (resolve web application subdomain within the internal business domain both forward and reverse)
4. Ok, we’ve walked through and completed Needs 1,2,3 and 4, now we’re on the final “Need 5“. We need bind to run in a chroot environment. This is simple.
Shut down and disable named.service:
[root@rhel92 ~]# systemctl stop named
[root@rhel92 ~]# systemctl disable named
Start and enable named-chroot.service:
[root@rhel92 ~]# systemctl enable --now named-chroot.service
Finally, our last requirement has now been fulfilled:
☑ Need 5: (run our DNS server in a chrooted environment)
IMPORTANT THING TO REMEMBER:
With named-chroot.service a chroot is created at /var/named/chroot/
Inside this chroot is the new ‘var/named’ directory. Our zone records from the standard named instance get copied here upon the first startup AND/OR reload of the named-chroot service.
Some customers will have different copies in /var/named/ from /var/named/chroot/var/named/ so it’s important to determine if they are using named-chroot or not and get copies from BOTH directories.