Wednesday, May 16, 2012

Dynamic DNS update Python script, for use with a home gateway device

I use the free ZoneEdit service to keep a dynamic DNS entry up-to-date. I also now use a Netgear WNDR4000 wireless router to connect to the Internet through my cable modem.

I have authored a script that uses HTTP basic authentication to grab the IP address from my router, compare it to the last polled IP address, and update ZoneEdit with the new IP if it has changed. I have this script set to run every minute.

#!/usr/local/bin/python

import urllib2, re, tempfile, os

# User variables - change these to fit your router
debug=False

router_user=""
router_passwd=""
router_webpage="http://192.168.0.254/RST_st_dhcp.htm"

zoneedit_user=""
zoneedit_passwd=''
zoneedit_host=""

# Returns a string containing webpage contents
def fetch_webpage(location, username, password):
  passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
  passman.add_password(None, location, username, password)
  authhandler = urllib2.HTTPBasicAuthHandler(passman)
  opener = urllib2.build_opener(authhandler)
  urllib2.install_opener(opener)
  return urllib2.urlopen(location).read()


s=fetch_webpage(router_webpage, router_user, router_passwd)
pattern = re.compile("IP Address.*?([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})", re.DOTALL)
m = pattern.search(s)
newip = m.group(1)
if debug: print "Current IP Address: " + newip

filename = tempfile.gettempdir() + "/router_ip"
flags = "r+"
if not os.path.exists(filename):
  flags = "w+"
f = open(filename, flags)

oldip = f.read().strip()

if (cmp(oldip,newip) == 0):
  if debug: print "Old IP is the same (" + oldip + ")"

else:
  web_result = fetch_webpage('https://dynamic.zoneedit.com/auth/dynamic.html?host='+zoneedit_host, zoneedit_user, zoneedit_passwd)
  if debug: print web_result

  f.seek(0)
  f.write(newip)