NGINX X-REAL-IP and X-FORWARDED-FOR: How to get the real IP address of a client

Updated: January 22, 2024 By: Guest Contributor Post a comment

Introduction

Understanding a client’s real IP address is crucial for server administration, security, and analytics. When an NGINX server sits behind a reverse proxy or load balancer, obtaining the client’s original IP address can be challenging. In this tutorial, we’ll dive into how we can use NGINX directive like X-REAL-IP and X-FORWARDED-FOR to retrieve a client’s real IP address.

Each header definition

X-REAL-IP: Is a non-standard header commonly used to determine a client’s real IP address. This header is added by some proxies to indicate the source/client IP address, regardless of how many layers of proxy are in between.

X-FORWARDED-FOR: Is a de-facto standard header for identifying the originating IP address of a client connecting through an HTTP proxy or load balancer.

Configuring nginx to log real IP

To make NGINX log the correct client IP address, you need to set it up to trust the proxy in front of it. This is done using the set_real_ip_from and the real_ip_header directives in your configuration.

set_real_ip_from 192.168.1.0/24; # Your proxy's subnet
real_ip_header   X-Real-IP;

You would add those lines to the respective location block, server block, or http block depending on the scope you want them to have.

Log Format Configuration

To see these changes reflected in the logs, include $remote_addr or the custom variable $http_x_real_ip you might set up in the log_format directive:

log_format main '$remote_addr - $remote_user [$time_local] "$request" ';

After making these changes, restart NGINX for the changes to take effect:

sudo systemctl restart nginx

Dealing with Multiple IP Addresses in X-FORWARDED-FOR

The X-FORWARDED-FOR can contain multiple IP addresses if the request has passed through multiple proxies. NGINX has the real_ip_recursive directive to deal with this situation.

real_ip_header   X-Forwarded-For;
real_ip_recursive on;

This ensures NGINX uses the last non-trusted IP address in the X-FORWARDED-FOR list.

Working with Real IP in Application Code

In application code, such as PHP, node.js, or Python, use the server variables to access these headers and thus the real IP:

PHP:

$real_ip = $_SERVER['HTTP_X_REAL_IP'] OR $_SERVER['REMOTE_ADDR'];

Node.js with Express:

const realIp = req.headers['x-real-ip'] || req.connection.remoteAddress;

Python with Flask:

real_ip = request.headers.get('X-Real-IP') or request.remote_addr

Security Considerations

It is critical to only trust proxies that you control. Trusting arbitrary proxies can allow an attacker to spoof an IP address. So, make sure to keep your set_real_ip_from configurations accurate to your infrastructure.

Conclusion

By following this tutorial, you have improved your understanding of NGINX’s X-REAL-IP and X-FORWARDED-FOR headers. You can now configure NGINX to log and use a client’s real IP address effectively, which enhances the ability to track and analyze traffic accurately, implement security measures and troubleshooting.