1. Prerequisites

Our site includes several DNS name servers.

server.ourdom.com is controlled by us and serves our zones to public internal.

ns.provider.com is controlled by interned provider. We use it as a slave for out primary zone and notify it about zone updates. Also, it is used as a DNS forwarder to leverage its large name cache.

The site also includes Windows machines and Active Directory (AD) controlled by a PDC (primary domain controller). PDC should have write access to DNS server to advertise its services, otherwise Active Directory will not function correctly. However, we do not want these zone updates to disturb provider server or be visible externally. Therefore, in addition to public zone we introduce a separate local zone with internal IP addresses, which is not visible from outside. PDC serves as a slave server for this zone. 

2. Initial Setup

Install packages

yum install bind bind-chroot system-config-bind<

This will create "chroot jail" for bind daemon. Run system-config-bind . It will create initial configuration. Click "Save" and exit the wizard. Create editable templates for the public forward? and reverse zones. Adjust domain name and IP subnet address and add more reverse zones as appropriate.

cd /var/named/chroot/var/named
touch ourdom.com.db 172.16.162.rev public.inc<

Also create templates for local forward? and reverse zones. Again, adjust domain name and IP subnet address. 

cd /var/named/chroot/var/named
touch vpn.db 10.20.rev local.inc<

Create symbolic links from BIND chroot jail for ease of modification 

