-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit d8a159a
Showing
21 changed files
with
1,033 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/.bundle/ | ||
/.yardoc | ||
/_yardoc/ | ||
/coverage/ | ||
/doc/ | ||
/pkg/ | ||
/spec/reports/ | ||
/tmp/ | ||
|
||
# rspec failure tracking | ||
.rspec_status | ||
|
||
Gemfile.lock | ||
*.gem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--format documentation | ||
--color | ||
--require spec_helper |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
AllCops: | ||
TargetRubyVersion: 2.5.1 | ||
# Rails: true | ||
# Include: | ||
# - '**/Rakefile' | ||
# - '**/config.ru' | ||
Exclude: | ||
- 'doc/**/*' | ||
- 'tmp/**/*' | ||
- 'bin/**/*' | ||
- 'db/**/*' | ||
- 'test/**/*' | ||
- 'config/**/*' | ||
- 'script/**/*' | ||
- 'vendor/**/*' | ||
- 'spec/**/*' | ||
- !ruby/regexp /old_and_unused\.rb$/ | ||
|
||
# Style/WhileUntilModifier: | ||
# MaxLineLength: 160 | ||
|
||
# Style/IfUnlessModifier: | ||
# MaxLineLength: 160 | ||
|
||
Metrics/LineLength: | ||
Max: 160 | ||
|
||
Metrics/AbcSize: | ||
Max: 120 | ||
|
||
Metrics/MethodLength: | ||
CountComments: false # count full line comments? | ||
Max: 120 | ||
|
||
NumericPredicate: | ||
EnforcedStyle: comparison | ||
|
||
Style/Documentation: | ||
Enabled: false | ||
|
||
Metrics/ModuleLength: | ||
Exclude: | ||
- 'lib/rack/cloudflare/countries.rb' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
sudo: false | ||
language: ruby | ||
rvm: | ||
- 2.5.1 | ||
before_install: gem install bundler -v 1.16.2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# frozen_string_literal: true | ||
|
||
source 'https://rubygems.org' | ||
|
||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } | ||
|
||
# Specify your gem's dependencies in rack-cloudflare.gemspec | ||
gemspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
# Rack::Cloudflare | ||
|
||
Deal with Cloudflare features in your Ruby app using Rack middleware. Also provides a Ruby toolkit to deal with Cloudflare in other contexts if you'd like. | ||
|
||
## Installation | ||
|
||
Add this line to your application's Gemfile: | ||
|
||
```ruby | ||
gem 'rack-cloudflare' | ||
``` | ||
|
||
And then execute: | ||
|
||
$ bundle | ||
|
||
Or install it yourself as: | ||
|
||
$ gem install rack-cloudflare | ||
|
||
## Usage | ||
|
||
### Whitelist Cloudflare IP addresses | ||
|
||
You can block access to non-Cloudflare networks using `Rack::Cloudflare::Middleware::AccessControl`. | ||
|
||
require 'rack/cloudflare' | ||
|
||
# In config.ru | ||
use Rack::Cloudflare::Middleware::AccessControl | ||
|
||
# In Rails config/application.rb | ||
config.middleware.use Rack::Cloudflare::Middleware::AccessControl | ||
|
||
# Configure custom blocked message (defaults to "Forbidden") | ||
Rack::Cloudflare::Middleware::AccessControl.blocked_message = "You don't belong here..." | ||
|
||
# Fully customize the Rack response (such as making it a redirect) | ||
Rack::Cloudflare::Middleware::AccessControl.blocked_response = lambda do |_env| | ||
[301, { 'Location' => 'https://somewhere.else.xyz' }, ["Redirecting...\n"]] | ||
end | ||
|
||
Alternatively, using [`Rack::Attack`](https://github.com/kickstarter/rack-attack) you can easily add a "safelist" rule. | ||
|
||
Rack::Attack.safelist('Only allow requests through the Cloudflare network') do |request| | ||
Rack::Cloudflare::Headers.trusted?(request.env) | ||
end | ||
|
||
Utilizing the `trusted?` helper method, you can implement a similar check using other middleware. | ||
|
||
See _Toolkits: Detect Cloudflare Requests_ for alternative uses. | ||
|
||
### Rewrite Cloudflare Remote/Client IP address | ||
|
||
You can set `REMOTE_ADDR` to the correct remote IP using `Rack::Cloudflare::Middleware::RewriteHeaders`. | ||
|
||
require 'rack/cloudflare' | ||
|
||
# In config.ru | ||
use Rack::Cloudflare::Middleware::RewriteHeaders | ||
|
||
# In Rails config/application.rb | ||
config.middleware.use Rack::Cloudflare::Middleware::RewriteHeaders | ||
|
||
You can customize whether rewritten headers should be backed up and what names to use. | ||
|
||
# Toggle header backups | ||
Rack::Cloudflare::Headers.backup = false | ||
|
||
# Rename backed up headers (defaults: "ORIGINAL_REMOTE_ADDR", "ORIGINAL_FORWARDED_FOR") | ||
Rack::Cloudflare::Headers.original_remote_addr = 'BACKUP_REMOTE_ADDR' | ||
Rack::Cloudflare::Headers.original_forwarded_for = 'BACKUP_FORWARDED_FOR' | ||
|
||
See _Toolkits: Rewrite Headers_ for alternative uses. | ||
|
||
### Logging | ||
|
||
You can enable logging to see what requests are blocked or headers are rewritten. | ||
|
||
Rack::Cloudflare.logger = Logger.new(STDOUT) | ||
|
||
Log levels used are INFO, DEBUG and WARN. | ||
|
||
## Toolkits | ||
|
||
### Detect Cloudflare Requests | ||
|
||
You can very easily check your HTTP headers to see if the request came from a Cloudflare network. | ||
|
||
# Your headers are in a `Hash` format | ||
# e.g. { 'REMOTE_ADDR' => '0.0.0.0', ... } | ||
# Verifies the remote address | ||
Rack::Cloudflare::Headers.trusted?(headers) | ||
|
||
Note that we can only trust the `REMOTE_ADDR` header to verify a request came from Cloudflare. | ||
The `HTTP_X_FORWARDED_FOR` header can be modified and therefore not trusted. | ||
|
||
Make sure your web server does not modify `REMOTE_ADDR` because it could cause security holes. | ||
Read this article, for example: [Anatomy of an Attack: How I Hacked StackOverflow](https://blog.ircmaxell.com/2012/11/anatomy-of-attack-how-i-hacked.html) | ||
|
||
### Rewrite Headers | ||
|
||
We can easily rewrite `REMOTE_ADDR` and add `HTTP_X_FORWARDED_FOR` based on verifying the request comes from a Cloudflare network. | ||
|
||
# Get a list of headers relevant to Cloudflare (unmodified) | ||
headers = Rack::Cloudflare::Headers.new(headers).target_headers | ||
|
||
# Get a list of headers that will be rewritten (modified) | ||
headers = Rack::Cloudflare::Headers.new(headers).rewritten_headers | ||
|
||
# Get a list of headers relevant to Cloudflare with rewritten values | ||
headers = Rack::Cloudflare::Headers.new(headers).rewritten_target_headers | ||
|
||
# Update original headers with rewritten ones | ||
headers = Rack::Cloudflare::Headers.new(headers).rewrite | ||
|
||
### Up-to-date Cloudflare IP addresses | ||
|
||
Cloudflare provides a [list of IP addresses](https://www.cloudflare.com/ips/) that are important to keep up-to-date. | ||
|
||
A copy of the IPs are kept in [/data](./data/). The list is converted to a `IPAddr` list and is accessible as: | ||
|
||
# Configurable list of IPs | ||
# Defaults to Rack::Cloudflare::IPs::DEFAULTS | ||
Rack::Cloudflare::IPs.list | ||
|
||
The list can be updated to Cloudflare's latest published IP lists in-memory: | ||
|
||
# Fetches Rack::Cloudflare::IPs::V4_URL and Rack::Cloudflare::IPs::V6_URL | ||
Rack::Cloudflare::IPs.refresh! | ||
|
||
# Updates cached list in-memory | ||
Rack::Cloudflare::IPs.list | ||
|
||
## Credits | ||
|
||
Inspired by: | ||
|
||
* https://github.com/tatey/rack-cloudflare | ||
* https://github.com/rikas/cloudflare_localizable | ||
|
||
## Contributing | ||
|
||
Bug reports and pull requests are welcome on GitHub at https://github.com/joelvh/rack-cloudflare. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'bundler/gem_tasks' | ||
require 'rspec/core/rake_task' | ||
require 'rubocop/rake_task' | ||
require 'rubycritic/rake_task' | ||
|
||
RuboCop::RakeTask.new do |task| | ||
task.requires << 'rubocop-rspec' | ||
end | ||
|
||
RubyCritic::RakeTask.new do |task| | ||
# # Name of RubyCritic task. Defaults to :rubycritic. | ||
# task.name = 'something_special' | ||
|
||
# # Glob pattern to match source files. Defaults to FileList['.']. | ||
task.paths = FileList['apps/**/*.rb', 'lib/**/*.rb'] | ||
|
||
# # You can pass all the options here in that are shown by "rubycritic -h" except for | ||
# # "-p / --path" since that is set separately. Defaults to ''. | ||
# task.options = '--mode-ci --format json' | ||
# # task.options = '--no-browser' | ||
|
||
# # Defaults to false | ||
task.verbose = true | ||
end | ||
|
||
RSpec::Core::RakeTask.new(:spec) | ||
|
||
# task default: %w[rubocop:auto_correct rubycritic spec] | ||
task default: %w[rubocop:auto_correct spec] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/usr/bin/env ruby | ||
|
||
require 'bundler/setup' | ||
require 'rack/cloudflare' | ||
|
||
# You can add fixtures and/or initialization code here to make experimenting | ||
# with your gem easier. You can also use a different console, if you like. | ||
|
||
# (If you use this, don't forget to add pry to your Gemfile!) | ||
# require "pry" | ||
# Pry.start | ||
|
||
require 'irb' | ||
IRB.start(__FILE__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/usr/bin/env bash | ||
set -euo pipefail | ||
IFS=$'\n\t' | ||
set -vx | ||
|
||
bundle install | ||
|
||
# Do any other automated setup that you need to do here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
103.21.244.0/22 | ||
103.22.200.0/22 | ||
103.31.4.0/22 | ||
104.16.0.0/12 | ||
108.162.192.0/18 | ||
131.0.72.0/22 | ||
141.101.64.0/18 | ||
162.158.0.0/15 | ||
172.64.0.0/13 | ||
173.245.48.0/20 | ||
188.114.96.0/20 | ||
190.93.240.0/20 | ||
197.234.240.0/22 | ||
198.41.128.0/17 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
2400:cb00::/32 | ||
2405:b500::/32 | ||
2606:4700::/32 | ||
2803:f800::/32 | ||
2c0f:f248::/32 | ||
2a06:98c0::/29 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative 'cloudflare/version' | ||
require_relative 'cloudflare/countries' | ||
require_relative 'cloudflare/ips' | ||
require_relative 'cloudflare/headers' | ||
|
||
require_relative 'cloudflare/middleware/access_control' | ||
require_relative 'cloudflare/middleware/rewrite_headers' | ||
|
||
module Rack | ||
class Cloudflare | ||
class << self | ||
attr_accessor :logger | ||
|
||
%i[info debug warn error].each do |m| | ||
define_method(m) { |*args| logger&.__send__(m, *args) } | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.