Hardening the BIND DNS Server

By Sean Boran | Dec 5, 2000 | Print this Page
http://www.enterprisenetworkingplanet.com/netsecur/article.php/10952_625181_3/Hardening-the-BIND-DNS-Server.htm

Editor's Note

Your Domain Name Service is the road sign to your systems on the Internet. No matter how secure and robust your Web, mail and other servers are, compromised and corrupted DNS systems can prevent customers and legitimate users from ever reaching you.

DNS, like many of the older protocols, was developed at a time when the Internet was a kinder, gentler place and was meant to provide a simple and unlimited way to provide information about what computers you have to anyone else. Obviously, the model of the Internet has changed, and changes to BIND (Berkeley Internet Name Domain software, the most common implementation of DNS), along with widely accepted configuration guidelines, have improved our ability to lock down DNS.

Introduction

BIND (the Berkeley Internet Name Domain) 1 is the most frequently used DNS server, maintained by the ISC. It is also known as "named," since this is the name of the actual daemon itself. BIND has a long history, is a core tool for most Internet sites and is currently at V8.

As with many applications exposed to the increasingly hostile Internet environment, security weaknesses have been discovered in BIND.


Why bother? What risks does an insecure BIND pose?

So what, you say? Yet another program with security problems? There are so many problems in so many applications these days, it's just not possible to keep up with all these advisories and patches. Do we really have to worry about DNS too? Well, a compromised DNS server can pose some interesting risks:

  1. An attacker can gain much interesting information if zone tranfers are allowed: the entire list of hosts and routers with IP addresses, names and possible even comments indicating location, names etc.

  2. Denial of service: If all your Internet DNS servers go down,
    • Your Website is no longer visible (other Websites can't look up your IP address).
    • Emails can't be delivered (some other Internet sites that you frequently exchange data with may have cached DNS entries, but they won't last more than a few days).
    • An attacker could start up a fake DNS server that pretends to be yours and delivers false DNS information to the Internet about your domain. That is, integrity is lost - see next section.

  3. Loss of integrity: If an attacker can change the DNS data or spoof other sites into believing false data (this is known as DNS poisoning), it gets very dangerous:
    • Fake Websites can be set up to look like yours and capture user input destined for your site, which may be anything from user/passwords to PINs to account information.
    • All email can be diverted to a relay which can copy, change or delete email before passing it to your site.
    • If your firewall or any Internet-accessible host uses DNS hostnames for authentication or trust relationships, these can be completely compromised, especially if a weak packet filter protects the Internet servers and Intranet. Imagine a Web proxy configured to only allow proxy requests from *.mydomain.com. The attacker adds his host to the domain, then the Web proxy may allow requests from him, allowing the attacker HTTP access to the Intranet. Imagine a system administrator who uses SSH (great crypto stuff), but the firewall host has a ".shosts" trust to "admin.mydomain.com," where "admin" is the administrator's workstation. If the attacker can replace the entry for "admin.mydomain.com" in the DNS, he has password-free access to the firewall hosts.


So What Needs To Be Done?

BIND weakness may be addressed with several prevention measures, but detection and reaction shouldn't be forgotten either:

  1. Resource isolation: Use a dedicated, hardened server for Internet DNS, don't share with other services, and especially do not allow user logins. Minimal services/users means reducing the amount of software running and hence the amount exposed to network attacks. Separation prevents other services or users possibly using local weakness in the system to attack BIND.

  2. Redundancy: Install a secondary on a different Internet connection (foreign branch of your company, another ISP, etc.). If your site dies, at least other sites won't think you "cease to exist"; they just think you're "not available," so that emails, for example, won't get lost but will be queued (typically up to four days).

  3. Use the latest version (e.g. 8.2.2-P5 or later, which includes security fixes).

  4. Access control: Restrict zone transfers to minimize the amount of information on your networks available to attackers. Consider using transaction signatures. Consider restricting/not allowing recursive queries.

  5. Run BIND with minimum privileges: Run BIND as a non-root user.

  6. More resource isolation: Run BIND in a "chroot" jail, so it is much more difficult for a compromised bind daemon to damage the operating system or compromise other services.

  7. Detection: Monitor logs for unusual activity; monitor the system for unauthorized changes with an integrity checker; keep an eye on relevant advisories.