for x in /var/named/chroot/etc/{named.conf,rndc.key}; do ln -sf $x /etc; done
for x in /var/named/chroot/var/named/*.{db,rev,inc}; do test -r $x && ln -sf $x /var/named; done<

3. Core configuration

Adjust core configuration file /etc/named.conf . Create DNS server ACLs grouped by function.

acl primaryns   { localhost; };
acl secondaryns { provider-ns-ip; };
acl windowsns   { pdc-ip-1; pdc-ip-2; };
acl localns     { primaryns; windowsns; };
acl servers     { primaryns; secondaryns; windowsns; };
acl clients     {; another-subnet; };
acl internal    { clients; servers; };<

Main options include forwarders, slave servers and directory names.

options {
       directory "/var/named";
       dump-file "/var/named/data/cache_dump.db";
       statistics-file "/var/named/data/named_stats.txt";
       notify no;
       //recursion yes;
       allow-query { any; };
       //allow-query { internal; };
       allow-transfer { servers; };
       also-notify { provider-ns-ip; };
       //forwarders { provider-ns-ip; };

Add definitions for your externally visible zones:

zone "ourdom.com." IN {
       type master;
       file "ourdom.com.db";
       allow-query { any; }
       allow-update { primaryns; }
       notify yes;
zone "65.16.172.in-addr.arpa." IN {
       type master;
       file "172.16.65.rev";
       allow-query { any; }
       allow-update { primaryns; }
       notify no;

In a similar way add internal zones

zone "vpn." IN {
       type master;
       file "vpn.db";
       allow-query { internal; }
       allow-update { primaryns; }
       notify no;
zone "20.10.in-addr.arpa." IN {
       type master;
       file "10.20.rev";
       allow-query { internal; }
       allow-update { primaryns; }
       notify no;

Locate all special boilerplate domains ("localdomain", "localhost", "broadcast" etc, except for hint domain "." which does not need ACLs) and set the following ACLs for them:

allow-query { any; }
allow-update { none; }<

Allow for control access from localhost

controls {
       inet allow { localhost; } keys { rndckey; };

4. Zones

We spin off serial number and SOA record into separate file public.inc for ease of maintenance, because it is the same for both forward? and reverse zones.

@        IN    SOA   server.ourdom.com. postmaster.ourdom.com. (
                              2009082000 7200 3600 604800 3600 )
         IN    NS    server.ourdom.com.
         IN    NS    ns.provider.com.
         IN    MX   10    mail.ourdom.com.<

Serial number has format yyyymmddHHMMss, where ss is a day-wise serial number.

The primary zone file ourdom.com.db includes the serial header:

$TTL       600
$ORIGIN    ourdom.com.
$INCLUDE   "public.inc"
server     IN    A
mail       IN    A
vpn        IN    A
windows    IN    A
tk         IN    A
win        IN    CNAME    windows
ldap       IN    CNAME    server
www        IN    CNAME    server
nfs        IN    CNAME    vpn
proxy      IN    CNAME    vpn
print      IN    CNAME    vpn
fax        IN    CNAME    tk<
  1. The server and mail records are NOT aliases, because it is prohibited by NS and MX records.
  2. Most services have dedicated alias names. Generally whatever needs to be open to the wild is aliased to server and internal services are aliased to vpn.
  3. Windows DNS server operates independently from main DNS.
  4. Administering can be performed using WebMin<.

The reverse zone file looks like

$TTL     600
$ORIGIN  67.16.172.in-addr.arpa.
$INCLUDE public.inc
52       IN    PTR    server.ourdom.com.
138      IN    PTR    somehost.ourdom.com.<

In the same manner add the local zones. Included header for local zone local.inc can look like

@        IN    SOA   server.ourdom.com. postmaster.ourdom.com. (
                              2008100200 7200 3600 604800 3600 )
         IN    NS    server.ourdom.com.<
Windows DNS server is allowed to send modifications for local primary and reverse zones, otherwise Active directory would fail. Therefore this file will be periodically modified by the bind daemon.

5. Logging

We need customize log rotation since daemon runs in chroot jail.First, link logs from chroot jail into /var/log

rm -rf /var/log/named*
ln -sf /var/named/chroot/var/log /var/log/named
ln -sf /var/log/named/named.log /var/log/named.log<

Then customize

/var/log/named/named.log {
    create 0644 named named
        /sbin/service named reload  2> /dev/null > /dev/null || true

6. Backup

The backup script /etc/vitki/bin/backup-named is

cd /
file="$dir/ps-named-ourdom-`date +'%Y%m%d%H%M'`.tar.gz"
tar cpzf $file
          etc/named.conf etc/rndc.*
echo $file<
See old backup attached<.

7. Recovery

We want by default that our local BIND server become a primary DNS after restarts and DHCP operations,that is


should look like this

search ourdom.com
domain ourdom.com
nameserver .....<

This should happen right after named starts during system boot. On my CentOS host its order is 13

grep chkconfig /etc/init.d/named
# chkconfig: - 13 87<

Therefore I create boot script /etc/init.d/recover-bind

# chkconfig: - 14 86
# description: Restore local BIND as preferred name server
grep -Fq /etc/resolv.conf || sed -i.bak '2 a nameserver' /etc/resolv.conf <

make it run by default

chkconfig recover-bind on<

and make re-run every hour

ln -s /etc/rc.d/init.d/recover-bind /etc/cron.hourly/ <

8. Testing

host ldap.ourdom.com
dig @ns ourdom.com axfr <


NSCD has several problems:

  • Its default retention times are too high<
    • Solution: set all positive-time-to-live to 60 seconds
  • He' is a sucky cache daemon< for hosts
    • Solution: set enable-cache hosts to no
  • It eats up too much memory
    • Solution: set all max-db-size to 4194304 (4 Mb)


  • edit /etc/nscd.conf
#positive-time-to-live   passwd  600
 positive-time-to-live   passwd  60
#max-db-dize             passwd  33554432
 max-db-dize             passwd  4194304

#positive-time-to-live   group   3600
 positive-time-to-live   group   60
#max-db-dize             group   33554432
 max-db-dize             group   4194304

#enable-cache            hosts   yes
 enable-cache            hosts   no
#positive-time-to-live   hosts   3600
 positive-time-to-live   hosts   60
#max-db-dize             hosts   33554432
 max-db-dize             hosts   4194304<
  • purge caches and restart nscd
rm /var/db/nscd/*
service nscd restart

10. Tuning

You may see many messages like this in the system log

named[xxx]: network unreachable resolving 'www.server.com/AAAA/IN': 2001:503:ba3e::2:30#53

This is because the new bind version 9.3.6+ tries to use IPv6 transport even if the server host does not have IPv6 connectivity, resulting in slower name resolution. To fix this you have to start the bind damon with "-4" (IPv4 only). You can add the line "OPTIONS="-4"" to /etc/sysconfig/named to do so.

11. Troubleshooting

dig @ns.ourdom.com ourdom.com axfr
dig +short mail.ourdom.com
host www.ourdom.com