# Error 525 SSL handshake failed：Cloudflare 回源握手失败的修法

> Cloudflare 525 表示 Cloudflare 和源站之间的 TLS 握手失败，和访客无关。按源站证书、SNI、443 端口、加密套件的顺序排查，附 Nginx、宝塔配置示例。

Source: https://ssl.sh/zh/errors/cloudflare-error-525-ssl-handshake-failed/
Last updated: 2026-11-10

**Cloudflare 525 的意思是：Cloudflare 连上了你的源站，但和源站之间的 TLS 握手没有完成。** 访客到 Cloudflare 的 HTTPS 连接没问题，坏的是 Cloudflare 回源这一段，在发出任何 HTTP 请求之前就失败了。只有加密模式为 Full 或 Full (strict) 时才会出现这个错误，因为只有这两种模式下 Cloudflare 才会用 HTTPS 连源站。

## 525 坏在哪一段

525 坏在 Cloudflare 到源站这一段。套了 Cloudflare 代理（小黄云）的网站有两条独立的 TLS 连接：

| 连接 | 由谁负责 | 出问题时的报错 |
|---|---|---|
| 访客 → Cloudflare 边缘 | Cloudflare 的边缘证书 | 浏览器报错，比如 [ERR_SSL_VERSION_OR_CIPHER_MISMATCH](https://ssl.sh/zh/errors/err-ssl-version-or-cipher-mismatch/) |
| Cloudflare → 源站 | 你服务器上的 TLS 配置 | **525**（握手失败）或 [526](https://ssl.sh/zh/errors/cloudflare-error-526-invalid-ssl-certificate/)（证书不被认可） |

如果 Cloudflare 连不上源站，会报别的代码，比如 521（源站宕机）、522（连接超时）。看到 525，说明 TCP 已经连上了，是上面的 TLS 层失败。

## 常见原因（按出现频率排序）

525 有 6 种原因，最常见的是源站 443 端口没有可用的 TLS。

### 1. 源站 443 端口没有可用的 TLS

最常见的情况：网站当初按 Flexible 模式搭的，源站只跑 HTTP，后来有人把加密模式改成了 Full。此时源站 443 要么跑的是明文 HTTP，要么压根没配证书。Cloudflare 官方列的第一条原因就是“源站没有安装有效的 SSL 证书”。

确认方法：绕过 Cloudflare 直连源站 IP，同时带上真实域名作 SNI：

```bash
openssl s_client -connect 203.0.113.10:443 -servername example.com -brief </dev/null
```

出现 `wrong version number` 或 `packet length too long`，说明 443 上跑的是明文 HTTP；连接被重置或提示 `no peer certificate available`，说明这个域名没有加载证书。

### 2. 源站没有 Cloudflare 所请求域名的证书

Cloudflare 回源时会在 SNI 里带上访客访问的域名。源站如果只给别的域名配了证书，或者默认站点设置了拒绝未知域名（Nginx 的 `ssl_reject_handshake on;`），握手就会失败。上面的命令要对每个开了代理的域名都跑一遍，`www` 也别漏。

### 3. 加密套件没有交集

Cloudflare 公开了回源时提供的套件清单：TLS 1.3 支持三个标准 AEAD 套件；TLS 1.2 提供 ECDHE-ECDSA、ECDHE-RSA 的 AES-GCM 套件，ECDHE-RSA-AES-SHA，以及纯 RSA 的 AES 套件，**没有 DHE，也没有 CHACHA20**。源站如果被“加固”成只开 TLS 1.2、只允许 CHACHA20 或 DHE，就和 Cloudflare 谈不拢。用下面的命令看源站接不接受某个套件：

```bash
openssl s_client -connect 203.0.113.10:443 -servername example.com -tls1_2 \
  -cipher 'ECDHE-RSA-AES128-GCM-SHA256' -brief </dev/null
```

### 4. 443 端口被防火墙过滤或重置

阿里云、腾讯云的安全组，宝塔的系统防火墙，或者入侵防护设备，如果放行了 TCP 但又掐断了 TLS 流量，表现就是 525 而不是 522。fail2ban 这类按请求量封 IP 的工具，在没配置真实 IP 时看到的全是 Cloudflare 的 IP，很容易把 Cloudflare 自己封掉，造成时好时坏的 525。

### 5. 源站要求客户端证书

源站在 TLS 层强制要求[双向 TLS](https://ssl.sh/zh/glossary/mtls/)（比如 Apache 的 `SSLVerifyClient require`），但 Cloudflare 那边没开 Authenticated Origin Pulls，Cloudflare 拿不出客户端证书，源站就会中止握手。Nginx 的行为不一样：`ssl_verify_client on;` 时它会先完成握手，再返回 HTTP 400 错误，所以不会表现为 525。

### 6. 高负载下偶发失败

525 时有时无时，Cloudflare 建议把出错时间点和源站错误日志对照。Nginx 日志里重点找 `SSL_do_handshake() failed` 和 `no shared cipher`，或者 TLS 终止程序崩溃重启的记录。

## 怎么修

修法是让源站在 443 端口完成 TLS 握手：装好证书，按 SNI 返回正确的站点，开启 Cloudflare 支持的协议和套件。

**先给源站装证书。** Full 模式下任何证书都行（包括自签名）；Full (strict) 则需要公共信任的证书，或者 Cloudflare 签发的 Origin CA 证书，后者的做法见 [Cloudflare 源站证书教程](https://ssl.sh/zh/guides/cloudflare-origin-certificate/)。也可以用 Let's Encrypt，或者阿里云、腾讯云的免费证书。

**Nginx 示例：**

```nginx
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;
    ssl_certificate     /etc/ssl/example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
}
```

**宝塔面板：** 在网站设置的“SSL”里粘贴证书和私钥并保存，宝塔会自动生成 443 监听。注意不要勾“强制 HTTPS”之后又把 Cloudflare 切回 Flexible，否则会出现重定向循环。

**Apache：** 启用 `mod_ssl`，新增 `<VirtualHost *:443>`，写上 `SSLEngine on`、`SSLCertificateFile`、`SSLCertificateKeyFile`，`ServerName`/`ServerAlias` 覆盖所有代理的域名，再执行 `apachectl configtest`。

**防火墙：** 安全组和系统防火墙放行 Cloudflare 公布的 IP 段访问 443，并把这些 IP 加进 fail2ban 等工具的白名单。

**双向 TLS 源站：** 要么在 Cloudflare 开启 Authenticated Origin Pulls，要么源站不再强制要求客户端证书。

## 源站前面还有一层负载均衡时

结构是“Cloudflare → 云厂商负载均衡 → 后端服务器”时，和 Cloudflare 握手的是负载均衡，而不是你登录的那台机器，所以要查负载均衡的配置：

- 负载均衡上要有 443 的 HTTPS 监听，并且绑定了覆盖所有域名的证书；只开了 80 的 HTTP 监听，就是第 1 种原因。
- 负载均衡的 TLS 安全策略决定了它接受哪些协议和套件。选了只含 TLS 1.2 加少数冷门套件的策略，可能和 Cloudflare 的清单没有交集，就是第 3 种原因。
- 后端服务器的 Nginx 配得再好也不影响这一段握手，改错了地方是排查时最常见的浪费时间。

直连测试时，`-connect` 后面填负载均衡的公网 IP，而不是后端机器的内网 IP。

协议和套件不确定怎么写，可以用 [TLS 配置生成器](https://ssl.sh/zh/tools/tls-config-generator/) 生成一份和 Cloudflare 清单有交集的配置。

## 怎么确认已经修好

直连源站的 openssl 握手成功，经 Cloudflare 访问不再返回 525，就说明修好了。

1. 直连源站：`openssl s_client -connect 203.0.113.10:443 -servername example.com -brief` 能打印出协议版本、套件和证书主体。
2. 通过 Cloudflare 访问：`curl -sI https://example.com/` 返回正常状态码，响应头里有 `cf-ray`，不再是 525。
3. 打算用 Full (strict) 的，同时检查源站证书链和域名，免得 525 修好又冒出 [526](https://ssl.sh/zh/errors/cloudflare-error-526-invalid-ssl-certificate/)。[SSL 检测](https://ssl.sh/zh/tools/ssl-checker/) 可以看边缘证书情况；握手每一步可能在哪里失败，见 [TLS 握手过程详解](https://ssl.sh/zh/learn/tls-handshake/)。
