我在代理后面运行Ruby on Rails应用程序。代理按预期设置并向应用程序发送X-Forwarded-For
头。它可能看起来像这样:
X-Forwarded-For = '1.1.1.1, 2.2.2.2'
当我调用remote_ip
时,Rails返回2.2.2.2
。当应用程序写入日志条目时也是如此,然后将请求记录为IP地址2.2.2.2
。
源代码中记录了此行为:
# In order to find the first address that is (probably) accurate, we
# take the list of IPs, remove known and trusted proxies, and then take
# the last address left, which was presumably set by one of those proxies.
到目前为止没有意外或令人惊讶的行为。
但我的问题的第一部分是,该列表中的最后一个IP地址是代理本身的IP。这意味着我实际上希望remote_ip
返回1.1.1.1
而不是2.2.2.2
。因为1.1.1.1
将是真实的客户端的IP地址。
Ruby on Rails为这个需求提供的解决方案是将2.2.2.2
添加到TRUSTED_PROXIES
,如ActionDispatch::RemoteIp中所述。当2.2.2.2
被添加到可信代理时,Rails将从X-Forwarded-For
中的IP地址列表中删除这些可信代理,并返回剩余IP列表中的最后一个,即1.1.1.1
。
但问题的第二部分是我使用的是基于云的托管代理。它的IP可以随时更改,它的IP可以是Amazon AWS上EC2示例可用的任何IP。这使得在TRUSTED_PROXIES
中添加其IP很容易出错,因为它随时可能过时。并且没有更改代理行为的选项。例如,我不能告诉代理不要将自己的IP添加到X-Forwarded-For
头中。
有什么办法解决这个问题吗?
1条答案
按热度按时间mzmfm0qo1#
我决定使用一个额外的中间件来解决这个问题,我将它添加到应用程序的中间件堆栈中,正好在
ActionDispatch::RemoteIp
之前,它为Rails应用程序提取remote_ip
。中间件只在检查应用程序实际上在代理之后运行之后才操作
X-Forwarded-For
头,我可以通过特定头的存在来检查。我只交换了最后两个条目,以使所有IP地址仍然可用,以便进行调试,并且现在检查默认行为太多。