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=="; }; ^DYou 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