-
-
Save apohllo/260307 to your computer and use it in GitHub Desktop.
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 = [] | |
@allowed = [] | |
if options[:banned] | |
options[:banned].each do |ip| | |
@banned << IPAddr.new(ip) | |
end | |
end | |
if options[:allowed] | |
options[:allowed].each do |ip| | |
@allowed << 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']) | |
unless @allowed.empty? | |
return @response unless @allowed.any?{|r| r.include?(remote_addr)} | |
else | |
return @response if @banned.any?{|r| r.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