Configuring a BIND DNS Server

August 7, 2004, updated August 11, 2004

I will be assuming you are running RedHat/Fedora or something of the like and you have BIND 9 already installed. Might as well use their rpm to put everything in place. This configuration does not use a chrooted environment . If one is setup you're going to have to disable it or figure out how to make this tutorial work for you. Make sure and comment out the ROOTDIR directive in /etc/sysconfig/named and clean out your /var/named directory. If you don't know what it is and you really don't care, I wouldn't worry about it unless your working on a root server.

Setting up your own caching server is something you want to do if you have a lot of computers behind a gateway/firewall and you want to save traffic and time for DNS queries. This can significantly reduce the amount of traffic and allow you to browse sites at a caffeine induced pace.

First thing we need to do is setup the /etc/named.conf file. This is the configuration file for named. You'll notice a /etc/named.custom file floating around also. I just commented that crap out as I am not going to be using any tools to edit these files. Don't let this example overwhelm you. You don't need half the crap in this file, but it looks like you know what you're doing if you use it.

acl "trusted" {
        localhost;
        192.168.0.0/16;
};
 
# these are just a list of ip's that I consider bogus and just ignore them
acl "bogusips" {
        0.0.0.0/8;
        1.0.0.0/8;
        2.0.0.0/8;
        192.0.2.0/24;
        224.0.0.0/3;
        169.254.0.0/16;
};
 
options {
 
        directory "/var/named";
 
        allow-transfer { none; };
        allow-query { trusted; };
        allow-recursion { trusted; };
        blackhole { bogusips; };
 
        # limit number of clients at a time; prevent some wack app or
        # somebody from DDoSing the server
        tcp-clients 32;
 
        # listen on these interfaces
        listen-on {
                127.0.0.1;
                192.168.0.1;
        };
 
        # forwarders will help speed things up, these should be
        # your ISP DNS servers or some other server you have permission
        # to query
        # it is NOT nice to query the root servers for everything
        # all the time
        forwarders {
                198.10.10.1;
                198.10.10.2;
        };
 
        # forward first/only, in this case we wanna try to forward
        # first before we query a root server
        forward first;
 
        # allow recursion
        recursion yes;
 
        # look at the documentation to see what this stuff does.
        # it may not be necessary in your case
        dialup yes;
        heartbeat-interval 1440;
 
        # delete expired records every 28 days
        cleaning-interval 40320;
 
        # not necessary to set the source port, I don't care 
        # what it ends up being
        #query-source port 53;
 
};
 
controls {
        inet 127.0.0.1 allow { localhost; } keys { rndckey; };
};
 
zone "." IN {
        type hint;
        file "db.cache";
};
 
zone "localhost" IN {
        type master;
        file "localhost.zone";
        allow-update { none; };
        notify no;
};
 
controls {
        inet 127.0.0.1 allow { localhost; } keys { rndckey; };
};
 
zone "." IN {
        type hint;
        file "db.cache";
};
 
zone "localhost" IN {
        type master;
        file "localhost.zone";
        allow-update { none; };
        notify no;
};
 
zone "0.0.127.in-addr.arpa" IN {
        type master;
        file "named.local";
        allow-update { none; };
        notify no;
};
 
zone "cooldomain" in {
        type master;
        file "cooldomain.zone";
        allow-update { trusted; };
        notify no;
};
 
zone "0.168.192.in-addr.arpa" IN {
        type master;
        file "192.168.0.rev";
        allow-update { trusted; };
        notify no;
};
 
# do a little logging for debug purposes
logging{
        channel "simple_log" {
                file "/var/named/bind.log" versions 3 size 5m;
                severity debug 100;
                print-time yes;
                print-severity yes;
                print-category yes;
        };
 
        category default{
                "simple_log";
        };
};
 
include "/etc/rndc.key";

Just to explain a couple things. You probably don't want that much freedom in your trusted hosts. You might want to seperate out those that are allowed to update, if any, and those that can query. You can use "none" where you don't want any other server/host to be allowed to update the zones. You can take out the whole logging directive once you're finished. Most of the stuff in there is for developers. Make sure and check /var/log/messages frequently as it will display some better errors.

Now we need to setup the zone files. We will setup the forward and reverse lookup zone files for cooldomain.

/var/named/named.local
$TTL    86400
@       IN      SOA     localhost. root.localhost.  (
                                      1          ; Serial
                                      28800      ; Refresh
                                      14400      ; Retry
                                      3600000    ; Expire
                                      86400 )    ; Minimum
              IN      NS      localhost.
 
1       IN      PTR     localhost.
/var/named/192.168.0.rev
$ORIGIN .
$TTL 259200     ; 3 days
168.192.0.in-addr.arpa     IN SOA  cooldomain. root.cooldomain. (
                                226        ; serial
                                28800      ; refresh (8 hours)
                                7200       ; retry (2 hours)
                                604800     ; expire (1 week)
                                86400      ; minimum (1 day)
                                )
                        NS      ns1.cooldomain.
