Skip to content
Find file
3b35d2b
executable file 151 lines (143 sloc) 4.59 KB
#!/usr/bin/python3.1
#
# Easy Python3 Dynamic DNS
# By Jed Smith <jed@jedsmith.org> 4/29/2009
# This code and associated documentation is released into the public domain.
#
# This script **REQUIRES** Python 3.0 or above. Python 2.6 may work.
# To see what version you are using, run this:
#
# python --version
#
# To use:
#
# 0. You'll probably have to edit the shebang above.
#
# 1. In the Linode DNS manager, edit your zone (must be master) and create
# an A record for your home computer. You can name it whatever you like;
# I call mine 'home'. Fill in 0.0.0.0 for the IP.
#
# 2. Save it.
#
# 3. Go back and edit the A record you just created. Make a note of the
# ResourceID in the URI of the page while editing the record.
#
# 4. Edit the four configuration options below, following the directions for
# each. As this is a quick hack, it assumes everything goes right.
#
# First, the resource ID that contains the 'home' record you created above. If
# the URI while editing that A record looks like this:
#
# linode.com/members/dns/resource_aud.cfm?DomainID=98765&ResourceID=123456
# ^
# You want 123456. The API key MUST have write access to this resource ID.
#
RESOURCE = "000000"
#
# Your Linode API key. You can generate this by going to your profile in the
# Linode manager. It should be fairly long.
#
KEY = "abcdefghijklmnopqrstuvwxyz"
#
# The URI of a Web service that returns your IP address as plaintext. You are
# welcome to leave this at the default value and use mine. If you want to run
# your own, the source code of that script is:
#
# <?php
# header("Content-type: text/plain");
# printf("%s", $_SERVER["REMOTE_ADDR"]);
#
GETIP = "http://hosted.jedsmith.org/ip.php"
#
# If for some reason the API URI changes, or you wish to send requests to a
# different URI for debugging reasons, edit this. {0} will be replaced with the
# API key set above, and & will be added automatically for parameters.
#
API = "https://api.linode.com/api/?api_key={0}&resultFormat=JSON"
#
# Comment or remove this line to indicate that you edited the options above.
#
exit("Did you edit the options? vi this file open.")
#
# That's it!
#
# Now run dyndns.py manually, or add it to cron, or whatever. You can even have
# multiple copies of the script doing different zones.
#
# For automated processing, this script will always print EXACTLY one line, and
# will also communicate via a return code. The return codes are:
#
# 0 - No need to update, A record matches my public IP
# 1 - Updated record
# 2 - Some kind of error or exception occurred
#
# The script will also output one line that starts with either OK or FAIL. If
# an update was necessary, OK will have extra information after it.
#
# If you want to see responses for troubleshooting, set this:
#
DEBUG = False
#####################
# STOP EDITING HERE #
try:
from json import load
from urllib.parse import urlencode
from urllib.request import urlretrieve
except Exception as excp:
exit("Couldn't import the standard library. Are you running Python 3?")
def execute(action, parameters):
# Execute a query and return a Python dictionary.
uri = "{0}&action={1}".format(API.format(KEY), action)
if parameters and len(parameters) > 0:
uri = "{0}&{1}".format(uri, urlencode(parameters))
if DEBUG:
print("-->", uri)
file, headers = urlretrieve(uri)
if DEBUG:
print("<--", file)
print(headers, end="")
print(open(file).read())
print()
json = load(open(file), encoding="utf-8")
if len(json["ERRORARRAY"]) > 0:
err = json["ERRORARRAY"][0]
raise Exception("Error {0}: {1}".format(int(err["ERRORCODE"]),
err["ERRORMESSAGE"]))
return load(open(file), encoding="utf-8")
def ip():
if DEBUG:
print("-->", GETIP)
file, headers = urlretrieve(GETIP)
if DEBUG:
print("<--", file)
print(headers, end="")
print(open(file).read())
print()
return open(file).read().strip()
def main():
try:
res = execute("domainResourceGet", {"ResourceID": RESOURCE})["DATA"]
if(len(res)) == 0:
raise Exception("No such resource?".format(RESOURCE))
public = ip()
if res["TARGET"] != public:
old = res["TARGET"]
request = {
"ResourceID": res["RESOURCEID"],
"DomainID": res["DOMAINID"],
"Name": res["NAME"],
"Type": res["TYPE"],
"Target": public,
"TTL_Sec": res["TTL_SEC"]
}
execute("domainResourceSave", request)
print("OK {0} -> {1}".format(old, public))
return 1
else:
print("OK")
return 0
except Exception as excp:
print("FAIL {0}: {1}".format(type(excp).__name__, excp))
return 2
if __name__ == "__main__":
exit(main())
Jump to Line
Something went wrong with that request. Please try again.