rack-dedos 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +2 -0
- data/CHANGELOG.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +163 -0
- data/lib/rack/dedos/base.rb +40 -0
- data/lib/rack/dedos/cache.rb +61 -0
- data/lib/rack/dedos/country.rb +46 -0
- data/lib/rack/dedos/user_agent.rb +48 -0
- data/lib/rack/dedos/version.rb +7 -0
- data/lib/rack/dedos.rb +31 -0
- data.tar.gz.sig +4 -0
- metadata +250 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 69f8976f9ee4fc15e9c0b3915020919fa72014acb8577933a5bdcd02b674570c
|
4
|
+
data.tar.gz: 31bbb973f18eee8e22ed576a12846f6443d1ab2106fa3b8a1cdf6b52cc374464
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f506c9e93a4eb859a79c74c2053e493455aa13ebe8487fc42650a59bdb3e65da862b02cfab1cbfc54cb2186e340e014547bf6df4caf4f0afe2eae7233f3c9c1a
|
7
|
+
data.tar.gz: 9a18dfe754ea786cbef049ec91a11108fb36c272ce954190331612089412957f3056f0635f6bf520a60ff0ab3373678067f6fcc5a7cf4e05799b170a6139a26f
|
checksums.yaml.gz.sig
ADDED
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 Sven Schwyn
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
[![Version](https://img.shields.io/gem/v/rack-dedos.svg?style=flat)](https://rubygems.org/gems/rack-dedos)
|
2
|
+
[![Tests](https://img.shields.io/github/actions/workflow/status/svoop/rack-dedos/test.yml?style=flat&label=tests)](https://github.com/svoop/rack-dedos/actions?workflow=Test)
|
3
|
+
[![Code Climate](https://img.shields.io/codeclimate/maintainability/svoop/rack-dedos.svg?style=flat)](https://codeclimate.com/github/svoop/rack-dedos/)
|
4
|
+
[![Donorbox](https://img.shields.io/badge/donate-on_donorbox-yellow.svg)](https://donorbox.org/bitcetera)
|
5
|
+
|
6
|
+
<img src="https://github.com/svoop/rack-dedos/raw/main/doc/chop-chop.png" alt="chop-chop" align="right">
|
7
|
+
|
8
|
+
# Rack::Dedos
|
9
|
+
|
10
|
+
Somewhat more radical filters designed to decimate malicious requests during a [denial-of-service (DoS) attack](https://en.wikipedia.org/wiki/Denial-of-service_attack) by chopping their connection well before your Rack app wastes any significant resources on them – ouch!
|
11
|
+
|
12
|
+
The filters have been proven to work against certain DoS attacks, however, they might also block IPs behind proxies or VPNs. Make sure you have understood how the filters are triggered and consider this middleware a last resort only to be enabled during an attack.
|
13
|
+
|
14
|
+
* [Homepage](https://github.com/svoop/rack-dedos)
|
15
|
+
* [API](https://www.rubydoc.info/gems/rack-dedos)
|
16
|
+
* Author: [Sven Schwyn - Bitcetera](https://bitcetera.com)
|
17
|
+
|
18
|
+
## Install
|
19
|
+
|
20
|
+
### Security
|
21
|
+
|
22
|
+
This gem is [cryptographically signed](https://guides.rubygems.org/security/#using-gems) in order to assure it hasn't been tampered with. Unless already done, please add the author's public key as a trusted certificate now:
|
23
|
+
|
24
|
+
```
|
25
|
+
gem cert --add <(curl -Ls https://raw.github.com/svoop/rack-dedos/main/certs/svoop.pem)
|
26
|
+
```
|
27
|
+
|
28
|
+
### Bundler
|
29
|
+
|
30
|
+
Add the following to the <tt>Gemfile</tt> or <tt>gems.rb</tt> of your [Bundler](https://bundler.io) powered Ruby project:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
gem 'rack-dedos'
|
34
|
+
```
|
35
|
+
|
36
|
+
And then install the bundle:
|
37
|
+
|
38
|
+
```
|
39
|
+
bundle install --trust-policy MediumSecurity
|
40
|
+
```
|
41
|
+
|
42
|
+
## Configuration
|
43
|
+
|
44
|
+
Given the drastic nature of the filters, you should use this middleware for production environments only and/or if an environment variable like `UNDER_ATTACK` is set to true.
|
45
|
+
|
46
|
+
### Rails
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
# config/application.rb
|
50
|
+
class Application < Rails::Application
|
51
|
+
if Rails.env.production? && ActiveModel::Type::Boolean.new.cast(ENV['UNDER_ATTACK'])
|
52
|
+
config.middleware.use Rack::Dedos
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
### Rackup
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
#!/usr/bin/env rackup
|
61
|
+
require 'rack/dedos'
|
62
|
+
|
63
|
+
if %w(true t on 1).include? ENV['UNDER_ATTACK']
|
64
|
+
use Rack::Dedos
|
65
|
+
end
|
66
|
+
|
67
|
+
run lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, world!\n"] }
|
68
|
+
```
|
69
|
+
|
70
|
+
### Response
|
71
|
+
|
72
|
+
If a request is classified as malicious by at least one filter, the middleware responds with:
|
73
|
+
|
74
|
+
> 403 Forbidden (Temporarily Blocked by Rules)
|
75
|
+
|
76
|
+
This is the most appropriate response, however, feel free to trick the requester by tweaking this:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
use Rack::Dedos,
|
80
|
+
status: 503,
|
81
|
+
text: "Temporary Server Error"
|
82
|
+
```
|
83
|
+
|
84
|
+
## Filters
|
85
|
+
|
86
|
+
By default, all filters described below are applied. You can exclude exclude certain filters:
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
use Rack::Dedos,
|
90
|
+
exclude: [:user_agent]
|
91
|
+
```
|
92
|
+
|
93
|
+
To only apply one specific filter, use the corresponding class as shown below.
|
94
|
+
|
95
|
+
### User Agent Filter
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
use Rack::Dedos::UserAgent,
|
99
|
+
cache_url: 'redis://redis.example.com:6379/12', # db 12 on default port
|
100
|
+
cache_key_prefix: 'dedos', # key prefix for shared caches (default: nil)
|
101
|
+
cache_period: 1800 # seconds (default: 900)
|
102
|
+
```
|
103
|
+
|
104
|
+
Requests are blocked for `cache_period` seconds in case another request has been made within `cache_period` seconds from by same IP address but with a different user agent.
|
105
|
+
|
106
|
+
The following cache backends are supported:
|
107
|
+
|
108
|
+
* `redis://...` – ⚠️ The [redis gem](https://rubygems.org/gems/redis) has to be installed.
|
109
|
+
* `hash` – Only for testing, don't use this in production.
|
110
|
+
|
111
|
+
### Country Filter
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
use Rack::Dedos::Country,
|
115
|
+
maxmind_db_file: '/var/db/maxmind/GeoLite2-Country.mmdb',
|
116
|
+
allowed_countries: %i(AT CH DE),
|
117
|
+
denied_countries: %i(RU)
|
118
|
+
```
|
119
|
+
|
120
|
+
Either allow or deny requests by probable country of origin. If both are set, the `denied_countries` option is ignored.
|
121
|
+
|
122
|
+
⚠️ The [maxmind-db gem](https://rubygems.org/gems/maxmind-db) has to be installed.
|
123
|
+
|
124
|
+
The MaxMind GeoLite2 database is free, however, you have to create an account on [maxmind.com](https://www.maxmind.com) and then download the country database.
|
125
|
+
|
126
|
+
For automatic updates, create a `geoipupdate.conf` file and then use the [geoipupdate tool](https://github.com/maxmind/geoipupdate/releases) to fetch the latest country database:
|
127
|
+
|
128
|
+
```
|
129
|
+
version=4.10.0
|
130
|
+
arch=linux_amd64
|
131
|
+
conf=/etc/geoipupdate.conf
|
132
|
+
dir=/var/db/maxmind/
|
133
|
+
|
134
|
+
mkdir -p "${dir}"
|
135
|
+
wget --quiet -O /tmp/geoipupdate.tgz https://github.com/maxmind/geoipupdate/releases/download/v${version}/geoipupdate_${version}_${arch}.tar.gz
|
136
|
+
tar -xz -C /tmp -f /tmp/geoipupdate.tgz
|
137
|
+
/tmp/geoipupdate_${version}_${arch}/geoipupdate -f "${conf}" -d "${dir}"
|
138
|
+
```
|
139
|
+
|
140
|
+
## Development
|
141
|
+
|
142
|
+
For all required test fixtures to be present, you have to check out the repo
|
143
|
+
with all of its submodules:
|
144
|
+
|
145
|
+
```
|
146
|
+
git clone git@github.com:svoop/rack-dedos.git
|
147
|
+
cd rack-dedos
|
148
|
+
git submodule update --init
|
149
|
+
```
|
150
|
+
|
151
|
+
To install the development dependencies and then run the test suite:
|
152
|
+
|
153
|
+
```
|
154
|
+
bundle install
|
155
|
+
bundle exec rake # run tests once
|
156
|
+
bundle exec guard # run tests whenever files are modified
|
157
|
+
```
|
158
|
+
|
159
|
+
You're welcome to [submit issues](https://github.com/svoop/rack-dedos/issues) and contribute code by [forking the project and submitting pull requests](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
|
160
|
+
|
161
|
+
## License
|
162
|
+
|
163
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Dedos
|
5
|
+
class Base
|
6
|
+
|
7
|
+
DEFAULT_OPTIONS = {
|
8
|
+
status: 403,
|
9
|
+
text: 'Forbidden (Temporarily Blocked by Rules)'
|
10
|
+
}
|
11
|
+
|
12
|
+
attr_reader :app
|
13
|
+
attr_reader :options
|
14
|
+
|
15
|
+
# @param app [#call]
|
16
|
+
# @param options [Hash{Symbol => Object}]
|
17
|
+
def initialize(app, options = {})
|
18
|
+
@app = app
|
19
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(env)
|
23
|
+
request = Rack::Request.new(env)
|
24
|
+
if allowed?(request)
|
25
|
+
app.call(env)
|
26
|
+
else
|
27
|
+
warn("rack-dedos: request from #{request.ip} blocked by #{self.class}")
|
28
|
+
[options[:status], { 'Content-Type' => 'text/plain' }, [options[:text]]]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def config
|
35
|
+
Rack::Dedos.config
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Dedos
|
5
|
+
class Cache
|
6
|
+
|
7
|
+
def initialize(url:, expires_in: nil, key_prefix: nil)
|
8
|
+
@url, @expires_in = url, expires_in
|
9
|
+
@key_prefix = ("#{key_prefix}:" if key_prefix).to_s
|
10
|
+
type = url.split(':').first
|
11
|
+
extend Object.const_get("Rack::Dedos::Cache::#{type.capitalize}")
|
12
|
+
rescue NameError
|
13
|
+
raise(ArgumentError, "type of cache for `#{@url}' not supported")
|
14
|
+
end
|
15
|
+
|
16
|
+
module Hash
|
17
|
+
def store
|
18
|
+
@store ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def set(key, value)
|
22
|
+
store[key] = [value, timestamp]
|
23
|
+
end
|
24
|
+
|
25
|
+
def get(key)
|
26
|
+
if (value, created_at = store[key])
|
27
|
+
if !@expires_in || @expires_in >= timestamp - created_at
|
28
|
+
value
|
29
|
+
else
|
30
|
+
store.delete(key)
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def timestamp
|
39
|
+
Time.now.to_i
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module Redis
|
44
|
+
require 'redis'
|
45
|
+
|
46
|
+
def store
|
47
|
+
@store ||= ::Redis.new(url: @url)
|
48
|
+
end
|
49
|
+
|
50
|
+
def set(key, value)
|
51
|
+
store.set(@key_prefix + key, value, ex: @expires_in)
|
52
|
+
end
|
53
|
+
|
54
|
+
def get(key)
|
55
|
+
store.get(@key_prefix + key)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'maxmind/db'
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
module Dedos
|
7
|
+
class Country < Base
|
8
|
+
|
9
|
+
# @option options [String] :maxmind_db_file MaxMind database file
|
10
|
+
# @option options [Symbol, Array<Symbol>] :allowed_countries ISO 3166-1 alpha 2
|
11
|
+
# @option options [Symbol, Array<Symbol>] :denied_countries ISO 3166-1 alpha 2
|
12
|
+
def initialize(*)
|
13
|
+
super
|
14
|
+
@maxmind_db_file = options[:maxmind_db_file] or fail "MaxMind database file not set"
|
15
|
+
@allowed = case
|
16
|
+
when @countries = options[:allowed_countries] then true
|
17
|
+
when @countries = options[:denied_countries] then false
|
18
|
+
else fail "neither allowed nor denied countries set"
|
19
|
+
end
|
20
|
+
maxmind_db # hit once to fail on errors at boot
|
21
|
+
end
|
22
|
+
|
23
|
+
def allowed?(request)
|
24
|
+
if country = maxmind_db.get(request.ip)
|
25
|
+
country_code = country.dig('country', 'iso_code').to_sym
|
26
|
+
@countries.include?(country_code) ? @allowed : !@allowed
|
27
|
+
else # not found in database
|
28
|
+
true
|
29
|
+
end
|
30
|
+
rescue => error
|
31
|
+
warn("rack-dedos: request from #{request.ip} allowed due to error: #{error.message}")
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def maxmind_db
|
38
|
+
config[:maxmind_db] ||= MaxMind::DB.new(
|
39
|
+
@maxmind_db_file,
|
40
|
+
mode: MaxMind::DB::MODE_FILE
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module Dedos
|
5
|
+
class UserAgent < Base
|
6
|
+
|
7
|
+
# @option options [String] :cache_url URL of the cache backend
|
8
|
+
# @option options [Integer] :cache_period how long to retain cached IP
|
9
|
+
# addresses in seconds (default: 900)
|
10
|
+
def initialize(*)
|
11
|
+
super
|
12
|
+
@cache_url = options[:cache_url] or fail "cache URL not set"
|
13
|
+
@cache_period = options[:cache_period] || 900
|
14
|
+
@cache_key_prefix = options[:cache_key_prefix]
|
15
|
+
cache # hit once to fail on errors at boot
|
16
|
+
end
|
17
|
+
|
18
|
+
def allowed?(request)
|
19
|
+
case cache.get(request.ip)
|
20
|
+
when nil # first contact
|
21
|
+
cache.set(request.ip, request.user_agent)
|
22
|
+
true
|
23
|
+
when 'BLOCKED' # already blocked
|
24
|
+
false
|
25
|
+
when request.user_agent # user agent hasn't changed
|
26
|
+
true
|
27
|
+
else # user agent has changed
|
28
|
+
cache.set(request.ip, 'BLOCKED')
|
29
|
+
false
|
30
|
+
end
|
31
|
+
rescue => error
|
32
|
+
warn("rack-dedos: request from #{request.ip} allowed due to error: #{error.message}")
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def cache
|
39
|
+
config[:cache] ||= Cache.new(
|
40
|
+
url: @cache_url,
|
41
|
+
expires_in: @cache_period,
|
42
|
+
key_prefix: @cache_key_prefix
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/rack/dedos.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rack'
|
4
|
+
|
5
|
+
require_relative 'dedos/version'
|
6
|
+
|
7
|
+
module Rack
|
8
|
+
module Dedos
|
9
|
+
lib_dir = ::File.expand_path(::File.dirname(__FILE__))
|
10
|
+
autoload :Cache, lib_dir + '/dedos/cache'
|
11
|
+
autoload :Base, lib_dir + '/dedos/base'
|
12
|
+
autoload :UserAgent, lib_dir + '/dedos/user_agent'
|
13
|
+
autoload :Country, lib_dir + '/dedos/country'
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def config
|
17
|
+
@config ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def new(app, options = {})
|
21
|
+
except = Array options[:except]
|
22
|
+
|
23
|
+
Rack::Builder.new do
|
24
|
+
use(::Rack::Dedos::UserAgent, options) unless except.include? :user_agent
|
25
|
+
use(::Rack::Dedos::Country, options) unless except.include? :country
|
26
|
+
run app
|
27
|
+
end.to_app
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data.tar.gz.sig
ADDED
metadata
ADDED
@@ -0,0 +1,250 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-dedos
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sven Schwyn
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDODCCAiCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhydWJ5
|
14
|
+
L0RDPWJpdGNldGVyYS9EQz1jb20wHhcNMjIxMTA2MTIzNjUwWhcNMjMxMTA2MTIz
|
15
|
+
NjUwWjAjMSEwHwYDVQQDDBhydWJ5L0RDPWJpdGNldGVyYS9EQz1jb20wggEiMA0G
|
16
|
+
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDcLg+IHjXYaUlTSU7R235lQKD8ZhEe
|
17
|
+
KMhoGlSUonZ/zo1OT3KXcqTCP1iMX743xYs6upEGALCWWwq+nxvlDdnWRjF3AAv7
|
18
|
+
ikC+Z2BEowjyeCCT/0gvn4ohKcR0JOzzRaIlFUVInlGSAHx2QHZ2N8ntf54lu7nd
|
19
|
+
L8CiDK8rClsY4JBNGOgH9UC81f+m61UUQuTLxyM2CXfAYkj/sGNTvFRJcNX+nfdC
|
20
|
+
hM9r2kH1+7wsa8yG7wJ2IkrzNACD8v84oE6qVusN8OLEMUI/NaEPVPbw2LUM149H
|
21
|
+
PVa0i729A4IhroNnFNmw4wOC93ARNbM1+LW36PLMmKjKudf5Exg8VmDVAgMBAAGj
|
22
|
+
dzB1MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBSfK8MtR62mQ6oN
|
23
|
+
yoX/VKJzFjLSVDAdBgNVHREEFjAUgRJydWJ5QGJpdGNldGVyYS5jb20wHQYDVR0S
|
24
|
+
BBYwFIEScnVieUBiaXRjZXRlcmEuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAYG2na
|
25
|
+
ye8OE2DANQIFM/xDos/E4DaPWCJjX5xvFKNKHMCeQYPeZvLICCwyw2paE7Otwk6p
|
26
|
+
uvbg2Ks5ykXsbk5i6vxDoeeOLvmxCqI6m+tHb8v7VZtmwRJm8so0eSX0WvTaKnIf
|
27
|
+
CAn1bVUggczVdNoBXw9WAILKyw9bvh3Ft740XZrR74sd+m2pGwjCaM8hzLvrVbGP
|
28
|
+
DyYhlBeRWyQKQ0WDIsiTSRhzK8HwSTUWjvPwx7SEdIU/HZgyrk0ETObKPakVu6bH
|
29
|
+
kAyiRqgxF4dJviwtqI7mZIomWL63+kXLgjOjMe1SHxfIPo/0ji6+r1p4KYa7o41v
|
30
|
+
fwIwU1MKlFBdsjkd
|
31
|
+
-----END CERTIFICATE-----
|
32
|
+
date: 2023-02-03 00:00:00.000000000 Z
|
33
|
+
dependencies:
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rack
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.2.0
|
41
|
+
type: :runtime
|
42
|
+
prerelease: false
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.2.0
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: redis
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: maxmind-db
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
type: :development
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: debug
|
78
|
+
requirement: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: rake
|
92
|
+
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
type: :development
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: minitest
|
106
|
+
requirement: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
- !ruby/object:Gem::Dependency
|
119
|
+
name: minitest-sound
|
120
|
+
requirement: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
type: :development
|
126
|
+
prerelease: false
|
127
|
+
version_requirements: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
- !ruby/object:Gem::Dependency
|
133
|
+
name: minitest-focus
|
134
|
+
requirement: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
type: :development
|
140
|
+
prerelease: false
|
141
|
+
version_requirements: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
- !ruby/object:Gem::Dependency
|
147
|
+
name: guard
|
148
|
+
requirement: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
type: :development
|
154
|
+
prerelease: false
|
155
|
+
version_requirements: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
- !ruby/object:Gem::Dependency
|
161
|
+
name: guard-minitest
|
162
|
+
requirement: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
type: :development
|
168
|
+
prerelease: false
|
169
|
+
version_requirements: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: yard
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
type: :development
|
182
|
+
prerelease: false
|
183
|
+
version_requirements: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
description: |
|
189
|
+
Somewhat more radical filters designed to decimate malicious requests during
|
190
|
+
a denial-of-service (DoS) attack by chopping their connection well before
|
191
|
+
your Rack app wastes any significant resources on them – ouch!
|
192
|
+
|
193
|
+
The filters have been proven to work against certain DoS attacks, however,
|
194
|
+
they might also block IPs behind proxies or VPNs. Make sure you have
|
195
|
+
understood how the filters are triggered and consider this middleware a last
|
196
|
+
resort only to be enabled during an attack.
|
197
|
+
email:
|
198
|
+
- ruby@bitcetera.com
|
199
|
+
executables: []
|
200
|
+
extensions: []
|
201
|
+
extra_rdoc_files:
|
202
|
+
- README.md
|
203
|
+
- CHANGELOG.md
|
204
|
+
- LICENSE.txt
|
205
|
+
files:
|
206
|
+
- CHANGELOG.md
|
207
|
+
- LICENSE.txt
|
208
|
+
- README.md
|
209
|
+
- lib/rack/dedos.rb
|
210
|
+
- lib/rack/dedos/base.rb
|
211
|
+
- lib/rack/dedos/cache.rb
|
212
|
+
- lib/rack/dedos/country.rb
|
213
|
+
- lib/rack/dedos/user_agent.rb
|
214
|
+
- lib/rack/dedos/version.rb
|
215
|
+
homepage: https://github.com/svoop/rack-dedos
|
216
|
+
licenses:
|
217
|
+
- MIT
|
218
|
+
metadata:
|
219
|
+
homepage_uri: https://github.com/svoop/rack-dedos
|
220
|
+
changelog_uri: https://github.com/svoop/rack-dedos/blob/main/CHANGELOG.md
|
221
|
+
source_code_uri: https://github.com/svoop/rack-dedos
|
222
|
+
documentation_uri: https://www.rubydoc.info/gems/rack-dedos
|
223
|
+
bug_tracker_uri: https://github.com/svoop/rack-dedos/issues
|
224
|
+
post_install_message:
|
225
|
+
rdoc_options:
|
226
|
+
- "--title"
|
227
|
+
- AIXM/OFMX Builder
|
228
|
+
- "--main"
|
229
|
+
- README.md
|
230
|
+
- "--line-numbers"
|
231
|
+
- "--inline-source"
|
232
|
+
- "--quiet"
|
233
|
+
require_paths:
|
234
|
+
- lib
|
235
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
236
|
+
requirements:
|
237
|
+
- - ">="
|
238
|
+
- !ruby/object:Gem::Version
|
239
|
+
version: 2.7.0
|
240
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
241
|
+
requirements:
|
242
|
+
- - ">="
|
243
|
+
- !ruby/object:Gem::Version
|
244
|
+
version: '0'
|
245
|
+
requirements: []
|
246
|
+
rubygems_version: 3.4.6
|
247
|
+
signing_key:
|
248
|
+
specification_version: 4
|
249
|
+
summary: Radical filters to block denial-of-service (DoS) requests.
|
250
|
+
test_files: []
|
metadata.gz.sig
ADDED
Binary file
|