Add nsupdate(1) support

The 'nsupdate' protocol is used to submit Dynamic DNS Update requests as
defined in RFC2136 to a name server using the 'nsupdate' command line
utility part of ISC BIND.  Dynamic DNS updates allow resource records to
be added or removed from a zone configured for dynamic updates through
DNS requests protected using TSIG.  BIND ships with 'ddns-confgen', a
utility to generate sample configurations and instructions for both the
server and the client.  See nsupdate(1) and ddns-confgen(8) for details.
This commit is contained in:
Daniel Roethlisberger 2014-04-27 20:03:38 +02:00
parent 2e33e8efb3
commit de9fee6eec
2 changed files with 117 additions and 0 deletions

View file

@ -22,6 +22,7 @@ Dynamic DNS services currently supported include:
Freedns - See http://freedns.afraid.org/ for details Freedns - See http://freedns.afraid.org/ for details
ChangeIP - See http://www.changeip.com/ for details ChangeIP - See http://www.changeip.com/ for details
dtdns - See http://www.dtdns.com/ for details dtdns - See http://www.dtdns.com/ for details
nsupdate - See nsupdate(1) and ddns-confgen(8) for details
DDclient now supports many of cable/dsl broadband routers. DDclient now supports many of cable/dsl broadband routers.

116
ddclient
View file

@ -429,6 +429,10 @@ my %variables = (
'login' => setv(T_LOGIN, 0, 0, 0, 'unused', undef), 'login' => setv(T_LOGIN, 0, 0, 0, 'unused', undef),
'client' => setv(T_STRING, 0, 1, 1, $program, undef), 'client' => setv(T_STRING, 0, 1, 1, $program, undef),
}, },
'nsupdate-common-defaults' => {
'ttl' => setv(T_NUMBER, 0, 1, 0, 600, undef),
'zone' => setv(T_STRING, 1, 1, 1, '', undef),
},
); );
my %services = ( my %services = (
'dyndns1' => { 'dyndns1' => {
@ -573,6 +577,16 @@ my %services = (
$variables{'service-common-defaults'}, $variables{'service-common-defaults'},
), ),
}, },
'nsupdate' => {
'updateable' => undef,
'update' => \&nic_nsupdate_update,
'examples' => \&nic_nsupdate_examples,
'variables' => merge(
{ 'login' => setv(T_LOGIN, 1, 0, 1, '/usr/bin/nsupdate', undef), },
$variables{'nsupdate-common-defaults'},
$variables{'service-common-defaults'},
),
},
); );
$variables{'merged'} = merge($variables{'global-defaults'}, $variables{'merged'} = merge($variables{'global-defaults'},
$variables{'service-common-defaults'}, $variables{'service-common-defaults'},
@ -3765,6 +3779,108 @@ sub nic_dtdns_update {
} }
} }
######################################################################
## nic_nsupdate_examples
######################################################################
sub nic_nsupdate_examples {
return <<EoEXAMPLE;
o 'nsupdate'
The 'nsupdate' protocol is used to submit Dynamic DNS Update requests as
defined in RFC2136 to a name server using the 'nsupdate' command line
utility part of ISC BIND. Dynamic DNS updates allow resource records to
be added or removed from a zone configured for dynamic updates through
DNS requests protected using TSIG. BIND ships with 'ddns-confgen', a
utility to generate sample configurations and instructions for both the
server and the client. See nsupdate(1) and ddns-confgen(8) for details.
Configuration variables applicable to the 'nsupdate' protocol are:
protocol=nsupdate
server=ns1.example.com ## name or IP address of the DNS server to send
## the update requests to; usually master for
## zone, but slaves should forward the request
password=tsig.key ## path and name of the symmetric HMAC key file
## to use for TSIG signing of the request
## (as generated by 'ddns-confgen -q' and
## configured on server in 'grant' statement)
zone=dyn.example.com ## forward zone that is to be updated
ttl=600 ## time to live of the record;
## defaults to 600 seconds
login=/usr/bin/nsupdate ## path and name of nsupdate binary;
## defaults to '/usr/bin/nsupdate'
<hostname> ## fully qualified hostname to update
Example ${program}.conf file entries:
## single host update
protocol=nsupdate \\
server=ns1.example.com \\
password=/etc/${program}/dyn.example.com.key \\
zone=dyn.example.com \\
ttl=3600 \\
myhost.dyn.example.com
EoEXAMPLE
}
######################################################################
## nic_nsupdate_update
## by Daniel Roethlisberger <daniel@roe.ch>
######################################################################
sub nic_nsupdate_update {
debug("\nnic_nsupdate_update -------------------");
## group hosts with identical attributes together
my %groups = group_hosts_by([ @_ ], [ qw(login password server zone) ]);
## update each set of hosts that had similar configurations
foreach my $sig (keys %groups) {
my @hosts = @{$groups{$sig}};
my $hosts = join(',', @hosts);
my $h = $hosts[0];
my $binary = $config{$h}{'login'};
my $keyfile = $config{$h}{'password'};
my $server = $config{$h}{'server'};
my $zone = $config{$h}{'zone'};
my $ip = $config{$h}{'wantip'};
delete $config{$_}{'wantip'} foreach @hosts;
info("setting IP address to %s for %s", $ip, $hosts);
verbose("UPDATE:","updating %s", $hosts);
## send separate requests for each zone with all hosts in that zone
my $instructions = <<EoINSTR1;
server $server
zone $zone.
EoINSTR1
foreach (@hosts) {
$instructions .= <<EoINSTR2;
update delete $_.
update add $_. $config{$_}{'ttl'} A $ip
EoINSTR2
}
$instructions .= <<EoINSTR3;
send
EoINSTR3
my $command = "$binary -k $keyfile";
$command .= " -d" if (opt('debug'));
verbose("UPDATE:", "nsupdate command is: %s", $command);
verbose("UPDATE:", "nsupdate instructions are:\n%s", $instructions);
my $status = pipecmd($command, $instructions);
if ($status eq 1) {
foreach (@hosts) {
$config{$_}{'ip'} = $ip;
$config{$_}{'mtime'} = $now;
success("updating %s: %s: IP address set to %s", $_, $status, $ip);
}
} else {
foreach (@hosts) {
failed("updating %s", $_);
}
}
}
}
###################################################################### ######################################################################
# vim: ai ts=4 sw=4 tw=78 : # vim: ai ts=4 sw=4 tw=78 :