Class: HttpBL

Inherits:
Object
  • Object
show all
Defined in:
lib/httpbl.rb

Overview

The Httpbl middleware

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ HttpBL

Returns a new instance of HttpBL.



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/httpbl.rb', line 6

def initialize(app, options = {})
  @app = app
  @options = {:blocked_search_engines => [],
              :age_threshold => 10,
              :threat_level_threshold => 2,
              :deny_types => [1, 2, 4, 8, 16, 32, 64, 128], # 8..128 aren't used as of 3/2009, but might be used in the future
              :dns_timeout => 0.5,
              :memcached_server => nil,
:memcached_options => {}
              }.merge(options)
  raise "Missing :api_key for Http:BL middleware" unless @options[:api_key]
  if @options[:memcached_server]
    require 'memcache'
    @cache = MemCache.new(@options[:memcached_server], @options[:memcached_options])
  end
end

Instance Method Details

#_call(env) ⇒ Object



27
28
29
30
31
32
33
34
35
36
# File 'lib/httpbl.rb', line 27

def _call(env)
  request = Rack::Request.new(env)
  bl_status = check(request.ip)
  if bl_status and blocked?(bl_status)
    [403, {"Content-Type" => "text/html"}, "<h1>403 Forbidden</h1> Request IP is listed as suspicious by <a href='http://projecthoneypot.org/ip_#{request.ip}'>Project Honeypot</a>"]
  else
    @app.call(env)
  end
  
end

#blocked?(response) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/httpbl.rb', line 60

def blocked?(response)
  response = response.split('.').collect!(&:to_i)
  if response[0] == 127 
    if response[3] == 0
      @blocked = @options[:blocked_search_engines].include?(response[2])
    else 
      @blocked = @options[:deny_types].collect{|key| response[3] & key == key }.any?
      @blocked = @blocked and response[2] > @options[:threat_level_threshold] 
      @blocked = @blocked and response[1] < @options[:age_threshold]
    end
  end
  return @blocked
end

#cache_check(ip) ⇒ Object



42
43
44
45
46
47
48
49
# File 'lib/httpbl.rb', line 42

def cache_check(ip)
  cache = @cache.clone if @cache
  unless response = cache.get("httpbl_#{ip}")
    response = resolve(ip)
    cache.set("httpbl_#{ip}", (response || "0.0.0.0"), 1.hour)
  end
  return response
end

#call(env) ⇒ Object



23
24
25
# File 'lib/httpbl.rb', line 23

def call(env)
  dup._call(env)
end

#check(ip) ⇒ Object



38
39
40
# File 'lib/httpbl.rb', line 38

def check(ip)
  @cache ? cache_check(ip) : resolve(ip)
end

#resolve(ip) ⇒ Object



51
52
53
54
55
56
57
58
# File 'lib/httpbl.rb', line 51

def resolve(ip)
  query = @options[:api_key] + '.' + ip.split('.').reverse.join('.') + '.dnsbl.httpbl.org'
  Timeout::timeout(@options[:dns_timeout]) do
     Resolv::DNS.new.getaddress(query).to_s rescue false
	puts "resolving"
  end
  rescue Timeout::Error, Errno::ECONNREFUSED
end