Rendering BIND 8.2.3 ultra secure

Applies to the practice :
Securing your DNS servers

 Applicable technologies:
BIND 8.2.3

The Internet's name resolution scheme is based on the Domain Name System (DNS) which utilises the Berkeley Internet Name Domain (BIND). The latest version can be found at www.isc.org, which at the time of this writing, is 8.2.3. If security is a concern, I strongly suggest you migrate from 4.9.x and 8.2.2-p5 to 8.2.3. There have been many vulnerabilites in all PRIOR versions of BIND, a list which can be found at http://www.isc.org/products/BIND/bind-security-19991108.html

 If you are unsure of your BIND version, you can execute the following command if it isn't blocked already .. :
 
paranoia> dig @jooky.org version.bind chaos txt
paranoia> named -v 
named 8.2.3-REL Mon Jan 29 15:15:19 EST 2001
       bind@paranoia.pgci.ca:/tmp/named

Reg Quinton - IST from uwaterloo.ca notes alternate methods:
paranoia> nslookup -class=chaos -type=txt version.bind 
paranoia> nslookup -class=chaos -type=txt authors.bind (for bind 9.1.0)

The version will appear on the line :
 
VERSION.BIND.0S CHAOS TXT "8.2.1" 

Another good reason is that ISC has stopped production on the 4.9.x versions of BIND, and now only supports security bug fixes for it. All the new features (especially the security ones) will be incorporated in 8.2.x versions. Solaris 7 ships with BIND 8.x installed.

There have been many security features that have been added, notably :

  • Access lists;
  • Allow-query statements;
  • Blackholes
  • The ability to specify one interface on which BIND will listen;
    BIND 8.2.x now uses a non-priviledged port ( > 1024) to query nameservers.


INSTALLING BIND 8.2.3 IN A CHROOT JAIL WITH STATIC BINAIRIES
 

1. gzip -dc bind-src.tar.gz | tar xf - 
   cd src/port/solaris

2. Edit Makefile.set and Makefile.set.gcc and modify all the DEST variables
   #sed -e "s|/usr/local|/opt/bind-8.2.3|" < Makefile.set > Makefile.set.tmp
   #sed -e "s|/usr/local|/opt/bind-8.2.3|" < Makefile.set.gcc > Makefile.set.gcc.tmp
   #mv Makefile.set.tmp Makefile.set
   #mv Makefile.set.gcc.tmp Makefile.set.gcc

3. make depend; make 
   su to root (you should be using sudo) 
   #make install
   #rm /usr/local/bind (unnecessary files) 

4. Make will install bind-8.2.3 in /opt/bind-8.2.3, now we must setup the chrooted environment.
   mkdir -p /opt/chroot/opt/bind-8.2.3/etc
   mkdir -p /opt/chroot/var/{run,log,named} /opt/chroot/lib 

5. Lets copy the bind related software 
   cd /opt/bind-8.2.3
   tar cf - *|(cd /opt/chroot/opt/bind-8.2.3;tar xvf -)
   rm -fr /opt/bind-8.2.3

