Datai.Net Datai.Net

  • Home
  • Webmail
Home / CentOS Server / CentOS ~ Secure BIND9 DNS Server

CentOS ~ Secure BIND9 DNS Server

Introduction

In this how-to article, we will walk you through the installation of a secure BIND9 authoritative DNS server on CentOS 6.x

BIND is open source software that implements the Domain Name System (DNS) protocols for the Internet. It is a reference implementation of those protocols, but it is also production-grade software, suitable for use in high-volume and high-reliability applications.

Outline of Configuration Steps

  1. Basic Server Preparation.
  2. Installation of the BIND software packages.
  3. Configuration of the BIND software packages.
  4. Adding a test zone (domain)
  5. Testing your DNS server

Prerequisites

Before you begin this how-to article, you will need to make sure that you have these prerequisites done first.

  • CentOS 6.x Server — If you do not have a server available, you can spin one up via our Cloud Hosting services here.

1 – Basic Server Preparation

The basic installation of CentOS 6.x comes with a limited set of packages, so the first thing we want to do is install the tools we’ll be using to complete all tasks in this article.

First, make sure that you are logged in as the root user account.

sudo su -

Now, let’s install the basic tools so that we can download files, and edit configuration files easily.

yum install wget nano
  • wget: package for retrieving files using HTTP, HTTPS and FTP, the most widely-used Internet protocols.
  • nano: command line text editor with easy to use controls.

Next, we are going to make sure the core operating system if fully updated.

yum update -y

Now that your system is fully updated, we will update the firewall (enabled by default) to allow DNS (TCP Port 53 / UDP Port 53) to access your server.

iptables -I INPUT 5 -m state --state NEW -m tcp -p tcp --dport 53 -j ACCEPT; 
iptables -I INPUT 5 -m state --state NEW -m udp -p udp --dport 53 -j ACCEPT;
service iptables save; service iptables restart;

2 – Installation of the BIND software packages

We are now ready to install the BIND software packages on your server.

yum install -y bind bind-utils bind-chroot
  • bind : The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) server
  • bind-utils : Utilities for querying DNS name servers
  • bind-chroot : A chroot runtime environment for the ISC BIND DNS server

Now that you have the required BIND software packages installed, we are ready to start the BIND services and set them to auto start upon a server reboot.

service named start;
chkconfig named on;

3 – Configuration of the BIND DNS Server

Upon starting the BIND DNS server, the chroot package automatically mounted all the configuration files in the /var/named/chroot directory of your server. When you run BIND (or any other process) in a chroot jail, the process is simply unable to see any part of the filesystem outside the jail.

For reference, the base directory you will be working in for any BIND configurations is: /var/named/chroot

First, lets change to that directory for the remainder of these steps.

cd /var/named/chroot

Now, lets create some directories and a configuration setting file for your new server and set the permissions.  These directories will be used to store forward and reverse zone files for your DNS server.

mkdir var/named/fwd-zones;
mkdir var/named/rev-zones;

chown -R named:named var/named/fwd-zones;
chown -R named:named var/named/rev-zones;

touch etc/zones.conf;
chown root:named etc/zones.conf;

Next, we are going to edit the etc/named.conf configuration file.  We will walk you through the entire setup so that you understand what each option is doing for your server.

nano etc/named.conf

Upon initial installation, the default configuration file will be the below:

//
// named.conf
//
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only nameserver (as a localhost DNS resolver only).
//
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//

options {
        listen-on port 53 { 127.0.0.1; };
        listen-on-v6 port 53 { ::1; };
        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; };
        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";
};

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";

The available configuration settings and options in BIND are very extensive, in this article we will be covering only the options to setup your server to be an authoritative DNS server and secure your server from Recursive DNS Amplification Attacks.

A site that we have found to be very good for explaining all the available options can be found here (Zytrax.com).

The first configuration option we are going to change is the listening options for your server.  By default, the server is setup to only listen on the local Loopback address (127.0.0.1).  We are going to change this to listen on all interfaces of your server.  Replace the following lines inside the options { } tag of the configuration file.

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

