Introduction

I recently configured a CentOS 7 server to run BIND as a DNS caching server. This post documents the process.

Although I used CentOS 7, these instructions should be equally applicable to CentOS 5 through 7, and Red Hat Enterprise Linux 5 through 7.

If you already know why and where you want to configure a DNS caching server, feel free to skip ahead to this page’s “DNS Cache Setup” section. Otherwise, read on.

A DNS Cache is normally setup accomplish one or more of the following:

  • Improve performance. This can be especially true for mail servers, which make a large number of DNS queries.
  • Bypass a flaky DNS resolver.

The DNS caching server configuration that’s described on this page is applicable to both situations.

It’s important to restrict which clients can query your DNS caching server, so that you don’t create an open resolver. This document includes instructions for doing so using BIND’s “allow-recursion” directive.

Performance Considerations

All other things being equal, I recommend placing your DNS caching server as close as possible to the clients which will query it.

If the DNS cache will be used by a single client, it could make sense to run the DNS cache on that client. For example, you could install a DNS cache on your mail server. By running the cache on the same system as the querying application, you bypass the network latency that there would normally be between the DNS cache, and client.

If the clients are primarily in a single data center or geographic area, try to place the DNS cache within that same datacenter or area. Network latency is the main factor here.

DNS caching servers do not have much overhead, so if you do setup a dedicated cache, you probably won’t need much in the way of hardware. For example, I opted to use a dedicated VM, so I selected a VM with 512MB of RAM and a single CPU core at Digital Ocean. That doesn’t sound like much, but it’s usually plenty for a dedicated DNS cache.

If you want this caching server to be be able to query IPv6 name servers, or be queried by IPv6 clients, then it pays to have it located on a network with native IPv6 support. A tunnel broker will work in a pinch, but the extra network latency that it introduces comes with a performance cost.

DNS Cache Setup

Now we’re ready to setup our DNS cache. The BIND configuration file that we end up with is included in the “BIND Configuration File” section:

  1. Install BIND:

    yum -y install bind

  2. Update BIND’s configuration file (/etc/named.conf) using your text editor of choice:
    • Allow the desired clients using the “allow-recursion” directive within the global options clause. For example, I’m allowing the localhost (127.0.0.1) and one of DNS Check’s servers (represented as 1.2.3.4) to query this name server:

      allow-recursion { 127.0.0.1; 1.2.3.4; };

    • BIND’s default CentOS 7 configuration listens for queries on the localhost interface only for both IPv4 and IPv6. If you allowed any other IP addresses to query your DNS cache in the previous step, then you’ll probably also want to listen for queries on at at least one additional interface by updating the “listen-on” directive for IPv4 and/or the “listen-on-v6″ directive for IPv6. For example, to listen on all IPv4 and IPv6 interfaces, add the following within the global options clause:

      listen-on {any;};
      listen-on-v6 {any;};

    • Optionally, adjust how long entries are cached. For example, if you wish to cache positive answers (successful lookups) for 15 minutes (900 seconds), and negative answers (failed lookups) for 1 minute (60 seconds), then you would add the following within the global options clause:

      max-cache-ttl 900;
      max-ncache-ttl 60;
  3. Start BIND’s “named” service, and configure it to automatically start at boot time:

    chkconfig named on
    service named restart

  4. Make the operating system that you just configured the DNS cache on query its own cache:

    echo "nameserver 127.0.0.1" > /etc/resolv.conf

  5. Add the new DNS cache’s IP address to /etc/resolv.conf on any other servers that you would like to query it. For example if the DNS cache’s IP address is 1.2.3.4, run:

    echo "nameserver 1.2.3.4" >> /etc/resolv.conf

  6. Run a test query from a client to verify that the DNS cache is working end-to-end:

    dig mx gmail.com

BIND Configuration File

Here are the final contents BIND’s configuration file (/etc/named.conf). If you copy this configuration, then at a minimum, you’ll want to either remove 1.2.3.4, or replace it with the IP address(es) that you want to be able to query the DNS caching server:


// named.conf

options {
listen-on {any;};
listen-on-v6 {any;};
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
allow-query { localhost; };
allow-recursion { 127.0.0.1; 1.2.3.4; };
max-cache-ttl 900;
max-ncache-ttl 60;

/*
- If you are building an AUTHORITATIVE DNS server, do NOT enable recursion.
- If you are building a RECURSIVE (caching) DNS server, you need to enable
recursion.
- If your recursive DNS server has a public IP address, you MUST enable access
control to limit queries to your legitimate users. Failing to do so will
cause your server to become part of large scale DNS amplification
attacks. Implementing BCP38 within your network would greatly
reduce such attack surface
*/
recursion yes;

dnssec-enable yes;
dnssec-validation yes;
dnssec-lookaside auto;

/* Path to ISC DLV key */
bindkeys-file "/etc/named.iscdlv.key";

managed-keys-directory "/var/named/dynamic";

pid-file "/run/named/named.pid";
session-keyfile "/run/named/session.key";
};

logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};
};

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

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";