Dynamic DNS on private DNS server (Router OS, Bind, Apache, and Shell script)

From MikroTik Wiki
Jump to: navigation, search

Original and updates here: [eurekamoment.eu] If you constantly connect to your home network (as I do), you have, on occasion, experienced that frustrating moment when the dynamic dns service is down for whatever reason. Let's assume that you are a person who likes to have more controll over the services you use, and have setup your private DNS server on a cheap VPS like [DigitalOcean]. If so, you're at the right place.

For this to work, we will need a smarter router that can fetch http data - Mikrotik in my case, and a private DNS server on the public network hosting your domain and under your control. If you can't access the shell, then you can't complete this tutorial.

Note that this isn't very secure and I will be modifying the process to get a secure solution

Setup

  1. Setup a web server on your DNS server
  2. Create a php update page
    <?php
      $ip=$_SERVER[REMOTE_ADDR];
      if ($_GET['hash']="ae2b1fca515949e5d54fb22b8ed95575") {
        file_put_contents("deviceupdate.log","DATE: ".date("Y-m-d H:i:s")." IP: ".$ip."\n",FILE_APPEND | LOCK_EX);
        file_put_contents("homeip.log",$ip,LOCK_EX);
        print "DATE: ".date("Y-m-d H:i:s")." IP: ".$ip;
      }
    ?>
  3. Setup Mikrotik schetuler that runs every few minutes
    /tool fetch keep-result=no mode=http url="http://www.my-dns-servers-web-server.com/mikrotik/deviceupdate.php?hash=ae2b1fca515949e5d54fb22b8ed95575"
  4. Create a shell script called dyndns.sh to update the DNS zone
    #!/bin/bash
    newip=$(cat /var/www/homeip.log)
    md5old=$(cat /var/www/homeip.md5)
    md5new=$(md5sum /var/www/homeip.log)
    
    #echo "$(date) RunTime" >> /var/log/dyndns.log
    if test "$md5old" = "$md5new"
    then
            echo "$(date) - No change" >> /var/log/dyndns.log
    else
            sed -i "s/^home.*/home IN A $newip/" /etc/bind/db.somedomain.com
            rndc reload somedomain.com
            md5sum /var/www/homeip.log > /var/www/homeip.md5
            echo "$(date) - Updated ip $newip" >> /var/log/dyndns.log
    fi
  5. Create a cron job to run every few minutes. Run crontab -e and type
    */5 * * * * /scripts/dyndns.sh<br>

How it works

  1. The router tries to access the specific web page on the web server that is located on the DNS server.
  2. Web server reads the IP from the router and if the hash is ok, it writes the IP into two files in the same folder
    1. One file for history purposes (with date and everything)
    2. One file with IP address only
  3. Cron runs a script that calculates the MD5 hash from the file containing only the IP address and compares it to the MD5 hash from before the change. If the two are different - it updates the zone file by replacing the one record and saves the new hash to a file for future comparison (so we don't update and reload the zone all the time
  4. Zone is reloaded and propagated.