How to Set Up Private DNS Servers with BIND on Ubuntu 16.04

How to Set Up Private DNS Servers with BIND on Ubuntu 16.04. BIND (Berkeley Internet Name Domain) is the most widely used DNS software over the Internet. The BIND package is available for all Linux distributions, making installation easy and simple. In today’s article, we will show you how to install, configure and manage BIND 9 as a private DNS server on an Ubuntu 16.04 VPS in a few steps.

Requirements:

  • Two servers (NS1 and NS2) connected to a private network
  • In this article, we will use subnets 10.35.0.0/16
  • DNS clients that will connect to your DNS servers

1. Update both servers

Start by updating packages on both servers:

# sudo apt-get update

2. Install BIND on both servers

# sudo apt-get install bind9 bind9utils

3. Set BIND to IPv4 mode

Installing BIND in IPv4 mode, we will do this by editing the file “/ etc / default / bind9” and adding “-4” to the OPTIONS variable:

# sudo nano /etc/default/bind9

The edited file should look like this:

# run resolvconf?
RESOLVCONF=no

# startup options for the server
OPTIONS="-4 -u bind"

Now let’s set up ns1 as our primary DNS server.

4. Setting up the primary DNS server

Edit the named.conf.options file:

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

At the top of the parameter block, add a new block called trust. This list will allow the clients specified in it to send recursive DNS queries to our main server:

acl "trusted" {
        10.35.30.13;  
        10.35.30.14;
        10.35.55.154;
        10.35.55.155;
};

5. Enable recursive queries on our ns1 server, and listen to the server on our private network

Then we will add some configuration parameters to enable recursive requests on our ns1 server and the server’s ability to listen on our private network, add configuration parameters in the “/ var / cache / bind” directory like in the example below:

options {
        directory "/var/cache/bind";

        recursion yes;
        allow-recursion { trusted; };
        listen-on { 10.35.30.13; };
        allow-transfer { none; };

        forwarders {
                8.8.8.8;
                8.8.4.4;
        };
};

If the “listen-on-v6” directive is present in the named.conf.options file, remove it since we only want to listen to BIND on IPv4. Now on ns1 open named.conf.local file for editing:

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

Here we are going to add a zone:

zone "test.example.ru" {
    type master;
    file "/etc/bind/zones/db.test.example.ru";
    allow-transfer { 10.35.30.14; };
};

Our private subnet is 10.35.0.0/16, so we’ll add a reverse zone with the following lines:

zone "20.10.in-addr.arpa" {
    type master;
    file "/etc/bind/zones/db.10.35";
    allow-transfer { 10.35.30.14; };
};

If the servers are on multiple private subnets in the same physical location, you must specify a zone and create a separate zone file for each subnet.

6. Create a reverse zone file

We will now create a directory where we will store our zone files:

# sudo mkdir /etc/bind/zones

We’ll use the example db.local file to make our direct zone file, let’s copy the file first:

# cd /etc/bind/zones
# sudo cp ../db.local ./db.test.example.ru

Now edit the zone file, we just copied:

# sudo nano /etc/bind/zones/db.test.example.ru

It should look like the example below:

