TL;DR: The Fast Fix
If your logs are flooded with proxy IPs, you need the ngx_http_realip_module. Add these lines to your Nginx configuration—usually within the http or server block—to tell Nginx which sources to trust:
# Trust Cloudflare's IP ranges
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
# ... add other ranges as needed ...
# Define the header containing the real IP
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
Apply the changes with sudo nginx -s reload.
Why Is This Happening?
When you put Nginx behind a service like Cloudflare or an AWS Load Balancer, the direct TCP connection comes from the proxy's IP. By default, Nginx records this immediate neighbor as the client. This leaves your logs showing 172.x.x.x or 10.x.x.x addresses instead of the person actually browsing your site.
Proxies usually pass the original IP along in a special HTTP header. Common ones include X-Forwarded-For or CF-Connecting-IP. Your job is to tell Nginx to ignore the proxy's IP and use the value from that header instead.
Step-by-Step Configuration
1. Check for Module Support
Most modern Nginx builds include the real_ip module out of the box. You can verify yours by running this command:
nginx -V 2>&1 | grep --color 'with-http_realip_module'
If the output highlights --with-http_realip_module, you are ready to go. If not, you may need to install the nginx-extras package or recompile from source.
2. Whitelist Your Trusted Proxies
Security matters here. You should only trust IP headers from sources you actually control or use. Whitelisting prevents "IP spoofing," where a malicious user sends a fake header to hide their identity.
Scenario A: Working with Cloudflare
Cloudflare uses specific IP ranges. Create a dedicated config file at /etc/nginx/conf.d/cloudflare.conf to keep things clean:
# Cloudflare IPv4 ranges (Partial list for example)
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
# Cloudflare IPv6 ranges
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
# Cloudflare always sends the real IP in this header
real_ip_header CF-Connecting-IP;
Scenario B: Behind an AWS ALB or HAProxy
If you are using an internal Load Balancer, use your VPC CIDR (e.g., 172.31.0.0/16) or the specific private IP of the balancer:
set_real_ip_from 172.31.0.0/16; # Example AWS VPC range
set_real_ip_from 10.0.0.0/8; # Internal network
real_ip_header X-Forwarded-For;
real_ip_recursive on;
Pro tip: Always use real_ip_recursive on; if you have multiple layers, like Cloudflare hitting an AWS ALB which then hits Nginx. This tells Nginx to look through the entire list of IPs in the header and pick the last one that isn't in your trusted list.
3. Adjust Your Log Format
Once real_ip is active, the standard $remote_addr variable updates automatically. If you use a custom log format, ensure it references $remote_addr. A typical setup in nginx.conf looks like this:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
How to Verify the Fix
Check the Access Logs
Open a terminal and watch your logs in real-time:
tail -f /var/log/nginx/access.log
Visit your website from your phone or a VPN. You should now see your actual public IP (e.g., 1.2.3.4) instead of a local 10.x.x.x address.
The Script Method
Drop a simple info.php file in your web directory to see what Nginx is passing to your application:
<?php
echo "Real IP: " . $_SERVER['REMOTE_ADDR'];
?>
Common Mistakes to Avoid
- **Trusting the whole world:** Never use `set_real_ip_from 0.0.0.0/0;`. Doing this allows anyone to fake their IP address just by adding an `X-Forwarded-For` header to their request.
- **Forgetting IPv6:** If your visitors use IPv6 but you only whitelisted IPv4 ranges, the logs will revert to showing the proxy IP for those users.
- **Stale IP lists:** Cloudflare updates their ranges every few months. Consider using a script to pull the latest IPs from `https://www.cloudflare.com/ips-v4` automatically.