The procedure in this paper concentrates only on measures 4), 5) and 6), which should help to protect a server against possible future weakness in BIND. This procedure has been tested on several production systems: a secondary on Solaris 2.5 + 2.8, a primary on Solaris 2.6 + 2.7.



Install and Configure BIND

It is assumed that Solaris is up and running and appropriately hardened and that the BIND delivered with Solaris is disabled. If you have not yet hardened Solaris, check out the YASSP tool first 7. This section runs through:

  1. Compiling BIND on a master host, since you probably don't have (or shouldn't have) a compiler on the hardened DNS server.
  2. Copying and installing BIND on the DNS server.
  3. Setting up DNS data files.
  4. Running BIND.


1. Compiling BIND (on a host with a compiler).

Download the distribution 1, and extract it to a subdirectory and compile. This can be done as any user.

make clean;
make depend && make; 

Now change to the root account, install to a temporary directory, and create a tarball:

su - root
# allow group, but not world access
umask 027
make install DESTDIR=/tmp
cd /tmp/usr/local
tar cf - * | compress > bind_dist.tar.Z


2. Copy and install BIND on the DNS server

Create a user and group account for BIND:

echo "named:x:20000:20000:BIND DNS daemon:/tmp:/bin/false" >> /etc/passwd
echo "named:NP:6445::::::"  >> /etc/shadow
echo "named::20000:" >> /etc/group

Don't allow the BIND account to use ftp:

echo "named" >> /etc/ftpusers

Copy bind_dist.tar.Z to /usr/local on the DNS server and extract into /usr/local:

zcat bind_dist.tar.Z | tar xvf -

Set up file permissions:

cd /var; mkdir named
/usr/ucb/chown -R root.named named
chmod 770 named

touch /var/run/named.pid;
/usr/ucb/chown named.named /var/run/named.pid;

chmod 755 /usr/local /usr/local/bin /usr/local/sbin /usr/local/etc

/usr/ucb/chown root.named /usr/local/bin/{dig,dnsquery,nslookup,nsupdate,host};

chmod 755 /usr/local/bin/ /usr/local/bin/{dig,dnsquery,nslookup,nsupdate,host};

/usr/ucb/chown root.named /usr/local/sbin/{dnskeygen,irpd,named,named-bootconf,named-xfer,ndc};

chmod 755 /usr/local/sbin/{dnskeygen, irpd,named,named-bootconf,named-xfer,ndc};

Optionally, you can rename the default DNS binaries installed on the system, so that they are not used by accident, and leave a reminder.

cd /usr/sbin;
mv nslookup nslookup.old
mv nsupdate nsupdate.old
mv in.named in.named.old
mv named-bootconf named-bootconf.old
mv named-xfer named-xfer.old
touch NAMED_NOW_IN_USR_SBIN

Add /usr/local/sbin to the root PATH in /.cshrc or /.profile.


2. Setting up DNS data files

Create a configuration file:

cd /usr/local/etc
vi named.conf 
chown root.named named.conf 
chmod 640 named.conf 

So what do you put in named.conf? Have a look at the examples provided in the second footnote 2. The file consists of options, logging, ACL, server and Zone sections. Some of the directives are:

  • The directory tells BIND where to look for data files.
  • Internal DNS servers without Internet access will need to use forwarders to forward all unknown queries to DNS servers which have Internet access.
  • The process number of BIND is stored according to the pid-file directive. The "named user" needs read and write access to this file.
  • BIND's logging is very flexible. The example show logs to the syslog local1.info facility.
  • Access control lists (ACLs) can and should be used to restrict what servers are allowed zone transfers. It is recommended to use this feature to make it more difficult for attackers to map your network layout. Servers typically allowed in the list are primaries/secondaries for the domain, your ISP and NIC for your country.

