From 18df2dadf8363b4b202497a68eb54bafee35d8ab Mon Sep 17 00:00:00 2001 From: swaits Date: Sat, 4 Mar 2006 17:06:28 +0000 Subject: [PATCH] function sshd brute force blocker script --- sshbruted.rb | 84 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/sshbruted.rb b/sshbruted.rb index 778b56a..b224f27 100644 --- a/sshbruted.rb +++ b/sshbruted.rb @@ -1,9 +1,81 @@ +#!/usr/bin/env ruby -regexp = /(.+).+mailsystem sshd\[\d+\]: Failed ([\A ]+) for ([\A\s]+) from ([\d\.]+) port (\d+) ssh2/ -match = regexp.match(subject) -if match - result = match[1] -else - result = "" +require 'time' +require 'thread' + +LOG_COMMAND = "/usr/bin/tail -F /var/log/auth.log" +BLACKLIST = "/etc/hosts.blacklist" +MAX_FAILURES = 3 +TIME_LIMIT = 30 * 60 # 30 minutes + +class Blacklister + def initialize + @iplog = Hash.new([]) + @iplog_lock = Mutex.new + end + + def add_hit(ip,time) + @iplog_lock.synchronize do + @iplog[ip] += [time] + end + end + + def list + badlist = [] + @iplog_lock.synchronize do + # clean up stale entries + @iplog.reject! { |ip,times| stale_entry(times) } + + # create our blacklist + @iplog.each { |ip,times| badlist << ip if fresh_count(times) > MAX_FAILURES } + end + badlist.sort + end + + private + + def fresh_count(times) + fresh_times = times.select { |t| (Time.now - t) < TIME_LIMIT } + fresh_times.size + end + + def stale_entry(times) + fresh_count(times) == 0 + end end + +blacklister = Blacklister.new + + +input_thread = Thread.new do + regexp = /(.+) [^\s]+ sshd\[\d+\]: Failed ([^\s]+) for ([\w\s]+?) from ([\d\.]+) port (\d+) ssh2/ + logfile = IO.popen(LOG_COMMAND) + while line = logfile.gets + match = regexp.match(line) + if match + time = Time.parse(match[1]) + ip = match[4] + blacklister.add_hit(ip,time) + end + end +end + + +output_thread = Thread.new do + list = [] + loop do + sleep 2 + new_list = blacklister.list.join("\n") + if new_list != list + File.open(BLACKLIST,"w") { |f| f.puts(new_list) } + #puts "[#{Time.now}]\n#{new_list}" + list = new_list + end + end +end + + +input_thread.join + +