接入 CDN 后日志全是节点 IP?Nginx 真实访客 IP 与可信代理配置
本内容发表于:2026-10-14 10:42:51
浏览量
1008

访客身份穿过可信 CDN 代理到达源站,旁侧伪造身份被阻断

接入 CDN 后,源站 access log 里出现的可能都是 CDN 节点地址。如果限流也按这个地址计算,多名访客就会共用一个限流额度。排查需要同时看 TCP 连接来自谁,以及代理如何传递原始访客地址。

Nginx 的 Real IP 模块可以根据指定请求头替换客户端地址,但前提是连接来源属于配置的可信代理。[1] 下面以 HTTP 反向代理为例说明配置和验证方法,适用于管理 CDN 回源与 Nginx 的运维人员。示例地址均为文档占位值,需要替换;本文依据官方文档整理,未对生产源站做配置变更或验证测试。

画出源站实际收到请求的路径

常见路径包括“访客 → CDN → Nginx”,以及“访客 → CDN → 负载均衡 → Nginx”。后者中,Nginx 的直接连接来源可能是内部负载均衡,CDN 节点地址则出现在转发链里。

配置前确认每一层的行为:它使用什么请求头,是否覆盖访客自带的同名头,怎样追加代理地址,是否保留 CDN 提供的专用访客 IP 头。头的名称相同,并不保证内容生成方式相同。

本文用 X-Forwarded-For 举例。若平台要求另一种头,要依据该平台的回源文档调整,并确认中间代理的处理方式。不能仅凭一个名字像“客户端 IP”的字段就信任它;本文也不假定 CloudFlew 使用某个固定头。

检查模块,再保留两种地址

先查看 Nginx 编译参数:

nginx -V 2>&1

官方文档说明,ngx_http_realip_module 并非默认编译,需要 --with-http_realip_module。[1] 如果当前二进制不包含它,按发行版或镜像的安装说明选择带模块的版本,不要直接把配置片段塞进生产环境。

Real IP 生效后,$remote_addr 是替换后的客户端地址,$realip_remote_addr 保留原始连接地址。后一个变量从 Nginx 1.9.7 起提供。[1] 排查期间把两个值都写入日志,可以辨别“访客是谁”和“是谁连接到源站”。

以下日志格式放在 http 块中;access_log 放到需要检查的 server 块内。保留原有日志,在测试站点增加这份临时日志。[2]

# http 块
log_format realip_check '$time_iso8601 client=$remote_addr '
                       'peer=$realip_remote_addr '
                       'xff="$http_x_forwarded_for" '
                       '"$request" $status';

# 目标 server 块
access_log /var/log/nginx/realip-check.log realip_check;

日志中的 xff 是原始请求头,可能含有访客提供的内容。它适合用来排查代理行为,不能直接作为已经验证的身份。日志还应按现有隐私和保留周期管理,排查结束后撤掉临时日志。

给可信代理明确的地址范围

下面是放在目标 server 块的说明片段。192.0.2.0/24 与 2001:db8::/32 是文档地址范围,不能当成真实 CDN 网段照抄。

# 占位值:替换为当前平台公布并核验过的回源代理网段
set_real_ip_from 192.0.2.0/24;
set_real_ip_from 2001:db8::/32;

real_ip_header X-Forwarded-For;
real_ip_recursive on;

set_real_ip_from 定义能够正确提供替代地址的可信来源。real_ip_header 指定从哪个头读取地址;上例开启递归,Nginx 会在原始连接来源可信的前提下,使用头中最后一个不受信任的地址。[1]

使用官方当前网段列表,覆盖实际采用的 IPv4 和 IPv6 回源地址。不要把 0.0.0.0/0 或 ::/0 当成解决遗漏网段的办法,这会把任意连接来源都视为可信。

如果直接连接 Nginx 的是内部负载均衡,需要纳入那台代理的准确地址或必要子网,并检查它对请求头的处理。不要为了方便信任整个私网:同一私网里还可能有不应获得身份声明权限的其他服务。

单独配置 Real IP 不会封闭源站。源站入口还需要依据架构限制可连接来源;内部负载均衡也必须限制入口或清理不可信请求头,否则外部请求可能借它进入可信链路。

多层代理要看整条地址链

假设某个请求的实际访客是 198.51.100.23,经过文档示例地址 192.0.2.10 的 CDN 节点,再由 10.20.0.10 的负载均衡连接 Nginx:

TCP 连接来源:10.20.0.10
X-Forwarded-For: 198.51.100.23, 192.0.2.10

在这条说明链路中,如果准确配置了负载均衡和 CDN 的可信范围,递归搜索可跳过链尾可信 CDN 地址,得到 198.51.100.23。若只信任负载均衡,搜索会停在未被信任的 CDN 节点,日志里仍会显示节点 IP。关闭递归时,可信连接来源会被替换为头中的最后一个地址,结果也可能是 CDN 节点。[1]

这个结果依赖上游确实按已确认的规则构造链。不要把“取最左边的 IP”写成通用方案:访客可能自行提交一个或多个地址,上游是否覆盖或追加决定了哪些内容可靠。

如果采用单地址的专用访客 IP 头,则核对平台怎样生成该头、中间层是否保留,以及是否可能被直连请求伪造。上面的 XFF 链式查找示例不能自动证明另一种头的配置安全。

给后端传递已确认的地址

Nginx 自己的日志正确后,还需要检查应用读取哪个字段。若后端仍只看连接来源,它可能看到 Nginx 的地址;若直接信任原始请求头,又可能重新引入不可信内容。

在后端支持 X-Real-IP,且只允许这台 Nginx 连接的场景,可以在现有代理 location 中明确设置:

proxy_set_header X-Real-IP $remote_addr;

后端也要把可信来源限制到实际的 Nginx 代理,按框架文档配置读取方式。[4] 不要为了让它“识别成功”而允许任意来源声明客户端地址。

$proxy_add_x_forwarded_for 的官方定义是:在收到的 XFF 后追加 $remote_addr;没有收到 XFF 时,它等于 $remote_addr。[4] Real IP 替换地址后继续追加,可能让访客地址重复出现,同时保留原始头里的不可信部分。需要完整代理链的系统应统一链路规则;只需要单一已确认地址的内部服务,可以选择覆盖输出字段,但须先确认其他审计和追踪系统是否依赖原始链。

按 $binary_remote_addr 建立的 Nginx 请求限流,与客户端地址有关,官方示例也采用这个变量。[3] Real IP 变更可能让额度从“每个代理节点”转为“每个访客地址”。检查原有 rate、burst 和监控结果,不要把修正日志与批量改动限流规则一起上线。

在小范围验证,再重载生产配置

修改前备份涉及的配置文件,记录原有头处理方式和可信网段。优先在测试站点或单个虚拟主机验证,避免 http 层的全局设置影响其他入口。

使用测试环境的只读地址发起请求,并对照该次请求的源站日志。路径需要能回源;若命中 CDN 缓存,源站可能没有这次日志,不应据此认定配置失效。

# 换成测试域名和已确认会回源的只读测试路径
curl -sS -o /dev/null -D - https://test.example.com/realip-check

# 模拟客户端自行声明地址;198.51.100.77 是文档地址
curl -sS -o /dev/null -D - \
  -H 'X-Forwarded-For: 198.51.100.77' \
  https://test.example.com/realip-check

普通请求中,client 应对应测试出口的公网地址,peer 应对应实际回源代理或内部负载均衡。若经过 NAT 或 VPN,以测试出口地址为准。加入伪造头后,已确认的地址应继续符合平台和中间代理的规则;不能仅靠 HTTP 状态码判断验证通过。

在你有权限的测试源站上,还可用 --resolve 固定连接地址,保留 URL 中的域名做 HTTPS 请求。[5] 下例的源站地址同样需要替换,不要关闭证书验证来掩盖另一个问题。

curl -sS -o /dev/null -D - \
  --resolve test.example.com:443:203.0.113.10 \
  -H 'X-Forwarded-For: 198.51.100.77' \
  https://test.example.com/realip-check

如果源站只允许代理回源,直连测试应被入口规则拒绝;若测试架构允许直连,来自非可信来源的头不应覆盖连接地址。补充 IPv6、经过内部负载均衡以及未携带目标头的请求,确认各条入口都有预期结果。

配置语法检查通过后,再按你的部署方式重载。以下适用于以 systemd 管理的 Nginx;容器和托管服务应使用各自的部署流程。

sudo nginx -t
sudo systemctl reload nginx

若出现身份错判或限流异常,恢复此次改动涉及的备份配置,重新执行语法检查和重载,并重复验证。恢复配置不能撤销已经发生的业务操作,因此验证应从只读请求开始。

上线后保留访客地址和连接来源的可观测性,定期核对 CDN 网段变更,以及负载均衡是否改变了请求头规则。应用日志、Nginx 日志和限流使用同一套可信来源约定,后续故障才容易追踪到具体一层。

官方参考资料

资料核验日期:2026 年 10 月 14 日。Nginx 页面读取受网络影响,本次核验使用 Nginx 官方文档仓库中的对应源文件。

[1] Nginx:ngx_http_realip_module;官方文档源文件。模块、可信来源、递归规则与原始连接地址变量。

[2] Nginx:ngx_http_log_module;官方文档源文件。日志格式和配置上下文。

[3] Nginx:ngx_http_limit_req_module;官方文档源文件。按客户端地址设置限流的官方示例。

[4] Nginx:ngx_http_proxy_module;官方文档源文件。请求头设置与 XFF 追加变量。

[5] curl:--resolve 官方文档源文件。按主机名与端口指定连接地址。