# 525 SSL Handshake Failed (Cloudflare)

> Cloudflare 525 means the TLS handshake with your origin server failed. Diagnose with openssl s_client, check SSL modes, ciphers, SNI and port 443, and fix it.

Source: https://howhttpworks.com/status-codes/525
Last reviewed: 2026-10-04

> **TL;DR:** Cloudflare could open a TCP connection to your origin on port 443 but the TLS handshake failed. Test the origin directly with `openssl s_client -connect ORIGIN_IP:443 -servername example.com`: if that does not complete, fix the origin's TLS listener, protocols, ciphers or certificate for that SNI name.

## What it means

525 is Cloudflare-specific, issued by Cloudflare's edge, not your server. The edge connected to the origin (so a [521](https://howhttpworks.com/status-codes/521) or [522](https://howhttpworks.com/status-codes/522) was avoided), then the TLS negotiation failed before any HTTP was exchanged. Origin logs often show nothing because no request was ever parsed.

The error page says **Error 525: SSL handshake failed** and includes a Ray ID. The response headers carry `Server: cloudflare` and a `CF-RAY` value.

```http
HTTP/2 525
server: cloudflare
cf-ray: 8a1b2c3d4e5f6a7b-AMS
content-type: text/html; charset=UTF-8
```

## Who sent it?

`Server: cloudflare` plus a `CF-RAY` header and the Cloudflare-styled error page mean the edge generated it. If your origin generated a 525, something is wrong (some applications echo upstream codes, so check origin logs).

Cloudflare's own troubleshooting page lists four origin-side causes: no valid certificate installed, port 443 (or the custom secure port) closed, no SNI support, and no cipher suite in common.

## SSL modes decide whether this can happen

| Mode | Edge to origin | Can produce 525? | Validates origin cert? |
|---|---|---|---|
| Off | HTTP | No | n/a |
| Flexible | HTTP on port 80 | No | n/a |
| Full | HTTPS | Yes | No (self-signed OK) |
| Full (strict) | HTTPS | Yes | Yes: 526 if invalid |

If you recently switched from Flexible to Full, every site whose origin does not listen on 443 starts returning 525 (or 521 if nothing is listening). Check **SSL/TLS > Overview**, and **Rules > Configuration Rules** for per-hostname overrides.

## Common causes

1. **No TLS listener on 443.** The origin only serves HTTP, or the web server is listening on 443 without `ssl`. Cloudflare connects to the standard HTTPS port unless an Origin Rule or the Cloudflare Tunnel overrides it.
2. **Origin lacks a certificate for the SNI name.** Cloudflare sends SNI with the request hostname unless an Origin Rule overrides it. If the origin's default vhost has no certificate, or a hosting panel returns a handshake failure for unknown names, the handshake dies.
3. **Cipher or protocol mismatch.** Cloudflare offers a list of cipher suites to the origin (TLS 1.3 AEAD suites, TLS 1.2 ECDHE suites with AES-GCM and ChaCha20, plus older CBC suites) and the origin picks one. If the origin's configuration shares none of them, or it only speaks SSLv3 or a TLS version with no overlapping suite, the handshake fails. Allow TLS 1.2 and 1.3 with ECDHE AES-GCM suites.
4. **Origin firewall or WAF drops TLS packets** (rate limiting by IP, an IDS interfering with the handshake). The TCP handshake passes, TLS does not.
5. **Load balancer or TLS-terminating proxy in front of the origin is misconfigured**, with only some backends having certificates.
6. **Custom port mismatch.** An Origin Rule sends traffic to a port that speaks HTTP.

## Diagnose from the command line

Test the origin directly, bypassing Cloudflare, with SNI set to the hostname that fails:

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

Healthy output ends with a certificate chain, `Verify return code`, and a negotiated protocol and cipher:

```text
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
```

Failure signatures:

```text
# nothing listening / HTTP only
140735... error:... SSL routines:... wrong version number
# handshake aborted: no cert for this SNI name, or unsupported protocol
... alert handshake failure
... tlsv1 alert protocol version
# connection dropped by firewall or non-TLS service
connect:errno=104 / unexpected eof while reading
```

Then probe protocols individually to see what the origin allows:

```bash
openssl s_client -connect 203.0.113.10:443 -servername www.example.com -tls1_2 </dev/null | grep -E 'Protocol|Cipher'
openssl s_client -connect 203.0.113.10:443 -servername www.example.com -tls1_3 </dev/null | grep -E 'Protocol|Cipher'
```

Also check the origin's own TLS error log. For nginx, run `error_log ... info;` temporarily and look for `SSL_do_handshake() failed`. For Apache check `ssl_error_log` (AH lines) and that `SSLProtocol` is not set to a narrow list.

## Fix it

1. Make sure the origin has a TLS listener on 443 and a certificate for the hostname, for example in nginx:

```nginx
server {
    listen 443 ssl;
    server_name www.example.com;

    ssl_certificate     /etc/ssl/certs/www.example.com.pem;
    ssl_certificate_key /etc/ssl/private/www.example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
}
```

2. If the origin cannot serve a valid public certificate, install a free **Cloudflare Origin CA certificate** (valid only for traffic coming from Cloudflare) and use Full (strict).
3. Allow TLS 1.2+ with modern ciphers, and unblock Cloudflare's published IP ranges in firewalls and rate limiters.
4. If the origin truly cannot do TLS, set the mode to Flexible only as a stopgap. It sends traffic in clear text between Cloudflare and the origin, and the combination with an origin that redirects HTTP to HTTPS produces redirect loops (`ERR_TOO_MANY_REDIRECTS`).
5. For multi-tenant origins that choose certificates by SNI, use an SNI override in an Origin Rule to send the name the origin expects.

## Related

- [526 Invalid SSL Certificate](https://howhttpworks.com/status-codes/526): handshake worked, certificate failed Full (strict) validation.
- [530 Origin DNS Error](https://howhttpworks.com/status-codes/530): Cloudflare could not resolve the origin at all.
- [521 Web Server Is Down](https://howhttpworks.com/status-codes/521) and [522 Connection Timed Out](https://howhttpworks.com/status-codes/522)
- [520 Web Server Returned an Unknown Error](https://howhttpworks.com/status-codes/520)
- [HTTPS and TLS](https://howhttpworks.com/guides/https-and-tls)
