Your website is humming along behind Cloudflare’s global content-delivery network when visitors suddenly see a stark gray screen: “Error 521 – Web Server Is Down.”
Search engines list hundreds of posts about it, yet most recycle the same four suggestions—“restart your server, check SSL, whitelist Cloudflare, contact your host.”
Those tips help, but they skip entire categories of root causes: automated firewalls that silently rate-limit the CDN, mismatched TLS modes, resource ceilings hit during traffic spikes, and platform-specific gotchas for Kubernetes or multi-origin load balancers.
This guide stitches those missing pieces together. By following the step-by-step workflow below, you’ll not only clear the immediate 521, but also harden your stack so it never returns.
What Exactly Is Error 521?
A 521 means Cloudflare tried to open a TCP connection to your origin and the origin refused it. The edge server sends a SYN packet on port 80 or 443 (or one of Cloudflare’s alternate ports). If three consecutive attempts are reset (RST) or never answered, Cloudflare stops and surfaces the error to the visitor. In other words, the CDN made it to the front door of your server but got a slammed door or stony silence in reply.
Contrast that with 522 (“Connection timed out”) where the handshake begins but stalls, or 526 (“Invalid SSL certificate”) where TLS negotiation fails; understanding these distinctions is vital because each code points to a different layer in the request path.
A Five-Step Diagnostic Workflow
Most 521 incidents disappear once you walk through the following ordered process. Work through each step, test, and stop as soon as the site loads again—no need to read the whole article at 03:00 AM.
Step 1: Confirm the origin is really online
curl -I http://<origin-IP>
curl -I https://<origin-IP> --insecureSSH into the box (or ask your host) and run
- You should see HTTP/1.1 200 OK or a purposeful redirect. Anything in the 500 range means the server itself is down; restart Apache/Nginx or open a support ticket before involving Cloudflare.
Step 2: Remove anything that blocks Cloudflare IP ranges
Firewalls, security plugins, and modules such as mod_evasive, mod_antiloris, or fail2ban often misinterpret Cloudflare’s many connections as an attack. An easy test is to pause Cloudflare (the gray-cloud icon) and load the site directly; if it works, you almost certainly have an IP-blocking problem.
Copy–paste allow rules:
# Ubuntu UFW whitelist – auto-updates the list every week
curl -s https://www.cloudflare.com/ips-v4 \
| xargs -I{} sudo ufw allow from {} to any port 80,443 proto tcp
curl -s https://www.cloudflare.com/ips-v6 \
| xargs -I{} sudo ufw allow from {} to any port 80,443 proto tcp
sudo ufw reload
Schedule the same commands weekly with cron or Ansible so new Cloudflare sub-nets are never accidentally blocked again.
Step 3: Match SSL/TLS mode with reality on the server
Cloudflare offers three HTTPS modes:
Cloudflare mode | What’s on the origin | Is it secure? |
---|---|---|
Flexible | Nothing; Cloudflare terminates SSL and talks HTTP to origin | No |
Full | Any certificate, even self-signed | Medium |
Full (Strict) | Valid cert or Cloudflare Origin CA cert | Best |
An origin that expects Full (Strict) but is paired with Flexible will refuse the initial handshake, leading Cloudflare to believe the web server is “down.” Fix by installing a valid certificate (Cloudflare Origin CA is free and lasts 15 years) or selecting the TLS mode that matches what you already have. Verify with:
openssl s_client -connect example.com:443 -servername example.com -tls1_2
Look for a clean certificate chain and an SSL-Session that ends with Verify return code: 0 (ok).
Step 4: Check DNS and listening ports
Make sure your A or AAAA record in Cloudflare points to the correct, unproxied origin IP and that the orange-cloud proxy is enabled. On the machine itself run:
sudo lsof -nPiTCP:80,443
You should see your web-server service listening. If you operate on a non-standard port, remember Cloudflare only proxies a limited list (2052/2053/2082/2083/2086/2087/2095/2096/8443).
Step 5: Inspect resource limits and current load
Sometimes the origin refuses new sockets simply because it is overwhelmed. Check:
- CPU/RAM: htop or your hosting panel
- Open files: ulimit -n, sysctl fs.file-max
- Apache: MaxRequestWorkers, ServerLimit
- Nginx: worker_connections, worker_rlimit_nofile
- PHP-FPM: pm.max_children
If metrics spike to 100 % during 521 events, upgrade resources or deploy a cache/warming strategy.
Deep-Dive Fixes Other Guides Skip
Step 1: Granular firewall snippets for every stack
Most tutorials tell you to “whitelist Cloudflare,” but admins still hunt through docs for the right syntax. Below are turnkey rules:
#!/usr/bin/env bash
# 3.1 Whitelist Cloudflare (iptables)
set -euo pipefail # safer scripting
# --- IPv4 ---------------------------------------------------------------
for cf_ip in $(curl -fsSL https://www.cloudflare.com/ips-v4); do
iptables -I INPUT -p tcp -s "$cf_ip" --dport 80 -j ACCEPT
iptables -I INPUT -p tcp -s "$cf_ip" --dport 443 -j ACCEPT
done
# --- IPv6 (optional) ----------------------------------------------------
for cf_ip in $(curl -fsSL https://www.cloudflare.com/ips-v6); do
ip6tables -I INPUT -p tcp -s "$cf_ip" --dport 80 -j ACCEPT
ip6tables -I INPUT -p tcp -s "$cf_ip" --dport 443 -j ACCEPT
done
# --- Persist the rules --------------------------------------------------
service netfilter-persistent save # Debian/Ubuntu; adjust for your distro
- CSF (ConfigServer Security & Firewall) – add lines like
tcp|in|d=443|s=173.245.48.0/20 to /etc/csf/csf.allow.
cPanel & Plesk – open “IP Blocker” → Trusted IPs and paste the list.
Running a managed WordPress host? Open a ticket linking to Cloudflare’s JSON feed so the NOC team can automate the import.
Step 2: A visual SSL/TLS decision tree
Readers often stare at Cloudflare’s five TLS toggles and freeze. Embed a one-screen PNG (or interactive SVG) that starts with the question “Do I have any certificate installed at the origin?” and ends with the exact mode to pick. Adding a small screenshot of the Cloudflare dashboard plus an openssl command makes the abstract concrete.
Step 3: Origin log cheat-sheet
Platform | Log file | 521 symptom to grep |
Apache (cPanel) | /etc/apache2/logs/error_log | AH01630: client denied by server configuration (173.245.*) |
Nginx (Ubuntu) | /var/log/nginx/error.log | access forbidden by rule |
LiteSpeed | /usr/local/lsws/logs/error.log | ModSecurity: Access denied |
IIS | C:\\inetpub\\logs\\LogFiles\\W3SVC1\\u_exYYMMDD.log | 403 1 0 after a Cloudflare IP |
Pair the timestamp with the Ray ID from the visitor’s error screen, and you’ll pinpoint the offending rule in seconds.
Step 4: Shared hosting versus VPS/bare-metal
Shared customers rarely have root. Emphasize GUI-level solutions—“disable ModSecurity in cPanel” or “use the host’s ‘Restart PHP’ button”—while highlighting root-level commands for VPS owners. Two color-coded callouts help readers leap to the track that applies to them, boosting dwell time and reducing bounce.
Step 5: Preventive monitoring and alerts
Don’t wait for a customer tweet to discover 521s:
- Cloudflare Health Monitor – free synthetic origin checks with Slack hooks.
- UptimeRobot – probe both the orange-cloud hostname and the raw origin IP every minute.
- Always Online – Cloudflare can serve the Wayback cached copy for brief outages.
Custom cron watchdog:
#!/usr/bin/env bash
URL=https://example.com
[[ $(curl -s -o /dev/null -w "%{http_code}" $URL) == 521 ]] && \
( systemctl restart nginx; logger -t cf-521 "Restarted Nginx after 521" )
- Log to syslog so Grafana or New Relic can visualize patterns.
Case Study: Black Friday Traffic Spike
Site: a WooCommerce store on a 2-vCPU VPS, Cloudflare Pro
Time: 24 Nov 2024, 10:02 UTC
Incident: Conversion tracking flagged a 40 % checkout drop; visitors saw 521 intermittently.
Investigation:
- Cloudflare Error Analytics revealed 3,100 spikes of 521 in five minutes.
- netstat -an | grep :443 | wc -l showed 55 sockets—beyond the Nginx worker_connections 50 limit.
- journalctl uncovered mod_evasive: Denying 173.245.49.28.
Fix:
- Raised worker_connections to 2 048 and set worker_rlimit_nofile to 4 096.
- Disabled Mod_Evasive for the published Cloudflare IP list.
- Temporarily scaled the VPS to 4 vCPU during the sale window.
The store processed 17 % more orders than the previous year, with zero 521s for the rest of Black Friday.
Ongoing Hygiene: Never See 521 Again
- Patch weekly. Out-of-date OpenSSL or nginx packages introduce TLS bugs that look like refusals.
- Automate IP imports. A two-line cron pulling the JSON feed prevents next month’s new /15 block from tripping rate-limits.
- Load-test quarterly. Tools like k6 or ApacheBench reveal how many concurrent Cloudflare sockets your stack can handle.
- Document your baseline. CPU < 40 %, 95th-percentile memory, normal Ray ID counts. Abnormalities will jump off the dashboard.
Advanced Troubleshooting for Modern Stacks
Kubernetes + Nginx Ingress
Because Cloudflare acts as the client, Nginx Ingress sees the connection coming from the edge, not the real visitor’s IP. If you enable source-range security controls, set:
controller:
config:
proxy-real-ip-cidr: 173.245.48.0/20,103.21.244.0/22,2400:cb00::/32
real-ip-header: CF-Connecting-IP
Otherwise the controller returns 403, Cloudflare records a refusal, and visitors see 521.
Cloudflare Load Balancing
Pool health checks must reach at least one origin. When all nodes in a pool fail health probes, Cloudflare surfaces a 521 even if individual nodes are up but blocking probes. Verify under Traffic → Load Balancing → Analytics, and ensure probes originate from the same IP ranges you whitelisted.
HTTP/3 (QUIC)
A 521 looks identical over QUIC because the refusal happens before any protocol negotiation. To rule out version-level issues, run:
curl --http3 -I https://example.com
If the command fails while HTTP/2 succeeds, your origin might lack ALPN h3. Disable HTTP/3 in Network → HTTP/3 (with QUIC) or upgrade the origin stack.
Conclusion
Error 521 is blunt: Cloudflare knocked, your server refused.
Resolve it just as bluntly:
- Prove the origin is listening.
- Stop your firewall from treating Cloudflare as hostile.
- Speak the same TLS dialect.
- Make sure resources and DNS point the right way.
Add a weekly script to auto-import Cloudflare’s ever-expanding IP list and a one-minute health probe, and chances are you’ll never see a 521 crash a campaign again. Bookmark this guide, and then go set that cron job before you forget.
Frequently Asked Questions

Is a 521 a sign of a DDoS attack?
Usually not. A volumetric attack might trigger your firewall, which then blocks Cloudflare and indirectly causes 521, but the error itself is only Cloudflare reporting a refusal.
How long until DNS changes eliminate a 521?
With a low TTL (300 s) most recursive resolvers refresh within five minutes, but some ISPs pin records for up to an hour. Test with dig +trace to confirm propagation.
Do I need a paid Cloudflare plan to fix 521?
No. All troubleshooting steps work on the free tier. Paid tiers add nicer dashboards, Load Balancing, and long-term Error Analytics, but the root fix is always on your server.
Can Always Online hide 521 from visitors?
It can serve a cached snapshot, but dynamic content (carts, checkouts) remains unavailable. Consider it an emergency band-aid, not a cure.