跳转到帖子

网站服务器接入 CDN 后的真实源站暴露排查与加固记录

精选回复

发布于

背景

最近帮一个中小型站点做授权安全检查,站点架构比较常见:域名接入 CDN,源站是一台云服务器,Nginx 反代 PHP-FPM,后台管理路径做了基础访问控制。客户的直观理解是“上了 CDN,源站 IP 就安全了”。但实际测试中发现,源站仍然可以被直接访问,并且绕过了 CDN 层的部分访问控制规则。

这个话题放在咖啡馆板块比较合适:它不是单纯漏洞复现,也不是工具使用,而是网站建设和服务器运维中很常见的安全边界问题。下面按一次真实排查流程展开,重点放在定位方法、配置检查、日志留痕和修复建议。

问题定位

授权范围内,先确认业务访问链路:

  • 公网用户访问: CNAME 到 CDN 厂商节点
  • CDN 回源到云服务器公网 IP
  • 源站 Nginx 根据 Host 分发到业务站点

初步检查发现两个异常点:

  • 直接访问源站公网 IP 时,仍然返回了业务首页。
  • 使用源站 IP 加 Host 头访问,可以完整访问网站,且响应头中看不到 CDN 注入的特征头。

这意味着攻击者一旦拿到源站 IP,就可以绕过 CDN 的 WAF、CC 防护、访问频控以及部分地域策略,直接打源站。

技术分析

源站暴露通常不是单点问题,常见原因有几类:

  • 历史 DNS 记录泄露,例如旧 A 记录、测试子域名、邮件记录。
  • 源站服务监听 0.0.0.0,且安全组允许全网访问 80/443。
  • Nginx 默认站点未限制,IP 访问也落到了业务 server 块。
  • 回源鉴权缺失,源站只认 Host,不校验 CDN 来源 IP 或自定义回源头。
  • 日志中没有区分 CDN 访问和直连访问,导致长期未发现。

这次的核心问题是:云安全组放行了 0.0.0.0/0 的 80、443,同时 Nginx 的 default_server 配置直接指向了业务站点。只要知道源站 IP,再带上正确 Host,就能绕过 CDN。

操作步骤

以下命令仅用于授权测试环境。先从客户端确认域名解析和访问链路:

dig  +short
curl -I 

# 测试源站 IP 是否可直接访问
curl -I 

# 带 Host 头访问源站,确认是否命中业务站点
curl -k -I  -H 'Host:  200、301、302,并且响应内容或 Location 指向真实业务路径,就需要继续看源站日志。

Nginx 默认日志如果只记录 remote_addr,在接入 CDN 后容易误判。建议临时增加一个更清晰的日志格式,把 Host、X-Forwarded-For、CDN 特征头都打出来。

log_format cdn_check '$remote_addr - $host [$time_local] '
                     '"$request" $status $body_bytes_sent '
                     'xff="$http_x_forwarded_for" '
                     'realip="$http_x_real_ip" '
                     'ua="$http_user_agent" '
                     'cdn_ray="$http_cf_ray" '
                     'via="$http_via"';

access_log /var/log/nginx/access_cdn_check.log cdn_check;

重新加载配置后观察直连请求和 CDN 请求的差异:

nginx -t && systemctl reload nginx

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

如果看到 remote_addr 是非 CDN 节点 IP,并且 Host 为业务域名,这类请求基本可以判断为直连源站。进一步可以统计最近一段时间是否已经存在绕过 CDN 的访问:

awk '{print $1}' /var/log/nginx/access_cdn_check.log | sort | uniq -c | sort -nr | head

grep ' /var/log/nginx/access_cdn_check.log \
  | grep -v 'cdn厂商IP段关键字或已知节点' \
  | tail -n 50

实际环境里不建议用 grep 简单排除 CDN IP 段做长期判断,更稳妥的是把 CDN 官方 IP 段维护成 allowlist,并在防火墙或 Nginx 层做限制。

关键配置示例

第一步,修正 Nginx 默认站点。不要让 IP 访问落到业务站点,可以直接返回 444 或固定的 403。

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;

    ssl_certificate     /etc/nginx/ssl/default.crt;
    ssl_certificate_key /etc/nginx/ssl/default.key;

    return 444;
}

第二步,在业务 server 块中限制来源。更推荐在云安全组或系统防火墙层面只允许 CDN 回源 IP 访问 80/443。Nginx 层可以作为补充,但不要把它当唯一边界。

# 示例:仅演示结构,实际 IP 段应以 CDN 厂商官方公布为准
geo $cdn_allowed {
    default 0;
    203.0.113.0/24 1;
    198.51.100.0/24 1;
}

server {
    listen 80;
    server_name 

    if ($cdn_allowed = 0) {
        return 403;
    }

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

第三步,如果 CDN 支持自定义回源 Header,可以增加一层轻量校验。注意这个 Header 不能暴露在前端响应中,也不要写得过于简单。

server {
    listen 80;
    server_name 

    if ($http_x_origin_verify != "change-this-to-a-long-random-value") {
        return 403;
    }

    location / {
        proxy_pass 
    }
}

这类 Header 校验不能替代 IP allowlist,因为 Header 可以伪造;但在“CDN IP 段更新滞后”或“多 CDN 回源”的场景下,它能提供额外防护。

日志留痕与排查重点

加固后建议至少观察 24 到 72 小时,重点看以下几类日志:

  • Nginx access 日志中是否仍有非 CDN IP 访问业务 Host。
  • Nginx error 日志中是否出现大量 403、444,判断是否有人在探测源站。
  • 云防火墙或安全组日志中是否有针对 80/443 的直连扫描。
  • 应用日志中是否存在异常后台路径访问、批量参数探测、异常 UA。

可以用一条简单命令查看被拦截的来源分布:

grep ' 403 ' /var/log/nginx/access_cdn_check.log \
  | awk '{print $1}' \
  | sort | uniq -c | sort -nr | head -20

如果在加固前已经发生过直连访问,建议回溯这些 IP 的请求路径。尤其关注:

  • /admin、/manage、/login 等后台入口。
  • /.env、/config.php、/backup、/sql、/zip 等敏感文件探测。
  • 带有明显注入、文件包含、路径穿越特征的参数。
  • 高频 POST 请求或异常 500 响应。

风险与修复建议

问题风险建议
源站 IP 可直接访问绕过 CDN 防护,直接消耗源站资源安全组仅允许 CDN 回源 IP,默认站点 return 444
Host 头即可命中业务攻击者可通过源站 IP 访问完整业务业务 server 限制来源,并校验回源 Header
日志未区分真实来源难以及时发现直连和绕过行为记录 XFF、Host、CDN 特征头,定期统计异常来源
历史解析记录泄露源站 IP 被动暴露清理旧 A 记录、测试域名,源站换 IP 后同步加固
个人经验:很多站点并不是被“打穿 CDN”,而是源站一直裸露在公网。CDN 只能保护经过它的流量,不能自动保护错误开放的源站端口。

总结

网站接入 CDN 后,真正要确认的是“用户是否只能通过 CDN 到达源站”。排查时不要只看 DNS 是否 CNAME 到 CDN,还要验证源站 IP、Host 头、默认站点、安全组和访问日志。比较稳的加固顺序是:先收敛云安全组,再修正 Nginx 默认站点,然后增加回源 Header 校验,最后通过日志持续观察。

这类问题不复杂,但很容易被忽略。对中小站点来说,把源站访问边界处理好,往往比堆很多上层安全策略更实际。

网络流量与边界分析示意图
网络请求、日志与边界流量分析示意

这类排查建议把“发现源站”和“阻断直连”分开做,很多站接了 CDN 但源站 80/443 仍然全网可达,后面再怎么隐藏 DNS 都不稳。

1)先确认是否存在直连源站特征

如果你已经怀疑某个 IP 是源站,可以用 Host 头直接验证,不要只看 IP 默认页:

curl -I --resolve example.com:443:1.2.3.4 
curl -I -H 'Host: example.com' 

重点看这几类差异:

  • Server、X-Powered-By、自定义响应头是否和 CDN 后一致;
  • 错误页样式是否是源站 Nginx/Apache 默认页;
  • TLS 证书是否包含业务域名,很多源站直接挂了同一张证书;
  • 静态资源路径、跳转 Location 是否暴露内部域名或真实 IP。

证书也建议查一下:

echo | openssl s_client -connect 1.2.3.4:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName

2)从日志里反向确认是否有人绕 CDN 打源站

Nginx 访问日志里如果 remote_addr 不是 CDN 节点 IP,却带着正常业务 Host,基本就说明源站已经被扫到或被直连访问了。可以临时统计:

awk '$1 !~ /^(CDN_IP段正则)/ {print $1,$7,$11}' /var/log/nginx/access.log | head
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -30

如果用了 real_ip_header,注意不要被伪造的 X-Forwarded-For 误导。源站只应信任 CDN 出口 IP 段:

set_real_ip_from  203.0.113.0/24;
set_real_ip_from  198.51.100.0/24;
real_ip_header    X-Forwarded-For;
real_ip_recursive on;

这里的 IP 段要换成你 CDN 厂商官方公布的段,并且定期更新。

3)源站侧直接做访问控制,不要只靠“域名不解析”

最有效的是安全组/防火墙只放行 CDN 回源 IP,其他全部拒绝。Linux 上可以先用 ipset 管理,避免规则太长:

ipset create cdn hash:net

ipset add cdn 203.0.113.0/24
ipset add cdn 198.51.100.0/24

iptables -I INPUT -p tcp -m multiport --dports 80,443 -m set --match-set cdn src -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j DROP

