fwstat.txt

#!/usr/bin/perl #===========================================================# # Simple Host Monitor # # Copyright 2004 Chris Sawall csawall@hotmail.com # # http://tech.stlsawall.com # # # $written = "02/03/04"; # $lastupdated = "02/10/04"; # $version = "1.0"; # $myemail = "sawall\@gmail.com"; # #===========================================================# #===========================================================# # COPYRIGHT NOTICE # # Copyright 2004 Chris Sawall All Rights Reserved. # # # # Simple Host Monitor (fwstat.pl) may be used and modified # # free of charge by anyone so long as this copyright notice # # and the comments above remain intact. By using this code # # you agree to indemnify Chris Sawall from any liability # # that might arise from its use. # # # # Selling the code for this program without prior written # # consent is expressly forbidden. In other words, # # please ask first before you try and make money off of my # # program. # # # # Obtain permission before redistributing this software # # over the Internet or in any other medium. In all cases # # copyright and header must remain intact. # #===========================================================# # # This main purpose of this script is to monitor # serveral hosts, dump the info to a web page # that can be viewed by anybody. It will # let users see what's up or down. This script can # also send emails to notify if hosts are down # after a defined period of time. #========================================== use Net::Ping; #========================================= # begin user defined area # # all other settings made in config file #========================================= $debug = 0; $configfile = "fwstat.cfg"; #========================================= # end user defined area #========================================= #========================================= # get info from config file #========================================= if (-e $configfile) {open(CONFFILE, "$configfile") || die "Failed to read config\n";} else {CreateCONFIG();} #if config file does exist, let's create one if ($debug) {print "#### Show Config file details ###\n";} while (<CONFFILE>) { chomp(); next if (/^(#.*|\s*)$/); #skip comments and blank lines ($key, $val) = split(/\s*=\s*/, $_, 2); $key =~ tr/a-z/A-Z/; $$key = $val; if ($debug) {print "key = $key and val = $val\n";} if ($key =~ "EXCLUDE") { next if ($EXCLUDE eq ""); $val =~ tr/a-z/A-Z/; push(@excludes,$val); } if ($key =~ "EMAILADDR") { next if ($EMAILADDR eq ""); push(@emailaddrs,$val); } } close(CONFFILE); if($debug) {print "### Show All Exclude Data ###\n"; print "all exclude data => @excludes\n";} if($debug) {print "### Show All Email ADDRs ###\n"; print "all email addr => @emailaddrs\n";} # check for any hosts that were down previously if (-e $DOWNFILE) { open (HOSTSDOWN, "$DOWNFILE") || die "Failed to read $DOWNFILE\n"; while (<HOSTSDOWN>) { chomp(); next if (/^(#.*|\s*)$/); #skip comments and blank lines ($downhost,$downtimes) = split(/\s*=\s*/, $_, 2); $HDH{$downhost}=$downtimes; } if ($debug) { print "### Show Current HASH Values ###\n"; foreach $key (keys %HDH) {print "$key = $HDH{$key}\n";} } close (HOSTSDOWN); } #========================================= # set current time and day var #========================================= ($sec,$min,$hour,$mday,$mon,$year) = localtime(time); $year+=1900; $mon+=1; if($mon < 10) {$mon = 0 . $mon;} if($mday < 10) {$mday = 0 . $mday;} if($sec < 10) {$sec = 0 . $sec;} if($min < 10) {$min = 0 . $min;} if($hour < 10) {$hour = 0 . $hour;} $currenttime = "$mon\/$mday\/$year\t$hour:$min:$sec"; if($debug) {print "###Show Current Time ###\n"; print "Time => $currenttime\n";} #========================================= # open firewall host info file # # open output file #========================================= if (-e $FWINFOFILE) {open(INFILE, "$FWINFOFILE")|| die "Failed to read FWINFO --> $FWINFOFILE\n";} else {CreateFWINFO();} #if the host info file doesn't exist, let's create it open(OUTPUT, ">$OUTFILE")|| die "Failed to open OUTPUT --> $OUTFILE\n"; #========================================= # configure html header #========================================= print OUTPUT "<Content-type: text/html>\n"; print OUTPUT "<HTML><HEAD><TITLE>$WEBTTL</TITLE></HEAD>\n"; print OUTPUT "<body bgcolor=$BDYBGND text=$BDYFGND> <font face=Courier size=2>\n"; print OUTPUT "<center><table border=0 cellpadding=4 cellspacing=2 width=\"100%\">\n"; print OUTPUT "<tr><td nowrap aligh=left>\n"; print OUTPUT "<font size=\"6\">$HEADING</font>\n"; print OUTPUT "&nbsp;&nbsp;<small>As of $currenttime</small><br>\n"; #========================================= # set vpn and fw headings to 1 so the # print the first time their loop starts #========================================= $vpnhead =1; $fwhead = 1; #========================================= # parse the host information file #========================================= if ($debug) {print "### Show HOST Information ###\n";} if ($debug) {print "HW Type --- HOST --- Hostname --- Location --- Description\n";} if ($debug) {print "----------------------------------------------------------\n";} while (<INFILE>) { chomp($_); next if (/^(#.*|\s*)$/); #skip comments and blank lines @data = split $FWDELIMIT,$_; $htype = $data[0]; $host = $data[1]; $host =~ tr/a-z/A-Z/; $hostname = $data[2]; $location = $data[3]; $descrip = $data[4]; $hostcheck = 1; if($debug) {print "$htype -- $host -- $hostname -- $location -- $descrip\n";} # if the host is in the exclude list, don't waste time in scanning for it foreach $exchost (@excludes) { if($debug) {if ($exchost =~ $host) {print "exchost = $exchost and host = $host\n";}} if ($exchost eq $host) {$hostcheck = 0;} } # if hostcheck is true, check to make sure the host is still up. if ($hostcheck) { $hoststat = 0; $p = Net::Ping->new("icmp") || die "can't create new ping, $!"; if($p->ping($host)) { $hoststatus = "UP"; $hoststat = 1; } else { $hoststatus = "DOWN"; $hoststat = 0; } $p->close(); if($debug) {print "host => $host -- $hoststatus => $hoststatus --- hoststat = $hoststat\n";} # if host was previously down,but is now up # remove it from the "down" hosts file. if ($hoststatus eq "UP") { foreach $key (keys %HDH) { if ($key eq $host) { delete($HDH{$key}); } } } # if host was down, and is still down # increase times down count if ($hoststatus eq "DOWN") { $keynotfound=1; #if host is down, but wasn't before, make sure it adds it foreach $key (keys %HDH) { if ($key eq $host) { $HDH{$key}++; if($debug) {print "### HASH INFO FOR HOST DOWN ###\n"; print "$key = $HDH{$key}\n";} if ($HDH{$key} == $MAXDOWNTIMES) { if ($NOTIFY eq "on") { $downmins = $MAXDOWNTIMES * $PINGINTERVAL; `echo $DOWNMSG |$MAILPROG -s "Host $host has been done for $MAXDOWNTIMES ping attempts!" @emailaddrs`; } delete($HDH{$key}); } $keynotfound=0; } } # if host is down, but wasn't before, add host to down hash if ($keynotfound) { if ($debug) {print "HASH INFO FOR HOST DOWN ###\n"; print "Host $host is down. Adding to hash.\n";} $HDH{$host}=1; } } } # if the config files says to monitor the vpn hosts and hostcheck is true, check the status if (($MONITORVPNS eq "on") && ($hostcheck)) { if ($htype eq "v") { if ($vpnhead) { $vpnhead = 0; # set to zero so this heading only prints once #========================================= # heading for vpn info #========================================= print OUTPUT "<br><font size=\"5\">$VPNSHEADING</font>\n"; print OUTPUT "<table height=100% width=\"100%\"><tr><td valign=\"top\"><center>\n"; print OUTPUT "<TABLE BORDER=0 WIDTH=\"100%\">\n"; print OUTPUT "<TR><TD><strong>$VPNSTATUSTTL</strong></TD><TD><strong>$VPNNAME</strong></TD>\n"; print OUTPUT "<TD><strong>$VPNLOCATIONTTL</strong></TD><TD><strong>$VPNDESCRIPTTL</strong></TD></TR>\n"; } $result = `$NMAP $PORT $PROTOCOL $host`; $isakmp=0; if ($result =~ /open/) {$isakmp=1; $isakmpstatus="UP";} if ($result =~ /closed/) {$isakmp=0; $isakmpstatus="DOWN";} if($hoststat) {print OUTPUT "<TR><TD><font color=\"$PINGDEVICEUPCOLOR\">$hoststatus</font></TD>\n";} else {print OUTPUT "<TR><TD><font color=\"$PINGDEVICEDOWNCOLOR\">$hoststatus</font></TD>\n";} if($hoststat) {print OUTPUT "<TD>$hostname</TD>\n";} else {print OUTPUT "<TD><font color=\"$PINGDEVICEDOWNCOLOR\">$hostname</font></TD>\n";} print OUTPUT "<TD>$location</TD><TD>$descrip</TD></TR>\n"; if($isakmp) { print OUTPUT "<TR><TD>$isakmpstatus</TD>\n"; print OUTPUT "<TD>$hostname</TD>\n"; print OUTPUT "<TD>&nbsp;</TD><TD><font color=\"$IPSECUPCOLOR\">$IPSECUPINFO</font></TD></TR>\n"; } else { print OUTPUT "<TR><TD><font color=\"$IPSECDOWNCOLOR\">$isakmpstatus</font></TD>\n"; print OUTPUT "<TD><font color=\"$PINGDEVICEDOWNCOLOR\">$hostname</font></TD>\n"; print OUTPUT "<TD>&nbsp;</TD><TD><font color=\"$IPSECDOWNCOLOR\">$IPSECDOWNINFO</font></TD></TR>\n"; } } } # if the config files says to monitor the firewall and hostcheck is true, check the status if (($MONITORFWS eq "on") && ($hostcheck)) { if ($htype eq "f") { if ($fwhead) { $fwhead=0; # set to zero so this heading only prints once #========================================= # if vpn data was published, we need to # close the table before starting fw info #========================================= if (!$vpnhead) { print OUTPUT "</table></center>\n"; } #========================================= # heading for firewall info #========================================= print OUTPUT "<br><font size=\"5\">$FWSHEADING</font>\n"; print OUTPUT "<table height=100% width=\"100%\"><tr><td valign=\"top\"><center>\n"; print OUTPUT "<TABLE BORDER=0 WIDTH=\"100%\">\n"; print OUTPUT "<TR><TD><strong>$FWSTATUSTTL</strong></TD><TD><strong>$FIREWALLNAME</strong></TD>\n"; print OUTPUT "<TD><strong>$FWLOCATIONTTL</strong></TD><TD><strong>$FWDESCRIPTTL</strong></TD></TR>\n"; } if($hoststat) {print OUTPUT "<TR><TD><font color=\"$PINGDEVICEUPCOLOR\">$hoststatus</font></TD>\n";} else {print OUTPUT "<TR><TD><font color=\"$PINGDEVICEDOWNCOLOR\">$hoststatus</font></TD>\n";} if($hoststat) {print OUTPUT "<TD><font color=\"$PINGDEVICEUPCOLOR\">$hostname</font></TD>\n";} else {print OUTPUT "<TD><font color=\"$PINGDEVICEDOWNCOLOR\">$hostname</font></TD>\n";} print OUTPUT "<TD>$location</TD><TD>$descrip</TD></TR>\n"; } } } close(INFILE); print OUTPUT "</table></center>\n"; #========================================= # Check to see if EXCLUDE data should be diplayed. #========================================= if ($SHOWEXCLUDES eq "on") { print OUTPUT "<h4>EXCLUDE DATA</h4>\n"; print OUTPUT "$SHOWEXCMSG<br><br>\n"; if (@excludes == "") {print OUTPUT "No EXCLUDE Data found.<br><br>\n";} foreach $exchost (@excludes) { print OUTPUT "$exchost<br>\n"; } } print OUTPUT "</body></html>\n"; close(OUTPUT); if ($debug) { print "### Show Current HASH Values ###\n"; foreach $key (keys %HDH) {print "$key = $HDH{$key}\n";} } # rewrite the downed hosts file for next time open(HOSTSDOWN, ">$DOWNFILE") || die "Failed to open $DOWNFILE\n" ; foreach $key (keys %HDH) { print HOSTSDOWN "$key = $HDH{$key}\n"; } close(HOSTSDOWN); if ($debug) {print "### SCRIPT DONE ####\n";} #### SUB ROUTINES FOR CREATING CONFIG FILES ### sub CreateCONFIG { $defaultcc = "Y"; print "\n"x3; print "The config file $configfile does not exist.\n"; print "Would you like to create the configuration file? [$defaultcc/n]: "; chomp($ccanswer = <STDIN>); $ccanswer =~ tr/a-z/A-Z/; $ccanswer = $defaultcc unless $ccanswer; if ($debug) {print "ccanswer is $ccanswer\n";} if ($ccanswer eq "N") {exit 0;} if ($ccanswer eq "Y") { open(CCFILE, ">$configfile"); print CCFILE <<EOM; # Main Configuration File for Simple Host Monitor # Written by Chris Sawall ($myemail) # Written: $written # Last Updated: $lastupdated # Version: $version # # #=========================================== # Turn on/off functionality to monitor # firewalls or vpns. Turn on/off # function to email admins if a host is down #=========================================== MONITORVPNS = on MONITORFWS = on NOTIFY = on #=========================================== # Configure location of mail and nmap programs # # Use the complete path to the program directory. # The PORT setting defines the port in which to # scan and the PROTOCOL set either UDP or TCP. # The default IKE port is UDP 500. # # If MONITORVPNS is set to "off", then the # NMAP, PORT and PROTOCOL settings are irrelevant # # If NOTIFY is set to "off", then the MAILPROG # and DOWNMSG settings are irrelevant #=========================================== MAILPROG = /bin/mail DOWNMSG = HOST IS DOWN. NMAP = /usr/bin/nmap PORT = -p 500 PROTOCOL = -sU #=========================================== # Define file locations. This should be the # full path to the files location. # # DOWNFILE -> file to store and track down hosts # OUTFILE -> file to write output of findings # FWINFOFILE -> file containing info on hosts to scan # FWDELIMIT -> define how FWINFOFILE is delimited #=========================================== DOWNFILE = /tmp/down.hosts OUTFILE = /var/www/html/fwstat1.html FWINFOFILE = /root/firewall.hosts FWDELIMIT = : #=========================================== # Define users to email of hosts are down # Define as many as needed by simply adding # another line. Blank lines are ignored. #=========================================== EMAILADDR = fwadmin\@yourdomain.com EMAILADDR = #=========================================== # Ping Interval in minutes as set in your Crontab # # Example Crontab Line: # */4 * * * * /root/fwstat.pl # #=========================================== PINGINTERVAL = 4 #=========================================== # Define maximum number of times a host can # be found down before notifying somebody #=========================================== MAXDOWNTIMES = 3 #=========================================== # Define hosts that should be ignored # # This can be as many as needed, just add # another EXCLUDE statement. Blank lines # are ignored. # # The main purpose for this setting is so that # a host can be defined within the FWINFOINFO # file, but be temporarily ignored. Good for # times when a host is known to be down for # maintenance, but you do not want to always # be notified. #=========================================== EXCLUDE = FIREWALL03 EXCLUDE = #=========================================== # Show the exclude data with the result data # # Set SHOWEXCLUDES to on or off. # Set the message to be displayed for these # excluded hosts #=========================================== SHOWEXCLUDES = on SHOWEXCMSG = The following hosts are NOT being monitored: #=========================================== # Configure information about the website #=========================================== # Default body and text colors BDYBGND = black BDYFGND = white # Main Title and Heading WEBTTL = Firewall and VPN Status HEADING = Firewall and VPN Status # Color to display hostname in if host is found # to be up or down PINGDEVICEUPCOLOR = white PINGDEVICEDOWNCOLOR = red # Settings for info about firewalls FWSHEADING = Cisco PIX Firewalls FWSTATUSTTL = Status FIREWALLNAME = PIX Name FWLOCATIONTTL = Location FWDESCRIPTTL = Description # Settings for info about vpns VPNSHEADING = VPN Devices VPNSTATUSTTL = Status VPNNAME = VPN Name VPNLOCATIONTTL = Location VPNDESCRIPTTL = Description IPSECUPINFO = IPSEC is Listening IPSECDOWNINFO = IPSEC is NOT Listening IPSECUPCOLOR = yellow IPSECDOWNCOLOR = red ### END ### EOM close(CCFILE); print "\n"x5; print "Configuration file $configfile, has been created.\nPlease check settings.\n\n"; exit 0; } } sub CreateFWINFO { $defaultcc = "Y"; print "\n"x3; print "The host info file $FWINFOFILE does not exist.\n"; print "Would you like to create the host information file? [$defaultcc/n]: "; chomp($ccanswer = <STDIN>); $ccanswer =~ tr/a-z/A-Z/; $ccanswer = $defaultcc unless $ccanswer; if ($debug) {print "ccanswer is $ccanswer\n";} if ($ccanswer eq "N") {exit 0;} if ($ccanswer eq "Y") { open(CCFWFILE, ">$FWINFOFILE"); print CCFWFILE <<EOM; # Main Host Information file for Simple Host Monitor # Written by Chris Sawall ($myemail) # Written: $written # Last Updated: $lastupdated # Version: $version # # # This file needs to contain all of the information for the hosts # that will be monitored. The delimiter is set in the main # configuration file. The default delimiter is a colon (:). # # The first varilable must define the host to be either a VPN device # or a firewall. Use "v" for VPN or "f" for firewall. # # The basic format of each line should be: # hosttype{v/f}:host ip or name:hostname to display:location:description # # Examples: # v:10.10.6.4:Cisco 3015:STL - Main Office:Cisco 3015 Client VPN # f:192.168.232.2:FIREWALL01:STL - Tucker Street:Internet GW, Mail DMZ # f:firewall02:FIREWALL02:KCMO:Field Office, Internet Connection # #================================================================= EOM close(CCFWFILE); print "\n"x5; print "Host Infomation file $FWINFOFILE, has been created.\nPlease enter host settings.\n\n"; exit 0; } }