rack-cloudflare_middleware 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e108186bec2a6dff38a2f6fa5edcfd196aa4e2199333a61d8c9a888edf65c3be
4
+ data.tar.gz: a8e0131c2fd8270784ed1155f114892bc26e3f65bf1eda55a547450bdf272fdb
5
+ SHA512:
6
+ metadata.gz: 5762e62571ea9c5dce83039b0616a3074a0ffa0f165430c4cc5dbc5c70ef0d3d34553965abe3f85c3c8e6222f0247290e1acb8a4538538e30bd1b88e6f5bbe7a
7
+ data.tar.gz: f04fa0b616f69d62f81568dc29c5e0428511a884e774685a6d869dfbef5765c9b0cac577fc42d1f08d747084369a1ff11baba8853cbbc36b71e8fee20e7773b2
@@ -0,0 +1,25 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "github-actions"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "weekly"
12
+ day: "wednesday"
13
+ labels:
14
+ - ":robot: dependabot"
15
+ - ":octocat: github-actions"
16
+ - ":heavy_plus_sign: dependencies"
17
+ - package-ecosystem: "bundler"
18
+ directory: "/"
19
+ schedule:
20
+ interval: "weekly"
21
+ day: "wednesday"
22
+ labels:
23
+ - ":robot: dependabot"
24
+ - ":gem: ruby"
25
+ - ":heavy_plus_sign: dependencies"
@@ -0,0 +1,51 @@
1
+ name: "CI"
2
+ on:
3
+ pull_request:
4
+ push:
5
+ branches: [ main ]
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ timeout-minutes: 30
11
+ permissions:
12
+ contents: read
13
+ checks: write
14
+ env:
15
+ RAILS_ENV: test
16
+ strategy:
17
+ fail-fast: true
18
+ matrix:
19
+ ruby: ["2.7", "3.0", "3.1", "3.2"]
20
+ steps:
21
+ - name: Checkout code
22
+ uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
23
+ - name: Install Ruby and gems
24
+ uses: ruby/setup-ruby@93287a1fa82c6ddbb6d8db978df4b0119cd8879f
25
+ with:
26
+ bundler-cache: true
27
+ ruby-version: ${{ matrix.ruby }}
28
+ - name: Run RSpec Tests
29
+ timeout-minutes: 20
30
+ run: bundle exec rspec -f doc
31
+ lint:
32
+ runs-on: ubuntu-latest
33
+ timeout-minutes: 20
34
+ permissions:
35
+ contents: read
36
+ steps:
37
+ - name: Checkout code
38
+ uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
39
+ - name: Install Ruby and gems
40
+ uses: ruby/setup-ruby@93287a1fa82c6ddbb6d8db978df4b0119cd8879f
41
+ with:
42
+ bundler-cache: true
43
+ ruby-version: "3.1"
44
+ - name: Bundle Audit Check
45
+ run: bundle exec bundle-audit update && bundle exec bundle-audit check
46
+ - name: Setup Python
47
+ uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435
48
+ with:
49
+ python-version: "3.10"
50
+ - name: Run pre-commit
51
+ uses: pre-commit/action@efd3bcfec120bd343786e46318186153b7bc8c68
@@ -0,0 +1,25 @@
1
+ name: Release to RubyGems
2
+ on:
3
+ release:
4
+ types: [published]
5
+ jobs:
6
+ release:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - name: Checkout code
10
+ uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
11
+ - name: Install Ruby and gems
12
+ uses: ruby/setup-ruby@93287a1fa82c6ddbb6d8db978df4b0119cd8879f
13
+ with:
14
+ bundler-cache: true
15
+ ruby-version: "3.2"
16
+ - name: Publish gem
17
+ run: |
18
+ umask 077
19
+ mkdir -p "$HOME/.gem"
20
+ printf -- "---\n:rubygems_api_key: ${RUBYGEMS_API_KEY}\n" > $HOME/.gem/credentials
21
+ gem build *.gemspec
22
+ gem push *.gem
23
+ rm -f "$HOME/.gem/credentials"
24
+ env:
25
+ RUBYGEMS_API_KEY: "${{secrets.RUBYGEMS_PUSH_API_KEY}}"
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ /.bundle
2
+ *.gem
@@ -0,0 +1,17 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v3.2.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ exclude: '^(config/secrets.yml.enc$)|(spec/data/)|(db/.*\.sql$)'
8
+ - id: check-yaml
9
+ exclude: '.rubocop.yml'
10
+ - id: check-added-large-files
11
+ - id: check-byte-order-marker
12
+ exclude: '^spec/data/'
13
+ - id: check-merge-conflict
14
+ - repo: https://github.com/instrumentl/pre-commit-standardrb.git
15
+ rev: '1ae56c7524a2d48cd2b7ca1f74bdb0cdd454477e'
16
+ hooks:
17
+ - id: standardrb
data/.rubocop.yml ADDED
@@ -0,0 +1,10 @@
1
+ require: standard
2
+ inherit_gem:
3
+ standard: config/base.yml
4
+ AllCops:
5
+ TargetRubyVersion: 2.7
6
+ Exclude:
7
+ - 'vendor/bundle/**/*'
8
+ - 'tmp/**/*'
9
+ - 'public/**/*'
10
+ - 'bin/{bundle,rails,rake,spring}'
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+
7
+ gem "faraday", "~> 1.0"
8
+ gem "rake", "~> 13.0"
9
+
10
+ group :development, :test do
11
+ gem "rspec", "~> 3.0"
12
+ gem "rspec-its", "~> 1.3"
13
+ gem "rack-test", "~> 2"
14
+ gem "standard", "~> 1"
15
+ gem "pry"
16
+ gem "webmock", "~> 3.18"
17
+ gem "bundle-audit", "~> 0.1.0"
18
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,127 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rack-cloudflare_middleware (1.0.0)
5
+ faraday (>= 1.0, < 3)
6
+ rack (~> 2)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ addressable (2.8.1)
12
+ public_suffix (>= 2.0.2, < 6.0)
13
+ ast (2.4.2)
14
+ bundle-audit (0.1.0)
15
+ bundler-audit
16
+ bundler-audit (0.9.1)
17
+ bundler (>= 1.2.0, < 3)
18
+ thor (~> 1.0)
19
+ coderay (1.1.3)
20
+ crack (0.4.5)
21
+ rexml
22
+ diff-lcs (1.5.0)
23
+ faraday (1.10.3)
24
+ faraday-em_http (~> 1.0)
25
+ faraday-em_synchrony (~> 1.0)
26
+ faraday-excon (~> 1.1)
27
+ faraday-httpclient (~> 1.0)
28
+ faraday-multipart (~> 1.0)
29
+ faraday-net_http (~> 1.0)
30
+ faraday-net_http_persistent (~> 1.0)
31
+ faraday-patron (~> 1.0)
32
+ faraday-rack (~> 1.0)
33
+ faraday-retry (~> 1.0)
34
+ ruby2_keywords (>= 0.0.4)
35
+ faraday-em_http (1.0.0)
36
+ faraday-em_synchrony (1.0.0)
37
+ faraday-excon (1.1.0)
38
+ faraday-httpclient (1.0.1)
39
+ faraday-multipart (1.0.4)
40
+ multipart-post (~> 2)
41
+ faraday-net_http (1.0.1)
42
+ faraday-net_http_persistent (1.2.0)
43
+ faraday-patron (1.0.0)
44
+ faraday-rack (1.0.0)
45
+ faraday-retry (1.0.3)
46
+ hashdiff (1.0.1)
47
+ json (2.6.3)
48
+ language_server-protocol (3.17.0.3)
49
+ method_source (1.0.0)
50
+ multipart-post (2.3.0)
51
+ parallel (1.22.1)
52
+ parser (3.2.1.1)
53
+ ast (~> 2.4.1)
54
+ pry (0.14.2)
55
+ coderay (~> 1.1)
56
+ method_source (~> 1.0)
57
+ public_suffix (5.0.1)
58
+ rack (2.2.6.4)
59
+ rack-test (2.1.0)
60
+ rack (>= 1.3)
61
+ rainbow (3.1.1)
62
+ rake (13.0.6)
63
+ regexp_parser (2.7.0)
64
+ rexml (3.2.5)
65
+ rspec (3.12.0)
66
+ rspec-core (~> 3.12.0)
67
+ rspec-expectations (~> 3.12.0)
68
+ rspec-mocks (~> 3.12.0)
69
+ rspec-core (3.12.1)
70
+ rspec-support (~> 3.12.0)
71
+ rspec-expectations (3.12.2)
72
+ diff-lcs (>= 1.2.0, < 2.0)
73
+ rspec-support (~> 3.12.0)
74
+ rspec-its (1.3.0)
75
+ rspec-core (>= 3.0.0)
76
+ rspec-expectations (>= 3.0.0)
77
+ rspec-mocks (3.12.4)
78
+ diff-lcs (>= 1.2.0, < 2.0)
79
+ rspec-support (~> 3.12.0)
80
+ rspec-support (3.12.0)
81
+ rubocop (1.48.1)
82
+ json (~> 2.3)
83
+ parallel (~> 1.10)
84
+ parser (>= 3.2.0.0)
85
+ rainbow (>= 2.2.2, < 4.0)
86
+ regexp_parser (>= 1.8, < 3.0)
87
+ rexml (>= 3.2.5, < 4.0)
88
+ rubocop-ast (>= 1.26.0, < 2.0)
89
+ ruby-progressbar (~> 1.7)
90
+ unicode-display_width (>= 2.4.0, < 3.0)
91
+ rubocop-ast (1.28.0)
92
+ parser (>= 3.2.1.0)
93
+ rubocop-performance (1.16.0)
94
+ rubocop (>= 1.7.0, < 2.0)
95
+ rubocop-ast (>= 0.4.0)
96
+ ruby-progressbar (1.13.0)
97
+ ruby2_keywords (0.0.5)
98
+ standard (1.25.3)
99
+ language_server-protocol (~> 3.17.0.2)
100
+ rubocop (~> 1.48.1)
101
+ rubocop-performance (~> 1.16.0)
102
+ thor (1.2.1)
103
+ unicode-display_width (2.4.2)
104
+ webmock (3.18.1)
105
+ addressable (>= 2.8.0)
106
+ crack (>= 0.3.2)
107
+ hashdiff (>= 0.4.0, < 2.0.0)
108
+
109
+ PLATFORMS
110
+ arm64-darwin-22
111
+ x86_64-linux
112
+
113
+ DEPENDENCIES
114
+ bundle-audit (~> 0.1.0)
115
+ bundler (~> 2)
116
+ faraday (~> 1.0)
117
+ pry
118
+ rack-cloudflare_middleware!
119
+ rack-test (~> 2)
120
+ rake (~> 13.0)
121
+ rspec (~> 3.0)
122
+ rspec-its (~> 1.3)
123
+ standard (~> 1)
124
+ webmock (~> 3.18)
125
+
126
+ BUNDLED WITH
127
+ 2.4.7
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2023 Instrumentl, Inc.
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13
+ PERFORMANCE OF THIS SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ This is a small Rack middleware for use with the [Cloudflare](https://www.cloudflare.com/) CDN.
2
+
3
+ We include two middlewares:
4
+
5
+ * `Rack::CloudflareMiddleware::RewriteRemoteAddr` swaps in `CF-Connecting-IP` for `REMOTE_ADDR` if and only if the "real" remote address is a trusted Cloudflare source IP address.
6
+ * `Rack::CloudflareMiddleware::DenyOthers` returns a 401 for all requests where `REMOTE_ADDR` is not Cloudflare
7
+
8
+ If you're using Rails, you may want to use [cloudflare-rails](https://github.com/modosc/cloudflare-rails) instead.
9
+
10
+ This library uses Faraday to dynamically update the list of trusted remote IPs every few hours, and includes a checked-in snapshot which will be used if the dynamic updater fails.
11
+
12
+ This library is licensed under the ISC license, a copy of which can be found at [LICENSE.txt](LICENSE.txt). "Cloudflare" is a registered trademark of Cloudflare, Inc and is used as per the [Cloudflare Trademark Guidelines](https://www.cloudflare.com/trademark/)
13
+
14
+ ### Usage
15
+
16
+ Add this library to your Gemfile (or otherwise include it with your application), and add it as a middleware in your `config.ru`; for example, if you're using [Sinatra](), this might look like:
17
+
18
+ ```ruby
19
+ require "rack/cloudflare_middleware"
20
+ require "sinatra"
21
+ require "./app"
22
+
23
+ use Rack::CloudflareMiddleware::DenyOthers, allow_private: true
24
+ use Rack::CloudflareMiddleware::RewriteRemoteAddr
25
+
26
+ run Sinatra::Application
27
+ ```
28
+
29
+ The `allow_private` kwarg to `DenyOthers` controls whether or not private and loopback addresses are allowed through. Whether or not you should set this depends on the exact specifics of your deployment environment; often it should be set in development, but not in production.
data/data/ips-v4 ADDED
@@ -0,0 +1,15 @@
1
+ 103.21.244.0/22
2
+ 103.22.200.0/22
3
+ 103.31.4.0/22
4
+ 104.16.0.0/13
5
+ 104.24.0.0/14
6
+ 108.162.192.0/18
7
+ 131.0.72.0/22
8
+ 141.101.64.0/18
9
+ 162.158.0.0/15
10
+ 172.64.0.0/13
11
+ 173.245.48.0/20
12
+ 188.114.96.0/20
13
+ 190.93.240.0/20
14
+ 197.234.240.0/22
15
+ 198.41.128.0/17
data/data/ips-v6 ADDED
@@ -0,0 +1,7 @@
1
+ 2400:cb00::/32
2
+ 2405:8100::/32
3
+ 2405:b500::/32
4
+ 2606:4700::/32
5
+ 2803:f800::/32
6
+ 2a06:98c0::/29
7
+ 2c0f:f248::/32
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ module CloudflareMiddleware
5
+ class DenyOthers
6
+ def initialize(app, allow_private: false)
7
+ @allow_private = allow_private
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ TrustedIps.instance.check_update
13
+ remote_addr = IPAddr.new env["REMOTE_ADDR"]
14
+ if (@allow_private && (remote_addr.private? || remote_addr.loopback?)) || TrustedIps.instance.include?(remote_addr)
15
+ @app.call(env)
16
+ else
17
+ ["403", {"Content-Type" => "text/plain"}, ["Forbidden by policy statement"]]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ module CloudflareMiddleware
5
+ class RewriteRemoteAddr
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ TrustedIps.instance.check_update
12
+ if TrustedIps.instance.include? env["REMOTE_ADDR"]
13
+ unless env["HTTP_CF_CONNECTING_IP"].nil?
14
+ env["HTTP_CF_ORIGINAL_REMOTE_ADDR"] = env["REMOTE_ADDR"]
15
+ env["REMOTE_ADDR"] = env["HTTP_CF_CONNECTING_IP"]
16
+ end
17
+ end
18
+
19
+ @app.call(env)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ipaddr"
4
+ require "singleton"
5
+
6
+ require "faraday"
7
+
8
+ module Rack
9
+ module CloudflareMiddleware
10
+ class TrustedIps
11
+ TIMEOUT = 7.0
12
+ OPEN_TIMEOUT = 4.0
13
+
14
+ UPDATE_THRESHOLD = 21600
15
+
16
+ attr_reader :ranges
17
+ attr_reader :mtimes
18
+
19
+ include Singleton
20
+
21
+ def initialize
22
+ reset!
23
+ end
24
+
25
+ def reset!
26
+ @ranges = {4 => Set.new, 6 => Set.new}
27
+ @mtimes = {4 => Time.new(1970, 1, 1), 6 => Time.new(1970, 1, 1)}
28
+ load_from_files
29
+ end
30
+
31
+ def include?(ip)
32
+ unless ip.is_a? IPAddr
33
+ ip = IPAddr.new(ip)
34
+ end
35
+ if ip.ipv4?
36
+ @ranges[4].any? { _1.include? ip }
37
+ else
38
+ @ranges[6].any? { _1.include? ip }
39
+ end
40
+ end
41
+
42
+ def update!
43
+ read_network "https://www.cloudflare.com/ips-v4", 4
44
+ read_network "https://www.cloudflare.com/ips-v6", 6
45
+ end
46
+
47
+ def check_update
48
+ if [4, 6].any? { (Time.now - @mtimes[_1]) > UPDATE_THRESHOLD }
49
+ update!
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def load_from_files
56
+ read_file "#{__dir__}/../../../data/ips-v4", 4
57
+ read_file "#{__dir__}/../../../data/ips-v6", 6
58
+ end
59
+
60
+ def process_body(body)
61
+ body.lines.map(&:strip).filter { !_1.empty? }.map(&IPAddr.method(:new)).to_set
62
+ end
63
+
64
+ def read_file(path, version)
65
+ ::File.open(path) do |f|
66
+ addresses = process_body(f.read)
67
+ @ranges[version] = addresses
68
+ @mtimes[version] = f.mtime
69
+ end
70
+ end
71
+
72
+ def read_network(url, version)
73
+ start_request = Time.now
74
+ response = faraday_connection.get(url)
75
+ @ranges[version] = process_body(response.body)
76
+ @mtimes[version] = start_request
77
+ rescue Faraday::Error => e
78
+ warn "Unable to fetch Cloudflare remote IPs: #{e}"
79
+ end
80
+
81
+ def faraday_connection
82
+ @faraday_connection ||= Faraday.new do |builder|
83
+ builder.options.open_timeout = OPEN_TIMEOUT
84
+ builder.options.timeout = TIMEOUT
85
+ builder.response :raise_error
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ module CloudflareMiddleware
5
+ VERSION = "1.0.0"
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cloudflare_middleware/version"
4
+ require_relative "cloudflare_middleware/trusted_ips"
5
+ require_relative "cloudflare_middleware/rewrite_remote_addr"
6
+ require_relative "cloudflare_middleware/deny_others"
7
+
8
+ module Rack
9
+ module CloudflareMiddleware
10
+ attr_accessor :logger
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "rack/cloudflare_middleware/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "rack-cloudflare_middleware"
9
+ spec.version = Rack::CloudflareMiddleware::VERSION
10
+ spec.authors = ["James Brown"]
11
+ spec.email = ["james@instrumentl.com"]
12
+ spec.license = "ISC"
13
+
14
+ spec.summary = "Rack middleware for handling Cloudflare remote IP headers"
15
+ spec.homepage = "https://github.com/instrumentl/rack-cloudflare_middleware"
16
+
17
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
+ `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ end
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "faraday", ">= 1.0", "< 3"
25
+ spec.add_dependency "rack", "~> 2"
26
+
27
+ spec.add_development_dependency "bundler", "~> 2"
28
+ spec.add_development_dependency "rake", "~> 13.0"
29
+ spec.add_development_dependency "rspec", "~> 3.0"
30
+ spec.add_development_dependency "standard", "~> 1"
31
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-cloudflare_middleware
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - James Brown
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-03-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rack
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2'
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '13.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '13.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: standard
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '1'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '1'
103
+ description:
104
+ email:
105
+ - james@instrumentl.com
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - ".github/dependabot.yml"
111
+ - ".github/workflows/ci.yml"
112
+ - ".github/workflows/release.yml"
113
+ - ".gitignore"
114
+ - ".pre-commit-config.yaml"
115
+ - ".rubocop.yml"
116
+ - Gemfile
117
+ - Gemfile.lock
118
+ - LICENSE.txt
119
+ - README.md
120
+ - data/ips-v4
121
+ - data/ips-v6
122
+ - lib/rack/cloudflare_middleware.rb
123
+ - lib/rack/cloudflare_middleware/deny_others.rb
124
+ - lib/rack/cloudflare_middleware/rewrite_remote_addr.rb
125
+ - lib/rack/cloudflare_middleware/trusted_ips.rb
126
+ - lib/rack/cloudflare_middleware/version.rb
127
+ - rack-cloudflare_middleware.gemspec
128
+ homepage: https://github.com/instrumentl/rack-cloudflare_middleware
129
+ licenses:
130
+ - ISC
131
+ metadata: {}
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubygems_version: 3.4.1
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Rack middleware for handling Cloudflare remote IP headers
151
+ test_files: []