We are now going to add some ACL (Access Control List) rules to the configuration.  These ACLs will be used to extend the security settings for the query lookup options as well as the recursive query options. The first rule “allowed-queries” will be used to allow any source address to query your DNS server. The second rule “allowed-recursion” will be used to restrict recursive lookup to only the LOCALHOST address.

Add the below ACL policy rules just above the options { } tag.

// ACL - Allow queries from ANY source address
acl "allowed-queries" {
     any;
};

// ACL - Allow recursion from LOCALHOST only.
acl "allowed-recursion" {
    127.0.0.1;
     ::1;
};

options {
    ...
};

Next, we are going to change the configuration value of the “allow-query” option variable to use the new ACL we just created.
The “allow-query” variable defines who (source networks) that are allowed to query your DNS server.  Replace the following lines inside the options { } tag of the configuration file.

     allow-query     { "allowed-queries"; };

Now we need to secure the recursion lookup permission on your server.  Recursion is a technique in which a DNS server queries other DNS servers on behalf of the requesting client to fully resolve the name and then sends an answer back to the client. Attackers can use recursion to deny the DNS Server service. Therefore, if a DNS server in your network is not intended to receive recursive queries, recursion should be disabled on that server or secured to not allow unauthorized sources to use the recursion technique.

By default, the BIND DNS server is configured to allow any source IP to request recursion. We are going to add a configuration variable to restrict who can use this server for recursive requests using the second ACL that we created already.  Add the following lines inside the options { } tag of the configuration file, just below the option variable “recursion yes;”.

     allow-recursion { "allowed-recursion"; };

We are now going to add an include statement to the configuration file.  This will be used to include the authoritative zone data (domains) that your server will be configured to respond to. Add the following line below the close of the option { } tag, just after the last include statement.

include "/etc/zones.conf";

We are now completed with the configuration changes in the etc/named.conf configuration file.  You can now save and exit your changes.

For review, your etc/named.conf configuration file should now look like the below:

//
// named.conf
//
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only nameserver (as a localhost DNS resolver only).
//
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//

// ACL - Allow queries from ANY source address
acl "allowed-queries" {
     any;
};

// ACL - Allow recursion from LOCALHOST only.
acl "allowed-recursion" {
    127.0.0.1;
    ::1;
};

