rack-cloudflare 1.0.1 → 1.0.2
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 +4 -4
- data/README.md +4 -4
- data/data/ips_private.txt +3 -0
- data/lib/rack/cloudflare/headers.rb +21 -16
- data/lib/rack/cloudflare/ips.rb +15 -8
- data/lib/rack/cloudflare/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 011cc369434439d481e71bd8010799cd88e87d982210c67981ac7105760aeff5
|
4
|
+
data.tar.gz: fe54456b3085e508bffffb3cab92a198bd0daba4ee91d9fd4166645bb6b2c8c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63b836789620e7ea49f7f278077918177f51df466e6a7ebddf4eb9e2d8f11c9fc2f03cc923cdf2ddbb7d291d77e7a1a10d7885699b1fe450986a9f1349ca9c4f
|
7
|
+
data.tar.gz: ef8a50c433d5d64fe98ab645a7d3163615c5986ca00f17cb8a54517d3c5dffe6f0415c5fc8b4a6dbeb13b1374f0a8e601a975ae5442335f3b66c590924156bd8
|
data/README.md
CHANGED
@@ -27,11 +27,11 @@ You can block access to non-Cloudflare networks using `Rack::Cloudflare::Middlew
|
|
27
27
|
```ruby
|
28
28
|
require 'rack/cloudflare'
|
29
29
|
|
30
|
-
# In config.ru
|
30
|
+
# In config.ru (recommended for Rails as well to preempt application loading)
|
31
31
|
use Rack::Cloudflare::Middleware::AccessControl
|
32
32
|
|
33
|
-
# In Rails config/application.rb
|
34
|
-
config.middleware.
|
33
|
+
# In Rails middleware: config/application.rb
|
34
|
+
config.middleware.unshift Rack::Cloudflare::Middleware::AccessControl
|
35
35
|
|
36
36
|
# Configure custom blocked message (defaults to "Forbidden")
|
37
37
|
Rack::Cloudflare::Middleware::AccessControl.blocked_message = "You don't belong here..."
|
@@ -144,7 +144,7 @@ The list can be updated to Cloudflare's latest published IP lists in-memory:
|
|
144
144
|
|
145
145
|
```ruby
|
146
146
|
# Fetches Rack::Cloudflare::IPs::V4_URL and Rack::Cloudflare::IPs::V6_URL
|
147
|
-
Rack::Cloudflare::IPs.
|
147
|
+
Rack::Cloudflare::IPs.update!
|
148
148
|
|
149
149
|
# Updates cached list in-memory
|
150
150
|
Rack::Cloudflare::IPs.list
|
@@ -32,10 +32,6 @@ module Rack
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
self.backup = true
|
36
|
-
self.original_remote_addr = 'ORIGINAL_REMOTE_ADDR'
|
37
|
-
self.original_forwarded_for = 'ORIGINAL_FORWARDED_FOR'
|
38
|
-
|
39
35
|
def initialize(headers)
|
40
36
|
@headers = headers
|
41
37
|
end
|
@@ -68,17 +64,15 @@ module Rack
|
|
68
64
|
|
69
65
|
# "Cf-Visitor: { \"scheme\":\"https\"}"
|
70
66
|
def visitor
|
71
|
-
|
72
|
-
::JSON.parse @headers[HTTP_CF_VISITOR]
|
67
|
+
@visitor ||= ::JSON.parse @headers[HTTP_CF_VISITOR] if has?(HTTP_CF_VISITOR)
|
73
68
|
end
|
74
69
|
|
75
70
|
def remote_addr
|
76
71
|
@remote_addr ||= IPs.parse(@headers[REMOTE_ADDR]).first
|
77
72
|
end
|
78
73
|
|
79
|
-
|
80
|
-
|
81
|
-
IPs.list.any? { |range| range.include? remote_addr }
|
74
|
+
def cloudflare_ip
|
75
|
+
@cloudflare_ip ||= IPs.private?(remote_addr) ? forwarded_for.last : remote_addr
|
82
76
|
end
|
83
77
|
|
84
78
|
def backup_headers
|
@@ -90,6 +84,12 @@ module Rack
|
|
90
84
|
end
|
91
85
|
end
|
92
86
|
|
87
|
+
# Headers that relate to Cloudflare
|
88
|
+
# See: https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
|
89
|
+
def target_headers
|
90
|
+
@headers.select { |k, _| ALL.include? k }
|
91
|
+
end
|
92
|
+
|
93
93
|
def rewritten_headers
|
94
94
|
# Only rewrites headers if it's a Cloudflare request
|
95
95
|
return {} unless trusted?
|
@@ -105,16 +105,10 @@ module Rack
|
|
105
105
|
# Cloudflare will already have modified the header if
|
106
106
|
# it was present in the original request.
|
107
107
|
# See: https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
|
108
|
-
headers[HTTP_X_FORWARDED_FOR] = "#{connecting_ip}, #{
|
108
|
+
headers[HTTP_X_FORWARDED_FOR] = "#{connecting_ip}, #{cloudflare_ip}" if forwarded_for.none?
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
|
-
# Headers that relate to Cloudflare
|
113
|
-
# See: https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-
|
114
|
-
def target_headers
|
115
|
-
@headers.select { |k, _| ALL.include? k }
|
116
|
-
end
|
117
|
-
|
118
112
|
def rewritten_target_headers
|
119
113
|
target_headers.merge(rewritten_headers)
|
120
114
|
end
|
@@ -123,9 +117,20 @@ module Rack
|
|
123
117
|
@headers.merge(rewritten_headers)
|
124
118
|
end
|
125
119
|
|
120
|
+
# Indicates if the headers passed through Cloudflare
|
121
|
+
def trusted?
|
122
|
+
@trusted ||= IPs.list.any? { |range| range.include? cloudflare_ip }
|
123
|
+
end
|
124
|
+
|
126
125
|
def has?(header)
|
127
126
|
@headers.key?(header)
|
128
127
|
end
|
128
|
+
|
129
|
+
### Configure
|
130
|
+
|
131
|
+
self.backup = true
|
132
|
+
self.original_remote_addr = 'ORIGINAL_REMOTE_ADDR'
|
133
|
+
self.original_forwarded_for = 'ORIGINAL_FORWARDED_FOR'
|
129
134
|
end
|
130
135
|
end
|
131
136
|
end
|
data/lib/rack/cloudflare/ips.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'ipaddr'
|
4
|
-
require '
|
4
|
+
require 'open-uri'
|
5
5
|
|
6
6
|
module Rack
|
7
7
|
class Cloudflare
|
@@ -14,13 +14,20 @@ module Rack
|
|
14
14
|
# List of IPs to reference
|
15
15
|
attr_accessor :list
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
def private?(ip)
|
18
|
+
PRIVATE.any? { |range| range.include? ip }
|
19
|
+
end
|
20
|
+
|
21
|
+
# Update list of IPs in-memory in case local copy is outdated
|
22
|
+
def update!
|
19
23
|
self.list = fetch(V4_URL) + fetch(V6_URL)
|
20
24
|
end
|
21
25
|
|
22
26
|
def fetch(url)
|
23
|
-
parse
|
27
|
+
parse URI(url).read
|
28
|
+
rescue OpenURI::HTTPError => ex
|
29
|
+
Cloudflare.error "[#{name}] #{ex.class.name} fetching #{url.inspect}: #{ex.message}"
|
30
|
+
[]
|
24
31
|
end
|
25
32
|
|
26
33
|
def read(filename)
|
@@ -29,13 +36,13 @@ module Rack
|
|
29
36
|
|
30
37
|
def parse(string)
|
31
38
|
return [] if string.to_s.strip.empty?
|
32
|
-
string.split(/[,\s]+/).map { |ip| ::IPAddr.new(ip.strip) }
|
39
|
+
string.strip.split(/[,\s]+/).map { |ip| ::IPAddr.new(ip.strip) }
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
36
|
-
V4
|
37
|
-
V6
|
38
|
-
|
43
|
+
V4 = read("#{__dir__}/../../../data/ips_v4.txt")
|
44
|
+
V6 = read("#{__dir__}/../../../data/ips_v6.txt")
|
45
|
+
PRIVATE = parse('10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16')
|
39
46
|
DEFAULTS = V4 + V6
|
40
47
|
|
41
48
|
### Configure
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-cloudflare
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Van Horn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-09-
|
11
|
+
date: 2018-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -96,6 +96,7 @@ files:
|
|
96
96
|
- Rakefile
|
97
97
|
- bin/console
|
98
98
|
- bin/setup
|
99
|
+
- data/ips_private.txt
|
99
100
|
- data/ips_v4.txt
|
100
101
|
- data/ips_v6.txt
|
101
102
|
- lib/rack/cloudflare.rb
|