Updated on | #dns, #crontab, #cronjob | 0 User comments

Dynamic DNS service for your homeserver by using Domaisy

If you’re hosting your Web site or running a mail server on a private server behind a Cable or a DSL modem, every time you connect to your Internet Service Provider (ISP), your computer is getting a different IP address. In my case, I'm using UnityMedia in Germany as an ISP and I want to forward my domain to this IP. Therefore, I'm using the Dynamic DNS Service updates from my domain provider Domaisy. If you call a special Domaisy URL, the domainsy nameservers is refreshing the domain with the new IP address.

This tutorial shows, how you can update (every 5 minutes) the IP-Address from your ISP with your domain by using an cronjob. At first it would be the best to create a log file called update_dns.log. After this, you can create the script file as well as the cronjob.

Create the Log-File

So, let's start with the log file and with the log file's permission for the python script.

  1. sudo touch /var/log/update_dns.log
  2. sudo chmod 666 /var/log/update_dns.log

Dynamic DNS Script

Please insert the code into /usr/bin/update_dns.

  1. sudo nano /usr/bin/update_dns

Don't forget to change {YOUR_USERNAME}, {YOUR_PASSWORD} and {YOUR_HOSTNAME}.

  1. #!/usr/bin/python
  2. __author__ = "Thomas Ludwig"
  3. __copyright__ = "Copyright (C) 2013 Thomas Ludwig"
  4. __license__ = "GNU GPL 3"
  5. __version__ = "1.0"
  6.  
  7. import urllib2
  8. import json
  9. import logging
  10. import sys
  11.  
  12. # Insert your configuration
  13. username="{YOUR_USERNAME}";
  14. password="{YOUR_PASSWORD}";
  15. hostname="{YOUR_HOSTNAME}";
  16. loglevel="INFO";                # DEBUG, INFO or WARN
  17. logfile="/var/log/update_dns.log";
  18.  
  19. # If you have an AVM fritzbox, you don't need an external ip provider
  20. provider="external"; # two options: external or avm (>= FRITZ!OS 06.05)
  21. fritzhost="fritz.box"; # default: fritz.box
  22.  
  23. # Get external IP
  24. def getExternalIp():
  25.         url='http://jsonip.com';
  26.         try:
  27.                 httpResponse = urllib2.urlopen(urllib2.Request(url)).read()
  28.                 jsonData = json.loads(httpResponse)
  29.                 return jsonData['ip'];
  30.         except:
  31.                 logger = logging.getLogger()
  32.                 logger.error('Error trying to fetch external IP from %s' % (url))
  33.                 sys.exit(1)
  34.  
  35. # Get IP from AVM fritzbox, which receives the IP from cable provider e.g. Unitymedia
  36. def getAvmIp():
  37.         from SOAPpy import SOAPProxy
  38.         try:
  39.                 return SOAPProxy(proxy='http://' + fritzhost + ':49000/igdupnp/control/WANIPConn1',
  40.                                 namespace='urn:schemas-upnp-org:service:WANIPConnection:1',
  41.                                 soapaction='urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress',
  42.                                 noroot=True).GetExternalIPAddress()
  43.         except:
  44.                 logger = logging.getLogger()
  45.                 logger.error('Error trying to fetch AVM fritzbox IP from %s' % (fritzhost))
  46.                 sys.exit(1)
  47.  
  48. # Convert answer string to json
  49. def getDomainsyJson( resp ):
  50.         mapping = { 'update':'"update"', 'False':'false', 'True':'true'};
  51.         for k, v in mapping.iteritems():
  52.                 resp = resp.replace(k, v);
  53.         return ( "{%s}" % ( resp ) );
  54.  
  55. # Get Status from Domainsy.de
  56. def getDomainsyStatus( url ):
  57.         try:
  58.                 httpResponse = urllib2.urlopen( url ).read();
  59.                 jsonData = json.loads( getDomainsyJson( httpResponse ) )
  60.                 return jsonData['update'];
  61.         except:
  62.                 logger = logging.getLogger()
  63.                 logger.error('Error trying to fetch external IP from %s' % (url));
  64.                 sys.exit(1)
  65.  
  66. # Create a log file
  67. def prepareLog( logfile ):
  68.         return logging.basicConfig(     filename=logfile,
  69.                                         filemode = "a",
  70.                                         format='%(asctime)s %(levelname)s %(message)s',
  71.                                         level = loglevel)
  72.  
  73. # Main
  74. def main():
  75.  
  76.         # Prepare logging
  77.         prepareLog( logfile );
  78.  
  79.         # Create URL
  80.         url = "https://my.domaisy.de/dns7/service/update/?username={0}&password={1}&hostname={2}".format( username, password, hostname );
  81.  
  82.         # Get Logger, IP Status (true or false)
  83.         logger = logging.getLogger()
  84.         status = getDomainsyStatus( url );
  85.  
  86.         # Get IP
  87.         if provider == "external":
  88.                 myip = getExternalIp();
  89.         else:
  90.                 myip = getAvmIp();
  91.  
  92.         # Check if the status == true
  93.         if status:
  94.                 logger.info('New IP: %s' % ( myip ) );
  95.         else:
  96.                 if loglevel == "DEBUG":
  97.                         logger.debug('Status: Using old IP %s' % ( myip ));
  98.  
  99.  
  100.         logging.shutdown();
  101.  
  102.  
  103. if __name__ == "__main__":
  104.         main()

After you inserted successfully the python script inside the file, you have to give the file the right write permissions:

  1. sudo chmod +x /usr/bin/update_dns

Create a crontab

Open root's crontab

  1. sudo crontab -e

and insert the dynamic DNS script:

  1. */5 * * * * /usr/bin/update_dns 2>&1

This script will be started every 5 minutes. Now, you have to restart the cronjob:

  1. sudo /etc/init.d/cron restart

Well, what do you think?

Comments powered by LudwigDisqus for ModX