DNS an acronym for Domain Name System is an internet service that resolves an IP address to a domain name and vice-versa. Usually, people access sites over the internet using domain names that are usually easier to memorize for example geeksforgeeks.org e.t.c. The web servers interact using the IP addresses, DNS now translates the addresses to allow the browsers to load the pages. This eliminates the complexity of memorizing the IP addresses associated with internet pages.
Berkeley Internet Name Domain abbreviated as BIND is open-source and extensive software originally written in the 1980s at the University of California’s Berkeley. It is used to provide all DNS-related service functions with the following capabilities:
- Authoritative DNS: allows one to publish the DNS zones and records under the server’s authoritative control as the primary or secondary server.
- Split DNS: the ability to publish multiple views of the DNS namespace
- Recursive DNS (caching resolver): It is able to obtain data from the authoritative/other DNS servers on behalf of client systems.
- IPv6 support: it supports IPv6 by publishing IPv6 addresses for names and by participating directly in IPv6 networking
- Data replication: you can copy data from the primary to secondary servers efficiently and in a time
By default, DNS is not secure and security was not a primary consideration in its design since it was designed at a time when the internet was a friendly and trusting place. When a recursive resolver sends the request to an authoritative DNS, there is no way to verify the authenticity of the received response. The resolver only ensures that the response is coming from the same IP. This is not secure enough since the IP can be easily forged or spoofed. The DNS resolver is not designed to detect any forged response to one of its queries.
Securing the BIND DNS is important since it precludes attackers from tampering with the DNS response, masquerading and manipulating the authoritative DNS cache. The DNS Security Extensions abbreviated as DNSSEC allow one to maintain the data integrity of DNS responses. It signs all the DNS records such as A, MX, CNAME e.t.c. of a zone using the Public Key Infrastructure(PKI).
DNSSEC introduces 8 new resource record types:
- DNSKEY (public key)
- RRSIG (digital resource record signature)
- DS (parent-child)
- NSEC (proof of nonexistence)
- NSEC3 (proof of nonexistence)
- NSEC3PARAM (proof of nonexistence)
- CDS (child-parent signaling)
- CDNSKEY (child-parent signaling)
When DNSSEC validation is enabled, the resolver asks for additional resource records in its query. It requests the authoritative DNS to provide the response with some proof associated with the answer. When the responses are received, the resolver performs some cryptographic checks to verify the authenticity and integrity of the answers. This process is repeated by get-key, validate, ask-parent, and its parent until a key is reached and trusted. Only one key is trusted by DNSSEC, the root key.
The image below can be used to demonstrate the working of DNSSEC.
Secure BIND DNS Server With DNSSec Keys
In this guide, we will learn how to secure the BIND DNS Server With DNSSec Keys.
Step 1: Install Bind DNS Server
This setup requires the latest BIND version, probably any version above 9.9. The BIND server can be installed using the aid provided in the below guides:
- Configure Master BIND DNS on Rocky Linux / AlmaLinux 9
- Configure BIND Master DNS Server on Debian
- Configure Slave BIND DNS Server on Ubuntu
Once installed, check the version with the command:
# named -V
BIND 9.16.23-RH (Extended Support Version) <id:fde3b1f>
.......
compiled by GCC 11.2.1 20220127 (Red Hat 11.2.1-9)
compiled with OpenSSL version: OpenSSL 3.0.1 14 Dec 2021
linked to OpenSSL version: OpenSSL 3.0.1 14 Dec 2021
compiled with libuv version: 1.42.0
linked to libuv version: 1.42.0
compiled with libxml2 version: 2.9.13
linked to libxml2 version: 20913
compiled with json-c version: 0.14
linked to json-c version: 0.14
compiled with zlib version: 1.2.11
linked to zlib version: 1.2.11
linked to maxminddb version: 1.5.2
compiled with protobuf-c version: 1.3.3
linked to protobuf-c version: 1.3.3
threads support is enabled
If BIND is built with OpenSSL then it supports DNSSEC. If the version does not support DNSSEC, then you need to upgrade to the latest release.
You can also check the version with the command:
dig -t txt -c chaos VERSION.BIND
Step 2: Enable DNSSEC on the BIND Master
Edit the master configuration and enable DNSSEC.
##On Debian/Ubuntu
sudo vim /etc/bind/named.conf.options
##On CentOS/Rocky Linux/Alma Linux
sudo vim /etc/named.conf
Ensure the below lines are available in the config;
.........
dnssec-enable yes;
dnssec-validation yes;
.......
Step 3: Generate key pair for ZSK and KSK
To generate the key pair for DNSSEC, switch to the BIND directory as root
##On Debian/Ubuntu
sudo su -
cd /etc/bind
##On CentOS/Rocky Linux/Alma Linux
sudo su -
cd /var/named/
Remember the above directory should contain your zone files. Generate the Zone Signing Key for your zone with the command:
dnssec-keygen -a <ALGORITHM> -b <BITS> -n ZONE <ZONENAME>
For this guide, I will be using:
- zone names:
- neveropen.local as the forward zone
- 205.168.192.in-addr.arpa as the reverse zone.
- Zone files
- neveropen.forward
- neveropen.reverse
So the ZSK Keys will be generated as shown:
##For the Foward Zone
dnssec-keygen -a RSASHA256 -b 2048 -n ZONE neveropen.local
##For the Reverse Zone
dnssec-keygen -a RSASHA256 -b 2048 -n ZONE 205.168.192.in-addr.arpa
Generate the Key Signing Key(KSK) for your zones
##For the Foward Zone
dnssec-keygen -f KSK -a RSASHA256 -b 4096 -n ZONE neveropen.local
##For the Reverse Zone
dnssec-keygen -f KSK -a RSASHA256 -b 4096 -n ZONE 205.168.192.in-addr.arpa
Add the generated keys to your zone files using the command:
##For the Foward Zone
for key in `ls Kneveropen.local*.key`
do
echo "\$INCLUDE $key">> neveropen.forward
done
##For the Reverse Zone
for key in `ls K205.168.192.in-addr.arpa*.key`
do
echo "\$INCLUDE $key">> neveropen.reverse
done
Set the required permissions for the keys.
##On Debian/Ubuntu
chown root:bind Kneveropen.*
chown root:bind K205.168.192.in-addr.arpa*
##On CentOS/Rocky Linux/Alma Linux
chown root:named Kneveropen.*
chown root:named K205.168.192.in-addr.arpa*
Step 4: Sign the Generated Keys
Now sign the zone keys using the dnssec-signzone
command with the below syntax:
dnssec-signzone -3 <salt> -A -N INCREMENT -o <zonename> -t <zonefilename>
For example in my Forward zone:
dnssec-signzone -A -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N INCREMENT -o neveropen.local -t neveropen.forward
Reverse Zone:
dnssec-signzone -A -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N INCREMENT -o 205.168.192.in-addr.arpa -t neveropen.reverse
Sample output:
After this, you will have new zone files as forward.signed, and reverse.signed. Now edit the below file to accommodate the newly signed zone files;
##On Debian/Ubuntu
sudo vim /etc/bind/named.conf.local
##On CentOS/Rocky Linux/Alma Linux
sudo vim /etc/named.rfc1912.zones
Make the changes to the file. For example on CentOS;
.....
zone "neveropen.local" IN {
type master;
file "neveropen.forward.signed";
allow-transfer { 2.2.2.2; };
allow-update { none; };
};
zone "205.168.192.in-addr.arpa" IN {
type master;
file "neveropen.reverse.signed";
allow-transfer { 2.2.2.2; };
allow-update { none; };
};
Set the required permissions:
##On Debian/Ubuntu
chown root:bind neveropen.forward.signed
chown root:bind neveropen.reverse.signed
##On CentOS/Rocky Linux/Alma Linux
chown root:named neveropen.forward.signed
chown root:named neveropen.reverse.signed
That is it! You have your DNS secured. Restart the service;
##On Debian/Ubuntu
sudo systemctl restart bind9
##On CentOS/Rocky Linux/Alma Linux
sudo systemctl restart named.service
Test DNSSEC on BIND DNS from the localhost
dig DNSKEY neveropen.local +multiline
Sample Output:
Check the availability of RRSIG records
dig www.neveropen.local. +noadditional +dnssec +multiline
Sample Output:
From the above output, we a validated response with the AD (Authenticated Data) bit flag set. The header has the status NOERROR. A response that is not validated, will have the HEADER status as SERVFAIL
;; >>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 21978
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
Wrapping Up
That marks the end of this guide on how to secure the BIND DNS Server With DNSSec Keys. You are now able to maintain the data integrity of DNS responses. The DNS responses can no longer be manipulated. I hope this worked for you too.
See more:
- Running PowerDNS and PowerDNS Admin in Docker Containers
- Configure BIND Slave DNS Server on Debian
- How To add DNS A/PTR Record in Windows Server 2019