Disabling failed ssh logins from script kiddies

I have been getting a huge number of failed login attempts on my web server. These have been anoying for two reasons.
  1. Someone is trying to hack into my machines.
  2. The machine can slow to a crawl when trying to deal with the thousands of requests that I am getting. Causing my web services to slow down.

So, the question is:

How can I deal with this?

Some common suggestions:

  1. Change your port to a non-standard port such as 2222, or some other random number. I agree that this does work, but it can be annoying if my applications cant be configured to connect to a non-standard port.
  2. Use port knocking to keep the port closed, until the right sequence of ports have been probed. This sounds more elegant than changing the port number, but again if my programs cant do this, then I need some sort of hack to get the port open.

I have gone for a slightly different approach, which is to setup a cronjob to monitor my log files and add the offenders to a list of banned ip addresses. The code was written in ruby and is running on a debian server

Without further ado, here is the code:
#!/usr/bin/ruby -T


# hash of found ips used to store the ips found in the 
# auth.log
ipFound = Hash.new(0)

puts 'Checking for scanning attempts'

# 1. read in the auth.log
authLog = File.open('/var/log/auth.log','r')

authLog.each_line { |line|
  # 2. check for the ip addresses that are scanning
  if line =~ /Failed password for invalid user/
    if line =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/
      @ipaddress = $1
      #add it to the list
      ipFound[@ipaddress] += 1
    end
  end
}

authLog.close

# hash used to store the ips that are already banned
ipDenied = Hash.new(0)

# open the list of banned ip adresses
hostsDeny = File.open('/etc/hosts.deny','r')

hostsDeny.each_line { |line|
  if line =~ /ALL:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/
    ipDenied[$1] += 1
  end
}

hostsDeny.close

# if ip not in denied list or from the local network,
# then add it

hostsDenied = File.open('/etc/hosts.deny','a')

ipFound.each_pair { |ip,count|
  puts "IP:#{ip} -> #{count}"
  if ipDenied[ip] != 0
    puts "IP Already denied"
    next
  end
  if ip =~ /^192.168.1/
    puts "IP in local network"
    next
  end
  if count < 10
    puts "Didn't scan that much"
    next
  end
  puts "Adding to the denied list"
  hostsDenied << "ALL:#{ip}\n"
}

hostsDenied.close

puts "Done"
And that's all there is for the code. Then all I did was install it in the root crontab with the following line:
10 * * * * /path/to/banning_code 2>&1 | Mail -s 'offender ban run' you@your.domain
Now it gets run every ten minutes and adds login offenders to the banned list. There is loads more that could be done with this code and it doesn't check for some edge cases, but it will catch most of the script kiddies and get rid of them, until their ip address changes :-(

Posted by neomorphic Sat, 29 Dec 2007 18:44:00 GMT



weewar.com corner