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:
“by 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
.
“by 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
you can easily add a “safelist” rule.
“by 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
.
“by 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.
“by
Toggle header backups (default: true)
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.
“by 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.
“by
Your headers are in a Hash
format
e.g.
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
Rewrite Headers
We can easily rewrite REMOTE_ADDR
and add HTTP_X_FORWARDED_FOR
based on verifying the request comes from a Cloudflare network.
“by
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 that are important to keep up-to-date.
A copy of the IPs are kept in /data. The list is converted to a IPAddr
list and is accessible as:
“by
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:
“by
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.