この問題に対して多くの解決策を試しました。これが私が見つけたものです:
cloudflare-rails
gem => これにより、ip と remote_ip の両方が元の IP に設定されます。私は ip が元の cloudflare ip を表し、remote_ip がユーザーの元の ip を表すようにしたかったので、それはうまくいきませんでした。Cloudflare IP 範囲のリストを 12 時間ごとに検索し、それらを trusted_proxy に追加することによって動作します。次にパッチActionDispatch::Request.ip
を適用ActionDispatch::Request.remote_ip
しRack::Attack::Request.trusted_proxy?
ます。
actionpack-cloudflare
gem => これははるかに簡単です。ActionDispatch.remote_ip = @env['HTTP_CF_CONNECTING_IP']
Cloudflare が推奨するベスト プラクティスに従って直接設定するだけですが、1 行のコードに gem を使用する価値はないように思われました。
- 手巻き
# config/initializers/cloudflare.rb
# These values should rarely or never change and Cloudflare should alert us before that happens.
# The list of Cloudflare proxy server ip ranges comes from https://www.cloudflare.com/ips/
CLOUDFLARE_IP_RANGES = [IPAddr.new("103.21.244.0/22"),IPAddr.new("103.22.200.0/22"),IPAddr.new("103.31.4.0/22"),IPAddr.new("104.16.0.0/12"),IPAddr.new("108.162.192.0/18"),IPAddr.new("131.0.72.0/22"),IPAddr.new("141.101.64.0/18"),IPAddr.new("162.158.0.0/15"),IPAddr.new("172.64.0.0/13"),IPAddr.new("173.245.48.0/20"),IPAddr.new("188.114.96.0/20"),IPAddr.new("190.93.240.0/20"),IPAddr.new("197.234.240.0/22"),IPAddr.new("2405:8100::/32"),IPAddr.new("2405:b500::/32"),IPAddr.new("2606:4700::/32"),IPAddr.new("2803:f800::/32"),IPAddr.new("2a06:98c0::/29"),IPAddr.new("2c0f:f248::/32")
]
# By adding the cloudflare IP ranges as trusted_proxies, rails ignores those IPs when setting remote_ip and correctly sets it to the originating IP
Rails.application.config.action_dispatch.trusted_proxies = CLOUDFLARE_IP_RANGES + ActionDispatch::RemoteIp::TRUSTED_PROXIES
最後に、プロキシされていないリクエストをブロックしたかった
# config/initializers/rack_attack.rb
class Rack::Attack
class Request < ::Rack::Request
# Create a remote_ip method for rack request by setting it equal to the cloudflare connecting ip header
# To restore original visitor IP addresses at your origin web server, Cloudflare recommends your logs or applications
# look at CF-Connecting-IP instead of X-Forwarded-For since CF-Connecting-IP has a consistent format containing only one IP.
# https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-CloudFlare-handle-HTTP-Request-headers-
def remote_ip
@remote_ip ||= (env['HTTP_CF_CONNECTING_IP'] || ip).to_s
end
# This checks the request IP against Cloudflare IP ranges and the action dispatch default trusted proxies.
# These include various local IPs like 127.0.0.1 so that local requests won't be blocked.
def proxied?
Rails.application.config.action_dispatch.trusted_proxies.any? { |range| range === ip }
end
end
# Block all requests coming from non-Cloudflare IPs
blocklist("block non-proxied requests in production") do |req|
if req.proxied?
false
else
req.log :warn
true
end
end
end