Filename: dyndns.py
Size: 7704 bytes
Lines: 176
Creation time: 1267738157 (2010-03-04)
Description: This is a dyndns.org update client, it's used on some of my servers which are on domestic lines to try and keep things running. It should be ran via cron once every 10-15minutes and *should* work properly.
Download
#!/usr/bin/python
import socket, sys, re, base64, httplib

system = "dyndns" #dyndns|statdns|custom
hosts = "test.dyndns.org,test.ath.cx,test.mine.nu"
wildcard = "NOCHG" #ON|OFF|NOCHG
mx = "NOCHG" #mailexchanger|NOCHG
backmx = "NOCHG" #YES|NO|NOCHG
offline = "NO" #YES|NO
user = "test"
passwd = "test"
ip = ""




i = 1
while i < len(sys.argv):
	if sys.argv[i] == "--system" or sys.argv[i] == "-s":
		i = i + 1
		system = sys.argv[i]
	elif sys.argv[i] == "--hosts" or sys.argv[i] == "-h":
		i = i + 1
		hosts = sys.argv[i]
	elif sys.argv[i] == "--wildcard" or sys.argv[i] == "-w":
		i = i + 1
		wildcard = sys.argv[i]
	elif sys.argv[i] == "--mx" or sys.argv[i] == "-m":
		mx = "mailexchanger"
	elif sys.argv[i] == "--backmx" or sys.argv[i] == "-b":
		i = i + 1
		backmx = sys.argv[i]
	elif sys.argv[i] == "--offline" or sys.argv[i] == "-o":
		offline = "YES"
	elif sys.argv[i] == "--user" or sys.argv[i] == "-u":
		i = i + 1
		user = sys.argv[i]
	elif sys.argv[i] == "--passwd" or sys.argv[i] == "-p":
		i = i + 1
		passwd = sys.argv[i]
	elif sys.argv[i] == "--ip" or sys.argv[i] == "-i":
		i = i + 1
		ip = "&myip=" + sys.argv[i]
	else:
		#something unknown
		print "unknown arguement: " + sys.argv[i]
		print "usage: " + sys.argv[0] + " [OPTION]..."
		print
		print "\t" + "-s, --system        The system you wish to use for"
		print "\t" + "                      this update. DynDNS will update"
		print "\t" + "                      a Dynamic DNS  hostname, custom"
		print "\t" + "                      will update a. Custom DNS"
		print "\t" + "                      hostname, while statdns will"
		print "\t" + "                      update a  Static DNS hostname."
		print "\t" + "                      If the system parameter given is"
		print "\t" + "                      not dyndns, custom or statdns the"
		print "\t" + "                      update will fail. If the system"
		print "\t" + "                      parameter is not specified at all,"
		print "\t" + "                      it will default to dyndns."
		print "\t" + "-h, --hosts         These are the comma delimited hostnames"
		print "\t" + "                      you wish to update."
		print "\t" + "-w, --wildcard      Enable/disable wildcards for this host"
		print "\t" + "                      (ON to enable). If omitted, will"
		print "\t" + "                      default to NOCHG"
		print "\t" + "-m, --mx            Specifies a Mail eXchanger for use with"
		print "\t" + "                      the hostname being modified."
		print "\t" + "                      The specified MX must resolve to an"
		print "\t" + "                      IP address, or it will be ignored."
		print "\t" + "                      Note: Providing no MX setting (or an"
		print "\t" + "                      MX that doesn't resolve properly to"
		print "\t" + "                      an A record) will cause the hostname's"
		print "\t" + "                      MX record(s) to be removed. Specifying"
		print "\t" + "                      an MX of \"NOCHG\" will cause the"
		print "\t" + "                      existing MX setting to be preserved"
		print "\t" + "                      in whatever state it was previously"
		print "\t" + "                      updated via a client or the DynDNS"
		print "\t" + "                      website."
		print "\t" + "-b, --backmx        Request that the MX in the previous"
		print "\t" + "                      parameter be set up as a backup MX"
		print "\t" + "                      by listing the host itself as an MX"
		print "\t" + "                      with a lower preference value. A"
		print "\t" + "                      value of \"NOCHG\" will result in the"
		print "\t" + "                      previous value of the setting being"
		print "\t" + "                      preserved. Ifo mitted, defaults to"
		print "\t" + "                      \"NOCHG\"."
		print "\t" + "-o, --offline       Sets the hostname to offline mode."
		print "\t" + "                      This feature is only available to"
		print "\t" + "                      credited users."
		print "\t" + "-u, --user          The username of your dyndns account"
		print "\t" + "-p, --passwd        The password for your account. A little"
		print "\t" + "                      note to careless unix users, this will"
		print "\t" + "                      show in ~/.bash_history so its better"
		print "\t" + "                      just to configure this script"
		print "\t" + "-i, --ip            The IP to set the hosts to. If omitted"
		print "\t" + "                      will attempt to guess the current"
		sys.exit(1)
	i = i + 1