options {
        listen-on port 53 { any; };
        listen-on-v6 port 53 { 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     { "allowed-queries"; };
        recursion yes;
        allow-recursion { "allowed-recursion"; };

        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";
};

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";
include "/etc/zones.conf";

4 – Adding your first zone (domain)

We are now going to add your first zone that your DNS server will be authoritative of.  We will be using a testing domain for this step as the example.

First, we will create a new file in the directory “fwd-zones” that we created earlier.

touch var/named/fwd-zones/example.tld.zone;
chown named:named var/named/fwd-zones/example.tld.zone;

Next, we are going to add the example zone record data for this domain.  Edit the new file that we just created and add the zone data to the configuration file. Once done, save and exit the configuration file.

nano var/named/fwd-zones/example.tld.zone;

Zone Data

; zone file for example.tld
$TTL 14400     ; 4 hours - default TTL for zone
$ORIGIN example.tld.

;; SOA Resource Record
@             IN      SOA   ns1.example.tld. hostmaster.example.tld. (
                        2015010100 ; se = serial number
                        12h        ; ref = refresh
                        15m        ; ret = update retry
                        3w         ; ex = expiry
                        3h         ; min = minimum
                        )

;; Name Servers
              IN      NS      ns1.example.com.
ns1           IN      A       192.0.2.3

;; Mail Exchange Resource Records
@             IN      MX  10  mail.example.tld.

;; Web Server Resource Records
@             IN      A       192.0.2.3
www           IN      CNAME   @

;; FTP Server Resource Records
ftp           IN      A       192.0.2.3

Now we are going to edit the etc/zones.conf configuration file to include our new domain that we just created.

nano etc/zones.conf;

Now add the below parameters to the configuration file.  Once done save and exit the file.

zone "example.tld" in {
     type master;
     file "fwd-zones/example.tld.zone";
     allow-transfer { none; };
};

We are now ready to restart your DNS services so that all the new configurations are put into place.

service named restart;

If everything restarted successfully, without any errors, you should receive the following response:

Stopping named: .                                          [  OK  ]
Starting named:                                            [  OK  ]

5 – Testing your DNS server

We are now ready to test the functionality of your new DNS server.  First, we are going to confirm that your DNS server is responding for the zone (domain) that we just created.  Execute the following command:

dig example.tld -t ANY @localhost

You should see the below similar response output from your server.  The key response values to look for are the “;; ANSWER SECTION:”  This lets you know that the server has responded to your request with record data that you entered above.

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.2 <<>> example.tld -t ANY @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61421
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;example.tld.                   IN      ANY

;; ANSWER SECTION:
example.tld.            14400   IN      SOA     ns1.example.tld. hostmaster.example.tld. 2015010100 43200 900 1814400 10800
example.tld.            14400   IN      NS      ns1.example.tld.
example.tld.            14400   IN      MX      10 mail.example.tld.
example.tld.            14400   IN      A       192.0.2.3

;; ADDITIONAL SECTION:
ns1.example.tld.        14400   IN      A       192.0.2.3

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: 
;; MSG SIZE  rcvd: 147

The second test we are going to do, is to check that your server is responding to recursive lookups from the localhost.  Execute the below command to begin the test:

dig google.com -t ANY @localhost

If the server is setup as expected, you should receive a similar recursive “;; ANSWER SECTION:” response.

;; ANSWER SECTION:
google.com.             86400   IN      SOA     ns1.google.com. dns-admin.google.com. 4294967295 7200 1800 1209600 300
google.com.             600     IN      MX      50 alt4.aspmx.l.google.com.
google.com.             600     IN      MX      40 alt3.aspmx.l.google.com.
google.com.             600     IN      MX      10 aspmx.l.google.com.
google.com.             600     IN      MX      20 alt1.aspmx.l.google.com.
google.com.             600     IN      MX      30 alt2.aspmx.l.google.com.
google.com.             3600    IN      TXT     "v=spf1 include:_spf.google.com ~all"
google.com.             86400   IN      TYPE257 \# 19 0005697373756573796D616E7465632E636F6D
google.com.             300     IN      AAAA    2607:f8b0:4008:804::200e
google.com.             300     IN      A       216.58.219.78
google.com.             172800  IN      NS      ns1.google.com.
google.com.             172800  IN      NS      ns3.google.com.
google.com.             172800  IN      NS      ns4.google.com.
google.com.             172800  IN      NS      ns2.google.com.

;; AUTHORITY SECTION:
google.com.             172800  IN      NS      ns4.google.com.
google.com.             172800  IN      NS      ns1.google.com.
google.com.             172800  IN      NS      ns3.google.com.
google.com.             172800  IN      NS      ns2.google.com.

;; ADDITIONAL SECTION:
ns2.google.com.         172800  IN      A       216.239.34.10
ns1.google.com.         172800  IN      A       216.239.32.10
ns4.google.com.         172800  IN      A       216.239.38.10
ns3.google.com.         172800  IN      A       216.239.36.10

The last test that we are going to do is to validate that your server is NOT open to a DNS Amplification attack.  The web site https://openresolver.com/ has a quick and easy tool available for testing for this vulnerability.

Upon testing with your Public IP Address, you should receive the following similar response:

open_recursive_dns_resolver_test

Congratulations!   You now have an authoritative DNS server configured and running.

CentOS Server

Related Articles

  • CentOS 6 ~ Percona MySQL XtraDB Multi-Master Clustering
  Copyright © 2020 | Datai.Net | All Rights Reserved