After setting up named.conf, the files containing the DNS records have to be set up on primaries (in /var/named in our example); these are automatically downloaded by secondaries.


3. Running BIND

Check the console and syslog (daemonlog) for errors, e.g.

tail -f local0log | grep "named" 

Start BIND:

/usr/local/sbin/named -u named

Configure automatic starting on boot
In /etc/init.d/inetsvc, change the DNS startup lines to:

# Start the BIND DNS server:
if [ -f /usr/local/sbin/named -a -f /usr/local/etc/named.conf ]; then
  echo "Starting BIND domain name server."
  /usr/local/sbin/named -u named;

Before moving on to the next stage, BIND should be working well, with no errors in the logs. See also the troubleshooting section.



Chroot'ing BIND

This process has three steps: create a general chroot jail, install BIND into the jail, start and test the chroot'ed BIND.

Set up a general chroot environment

BIND is now up and running, but we want to tighten security further by forcing it to run in a chroot environment (also called a jail or padded cell: Basically, restrict the files visible to BIND to a subdirectory within the file system). See also the second footnote 2 for a discussion of chroot environments.

We will now walk through the steps for setting up the chroot environment, copying over the BIND files, starting BIND and troubleshooting. These steps chroot the entire BIND program, not just using BIND's "-t" feature (see Note 1).

The following steps assume use of the C-Shell. We start by setting a variable for the chroot environment (jail) location, and setting umask so that all files copied can be read by both groups and world. These commands are designed to be copied and pasted.

  • Set source and destination directories
csh
set jail='/home/dns';
umask 022; 
  • Set up empty directories and links:
mkdir $jail;
cd $jail;
mkdir -p {dev,opt,usr,var,etc};
mkdir -p var/{run,log,named} usr/{local,lib};
mkdir -p usr/share/lib/zoneinfo; 
  • Setup /etc
cp /etc/{syslog.conf,netconfig,nsswitch.conf,resolv.conf,TIMEZONE} $jail/etc 
  • Create a user and group account within chroot and for the whole system. BIND will run under this account.
  • Create $jail/etc/passwd and add to /etc/passwd also

echo "named:x:20000:20000:BIND DNS daemon:/tmp:/bin/false" >> /etc/passwd
echo "named:x:20000:20000:BIND DNS daemon:/tmp:/bin/false" > $jail/etc/passwd

    And $jail/etc/shadow and add to /etc/shadow:

echo "named:NP:6445::::::"  >> /etc/shadow
echo "named:NP:6445::::::"  > $jail/etc/shadow

    And $jail/etc/group and add to /etc/group:

echo "named::20000:" >> /etc/group
echo "named::20000:" > $jail/etc/group 
  • Set up libraries:
  • Use ldd to see what shared object libraries named and named-xfer rely on:

  • Check the domains using the IP-Plus tool 4.
  • Read the sections Known Problems and Configuration Notes below.
  • Join the FOCUS-SUN@SECURITYFOCUS.COM list and discuss the problem ;-)


  • Known Problems

    • BIND will still log to syslog "daemon" for certain events, even if the logging directive tells BIND to local to "local1" (as in our example).
    • ndc does not work correctly in a chroot'ed environment. It would be better to start BIND via ndc:

      ldd /usr/local/sbin/named /usr/local/sbin/named-xfer

        Copy the files listed above, for example for Solaris 2.6/7:

      cp -p /usr/lib/libnsl.so.1 \
      /usr/lib/libsocket.so.1 /usr/lib/libc.so.1 \
      /usr/lib/libdl.so.1 /usr/lib/libmp.so.2 $jail/usr/lib

        On Solaris 2.5:

      cp -p /usr/lib/libnsl.so.1\
      /usr/lib/libsocket.so.1 /usr/lib/libc.so.1\
      /usr/lib/libdl.so.1 /usr/lib/libmp.so.1 /usr/lib/libw.so.1\
      /usr/lib/libintl.so.1 $jail/usr/lib

        Experience has shown the following are also needed for Solaris 2.5/6/7:

      cp /usr/lib/ld.so.1 /usr/lib/nss_files.so.1 $jail/usr/lib

        ("Experience" means that first attempts didn't work, but by running BIND with truss, one could see what libraries were being sought after.)

      • Copy over Timezone files (I use MET, here in Europe):
      mkdir -p $jail/usr/share/lib/zoneinfo;
      cp -p /usr/share/lib/zoneinfo/MET $jail/usr/share/lib/zoneinfo/MET
      • Set up devices for communication, console, syslog, etc.
      cd $jail/dev
      mknod tcp c 11 42
      mknod udp c 11 41
      mknod log c 21 5 
      mknod null c 13 2 
      mknod zero c 13 12 
      chgrp sys null zero
      chmod 666 null
      mknod conslog c 21 0
      mknod syscon c 0 0 
      chmod 620 syscon
      chgrp tty syscon
      chgrp sys conslog


      Copying BIND to the Jail

      We assume bind was already in /usr/local, so copy the BIND files over from there:

      cd $jail; 
      mkdir -p usr/local/{bin,lib,sbin,bind,etc}
      cd $jail/usr/local/sbin;
      (cd /usr/local/sbin; tar cf - dnskeygen named* irpd ndc ) |tar xvf -
      cd $jail/usr/local/bin;
      (cd /usr/local/bin; tar cf - dnsquery dig host nslookup nsupdate) |tar xvf -
      cd $jail/usr/local;
      cp /usr/local/etc/named.conf etc;
      (cd /usr/local; tar cf - bind) |tar xvf -

      Your DNS data can be located in several directories; here we present two examples. The location is specified in named.conf.

      1. Data in /etc/named/

      mkdir -p $jail/etc/named;  cd $jail/etc/named;
      (cd /etc/named; tar cf - * ) | tar xvf -

      2. or DNS data in /var/named (my preference)

      cd $jail/var/named;
      (cd /var/named; tar cf - * ) | tar xvf -

      Next, set permissions on files, so that root owns files and named can read all files and write some files. And, disable any SUID/SGID files.
      The PID file is put in /var/run and not /usr/local, because we don't want the named user to be able to write to /usr/local/etc (and hence named.conf). The location of the PID file is specified in named.conf.

      cd $jail
      chmod -R g-w var;
      chmod -R a-w opt usr
      chmod g+w var/run var/log
      chgrp named var/log var/run;
      touch var/log/all.log var/run/named.pid;
      /usr/ucb/chown named.named
      var/log/all.log var/run/named.pid;
      chgrp named $jail/usr/local/etc;
      /usr/ucb/chown root.named $jail/usr/local/etc/named.conf;
      find . -type f -exec chmod ug-s {} \;

      See the eighth footnote 8 for an example of an "ls -alR" on a production DNS primary.

      Edit DNS config file: if the PID or data location has changed from your original installation, then $jail/usr/local/etc/named.conf needs to be adapted (see also the section BIND Configuration Notes).


      Starting BIND

      The chroot environment is set up and BIND is installed, so the current (non-chroot'ed) BIND can be stopped and the new one started.

      1. Set up a tail on the (syslog) logs, to watch BIND activity:
        tail -f local0log | grep server1
        The logs may be in /var/adm/messages or on a remote server, depending on your /etc/syslog.conf configuration. In this example, a centralized server collects logs and we look for messages from server1 (my test server).
      2. Stop the existing BIND...
        On Solaris 2.7: kill `pgrep named`
        On Solaris 2.5/6: ps -ef |grep named   then kill the appropriate PID.
      3. Start BIND chroot'ed:
        /usr/sbin/chroot /home/dns /usr/local/sbin/named -u named
      4. Check for errors:
            • in the syslog log
            • do nslookups
            • make sure the secondary can do zone transfers
            • send a HUP signal to named, to ensure that it reloads configuration correctly.
            • Check the domains using the IP-Plus tool 4.
      5. If everything still looks good, change the /etc/rc2.d/S72inetsvc (or equivalent startup file) entries for starting BIND to something like this:
        if [ -f /home/dns/usr/local/sbin/named -a -f /home/dns/usr/local/etc/named.conf ]; then 
        /usr/sbin/chroot /home/dns /usr/local/sbin/named -u named; 
        echo "Started chroot'ed BIND domain name server." 
        fi



      Troubleshooting

      If you have a problem, a few tips:

      • Use nslookup or dig to check server results.
      • Client:
        • Check /etc/nsswitch.conf and /etc/resolv.conf.
        • Start nslookup with the "-d2" option to get buckets of debugging info, or start it without any argurments and type "help" at the prompt. There is also a "debug" command from the interactive prompt.
        • Try killing the nscd daemon.
      • Server
        • Send a HUP signal to named, to reread the config file after changes.
          kill -HUP `cat /var/run/named.pid`
        • Look at the syslog entries. Typically logs are found in the syslog "daemon" section.
        • Named has a "-d X" option, which switches on debugging (X is a number indicating the debug level).
        • To get statistics from the name server into /usr/tmp/named.stats:
          kill -ABRT `cat /var/run/named.pid`
        • If the logs indicate permission problems, check your file permissions against the example of an "ls -alR" on a production DNS primary 8.
      • If domain transfers are not working, try manual transfers, for example:
        truss >/usr/local/sbin/named -u named
        truss /usr/sbin/chroot /home/dns /usr/local/sbin/named -u named

      • Check the domains using the IP-Plus tool 4.
      • Read the sections Known Problems and Configuration Notes below.
      • Join the FOCUS-SUN@SECURITYFOCUS.COM list and discuss the problem ;-)



      Known Problems

      • BIND will still log to syslog "daemon" for certain events, even if the logging directive tells BIND to local to "local1" (as in our example).
      • ndc does not work correctly in a chroot'ed environment. It would be better to start BIND via ndc:
        /usr/sbin/chroot /home/dns /usr/local/sbin/ndc -c /var/run/ndc start -u named

      rather than:

      /usr/sbin/chroot /home/dns /usr/local/sbin/named -u named

      One reader (J. S. Townsley) had similar problems, so he replaced ndc with a script:

      #!/bin/sh
      case "$1" in
        start)
          /etc/rc.d/init.d/named start;
          ;;
        stop)
          /etc/rc.d/init.d/named stop;
          ;;
        restart)
          /etc/rc.d/init.d/named restart;
          ;;
        *)
          /usr/sbin/chroot /chroot/named /usr/sbin/ndc $1
      esac



      Configuration Notes


      Note 1: BIND's Built-in chroot

      BIND 8 had its own chroot function, which works by giving named an option "-t" which points to the chroot jail, for example "named -t /home/dns." When BIND starts up, it chroot's to the jail, after processing command line options and before it starts to answer queries. By compiling BIND and installing directly into the jail, all the bind programs will be correctly in place. Since BIND chroot's after reading user/group information, it doesn't need the other /etc and /usr/lib files noted above.

      If BIND is set up as described above, it can still be started using this method, for example,
      /home/dns/usr/local/sbin/named -t /home/dns -u named

      This method is simpler than the general chroot method below, but it does have the disadvantage that we rely on the BIND code to be executed before the chroot is bug-free. Also, a general chroot can be used to "jail" other programs too.
      For the moment, I'll continue using the general chroot method described below, and update this article as problems are found/solved. See also the Known Problems section.


      Note 2: The BIND Configuration File

      The following is an example named.conf with many comments to explain individual features. The file consists of an options section, ACL and server definitions, and Zone data.

      acl "trusted-nameservers" {
        localhost;
        193.A.B.C; // my secondary
        193.A.B.D; // another secondary
        X.A.A.A;   // ISP
        X.Y.Z.X;   // NIC for your country                                                     
      };
      
      options {         
        directory "/var/named";                       /* /etc/named is also common */
        //forward only;
        // for Internal DNS servers, forward all unknown queries to external servers:
        //forwarders { 193.a.b.c; 193.a.b.d; };
        /* If there is a firewall between you and nameservers you want
         * to talk to, you might need to uncomment the query-source
         * directive below.  Previous versions of BIND always asked
         * questions using port 53, but BIND 8.1 uses an unprivileged
         * port by default.
         */
        query-source address * port 53;
        pid-file "/var/run/named.pid";
        check-names master warn;                  /* default. */
        datasize 20M;
        // The following will restrict transfers for all zones, if enabled:
        // allow-transfer { trusted-nameservers; };
        recursion yes;          // default
      
        //allow-query { 193.a.b.c/24; };
      };
      
      logging {
        channel syslog_errors {
          //syslog daemon;
          syslog local1;           // choose local1 since rarely used
          severity info;
        };
        category default {                                                                                 
          syslog_errors;            // you can log to as many channels
          //default_syslog;          // by default goes to daemon in syslog
        };
        // ignore all "lame server" errors (only do this if none of the lame 
        // servers belong to you; otherwise, fix them)
        category lame-servers{ null; }; 
      };
      
      // Example definition of a Primary
      zone "mytestdomain.com" {
        type master;
        file "mytestdomain.com";
        allow-query    { any; };      // no restriction on queries
        allow-update   { none; };    // don't allow dynamic updates
        allow-transfer { trusted-nameservers; }; // restrict zone transfers
      };
      
      // Example definition of a secondary
      zone "mytestdomain2.com" {
        type slave;
        file "mytestdomain2.com";
        masters          { A.B.C-D };  // IP address of the primary
        allow-query    { any; };
        allow-update   { none; };
        allow-transfer { trusted-nameservers; };
      };
      
      // if you get servers giving bad data, ignore them with:
      //server 10.0.0.2 { bogus yes; };
      
      // this is the main file for the domain name server. Each line gives
      // the file where is stored the name table for a particular domain.
      // named.root can be downloaded from ftp.rs.internic.net/domain 
      
      zone "." {
        type hint;
        file "named.root";
      };
      
      zone "0.0.127.in-addr.arpa" {
        type master;
        file "db.127.0.0";
      };
      


      Note 3: TSIG, Transaction Signatures

      BIND provides some new security features in its latest release. Here we examine one: the use of TSIG (transaction signatures) to authenticate zone transfers.

      Zone transfers are usually limited to a list of IP addresses (via the ACL mechanism) which correspond to specific DNS servers for a zone. Since only IP addresses are used, this mechanism is open to IP spoofing. BIND 8.2 and later allow authentication and verification of zone data. A key is configured on primary and secondary name servers and used to sign messages exchanged between the servers. It's important that the server times are synchronized. If the transfer is not authenticated with the correct key, no zone transfer may take place.

      Let's look at an example where we use TSIG to restrict the zone transfers between a DNS primary "prim" (IP address 10.1.1.2) and DNS slave secondary "sec1" (IP address 10.1.2.2).

      a) Generate an MD5 key, which will be used as a shared secret between the DNS servers. The "dnskeygen" tool is used. The key is written to a file.

      # /usr/local/sbin/dnskeygen -H 128 -h -n prim-sec1.
      Generating 128 bit HMAC-MD5 Key for prim-sec1.
      Generated 128 bit Key for prim-sec1. id=0 alg=157 flags=513
      
      # cat Kprim-sec1.+157+00000.private
      Private-key-format: v1.2
      Algorithm: 157 (HMAC)
      Key: bFs2bXnLTYTI7r0WJv7HMA==
      

      b) Create an identical key entry on both servers in named.conf:

      key prim-sec1 {
      	algorithm hmac-md5;
      	secret "bFs2bXnLTYTI7r0WJv7HMA==";
      };

      c) Add an ACL on both servers to limit transfers to specific hosts, for example:

      acl "my-nameservers" {
      	localhost;
      	10.1.1.2;
      	10.1.2.2;
      };

      d) For each host in the ACL, tell the BIND which key to use (do this for each server), for example on the primary:

      server 10.1.2.2 {
        transfer-format many-answers;
        keys { prim-sec1 ; };
      };
      zone "mytestdomain.com" {
        type master;
        file "mytestdomain.hosts";
        allow-query    { any; };
        allow-update   { none; };
        allow-transfer { my-nameservers; };
      }

      e) Restart both named servers (send a HUP signal), then check the (syslog) logs for errors.

      Testing if it works:

      • On the secondary, stop named, delete one of the zone files and restart. Watch the logs. A message indicating a successful zone transfer should appear and the corresponding zone file be created.

      • To make sure the TSIG key is really being used, change the key on the primary (e.g. add the letters "TEST" as the first few letters), stop both name servers, delete the zone file on the secondary, and restart both. The zone transfer will not take place, an error message like
        "named-xfer[16280]: [ID 745729 daemon.notice] SOA TSIG verification from server [10.1.1.2], zone mytestdomain.com: BADKEY (-17)"
        appears in the log, and the zone file is not recreated. Changing back the key on the primary and restarting BIND on primary and secondary fixes our deliberate fault.

      So it's really not so difficult to significantly increase the security of your zone transfers. It is important that the file permissions on named.conf be restrictive so that it cannot be read by everyone on a system. The secret string used in the key must remain secret.


      Note 4: More tips

      • Firewall filters: Resolvers and servers query other servers by initialising a connection from a high port (>1024) to port 53 on the target server.

        • DNS uses port 53, both udp (resolving) and tcp (server to server communications).

        • For server to server communications, the source server can be configured to use source port 53 (rather than a dynamic high port), with the option:

          query-source * port 53;

        • Typical firewall rules would be:
          allow udp 53 in from outside to dns server    [queries to your server]
          allow udp 53 in from dns server to outside    [queries from your server]
          allow tcp 53 in from secondaries or ISP server  to dns server [zone transfers from your server]
          allow tcp 53 out from dns server to outside [zone transfers from primaries, for which you are a secondary]
          Note: queries normally use udp, but apparently also use tcp under load, so restrict queries to udp may cause headaches in some situations.

      • If you want to enable dynamic updates, despite the additional risk, use TSIG for better authentication of hosts allowed to make updates. Always restrict updates via an ACL.

      • BIND can be configure to only allow resolver queries for explicit hosts or networks via the option:
        allow-query { 193.a.b.c/24; };
        An interesting way of using this is to restrict access globally (in 'options') to your own networks and then allow 'all' access in specific zones or subzones, that you wish to be published to the Internet.

      • Intranet DNS servers do not need to have Internet access. They can forward unresolved queries to the external Internet DNS server(s), with the forwarders command:
        forwarders { 193.a.b.c; 193.a.b.d; };
        Likewise, queries on intranet DNS servers can be restricted to valid intranet addresses via the "allow-query" command.
        allow-query { 193.a.b.c/24; };

      • Internet servers or 'delegate' servers should be configured to only allow "recursive queries" from valid DNS servers/clients in your company, but not the Internet. Recursive queries allow the DNS client to ask the DNS server for information on IP addresses for which it is not authoritive. The server will do it's best to get the needed infotmation and will cache it, but we don't want that, we only want to serve information to others that we know is 100% correct, i.e. that the server is authoritive for. Stopping or restricting recursion can improve performance and help prevent a form of attack known as DNS cache poisoning. The appropriate option is:

      allow-recursion { 193.a.b.c/24; };

      To stop recursion completely (e.g. on a deligate server), set the option:

      recursion no;

      In the same vein, bind can be prevented from automatically resolving name server names in NS or RDATA records by setting the option:

      fetch-glue no;

      • Read the book DNS and BIND 5.



      Footnotes

      1. BIND Home Page - http://www.isc.org/products/BIND
      2. How to Break Out of a chroot() Jail - http://www.bpfh.net/simes/computing/chroot-break.html
        Creating a Basic Padded Cell - http://www.sunworld.com/swol-01-1999/swol-01-security.html
      3. Securing Your Name Servers - http://securityportal.com/closet/closet19991124.html
        An Introduction to BIND's security features
      4. IP-Plus provides a tool for remotely checking your DNS configuration - http://www.ip-plus.net/tools/dns_check_set-en.html
      5. DNS and BIND, 3rd Edition, Paul Albitz & Cricke Liu, published by O'Reilly & Associates.
        A great reference work.
      6. RFC2845: Secret Key Transaction Authentication for DNS (TSIG) - community.roxen.com/developers/idocs/rfc/rfc2845.html
      7. YASSP Solaris Hardening Tool - http://www.yassp.org
      8. An example of an "ls -alR" on a production chroot'ed DNS primary, to show what the file permissions should look like - http://www.boran.com/security/sp/solaris/bind_perms.txt



      References

      Chroot-BIND HOWTO for Linux - http://www.losurs.org/docs/howto/Chroot-BIND.html
      A Linux equivalent of this article. Access to the Website can be sporadic and slow. It concentrates on the chroot aspects and assumes you know how to configure BIND.

      Linux users may also be interested in Stackguard (a compiler for improved resistance to 'stack smashing' attacks) or Immunix OS (RH Linux rebuilt with Stackguard) See Immunix.org. Note that Stackguard v1.2 had security flaws - use v1.21 or later.

      Chroot BIND 8 on Solaris - http://www.securityfocus.com/focus/sun/articles/bind-inst.html
      Similar to this paper, but it didn't work for me.

      Chroot BIND 4.9.x on Solaris - http://www.homeport.org/~adam/dns.html  

      Using BIND: Don't Get Spoofed Again - http://www.sunworld.com/swol-11-1997/swol-11-bind.html

      Linux: Dual chroot'ed BIND/DNS Servers - http://www.etherboy.com/dns/chrootdns.html

      DNS Security, by Jeff Holland - http://www.sans.org/infosecFAQ/DNS_sec.htm
      Concise but useful; good diagrams.

      BIND FAQ - http://www.nominum.com/resources/bind-faq.html

      BIND9 is under development - http://www.isc.org/products/BIND/bind9.html.
      It is a complete rewrite. An 'early release' 9.0.0 is available for the curious.

      DNS related RFCs: http://www.dns.net/dnsrd/rfc/

      DNS Resources Directory www.dns.net/dnsrd

      Bind for NT links:

      Dents, an alternative DNS server, still in alpha - http://www.dents.org

      djbdns is a collection of Domain Name System tools, http://cr.yp.to/djbdns.html, that includes several components:

      • The DNScache program is a local DNS cache. It accepts recursive DNS queries from local clients such as Web browsers. It collects responses from remote DNS servers.
      • The tinydns program is a fast, UDP-only DNS server. It makes local DNS information available to the Internet.
      • The pickdns program is a load-balancing DNS server. It points clients to a dynamic selection of IP addresses.
      • The walldns program is a reverse DNS wall. It provides matching reverse and forward records while hiding local host information.
      • The rbldns program is an IP-address-listing DNS server. It uses DNS to publish a list of IP addresses, such as RBL or DUL.
      • The DNS library handles outgoing and incoming DNS packets. It can be used by clients such as Web browsers to look up host addresses, host names, MX records, etc. It supports asynchronous resolution.
      • The dnsfilter program is a parallel IP-address-to-host-name converter.
      • The dnsip, dnsipq, dnsname, dnstxt, and dnsmx programs are simple command-line interfaces to DNS.
      • The dnsq and dnstrace programs are DNS debugging tools.



      Acknowledgments

      Useful tips were also provided by FOCUS-SUN@SECURITYFOCUS.COM members, including C.M. Wong, Eric Jon Rostetter, J. S. Townsley, Wyman Eric Miles, and Colin Stefani. Fabrice Bacchella pointed out how to use BIND's inbuilt chroot function. See also the archive of focus-sun messages. Thanks also to Stephane Grundschober and Kurt Seifried.



      About the Author

      Sean Boran is an IT security consultant based in Switzerland and the author of the online IT Security Cookbook. He has over 4 years experience managing DNS servers.


      SecurityPortal is the world's foremost on-line resource and services provider for companies and individuals concerned about protecting their information systems and networks.
      http://www.SecurityPortal.com
      The Focal Point for Security on the Net (tm)