Creating an authoritative-only DNS system for your domain

Most registrars they provide a DNS service when you purchase a domain name. But having your own DNS servers means more control to you. And if you are an aspiring sysadmin, you will find it fun and educational. We will be using BIND 9 which is, by far the most popular DNS implementation.

Prerequisites

We will need two systems (VMs or containers) preferably on different geographic locations and different providers. One will be the master and the other system, the slave. This guide works for recent Debian or Ubuntu systems.

Some assumptions:

  • Master DNS:
    • Hostname: ns1.example.com
    • IP: 1.1.1.1
  • Slave DNS:
    • Hostname: ns2.example.com
    • IP: 2.2.2.2
  • Webserver:
    • Hostname: example.com (www.example.com is an alias)
    • IP: 3.3.3.3
  • Main mailserver:
    • Hostname: mx1.example.com ({mail,smtp,pop,imap,webmail}.example.com are aliases)
    • IP: 4.4.4.4
  • Backup mailserver:
    • Hostname: mx2.example.com
    • IP: 5.5.5.5

Preparations

Setup the /etc/hosts file

On master’s /etc/hosts:

1.1.1.1    ns1.example.com ns1

On slave’s /etc/hosts:

2.2.2.2    ns2.example.com ns2

Installing BIND

NOTE: all commands must be applied to both master and slave unless otherwise stated

apt-get -y install bind9 bind9utils

Allow port 53:

ufw allow 53

Configure the global options

Make the following changes in the /etc/bind/named.conf.options of both servers:

--- /etc/bind/named.conf.options        2016-12-12 14:44:57.163515708 -0500
+++ /etc/bind/named.conf.options.new    2016-12-12 14:52:29.749268250 -0500
@@ -1,5 +1,7 @@
 options {
        directory "/var/cache/bind";
+       recursion no;
+       allow-transfer { none; };

        // If there is a firewall between you and nameservers you want
        // to talk to, you may need to fix the firewall to allow multiple

Configure the local options

On master’s /etc/bind/named.conf.local:

--- /etc/bind/named.conf.local  2016-12-12 20:06:27.000000000 +0000
+++ /etc/bind/named.conf.local.new      2016-12-12 20:07:03.000000000 +0000
@@ -6,3 +6,8 @@
 // organization
 //include "/etc/bind/zones.rfc1918";

+zone "example.com" {
+    type master;
+    file "/etc/bind/db.example.com";
+    allow-transfer { 2.2.2.2; };
+};

On slave’s /etc/bind/named.conf.local:

--- /etc/bind/named.conf.local  2016-11-01 13:02:24.000000000 -0400
+++ /etc/bind/named.conf.local.new      2016-12-12 15:09:47.445235343 -0500
@@ -6,3 +6,8 @@
 // organization
 //include "/etc/bind/zones.rfc1918";

+zone "example.com" {
+    type slave;
+    file "db.example.com";
+    masters { 1.1.1.1; };
+};

Create the zone file

On master server create the zone file (/etc/bind/db.example.com):

$TTL 3600
@    IN    SOA    ns1.example.com.    root.example.com. (
                                            2016121201
                                            7200
                                            3600
                                            1209600
                                            180 )

; NS Records
@       300    IN      NS              ns1.example.com.
@       300    IN      NS              ns2.example.com.

; MX Records
@       300    IN      MX      10      mx1.example.com.
@       300    IN      MX      20      mx2.example.com.

; Address records
@       300    IN      A               3.3.3.3
ns1     300    IN      A               1.1.1.1
ns2     300    IN      A               2.2.2.2
mx1     300    IN      A               4.4.4.4
mx1     300    IN      A               5.5.5.5

; Alias (Canonical Name) records
www     300    IN      CNAME           example.com.
mail    300    IN      CNAME           mx1.example.com.
smtp    300    IN      CNAME           mx1.example.com.
imap    300    IN      CNAME           mx1.example.com.
pop     300    IN      CNAME           mx1.example.com.
webmail 300    IN      CNAME           mx1.example.com.

; TXT records
@       300    IN      TXT             "v=spf1 a mx ?all"

Verify the global configuration

Run the named-checkconf command on both servers. If you get any errors you should fix them before proceeding.

Verify the zone configuration

Run the following command on the master server:

named-checkzone theo-andreou.org /etc/bind/db.example.com 
zone example.com/IN: loaded serial 2016121201
OK

If you get ‘OK’ then your setup is correct, otherwise you should fix it before proceeding.

Restart bind and test your servers

systemctl restart bind9.service

Now test if your servers resolve your records.

The master:

dig smtp.example.com @1.1.1.1
...
;; ANSWER SECTION:
smtp.example.com.   300 IN  CNAME   mx1.example.com.
mx1.example.com.    300 IN  A   4.4.4.4
...

The slave:

dig smtp.example.com @2.2.2.2
...
;; ANSWER SECTION:
smtp.example.com.   300 IN  CNAME   mx1.example.com.
mx1.example.com.    300 IN  A   4.4.4.4
...

If you get any errors you can check your syslog file (/var/log/syslog).

Finalizing

After you have tested that everything is OK, it is time to tell your registrar about the new servers. This is called setting the glue records and you should consult the documentation of your registrar on how to do that. Ask support if you have any trouble.

References

Leave a Reply

Your email address will not be published. Required fields are marked *