[ Servers & DevOps  /  7 min read ]

Cloudflare 522 error (connection timed out): a step-by-step fix

[ Short answer ]

A Cloudflare 522 error means Cloudflare tried to open a TCP connection to your origin server and got no answer in time. The usual causes are an origin that is down or overloaded, a firewall dropping Cloudflare's IP ranges, the wrong origin IP in DNS, or an SSL mode that sends traffic to a port nothing is listening on.

A Cloudflare 522 error means Cloudflare's edge tried to open a TCP connection to your origin server and never got a reply. Per Cloudflare's documentation, that is either no SYN+ACK within 19 seconds of sending a SYN, or no acknowledgement of the request within 90 seconds of the connection being established. Cloudflare itself is fine; the problem sits between its edge and your server. In practice it is one of five things: the origin is down or overloaded, a firewall is dropping Cloudflare's IPs, DNS points at the wrong IP, the SSL mode sends traffic to a closed port, or keepalive is misconfigured. Here is how I work through it, in the order that finds the cause fastest.

What "connection timed out" on Cloudflare actually means

When a request comes in, Cloudflare looks up the origin IP from your proxied DNS record and opens a connection to it on port 80 or 443, depending on your SSL/TLS mode. A 522 says that connection attempt went nowhere. The packets were silently dropped or the server was too busy to answer. That is different from the server actively refusing, which is a 521, and different from a server that accepted the connection but took too long to send a response, which is a 524.

That distinction matters because a silent drop almost always means a firewall or a dead host, while a refusal means the host is up but nothing is listening on that port. Before changing anything, grab the Ray ID from the bottom of the error page and the time it happened. You will want them when you read the logs.

521 vs 522 vs 524 vs 525: which error do you have?

Cloudflare's 52x errors look alike on screen but point at different layers. This is the table I keep in my head when someone sends me a screenshot.

ErrorWhat happenedUsual cause
520Origin returned an empty or unexpected responseCrashing app, oversized headers, connection reset mid-response
521Origin actively refused the connectionWeb server stopped, or nothing listening on 80/443
522TCP connection to origin timed outFirewall dropping Cloudflare IPs, host down, wrong IP, overload
524Connected, but no HTTP response in timeSlow PHP or database query exceeding the 100-second proxy timeout
525SSL handshake with origin failedNo certificate or bad TLS config on origin in Full / Full (strict) mode
526Origin certificate invalidExpired, self-signed or wrong-hostname certificate in Full (strict)

If you are seeing a Cloudflare 525 instead, skip ahead to the SSL mode section: the TCP connection worked, but TLS did not.

Step 1: test the origin directly with curl --resolve

The single most useful test is to bypass Cloudflare and talk to the origin yourself, while still sending the correct hostname. curl --resolve does exactly that: it pins the hostname to an IP for that one request, so SNI and the Host header are correct.

# Replace 203.0.113.10 with the origin IP shown in your Cloudflare DNS record
curl -svo /dev/null --connect-timeout 10 \
  --resolve example.com:443:203.0.113.10 https://example.com/

# And plain HTTP, which is what Flexible SSL mode uses
curl -svo /dev/null --connect-timeout 10 \
  --resolve example.com:80:203.0.113.10 http://example.com/

Read the result carefully, because each outcome points somewhere different:

  • Connection timed out from your laptop too — the host is down, the IP is wrong, or a cloud firewall (security group, provider firewall) blocks the port for everyone.
  • Connection refused — the host is up but nothing listens on that port. On Cloudflare that normally shows as 521, but check it anyway.
  • Works from your laptop — the origin is healthy and something is blocking Cloudflare specifically. That is the most common case, and it is almost always a firewall.

Also confirm the IP itself. After a server move, I regularly find the proxied A record still pointing at the old machine, or an AAAA record pointing at an IPv6 address the new server does not listen on. Cloudflare can connect to your origin over IPv6 when an AAAA record exists, so a stale AAAA record produces exactly this error. If you recently moved hosts, my guide to migrating a website without downtime covers how to cut over DNS cleanly.

Step 2: check the firewall is not blocking Cloudflare IP ranges

Once traffic goes through Cloudflare, every request reaches your server from a relatively small set of Cloudflare IP ranges. Security tools that were written for direct traffic see thousands of requests from a handful of IPs and conclude they are under attack. I see three versions of this constantly:

  • fail2ban or CSF/LFD banning edge IPs. Without the real visitor IP restored, one abusive visitor gets a Cloudflare IP banned, and every visitor routed through that edge location gets a 522.
  • Host-level firewalls with an allowlist (ufw, firewalld, nftables) that never included Cloudflare's ranges.
  • Cloud firewalls such as AWS security groups or a VPS provider panel that only opened port 80, while Cloudflare is trying 443.

Check whether Cloudflare packets are arriving at all. If you see SYNs coming in with no replies, your firewall is dropping them. If nothing arrives, the block is upstream at the provider level.

# Watch for incoming connections on 443 (Ctrl+C to stop)
sudo tcpdump -ni any 'tcp port 443 and tcp[tcpflags] & tcp-syn != 0'

# Is any Cloudflare IP banned?
sudo fail2ban-client status
sudo iptables -S | grep -E 'DROP|REJECT'
sudo nft list ruleset | grep -iE 'drop|reject'

The fix is to explicitly allow Cloudflare's published ranges, which live at https://www.cloudflare.com/ips-v4 and https://www.cloudflare.com/ips-v6. Pull them from those URLs rather than copying a list from a blog post, because they do change occasionally.

