cloudflare-rails 6.1.0 → 6.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +15 -9
- data/cloudflare-rails.gemspec +2 -3
- data/lib/cloudflare_rails/check_trusted_proxies.rb +1 -1
- data/lib/cloudflare_rails/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6744917646a84fbd4d06faabf47537911ebc59369ab4848c0a3e9979ee21116e
|
4
|
+
data.tar.gz: 7bf4fc1daee7eb7101056eb3ab18d765ccfccbe5b8c02608f65daced10d0f49b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49816d30c9ef0c1b59aac36eb59d4a30465d285e0426ed7a1c3b41439910acb2ab4c0f71c2d7f4fa90a5c02baba2ad58b23338b446120c6c4b078d691cede797
|
7
|
+
data.tar.gz: 2121fa3a384f1d3630cb0f87bd2a40bb6228ad2a5defa8fddad514c6b84c9cca37e19bc50bbdbf69e4fdee43966ba7cd8e7fb53f109176e8a45e1df3d63e0cf9
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
## [6.2.0]
|
7
|
+
- Trust X-Forwarded-For from the right to the left (https://github.com/modosc/cloudflare-rails/pull/162)
|
8
|
+
|
6
9
|
## [6.1.0]
|
7
10
|
- Add cloudflare? method to determine if request passed through CF (https://github.com/modosc/cloudflare-rails/pull/149)
|
8
11
|
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# CloudflareRails [![Gem Version](https://badge.fury.io/rb/cloudflare-rails.svg)](https://badge.fury.io/rb/cloudflare-rails)
|
2
|
+
|
2
3
|
This gem correctly configures Rails for [CloudFlare](https://www.cloudflare.com) so that `request.remote_ip` / `request.ip` both work correctly. It also exposes a `#cloudflare?` method on `Rack::Request`.
|
3
4
|
|
4
5
|
## Rails Compatibility
|
@@ -38,9 +39,11 @@ Using Cloudflare means it's hard to identify the IP address of incoming requests
|
|
38
39
|
`cloudflare-rails` mitigates this attack by checking that the originating ip address of any incoming connection is from one of Cloudflare's ip address ranges. If so, the incoming `X-Forwarded-For` header is trusted and used as the ip address provided to `rack` and `rails` (via `request.ip` and `request.remote_ip`). If the incoming connection does not originate from a Cloudflare server then the `X-Forwarded-For` header is ignored and the actual remote ip address is used.
|
39
40
|
|
40
41
|
## How it works
|
42
|
+
|
41
43
|
This code fetches and caches CloudFlare's current [IPv4](https://www.cloudflare.com/ips-v4) and [IPv6](https://www.cloudflare.com/ips-v6) lists. It then patches `Rack::Request::Helpers` and `ActionDispatch::RemoteIP` to treat these addresses as trusted proxies. The `X-Forwarded-For` header will then be trusted only from those ip addresses.
|
42
44
|
|
43
45
|
### Why not use `config.action_dispatch.trusted_proxies` or `Rack::Request.ip_filter?`
|
46
|
+
|
44
47
|
By default Rails includes the [ActionDispatch::RemoteIp](https://api.rubyonrails.org/classes/ActionDispatch/RemoteIp.html) middleware. This middleware uses a default list of [trusted proxies](https://github.com/rails/rails/blob/6b93fff8af32ef5e91f4ec3cfffb081d0553faf0/actionpack/lib/action_dispatch/middleware/remote_ip.rb#L36C5-L42). Any values from `config.action_dispatch.trusted_proxies` are appended to this list. If you were to set `config.action_dispatch.trusted_proxies` to the current list of Cloudflare IP addresses `request.remote_ip` would work correctly.
|
45
48
|
|
46
49
|
Unfortunately this does not fix `request.ip`. This method comes from the [Rack::Request](https://github.com/rack/rack/blob/main/lib/rack/request.rb) middleware. It has a separate implementation of [trusted proxies](https://github.com/rack/rack/blob/main/lib/rack/request.rb#L48-L56) and [ip filtering](https://github.com/rack/rack/blob/main/lib/rack/request.rb#L58C1-L59C1). The only way to use a different implementation is to set `Rack::Request.ip_filter` which expects a callable value. Providing a new one will override the old one so you'd lose the default values (all of which should be there). Those values aren't exported anywhere so your callable would now have to maintain _that_ list on top of the Cloudflare IPs.
|
@@ -48,33 +51,36 @@ Unfortunately this does not fix `request.ip`. This method comes from the [Rack::
|
|
48
51
|
These issues are why this gem patches both `Rack::Request::Helpers` and `ActionDispatch::RemoteIP` rather than using the built-in configuration methods.
|
49
52
|
|
50
53
|
## Prerequisites
|
54
|
+
|
51
55
|
You must have a [`cache_store`](https://guides.rubyonrails.org/caching_with_rails.html#configuration) configured in your `rails` application.
|
52
56
|
|
53
57
|
## Usage
|
58
|
+
|
54
59
|
You can configure the HTTP `timeout` and `expires_in` cache parameters inside of your `rails` config:
|
60
|
+
|
55
61
|
```ruby
|
56
62
|
config.cloudflare.expires_in = 12.hours # default value
|
57
63
|
config.cloudflare.timeout = 5.seconds # default value
|
58
64
|
```
|
59
65
|
|
60
66
|
## Blocking non-Cloudflare traffic
|
61
|
-
|
67
|
+
|
68
|
+
You can use the `#cloudflare?` method from this gem to block all non-Cloudflare traffic to your application. Here's an example of doing this with [`Rack::Attack`](https://github.com/rack/rack-attack):
|
69
|
+
|
62
70
|
```ruby
|
63
71
|
Rack::Attack.blocklist('CloudFlare WAF bypass') do |req|
|
64
72
|
!req.cloudflare?
|
65
73
|
end
|
66
74
|
```
|
67
|
-
Note that the request may optionally pass through additional trusted proxies, so it will return true for any of these scenarios:
|
68
|
-
|
69
|
-
* `REMOTE_ADDR: CloudFlare`
|
70
|
-
* `REMOTE_ADDR: trusted_proxy`, `X_HTTP_FORWARDED_FOR: CloudFlare`
|
71
|
-
* `REMOTE_ADDR: trusted_proxy`, `X_HTTP_FORWARDED_FOR: trusted_proxy2,CloudFlare,...`
|
72
75
|
|
73
|
-
|
76
|
+
Note that the request may optionally pass through additional trusted proxies, so it will return `true` for any of these scenarios:
|
74
77
|
|
75
|
-
|
78
|
+
- `REMOTE_ADDR: CloudFlare`
|
79
|
+
- `REMOTE_ADDR: trusted_proxy`, `X_HTTP_FORWARDED_FOR: CloudFlare`
|
80
|
+
- `REMOTE_ADDR: trusted_proxy`, `X_HTTP_FORWARDED_FOR: CloudFlare,trusted_proxy2`
|
81
|
+
- `REMOTE_ADDR: trusted_proxy`, `X_HTTP_FORWARDED_FOR: untrusted,CloudFlare`
|
76
82
|
|
77
|
-
|
83
|
+
but it will return `false` if CloudFlare comes to the left of an untrusted IP in `X-Forwarded-For`.
|
78
84
|
|
79
85
|
## Development
|
80
86
|
|
data/cloudflare-rails.gemspec
CHANGED
@@ -27,9 +27,8 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_development_dependency 'rubocop', '~> 1.66.1'
|
28
28
|
spec.add_development_dependency 'rubocop-performance', '~> 1.22.1'
|
29
29
|
spec.add_development_dependency 'rubocop-rails', '~> 2.26.1'
|
30
|
-
spec.add_development_dependency 'rubocop-rspec', '~> 3.0
|
31
|
-
spec.add_development_dependency 'webmock', '~> 3.
|
32
|
-
|
30
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 3.1.0'
|
31
|
+
spec.add_development_dependency 'webmock', '~> 3.24.0'
|
33
32
|
spec.add_dependency 'actionpack', '>= 7.1.0', '< 8.1.0'
|
34
33
|
spec.add_dependency 'activesupport', '>= 7.1.0', '< 8.1.0'
|
35
34
|
spec.add_dependency 'railties', '>= 7.1.0', '< 8.1.0'
|
@@ -20,7 +20,7 @@ module CloudflareRails
|
|
20
20
|
forwarded_for = self.forwarded_for || []
|
21
21
|
|
22
22
|
# Select only the trusted prefix of REMOTE_ADDR + X_HTTP_FORWARDED_FOR
|
23
|
-
trusted_proxies = (remote_addresses + forwarded_for).take_while do |ip|
|
23
|
+
trusted_proxies = (remote_addresses + forwarded_for.reverse).take_while do |ip|
|
24
24
|
trusted_proxy?(ip)
|
25
25
|
end
|
26
26
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudflare-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jonathan schatz
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|
@@ -156,28 +156,28 @@ dependencies:
|
|
156
156
|
requirements:
|
157
157
|
- - "~>"
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version: 3.0
|
159
|
+
version: 3.1.0
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version: 3.0
|
166
|
+
version: 3.1.0
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
168
|
name: webmock
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
171
|
- - "~>"
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 3.
|
173
|
+
version: 3.24.0
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 3.
|
180
|
+
version: 3.24.0
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: actionpack
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|