Secure BIND Template Version 2.2

By Rob Thomas, robt@cymru.com, 03 FEB 2001


Changes in version 2.2:

NOTE:

This is the last release of the 2.X train of the Secure BIND Template. I will no longer be developing this variant of the "split brain model," as I have switched to using the views feature of BIND 9. Please see the latest Secure BIND Template, now in version 3.X.

Introduction

The ubiquitous BIND (Berkeley Internet Name Domain) server is distributed with most UNIX variants and provides name services to countless networks.  However, the BIND server is not without certain vulnerabilities, and is often a choice target for Internet vandals.  These vandals utilize BIND vulnerabilities to gain root access to the host or to turn the host into a launching platform for DDOS attacks.  An improper or insufficiently robust BIND configuration can also "leak" information about the hosts and addressing within the intranet.  This article presents a template for deploying a secure BIND configuration, thus mitigating some of the risk of running the BIND server.

If you are not familiar with BIND configuration, I highly recommend that you pick up a copy of DNS and BIND, by Albitz and Liu, published by O'Reilly and Associates.

Please feel free to share any suggestions or bug reports with me.  Feedback is always welcome!  Send all feedback to robt@cymru.com.

Credits

My thanks to several folks who offered suggestions, input, and took the time to review this document.

Tools

There exist myriad tools for debugging BIND configuration errors.  Aside from the log files, I recommend that you include the following tools in your DNS toolbox. Keep in mind that the miscreants often use these tools when scanning a network, so it is a good idea to test your network security before someone with evil intent scans your network.

Secure the BIND Configuration

The following configuration presumes that the host network is connected to the Internet.  It is assumed that the reader has a working knowledge of the BIND version 9, and this article will not detail the creation of zone files or general DNS configuration and maintenance.  Instead, this article supplements and protects an existing BIND configuration.  This is a "split brain" DNS model with a twist - the two "sides" of DNS are contained within completely distinct spaces.  The files and address space are separate, thus providing a great deal of protection against an attack that targets one side of the DNS topology.

For our purposes, we will assume that our internal network is 7.7.7.0/24, and that our external network is 8.8.8.0/24.  Our name server has a NIC in each subnet, with the internal NIC as 7.7.7.1 and the external NIC as 8.8.8.1.  It is often the case that the name server is also the firewall, so the addressing scheme and dual NIC configuration likely fits many network topologies.

Ensure that you have the latest version of the BIND.  You can obtain the latest version by visiting the Internet Software Consortium BIND site at http://www.isc.org/products/BIND/.  The compilation and installation of the BIND is well detailed at this site.  This template has been most recently tested with BIND version 9.1.0.

BIND 9.1.0 contains two interesting records in the CHAOS class - version.bind and authors.bind, both type TXT.  The version.bind TXT record will return the version of BIND running on the server.  The authors.bind TXT record will return a list of the authors of the BIND 9.1.0.  While the version.bind TXT record may assist admins, it runs counter to the philosophy of "keep the miscreants guessing."  For this reason, it is recommended that you hide these records from external hosts.  This is done through a view, and it will be demonstrated in the template below.

You may wish to ensure that your BGP configuration does not dampen the netblocks that contain the DNS root servers.  Please consult my Secure BGP Template for further details on this topic.

The chroot Jail

It is best to run BIND in a chroot'd jail.  This will prevent a miscreant from using named to access or manipulate other files on the host system, as well as preventing an overflow in BIND from granting a shell to the miscreant.  Presently, this document contains links to a chroot jail for Solaris and FreeBSD.  Other will be added as time and testing allow.

To view a chroot jail configuration for Solaris 7, click HERE.

To view a chroot jail configuration for FreeBSD, click HERE.

After building the chroot environment, create a small passwd file in each jail.  The passwd file should contain only a root account and the BIND user.  For the internal BIND jail, call the user intnamed.  For the external BIND jail, call the user extnamed.  Assign a UID greater than 100 to each named account, and remember to sync up the passwd file with the shadow file (pwconv in Solaris).  Do not create passwords for the accounts.  Instead, lock them with entries in the shadow file such as this one for the internal BIND:

