X-Forwarded-For中多个IP哪个是真实客户端IP? - adam-p

22-03-06 banq

直接上结论:如何从Http的标头X-Forwarded-For(简称XFF)中寻找“真实客户端 IP 地址”?请使用IP地址列表中最右侧的 IP。
XFF 标头中最左边的 IP 通常被认为是“最接近客户端”和“最真实”的,但它很容易被欺骗。不要将它用于任何与安全相关的事情。

Web 服务对其客户的 IP 地址感兴趣的原因有很多:地理统计、地理定位、审计、速率限制、滥用阻止、会话历史等。
当客户端直接连接到服务器时,服务器可以看到客户端的 IP 地址。如果客户端通过一个或多个代理连接(任何类型:正向、反向、负载均衡器、API 网关、TLS 卸载、IP 访问控制等),那么服务器只能直接看到最终代理使用的 IP 地址客户端连接。
为了将原始 IP 地址传递给服务器,有几个常用的标头:
  • X-Forwarded-For 是一个以逗号分隔的IP列表,由请求路径中经历的每个代理服务器追加的。我们的通常想法是:第一个IP(由第一个代理添加)是真正的客户IP。每个后续的IP是沿着路径的下一个代理。最后一个代理的IP是不存在的(因为代理不添加自己的IP,而且因为它直接连接到服务器,所以它的IP将直接可用)。
  • Forwarded 是最正式但似乎最不常用的头。它实际上只是XFF的一个高级版本。
  • 还有一些特殊的单IP头,如X-Real-IP(Nginx)、CF-Connecting-IP(Cloudflare),或True-Client-IP(Cloudflare和Akamai)。

请注意:X-Forwarded-For使用和其他 HTTP 标头获取“真实客户端 IP”的状态非常糟糕。它执行不正确、不一致,并且结果使用不当。这导致了各种项目中的安全漏洞,并且肯定会在未来导致更多。
 
其他注意点:
当选择最右边的XFF IP时,确保使用标头Header的最后最新的一个实例。
 
使用反向代理设置的特殊 "真正的客户IP"(如X-Real-IP、True-Client-IP等)可能是好的,但这取决于
  • a)反向代理如何实际设置,
  • b)如果已经存在/欺骗,反向代理是否设置,以及
  • c)你如何配置反向代理(有时)。

任何不是由你的反向代理特别设置的头Header都不能被信任。例如,如果你位于Nginx或其他会给标头X-Real-IP赋值的代理后面,你一定不要检查标头X-Real-IP的值,因为你会读到一个欺骗的值。
很多速率限制器的实现都在使用可欺骗的IP,容易受到速率限制器逃逸和内存耗尽的攻击。
 
您必须始终注意,由不受您控制的任何代理添加(或似乎已添加)的任何 XFF IP 都是完全不可靠的。任何代理都可以按照它想要的方式添加、删除或修改标头。
例如,如果您向 AWS 负载均衡器2发出此请求……
curl -X POST https://my.load.balanced.domain/login -H "X-Forwarded-For: 1.2.3.4, 11.22.33.44"
负载均衡器后面的服务器会得到这个:
X-Forwarded-For: 1.2.3.4, 11.22.33.44, <真实客户端IP>
 
或者再次发送请求:
curl -X POST https://my.load.balanced.domain/login -H "X-Forwarded-For: oh, hi,,127.0.0.1,,,,"
你会从XFF标头中得到:
X-Forwarded-For: oh, hi,,127.0.0.1,,,,, <真实客户端IP>

如您所见,已经存在的所有内容都只是未更改且未经验证。最终的实际 IP 只是附加到已经存在的任何内容上。
 
详细分析点击标题