#!/usr/local/bin/perl use strict; use warnings; my %possibleDenyIPs = (); my %alreadyDeniedIPs = (); my $sleepSeconds = 3; my $minutes = 1; # failed logins within this number of mi +nutes my $failCriteria = 9; # number of failed logins within $minute +s minutes my @tailLines = (); while(1) { my $currentTime = pastTime(); # First we tail the last 100 lines of /var/log/secure and then grep + those lines for failed password. @tailLines = `tail -n 100 /var/log/secure | grep -i "failed passwor +d"`; my $count = @tailLines; # only need to check if the number of lines with failed password i +s greater than $failCriteria if($count > $failCriteria ) { # use those lines to get the IPs with failed passwords. my $pastTime = pastTime($minutes); %possibleDenyIPs = getPossibleDenyIPs($currentTime, $pastTime, + @tailLines); # Now we read the existing hosts.deny file for IP address alre +ady in the file. # We do NOT want duplicate entries in the /etc/hosts.deny file. %alreadyDeniedIPs = getAlreadyDeniedIPs(); # Finally we write the IP to /etc/hosts.deny, excluding any IP +already in the file. writeHostsDenyFile($failCriteria, %possibleDenyIPs); #*** ********************************************************** +******************************* } # clear all the lists @tailLines = (); %possibleDenyIPs=(); %alreadyDeniedIPs=(); # run every $sleepSeconds sleep($sleepSeconds); } ###################################################################### +############################################### sub getPossibleDenyIPs { my $currentTime = shift; my $pastTime = shift; my @tailLines = @_; my %possibleDenyIPs = (); for(my $index=0; $index<@tailLines; $index++) { if($tailLines[$index]=~/failed password/io) { chomp($tailLines[$index]); print "\nLine$index***$tailLines[$index]***\n"; my @line = split /:/,$tailLines[$index]; #showArray(@line); my $seconds = (split /\s/, $line[2])[0]; # Needs to be a numeric date versus an alpha-numeric d +ate. # Necessary so that comparisons between line date time + and past time work. my $lineTime = lineDateTime($line[0]); my $lineDateTime = $lineTime . $line[1] . $seconds; print "lineDateTime: ***$lineDateTime***\n"; print "currentTime: ***$currentTime***\n"; print "pastDateTime: ***$pastTime***\n"; #<STDIN>; # crite +ria: (1) must be failed login attempt if($lineDateTime gt $pastTime) # + (2) login is within time limit { # i.e, +lineDateTime after pastTime #************************************************* +*********************************** #my $IP = old_getIP($line[3]); my $IP = getIP($tailLines[$index]); print "Possible deny IP:***$IP***\n"; #************************************************* +************************************ $possibleDenyIPs{$IP}++; # These are +POSSIBLE deny IP's # use the IP + as a key to the hash and keep track of failed login attempts } } } return %possibleDenyIPs; } sub getIP { my $line = $_[0]; if($line =~/(\d{1,3}\.){3}\d{1,3}/) { # $&: Perl internal variable contains the pattern that wa +s matched return $&; } } sub getAlreadyDeniedIPs { my $hostsDeny = "//etc//hosts.deny"; my %deniedIPs = (); # We read the existing hosts.deny file for IP addresses already +in the file. # We do not want duplicate entries in the /etc/hosts.deny file. if(-e $hostsDeny) # if the file exists { unless(open(INDENY, "<$hostsDeny")) # readfile { warn "Can't create\\open file $hostsDeny : $!\n"; die; } while(<INDENY>) # get the IP's already in hosts.deny { my $line = $_; #print "line:***$line***\n"; if($line =~/^(\#)/io) {next;} # skip comment lines + in /etc/hosts.deny, line starts with #. else { my $IP = getIP($line); # ************************ +*************** print "Already denied IP:***$IP***\n"; if($IP) { $deniedIPs{$IP}++; } # use the IP as a ke +y to the hash and set value to TRUE (1 or greater) } } close(INDENY); } else { print "$hostsDeny does not exist\n";} return %deniedIPs; } sub writeHostsDenyFile { my $failCriteria = shift; my %possibleDenyIPs = @_; my $hostsDeny = "//etc//hosts.deny"; my $newDenyIPsFile = "//var//log//newDenyIPs"; if(-e $hostsDeny) # if the file /etc/hosts.deny already exists + append to it { if( open(INDENY, ">>$hostsDeny") ) { } +# append to file /etc/hosts.deny else { warn "Can't create\\o +pen file $hostsDeny: $!\n";} } else # if the file does not exist, create and writ +e to it { if( open(INDENY, ">$hostsDeny") ) { } + # create and write to file /etc/hosts.deny else { warn "Can't create\\op +en file $hostsDeny: $!\n";} } # this file is strictly not necessary since the /etc/hosts.deny fi +le will also contain the denied IP's if(-e $newDenyIPsFile) # if the file /var/log/newDenyIPs alrea +dy exists { if( open(INF, ">>$newDenyIPsFile") ) { } + # append to file /var/log/newDenyIPs else { warn "Can't create\ +\open file $newDenyIPsFile: $!\n";} } else { if( open(INF, ">>$newDenyIPsFile") ) { } + # create and write to file /var/log/newDenyIPs else { warn "Can't create\\ope +n file $newDenyIPsFile: $!\n";} } my $comment = commentDateTime(); foreach my $key (sort keys %possibleDenyIPs) { # If the IP has already been denied, # i.e., it is already in /etc/hosts.deny, do nothing. if($alreadyDeniedIPs{$key}) {next;} else { # If the IP has $failCriteria or more failed login attempt +s, # write a new rule in the /etc/hosts.deny file for the +IP. if( $possibleDenyIPs{$key} > $failCriteria) { print INDENY "sshd : $key $comment\n"; print INF "sshd : $key $comment failed logins: $p +ossibleDenyIPs{$key}\n"; } } } close(INDENY); close(INF); } sub pastTime # used to get current time and past time for compa +risons { my $secondsPast = 0; if($_[0]) { $secondsPast = $_[0]*60; } my $Time = time() - $secondsPast; my ($sec, $min, $hour, $monthday, $month, $year, $wday, $yday, $is +dst) = localtime ($Time); #my $thisday = qw(Sun Mon Tue Wed Thur Fri Sat)[(localtime)[6]]; #$mon = qw(Jan Feb Mar Apr May June July Aug Sept Oct Nov Dec)[(lo +caltime)[4]]; # month: Jan=0, Feb=1, Mar=3, etc. $year = $year + 1900; $month++; if($monthday < 10) {$monthday = '0' . $monthday}; if($hour < 10) {$hour = '0' . $hour}; if($min < 10) {$min = '0' . $min}; if($sec < 10) {$sec = '0' . $sec}; if($month <10) {$month = '0' . $month}; #my $timeString = "$mon ". "$monthday " . "$hour:$min:$sec"; my $timeString = $month . $monthday . "$hour$min$sec"; return $timeString; } sub lineDateTime { # date will be like May 19 10:07:25 my $dateTimeString = shift; # split on space my ($month, $monthday, $time) = split /\s/, $dateTimeString; # Need 2 digit date for comparisons like 7 10 and 7 8 to work prop +erly if($monthday && $monthday < 10) # the date { $monthday = '0' . $monthday; } # split on colon and then join # want time to be formatted as hhmmss versus hh:mm:ss my @timeString = split /:/, $time; for(my $index=0; $index<@timeString; $index++) { if($timeString[$index] < 10) { $timeString[$index] = '0' . $timeString[$index]; } } $time = join "", @timeString); # want numeric month if($month =~ /^(jan)/io) {$month = '01';} if($month =~ /^(feb)/io) {$month = '02';} if($month =~ /^(mar)/io) {$month = '03';} if($month =~ /^(apr)/io) {$month = '04';} if($month =~ /^(may)/io) {$month = '05';} if($month =~ /^(jun)/io) {$month = '06';} if($month =~ /^(jul)/io) {$month = '07';} if($month =~ /^(aug)/io) {$month = '08';} if($month =~ /^(sep)/io) {$month = '09';} if($month =~ /^(oct)/io) {$month = '10';} if($month =~ /^(nov)/io) {$month = '11';} if($month =~ /^(dec)/io) {$month = '12';} $dateTimeString = join "", $month, $monthday, $time; return $dateTimeString; } sub commentDateTime { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = l +ocaltime(); #my $thisday = qw(Sun Mon Tue Wed Thur Fri Sat)[(localtime)[6]]; $mon = qw(Jan Feb Mar Apr May June July Aug Sept Oct Nov Dec)[(local +time)[4]]; # month: Jan=0, Feb=1, Mar=3, etc. #**************mon++; if($mon < 10) {$mon = '0' . $mon}; $year = $year + 1900; #$mon++; #print "comment month = $mon\n"; if($mday < 10) {$mday = '0' . $mday}; if($hour < 10) {$hour = '0' . $hour}; if($min < 10) {$min = '0' . $min}; if($sec < 10) {$sec = '0' . $sec}; #if($mon < 10) {$mon = '0' . $mon}; my $commentDateTime = "# $year" . "$mon". "$mday " . "$hour:$min:$s +ec"; return $commentDateTime; }
In reply to RedHat Linux ssh deny by redleg7
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |