Commit initial: récupération et tri rapide
This commit is contained in:
commit
a52829f96c
104 changed files with 11892 additions and 0 deletions
313
nagios/check_zone_rrsig_expiration
Executable file
313
nagios/check_zone_rrsig_expiration
Executable file
|
@ -0,0 +1,313 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# $Id: check_zone_rrsig_expiration,v 1.14 2015/10/12 16:54:20 wessels Exp $
|
||||
#
|
||||
# check_zone_rrsig_expiration
|
||||
#
|
||||
# nagios plugin to check expiration times of RRSIG records. Reminds
|
||||
# you if its time to re-sign your zone.
|
||||
|
||||
# Copyright (c) 2008, The Measurement Factory, Inc. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# Neither the name of The Measurement Factory nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# usage
|
||||
#
|
||||
# define command {
|
||||
# command_name check-zone-rrsig
|
||||
# command_line /usr/local/libexec/nagios-local/check_zone_rrsig -Z $HOSTADDRESS$
|
||||
# }
|
||||
#
|
||||
# define service {
|
||||
# name dns-rrsig-service
|
||||
# check_command check-zone-rrsig
|
||||
# ...
|
||||
# }
|
||||
#
|
||||
# define host {
|
||||
# use dns-zone
|
||||
# host_name zone.example.com
|
||||
# alias ZONE example.com
|
||||
# }
|
||||
#
|
||||
# define service {
|
||||
# use dns-rrsig-service
|
||||
# host_name zone.example.com
|
||||
# }
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Getopt::Std;
|
||||
use Net::DNS::Resolver;
|
||||
use Time::HiRes qw ( gettimeofday tv_interval);
|
||||
use Time::Local;
|
||||
use List::Util qw ( shuffle );
|
||||
|
||||
# options
|
||||
# -Z zone Zone to test
|
||||
# -t seconds DNS query timeout
|
||||
# -d debug
|
||||
# -C days Critical if expiring in this many days
|
||||
# -W days Warning if expiring in this many days
|
||||
# -T type Query type (default SOA)
|
||||
# -4 use IPv4 only
|
||||
# -U size EDNS0 UDP packet size (default 4096)
|
||||
my %opts = (t=>30, C=>2, W=>3, T=>'SOA', U=>4096);
|
||||
getopts('4Z:dt:W:C:T:U:', \%opts);
|
||||
usage() unless $opts{Z};
|
||||
usage() if $opts{h};
|
||||
my $zone = $opts{Z};
|
||||
$zone =~ s/^zone\.//;
|
||||
|
||||
my $data;
|
||||
my $start;
|
||||
my $stop;
|
||||
|
||||
my @refs = qw (
|
||||
a.root-servers.net
|
||||
b.root-servers.net
|
||||
c.root-servers.net
|
||||
d.root-servers.net
|
||||
e.root-servers.net
|
||||
f.root-servers.net
|
||||
g.root-servers.net
|
||||
h.root-servers.net
|
||||
i.root-servers.net
|
||||
j.root-servers.net
|
||||
k.root-servers.net
|
||||
l.root-servers.net
|
||||
m.root-servers.net
|
||||
);
|
||||
|
||||
$start = [gettimeofday()];
|
||||
do_recursion();
|
||||
do_queries();
|
||||
$stop = [gettimeofday()];
|
||||
do_analyze();
|
||||
|
||||
sub do_recursion {
|
||||
my $done = 0;
|
||||
my $res = Net::DNS::Resolver->new;
|
||||
do {
|
||||
print STDERR "\nRECURSE\n" if $opts{d};
|
||||
my $pkt;
|
||||
foreach my $ns (shuffle @refs) {
|
||||
print STDERR "sending query for $zone $opts{T} to $ns\n" if $opts{d};
|
||||
$res->nameserver($ns);
|
||||
$res->udp_timeout($opts{t});
|
||||
$res->recurse(0);
|
||||
$res->dnssec(1);
|
||||
$res->udppacketsize($opts{U});
|
||||
$res->force_v4(1) if $opts{'4'};
|
||||
$pkt = $res->send($zone, $opts{T});
|
||||
last if $pkt;
|
||||
}
|
||||
critical("No response to seed query") unless $pkt;
|
||||
critical($pkt->header->rcode . " from " . $pkt->answerfrom)
|
||||
unless ($pkt->header->rcode eq 'NOERROR');
|
||||
@refs = ();
|
||||
foreach my $rr ($pkt->authority) {
|
||||
next unless $rr->type eq 'NS';
|
||||
print STDERR $rr->string, "\n" if $opts{d};
|
||||
push (@refs, $rr->nsdname);
|
||||
next unless names_equal($rr->name, $zone);
|
||||
add_nslist_to_data($pkt);
|
||||
$done = 1;
|
||||
}
|
||||
} while (! $done);
|
||||
}
|
||||
|
||||
|
||||
sub do_queries {
|
||||
my $n;
|
||||
do {
|
||||
$n = 0;
|
||||
foreach my $ns (keys %$data) {
|
||||
next if $data->{$ns}->{done};
|
||||
print STDERR "\nQUERY $ns\n" if $opts{d};
|
||||
|
||||
my $pkt = send_query($zone, $opts{T}, $ns);
|
||||
add_nslist_to_data($pkt);
|
||||
$data->{$ns}->{queries}->{$opts{T}} = $pkt;
|
||||
|
||||
print STDERR "done with $ns\n" if $opts{d};
|
||||
$data->{$ns}->{done} = 1;
|
||||
$n++;
|
||||
}
|
||||
} while ($n);
|
||||
}
|
||||
|
||||
sub do_analyze {
|
||||
my $nscount = 0;
|
||||
my $NOW = time;
|
||||
my %MAX_EXP_BY_TYPE;
|
||||
foreach my $ns (keys %$data) {
|
||||
print STDERR "\nANALYZE $ns\n" if $opts{d};
|
||||
my $pkt = $data->{$ns}->{queries}->{$opts{T}};
|
||||
critical("No response from $ns") unless $pkt;
|
||||
print STDERR $pkt->string if $opts{d};
|
||||
critical($pkt->header->rcode . " from $ns")
|
||||
unless ($pkt->header->rcode eq 'NOERROR');
|
||||
critical("$ns is lame") unless $pkt->header->ancount;
|
||||
foreach my $rr ($pkt->answer) {
|
||||
next unless $rr->type eq 'RRSIG';
|
||||
my $exp = sigrr_exp_epoch($rr);
|
||||
my $T = $rr->typecovered;
|
||||
if (!defined($MAX_EXP_BY_TYPE{$T}->{exp}) || $exp > $MAX_EXP_BY_TYPE{$T}->{exp}) {
|
||||
$MAX_EXP_BY_TYPE{$T}->{exp} = $exp;
|
||||
$MAX_EXP_BY_TYPE{$T}->{ns} = $ns;
|
||||
}
|
||||
}
|
||||
$nscount++;
|
||||
}
|
||||
warning("No nameservers found. Is '$zone' a zone?") if ($nscount < 1);
|
||||
warning("No RRSIGs found") unless %MAX_EXP_BY_TYPE;
|
||||
my $min_exp = undef;
|
||||
my $min_ns = undef;
|
||||
my $min_type = undef;
|
||||
foreach my $T (keys %MAX_EXP_BY_TYPE) {
|
||||
printf STDERR ("%s RRSIG expires in %.1f days\n", $T, ($MAX_EXP_BY_TYPE{$T}->{exp}-$NOW)/86400) if $opts{d};
|
||||
if (!defined($min_exp) || $MAX_EXP_BY_TYPE{$T}->{exp} < $min_exp) {
|
||||
$min_exp = $MAX_EXP_BY_TYPE{$T}->{exp};
|
||||
$min_ns = $MAX_EXP_BY_TYPE{$T}->{ns};
|
||||
$min_type = $T;
|
||||
}
|
||||
}
|
||||
critical("$min_ns has expired RRSIGs") if ($min_exp < $NOW);
|
||||
if ($min_exp - $NOW < ($opts{C}*86400)) {
|
||||
my $ND = sprintf "%3.1f days", ($min_exp-$NOW)/86400;
|
||||
critical("$min_type RRSIG expires in $ND at $min_ns")
|
||||
}
|
||||
if ($min_exp - $NOW < ($opts{W}*86400)) {
|
||||
my $ND = sprintf "%3.1f days", ($min_exp-$NOW)/86400;
|
||||
warning("$min_type RRSIG expires in $ND at $min_ns")
|
||||
}
|
||||
success("No RRSIGs expiring in the next $opts{W} days");
|
||||
}
|
||||
|
||||
sub sigrr_exp_epoch {
|
||||
my $rr = shift;
|
||||
die unless $rr->type eq 'RRSIG';
|
||||
my $exp = $rr->sigexpiration;
|
||||
die "bad exp time '$exp'"
|
||||
unless $exp =~ /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/;
|
||||
my $exp_epoch = timegm($6,$5,$4,$3,$2-1,$1);
|
||||
return $exp_epoch;
|
||||
}
|
||||
|
||||
sub add_nslist_to_data {
|
||||
my $pkt = shift;
|
||||
foreach my $ns (get_nslist($pkt)) {
|
||||
next if defined $data->{$ns}->{done};
|
||||
print STDERR "adding NS $ns\n" if $opts{d};
|
||||
$data->{$ns}->{done} |= 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub success {
|
||||
output('OK', shift);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sub warning {
|
||||
output('WARNING', shift);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sub critical {
|
||||
output('CRITICAL', shift);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
sub output {
|
||||
my $state = shift;
|
||||
my $msg = shift;
|
||||
$stop = [gettimeofday()] unless $stop;
|
||||
my $latency = tv_interval($start, $stop);
|
||||
printf "ZONE %s: %s; (%.2fs) |time=%.6fs;;;0.000000\n",
|
||||
$state,
|
||||
$msg,
|
||||
$latency,
|
||||
$latency;
|
||||
}
|
||||
|
||||
sub usage {
|
||||
print STDERR "usage: $0 -Z zone -d -t timeout -W days -C days\n";
|
||||
print STDERR "\t-Z zone zone to test\n";
|
||||
print STDERR "\t-T type query type (default SOA)\n";
|
||||
print STDERR "\t-d debug\n";
|
||||
print STDERR "\t-t seconds timeout on DNS queries\n";
|
||||
print STDERR "\t-W days warning threshhold\n";
|
||||
print STDERR "\t-C days critical threshold\n";
|
||||
print STDERR "\t-4 use IPv4 only\n";
|
||||
print STDERR "\t-U bytes EDNS0 UDP buffer size (default 4096)\n";
|
||||
exit 3;
|
||||
}
|
||||
|
||||
sub send_query {
|
||||
my $qname = shift;
|
||||
my $qtype = shift;
|
||||
my $server = shift;
|
||||
my $res = Net::DNS::Resolver->new;
|
||||
$res->nameserver($server) if $server;
|
||||
$res->udp_timeout($opts{t});
|
||||
$res->retry(2);
|
||||
$res->recurse(0);
|
||||
$res->dnssec(1);
|
||||
$res->udppacketsize($opts{U});
|
||||
$res->force_v4(1) if $opts{'4'};
|
||||
my $pkt = $res->send($qname, $qtype);
|
||||
unless ($pkt) {
|
||||
$res->usevc(1);
|
||||
$res->tcp_timeout($opts{t});
|
||||
$pkt = $res->send($qname, $qtype);
|
||||
}
|
||||
return $pkt;
|
||||
}
|
||||
|
||||
sub get_nslist {
|
||||
my $pkt = shift;
|
||||
return () unless $pkt;
|
||||
return () unless $pkt->authority;
|
||||
my @nslist;
|
||||
foreach my $rr ($pkt->authority) {
|
||||
next unless ($rr->type eq 'NS');
|
||||
next unless names_equal($rr->name, $zone);
|
||||
push(@nslist, lc($rr->nsdname));
|
||||
}
|
||||
return @nslist;
|
||||
}
|
||||
|
||||
sub names_equal {
|
||||
my $a = shift;
|
||||
my $b = shift;
|
||||
$a =~ s/\.$//;
|
||||
$b =~ s/\.$//;
|
||||
lc($a) eq lc($b);
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue