rack-attack 2.2.1 → 2.3.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.
Potentially problematic release.
This version of rack-attack might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/README.md +44 -10
- data/lib/rack/attack.rb +1 -0
- data/lib/rack/attack/allow2ban.rb +23 -0
- data/lib/rack/attack/fail2ban.rb +10 -5
- data/lib/rack/attack/throttle.rb +3 -3
- data/lib/rack/attack/version.rb +1 -1
- data/spec/allow2ban_spec.rb +121 -0
- data/spec/rack_attack_throttle_spec.rb +21 -1
- data/spec/spec_helper.rb +1 -1
- metadata +56 -31
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b294cc1911f079c5df74d5325e01fabd2a207498
|
4
|
+
data.tar.gz: 99306d1db94cfeab978bef7573e1455c0e2cc428
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 12a543ddffa7cc24893c3ee302071738e8f9e39fe063e9b6610492c41d03ba5179c43bffe50ff182e880fd936a1d970ab9f6a0d6c536c2db77e89b555dd253d2
|
7
|
+
data.tar.gz: b439faf86fd536d941327aa03c0d4e2d344a527857f120e09e0ab0bdec9fbbcef686d716da9c56867d4ca277c20edf7d8313c6c79d7f01c4e09ff0d929092a7a
|
data/README.md
CHANGED
@@ -4,7 +4,14 @@
|
|
4
4
|
Rack::Attack is a rack middleware to protect your web app from bad clients.
|
5
5
|
It allows *whitelisting*, *blacklisting*, *throttling*, and *tracking* based on arbitrary properties of the request.
|
6
6
|
|
7
|
-
Throttle state is stored in a configurable cache (e.g. `Rails.cache`), presumably backed by memcached or redis (at least v3.0.0).
|
7
|
+
Throttle state is stored in a configurable cache (e.g. `Rails.cache`), presumably backed by memcached or redis ([at least gem v3.0.0](https://rubygems.org/gems/redis)).
|
8
|
+
|
9
|
+
See the [Backing & Hacking blog post](http://www.kickstarter.com/backing-and-hacking/rack-attack-protection-from-abusive-clients) introducing Rack::Attack.
|
10
|
+
|
11
|
+
[](http://badge.fury.io/rb/rack-attack)
|
12
|
+
[](https://travis-ci.org/kickstarter/rack-attack)
|
13
|
+
[](https://codeclimate.com/github/kickstarter/rack-attack)
|
14
|
+
|
8
15
|
|
9
16
|
## Installation
|
10
17
|
|
@@ -15,7 +22,7 @@ Install the [rack-attack](http://rubygems.org/gems/rack-attack) gem; or add it t
|
|
15
22
|
gem 'rack-attack'
|
16
23
|
```
|
17
24
|
Tell your app to use the Rack::Attack middleware.
|
18
|
-
For Rails 3 apps:
|
25
|
+
For Rails 3+ apps:
|
19
26
|
|
20
27
|
```ruby
|
21
28
|
# In config/application.rb
|
@@ -43,7 +50,7 @@ The Rack::Attack middleware compares each request against *whitelists*, *blackli
|
|
43
50
|
|
44
51
|
* If the request matches any **whitelist**, it is allowed.
|
45
52
|
* Otherwise, if the request matches any **blacklist**, it is blocked.
|
46
|
-
* Otherwise, if the request matches any **throttle**, a counter is incremented in the Rack::Attack.cache. If
|
53
|
+
* Otherwise, if the request matches any **throttle**, a counter is incremented in the Rack::Attack.cache. If any throttle's limit is exceeded, the request is blocked.
|
47
54
|
* Otherwise, all **tracks** are checked, and the request is allowed.
|
48
55
|
|
49
56
|
The algorithm is actually more concise in code: See [Rack::Attack.call](https://github.com/kickstarter/rack-attack/blob/master/lib/rack/attack.rb):
|
@@ -71,7 +78,7 @@ The algorithm is actually more concise in code: See [Rack::Attack.call](https://
|
|
71
78
|
|
72
79
|
## Usage
|
73
80
|
|
74
|
-
Define whitelists, blacklists, throttles, and tracks as blocks that return truthy values if matched, falsy otherwise. In a Rails app
|
81
|
+
Define whitelists, blacklists, throttles, and tracks as blocks that return truthy values if matched, falsy otherwise. In a Rails app
|
75
82
|
these go in an initializer in `config/initializers/`.
|
76
83
|
A [Rack::Request](http://rack.rubyforge.org/doc/classes/Rack/Request.html) object is passed to the block (named 'req' in the examples).
|
77
84
|
|
@@ -121,6 +128,24 @@ how the parameters work.
|
|
121
128
|
end
|
122
129
|
```
|
123
130
|
|
131
|
+
#### Allow2Ban
|
132
|
+
`Allow2Ban.filter` works the same way as the `Fail2Ban.filter` except that it *allows* requests from misbehaving
|
133
|
+
clients until such time as they reach maxretry at which they are cut off as per normal.
|
134
|
+
```ruby
|
135
|
+
# Lockout IP addresses that are hammering your login page.
|
136
|
+
# After 20 requests in 1 minute, block all requests from that IP for 1 hour.
|
137
|
+
Rack::Attack.blacklist('allow2ban login scrapers') do |req|
|
138
|
+
# `filter` returns false value if request is to your login page (but still
|
139
|
+
# increments the count) so request below the limit are not blocked until
|
140
|
+
# they hit the limit. At that point, filter will return true and block.
|
141
|
+
Rack::Attack::Allow2Ban.filter(req.ip, :maxretry => 20, :findtime => 1.minute, :bantime => 1.hour) do
|
142
|
+
# The count for the IP is incremented if the return value is truthy.
|
143
|
+
req.path = '/login' and req.method == 'post'
|
144
|
+
end
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
148
|
+
|
124
149
|
### Throttles
|
125
150
|
|
126
151
|
```ruby
|
@@ -140,6 +165,13 @@ how the parameters work.
|
|
140
165
|
Rack::Attack.throttle('logins/email', :limit => 6, :period => 60.seconds) do |req|
|
141
166
|
req.params['email'] if req.path == '/login' && req.post?
|
142
167
|
end
|
168
|
+
|
169
|
+
# You can also set a limit using a proc instead of a number. For
|
170
|
+
# instance, after Rack::Auth::Basic has authenticated the user:
|
171
|
+
limit_based_on_proc = proc {|req| req.env["REMOTE_USER"] == "admin" ? 100 : 1}
|
172
|
+
Rack::Attack.throttle('req/ip', :limit => limit_based_on_proc, :period => 1.second) do |req|
|
173
|
+
req.ip
|
174
|
+
end
|
143
175
|
```
|
144
176
|
|
145
177
|
### Tracks
|
@@ -204,9 +236,9 @@ You can subscribe to 'rack.attack' events and log it, graph it, etc:
|
|
204
236
|
|
205
237
|
## Testing
|
206
238
|
|
207
|
-
A note on developing and testing apps using Rack::Attack - if you are using throttling in particular, you will
|
208
|
-
need to enable the cache in your development environment. See [Caching with Rails](http://guides.rubyonrails.org/caching_with_rails.html)
|
209
|
-
for more on how to do this.
|
239
|
+
A note on developing and testing apps using Rack::Attack - if you are using throttling in particular, you will
|
240
|
+
need to enable the cache in your development environment. See [Caching with Rails](http://guides.rubyonrails.org/caching_with_rails.html)
|
241
|
+
for more on how to do this.
|
210
242
|
|
211
243
|
## Performance
|
212
244
|
|
@@ -230,10 +262,12 @@ It is impractical if not impossible to block abusive clients completely.
|
|
230
262
|
Rack::Attack aims to let developers quickly mitigate abusive requests and rely
|
231
263
|
less on short-term, one-off hacks to block a particular attack.
|
232
264
|
|
233
|
-
|
265
|
+
## Mailing list
|
234
266
|
|
235
|
-
|
236
|
-
|
267
|
+
New releases of Rack::Attack are announced on
|
268
|
+
<rack.attack.announce@librelist.com>. To subscribe, just send an email to
|
269
|
+
<rack.attack.announce@librelist.com>. See the
|
270
|
+
[archives](http://librelist.com/browser/rack.attack.announce/).
|
237
271
|
|
238
272
|
## License
|
239
273
|
|
data/lib/rack/attack.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Rack
|
2
|
+
module Attack
|
3
|
+
class Allow2Ban < Fail2Ban
|
4
|
+
class << self
|
5
|
+
protected
|
6
|
+
def key_prefix
|
7
|
+
'allow2ban'
|
8
|
+
end
|
9
|
+
|
10
|
+
# everything the same here except we return only return true
|
11
|
+
# (blocking the request) if they have tripped the limit.
|
12
|
+
def fail!(discriminator, bantime, findtime, maxretry)
|
13
|
+
count = cache.count("#{key_prefix}:count:#{discriminator}", findtime)
|
14
|
+
if count >= maxretry
|
15
|
+
ban!(discriminator, bantime)
|
16
|
+
end
|
17
|
+
# we may not block them this time, but they're banned for next time
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/rack/attack/fail2ban.rb
CHANGED
@@ -15,23 +15,28 @@ module Rack
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
protected
|
19
|
+
def key_prefix
|
20
|
+
'fail2ban'
|
21
|
+
end
|
22
|
+
|
19
23
|
def fail!(discriminator, bantime, findtime, maxretry)
|
20
|
-
count = cache.count("
|
24
|
+
count = cache.count("#{key_prefix}:count:#{discriminator}", findtime)
|
21
25
|
if count >= maxretry
|
22
26
|
ban!(discriminator, bantime)
|
23
27
|
end
|
24
28
|
|
25
|
-
# Return true for blacklist
|
26
29
|
true
|
27
30
|
end
|
28
31
|
|
32
|
+
|
33
|
+
private
|
29
34
|
def ban!(discriminator, bantime)
|
30
|
-
cache.write("
|
35
|
+
cache.write("#{key_prefix}:ban:#{discriminator}", 1, bantime)
|
31
36
|
end
|
32
37
|
|
33
38
|
def banned?(discriminator)
|
34
|
-
cache.read("
|
39
|
+
cache.read("#{key_prefix}:ban:#{discriminator}")
|
35
40
|
end
|
36
41
|
|
37
42
|
def cache
|
data/lib/rack/attack/throttle.rb
CHANGED
@@ -22,14 +22,15 @@ module Rack
|
|
22
22
|
|
23
23
|
key = "#{name}:#{discriminator}"
|
24
24
|
count = cache.count(key, period)
|
25
|
+
current_limit = limit.respond_to?(:call) ? limit.call(req) : limit
|
25
26
|
data = {
|
26
27
|
:count => count,
|
27
28
|
:period => period,
|
28
|
-
:limit =>
|
29
|
+
:limit => current_limit
|
29
30
|
}
|
30
31
|
(req.env['rack.attack.throttle_data'] ||= {})[name] = data
|
31
32
|
|
32
|
-
(count >
|
33
|
+
(count > current_limit).tap do |throttled|
|
33
34
|
if throttled
|
34
35
|
req.env['rack.attack.matched'] = name
|
35
36
|
req.env['rack.attack.match_type'] = :throttle
|
@@ -38,7 +39,6 @@ module Rack
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end
|
41
|
-
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
data/lib/rack/attack/version.rb
CHANGED
@@ -0,0 +1,121 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
describe 'Rack::Attack.Allow2Ban' do
|
3
|
+
before do
|
4
|
+
# Use a long findtime; failures due to cache key rotation less likely
|
5
|
+
@cache = Rack::Attack.cache
|
6
|
+
@findtime = 60
|
7
|
+
@bantime = 60
|
8
|
+
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
9
|
+
@f2b_options = {:bantime => @bantime, :findtime => @findtime, :maxretry => 2}
|
10
|
+
Rack::Attack.blacklist('pentest') do |req|
|
11
|
+
Rack::Attack::Allow2Ban.filter(req.ip, @f2b_options){req.query_string =~ /OMGHAX/}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'discriminator has not been banned' do
|
16
|
+
describe 'making ok request' do
|
17
|
+
it 'succeeds' do
|
18
|
+
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
|
19
|
+
last_response.status.must_equal 200
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'making qualifying request' do
|
24
|
+
describe 'when not at maxretry' do
|
25
|
+
before { get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4' }
|
26
|
+
it 'succeeds' do
|
27
|
+
last_response.status.must_equal 200
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'increases fail count' do
|
31
|
+
key = "rack::attack:#{Time.now.to_i/@findtime}:allow2ban:count:1.2.3.4"
|
32
|
+
@cache.store.read(key).must_equal 1
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'is not banned' do
|
36
|
+
key = "rack::attack:allow2ban:1.2.3.4"
|
37
|
+
@cache.store.read(key).must_be_nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'when at maxretry' do
|
42
|
+
before do
|
43
|
+
# maxretry is 2 - so hit with an extra failed request first
|
44
|
+
get '/?test=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
|
45
|
+
get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'succeeds' do
|
49
|
+
last_response.status.must_equal 200
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'increases fail count' do
|
53
|
+
key = "rack::attack:#{Time.now.to_i/@findtime}:allow2ban:count:1.2.3.4"
|
54
|
+
@cache.store.read(key).must_equal 2
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'is banned' do
|
58
|
+
key = "rack::attack:allow2ban:ban:1.2.3.4"
|
59
|
+
@cache.store.read(key).must_equal 1
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'discriminator has been banned' do
|
67
|
+
before do
|
68
|
+
# maxretry is 2 - so hit enough times to get banned
|
69
|
+
get '/?test=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
|
70
|
+
get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'making request for other discriminator' do
|
74
|
+
it 'succeeds' do
|
75
|
+
get '/', {}, 'REMOTE_ADDR' => '2.2.3.4'
|
76
|
+
last_response.status.must_equal 200
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'making ok request' do
|
81
|
+
before do
|
82
|
+
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'fails' do
|
86
|
+
last_response.status.must_equal 401
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'does not increase fail count' do
|
90
|
+
key = "rack::attack:#{Time.now.to_i/@findtime}:allow2ban:count:1.2.3.4"
|
91
|
+
@cache.store.read(key).must_equal 2
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'is still banned' do
|
95
|
+
key = "rack::attack:allow2ban:ban:1.2.3.4"
|
96
|
+
@cache.store.read(key).must_equal 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'making failing request' do
|
101
|
+
before do
|
102
|
+
get '/?foo=OMGHAX', {}, 'REMOTE_ADDR' => '1.2.3.4'
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'fails' do
|
106
|
+
last_response.status.must_equal 401
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'does not increase fail count' do
|
110
|
+
key = "rack::attack:#{Time.now.to_i/@findtime}:allow2ban:count:1.2.3.4"
|
111
|
+
@cache.store.read(key).must_equal 2
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'is still banned' do
|
115
|
+
key = "rack::attack:allow2ban:ban:1.2.3.4"
|
116
|
+
@cache.store.read(key).must_equal 1
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
@@ -37,7 +37,27 @@ describe 'Rack::Attack.throttle' do
|
|
37
37
|
last_response.headers['Retry-After'].must_equal @period.to_s
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
41
40
|
end
|
42
41
|
|
42
|
+
describe 'Rack::Attack.throttle with limit as proc' do
|
43
|
+
before do
|
44
|
+
@period = 60 # Use a long period; failures due to cache key rotation less likely
|
45
|
+
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
|
46
|
+
Rack::Attack.throttle('ip/sec', :limit => lambda {|req| 1}, :period => @period) { |req| req.ip }
|
47
|
+
end
|
48
|
+
|
49
|
+
allow_ok_requests
|
50
|
+
|
51
|
+
describe 'a single request' do
|
52
|
+
before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
|
53
|
+
it 'should set the counter for one request' do
|
54
|
+
key = "rack::attack:#{Time.now.to_i/@period}:ip/sec:1.2.3.4"
|
55
|
+
Rack::Attack.cache.store.read(key).must_equal 1
|
56
|
+
end
|
43
57
|
|
58
|
+
it 'should populate throttle data' do
|
59
|
+
data = { :count => 1, :limit => 1, :period => @period }
|
60
|
+
last_request.env['rack.attack.throttle_data']['ip/sec'].must_equal data
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,110 +1,134 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-attack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
5
|
-
prerelease:
|
4
|
+
version: 2.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Aaron Suggs
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-10-11 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rack
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
17
|
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
28
|
name: minitest
|
27
|
-
requirement:
|
28
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
31
|
- - '>='
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
34
|
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
36
41
|
- !ruby/object:Gem::Dependency
|
37
42
|
name: rack-test
|
38
|
-
requirement:
|
39
|
-
none: false
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
40
44
|
requirements:
|
41
45
|
- - '>='
|
42
46
|
- !ruby/object:Gem::Version
|
43
47
|
version: '0'
|
44
48
|
type: :development
|
45
49
|
prerelease: false
|
46
|
-
version_requirements:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
47
55
|
- !ruby/object:Gem::Dependency
|
48
56
|
name: rake
|
49
|
-
requirement:
|
50
|
-
none: false
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
51
58
|
requirements:
|
52
59
|
- - '>='
|
53
60
|
- !ruby/object:Gem::Version
|
54
61
|
version: '0'
|
55
62
|
type: :development
|
56
63
|
prerelease: false
|
57
|
-
version_requirements:
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
58
69
|
- !ruby/object:Gem::Dependency
|
59
70
|
name: activesupport
|
60
|
-
requirement:
|
61
|
-
none: false
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
62
72
|
requirements:
|
63
73
|
- - '>='
|
64
74
|
- !ruby/object:Gem::Version
|
65
75
|
version: 3.0.0
|
66
76
|
type: :development
|
67
77
|
prerelease: false
|
68
|
-
version_requirements:
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.0.0
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: debugger
|
71
|
-
requirement:
|
72
|
-
none: false
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
73
86
|
requirements:
|
74
87
|
- - ~>
|
75
88
|
- !ruby/object:Gem::Version
|
76
89
|
version: '1.5'
|
77
90
|
type: :development
|
78
91
|
prerelease: false
|
79
|
-
version_requirements:
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.5'
|
80
97
|
- !ruby/object:Gem::Dependency
|
81
98
|
name: redis-activesupport
|
82
|
-
requirement:
|
83
|
-
none: false
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
84
100
|
requirements:
|
85
101
|
- - '>='
|
86
102
|
- !ruby/object:Gem::Version
|
87
103
|
version: '0'
|
88
104
|
type: :development
|
89
105
|
prerelease: false
|
90
|
-
version_requirements:
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
91
111
|
- !ruby/object:Gem::Dependency
|
92
112
|
name: dalli
|
93
|
-
requirement:
|
94
|
-
none: false
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
95
114
|
requirements:
|
96
115
|
- - '>='
|
97
116
|
- !ruby/object:Gem::Version
|
98
117
|
version: '0'
|
99
118
|
type: :development
|
100
119
|
prerelease: false
|
101
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
102
125
|
description: A rack middleware for throttling and blocking abusive requests
|
103
126
|
email: aaron@ktheory.com
|
104
127
|
executables: []
|
105
128
|
extensions: []
|
106
129
|
extra_rdoc_files: []
|
107
130
|
files:
|
131
|
+
- lib/rack/attack/allow2ban.rb
|
108
132
|
- lib/rack/attack/blacklist.rb
|
109
133
|
- lib/rack/attack/cache.rb
|
110
134
|
- lib/rack/attack/check.rb
|
@@ -117,6 +141,7 @@ files:
|
|
117
141
|
- lib/rack/attack.rb
|
118
142
|
- Rakefile
|
119
143
|
- README.md
|
144
|
+
- spec/allow2ban_spec.rb
|
120
145
|
- spec/fail2ban_spec.rb
|
121
146
|
- spec/rack_attack_cache_spec.rb
|
122
147
|
- spec/rack_attack_spec.rb
|
@@ -126,30 +151,30 @@ files:
|
|
126
151
|
homepage: http://github.com/kickstarter/rack-attack
|
127
152
|
licenses:
|
128
153
|
- MIT
|
154
|
+
metadata: {}
|
129
155
|
post_install_message:
|
130
156
|
rdoc_options:
|
131
157
|
- --charset=UTF-8
|
132
158
|
require_paths:
|
133
159
|
- lib
|
134
160
|
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
-
none: false
|
136
161
|
requirements:
|
137
162
|
- - '>='
|
138
163
|
- !ruby/object:Gem::Version
|
139
164
|
version: 1.9.2
|
140
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
-
none: false
|
142
166
|
requirements:
|
143
167
|
- - '>='
|
144
168
|
- !ruby/object:Gem::Version
|
145
169
|
version: '0'
|
146
170
|
requirements: []
|
147
171
|
rubyforge_project:
|
148
|
-
rubygems_version: 1.
|
172
|
+
rubygems_version: 2.1.6
|
149
173
|
signing_key:
|
150
|
-
specification_version:
|
174
|
+
specification_version: 4
|
151
175
|
summary: Block & throttle abusive requests
|
152
176
|
test_files:
|
177
|
+
- spec/allow2ban_spec.rb
|
153
178
|
- spec/fail2ban_spec.rb
|
154
179
|
- spec/rack_attack_cache_spec.rb
|
155
180
|
- spec/rack_attack_spec.rb
|