如果是云服务器,优先在云安全组做,源站本机防火墙作为第二层。否则攻击流量已经打到主机网卡了。

4)Nginx 层再加一道 Host 校验

即使放行 CDN,也建议默认 server 不返回业务内容,防止通过 IP 或异常 Host 命中站点:

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    return 444;
}

server {
    listen 80;
    listen 443 ssl;
    server_name example.com 

    # 正常业务配置
}

如果 CDN 支持自定义回源头,可以在源站校验一个固定 header,降低被人伪造 Host 直连的风险:

if ($http_x_origin_token != "your_random_token_here") {
    return 403;
}

这个不能替代 IP 白名单,但作为补充有用,尤其是 CDN IP 段较大、同厂商其他用户也能回源的场景。

5)容易遗漏的暴露点

  • 历史 DNS 记录:旧 A 记录、测试域名、origin.example.com 这类子域;
  • 邮件头、错误堆栈、监控探针返回内容里暴露内网/公网 IP;
  • 对象存储回调、支付回调、Webhook 配置里直接写了源站 IP;
  • 证书透明日志里暴露了源站专用域名;
  • IPv6 忘记接 CDN,只限制了 IPv4。

最后建议做一次外部视角验证:找一台非本机、非 CDN 节点的机器直接访问源站 IP,确认 80/443 无法拿到业务页面;再从 CDN 正常访问,确认回源不受影响。这个闭环比单纯扫 DNS 记录可靠得多。

补一个容易漏的点:源站不只是 80/443,很多“暴露”其实来自旁路端口或历史解析。 我一般会再查这几类: 1)检查源站是否还有管理端口、备用端口开放 比如 8080、8443、8000、9000、9200、5601、3306、6379 这类,CDN 只代理 Web,但源站安全组没收口。
nmap -Pn -sS -sV --top-ports 1000 1.2.3.4

# 针对常见 Web 备用端口
nmap -Pn -sV -p 80,443,8080,8081,8000,8443,8888,9000 1.2.3.4
如果这些端口存在 Web 服务,也要带 Host 头测,不然默认页不一定能看出来:
curl -I -H 'Host: example.com' 
curl -k -I --resolve example.com:8443:1.2.3.4 

2)查历史 DNS 和子域名  
很多源站不是当前 A 记录暴露,而是以前的解析、测试域名、回源域名没清。

可以重点看这些记录:

- 历史 A 记录;
- dev、test、staging、origin、admin、api 等子域;
- 邮件、监控、对象存储回调里引用的域名;
- Git 仓库、前端 JS、配置文件里硬编码的源站地址。

本地可以先简单搜一下前端静态资源:

wget -r -l1 -nd -A js  -P /tmp/jscheck

grep -RniE "([0-9]{1,3}\.){3}[0-9]{1,3}|origin|staging|internal| /tmp/jscheck
3)加固时不要只靠 Nginx 判断 Host Host 校验能挡一部分误访问,但真正有效的还是网络层只允许 CDN 回源 IP。 如果用的是云主机,优先在安全组做白名单;如果只能在机器上做,可以用 ipset 管 CDN IP 段,避免 iptables 规则太长。 示例:
ipset create cdn hash:net

# 示例,实际替换为 CDN 官方回源 IP 段
ipset add cdn 203.0.113.0/24
ipset add cdn 198.51.100.0/24

iptables -A INPUT -p tcp -m multiport --dports 80,443 -m set --match-set cdn src -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j DROP
如果是 Nginx,也建议同时加一层 Host 白名单,避免 CDN 被配置错误或被拿来泛域名回源:
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    return 444;
}

server {
    listen 443 ssl;
    server_name example.com 

    # 正常业务配置
}
4)日志里确认是否还有直连流量 加固前后都建议看一下源站 access log,直接访问源站的请求通常会有几个特征: - remote_addr 不是 CDN 回源 IP; - Host 是 IP、陌生域名或空; - User-Agent 很杂,常见扫描器较多; - 请求路径集中在 /.env、/phpinfo.php、/admin、/wp-login.php 等。 可以临时跑一下:
awk '{print $1,$7,$9,$12}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -50
如果 Nginx 有记录 Host:
awk '{print $1,$2,$7,$9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -100
5)注意 CDN 回源 IP 变化 不少故障都是白名单写死后,CDN 厂商扩容或区域切换导致回源失败。最好把 CDN 官方 IP 段做成定时更新,并在更新后 reload 防火墙规则。至少要有监控,发现 5xx 或回源失败能及时告警。 最后一个经验:如果业务允许,源站证书可以不要直接使用公网业务证书,改成 CDN 到源站专用证书,或者启用 CDN 的 Authenticated Origin Pull / 回源 mTLS。这样即使源站 IP 被扫到,也不能简单通过 HTTPS Host 直连拿到完整业务响应。

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

最近浏览 0

  • 没有会员查看此页面。

SiteMap HACKHAT © 2026 All rights reserved.