6. Setup links:
   ln -s bind-8.2.3 bind (while in /opt/chroot/opt)
   ln -s chroot/opt/bind bind (while in /opt)
   ln -s ../../var (while in /opt//chroot/opt/bind-8.2.3)

7. Building your compartemented binaries {named, named-xfer} static.

   In order to do so, you must first verify against what libraries your binaries are compiled.
   #cd opt/chroot/opt/bind/sbin
   #ldd named
   libnsl.so.1 =>   /usr/lib/libnsl.so.1
   libsocket.so.1 =>        /usr/lib/libsocket.so.1
   libc.so.1 =>     /usr/lib/libc.so.1
   libdl.so.1 =>    /usr/lib/libdl.so.1
   libmp.so.2 =>    /usr/lib/libmp.so.2

   Lets see if we have all the static equivalents...

   # find / \( -name libnsl.a -o -name libsocket.a -o -name libc.a -o -name libdl.a -o -name libmp.a \) -print 
   /usr/lib/libp/libc.a
   /usr/lib/libc.a
   /usr/lib/libmp.a
   /usr/lib/libnsl.a
   /usr/lib/libsocket.a

   Great. libnsl, libsocket, libc, libmp... Oups, where is libdl? This gets
   pretty problematic at first sight. If named uses the dl api in any way, 
   it will be a big problem. However, we can take a chance by writing a 
   fake dl object against which we will link the rest of our named code.

   We now have to go back to the named source dir, src/bin/named and create dl.o

   # cd src/bin/named ; cat > dl.c
   void *dlopen(const char *pathname, int mode) { return (void *)0; }
   void *dlsym(void *handle, const char *name) { return (void *)0; }
   int dlclose(void *handle) { return -1; }
   char *dlerror(void) {
   char *buf;
   buf=(char *)malloc(64);
           if (!buf) { 
                   return (void *)0; 
           } else {
           strncpy(buf,"Dynamic linking not available",64);
           return buf;
           }
   }
   ^C
   #gcc -c dl.c

   Now that we have all our dependencies ready to compile our code static,
   we need to make some changes to our Makefile.

   # grep ^SYS\[\"TYPE\"\"LIBS\"\] Makefile 
   SYSTYPE = bsdos
   SYSLIBS = -ll -lutil
   # sed s/^SYSLIBS.\*/"SYSLIBS = dl.o -Xlinker -zmuldefs -static -lc -lsocket -lnsl -lmp"/g Makefile > Makefile.tmp
   # sed s/^SYSTYPE.\*/"SYSTYPE = solaris"/g Makefile.tmp > Makefile

   # grep ^SYS\[\"TYPE\"\"LIBS\"\] Makefile
   SYSTYPE = solaris
   SYSLIBS = dl.o -static -lc -lsocket -lnsl -lmp
 

   Now lets make sure the pathnames.h file is allright

   # sed -e "s|%DESTSBIN%|/opt/bind-8.2.3/sbin|" \ 
   -e "s|%DESTEXEC%|/opt/bind-8.2.3/sbin|" \ 
   -e "s|%DESTETC%|/opt/bind-8.2.3/etc|" \ 
   -e "s|%DESTRUN%|/opt/bind-8.2.3/etc|" \ 
   < pathtemplate.h > pathnames.h

   We're all set now. Time to compile.

   # make
   ...
   cc -I../../port/solaris/include -I../../include  -g -Wall  -c tmp_version.c 
   cc -g -Wall   -o named db_dump.o db_load.o db_lookup.o db_save.o db_update.o  db_glue.o db_ixfr.o db_sec.o db_tsig.o  \
   ns_parser.o ns_lexer.o ns_parseutil.o ns_ctl.o  ns_forw.o ns_init.o ns_main.o ns_maint.o ns_req.o  ns_resp.o ns_stats.o \
   ns_ncache.o ns_xfr.o ns_glue.o  ns_udp.o ns_config.o ns_update.o ns_ixfr.o ns_signal.o  ns_sort.o ns_notify.o \
   tmp_version.o ../../lib/libbind.a dl.o -Xlinker -zmuldefs -static -lc -lsocket -lnsl -lmp

   # file named
   named:          ELF 32-bit MSB executable SPARC Version 1, statically linked, not stripped
   # strip named
   # cp named /opt/chroot/opt/bind/sbin/

   We're not done yet. Named relies on the existence of named-xfer, which we will also build as static. 

   # cd ../named-xfer
   # ldd named-xfer
           libnsl.so.1 =>   /usr/lib/libnsl.so.1
           libsocket.so.1 =>       /usr/lib/libsocket.so.1
           libc.so.1 =>     /usr/lib/libc.so.1
           libdl.so.1 =>    /usr/lib/libdl.so.1
           libmp.so.2 =>    /usr/lib/libmp.so.2
   #

   We're obviously lucky. Named-xfer relies on the same libraries as named.
   All we have to do is perform the same steps as previously... 

   # cp ../named/dl.o . 
   # sed s/^SYSLIBS.\*/"SYSLIBS = dl.o -Xlinker -zmuldefs -static -lc -lsocket -lnsl -lmp"/g Makefile > Makefile.tmp
   # sed s/^SYSTYPE.\*/"SYSTYPE = solaris"/g Makefile.tmp > Makefile

   # make
   cc -I../../port/solaris/include -I../../include -g -Wall  -c named-xfer.c
   cc -g -Wall   -o named-xfer named-xfer.o ../named/db_glue.o ../named/ns_glue.o ../named/tmp_version.o \
   ../../lib/libbind.a dl.o -Xlinker -zmuldefs -static -lc -lsocket -lnsl -lmp

   # file named-xfer 
   named-xfer:     ELF 32-bit MSB executable SPARC Version 1, statically linked, not stripped
   # strip named-xfer
   # cp named-xfer /opt/chroot/opt/bind/sbin/
 

8. Make your devices

   Under Solaris, make the tcp, udp, null and zero devices:
   # mkdir /opt/chroot/dev
   # cd /opt/chroot/dev
   # mknod tcp c 11 42
   # mknod udp c 11 41
   # mknod null c 13 2
   # mknod zero c 13 12
   # chgrp sys null zero
   # chmod 666 tcp udp null

9. Create a seperate partition named /opt, which is mounted with the nosuid option:

   #device          device           mount   FS      fsck    mount   mount
   #to mount        to fsck          point   type    pass    at boot options
   /dev/dsk/c0t0d0s5       /dev/rdsk/c0t0d0s5      /opt    ufs     2       yes     nosuid

10. Create the following users in /etc/passwd

   echo "named:x:20000:20000::/opt/bind:/bin/false" >> /etc/passwd
   echo "dnsadmin:x:20100:20100::/var/named:/bin/false" >> /etc/passwd
   #pwconv

11. Create the following groups in /etc/group

   echo "named::20000:named" >> /etc/group
   echo "dnsadmin::20100:dnsadmin" >> /etc/group
   #grpck

12. Modify /etc/init.d/inetsvc to have the following:

   #
   # If this machine is configured to be an Internet Domain Name 
   # System (DNS) server, run the name daemon.
   # Start named prior to: route add net host, to avoid dns
   # gethostbyname timout delay for nameserver during boot.
   #
   if [ -f /opt/chroot/opt/bind/sbin/named -a -f /opt/chroot/opt/bind/etc/named.conf ]; then
           chroot /opt/chroot /opt/bind/sbin/named -u 20000 -g 20000;      echo "starting chrooted named server."
   fi
 

13. Setup your /opt/chroot/opt/bind/etc/named.conf 
         // generated by named-bootconf.pl

Here is an example of the named.conf file using BIND 8.2.3. This is for the fictional domain of jooky.org, which we like the ip 10.0.0.1 assigned.

/* We first setup an access list for hosts that we will allow to query
* us, using the form {[<network>/<bits>; | <address>;] ... };
*/
    acl "internal" { 
     10.0.0/24;}; 

/* We shouldn't be getting requests from these ip's */ 

     acl "bogus" {
     0.0.0.0/8;
     1.0.0.0/8;
     2.0.0.0/8;
     169.254.0.0//16;
     192.0.2.0/24;
     172.16.0.0/12;
     192.168.0.0/16;
     224.0.0.0/3;
     240.0.0.0/4;
    };

    options {
            directory "/var/named";
            version "you must be kidding";

/* 8.x has the ability to specify which interface to listen on, 
 * where as 4.9.x listened on all the interfaces.
 */
            listen-on { 10.0.0.2;}; 
            statistics-interval 1440;
            /*
             * 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";

/* The following allow-query directive will restrict queries to our
 * name server to come only from the definined acl "internal". Only
 * 8.x offers this type of fine-grained access.
 */

allow-query { "internal";};
            blackhole {
             // Throw these request into the pit from whence they came
             bogus;
            };

    };

zone "." {
type hint;
file "named.ca";
};

zone "jooky.org" {
type master;
file "named.jooky.org";

/* Anyone can ask us about jooky.org (we are authorative for
 * our domain), but cannot ask about anything else that isn't 
 * under our authority. The reason for this is simple. We don't 
 * want anyone from the outside to poke at our nameservers and
 * make named cache false information from a domain the poker has 
 * under his control. 
 *
 * This attack consist of poisoning a name servers cache. Under 
 * 4.9.7 a possible solution to this type of attack is to turn
 * off recursion with the following statement; 
 * options no-recursion.
 *
 * But then be sure to have a remote nameserver that does support 
 * recursion.
 */

allow-query { any; };

/* Our secondary name server orange-cola.org (10.0.0.2) is the
 * only one allowed to transfer the jooky.org zone. While this prevents
 * someone from transfering the whole domain at once, the information
 * is public and can be obtained trivially. The equivalent statement for
 * BIND 4.9.7 is xfernets 10.0.0.2&255.255.255.255
 */

allow-transfer {
 10.0.0.2/32;
 };

zone "0.0.10.in-addr.arpa" {
type master;
file "named.0.0.10.in-addr.arpa";
};
 
 

              logging {
                  channel default_log {
                  file "/var/log/named.log";
                  severity info;
                  print-time yes;                 // timestamp log entries
                  print-category yes;             // print category name
                  print-severity yes;             // print severity level
                  };

                  category default { default_log; }; 
                  category lame-servers { null; };
                  category cname { null; };
                  category response-checks { null; };
                  };
 
 

14. Set permissions:
    # cd /opt/chroot
    # find . -type f -exec chmod ug-s {} \;
    # find . -type f -perm -111 -exec chmod -r {} \;
    # chown -R root:named opt var
    # chown -R dnsadmin:named var/named
    # chmod -R g-w var
    # chmod -R -w opt lib
    # chmod -R o-rx .
    # chmod g+w var/run var/log
    # touch var/log/named.log var/run/named.pid
    # chown named:named var/log/all.log var/run/named.pid

15. You can delete the following without altering the nameserver's ability to function: 
              opt/bind/bin/* 
              opt/bind/sbin/{dnskeygen,irpd,named-bootconf,ndc} 

16. Testing named-xfer 
    #/usr/sbin/chroot /opt/chroot /opt/bind/sbin/named-xfer -z domain.name -f test -d 3 -l test.log primary_dns_server

17. Here are the permissions

#pwd
/opt/chroot
#ls -alR
.:
total 14
drwxr-x---   7 root     named        512 Feb  7 10:51 ./
drwxrwxr-x   5 root     sys          512 Jan 30 14:45 ../
drwxr-x---   2 root     named        512 Apr 13  2000 dev/
drwxr-x---   2 root     named        512 Feb  7 10:53 etc/
dr-xr-x---   2 root     named        512 Apr  6  2000 lib/
dr-xr-x---   3 root     named        512 Jan 29 15:58 opt/
dr-xr-x---   5 root     named        512 Apr  6  2000 var/

./dev:
total 4
drwxr-x---   2 root     named        512 Apr 13  2000 ./
drwxr-x---   7 root     named        512 Feb  7 10:51 ../
crw-rw--w-   1 root     other     11, 42 Apr 12  2000 tcp
crw-rw--w-   1 root     other     11, 41 Apr 12  2000 udp
crw-rw-rw-   1 root     other     13, 12 Apr 13  2000 zero

./etc:
total 10
drwxr-x---   2 root     named        512 Feb  7 10:53 ./
drwxr-x---   7 root     named        512 Feb  7 10:51 ../
-r--r-----   1 root     named       2618 Aug  3  2000 named.conf

./lib:
total 4
dr-xr-x---   2 root     named        512 Apr  6  2000 ./
drwxr-x---   7 root     named        512 Feb  7 10:51 ../

./opt:
total 8
dr-xr-x---   3 root     named        512 Jan 29 15:58 ./
drwxr-x---   7 root     named        512 Feb  7 10:51 ../
lrwxrwxrwx   1 root     other         10 Jan 29 15:58 bind -> bind-8.2.3/
dr-xr-x---   6 root     named        512 Jan 29 15:58 bind-8.2.3/

./opt/bind-8.2.3:
total 14
dr-xr-x---   6 root     named        512 Jan 29 15:58 ./
dr-xr-x---   3 root     named        512 Jan 29 15:58 ../
dr-xr-x---   2 root     named        512 Apr 13  2000 bin/
dr-xr-x---   3 root     named        512 Feb  7 10:52 etc/
dr-xr-x---   2 root     named        512 Apr 13  2000 lib/
dr-xr-x---   2 root     named        512 Feb  7 10:48 sbin/
lrwxrwxrwx   1 root     other          9 Apr 12  2000 var -> ../../var/

./opt/bind-8.2.3/bin:
total 3388
dr-xr-x---   2 root     named        512 Apr 13  2000 ./
dr-xr-x---   6 root     named        512 Jan 29 15:58 ../
---x--x---   1 root     named      11640 Apr 13  2000 addr*
---x--x---   1 root     named     345988 Apr 13  2000 dig*
---x--x---   1 root     named     310956 Apr 13  2000 dnsquery*
---x--x---   1 root     named     330468 Apr 13  2000 host*
---x--x---   1 root     named       7824 Apr 13  2000 mkservdb*
---x--x---   1 root     named     358028 Apr 13  2000 nslookup*
---x--x---   1 root     named     310612 Apr 13  2000 nsupdate*

./opt/bind-8.2.3/etc:
total 14
dr-xr-x---   3 root     named        512 Feb  7 10:52 ./
dr-xr-x---   6 root     named        512 Jan 29 15:58 ../
-r--r-----   1 root     named       2775 Jan 30 14:39 named.conf
-rw-r--r--   1 named    named          6 Feb  7 10:50 named.pid
drwx------   2 root     root         512 Feb  7 10:50 ndc.d/

./opt/bind-8.2.3/etc/ndc.d:
total 4
drwx------   2 root     root         512 Feb  7 10:50 ./
dr-xr-x---   3 root     named        512 Feb  7 10:52 ../
srwxrwxrwx   1 root     other          0 Feb  7 10:50 ndc=

./opt/bind-8.2.3/lib:
total 8
dr-xr-x---   2 root     named        512 Apr 13  2000 ./
dr-xr-x---   6 root     named        512 Jan 29 15:58 ../
-r--r-----   1 root     named       1815 Apr 13  2000 nslookup.help

./opt/bind-8.2.3/sbin:
total 4660
dr-xr-x---   2 root     named        512 Feb  7 10:48 ./
dr-xr-x---   6 root     named        512 Jan 29 15:58 ../
---x--x---   1 root     named    1420184 Jan 31 14:43 named*
---x--x---   1 root     named     938520 Jan 31 14:48 named-xfer*

./var:
total 10
dr-xr-x---   5 root     named        512 Apr  6  2000 ./
drwxr-x---   7 root     named        512 Feb  7 10:51 ../
drwxr-x---   2 root     named        512 Apr 14  2000 log/
drwxr-x---   2 dnsadmin named        512 Feb  7 10:49 named/
drwxr-x---   2 named    named        512 Feb  1 14:40 run/

./var/log:
total 1444
drwxr-x---   2 root     named        512 Apr 14  2000 ./
dr-xr-x---   5 root     named        512 Apr  6  2000 ../
-rw-r-----   1 named    named     724760 Feb  7 10:51 named.log

./var/named:
total 92
drwxr-x---   2 dnsadmin named        512 Feb  7 10:49 ./
dr-xr-x---   5 root     named        512 Apr  6  2000 ../
-rw-r-----   1 dnsadmin named        226 Apr 12  2000 bind
-rw-r-----   1 dnsadmin named       1935 Oct  2 15:05 named.27.80.35.207.in-addr.arpa
-rw-r-----   1 dnsadmin named       2041 Aug  3  2000 named.80.35.207.in-addr.arpa
-rw-r-----   1 dnsadmin named       1636 Apr 12  2000 named.ca
-rw-r-----   1 dnsadmin named       1822 Sep 30 21:22 named.pgci.ca
-rw-r-----   1 dnsadmin named      12121 Apr 12  2000 named.stats

./var/run:
total 6
drwxr-x---   2 named    named        512 Feb  1 14:40 ./
dr-xr-x---   5 root     named        512 Apr  6  2000 ../
-rw-r--r--   1 named    named          6 Jan 31 14:03 named.pid
 
 

  •  


  • Here is a little class c and d scanner that I wrote last year, it's always nice to see what is published out there. It uses perl , which you probably have already installed on your *nix system. 


    Questions or comments? Copyright 1996-2000 PGCI Inc.
    All rights reserved. Legal terms. Privacy policy