rack-ip_filter 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|