# HG changeset patch # User Heiko Schlittermann (JUMPER) # Date 1419946845 -3600 # Node ID 2e27cfdf85ea5aa453f29756a66e022cfeed2552 # Parent ebada07bb7016319cbda7bae75e664da6c3480ae check for AA flag Make sure that we compare the authoritive answers with the outside worlds view. diff -r ebada07bb701 -r 2e27cfdf85ea Build.PL --- a/Build.PL Tue Dec 30 12:24:43 2014 +0100 +++ b/Build.PL Tue Dec 30 14:40:45 2014 +0100 @@ -13,7 +13,7 @@ license => 'perl', requires => { perl => '5.14.2', - 'Net::DNS' => '0.74', + 'Net::DNS' => '0.66', }, test_requires => { 'Test::Exception' => '0.32', diff -r ebada07bb701 -r 2e27cfdf85ea plugins/check_dns-serial --- a/plugins/check_dns-serial Tue Dec 30 12:24:43 2014 +0100 +++ b/plugins/check_dns-serial Tue Dec 30 14:40:45 2014 +0100 @@ -44,8 +44,8 @@ use Getopt::Long qw(GetOptionsFromArray); use Net::DNS; use Pod::Usage; +use Smart::Comments; -my %resolver; sub uniq { my %h; @h{@_} = (); return keys %h; } # return a list of the zones known to the local @@ -94,26 +94,30 @@ } # return a list of "official" nameservers -sub get_ns { - my ($nameserver) = map { /^\@(.*)/ } $_[0] =~ /^\@/ ? shift : '@8.8.8.8'; - my ($domain) = @_; +sub ns { + my $domain = shift; + ### assert: @_ % 2 == 0 + my %resflags = (nameservers => [qw/8.8.8.8/], @_); + my $aa = delete $resflags{aa}; + my $nameservers = $resflags{nameservers}; my @ns; - my $r = $resolver{$nameserver} //= - Net::DNS::Resolver->new(nameservers => [$nameserver]); - my $q = $r->query($domain, 'NS') or die $r->errorstring, "\@$nameserver\n"; + my $r = Net::DNS::Resolver->new(%resflags); + my $q = $r->query($domain, 'NS') or die $r->errorstring, "\@@$nameservers\n"; + + die "no aa @@$nameservers\n" if $aa and not $q->header->aa; push @ns, map { $_->nsdname } grep { $_->type eq 'NS' } $q->answer; return sort @ns; } -sub get_serial { - my ($nameserver) = map { /^\@(.*)/ } $_[0] =~ /^\@/ ? shift : '@8.8.8.8'; - my ($domain) = shift; +sub serial { + my $domain = shift; + my %resflags = (nameservers => [qw/8.8.8.8/], @_); + my $nameservers = $resflags{nameservers}; - my $r = $resolver{$nameserver} //= - Net::DNS::Resolver->new(nameservers => [$nameserver]); - my $q = $r->query($domain, 'SOA') or die $r->errorstring, "\@$nameserver\n"; + my $r = Net::DNS::Resolver->new(%resflags); + my $q = $r->query($domain, 'SOA') or die $r->errorstring, "\@@$nameservers\n"; return (map { $_->serial } grep { $_->type eq 'SOA' } $q->answer)[0]; } @@ -127,10 +131,10 @@ # CRITICAL - if the serial cannot be found at one of the sources sub ns_ok { - my ($reference, $domain) = @_; + my ($domain, $reference) = @_; - my @our = sort eval { get_ns($reference, $domain) }; - my @their = sort +get_ns($domain); + my @our = sort +ns($domain, nameservers => [$reference], aa => 1); + my @their = sort +ns($domain); { local $" = "\0"; @@ -148,8 +152,6 @@ GetOptionsFromArray( \@argv, -## Please see file perltidy.ERR -## Please see file perltidy.ERR 'reference=s' => \$opt_reference, 'progress!' => \$opt_progress, 'h|help' => sub { pod2usage(-verbose => 1, -exit => 0) }, @@ -168,7 +170,7 @@ my (@OK, %CRITICAL); foreach my $domain (@domains) { print STDERR "$domain " if $opt_progress; - eval { ns_ok('@212.80.235.130', $domain) }; + eval { ns_ok($domain, $opt_reference) }; if ($@) { $CRITICAL{$domain} = $@ } else { push @OK, $domain } say STDERR $@ ? 'not ok' : 'ok' if $opt_progress; diff -r ebada07bb701 -r 2e27cfdf85ea t/10-minimal.t --- a/t/10-minimal.t Tue Dec 30 12:24:43 2014 +0100 +++ b/t/10-minimal.t Tue Dec 30 14:40:45 2014 +0100 @@ -14,7 +14,10 @@ $tmp->flush; sub dig_serial { (split " ", `dig +short SOA @_`)[2] } -sub dig_ns { sort map { /(\S+?)\.?$/ } `dig +short NS @_` } + +sub dig_ns { + sort map { /(\S+?)\.?$/ } `dig +short NS @_`; +} # we require it, it's not a normal module require_ok 'blib/nagios/plugins/ius/check_dns-serial' @@ -31,23 +34,28 @@ for (qw(heise.de schlittermann.de google.com debian.org example.org)) { - subtest $_ => sub { + subtest $_ => sub { - # get_ns should return the NS from public dns servers - is_deeply [get_ns($_)], [dig_ns($_)] => "ns \@default"; - is_deeply [get_ns('@8.8.4.4', $_)], [dig_ns('@8.8.4.4', $_)] => "ns \@8.8.4.4"; - is get_serial('@8.8.8.8', $_), dig_serial('@8.8.8.8', $_) => 'serial'; - }; + throws_ok { ns($_, nameservers => [qw/8.8.8.8/], aa => 1) } + qr/no aa/ => 'not authoritive @8.8.8.8'; + is_deeply [ns($_)], [dig_ns($_)] => "ns \@default"; + is_deeply [ns($_, nameservers => [qw/8.8.4.4/])], + [dig_ns('@8.8.4.4', $_)] => "ns \@8.8.4.4"; + is serial($_, nameservers => [qw/8.8.8.8/]), + dig_serial('@8.8.8.8', $_) => 'serial'; + }; } # ns for some domain we're not the master for, should be refused -throws_ok { get_ns('@212.80.235.130', 'heise.de') } qr/^REFUSED/ => 'throws on refused query'; -throws_ok { get_ns('safasdfasdfrandomadsfefvddeas') } qr/^NXDOMAIN/ => 'throws on nx domain'; +throws_ok { ns('example.org', nameservers => [qw/f.nic.de a.nic.de b.nic.de/]) } +qr/^REFUSED/ => 'throws on refused query'; +throws_ok { ns('safasdfasdfrandomadsfefvddeas') } +qr/^NXDOMAIN/ => 'throws on nx domain'; -ok ns_ok('@212.80.235.130', 'schlittermann.de') => 'ns for schlittermann.de'; -throws_ok { ns_ok('@212.80.235.130', 'heise.de') } qr/differ/ => 'ns for heise.de'; - +ok ns_ok('schlittermann.de', '212.80.235.130') => 'ns_ok for schlittermann.de'; +throws_ok { ns_ok('heise.de', '212.80.235.130') } qr/no aa|differ|REFUSED/ => 'ns_ok for heise.de'; +throws_ok { ns_ok('heise.de', '8.8.8.8') } qr/no aa|differ|REFUSED/ => 'ns_ok for heise.de'; # serial