# kaashif's blog

Programming, software freedom and Unix

## Updating DNS records

### 2014-01-22

Assuming that getting a static IP is impossible, there is only one solution: dynamic DNS. While it is possible to transfer your records to someone other than your domain registrar to manage DNS records, I just keep all things related to my domain with Namecheap, which is where my domain was registered.

## Choosing a client

Several websites, DynDNS and NoIP being examples, offer their own clients. You can install these, put your site-specific username and password into a config file, and let your DNS be handled automatically. Usually, these programs can do a lot more than update your DNS, and are needlessly complicated if that's all you want to do. The same goes for most multi-service dynamic DNS clients, for example, ddclient.

Most services provide a URL with which you can update your A records. Fetch this URL, and the A records on your domain will be changed to match the IP you fetched the URL with. It's a very simple system, and can be automated within minutes, with a simple script. Because I like to keep my servers bare, and avoid installing anything bulky (like Python, Ruby, and the like), I'm going to ues Perl, which is in the base system of every good *BSD, and comes installed by default on most GNU/Linux distros.

## Writing the client

There is some Perl boilerplate we have to get out of the way - the shebang and some "use" statements.

#!/usr/bin/env perl
use strict;
use warnings;


It's worth commenting on my use of "env". On FreeBSD (the OS my servers use), Perl is located at /usr/local/bin/perl, while on most GNU/Linux systems, it's at /usr/bin/perl. Using "env" avoids the issue of finding the Perl binary, and is more cross-platform.

Next, we have to find the URL, password, hosts, and domain we will use. Namecheap uses the word "host" to mean the subdomain, e.g. the "www" part of "www.fsf.com". For this example, let's just say we want "ftp", "www" and "@", "@" being no subdomain, e.g. "mydomain.com".

my $password = "blahblahblah"; my$domain = "mydomain.com";
my @hosts = ("ftp", "www", "@");
my $update_url = "http://dynamicdns.com/update?domain=$domain&password=$password&host=";  Notice we didn't attempt to put the hosts into the initial definition of the update URL. We will do that when we loop over the array and fetch the URL using cURL, thus updating the domain. foreach(@hosts) { my$final_url = "$update_url$_";
my $output = curl -s "$final_url";


So far, we have fetched the URL, so the IP of the host's A record should be updated at this point. We still need to check for errors and such, so let's do that next.

   if ($output =~ /<ErrCount>0/) { print("Update of$_.$domain succeeded."); } else { print("Update of$_.\$domain failed!");
}
}


It's possible to use XML::Simple and actually parse the XML output by the server handling DNS updates, but that would be overkill and waste everyone's time. So I just regex the output for errors, it works fine, and the problem is generally obvious if it fails, which is why I didn't print the output. It's perfectly possible to add some verbosity and do all of this "correct" stuff, but no-one, not even you, will ever care (unless you just do it for practice).

So save this script in /usr/local/bin/dnsup, or somewhere else appropriate and memorable.

*/10 * * * * nobody /usr/local/bin/dnsup