rack-dedos 0.5.1 → 0.7.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7345523b97820b5bae83175067c3f76b69a4c9f7f57d3bb5faa5175f5fbcdbe4
4
- data.tar.gz: 241fc35b7c5c8df31468186079dc1ba27039481437cb249ae8884cee76c94f68
3
+ metadata.gz: c9198afaa909fd5893e05e59d4e107303aedb6d9cba9a99fc26025d4785fb0f1
4
+ data.tar.gz: 573d19c93954eb75ad4f4db7b9ea92003162c1648e9b576a8e4279aa2efb6dbc
5
5
  SHA512:
6
- metadata.gz: 7daa7932e86cea82bf48f6b26e14c70e3b8732b59d6b8495531795f60c79449fe7c25f40f213bfd22098dfe5565b20e34200e5b3a035840171286b93c569deb6
7
- data.tar.gz: 94f5e9db12c676fb325624679b3105bdcdf1c107e552725cc56fc8ff77d3c84b9e617c30ccc183866c5ce7b36942843b1385befc0ec29c229807a2fa15a5f973
6
+ metadata.gz: 95d555d680506742c46c9de899c2ec17a9e4cb4d5423326777cf3b0b4b8131e85798b2f9bccbb3c9e4c7f6be44e0e2a86442ace63aab11e02cf2f21cc76a3924
7
+ data.tar.gz: 2e633200a5563c497354bba636abc42a829f4d24297fd9d8174f767c2ca789edd1e7758e83ca1eaea4788c0acb084eb9378fe9ce85c3a82f4d34d880d3f3e9b3
data/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  Nothing so far
4
4
 
5
+ ## 0.7.1
6
+
7
+ ### Improvements
8
+ * Enforce MFA for future gem releases
9
+
10
+ ## 0.7.0
11
+
12
+ ### Breaking changes
13
+ * Change format of country code details in log
14
+
15
+ ### Fixes
16
+ * Drop keyword arguments for Rack compatibility
17
+ * Fix collision with Rack::Logger
18
+
19
+ ## 0.6.0 (yanked)
20
+
21
+ ### Breaking changes
22
+ * Log to STDOUT (instead of STDERR) by default
23
+
24
+ ### Additions
25
+ * Suppport custom loggers
26
+ * Optionally log request headers
27
+
5
28
  ## 0.5.1
6
29
 
7
30
  ### Fixes
data/README.md CHANGED
@@ -122,6 +122,33 @@ use Rack::Dedos,
122
122
  text: "Temporary Server Error"
123
123
  ```
124
124
 
125
+ ### Log
126
+
127
+ By default, blocked request are logged as info to `$stdout` such as:
128
+
129
+ > rack-dedos: request /foobar from 1.2.3.4 blocked by Rack::Dedos::Filters::Country: CN
130
+
131
+ The level of details may differ by filter, however, if you want to drill down and log additional request headers, you can configure which headers to include as follows:
132
+
133
+ ```ruby
134
+ use Rack::Dedos,
135
+ headers: ['HTTP_USER_AGENT', 'HTTP_REFERER']
136
+ ```
137
+
138
+ You can direct the log stream to any logger object you wish:
139
+
140
+ ```ruby
141
+ use Rack::Dedos,
142
+ logger: Logger.new('/var/log/rack-dedos.log')
143
+ ```
144
+
145
+ Or disable logging entirely:
146
+
147
+ ```ruby
148
+ use Rack::Dedos,
149
+ logger: Logger.new(nil)
150
+ ```
151
+
125
152
  ## Filters
126
153
 
127
154
  By default, all filters described below are applied. You can exclude certain filters:
@@ -199,12 +226,19 @@ cd rack-dedos
199
226
  git submodule update --init
200
227
  ```
201
228
 
202
- To install the development dependencies and then run the test suite:
229
+ To install only the development dependencies:
230
+
231
+ ```
232
+ bundle install
233
+ bundle exec rake # run the tests once
234
+ ```
235
+
236
+ To install the development dependencies and development tools (such as guard):
203
237
 
