-
-
Save mudge/e5c72d701d7fcbda67608deb800193cb to your computer and use it in GitHub Desktop.
Rails.application.configure do | |
# Add Cloudflare's IPs to the trusted proxy list so they are ignored when | |
# determining the true client IP. | |
# | |
# See https://www.cloudflare.com/ips-v4/ and https://www.cloudflare.com/ips-v6/ | |
config.action_dispatch.trusted_proxies = ActionDispatch::RemoteIp::TRUSTED_PROXIES + %w[ | |
173.245.48.0/20 | |
103.21.244.0/22 | |
103.22.200.0/22 | |
103.31.4.0/22 | |
141.101.64.0/18 | |
108.162.192.0/18 | |
190.93.240.0/20 | |
188.114.96.0/20 | |
197.234.240.0/22 | |
198.41.128.0/17 | |
162.158.0.0/15 | |
104.16.0.0/13 | |
104.24.0.0/14 | |
172.64.0.0/13 | |
131.0.72.0/22 | |
2400:cb00::/32 | |
2606:4700::/32 | |
2803:f800::/32 | |
2405:b500::/32 | |
2405:8100::/32 | |
2a06:98c0::/29 | |
2c0f:f248::/32 | |
].map { |proxy| IPAddr.new(proxy) } | |
end |
Rack::Attack.throttle("req/ip", limit: 300, period: 5.minutes) do |req| | |
req.get_header("action_dispatch.remote_ip") unless req.path.start_with?("/assets") | |
end |
In practice, if you’re running on Heroku, your app will be restarted daily so that gives you some upper limit of how long your IPs will be potentially outdated if Cloudflare does make a change (I have no sense how often they update their IP ranges).
True. We're actually running on Heroku, at the moment 😅
The gem's test suite looked solid to me to use a gem, and monkey patching, rather than having to manage this functionality on our own.
Talking about Cloudflare, Heroku, and Rack::Attack. We use this Rack::Attack configuration to prevent skipping Cloudflare in production. May be helpful for you or others who get here.
class Rack::Attack
if %w[1 true True enabled yes].include?(ENV["REJECT_UNPROXIED_REQUESTS"])
blocklist("block non-proxied requests in production") do |request|
raw_ip = request.get_header("HTTP_X_FORWARDED_FOR")
ip_addresses = raw_ip ? raw_ip.strip.split(/[,\s]+/) : []
proxy_ip = ip_addresses.last
if ::Rails.application.config.cloudflare.ips.any? { |proxy|
proxy === proxy_ip
}
false
else
::Rails.logger.warn "Rack Attack IP Filtering: blocked request from #{proxy_ip} to #{request.url}"
true
end
end
end
end
Ah yes, I do something similar via:
blocklist("herokuapp") do |req|
req.host =~ /herokuapp/
end
...which works for my case, simply enforcing access through my domain as opposed to Heroku directly.
Thanks for sharing!
Yes, I feel you.
It uses monkey patching so that your Rails app doesn't have to restart if Cloudflare's IP addresses change.
There are certainly pros and cons to both approaches.