适用场景
网站接入 CDN(阿里云 CDN、腾讯云 CDN、百度云加速等)后,源站防护的核心问题是:攻击者一旦通过历史 DNS 记录、证书透明度日志或邮件头扫描出源站真实 IP,就会绕过 CDN 直接发起 CC 攻击与漏洞扫描,CDN 层的所有防护规则全部失效。本方案通过 Nginx 层 IP 白名单,只允许CDN 回源节点的 IP 段访问 80/443 端口,直连源站的请求直接断开连接。
前置条件
- 已接入 CDN,且源站 IP 未暴露在公网 DNS 解析中(可用 CNAME 指向 CDN 域名)
- Nginx 1.10 及以上版本,拥有 root 或 sudo 权限
- 从 CDN 控制台获取官方公布的回源 IP 段列表(不要使用网上转载的旧列表)
原理说明
CDN 节点回源拉取内容时,TCP 连接的源地址必然属于 CDN 厂商公布的 IP 段。利用这一特征,在 Nginx 中通过 geo 模块对连接源 IP 做白名单判断:命中的请求正常转发,未命中的请求返回 444 状态码(Nginx 特有,直接断开连接不回包),使扫描器无法获得任何响应。相比 allow/deny ACL,geo 模块匹配在 access 阶段前完成,性能开销可忽略,且便于在多个 server 块中复用。
操作步骤
第一步:收集 CDN 回源 IP 段
登录 CDN 控制台,在「IP 清单」「回源节点」或帮助文档中下载回源 IP 段。以下以示例格式列出(实际以厂商控制台为准):
# 示例:阿里云 CDN 回源 IP 段(部分示意,务必以控制台最新列表为准)
163.171.0.0/16
147.138.0.0/17
118.107.0.0/16
第二步:配置 geo 白名单
在 http {} 层创建独立配置文件 /etc/nginx/conf.d/cdn_allow.conf:
geo $cdn_allowed {
default 0;
# CDN 回源 IP 段(以厂商控制台为准)
163.171.0.0/16 1;
147.138.0.0/17 1;
118.107.0.0/16 1;
# 本机与内网健康检查
127.0.0.1 1;
10.0.0.0/8 1;
172.16.0.0/12 1;
}
第三步:在 server 块中拦截直连请求
在业务 server 块的 80 与 443 监听中加入判断:
server {
listen 80;
server_name example.com;
# 非 CDN 回源 IP 直接断开
if ($cdn_allowed = 0) {
return 444;
}
# 正常业务配置 ...
location / {
proxy_pass http://127.0.0.1:8080;
}
}
server {
listen 443 ssl;
server_name example.com;
# SSL 证书配置 ...
if ($cdn_allowed = 0) {
return 444;
}
location / {
proxy_pass http://127.0.0.1:8080;
}
}
关键点:return 444 会静默断开连接,攻击者的扫描工具只会看到 connection reset,无法判断服务器类型;if 判断必须放在 server 块最顶部,避免与 location 内的 rewrite 规则冲突。若站点同时使用 HTTP/2,此规则同样生效,geo 判断发生在协议协商之后、请求处理之前。
第四步:处理证书暴露风险
即使 443 端口拦截了请求,攻击者直连源站 IP 时仍可通过 TLS 握手获取证书域名,确认这就是目标站点。建议给 443 监听配置一张默认占位证书:
server {
listen 443 ssl default_server;
ssl_certificate /etc/nginx/ssl/fake.crt;
ssl_certificate_key /etc/nginx/ssl/fake.key;
return 444;
}
使用 openssl req -x509 -nodes -newkey rsa:2048 -keyout fake.key -out fake.crt -subj "/CN=localhost" 一行生成自签占位证书即可。
配置验证
# 1. 检查配置语法
nginx -t
# 2. 重载配置
nginx -s reload
# 3. 直连源站 IP(应无响应或 connection reset)
curl -sv --resolve example.com:443:源站IP https://example.com/ -o /dev/null --max-time 5
# 4. 通过 CDN 域名正常访问(应返回 200)
curl -sI https://example.com/ | head -1
同时检查源站 Nginx 日志:tail -f /var/log/nginx/access.log,正常业务流量应全部来自 CDN IP 段。
常见问题
FAQ 1:CDN 厂商扩容新增回源节点后,部分用户访问报 502/504
原因是新增回源 IP 段未及时加入白名单。处理方法:定期(建议每月)从控制台重新拉取 IP 清单更新 geo 配置;同时监控 access.log 中出现 444 的源 IP,发现非白名单但流量特征正常的 IP 段立即核实是否为厂商新增节点。
FAQ 2:搜索引擎蜘蛛直连源站被封,影响收录吗
不影响。百度、Google 等主流搜索引擎蜘蛛抓取的是 DNS 解析结果,站点接入 CDN 后蜘蛛同样经由 CDN 节点回源,在白名单内。但需注意:蜘蛛曾经缓存过源站直连 IP 的极端情况(换 CDN 时),可通过蜘蛛 UA 日志确认,必要时临时放行验证 IP 段。
FAQ 3:宝塔面板等管理端口被误拦
geo 白名单只作用于配置了 if ($cdn_allowed = 0) 的 server 块。宝塔、SSH 等管理服务使用独立端口与独立 server 配置,不在拦截范围内,无需额外放行。
总结
源站防护是 CDN 体系中最容易被忽视的一环:CDN 上的 WAF 与限流规则再完善,源站 IP 暴露后一切归零。通过 geo 模块 + 444 静默断开,仅十几行配置即可把源站从公网可达收窄为 CDN 回源专用,配合占位证书隐藏域名信息,实现完整的回源链路收敛。运维侧重点在于CDN 回源 IP 段的定期更新与 444 日志监控,确保厂商扩容节点不引发误拦。