# Cloudflare Error 525: SSL handshake failed with the origin

> Error 525 means Cloudflare could not complete a TLS handshake with your origin. Check the origin certificate, SNI, port 443 and cipher suites.

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

**Cloudflare Error 525 means Cloudflare reached your origin server but could not complete a TLS handshake with it.** The visitor's connection to Cloudflare worked; the leg from Cloudflare to your server failed. It only happens in Full or Full (strict) mode, because only those modes connect to the origin over HTTPS.

## Where the failure is

The failure is on the second of two TLS connections, between Cloudflare and your origin:

| Leg | Who controls it | Error if it breaks |
|---|---|---|
| Visitor → Cloudflare edge | Cloudflare's edge certificate | Browser errors such as [ERR_SSL_VERSION_OR_CIPHER_MISMATCH](https://ssl.sh/errors/err-ssl-version-or-cipher-mismatch/) |
| Cloudflare → origin | Your server's TLS configuration | **525** (handshake failed) or [526](https://ssl.sh/errors/cloudflare-error-526-invalid-ssl-certificate/) (certificate rejected) |

Cloudflare uses different codes when the origin cannot be reached at all, for example 521 (web server is down) and 522 (connection timed out). A 525 tells you that a TCP connection was established and the TLS layer failed on top of it.

## Common causes, most frequent first

### 1. The origin has no working TLS on port 443

The most common case: the site was set up for Flexible mode with HTTP only, and someone later switched the zone to Full. Port 443 either serves plain HTTP or has no certificate configured. Cloudflare's own list starts with "no valid SSL certificate is installed".

Confirm it by connecting straight to the origin IP, with the real hostname as SNI:

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

`wrong version number` or `packet length too long` means port 443 is answering in plain HTTP. A connection reset or `no peer certificate available` means no certificate is loaded for that name.

### 2. No certificate for the SNI name Cloudflare sends

Cloudflare sends the visitor's hostname in the SNI extension. If your server has certificates only for other names, or the default server block is configured to reject unknown names (`ssl_reject_handshake on;` in Nginx), the handshake fails. Repeat the command above with each proxied hostname, including `www`.

### 3. No cipher suite in common

Cloudflare publishes the cipher suites it offers to origins. On TLS 1.3 it supports the three standard AEAD suites. On TLS 1.2 it offers ECDHE-ECDSA and ECDHE-RSA with AES-GCM, ECDHE-RSA-AES-SHA and plain RSA AES suites, but no DHE and no CHACHA20 suites. An origin hardened to "TLS 1.2 only, CHACHA20 or DHE only" has nothing to agree on. Check what the origin accepts:

```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. Port 443 filtered or reset by a firewall

A host firewall, cloud security group or intrusion-prevention system that accepts the TCP connection and then drops the TLS traffic produces 525 rather than 522. Tools such as fail2ban that ban IPs after many requests can ban Cloudflare's own ranges, which causes intermittent 525s.

### 5. The origin demands a client certificate

If the origin requires [mutual TLS](https://ssl.sh/glossary/mtls/) at the TLS layer (for example Apache with `SSLVerifyClient require`) but Authenticated Origin Pulls is not enabled on Cloudflare, Cloudflare presents no client certificate and the server aborts the handshake. Nginx behaves differently: with `ssl_verify_client on;` it completes the handshake and answers with an HTTP 400 error instead.

### 6. Intermittent failures under load

When 525s come and go, Cloudflare recommends comparing their timestamps with the origin's error log. Look for lines such as `SSL_do_handshake() failed` or `no shared cipher` in Nginx, or worker crashes and restarts in the TLS terminator.

## How to fix it

**Install a certificate on the origin.** Any certificate makes Full mode work; Full (strict) additionally needs a publicly trusted certificate or a Cloudflare Origin CA certificate. The [Cloudflare Origin CA guide](https://ssl.sh/guides/cloudflare-origin-certificate/) covers the second option, and Let's Encrypt works too.

**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;
}
```

**Apache:** enable `mod_ssl`, add a `<VirtualHost *:443>` with `SSLEngine on`, `SSLCertificateFile` and `SSLCertificateKeyFile`, and list every proxied name in `ServerName`/`ServerAlias`. Then run `apachectl configtest`.

**Firewalls:** allow inbound 443 from Cloudflare's published IP ranges and exclude them from automatic banning.

**mTLS origins:** either enable Authenticated Origin Pulls on Cloudflare or stop requiring a client certificate on the origin.

The [TLS config generator](https://ssl.sh/tools/tls-config-generator/) produces a protocol and cipher block that overlaps with Cloudflare's list.

## How to verify the fix

1. From any machine, test the origin directly: `openssl s_client -connect 203.0.113.10:443 -servername example.com -brief` should print the protocol, cipher and certificate subject.
2. Request the site through Cloudflare: `curl -sI https://example.com/` should return your normal status code with a `cf-ray` header and no 525.
3. If you plan to use Full (strict), also check the origin certificate chain and hostname so you do not trade a 525 for a [526](https://ssl.sh/errors/cloudflare-error-526-invalid-ssl-certificate/). The [SSL checker](https://ssl.sh/tools/ssl-checker/) shows what the edge presents; the handshake walk-through in [how the TLS handshake works](https://ssl.sh/learn/tls-handshake/) explains each step that can fail.
