Skip to content

Instantly share code, notes, and snippets.

@ratbeard
Forked from postmodern/ban_hammer.rb
Created October 16, 2009 04:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ratbeard/211542 to your computer and use it in GitHub Desktop.
Save ratbeard/211542 to your computer and use it in GitHub Desktop.
saw at http://coderack.org/users/Postmodern/entries/26-banhammer and felt like tweaking the code :)
require 'ipaddr'
module Rack
#
# BanHammer is a Rack middleware app that restricts access to your server
# using a black-list of IPv4/IPv6 addresses and ranges.
#
# MIT License - Hal Brodigan (postmodern.mod3 at gmail.com)
#
# Needlessly modified by Mike Frawley
#
class BanHammer
DEFAULT_MESSAGE = %{
<html>
<head>
<title>Banned</title>
</head>
<body>
<h1>Banned</h1>
<p>Your IP address has been banned by BanHammer. Please contact the site administrators for information on why you were banned.</p>
</body>
</html>
}
#
# Initializes the ban hammer.
#
# @param [#call] app
# The Rack application to protect.
#
# @param [Hash] options
# Additional options.
#
# @option options [Array<String>] :banned ([])
# The list of IPv4/IPv6 addresses and netmasked ranges that are banned.
#
# @option options [String] :message ('')
# A message to display to those banned.
#
# @option options [String] :content_type ('text/html')
# The Content-Type of the ban message.
#
# @example
# use BanHammer, :banned => ['219.140.118.33/24'],
# :message => %{
# <html>
# <head>
# <title>Banned</title>
# </head>
#
# <body>
# <h1>Not even seven proxies can protect you from the BAN HAMMER.</h1>
# </body>
# </html>
# }
#
def initialize(app, options={})
defaults = {
:banned => [],
:content_type => 'text/html',
:message => DEFAULT_MESSAGE
}
options = defaults.merge(options)
@app = app
@banned_ips = options[:banned].map {|ip| IpAddr.new(ip) }
@banned_response = [
403,
{'Content-Type' => options[:content_type]},
[ options[:message] ]
]
end
def call(env)
stop_if_remote_addr_banned || @app.call(env)
end
private
def stop_if_remote_addr_banned
remote_addr = IPAddr.new(env['REMOTE_ADDR'])
@banned_response if banned? remote_addr
end
def banned?(ip)
@banned_ips.any {|ip_range| ip_range.include? ip }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment