网站接入CDN后无法访问怎么办?回源、DNS与证书排查方法

一个很常见的场景:网站本来在源站上跑得好好的,出于提速考虑接入了 CDN,配置改完刷新后,网站反而打不开了——有的报 403、有的报 502、有的直接转圈超时、有的浏览器提示证书错误。这时候人容易慌,要么怀疑 CDN 服务商有问题,要么乱改配置越搞越乱。

其实接入 CDN 后无法访问,绝大多数情况下就那么几类原因,而且有清晰的排查顺序。这篇文章给出一套从外到内的排查清单:先确认 DNS 有没有解析到 CDN,再看 CNAME 配置,然后查回源地址和协议,接着排查源站防火墙,最后核对证书和缓存。按这个顺序走,绝大多数问题都能定位。

一、先判断问题出在哪一层

排障最重要的是别乱试,先确定"请求到底走到了哪里"。用一条命令就能看个大概:

# 看域名解析结果,判断是否已经走了 CDN
dig www.example.com +short

# 看完整解析链路,包括 CNAME
dig www.example.com ANY +noall +answer

# 直接看 HTTP 响应头,判断是谁在响应
curl -I https://www.example.com/

# 带详细过程,能看到解析、连接、TLS 各阶段耗时
curl -v -o /dev/null https://www.example.com/

关键看两点:解析结果是不是 CDN 节点的 IP,以及响应头里有没有 CDN 的特征字段(比如 X-Cache、Via、Server 里带 CDN 服务商标识)。如果解析结果还是你自己的源站 IP,说明请求根本没走 CDN,问题出在 DNS 层,往下查源站是白费功夫。

# 从多个公共 DNS 分别查询,排除本地 DNS 缓存干扰
dig @8.8.8.8 www.example.com +short
dig @223.5.5.5 www.example.com +short
dig @1.1.1.1 www.example.com +short

# 查 TTL 和记录类型
dig www.example.com +noall +answer

如果不同 DNS 返回的结果不一致(有的还是旧 IP),通常是 DNS 缓存还没过期,等 TTL 到期会自动更新;急着验证可以先降低 TTL 再重新解析。

二、DNS 有没有解析到 CDN

这是接入 CDN 后最常见的第一道坎。接入流程一般是:CDN 服务商会给你一个 CNAME 目标域名(形如 www.example.com.xxxcdn.net),你要到自己的域名解析商那里,把原来的 A 记录(指向源站 IP)改成一个 CNAME 记录指向它。

要检查的点:

第一,CNAME 记录加对了没有。名字和值都要对,值就是 CDN 服务商给的目标域名,一个字符都不能错。

第二,原来的 A 记录删掉了没有。如果 A 记录和 CNAME 记录同时存在,解析可能不生效或者结果混乱。同一个主机名一般不能同时有 A 记录和 CNAME 记录。

第三,变更生效了没有。DNS 变更有传播时间,取决于原来 TTL 设了多久,可能是几分钟也可能是几小时。

# 确认 CNAME 是否正确
dig www.example.com CNAME +short
# 期望输出:www.example.com.xxxcdn.net.(或者多级 CNAME)

# 如果返回的是 IP 而不是 CNAME,说明可能还是 A 记录,或 CNAME 被 CDN 解析后返回了 A
nslookup -type=CNAME www.example.com

还有一个细节:如果你的主域名(裸域名,如 example.com)要接入 CDN,很多解析商不支持裸域名做 CNAME。这时候通常要用 CDN 服务商提供的 CNAME 拉平功能,或者用解析商的别名记录。

三、CNAME 配了但访问异常:查回源

如果确认请求已经走到 CDN 了(解析是 CDN 节点、响应头有 CDN 特征),但访问还是报错,问题多半在"回源"这一段,也就是 CDN 节点去源站取内容的过程。

回源相关的报错里,502 和 504 最常见:

  • 502 Bad Gateway:CDN 连上了源站,但源站返回了错误,或者源站主动断开了连接。常见于源站端口没开、程序没起、回源 Host 配错导致源站返回错误页面。
  • 504 Gateway Timeout:CDN 向源站请求超时,源站响应太慢或者根本没响应。

排查回源,要核对这几个配置:

回源地址。CDN 回源是回到哪个 IP 和端口?如果源站 IP 填错了、填成了内网 IP、或者端口填错了(比如源站监听 8080,回源配的 80),都会失败。

回源 Host。CDN 回源时会带一个 Host 头,源站(尤其是 Nginx 按域名分站点时)会根据 Host 找对应的站点。如果回源 Host 配的是源站 IP 而源站只认域名,就会回到一个空站点或者报错。

# 在源站上直接模拟 CDN 回源,验证源站能不能正常响应
# 用回源 Host 访问源站,看是否返回正常页面
curl -I -H "Host: www.example.com" http://源站IP/

# 如果源站是 HTTPS,加上 --resolve 指定解析
curl -I --resolve www.example.com:443:源站IP https://www.example.com/

# 看源站端口是否在监听
ss -lntp | grep -E ':80|:443'

回源协议。回源用 HTTP 还是 HTTPS、是固定还是跟随用户请求,这几个选项要选对。如果源站只支持 HTTPS 而回源配成了 HTTP,或者反过来,都会出问题。协议不匹配时,报错往往表现为 502 或重定向循环。

在源站上,要确保 CDN 能正常访问到内容:

# 在源站上看访问日志,确认 CDN 回源请求有没有到达
tail -f /var/log/nginx/access.log
# 观察是否有来自 CDN 回源 IP 的请求,以及返回的状态码

# 检查源站本身是否正常(本机自测)
curl -I http://127.0.0.1/ -H "Host: www.example.com"

如果源站日志里根本看不到回源请求,说明请求没到源站,问题在网络或防火墙;如果看到了但返回 5xx,说明源站程序有问题。

四、源站防火墙与安全组放行

这是新手最容易踩的坑之一:源站为了"安全",把防火墙或云安全组设成了只允许特定 IP 访问,结果把 CDN 的回源 IP 也挡在外面了。CDN 节点遍布各地,回源 IP 是一大批(业内叫"回源 IP 段"),不可能一个个手动加,正确做法是放行 CDN 服务商公布的回源 IP 段。

主流 CDN 服务商都会在文档里提供回源 IP 段列表,通常是一个 CIDR 列表,而且会定期更新。你需要把这个列表加到源站的防火墙或云安全组里。

# 以 firewalld(RHEL/CentOS/Rocky)为例,放行 CDN 回源 IP 段
# 注意:下面的网段只是示例格式,实际请使用 CDN 服务商公布的最新回源 IP 段
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" accept'
firewall-cmd --reload
firewall-cmd --list-all

# 回滚:删除刚加的规则
# firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="203.0.113.0/24" accept'
# firewall-cmd --reload
# 以 ufw(Debian/Ubuntu)为例
ufw allow from 203.0.113.0/24 to any port 80,443 proto tcp
ufw status numbered
# 回滚:ufw delete <规则编号>
# 直接看 iptables 现有规则,确认有没有把 CDN 回源段挡了
iptables -L -n --line-numbers | less

改防火墙是高风险操作,稍有不慎会把自己也锁在外面。务必先确认当前 SSH 端口是放行的,再动手;改完立刻用另一个终端验证能否继续连接,出问题马上回滚。

如果源站用的是云服务商的安全组,还要去控制台检查安全组规则:入方向要放行 80 和 443,并且来源包含 CDN 回源 IP 段。安全组和实例防火墙是两层,两层都要放行。

五、证书与 HTTPS 问题

接入 CDN 后 HTTPS 报错,集中在证书上。通常有几种情况:

证书只配在源站,没配在 CDN 侧。用户访问的是 CDN,握手发生在用户和 CDN 节点之间,所以证书必须上传(或申请)到 CDN 侧。只在源站配了证书,用户看到的仍然是 CDN 的默认证书或者握手失败。

证书链不完整。有些证书文件只包含站点证书,缺少中间证书,在部分浏览器上会报"证书链不完整"或直接失败。上传到 CDN 的证书要包含完整的证书链(站点证书 + 中间证书)。

# 验证证书链是否完整
openssl s_client -connect www.example.com:443 -servername www.example.com /dev/null | openssl x509 -noout -subject -issuer -dates

# 展开完整链
openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts /dev/null | openssl x509 -noout -enddate

开了强制 HTTPS 但源站不支持。如果 CDN 侧开了"强制跳转 HTTPS",所有 HTTP 请求都会被 301 到 HTTPS。如果源站的证书有问题或者只支持部分协议版本,跳转后就会失败。要确认从 CDN 回源到源站这一段(回源协议)也是通的。

SNI 问题。现代 CDN 和浏览器基本都支持 SNI(在 TLS 握手时带上要访问的域名),但个别老旧客户端或特殊环境下可能有问题。如果发现某些老设备访问异常,可以检查是否与 SNI 相关。

域名和证书不匹配。证书上的域名必须覆盖用户访问的域名,包括 www 和裸域名要分别覆盖(或用通配符证书)。换了域名、加了新子域名,证书也要跟着更新。

六、缓存了错误页面

有一种很隐蔽的故障:网站中途出过一次错,CDN 把当时的错误页面(比如 404、500 页面)缓存了下来,之后即使源站恢复了,用户拿到的还是那个被缓存的错误页。表面上像是"网站坏了",其实是缓存污染。

判断方法是看响应头里的缓存状态字段,以及响应内容是不是一个旧的错误页。解决办法是到 CDN 控制台刷新对应 URL 的缓存,如果是整站出错,就按目录或全站刷新。

# 看响应头里的缓存命中和缓存时间信息
curl -I https://www.example.com/some-page
# 关注 X-Cache: HIT/MISS、Age、Last-Modified 等字段
# Age 很大且内容是错误页,基本可以确定是缓存了错误页

预防措施是配置按状态码缓存的规则:只缓存 2xx 和 3xx,不缓存 4xx 和 5xx(或者只缓存很短时间)。这样即使源站偶发错误,也不会被长期缓存下来。具体怎么配在回源和缓存命中率那两篇里会展开。

# 在源站上确认当前返回的状态码是否正常
curl -I -H "Host: www.example.com" http://源站IP/

七、一套完整的排查顺序

把上面几节串成一份可以直接照着做的清单:

  1. dig 域名,看解析是不是 CDN 节点 IP。不是 → 查 CNAME 和 A 记录,确认 DNS 变更生效。
  2. curl -I 看响应头,确认是否由 CDN 返回,看状态码是多少。
  3. 看具体报错:403 多为权限/防盗链/回源被拒,502 多为回源连接失败,504 为回源超时,证书错误为证书配置问题。
  4. 查回源配置:回源 IP、端口、回源 Host、回源协议是否正确。
  5. 到源站看 access.log,确认回源请求是否到达、返回什么状态码。
  6. 检查源站防火墙和云安全组,是否放行了 CDN 回源 IP 段。
  7. 核对 CDN 侧证书是否配置完整,是否与域名匹配,强制 HTTPS 是否合适。
  8. 检查是否缓存了错误页,必要时刷新缓存,并配置按状态码缓存规则。
# 一次跑完基础信息收集,方便快速定位
echo "== DNS ==" && dig www.example.com +short
echo "== HEAD ==" && curl -sI https://www.example.com/
echo "== 源站直连 ==" && curl -sI -H "Host: www.example.com" http://源站IP/
echo "== 证书 ==" && echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null | openssl x509 -noout -subject -enddate

常见问题

Q:接入 CDN 后本地能打开,外地用户打不开,为什么?
多半是解析或调度问题。本地可能有 DNS 缓存,或者本地节点正常而其他地区节点回源异常。用多地拨测工具或公共 DNS 分别解析,看不同地区的结果。

Q:改了源站配置,为什么用户看到的还是旧内容?
CDN 和浏览器都可能有缓存。先在 CDN 控制台刷新缓存,再让用户强制刷新浏览器(通常是 Ctrl+F5 或清缓存)。根治办法是静态资源用带版本的文件名。

Q:安全组放行了 80,为什么还报回源失败?
可能 CDN 回源走的是 443,或者回源用的是自定义端口。核对回源协议和端口配置,必要时同时放行 80 和 443。

Q:证书在浏览器里显示正常,但 CDN 报证书错误?
用户看到的是 CDN 节点的证书。要确认 CDN 侧上传的证书有效且链完整,并检查回源到源站那一段的证书是否被 CDN 接受(有的 CDN 默认校验证书,源站自签名会导致回源失败)。

Q:怎么快速确认是不是缓存问题?
加一个随机查询参数绕开缓存访问,比如 curl -I "https://www.example.com/?t=123"(前提是 CDN 没忽略这个参数)。如果带参数能打开、不带参数打不开,基本就是缓存了错误内容。

总结

接入 CDN 后无法访问,先别慌着改配置,按"由外到内"的顺序排查:DNS 解析对不对、CNAME 配没配、请求有没有真的走到 CDN,这三步能筛掉一大半问题。

请求到 CDN 之后仍异常,重点查封回源:回源 IP、端口、回源 Host、回源协议四项要全部核对,502 和 504 基本都是回源这一层的信号。

源站防火墙和云安全组是最容易忽视的一环,一定要放行 CDN 服务商公布的回源 IP 段,而不是自己凭感觉配白名单。改防火墙前先确认 SSH 端口放行并留好回滚方案。

HTTPS 报错集中在证书:证书要配在 CDN 侧、链要完整、域名要匹配、强制跳转要和回源协议对得上。最后别忘了检查是否缓存了错误页,并配置按状态码缓存的规则来预防。

排查的本质是"定位请求走到了哪一层、在哪一层断掉的",而不是改一堆配置碰运气。养成先收集 dig、curl -I、源站日志这几个信息的习惯,问题会好定位得多。