#!/bin/sh
#
# script to check logs for SSH bruteforce attempts - v.0.2
# and block attackers automatically via the firewall
#
# GroundZero Security Research and Software Development 2005.
# http://www.groundzero-security.com / http://www.g-0.org
#
# released under the GNU GPL - http://www.gnu.org

 # temp files
 fail="fail.log"
 fail2="fail2.log"
 fail3="fail3.log"
 fail4="fail4.log"
 blocklist="block.lst"

 # get local interface ip
 # if you have more interfaces
 # then simply add lIP2
 lIP=`ifconfig|grep -1 eth0|grep inet|sed 's/inet addr://'|awk '{print $1}'`

 # logfile
 log="/var/log/ssh-attacker.log"

 # firewall location
 fw="`which iptables`"

 blk=""
 i=0

 while true
 do
 echo "quick ssh bruteforce blocker"
 echo "by GroundZero Security Research"
 echo "###############################"
 echo "~ using firewall: $fw"
 echo "~ get brute force attempts"

 echo "~ sorting IPs out"

 # this has been tested on 2 (Linux) development systems. 
 # might need slight changes on other systems, but should 
 # work on most. just look for the string in your logs
 # which shows the invalid/failed login 

 cat /var/log/messages |grep "Failed password" >$fail
 cat /var/log/messages |grep "Illegal user" >$fail2
 cat /var/log/messages |grep "Invalid user" >$fail3
 cat /var/log/messages |grep "Failed keyboard" >$fail4

 # you may have to adjust this a litlle, but usually you dont have to.

 if [ "` cat $fail |grep "Failed password" |awk '{ print $15 }'`" == "" ];
 then 
 	 cat $fail |grep "Failed password" |awk '{ print $11 }' >ips1
 fi
 if [ "` cat $fail2 |grep "Illegal user" |awk '{ print $14 }'`" == "" ];
 then
 	 cat $fail2 |grep "Illegal user" |awk '{ print $10 }' >ips2
 fi
 if [ "` cat $fail3 |grep "Invalid user" |awk '{ print $14 }'`" == "" ];
 then
 	 cat $fail3 |grep "Invalid user" |awk '{ print $10 }' >ips3
 fi
 if [ "` cat $fail4 |grep "Failed keyboard" |awk '{ print $17 }'`" == "" ];
 then
  	 cat $fail4 |grep "Failed keyboard" |awk '{ print $13 }' >ips4
 fi

 echo "~ sorting out ip by ip"
 for line in `cat ips1` # |read line
 do
    echo $line| grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$' >>ip.$line
 done
 for line in `cat ips2` # |read line
 do
    echo $line| grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$' >>ip.$line
 done
 for line in `cat ips3` # |read line
 do
    echo $line| grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$' >>ip.$line
 done
 for line in `cat ips4` # |read line
 do
    echo $line| grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$' >>ip.$line
 done
 
 # generating a list of all temporary files
 ls -la ip.*|awk '{ print $9 }' > ip.lst

 # check how much failed logins every ip has.
 # if the ip has more than 4 failed logins
 # it will be blocked from the host

 echo "~ checking failed logins for each ip and generate blocklist ($blocklist)"
 echo "  (avoiding: $lIP)"

 for line in `cat ip.lst` 
 do       
    if [ `wc -l $line |awk '{ print $1 }'` = '1' ];
        then
            # echo ""
            # echo "not enough failed logins, probably no attack from: $line"
            echo -n "*"
        else if [ `wc -l $line |awk '{ print $1 }'` = '2' ];
        then
            # echo ""
            # echo "not enough failed logins, probably no attack from: $line"
            echo -n "*"
        else if [ `wc -l $line |awk '{ print $1 }'` = '3' ];
        then
            # echo ""
            # echo "not enough failed logins, probably no attack from: $line"
            echo -n "*"
        else if [ `wc -l $line |awk '{ print $1 }'` = '4' ];
        then
            # echo ""
            # echo "not enough failed logins, probably no attack from: $line"
            echo -n "*"
    else   
        # generate list of the ip's to be blocked
        # echo "* IP: $line will be blocked!"
        echo -n "."
        echo $line >>$blocklist
	i=1;
        fi
 	fi
	fi
    fi
 done

if [ $i != 0 ];
then
 # edit blocklist (sometimes needs to be commented out or edited)
 cat $blocklist |sed 's/ip.::ffff://' >g && mv g $blocklist

 # cleanup
 rm -f ip.* ips1 ips2 ips3 ips4 ip.lst $fail $fail2 $fail3 $fail4

 for host in `cat $blocklist`
 do
	if ((${#host}>6)) && ((${#host}<16)) 
	then
	    blk="`echo $host| grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$'`"
	    if [[ "$blk" != "$lIP" && "$blk" != "" ]]; 
	    then
	
                echo "  blocking IP: $blk" >> $log
                $fw -A INPUT -s $blk -j REJECT
 	    fi
 	fi
 done
 cp $blocklist saved.blocklist
 rm -f $blocklist

 # left this in, in case you may not want to run this in background.
 #
 # echo "~ do you want to clean those entries from /var/log/messages ?" 
 # read -e answer

 # if [ "$answer" == "y" ];
 #   then
 	 echo "+ cleaning system logs.."
         cat /var/log/messages |grep -v "llegal user" |grep -v "ailed password" |grep -v "nvalid user"|grep -v "ailed keyboard" >m
         echo "+ creating backup of old logfile.." 
         cp /var/log/messages msg.copy
         echo "+ replacing logfile.."
         cat m > /var/log/messages
         rm -f m
 # fi
 else
     echo "no attackers found."
 fi
 echo "finished."

 # wait and loop
 sleep 20
 done