$ORIGIN 168.192.0.in-addr.arpa.
1                       PTR     server.cooldomain.
                        PTR     mail.cooldomain.
/var/named/cooldomain.zone
$ORIGIN .
$TTL 3600       ; 1 hour
cooldomain             IN SOA  ns1.cooldomain. root.cooldomain. (
                                833        ; serial
                                21600      ; refresh (6 hours)
                                1800       ; retry (30 minutes)
                                604800     ; expire (1 week)
                                3600       ; minimum (1 hour)
                                )
                        NS      ns1.cooldomain.
                        A       192.168.0.1
                        MX      10 mail.cooldomain.
                        TXT     "Server"
$ORIGIN cooldomain.
server                     A       192.168.0.1
/var/named/localhost.zone
$TTL    86400
$ORIGIN localhost.
@                       1D IN SOA       @ root (
                                        1               ; serial (d. adams)
                                        3H              ; refresh
                                        15M             ; retry
                                        1W              ; expiry
                                        1D )            ; minimum
 
                        1D IN NS        @
                        1D IN A         127.0.0.1

Now, get the latest list of root servers, run the following command and save it as your /var/named/db.cache file:

dig @e.root-servers.net . ns > db.cache

Because the root servers change (although rarely) it's a good idea to keep your db.cache file updated. The following script should be run as a cron job once a month or every couple months at most. It will keep your db.cache file up to date and report any problems via email to you.

#!/bin/sh
#
# Update the nameserver cache information file once per month.
# This is run automatically by a cron entry.
#
# Original by Al Longyear
# Updated for BIND 8 by Nicolai Langfeldt
# Miscelanious error-conditions reported by David A. Ranch
# Ping test suggested by Martin Foster
# named up-test suggested by Erik Bryer.
# Updated for BIND 9 by digitalpeer
#
(
 echo "To: root <root>"
 echo "From: system <root>"
 
 # Is named up? Check the status of named.
 case `rndc status 2>&1` in
    *'cannot connect to command channel'*)
        echo "named is DOWN. root.hints was NOT updated"
        echo
        exit 0
        ;;
 esac
 
 PATH=/sbin:/usr/sbin:/bin:/usr/bin:
 export PATH
 # NOTE: /var/named must be writable only by trusted users or this script
 # will cause root compromise/denial of service opportunities.
 cd /var/named 2>/dev/null || {
    echo "Subject: Cannot cd to /var/named, error $?"
    echo
    echo "The subject says it all"
    exit 1
 }
 
 # Are we online?  Ping a server at your ISP
 case `ping -qnc 1 10.0.0.2 2>&1` in
   *'100% packet loss'*)
        echo "Subject: root.hints NOT updated.  The network is DOWN."
        echo
        echo "The subject says it all"
        exit 1
        ;;
 esac
 
dig @e.root-servers.net . ns >root.hints.new 2> errors
 
 case `cat root.hints.new` in
   *NOERROR*)
        # It worked
        :;;
   *)
        echo "Subject: The root.hints file update has FAILED."
        echo
        echo "The root.hints update has failed"
        echo "This is the dig output reported:"
        echo
        cat root.hints.new errors
        exit 1
        ;;
 esac
 
 echo "Subject: The root.hints file has been updated"
 echo
 echo "The root.hints file has been updated to contain the following information:"
 echo
 cat root.hints.new
 
chown root.root root.hints.new
 chmod 444 root.hints.new
 rm -f root.hints.old errors
 mv db.cache root.hints.old
 mv root.hints.new db.cache
 rndc reload
 echo
 echo "The nameserver has been restarted to ensure that the update is complete."
 echo "The previous root.hints file is now called  /var/named/root.hints.old."
) 2>&1 | /usr/lib/sendmail -t
exit 0

So you've got this nice caching server setup and you expect it to cache domains. As a warning, a lot of the big domains out there have a pretty small TTL. I'm sure there's some way to override that, but as soon as that TTL expires your server will have to requery externally. I'm just making the point that you shouldn't be down if your server isn't caching some domains for a long period and has to re-query.

Related Posts

6 Comments

Comment October 27, 2004 by Andrew
Very Helpful and Informative. Thanks!
Comment April 23, 2006 by Travis
In regard to your script that updates the db.cache file: line #70 should be "chown named.named root.hints.new" and line #71 should be "chmod 644 root.hints.new".
Comment April 23, 2006 by digitalpeer
Travis, your suggestion is noted. In fact, your suggestion may be prefered. However, I run the script as root cron job and I explicitly only want root to be allowed to modify that file.
Comment January 29, 2008 by faras sadek
thank you for this great help
Comment April 20, 2008 by Jas
Thanks Dude, had my nameserver up and running in less than 5 minutes with a simple copy and paste of your config's. Much apprecaited and keep up the good work. All the best!! :)
Comment April 20, 2008 by Jas
If you wanted to expand on this I would suggest (hopefully) to see some sections/examples on rndc config/keys, and configuring bind with a chroot env. Always seem to have probs with that!!!! Thanks again!