Skip to content

Instantly share code, notes, and snippets.

@mattheworiordan
Last active October 24, 2017 06:41
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattheworiordan/9024372 to your computer and use it in GitHub Desktop.
Save mattheworiordan/9024372 to your computer and use it in GitHub Desktop.
Cloudflare Middleware for Rails
# insert within your Application
config.middleware.insert_before(0, Rack::CloudFlareFixup)
# CloudFlare masks the true IP
# This middleware ensures the Rails stack obtains the correct IP when using request.remote_ip
# See https://support.cloudflare.com/hc/en-us/articles/200170786
module Rack
class CloudFlareFixup
def initialize(app)
@app = app
end
def call(env)
if env['HTTP_CF_CONNECTING_IP']
env['HTTP_X_FORWARDED_FOR'] = env['HTTP_CF_CONNECTING_IP']
env['REMOTE_ADDR'] = env['HTTP_CF_CONNECTING_IP']
end
@app.call(env)
end
end
end
@lmmendes
Copy link

lmmendes commented May 8, 2014

Your middleware should be placed right before ActionDispatch::RemoteIp middleware and not in at the top of the rack stack.

use config.middleware.insert_before(ActionDispatch::RemoteIp, Rack::CloudFlareFixup)

That way use ActionDispatch::ShowExceptions and ActionDispatch::DebugExceptions can catch the app route exceptions before before the request is handled by your middleware.

You can read more about ActionDispatch::RemoteIp at rails api:

http://api.rubyonrails.org/classes/ActionDispatch/RemoteIp.html

@Arcolye
Copy link

Arcolye commented Mar 10, 2015

@metavida
Copy link

metavida commented Apr 2, 2015

I've been working to solve this same problem. I wrapped my rack middleware solution into the remote_ip_proxy_scrubber gem.

My gem's weakness is that it relies on your app maintaining an up-to-date list of current CloudFlare IPs.

My gem's benefits are that it prevents IP spoofing even if part of your app's traffic is not passing through CloudFlare (with your middleware, a request that bypasses CloudFlare could spoof its IP by setting the CF_CONNECTING_IP header). My gem also includes a patched version of Rails::Rack::Logger so that your Rails logs show the client's remote_ip address.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment