Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
...
  • 2 commits
  • 12 files changed
  • 0 commit comments
  • 1 contributor
View
28 README.md
@@ -1,6 +1,8 @@
# Rack::IpFilter
-TODO: Write a gem description
+A Rack middleware component which does simple White and Black list filtering of remote IP Adresses.
+
+Provides support for CIDR notation for ranges as well as specific addresses.
## Installation
@@ -18,7 +20,29 @@ Or install it yourself as:
## Usage
-TODO: Write usage instructions here
+First require:
+
+ require 'rack/ip_filter'
+
+For Rails, you can insert the middleware in your `config/application.rb`:
+
+ IP_WHITELIST = %w(192.168.2.0/24 127.0.0.1)
+
+ module YourApp
+ class Application < Rails::Application
+ config.middleware.use Rack::IpFilter, IpFilter::WhiteList.new(::IP_WHITELIST)
+ end
+ end
+
+See example/app.rb for a simple Sinatra app which illustrates proper usage.
+
+## Options
+
+Rack::IpFilter takes two arguments, the first is an object that responds to `approved?` and returns a boolean.
+The second argument is the path to apply the filter, defaults to root: `'/'`.
+
+IpFilter::WhiteList and IpFilter::Black list ship with the gem and explicitly allow or block remote ip addresses
+respectively.
## Contributing
View
22 example/app.rb
@@ -0,0 +1,22 @@
+require 'sinatra/base'
+
+$LOAD_PATH << File.dirname(__FILE__) + '/../lib'
+
+require 'rack/ip_filter'
+
+# rackup -s thin app.rb
+# http://localhost:9292/test
+class App < Sinatra::Base
+
+ use Rack::IpFilter, IpFilter::WhiteList.new('192.168.2.0/24', '127.0.0.1'), '/'
+ use Rack::IpFilter, IpFilter::WhiteList.new('127.0.0.1'), '/admin'
+ use Rack::IpFilter, IpFilter::BlackList.new('192.168.2.23'), '/'
+
+ set :root, File.dirname(__FILE__)
+
+ get '/test' do
+ content_type "text/plain"
+ body "Hello world!"
+ end
+
+end
View
10 lib/ip_filter.rb
@@ -1 +1,11 @@
+require 'ipaddr'
+require 'ip_filter/list'
+require 'ip_filter/white_list'
+require 'ip_filter/black_list'
require 'rack/ip_filter'
+
+module IpFilter
+
+ VERSION = '0.1.0'
+
+end
View
9 lib/ip_filter/black_list.rb
@@ -0,0 +1,9 @@
+module IpFilter
+
+ class BlackList < List
+
+ def approved?(remote_ip)
+ !any?(remote_ip)
+ end
+ end
+end
View
12 lib/ip_filter/list.rb
@@ -0,0 +1,12 @@
+module IpFilter
+
+ class List
+ def initialize(*list)
+ @list = list.flatten.map { |ip| IPAddr.new(ip) }
+ end
+
+ def any?(remote_ip)
+ @list.any? { |ip| ip.include?(remote_ip) }
+ end
+ end
+end
View
9 lib/ip_filter/white_list.rb
@@ -0,0 +1,9 @@
+module IpFilter
+
+ class WhiteList < List
+
+ def approved?(remote_ip)
+ any?(remote_ip)
+ end
+ end
+end
View
30 lib/rack/ip_filter.rb
@@ -1,36 +1,28 @@
-require 'netaddr'
+require 'ip_filter'
module Rack
class IpFilter
- VERSION = "0.0.2"
-
- def initialize(app, ip_whitelist, path)
- @app = app
- @ip_whitelist = ip_whitelist.map { |ip| NetAddr::CIDR.create(ip) }
+ def initialize(app, list, path = '/')
+ @app = app
@path = path
+ @list = list
end
def call(env)
- if white_listed?(env)
+ if approved?(env)
@app.call(env)
else
forbidden!
end
end
-
- def white_listed?(env)
- return true unless env['REQUEST_PATH'] =~ /^#{@path}/
-
- remote_addr = remote_address(env)
- remote_addr == '127.0.0.1' || @ip_whitelist.any? { |ip_range| ip_range.contains?(remote_addr) }
- end
- def black_listed?(env)
-
+ def approved?(env)
+ return true unless path_match?(env['REQUEST_PATH'])
+ @list.approved?(remote_address(env))
end
-
+
def remote_address(env)
if env['HTTP_X_FORWARDED_FOR']
env['HTTP_X_FORWARDED_FOR'].split(',').first.strip
@@ -43,5 +35,9 @@ def forbidden!
[403, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, []]
end
+ def path_match?(path)
+ path =~ /^#{@path}/
+ end
+
end
end
View
4 rack-ip_filter.gemspec
@@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
lib = File.expand_path('../lib/', __FILE__)
$:.unshift lib unless $:.include?(lib)
-require 'rack/ip_filter'
+require 'ip_filter'
Gem::Specification.new do |gem|
gem.authors = ["Mike Evans"]
@@ -18,5 +18,5 @@ Gem::Specification.new do |gem|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
gem.name = "rack-ip_filter"
gem.require_paths = ["lib"]
- gem.version = Rack::IpFilter::VERSION
+ gem.version = IpFilter::VERSION
end
View
1 test/helper.rb
@@ -1,4 +1,5 @@
require 'minitest/autorun'
+require 'ip_filter'
require 'rack'
require 'rack/test'
require 'rack/ip_filter'
View
26 test/test_black_list.rb
@@ -0,0 +1,26 @@
+require 'helper'
+
+class TestWhiteList < MiniTest::Unit::TestCase
+
+ def setup
+ @range = '192.168.2.0/24'
+ @included = '192.168.2.100'
+ @not_included = '192.168.3.0'
+ end
+
+ def test_ip_approved
+ list = IpFilter::WhiteList.new(@range)
+ assert !list.approved?(@included)
+ end
+
+ def test_ip_restricted
+ list = IpFilter::WhiteList.new(@range)
+ assert list.approved?(@not_included)
+ end
+
+ def test_allows_arrays
+ list = IpFilter::WhiteList.new([@range, @not_included])
+ assert !list.approved?(@included)
+ end
+
+end
View
26 test/test_ip_filter.rb → test/test_rack_ip_filter.rb
@@ -1,43 +1,47 @@
require 'helper'
-class IpWhitelistTest < MiniTest::Unit::TestCase
+class TestRackIpFilter < MiniTest::Unit::TestCase
include Rack::Test::Methods
- LOCAL_IP = '127.0.0.1'
- GOOD_IP = '24.40.64.23'
- BAD_IP = '9.9.9.9'
+ def setup
+ @range = '24.40.64.0/20'
+ @local = '127.0.0.1'
+ @good = '24.40.64.23'
+ @bad = '9.9.9.9'
+ @list = [@range, @local]
+ end
def app
- Rack::IpFilter.new(lambda {|env| [200, {}, []] }, ['24.40.64.0/20'], '/')
+ Rack::IpFilter.new(lambda {|env| [200, {}, []] }, IpFilter::WhiteList.new(@list), '/')
end
def test_local_ip_address_admitted
- get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' => LOCAL_IP }
+ get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' => @local }
assert last_response.ok?
end
def test_allowed_remote_ip_address_admitted
- get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' => GOOD_IP }
+ get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' => @good }
assert last_response.ok?
end
def test_outside_remote_ip_address_rejected
- get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' => BAD_IP }
+ get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' => @bad }
assert !last_response.ok?
end
def test_local_ip_address_admitted_via_proxy
- get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [LOCAL_IP, BAD_IP].join(', ') }
+ get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [@local, @bad].join(', ') }
assert last_response.ok?
end
def test_allowed_remote_ip_address_admitted_via_proxy
- get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [GOOD_IP, BAD_IP].join(', ') }
+ get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [@good, @bad].join(', ') }
assert last_response.ok?
end
def test_outside_remote_ip_address_rejected_via_proxy
- get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [BAD_IP, GOOD_IP].join(', ') }
+ get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [@bad, @good].join(', ') }
assert !last_response.ok?
end
View
26 test/test_white_list.rb
@@ -0,0 +1,26 @@
+require 'helper'
+
+class TestWhiteList < MiniTest::Unit::TestCase
+
+ def setup
+ @range = '192.168.2.0/24'
+ @included = '192.168.2.100'
+ @not_included = '192.168.3.0'
+ end
+
+ def test_ip_approved
+ list = IpFilter::WhiteList.new(@range)
+ assert list.approved?(@included)
+ end
+
+ def test_ip_restricted
+ list = IpFilter::WhiteList.new(@range)
+ assert !list.approved?(@not_included)
+ end
+
+ def test_allows_arrays
+ list = IpFilter::WhiteList.new([@range, @not_included])
+ assert list.approved?(@included)
+ end
+
+end

No commit comments for this range

Something went wrong with that request. Please try again.