· 8 years ago · Mar 14, 2018, 09:54 AM
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 # Needlessly modified by Mike Frawley
11 #
12 class BanHammer
13
14 DEFAULT_MESSAGE = %{
15<html>
16<head>
17<title>Banned</title>
18</head>
19<body>
20<h1>Banned</h1>
21<p>Your IP address has been banned by BanHammer. Please contact the site administrators for information on why you were banned.</p>
22</body>
23</html>
24}
25
26 #
27 # Initializes the ban hammer.
28 #
29 # @param [#call] app
30 # The Rack application to protect.
31 #
32 # @param [Hash] options
33 # Additional options.
34 #
35 # @option options [Array<String>] :banned ([])
36 # The list of IPv4/IPv6 addresses and netmasked ranges that are banned.
37 #
38 # @option options [String] :message ('')
39 # A message to display to those banned.
40 #
41 # @option options [String] :content_type ('text/html')
42 # The Content-Type of the ban message.
43 #
44 # @example
45 # use BanHammer, :banned => ['219.140.118.33/24'],
46 # :message => %{
47 # <html>
48 # <head>
49 # <title>Banned</title>
50 # </head>
51 #
52 # <body>
53 # <h1>Not even seven proxies can protect you from the BAN HAMMER.</h1>
54 # </body>
55 # </html>
56 # }
57 #
58 def initialize(app, options={})
59 defaults = {
60 :banned => [],
61 :content_type => 'text/html',
62 :message => DEFAULT_MESSAGE
63 }
64 options = defaults.merge(options)
65
66 @app = app
67 @banned_ips = options[:banned].map {|ip| IpAddr.new(ip) }
68 @banned_response = [
69 403,
70 {'Content-Type' => options[:content_type]},
71 [ options[:message] ]
72 ]
73 end
74
75 def call(env)
76 stop_if_remote_addr_banned || @app.call(env)
77 end
78
79 private
80 def stop_if_remote_addr_banned
81 remote_addr = IPAddr.new(env['REMOTE_ADDR'])
82 @banned_response if banned? remote_addr
83 end
84
85 def banned?(ip)
86 @banned_ips.any {|ip_range| ip_range.include? ip }
87 end
88 end
89end