Introduction
We are going to setup and confgure a DNS server with a failover and dynamic updates on RockyLinux using BIND.
named stands for NAMEserver Daemon.
The Bind packages is called named in the RedHat-like distribution like RockyLinux.
Prerequisites
Two VMs with RockyLinux with the following configurations
| Hostname | IP address | Roles | SELinux | FirewallD |
|---|---|---|---|---|
| admin1.hl.test | 10.10.0.2/24 | Master DNS | Enforcing | Enabled |
| admin2.hl.test | 10.10.0.3/24 | Backup DNS | Enforcing | Enabled |
The Plan
- Install the required packages on both servers
- RNDC Setup
- Configure Master DNS
- Configure Backup DNS
- Configure a client server for testing
Primary configuration on the nodes
On both server, install the following packages
sudo dnf install bind bind-utils -y
Let's make sure that the service is enabled at startup.
sudo systemctl enable named
Allow DNS traffic
sudo firewall-cmd --add-service=dns --permanent
sudo firewall-cmd --reload
Setup the log directory for named
sudo mkdir -p -m 0700 /var/log/named
sudo chown named:named /var/log/named
sudo ls -ldh /var/log/named
RNDC Setup
Check out this great book for more information about DNS and other System Administration stuff.

RNDC or "Remote Name Daemon Control Utility". It's a command that allows you to control you Domain Name System (DNS) without altering or modifying you DNS configuration files.
To use the rndc command, we must first generate a key and then import it into the named configuration file.
Let's create a key
sudo rndc-confgen -a -b 512
We need to give it appropriate permissions.
chown root:named /etc/rndc.key
chmod 0640 /etc/rndc.key
Master DNS configuration
We will seperate our configuration into multiple files and use include statement to embed these files into /etc/named.conf file. This will help us seperate the the parts of the configuraton that are static from those that can be changed overtime.
sudo tree /etc/named --noreport
The main configuration file
the main configuration file for named is /etc/named.conf, open this file and add the following content
# vim: syntax=named
# Include RFC 1912 compliant zone files
include "/etc/named.rfc1912.zones";
# Include root DNSSEC trust anchor key
include "/etc/named.root.key";
# Include rndc key for remote control of named
include "/etc/rndc.key";
# Include zones configuration file
include "/etc/named/zones.conf";
# Include logging configuration file
include "/etc/named/logging.conf";
# Allow rndc management on localhost using rndc-key
controls {
inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; };
};
# Limit access to trusted networks
acl "trusted" {
# Allow loopback addresses
127.0.0.0/8;
# Add local LAN subnet(s)
10.10.0.0/24;
};
# Set global options
options {
# Listen on port 53 for requests from localhost and 10.10.0.2 (MASTER)
listen-on port 53 { 127.0.0.1; 10.10.0.2; };
# Disable IPv6
listen-on-v6 port 53 { none; };
# Set directory for zone files, cache dump, stats, and root DNSSEC trust anchors
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";
# Disable built-in server information zones
version none;
hostname none;
server-id none;
# Enable recursion and allow queries from trusted networks only
recursion yes;
allow-recursion { trusted; };
allow-query { trusted; };
# Allow zone transfers from localhost and 10.10.0.3 (SLAVE)
allow-transfer { localhost; 10.10.0.3; };
# Enable DNSSEC validation
dnssec-validation yes;
# Set directory for managed keys
managed-keys-directory "/var/named/dynamic";
# Set directory for GeoIP data
geoip-directory "/usr/share/GeoIP";
# Set PID file and session key file
pid-file "/run/named/named.pid";
session-keyfile "/run/named/session.key";
# Include bind crypto policies configuration
include "/etc/crypto-policies/back-ends/bind.config";
};
The zones configuration file
Here we define our zones; each zone must have its corresponding reverse zone
In our case, we need to setup a forward zone and a reverse zone for our local domain hl.test. All data related to this zones is saved on /data/db.hl.test and /data=db.0.10.10 respectively.
[!NOTE] Of course, you can use whatever filename with the
fileclause in thezonesection, here I chose to usedb.hl.testanddb.0.10.10for example.reverse zone is indentified as follow:
<subnet ip in reverse>.in-addr.arpa
in-addr.arpais a fixed suffix.
# vim: syntax=named
# Use the root hints file for "." zone
zone "." IN {
type hint;
file "named.ca";
};
# Internal zone definitions
zone "hl.test" {
type master;
file "data/db.hl.test";
# Allow updates with rndc key
allow-update { key rndc-key; };
# Notify slave servers when zone changes
notify yes;
};
# Reverse DNS zone for 10.10.0.0/16 subnet
zone "0.10.10.in-addr.arpa" {
type master;
file "data/db.0.10.10";
# Allow updates with rndc key
allow-update { key rndc-key; };
# Notify slave servers when zone changes
notify yes;
};
Our DNS records are stored in files that act as a database on the primary server and called the Zones files. The secondary server fetches this data regularly for consistency.
[!NOTE] Hence, the full path is
/var/named/data/db.hl.test
As you can see from the zones configuration we used above, we ordered our server to fetch it's records data from data/db.hl.test.
Of course, this path is relative, because we mentioned the root directory in the main configuration above with =directory "/var/named"=
The forward zone records.
[!NOTE] Make sure to update the
Serialnumber in the zone files file every time it is modified. This allows Bind to recognize that a change has been made.
; vim: ft=bindzone
$TTL 86400 ; 1 day
@ IN SOA dns1.hl.test. root.hl.test. (
3 ; Serial
3600 ; Refresh (1 hour)
3600 ; Retry (1 hour)
604800 ; Expire (1 week)
3600 ; Minimum (1 hour)
)
; name servers -- NS records
@ IN NS ns1.hl.test.
@ IN NS ns2.hl.test.
; name servers -- A records
ns1.hl.test. IN A 10.10.0.2
ns2.hl.test. IN A 10.10.0.3
; 10.10.0.0/24 -- A records
admin1.hl.test. IN A 10.10.0.2
admin2.hl.test. IN A 10.10.0.3
And then, the reverse zone records
; vim: ft=bindzone
;
; BIND reverse data file for broadcast zone
;
$TTL 604800
@ IN SOA hl.test. root.hl.test. (
3 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
; name servers
IN NS ns1.hl.test.
IN NS ns2.hl.test.
; PTR Records
2 IN PTR ns1.hl.test. ; 10.10.0.2
3 IN PTR ns2.hl.test. ; 10.10.0.2
2 IN PTR admin1.hl.test. ; 10.10.0.2
3 IN PTR admin2.hl.test. ; 10.10.0.2
The logging configuration file
And the logging configuration file
# vim: syntax=named
# Logging configuration
logging {
# Default debug channel
channel default_debug {
file "data/named.run";
severity dynamic;
};
# Common log channel
channel "common_log" {
file "/var/log/named/named.log" versions 10 size 5m;
severity dynamic;
print-category yes;
print-severity yes;
print-time yes;
};
# Categories for logging
category default { "common_log"; };
category general { "common_log"; };
category queries { "common_log"; };
category client { "common_log"; };
category security { "common_log"; };
category query-errors { "common_log"; };
category lame-servers { null; };
};
Backup DNS configuration
The main configuration file
Now with the backup DNS configuration
# vim: syntax=named
# Include RFC 1912 compliant zone files
include "/etc/named.rfc1912.zones";
# Include root DNSSEC trust anchor key
include "/etc/named.root.key";
# Include zones configuration file
include "/etc/named/zones.conf";
# Include logging configuration file
include "/etc/named/logging.conf";
# Limit access to trusted networks
acl "trusted" {
# Allow loopback addresses
127.0.0.0/8;
# Add local LAN subnet(s)
10.10.0.0/24;
};
# Set global options
options {
# Listen on port 53 for requests from localhost and 10.10.0.3 (SLAVE)
listen-on port 53 { 127.0.0.1; 10.10.0.3; };
# Disable IPv6
listen-on-v6 port 53 { none; };
# Set directory for zone files, cache dump, stats, and root DNSSEC trust anchors
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";
# Disable built-in server information zones
version none;
hostname none;
server-id none;
# Enable recursion and allow queries from trusted networks only
recursion yes;
allow-recursion { trusted; };
allow-query { trusted; };
allow-transfer { none };
# Enable DNSSEC validation
dnssec-validation yes;
# Set directory for managed keys
managed-keys-directory "/var/named/dynamic";
# Set directory for GeoIP data
geoip-directory "/usr/share/GeoIP";
# Set PID file and session key file
pid-file "/run/named/named.pid";
session-keyfile "/run/named/session.key";
# Include bind crypto policies configuration
include "/etc/crypto-policies/back-ends/bind.config";
};
The zones configuration file
# vim: syntax=named
# Use the root hints file for "." zone
zone "." IN {
type hint;
file "named.ca";
};
# Internal zone definitions
zone "hl.test" {
type slave;
file "data/db.hl.test";
masters { 10.10.0.2; };
allow-notify { 10.10.0.2; };
};
zone "0.10.10.in-addr.arpa" {
type slave;
file "data/db.0.10.10";
masters { 10.10.0.2; };
allow-notify { 10.10.0.2; };
};
The logging configuration file
And then the logging configuration file.
# vim: syntax=named
# Logging configuration
logging {
# Default debug channel
channel default_debug {
file "data/named.run";
severity dynamic;
};
# Common log channel
channel "common_log" {
file "/var/log/named/named.log" versions 10 size 5m;
severity dynamic;
print-category yes;
print-severity yes;
print-time yes;
};
# Categories for logging
category default { "common_log"; };
category general { "common_log"; };
category queries { "common_log"; };
category client { "common_log"; };
category security { "common_log"; };
category query-errors { "common_log"; };
category lame-servers { null; };
};
Configure a client server
Note
- The number of nameservers allowed on
/etc/resolv.confare 3. - The first request are tried against the first nameserver, if the query was timed out, it will move to the next.
- Each nameserver is tried 4 times.
To configure the client, all we need to do is to update the /etc/resolv.conf file with the IP addresses of our new local DNS server.
sudo nmcli c mod eth0 ipv4.dns '10.10.0.2 10.10.0.3'
cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 10.10.0.2
nameserver 10.10.0.3