rack-dedos 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,2 @@
1
+ �n
2
+ �.�D�j��v����=0��91[�⅑E��"g�({[�n��:�s�fqSc���+����c�Ș��58j���`�j�~ur��sn�-�m�P@���#D�.�p�!%`W�{3qw���$|�3�Dݴ��nJR�ڥW�ߦ��CΘ�2��k9>|����c�e@�K6��I뒢�y�,��*C���il�G�:I�zk��X��G�� HP�VK��$�_��s�}8b0 �L�JX9����4@��R]:
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ ## Main
2
+
3
+ Nothing so far
4
+
5
+ ## 0.1.0
6
+
7
+ #### Initial implementation
8
+
9
+ * UserAgent filter
10
+ * Country filter
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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ module Dedos
5
+ VERSION = "0.1.0"
6
+ end
7
+ 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
@@ -0,0 +1,4 @@
1
+ �!-�h�v�
2
+ gJ%�*.�|T�����X �IN郵������[HDt E.���S��S�R�U+;M��]�#8��t��7���,y�DQ��qà�Î��n����[6 �g
3
+ ��8[��҄�z�9Ais$�gY��g G���U1E]����mCH{��y������j'
4
+ ��xK�����=g�vW��ň;x��Ɲ�-,��Ⱦ??��p �j%�js�g��a��Ċ��?L^�$kr
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