def getip():
	checkip = httplib.HTTPConnection('checkip.dyndns.org', 80);
	checkip.putrequest("GET", "/")
	checkip.endheaders()
	dataresponce = checkip.getresponse()
	if dataresponce:
		data = dataresponce.read()
	else:
		data = ""
		print "Error, no responce"
		return None
	stuff = re.findall("<html><head><title>Current IP Check</title></head><body>Current IP Address: ([0-9\.]+)</body></html>", data)
	if stuff:
		return stuff[0]
	return None
def ipchanged(host):
	return not (getip() == socket.gethostbyname(host))


dyndns = httplib.HTTPConnection('members.dyndns.org', 80);
updatehosts = ""
subjecthosts = re.split(",", hosts)
for host in subjecthosts:
	if ipchanged(host):
		updatehosts = updatehosts + host + ","


if updatehosts == "":
	print "No hosts to update"
	sys.exit(1)
updatehosts = updatehosts[:-1]

dyndns.putrequest("GET", "/nic/update?system=" + system + "&hostname=" + updatehosts +
			ip + "&wildcard=" + wildcard + "&mx=" + mx + "&backmx=" +
			backmx + "&offline=" + offline)
encoding = base64.encodestring(user + ":" + passwd)
dyndns.putheader("Authorization", "Basic " + encoding[:-1])
dyndns.putheader("User-Agent", "nulldyndns/1.0")
dyndns.endheaders()
dataresponce = dyndns.getresponse()
if dataresponce:
	data = dataresponce.read()
else:
	data = ""
	print "Error, no responce"

good = 0
nochg = 0
i = 0
host = re.split(",", hosts)
codes = re.split("[\n\r]", data)
for code in codes:
	line = re.split("\s", code)
	if line[0] == "badsys" or data == "badagent":
		print data + " was returned. contact the coders"
	elif line[0] == "badauth":
		print "Incorrect password or username"
	elif line[0] == "!donator":
		print "This action is only available to credited users. You are not a credited user"
	elif line[0] == "good":
		good = good + 1
		print host[i] + " updated to " + line[1] + " successfully"
	elif line[0] == "nochg":
		nochg = nochg + 1
		print host[i] + " unchanged"
	elif line[0] == "notfqdn":
		print "The hostname " + host[i] + " is not a fully-qualified domain name (not in the form hostname.dyndns.org or domain.com)."
	elif line[0] == "nohost":
		print "The hostname " + host[i] + " does not exist (or is not in the service specified in the system parameter)"
	elif line[0] == "!yours":
		print host[i] + " doesn't belong to you"
	elif line[0] == "abuse":
		print host[i] + " has been blocked for \"abuse\""
	elif line[0] == "numhost":
		print "Too many or too few hosts found"
	elif line[0] == "dnserr":
		print "DNS error encountered"
	elif line[0] == "911":
		print "Serious server side failure. Please refrain from updating until http://www.dyndns.com/news/status/ informs you of the situation"
	else:
		print "I haven't a fucking clue whats gone wrong here man, contact the coders"
 		print "Data:"
		print data
	i = i + 1
print

if good:
	print str(good) + " host(s) were updated"
if nochg:
	print str(nochg) + " host(s) were not changed because they are already pointing at the ip. Warning: Seeing this error and continuing to attempt to update it with the same IP will lead to your account being blocked for abuse"