########################################################################## # $Id$ ########################################################################## # $Log: pluto,v $ # Revision 1.18 2009/06/05 13:50:26 mike # Patch from Geert Janssens -mgt # # Revision 1.17 2008/06/30 23:07:51 kirk # fixed copyright holders for files where I know who they should be # # Revision 1.16 2008/03/24 23:31:26 kirk # added copyright/license notice to each script # # Revision 1.15 2006/10/20 17:08:02 bjorn # Additional filtering, by Marcus Better. # # Revision 1.14 2005/12/05 23:40:13 bjorn # # Corrected attribution in log. # # Revision 1.13 2005/12/02 16:42:37 bjorn # Additional filtering of STATE changes, by Markus Better. # # Revision 1.12 2005/09/26 10:58:04 bjorn # Additional filtering contributed by Marcus Better # ########################################################################## # Note (8/28/2005, BL): # # This script was apparently written for FreeS/WAN, which is no longer # supported (see http://www.freeswan.org). But it also appears to work # with Openswan (http://www.openswan.org), which is described as a code # fork of FreeS/WAN. # # Also, notice that in this script, many variables are set, but not # printed. And many logged statements are filtered by this script. # # So this script would probably benefit from an update to clean it up # and ensure full compatibility with the newer Openswan. ########################################################################## # This is a scanner for logwatch (see www.logwatch.org) that processes # FreeSWAN's Pluto log files and attempts to # make some sense out of them. # # Please CC suggestions to mcr@freeswan.org and/or design@lists.freeswan.org # the vendorID hash maps vendor IDs to products. VendorIDs are hashs of # internal stuff from each vendor. Grow this table as you encouter new # products. ####################################################### ## Copyright (c) 2008 Kirk Bauer ## Covered under the included MIT/X-Consortium License: ## http://www.opensource.org/licenses/mit-license.php ## All modifications and contributions by other persons to ## this script are assumed to have been donated to the ## Logwatch project and thus assume the above copyright ## and licensing terms. If you want to make contributions ## under your own copyright or a different license this ## must be explicitly stated in the contribution an the ## Logwatch project reserves the right to not accept such ## contributions. If you have made significant ## contributions to this script and want to claim ## copyright please contact logwatch-devel@lists.sourceforge.net. ######################################################### $vendorID{"p....}..&..i...5..............................."}="KAME/Racoon"; $debug=0; while(<>) { # May 4 04:04:33 abigail Pluto[24170]: "abigail-istari" #1479: ISAKMP SA expired (LATEST!) chop; ($month,$day,$time,$host,$process,$conn,$msg)=split(/ +/,$_,7); $today="$month $day"; next unless ($process =~ /pluto/i); $iserror=0; if ($conn eq "ERROR:") { $iserror = 1; ($junk,$conn,$msg)=split(/ +/,$msg,3); } $loglines{$today}++; print STDERR "Msg: $msg\n" if $debug>1; if($msg =~ /([^\#]*)\#(\d*)\:(.*)/) { $ipaddr = $1; $stateinfo = $2; $rest = $3; } elsif($msg =~ /no Phase 1 state for Delete/) { $baddelete++; next; } elsif($msg =~ /from ([^:]*)\:([^:]*)\: Main Mode message is part of an unknown exchange/) { $ipaddr = $1; $ipport = $2; $badexch{"[$ipaddr]:$ipport"}++; next; } else { print STDERR "Failed to decode: $msg (of $_)\n" if $debug; next; } # print STDERR "conn: $conn IP: $ipaddr STATE: $stateinfo\n" if $debug; $conn =~ s/\"(.*)\"/$1/; $conn =~ s/\[\d\]$//; $conns{$conn}++; if(!defined($peerIP{"$conn|$ipaddr"})) { #print STDERR "Adding $ipaddr to $conn\n" if $debug; $peerIP{$conn}=$peerIP{$conn}.$ipaddr." "; } $peerIP{"$conn|$ipaddr"}++; $stateobjects{$stateinfo}++; if(!defined($peer{$stateinfo}) && length($ipaddr)>0) { $peer{$stateinfo}=$ipaddr; } # ignore following next if($rest =~ /ISAKMP SA expired/); next if($rest =~ /responding to Main Mode/); next if($rest =~ /responding to Quick Mode/); next if($rest =~ /IPsec SA expired/); next if($rest =~ /ignoring informational payload, type IPSEC_INITIAL_CONTACT/); next if($rest =~ /regenerating DH private secret to avoid Pluto 1.0 bug handling public value with leading zero/); next if($rest =~ /regenerating DH private secret to avoid Pluto 1.0 bug handling shared secret with leading zero/); next if($rest =~ /shared DH secret has leading zero -- triggers Pluto 1.0 bug/); next if($rest =~ /(received|ignoring) Delete SA(|\(0x.*\)) payload/); next if($rest =~ /received and ignored informational message/); next if($rest =~ /discarding duplicate packet; already STATE_MAIN_../); next if($rest =~ /discarding duplicate packet; already STATE_QUICK_../); next if($rest =~ /deleting state \(STATE_MAIN_..\)/); next if($rest =~ /deleting state \(STATE_QUICK_..\)/); next if($rest =~ /Quick Mode .. message is unacceptable because it uses a previously used Message ID/); next if($rest =~ /deleting connection .* instance with peer .*/); next if($rest =~ /dropping and reinitiating exchange to avoid Pluto 1.0 bug handling DH shared secret with leading zero byte/); next if($rest =~ /KE has 191 byte DH public value; 192 required/); next if($rest =~ /retransmitting in response to duplicate packet; already STATE_MAIN_../); next if($rest =~ /(Main mode p|P)eer ID is /); next if($rest =~ /transition from state .* to state/); next if($rest =~ /NAT-Traversal: Result using/); next if($rest =~ /no crl from issuer/); next if($rest =~ /I am sending (a certificate request|my cert)/); next if($rest =~ /no suitable connection for peer/); next if($rest =~ /sending encrypted notification/); next if($rest =~ /enabling possible NAT-traversal with method/); next if($rest =~ /(received|ignoring) Vendor ID payload/); next if($rest =~ /ignoring unknown Vendor ID payload/); next if($rest =~ /Dead Peer Detection \(RFC 3706\): enabled/); next if($rest =~ /DPD: No response from peer - declaring peer dead/); next if($rest =~ /DPD Error: could not find newest phase 1 state/); next if($rest =~ /Informational Exchange message is invalid because it has a previously used Message ID/); next if($rest =~ /discarding packet received during asynchronous work \(DNS or crypto\) in STATE_(MAIN|QUICK)_../); next if($rest =~ /STATE_(MAIN|QUICK)_[RI][1-3]: sent [MQ][RI][1-3], expecting [MQ][IR][1-3]/); next if($rest =~ /STATE_QUICK_R1: sent QR1, inbound IPsec SA installed, expecting QI2/); next if($rest =~ /down-client output/); next if($rest =~ /(restore|update)resolvconf-client output/); next if($rest =~ /transform .* ignored/); next if($rest =~ /multiple DH groups were set in aggressive mode\./); next if($rest =~ /received mode cfg reply/); next if($rest =~ /modecfg: Sending IP request/); next if($rest =~ /setting .* address to/); next if($rest =~ /STATE_XAUTH_I1: XAUTH client - awaiting CFG_set/); next if($rest =~ /initiating Aggressive Mode/); next if($rest =~ /Aggressive mode peer ID is/); next if($rest =~ /protocol\/port in Phase \d ID Payload must be/); next if($rest =~ /XAUTH: Bad Message: /); next if($rest =~ /XAUTH: Answering XAUTH challenge with user/); next if($rest =~ /Received IP4|DNS|subnet /); next if($rest =~ /sendto on .* to .* failed in delete notify/); $relevantlog{"$today"}++; print STDERR "Rest is $rest\n" if $debug>1; # but process these. if($rest =~ /initiating Main Mode to replace \#(.*)/) { $oldinfo = $1; $statechain{$conn.$stateinfo}="$conn|$oldinfo"; next; } elsif($rest =~ /initiating Main Mode/) { $statechain{$conn.$stateinfo}="$conn"; next; } elsif($rest =~ /initiating Quick Mode (.*) to replace \#(.*)/) { $oldinfo = $2; $phase2 = $1; $statechain{"$conn|$stateinfo"}="$conn|$oldinfo"; $quickmode{"$conn"}=$quickmode{"$conn"}." ".$phase2; next; } elsif($rest =~ /initiating Quick Mode (.*)/) { $phase2 = $1; $statechain{"$conn|$stateinfo"}="$conn"; $quickmode{"$conn"}=$quickmode{"$conn"}." ".$phase2; next; } elsif($rest =~ /ISAKMP SA established/) { $rekeysuccess{$conn}++; next; } elsif($rest =~ /cannot respond to IPsec SA request because no connection is known for (.*)/) { $rekeyfail{$conn}++; $rekeyfail_notknown{$1}++; } elsif($rest =~ /crl update is overdue since (.*)/) { $crlUpdate{$conn}++; $crlUpdateSince{$conn} = $1; next; } elsif($rest =~ /max number of retransmissions \((.*)\) reached STATE_QUICK_I./) { $rekeyfail{$conn}++; $rekeyfailQI1{$conn}++; next; } elsif($rest =~ /max number of retransmissions \((.*)\) reached STATE_QUICK_R./) { $rekeyfail{$conn}++; $rekeyfailQR1{$conn}++; next; } elsif($rest =~ /max number of retransmissions \((.*)\) reached STATE_MAIN_I./) { $rekeyfail{$conn}++; $rekeyfailI1{$conn}++; next; } elsif($rest =~ /max number of retransmissions \((.*)\) reached STATE_MAIN_R./) { $rekeyfail{$conn}++; $rekeyfailR1{$conn}++; next; } elsif($rest =~ /ERROR: asynchronous network error report on .* for message to .* port 500, complainant .*:.*errno (.*), origin ICMP type (.*) code (.*)/) { $rekeyfail{$conn}++; $rekeyfail_ICMPunreachable{$conn}++; } elsif($rest =~ /ERROR: asynchronous network error report on .* for message to .* port 500, complainant .*:.*errno (.*), origin ICMP type (.*) code (.*)/) { $rekeyfail{$conn}++; $rekeyfail_ICMPunreachable{$conn}++; } elsif($rest =~ /XAUTH: Successfully Authenticated/) { $xauthsuccess{$conn}++; } elsif($rest =~ /starting keying attempt (.*) of an unlimited number/) { $lastattempt=$1; if($maxattempts{$conn} < $lastattempt) { $maxattempts{$conn} = $lastattempt; } next; } elsif($rest =~ /Vendor ID: (.*)/) { $vid=$1; if(defined($vendorID{$vid})) { $peerID{$conn}=$vendorID{$vid}; } else { $peerID{$conn}="unknown $vid"; $vendorID{$vid}="unknown $vid at $stateinfo/$ipaddr\n"; } next; } elsif($rest =~ /prepare-client output.*/) { $setupfail{$conn}++; } elsif(($rest =~ /sent QI2, IPsec SA established/) || ($rest =~ /IPsec SA established/)) { $ipsecSAs{$conn}++; next; } else { print STDERR "UNKNOWN: $_"."\n"; } } if (keys %loglines) { print "Overview summary of log files:\n"; foreach $day (keys %loglines) { print "\t $day had ".$loglines{$day}." entries of which ".$relevantlog{$day}." were relevant\n"; } } if (keys %conns) { print "Summary by peer:\n"; foreach $conn (keys %conns) { print " Peer $conn caused $conns{$conn} lines of output.\n"; print "\tconnected from:".$peerIP{$conn}."\n"; if(defined($peerID{$conn})) { print "\tVID: ".$peerID{$conn}."\n"; } print "\tKeyed: ".($rekeysuccess{$conn}+0)." successes ",($rekeyfail{$conn}+0)." failures (max retries: ".($maxattempts{$conn}+0).")\n"; print "\tIPsec SAs: ".($ipsecSAs{$conn}+0)."\n"; if($setupfail{$conn} > 0) { print "\tSetup failures: ".$setupfail{$conn}."\n"; } if($xauthsuccess{$conn} > 0) { print "\tXAUTH successful connections: ".$xauthsuccess{$conn}."\n"; } if($crlUpdate{$conn} > 0) { print "\tOverdue CRL update since: ".$crlUpdateSince{$conn}." (".$crlUpdate{$conn}." times)\n"; } } } if (keys %badexch) { print "Summary of bad peers\n"; foreach $badpeer (keys %badexch) { print "\t".$badpeer." caused ".$badexch{$badpeer}." bad exchanges\n"; } } # vi: shiftwidth=3 tabstop=3 syntax=perl et # Local Variables: # mode: perl # perl-indent-level: 3 # indent-tabs-mode: nil # End: