# proftpd-messages,v 1.20 2005/12/30 18:40:30 bjorn Exp $ ########################################################################## # $Log: proftpd-messages,v $ # # Revision 1.21b1 2007/03/16 # Corrected to work with current release of ProFTPD (1.3.1rc2) james treworgy jamietre@yahoo.com # NOTE this is a beta, it works for most common log entries as I have personally received and corrections # to the general format were made but many entries have not been tested. # Added support for "summarizing unmatched entries" by setting $ftpd_ignore_unmatched = 2 in proftpd-messages.conf # # Revision 1.20 2005/12/30 18:40:30 bjorn # Filtering "masquerading" statements, and corrected bug submission string, # per B Wooster. # # Revision 1.19 2005/02/24 17:08:05 kirk # Applying consolidated patches from Mike Tremaine # # Revision 1.6 2005/02/13 22:50:46 mgt # patches from Pawel -mgt # # Revision 1.5 2005/02/13 20:28:42 mgt # More init corrections -mgt # # Revision 1.4 2004/07/29 19:33:29 mgt # Chmod and removed perl call -mgt # # Revision 1.3 2004/07/10 01:54:35 mgt # sync with kirk -mgt # # Revision 1.16 2004/02/03 02:45:26 kirk # Tons of patches, and new 'oidentd' and 'shaperd' filters from # Pawe? Go?aszewski" # ######################################################## # This was written by Simon Liddington for use with Logwatch # # Please send all comments, suggestions, bug reports, # etc, to logwatch-devel@logwatch.org ######################################################## $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0; $IgnoreUnmatched = $ENV{'ftpd_ignore_unmatched'}; $NoEndpoints = 0; $UnmatchedEntries = 0; while (defined($ThisLine = )) { if ( ( $ThisLine =~ /FTP session closed./ ) or ( $ThisLine =~ /FTP session opened./ ) or ( $ThisLine =~ /^(ANONYMOUS )?FTP login as \'.*\' from [^ ]+ \[.*\] to .*/ ) or ( $ThisLine =~ /PAM\(.*\): Authentication failure/ ) or ( $ThisLine =~ /^data_sendfile/ ) or ( $ThisLine =~ / - FTP session opened/ ) or ( $ThisLine =~ / - FTP session closed/ ) or ( $ThisLine =~ / - No certificate files found/ ) or ( $ThisLine =~ /FTP (no transfer|session idle) timeout, disconnected/ ) or ( $ThisLine =~ / masquerading as / ) or ( $ThisLine =~ /FTP login timed out, disconnected/ ) or ( $ThisLine =~ /Preparing to chroot to directory \'.*\'/ ) or ( $ThisLine =~ /Data connection closed/ ) or ( $ThisLine =~ /no such user \'.*\'/ ) ) { #We don't care about these } elsif ( ($Host,$IP,$Email,) = ( $ThisLine =~ /^FTP session opened: ftp\/ftp (.*)\[(.*)\] (.*)$/ ) ) { $Temp = " " . $Host . " (" . $IP . "): " . $Email . " - "; $AnonLogins{$Temp}++; } elsif ( ($Host, $IP) = ( $ThisLine =~ /\((.*)\[(.*)\]\): ANON .+: Login successful\./ ) ) { $Temp = " " . $Host . " (" . $IP . ")"; $AnonLogins{$Temp}++; } elsif ( ($User,$Host,$IP) = ( $ThisLine =~ /^FTP session opened: (.*\/.*) (.*)\[(.*)\] (.*)$/ ) ) { $Temp = " $Host : $User - "; $UserLogins{$Temp}++; } elsif ( ($Host,$IP,$User) = ( $ThisLine =~ /\((.*)\[(.*)\]\): USER (.+): Login successful/ ) ) { $Temp = " " . $Host . ": " . $User . " - "; $UserLogins{$Temp}++; } elsif ( ($User) = ( $ThisLine =~ /^failed login, can\'t find user \'(.*)\' $/ ) ) { $Temp = " " . "Unknown" . " (" . "Unknown.IP" . "): " . $User . " - "; $BadUsers{$Temp}++; } elsif ( ($User,$Host,$IP) = ( $ThisLine =~ /USER (.*): no such user found from (.*) \[(.*)\] to/ ) ) { $Temp = " $Host \[$IP\] : $User - "; $BadUsers{$Temp}++; } elsif ( ($Host,$IP,$User) = ( $ThisLine =~ /\((.*)\[(.*)\]\): no such user \'(.*)\'.$/ ) ) { $Temp = " $Host \[$IP\] : $User - "; #$BadUsers{$User}{$Host}++; $BadUsers{$Temp}++; } elsif ( ($Host,$User) = ( $ThisLine =~ /\[(.*)\]\): USER (.*) \(Login failed\): Incorrect password/ ) ) { $Temp = " $Host : $User - "; $BadPasswds{$Temp}++; } elsif ( ($Host,$User) = ( $ThisLine =~ /\[(.*)\]\): USER (.*) \(Login failed\): Invalid shell/ ) ) { $Temp = " $Host : $User - "; $BadShell{$Temp}++; } elsif ( ($Host,$Ip) = ( $ThisLine =~ /\((.*)\[(.*)\]\): SECURITY VIOLATION: root login attempted./ ) ) { $RootLoginAttempt{$Host}++; } elsif ( ($Host,$IP) = ( $ThisLine =~ /\((.*)\[(.*)\]\): Maximum login attempts \((.*)\) exceeded/ ) ) { $Temp = " $Host \[$IP\]"; $MaxLoginAttempts{$Temp}++; } elsif ( ($Host,$IP) = ( $ThisLine =~ /\((.*)\[(.*)\]\): mod_ban\/(.*): Login denied: host \'(.*)\' banned/ ) ) { $Temp = " $Host \[$IP\]"; $HostBanned{$Temp}++; } elsif ( ($Host,$Reason) = ( $ThisLine =~ /\[(.*)\]\): Refused PORT [\d,]+ \((.*)\)/ ) ) { $Temp = " " . $Host . ": " . $Reason . " - "; $RefusedPorts{$Temp}++; } elsif ( ($Host,$Reason) = ( $ThisLine =~ /\(((.*)\[(.*)\])\): Connection refused \((.*)\)./ ) ) { $ConnectionRefused{$Reason}{$Host}++; } elsif ( ($Host) = ( $ThisLine =~ /\(((.*)\[(.*)\])\): Data transfer stall timeout/ ) ) { $TransferTimeout{$Host}++; } elsif ( $ThisLine =~ m/[^ ]*: Fatal: Transport endpoint is not connected/ ) { $NoEndpoints++; } elsif ( ($Option) = ( $ThisLine =~ /warning: (.*) is deprecated/ ) ) { $DeprecatedOptions{$Option}++; } else { # Report any unmatched entries... $UnmatchedEntries++; if ($IgnoreUnmatched == 2) { ($Host,$IP,$Message) = ($ThisLine =~ /\((.*)\[(.*)\]\): (.*)$/); if ($Message == "") { ($Message) = ($ThisLine =~ /.*: (.*)$/); $UnmatchedList{$Message . " - "}++; } else { $Temp = " $Host \[$IP\] : $Message - "; $UnmatchedList{$Temp}++; } } elsif ($IgnoreUnmatched == 0) { push @OtherList,$ThisLine . "\n"; } } } ############################################## if (keys %DeprecatedOptions) { print "\nDeprecated options in config:\n"; foreach $Option (sort {$a cmp $b} keys %DeprecatedOptions) { print " $Option\n"; } } if ( (keys %AnonLogins) and ($Detail >= 5) ) { print "\nAnonymous FTP Logins:\n"; foreach $ThisOne (sort {$a cmp $b} keys %AnonLogins) { print $ThisOne . $AnonLogins{$ThisOne} . " Time(s)\n"; } } if ( (keys %DeletedFiles) and ($Detail >= 10) ) { print "\nFiles deleted through FTP:\n"; foreach $ThisOne (sort {$a cmp $b} keys %DeletedFiles) { print $ThisOne; print @{$DeletedFiles{$ThisOne}}; } } if (keys %UserLogins) { print "\nUser FTP Logins:\n"; foreach $ThisOne (sort {$a cmp $b} keys %UserLogins) { print $ThisOne . $UserLogins{$ThisOne} . " Time(s)\n"; } } if (keys %RootLoginAttempt) { print "\nSECURITY VIOLATION!!!!\n"; print "Root login attempt from:\n"; foreach $Host (sort {$a cmp $b} keys %RootLoginAttempt) { print " $Host : $RootLoginAttempt{$Host} Time(s)\n"; } } if (keys %MaxLoginAttempts) { print "\nMaximum login attempts exceeded from hosts:\n"; foreach $Host (sort {$a cmp $b} keys %MaxLoginAttempts) { print " $Host : $MaxLoginAttempts{$Host} Time(s)\n"; } } if (keys %HostBanned) { print "\nHost banned by mod_ban:\n"; foreach $Host (sort {$a cmp $b} keys %HostBanned) { print " $Host : $HostBanned{$Host} Time(s)\n"; } } if (keys %ConnectionRefused) { print "\nConnection refused with reason:\n"; foreach $Reason (sort {$a cmp $b} keys %ConnectionRefused) { print " $Reason :\n"; foreach $Host (sort {$a cmp $b} keys %{$ConnectionRefused{$Reason}}) { print " $Host : $ConnectionRefused{$Reason}{$Host} Time(s)\n"; } } } if ((keys %BadUsers) or (keys %BadPasswds)) { print "\nFailed FTP Logins:\n"; if (keys %BadUsers) { print "\n Invalid Username:\n"; foreach $ThisOne (sort {$a cmp $b} keys %BadUsers) { print $ThisOne . $BadUsers{$ThisOne} . " Time(s)\n"; } } if (keys %BadPasswds) { print "\n Invalid Password:\n"; foreach $ThisOne (sort {$a cmp $b} keys %BadPasswds) { print $ThisOne . $BadPasswds{$ThisOne} . " Time(s)\n"; } } if (keys %BadShell) { print "\n Invalid Shell:\n"; foreach $ThisOne (sort {$a cmp $b} keys %BadShell) { print $ThisOne . $BadShell{$ThisOne} . " Time(s)\n"; } } } if ( (keys %RefusedPorts) and ($Detail >= 5) ) { print "\nRefused PORTs:\n"; foreach $ThisOne (sort {$a cmp $b} keys %RefusedPorts) { print $ThisOne . $RefusedPorts{$ThisOne} . " Time(s)\n"; } } if ( (keys %TransferTimeout) and ($Detail >= 5) ) { print "\nData transfer stall timeout:\n"; foreach $Host (sort {$a cmp $b} keys %TransferTimeout) { print " $Host : $TransferTimeout{$Host} Time(s)\n"; } } if ($NoEndpoints > 0) { print "\nTransport endpoint is not connected error $NoEndpoints Time(s)\n"; } if ($UnmatchedEntries > 0) { print "\n**Unmatched Entries** ($UnmatchedEntries)\n\n"; if ($IgnoreUnmatched == 0 ) { print @OtherList; } elsif ($IgnoreUnmatched == 2) { if (keys %UnmatchedList) { foreach $ThisOne (sort {$a cmp $b} keys %UnmatchedList) { print $ThisOne . $UnmatchedList{$ThisOne} . " Time(s) \n"; } } } } exit(0); # vi: shiftwidth=3 tabstop=3 syntax=perl et