Building Your Own Internal DNS Server with BIND9 on Ubuntu: A Solution to Replace Bulky Hosts Files

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

The Nightmare of “Remembering IP Addresses”

If you manage an office of about 50 employees with dozens of devices, you’ll understand this feeling. When I first started, I used to have headaches trying to remember all sorts of IPs: 192.168.1.10 for the accounting server, 192.168.1.50 for the file server, then printers, cameras…

Every time there was a new hire, I had to laboriously go to each machine to edit the hosts file on Windows or Linux. If a server’s IP changed, my phone would “burn up” all day with support calls. Typing nas.company.local instead of a dry string of numbers is clearly more urgent than ever.

Why the /etc/hosts File Can No Longer Carry the System

Using a hosts file is only fine when your network has 2-3 devices. As the scale grows, it becomes a true nightmare for several reasons:

  • Torturous Manual Updates: Adding a new server means you have to edit the hosts file on hundreds of client machines.
  • High Risk of Errors: Just one mistyped IP digit, and that department’s entire service goes “down” in the eyes of the user.
  • Mobile Devices Left Behind: Smartphones and tablets are almost impossible to modify hosts files on without rooting or jailbreaking.

An internal DNS Server is the lifesaver. It acts like a shared phonebook. When someone types git.lab.io, the computer asks the DNS Server: “Where is this guy?”, and receives the exact IP in just a few milliseconds.

BIND9 – The “Veteran” in the DNS World

Although there are many options today like Unbound or CoreDNS, BIND9 (Berkeley Internet Name Domain) remains the gold standard. When I moved from CentOS to Ubuntu, the BIND9 configuration had some differences in file organization. However, once you grasp its logic, you’ll see that BIND9’s customization capabilities are extremely powerful.

BIND9 smoothly handles forward resolution (Forward DNS), reverse resolution (Reverse DNS), and request forwarding. This is an indispensable foundation if you want to manage network infrastructure professionally.

Practical Steps for Deploying BIND9 on Ubuntu Server

To help you visualize it easily, I’ll use a practical lab model with the following parameters:

  • OS: Ubuntu Server 22.04 LTS
  • DNS Server IP: 192.168.1.100
  • Internal Domain: itfromzero.local

Step 1: Install the BIND9 Software Package

First, update the repository and install BIND9 along with supporting tools:

sudo apt update
sudo apt install bind9 bind9utils bind9-doc -y

Step 2: Configure Forwarders (Query Forwarding)

We want this DNS Server to answer internal domains, and if an employee browses facebook.com, it will push the request out to the Internet.

Open the /etc/bind/named.conf.options file:

sudo nano /etc/bind/named.conf.options

First, define a Trusted IP List (ACL) to prevent your DNS from being exploited for external attacks:

acl "trusted" {
    192.168.1.0/24;
    localhost;
    localnets;
};

Then, inside the options block, add the configuration to allow queries and declare Forwarders:

options {
    directory "/var/cache/bind";
    allow-query { trusted; };
    forwarders {
        8.8.8.8;
        1.1.1.1;
    };
    // ... keep other configurations unchanged
};

Step 3: Declare Management Zones

Now, tell BIND9 that you will be responsible for the itfromzero.local domain. Open the /etc/bind/named.conf.local file:

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

Add the following content to define the forward and reverse resolution zones:

// Forward Zone
zone "itfromzero.local" {
    type master;
    file "/etc/bind/zones/db.itfromzero.local";
};

// Reverse Zone
zone "1.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/zones/db.192.168.1";
};

Step 4: Create the Forward Zone File (Forward Resolution)

This is where you place A and CNAME records. Create a separate directory to keep things organized:

sudo mkdir /etc/bind/zones
sudo cp /etc/bind/db.local /etc/bind/zones/db.itfromzero.local
sudo nano /etc/bind/zones/db.itfromzero.local

Update the file with actual records. Note: The dot at the end of the domain name is mandatory.

$TTL    604800
@       IN      SOA     ns1.itfromzero.local. admin.itfromzero.local. (
                              3         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      ns1.itfromzero.local.
ns1     IN      A       192.168.1.100
web     IN      A       192.168.1.101
nas     IN      A       192.168.1.102

Step 5: Create the Reverse Zone File (Reverse Resolution)

Reverse resolution helps map an IP back to a domain name. This is extremely important for logging services or internal mail servers.

sudo cp /etc/bind/db.127 /etc/bind/zones/db.192.168.1
sudo nano /etc/bind/zones/db.192.168.1

Configure it according to your IP range:

$TTL    604800
@       IN      SOA     ns1.itfromzero.local. admin.itfromzero.local. (
                              3         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      ns1.itfromzero.local.
100     IN      PTR     ns1.itfromzero.local.
101     IN      PTR     web.itfromzero.local.
102     IN      PTR     nas.itfromzero.local.

Step 6: Check Syntax and Activate

Don’t rush to restart the service just yet. Use the check tools to avoid typos that could crash the DNS:

sudo named-checkconf
sudo named-checkzone itfromzero.local /etc/bind/zones/db.itfromzero.local
sudo systemctl restart bind9
sudo systemctl enable bind9

Practical Experience: Don’t Make Silly Mistakes

After many times “getting burned” by BIND9, I’ve distilled 3 golden rules:

  1. The “Powerful” Dot (.): In the zone file, ns1.itfromzero.local. must have a dot at the end to be a FQDN. Forget it, and BIND will interpret it as ns1.itfromzero.local.itfromzero.local. This is a “death trap” that almost every beginner has fallen into.
  2. Always Increment the Serial Number: Every time you edit a zone file, increase the Serial number by 1 (e.g., from 3 to 4). Otherwise, secondary DNS servers will never update with new data from the primary server.
  3. Check Ownership Carefully: If you copy files using root privileges, the bind user might not be able to read them. Run the command sudo chown -R bind:bind /etc/bind/zones to ensure everything runs smoothly.

Deploying BIND9 isn’t just about installing software; it’s about standardizing your network infrastructure. Good luck with your configuration, and may you soon escape the worry of manual hosts file updates!

Share: