I don't know why there aren't more simple ways to detect rogue DHCP servers. It can have nasty effects on a network and can be difficult to diagnose and it's easy for it to happen. Someone can plug in a machine set to share its internet connection and bam.
I wrote a perl script to detect rogue DHCP servers in nagios. I found one on the web here but I wanted it a bit more flexible so the hosts it was testing were in the nagios config files rather than in the script itself. It's a debian policy thing I like.
So I adjusted the script. It requires the check_dhcp plugin which for me was part of my ubuntu nagios install. It takes options "-v" and a list of servers. In your nagios-plugins/configure file the command looks like:
Post on new version can be found here.
I wrote a perl script to detect rogue DHCP servers in nagios. I found one on the web here but I wanted it a bit more flexible so the hosts it was testing were in the nagios config files rather than in the script itself. It's a debian policy thing I like.
So I adjusted the script. It requires the check_dhcp plugin which for me was part of my ubuntu nagios install. It takes options "-v" and a list of servers. In your nagios-plugins/configure file the command looks like:
/usr/lib/nagios/plugins/check_rogue_dhcp.pl!$ARG1$!$ARG3$!$ARG3$
The script can be downloaded from here. (Sorry the link is corrected now!)
Post on new version can be found here.
-----check_rogue_dhcp.pl-------------
#!/usr/bin/perl -w
# nagios: -epn
# the above makes nagios run the script separately.
use POSIX;
use lib "/usr/lib/nagios/plugins";
use utils qw(%ERRORS);
sub fail_usage {
if (scalar @_) {
print "$0: error: \n";
map { print " $_\n"; } @_;
}
print "$0: Usage: \n";
print "$0 [-v [-v [-v]]] (server-ip) [(server-ip) (server-ip) ....] \n";
print "$0 [-v [-v [-v]]] [-s] (server-ip) [[-s] (server-ip) (server-ip)....] \n";
print " \n";
exit 3 ;
}
my $verbose = 0;
my %servers=();
# examine commandline args
while ($ARGV=$ARGV[0]) {
my $myarg = $ARGV;
if ($ARGV eq '-s') {
shift @ARGV;
if (!($ARGV = $ARGV[0])) { fail_usage ("$myarg needs an argument"); }
if ($ARGV =~ /^-/) { fail_usage ("$myarg must be followed by an argument"); }
if (!defined($servers{$ARGV})) { $servers{$ARGV}=1; }
}
elsif ($ARGV eq '-v' ) { $verbose++; }
elsif ($ARGV eq '-h' or $ARGV eq '--help' ) { fail_usage ; }
elsif ($ARGV =~ /^-/ ) { fail_usage " invalid option ($ARGV)"; }
elsif ($ARGV =~ /^\d+\.\d+\.\d+\.\d+$/)
# servers should be ip addresses. I'm not doing detailed checks for this.
{ if (!defined($servers{$ARGV})) { $servers{$ARGV}=1; } }
else { last; }
shift @ARGV;
}
# for some reason I can't test for empty ARGs in the while loop
@ARGV = grep {!/^\s*$/} @ARGV;
if (scalar @ARGV) { fail_usage "didn't understand arguments: (".join (" ",@ARGV).")"; }
my $serversn = scalar keys %servers;
if ($verbose > 2) {
print "verbosity=($verbose)\n";
print "servers = ($serversn)\n";
if ($serversn) { for my $i (keys %servers) { print "server ($i)\n"; } }
}
if (!$serversn) { fail_usage "no servers"; }
my $responses=0;
my $responders="";
my @check_dhcp = qx{/usr/lib/nagios/plugins/check_dhcp -v};
foreach my $value (@check_dhcp) {
if ($value =~ /Added offer from server \@ /i){
$value =~ m/(\d+\.\d+\.\d+\.\d+)/i;
my $host = $1;
# we find a server in our list
if (defined($servers{$host})) { $responses++; $responders.="$host "; }
# we find a rogue DHCP server. Danger Will Robinson!
else {
print "SERVICE STATUS:CRITICAL: DHCP service running on $host";
exit $ERRORS{'CRITICAL'}
}
}
}
# we saw all the servers in our list. All is good.
if ($responses == $serversn) {
print "SERVICE STATUS:OK: $responses of $serversn Expected Responses to DHCP Broadcast";
exit $ERRORS{'OK'};
}
# we found no DHCP responses.
if ($responses == 0) {
print "SERVICE STATUS:CRITICAL: no DHCP service responded";
exit $ERRORS{'CRITICAL'}
}
# we found less DHCP servers than we should have. Oh Nos!
$responders =~ s/ $//;
print "SERVICE STATUS:WARNING: $responses of $serversn Responses to DHCP Broadcast. Only ($responders) responded. ";
exit $ERRORS{'WARNING'};