Sep 132009
 

(from tuxopia.net)

I was troubled by the fact that my server was constantly being bombarded with SSH probes for as long as 1 to 2 hours at a stretch. Although the SSH daemon configuration has been tuned for security like disabling root access, allowing only a certain list of users, etc., a continuous SSH probe is still disturbing. I could block all other IPs for SSH access except for the ones that I use, but who knows where I will be when I need to SSH to my machine? I could be on any where. So the solution, I found was to just block SSH access to IPs that were violating my server’s and my peace. Since, I know that many of you out there have seen such attacks in your logs, I will share the script with you and a short explanation of how it works.
The Logic

Whenever an invalid ssh login appears you usually get a log message like

May 3 13:21:44 bell sshd[11909]: Failed password for invalid user root from 90.228.208.201 port 59948 ssh2

So we need to grep the lines from the log that have “Failed Password” in them. This can be done by

grep “Failed Password” /var/log/messages

Now that we have the lines we can grab the IP. Note that the IP is the 4th item from the end of line. To grab it we will pipe the output of previous command to awk.

grep “Failed Password” /var/log/messages |awk ‘{a=NF-3; print $a}’

Unfortunately this gives us duplicate IPs as well. we need to count how many times each IP has failed, since even our own IP may be in the list. Chances are legitimate users could be bloked too. So we need a count. we can do this using uniq command. Also for sake of redability lets sort it numerically and remove the spaces at the beginning of the line we get with output of uniq.

grep ‘Failed password’ /var/log/messages | awk ‘{ a=NF-3; print $a}’ |uniq -c| sed ‘s/^ *//’ | sort -n

Once we have got this it is only a matter of checking if each IP which is above the bad countlevel exists in /etc/hosts.deny and add the ones that are not.
The Script

Compiling all this together we have our bash script:

#!/bin/bash
AWK=/bin/awk
SORT=/bin/sort
GREP=/bin/grep
UNIQ=/bin/uniq
SED=/bin/sed
LOGFILE=/var/log/messages
BADCOUNT=”5″

$GREP ‘Failed password’ $LOGFILE | $AWK ‘{ a=NF-3; print $a}’ | $UNIQ -c| $SED ‘s/^ *//’| $SORT -n | while read i
do
COUNT=`echo $i | cut -d ” ” -f1`
IP=`echo $i | cut -d ” ” -f2`
INLIST=`$GREP $IP /etc/hosts.deny | $GREP sshd`
if [ -z “$INLIST” ]
then
if [ “$COUNT” -ge “$BADCOUNT” ]
then
echo “sshd: $IP” >> /etc/hosts.deny
fi
fi
done

Since, I will be away for a month, I decided to add this to cron as well running every minute every hour, every day. So the cron entry reads

* * * * * /root/bin/ssh-block.sh 1> /dev/null

Note that although this will block the IP from making yet another SSH probe, the machine will be able to make probes for about a minute before it is blocked. So you need to be sure to strengthen your SSHD configuration.

Hope this helps you guys.

NOTE: The script is a modified version from a script I found on Novel’s site http://www.novell.com/coolsolutions/tools/19769.html My editted version removes one of the vulnerabilty of the Novel script that would allow an attacker to log inject an IP. So the credit for the original script goes to the original author.
Bookmark/Search this post with:

 Posted by at 8:18 am

 Leave a Reply