跳转到帖子

咖啡馆实战:网站加速器与 Nginx 反向代理中的真实 IP 信任边界排查

精选回复

发布于

背景

网站接入 CDN、WAF 或四层负载均衡后,源站看到的客户端通常是代理节点地址。为了恢复访客 IP,常见做法是读取 X-Forwarded-For、X-Real-IP 或厂商提供的专用请求头。

这里容易出现一个权限边界问题:源站把客户端可控的请求头当成可信身份。影响不只体现在日志污染,还可能绕过基于 IP 的后台限制、接口限速、封禁策略和审计关联。下面以经过授权的网站测试为前提,记录一套从链路确认、漏洞验证到配置修复的方法。

典型场景

目标链路如下:

客户端 → CDN/WAF → 负载均衡 → Nginx → 应用

应用通过 Nginx 传入的 X-Real-IP 判断访问来源,并允许办公网地址访问管理接口。Nginx 同时启用了 Real IP 模块。如果信任范围设置过宽,攻击者直接访问源站,或者向加速节点提交伪造头,就可能让应用得到一个虚假的办公网 IP。

需要分别确认四个地址的含义:

  • $remote_addr:Real IP 模块处理后的客户端地址。
  • $realip_remote_addr:建立 TCP 连接的原始对端地址,排查信任链时很重要。
  • $http_x_forwarded_for:客户端请求中原始的 X-Forwarded-For 内容,默认不可信。
  • $proxy_add_x_forwarded_for:在现有 X-Forwarded-For 后追加当前 remote_addr,不能单独解决上游头部伪造问题。

问题定位

先确认源站是否能绕过 CDN 直接访问。可从 DNS 历史、证书、运维记录和当前防火墙策略入手,但测试时不要对无授权地址进行扫描。已知源站地址后,可以使用 --resolve 保持正确的 Host 与 TLS SNI。

# 正常经过加速节点访问
curl -sk -D- 

# 在授权范围内直接访问已知源站,同时保持域名和 SNI
curl -sk --resolve  \
  

# 验证源站是否错误信任客户端提交的地址头
curl -sk --resolve  \
  -H 'X-Forwarded-For: 10.10.20.30' \
  -H 'X-Real-IP: 10.10.20.30' \
   是文档示例地址,实际测试应替换为已获授权的源站。验证接口最好临时返回服务端识别到的地址,不建议直接用管理后台是否放行作为唯一依据。

如果第三次请求让应用识别到 10.10.20.30,还需要区分问题位于 Nginx 还是应用层。查看完整配置,而不是只检查单个站点文件:

nginx -T 2>&1 | grep -nE 'real_ip|forwarded|proxy_set_header|allow|deny'

# 查看编译参数,确认是否包含 http_realip_module
nginx -V 2>&1 | grep -o -- '--with-http_realip_module'

技术分析

下面是一类高风险配置:

set_real_ip_from 0.0.0.0/0;
set_real_ip_from ::/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass 
}

set_real_ip_from 0.0.0.0/0 表示任何来源都被视为可信代理。启用 real_ip_recursive on 后,Nginx 会沿地址链从右向左跳过可信代理,并选择第一个不可信地址作为客户端地址;当所有来源都被错误标记为可信时,客户端构造的地址就可能进入 $remote_addr。

另一类常见问题是多层代理的职责不清。例如 CDN 会清洗并重写 X-Forwarded-For,但内部负载均衡只做透传;如果源站同时信任 CDN 网段和整个内网网段,那么内网中任意能连接源站的主机都可能伪装地址。这里的信任对象应是“实际上一跳代理”,而不是笼统的整个私有网络。

分层验证步骤

建议按以下顺序定位,避免仅凭一个响应头下结论:

  • 记录直连源站和经过加速器时的 TCP 对端地址。
  • 分别提交无地址头、单个地址头、包含多个地址的 X-Forwarded-For。
  • 对照 Nginx 的 $realip_remote_addr、$remote_addr 与应用识别结果。
  • 确认 CDN/WAF 是覆盖客户端头、追加地址,还是使用专用头。
  • 检查管理接口、限速模块和应用框架分别使用哪个变量。

可以临时增加独立审计日志,不要直接替换现有访问日志:

log_format ip_chain escape=json
  '{"time":"$time_iso8601",'
  '"host":"$host",'
  '"peer":"$realip_remote_addr",'
  '"client":"$remote_addr",'
  '"xff":"$http_x_forwarded_for",'
  '"xri":"$http_x_real_ip",'
  '"request":"$request",'
  '"status":$status}';

access_log /var/log/nginx/ip_chain.log ip_chain;

修改后先检查并平滑加载:

nginx -t && nginx -s reload

