发布于11小时前11小时 背景:加速生效,不代表源站已经收口网站建设里很常见的一种部署是:域名接入 CDN,回源到一台运行 Nginx 的服务器,Nginx 再转发给本机应用。页面访问速度正常,证书也没有报错,于是大家默认公网流量已经全部经过 CDN。但在授权检查中,需要单独验证一个问题:知道源站地址后,是否还能绕过 CDN,直接访问相同站点?如果可以,CDN 上配置的限速、访问控制和部分防护规则,就不再是这个网站唯一的入口边界。本文只讨论自有或明确授权的网站服务器。示例域名为 198.51.100.20,地址均为文档示例,操作时需替换为自己的测试资产。问题定位:先区分访问路径,再看响应状态不要只检查域名是否解析到了 CDN。DNS 只能说明正常解析路径,不能证明源站拒绝了其他路径。建议先对照三类请求:正常通过 CDN 访问站点,确认业务可用。保持相同域名和 TLS SNI,直接连接源站,确认入口是否受限。直接连接源站,同时伪造客户端地址头,检查是否错误地把请求头当成访问凭据。测试路径可以使用站点已有的轻量健康检查接口。避免选取下单、发信等有业务副作用的接口。# 1. 正常访问:经过域名当前解析路径 curl --noproxy '*' -sS -o /dev/null -D - \ # 2. 固定连接源站,但仍使用正确的 Host 和 TLS SNI curl --noproxy '*' --connect-timeout 5 \ --resolve \ -sS -o /dev/null -D - # 3. 检查伪造来源头是否影响源站准入 curl --noproxy '*' --connect-timeout 5 \ --resolve \ -H 'X-Forwarded-For: 192.0.2.10' \ -sS -o /dev/null -D - -k。前者可能落到错误的虚拟主机,后者会掩盖证书问题。使用 --resolve 可以在不修改公共 DNS 的情况下,保留正常的域名校验和站点选择。如果源站使用仅供 CDN 校验的源站证书,应通过 --cacert 指定相应可信 CA。证书校验失败本身不能证明入口已封闭。技术分析:连接来源和访客地址是两回事接入 CDN 后,源站看到的 TCP 连接对端通常是 CDN 节点。访客地址则通过约定的 HTTP 头传递。前者用于判断“谁可以连接源站”,后者主要用于业务日志和访客维度的限流。常见配置错误是把 set_real_ip_from 写成 0.0.0.0/0,允许任意连接方提供可信客户端地址。另一个容易忽略的问题是:启用 realip 模块后,$remote_addr 可能已经变成还原后的访客地址,不能再不加区分地用它判断连接是否来自 CDN。Nginx 的 $realip_remote_addr 保留 realip 改写前的地址,可用于核对直接连接来源。下面给出一个应用层兜底配置;网络层仍应优先限制入口。操作步骤:收紧信任来源,并保留两层地址先确认 Nginx 带有 realip 模块:nginx -V 2>&1 | grep -- --with-http_realip_module以下内容放在 http 上下文。192.0.2.0/24 只是配置格式示例,必须替换为 CDN 官方发布的真实回源网段;如果 CDN 提供更小范围的专用回源地址,应优先采用。使用 X-Forwarded-For 前,也要确认服务商的覆盖、追加与清洗规则。# http 上下文 set_real_ip_from 192.0.2.0/24; real_ip_header X-Forwarded-For; real_ip_recursive on; # 判断改写前的连接对端,而不是还原后的访客地址 geo $realip_remote_addr $origin_peer_allowed { default 0; 192.0.2.0/24 1; } # 不记录查询串,降低令牌等敏感参数进入日志的概率 log_format origin_audit escape=json '{"time":"$time_iso8601",' '"request_id":"$request_id",' '"peer":"$realip_remote_addr",' '"client":"$remote_addr",' '"host":"$host",' '"method":"$request_method",' '"uri":"$uri",' '"status":$status,' '"origin_peer_allowed":$origin_peer_allowed,' '"request_time":$request_time}';在已有 HTTPS 站点的 server 块中加入以下内容,保留原来的证书和业务配置。此处 if 只执行 return,不涉及复杂重写。# 加入目标站点已有的 server 块 access_log /var/log/nginx/origin_audit.log origin_audit; if ($origin_peer_allowed = 0) { return 403; } # 原有 location /、proxy_pass 等业务配置保持不变部署前,先核对健康检查、证书续期、监控探测是否也经过 CDN。确有直连需求时,为其设计独立入口和明确的来源限制,不要为了让探测变绿而重新允许所有地址。# 先检查语法,再平滑加载 sudo nginx -t && sudo systemctl reload nginx # 查看被应用层入口规则拦截的请求 sudo tail -n 100 /var/log/nginx/origin_audit.log \ | jq -c 'select(.origin_peer_allowed == 0) \ | {time, peer, client, host, uri, status}'验证结果:不能只看一个 403正常 CDN 请求应保持可用,日志中的 peer 应属于预期回源网段,client 应符合服务商的真实地址传递规则。非白名单地址直连源站,应在网络层被拒绝,或被 Nginx 返回 403,不能返回正常业务内容。伪造 X-Forwarded-For 后,直连请求仍应失败,不能因为头部内容变化获得准入。对照时间、路径和源站日志确认拦截位置。CDN 返回的 403、应用自身返回的 403,都不能直接证明源站入口规则生效。如果已经在云安全组或防火墙阻断直连,测试请求不会进入 Nginx,此时没有访问日志是正常现象。应结合安全组命中记录、流日志或短时受控抓包核验,不要为了得到一条 Nginx 日志而放开入口。风险与修复建议优先在安全组或防火墙中限制源站 80/443 的连接来源,IPv4 和 IPv6 都要检查。只收紧 IPv4,而 IPv6 仍开放,是常见遗漏。检查应用端口是否仍对公网监听,例如 8080、8000。即便 Nginx 已收口,直接暴露的后端仍可能成为另一条入口。逐一核对同一地址上的默认站点、其他 server_name 和其他监听端口。只修改一个业务 server 块,不等于整台服务器已经收口。CDN 网段白名单只能证明请求来自服务商网络,不能必然证明来自自己的 CDN 配置。服务商支持时,应增加回源 mTLS 等身份校验,并确认凭据的隔离范围。回源网段需要维护。自动更新时,应校验下载结果非空、变更范围合理,并保留上一版配置;测试通过后再加载,避免错误更新造成全站中断。日志不要默认采集 Cookie、Authorization 或完整查询串。即便只记录 URI,路径中也可能含有敏感标识,仍需设置访问权限和合理保留周期。总结给网站接入 CDN,解决的是正常访问路径上的加速与防护问题;限制源站入口,解决的是其他路径能否绕过去的问题。这两件事需要分别验证。实际落地时,至少保留三项可复查证据:正常 CDN 访问成功、非授权直连失败、连接来源与访客地址能够在日志中区分。做到这一步,后续讨论限速、防护规则和异常流量,才有可靠的入口边界作为基础。 网络请求、日志与边界流量分析示意 服务器、云资产与权限边界梳理示意
10小时前10小时 接了 CDN 只代表正常流量经过 CDN,不等于源站入口已经收口。排查时建议把“网络边界”和“Nginx 对真实来源的识别”分开看,否则日志里很容易把客户端 IP、CDN 节点 IP 混在一起。 先确认源站实际暴露面: ss -lntup nft list ruleset # 使用 iptables 的机器 iptables -S ip6tables -S # 同时检查云平台安全组、IPv6 入站规则 curl -4 ifconfig.me curl -6 ifconfig.me 常见遗漏是只限制了 IPv4 的 80/443,但 IPv6、8080、8443 或面板端口仍可直连。云安全组和系统防火墙也要同时检查,不能只改其中一层。 已知源站 IP 时,可以从外部验证是否能绕过 CDN: curl -vk --resolve example.com:443:源站IP curl -v -H 'Host: example.com' 如果能拿到正常站点响应,说明源站仍接受公网直连。只靠 Nginx 的 server_name 或默认站点拦截不够,因为请求者可以自行设置 Host/SNI。更可靠的做法是: 安全组或防火墙仅允许 CDN 官方回源网段访问 80/443; SSH、管理端口只允许固定运维 IP 或内网/VPN; 条件允许时启用 CDN 的回源 mTLS(Authenticated Origin Pull); CDN 网段需要自动同步,避免网段变更后误封回源。 Nginx 日志建议同时记录连接对端和还原后的客户端地址: log_format edge '$time_iso8601 ' 'client=$remote_addr ' 'peer=$realip_remote_addr ' 'host=$host request="$request" status=$status ' 'xff="$http_x_forwarded_for" ' 'ua="$http_user_agent" rt=$request_time'; access_log /var/log/nginx/access.log edge; 配置 real IP 时,必须只信任 CDN 回源网段,不能直接对全网信任 X-Forwarded-For: # 以下网段仅为格式示例,应替换为 CDN 官方公布的回源地址 set_real_ip_from 192.0.2.0/24; set_real_ip_from 2001:db8:1234::/48; # 按 CDN 实际提供的头选择,例如 CF-Connecting-IP、True-Client-IP real_ip_header CF-Connecting-IP; real_ip_recursive on; 如果写成 set_real_ip_from 0.0.0.0/0,直连源站的人可以伪造请求头污染日志,基于 IP 的限速、封禁和后台白名单也可能被绕过。 日志排查可以先看连接对端是否都是 CDN 节点,以及异常 URI、状态码和请求耗时: # 统计连接对端 awk '{ for (i=1;i<=NF;i++) if ($i ~ /^peer=/) {sub(/^peer=/,"",$i); print $i} }' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -30 # 常见扫描路径 grep -E '(\.\./|/\.env|/wp-login|/phpmyadmin|/actuator|/vendor/phpunit)' \ /var/log/nginx/access.log | tail -100 # 汇总状态码 awk '{ for (i=1;i<=NF;i++) if ($i ~ /^status=/) {sub(/^status=/,"",$i); print $i} }' /var/log/nginx/access.log | sort | uniq -c | sort -nr 如果日志中的 peer 出现非 CDN 地址,基本可以确认存在直连;如果全部是 CDN 节点,但攻击请求仍很多,则应继续检查 CDN 是否只是代理而没有启用 WAF、速率限制,或者缓存规则是否导致动态接口直接回源。 另外还要检查历史 DNS、旧的 A/AAAA 记录、证书透明度记录、邮件头和其他子域是否泄露源站 IP。更换源站 IP 只能作为泄露后的补救,最终还是要靠安全组/CDN 回源认证把入口真正收紧。
创建帐户或登录后发表意见