class Rack::Deflect
Rack
middleware for protecting against Denial-of-service attacks en.wikipedia.org/wiki/Denial-of-service_attack.
This middleware is designed for small deployments, which most likely are not utilizing load balancing from other software or hardware. Deflect
current supports the following functionality:
-
Saturation prevention (small DoS attacks, or request abuse)
-
Blacklisting of remote addresses
-
Whitelisting of remote addresses
-
Logging
Options:¶ ↑
:log When false logging will be bypassed, otherwise pass an object responding to #puts :log_format Alter the logging format :log_date_format Alter the logging date format :request_threshold Number of requests allowed within the set :interval. Defaults to 100 :interval Duration in seconds until the request counter is reset. Defaults to 5 :block_duration Duration in seconds that a remote address will be blocked. Defaults to 900 (15 minutes) :whitelist Array of remote addresses which bypass Deflect. NOTE: this does not block others :blacklist Array of remote addresses immediately considered malicious
Examples:¶ ↑
use Rack::Deflect, :log => $stdout, :request_threshold => 20, :interval => 2, :block_duration => 60
CREDIT: TJ Holowaychuk <tj@vision-media.ca>
Attributes
options[R]
Public Class Methods
new(app, options = {})
click to toggle source
# File lib/rack/contrib/deflect.rb 46 def initialize app, options = {} 47 @mutex = Mutex.new 48 @remote_addr_map = {} 49 @app, @options = app, { 50 :log => false, 51 :log_format => 'deflect(%s): %s', 52 :log_date_format => '%m/%d/%Y', 53 :request_threshold => 100, 54 :interval => 5, 55 :block_duration => 900, 56 :whitelist => [], 57 :blacklist => [] 58 }.merge(options) 59 end
Public Instance Methods
block!(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 102 def block!(remote_addr) 103 return if blocked?(remote_addr) 104 log "blocked #{remote_addr}" 105 map(remote_addr)[:block_expires] = Time.now + options[:block_duration] 106 end
block_expired?(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 112 def block_expired?(remote_addr) 113 map(remote_addr)[:block_expires] < Time.now rescue false 114 end
blocked?(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 108 def blocked?(remote_addr) 109 map(remote_addr).has_key? :block_expires 110 end
call(env)
click to toggle source
# File lib/rack/contrib/deflect.rb 61 def call env 62 return deflect! if deflect? env 63 status, headers, body = @app.call env 64 [status, headers, body] 65 end
clear!(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 120 def clear!(remote_addr) 121 return unless watching?(remote_addr) 122 log "released #{remote_addr}" if blocked?(remote_addr) 123 @remote_addr_map.delete remote_addr 124 end
deflect!()
click to toggle source
# File lib/rack/contrib/deflect.rb 67 def deflect! 68 [403, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, []] 69 end
deflect?(env)
click to toggle source
# File lib/rack/contrib/deflect.rb 71 def deflect? env 72 remote_addr = env['REMOTE_ADDR'] 73 return false if options[:whitelist].include? remote_addr 74 return true if options[:blacklist].include? remote_addr 75 sync { watch(remote_addr) } 76 end
exceeded_request_threshold?(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 130 def exceeded_request_threshold?(remote_addr) 131 map(remote_addr)[:requests] > options[:request_threshold] 132 end
increment_requests(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 126 def increment_requests(remote_addr) 127 map(remote_addr)[:requests] += 1 128 end
log(message)
click to toggle source
# File lib/rack/contrib/deflect.rb 78 def log message 79 return unless options[:log] 80 options[:log].puts(options[:log_format] % [Time.now.strftime(options[:log_date_format]), message]) 81 end
map(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 87 def map(remote_addr) 88 @remote_addr_map[remote_addr] ||= { 89 :expires => Time.now + options[:interval], 90 :requests => 0 91 } 92 end
sync(&block)
click to toggle source
# File lib/rack/contrib/deflect.rb 83 def sync &block 84 @mutex.synchronize(&block) 85 end
watch(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 94 def watch(remote_addr) 95 increment_requests(remote_addr) 96 clear!(remote_addr) if watch_expired?(remote_addr) and not blocked?(remote_addr) 97 clear!(remote_addr) if blocked?(remote_addr) and block_expired?(remote_addr) 98 block!(remote_addr) if watching?(remote_addr) and exceeded_request_threshold?(remote_addr) 99 blocked?(remote_addr) 100 end
watch_expired?(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 134 def watch_expired?(remote_addr) 135 map(remote_addr)[:expires] <= Time.now 136 end
watching?(remote_addr)
click to toggle source
# File lib/rack/contrib/deflect.rb 116 def watching?(remote_addr) 117 @remote_addr_map.has_key? remote_addr 118 end