rack-cloudflare 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|