Ruby on Rails应用remote_ip返回代理IP而非客户端IP的解决方案咨询
解决方案
方案1:自动同步AWS代理IP范围到TRUSTED_PROXIES
AWS会公开其各类服务的IP地址范围(如ELB、CloudFront),你可以通过自动拉取这些范围并配置到Rails的TRUSTED_PROXIES中,步骤如下:
- 拉取AWS官方发布的IP范围JSON文件(
https://ip-ranges.amazonaws.com/ip-ranges.json)
- 拉取AWS官方发布的IP范围JSON文件(
- 筛选出你所用代理服务对应的CIDR段(比如筛选
service字段为ELB或CLOUDFRONT的条目)
- 筛选出你所用代理服务对应的CIDR段(比如筛选
- 将筛选后的CIDR段添加到Rails配置中,示例代码:
# config/initializers/remote_ip.rb require 'net/http' require 'json' def aws_proxy_cidrs(service_name) uri = URI('https://ip-ranges.amazonaws.com/ip-ranges.json') response = Net::HTTP.get(uri) data = JSON.parse(response) data['prefixes'].select { |prefix| prefix['service'] == service_name }.map { |prefix| prefix['ip_prefix'] } end # 根据实际使用的代理服务修改,比如ELB或CLOUDFRONT AWS_PROXY_CIDRS = aws_proxy_cidrs('ELB') Rails.application.config.action_dispatch.trusted_proxies += AWS_PROXY_CIDRS
- 设置定时任务(如cron)定期拉取更新IP范围,避免每次启动请求,更新后重启Rails服务生效
方案2:自定义RemoteIp中间件逻辑
如果确认请求只会经过这一层AWS托管代理,且X-Forwarded-For格式固定为客户端IP, 代理IP,可以自定义中间件覆盖默认逻辑,直接提取客户端IP。必须验证请求源IP属于AWS代理范围,防止恶意伪造请求头:
# app/middlewares/custom_remote_ip.rb class CustomRemoteIp def initialize(app) @app = app @aws_proxy_cidrs = aws_proxy_cidrs('ELB') end def call(env) request = ActionDispatch::Request.new(env) # 验证请求来自AWS代理 if @aws_proxy_cidrs.any? { |cidr| IPAddr.new(cidr).include?(request.remote_ip) } client_ip = env['HTTP_X_FORWARDED_FOR']&.split(',')&.first&.strip env['action_dispatch.remote_ip'] = client_ip if client_ip.present? end @app.call(env) end private def aws_proxy_cidrs(service_name) require 'net/http' require 'json' uri = URI('https://ip-ranges.amazonaws.com/ip-ranges.json') response = Net::HTTP.get(uri) data = JSON.parse(response) data['prefixes'].select { |prefix| prefix['service'] == service_name }.map { |prefix| prefix['ip_prefix'] } end end # 注册中间件,放在默认RemoteIp中间件之后 # config/application.rb config.middleware.insert_after ActionDispatch::RemoteIp, CustomRemoteIp
方案3:用第三方gem简化配置
使用trusted_proxies gem可以自动从AWS等服务商拉取代理IP段,只需简单配置:
# Gemfile gem 'trusted_proxies' # config/initializers/trusted_proxies.rb TrustedProxies.config do |config| config.providers = [:aws_elb] # 根据代理服务选择,比如:aws_cloudfront end Rails.application.config.action_dispatch.trusted_proxies += TrustedProxies.all
内容的提问来源于stack exchange,提问作者spickermann
相关产品推荐
相关产品推荐

