View Single Post
  #1   (View Single Post)  
Old 20th February 2013
Posts: n/a
Default How to achieve dynamic DNS with and the shell

Per J65kno's suggestion, I am creating this thread as an expansion of the thread I created here.

Since doesn't support dynamic DNS, the equivalent has to be accomplished via their XML-RPC API. In addition to the shell script I wrote, there is a Python equivalent, whose functionality I can not attest to. While parsing XML in the shell isn't the most fun thing in the world, I wrote this script both because I'm a masochist and because I wanted an option that didn't require any extra software on my OpenBSD firewall.

If you have a BSD machine that is directly connected to the internet, you can use the -i flag to pass the script your external network interface and it will determine your IP address based on that. Otherwise, OpenDNS is used. Here is the complete usage information:

gad [-f] [-t] [-v] [-i EXT_IF] -a APIKEY -d EXAMPLE.COM -r "RECORD-NAMES"

-f: Force an update regardless of IP address discrepancy
-t: Only create the new version file; don't activate it
-v: Print information to stdout even if a new zonefile isn't needed
-i: Use ifconfig instead of OpenDNS to determine external IP address

EXT_IF: The name of your external network interface
APIKEY: Your API key provided by Gandi
EXAMPLE.COM: The domain name whose active zonefile will be updated
RECORD-NAMES: A space-separated list of the names of the A records to update or create
Here is an example of a crontab entry that will compare the IP address of interface re0 with the IP address of the @ record in the active zonefile for domain

0 * * * * /home/brian/bin/gad -i re0 -a asdf1234 -d -r "@"
asdf1234 is obviously not my actual API key. If you have a Gandi account you can request your own API key here.

With some minimal tweaking (changing User-Agent, Host, and the openssl command) of the rpc() function in the script, it could be modified to talk to any XML-RPC API. The syntax of the rpc() function is:

rpc "methodName" "datatype" "value" "struct" "name" "datatype" "value"
Thanks to a bunch of nested while loops, you can pass an arbitrary number of datatype/value pairs and structs with their member name/datatype/value tuples. Valid method names for Gandi's API are in their documentation.

Some fun things I learned writing this script: how to parse command line flags/options with the shell, how to use the openssl s_client command as an SSL client, and how to construct XML RPCs. Here are some helpful sites that I used:

Good Shell Coding Practices: Handling Command Line Arguments
XML-RPC Wikipedia page
S_CLIENT section of the openssl man page

The most recent version of the script attached to this post can be found on Google Code.
Attached Files
File Type: sh (5.5 KB, 283 views)
Reply With Quote