高防、CDN、WAF 层层叠加,防护链路本身也会出故障,越叠单点越多。本文用 10 个问答讲清故障点在哪、怎么 bypass 回源、源站怎么留直连预案。
Q:为什么说防护设备本身成了新的单点?
- 没上防护时,单点是源站。上了高防、CDN、WAF 之后,单点变成四五个:DNS 调度、边缘节点、清洗中心、回源链路、证书与规则配置。
- 每一层都能把整站拖死:边缘节点异常返回 5xx,清洗中心故障丢包,证书过期全站握手失败,规则写错把自己人全拦掉。
- 从事故统计看,配置类故障远多于硬件故障。所以防护链路的第一预案不是「换节点」,而是「能把自己加的那条规则干净地摘掉」。
- 衡量标准很直白:这条链路能不能在 5 分钟内被完整绕开,且绕开之后源站不会裸奔。
Q:防护链路常见故障点分哪几类?
- 调度层:DNS 解析错误、TTL 太长切不动、CNAME 指到了已过期的加速域名。
- 边缘层:节点回源失败、缓存规则把动态页缓存了、证书到期或证书链不全。
- 清洗层:节点被大流量攻击后整段丢包、防护阈值被误设成极低值、独享带宽被打满。
- 回源层:源站只放行 CDN 段,而 CDN 回源段变更后没同步,全站 403;或者回源 Host 配错,请求落到默认站点。
- 配置层:WAF 规则误拦、限流阈值写错、人机验证全量开启、挑战页把正常浏览器也卡住。
- 五类里前三类要等厂商,后两类基本靠自己。所以先分清归属,再决定要不要切换。
Q:怎么在 5 分钟内确认是不是防护链路的锅?
- 四个命令,一步分清源站问题还是防护问题。
# 1) 直连源站,绕开 CDN(源站 IP 只在运维机可见)
curl -sS -o /dev/null -w "origin %{http_code} %{time_total}s\n" \
--resolve www.example.com:443:10.0.0.12 https://www.example.com/
# 2) 走 CDN 正常访问
curl -sS -o /dev/null -w "cdn %{http_code} %{time_total}s\n" \
https://www.example.com/
# 3) 看响应头是谁回的、缓存是否命中
curl -sSI https://www.example.com/ | grep -Ei "server|via|x-cache|age|cf-"
# 4) 证书是否过期
echo | openssl s_client -connect www.example.com:443 \
-servername www.example.com 2>/dev/null | openssl x509 -noout -dates
- 结果对照:源站 200 而 CDN 5xx,问题在边缘或回源配置;两边都 5xx,源站自己挂了;两边都超时,网络或 DNS;握手直接失败,证书问题。
- 这一步做完,至少不会在错误的方向上折腾一小时。
Q:CDN 或高防节点出问题,怎么 bypass 回源?
- 三条路径,按可逆性从好到差排:
- 切备用 CNAME:域名同时挂两个加速域名,故障时把 CNAME 指到备用。最快,但完全依赖 DNS TTL。
- 切备用源站:主源站不可用时改回源地址,或者先切到对象存储上的静态兜底页,把主流程保住。
- 直接摘掉加速:把域名 A 记录指回源站。最后手段,因为源站会直接暴露,必须配合限流和放行名单。
- 前提条件只有一个,但最常被忽略:TTL 必须提前降到 60 秒。TTL 还是 3600 时,所有切换预案都是纸上预案。
# 切换前先确认当前 TTL 和解析链
dig +noall +answer www.example.com A
dig +noall +answer www.example.com CNAME
# 提前把 TTL 降下来(在域名服务商侧操作,生效需要等一个旧 TTL 周期)
# 建议平时就固定 60 秒,别等出事再改
Q:源站怎么保留直连能力,又不至于裸奔?
- 三件事平时就要做好,出事才有得选:
- 源站自己也有限流。不要因为有了 WAF 就把源站的
limit_req关掉。bypass 时源站能靠自己的闸门扛住第一波。 - 放行名单能临时扩容。CDN 回源段、运维跳板机写进独立文件,切换时只改这个文件,改完
nginx -t再 reload。 - 备用入口不公开。备用 IP 与备用二级域名只在内网或运维机可见,不写进工单、不贴进聊天群。
# /etc/nginx/conf/allow_origin.conf —— 只放行 CDN 回源段与运维机
allow 203.0.113.0/24; # CDN 回源段 A
allow 198.51.100.0/24; # CDN 回源段 B
allow 192.0.2.10; # 运维跳板机
deny all;
# server 块内引用
include /etc/nginx/conf/allow_origin.conf;
# 源站兜底限流,与 WAF 独立,bypass 后仍然生效
limit_req zone=cc_norm burst=40 nodelay;
limit_conn cconn 30;
limit_req_status 429;
- 顺序注意:
allow/deny要放在location的最前面,别被后面的return或try_files抢先执行。 - 再加一条:源站不要对公网暴露 SSH 以外的管理端口,bypass 期间最怕的是攻击者顺着备用入口摸到后台。
Q:怎么提前发现防护链路在劣化?
- 别只信厂商控制台上的绿点。自己做外部拨测,并且把结果落成时序,看趋势。
#!/bin/bash
# /usr/local/bin/probe.sh —— 每分钟落一行,异常就告警
for u in "https://www.example.com/" "https://www.example.com/healthz"; do
out=$(curl -s -o /dev/null -m 5 -w "%{http_code} %{time_total}" "$u")
echo "$(date +%FT%T) $u $out"
done >> /var/log/probe.log
- 四个劣化信号:P95 缓慢抬升、缓存命中率下降、5xx 占比上升、同一域名在不同节点解析结果来回跳。
- 告警要按分钟级,不要按小时。链路类故障从「有感觉」到「全站不可用」往往只有几分钟。
Q:bypass 演练怎么做才算真的有效?
- 季度一次,选低峰时段,提前通知业务方,全程限时。
- 四步:摘掉 CDN 改成直连源站,压 200 QPS 看源站是否扛住,恢复链路,记录耗时。
- 验收标准:切换在 5 分钟内完成,bypass 期间错误率低于 1%,业务方无感知。
- 演练最容易暴露的三件事:TTL 没降、放行名单漏了新加的运维机、没人记得源站 IP 到底是多少。
Q:采购时 SLA 要看哪几条?
- 别只盯防护峰值。下面几条才决定出事时能不能活下来:
- 节点故障的响应与赔偿:有没有明确的可用性承诺和赔付比例,还是只有一句「尽力保障」。
- 切换协助:故障时有没有技术对接人,响应时限是多少。
- 回源灵活性:是否支持自定义回源端口、Host、多源站。不支持,出事时你连切都切不了。
- 日志可导出:原始访问日志能不能导出,没有日志就没法定位,也无法复盘。
- 备份节点:同一家厂商是否能指定异地节点,同一家全挂的情况并不罕见。
Q:层数叠得越多越安全吗?
- 不是。每多一层,多一个故障点、多一段排查路径、多一份配置漂移的可能。
- 中小站两到三层足够:CDN 加 WAF 兜住七层,高防兜住四层,源站自己有限流。
- 层与层之间要有明确的职责,别让三层都做同一件事。职责重叠的直接后果是出事时分不清是谁拦的。
- 每层响应头打一个来源标记,例如
X-Block-By: edge,投诉时一眼知道该去哪个控制台查。
Q:还有什么补充建议?
- 把「任意一层能被摘掉」当成设计目标。凡是摘不掉的层,都是单点,迟早会教你做人。
- 所有配置变更走同一套流程:改前备份、改后
nginx -t、变更留记录。多数「防护把自己打死」的事故,都发生在凌晨的一次手改。 - 维护一个联系清单:CDN 工单入口、高防对接人、域名服务商、机房值班电话。出事时最贵的成本是找电话。
- 最后一句:防护的价值不只是挡攻击,还包括它自己出问题时,你的业务还能活着。