Hi there,
 
Here is a simple script I've coded up that I use on 3 of my RedHat Enterprise Linux 3 (RHEL3) servers. I decided to do this after seeing the
amount of activity from places like China/Korea/Taiwan in relation to SSH brute force probes. I'll throw it open here for analysis/suggestions. It
leverages off the TCPWrappers /etc/hosts.deny /etc/hosts.allow functionality.
 
Naturally I could implement SSH port-knocking or something similar or move the SSH port, but I feel that I'm pretty well off blocking the sorts
of hosts that would attempt this in the first place, as they seem to mainly be compromised unix boxen and are persistent, and why should I
change on their behalf?
 
It may have a bugs related to counting the attacks, but otherwise it is solid. The thing you want to keep in mind is that you should add friendly
hosts to /etc/hosts.allow lest they get blocked by accident. /etc/hosts.allow will override /etc/hosts.deny always, even if a host is accidentally
added there. I have yet to code up an exclusions list technique that would achieve a similar effect.
 
I don't want to debate the goodness or badness of the strategy of blocking hosts like this in /etc/hosts.deny. It works perfectly for me, and most
likely would for you, so no religious debates thanks. It's effective at blocking bruteforce attacks. If a host EXCEEDS a specified number of guesses
during the (configurable) 30 seconds it takes the script to cycle, the host is blacklisted.
 
The script is simple, and it is one script, it doesn't require gobs of documentation, CPU, or ancillary files as some methods appear to. It uses Korn
shell simply because that's my preferred shell, it could be easily ported to other shells as it lacks any complexity.
 
I have left in some of the original lines of code during development, but they can be safely removed.
 
I hope it proves of some use to you.
 
-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<
 
#!/bin/ksh
#
# ssh_brute_blocker
#
# 05/07/2004 15:05 - Michael L. Benjamin
#
 
SCRIPT_NAME=$(basename $0)
LOG_FILE="/var/log/secure"
DENY_FILE="/etc/hosts.deny"
TMP_FILE="/tmp/${SCRIPT_NAME}.$$"
INBOUND_IP=""
INLINE=""
GUESS_COUNT=0
PERMIT_GUESS=4
 
touch ${TMP_FILE}
 
while :
do
 
tail -10000 ${LOG_FILE} | grep "Failed password for illegal user" | awk -F"from" {'print $2'} | awk {'print $1'} | uniq > ${TMP_FILE}
 
while read -r INBOUND_IP
do
  GUESS_COUNT=0
#  GUESS_COUNT=$(grep ${INBOUND_IP} ${LOG_FILE} | wc -l)
  GUESS_COUNT=$(grep "from ${INBOUND_IP}" /var/log/secure | grep "Failed password for" | wc -l | awk {'print $1'})
 
#  echo IP: ${INBOUND_IP} made ${GUESS_COUNT} guesses against our server
 
  if [ ${GUESS_COUNT} -ge ${PERMIT_GUESS} ]
  then
      if grep ${INBOUND_IP} ${DENY_FILE} > /dev/null
      then
#          echo ${INBOUND_IP} is already listed in ${DENY_FILE} ; echo
           echo > /dev/null
      else
#          echo ${INBOUND_IP} is not listed. Adding host ${INBOUND_IP} to ${DENY_FILE} ; echo
          echo "ALL: ${INBOUND_IP}" >> ${DENY_FILE}
          /usr/bin/logger -t ssh_brute_blocker -is Added SSH attacking host ${INBOUND_IP} to ${DENY_FILE} [${GUESS_COUNT} attempts].
  fi
  else
#     echo Ignoring host ${INBOUND_IP} less than ${PERMIT_GUESS} wrong guesses.
      echo > /dev/null
  fi
 
done < ${TMP_FILE}
 
sleep 30
 
rm -f ${TMP_FILE}
 
done
 
exit 0
 
-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<
 
 
I call it as follows in /etc/rc.local, and runs completely silently in the background blocking bad hosts:
 
 
# Fire up ssh_brute_blocker security script
 
/usr/local/scripts/ssh_brute_blocker &
 
-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<
 
I also have some webpages that I generate to show me /etc/hosts.deny, count blocked hosts and report on blocked hosts from /var/log/messages
eg:
 
