Exercise: Setting Up a DNS Server with BIND9 on Ubuntu 24.04
Introduction
In the previous exercise, you set up a DHCP server inside a virtual machine and tested it with a client machine in VirtualBox. Now you’ll extend your server to also provide DNS (Domain Name System) services for your internal network.
DNS translates domain names (like www.example.com) into IP addresses and back again. In your local network, you can run your own DNS server to resolve names of machines without relying on the internet.
You’ll use BIND9, the most widely used DNS server software on Linux.
By the end of this exercise you will:
- Install and configure BIND9
- Create a forward lookup zone (name → IP)
- Create a reverse lookup zone (IP → name)
- Test your DNS configuration from the client machine
1. Preparing the Server Machine
Make sure you are working on the same server VM that already runs your DHCP server. Update and install BIND9:
sudo apt update
sudo apt install bind9 bind9-utils -ybind9: the DNS server softwarebind9-utils: contains useful tools likedigfor testing
Check if the service is running:
systemctl status bind9You should see it as active (running). If not, start it:
sudo systemctl start bind9
sudo systemctl enable bind92. Understanding DNS Zones
DNS is structured into zones.
- A forward zone maps names → IP addresses.
Example:www.mynetwork.local → 192.168.56.10 - A reverse zone maps IP addresses → names.
Example:192.168.56.10 → www.mynetwork.local
We’ll configure both.
3. Configuring a Forward Zone
- Open the BIND configuration for local zones:
sudo nano /etc/bind/named.conf.local- Add the following block (replace the network/domain names as needed):
zone "mynetwork.local" {
type master;
file "/etc/bind/db.mynetwork.local";
};
This tells BIND that it will act as the master DNS server for the domain mynetwork.local, using the zone file db.mynetwork.local.
- Create the forward zone file by copying the default template:
sudo cp /etc/bind/db.local /etc/bind/db.mynetwork.local- Edit the new zone file:
sudo nano /etc/bind/db.mynetwork.localExample content (adapt as needed):
$TTL 604800
@ IN SOA ns1.mynetwork.local. admin.mynetwork.local. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
; Name server
@ IN NS ns1.mynetwork.local.
; A records
ns1 IN A 192.168.56.10
www IN A 192.168.56.20
www2 IN A 192.168.56.21
; MX records
@ IN MX 10 mail.mynetwork.local.
@ IN MX 20 mail2.mynetwork.local.
mail IN A 192.168.56.30
mail2 IN A 192.168.56.31
Explanation:
ns1is the DNS server itself (at.10)- Two web servers:
wwwandwww2 - Two mail servers with MX priorities
4. Configuring a Reverse Zone
- Edit the config file again:
sudo nano /etc/bind/named.conf.localAdd:
zone "56.168.192.in-addr.arpa" {
type master;
file "/etc/bind/db.192.168.56";
};
This reverse zone corresponds to the subnet 192.168.56.0/24. (It’s written backwards for DNS purposes.)
- Create the reverse zone file:
sudo cp /etc/bind/db.127 /etc/bind/db.192.168.56- Edit the new file:
sudo nano /etc/bind/db.192.168.56Example content:
$TTL 604800
@ IN SOA ns1.mynetwork.local. admin.mynetwork.local. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
; Name server
@ IN NS ns1.mynetwork.local.
; PTR records
10 IN PTR ns1.mynetwork.local.
20 IN PTR www.mynetwork.local.
21 IN PTR www2.mynetwork.local.
30 IN PTR mail.mynetwork.local.
Explanation:
- IP
192.168.56.10maps tons1.mynetwork.local - IP
192.168.56.20maps towww.mynetwork.local - IP
192.168.56.21maps towww2.mynetwork.local - IP
192.168.56.30maps tomail.mynetwork.local
5. Checking Configuration
Run:
sudo named-checkconf
sudo named-checkzone mynetwork.local /etc/bind/db.mynetwork.local
sudo named-checkzone 56.168.192.in-addr.arpa /etc/bind/db.192.168.56If no errors appear, restart BIND:
sudo systemctl restart bind96. Configuring the Client to Use the DNS Server
On your client VM, set the DNS server to point to your server VM (e.g. 192.168.56.10).
If you have already installed and configured DHCP on your server, configure your DHCP accordingly, so that your host knows which DNS server to use.
Otherwise set it manually in /etc/netplan/ or Network Manager.
7. Testing DNS Resolution
From the client VM, run:
dig @192.168.56.10 www.mynetwork.local
dig @192.168.56.10 www2.mynetwork.local
dig @192.168.56.10 mail.mynetwork.local
dig -x 192.168.56.20Expected results:
www.mynetwork.localresolves to192.168.56.20www2.mynetwork.localresolves to192.168.56.21- Reverse lookup of
192.168.56.20giveswww.mynetwork.local
You can also try with:
nslookup www.mynetwork.local 192.168.56.108. Extending DNS with DDNS (Dynamic DNS Updates)
So far, you configured DNS zones manually. That works for static servers (like www, mail), but for client machines that come and go, maintaining DNS by hand is impractical.
With Dynamic DNS (DDNS), the DHCP server can automatically update the DNS server whenever it leases a new IP to a client.
- When a host gets an IP, its hostname → IP (A record) and IP → hostname (PTR record) are added to DNS.
- When the lease expires or is released, the records are removed.
This creates a seamless integration between DHCP and DNS.
8.1. Create a TSIG Key for Secure Updates
DNS updates must be secured to prevent unauthorized changes. The DHCP server and DNS server share a secret key (TSIG).
On the server VM:
sudo rndc-confgen -a -r /dev/urandomThis creates a key in /etc/bind/rndc.key. But for DHCP we’ll generate our own:
sudo dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST dhcpupdateThis generates two files like Kdhcpupdate.+163+12345.key and .private.
View the key:
cat Kdhcpupdate.+163+*.keyYou’ll see something like:
dhcpupdate. IN KEY 512 3 163 XXXXXXXXXXXXXXXXXXXXX==
The last part (XXXXXXXXXXXXXXXXX==) is the secret. Save it.
8.2. Configure BIND to Accept DDNS Updates
Edit your named.conf.local:
sudo nano /etc/bind/named.conf.localModify your zones to allow updates with the key:
key "dhcpupdate" {
algorithm hmac-sha256;
secret "XXXXXXXXXXXXXXXXXXXX==";
};
zone "mynetwork.local" {
type master;
file "/etc/bind/db.mynetwork.local";
allow-update { key dhcpupdate; };
};
zone "56.168.192.in-addr.arpa" {
type master;
file "/etc/bind/db.192.168.56";
allow-update { key dhcpupdate; };
};
8.3. Configure DHCP Server to Send Updates
Edit your DHCP config:
sudo nano /etc/dhcp/dhcpd.confAdd the same key definition:
key dhcpupdate {
algorithm hmac-sha256;
secret "XXXXXXXXXXXXXXXXXXXX==";
};
zone mynetwork.local. {
primary 127.0.0.1;
key dhcpupdate;
}
zone 56.168.192.in-addr.arpa. {
primary 127.0.0.1;
key dhcpupdate;
}
Explanation:
zone mynetwork.local.→ updates forward zonezone 56.168.192.in-addr.arpa.→ updates reverse zone- Both use the key you generated
Restart both services:
sudo systemctl restart bind9
sudo systemctl restart isc-dhcp-server8.4. Testing DDNS
-
On your client VM, configure it to get a hostname via DHCP (default on Ubuntu).
For example, set hostname toclient1:sudo hostnamectl set-hostname client1Then reconnect network (or reboot).
-
On the server VM, check if DNS got updated:
dig @127.0.0.1 client1.mynetwork.local dig -x <client1-IP>You should see both:
client1.mynetwork.local→ correct IP- reverse lookup of IP →
client1.mynetwork.local
-
Add a second client (e.g.
client2), and repeat. DNS should update automatically.