root:*LK*:6445::::::
intnamed:*LK*:11136::::::

I recommend using a shell that will allow no access, such as /bin/false or my own denial shell, nocando.  The nocando denial shell, which includes detailed logging, can be found in the Tools section of my web site.  The home directories for these accounts will be the directories we create below.

Next, create two directory structures to contain our configuration files.  For example, use /jail/external-bind/var/named for the external BIND and /jail/internal-bind/var/named for the internal BIND.  In each directory, create a subdirectory named master for our master zones and slave for our slave zones, if such zones exist.  Change the ownership of these subdirectories to the proper named UID, e.g.:

chown -R intnamed:intnamed /jail/internal-bind/var/named

Configure the zone files normally, and place them in the proper subdirectories.  Remember to place the internal zone files in /jail/internal-bind/var/named, and the external zone files in /jail/external-bind/var/named.  Each subdirectory must also have a hint file (often named db.cache) and a named.conf file.  Don't forget to create a loopback zone file for each subdirectory!  Details regarding the creation of the hint and zone files can be found in the August 2000 issue of  "Inside Solaris," in the article entitled "Configuring BIND 8," by Don Kuenz.  See also DNS and BIND, by Albitz and Liu, published by O'Reilly and Associates.

We will now configure the two named configuration files, one for internal DNS and another for external DNS.  Pay close attention to the subtle differences between them.

External DNS - named.conf

The external DNS configuration file is built to service externally based queries, recursively answer internally based queries, and to mitigate many of the attacks commonly found on the Internet.  If an attack does succeed in breaching or halting the external named daemon, service on the internal named daemon for queries of internal names and addresses is largely unaffected.

// @(#)named.conf 20 DEC 2000 Rob Thomas robt@cymru.com
// Set up our ACLs
acl "xfer" {
    none;   // Allow no transfers.  If we have other
            // name servers, place them here.
            // Note that in the Netherlands, for example,
            // the TLD servers 193.176.144.2 and 193.176.144.138
            // are allowed to perform zone tranfers
            // from the domains under .nl.
};

acl "trusted" {
    // Place our internal and DMZ subnets in here so that
    // intranet and DMZ clients may send DNS queries.  This
    // also prevents outside hosts from using our name server
    // as a resolver for other domains.
    7.7.7.0/24;
    8.8.8.0/24;
    localhost;
};

acl "bogon" {
// Filter out the bogon networks.  These are networks
// listed by IANA as test, RFC1918, Multicast, experi-
// mental, etc.  If you see DNS queries or updates with
// a source address within these networks, this is likely
// of malicious origin. CAUTION: If you are using RFC1918
// netblocks on your network, remove those netblocks from
// this list of blackhole ACLs!
    0.0.0.0/8;
    1.0.0.0/8;
    2.0.0.0/8;
    10.0.0.0/8;
    23.0.0.0/8;
    31.0.0.0/8;
    69.0.0.0/8;
    70.0.0.0/8;
    71.0.0.0/8;
    72.0.0.0/8;
    73.0.0.0/8;
    74.0.0.0/8;
    75.0.0.0/8;
    76.0.0.0/8;
    77.0.0.0/8;
    78.0.0.0/8;
    79.0.0.0/8;
    82.0.0.0/8;
    83.0.0.0/8;
    84.0.0.0/8;
    85.0.0.0/8;
    86.0.0.0/8;
    87.0.0.0/8;
    88.0.0.0/8;
    89.0.0.0/8;
    90.0.0.0/8;
    91.0.0.0/8;
    92.0.0.0/8;
    93.0.0.0/8;
    94.0.0.0/8;
    95.0.0.0/8;
    96.0.0.0/8;
    97.0.0.0/8;
    98.0.0.0/8;
    99.0.0.0/8;
    100.0.0.0/8;
    101.0.0.0/8;
    102.0.0.0/8;
    103.0.0.0/8;
    104.0.0.0/8;
    105.0.0.0/8;
    106.0.0.0/8;
    107.0.0.0/8;
    108.0.0.0/8;
    109.0.0.0/8;
    110.0.0.0/8;
    111.0.0.0/8;
    112.0.0.0/8;
    113.0.0.0/8;
    114.0.0.0/8;
    115.0.0.0/8;
    126.0.0.0/8;
    169.254.0.0/16;
    172.16.0.0/12;
    191.255.0.0/16;
    192.0.2.0/24;
    192.168.0.0/16;
    198.18.0.0/16;
    201.0.0.0/8;
    223.255.255.0/24;
    224.0.0.0/3;
    240.0.0.0/4;
};

