Below (and atached) is a script I wrote do exactly what you are talking about. It's commented, so edit to your taste. I have been using to for about 4 months.
Since I am using PF as my firewall, it is customized for that. If you are using something other then PF, again... edit to your taste. -Erik- #!/usr/bin/perl # created by [EMAIL PROTECTED] 03/05 my $time=localtime(); use strict; use Time::localtime; use Mail::Send; my $hostname="domain.orIP.com"; #The white list that contains either the account or host. my $whilelist="/home/user/scripts/sshwhitelist"; #LOG to search on my $logfile="/var/log/auth.log"; #Where to read the current list of blackhole address. my $blacklist="/etc/pf.blackholes"; #Name of the table in your pf.conf my $tablename="blackhole"; #Where to store the cache file. This is removed and updated daily my $cache="/root/.sshprotect.cache"; #Where to log actions taken. my $log="/root/sshprotect.log"; #Command you want to run in response of a potential attack. my $command="whois"; my $useip=1; #useful in conjunction with $command which will do something with the IP. #comment out if not needed. #Max attempts a host can have until blocked. my $attempts=5; # Set this to "run" the $command or "print" a report or "email" the report, # also "update" will update the $blacklist and reload the blackholes table. # "abuse" will try to find and email the offending network about the attack # These can be combind to run all actions: #my $action="run print"; #my $action="print"; my $action="email run update abuse"; #my $action="print email update"; #my $action="print email"; #Email setup; my $to="[EMAIL PROTECTED]"; my $from="[EMAIL PROTECTED]"; my $cc=""; my $subject="Excesssive login attempts"; my $debug=0; my $host; my @logs; my @whtlst; my %track; my @blacklist; my $block=1; my @abuse; my @cache; my $currentcache; my @runoutput; my $version="1.2.1beta"; print "Version: $version\n" if $debug; #find todays datemask use vars qw($yr $mon $day $today $mday); $yr=localtime->year() + 1900; $mon=localtime->mon() + 1; $mday=localtime->mday(); if ($mon != /\d\d/) {$mon="0$mon";} if ($mday < 10) {$mday="0$mday";} $today="$yr$mon$mday"; print "$today\n" if $debug; #no Time::localtime; open (WRITELOG, ">> $log") || die "$log $!\n"; open (BLACK,$blacklist) || die "$blacklist $!\n"; while (<BLACK>) { chomp; push (@blacklist, $_); } close BLACK; open (WHITE, $whilelist) || die "$whilelist $!\n"; while (<WHITE>) { chomp; push (@whtlst,$_); } close WHITE; open (READCACHE, $cache) || print "$cache $!\n"; while (<READCACHE>) { chomp; push (@cache, $_); } close READCACHE; open (WRITECACHE, ">> $cache") || print "$cache $!\n"; if (@cache[0] < $today) { close WRITECACHE; system ("rm -f $cache"); open (WRITECACHE, ">> $cache") || print "$cache $!\n"; print "Cache file is out of date @cache[0] < $today\n" if $debug; @cache=(); print WRITECACHE "$today\n" } open (LOG, $logfile) || die "logfile $!"; while (<LOG>) { chomp; if ( /Failed password for illegal user (.*) from (.*) port/ || /Failed password for (.*) from (.*) port/ || /Illegal user (.*) from (.*)/ || /Did not (receive) identification string from (.*)/ ) { my $account=$1; my $host=$2; ckwhtlst($account, $host); if ($block == 0 ) { next; } ckcache($host); if ($block == 0 ) { next; } ckblklst($host); if ($block == 0 ) { next; } $block=1; if ($track{$host}) { $track{$host}=$track{$host}+1; print "$host is now $track{$host} user=$account\n" if $debug; } else { $track{$host}=1; } } } close LOG; for my $host (%track) { if (!$host) {print "Nothing Found\n"; exit;} if ($track{$host} >= $attempts) { push (@abuse,$host); ckcache($host); print WRITECACHE "$host\n" if !$block == 0; if ($action =~ /print/) { print "Host $host, past $attempts attempted logins\n"; } if ($action =~ /run/ && $useip) { (@runoutput=`$command $host`); } if ($action =~ /run/ && !$useip) { (@runoutput=`$command`); } if ($action =~ /update/) { update($host); } } } #Sends emails if ($action !~/email/) { exit; } elsif (@abuse) { send_email(@abuse); } if ($action !~/abuse/) { exit; } elsif (@abuse) { abuse_email(@abuse); } sub ckwhtlst { (my $account, my $host)[EMAIL PROTECTED]; foreach (@whtlst) { if (!/$account|$host/) { $block=1; return; } else { print "$host or $account is on the while list.\n" if $debug; $block=0; return; } } } sub ckblklst { my [EMAIL PROTECTED]; foreach (@blacklist) { if (/$host/) { print "$host $_ is already blacklisted\n" if $debug; $block=0; return; } else { $block=1; } #print "$host is NOT blacklisted\n" if $debug; } } } sub ckcache { my [EMAIL PROTECTED]; if ([EMAIL PROTECTED]) { $block=1; return;} foreach (@cache) { if (/$host/) { $block=0; print "$host is already cached\n" if $debug; return; } else { $block=1; } #print "$host is not found in cache\n" if $debug; } } } sub update { open (OUT, ">> $blacklist") || die "$blacklist $!\n"; print OUT "@_[0]\n"; system ("pfctl -t $tablename -f /etc/pf.conf"); close OUT; } sub send_email { my $subject="$subject $today"; my $msg = new Mail::Send; my $host; $msg->subject($subject); $msg->to($to); $msg->cc($cc) if $cc; $msg->add("From", "$from"); $msg->add("Return-Path", "$from"); $msg->add("Reply-To", "$from"); my $fh=$msg->open; foreach (@_) { $host=$_; if (!$track{$_}) {return;} print $fh "\nThe host $_ has $track{$_} attempted logins.\n"; } print $fh "\nThe threshold is set to $attempts attempts\n"; print $fh "\nActions taken: $action\n\n"; if (($action =~/run/ && $command) && !$useip) { print $fh "Ran: $command\n\n Output:[EMAIL PROTECTED]"; } if (($action =~/run/ && $command) && $useip) { print $fh "Ran: $command $host,\n\n Output:[EMAIL PROTECTED]"; } print $fh "\nVersion: $version\n"; print "Sending email\n" if $debug; print WRITELOG "$time Sent email to $to about $_ \"$subject\"\n"; $fh->close; } sub abuse_email { $subject="[ABUSE] $subject $today"; my $msg; my $fh; my $acct; my $domain; foreach my $ip (@_) { my $syntax="$ip SOA"; if (!$track{$ip}) {return;} if (~/\d{1,3\.\d{1,3}\.\d{1,3}\.\d{1,3}/) { $syntax="-x $ip SOA"; } print "Running dig $syntax\n" if $debug; my @dig=`/usr/bin/dig $syntax`; foreach my $dig (@dig) { if ($dig =~ /in-addr\.arpa\..*SOA\t.*\. (.*)\./) { my $addy=$1; if (!$addy) { next; } if ($addy =~ /(\w+)\.(.+)/) { $acct=$1; $domain=$2; } $to="[EMAIL PROTECTED]"; print "Found $to from Dig\n" if $debug; $msg = new Mail::Send; $msg->subject($subject); $msg->to($to); $msg->cc($cc) if $cc; $msg->add("From", "$from"); $msg->add("Return-Path", "$from"); $msg->add("Reply-To", "$from"); $fh=$msg->open; print $fh "\nThis host $ip has attempted $track{$ip} erroneous ssh logins to my server $hostname on $today.\n"; print $fh "Please report this to your customer and advise them on any AUP violations you enforce.\n"; print $fh "\n\nThank you\nErik\n"; print $fh "\nVersion: $version\n" if $debug; print "Sending abuse email to $to\n" if $debug; print WRITELOG "$time ABUSE:Sent email to $to about $ip\n"; $fh->close; } } } } close WRITECACHE; close LOG; use Data::Dumper; print Dumper %track if $debug; On 7/1/05, John Cholewa <[EMAIL PROTECTED]> wrote: > Jun 30 10:36:05 phantom sshd[70478]: Failed password for news from > 212.88.182.121 port 51218 ssh2 > Jun 30 10:36:16 phantom sshd[70500]: Failed password for sshd from > 212.88.182.121 port 51608 ssh2 > Jun 30 10:36:39 phantom sshd[70569]: Failed password for root from > 212.88.182.121 port 52297 ssh2 > > I get the above a lot in my logs (except more of it). Each day, a couple > hundred failed attempts to log in from one or sometimes two IP addresses > shows up. I don't have anything like ipf running, and since this machine is > about fifteen hundred miles away from me, I don't want to experiment with > software firewalling right now. > > That known, is there any way to tell sshd (or some more powerful daemon) to > stop accepting login attempts from a given IP if it tries and fails to log in > too many times in a limited duration (like in the same minute)? > > I suppose, now that I'm thinking about it, that it'd be best to actually just > read the man pages and figure out how to get sshd to ignore any attempt to > attach from ports other than 22. I mean, why are other machines trying to > ssh in at ports over fifty thousand anyway? > > -- > -JC > http://www.livejournal.com/users/jcholewa/ > > PS: Oh, yeah ... "FreeBSD 4.8-RELEASE #0: Thu Apr 3 10:53:38 GMT 2003" ; > openssh-3.6.1_5 ; openssl-0.9.7d_1 > > > > _______________________________________________ > freebsd-questions@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-questions > To unsubscribe, send any mail to "[EMAIL PROTECTED]" >
sshprotect.pl
Description: Binary data
_______________________________________________ freebsd-questions@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-questions To unsubscribe, send any mail to "[EMAIL PROTECTED]"