Dear Mr. Dippery, The method I use is the check_nmap_scan plug-in by Serg Belokamen, which I've attached to this email. It is written in perl and requires that you have nmap installed on your nagios host.
Basically, you define what ports should be open (and not open) on a given host 
and then it runs a regular check to see if the ports you define as open or 
closed really are open or closed and reports on discrepancies. Very handy.

Regards,
Richard Remington
Unix Systems Administrator

Kyle Dippery wrote:
Is there an easy way to use nagios to check for the absence of a
service?

I want to have nagios monitor SMTP and a few other services on hosts
that aren't supposed to be running them, and tell me if they
suddenly get turned on.

Is there a plugin for this, or a way to trick an existing plugin to
make it work?  I suppose if nothing else I can write a wrapper for
check_smtp or check_tcp to swap the OK and CRITICAL return values,
but it'd be much easier if someone else has already done it...

Cheers,
Kyle

#!/usr/bin/perl -w
####
#       Author:         Serg Belokamen <s...@fuzzyit.com>
#       Date:           22-Sep-2006
#       Version:        0.0.2
#       License:        GPL
####

use strict;
use Getopt::Long;

# Nagios parsable return codes
use constant OK       => 0;
use constant WARNING  => 1;
use constant CRITICAL => 2;
use constant UNKNOWN  => 3;

MAIN:
{
        # Values for variable below will be collected from CLI
        my $nmap_path     = undef(); # Path to Nmap
        my $scan_address  = undef(); # IP to scan
        my $allowed_ports = undef(); # Allowed ports
        my $nmap_args     = undef(); # User defined Nmap arguments
        my $help          = undef(); # Ask for usage info.

        # Store Nmap output here.
        my @nmap_raw = (); # Raw Nmap output
        my @allowed  = (); # Allowed port list
        my @opened   = (); # Opened not-allowed ports
        my @total    = (); # All listening ports
        my @closed   = (); # Allowed closed ports

        # Receive command line parameters.
        GetOptions
        (
                "ip=s"    => \$scan_address,
                "nmap=s"  => \$nmap_path,
                "ports=s" => \$allowed_ports,
                "help"    => \$help
        );

        # Show usage info.      
        if($help) { showHelp(); exit(OK); }

        # Parse command line arguments.
        if(!parseCLIArgs($scan_address, $nmap_path, $allowed_ports))
        {
                print "Invalid command line arguments supplied.";
                showHelp();
                exit(UNKNOWN);
        }

        # Parse supplied port list.
        @allowed = sort(extractPortList($allowed_ports));

        # All ports should be blocked
        $allowed_ports = "none" if(scalar @allowed == 0);

        # Check that supplied ports were parsed correctly
        if($allowed[0] and $allowed[0] == -1)
        {
                print "Port number(s) supplied are invalid.";
                exit(UNKNOWN);
        }

        # Start nmap scan.
        ####
        # Security update:
        # Patch submitted by: Erik Strahl <beame...@gmx.net>
        # This tells nmap to scan all ports from 1 to 65535 and not just often 
        # utilized ports, which is the nmap default setting.
        #
        # Old: @nmap_raw = `$nmap_path -P0 $scan_address`;
        ####
        @nmap_raw = `$nmap_path -P0 -p1-65535 $scan_address`;

        # Parse nmap scan results.
        for(my $i = 0; $i < scalar @nmap_raw; $i++)
        {
                # Clean output
                chomp $nmap_raw[$i];

                # Extract and store port numbers from scan output
                push(@total, $1)
                        if($nmap_raw[$i] =~ /^(\d{1,})\/(tcp|udp).*$/);
        }

        # Sort open ports array
        @total  = sort(@total);
        @opened = @total;

        # Check if ONLY (all of the) allowed ports were found - OK
        if(join("", @opened) eq join("", @allowed))
        {
                # Print Nagios OK message
                print "OK, ";
                print "IP: ".$scan_address."; ";
                print "Scanned: ".$allowed_ports."; ";
                print "Allowed: ".$allowed_ports;

                # Return OK to Nagios parser
                exit(OK);
        }

        for(my $i = 0; $i < scalar @allowed; $i++)
        {
                my $found = 0;

                for(my $j = 0; $j < scalar @opened; $j++)
                {
                        if($allowed[$i] eq $opened[$j])
                        {
                                $opened[$j] = $opened[scalar @opened- 1];
                                pop(@opened);
                                $found = 1;
                        }
                }

                push(@closed, "-".$allowed[$i])
                        if($found == 0);
        }

        map($_ = "+".$_, @opened);

        my $t_exit  = UNKNOWN;
        my $t_output = undef();

        if(scalar @closed > 0) { $t_exit = WARNING;  $t_output = "WARNING, ";  }
        if(scalar @opened > 0) { $t_exit = CRITICAL; $t_output = "CRITICAL, "; }

        print $t_output.
                        "IP: ".$scan_address."; ".
                        "Result: ".join(",", @opened, @closed, )."; ".
                        "Scaned: ".join(",", @total)."; ".
                        "Allowed: ".$allowed_ports;

        exit($t_exit);

} # END MAIN


sub parseCLIArgs
{
        my ($scan_address,      $nmap_path, $allowed_ports) = @_;

        # Make sure that Nmap is executable...
        return 0
                if(!$nmap_path or !-x $nmap_path);

        # Check for syntatically valid IP address
        return 0
                if($scan_address !~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);

        # Check if port list was supplied
        return 0 
                if(!$allowed_ports);

        return 1;
} # END sub parseCLIArgs


sub extractPortList
{
        my ($ports) = @_;
        my @ports   = ();

        my $port_min   = 0;
        my $port_max   = 65534;
        my $empty_list = "e";

        chomp($ports);

        @ports = split(/,/, $ports);

        # Validate port numbers
        for(my $i= 0; $i < scalar @ports; $i++)
        {
                return ()
                        if($ports[$i] eq $empty_list);

                $ports[0] = -1
                        if($ports[$i] !~ /^\d{1,}$/ or
                                ($ports[$i] > $port_max or $ports[$i] < 
$port_min));
        }

        return @ports;
} # END sub extractPortList


sub showHelp
{
        my @showHelpMsg =
        (
                "USAGE:",
                "    -n --nmap  /path/to/nmap.",
                "    -i --ip    IP address to scan.",
                "    -p --ports Comma sepparated list of allowd ports or 'e' 
(empty).",
                "    -h --help  Display help message (this).",
                "",
                "DEFINITIONS:",
                "    OK",
                "    Nothing change, allowed ports list matches scanned ports 
list.",
                "",
                "    CRITICAL",
                "    Allowed ports list does not match scanned ports list. 
Additional",
                "    ports were found to be listening. They are denoted by a 
'+' sign",
                "    infront of them in the 'Result' string.",
                "",
                "    WARNING",
                "    Allowed ports list does not match scanned ports list. Some 
of ",
                "    the ports in 'Allowed' string were found to be closed. 
They are",
                "    are denoted by a '-' sign infront of them in the 'Result'",
                "    string.",
                "",
                "NOTE:",
                "    To define an empty port (--port) list use a value of e 
(e). For",
                "    example '--ports e'",
                "",
                "    If CRITICAL AND WARNING states are one then CRITICAL will 
be",
                "    displayed. However, WARNING results can be destinguished 
from ",
                "    CRITICAL since they will have a '-' prefix (CRITICAL will 
have",
                "    a '+' prefix).",
                "",
                "USAGE EXAMPLES:",
                "    Alowed ports are NULL:",
                "    script -n /usr/bin/nmap -i 192.168.1.1 -p e",
                "",
                "    More regular usage (allowed port is SSH: 22 and HTTP: 
445):",
                "    script -n /usr/bin/nmap -i 192.168.1.1 -p 22,445",
                ""
        );

        print join("\n", @showHelpMsg);
} # END sub showHelp
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize  
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
Nagios-users mailing list
Nagios-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nagios-users
::: Please include Nagios version, plugin version (-v) and OS when reporting 
any issue. 
::: Messages without supporting info will risk being sent to /dev/null

Reply via email to