什么决定什么时候mod_proxy有时只将内部IP地址添加到X-Forwarded-For标题

时间:2016-11-03 22:00:57

标签: apache mod-proxy x-forwarded-for

我一直在尝试使用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标头的规则是什么。

documentation on 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

一个具有以下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发出请求时,它的代理如下

  1. 收到请求后,向两个http://10.0.7.2/proxyToOne/foo
  2. 发出以下请求
  3. 两人收到请求,将以下请求发回一http://10.0.7.1/foo
  4. 收到/foo的请求并实际提供资源
  5. 所以每个请求都会从一到两个被反弹回一个请求,然后再回复两个。

    使用内部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地址附加到标题更有用,但我无法在任何地方找到它,所以我希望确保我完全理解它。

1 个答案:

答案 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案例的结果,有以下处理:

  1. 我的计算机(35.163.25.76)连接到没有X-Forwarded-For
  2. 的One
  3. 使用我的IP在X-Forwarded-For标题(X-Forwarded-For: 35.163.25.76
  4. 中将此请求发送给Two
  5. 两个收到此请求,mod_remoteip处理X-Forwarded-For标头,因为One是可信的,客户端IP实际上是35.163.25.76并且实际上没有传递给mod_proxy的X-Forward-For标头
  6. 两个人将此请求发送给One,其中我的IP位于X-Forwarded-For标头中(X-Forwarded-For: 35.163.25.76
  7. 这就是“不附加私有IP”,但实际上正在处理X-Forward-For标头并生成相同的标题。

    私有ID情况的行为不同,因为mod_remoteip不接受X-Forward中的私有IP地址。所以它由以下方式处理:

    1. 两个(10.0.7.2)连接到没有X-Forwarded-For
    2. 的One
    3. One将此请求发送给两个带有两个IP的X-Forwarded-For标头(X-Forwarded-For: 10.0.7.2
    4. 两个收到此请求,mod_remoteip处理X-Forwarded-For标头,但不信任该值,因此保持原样。所以客户端IP仍然是One的IP(10.0.7.1),传递给mod_proxy的X-Forward-For标头是未修改的
    5. 两个将此请求发送给一个将客户端IP(一个)附加到X-Forwarded-For标头,导致X-Forwarded-For: 10.0.7.2, 10.0.7.1
    6. 我通过从可信主机发送一些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重新发出。