Fix Cloudflare 521 and 522 Errors for a Django Origin

Fix Cloudflare Error 521 web server is down and Error 522 connection timed out in front of Django: check that Nginx listens, allow Cloudflare IPs through the firewall, match the SSL mode to the origin, and fix origin DNS records.

Problem statement

Visitors see a Cloudflare error page instead of your Django site:

  • Error 521: Web server is down โ€” Cloudflare reached your server's IP, but the connection was refused.
  • Error 522: Connection timed out โ€” Cloudflare could not complete a TCP connection to your server at all.

Both are about the network path from Cloudflare to your origin, before Nginx or Django handle anything. A 521 means nothing accepted the connection on the port Cloudflare used (80 or 443). A 522 means packets were dropped: a firewall blocking Cloudflare's IPs, a wrong origin IP in DNS, or a server too overloaded to accept connections.

Where the connection failsVisitorreaches CloudflareCloudflareconnects to origin IPOrigin port80 or 443521 or 522refused or dropped521 means refused on the port; 522 means the packets never got an answer.
  1. Check the origin IP in Cloudflare DNS matches the server's current public IP.
  2. 521: make sure Nginx is running and listening on the port your SSL mode uses (443 for Full, 80 for Flexible).
  3. 522: allow Cloudflare's IP ranges on ports 80 and 443 in ufw and the cloud firewall, and remove rate-limits or fail2ban bans on them.
  4. Set SSL/TLS mode to Full (strict) and install a valid origin certificate.
  5. If the server is overloaded, fix capacity; Cloudflare times out connections it cannot open in about 15 seconds.

Step-by-step solution

1. Test the origin directly

Bypass Cloudflare by connecting to the origin IP with the right Host and SNI:

curl -svo /dev/null --resolve example.com:443:203.0.113.10 https://example.com/
curl -svo /dev/null --resolve example.com:80:203.0.113.10 http://example.com/

Connection refused reproduces a 521; a timeout reproduces a 522 (from your network, which may be allowed where Cloudflare is not). Compare the IP with the A record in the Cloudflare dashboard; after rebuilding a server, the DNS record often still points at the old one.

2. Fix 521: something must listen

sudo systemctl status nginx
sudo ss -ltnp | grep -E ':(80|443) '

Match the listener to the SSL mode:

  • Full / Full (strict): Cloudflare connects to port 443. Nginx needs a listen 443 ssl block with a certificate.
  • Flexible: Cloudflare connects to port 80. (Avoid Flexible; see below.)

If Nginx listens only on 80 and the zone uses Full, every request is a 521.

what the origin is doingSymptom at originCause and fix521, nothing on :443SSL mode Full but noTLS listener; add one521, Nginx stoppedservice down or failedconfig; start and test522, firewall drops CF IPsallow Cloudflare ranges on 80 and 443522, wrong A recordDNS still points at an old server IP522 under load onlyserver cannot acceptconnections; add capacityTest the origin with curl --resolve to see what Cloudflare seesdjango-deployment.com
A 521 is a refusal you can see locally; a 522 is often a firewall that only blocks Cloudflare.

3. Fix 522: let Cloudflare through

Allow Cloudflare's published ranges (from https://www.cloudflare.com/ips-v4 and ips-v6) on 80 and 443:

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 80,443
done

Also check the provider firewall or security group, and any IP blocking you added: fail2ban jails that ban by $remote_addr will ban Cloudflare edge IPs unless Nginx restores the real client IP first, and Nginx limit_req zones keyed on the connecting IP throttle Cloudflare as one huge client. Restore real IPs:

# /etc/nginx/conf.d/cloudflare-realip.conf  (regenerate when Cloudflare updates its list)
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 2400:cb00::/32;
# ... all ranges ...
real_ip_header CF-Connecting-IP;

4. Use Full (strict) SSL

Flexible mode sends traffic from Cloudflare to your origin over plain HTTP, which also causes redirect loops with SECURE_SSL_REDIRECT. Use Full (strict) with either a Let's Encrypt certificate or a free Cloudflare Origin CA certificate on Nginx, plus:

SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")

5. Check capacity

If 522s appear only at peaks, the server's accept queue overflows or Nginx runs out of worker connections. Check dmesg for SYN flooding messages, Nginx worker_connections, and CPU. Cloudflare's caching of static assets and anonymous pages can reduce origin load substantially.

an origin Cloudflare can always reachA record points at the current serverupdate after rebuildsNginx listens on 443 with a valid certSSL mode Full (strict)Cloudflare IP ranges allowedufw and cloud firewallReal client IP restored in NginxCF-Connecting-IPBans and rate limits use the real IPnever ban Cloudflare edgesMost 52x errors come from one of these five being out of datedjango-deployment.com
Keep the IP list in configuration management so it stays current.

Verification check: the curl --resolve tests succeed against port 443, Cloudflare's dashboard shows no 52x errors in Analytics, and tail -f /var/log/nginx/access.log shows real visitor IPs, not Cloudflare ranges.

Explanation

Cloudflare acts as a reverse proxy: visitors connect to its edge, and the edge opens its own connection to your origin. Errors in the 52x range describe that second connection. A 521 is an active refusal (TCP reset), meaning the host answered but nothing listens on the port. A 522 means the TCP handshake never completed, so packets were dropped or the host is unreachable. Because Cloudflare connects from its own IP ranges, a firewall that allows your office but not those ranges produces a 522 that you cannot reproduce from your desk.

Edge cases / notes

  • Error 520 is an unknown error: the origin returned something empty or invalid, often a crashed upstream behind Nginx.
  • Error 523 means the origin is unreachable at the routing level, usually a wrong IP; 525 and 526 are TLS handshake and certificate validation failures.
  • Locked-down origins that only accept Cloudflare can use Authenticated Origin Pulls or a Cloudflare Tunnel instead of IP lists.
  • IPv6. If your A record is fine but an AAAA record points at an address without a listener, some connections fail.

Next steps

FAQ

What is the difference between Cloudflare 521 and 522?

521 means your server refused the connection; 522 means the connection attempt timed out with no answer.

Why can I reach my server but Cloudflare cannot?

Your firewall may allow your IP but not Cloudflare's ranges, or fail2ban may have banned Cloudflare edge IPs.

Should I use Flexible SSL?

No. Use Full (strict) with a certificate on the origin. Flexible sends traffic unencrypted and causes redirect loops.

Do I need to allow Cloudflare IPs?

If your firewall restricts inbound web traffic, yes. Otherwise Cloudflare cannot reach your origin.

Keep going