1. 本文场景

这里以我自己的结构为例:

访客→CDN 边缘节点→WAF→Origin Nginx

2. X-Forwarded-For(XFF)介绍

2.1 什么是 XFF?

X-Forwarded-For(XFF)请求标头是一个事实上的用于标识通过代理服务器连接到 web 服务器的客户端的原始 IP 地址的标头。

——X-Forwarded-For - HTTP | MDN

简单来说,就是用于多层反代之间传递真实的用户 IP。

一下简称 X-Forwarded-For 为 XFF。

2.2 XFF的格式及原理

这种请求头格式并没有多么难以理解,一般为一下这种:

X-Forwarded-For: client, proxy1, proxy2

名词解释:

  • Client——客户端
  • Proxy1——第一层代理
  • Proxy2——第二层代理

XFF 会由左向右添加记录各级代理的 IP。

例如,在这里,我的 CDN 边缘节点 IP 是 1.1.1.1,WAF IP 是 2.2.2.2,访客 IP 是 3.3.3.3,那么最终源站将会得到这样的 XFF 请求头内容:

X-Forwarded-For: 3.3.3.3, 1.1.1.1, 2.2.2.2

这样,若是源站取其中 3.3.3.3 为访客 IP,即可获得真实 IP。

在本文所举例子中,请确保 CDN 边缘节点直接使用 Remote Address(网络连接中获取)来作为真实 IP 记录,因为 Remote Address 无法被伪造(由于 TCP 四次握手的过程)。否则可能会导致攻击者伪造 XFF 并进而导致一些安全事故。

3. 源站配置

我们首先确保 CDN 会传递 XFF给上游,WAF 也通过 XFF 获取真实 IP 并传递给上游(本例子中为源站 NG)

随后,可以在源站修改 web 服务端配置文件。

3.1 修改 Nginx 配置文件

在 http 块加入以下代码:

http{    
......    
        set_real_ip_from CDN 边缘节点 IP;
        set_real_ip_from WAF IP;
        real_ip_header X-Forwarded-For;
        real_ip_recursive on;
......

代码解释:

  • set_real_ip_from CDN 边缘节点 IP——声明CDN服务的IP地址为可信代理。只有来自该IP的请求,Nginx才会处理X-Forwarded-For头。若CDN未在可信列表,Nginx会将其视为客户端IP,导致获取错误。
  • set_real_ip_from WAF IP——声明WAF(Web应用防火墙)的IP为可信代理,原理同上。
  • real_ip_header X-Forwarded-For——指定从X-Forwarded-For请求头中提取原始客户端IP。
  • real_ip_recursive on——从右至左遍历X-Forwarded-For中的IP,跳过所有可信代理IP,首个非可信IP即为客户端真实IP。

注意:

Nginx 会从右往左读取 IP,直到读取第一个不在 set_real_ip_from 中的 IP 为止。

所以,在 set_real_ip_from 行中,请务必囊括您整条代理流程中的所有 代理 IP(或 IP 段),否则可能会导致源站无法正常解析出真实 IP。

这里放出一个错误示范

http{    
......    
        set_real_ip_from WAF IP;
        real_ip_header X-Forwarded-For;
        real_ip_recursive on;
......

可以看到,这个配置文件中仅仅将 WAF IP 添加到了列表中,而没有添加 CDN 边缘节点的 IP。由于 2.2 段中提到的 XFF 工作原理,Nginx 会在从右往左取 IP 时,把 CDN 边缘节点 IP 错误地解析为真实 IP。

X. 版权申明