Open Source Software Technical Articles

Want the Best of the Wazi Blogs Delivered Directly to your Inbox?

Subscribe to Wazi by Email

Your email:

Connect with Us!

Current Articles | RSS Feed RSS Feed

Secure and Reliable Authoritative DNS with BIND


Almost every IT service relies on the Domain Name System; DNS failures cause problems with web access, email communication, applications, and even database operations. Under Linux, BIND is the most widely used DNS server. While common BIND administration tasks are simple and straightforward, BIND also has powerful and advanced features for improved DNS security and performance. Thus it pays to make some configuration changes to ensure a more robust corporate BIND implementation.

Start by creating one BIND master DNS server with a few slave servers, and place the slaves in data centers in different geographic locations so that they don't suffer from the same network and power problems. For this task, edit the Name Server (NS) records for your domain. NS records determin the DNS zone's authoritative DNS servers. When there is more than one NS record the DNS queries go randomly to all servers. If one server is down, the client just sends its queries to another. NS records are usually configured at domain registrars because they have to be included in the parent DNS zone, such as .com or .net.

Don't expose the master DNS server to the public; that is, don't include it in the NS zone records for the domains it serves. Also, allow DNS connections to the master server only from its slaves to prevent attackers learning about the DNS service when probing the network. You can configure this easily via iptables. If you use the default CentOS firewall, which blocks all connections, run the command:

/sbin/iptables -I INPUT -m state --state NEW -s X.X.X.X -m tcp -p tcp --dport 53 -j ACCEPT

Make sure to replace X.X.X.X with the IP address of a slave server. Repeat the command for each slave server. After that, save the firewall state with the command service iptables save.

BIND in chroot

You can also install BIND in a chrooted version. A chrooted service isolates security problems to the chroot directory, /var/named/chroot/, so even if an attacker manages to compromise the chrooted version, he will have access to only a minimal environment that will not give him many resources.

To install BIND's chrooted version under Centos, execute the command yum install bind-chroot. To start it for the first time, run service named start. Finally, make sure it automatically starts and stops when the server does by executing chkconfig named on.

You may have noticed that the service name for BIND under CentOS is "named." This name is also used in BIND's root directory, /var/named/chroot/. CentOS and its upstream provider Red Hat renamed BIND to named in their distributions for their own reasons. We'll stick to the name server's original name – BIND.

BIND's chrooted filesystem, /var/named/chroot/, exists only when BIND is running. If you run the command mount -l | grep chroot, you'll see that all essential files and directories of a regular BIND are mounted as separate filesystems inside the /var/named/chroot/ directory. Changes outside and inside the BIND chroot are synchronized; in other words, when you make a change on /var/named/chroot/etc/named.conf, you are also updating /etc/named.conf, and vice versa.

BIND General Configuration

In a chrooted installation, BIND's configuration files are under the directory /var/named/chroot/etc/. The main configuration file is /var/named/chroot/etc/named.conf. It contains a few nested directives, which are placed in curly brackets. The first, options {}, contains various settings applicable both for master and slave servers. Here are a few things you should put between the brackets:

    • Hide the server's version for additional security. Add a new row version "NONE";

    • Configure the server to listen on all interfaces. By default, BIND listens only on the local interface, as configured with the row listen-on port 53 {; };. This is correct for a server that does not serve remote clients, but we need external connectivity, and the server should listen on public interfaces. Replace this row with listen-on { any; };.

    • Forbid recursion – that is, configure BIND to act only as authoritative DNS and not serve requests for other domains. Specify recursion no;. By default recursion is enabled, but you should disable it because many malicious attacks rely on it being enabled.

Sometimes universal rules in the configuration file need customization. Luckily, BIND has a useful option called view that allows you to customize the rules based on clients, destinations, and even on whether the type of query is recursive or not. Here's an example with a view statement:

