Dynamic DNS Updates via TSIG

DynDNS provides an account level key which can be used to update DNS hosts instead of our HTTP-based DNS Update API. You can generate and obtain your key from your TSIG account settings page. Your account must be a paid account to use this mechanism.

TSIG updates are a mechanism to transport zone updates over a secured mechanism. This feature is available for paid accounts (Account Upgrades and Custom DNS) and can be used with nsupdate or with dhcpd. For more information on this mechanism, please see RFC 2845 and the Wikipedia page for TSIG.

TTL values are only respected for Custom DNS hosts.

Using nsupdate for DDNS TSIG Updates

To update a DNS Server dynamically using TSIG for authorization, run nsupdate by doing the following:

 $ nsupdate -d
 > server update.dyndns.com
 > zone $ZONE
 > key $KEY_NAME $KEY_HMAC
 > update add $HOST.$ZONE 60 A 10.0.0.1
 > send 
 > quit

For dynamic DNS hosts, $ZONE should be the third level DNS name like myhost.dyndns.org

Using Perl for TSIG Updates

You can also use this sample Perl script using Net::DNS as an example for your applications to perform updates.

#!/usr/bin/perl

use warnings;
use strict;

use MIME::Base64;
use Net::DNS;
use Net::DNS::Update;
use Net::DNS::Resolver;

# Your account info
my $key_name = "";
my $key_hmac = "";
my $host     = "";

# DynDNS server information
my $tsig_server = 'update.dyndns.com';
my $tsig_server_pt = '53';

# Create update packet, only updates are permitted
my $update = Net::DNS::Update->new($host);
$update->push("update", rr_add("$host A 1.2.3.4"));


### End Configuration ###
$update->sign_tsig($key_name, $key_hmac);

my $res = Net::DNS::Resolver->new(
	port => $tsig_server_pt, 
	nameservers => [ $tsig_server ],
	debug => 0,
);

my $pack = Net::DNS::Packet->new(\($update->data));

my $mac = $pack->{additional}[-1]->mac;
my $mac_size = $pack->{additional}[-1]->mac_size;

my $time = $pack->{additional}[-1]->time_signed;
my $reply = $res->send($update);

if ($reply) {
	if ($reply->header->rcode eq 'NOERROR') {
		print "Update succeeded, verifying source.\n";

		my $tsigRR = $reply->{additional}[0];
		delete $reply->{additional};

		$reply->sign_tsig($key_name, $key_hmac);

		# Net::DNS::RR::TSIG should be handling this for us...
		my $size = unpack("H*", pack('n', $mac_size));

		$reply->{additional}[-1]->{request_mac} = $size . $mac;
		$reply->{additional}[-1]->{time_signed} = $time;

		my $packet = Net::DNS::Packet->new(\($reply->data));

		if ($packet->{additional}[-1]->{mac} eq $tsigRR->{mac}) {
			print "Verified!\n";
		} else {
			print "Failed! Potential man in the middle attack!\n";
		}
	} else {
		print 'Update failed: ', $reply->header->rcode, $reply->{additional}[-1]->{error}, "\n";
	}
} else {
	print 'Update failed: ', $res->errorstring, "\n";
}