From 3f1c98a86802fca557c585432341b6050f3f1389 Mon Sep 17 00:00:00 2001 From: madlep Date: Wed, 12 Jun 2013 15:51:13 +1000 Subject: [PATCH] Fail2Ban helper based on gist from @ktheory https://gist.github.com/ktheory/5723534 Modified slightly to use fail2ban `filter` terminology to simplify Rack::Attack initializer configuration (only one block is requred for this approach instead of 2) --- lib/rack/attack.rb | 1 + lib/rack/attack/fail2ban.rb | 42 +++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 lib/rack/attack/fail2ban.rb diff --git a/lib/rack/attack.rb b/lib/rack/attack.rb index b741478..7ff8c79 100644 --- a/lib/rack/attack.rb +++ b/lib/rack/attack.rb @@ -7,6 +7,7 @@ module Rack::Attack autoload :Blacklist, 'rack/attack/blacklist' autoload :Track, 'rack/attack/track' autoload :StoreProxy,'rack/attack/store_proxy' + autoload :Fail2Ban, 'rack/attack/fail2ban' class << self diff --git a/lib/rack/attack/fail2ban.rb b/lib/rack/attack/fail2ban.rb new file mode 100644 index 0000000..c6c2ddf --- /dev/null +++ b/lib/rack/attack/fail2ban.rb @@ -0,0 +1,42 @@ +module Rack + module Attack + class Fail2Ban + class << self + def filter(name, discriminator, options) + bantime = options[:bantime] or raise ArgumentError, "Must pass bantime option" + findtime = options[:findtime] or raise ArgumentError, "Must pass findtime option" + maxretry = options[:maxretry] or raise ArgumentError, "Must pass maxretry option" + + if yield + fail!(name, discriminator, bantime, findtime, maxretry) + else + banned?(discriminator) + end + end + + private + def fail!(name, discriminator, bantime, findtime, maxretry) + count = cache.count("#{name}:#{discriminator}", findtime) + if count >= maxretry + ban!(discriminator, bantime) + end + + # Return true for blacklist + true + end + + def ban!(discriminator, bantime) + cache.write("fail2ban:#{discriminator}", 1, bantime) + end + + def banned?(discriminator) + cache.read("fail2ban:#{discriminator}") + end + + def cache + Rack::Attack.cache + end + end + end + end +end