view "internal" {
match-clients {; }; // office network
recursion yes;
view "external" {
match-clients {"any"; }; // all other hosts
recursion no;

With the above customization, local clients from the network are able to use the server for querying external domains too, making for a typical caching server. External clients are allowed to use the server only as authoritative.

Using rndc for BIND Administration

BIND is installed with rndc (/usr/sbin/rndc), a utility for easy, remote, less service-disruptive administration. It allows you to do everything from stopping the server to reloading a single DNS zone, as we'll see in a moment.

To use rndc you have to configure it to authenticate to BIND using a secret key. First, generate the key using the command rndc-confgen -r /dev/urandom -a > /etc/rndc.key. The -r argument says to use /dev/urandom for randomization. The -a argument indicates automatic, which avoids the need to specify further configuration options.

Next, edit the named.conf file, paste the contents of /etc/rndc.key, and create a new controls option as follows:

key "rndc-key" {
algorithm hmac-md5;
secret "girKwLEa5rETKoJDKtIVIA==";

controls {
inet allow { localhost; }
keys { rndc-key; };

The option controls specifies the rndc-key, as in /etc/rndc.key, and specifies that connections from localhost to are allowed. If you are controlling the server remotely, adjust this configuration to your IP address and hostname.

Authoritative Master Server Configuration

The authoritative master server has a similar options configuration to the slaves'. It differs mainly in the zone configurations. Here's an example for the zone file for an domain:

zone "" in{
type master;
file "zones/";
allow-transfer {X.X.X.X;Y.Y.Y.Y;};

This bare-minimum master configuration ensures that slaves can receive the DNS zone properly. Many things happen behind the scenes and don't require explicit configuration. For example, you don't have to list the slaves, because they are automatically determined by the NS DNS records. Also, the master will notify the slave servers of potential changes because the option notify is set to yes by default.

Here's a minimal master DNS zone for

$TTL 3600 ; 1 hour default TTL IN SOA (
2012063001 ; Serial number
600 ; Refresh time
60 ; Retry time
86400 ; Expire time
300 ; Negative Caching TTL

ns1 IN A X.X.X.X
ns2 IN A Y.Y.Y.Y

The first value in the zone is the TTL (time to live), which is 3,600 seconds or one hour. TTL determines for how long a client or a caching DNS server can store the record before looking for an update. The Start Of Authority (SOA) record specifies the master server ( and the admin email address ("." is used instead of "@").


You have to increment the serial number manually for each new version of the DNS zone. By convention, this number includes the current date (YYYYMMDD) plus two digits at the end for revisions. When it is incremented, a new serial number instructs the slave servers to transfer the new DNS zone. The refresh time (600 seconds in our example) determines how often the slave servers check for incremented serial numbers.

The value of the expire time, 86400, is one day in seconds. It determines for how long the slave keeps serving the DNS zone even if the TTL is overdue but the master server cannot be reached. This value gives you one day to repair the master server without affecting the slaves and DNS service stability. Next, the negative caching TTL determines for how long negative lookups are remembered, such as when a missing entry result is returned.

At the end are two NS records and their respective A records. To ensure consistency, keep these records synced with the DNS server records at the registrar.

Slave Server Configurations

As I mentioned, most of the options are similar for master and slave servers. The slave's DNS zone configuration looks like this:

zone "" {
type slave;
masters { Z.Z.Z.Z; };
file "zones/";

The zone on the slave server contains a very minimal set of options. The option type determines that it's a slave server with master server IP address Z.Z.Z.Z. You must specify an IP address for the master because a hostname will not work.

Nothing else is needed for the zone to be served from this slave server. All the fine-grained configuration is contained within the DNS zone, which is centrally synchronized from the master.

As I already mentioned, it's a good idea to spread your slave DNS servers geographically to avoid common infrastructure problems. Also, try to locate the slave DNS servers as close as possible to your end users to avoid network latency. Dispersed servers for DNS slaves is a costly task, however, so you may also consider free providers that offer reliable and easy-to-use DNS slave services.

Cache Poisoning Protection with DNSSEC

After we have the basic DNS setup complete, let's continue with the security ehhancements and work again on the DNS master server. Domain Name System Security Extensions (DNSSEC) provides a means to secure your DNS zones and prevent common threats such as DNS cache poisoning. You should use it if your sites include sensitive data. In order to use it for the zone, run these commands inside the zones' directory (/var/named/chroot/var/named/zones/):

dnssec-keygen -r /dev/urandom -a rsasha1 -b 1024 -n ZONE
dnssec-keygen -r /dev/urandom -a rsasha1 -b 1024 -n ZONE -f KSK
cat *.key >>
rndc reload
rndc reload

On the first two lines we generate the DNSSEC signing keys using the rsa-sha1 algorithm with 1,024-bit lengths. The first line is for the Zone Signing Key (ZSK), while the second one is for the Key Signing Key (KSK). KSKs sign the public key records – that is, the ones included in the DNS zone as DNSKEY type. ZSKs sign all the records in the zone and are not publicly referenced.

On the third line we copy the public keys for both KSK and ZSK directly to the DNS zone file for After that we reload the zone with rndc to make the new changes take effect. At the end we sign the zone with dnssec-signzone, which generates a new file called It has to replace the old, unsigned file in the BIND's configuration for

zone "" {
type slave;
masters { Z.Z.Z.Z; };
file "zones/";

After the above change, run rndc reload to reload the server's configuration, and your DNS zone is protected with DNSSEC. Every time you need to edit the zone, make the changes to the original zone file and then run dnssec-signzone to create a new DNSSEC signed zone.

I hope this DNS review helps you enhance your IT infrastructure and make it more reliable. But this is far from being a complete reference, so I hope you'll continue exploring BIND's advanced features and options further on your own.

This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.


Currently, there are no comments. Be the first to post one!
Post Comment
Website (optional)

Allowed tags: <a> link, <b> bold, <i> italics