Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1142924
  • 博文数量: 168
  • 博客积分: 4445
  • 博客等级: 上校
  • 技术积分: 1307
  • 用 户 组: 普通用户
  • 注册时间: 2005-11-02 14:04
文章分类

全部博文(168)

文章存档

2018年(2)

2017年(5)

2016年(7)

2015年(1)

2014年(8)

2013年(1)

2012年(4)

2011年(54)

2010年(8)

2009年(19)

2008年(18)

2007年(36)

2006年(1)

2005年(4)

分类: 系统运维

2009-06-25 11:13:18

  Running the BIND9 DNS Server securely

By www.boran.com/security/sp/bind9_20010430.html

This paper walks through compiling, installing and configuring a chroot'ed BIND v9 on Solaris 2.6 and 8. It also presents examples of advanced topics such as TSIGs and dynamic updates. It is specific to version 9 but we aim to help existing BIND 8 administrators realize what is involved in migrating to v9.

Although originally written in 2001, information here may still be relevant to you: I do update now and again due to positive feedback and to document some Solaris servers I still have running productively. If starting from scratch now, I'd probably use Ubuntu LTS as the base OS and use the standard packages and automated updates :-)

Table of contents:
Document Changes:
4.Aug.08 Update for Bind 9.5.1 (see also upgrade commands.
31.Mar.08 OpenBSD note correction.

v9.5.1/Solaris 8

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.

BIND [1] is the most frequently used DNS server and maintained by the ISC. It is also known as "named", since this is the name of the actual daemon itself. As with many applications exposed to the increasingly hostile Internet environment, security weaknesses have been discovered in BIND. There are three major versions:

  1. v4 was bundled with most UNIX systems up to around 1998. It has been abandoned by most vendors. The OpenBSD crew audited / corrected v4 and more recently v9 (they found v8 is be overly complex).
  2.  v8 now aging too, although still in use. We have discussed hardening this version is a separate article [13].
  3.  v9 is complete rewrite, free, but commercially sponsored. It has lots of new features (which is nice, but a security concern). v9 reached production status in October 2000 and has been regular improvemented since then.
    The engineering staff at Nominum authored BIND9 and are experts in the DNS community. They provides software, hardware, training and Consulting services for DNS and DHCP, as well as DNS hosting service through .

This article concentrates on using Bind version 9 securely.


Why Bother? What Risks Does an Insecure BIND Pose?

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 transfers 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.
       
  • 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, but the firewall hosts have 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.

DNS has been become a favorite target of hackers as witnessed by the automated attack tools and worms using a DNS weaknesses that appeared in winter 2001 and summer 2008.


So What Needs to Be Done?

BIND risks may be reduced with several prevention measures:

  1. Resource isolation: Use a dedicated, hardened server for Internet DNS, don't share it 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 weaknesses 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 be will be queued (typically up to four days).
  3. Use the latest version.
  4. Access control: Restrict zone transfers to minimize the amount of information on your networks available to attackers. Consider using transaction signatures (TSIG). Consider restricting/not allowing recursive queries.
  5.  Run BIND with minimum privileges: as a non-root user, with a tight umask.
  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.  Configure BIND not to report its version number (see below). Some people don't believe in hiding the version number, as it is "security by obscurity," but I maintain that it at least helps against the script kiddies who are roaming the net looking for obvious targets. Defending against the pros is a different matter.
  8.  Detection: Monitor logs for unusual activity and the system for unauthorized changes with an integrity checker.
  9.  Keep an eye on relevant advisories, make sure your are notified of future BIND problems in a timely manner.

The procedure in this paper concentrates only on measures 4), 5) and 6), which should help to protect a server against possible future weaknesses in BIND.

This article has been tested on many production systems since 2001 on Solaris 2.6 and on Solaris 8.

Apart from being multi-threaded, and a complete code rewrite - which should provide better stability and security in the long term, there are other differences;

  • If there is a syntax error in named.conf, BIND9 will log errors and not reload the named server. BIND8 will log errors and the daemon will die!
  • Extensive support of TSIGs (shared keys) for access control, for example, "update-policy" can be used for fine grained access control of dynamic updates.
  • The tool for starting/stopping/reloading etc., rndc  is different from the v8 ndc - different communications, authentication and features. See the rndc section.
  • Syntax in zone files is more rigorously checked (e.g. a TTL line must exist)
  • In named.conf:
    • v8 options 'check-names' and 'statistics-interval' are not yet implemented in V9.
    • the default for the option 'auth-nxdomain' is now 'no', if you don't set this manually, BIND 9 logs a corresponding message on startup.
  • The root server list, often called named.root or root.hints in BIND8 is not necessary in BIND 9, as it is included within the server.
  • See also [11].

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 Jass first [7]. This section runs through:

  • Compiling BIND on a master host, since you probably don't have (or shouldn't have) a compiler on the hardened DNS server.
  • Installing BIND to the DNS server.
  • Setting up and running BIND.

