#!/usr/bin/perl # ------------------------------------------------------- # -=- -=- # ------------------------------------------------------- # # Description : This plugin checks if the fail2ban server is running # and how many IPs are currently banned. # # # inspired by the work of Sebastian Mueller - http://www.elchtest.eu # # # Version : 0.1 # ------------------------------------------------------- # In : # - see the How to use section # # Out : # - only print on the standard output # # Features : # - perfdata output # - works with only a specific jail # # Fix Me/Todo : # - too many things ;) but let me know what do you think about it # # #################################################################### # #################################################################### # GPL v2 # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # #################################################################### # #################################################################### # How to use : # ------------ # # Just have to run the following command: # $ ./check_fail2ban --help # # If you need to use this script with NRPE you just have to do the # following steps: # # 1 allow your user to run the script with the sudo rights. Just add # something like that in your /etc/sudoers (use visudo) : # nagios ALL=(ALL) NOPASSWD: //check_fail2ban # # 2 then just add this kind of line in your NRPE config file : # command[check_fail2ban]=/usr/bin/sudo //check_fail2ban # # 3 don't forget to restart your NRPE daemon # # # /!\ be careful to let no one able to update the check_fail2ban ;) # ------------------------------------------------------------------------------ # # #################################################################### # #################################################################### # Changelog : # ----------- # # -------------------------------------------------------------------- # Date:12/03/2013 Version:0.1 Author:Erwan Ben Souiden # >> creation # #################################################################### # #################################################################### # Don't touch anything under this line! # You shall not pass - Gandalf is watching you # #################################################################### use strict; use warnings; use Getopt::Long qw(:config no_ignore_case); # Generic variables # ----------------- my $version = '0.1'; my $author = 'Erwan Labynocle Ben Souiden'; my $a_mail = 'erwan@aleikoum.net'; my $script_name = 'check_fail2ban'; my $verbose_value = 0; my $version_value = 0; my $more_value = 0; my $help_value = 0; my $perfdata_value = 0; my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); # Plugin default variables # ------------------------ my $display = 'CHECK FAIL2BAN ACTIVITY'; my ($critical,$warning) = (2,1); my $fail2ban_client_path = '/usr/bin/fail2ban-client'; my $fail2ban_socket = ''; my $jail_specific = ''; my $jail_name = ''; GetOptions ( 'P=s' => \ $fail2ban_client_path, 'path-fail2ban_client=s' => \ $fail2ban_client_path, 'j=s' => \ $jail_specific, 'jail=s' => \ $jail_specific, 'w=i' => \ $warning, 'warning=i' => \ $warning, 'socket=s' => \ $fail2ban_socket, 'S=s' => \ $fail2ban_socket, 'c=i' => \ $critical, 'critical=i' => \ $critical, 'V' => \ $version_value, 'version' => \ $version_value, 'h' => \ $help_value, 'H' => \ $help_value, 'help' => \ $help_value, 'display=s' => \ $display, 'D=s' => \ $display, 'perfdata' => \ $perfdata_value, 'p' => \ $perfdata_value, 'v' => \ $verbose_value, 'verbose' => \ $verbose_value ); print_usage() if ($help_value); print_version() if ($version_value); # Syntax check of your specified options # -------------------------------------- print "DEBUG : fail2ban_client_path: $fail2ban_client_path\n" if ($verbose_value); if (($fail2ban_client_path eq "")) { print $display.'- one or more following arguments are missing: fail2ban_client_path'."\n"; exit $ERRORS{"UNKNOWN"}; } if(! -x $fail2ban_client_path) { print $display.' - '.$fail2ban_client_path.' is not executable by you'."\n"; exit $ERRORS{"UNKNOWN"}; } print "DEBUG : $fail2ban_client_path exists and is executable\n" if ($verbose_value); my $fail2ban_cmd = $fail2ban_client_path; $fail2ban_cmd .= " -s $fail2ban_socket" if ($fail2ban_socket); print "DEBUG : final fail2ban command: $fail2ban_cmd\n" if ($verbose_value); print "DEBUG : warning threshold : $warning, critical threshold : $critical\n" if ($verbose_value); if (($critical < 0) or ($warning < 0) or ($critical < $warning)) { print $display.' - the thresholds must be integers and the critical threshold higher or equal than the warning threshold'."\n"; exit $ERRORS{"UNKNOWN"}; } # Core script # ----------- my ($how_many_jail,$how_many_banned,$return_print,$perf_print,$plugstate) = (0,0,"","","OK"); ### Test the connection to the fail2ban server my @command_output = `$fail2ban_cmd ping`; my $return_code = $?; if ($return_code) { print $display.'CRITICAL - non-zero exit code during testing fail2ban-client ping, check if the server is running and if you have the good permissions'; exit $ERRORS{"CRITICAL"}; } else { print "DEBUG : it seems the connection with the fail2ban server is ok\n" if ($verbose_value); } ### Only if you specify one jail if ($jail_specific) { my $current_ban_number = currently_ban("$fail2ban_cmd","$jail_specific"); if ($current_ban_number == -1) { print $display.' - CRITICAL - impossible to retrieve info about the jail '.$jail_specific; exit $ERRORS{"CRITICAL"}; } else { $how_many_banned = int($current_ban_number); $return_print = $how_many_banned.' current banned IP(s) for the specific jail '.$jail_specific; $perf_print .= "$current_ban_number " if ($perfdata_value); } } ### To analyze all the jail else { # Retrieve the jails list my @jail_list = obtain_jail_list("$fail2ban_cmd"); if ($jail_list[0] eq "-1") { print $display.' - CRITICAL - impossible to retrieve the jail list'."\n"; exit $ERRORS{"CRITICAL"}; } foreach (@jail_list) { $how_many_jail ++; my $jail_name = $_; $jail_name =~ tr/ //ds; my $current_ban_number = currently_ban("$fail2ban_cmd","$jail_name"); if ($current_ban_number == -1) { print "DEBUG : problem to parse the current banned IPs for jail $jail_name\n" if ($verbose_value); } else { print "DEBUG : the jail $jail_name has currently $current_ban_number banned IPs\n" if ($verbose_value); $how_many_banned += int($current_ban_number); $perf_print .= "$jail_name.currentBannedIP=$current_ban_number " if ($perfdata_value); } } $return_print = $how_many_jail.' detected jails with '.$how_many_banned.' current banned IP(s)'; } ### Final $plugstate = "CRITICAL" if ($how_many_banned >= $critical); $plugstate = "WARNING" if (($how_many_banned >= $warning) && ($how_many_banned < $critical)); $return_print = $display." - ".$plugstate." - ".$return_print; $return_print .= " | $perf_print" if ($perfdata_value); print $return_print; exit $ERRORS{"$plugstate"}; # #################################################################### # function 1 : display the help # ----------------------------- sub print_usage { print </$script_name [-p] [-D "$display"] [-v] [-c 2] [-w 1] [-s //socket] [-P /usr/bin/fail2ban-client] Options: -h, --help Print detailed help screen -V, --version Print version information -D, --display=STRING To modify the output display default is "CHECK FAIL2BAN ACTIVITY" -P, --path-fail2ban_client=STRING Specify the path to the tw_cli binary default value is /usr/bin/fail2ban-client -c, --critical=INT Specify a critical threshold default is 2 -w, --warning=INT Specify a warning threshold default is 1 -s, --socket=STRING Specify a socket path default is unset -p, --perfdata If you want to activate the perfdata output -v, --verbose Show details for command-line debugging (Nagios may truncate the output) Send email to $a_mail if you have questions regarding use of this software. To submit patches or suggest improvements, send email to $a_mail This plugin has been created by $author Hope you will enjoy it ;) Remember : This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. EOT exit $ERRORS{"UNKNOWN"}; } # function 2 : display version information # ---------------------------------------- sub print_version { print <