发布于1小时前1小时 背景网站接入 CDN、云加速器或反向代理后,常见架构是“客户端 → CDN/WAF → 负载均衡 → Nginx 源站”。这类改造能提升访问速度和抗压能力,但也容易引入三个实际问题:源站仍可被直接访问、客户端 IP 可通过请求头伪造、边缘与源站日志无法关联。下面以一次授权测试中的典型场景为例:业务域名已经接入 CDN,管理后台按客户端 IP 做访问限制,源站 Nginx 使用 X-Forwarded-For 获取真实地址。测试发现,修改请求头后可以绕过后台限制,同时使用历史解析记录中的源站地址能够直接访问站点,导致 CDN 上的限速和 WAF 规则失效。以下命令中的域名、地址均为示例。验证应在明确授权的业务、测试源地址和时间窗口内进行,避免对生产缓存及访问控制造成影响。问题定位排查时不要先盯着单条 WAF 告警,应先画清实际链路,并确认每一跳由谁写入、追加或信任转发头。重点核对以下内容:DNS 当前解析、历史地址及源站证书是否暴露真实入口。源站 80、443 端口是否允许任意公网地址连接。Nginx 是否把 0.0.0.0/0 配置成可信代理。CDN、负载均衡是否覆盖客户端传入的 X-Forwarded-For、X-Real-IP。源站访问控制使用的是 TCP 对端地址,还是经过 realip 模块重写后的地址。边缘层和源站是否保留统一的请求 ID。先在源站确认监听情况、编译模块和最终生效配置。nginx.conf 中看起来正确,并不代表 include 后的完整配置正确。ss -lntp | grep -E ':80|:443' nginx -V 2>&1 | grep -o http_realip_module nginx -T 2>&1 | grep -nE 'listen|server_name|real_ip|set_real_ip_from|X-Forwarded-For|allow|deny' nft list ruleset 技术分析一:错误信任转发头高风险配置通常类似下面这样:set_real_ip_from 0.0.0.0/0; real_ip_header X-Forwarded-For; real_ip_recursive on; 这相当于把所有访问者都当成可信代理。攻击者直接连接源站或经过不会清洗请求头的上游时,可以自行构造 X-Forwarded-For。Nginx 的 $remote_addr 经过 realip 模块处理后可能变成伪造地址,基于它实现的后台白名单、限速、审计和封禁都会失去可靠性。需要区分两个变量:$remote_addr:启用 realip 后,通常表示解析得到的客户端地址。$realip_remote_addr:保存建立 TCP 连接的原始对端地址,适合确认请求实际上来自哪个 CDN 节点或负载均衡。在“客户端 → CDN → 内部负载均衡 → Nginx”的多跳架构中,源站只能信任已确认的 CDN 出口网段和内部负载均衡网段。不能为了兼容多跳直接信任全网。技术分析二:源站直连绕过即使真实 IP 配置正确,只要源站公网端口对任意地址开放,访问者仍可能通过源站 IP 绕开 CDN。仅修改 Host 头或使用本地解析即可验证这一点:# 仅从已登记的授权测试地址执行 curl -skI --resolve site.example:443:192.0.2.10 # 对比正常 CDN 路径 curl -skI 如果两个请求都返回相同业务内容,说明源站缺少网络层或应用层入口限制。需要进一步比较响应头、证书、缓存标记和日志中的 TCP 对端地址,避免把 CDN 回源地址误判为真实源站。默认虚拟主机返回 444 可以减少直接扫 IP 时的信息暴露,但不能替代源站防火墙。只要访问者知道正确的域名并携带对应 SNI 和 Host,仍可能命中正式站点。操作步骤:建立可关联的日志链路先补齐日志字段,再做修复验证。建议源站同时记录原始对端、解析后的客户端地址、转发链、请求 ID、Host、上游耗时和状态码。log_format origin_trace '$time_iso8601 rid=$http_x_request_id ' 'peer=$realip_remote_addr client=$remote_addr ' 'xff="$http_x_forwarded_for" host="$host" ' 'request="$request" status=$status bytes=$body_bytes_sent ' 'rt=$request_time ua="$http_user_agent"'; access_log /var/log/nginx/origin_trace.log origin_trace; 边缘代理应覆盖而不是盲目信任客户端提交的请求 ID。自建 Nginx 边缘层可以这样传递:proxy_set_header X-Request-ID $request_id; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; 若使用云 CDN,应确认控制台是否支持覆盖 X-Request-ID 或使用厂商提供的唯一请求标识。不要直接把外部传入的任意字符串当成审计主键,否则可能出现日志混淆。验证时发送一个唯一请求,然后在边缘和源站按请求 ID 检索:RID=test-20250308-001 curl -sk \ -H "X-Request-ID: ${RID}" \ -H 'X-Forwarded-For: 198.51.100.77' \ -o /dev/null -D - grep 'rid=test-20250308-001' /var/log/nginx/origin_trace.log 如果边缘层正确覆盖请求 ID,上述客户端自定义值不应原样成为可信关联字段。若测试环境暂时允许透传,则至少要结合时间、URI、边缘日志和 TCP 对端共同判断。操作步骤:正确配置真实 IP下面是源站直接接收 CDN 回源流量时的示例。示例网段必须替换为 CDN 官方公布并经过核验的出口网段:# 只信任真实存在的 CDN 回源地址 set_real_ip_from 203.0.113.0/24; set_real_ip_from 2001:db8:100::/48; real_ip_header X-Forwarded-For; real_ip_recursive on; 如果源站前还有内部负载均衡,需要同时信任负载均衡网段,并确认它不会接受任意公网流量:set_real_ip_from 10.20.0.0/16; set_real_ip_from 203.0.113.0/24; real_ip_header X-Forwarded-For; real_ip_recursive on; 不要把 PROXY Protocol 和普通 X-Forwarded-For 混在一起试错。只有负载均衡明确发送 PROXY Protocol 时,源站才能使用 listen 443 ssl proxy_protocol 和 real_ip_header proxy_protocol;否则会直接导致 TLS 请求失败。配置修改后应先执行 nginx -t,再灰度重载。nginx -t && nginx -s reload 操作步骤:限制源站入口优先在安全组、防火墙或负载均衡监听器上限制源站 80、443,只允许 CDN 回源网段和必要的健康检查地址。应用层限制可以作为补充,但不应是唯一防线。如果短期内无法调整网络策略,可以基于原始 TCP 对端增加临时保护。这里使用 $realip_remote_addr,而不是可能已被改写的 $remote_addr:geo $realip_remote_addr $edge_peer_ok { default 0; 203.0.113.0/24 1; 2001:db8:100::/48 1; 10.20.0.0/16 1; } server { listen 443 ssl; server_name site.example; if ($edge_peer_ok = 0) { return 403; } location / { proxy_pass } } 这里的 if 只执行 return,行为相对明确。长期方案仍应放到网络层,避免 Nginx 配置遗漏某个虚拟主机或新端口。同时配置默认虚拟主机,减少错误 Host 和直接扫 IP 的信息暴露:server { listen 80 default_server; server_name _; return 444; } server { listen 443 ssl default_server; server_name _; ssl_certificate /etc/nginx/tls/default.crt; ssl_certificate_key /etc/nginx/tls/default.key; return 444; } 修复后的验证方法从正常公网访问业务域名,确认 CDN 路径可用,源站日志中的 peer 为 CDN 或负载均衡地址。携带伪造 X-Forwarded-For 请求,确认 client 不会被错误解析为攻击者指定的白名单地址。从授权测试地址直连源站,预期在网络层超时或被拒绝,而不是返回正式业务页面。检查后台白名单、Nginx limit_req、应用审计使用的地址字段是否一致。抽取同一请求 ID,对比 CDN、负载均衡、Nginx 和应用日志,确认状态码与时间线能够闭环。检查 IPv6。很多环境只限制了 IPv4 源站地址,却保留了可直连的 AAAA 记录或 IPv6 安全组规则。风险与修复建议最高优先级:在网络层关闭源站公网直连,仅允许 CDN、负载均衡和健康检查网段。最高优先级:删除 set_real_ip_from 0.0.0.0/0,只信任经过核验的代理地址。高优先级:由最外层可信代理覆盖客户端可控的真实 IP 头和请求 ID。高优先级:管理后台不要只依赖源 IP,至少叠加身份认证、MFA 和独立访问入口。中优先级:同步维护 CDN IPv4、IPv6 网段。自动更新脚本应先校验数据格式和变更范围,不要直接 curl 后覆盖生产配置。中优先级:保留 peer、client、X-Forwarded-For 和请求 ID,设置合理的日志留存及时间同步。中优先级:检查缓存键是否包含正确的 Host、URI 和必要查询参数,避免不同站点或权限响应共享缓存。总结CDN 和反向代理上线后,真正需要关注的不是“页面是否加速”,而是入口边界和信任链是否发生变化。源站防火墙决定谁能连接,realip 配置决定谁有资格声明客户端地址,日志字段决定事后能否还原链路。这三部分缺少任何一项,都可能让 WAF、限速、后台白名单和审计产生错误结论。比较稳妥的处理顺序是:先补日志并确认实际链路,再收紧可信代理范围,最后封闭源站直连并完成旁路验证。这样既能减少业务中断,也能让每一步修复都有明确证据。 网络请求、日志与边界流量分析示意 服务器、云资产与权限边界梳理示意
52分钟前52分钟 这类问题建议把“源站是否能被绕过”和“日志里的客户端 IP 是否可信”分开查。接了 CDN 不等于源站已隔离,日志里出现公网 IP 也不代表取值正确。 先验证源站入口是否真的收口。在自有或授权环境下,从非 CDN 网络直连源站,保留域名的 Host 和 TLS SNI: curl -sv --connect-timeout 5 \ --resolve ' \ -o /dev/null 如果仍能拿到业务页面,说明至少这个入口可以绕过 CDN。除了 IPv4,还要检查 IPv6、安全组、备用端口,以及直接暴露的反向代理节点。纯 CDN 回源架构下,公网入口只允许 CDN 官方回源网段;若源站前还有独立反代,源站则只允许反代访问。需要更强约束时加回源 mTLS,不能只靠隐藏 IP 或检查 Host。 真实 IP 要从第一个可信入口开始处理,不能直接相信请求自带的 X-Forwarded-For。以 CDN → Nginx 反代 → 源站为例,反代只信任 CDN 网段,解析完成后向源站覆盖写入客户端 IP: # 放在 CDN 后面的 Nginx;网段必须换成服务商官方列表并持续更新 set_real_ip_from 192.0.2.0/24; # 仅为文档示例,不能照抄上线 real_ip_header X-Forwarded-For; real_ip_recursive on; location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Request-ID $request_id; proxy_pass } 这里用覆盖而不是追加,是为了让源站接收到一条明确、受控的客户端地址;完整来路留在入口日志里。前提是 CDN 确实会按官方规则清洗或追加该头;如果服务商提供专用客户端 IP 头,应按其文档配置。源站只信任反代地址,业务代码不要再自行取 XFF 最左项。 日志同时保留“解析后的客户端”和“实际连接对端”。启用 realip 后,$remote_addr 已可能被改写,连接对端要看 $realip_remote_addr: log_format chain escape=json '{"time":"$time_iso8601","rid":"$request_id",' '"client":"$remote_addr","peer":"$realip_remote_addr",' '"xff":"$http_x_forwarded_for","status":"$status",' '"upstream":"$upstream_addr","urt":"$upstream_response_time"}'; access_log /var/log/nginx/chain.log chain; 最后补一次伪造头测试:经过 CDN 请求时手动加 X-Forwarded-For: 1.2.3.4,确认入口解析出的客户端及源站日志不会被改成这个值。再用同一个入口生成的请求 ID 串起反代和应用日志;源站应记录收到的 ID,而不是重新生成,否则排查时很容易把两次请求对错。
创建帐户或登录后发表意见