← 全部文章

反向代理后面的真实客户端IP

2026年11月4日,作者:The Casbin Authors

反向代理放到应用前面之后,第一件坏掉的事情是客户端地址。之前应用看得见访客,之后所有连接都来自代理:日志里全是 10.0.0.14,限流把整个互联网当成一个地址在数,IP黑名单完全不起作用。

地址其实还在,就在 X-Forwarded-For 请求头里,每个代理路过时往里追加一段。问题在于客户端自己也能写这个头,无条件相信它的代理,等于给攻击者提供了冒充任意地址的办法。

CasWAF 在一个地方把这个地址算清楚,后面全部用这个结果:IP规则、限流、请求记录、发给上游的 X-Real-Ip,以及看板上显示的地址。

怎么判断

  1. 连接不来自可信代理。 客户端就是连接本身的地址,客户端自己发的 X-Forwarded-For 一律忽略,并在转发前删掉。
  2. 连接来自可信代理。 从右往左读 X-Forwarded-For,跳过本身就是可信代理的地址,取第一个不是的。那是进入你自己基础设施之前的最后一跳,客户端伪造不了。
  3. 没有 X-Forwarded-For。 可信代理发过 X-Real-IP 就用它,否则用连接地址。

从右往左读是关键。客户端可以发 X-Forwarded-For: 1.2.3.4,而每个真实代理会追加它实际收到的连接地址。取最右边第一个不可信的地址,伪造的那个永远轮不上。

可信代理

默认信任私有地址和本地地址:

127.0.0.0/8, ::1/128, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 100.64.0.0/10, fc00::/7

这覆盖了自家网络里的负载均衡,也是最常见的情况:云负载均衡从内网地址转发,CasWAF 信它,真实客户端从请求头里读出来。

CDN 不一样,它是从公网地址连到 CasWAF 的。把它的网段,连同仍然需要的私有网段,写进 trustedProxies:

trustedProxies = 127.0.0.0/8, ::1/128, 10.0.0.0/8, 173.245.48.0/20, 103.21.244.0/22

这个值是替换默认列表,不是追加;不带前缀的单个地址也接受;也可以用同名的环境变量设置。只在启动时读一次。

应用能看到什么

CasWAF 转发请求时带上:

  • X-Real-Ip:上面算出来的客户端地址
  • X-Forwarded-Proto:https 或 http,按客户端连到 CasWAF 时用的协议
  • X-Forwarded-For:来自可信代理就原样保留,否则删掉

CasWAF 后面的应用应该读 X-Real-Ip,并且只在请求确实来自 CasWAF 时才信它。如果应用还有直接可达的入口,那它就有一模一样的伪造问题,只是低了一层。

唯一要紧的规则

只列你真正在跑的代理的网段。trustedProxies 里的每一个地址,都能声称自己在替任何人转发。CDN 的网段是公开信息;你忘了还在那儿的、直接对公网的代理则不是。

完整说明在代理后的客户端IP,地址算对之后拿它做什么,见IP规则。