204
238
  ```
239
+ bundle config set --local with toolbox
205
240
  bundle install
206
- bundle exec rake # run tests once
207
- bundle exec guard # run tests whenever files are modified
241
+ bundle exec guard # run the tests whenever files are modified
208
242
  ```
209
243
 
210
244
  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).
@@ -1,27 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'logger'
4
+
3
5
  module Rack
4
6
  module Dedos
5
7
  module Filters
6
8
  class Base
7
9
 
8
10
  DEFAULT_OPTIONS = {
11
+ logger: nil,
9
12
  only_paths: [],
10
13
  except_paths: [],
11
14
  status: 403,
12
- text: 'Forbidden (Temporarily Blocked by Rules)'
15
+ text: 'Forbidden (Temporarily Blocked by Rules)',
16
+ headers: []
13
17
  }.freeze
14
18
 
15
- attr_reader :app
16
- attr_reader :options
17
- attr_reader :details
19
+ attr_reader :app, :options, :details
18
20
 
19
21
  # @param app [#call]
20
22
  # @param options [Hash{Symbol => Object}]
21
- def initialize(app, options = {})
23
+ def initialize(app, options={})
22
24
  @app = app
23
25
  @options = DEFAULT_OPTIONS.merge(options)
24
- @details = nil
26
+ @details = {}
25
27
  end
26
28
 
27
29
  def call(env)
@@ -30,8 +32,10 @@ module Rack
30
32
  if !apply?(request) || allowed?(request, ip)
31
33
  app.call(env)
32
34
  else
33
- message = "rack-dedos: request #{request.path} from #{ip} blocked by #{name}"
34
- warn([message, details].compact.join(": "))
35
+ message = ["request #{request.path} from #{ip} blocked by #{name}"]
36
+ message += details_list
37
+ message += headers_list(request)
38
+ logger.info(message.join(' '))
35
39
  [options[:status], { 'Content-Type' => 'text/plain' }, [options[:text]]]
36
40
  end
37
41
  end
@@ -42,6 +46,10 @@ module Rack
42
46
  Rack::Dedos.config
43
47
  end
44
48
 
49
+ def logger
50
+ @logger ||= options[:logger] || ::Logger.new($stdout, progname: 'rack-dedos')
51
+ end
52
+
45
53
  def apply?(request)
46
54
  return false if @options[:except_paths].any? { request.path.match? _1 }
47
55
  return true if @options[:only_paths].none?
@@ -71,6 +79,17 @@ module Rack
71
79
  end
72
80
  end
73
81
 
82
+ def details_list
83
+ details.map do |key, value|
84
+ "#{key.upcase}=#{value.inspect}"
85
+ end
86
+ end
87
+
88
+ def headers_list(request)
89
+ options[:headers].map do |header|
90
+ "#{header.upcase}=#{request.get_header(header).inspect}"
91
+ end
92
+ end
74
93
  end
75
94
  end
76
95
  end
@@ -14,7 +14,7 @@ module Rack
14
14
  # @option options [String] :maxmind_db_file MaxMind database file
15
15
  # @option options [Symbol, Array<Symbol>] :allowed_countries ISO 3166-1 alpha 2
16
16
  # @option options [Symbol, Array<Symbol>] :denied_countries ISO 3166-1 alpha 2
17
- def initialize(*)
17
+ def initialize(...)
18
18
  super
19
19
  @maxmind_db_file = options[:maxmind_db_file] or fail "MaxMind database file not set"
20
20
  @allowed = case
@@ -26,14 +26,14 @@ module Rack
26
26
  end
27
27
 
28
28
  def allowed?(request, ip)
29
- if country = maxmind_db&.get(ip)
30
- country_code = @details = country.dig('country', 'iso_code').to_sym
31
- @countries.include?(country_code) ? @allowed : !@allowed
29
+ if db = maxmind_db&.get(ip)
30
+ details[:country_code] = db.dig('country', 'iso_code').to_sym
31
+ @countries.include?(details[:country_code]) ? @allowed : !@allowed
32
32
  else # not found in database
33
33
  true
34
34
  end
35
35
  rescue => error
36
- warn("rack-dedos: request from #{ip} allowed due to error: #{error.message}")
36
+ logger.error("request from #{ip} allowed due to error: #{error.message}")
37
37
  true
