#!/usr/bin/perl # This script watches the /var/log/secure for failed ssh attempts. Wh +en found, it will add a reject route to your routing table, making it + impossible for your machine to communicate with that host again. # # Written By: Matt Joubert (matt __at__ uucp _dot_ ca) # Date: June 2, 2006 # use strict; use warnings; use Sys::Syslog; # define ssh log file location my $logFile = '/var/log/secure'; # syslog facility my $syslogFac = 'local0'; # syslog level my $syslogLevel = 'info'; # SAFE IPS, NEVER BLOCK (I sometimes forget a password..) my @safe = qw/ 192.168.0.1 /; # define threshold in minutes to reset the failed attempt counter # note, this shouldn't be nuts because if set to high, you could shoot + yourself in the foot my $thresHold = 10; # minutes my $maxAttempts = 5; ##### Probably wont need to change anything below ##### use File::Tail; use Time::ParseDate; $thresHold *= 60; # convert to seconds; my $fh = File::Tail->new( name => $logFile, maxinterval => 10, interval => 10, adjustafter => 5 ) || die ("could not open log file: $!"); # at this point, the file is open.. so the rest should be able to work + fine in fork. defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; my %db; my @rejects; while ( my $line = $fh->read ) { # ignore all lines except for the failed ones next unless $line =~ /Failed password/ig; my @column = split ( /\s+/, $line ); # grab the IP address $line =~ m/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/g; my $ip = $1; next unless $ip; next if safe( $ip, @safe ); my ( $mon, $day, $time ) = (@column)[ 0, 1, 2 ]; my $epoch = parsedate("$mon $day $time"); if ( !defined( $db{$ip} ) ) { push ( @{ $db{$ip} }, $epoch ); } else { push ( @{ $db{$ip} }, $epoch ); # past threshold.. start over from scratch if ( $db{$ip}[ $#{ $db{$ip} } ] - $db{$ip}[ $#{ $db{$ip} } - 1 + ] > $thresHold ) { undef( $db{$ip} ); push ( @{ $db{$ip} }, $epoch ); } else { # threshold is good - check for attempts if ( scalar @{ $db{$ip} } > $maxAttempts ) { if ( !isRejected( $ip, @rejects ) ) { push ( @rejects, $ip ); syslog("$syslogLevel|$syslogFac", "Adding $ip to r +eject route table for too many failed attempts"); system("/sbin/route add -host $ip reject"); } } } } } # check if ip is "safe" from being blocked sub safe { my $ip = shift; my @safe = @_; foreach (@safe) { return 1 if $ip eq $_; } return 0; } # check if ip has alread been recently reacted too sub isRejected { my $ip = shift; my @rejects = @_; foreach (@rejects) { return 1 if $ip eq $_; } return 0; }
In reply to SSH Failed Attempt Monitor by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |