I wanted to transfer DNS zones with Perl using a TSIG key, but found no howto. Thus, this describes how to setup dynamic DNS zones with BIND, update them via nsupdate, and transfer them with Perl and Net::DNS.
$TTL 86400 @ SOA ns1.test.invalid. hostmaster.test.invalid. 2022082501 16384s 2048s 1048576s 2560s @ NS ns1.test.invalid.If you run the test.invalid domain as well, then add a NS glue record to that zone:
... dyn NS ns1 ...
# dd if=/dev/random bs=1 count=64 | openssl base64 -e -A rLY9................................................................................KQ==
key "dyn.test.invalid" {
algorithm hmac-sha512;
secret "rLY9................................................................................KQ==";
};
zone "dyn.test.invalid" {
type master;
file "/usr/local/etc/namedb/dynamic/dyn.test.invalid";
allow-transfer {
key "dyn.test.invalid";
};
update-policy {
grant "dyn.test.invalid" zonesub;
};
};
This allows anyone, who knows the secret key, to transfer and to update the dyn.test.invalid zone.
# tsig-keygen -a hmac-sha512 dyn.test.invalid
key "dyn.test.invalid" {
algorithm hmac-sha512;
secret "rLY9................................................................................KQ==";
};
# cat > dyn.test.invalid.key
key "dyn.test.invalid" {
algorithm hmac-sha512;
secret "rLY9................................................................................KQ==";
};
^D
You might have piped the output of tsig-keygen to tee:
# tsig-keygen -a hmac-sha512 dyn.test.invalid | tee dyn.test.invalid.key
# rndc reload
# dig @ns1.test.invalid dyn.test.invalid NS +short ns1.test.invalid. # dig @ns1.test.invalid dyn.test.invalid SOA +short ns1.test.invalid. hostmaster.test.invalid. 2022082501 16384 2048 1048576 2560
# dig @ns1.test.invalid dyn.test.invalid AXFR +short ; Transfer failed.
# dig -k dyn.test.invalid.key @ns1.test.invalid dyn.test.invalid AXFR ; <<>> DiG 9.16.32 <<>> -k dyn.test.invalid.key @ns1.test.invalid dyn.test.invalid AXFR ; (1 server found) ;; global options: +cmd dyn.test.invalid. 86400 IN SOA ns1.test.invalid. hostmaster.test.invalid. 2022082501 16384 2048 1048576 2560 dyn.test.invalid. 86400 IN NS ns1.test.invalid. dyn.test.invalid. 86400 IN SOA ns1.test.invalid. hostmaster.test.invalid. 2022082501 16384 2048 1048576 2560 dyn.test.invalid. 0 ANY TSIG hmac-sha512 ... NOERROR 0 ;; ....
# nsupdate -k dyn.test.invalid.key > server ns1.test.invalid > update add dyn.test.invalid 23 TXT "hello, world" > send > quit
# dig @ns1.test.invalid dyn.test.invalid SOA +short ns1.test.invalid. hostmaster.test.invalid. 2022082502 16384 2048 1048576 2560And check the newly added TXT record as well:
# dig @ns1.test.invalid dyn.test.invalid TXT +short "hello, world"
#!/usr/bin/perl -w
use strict;
use warnings;
use Net::DNS;
my $resolver = Net::DNS::Resolver->new(
nameservers => [ "ns1.test.invalid", ],
);
my $tsig = Net::DNS::RR->new(
owner => "dyn.test.invalid",
type => "TSIG",
algorithm => "hmac-sha512",
key => "rLY9................................................................................KQ==",
);
$resolver->tsig($tsig);
my @records = $resolver->axfr("dyn.test.invalid");
foreach my $rr(@records) {
$rr->print;
}
# chmod 0755 tsig.pl # ./tsig.pl dyn.test.invalid. 86400 IN SOA ( ns1.test.invalid. hostmaster.test.invalid. 2022082502 ;serial 16384 ;refresh 2048 ;retry 1048576 ;expire 2560 ;minimum ) dyn.test.invalid. 23 IN TXT "hello, world" dyn.test.invalid. 86400 IN NS ns1.test.invalid.
# ./tsig.pl