某天访问站点,Cloudflare 直接抛了个 525:
{
"title": "Error 525: SSL handshake failed",
"status": 525,
"detail": "The SSL/TLS handshake between Cloudflare and the origin server failed."
}
意思就是——Cloudflare 收到了请求,但它和你的源站之间的 TLS 握手没建起来。不是 Cloudflare 挂了,是源站 SSL 有问题。
常见 8 种原因
1. 源站证书失效
在源站本机测:
echo | openssl s_client -servername example.com -connect example.com:443
看输出里有没有:
Verify return code: 0 (ok)
如果出现 certificate has expired,证书过期了,续签或换证书。
2. Nginx 证书和私钥不匹配
分别算 MD5,两边必须一致:
openssl x509 -noout -modulus -in cert.pem | md5sum
openssl rsa -noout -modulus -in key.pem | md5sum
不一致就是配错了。
3. TLS 版本太老
Cloudflare 现在只接受 TLS 1.2 / 1.3。Nginx 配置里明确写清:
ssl_protocols TLSv1.2 TLSv1.3;
4. Cipher Suite 不兼容
某些老配置写得太激进(HIGH:!aNULL:!MD5 只留少数几个),Cloudflare 找不到共同 cipher。用 nmap 探一下源站支持哪些:
nmap --script ssl-enum-ciphers -p 443 <origin-ip>
5. Cloudflare 用了 Full (strict) 模式
Dashboard → SSL/TLS → Overview 里检查模式:
- Flexible:Cloudflare 到源站走 HTTP
- Full:源站要有证书(不校验)
- Full (strict):源站必须有效证书、链完整、域名匹配
如果是 strict,用 Cloudflare Origin CA 签的证书最省事。
6. 证书链不完整(最常见的坑)
如果 openssl s_client 里出现:
verify error:num=20:unable to get local issuer certificate
多半是 Nginx 只配了 cert.pem 而不是 fullchain.pem。
正确写法:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
7. 源站 443 没监听
直接测:
curl -vk https://<origin-ip>
如果 Connection refused,Nginx 没在这个 IP 上监听 443。防火墙、云安全组同样要放行。
8. IPv6 配置错误
Cloudflare 可能优先走 IPv6,如果 Nginx 没监听或者防火墙漏放,就 525。
dig AAAA example.com
出现 AAAA 记录时,Nginx 记得写:
listen 443 ssl;
listen [::]:443 ssl;
快速定位思路
先在源站本机执行:
openssl s_client -connect localhost:443 -servername example.com
- 本机就
handshake failure:问题在 Nginx 或证书 - 本机 OK 但外网 525:问题在 IP 路由 / 防火墙 / IPv6 / Cloudflare 连的不是这台机器
再看 Cloudflare 实际解析到哪个 IP:
dig A example.com
dig AAAA example.com
用 --resolve 强制走特定 IP 复现:
curl -I https://example.com --resolve example.com:443:<origin-ip>
一句话总结
525 = Cloudflare 和源站的 TLS 握手失败。八成落在 证书链不完整 或 Full (strict) 模式下证书不合规,用 openssl s_client 从源站本机开始逐层排查。
