Action Dispatch RemoteIp
此中间件计算发出请求的远程客户端的 IP 地址。它通过检查可能包含地址的各种标头来实现此目的,然后选择不在受信任 IP 列表中的最后一个设置的地址。这遵循例如 Tomcat 服务器 的先例。有关算法的更详细说明,请参见 GetIp#calculate_ip
。
一些 Rack 服务器会连接重复的标头,就像 HTTP RFC 2616 所要求的那样。一些 Rack 服务器只是丢弃前面的标头,并且只报告 最后一个标头中给出的值。如果您位于多个代理服务器(如 NGINX 到 HAProxy 到 Unicorn)之后,那么您应该测试您的 Rack 服务器以确保您的数据是正确的。
如果您不使用代理,这会让您容易受到 IP 欺骗的攻击。此中间件假设至少有一个代理在设置包含客户端远程 IP 地址的标头。如果您不使用代理,因为您是在例如没有 SSL
的 Heroku 上托管的,任何客户端都可以通过设置 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 61 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 89 def call(env) req = ActionDispatch::Request.new env req.remote_ip = GetIp.new(req, check_ip, proxies) @app.call(req.env) end