Domain Name Service (DNS)
The Domain Name System (DNS) is a hierarchical and distributed name service that provides a naming system for computers, services, and other resources on the Internet or other Internet Protocol (IP) networks. Most prominently, it translates readily memorized domain names to the numerical IP addresses needed for locating and identifying computer services and devices with the underlying network protocols.
Prerequisite
Disable “run at boot” and shutdown the following service.
1
systemctl disable --now systemd-reolved.service
This seems deprecated since Debian 12 but it might important for other distros like RHEL.
Edit /etc/resolv.conf to always resolve dns queries from localhost (with bind9).
1
nameserver 127.0.0.1
Installation
1
apt install bind9
Configuration
Following files in /etc/bind/ are mandatory:
| file | description |
|---|---|
| named.conf | Main configuration file which combines all other configuration files |
| named.conf.local | Local zone configuration file |
| named.conf.options | Permissions configuration file, e.g. for the daemon |
| /var/cache/bind/”zonefile” | Lists entries of dns queries IP to domain |
Edit /etc/bind/named.conf.options, this is an example.
1
2
3
4
5
options {
directory "/var/cache/bind";
dnssec-validation no;
allow-recursion { localhost; 192.168.0.0/24 };
};
| option | description |
|---|---|
| directory | Defines the directory in which the local zone files are stored |
| dnssec-validation | Defines the usage of DNSSEC if you configured it. |
| allow-recursion | Networks that are allowed to make DNS requestes. |
Create forward lookup zone
Edit /etc/bind/named.conf.local.
1
2
3
4
zone "local.lan" {
type master;
file "local.lan";
};
Edit zone file in /var/cache/bind/local.lan, if it doesn’t exist create it. The file name must be the same as in zone block under file.
1
2
3
4
5
$TTL 300
@ IN SOA dns.local.lan. mail.local.lan. (2023041702 14400 3600 3600000 86400)
IN NS dns
dns IN A 192.168.0.2
fw IN A 192.168.0.1
Important: Next to IN SOA dns domain, there must be a, maybe yet fictive, mail domain be configured!
| value | description |
|---|---|
| 2023041702 | Date = 20230417 = YYYYMMDD; Version of DNS-Zone |
| 14400 | refresh time between primary and secondary dns servers |
| 3600 | retry time between primary and secondary dns servers |
| 3600000 | expire time |
| 86400 | negative cache, secondary dns servers are caching negative answers |
All time related values are in sconds.
Usage
1
2
systemctl enable bind9.service
systemctl enable named.service
1
2
systemctl ( start | stop | restart ) bind9.service
systemctl ( start | stop | restart ) named.service
Create reverse lookup zone
Edit /etc/bind/named.conf.local.
1
2
3
4
zone "0.168.192.in-addr.arpa" {
type master;
file "0.168.192.in-addr.arpa";
};
Edit zone file in /var/cache/bind/0.168.192.in-addr.arpa, if it doesn’t exist create it. The file name must be the same as in zone block under file.
1
2
3
4
5
$TTL 300
@ IN SOA dns.local.lan. mail.local.lan. (2023041702 14400 3600 3600000 86400)
IN NS dns.local.lan.
1 IN PTR fw.local.lan.
2 IN PTR dns.local.lan.
Important: Next to IN SOA dns domain, there must be a, maybe yet fictive, mail domain be configured!
| value | description | | — | — | | 2023041702 | Date = 20230417 = YYYYMMDD; Version of DNS-Zone | | 14400 | refresh time between primary and secondary dns servers | | 3600 | retry time between primary and secondary dns servers | | 3600000 | expire time | | 86400 | negative cache, secondary dns servers are caching negative answers |
All time related values are in sconds.
Troubleshooting
1
systemctl status bind9.service
1
systemctl status named.service
Type journalctl -u to show the last 30 entries with -n30.
1
journalctl -u named.service -f -n30
| parameter | description |
|---|---|
| -u | Systemd unit, like named.service |
| -f | Following, new offers will displayed immediatly |
| -nX | Also display the last X entries |
To check the bind9 configuration syntax in named.conf.* files you can use:
1
2
named-checkconf
named-checkzone local.lan /var/cache/bind/local.lan
local.lan is depending on your configured zone file name
Test DNS forward lookup with dig.
1
dig +short @10.12.0.2 fw.local.net
Test DNS reverse lookup with dig.
1
dig +short @10.12.0.2 -x 10.12.0.1
Lookup a complete zone if you have the right to.
1
dig axfr local.lan
| paramter | description |
|---|---|
| +short | Optione to only show IP or hostname. For more verbose output use +trace. |
| @10.12.0.2 | DNS-server to use |
| fw.local.net | Targeted hostname or IP if using -x |
Dynamic DNS (DDNS)
DDNS services keep hostnames up to date with the latest dynamic IP address. This way, IP addresses can change as much as they like without causing any confusion or deeming requests for information unsuccessful.
If DDNS didn’t exist, DNS records would have to be updated manually every time a connection is made.
Preparation
For automatic DNS updates a SHA256-key is needed. Copy that key to clipboard because we will need it later.
1
echo -n "Very secret secret..." | openssl sha256 -hmac "nonbase64key" | awk '{print $2}'
The text in
echoyou can choose randomly. The larger the text the better.
The Ouput should look something like this:
1
a8796575ab0a3124fb753162ede33776284d38ae3c62a78e80420435d9238336
Configuration
Edit /etc/bind/named.conf.local.
1
2
3
4
key ddns-update.key {
algorithm HMAC-SHA256;
secret "a8796575ab0a3124fb753162ede33776284d38ae3c62a78e80420435d9238336";
};
This code block must be placed above the zone declaration.
Edit your forward zone definition to allow-update(s) with the previously generated key.
1
2
3
4
5
zone "local.lan" {
type master;
allow-update { key ddns-update.key; };
file "local.lan";
};
Edit your reverse zone definition to allow-update(s) with the previously generated key.
1
2
3
4
5
zone "0.168.192.in-addr.arpa" {
type master;
allow-update { key ddns-update.key; };
file "0.168.192.in-addr.arpa";
};
Afterwards you have to restart bind9.
1
systemctl restart bind9
Adding hosts entries per script
Now we create a little shell script. Sounds hard, but it will become handy later on. Let’s call it ddns_add_host.sh.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
TTL=300
SERVER="10.12.0.2"
HOSTNAME=$1
IP=$2
KEY="a8796575ab0a3124fb753162ede33776284d38ae3c62a78e80420435d9238336"
KEYNAME="ddns-update.key"
HMAC=hmac-sha256:$KEYNAME:$KEY
date >> /var/log/ddns.log
nsupdate -y $HMAC 2>> /var/log/ddns.log << EOF
server $SERVER
update add $HOSTNAME $TTL A $IP
send
EOF
| variable | description | | — | — | | SERVER=”” | Your primary DNS-server who should receive the updates. | | HOSTNAME=”” | Fully-Qualified-Domain-Name (FQDN) of your new host, e.g. mail.local.lan | | IP=”” | IP of your new host. |
$1and$2are parameters given when the script is executed, like./ddns_add_host.sh $1 $2
Then the script must set to be executable…
1
chmod +x ddns_add_host.sh
… and executed like this:
1
./ddns_add_host.sh mail.local.lan 10.12.0.3
Deleting hosts entries per script
Copy the little shell script we created earlier. Let’s call it ddns_del_host.sh.
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
TTL=300
SERVER="10.12.0.2"
HOSTNAME=$1
KEY="a8796575ab0a3124fb753162ede33776284d38ae3c62a78e80420435d9238336"
KEYNAME="ddns-update.key"
HMAC=hmac-sha256:$KEYNAME:$KEY
date >> /var/log/ddns.log
nsupdate -y $HMAC 2>> /var/log/ddns.log << EOF
server $SERVER
update delete $HOSTNAME
send
EOF
Execute it like:
1
./ddns_del_host.sh test.local.lan
Troubleshooting and testing
As you might noticed the script writes a log file to /var/log/ddns.log. It contains just the date and update occurs, because nsupdate don’t print a success message, but you can look after error messages. That’s what 2>> in the script means and does. bind9 also creates a new journal file for the new / updated host located at /var/cache/bind/local.lan.jnl. But the output looks weird because it’s binary. The following is just an example log for presentation.
1
2
;BIND LOG V9.2
x*x*8x*x*x*Nnetz012lab,7dnsnetz012labinfonetz012labx*8@6QNnetz012lab,7dnsnetz012labinfonetz012labx*8@6Q!mortinetz012lab,
When the DNS server gets restarted the journal file will be merged into your zone file. Changes may occur compared to your editing.
You can also prove your success with the known dig commands.
Update DDNS with DHCP
In medium to large enterprise companies this can come in very handy for logging purposes. With a reasonable naming convention of course.
Prerequisites
For this to achieve you must have a DHCP and DNS server with DDNS configured and running.
Configuration
Edit /etc/dhcp/dhcpd.conf on your DHCP server.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ddns-updates on;
ddns-update-style interim;
key ddns-update.key {
algorithm HMAC-SHA256;
secret "52b66d1e81efce864c1a1a3c5435f9e44d0a0b76dd3fd1bb307f818284379264";
};
zone local.lan {
primary 10.12.0.2; # DNS-Server
key "ddns-update.key";
}
zone 0.168.192.in-addr.arpa {
primary 10.12.0.2;
key "ddns-update.key";
}
subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.0.55 192.168.19.75;
option routers 192.168.0.1;
option domain-search "local.lan";
ddns-domainname "local.lan";
}
Similar to the DDNS configuration file you have to place the exact same key and forward / reverse zone definitions above your subnet definitions. When your finished it’s time to restart the DHCP service.
In
keydefinition the name of the key could be another than in DDNS config but thesecretmust be the same.
Troubleshooting
Type journalctl -u to show the last 30 entries with -n30.
1
journalctl -u isc-dhcp-server -f -n30
| parameter | description |
|---|---|
| -u | Systemd unit, like isc-dhcp-server |
| -f | Following, new offers will displayed immediatly |
| -nX | Also display the last X entries |
The Output should look like this:
1
2
3
4
5
6
7
8
9
Aug 23 11:12:31 dhcp dhcpd[798]: DHCPDISCOVER from 08:00:27:aa:a8:18 (client) via 172.16.12.1
Aug 23 11:12:31 dhcp dhcpd[798]: DHCPOFFER on 172.16.12.101 to 08:00:27:aa:a8:18 (client) via 172.16.12.1
Aug 23 11:12:31 dhcp dhcpd[798]: DHCPREQUEST for 172.16.12.101 (172.16.12.2) from 08:00:27:aa:a8:18 (client) via enp0s3
Aug 23 11:12:31 dhcp dhcpd[798]: DHCPACK on 172.16.12.101 to 08:00:27:aa:a8:18 (client) via enp0s3
Aug 23 11:12:31 dhcp dhcpd[798]: DHCPREQUEST for 172.16.12.101 (172.16.12.2) from 08:00:27:aa:a8:18 (client) via 172.16.12.1
Aug 23 11:12:31 dhcp dhcpd[798]: DHCPACK on 172.16.12.101 to 08:00:27:aa:a8:18 (client) via 172.16.12.1
Aug 23 11:12:31 dhcp dhcpd[798]: Added new forward map from client.netz012.lab to 172.16.12.101
Aug 23 11:12:31 dhcp dhcpd[798]: Added reverse map from 101.12.16.172.in-addr.arpa. to client.netz012.lab
The last line is the important one. That shows that a forward and a reverse entry (A) is added to the DNS server.
Pseudo Top Level Domain
Let’s assume we have a private domain and a DMZ domain and need some “master” for them to reach and update each other. 
This part is under construction.
