#!/usr/bin/perl # This Plugin checks the VPN states of Fortigate Firewalls # Tested on FG200A, FG200B, FG80C, Software v3MR7SP2, v4MR1P1 # WARNING: NOT WORKING ON FortiOS v4MR2 AND HIGHER! # # Copyright (c) 2009 Gerrit Doornenbal, g(dot)doornenbal(at)hccnet(dot)nl # Many thanks to Sascha Tentscher , who provided a very good example # with his 3com plugin! # # Changelog: # 23-1-2009 Initial Release, monitoring IPSEC and SSL-VPN # 25-3-2009 Added feature to disable monitoring, just for counting # number of IPSEC connections # 10-11-2010 Numerous perl coding errors solved, added SNMP availabity check # and added VPN type choice for ipsec and ssl. # 11-05-2011 Added feature to get performance data # # 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. # # If you wish to receive a copy of the GNU General Public License, # write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-130 use strict; use Net::SNMP; if ($#ARGV <= 0) { &print_help(); } my %status = ( 'UNKNOWN' => '-1', 'OK' => '0', 'WARNING' => '1', 'CRITICAL' => '2' ); my %entitystate = ( '1' => 'down', '2' => 'up' ); sub pars_args { my $ip = ""; my $community = ""; my $modus = "2"; my $type = "both"; my $performance = "no"; while(@ARGV) { if($ARGV[0] =~/^-H|^--host/) { $ip = $ARGV[1]; shift @ARGV; shift @ARGV; next; } if($ARGV[0] =~/^-C|^--community/) { $community = $ARGV[1]; shift @ARGV; shift @ARGV; next; } if($ARGV[0] =~/^-M|^--modus/) { $modus = $ARGV[1]; shift @ARGV; shift @ARGV; next; } if($ARGV[0] =~/^-T|^--type/) { $type = $ARGV[1]; shift @ARGV; shift @ARGV; next; } if($ARGV[0] =~/^-f|^-F/) { $performance = "yes"; shift @ARGV; next; } } return ($ip, $community, $modus, $type, $performance); } sub print_help() { print "Usage: check_fortigate_vpn -H host -C community\n"; print "Options:\n"; print " -H --host STRING or IPADDRESS\n"; print " Check interface on the indicated host.\n"; print " -C --community STRING\n"; print " Community-String for SNMP.\n"; print " -M --modus default = 2\n"; print " 0: Just counting, no alarms\n"; print " 1: Just counting, failed tunnels will be showed\n"; print " 2: Monitoring, failed tunnels cause failed status. \n"; print " -T --type default = both\n"; print " ssl: only SSL VPN connections wil be monitored\n"; print " ipsec: only IPSEC VPN connections wil be monitored\n"; print " both: monitoring all types of VPN connections \n"; print " -F Also giving performance data output.\n\n"; print "This plugin checks all configured IPSEC tunnels, and gives\nthe number of current IPSEC tunnels and SSL-VPN tunnels.\n\n"; exit($status{"UNKNOWN"}); } sub get_snmp_session { my $ip = $_[0]; my $community = $_[1]; my ($session, $error) = Net::SNMP->session( -hostname => $ip, -community => $community, -port => 161, -timeout => 1, -retries => 3, -translate => [-timeticks => 0x0] #schaltet Umwandlung von Timeticks in Zeitformat aus ); return ($session, $error); } sub close_snmp_session { my $session = $_[0]; $session->close(); } sub get_snmp_request { my $session = $_[0]; my $oid = $_[1]; return $session->get_request($oid); } sub get_snmp_table { my $session = $_[0]; my $oid = $_[1]; return $session->get_table(-baseoid =>$oid); } my ($ip, $community, $modus, $type, $performance) = pars_args(); my ($session, $error) = get_snmp_session($ip, $community); #Requests my $oid_unitdesc = ".1.3.6.1.2.1.1.1.0"; my $oid_ActiveSSL = ".1.3.6.1.4.1.12356.9.5.1.7.1"; #Tables my $oid_ipsecphase2name = ".1.3.6.1.4.1.12356.9.4.1.3"; my $oid_ipsecstate = ".1.3.6.1.4.1.12356.9.4.1.20"; # At only the first get_snmp a die to check if SNMP agent is responding.... my (%result) = %{get_snmp_request($session, $oid_unitdesc) or die ("SNMP service is not available on ".$ip) }; my $unitdesc = $result{$oid_unitdesc}; my $counter = 0; my $ActiveSSL; if ($type ne "ipsec") #check ssl tunnels { %result = %{get_snmp_request($session, $oid_ActiveSSL)}; $ActiveSSL = $result{$oid_ActiveSSL}; } my @ipsecphase2name; my @ipsecstate; my $string_errors=""; my $failed_ipsec=0; if ($type ne "ssl") #check ipsec tunnels { my %result1 = %{get_snmp_table($session, $oid_ipsecphase2name)}; my %result2 = %{get_snmp_table($session, $oid_ipsecstate)}; #print %result1; foreach my $oid(sort keys %result1) { $ipsecphase2name[$counter] = $result1{$oid}; $counter++; } $counter = 0; foreach my $oid(sort keys %result2) { $ipsecstate[$counter] = $result2{$oid}; $counter++; } #IPSEC Tunnels checken for(my $i =0; $i<$counter; $i++) { if ($ipsecstate[$i] == 1) { $failed_ipsec++; if ($modus >= 1) { $string_errors .= ", "; $string_errors .= $ipsecphase2name[$i]." ".$entitystate{$ipsecstate[$i]}; } } } } close_snmp_session($session); #Set Unitstate my $unitstate="OK"; if (($modus >= 2 ) && ($type ne "ssl")) { if ($failed_ipsec == 1) { $unitstate="WARNING"; } if ($failed_ipsec >= 2) { $unitstate="CRITICAL"; } } # Set output String my $active_ipsec = $counter - $failed_ipsec; my $string = $unitdesc.": ".$unitstate; if ($type ne "ipsec") { #show ssl info $string = $string.", Active SSL-VPN Tunnels: ".$ActiveSSL.""; } if ($type ne "ssl") { #show ipsec info $string = $string.", Active IPSEC Tunnels: ".$active_ipsec." ".$string_errors; } # Create performance data my $perfstring=""; if ( $performance eq "yes" ) { $perfstring="| ActiveSSL-VPN=".$ActiveSSL." ActiveIPSEC=".$active_ipsec; # print $perfstring."\n"; } $string = $string.$perfstring; my $state = "OK"; if($string =~/uknw/) { $state = "UNKNOWN"; } if($string =~/WARNING/) { $state = "WARNING"; } if($string =~/down/) { $state = "CRITICAL"; } print $string."\n"; exit($status{$state});