#!/usr/bin/perl -w # # Watch syslog for ssh, ftp or dovecot attacks. Call like this: # sshwatch.pl ) { } while (1) { sleep $pause_time; $t = time(); foreach $ip (keys(%times)) { $age = $t - $times{$ip}; if ($age > $block_time) { if (defined($blocked{$ip})) { Unix::Syslog::syslog(Unix::Syslog::LOG_INFO, "$ip blocked for more than $block_time seconds, unblocking"); $cmd = sprintf $unblock_cmd, $ip; Unix::Syslog::syslog(Unix::Syslog::LOG_INFO, $cmd); system $cmd; delete $blocked{$ip}; } else { Unix::Syslog::syslog(Unix::Syslog::LOG_INFO, "forgetting $tries{$ip} failed logins from $ip after $block_time seconds") } delete $times{$ip}; delete $tries{$ip}; } } while ($line = ) { chomp($line); $ip = ""; if ($line =~ /sshd.*Failed password for.*from/) { ($ip = $line) =~ s/.*from ([^ ]*) .*/$1/; } elsif ($line =~ /dovecot.*auth failed/) { ($ip = $line) =~ s/.*rip=([^,]*),.*/$1/; } elsif ($line =~ /ftpd.*Authentication failed/) { ($ip = $line) =~ s/.*\@([^\)]*)\).*/$1/; } if ($ip ne "") { $times{$ip} = $t; if (defined($tries{$ip})) { $tries{$ip}++; } else { $tries{$ip} = 1; } Unix::Syslog::syslog(Unix::Syslog::LOG_INFO, "possible attack from $ip: $tries{$ip} failed logins"); if ($tries{$ip} == 6) { Unix::Syslog::syslog(Unix::Syslog::LOG_INFO, "more than 5 failed logins from $ip, blocking"); $cmd = sprintf $block_cmd, $ip; Unix::Syslog::syslog(Unix::Syslog::LOG_INFO, $cmd); system $cmd; $blocked{$ip} = $t; } } } }