-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdnscheck.pl
executable file
·130 lines (110 loc) · 3.49 KB
/
dnscheck.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/perl -w
# nagios: -epn
##########################################################################
# Name: DNS Sanity Checker
# Author: Daniel Hall <[email protected]>
# License: GPLv3+
# URL: https://github.com/smarthall/dns-sanity-checker
# Description:
# DNS Sanity check is designed to check that DNS RR or A records are
# being correctly served by all the authorative nameservers. It does
# this by first asking for the list of authorities, then checking that
# each one returns results, and that there are no invalid ips.
#
# TODO:
# - Accept address ranges as valid ips
# - If no valid ip list is given, only check for empty results
# - Support CNAME and MX records
# - Different output formats, not just Nagios
#
##########################################################################
use 5.010000;
use Net::DNS::Resolver::Recurse;
use Getopt::Long;
use Data::Dumper;
# Configuration
my $domain = '';
my $host = '';
my $ipstring = '';
my $verbose = '';
###### Fetch config from command line ######
my $cmdline = GetOptions ("domain|zone=s" => \$domain,
"record|property|host=s" => \$host,
"validips|ip|iplist=s" => \$ipstring,
"verbose" => \$verbose);
if (($domain eq '') || ($host eq '') || ($ipstring eq '')) {
print "Please provide a domain, host and list of valid ips\n";
print "Example: ./dnscheck.pl --domain danielhall.me --record mail --validips 106.187.99.154\n";
exit 2;
}
my @validips = split(/,/, $ipstring);
my $unknown = 0;
###### Fetch data from the authorative NS ######
my $fqdn = $host . "." . $domain;
my $pres = Net::DNS::Resolver->new;
$pres->tcp_timeout(2);
$pres->udp_timeout(2);
if ($verbose) {
$pres->debug(1);
} else {
$pres->debug(0);
}
my $packet = $pres->query($domain, "NS");
my %answers = ();
foreach my $ns ($packet->answer) {
if ($verbose) {print "**** Checking " . $ns->nsdname . "\n"};
$pres->nameservers($ns->nsdname);
$answer = $pres->send($fqdn, "A");
$answers{$ns->nsdname} = [];
if (defined $answer) {
foreach my $ip ($answer->answer) {
push (@{$answers{$ns->nsdname}}, $ip->address);
}
} else {
$unknown = 1;
}
}
###### Process the data ######
my @emptyns = ();
my %invalidip = ();
# Check each nameserver
foreach my $ns (keys %answers) {
if ($verbose) {print "**** Processing $ns\n"};
my @ips = @{$answers{$ns}};
if (scalar(@ips) == 0) {
if ($verbose) {print "**** Nameserver $ns had no results\n"};
push @emptyns, $ns
}
foreach my $ip (@ips) {
if ( !($ip ~~ @validips) ) {
if ($verbose) {print "**** Nameserver $ns sent an invalid IP of $ip\n"};
$invalidip{$ns} = $ip;
}
}
}
###### Tell nagios ######
my $rtrncode = 0;
my $status = '';
my $extstatus = '';
if (scalar(@emptyns) > 0) {
$rtrncode = 2;
$extstatus .= 'Nameservers sending empty results: ' . join(', ', @emptyns) . " ";
}
if (scalar(keys %invalidip) > 0) {
$rtrncode = 2;
$extstatus .= 'Nameservers sending invalid IP addresses: ' . join(', ', %invalidip) . " ";
}
if ($unknown == 1) {
$rtrncode = 3;
}
if ($rtrncode == 0) {
$status = 'NS OK - All authorative nameservers correct';
} elsif ($rtrncode == 1) {
$status = 'NS WARNING - Something is slightly wrong';
} elsif ($rtrncode == 2) {
$status = 'NS CRITICAL - One or more nameservers are sending incorrect results';
} elsif ($rtrncode == 3) {
$status = 'NS UNKNOWN - Something is preventing the check from checking';
}
print "$status|$extstatus\n";
exit $rtrncode;