I run a DNS server (oooh, aaah) and I secondary a few (200+) domains for some friends of mine. One of them (whom I like, don’t take this the wrong way if you read it and think it’s you) notoriously will not tell me when he’s had new domains added, or when he’s no longer the domain holder of record for a domain.
Sometimes I can be a bit finicky, and I go on cleaning and data purification binges (behold the Information Inquisition! Our primary weapon is vi and perl…). On the most recent of these cleaning binges I realized I wanted to know two things, who claimed I was acting as authoritative for their domain, and who I though I was authoritative for, but was not listed.
A couple of moments thinking about DNS and you will quickly understand that the first of these two questions is ridiculously hard to answer by querying DNS. I’ll have to figure it out from the logs of my DNS server another day. However, the first of these turns out to be pretty quick to answer. Given a little perl hackery, and the willingness to visually scan the output, you can quickly find those hosts that you have listed in your zone files and for which you aren’t actually listed at the root servers as an authoritative server.
I discovered a couple things along the way, and built in appropriate code to solve the problems:
1) The different TLD’s have different root name servers. So I dynamically grab, from the local name server, what the root name servers are for each TLD. (TLD stands for top level domain, e.g. com org net ru to se)
2) The different TLD servers answer NS queries by putting the results of the query in different locations. com and net (run off of Verisigns root name servers) puts the results in the ANSWER section of the response, nice and logical. Everyone else seems to think that an NS query should have the answer stuffed into the AUTHORITY section of the answer. I didn’t go read the RFC to see if either of them was the right way, cause it doesn’t matter to me, I just needed to learn that I had to look in both sections to make sure I got the results of my query.
Yes, I realize that I could have spent another few minutes and actually had it look for my domain server name(s) in the NS records and if I didn’t find one then spew an appropriate message, but I’m good and fast at visual greps on relatively small (less than 5000 lines) of output so I didn’t bother. If you’d like to do that to this script and send me your suggestion, I’ll take it into consideration.
Without further ado, a little bit of perl that will show you who the listed authoritative servers are for a domain (cutting and pasting the script I discovered that this lovely little system replaces all the ” that are in the code with either a start ” or an end “, and you need to go through and replace them all in the code, just so you’re warned it won’t run right off the page):
#!perl
use strict; # cause I'm that sort of person
use Net::DNS; # cause that's what we're working with today
my %q;
while (<>) {
my $result;
my @servers;
/([0-9A-z\-]+)\.([A-z]+)/;
my $tld = $2;
my $second = $1;
print "\n$second.$tld\n";
if ( !$q{$tld} ) {
print "New TLD: ", $tld, "\n";
$q{$tld} = Net::DNS::Resolver->new;
$q{$tld}->recurse(0);
$result = $q{$tld}->send( $tld, "NS" );
@servers = ();
foreach my $rr ( $result->answer() ) {
print "\t Adding NS: ", $rr->nsdname, "\n";
@servers = ( @servers, $rr->nsdname );
}
$q{$tld}->nameservers(@servers);
# $q{$tld}->debug(1);
print "\n";
}
# do the query for the domain
my $result = $q{$tld}->send( "$second.$tld", "NS" );
print " answer from: ", $result->answerfrom, "\n";
foreach my $rr ( $result->answer() ) {
print "\t", $rr->string, "\n";
}
foreach my $rr ( $result->authority() ) {
print "\t", $rr->string, "\n";
}
}