# ufw example: allow HTTPS only from Cloudflare
for ip in $(curl -s https://www.cloudflare.com/ips-v4) $(curl -s https://www.cloudflare.com/ips-v6); do
  sudo ufw allow proto tcp from "$ip" to any port 443 comment 'cloudflare'
done
sudo ufw reload

Then restore the real visitor IP in your web server, so fail2ban and your logs see actual visitors instead of Cloudflare. On Nginx that means set_real_ip_from for each Cloudflare range plus real_ip_header CF-Connecting-IP;. On Apache it is mod_remoteip with RemoteIPHeader CF-Connecting-IP. Locking the origin to Cloudflare-only traffic is a sensible hardening step in its own right; it is part of what I do in server security hardening.

Step 3: match the SSL mode to the ports your origin listens on

Cloudflare's SSL/TLS encryption mode decides which port it connects to on your origin. This is where a lot of 522s and 525s come from after someone changes a setting in the dashboard.

  • Flexible — Cloudflare connects to your origin over plain HTTP on port 80.
  • Full — connects over HTTPS on port 443 and accepts any certificate, including self-signed.
  • Full (strict) — connects on 443 and requires a valid certificate, either publicly trusted or a free Cloudflare Origin CA certificate.

The classic failure: the origin only has port 80 open in its security group, someone switches the mode to Full, and Cloudflare starts connecting to 443, where packets are dropped. Result: 522 on every page. If 443 is open but no certificate is installed, you get a 525 instead. Confirm what is actually listening:

sudo ss -tlnp | grep -E ':80 |:443 '

If your app runs on a non-standard port, remember that Cloudflare only proxies specific ports. For HTTPS those are 443, 2053, 2083, 2087, 2096 and 8443; for HTTP they are 80, 8080, 8880, 2052, 2082, 2086 and 2095. Anything else times out. My recommendation for nearly every site is Full (strict) with an Origin CA certificate on the server, which removes this whole class of problem and actually encrypts the leg to your origin. Setting that up correctly is a core part of my Cloudflare setup service.

Step 4: rule out an overloaded origin and keepalive issues

If the 522s are intermittent and your firewall is clean, the server is probably too busy to accept new connections. Under load, the kernel's SYN backlog fills and new connection attempts are dropped, which looks identical to a firewall block from Cloudflare's side. Check load, memory and whether the web server has run out of workers:

uptime; free -m
sudo dmesg | grep -iE 'oom|syn flooding|nf_conntrack: table full'
sudo journalctl -u nginx -u php8.3-fpm --since "1 hour ago" | grep -iE 'max_children|worker_connections'

A full nf_conntrack table, PHP-FPM hitting pm.max_children, or the OOM killer taking out your database are all common. The cure is capacity or efficiency, not a Cloudflare setting, although caching more at the edge takes a lot of pressure off the origin.

Keepalive is the other piece. Cloudflare reuses connections to your origin, and its troubleshooting guidance recommends keeping HTTP keep-alive enabled on the origin. If keepalive is disabled, every request needs a fresh TCP handshake, which multiplies connection load exactly when you can least afford it. On Nginx, make sure keepalive_timeout is not set to 0; the default of 75 seconds is fine.

How to stop 522 errors coming back

  • Allow Cloudflare ranges explicitly and restore the real visitor IP, so security tools never ban the edge again.
  • Use Full (strict) with an Origin CA certificate and keep 443 open to Cloudflare.
  • Delete stale A and AAAA records whenever you move servers.
  • Monitor the origin directly, not only the public URL, so you know whether a problem is your server or the proxy path.
  • Cache aggressively at the edge so traffic spikes do not become origin overload.

Most 522s take ten minutes to fix once you know which layer is failing. If you have worked through these steps and still see the error, or you want the origin locked down properly so it does not happen again, I can do it as part of a Cloudflare setup and troubleshooting job, or review the whole box under server setup and configuration. Small fixes are $20/hour; larger jobs get a fixed price agreed in writing before I start.

Frequently asked questions

Is a 522 error my fault or Cloudflare's?

Almost always the origin side. The Cloudflare error page shows three boxes: Browser, Cloudflare and Host. A 522 marks Host as the error, meaning Cloudflare's edge was working but could not reach your server. Cloudflare-side incidents do happen, but check cloudflarestatus.com once and then look at your own server.

Why do I get 522 errors only sometimes?

Intermittent 522s usually point to an origin that is overloaded at peak times, a SYN backlog or connection-tracking table filling up, or a rate limiter or fail2ban jail that bans some Cloudflare edge IPs but not others. Correlate the Ray IDs and timestamps with your server's load and firewall logs.

Will pausing Cloudflare fix a 522?

Pausing Cloudflare or switching the record to DNS only sends visitors straight to your origin, which confirms whether the origin works at all. It is a useful test, but it exposes your origin IP and removes caching and protection, so switch the proxy back on once you have found the cause.

How long does it take for a 522 fix to take effect?

Firewall and web server changes take effect immediately. If the fix is a changed origin IP in the DNS record, proxied records update across Cloudflare's edge within a few minutes because visitors never see your origin IP directly.

[ Want it done for you? ]

Cloudflare Setup

DNS, SSL, WAF and caching on Cloudflare, configured properly. Hourly work is $20/hour; defined projects get a fixed price in writing.

See the service

[ Let's talk ]

Broken, slow, or not built yet?

Describe it in a few lines and you'll get a real reply from the person who'd do the work — same working day, no discovery call required.