我一直在尝试使用Apache mod_proxy和mod_remoteip来确认我对X-Forwarded-For标头处理的理解,特别是关于内部IP地址(例如10.xxx或192.168.xx范围)的处理方式。被处理。
似乎mod_proxy并不总是将内部IP地址添加到X-Forwarded-For标头,但是我无法找到任何解释此预期行为的文档。
据我所知,当请求从内部IP地址发起时,mod_proxy会将内部IP地址添加到X-Forwarded-For标头,但是当初始请求来自公共IP时,mod_proxy不会似乎将任何内部IP地址添加到X-Forwarded-For。
问题
我的问题是:管理mod_proxy是否会将调用IP地址附加到X-Forwarded-For标头的规则是什么。
当以反向代理模式运行时(例如,使用ProxyPass指令),mod_proxy_http会添加多个请求标头,以便将信息传递给源服务器。这些标题是:
X-Forwarded-For - 客户端的IP地址。
X-Forwarded-Host - 客户端在Host HTTP请求标头中请求的原始主机。
X-Forwarded-Server - 代理服务器的主机名。
在原始服务器上使用这些标头时要小心,因为如果原始请求已包含其中一个标头,它们将包含多个(逗号分隔)值。例如,您可以在源服务器的日志格式字符串中使用%{X-Forwarded-For} i来记录原始客户端的IP地址,但如果请求通过多个代理,您可能会获得多个地址。
我读到这一点时说客户端IP地址将始终附加到X-Forwarded-For标头,但这不是我观察到的行为。
这个问题的其余部分是我所进行的测试以及我观察到的行为。
设置
我已经安装了两个运行Apache并安装了mod_proxy的服务器。我将这些称为“一对一”。
一个具有以下ProxyPass指令,以便对/ proxyToTwo的子路径的请求发送到/ proxyToOne on two下的等效子路径
<Location "/proxyToTwo">
ProxyPass http://10.0.7.2/proxyToOne
</Location>
两个具有以下ProxyPass指令,以便对/ proxyToOne的子路径的请求发送回One但没有/ proxyToOne前缀
<Location "/proxyToOne">
ProxyPass http://10.0.7.1
</Location>
这样做的结果是,当我向http://One/proxyToTwo/foo
发出请求时,它的代理如下
http://10.0.7.2/proxyToOne/foo
http://10.0.7.1/foo
/foo
的请求并实际提供资源所以每个请求都会从一到两个被反弹回一个请求,然后再回复两个。
使用内部IP呼叫
使用上述设置,我使用它的内部IP地址呼叫One from Two:
curl http://10.0.7.1/proxyToTwo/foo
当One最终获得/foo
资源的请求时收到的X-Forwarded-For和X-Forwarded-Host标头是我期望的:
X-Forwarded-For: 10.0.7.2, 10.0.7.1
X-Forwarded-Host: 10.0.7.1, 10.0.7.2
这就是我所期望的,请求首先通过One然后是Two代理,请求的IP地址首先是来自Two(curl)的初始请求,然后来自One(mod_proxy)的请求和最终请求(不是标头,因为它的连接的客户端IP来自Two(mod_proxy)
使用外部IP呼叫
出乎意料的行为是,当从公共IP调用时,mod_proxy的行为似乎有所不同。因此,我不是从Two调用One,而是使用公共地址从本地机器调用One
curl http://35.162.28.102/proxyToTwo/foo
X-Forwarded-Host仍然是我的期望:
X-Forwarded-Host: 35.162.28.102, 10.0.7.2
也就是说,请求首先通过One(使用它的外部地址)然后通过Two代理。
但是X-Forwarded-For标头只显示我的(外部)IP地址:
X-Forwarded-For: 35.163.25.76
这告诉我,mod_proxy的初始执行是添加带有客户端IP地址的X-Forwarded-For标头。但随后由Two进行的代理并未附加One的地址。
我认为这种行为可能比盲目地将内部IP地址附加到标题更有用,但我无法在任何地方找到它,所以我希望确保我完全理解它。
答案 0 :(得分:1)
回答这个问题,以便其他人可以犯同样的错误。
简而言之:mod_proxy总是将客户端IP附加到X-Forwarded-For标头(如果没有现有标头,则添加X-Forwarded-For标头)。
但是,其他Apache模块可以在mod_proxy处理它之前操作X-Forwarded-For标头。 Mod_proxy会将客户端IP附加到它所看到的X-Forwarded-For标头,它可以是其他Apache模块的输出。
在我的测试中,影响结果的另一个模块是mod_remoteip。产生行为差异的原因是我使用RemoteIpTrustedProxy指令来指定我的可信代理,这将允许信任私有IP作为第一个连接,但不会处理X-Forwarded-For中的私有IP报头中。
作为外部IP案例的结果,有以下处理:
35.163.25.76
)连接到没有X-Forwarded-For X-Forwarded-For: 35.163.25.76
)35.163.25.76
并且实际上没有传递给mod_proxy的X-Forward-For标头X-Forwarded-For: 35.163.25.76
)这就是“不附加私有IP”,但实际上正在处理X-Forward-For标头并生成相同的标题。
私有ID情况的行为不同,因为mod_remoteip不接受X-Forward中的私有IP地址。所以它由以下方式处理:
10.0.7.2
)连接到没有X-Forwarded-For X-Forwarded-For: 10.0.7.2
)10.0.7.1
),传递给mod_proxy的X-Forward-For标头是未修改的X-Forwarded-For: 10.0.7.2, 10.0.7.1
我通过从可信主机发送一些X-Forwarded-For标头来验证这一点。例如。
curl http://10.0.7.1/proxyToTwo/foo --header "X-Forwarded-For: TrustedHost1, TrustedHost2"
这导致最终的X-Forward-For标头仅包含TrustedHost1,表明标头确实由mod_remoteip处理并由mod_proxy重新发出。