rack-ip_filter 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +26 -2
- data/example/app.rb +22 -0
- data/lib/ip_filter.rb +10 -0
- data/lib/ip_filter/black_list.rb +9 -0
- data/lib/ip_filter/list.rb +12 -0
- data/lib/ip_filter/white_list.rb +9 -0
- data/lib/rack/ip_filter.rb +13 -17
- data/rack-ip_filter.gemspec +2 -2
- data/test/helper.rb +1 -0
- data/test/test_black_list.rb +26 -0
- data/test/{test_ip_filter.rb → test_rack_ip_filter.rb} +15 -11
- data/test/test_white_list.rb +26 -0
- metadata +18 -10
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Rack::IpFilter
|
2
2
|
|
3
|
-
|
3
|
+
A Rack middleware component which does simple White and Black list filtering of remote IP Adresses.
|
4
|
+
|
5
|
+
Provides support for CIDR notation for ranges as well as specific addresses.
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -18,7 +20,29 @@ Or install it yourself as:
|
|
18
20
|
|
19
21
|
## Usage
|
20
22
|
|
21
|
-
|
23
|
+
First require:
|
24
|
+
|
25
|
+
require 'rack/ip_filter'
|
26
|
+
|
27
|
+
For Rails, you can insert the middleware in your `config/application.rb`:
|
28
|
+
|
29
|
+
IP_WHITELIST = %w(192.168.2.0/24 127.0.0.1)
|
30
|
+
|
31
|
+
module YourApp
|
32
|
+
class Application < Rails::Application
|
33
|
+
config.middleware.use Rack::IpFilter, IpFilter::WhiteList.new(::IP_WHITELIST)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
See example/app.rb for a simple Sinatra app which illustrates proper usage.
|
38
|
+
|
39
|
+
## Options
|
40
|
+
|
41
|
+
Rack::IpFilter takes two arguments, the first is an object that responds to `approved?` and returns a boolean.
|
42
|
+
The second argument is the path to apply the filter, defaults to root: `'/'`.
|
43
|
+
|
44
|
+
IpFilter::WhiteList and IpFilter::Black list ship with the gem and explicitly allow or block remote ip addresses
|
45
|
+
respectively.
|
22
46
|
|
23
47
|
## Contributing
|
24
48
|
|
data/example/app.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
$LOAD_PATH << File.dirname(__FILE__) + '/../lib'
|
4
|
+
|
5
|
+
require 'rack/ip_filter'
|
6
|
+
|
7
|
+
# rackup -s thin app.rb
|
8
|
+
# http://localhost:9292/test
|
9
|
+
class App < Sinatra::Base
|
10
|
+
|
11
|
+
use Rack::IpFilter, IpFilter::WhiteList.new('192.168.2.0/24', '127.0.0.1'), '/'
|
12
|
+
use Rack::IpFilter, IpFilter::WhiteList.new('127.0.0.1'), '/admin'
|
13
|
+
use Rack::IpFilter, IpFilter::BlackList.new('192.168.2.23'), '/'
|
14
|
+
|
15
|
+
set :root, File.dirname(__FILE__)
|
16
|
+
|
17
|
+
get '/test' do
|
18
|
+
content_type "text/plain"
|
19
|
+
body "Hello world!"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/ip_filter.rb
CHANGED
data/lib/rack/ip_filter.rb
CHANGED
@@ -1,36 +1,28 @@
|
|
1
|
-
require '
|
1
|
+
require 'ip_filter'
|
2
2
|
|
3
3
|
module Rack
|
4
4
|
|
5
5
|
class IpFilter
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
def initialize(app, ip_whitelist, path)
|
10
|
-
@app = app
|
11
|
-
@ip_whitelist = ip_whitelist.map { |ip| NetAddr::CIDR.create(ip) }
|
7
|
+
def initialize(app, list, path = '/')
|
8
|
+
@app = app
|
12
9
|
@path = path
|
10
|
+
@list = list
|
13
11
|
end
|
14
12
|
|
15
13
|
def call(env)
|
16
|
-
if
|
14
|
+
if approved?(env)
|
17
15
|
@app.call(env)
|
18
16
|
else
|
19
17
|
forbidden!
|
20
18
|
end
|
21
19
|
end
|
22
|
-
|
23
|
-
def white_listed?(env)
|
24
|
-
return true unless env['REQUEST_PATH'] =~ /^#{@path}/
|
25
|
-
|
26
|
-
remote_addr = remote_address(env)
|
27
|
-
remote_addr == '127.0.0.1' || @ip_whitelist.any? { |ip_range| ip_range.contains?(remote_addr) }
|
28
|
-
end
|
29
20
|
|
30
|
-
def
|
31
|
-
|
21
|
+
def approved?(env)
|
22
|
+
return true unless path_match?(env['REQUEST_PATH'])
|
23
|
+
@list.approved?(remote_address(env))
|
32
24
|
end
|
33
|
-
|
25
|
+
|
34
26
|
def remote_address(env)
|
35
27
|
if env['HTTP_X_FORWARDED_FOR']
|
36
28
|
env['HTTP_X_FORWARDED_FOR'].split(',').first.strip
|
@@ -43,5 +35,9 @@ module Rack
|
|
43
35
|
[403, { 'Content-Type' => 'text/html', 'Content-Length' => '0' }, []]
|
44
36
|
end
|
45
37
|
|
38
|
+
def path_match?(path)
|
39
|
+
path =~ /^#{@path}/
|
40
|
+
end
|
41
|
+
|
46
42
|
end
|
47
43
|
end
|
data/rack-ip_filter.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
lib = File.expand_path('../lib/', __FILE__)
|
3
3
|
$:.unshift lib unless $:.include?(lib)
|
4
|
-
require '
|
4
|
+
require 'ip_filter'
|
5
5
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.authors = ["Mike Evans"]
|
@@ -18,5 +18,5 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.name = "rack-ip_filter"
|
20
20
|
gem.require_paths = ["lib"]
|
21
|
-
gem.version =
|
21
|
+
gem.version = IpFilter::VERSION
|
22
22
|
end
|
data/test/helper.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestWhiteList < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@range = '192.168.2.0/24'
|
7
|
+
@included = '192.168.2.100'
|
8
|
+
@not_included = '192.168.3.0'
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_ip_approved
|
12
|
+
list = IpFilter::WhiteList.new(@range)
|
13
|
+
assert !list.approved?(@included)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_ip_restricted
|
17
|
+
list = IpFilter::WhiteList.new(@range)
|
18
|
+
assert list.approved?(@not_included)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_allows_arrays
|
22
|
+
list = IpFilter::WhiteList.new([@range, @not_included])
|
23
|
+
assert !list.approved?(@included)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -1,43 +1,47 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class TestRackIpFilter < MiniTest::Unit::TestCase
|
4
4
|
include Rack::Test::Methods
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def setup
|
7
|
+
@range = '24.40.64.0/20'
|
8
|
+
@local = '127.0.0.1'
|
9
|
+
@good = '24.40.64.23'
|
10
|
+
@bad = '9.9.9.9'
|
11
|
+
@list = [@range, @local]
|
12
|
+
end
|
9
13
|
|
10
14
|
def app
|
11
|
-
Rack::IpFilter.new(lambda {|env| [200, {}, []] },
|
15
|
+
Rack::IpFilter.new(lambda {|env| [200, {}, []] }, IpFilter::WhiteList.new(@list), '/')
|
12
16
|
end
|
13
17
|
|
14
18
|
def test_local_ip_address_admitted
|
15
|
-
get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' =>
|
19
|
+
get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' => @local }
|
16
20
|
assert last_response.ok?
|
17
21
|
end
|
18
22
|
|
19
23
|
def test_allowed_remote_ip_address_admitted
|
20
|
-
get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' =>
|
24
|
+
get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' => @good }
|
21
25
|
assert last_response.ok?
|
22
26
|
end
|
23
27
|
|
24
28
|
def test_outside_remote_ip_address_rejected
|
25
|
-
get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' =>
|
29
|
+
get '/', {}, { 'REQUEST_PATH' => '/', 'REMOTE_ADDR' => @bad }
|
26
30
|
assert !last_response.ok?
|
27
31
|
end
|
28
32
|
|
29
33
|
def test_local_ip_address_admitted_via_proxy
|
30
|
-
get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [
|
34
|
+
get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [@local, @bad].join(', ') }
|
31
35
|
assert last_response.ok?
|
32
36
|
end
|
33
37
|
|
34
38
|
def test_allowed_remote_ip_address_admitted_via_proxy
|
35
|
-
get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [
|
39
|
+
get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [@good, @bad].join(', ') }
|
36
40
|
assert last_response.ok?
|
37
41
|
end
|
38
42
|
|
39
43
|
def test_outside_remote_ip_address_rejected_via_proxy
|
40
|
-
get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [
|
44
|
+
get '/', {}, { 'REQUEST_PATH' => '/', 'HTTP_X_FORWARDED_FOR' => [@bad, @good].join(', ') }
|
41
45
|
assert !last_response.ok?
|
42
46
|
end
|
43
47
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestWhiteList < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@range = '192.168.2.0/24'
|
7
|
+
@included = '192.168.2.100'
|
8
|
+
@not_included = '192.168.3.0'
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_ip_approved
|
12
|
+
list = IpFilter::WhiteList.new(@range)
|
13
|
+
assert list.approved?(@included)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_ip_restricted
|
17
|
+
list = IpFilter::WhiteList.new(@range)
|
18
|
+
assert !list.approved?(@not_included)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_allows_arrays
|
22
|
+
list = IpFilter::WhiteList.new([@range, @not_included])
|
23
|
+
assert list.approved?(@included)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-ip_filter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: netaddr
|
16
|
-
requirement: &
|
16
|
+
requirement: &70211260750580 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70211260750580
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rack
|
27
|
-
requirement: &
|
27
|
+
requirement: &70211260744980 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70211260744980
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rack-test
|
38
|
-
requirement: &
|
38
|
+
requirement: &70211260760140 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70211260760140
|
47
47
|
description: White and clacklist IPs
|
48
48
|
email:
|
49
49
|
- mike@urlgonomics.com
|
@@ -56,11 +56,17 @@ files:
|
|
56
56
|
- LICENSE
|
57
57
|
- README.md
|
58
58
|
- Rakefile
|
59
|
+
- example/app.rb
|
59
60
|
- lib/ip_filter.rb
|
61
|
+
- lib/ip_filter/black_list.rb
|
62
|
+
- lib/ip_filter/list.rb
|
63
|
+
- lib/ip_filter/white_list.rb
|
60
64
|
- lib/rack/ip_filter.rb
|
61
65
|
- rack-ip_filter.gemspec
|
62
66
|
- test/helper.rb
|
63
|
-
- test/
|
67
|
+
- test/test_black_list.rb
|
68
|
+
- test/test_rack_ip_filter.rb
|
69
|
+
- test/test_white_list.rb
|
64
70
|
homepage: ''
|
65
71
|
licenses: []
|
66
72
|
post_install_message:
|
@@ -87,4 +93,6 @@ specification_version: 3
|
|
87
93
|
summary: ''
|
88
94
|
test_files:
|
89
95
|
- test/helper.rb
|
90
|
-
- test/
|
96
|
+
- test/test_black_list.rb
|
97
|
+
- test/test_rack_ip_filter.rb
|
98
|
+
- test/test_white_list.rb
|