1. (on the Compiler host)

Download the distribution [1], and extract it to a subdirectory and compile. This can be done as a non-root user.

  • Prerequisites:
    Install '' first, so that the installation to a temporary directory below works correctly. Note that we refer to /usr/local/bin/make below, and not the standard Solaris /usr/ccs/bin/make.
    GNU bison was needed on my (old) test system, although the standard Solaris yacc should be enough.
    GNU grep was needed for the upgrade to v9.5.1
    A recent version of the SSL libraries needs to be installed. Bind will complain if the SSL libraries are old (since older versions have security vulnerabilities).
    Packages for the above are available on SunFreeware.com that are easy to install, for example: wget ftp://ftp.sunfreeware.com/pub/freeware/sparc/8/grep-2.5.1a-sol8-sparc-local.gz gunzip grep-2.5.1a-sol8-sparc-local.gz pkgadd -d grep-2.5.1a-sol8-sparc-local After installing the new grep, ensure 'make' finds it: export GREP=/usr/local/bin/grep
    • In the release notes for BIND 9.1.0, it is stated that the multi-threading on Solaris 2.6 has problems, so we compile without multi-thread support:
    ./configure --disable-threads
    • On Solaris 7/8 we can leave multi-threading enabled:
    ./configure
  • So we can now compile, using GNU make:

    /usr/local/bin/make
  • Now change to the root account, install to a temporary directory, and create a tarball:

  • NOTES:
    The strip command is optional, used to remove debugging information and symbols. This reduces the uncompressed distribution from 90MB to around 25MB (for v9.1.0).

    Compressed, the 9.1.3 binary tarball is 8MB.

    The deletion of the include files is also optional, its purpose is to save space.

    su - root # allow group, but not world access umask 027 /usr/local/bin/make install DESTDIR=/tmp cd /tmp/usr/local strip bin/* sbin/* lib/* \rm -rf include tar cf - * | compress > bind9_dist.tar.Z
  • Next, move the bind9_dist.tar.Z to somewhere safe and remove the /tmp/usr and possibly the directory where you compiled BIND to clean up.

  • Documentation:

    Included in the distribution, is the Administrators Guide (html format) in doc/arm/Bv9ARM.html. This is worth reading. Man pages are also included but they are very difficult to install on Solaris. The next release, v9.2, should have properly formatted man-pages installed, in the meantime, the man pages are available in text form [9].

    (on target system)

    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.

    1. Set destination directories  for chroot jail, everything will be installed in subdirectories of this tree.

    csh
    unset noclobber
    set jail='/home/dns';
    umask 022;

    2. Set up empty directories and links for chroot environment:

    mkdir $jail; Create a link from /dns to the jail to make life easier we'll assume through this article that "/dns" points to the top of the chroot tree rm /dns ln -s $jail /dns cd /dns; mkdir -p {dev,opt,usr,var,etc}; mkdir -p var/{run,log,named} usr/lib; mkdir -p usr/local/etc mkdir -p usr/share/lib/zoneinfo;

    3.  Accounts.

    Create a user and group account for BIND:

    groupadd named;
    useradd -d /dns -s /bin/false -g named -c "BIND daemon" -m named

    Create an identical user and group account within the chroot:

    Aside: We assume that the production BIND configuration will be changed/managed by root. You may prefer to create a specific user for this task at this stage, e.g. 'dnsmgr' which belongs to the 'bind' group and has write access to /dns/etc/named.conf and /dns/var/named.

    grep named /etc/passwd >> /dns/etc/passwd
    grep named /etc/shadow >> /dns/etc/shadow
    grep named /etc/group >> /dns/etc/group

    Don't allow the BIND account to use ftp:

    echo "named" >> /etc/ftpusers

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

    4. Install the bind distribution - first change to the directory where the tarball is located, then:

    cp bind9_dist.tar.Z /dns/usr/local;
    cd /dns/usr/local;
    zcat bind9_dist.tar.Z| tar xvf -

    5. Copy system files needed to the chroot environment

    cp /etc/{syslog.conf,netconfig,nsswitch.conf,resolv.conf,TIMEZONE} /dns/etc

    Use ldd to see what shared object libraries named relies on:

    ldd /dns/usr/local/sbin/named

    Copy the files listed by ldd, for example on Solaris 10 x86:

                
     cp -p /usr/local/ssl/lib/libcrypto.so.0.9.8  \
    /usr/lib/libnsl.so.1 /usr/lib/libsocket.so.1 \
    /usr/lib/libscf.so.1 /usr/lib/libpthread.so.1 \
    /usr/lib/libxml2.so.2 /usr/lib/libz.so.1 \
    /usr/lib/libm.so.2 /usr/lib/libc.so.1 \
    /lib/libdl.so.1  /usr/local/lib/libgcc_s.so.1 \
    /lib/libmp.so.2 /lib/libmd.so.1 \
    /lib/libdoor.so.1 /lib/libuutil.so.1 \
    /lib/libgen.so.1 /usr/lib/libthread.so.1 \
    /dns/usr/lib

     

     

    on Solaris 8:

    cp -p /usr/lib/libnsl.so.1  \
    /usr/lib/libsocket.so.1 /usr/lib/libc.so.1 \
    /usr/lib/libthread.so.1 /usr/lib/libpthread.so.1 \
    /usr/lib/libdl.so.1 /usr/lib/libmp.so.2 \
    /usr/lib/ld.so.1 /usr/lib/nss_files.so.1 \
    /usr/platform/SUNW,UltraAX-i2/lib/libc_psr.so.1 \
    /dns/usr/lib

    Solaris 2.6:

    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 /dns/usr/lib

    On a Solaris 2.6 UltraSPARC, ldd also listed the following as being necessary
    cp /usr/platform/SUNW,Ultra-250/lib/libc_psr.so.1  /dns/usr/lib

    Experience has shown the following are also needed:
    cp /usr/lib/ld.so.1 /usr/lib/nss_files.so.1 /dns/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 (for example MET, here in Europe):

    mkdir -p /dns/usr/share/lib/zoneinfo;
    cp -p /usr/share/lib/zoneinfo/MET /dns/usr/share/lib/zoneinfo/MET

    Set up devices for communication, console, syslog, etc.

    cd /dns/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 For Bind v9.5.1 create /dev/poll cd /dns/dev mknod poll c 138 0 chgrp sys random 这里应该是poll吧? chmod 644 random 这里应该是poll吧?

    Optional for local syslog messages: Create a loop-back for syslog. The following was suggested by a reader, although I've not found it necessary.

    mkdir /dns/etc/.syslog_door
    mount -F lofs /etc/.syslog_door /dns/etc/.syslog_door

    On Solaris 8/9, provide access to /dev/random, by  

    creating a loopback mount for the /dns jail (which I use for historical reasons...):
    mkdir /dns/dev/random
    mount -F lofs /dev/random /dns/dev/random

    or creating a device within the DNS jail (first check the current minor/major device number with ls -al /devices/pseudo/random\@0\:random):
    cd /dns/dev
    mknod random c 240 0
    chgrp sys random
    chmod 644 random

     

    Create a directory for DNS data; we assume it is in /var/named:

    mkdir -p /dns/var/named;


    cd /dns/etc
    touch named.conf
    chown root:named named.conf
    chmod 640 named.conf

    vi named.conf

    So what do you put in named.conf? We start off with a simple example to get BIND running: lookups of 'localhost', reverse lookups of 127.0.0.1 and a simple domain test1.com

    • A simple Primary DNS system (assumed to have the address 192.168.128.34):
    • A simple secondary DNS system (assumed to have the address 192.168.128.33):

    We'll go into more detail on DNS configuration below, at this stage we concentrate on getting BIND running.

    After copying these files, verify the syntax:

    Primary + secondary:
    chroot /dns /usr/local/sbin/named-checkconf /etc/named.conf
    chroot /dns /usr/local/sbin/named-checkzone local /var/named/localhost.zone
    chroot /dns /usr/local/sbin/named-checkzone local /var/named/localhost.rev

    The localhost.zone file may complain about a missing SOA and NS records. Ignore these.

    Primary:
    /dns/usr/local/sbin/named-checkzone test1.com /dns/var/named/test1.com


    4. s

    Next, we set permissions on files, so that root owns files and named can read all files and write some files. Then, 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 /dns
    chgrp -R named *

    # remove group write from var, write access to opt and usr
    chmod -R g-w var;
    chmod -R a-w opt usr;

    # For secondaries, allow named to create/change data files:
    chown -R root:named /dns/var/named;
    chmod 770 /dns/var/named;

    # For primaries, allow named read-only access, it does not need write access to data files:
    chown -R root:named /dns/var/named;
    chmod 750 /dns/var/named;
    chmod -R go-w /dns/var/named;
    # Note: I lied a little bit... if named needs to write a debug file, or dump statistics, it will need write
    # access to /dns/var/named. So you choose if you want a very tight, or more relaxed setup:
    chmod 770 /dns/var/named;

    # Create empty log and pid files:
    touch var/log/all.log var/run/named.pid;
    chown named:named var/log/all.log var/run/named.pid;

    # Allow named user/group to write logs and pid files:
    chgrp -R named /dns/var/log /dns/var/run;
    chmod 770 /dns/var/run /dns/var/log;
    chmod -R o-rwx /dns/var/run /dns/var/log;

    # Allow named to access BIND config file:
    chgrp named /dns/etc;
    chown root:named /dns/etc/named.conf;
    chmod 640 /dns/etc/named.conf;
    chmod 755 /dns/etc;

    # Remove SUID or SGID bits, if any exist:
    find . -type f -exec chmod ug-s {} \;

    # Remove world access:
    chmod -R o-rwx * /dns/usr

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


    OK, we have DNS configuration is in /dns/etc/named.conf, zone files in /dns/var/named (where /dns is a link to the top of the chroot tree, e.g. /export/home/dns), let's try and start BIND!

    1. Set up a tail on the (syslog) logs, to watch BIND activity, for example
      tail -f /var/adm/messages |grep named  &
      tail -f /var/log/daemonlog |grep named  &
      The logs may be in /var/adm/messages or on a remote server, depending on your /etc/syslog.conf configuration.
    2. Start BIND chroot'ed:
      /usr/sbin/chroot /dns /usr/local/sbin/named -u named
    3. Check for errors:
      • Examine syslog.
      • Test our example domains:

      /dns/usr/local/bin/dig @localhost 127.0.0.1
      /dns/usr/local/bin/dig @localhost localhost
      /dns/usr/local/bin/dig @localhost localhost mx
      /dns/usr/local/bin/dig @localhost localhost ns

      /dns/usr/local/bin/dig @localhost
      /dns/usr/local/bin/dig @localhost www1.test1.com
      /dns/usr/local/bin/dig @localhost test1.com ns
      /dns/usr/local/bin/dig @localhost test1.com mx

      • Make sure the secondary can do zone transfers: in our example, a file 'test1.com' should appear in /dns/var/named.
      • If you change configuration, send a HUP signal to named, to ensure that it reloads configuration correctly.
        kill -1 `cat /dns/var/run/named.pid`
      • If your are connected to the Internet, check the domains using the IP-Plus tool 4.
    4. If everything still looks good, let's start BIND each time the system boots.

    Change the /etc/rc2.d/S72inetsvc entries for named to disable Sun's default. Then create a startup file /etc/init.d/dns and setup links:

    ln -s /etc/init.d/dns /etc/rc2.d/S50dns
    ln -s /etc/init.d/dns /etc/rc2.d/K50dns

    My example startup file /etc/init.d/dns has a few bells and whistles you may like to check out, for example it crates and mounts /dev/random within the /dns chroot environment).

    Client:

    Use  dig or host or nslookup to check server results. Dig is better, as nslookup needs to find a PTR record for the DNS server; otherwise it won't start. You'll also find that many implementations of nslookup don't work with IPv6.

    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 arguments 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 /dns/var/run/named.pid`

    Look at the syslog entries. Typically logs are found in the syslog "daemon" section.

    Run a check on the configuration:
    chroot /dns /usr/local/sbin/named-checkconf /etc/named.conf

    Run a check on a specific zone:
    cd /dns/var/named; named-checkzone myzone.com zonefile

    Named has a "-d X" option, which switches on debugging (X is a number indicating the debug level), for example:
    /usr/sbin/chroot /dns /usr/local/sbin/named -u named -d3

    Run named in the foreground and log to stderr (i.e. the screen):
    /usr/sbin/chroot /dns /usr/local/sbin/named -u named -g

    To get statistics from the name server into /dns/named/named.stats:
    rndc stats

    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 on a secondary:

    Make sure the named user has write access to /dns/var/named on the secondary

    Try manual zone transfers, for example:

    /dns/usr/local/bin/dig @SERVER DOMAIN.NAME axfr
    /dns/usr/local/bin/dig @192.168.128.34 test1.com axfr

    Make sure the option forward only has not been enabled by mistake in named.conf.

    Make sure that the filesystem where you do your chroot'ing is not mounted nosuid, otherwise /dev/zero won't work.

    truss is very useful for following program execution, for example:

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

    Check the domains using the IP-Plus tool 4.

    If you suspect that the chroot is causing problems

    • run BIND outside the chroot and debug. For example:
      ln -s /dns/var/named /var/named;
      /dns/usr/local/sbin/named -u named -c /dns/etc/named.conf
    • Use the '-t' option that enables the built-in BIND chroot feature. This means that BIND starts normally, load libraries etc., then calls chroot() itself. This method of chroot'ing requires no libraries, less /etc files and less devices (/dev/null might be enough). So, you may ask why bother with the more complicated procedure in this guide? Well this guide was started before the -t option existed and also, this method chroot's the entire bind process; the -t option only chroots after connecting to libraries, devices and ports.

    Read the sections Known Problems and Configuration Notes below.

    Check the BIND-users email list [10].

    Read the book DNS and BIND [5].


    Example 1: test1.com (simple domain, reverse lookup, zone transfer ACL)
    • Primary  (assumed to have the address 192.168.128.34):

    Copy to /dns/var/named:   test1.com, rev.192.168.128
    Copy to /dns/etc/named.conf: named.conf.primary

    • Secondary (assumed to have the address 192.168.128.33):

    Copy to /dns/etc/named.conf: named.conf.secondary

    Notes:

    • After starting the secondary, the files secondary.test1.com and secondary.rev.192.168.128 should be created in /dns/var/named by the automatic zone transfer after BIND starts.
    • Zone transfers are limited to the primary, secondary, and example ISP and the root domain for our country. See acl "nameservers"  and the option allow-transfer { nameservers; }; in named.conf
    • Reverse lookups of 192.168.128.33 and 192.168.128.34 should work.
    • MX, NS lookups on test1.com and lookups of , ns1.test1.com, www1.test1.com should work.
    • Dynamic updates are not allowed.

    Example 2: test2.com (Dynamic Updates with Simple ACL)

    In this case, we copy the /dns/var/named/test1.com configuration above to test2.com, but the domain names are changed. The new zone file /dns/var/named/test2.com must belong to named and be writeable by named.

    chown named.named /dns/var/named/test2.com;
    chmod 600 /dns/var/named/test2.com

    In named.conf we add a few lines that allow dynamic updates from the IP address 192.168.128.33 only.

    acl "updaters" {
    192.168.128.33;
    };

    zone "test2.com" {
    type master;
    file "test2.com";
    allow-update { updaters; };
    };

    When we restart named, the following entry appears in syslog warning us that the method chosen above is not the most secure for dynamic updates. Our next example will improve on this.

    /usr/local/sbin/named: zone 'test2.com' allows up dates by IP address, which is insecure


    Testing:

    Updates are only allowed from 192.168.128.33 and we assume the primary has the address 192.168.128.34, so we have to run the 'nsupdate' program from 192.168.128.33. The nsupdate program reads the update commands from a file or standard input, hence we use the "<<" redirection symbols in the following examples:

    # add "host1" to the domain
    /dns/usr/local/bin/nsupdate <server 192.168.128.34 53
    update add host1.test2.com 3600 A 10.1.1.1

    EOF
    echo $status
    /dns/usr/local/bin/nslookup -sil host1.test2.com 192.168.128.34

     

    # remove "host1" from the domain
    /dns/usr/local/bin/nsupdate <server 192.168.128.34 53
    update delete host1.test2.com A

    EOF
    echo $status
    /dns/usr/local/bin/nslookup -sil host1.test2.com 192.168.128.34

     

    # First delete the host (if it exists), then add it:
    /dns/usr/local/bin/nsupdate <server 192.168.128.34 53
    update delete host1.test2.com A
    update add host1.test2.com 3600 A 10.1.1.1

    EOF
    echo $status
    /dns/usr/local/bin/nslookup -sil host1.test2.com 192.168.128.34

     

    : test3.com (dynamic updates with TSIG authentication)

    Dynamic updates in the previous example are usually to a list of IP addresses (via the ACL mechanism) which correspond to specific servers for a zone. Since only IP addresses are used, this mechanism is open to IP spoofing. BIND allows additional authentication of the servers in the ACL list. A key is configured on each server and used to sign messages exchanged between them. Its important that the server times are synchronized. If the communication is not authenticated with the correct key, no updates may take place.

    In this case, we copy the /dns/var/named/test2.com configuration above to test3.com, but the domain names are changed.

    Let's look at an example where we use TSIG to authenticate updates.

    a) Generate an MD5 key, which will be used as a shared secret. The "dnssec-keygen" tool is used. The key is written to a file.

    /dns/usr/local/sbin/dnssec-keygen -a HMAC-MD5 -b 128 -n HOST updater1

    Which creates files like: Kupdater1.+157+08531.key and Kupdater1.+157+08531.private. What interests us is the 'Key' entry in the private file, which looks something like k2Pb7gEcbXg6ZosOqAbV8A==.

    So we add the following to /dns/etc/named.conf:

    // TSIG keys
    key updater1 { algorithm hmac-md5; secret "k2Pb7gEcbXg6ZosOqAbV8A=="; };

    And in the zone definition for test3.com:

    allow-update { key updater1; };

    Testing updates:

    a) We try to add a "host1" to the domain in the usual manner: this will fail (exist status 2, with an "update denied" entry in the primary's log), because we have tried an update without a TSIG key exchange.

    /dns/usr/local/bin/nsupdate <server 192.168.128.34 53
    update add host1.test3.com 3600 A 10.1.1.1

    EOF
    echo $status

    b) This time we do it correctly - add a "host1" to the domain and provide the TSIG key on the command line.

    /dns/usr/local/bin/nsupdate -y "updater1:k2Pb7gEcbXg6ZosOqAbV8A=="   <server 192.168.128.34 53
    update add host1.test3.com 3600 A 10.1.1.1

    EOF
    echo $status

    c) Nsupdate can use a TSIG key also be stored in a file, for example Kupdater1.+157+08531.private which we generated above. The file Kupdater1.+157+08531.key must also be in the same directory or in the PATH.

    /dns/usr/local/bin/nsupdate -k Kupdater1.+157+08531.private <server 192.168.128.34 53
    update add host1.test3.com 3600 A 10.1.1.1

    EOF
    echo $status


    Comments on Dynamic Updates, TSIG Security and ACLs
    • It is critical that the key be kept secret, which means for example:
      • that named.conf and key files must not be readable by anyone other than named or the user running nsupdate.
      • the key should not be transmitted in emails, unless encrypted
      • anyone you give this key to is implicitly trusted: so only give it to those who need it, never untrusted persons.
      • consider changing the key on a regular basis, after personnel changes, or after you suspect its secrecy may have been compromised.
    • If the two hosts are on the same subnet, spoofing the IP address might be more difficult than getting a copy of the key (for example if border routers filter spoofed addresses), so an IP ACL would be more effective.
    • If both an ACL and TSIG key are specified, for example:
      allow-update { key updater1; updaters};
      This means that either TSIG or the IP ACL is valid for updates.
    • It is not possible to require both the TSIG and IP access control. The BIND developers don't think this is useful, because their focus is on user-level, rather than host level access control for dynamic updates (hence the emphasis on the new update-policy feature which allows users with dynamic IPs to update their DNS entry). I disagree, the use of both is useful for many situations and would add an additional security barrier, even if IP ACLs can be spoofed for non-local-subnet IP addresses. Strangely enough the rndc access control (see below) does allow the combined use of IP and TSIG access control.
    • Dynamic updates can't add or remove domains, only entries within domains.
    • A client host that wish to update a BIND server needs only the nsupdate binary and the appropriate keys. No other binaries or libraries are required.
    • nsupdate also has '-d' option for debugging.
    • nsupdate can also use tcp rather than udp for updates ('-v' option), this provides better performance if there are many updates and better security since tcp is connection oriented. A tcp connection could also be piped through an encrypted SSH tunnel for additional security (encryption and access control).
    • is a new v9 feature which allows updates to be restricted to individual names. For example to allow an ADSL or DHCP user to update their own hostname (i.e. where the IP address can change). With update-policy, a list of per-hostname keys can be setup and allow each key to update only the associated hostname.
    Tips

    The named.conf 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 below logs to the syslog facility, with debug logging of queries to a local file:
      logging {
      channel syslog_errors {syslog daemon; severity info; };
      channel debug_file {file "debuglog"; severity dynamic;};
      category queries {debug_file; };
      };
    • To switch on the actual debug logging (to /dns/var/named/debuglog), instruct the named daemon via rndc:
      /dns/usr/local/sbin/rndc querylog
    • To disable noisy "disabling EDNS" messages in Bind 9.5.1:
      category edns-disabled { null; };
    • If you get "ns_client_replace() failed: out of memory" messages, comment out any "datasize" directive.
    • If the server does not normally resolve private addresses, log warning like ""RFC 1918 response from Internet for 12.66.185.10.in-addr.arpa" may appear. Then either forward them to a server that can resolves these addresses (replace 1.2.3.4 with the resolving NS):
      zone "10.IN-ADDR.ARPA" { type forward; forwarders { 1.2.3.4; }; forward only; }; Or add an empty zone zone "10.IN-ADDR.ARPA" { type master; file "empty"; };The file "empty" conatins: @ 10800 IN SOA . . ( 1 3600 1200 604800 10800 ) @ 10800 IN NS .This should be done for 16.172.IN-ADDR.ARPA, 31.172.IN-ADDR.ARPA and 168.192.IN-ADDR.ARPA too.
    • 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.
    • The version number that BIND reports to clients such as dig can be changed with the version directive. Its a good idea to set this, to stop simple attackers scanning for particular BIND version (with known weaknesses/exploits). To query the version of a remote BIND, try:
      dig @NAMESERVER version.bind chaos txt
       
    • : An interesting new feature in v9 is the ability to answer a query in a different way depending on who is asking, or putting it another way - restrict specific remote users from looking up portions of the DNS namespace. You'll find an excellent tutorial at [15].
      • The following view statement is an example of providing two different DNS maps, one for internal queries, the other for Internet queries. 
      • Note: to setup a "split dns" with internal and external views on the primary and secondary, there were two issues that caught me out: 
        a) Zones that are to be visible in the Internal and External view have to be defined twice in named.conf, once in each view. All zone definitions much occur within views (there is no concept of an automatic "default" view, from which other views inherit).
        b) Its easy to publish the internal namespace on the secondary accidentally without realising it. The problem is that the zones transferred from primary to secondary depends on the source address of the secondary to determin which view the secondary should see!
        To ensure the secondary creates an separate internal and external view:
        - create a second virtual network interface on the secondary, tell the secondary to use this new address for transfers from the primary (transfer-source A.B.C.D) for the external namespace.
        - On the primary, ensure that this new secondary address is in the ACL to allow zone transfers  and that it is excluded from the match-clients for the internal view.
        - Also ensure that this address appears nowhere is your namespace, i.e. it should not resolve in the internal or external view.
         
      • Ensure the primary and secondary primary interfaces resolve in both namespaces.
      • The following example assumes we have used 176.17.17.8 as the special address for external zone transfers.

    view "internal" {// This should match our internal networks.
    match-clients { !176.17.17.8; 10.0.0.0/8; }; // important to exclude 176.17.17.8 from the Internal view
    allow-transfer { internal-nameservers; };  
    // Provide recursive service to internal clients only.
    recursion yes;

    // Provide a complete view of the example.com zone
    // including addresses of internal hosts.
    zone "example.com" {
    type master;
    file "example-internal.db";
    };

    zone "localhost" {
    type master;
    file "localhost.zone";
    notify no;
    allow-update { none; };
    };
    };

    view "external" {
    match-clients { any; };
    // Refuse recursive service to external clients.
    //transfer-source 176.17.17.8; // On secondary: Network Interface for Internal ZoneTx
    recursion no;
    // Provide a restricted view of the example.com zone
    // containing only publicly accessible hosts.

    zone "example.com" {
    type master;
    file "example-external.db";
    };

    zone "localhost" {
    type master;
    file "localhost.zone";
    notify no;
    allow-update { none; };
    };
    };

    Bind v9 provides the rndc tool for stopping, starting, reloading the named daemon. In this section we examine ways of using rndc and document problems and limitations.

    Bind v8 included the ndc tool, so what is the difference? Well, rndc (v9) uses TCP sockets (default 953) as opposed to  ndc's (v8) UNIX-domain sockets. Ndc didn't work in a chroot environment, rndc does.

    • For rndc to work, named has to be configured to listen on the rndc port. Access control on this port is implemented via TSIG keys. So these keys have to be setup for rndc to work. So lets run through the steps involved:
      1. Generate a new shared key to control access to the rndc port:
        /dns/usr/local/sbin/dnssec-keygen -a hmac-md5 -b 128 -n user rndc
        Copy the key from the 'private' file generated, it should look something like 'NsuYsQ0Pp7J3LaOsVHr0uw=='.
      2.  Add the key to /dns/etc/named.conf, for example:
        key key_rndc {algorithm hmac-md5; secret "NsuYsQ0Pp7J3LaOsVHr0uw=="; };
      3.  Then tell named to listen on the rndc port, at our primary's IP address and respond to requests that have the appropriate key:
        controls {inet 192.168.128.34  port 953 allow {localhost;} keys {key_rndc;} ; };
        Note: if you change the control section, I recommend stopping and starting the server, not just a 'reload' or 'kill -1'.
      4.  Stop named, restart it (chroot'ed of course, and as root).

        sh /etc/init.d/dns stop
        sh /etc/init.d/dns start

        You should see a message in the logs like:
        /usr/local/sbin/named[12993]: command channel listening on 19 2.168.128.34#953

      5.  Next setup /etc/rndc.conf to contain the appropriate key and the address of the default server.

        key key_rndc {
        algorithm hmac-md5;
        secret "NsuYsQ0Pp7J3LaOsVHr0uw==";
        };
        options {
        default-server 192.168.128.34;
        default-key key_rndc;
        };

        Protect this file:
        chmod 600 /etc/rndc.conf

      6.  Now we're ready to do some tests.
    • Testing rndc:
  • To reload the named server configuration:
    /dns/usr/local/sbin/rndc reload
    A message like 'rndc: reload command successful' should appear.

  • Let's reload a specific zone only:
    /dns/usr/local/sbin/rndc reload test1.com

  • Let's force a secondary to update from its master:
    /dns/usr/local/sbin/rndc refresh test1.com

  • Write some statistics to /dns/var/named/named.stats:
    /dns/usr/local/sbin/rndc stats

  • Switch on logging of queries on or off:
    /dns/usr/local/sbin/rndc querylog

  • Write DNS cache contents to /dns/var/named/named_dump.db:
    /dns/usr/local/sbin/rndc dumpdb

    • Testing access control:
      • If we now copy out /etc/rndc.conf file to another host (for example our secondary 192.168.128.33) and try to run 'rndc reload', we get the rather cryptic message 'rndc: connect: end of file' (no entry appears in the server syslog). This message, in fact, means that the rndc connection has been refused access.
      • So we go back to the primary's named.conf and we change the access list to allow connections from the secondary's IP address:
        inet 192.168.128.34 port 953 allow {localhost;192.168.128.33;} keys {key_rndc ;}
      • Now the 'rndc reload' will work fine remotely from the secondary host.

    Nice things about rndc:

    • Individual zones can be reloaded.
    • It works in a chroot environment.

    Disadvantages:

    • Several features are planned but not yet implemented:
      status: Display ps(1) status of named.
      trace: Increment debugging level by one.
      notrace: Set debugging level to 0.
      restart: Restart the server.
    • A bit complicated, it would have been nice to use only IP addresses for access control, for example restricting access to localhost.
    • Access control violations are not logged server-side.
    • Since keys are used for access control, restrictive file permissions on /etc/rndc.conf and named.conf are critical.
    References
    1. BIND Home Page -
    2. How to Break Out of a chroot() Jail -
    3. There is an Administrators guide in html format included in the BIND9 tarball, in doc/arm/Bv9ARM.html. This is worth reading.
    4. IP-Plus provides a tool for remotely checking your DNS configuration -

      Note: to get correct results, your server must allow zone transfers from the IP address 164.128.36.54.
    5.  "DNS and BIND", by Paul Albitz & Cricket Liu, published by O'Reilly & Associates.
      A great reference work. The 3rd edition does not cover v9, but the new 4th edition does.
      Chapter 11 (Security) is available free online.

    6.  RFC2845: Secret Key Transaction Authentication for DNS (TSIG) - community.roxen.com/developers/idocs/rfc/rfc2845.html
    7. Solaris Hardening Tools - YASSP , Titan , Jass , My notes www.boran.com/security/sp/Solaris_hardening.html
    8. An example of an "ls -alR" on a production chroot'ed DNS primary, to show what the file permissions should look like - bind/bind9_perms.txt
    9. BIND9 man pages in text format: bind/man
    10. Check the BIND-users email list:


    11. Upgrading to BIND 9: The Top Nine Gotchas, by Cricket Liu.

    12. Example configuration files from this article: bind
    13. Our previous article on Hardening BIND v8 bind_hardening8.html
    14. - DNS Security Extensions,  
    15. Views tutorial, by Cricket Liu
    16. Bind Upgrade copy/paste example: bind9.5.1_upgrade.txt
    Further Reading

    BINDv9 and Internet Security
    Paul Vixie and David Conrad

    In this interview, Paul Vixie and David Conrad talk about the Internet Software Consortium, the changes in the latest major version of bind, the security features designed into it, and the future of Internet security.

    Fingerprinting Bind 9 (discussion)

    BIND Manual
     

    Securing an Internet Name Server: Presentation
    Cricket Liu
     

    Dnsjava is dns server and client in Java. I found it interesting as a basis for programming dynamic DNS updates in Java.

    Thanks to Rejane Forré for proof-reading, David "Tale" Lawrence and Brian Wellington of Nominum for precise feedback and help.

    Brian Friday, 6.mar.02

    debug_file:
    Instead of putting this into the named directory you could put this in the var directory by putting "/var/log/debuglog" in the file area of the channel debug_file section of the named.conf file.

    /var/named directory usage:
    I did take some tips from the linux chroot guide one of them was putting a directory under /var/named called "slave" making only that directory writeable by named. /var/named remains writeable only by root but this slave directory can be written by named. Using this you could be a master/slave for some zones and still retain a decent security level.

    RNDC:
    I discovered it was easier to use the rndc-confgen application then follow the instructions you have for enabling rndc. The rndc-confgen actually prints out the code which you should put in the /etc/rndc.conf and named.conf. Not really a big deal just a little shortcut.

    s 14.Mar sb First draft, Solaris 2.6 Primary/secondary. Doc 1747 securityportal.com/articles/bind9_20010430.html
    22.Mar sb Feedback Brian Wellington, fix links to examples.
    02.Apr sb Adapt for Solaris 8 secondary. Man pages. Strip.
    25.Apr sb prepare for first publication. Proofed by Rejane.
    30.Apr sb Diverse tweaks, first publication.
    14.May sb Add Nominum note. Liu presentation, FAQ link.
    18.Sep  Correct formatting. SecurityPortal gone. Tested on Bind 9.1.3/Solaris 2.6.
    4.Nov.01  Bind 9.1.3/Solaris 8 secondary.

    7.Jun  Bind 9.2.1/Solaris 8 secondary
    16.Jun  Bind 9.2.1/Solaris 8 secondary,
    /dev/random tests.

    28.Jan.03  Recheck doc with Solaris 8 + Bind 9.2.1 primary, gcc 3.1. Add references to /dev/random.
    6.mar.03 : Add Reader Feedback Tested v9.2.1/Solaris 8 /prim/sec. with /dev/random
    5.Aug.03 link to dnssec 
    26.Nov.03 Implemented full Split dns and hence added notes to Views section. Add mknod alternative to lofs for /dev/random.

    31.Mar.04 Minor corrections.
    30.Apr.04 Update views.
    13.May.04 Toubleshooting tips
    26.Jan.07 Update for Bind 9.3.4.

    , Sean Boran,

    阅读(3175) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~