#!/usr/bin/perl -w # tristan+dns@ethereal.net 7mar2003 # # goes through a list of domains to slave, verifies their legitimacy, outputs # bind8/9 config # # whipped this up in about an hour, don't blame me for bugs :) use strict; use Net::DNS; my $root = 'a.root-servers.net.'; my %domains = (); #my %iam = ( # 'ns1.electricrain.com' => 1, # 'ns2.electricrain.com' => 1, #); my %iam = ( 'ns1.ethereal.net' => 1, 'ns.yikes.net' => 1, 'spicy.datasoup.com' => 1, ); sub main { my $searcher = Net::DNS::Resolver->new(); my $resolver = Net::DNS::Resolver->new(); $resolver->recurse(0); $resolver->udp_timeout(1); $resolver->tcp_timeout(1); while (my $domain = <>) { chomp $domain; last if !$domain or $domain =~ /^\s*$/; if ($domain && $domain !~ /^#/) { warn "Working on domain: [$domain]\n"; runquery($resolver, $root, $domain); } } foreach my $domain (sort keys %domains) { next if $domains{$domain}{'bad'}; my $lame = 1; for my $ns (@{$domains{$domain}{'ns'}}) { next unless $lame; $resolver->nameservers($ns); my $query = $resolver->query($domain, 'SOA'); if (!$query or !$query->answer()) { $domains{$domain}{'bad'} = "couldn't get SOA - lame delegation to $ns"; next; } foreach my $rr ($query->answer()) { next unless $rr->type() eq 'SOA'; my $mname = $rr->mname(); if ($iam{$mname}) { $domains{$domain}{'bad'} = "SOA MNAME is me"; last; } $resolver->nameserver($mname); my @zone = $resolver->axfr($domain); if (scalar @zone < 1) { $domains{$domain}{'bad'} = "$mname refused AXFR"; next; } my $query = $searcher->search($mname); if (!$query or !$query->answer()) { # this shouldn't happen... $domains{$domain}{'bad'} = "can't look up $mname"; next; } foreach my $rr ($query->answer()) { next unless $rr->type() eq 'A'; my $addr = $rr->address(); print qq!zone "$domain" {\n\ttype slave;\n\tmasters { $addr; };\n };\n!; } } $lame = 0; } } foreach my $domain (sort keys %domains) { next unless $domains{$domain}{'bad'}; print "// $domain: $domains{$domain}{'bad'}\n"; } } sub runquery { my ($resolver,$ns,$domain) = @_; $resolver->nameservers($ns); print "Sending NS query to $ns\n"; my $packet = Net::DNS::Packet->new($domain, 'NS', 'IN'); my $query = $resolver->send($packet); unless ($query) { print "query against $ns failed: ", $resolver->errorstring(), "\n"; return 0; } if ($query->answer()) { print "Got answer..\n"; my $good = 0; my @nameservers = (); foreach my $rr ($query->answer()) { next unless $rr->type() eq 'NS'; my $name = lc $rr->nsdname(); print "\tname: [$name]\n"; if ($iam{$name}) { $good = 1; } else { push(@nameservers, $name); } } if ($good) { @{$domains{$domain}{'ns'}} = @nameservers; } else { $domains{$domain}{'bad'} = "exists, but I'm not a nameserver for it"; } return 1; } elsif ($query->authority()) { print "Got authority..\n"; my $results = 0; foreach my $rr ($query->authority()) { next unless $rr->type() eq 'NS'; $results++; last if runquery($resolver, $rr->nsdname(), $domain); } $domains{$domain}{'bad'} = "domain doesn't exist" unless $results; } } main() __END__