// Set options for security
options {
    directory "/var/named";
    pid-file "/var/named/named.pid";
    statistics-file "/var/named/named.stats";
    dump-file "/var/adm/named.dump";
    query-source address 8.8.8.1;
    transfer-source address 8.8.8.1;

    // Return a bogus response to miscreants
    // who query for our BIND version.  Do not
    // use this trick if you are going to use
    // the view trick detailed below.
    version "Off with your head!";

    // Prevent DoS attacks by generating bogus zone transfer
    // requests.  This will result in slower updates to the
    // slave servers (e.g. they will await the poll interval
    // before checking for updates).
    notify no;

        // Generate more efficient zone transfers.  This will place
    // multiple DNS records in a DNS message, instead of one per
    // DNS message.
    transfer-format many-answers;

    // Set the maximum zone transfer time to something more
    // reasonable.  In this case, we state that any zone transfer
    // that takes longer than 60 minutes is unlikely to ever
    // complete.  WARNING:  If you have very large zone files,
    // adjust this to fit your requirements.
    max-transfer-time-in 60;

    // We have no dynamic interfaces, so BIND shouldn't need to
    // poll for interface state {UP|DOWN}.
    interface-interval 0;

    listen-on { 8.8.8.1; };
        // Listen on our external interface
        // only.

    allow-transfer {
        // Zone tranfers limited to members of the
        // "xfer" ACL.
        xfer;
    };

    allow-query {
        // Accept queries from our "trusted" ACL.  We will
        // allow anyone to query our master zones below.
        // This prevents us from becoming a free DNS server
        // to the masses.
        trusted;
    };

    blackhole {
        // Deny anything from the bogon networks as
        // detailed in the "bogon" ACL.
        bogon;
    };
};


zone "." in {
    type hint;
    file "db.cache";
};

// Allow queries for the 127/8 network, but not zone transfers.
// Every name server, both slave and master, will be a master
// for this zone.
zone "0.0.127.in-addr.arpa" in {
    type master;
    file "master/db.127.0.0";

    allow-query {
        any;
    };

    allow-transfer {
        none;
    };
};

zone "ournetwork.net" in {
    type master;
    file "master/db.ournetwork";

    allow-query {
        any;
    };
};

zone "8.8.8.in-addr.arpa" in {
    type master;
    file "master/db.8.8.8";

    allow-query {
        any;
    };
};

// Now create a view for the CHAOS class - again, only if
// you are running BIND 9.1.0.  The bind zone file will be
// detailed below.  Set allow-query to trusted or none,
// depending on your policies.

view "external-chaos" chaos {
    recursion no;

    zone "." {
        type hint;
        file "/dev/null";
    };

    zone "bind" {
        type master;
        file "master/db.bind";

        allow-query {
            trusted;
        };
        allow-transfer {
            none;
        };
    };
};

Internal DNS - named.conf

The internal DNS configuration file is built to service queries from hosts on the internal network(s).  It is also built to forward queries for external hosts to the named daemon servicing the external side of the name server.

// @(#)named.conf 20 DEC 2000 Rob Thomas robt@cymru.com
// Set up our ACLs

acl "xfer" {
    none;   // Allow no transfers.  If we have other
            // Note that in the Netherlands, for example,
            // the TLD servers 193.176.144.2 and 193.176.144.138
            // are allowed to perform zone tranfers
            // from the domains under .nl.
};

acl "trusted" {
    // Place our internal subnet in here so that intranet
    // clients may send DNS queries.
    7.7.7.0/24;
    localhost;
};
 

