· 8 years ago · Mar 16, 2018, 09:48 PM
1require 'ipaddr'
2
3module Rack
4 #
5 # BanHammer is a Rack middleware app that restricts access to your server
6 # using a black-list of IPv4/IPv6 addresses and ranges.
7 #
8 # MIT License - Hal Brodigan (postmodern.mod3 at gmail.com)
9 #
10 class BanHammer
11
12 DEFAULT_MESSAGE = %{
13 <html>
14 <head>
15 <title>Banned</title>
16 </head>
17 <body>
18 <h1>Banned</h1>
19
20 <p>Your IP address has been banned by BanHammer. Please contact the site administrators for information on why you were banned.</p>
21 </body>
22 </html>
23 }
24
25 #
26 # Initializes the ban hammer.
27 #
28 # @param [#call] app
29 # The Rack application to protect.
30 #
31 # @param [Hash] options
32 # Additional options.
33 #
34 # @option options [Array<String>] :banned ([])
35 # The list of IPv4/IPv6 addresses and netmasked ranges that are banned.
36 #
37 # @option options [String] :message ('')
38 # A message to display to those banned.
39 #
40 # @option options [String] :content_type ('text/html')
41 # The Content-Type of the ban message.
42 #
43 # @example
44 # use BanHammer, :banned => ['219.140.118.33/24'],
45 # :message => %{
46 # <html>
47 # <head>
48 # <title>Banned</title>
49 # </head>
50 #
51 # <body>
52 # <h1>Not even seven proxies can protect you from the BAN HAMMER.</h1>
53 # </body>
54 # </html>
55 # }
56 #
57 def initialize(app,options={})
58 @app = app
59 @banned = []
60 @allowed = []
61
62 if options[:banned]
63 options[:banned].each do |ip|
64 @banned << IPAddr.new(ip)
65 end
66 end
67
68 if options[:allowed]
69 options[:allowed].each do |ip|
70 @allowed << IPAddr.new(ip)
71 end
72 end
73
74 @response = [
75 403,
76 {'Content-Type' => (options[:content_type] || 'text/html')},
77 [options[:message] || DEFAULT_MESSAGE]
78 ]
79 end
80
81 def call(env)
82 remote_addr = IPAddr.new(env['REMOTE_ADDR'])
83
84 unless @allowed.empty?
85 return @response unless @allowed.any?{|r| r.include?(remote_addr)}
86 else
87 return @response if @banned.any?{|r| r.include?(remote_addr)}
88 end
89
90 @app.call(env)
91 end
92
93 end
94end