Aug 29 03:05:57 XXXXXXXXXXXX ssh_brute_blocker[20644]: Added SSH attacking host 83.133.125.4 to /etc/hosts.deny [4 attempts].
Aug 29 13:18:33 XXXXXXXXXXXX ssh_brute_blocker[15590]: Added SSH attacking host 220.82.197.48 to /etc/hosts.deny [4 attempts].
Aug 30 04:24:39 XXXXXXXXXXXX ssh_brute_blocker[20637]: Added SSH attacking host 203.98.150.6 to /etc/hosts.deny [9 attempts].
Aug 30 19:24:08 XXXXXXXXXXXX ssh_brute_blocker[10139]: Added SSH attacking host 62.61.140.116 to /etc/hosts.deny [8 attempts].
Sep  1 03:49:01 XXXXXXXXXXXX ssh_brute_blocker[4104]: Added SSH attacking host 83.16.116.110 to /etc/hosts.deny [5 attempts].
Sep  2 02:48:22 XXXXXXXXXXXX ssh_brute_blocker[1633]: Added SSH attacking host 60.248.154.162 to /etc/hosts.deny [8 attempts].
 
IP's have been left in place to un-protect the guilty...
 
 
Here are some typical attacks logged to /var/log/secure:
 
Aug 30 04:24:02 XXXXXXXXXXXX sshd[20561]: Illegal user patrick from 203.98.150.6
Aug 30 04:24:06 XXXXXXXXXXXX sshd[20563]: Illegal user patrick from 203.98.150.6
Aug 30 04:24:32 XXXXXXXXXXXX sshd[20604]: Illegal user rolo from 203.98.150.6
Aug 30 04:24:37 XXXXXXXXXXXX sshd[20606]: Illegal user iceuser from 203.98.150.6
Aug 30 05:48:43 XXXXXXXXXXXX sshd[31199]: Illegal user test from 218.69.8.78
Aug 30 19:23:15 XXXXXXXXXXXX sshd[10045]: Illegal user test from 62.61.140.116
Aug 30 19:23:23 XXXXXXXXXXXX sshd[10047]: Illegal user guest from 62.61.140.116
Aug 30 19:23:29 XXXXXXXXXXXX sshd[10049]: Illegal user admin from 62.61.140.116
Aug 30 19:23:36 XXXXXXXXXXXX sshd[10051]: Illegal user admin from 62.61.140.116
Aug 30 19:23:42 XXXXXXXXXXXX sshd[10091]: Illegal user user from 62.61.140.116
Aug 30 19:24:06 XXXXXXXXXXXX sshd[10099]: Illegal user test from 62.61.140.116
Aug 31 09:52:59 XXXXXXXXXXXX sshd[4375]: Illegal user test from 211.147.5.54
Sep  1 03:48:34 XXXXXXXXXXXX sshd[4000]: Illegal user fluffy from 83.16.116.110
Sep  1 03:48:41 XXXXXXXXXXXX sshd[4049]: Illegal user admin from 83.16.116.110
Sep  1 03:48:49 XXXXXXXXXXXX sshd[4051]: Illegal user test from 83.16.116.110
Sep  1 03:48:56 XXXXXXXXXXXX sshd[4053]: Illegal user guest from 83.16.116.110
Sep  1 03:49:04 XXXXXXXXXXXX sshd[4055]: Illegal user webmaster from 83.16.116.110
Sep  1 21:17:35 XXXXXXXXXXXX sshd[11002]: Illegal user admin from 202.129.34.101
Sep  2 02:47:27 XXXXXXXXXXXX sshd[1505]: Illegal user alin from 60.248.154.162
Sep  2 02:47:41 XXXXXXXXXXXX sshd[1507]: Illegal user alin from 60.248.154.162
Sep  2 02:47:46 XXXXXXXXXXXX sshd[1509]: Illegal user theo from 60.248.154.162
Sep  2 02:47:51 XXXXXXXXXXXX sshd[1511]: Illegal user theo from 60.248.154.162
Sep  2 02:48:00 XXXXXXXXXXXX sshd[1569]: Illegal user theo from 60.248.154.162
Sep  2 02:48:10 XXXXXXXXXXXX sshd[1571]: Illegal user damian from 60.248.154.162
Sep  2 02:48:15 XXXXXXXXXXXX sshd[1573]: Illegal user damian from 60.248.154.162
Sep  2 02:48:20 XXXXXXXXXXXX sshd[1575]: Illegal user comun from 60.248.154.162
 
 
Cheers, Mike.
 
 
 
_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/

Reply via email to