Configuring a BIND DNS Server
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.
6 Comments