Action Dispatch RemoteIp
此中间件计算发出请求的远程客户端的 IP 地址。它通过检查可能包含地址的各种标头来实现,然后选择不在受信任 IP 列表中的最后一个设置地址。这遵循了例如 Tomcat 服务器 的先例。关于算法的更详细解释,请参见 GetIp#calculate_ip
。
一些 Rack 服务器会连接重复的标头,例如 HTTP RFC 2616 所要求的。一些 Rack 服务器只是丢弃前面的标头,只报告 最后一个标头中给出的值。如果您位于多个代理服务器后面(例如 NGINX 到 HAProxy 到 Unicorn),那么您应该测试您的 Rack 服务器以确保您的数据是好的。
如果您不使用代理,这会导致您容易受到 IP 欺骗攻击。此中间件假设至少有一个代理在周围设置了包含客户端远程 IP 地址的标头。如果您不使用代理,因为您托管在例如 Heroku 上,没有 SSL
,任何客户端都可以通过设置 X-Forwarded-For
标头来声称拥有任何 IP 地址。如果您关心这个问题,那么您需要在该中间件运行之前显式地丢弃或忽略这些标头。或者,删除此中间件以避免无意中依赖它。
常量
TRUSTED_PROXIES | = | [ "127.0.0.0/8", # localhost IPv4 范围,根据 RFC-3330 "::1", # localhost IPv6 "fc00::/7", # 私有 IPv6 范围 fc00::/7 "10.0.0.0/8", # 私有 IPv4 范围 10.x.x.x "172.16.0.0/12", # 私有 IPv4 范围 172.16.0.0 .. 172.31.255.255 "192.168.0.0/16", # 私有 IPv4 范围 192.168.x.x ].map { |proxy| IPAddr.new(proxy) } |
默认的受信任 IP 列表只是包含根据 IP 规范保证为私有地址的 IP 地址。这些在生产环境中不会是最终的客户端 IP,因此被丢弃。有关详细信息,请参见 en.wikipedia.org/wiki/Private_network。 |
属性
[R] | check_ip | |
[R] | proxies |
类公共方法
new(app, ip_spoofing_check = true, custom_proxies = nil) 链接
创建一个新的 RemoteIp
中间件实例。
ip_spoofing_check
选项默认情况下处于开启状态。如果看起来客户端试图谎报自己的 IP 地址,则会引发异常。在针对非 IP 客户端(如 WAP 设备)的网站上,或在以不正确或令人困惑的方式设置标头的代理(如 AWS ELB)后面,关闭此检查是有意义的。
custom_proxies
参数可以接受一个可枚举对象,它将用于代替 TRUSTED_PROXIES
。任何代理设置都会将您想要的值放在 X-Forwarded-For
列表的中间(或开头),您的代理服务器在它后面。如果您的代理未被删除,请通过 custom_proxies
参数传递它们。这样,中间件将忽略这些 IP 地址,并返回您想要的那个。
来源:显示 | 在 GitHub 上
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 65 def initialize(app, ip_spoofing_check = true, custom_proxies = nil) @app = app @check_ip = ip_spoofing_check @proxies = if custom_proxies.blank? TRUSTED_PROXIES elsif custom_proxies.respond_to?(:any?) custom_proxies else raise(ArgumentError, <<~EOM) Setting config.action_dispatch.trusted_proxies to a single value isn't supported. Please set this to an enumerable instead. For example, instead of: config.action_dispatch.trusted_proxies = IPAddr.new("10.0.0.0/8") Wrap the value in an Array: config.action_dispatch.trusted_proxies = [IPAddr.new("10.0.0.0/8")] Note that passing an enumerable will *replace* the default set of trusted proxies. EOM end end
实例公共方法
call(env) 链接
由于可能不需要 IP 地址,因此我们在此处存储对象而不计算 IP,以避免减慢大多数请求的速度。对于那些需要知道 IP 的请求,GetIp#calculate_ip
方法将计算已记忆的客户端 IP 地址。
来源:显示 | 在 GitHub 上
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 93 def call(env) req = ActionDispatch::Request.new env req.remote_ip = GetIp.new(req, check_ip, proxies) @app.call(req.env) end