tail -f /var/log/nginx/ip_chain.log

重点观察 peer。它应对应实际 CDN、WAF 或负载均衡节点;如果 peer 是测试机地址,而 client 变成请求头中填写的地址,基本可以确认源站信任边界配置错误。

推荐配置

修复的核心不是简单删除 X-Forwarded-For,而是限定可信代理并阻断非预期直连。以下配置中的网段仅为示例,生产环境应使用加速服务商公布并可自动校验更新的出口网段,以及实际负载均衡节点地址。

# 只信任实际会连接本机的上一跳代理
# 203.0.113.0/24 为文档示例网段
set_real_ip_from 203.0.113.0/24;
set_real_ip_from 10.20.0.11;
set_real_ip_from 10.20.0.12;

real_ip_header X-Forwarded-For;
real_ip_recursive on;

location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass 
}

如果加速服务提供不可由普通用户写入、且会在边缘节点强制覆盖的专用头,可以使用该头,但仍必须配合 set_real_ip_from。仅仅把 real_ip_header 改为厂商头,并不能防止攻击者直连源站后自行构造同名头。

源站网络层还应只允许 CDN/WAF 或负载均衡访问 80、443 端口。以 nftables 为例,规则应在维护窗口内结合现网管理通道部署,避免误锁:

table inet web_origin {
  set trusted_proxy_v4 {
    type ipv4_addr
    flags interval
    elements = { 203.0.113.0/24, 10.20.0.11, 10.20.0.12 }
  }

  chain input {
    type filter hook input priority 0; policy accept;
    tcp dport { 80, 443 } ip saddr @trusted_proxy_v4 accept
    tcp dport { 80, 443 } drop
  }
}

部署前应通过 nft -c -f 做语法检查,并确认 IPv6、健康检查节点、证书回源节点和应急运维入口都已纳入设计。只限制 IPv4 而遗漏 AAAA 记录或 IPv6 监听,是源站保护中比较常见的缺口。

权限边界与限速注意事项

不要把来源 IP 当成管理接口的唯一认证条件。IP 白名单适合做附加边界,管理入口仍应使用独立身份认证、最小权限和多因素验证。对于 Nginx 限速,如果键值使用已经被污染的 $binary_remote_addr,攻击者可以轮换伪造地址规避限制,也可以伪造同一地址造成误封。

limit_req_zone $binary_remote_addr zone=api_per_ip:20m rate=5r/s;

location /api/ {
    limit_req zone=api_per_ip burst=20 nodelay;
    proxy_pass 
}

这段限速配置只有在 Real IP 信任链正确时才有意义。对登录、短信和高价值业务接口,还应叠加账号、设备标识或业务对象维度的限制,避免把所有控制都压在客户端 IP 上。

日志留痕与复测

修复后至少保留一段时间的 peer、client、X-Forwarded-For 和请求标识。若发现同一个 peer 持续提交异常长的地址链、私网地址、回环地址或格式错误内容,应进一步检查边缘节点是否确实执行了头部清洗。

复测应覆盖以下情况:

  • 直连源站的 80、443 端口被网络层拒绝。
  • 通过 CDN 访问时,应用得到真实测试客户端地址。
  • 提交伪造 X-Forwarded-For 后,应用地址不受客户端输入控制。
  • 多级代理链中,日志同时保留原始对端和最终识别地址。
  • 后台白名单、接口限速与封禁策略使用的是修复后的可信地址。
  • IPv4、IPv6、健康检查和回源重试路径行为一致。

风险与修复建议

  • 禁止使用 0.0.0.0/0、::/0 或整个内网作为通用可信代理范围。
  • 在网络层限制源站只接受实际代理节点回源,避免仅依赖 HTTP 头判断。
  • 明确每一层代理对地址头执行覆盖、追加还是透传,并形成可审计配置。
  • 同时记录 TCP 原始对端和处理后的客户端地址,避免修复后丢失取证依据。
  • 加速服务商网段发生变化时,通过受控任务更新,更新前校验来源、格式和差异。
  • 管理接口不要只依赖 IP 白名单,限速也不要只依赖单一 IP 维度。

总结

网站接入加速器后,真实 IP 不是简单读取一个请求头,而是一条需要逐跳确认的信任链。排查时应同时看网络可达性、Nginx Real IP 配置、代理头处理方式、应用取值和日志字段。比较稳妥的落地方式是:源站禁止非代理直连,只信任明确的上一跳节点,保留原始对端日志,并让身份认证与限速策略避免过度依赖 IP。

网络流量与边界分析示意图
网络请求、日志与边界流量分析示意
服务器与云环境安全示意图
服务器、云资产与权限边界梳理示意

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。

SiteMap HACKHAT © 2026 All rights reserved.