38
38
  end
39
39
 
@@ -12,7 +12,7 @@ module Rack
12
12
  # @option options [String] :cache_url URL of the cache backend
13
13
  # @option options [Integer] :cache_period how long to retain cached IP
14
14
  # addresses in seconds (default: 900)
15
- def initialize(*)
15
+ def initialize(...)
16
16
  super
17
17
  @cache_url = options[:cache_url] or fail "cache URL not set"
18
18
  @cache_period = options[:cache_period] || 900
@@ -34,7 +34,7 @@ module Rack
34
34
  false
35
35
  end
36
36
  rescue => error
37
- warn("rack-dedos: request from #{ip} allowed due to error: #{error.message}")
37
+ logger.error("request from #{ip} allowed due to error: #{error.message}")
38
38
  true
39
39
  end
40
40
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rack
4
4
  module Dedos
5
- VERSION = "0.5.1"
5
+ VERSION = "0.7.1"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-dedos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Schwyn
@@ -24,13 +24,13 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: 2.2.0
26
26
  - !ruby/object:Gem::Dependency
27
- name: redis
27
+ name: logger
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: '0'
33
- type: :development
33
+ type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
@@ -38,7 +38,7 @@ dependencies:
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0'
40
40
  - !ruby/object:Gem::Dependency
41
- name: maxmind-db
41
+ name: rake
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ">="
@@ -52,7 +52,7 @@ dependencies:
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
54
  - !ruby/object:Gem::Dependency
55
- name: debug
55
+ name: redis
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
@@ -66,7 +66,7 @@ dependencies:
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
68
  - !ruby/object:Gem::Dependency
69
- name: rake
69
+ name: maxmind-db
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - ">="
@@ -107,62 +107,6 @@ dependencies:
107
107
  - - ">="
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
- - !ruby/object:Gem::Dependency
111
- name: minitest-flash
112
- requirement: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- version: '0'
117
- type: :development
118
- prerelease: false
119
- version_requirements: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - ">="
122
- - !ruby/object:Gem::Version
123
- version: '0'
124
- - !ruby/object:Gem::Dependency
125
- name: guard
126
- requirement: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - ">="
129
- - !ruby/object:Gem::Version
130
- version: '0'
131
- type: :development
132
- prerelease: false
133
- version_requirements: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - ">="
136
- - !ruby/object:Gem::Version
137
- version: '0'
138
- - !ruby/object:Gem::Dependency
139
- name: guard-minitest
140
- requirement: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - ">="
143
- - !ruby/object:Gem::Version
144
- version: '0'
145
- type: :development
146
- prerelease: false
147
- version_requirements: !ruby/object:Gem::Requirement
148
- requirements:
149
- - - ">="
150
- - !ruby/object:Gem::Version
151
- version: '0'
152
- - !ruby/object:Gem::Dependency
153
- name: yard
154
- requirement: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - ">="
157
- - !ruby/object:Gem::Version
158
- version: '0'
159
- type: :development
160
- prerelease: false
161
- version_requirements: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - ">="
164
- - !ruby/object:Gem::Version
165
- version: '0'
166
110
  description: |
167
111
  Somewhat more radical filters designed to decimate malicious requests during
168
112
  a denial-of-service (DoS) attack by chopping their connection well before
@@ -202,6 +146,7 @@ metadata:
202
146
  source_code_uri: https://github.com/svoop/rack-dedos
203
147
  documentation_uri: https://www.rubydoc.info/gems/rack-dedos
204
148
  bug_tracker_uri: https://github.com/svoop/rack-dedos/issues
149
+ rubygems_mfa_required: 'true'
205
150
  rdoc_options:
206
151
  - "--title"
207
152
  - Rack::Dedos
@@ -223,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
223
168
  - !ruby/object:Gem::Version
224
169
  version: '0'
225
170
  requirements: []
226
- rubygems_version: 4.0.3
171
+ rubygems_version: 4.0.6
227
172
  specification_version: 4
228
173
  summary: Radical filters to block denial-of-service (DoS) requests.
229
174
  test_files: []