Install a DNS Server with a Shell Script (Linux Automation — Part I)
When I set up a Red Hat virtual machine for the first time and got to the software installation part of the set-up, the automator in me wondered if there was a way to set up all of this software with my own scripts. Turns out, there is! :)
I started off by following a tutorial video on how to set up a DNS server. The video lasts about 15 minutes but the script took a few days to debug. It is my belief that half the battle in shell scripting is figuring out how text manipulation works (the “sed”, “awk” and “cut” commands.)
Fortunately, I’m willing to put in the work so you don’t have to. :)
This tutorial series will be broken down into explanations of each section of the scripts, screenshots of terminal commands, before-and-after screenshots and the complete scripts.
It is good practice to start the script with a shebang (#!/bin/bash) — in case you’re working on a Linux system that is not configured with the Bash shell by default — and an update of the system (the -y option automatically answers “yes” to future questions, such as “Are you sure? [y/N]”.)
If you’re using this section for testing purposes, then this is optional. This section of the script modifies the domain name of the system. The default domain name is “localdomain”.
The “hostname” command prints the fully qualified domain name (FQDN) of the system, which is a combo of the hostname and the domain name.
The “awk” command above divides the FQDN by the period “.” and prints the second column of text, which is the domain name.
The “ip -o link show” command prints the system’s network interfaces. The command concatenated with the “awk” command makes the text more condensed and readable.
There are four network interfaces on my system: the loopback interface (“lo”), Ethernet interface (“enp0s3”) and the virtual bridge interfaces (“virbr0” and “virbr0-nic”.)
Of course, I will be using the Ethernet interface to configure the DNS server with.
There are four files that will be configured for this tutorial (the fourth file will be mentioned later.)
The three files mentioned in this sections are:
- “/etc/named.conf” = the DNS server’s configuration file
- “/var/named/forward.[domain name]” = the DNS server’s forward zone file
- “/var/named/reverse.[domain name]” = the DNS server’s reverse zone file
The forward zone file points the hosts in the forward zone, a.k.a. the domain, to their respective IPv4 addresses with “A” records.
The reverse zone file provides the ability to do reverse lookups by pointing IPv4 addresses to their respective hosts.
The “read” command in the script is a will allow you to enter the name of the network interface of your choosing.
The “ifconfig enp0s3” command prints networking information about the Ethernet interface. Concatenated with the “awk” command, it prints only the Ethernet interface’s IPv4 address (‘awk -F‘ ’ ‘FNR == 2 {print $2}’’ prints the second row and the second column of text that is separated by a space, ‘ ’).
The “net_int_ip” variable is the IPv4 address of the Ethernet interface.
The “echo” command points the Ethernet interface’s IPv4 address to the system’s FQDN and saves this to the “/etc/hosts” file, the fourth file that was mentioned earlier.
The “oct_1”, “oct_2”, etc. variables are the octets of the IPv4 address.
The “first_3_oct_reverse” variable reverses the first 3 octets of the IPv4 address. This will come in handy when we configure the reverse lookup zone in the “/etc/named.conf” file.
The “desktop_ip” variable is the IPv4 address of a host that would be in the domain.
The “bind” package installs the DNS server. The “bind-utils” package allows you to query the DNS server.
If you like more information on a particular package, use the “rpm -qi [name of package]” command.
This is where the part of learning how shell scripting works got interesting. I wanted to insert the IP address at a specific position in the “/etc/named.conf” file.
To break down this command, the “-i” option inserts the text, “13” is the line number in the file where I want to insert the text, “32” is the index of the line where I want to insert the text (meaning, the first letter of the text that I want to insert will be the 32nd character of the line) and “$_net_int_ip;” is the “net_int_ip” variable (the “/etc/named.conf” requires a “;” at the end of the IP address.)
This is an array and a for-loop that sends 4 commands to the firewall. I could’ve just written out the firewall rules as such:
firewall-cmd --add-port=53/tcp --permanent --zone=public
firewall-cmd --add-port=53/udp --permanent --zone=public
firewall-cmd --reload
firewall-cmd --list-all
However, I created the array and for-loop to avoid repetitiveness.
The “\” in the array splits it in two so that you will be able to see the entire array, since I didn’t configure my Nano text editor to wrap words.
This is another array and for-loop that configures the system to start the DNS server during bootup, start the DNS server right now and show the status of the DNS server.
This section looks like a lot but it’s actually simple; it inserts the forward and reverse lookup zones in the “/etc/named.conf” file. Below is what the script did.
This section creates a file for the forward lookup zone by creating a copy of the “/var/named/named.localhost” file, renaming it after the variable that I created earlier (forward_file=“/var/named/forward.[domain name]”) and entering the DNS records of the domain name and IP address at the end of the file.
This section creates the reverse lookup zone file by making a copy of the forward lookup zone file and renaming it, using the “$reverse_file” variable I made earlier.
This section configures “root” as the user and “named” as the group that owns the forward and reverse lookup zone files, checks the validity of the files we just configured and restarts the DNS server so that the configurations will be implemented.
To execute the shell script, I use the “sudo sh [file path of the script]” command since there are some commands in the script that require root access, like the firewall commands and editing files in the /var and /etc directories.
Based on the output, the shell script’s DNS server configuration was successful. Below is the shell script in full:
#!/bin/bash
# Update the metadata of the yum repository.
yum update -y# Configure a domain name for your system.
host_name=$(hostname | awk -F”.” ‘{print $1}’)
echo ‘Enter a new domain name for your system: ‘
read -r “domain_name”
hostnamectl — static set-hostname “${host_name}.$domain_name”
fqdomain_name=$(hostname)# Assign the configuration files to variables.
named_file=”/etc/named.conf”
forward_file=”/var/named/forward.$domain_name”
reverse_file=”/var/named/reverse.$domain_name”# List the available network interfaces.
net_int=$(ip -o link show | awk -F’: ‘ ‘{print $2}’)
echo $net_intecho ‘Enter the network interface to configure the DNS server with: ‘
read -r “net_int_name”# Assign IP addresses to variables.
net_int_ip=$(ifconfig $net_int_name | awk -F’ ‘ ‘FNR == 2 {print $2}’)
echo “${net_int_ip} ${fqdomain_name}” >> /etc/hosts
oct_1=$(expr $net_int_ip | cut -d”.” -f1)
oct_2=$(expr $net_int_ip | cut -d”.” -f2)
oct_3=$(expr $net_int_ip | cut -d”.” -f3)
oct_4=$(expr $net_int_ip | cut -d”.” -f4)
first_3_oct_reverse=”${oct_3}.${oct_2}.${oct_1}”
desktop_ip=”${oct_1}.${oct_2}.${oct_3}.$(expr $oct_4–1)”# Install the packages for the DNS server.
yum install -y bind bind-utils# Configure the “named” server configuration file with the IP address at line 13.
sed -i “13s/^\(.\{32\}\)/\1$net_int_ip; /” $named_file# Enable a firewall rule that permits DNS traffic.
firewall_array=(‘ — add-port=53/tcp — permanent — zone=public’ ‘ — add-port=53/udp — permanent — zone=public’ ‘ — reload’ ‘ — list-all’)
for i in ${firewall_array[@]}
do
firewall-cmd $i
done# Enable, start and verify the status of the “named” server.
named_array=(‘enable’ ‘start’ ‘ — no-pager status’)
for i in ${named_array[@]}
do
systemctl $i named
done# Configure a primary zone for the DNS server.
# Insert 12 blank lines at line 59.
sed -i ‘59s/^/\n\n\n\n\n\n\n\n\n\n\n\n/’ $named_file# Insert ‘zone “[domain name]” IN {‘ at line 59
sed -i ‘59s/^/” IN {/’ $named_file
sed -i “59s/^/$domain_name/” $named_file
sed -i ‘59s/^/zone “/’ $named_file# Insert ‘ type master;’ at line 60
sed -i ‘60s/^/\t type master;/’ $named_file# Insert ‘ file “forward.[domain name]”;’ at line 61
sed -i ‘61s/^/”;/’ $named_file
sed -i “61s/^/$domain_name/” $named_file
sed -i ‘61s/^/ \t file “forward./’ $named_file# Insert ‘ allow-update { none; };’ at line 62
sed -i ‘62s/^/ \t allow-update { none; };/’ $named_file# Insert ‘};’ at line 63
sed -i ‘63s/^/};/’ $named_file# Configure a reverse lookup zone for the DNS server.
# Insert ‘zone “[first 3 octets of IP address in reverse].in-addr.arpa” IN {‘ at line 65
sed -i ‘65s/^/.in-addr.arpa” IN {/’ $named_file
sed -i “65s/^/$first_3_oct_reverse/” $named_file
sed -i ‘65s/^/zone “/’ $named_file# Insert ‘ type master;’ at line 66.
sed -i ‘66s/^/\t type master;/’ $named_file# Insert ‘ file “reverse.[domain name]”;’ at line 67.
sed -i ‘67s/^/”;/’ $named_file
sed -i “67s/^/$domain_name/” $named_file
sed -i ‘67s/^/ \t file “reverse./’ $named_file# Insert ‘ allow-update { none; };’ at line 68.
sed -i ‘68s/^/ \t allow-update { none; };/’ $named_file# Insert ‘};’ at line 69.
sed -i ‘69s/^/};/’ $named_file# Configure the DNS server’s forward zone file.
cp /var/named/named.localhost $forward_file# Edit line 2 as “@ IN SOA [domain name]. root.[domain name]. (“
sed -i -e “2s/@ rname.invalid/${domain_name}. root.$domain_name/” $forward_file# Remove the last 3 lines of the forward zone file.
for i in $(seq 1 3)
do
sed -i ‘$d’ $forward_file
done# Add DNS records to the end of the forward zone line.
echo “
@ IN NS $domain_name.
@ IN A $net_int_ip
server IN A $net_int_ip
host IN A $net_int_ip
desktop IN A $desktop_ip
client IN A $desktop_ip” >> $forward_file# Configure the reverse zone file.
cp $forward_file $reverse_file# Edit line 10 as “@ IN PTR [domain name].”
sed -i -e “10s/A/PTR/;10s/${net_int_ip}/${domain_name}./” $reverse_file# Add PTR records to the end of the reverse zone file.
echo “11 IN PTR server.$domain_name.
10 IN PTR desktop.$domain_name.” >> $reverse_file# Configure the ownership of the forward and reverse zone files.
chown root:named $forward_file
chown root:named $reverse_file# Verify the validity of the DNS server’s configuration files.
named-checkconf -z $named_file
named-checkzone forward $forward_file
named-checkzone reverse $reverse_file# Restart the DNS server.
systemctl restart named
View Part II of this tutorial series on DHCP server automation.
View Part III of this tutorial series on blog and web server automation.