$TTL    604800
@       IN      SOA     localhost. root.localhost. (
                              2         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      localhost.      ; delete this
@       IN      A       127.0.0.1       ; delete this
@       IN      AAAA    ::1             ; delete this

Now let’s edit the SOA record. Replace Localhost with the domain name of your Ns1 server, and then replace “root.localhost” with “admin.test.example.ru”. Every time you edit the zone file, increase the serial value before restarting the name, otherwise the binding won’t apply the change to the zone, we will increase the value to “3”, it should look something like this:

@       IN      SOA     ns1.test.example.ru. admin.test.example.ru. (
                              3         ; Serial

Then, delete the last three records marked “delete this” after the SOA record.

Add nameserver entries at the end of the file:

; name servers - NS records
    IN      NS      ns1.test.example.ru.
    IN      NS      ns2.test.example.ru.

After that, add entries for the hosts that should be in this zone. This means that any server whose name we want to end with “.test.example.ru”:

; name servers - A records
ns1.test.example.ru.          IN      A       10.35.30.13
ns2.test.example.ru.          IN      A       10.35.30.14

; 10.35.0.0/16 - A records
host1.test.example.ru.        IN      A      10.35.55.154
host2.test.example.ru.        IN      A      10.35.55.155

The db.test.example.ru file should look like this:

$TTL    604800
@       IN      SOA     ns1.test.example.ru. admin.test.example.ru. (
                  3       ; Serial
             604800     ; Refresh
              86400     ; Retry
            2419200     ; Expire
             604800 )   ; Negative Cache TTL
;
; name servers - NS records
     IN      NS      ns1.test.example.ru.
     IN      NS      ns2.test.example.ru.

; name servers - A records
ns1.test.example.ru.          IN      A       10.35.30.13
ns2.test.example.ru.          IN      A       10.35.30.14

; 10.35.0.0/16 - A records
host1.test.example.ru.        IN      A      10.35.55.154
host2.test.example.ru.        IN      A      10.35.55.155

7. Create a reverse zone file

Let’s set up PTR records for reverse DNS queries in reverse zone files. When the DNS server receives a PTR lookup request for the IP example: “10.35.55.154”, it will check the reverse zone file to retrieve the fully qualified domain name of the IP address, in our case it will be “host1.test.example.ru”.

We will create a reverse zone file for each reverse zone specified in the named.conf.local file we created for ns1. We’ll use the db.127 zone file as a sample to create our reverse zone file:

# cd /etc/bind/zones
# sudo cp ../db.127 ./db.10.35

Edit the reverse zone file to match the reverse zone defined in named.conf.local:

# sudo nano /etc/bind/zones/db.10.35

The original file should look like this:

$TTL    604800
@       IN      SOA     localhost. root.localhost. (
                              1         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@       IN      NS      localhost.      ; delete this
1.0.0   IN      PTR     localhost.      ; delete this

You have to change the SOA record and increase the serial value. It should look something like this:

@       IN      SOA     ns1.test.example.ru. admin.test.example.ru. (
                              3         ; Serial

Then delete the last three records marked “delete this” after the SOA record.

Add nameserver entries at the end of the file:

; name servers - NS records
      IN      NS      ns1.test.example.ru.
      IN      NS      ns2.test.example.ru.

Now add ptr records for all hosts that are on the same subnet to the zone file you created. It consists of our hosts, which are on the 10.20.0.0/16 subnet. In the first column, we will change the order of the last two octets of the host IP address that we want to add:

; PTR Records
13.30  IN      PTR     ns1.test.example.ru.    ; 10.35.30.13
14.30  IN      PTR     ns2.test.example.ru.    ; 10.35.30.14
154.55 IN      PTR     host1.test.example.ru.  ; 10.35.55.154
155.55 IN      PTR     host2.test.example.ru.  ; 10.35.55.155

Save and exit reverse zone file.

The reverse zone file “/etc/bind/zones/db.10.35” should look like this:

$TTL    604800
@       IN      SOA     test.example.ru. admin.test.example.ru. (
                              3         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
; name servers
      IN      NS      ns1.test.example.ru.
      IN      NS      ns2.test.example.ru.

; PTR Records
13.30  IN      PTR     ns1.test.example.ru.    ; 10.35.30.13
14.30  IN      PTR     ns2.test.example.ru.    ; 10.35.30.14
154.55 IN      PTR     host1.test.example.ru.  ; 10.35.55.154
155.55 IN      PTR     host2.test.example.ru.  ; 10.35.55.155

8. Check configuration files

Use the following command to check the configuration syntax of all named.conf files that we have configured:

# sudo named-checkconf

If the configuration files do not have any syntax problems, the output will not contain any error messages. However, if you have problems with the configuration files, compare the settings in the “Configuring the Primary DNS Server” section with the files, if you have errors, make the correct adjustments, and you can try again by running named-checkconf.

named-checkconf can be used to check that your zone files are configured correctly. You can use the following command to test the zone directly “test.example.ru”:

# sudo named-checkzone test.example.ru db.test.example.ru

And if you want to check the reverse zone configuration, run the following command:

# sudo named-checkzone 20.10.in-addr.arpa /etc/bind/zones/db.10.35

After you have configured the configuration and zone files correctly, restart the BIND service:

# sudo service bind9 restart

9. Setting up a secondary DNS server

Setting up a secondary DNS server is always a good idea, as it will serve as a failover and will answer queries if the primary server is not responding.

On ns2, edit the named.conf.options file:

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

At the top of the file, add an ACL with private IP addresses for all your trusted servers:

acl "trusted" {
        10.35.30.13;
        10.35.30.14;
        10.128.100.101;
        10.128.200.102;
};

Just like in the named.conf.options file for ns2, add the following lines to the directory “/ var / cache / bind” directive:

        recursion yes;
        allow-recursion { trusted; };
        listen-on { 10.35.30.13; };
        allow-transfer { none; };

        forwarders {
                8.8.8.8;
                8.8.4.4;
        };

Save and close the file.

Now open named.conf.local file for editing:

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

Now we must specify the slave zones corresponding to the master zone on the DNS server ns1. The wizard directive must be set to the private IP address of the DNS Ns1 server:

zone "test.example.ru" {
    type slave;
    file "slaves/db.test.example.ru";
    masters { 10.35.30.13; };
};

zone "20.10.in-addr.arpa" {
    type slave;
    file "slaves/db.10.35";
    masters { 10.35.30.13; };
};

Now save and close the file.

Use the following command to check the syntax of the configuration files:

# sudo named-checkconf

Then restart the BIND service:

# sudo service bind9 restart

10. Configuring DNS Clients

Now let’s configure the hosts on our 10.35.0.0/16 subnet to use NS1 and NS2 servers as primary and secondary DNS servers. This is largely operating system dependent, but for most Linux distributions, the settings that need to be changed are permanently located in the /etc/resolv.conf file.

Typically on Ubuntu, Debian and CentOS distributions, just edit the /etc/resolv.conf file, run the following command as root:

# nano /etc/resolv.conf

Then replace the existing nameservers with:

nameserver 10.35.30.13 #ns1
nameserver 10.35.30.14 #ns2

Now save and close the file and the client should be configured to use the NS1 and NS2 nameservers.

Then check how your clients can send queries to the DNS servers you just configured:

# nslookup host1.test.example.ru

The output of this command should be as follows:

Output:
Server:     10.35.30.13
Address:    10.35.30.13#53

Name:   host1.test.example.ru
Address: 10.35.55.154

You can also test reverse lookups by querying the DNS server with the host’s IP address:

# nslookup 10.35.55.154

The output should look like this:

Output:
Server:     10.35.30.13
Address:    10.35.30.13#53

154.55.20.10.in-addr.arpa   name = host1.test.example.ru.

Verify that all nodes are resolved correctly using the commands above, if it means everything is configured correctly.

Adding a new host to DNS servers

If you need to add a host to DNS servers, just follow these steps:

On the ns1 name server, do the following:

  • Create an A record in the front zone file for the host and increment the sequential variables.
  • Create a PTR record in the reverse zone file for the host and increment the sequential variables.
  • Add the private IP address of the host to the trusted ACL in named.conf.options.
  • Refresh BIND with the following command: sudo service bind9 reload

On the ns2 name server, do the following:

  • Add the private IP address of the host to a trusted ACL in named.conf.options.
  • Refresh BIND with the following command: sudo service bind9 reload

On the host computer, do the following:

  • Edit /etc/resolv.conf and change the nameserver for your DNS servers.
  • Use nslookup to check that the host is querying DNS servers.

Removing an existing host from your DNS servers

If you want to remove a host from your DNS servers, just reverse the steps above.

Note: Please replace the name and IP address used in this manual with the names and IP addresses of hosts on your own private network.

Sidebar