Hack and / - Your Own Personal Server: DNS

Why let registrars have all the fun? Learn how to set up your own DNS server completely under your own control.
Master DNS Configuration

A DNS master contains its own zone files that have name→IP address mappings, and it doesn't have to consult any other source to answer queries for those names. By contrast, a DNS slave is configured to load all of its zone configurations from a DNS master. Any future changes are made on the master and propagate to each of the slaves. Any individual BIND instance acts as a DNS master, a DNS slave or a caching name server, or all three at the same time (although it can be a master or a slave only to any individual zone, not both).

For this example, let's set up a DNS master for example.org, and this master will have the following records:

  • ns1.example.org, which points to (the public IP of the name server itself).

  • example.org, which points to

  • www.example.org also points to

To start, I create the zone file at /etc/bind/db.example.org (remember Red Hat stores these zones in a different places) and put the following information in it:

; BIND data file for example.org
$TTL 4h
@  IN  SOA ns1.example.org. root.example.org. (
	    2		; Serial
	    604800 	; Refresh
	    86400 	; Retry
	    2419200 	; Expire
	    604800 ) 	; Negative Cache TTL
@	IN NS	ns1.example.org.
@ 	IN A
www	IN A
ns1 	IN A

Make sure this file has similar permissions to the other zone files you find in the /etc/bind directory. The first non-comment line in the file sets the TTL or Time To Live, the default time in which a remote DNS server will cache any answers it gets from your DNS server before it will ask it again. The value you put here will help determine how fast changes you make will propagate. BIND accepts seconds in this field, or you can use shorthand values like 1d for one day, 4h for four hours or 20m for 20 minutes. I set the TTL to four hours here; however, if you make frequent changes to your records (or know you are going to soon), you may want to make the TTL shorter. On the other hand, if you find you hardly ever change these values, you might want to bump up the TTL to a day to reduce load on your DNS server.

Something to note is that zone files use semicolons not hashes at the beginning of a line for comments. A common mistake is to put hashes in a zone file to make a comment, reload BIND and then wonder why your changes didn't take. When BIND sees a mistake like that, it just skips that particular zone.

To keep things simple, I'm going to skip the Retry, Refresh and other values here—just keep them with these defaults unless you know what you are doing. The Serial line is for DNS slaves, which I discuss later. Below those values, however, you'll see the syntax I used to define the different records:

@	IN NS	ns1.example.org.
@ 	IN A
www	IN A
ns1 	IN A

The first record starts with @, which means it is a record for example.org itself. In this case, it is an NS record that defines the hostname I'm going to use for my name server. You can use any hostname you control here (including hostnames on a different domain, actually), but one popular convention is to use hostnames like ns1 and ns2 for the first and second name servers. The second record begins with an @ as well, only in this case, it's an A record. An A record is a fundamental DNS record that maps a hostname (like www) to an IP address (like In this case, because the record starts with @, I am setting the IP address for example.org itself. The next two lines define two more A records, one for www.example.org and one for ns1.example.org. It's important if you used a name within this same domain for your name server (like ns1.example.org) that you be sure to add an A record so that it has an IP address.

Now that I have created my zone, next I need to modify the /etc/bind/named.conf file and add a new section at the end of the file to point to the /etc/bind/db.example.org file I just created:

zone "example.org" {
	type master;
	file "/etc/bind/db.example.org";

After the file is changed, I reload BIND, and I should be able to send DNS requests to my new DNS server:

$ sudo /etc/init.d/bind9 reload
* Reloading domain name server... bind [OK]

$ nslookup www.example.org localhost
Server:		localhost

Name:	www.example.org

If there is a problem with the BIND reload, it should tell you on the command line. Otherwise, if it still doesn't work, you may have to look in your syslog file (/var/log/syslog on Debian-based systems and /var/log/messages on Red Hat) for clues.


Kyle Rankin is Chief Security Officer at Purism, a company focused on computers that respect your privacy, security, and freedom. He is the author of many books including Linux Hardening in Hostile Networks, DevOps Troubleshooting and The Official Ubuntu


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.


jonny rocket's picture


A good high level explanation.

pradeep.aradhya's picture

A good high level explanation.