Apr 112011

The goal of this article is to describe how to setup your own DNS server to serve the domain name service entries for a TLD (example.com). In the last part of the article I describe how to increase the speed of the system and the security in order to use it as public authoritative DNS nameserver for your domain.

Install the Nameserver using the Package Manager

Access the server, become the root user, install the bind9 package and stop the server for the moment:

apt-get install bind9
/etc/init.d/bind9 stop

On Debian squeeze, the current version being installed is BIND 9.6-ESV-R3 (find out by running named -v on the command line locally or dig @your-nameserver version.bind txt chaos remotely).

Configure a Forward Lookup Zone File

Now create your zone configuration file for the domain example.com, /etc/bind/db.example.com. In this file you set up your subdomains, how the domain is resolved for the email system etc.:

;; `/etc/bind/db.example.com` - Forward lookup zone file for the TLD example.com
;; For explanations: <http://blog.philippklaus.de/2011/04/get-your-own-dns-server-up-and-running-with-bind9-on-ubuntu-or-debian/>
$ORIGIN example.com.
; The SOA Resource Record (in the following format:)
;name [ttl] [class] rr      name-server           e-mail             ( [...] )
@           IN      SOA     ns.example.com.       mail.example.com.  (
                        2011041101      ; Serial (usually YYYYMMDDSS): increment after any change
                                8H      ; Refresh (8 hours)
                                2H      ; Retry (2 hours)
                                4W      ; Expire (4 weeks)
                                3H )    ; NX (3 hours) TTL Negativ Cache

@                               IN      NS      ns.example.com.
                                IN      MX      10 mailserver.example.com.
                                IN      A

ns                              IN      A
localhost                       IN      A
computer1                       IN      A
mailserver                      IN      A
computer2                       IN      CNAME   mailserver

You might want to learn more about the different RR types on http://en.wikipedia.org/wiki/List_of_DNS_record_types.

$TTL (time to live): The number of seconds a domain name is cached locally before expiration and return to authoritative nameservers for updated information.

Explanation of the the SOA record:

  • Serial
    The zone serial number, incremented when the zone file is modified, so the slave and secondary name servers know when the zone has been changed and should be reloaded.
  • Refresh
    This is the number of seconds between update requests from secondary and slave name servers.
  • Retry
    This is the number of seconds the secondary or slave will wait before retrying when the last attempt has failed.
  • Expire
    This is the number of seconds a master or slave will wait before considering the data stale if it cannot reach the primary name server.
  • NX
    TTL for negative caching. (This value has previously been used to determine the minimum TTL.)

