1

我一直在尝试使用 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 似乎没有添加X-Forwarded-For 的任何内部 IP 地址。

问题

我的问题是:管理 mod_proxy 是否将调用 IP 地址附加到 X-Forwarded-For 标头的规则是什么。

mod_proxy 上的文档说:

在反向代理模式下(例如,使用 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 的服务器。我将它们称为一和二。

  • 一个具有(内部)IP 地址 10.0.7.1
  • 两个具有(内部)IP 地址 10.0.7.2

One 具有以下 ProxyPass 指令,以便对 /proxyToTwo 的子路径的请求发送到 /proxyToOne 下的等效子路径 on Two

<Location "/proxyToTwo">
        ProxyPass http://10.0.7.2/proxyToOne
</Location>

Two 具有以下 ProxyPass 指令,因此对 /proxyToOne 的子路径的请求被发送回 One 但没有 /proxyToOne 前缀

<Location "/proxyToOne">
        ProxyPass http://10.0.7.1
</Location>

这样做的效果是,当我向http://One/proxyToTwo/foo它发出请求时,代理如下

  1. 一收到请求,向二发出以下请求http://10.0.7.2/proxyToOne/foo
  2. 二收到请求,将以下请求发回给一http://10.0.7.1/foo
  3. 接收请求/foo并实际为资源提供服务

因此,每个请求都会从一跳到二,然后再退回到一,然后再响应两次。

使用内部 IP 调用

使用上面的设置,我使用它的内部 IP 地址从两个呼叫一个:

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

这就是我所期望的,请求首先通过一个代理,然后是两个,并且请求的 IP 地址首先是来自两个(curl)的初始请求,然后是来自一个(mod_proxy)的请求和最终请求(不在标头中,因为它是来自两个(mod_proxy)的连接的客户端 IP

使用外部 IP 调用

出乎意料的行为是 mod_proxy 在从公共 IP 调用时似乎表现不同。因此,我没有从两个呼叫一个,而是使用公共地址从本地计算机呼叫一个

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 地址附加到标头更有用,但我无法在任何地方找到它的文档,所以想确保我完全理解它。

4

1 回答 1

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 案例,进行了以下处理:

  1. 我的机器 ( 35.163.25.76) 连接到一台没有 X-Forwarded-For
  2. 一个将此请求发送给两个,并在 X-Forwarded-For 标头 ( X-Forwarded-For: 35.163.25.76)中使用我的 IP
  3. 二收到此请求,mod_remoteip 处理 X-Forwarded-For 标头,因为 One 是受信任的,客户端 IP 有效,35.163.25.76并且实际上没有传递给 mod_proxy 的 X-Forward-For 标头
  4. 两个将此请求发送给一个,并在 X-Forwarded-For 标头 ( X-Forwarded-For: 35.163.25.76)中使用我的 IP

这表现为“不附加私有 IP”,但实际上是在处理 X-Forward-For 标头并产生相同的标头。

Private ID case 的行为不同,因为 mod_remoteip 不接受 X-Forward 中的私有 IP 地址。所以它由以下人员处理:

  1. 两个 ( 10.0.7.2) 连接到一个没有 X-Forwarded-For
  2. X-Forwarded-For: 10.0.7.2一个在 X-Forwarded-For 标头 ( )中使用两个 IP 将此请求发送给两个
  3. 两个收到此请求,mod_remoteip 处理 X-Forwarded-For 标头但不信任该值,因此保持原样。所以客户端 IP 仍然是 One 的 IP ( 10.0.7.1) 并且传递给 mod_proxy 的 X-Forward-For 标头未修改
  4. 两个将此请求发送给一个,将客户端 IP(一个)附加到 X-Forwarded-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 重新发布。

于 2016-11-07T04:25:48.050 回答