// CAUTION: If you are using RFC1918 netblocks on your
// network, remove those netblocks from this list of
// blackhole ACLs!
acl "bogon" {
    0.0.0.0/8;
    1.0.0.0/8;
    2.0.0.0/8;
    10.0.0.0/8;
    23.0.0.0/8;
    31.0.0.0/8;
    67.0.0.0/8;
    68.0.0.0/8;
    69.0.0.0/8;
    70.0.0.0/8;
    71.0.0.0/8;
    72.0.0.0/8;
    73.0.0.0/8;
    74.0.0.0/8;
    75.0.0.0/8;
    76.0.0.0/8;
    77.0.0.0/8;
    78.0.0.0/8;
    79.0.0.0/8;
    80.0.0.0/8;
    81.0.0.0/8;
    82.0.0.0/8;
    83.0.0.0/8;
    84.0.0.0/8;
    85.0.0.0/8;
    86.0.0.0/8;
    87.0.0.0/8;
    88.0.0.0/8;
    89.0.0.0/8;
    90.0.0.0/8;
    91.0.0.0/8;
    92.0.0.0/8;
    93.0.0.0/8;
    94.0.0.0/8;
    95.0.0.0/8;
    96.0.0.0/8;
    97.0.0.0/8;
    98.0.0.0/8;
    99.0.0.0/8;
    100.0.0.0/8;
    101.0.0.0/8;
    102.0.0.0/8;
    103.0.0.0/8;
    104.0.0.0/8;
    105.0.0.0/8;
    106.0.0.0/8;
    107.0.0.0/8;
    108.0.0.0/8;
    109.0.0.0/8;
    110.0.0.0/8;
    111.0.0.0/8;
    112.0.0.0/8;
    113.0.0.0/8;
    114.0.0.0/8;
    115.0.0.0/8;
    126.0.0.0/8;
    169.254.0.0/16;
    172.16.0.0/12;
    191.255.0.0/16;
    192.0.2.0/24;
    192.168.0.0/16;
    198.18.0.0/16;
    201.0.0.0/8;
    223.255.255.0/24;
    224.0.0.0/3;
    240.0.0.0/4;
};

options {
    directory "/var/named";
    pid-file "/var/named/named.pid";
    statistics-file "/var/named/named.stats";
    dump-file "/var/adm/named.dump";
    listen-on { 7.7.7.1; };

    // Return a bogus response to miscreants
    // who query for our BIND version.  Do not
    // use this trick if you are going to use
    // the view trick detailed below.
    version "Off with your head!";

    // Prevent DoS attacks by generating bogus zone transfer
    // requests.  This will result in slower updates to the
    // slave servers (e.g. they will await the poll interval
    // before checking for updates).
    notify no;

         // Generate more efficient zone transfers.  This will place
    // multiple DNS records in a DNS message, instead of one per
    // DNS message.
    transfer-format many-answers;

    // Set the maximum zone transfer time to something more
    // reasonable.  In this case, we state that any zone transfer
    // that takes longer than 60 minutes is unlikely to ever
    // complete.  WARNING:  If you have very large zone files,
    // adjust this to fit your requirements.
    max-transfer-time-in 60;

    // We have no dynamic interfaces, so BIND shouldn't need to
    // poll for interface state {UP|DOWN}.
    interface-interval 0;

    forwarders { 8.8.8.1; };
    // Send all queries for external hosts to the external
    // named on this same host.  The external named daemon
    // will recursively seek the answer to the internal
    // query, then return the answer.

    allow-transfer {
        xfer;
    };

    allow-query {
        trusted;
    };

    blackhole {
        bogon;
    };
};

zone "." in {
    type hint;
    file "db.cache";
};

zone "0.0.127.in-addr.arpa" in {
    type master;
    file "master/db.127.0.0";

    allow-query {
        any;
    };

    allow-transfer {
        none;
    };
};

zone "internal.ournetwork.com" in {
    type master;
    file "master/db.internal";
};

zone "7.7.7.in-addr.arpa" in {
    type master;
    file "master/db.7.7.7";
};

