Introduction

When Nginx sits behind Cloudflare, the origin sees Cloudflare edge connections by default. If the real_ip module is not configured correctly, access logs, fail2ban rules, geographic controls, and rate limiting all work against Cloudflare IPs instead of the real visitor address.

Symptoms

  • Access logs show only Cloudflare edge addresses instead of client IPs
  • Rate limiting blocks large groups of unrelated users at once
  • Security tools such as fail2ban keep banning Cloudflare IP ranges
  • The problem started after putting the site behind Cloudflare or changing proxy settings

Common Causes

  • Nginx does not trust Cloudflare proxy IP ranges
  • The wrong header is configured for real_ip_header
  • Cloudflare IP ranges were configured once but never updated
  • Real IP handling is defined in one server block but missing in another

Step-by-Step Fix

  1. 1.Confirm which IP address Nginx is logging right now
  2. 2.Check the live access log before changing the configuration so you can verify the fix later.
bash
tail -n 20 /var/log/nginx/access.log
  1. 1.Trust the Cloudflare proxy ranges and use the correct header
  2. 2.Cloudflare sends the original client address in CF-Connecting-IP, which Nginx should trust only for Cloudflare proxy ranges.
nginx
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
  1. 1.Reload Nginx and test with a fresh request
  2. 2.A config change without a reload leaves the origin serving the old behavior.
bash
nginx -t && systemctl reload nginx
curl -I https://example.com
  1. 1.Verify the logs and security controls now see the visitor IP
  2. 2.Check logs, geo rules, and rate limiting after the reload so you know downstream controls are using the corrected address.
bash
tail -n 20 /var/log/nginx/access.log

Prevention

  • Keep Cloudflare IP ranges updated as part of proxy hardening maintenance
  • Centralize real_ip configuration in shared Nginx includes
  • Re-test logging and rate limiting whenever a CDN or reverse proxy changes
  • Avoid trusting forwarded IP headers from arbitrary sources