Baeldung Pro – Linux – NPI EA (cat = Baeldung on Linux)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

1. Overview

The Domain Name System (DNS) is like a phonebook for the internet. It translates human-readable domain names (like baeldung.com) into IP addresses that computers use to find each other.

Furthermore, configuring our own DNS server with BIND9 gives us more control over this process. BIND9 is a popular DNS server software for Linux, and it’s quite powerful. Consequently, it enables us to manage how devices on our network resolve domain names to IP addresses.

In this tutorial, we’ll walk through the process of setting up a BIND9 DNS server.

2. Preparing the Server

Before we install and configure BIND9, let’s prepare our server.

2.1. Setting the Hostname

Let’s give our server a proper name. We need to give our server a hostname so we can easily identify it on the network.

We can set the hostname by editing the /etc/hostname file:

$ cat /etc/hostname
baeldung-dns

Inside the /etc/hostname file, we replace the existing hostname with our desired one, baeldung-dns.

2.2. Updating the /etc/hosts File

Now that our server has a name, we need to make sure it knows its own address. Let’s do this by updating the /etc/hosts file:

$ sudo vim /etc/hosts

Next, let’s add a line that associates our new hostname with the server’s static IP address:

$ cat /etc/hosts
195.133.93.153 baeldung-dns.example.com baeldung-dns
127.0.0.1       localhost
...

This tells the server that the hostname baeldung-dns refers to itself and that its fully qualified domain name (FQDN) is baeldung-dns.example.com.

Finally, let’s restart our server to apply these changes:

$ sudo reboot

Once the server restarts, it uses the new hostname and IP address.

3. Installing BIND9

First, let’s ensure our system is up-to-date. We can do this by running a quick update:

$ sudo apt update && sudo apt upgrade -y

Next, let’s install the BIND9 package, along with some useful utilities and documentation:

$ sudo apt install bind9 bind9utils bind9-doc -y

The command downloads and installs BIND9, giving us the tools we need to set up our DNS server.

Furthermore, as soon as the installation is complete, let’s ensure the BIND9 service is up and running:

$ sudo systemctl status bind9
 named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2024-10-05 09:06:07 UTC; 1min 58s ago
       Docs: man:named(8)
   Main PID: 12196 (named)
      Tasks: 14 (limit: 4537)
     Memory: 8.3M
     CGroup: /system.slice/named.service
             └─12196 /usr/sbin/named -f -u bind

Hence, if the installation went smoothly, we should see that BIND9 is active (running) as shown above.

4. Configuring BIND9

With our server properly set up and BIND9 installed, let’s configure BIND9 itself.

4.1. Configure Forwarders in named.conf.options

The first step in configuring BIND9 is to set up forwarders. Think of forwarders as asking a friend for help when we can’t find something ourselves. In this case, if our DNS server can’t resolve a domain name, it can ask these external DNS servers for assistance.

To configure forwarders, we need to edit the named.conf.options file. This file contains global options for our DNS server:

$ sudo vim /etc/bind/named.conf.options

Inside this file, find a section called forwarders. This is where we’ll add the IP addresses of external servers we want to use.

Additionally, we can use public DNS servers like Google Public DNS or Cloudflare DNS, or we can specify the DNS servers provided by our internet service provider.

Let’s use Google’s DNS servers in our configuration:

$ cat /etc/bind/named.conf.options
...
forwarders {
        8.8.8.8;
        8.8.4.4;
};
...

Consequently, this tells our DNS server: “If you can’t find the answer yourself, ask these servers.” Moreover, we can add more IP addresses if we want to use additional forwarders.

After adding the forwarders, we need to save the file and restart BIND9 for the changes to take effect:

$ sudo systemctl restart bind9

With forwarders set up, our server can now handle external DNS lookups.

4.2. Set up Zones in named.conf.local

After configuring forwarders, we need to define our DNS zones. Zones are like sections in our DNS server’s address book, each responsible for a specific domain or subnet. Let’s set up two types of zones: a forward lookup zone and a reverse lookup zone.

The named.conf.local file is where we define these zones. Let’s open it with our text editor:

$ sudo vim /etc/bind/named.conf.local

First, let’s define our forward lookup zone. This zone handles translations from domain names to IP addresses.

Then, let’s add a zone block for our domain, specifying it as master and providing the location of its zone file:

$ cat /etc/bind/named.conf.local
# Forward zone
zone "example.com" {
    type master;
    file "/etc/bind/zones/db.example.com";
};

This tells our DNS server that it’s the master source of information for example.com and that the DNS records for this zone are stored in the /etc/bind/zones/db.example.com file.

Next, let’s define our reverse lookup zone. This zone handles translations from IP addresses to domain names.

Similarly, in the same file, let’s add another zone block for our subnet, again specifying its type as master and the location of its zone file:

$ cat /etc/bind/named.conf.local
...
# Reverse zone
zone "153.93.133.195.in-addr.arpa" {
    type master;
    file "/etc/bind/zones/db.195";
};

However, this configuration tells our DNS server that it’s responsible for reverse lookups of the IP address 195.133.93.153, and the corresponding records are stored in /etc/bind/zones/db.195.

Additionally, after configuring the zones, we need to create the corresponding zone files.

5. Creating Forward and Reverse Zone Files

Now that we’ve told our DNS server which zones it’s responsible for, let’s create the actual zone files. These files are like dedicated address books containing the specific mappings between domain names and IP addresses, along with other important information.

5.1. Create the Zones Directory

First, we need a place to store these zone files. BIND9 expects them to be in a specific directory, so let’s create it:

$ sudo mkdir /etc/bind/zones

5.2. Create Forward Zone File

Next, let’s create the forward zone file. This file handles the “forward” lookups, translating domain names into IP addresses.

Hence, we can start with a template file provided by BIND9:

$ cat /etc/bind/db.local
;
; BIND data file for local loopback interface
;
$TTL	604800
@	IN	SOA	localhost. root.localhost. (
			      2		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL
;
@	IN	NS	localhost.
@	IN	A	127.0.0.1
@	IN	AAAA	::1

Let’s copy this file into db.example.com and then customize it:

$ sudo cp /etc/bind/db.local /etc/bind/zones/db.example.com

This copies the template into our db.example.com file, which we can edit to suit our purpose. Inside the file, let’s define the DNS records that map domain names to IP addresses:

$ cat /etc/bind/zones/db.example.com
;
; BIND data file for local loopback interface
;
$TTL	604800
@	IN	SOA	baeldung-dns.example.com. admin.example.com. (
			      2		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL
;
@	IN	NS	baeldung-dns.example.com.
@       IN      A       195.133.93.153
baeldung-dns   IN  A	195.133.93.153

Here, we’ve set up baeldung-dns.example.com as the primary name server for our domain and mapped the domain to the IP address 195.133.93.153.

5.3. Create Reverse Zone File

Now, let’s create the reverse zone file. This file handles reverse lookups, translating IP addresses back into domain names.

Similarly, let’s start with the template we’ll customize:

$ cat /etc/bind/db.127
;
; BIND reverse data file for local loopback interface
;
$TTL	604800
@	IN	SOA	localhost. root.localhost. (
			      1		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL
;
@	IN	NS	localhost.
1.0.0	IN	PTR	localhost.

Let’s copy the above file into db.195:

$ sudo cp /etc/bind/db.127 /etc/bind/zones/db.195

Next, let’s modify the file to reflect the correct IP address range and hostname:

$ cat /etc/bind/zones/db.195
;
; BIND reverse data file for local loopback interface
;
$TTL	604800
@	IN	SOA	baeldung-dns.example.com. admin.example.com. (
			      1		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL
;
@	IN	NS	baeldung-dns.example.com.
153	IN	PTR	baeldung-dns.example.com.

Similarly, this maps the last octet of the IP address (153 in 195.133.93.153) back to baeldung-dns.example.com.

6. Verifying Configuration and Restarting BIND9

First, let’s double-check our zone files using the tool named-checkzone. This tool helps us spot any errors in our configuration:

$ sudo named-checkzone example.com /etc/bind/zones/db.example.com
zone example.com/IN: loaded serial 2
Ok

If everything looks good, we’ll see the Ok message indicating that the zone was loaded successfully. Next, let’s verify the reverse zone file in the same way:

$ sudo named-checkzone example.com /etc/bind/zones/db.195
zone example.com/IN: loaded serial 1
Ok

Again, a successful output means our reverse zone is properly configured.

Let’s restart the BIND9 service to apply all these changes we’ve made:

$ sudo systemctl restart bind9

With the service restarted, we can check if our DNS server actually resolves names correctly.

Let’s test using the dig tool to confirm the DNS server is operational:

$ dig @195.133.93.153 example.com

; <<>> DiG 9.18.28-0ubuntu0.22.04.1-Ubuntu <<>> @195.133.93.153 example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8560
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: db32f227c48dd64c01000000672f6b1aec7a72aaf5646099 (good)
;; QUESTION SECTION:
;example.com.			IN	A

;; ANSWER SECTION:
example.com.		604800	IN	A	195.133.93.153

;; Query time: 0 msec
;; SERVER: 195.133.93.153#53(195.133.93.153) (UDP)
;; WHEN: Sat Nov 09 14:00:58 GMT 2024
;; MSG SIZE  rcvd: 84

These results indicate that our BIND9 server is running as expected.

7. Configuring DNS Clients

With our BIND9 server running, let’s configure our client machines to use it for name resolution. Moreover, this ensures that devices on our network can take advantage of our local DNS server for faster and more reliable name lookups.

For Linux clients, we need to edit the /etc/resolv.conf file to specify our server’s IP address:

$ sudo vim /etc/resolv.conf

Furthermore, inside this file, let’s add a line with the nameserver directive, followed by the IP address of our BIND9 server:

nameserver 195.133.93.153

Moreover, we can also add a search directive to specify the domain that should be used for unqualified names:

search example.com

Therefore, if a user on the client machine tries to access baeldung-dns (without the domain), the client will automatically try to resolve baeldung-dns.example.com.

After saving the changes, the client should start using our BIND9 server.

8. Conclusion

In this article, we walked through the process of setting up a BIND9 DNS server. We successfully set up a local DNS server that can efficiently resolve names within our network.

Additionally, this DNS server not only improves name resolution speed but also gives us greater control over our DNS records and improves privacy.