// Now create a view for the CHAOS class - again, only if
// you are running BIND 9.1.0.  The bind zone file will be
// detailed below.  Set allow-query to trusted or none,
// depending on your policies.

view "external-chaos" chaos {
    recursion no;

    zone "." {
        type hint;
        file "/dev/null";
    };

    zone "bind" {
        type master;
        file "master/db.bind";

        allow-query {
            trusted;
        };
        allow-transfer {
            none;
        };
    };
};

Internal DNS - db.cache

The hint file for the external DNS server should be the standard hint file.  The hint file for the internal DNS server, however, should be configured
with only the names and addresses of our external DNS server(s).  An example would be:

; @(#)db.cache for internal DNS 12 AUG 2000 Rob Thomas robt@cymru.com
.   99999999    IN  NS  ns1.ournetwork.net.

;
; hotwire the addresses
;

ns1.ournetwork.net.      IN  A   8.8.8.1
 

The db.bind zone file

The db.bind zone file is used to track miscreants who attempt to query the CHAOS TXT records version.bind and authors.bind.  You can also use this zone file to change the strings returned by such queries.  Using the "version" directive in the options stanza will block the version.bind query, but it will not log such attempts.

; @(#)db.bind for internal and external DNS 25 JAN 2001 Rob Thomas robt@cymru.com
;
$TTL    1D
$ORIGIN bind.
@       1D      CHAOS   SOA     localhost. root.localhost. (
                2001013101      ; serial
                3H              ; refresh
                1H              ; retry
                1W              ; expiry
                1D )            ; minimum
        CHAOS NS        localhost.

version.bind.   CHAOS  TXT "BIND 9.1.0-modified"
authors.bind.   CHAOS  TXT "A very silly query, don't you think?"
 

Starting the two named daemons

Once the configuration is complete, it is time to launch the two named daemons.  Without changing /etc/init.d/inetsvc on Solaris, it is wise to test the configurations first.  Remember that we are running our named daemons in a chroot jail.  Further we wish to have each named run in a separate user space and under a unique user.  To start the external DNS service, type:

cd /jail/external-bind
/usr/sbin/chroot /jail/external-bind usr/local/sbin/named -u extnamed

By typing the ps -fu extnamed command, you can verify that our external named daemon is running.  To start our internal DNS service, type:

cd /jail/internal-bind
/usr/sbin/chroot /jail/internal-bind usr/local/sbin/named -u intnamed

Typing ps -fu extnamed will verify that our external  name service is up and running.  Typing ps -fu intnamed will verify that our internal name service is up and running.

Once you have /etc/resolv.conf properly configured (use the internal address for the nameserver line), you should be able to launch queries.  Test a few basic queries for both internal and external names and addresses.  Then test an intranet client to ensure that the forwarding is properly working.  If you have secondary name servers, ensure that zone transfers are functional and complete.  If possible, test the external name server from an external host to ensure that the ACLs are functional and that logging is working.

Once all testing is successfully completed, modify /etc/init.d/inetsvc to start two named daemons at boot.  Comment out the current named lines and insert the following:

# Start external DNS
if [ -f /jail/external-bind/usr/local/sbin/named -a -f /jail/external-bind/usr/local/etc/named.conf ];
then
    echo "Starting external BIND server."
    (cd /jail/external-bind; /usr/sbin/chroot /jail/external-bind usr/local/sbin/named -u extnamed)
fi

# Start internal DNS
if [ -f /jail/internal-bind/usr/local/sbin/named -a -f /jail/internal-bind/usr/local/etc/named.conf ];
then
    echo "Starting internal BIND server."
    (cd /jail/internal-bind; /usr/sbin/chroot /jail/internal-bind usr/local/sbin/named -u intnamed)
fi

Conclusion

The BIND is a necessary application on almost all networks.  However, it is not without certain risks.  By implementing a secure configuration and a separation of internal and external name services, we can increase the security and reliability of our name services and protected networks.
 

[ Articles ]       [ ]

Rob Thomas, robt@cymru.com,