Another bunch of important tips:

  • If you leave out the name in a line it is taken from the line above.
  • @ will be replaced by the FQDN of $ORIGIN (if it is set) or by the domainname set in the line zone "domainname" { in the file /etc/bind/named.conf.local.
  • When setting up the subdomain www you might want to add it as a CNAME record for @.
  • You can leave out the TTL and CLASS entry for a record line (TTL will be set to the value of $TTL and the class will be INinternet).

Create a Reverse Lookup Zone File

Create the file /etc/bind/db.1.168.192

;; db.1.168.192 - Reverse lookup zone for domain-name
@       IN      SOA     ns.example.com. mail.example.com. (
                                2011041101      ; Serial
                                        8H      ; Refresh
                                        2H      ; Retry
                                        4W      ; Expire
                                        2D )    ; TTL Negative Cache

@       IN      NS      ns.example.com.
                                               ;;; what it stands for:
10      IN      PTR     ns.example.com.        ; The nameserver:
200     IN      PTR     computer1.example.com. ; Computer #1:
201     IN      PTR     computer2.example.com. ; Computer #2:

add your new zone files to the local config file named.conf.local

Now add your new zone configuration files to your /etc/bind/named.conf.local:

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

zone "1.168.192.in-addr.arpa" {
  type master;
  file "/etc/bind/db.1.168.192";

Allow your subnet to access the DNS server

If you want to access your new DNS server from your subnet 192.168.1/24 (all IPs from up to, add allow-query-cache {192.168.1/24;}; to your /etc/bind/named.conf.options so that it looks like this:

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

  auth-nxdomain no;    # conform to RFC1035

  allow-query-cache {192.168.1/24;};

Start the nameserver bind9

Now you should be ready to restart bind9 with your new configuration:

/etc/init.d/bind9 restart

If could fail (like in the following code block):

lion:/etc/bind# /etc/init.d/bind9 restart
Stopping domain name service...: bind9rndc: connect failed: connection refused
Starting domain name service...: bind9 failed!

Then have a look at /var/log/syslog which will help you out with debugging information:

Apr 11 17:27:24 lion named[29991]: loading configuration from '/etc/bind/named.conf'
Apr 11 17:27:24 lion named[29991]: /etc/bind/named.conf:36: missing ';' before '}'
Apr 11 17:27:24 lion named[29991]: loading configuration: failure
Apr 11 17:27:24 lion named[29991]: exiting (due to fatal error)

In this case a colon ; was missing in the configuration file.

Setting up an authoritative-only DNS server with Bind9

The following paragraph is based on pages 154-155 of the book “Pro DNS and BIND 10″, Apress, 2011, ISBN: 9781430230489.

To set up an authoritative-only DNS server with Bind9 on Ubuntu/Debian I recommend to replace the default set of configuration files on the standard Ubuntu/Debian installation (including named.conf, named.conf.options, named.conf.local and some zone files such as db.0, db.255, db.127, db.local, db.empty, zones.rfc1918, db.root, all stored in /etc/bind/) with the following global configuration file /etc/bind/named.conf:

// ----------------------- Options ----------------------- 
options {
  // all relative paths use this directory as a base
  directory "/var/cache/bind";
  // version statement changed for security (to avoid hacking known weaknesses)
  version "not currently available";
  // This prevents bind from serving other than authoritative requests:
  recursion no;
  // disables all zone transfer requests for performance as well as security reasons
  dnssec-enable no; // zone not signed
  minimal-responses yes; // optional - improved performance
  additional-from-auth no; // optional - improved performance
  additional-from-cache no; // optional - minimal performance change

// ----------------------- Logging ----------------------- 
// log to /var/log/named/zytrax-named all events from info UP in severity (no debug)
// uses 3 files in rotation swaps files when size reaches 250K
// failure messages up to this point are in (syslog) /var/log/messages
  channel custom_log{
    file "/var/log/bind9_info.log" versions 3 size 250k;
    severity info;
  category default{

// ----------------------- Zones ----------------------- 
zone "example.com" in{
  type master;
  file "/etc/bind/db.example.com";
  allow-transfer {;}; // slave server for the domain
// reverse map for local address at example.com (uses for illustration)
zone "1.168.192.IN-ADDR.ARPA" in{
  type master;
  file "/etc/bind/db.1.168.192";

// local host domain (required)
zone "localhost" in{
  type master;
  file "/etc/bind/master.localhost";
// localhost reverse map
  zone "0.0.127.IN-ADDR.ARPA" in{
  type master;
  file "/etc/bind/localhost.rev";

Where /etc/bind/db.example.com and /etc/bind/db.1.168.192 are your custom zone files (as described earlier in this post).


  • An authoritative-only DNS server does not provide services for any domain except those for which it is either a master or a slave. As a consequence the root.servers zone file is not present (cf. zone "."). The recursion no; statement inhibits recursive behavior; the name server will return REFUSED status (BIND >=9.7) if it receives a query for any domain or zone for which it is neither master nor slave.
  • DNSSEC is turned off using dnssec-enable no; (this zone is not signed and since BIND 9.5, yes is the BIND 9 default setting).
  • Zone transfers are disabled (allow-transfer {none;};) in the options section which means you can avoid possible DDoS attacks via zone transfer on the localhost or reverse-map zones as well as the more obvious example.com zone. Zone transfer is allowed to the assumed slave zone at in the zone example.com only. This configuration also assumes that the master file is moved to this server by some out-of band method such as USB stick, secure FTP, ssh, etc. It is also possible to make this a slave server to a hidden master. However, the IP address of this hidden master (because it will appear in the slave’s masters statement) might get compromised if an attacker can read the named.conf file on your system; since this external server must be able to communicate with the hidden master (to transfer the zone), so can an attacker—with less benign motives.
  • To boost the performance of Bind, you have to reduce the volume of data returned to requests as much as possible. This is done by setting the options minimal-responses, additional-from-auth and additional-from-cache.
    minimal-responses alone, depending on the configuration, can theoretically almost double query throughput. In the real world, this is not exact, as some of the data that is omitted is still required by the resolver. In the case of in-zone data, for example, it will immediately result in another query. After all it can still have a significant effect.
    Neither of the statements additional-from-auth no; nor additionalfrom-cache no; will have any effect on performance with the example configuration above. But with some changes they could have.
    If additional-from-auth was not present (it defaults to yes) and this name server was also authoritative (master or slave) for any out-of-zone reference, then this name server would add data to the ADDITIONAL SECTION in responses to example.com queries by following the out-of-zone references.
    additional-from-cache prevents adding any data to the ADDITIONAL SECTION if it happens to be lying around in the cache. Since recursion is turned off completely, there should be nothing in the cache, but it does prevent the cache from even being searched. Prior to BIND 9.7, this statement also controlled returning referrals to a query for a zone this server was not authoritative for. Since BIND 9.7 such queries now result in REFUSED status being returned. The effect of additional-from-cache no; is probably less than minimal and it could be omitted with little loss of performance.
  • The reverse-map zone (zone "1.168.192.IN-ADDR.ARPA") is assumed to represent the domain’s public addresses (the use of a private IP RFC 1918 address netblock is simply to avoid using a real public IPv4 address range). This reverse-map zone would only be present if the domain owner has the responsibly for reverse mapping. Either because they own the IPv4 netblock or their service provider has delegated the responsibility. In all cases, because mail servers do reverse-map look-ups, you will need to ensure that your mail server(s) have properly configured reverse maps either by creating and maintain a reverse-map zone or ensuring that your service providers adds the required the reverse map entries. In the case of IPv6, reverse maps are compulsory and will be in the user’s responsibility.
  • BIND provides 3 statements to control the caching behavior: max-cache-size and max-cache-ttl, neither of which will have any effect on performance in the preceding case; and allow-recursion, which allows a list of hosts that are permitted to use recursion – all others are not (a kind of “poor man’s view clause”).

Please not that we didn’t include the root zone (“.”). You are, however, required to include it in some cases: The configuration requires a root zone if NOTIFY is being used (set by default unless you set notify no;) and if one or more of the NS RR entries is out-of-zone and if this server is not authoritative for the out-of-zone domain name. Please refer to p. 153 in the book “Pro DNS and BIND 10″, Apress, 2011, ISBN: 9781430230489 for more information.

The localhost forward zone file /etc/bind/master.localhost and its reverse zone file /etc/bind/localhost.rev should be set to the following:

;;; /etc/bind/master.localhost
$TTL 1d ;
$ORIGIN localhost.
@   IN   SOA   @   hostmaster.localhost. (
                 2011041101 ; serial
                 3H ; refresh
                 15M ; retry
                 1w ; expire
                 3h ; nx
@   IN   NS    @ ; localhost is the name server
    IN   A ; the loop-back address


;;; /etc/bind/localhost.rev
; could use $ORIGIN 0.0.127.IN-ADDR.ARPA.
@   IN   SOA   @    hostmaster.localhost. (
                3h )
    IN   NS    localhost.
1   IN   PTR   localhost.

Get the logging right / debug Bind9

If you add a logging section to your /etc/bind/named.conf, you can send debug output to a dedicated logfile. If your logfile is /var/log/bind9_info.log, you have to create it manually and give it the right ownership:

touch /var/log/bind9_info.log
chown bind:root /var/log/bind9_info.log

For extended debugging, you might consider to temporarily set the following logging section:

logging {
    category "default" { "debug"; };
    category "general" { "debug"; };
    category "database" { "debug"; };
    category "security" { "debug"; };
    category "config" { "debug"; };
    category "resolver" { "debug"; };
    category "xfer-in" { "debug"; };
    category "xfer-out" { "debug"; };
    category "notify" { "debug"; };
    category "client" { "debug"; };
    category "unmatched" { "debug"; };
    category "network" { "debug"; };
    category "update" { "debug"; };
    category "queries" { "debug"; };
    category "dispatch" { "debug"; };
    category "dnssec" { "debug"; };
    category "lame-servers" { "debug"; };
    channel "debug" {
    file "/var/log/bind.log" versions 2 size 50m;
        print-time yes;
        print-category yes;


VN:F [1.9.22_1171]
Rating: 6.2/10 (6 votes cast)
Get your own DNS server up and running with Bind9 on Ubuntu or Debian, 6.2 out of 10 based on 6 ratings

Related Posts:

  11 Responses to “Get your own DNS server up and running with Bind9 on Ubuntu or Debian”

  1. That’s just what I needed – something simple to get me started, and it worked like a dream. Nice, thanks.

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
    • Hi Kenny! I’m glad you found the the post to be useful!

      VN:F [1.9.22_1171]
      Rating: 0 (from 2 votes)
  2. […] is NOT present on the new host. I started with this… (getting started/recipe-type/howto…) My references are: BIND9ServerHowto […]

  3. Exactly what i needed. I’ve been looking at a way to get this to work in Debian Wheezy in Hyper-V and I’d been struggling configuring my Zone. I didn’t add my subnet to the named.conf.options file as it was working without it, but i guess for a small private network like mine it isn’t needed.

    Thanks again.

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  4. […] Configuring Bind or Bind9

    To cut down on the size of this post, I am going to redirect you to do the main name server configuration. This is the tutorial I used when I set mine up:


    The above link simplifies the config process as much as possible. It is still complex and overwhelming for many people though, so if you have the patience, go for it, but if you don’t, then this may not be the project for you to be honest.[…]

    VN:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  5. This was one of many great resources in getting my authoritative-only bind dns server up. I had spent a great deal of time going through my server configs, named-checkconfig, named-checkzone, and re-configuring my 3 non-delegated subszones, and logs prior to this. With BIND DNS, there were so many ways to set it up that can get you into trouble when it comes to security. Here’s another good resource for those of you who work with BIND DNS. It’s online reference that is pretty good: http://www.zytrax.com/books/dns/

    Thank you for you time and effort in providing this writeup.

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  6. Hi. Thanks for the detailed tutorial. I’m new to Bind and would like to achieve the following:

    1. Register own domain name (done) with GoDaddy.com e.g (mydom1.com) which I will setup two hosts using VPS from DigitalOcean (done). Bind9 is also installed on both hosts, ns1.mydom1.com and ns2.mydom2.com
    2. Next, register 2ND domain name (e.g mydom2.com) with GoDaddy.com and set my own nameserver (ns1.mydome1.com and ns2.mydom1.com) in a master/slave configuration.
    3. Next, register 3RD domain name (e.g mydom3.com) with GoDaddy.com and set my own nameserver (ns1.mydome1.com and ns2.mydom1.com) in a master/slave configuration.

    Basically, I would have my own publicly available nameservers which I can host the zones for mydom2.com and mydom3.com and any other domain names I may be registering.

    I understand this is a lot of advice to ask for and I would really appreciate it if you could point me to some tutorials if you don’t already have them in your repository.

    Q1. Do I need to do something with my ISP or Domain name registrar in order to have my MYDOM1.COM’s NS1.MYDOM1.COM and NS2.MYDOM1.COM recognized as legitimate nameservers?

    Q2. If NS1.MYDOM1.COM and NS2.MYDOM2.COM aren’t able to resolve DNS requests from HOSTNAME.MYDOM2.COM AND HOSTNAME.MYDOM3.COM, then the requests could be forwarded to Google’s public DNS where the results would then be cached in NS1.MYDOM1.COM and NS2.MYDOM1.COM. Is this possible?

    Q3. If NS1.MYDOM1.COM is down for any reason, how may I make NS2.MYDOM1.COM take its place seemlessly?

    Sorry if I’m creating some confusion here. I would really like to learn how to setup Bind properly on my Ubuntu VPS and of course save money since I may be registering more domain names.

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
    • Hi Trempest,

      what you want to achieve should absolutely be possible. To answer your questions:

      Q1: Your ISP is not involved in this but your domain name registrar must allow you to set the NS resource records for your domain. Most registrars do. If you want to know how those resource records should look like, you can ask how they are set for other domains. You can use the tool dig on the Linux terminal to check how Google’s records are set:

      philipp@lion$ dig google.com ns
      google.com.     345517  IN  NS  ns2.google.com.
      google.com.     345517  IN  NS  ns1.google.com.
      philipp@lion$ dig ns2.google.com a
      ns2.google.com.     345600  IN  A

      Q2: First of all: You mean NS2.MYDOM1.COM, right? I don’t understand the from in your sentence “able to resolve DNS requests from”. Do you care from where (in terms of domain names) your requests come from? Or is your question about resolving request for that domain? You can configure Bind to forward DNS requests that it is not responsible for and doesn’t know about to another DNS server or to fetch the result from the global DNS tree itself. If you don’t want to offer this (recursive) service to the whole Internet world (you shouldn’t) than you should restrict this service to a network that belongs to you. You can restrict it to certain IP addresses but not that easily to host names.

      Q3. If both servers are set in the NS entries for the domain to be resolved then this is done automatically. Clients resolving an address will try to get an answer from all nameservers if the others are unavailable.

      Hope I could help you a little bit with your questions.

      Best, Philipp

      VN:F [1.9.22_1171]
      Rating: 0 (from 0 votes)
  7. Thank you for a good insight! Guys, anyone out there having a script similar to these requirements? Create a script that installs and configures bind to serve a private domain.

    Test if bind is installed, and install it if it is not installed.

    Get a domain name from the script user. Complain and exit if the domain already exists.

    Create a zone file for the new domain.

    Use as the IP address for the name ns1 in the new domain. Use that as the name of the nameserver for the domain.

    Add the name www with the address to the domain.

    Add the name mail with the address to the domain.

    Set the origin of the domain to be ns1 in the domain and the domain admin email to be hostmaster@thedomainname.

    Create reverse zone files for the 192.168 addresses we have used.

    Add your new zones to the named.conf.local file if they aren’t already there. Any help would be appreciated as well as rewarded!

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>