Created
October 12, 2009 01:24
-
-
Save postmodern/208035 to your computer and use it in GitHub Desktop.
A Rack middleware app that bans specified IPv4/IPv6 addresses and ranges.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
# | |
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={}) | |
@app = app | |
@banned = [] | |
if options[:banned] | |
options[:banned].each do |ip| | |
@banned << IPAddr.new(ip) | |
end | |
end | |
@response = [ | |
403, | |
{'Content-Type' => (options[:content_type] || 'text/html')}, | |
[options[:message] || DEFAULT_MESSAGE] | |
] | |
end | |
def call(env) | |
remote_addr = IPAddr.new(env['REMOTE_ADDR']) | |
@banned.each do |range| | |
return @response if range.include?(remote_addr) | |
end | |
@app.call(env) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment