Why a Healthy Origin Can Still Trigger Cloudflare 520‑524 Errors
A 2 a.m. pager alert wakes you to a "Cloudflare 522" on a critical API endpoint. The origin server logs show the request completed in 0.3 s, TLS handshake succeeded locally, and the TCP connection to the origin is open. Yet Cloudflare cannot reach the origin. This scenario repeats with 520 and 524 after a recent load‑balancer configuration change. The root cause is rarely the origin itself; it is usually a mismatch between what Cloudflare expects and what the origin delivers across DNS, TLS, and network layers.
How Cloudflare Internally Generates a 520, 522, or 524 Response
What Happens When a Request Hits Cloudflare
- DNS Resolution – Cloudflare resolves the CNAME to the origin IP using public DNS. A mis‑propagation or stale DNS record will cause the TCP SYN to miss the origin.
- TCP SYN/ACK – Cloudflare opens a TCP socket to port 443 (or 80). If the SYN is dropped by a firewall or the origin’s network refuses the connection, Cloudflare records a 524.
- TLS Handshake – Once TCP is established, Cloudflare performs an TLS handshake using the origin’s certificate bundle. If the certificate chain is incomplete, missing the intermediate CA, or the SNI doesn’t match the origin, the handshake times out after ~10 s, resulting in a 522.
- HTTP Request/Response – After TLS is established, Cloudflare sends the HTTP request. If the origin closes the socket before sending a valid status line, or returns a response that does not start with “HTTP/1.1” or “HTTP/2”, Cloudflare interprets this as a malformed response and returns a 520.
- Logging and Fallback – Each step is logged in Cloudflare’s dashboard and the origin’s access log (if enabled). The error code is chosen based on the first failed step, allowing engineers to isolate the problem without touching the application code.
Real‑World Example
A typical request flow looks like this in pseudo‑code:
# Cloudflare internal steps (simplified)
ORIGIN_IP=$(dig +short api.example.dev)
# TCP connect
nc -zv $ORIGIN_IP 443 # succeeds
# TLS handshake
openssl s_client -connect $ORIGIN_IP:443 -servername api.example.dev < /dev/null
# HTTP request
curl -k -i https://api.example.dev/health
If any of these steps fails, Cloudflare returns the corresponding error.
Real‑World Incident: TLS Chain Renewal Gone Wrong
Date: 2023‑09‑14
Time: 02:12 UTC
Symptom: Users reported “Cloudflare 522” on a payment‑processing endpoint.
Origin logs: curl -v https://api.example.dev/health returned 200 OK locally, TLS handshake succeeded.
Root cause: The SSL certificate uploaded to the origin’s load balancer was missing the intermediate certificate DST Root CA X3. Cloudflare’s SSL chain checker flagged the chain as incomplete, causing the handshake to abort after the default timeout.
Resolution:
- Re‑uploaded the full chain via the origin’s certificate manager.
- Purged the Cloudflare cache (
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" -H "X-Auth-Email: ...").
- Verified the chain with the free SarangAI's SSL chain checker. The chain displayed as complete, and the 522 disappeared within 4 minutes.
Key takeaway: A missing intermediate CA is the most common cause of 522 errors, even when the origin reports a successful TLS handshake.
Step‑by‑Step Remediation Walkthrough
-
Confirm DNS propagation
dig +short api.example.dev
Expected result: The resolved IP matches the origin server’s public IP. If not, run nslookup and compare with the Cloudflare DNS records; use the free DNS propagation checker on SarangAI to verify global propagation.
-
Test TCP connectivity from Cloudflare edge
curl -v --connect-timeout 5 https://api.example.dev/health
Expected result: CONNECT 93.184.216.34:443 (93.184.216.34) port 443 connected: OK. If you see curl: (52) SSL certificate problem: unable to get local issuer certificate, the chain is broken.
-
Inspect the TLS chain with OpenSSL
openssl s_client -connect api.example.dev:443 -servername api.example.dev < /dev/null 2>/dev/null | openssl x509 -noout -text | grep -A2 "Certificate Chain"
Expected result: A list of certificates ending with a trusted root (e.g., Let’s Encrypt Authority X3). Any gap indicates a missing intermediate.
-
Check origin HTTP response format
import requests, sys
try:
r = requests.get('https://api.example.dev/health', timeout=10)
print('Status:', r.status_code)
print('Headers:', dict(r.headers))
print('First 100 bytes of body:', r.text[:100])
except Exception as e:
print('Error:', e)
sys.exit(1)
Expected result: The printed status is 200 (or whatever the origin returns), and the raw response begins with HTTP/1.1 200 OK in the underlying socket data. If r.raw is empty or contains garbage, the origin is sending malformed data.
-
Validate firewall and security group rules
# Example using iptables (Linux) – replace with cloud provider CLI as needed
iptables -L INPUT -n --line-numbers | grep 443
Expected result: An allowance rule for port 443 from Cloudflare’s edge IP ranges (104.16.0.0/12, 172.64.0.0/13, 2606:4700::/32). If missing, add the rule and restart the instance.
-
Verify Cloudflare cache and settings
- Ensure “Development Mode” is off; it can cause stale edge configurations.
- Check that the origin port in Cloudflare’s origin DNS matches the listening port ().
Common Mistakes That Mask the Real Problem
- Wrong certificate bundle – Uploading only the leaf cert instead of the full chain. Correct: Include all intermediates ending with a trusted root.
- Stale DNS TTL – Setting TTL to 5 minutes after a load‑balancer change. Correct: Lower TTL to 30 seconds during changes, then increase after propagation.
- Misconfigured firewall – Blocking outbound port 443 from Cloudflare’s edge IPs. Correct: Allow
0.0.0.0/0 on port 443 or add specific Cloudflare ranges.
- Assuming 520 means origin 5xx – 520 is Cloudflare‑specific; the origin may have closed the socket. Correct: Examine the raw socket data and origin access logs for connection drops.
- Ignoring cache purges – Leaving old edge rules after a certificate update. Correct: Purge the cache and wait for the new edge configuration to propagate (typically <5 minutes).
Comparison Table: Error Codes, Typical Causes, and Quick Fixes
| Error | Typical Cause | Quick Diagnostic | Fix |
|---|
| 520 | Malformed or missing HTTP response from origin | curl -v https://origin/ shows empty response body | Ensure origin sends valid status line; disable middleware that strips headers |
| 522 | TLS handshake timeout (often missing intermediate CA) | openssl s_client -connect origin:443 prints certificate verify error | Upload complete certificate chain; re‑issue if needed |
| 524 | TCP connection timeout (firewall, routing, port mismatch) | ping -c 3 origin_ip and telnet origin_ip 443 | Open firewall rule; verify security group; confirm origin listening on correct port |
| 520 vs 5xx | 520 is Cloudflare‑specific; origin may close socket early | Compare Cloudflare error page with origin log for connection reset | Check origin’s socket handling; increase keep‑alive timeout if required |
Key Takeaways
- Cloudflare 520, 522, and 524 map directly to HTTP, TLS, and TCP layers; isolate the failing layer first.
- A missing intermediate CA is the single biggest cause of 522 errors, even when the origin reports success.
- Use the free SarangAI DNS propagation checker and SarangAI's SSL chain checker for rapid validation of DNS and TLS state.
- Verify firewall rules against Cloudflare edge IP ranges (
104.16.0.0/12, 172.64.0.0/13, 2606:4700::/32).
- Always inspect raw origin response; malformed status lines produce 520 even when the origin returns a 200.
Frequently Asked Questions
What should I check first when a 520 error appears after a recent code push?
Verify that the origin still returns a valid HTTP status line. Run a local curl -v or a Python requests call and ensure the raw socket data starts with HTTP/1.1. If the response body is empty or garbled, the issue is likely middleware stripping headers, not Cloudflare.
Why does a recent TLS certificate renewal cause a 522 error?
During renewal, the intermediate CA may be omitted from the uploaded bundle. Cloudflare’s TLS handshake fails because it cannot build a chain to a trusted root, timing out after ~10 seconds and returning a 522. Re‑upload the full chain and purge the cache.
My origin is reachable locally, yet Cloudflare reports a 524. What are the next steps?
Check outbound firewall or security group rules for TCP port 443 from Cloudflare’s edge IP ranges. Use iptables -L or cloud provider CLI to confirm the rule exists. If missing, add it and restart the instance.
How can I differentiate a true origin 5xx from a Cloudflare 520?
Origin 5xx errors are returned by the application and logged on the origin server. A 520 is generated by Cloudflare when the TCP/HTTP response is malformed or missing. Compare the Cloudflare error page (Cloudflare-Ray: ...) with the origin access logs for connection reset messages.
Which logs give the most actionable information for 520‑524 debugging?
Cloudflare dashboard logs show the exact step that failed (TCP, TLS, HTTP). Origin access logs provide the raw request/response details. Export the Cloudflare logs and pair them with the origin access log in your terminal (jq or tail -f) to correlate timestamps and isolate the failing layer faster.