Skip to content

Linux Exercise 8 - Ubuntu DNS Server with Bind9

Exercise: Setting Up a DNS Server with BIND9 on Ubuntu 24.04

Section titled “Exercise: Setting Up a DNS Server with BIND9 on Ubuntu 24.04”

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

Make sure you are working on the same server VM that already runs your DHCP server. Update and install BIND9:

Terminal window
sudo apt update
sudo apt install bind9 bind9-utils -y
  • bind9: the DNS server software
  • bind9-utils: contains useful tools like dig for testing

Check if the service is running:

Terminal window
systemctl status bind9

You should see it as active (running). If not, start it:

Terminal window
sudo systemctl start bind9
sudo systemctl enable bind9

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.


  1. Open the BIND configuration for local zones:
Terminal window
sudo nano /etc/bind/named.conf.local
  1. 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.

  1. Create the forward zone file by copying the default template:
Terminal window
sudo cp /etc/bind/db.local /etc/bind/db.mynetwork.local
  1. Edit the new zone file:
Terminal window
sudo nano /etc/bind/db.mynetwork.local

Example 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:

  • ns1 is the DNS server itself (at .10)
  • Two web servers: www and www2
  • Two mail servers with MX priorities

  1. Edit the config file again:
Terminal window
sudo nano /etc/bind/named.conf.local

Add:

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.)

  1. Create the reverse zone file:
Terminal window
sudo cp /etc/bind/db.127 /etc/bind/db.192.168.56
  1. Edit the new file:
Terminal window
sudo nano /etc/bind/db.192.168.56

Example 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.10 maps to ns1.mynetwork.local
  • IP 192.168.56.20 maps to www.mynetwork.local
  • IP 192.168.56.21 maps to www2.mynetwork.local
  • IP 192.168.56.30 maps to mail.mynetwork.local

Run:

Terminal window
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.56

If no errors appear, restart BIND:

Terminal window
sudo systemctl restart bind9

6. Configuring the Client to Use the DNS Server

Section titled “6. 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.


From the client VM, run:

Terminal window
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.20

Expected results:

  • www.mynetwork.local resolves to 192.168.56.20
  • www2.mynetwork.local resolves to 192.168.56.21
  • Reverse lookup of 192.168.56.20 gives www.mynetwork.local

You can also try with:

Terminal window
nslookup www.mynetwork.local 192.168.56.10

8. Extending DNS with DDNS (Dynamic DNS Updates)

Section titled “8. 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.


DNS updates must be secured to prevent unauthorized changes. The DHCP server and DNS server share a secret key (TSIG).

On the server VM:

Terminal window
sudo rndc-confgen -a -r /dev/urandom

This creates a key in /etc/bind/rndc.key. But for DHCP we’ll generate our own:

Terminal window
sudo dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST dhcpupdate

This generates two files like Kdhcpupdate.+163+12345.key and .private.
View the key:

Terminal window
cat Kdhcpupdate.+163+*.key

You’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

Section titled “8.2. Configure BIND to Accept DDNS Updates”

Edit your named.conf.local:

Terminal window
sudo nano /etc/bind/named.conf.local

Modify 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

Section titled “8.3. Configure DHCP Server to Send Updates”

Edit your DHCP config:

Terminal window
sudo nano /etc/dhcp/dhcpd.conf

Add 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 zone
  • zone 56.168.192.in-addr.arpa. → updates reverse zone
  • Both use the key you generated

Restart both services:

Terminal window
sudo systemctl restart bind9
sudo systemctl restart isc-dhcp-server

  1. On your client VM, configure it to get a hostname via DHCP (default on Ubuntu).
    For example, set hostname to client1:

    Terminal window
    sudo hostnamectl set-hostname client1

    Then reconnect network (or reboot).

  2. On the server VM, check if DNS got updated:

    Terminal window
    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
  3. Add a second client (e.g. client2), and repeat. DNS should update automatically.