Sunday, April 26, 2015


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 "" {
        algorithm hmac-md5;
        secret "w81WcwhateverhereGnCQ==";

zone "" {
        type master;
        allow-update { key ""; };
        journal "/var/cache/bind/";
        file "/etc/bind/master/";


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

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/
Change permission on the folder

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

Step #3 - Edit /etc/bind/master/

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 file with the following content:

# 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=$($WGET -q -O -|sed -e 's/.*Current IP Address: //' -e 's/<.*$//')


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

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

$ECHO "server" > /tmp/nsupdate
$ECHO "debug yes" >> /tmp/nsupdate
$ECHO "zone" >> /tmp/nsupdate
$ECHO "update delete A" >> /tmp/nsupdate
$ECHO "update add 600 A $IP" >> /tmp/nsupdate
$ECHO "update delete A" >> /tmp/nsupdate
$ECHO "update add 600 A $IP" >> /tmp/nsupdate
$ECHO "send" >> /tmp/nsupdate

$ECHO "Is Update: $IS_UPDATE"

if [ "$IS_UPDATE" == "yes" ]
        $NSUPDATE -k /home/ddns/ -v /tmp/nsupdate 2>&1
        $ECHO "Updating..."

The script does the following:
  • Get the Public IP address from
  • 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 regularly

No comments: