CDN回源TLS握手失败主因是Nginx未发送完整证书链,需将ssl_certificate指向fullchain.pem(域名证+中间证),禁用根证、确保顺序正确,并通过openssl s_client验证输出是否含两行subject。

CDN回源时TLS握手被拦截,常见表现是CDN节点无法成功连接你的Nginx源站,日志中出现类似 SSL_do_handshake() failed 或 certificate verify failed,但直接访问源站域名(绕过CDN)却正常。问题往往不在CDN本身,而在于它作为“客户端”验证你Nginx源站证书时,因证书链不完整而拒绝建立连接。
确认CDN是否真在验证源站证书
多数主流CDN(如Cloudflare、阿里云全站加速、腾讯云CDN)在回源HTTPS请求时默认启用证书校验,即把你的Nginx当作服务端、CDN自身当作TLS客户端。它会严格检查你源站返回的证书链是否可构建至其信任的根CA。若只发了域名证书、缺中间证书,CDN就会中断回源,返回502或超时。
验证方法:在源站服务器上运行
openssl s_client -connect your-domain.com:443 -servername your-domain.com -showcerts 2>/dev/null | grep "subject="观察输出:
- 正常应有至少两行:第一行含
CN=your-domain.com(你的证书),第二行含中间CA名(如CN=Let's Encrypt R3) - 如果只有一行,或第二行是
CN=ISRG Root X1(根证书),说明Nginx未发送完整链,CDN大概率会拒连
检查Nginx配置是否满足CDN回源要求
CDN对源站证书链比普通浏览器更严格,尤其在意顺序和纯净度:
- ssl_certificate 必须指向 fullchain.pem,不是 cert.pem;该文件内容必须是:域名证书(BEGIN CERTIFICATE)→ 中间证书(BEGIN CERTIFICATE),不能含根证书,不能颠倒顺序,不能有空行
- 确保
ssl_certificate_key指向正确的私钥,权限为600;fullchain.pem 权限建议644 - 部分CDN(如Cloudflare)要求SNI字段匹配,需确认Nginx已开启
ssl_protocols TLSv1.2 TLSv1.3;,且未禁用SNI相关协商
模拟CDN视角做交叉验证
不要依赖本地浏览器或curl默认行为(它可能跳过链验证)。用以下方式贴近CDN真实行为:
- 使用
curl -vI https://your-domain.com --cacert /etc/ssl/certs/ca-certificates.crt,强制指定系统CA包验证链完整性 - 用在线工具如 SSL Labs 测试源站IP或回源域名,重点看 “Chain issues” 是否显示 “OK”
- 若CDN提供回源诊断日志(如阿里云CDN的“回源失败原因”字段),直接查看是否提示 “CERTIFICATE_VERIFY_FAILED” 或 “unable to get local issuer certificate”
排除CDN缓存与配置干扰
CDN可能缓存了旧的回源失败状态,或其控制台中误配了“仅HTTP回源”“忽略证书错误”等开关:
- 临时将CDN回源协议切换为HTTP(非HTTPS),确认能否成功回源——若能,基本锁定是源站HTTPS证书链问题
- 在CDN控制台关闭“证书校验”或开启“忽略证书错误”(仅测试用),若回源恢复,则进一步证实链缺失是主因
- 清除CDN节点缓存,并等待DNS TTL过期后重试,避免旧握手结果残留影响判断


















