Sunday, April 26, 2015

BIND DDNS

OK, So I have a requirement to host one of my domains internally. The reason for this is because I would like to be able to learn more about BIND9 as well as having flexibility to do Dynamic DNS.

I spawned a VM and install Ubuntu on it. During the installation, I selected DNS server as part of the feature to be installed.

Here are the steps I took to set it up:

Step #1 - Edit /etc/bind/named.conf.local

key "domain.com.au." {
        algorithm hmac-md5;
        secret "w81WcwhateverhereGnCQ==";
};

zone "domain.com.au" {
        type master;
        allow-update { key "domain.com.au."; };
        journal "/var/cache/bind/db.domain.com.au.jnl";
        file "/etc/bind/master/db.domain.com.au";

};

The key section is used for the automatic update using nsupdate tool which is part of BIND installation package. the secret value is generated by using the following:

dnssec-keygen -a HMAC-MD5 -b 128 -n HOST domain.com.au

This tool generates 2 files = .key and .private
open the .key file and copy the key, e.g. w81WcwhateverhereGnCQ==, and put it in the key section above. 

Note: That is NOT my KEY -

Then you need to save the .private file and keep is safe to be used later with nsupdate

The zone section is where my DNS zone is configured

Step #2 - Create Zone File

Create a master folder within /etc/bind
Copy /etc/bind/db.local to /etc/bind/master/db.domain.com.au
Change permission on the folder

chown -R bind:bind /etc/bind/master
chmod 775 -R /etc/bind/master

Step #3 - Edit /etc/bind/master/db.domain.com.au

Edit the file and adjust the content to suit your need
Restart the BIND process:

sudo /etc/init.d/bind9 restart

Have a look the syslog file to make sure everything is OK

tail -f /var/log/syslog

Step #4 - Create Dynamic DNS Script File

Create ddns.sh file with the following content:

#!/bin/bash
# This script fetches the current external IP Address, writes out an nsupdate file
# Then performs an nsupdate to our remote server of choice
# This script should be placed on a 10 minute crontab

WGET=$(which wget)
ECHO=$(which echo)
NSUPDATE=$(which nsupdate)
IP_FILE="/home/ddns/ip"

IP=$($WGET -q -O - checkip.dyndns.org|sed -e 's/.*Current IP Address: //' -e 's/<.*$//')

IS_UPDATE="no"

if [ -f $IP_FILE ]
then
        #Get file content
        IP_OLD=$(<$IP_FILE)
        $ECHO "File IP exists with the content: $IP_OLD"
        $ECHO "Old IP: $IP_OLD"

        if [ "$IP_OLD" == "$IP" ]
        then
                $ECHO "IP is not changing: $IP"
        else
                $ECHO "IP changes. OLD IP: $IP_OLD, NEW IP: $IP"
                $ECHO "$IP" > $IP_FILE
                IS_UPDATE="yes"
        fi
else
        $ECHO "File IP does not exist, creating one..."
        IS_UPDATE="yes"
        $ECHO "$IP" > $IP_FILE
fi

$ECHO "server bind.domain.com.au" > /tmp/nsupdate
$ECHO "debug yes" >> /tmp/nsupdate
$ECHO "zone domain.com.au." >> /tmp/nsupdate
$ECHO "update delete domain.com.au A" >> /tmp/nsupdate
$ECHO "update add domain.com.au 600 A $IP" >> /tmp/nsupdate
$ECHO "update delete www.domain.com.au A" >> /tmp/nsupdate
$ECHO "update add www.domain.com.au 600 A $IP" >> /tmp/nsupdate
$ECHO "send" >> /tmp/nsupdate

$ECHO "Is Update: $IS_UPDATE"

if [ "$IS_UPDATE" == "yes" ]
then
        $NSUPDATE -k /home/ddns/Kdomain.com.au.+157+05161.private -v /tmp/nsupdate 2>&1
        $ECHO "Updating..."
fi

The script does the following:
  • Get the Public IP address from checkip.dyndns.org
  • Check whether or not the IP has changed from the previous pooling. This is done by storing the IP to a file and compare it on the next query
  • If the IP has changed, run nsupdate
Notice the .private key is used here.

Then you can do cronjob to run ddns.sh regularly