Dynamic DNS Using Mythic Beast's DNS API

Dynamic DNS allows a persistent domain name to point at a changing IP address on the Internet. This is extremely useful because most home internet packages give their users dynamic IP addresses. This means that you will get a different IP address each time you connect to your Internet Service Provider. This is fine for most users. However, what if you had a home server that you'd like to access away from home? Dynamic DNS can help you get to that server by allowing your home IP address to be resolved using a memorable DNS address.

You'll need a couple of things to follow this article:

This article is now out of date because Mythic Beasts have a simple way to do Dynamic DNS. See their write-up here.

Examples:

liam@onza:~$ curl --data "domain=liamfraser.co.uk&password=hunter2&command=REPLACE onza 300 AAAA DYNAMIC_IP" https://dnsapi6.mythic-beasts.com
REPLACE onza 300 AAAA 2a00:1098:0:86:1000::11

liam@onza:~$ curl --data "domain=liamfraser.co.uk&password=hunter2&command=REPLACE onza 300 A DYNAMIC_IP" https://dnsapi4.mythic-beasts.com
REPLACE onza 300 A 93.93.131.30

liam@onza:~$ curl --data "domain=liamfraser.co.uk&password=hunter2&command=REPLACE foo 300 A 127.0.0.1" https://dnsapi4.mythic-beasts.com
REPLACE foo 300 A 127.0.0.1

To start off, we need a script that will run from your website, and print out the client's IP address (i.e your home IP address). That script should have the following contents:

#!/usr/bin/perl

use CGI;

my $cgi = new CGI;
print $cgi->header();
print $cgi->remote_host();

To run that perl script, you'll need to make it executable with:

chmod +x
    

and have a .htaccess file that looks like:

Options +ExecCGI
AddHandler cgi-script .cgi .pl
    

The main bulk of the work is done by the script that will run on your server at home. You'll need to set an API Password using the Mythic Beasts Control Panel for the domain you would like to use for this script to work. The server side script looks like this:

#!/usr/bin/perl
# This program allows a domain managed by Mythic Beasts to be used as a Dynamic
# DNS address. Written by Liam Fraser - 2012.

use strict;
use warning;

use WWW::Mechanize;

# Configuration variables - replace as necessary
my $domain = 'liamfraser.co.uk';
my $password = '**********';
my $api_url = 'https://secure.mythic-beasts.com/control/fcgi/customer/primarydnsapi';
my $checkip_url = 'http://liamfraser.co.uk/liam/checkip.pl';
my $dynamic_hostname = 'dyndns';
# With this configuration, the Dynamic DNS address would be dyndns.liamfraser.co.uk

# Create an instance of WWW:Mechanize to use
my $mech = new WWW::Mechanize;

# We don't want to deal with a gzipped response
$mech->add_header( 'Accept-Encoding' => 'identity' );

# Get our IP address from the checkip url
$mech->get($checkip_url);
my $ip = $mech->content();

# Get a list of the zones for our domain
my $zone = $mech->post($api_url,
                       { domain => $domain, password => $password, command => 'LIST'});
my $zones = $zone->content();
# Split the zones into an array
my @zone_array = split('\n', $zones);

# Find the dynamic_hostname entry in the list of zones
my $dynamic_hostname_entry = undef;
foreach my $entry (@zone_array) {
    # Note, we add a space to dynamic hostname so that we have to match the full hostname
    # not just part of it. This works because the parameters are seperated by spaces.
    if (index($entry, ($dynamic_hostname . " ")) != -1) {
        $dynamic_hostname_entry = $entry;
    }
}

# If we didn't find an entry then just create one
if (!defined($dynamic_hostname_entry)) {
    $mech->post($api_url,
                { domain => $domain, password => $password,
                  command => ('ADD ' . $dynamic_hostname . ' 300 A ' . $ip)});
} else {
    # Now check if the dynamic_hostname_entry has an up to date IP address
    if (index($dynamic_hostname_entry, $ip) == -1) {
        # If not, then we need to delete the current entry and add a new one
        # We use substring to get rid of the blank space at the end of the entry
        $mech->post($api_url,
                    { domain => $domain, password => $password,
                      command => [('DELETE ' . substr($dynamic_hostname_entry, 0, -1)),
                                  ('ADD ' . $dynamic_hostname . ' 300 A ' . $ip)] });
    }
}

As you can probably tell from the code above, we're creating an A record with a time-to-live of 300 seconds (5 minutes). You can read more about the syntax of Mythic Beast's DNS API here.

To get this script to work, you need to mark it as executable and then add it to the crontab on your home server. You can edit your crontab using the command:

crontab -e
    

The crontab file takes entries in the form:

# MIN HOUR DOM MON DOW CMD
    

I advise adding the following line to your crontab:

*/5 * * * * /path/to/dynamic_dns.pl
    

which would run the script every 5 minutes.