We are looking to setup up a minimal forwarding DNS server on Ubuntu 16.04. After that we will see how to use nsupdate and dig to verify our configuration.


  • A VM running Ubuntu 16.04 with BIND installed
    • You need root access for the VM
  • External DNS server information
    • We are going to use google’s DNS servers ( and as our external servers. In case a query can’t be resolved by our DNS server it will forward the request to the external server.
  • Domain information
    • We need to know the domain topology we want our DNS server to manage. In this tutorial we are going to manage dev.lab domain using our DNS server
  • Network information (optional)
    • We need to know the network topology we which to use as part of our setup. For this example we will use a simple Class C network
  • Optionally you can setup a reverse DNS resolution but we are not going todo that today

For our example we are going to use the below network configuration on the VM running the DNS service. The below code block represents the /etc/network/interfaces file from our VM which is going to run the DNS service.

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface enh0 inet static
        # dns-* options are implemented by the resolvconf package, if installed
        dns-search dev.lab

DNS service setup

We can install bind by running the following command from the termial.

apt install bind9

After installing bind we need configure the below listed files to make setup our domain dev.lab.

First we will generate TSIG key for our domain by running the below command. These keys are required if you need to update your DNS records dynamicaly using a tool such as nsupdate. We will see the details in the later section.

dnssec-keygen -a HMAC-MD5 -b 128 -n HOST dev.lab.

After you run above mentioned command you should see two new files with names similiar to the ones listed below when you run ls -l command in your pwd.

├── Kdev.lab.+157+08670.key
└── Kdev.lab.+157+08670.private

If you cat the above listed files you should see entries like the following two.

dev.lab. IN KEY 512 3 157 6wYwnp6Y8oyg4H6HGWc2pw==
Private-key-format: v1.3
Algorithm: 157 (HMAC_MD5)
Key: 6wYwnp6Y8oyg4H6HGWc2pw==
Bits: AAA=
Created: 20170822164340
Publish: 20170822164340
Activate: 20170822164340

Backup of these files in a safe location. They are required in case you need to communicated with you DNS server via nsupdate in the future.

Second we will create a new db for the domain dev.lab. This files needs to be placed at /etc/bind/db.dev.lab with the exact same file name. The content of the file looks similiar to the one below. If you closely observe line numbers 15 to 17 you will see two CNAME entries and on A entry. Both dns and ntp entries are pointing to ns entry because we are planing to run both NTP and DNS services on the same machine.

; BIND reverse data file for empty rfc1918 zone
; DO NOT EDIT THIS FILE - it is used for multiple zones.
; Instead, copy it, edit named.conf, and use that copy.
$TTL	86400
@	IN	SOA	dev.lab. root.dev.lab. (
			      1		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			  86400 )	; Negative Cache TTL
@	IN	NS		ns.dev.lab.
dns	IN	CNAME	ns.dev.lab.
ntp	IN	CNAME	ns.dev.lab.
ns	IN	A

After creating /etc/bind/db.dev.lab file make a softlink for the file /etc/bind/db.dev.lab inside /var/cache/bind.

ln -s /etc/bind/db.dev.lab /var/cache/bind/db.dev.lab

As third step, we will configure the TSIG key and the bind it to the domain name dev.lab via zone entry. Create file /etc/bind/dev-lab.key with same content as shown in the below code block. Note that the line number 3 contains the TSIG key value which we generated previously.

key "dev.lab." {
        algorithm hmac-md5;
        secret "6wYwnp6Y8oyg4H6HGWc2pw==";

Now append the below configuration to the /etc/bind/named.conf.local to bind the TSIG key and dev.lab domain. The zone entry basically lists where is the db file for dev.lab domain is located and which key to use for authenticating while modifying the entries for the domain dev.lab dynamically.

include "/etc/bind/dev-lab.key";

zone "dev.lab." {
     type master;
     notify no;
     file "/var/cache/bind/db.dev.lab";
     allow-update { key "dev.lab."; };

And for the final step, we will configure the forward DNS server entries in case our DNS server could’t resolve a particular domain request. For this we need to add forwarders block to /etc/bind/named.conf.options file. Note the line numbers 13 to 16.

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

	// If there is a firewall between you and nameservers you want
	// to talk to, you may need to fix the firewall to allow multiple
	// ports to talk.  See http://www.kb.cert.org/vuls/id/800113

	// If your ISP provided one or more IP addresses for stable
	// nameservers, you probably want to use them as forwarders.
	// Uncomment the following block, and insert the addresses replacing
	// the all-0's placeholder.

	forwarders {;;

	forward only;

	// If BIND logs error messages about the root key being expired,
	// you will need to update your keys.  See https://www.isc.org/bind-keys
	dnssec-enable no;
	dnssec-validation no;
	dnssec-lookaside no;

	auth-nxdomain no;    # conform to RFC1035
	listen-on-v6 { any; };
	listen-on {;;

By default bind listens only on But for our use case we need this server to be accessible from all the clients connected to subnet. For this you need to add our VM’s ip address to the listen block (line number 32). Now if you want your DNS server to serve DNS requests from clients connected to network other than google for how to configure and use allow-query / allow-query-cache blocks.

With this the configuration portion is complete for our domain dev.lab. To start/restart the DNS server run the below command.

systemctl restart bind9

You can get to know the status of the service by running systemctl status bind9

Verifying the DNS setup

We will see how to validate our DNS server is working as expected using two simple commands nsupdate and dig.

Verifying DNS domain setup

We can verify our domain dev.lab is setup properly by adding and removing DNS entries.

Adding a new DNS entry

To add a new DNS entry invoke nsupdate followed by below instruction. The below instructions add nfs.dev.lab as domain name to the ip address

Note the key used in third line is the same TSIG key we generated and configured for our domain dev.lab in the above section.

debug yes
key dev.lab 6wYwnp6Y8oyg4H6HGWc2pw==
update add nfs.dev.lab 86400 a

Deleting a DNS entry

To remove an existing entry invoke nsupdate with following commands

debug yes
key dev.lab 6wYwnp6Y8oyg4H6HGWc2pw==
update delete nfs.dev.lab 86400 a

We can mix match the use of add and delete statements. For example the below list of instructions for nsupdate is perfectly valid.

debug yes
key dev.lab 6wYwnp6Y8oyg4H6HGWc2pw==
update add nfs.dev.lab 86400 a
update delete nfs.dev.lab 86400 a
update add nfs.dev.lab 86400 a

Verifying DNS entries and DNS forwarding

To verify a DNS entry added to the server execute dig @ nfs.dev.lab and you should get an output similiar to the below one:

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @ nfs.dev.lab
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24342
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

; EDNS: version: 0, flags:; udp: 4096
;nfs.dev.lab.	IN	A

nfs.dev.lab. 86400 IN	A

dev.lab.		86400	IN	NS	ns.dev.lab.

ns.dev.lab.	86400	IN	A

;; Query time: 0 msec
;; WHEN: Tue Aug 22 23:10:16 IST 2017
;; MSG SIZE  rcvd: 104

To verify the forward DNS functionality execute the above command requesting an resolution to a domain other than dev.lab. For example, dig @ gitlab.com should produce an output similiar to the below one.

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @ github.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44220
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 13, ADDITIONAL: 26

; EDNS: version: 0, flags:; udp: 4096
;github.com.			IN	A

github.com.		35	IN	A
github.com.		35	IN	A

com.			45434	IN	NS	b.gtld-servers.net.
com.			45434	IN	NS	d.gtld-servers.net.
com.			45434	IN	NS	a.gtld-servers.net.
com.			45434	IN	NS	e.gtld-servers.net.
com.			45434	IN	NS	j.gtld-servers.net.
com.			45434	IN	NS	g.gtld-servers.net.
com.			45434	IN	NS	l.gtld-servers.net.
com.			45434	IN	NS	m.gtld-servers.net.
com.			45434	IN	NS	h.gtld-servers.net.
com.			45434	IN	NS	f.gtld-servers.net.
com.			45434	IN	NS	c.gtld-servers.net.
com.			45434	IN	NS	i.gtld-servers.net.
com.			45434	IN	NS	k.gtld-servers.net.

a.gtld-servers.net.	87848	IN	A
a.gtld-servers.net.	87848	IN	AAAA	2001:503:a83e::2:30
b.gtld-servers.net.	20034	IN	AAAA	2001:503:231d::2:30
c.gtld-servers.net.	115424	IN	A
c.gtld-servers.net.	115424	IN	AAAA	2001:503:83eb::30
d.gtld-servers.net.	18843	IN	A
d.gtld-servers.net.	18399	IN	AAAA	2001:500:856e::30
e.gtld-servers.net.	110668	IN	A
e.gtld-servers.net.	110668	IN	AAAA	2001:502:1ca1::30
f.gtld-servers.net.	97272	IN	A
f.gtld-servers.net.	147976	IN	AAAA	2001:503:d414::30
g.gtld-servers.net.	145988	IN	A
g.gtld-servers.net.	43547	IN	AAAA	2001:503:eea3::30
h.gtld-servers.net.	97403	IN	A
h.gtld-servers.net.	97403	IN	AAAA	2001:502:8cc::30
i.gtld-servers.net.	10551	IN	A
i.gtld-servers.net.	10669	IN	AAAA	2001:503:39c1::30
j.gtld-servers.net.	11797	IN	A
j.gtld-servers.net.	11797	IN	AAAA	2001:502:7094::30
k.gtld-servers.net.	74153	IN	A
k.gtld-servers.net.	74153	IN	AAAA	2001:503:d2d::30
l.gtld-servers.net.	110299	IN	A
l.gtld-servers.net.	109769	IN	AAAA	2001:500:d937::30
m.gtld-servers.net.	127321	IN	A
m.gtld-servers.net.	125906	IN	AAAA	2001:501:b1f9::30

;; Query time: 44 msec
;; WHEN: Tue Aug 22 23:12:23 IST 2017
;; MSG SIZE  rcvd: 851


  1. How To Configure Bind as a Caching or Forwarding DNS Server on Ubuntu 14.04 - from Digital Ocean blog
  2. How To Configure BIND as a Private Network DNS Server on Ubuntu 14.04 - from Digital Ocean blog
  3. nsupdate - linux man page
  4. dig - linux man page