How to get X-Forwarded-For IP addresses in Nginx
X-Forwarded-For (XFF) is a special HTTP header field that is used to identify the originating client IP address, regardless of whether connecting through a proxy, load balancer, or other such service. Normally, when you have something like a load balancer intercepting traffic to your website and then forwarding it to your back end server, the back end server will interpret all traffic it receives as coming from the load balancer. However, it can be easy to see how what you really want is to know the address of the client, and not your own load balancer. In order to obtain the actual client’s IP address, for example to use for geolocation data, you will need to enable usage of the X-Forwarded-For header field when determining the client IP address.
This brief tutorial will cover how you can enable usage of X-Forwarded-For in your Nginx server with a few simple configurations.
X-Forwarded-For in the Real World
Before we begin the tutorial, let’s discuss a possible real-world application of using X-Forwarded-For. The service CloudFlare, used for protection against Distributed Denial of Service (DDoS) attacks, is a popular use case.
To protect your server, CloudFlare actually acts as a reverse proxy. This means that instead of all requests going directly to your web server, they all first go to the CloudFlare servers. At this point, CloudFlare is receiving the actual client’s IP address in their header information. After the requests sent by the client are determined to be safe, the CloudFlare server will then forward the requests to your server. Here however, your server will see the IP address of the CloudFlare server as the originating client.
In the case that your web application uses the originating IP of the visitor as part of its logic or for geolocation data, the usage of the CloudFlare server’s IP address will essentially break down how your application needs the data. If you were to open the access logs on your server, you would quickly see the root of the problem: all originating requests appear to be coming from the CloudFlare server, with no actual client IP addresses in sight.
If you then use a security service such as CloudFlare or a load balancer such as HAProxy, you will encounter this issue unless you take the X-Forwarded-For IP header field into account. All intermediary services such as CloudFlare must include the originating client IP address that they receive in the X-Forwarded-For IP field, as is industry standard. This makes the solution very simple: all you need to do is configure your server to use the client information from X-Forwarded-For IP when processing data, and not the client IP address it is receiving directly.
Nginx Setup: Compiling with the RealIP Module
Nginx is a web server that can act as a reverse proxy as well as a load balancer. If you are using Nginx, you will need to modify it in order to make use of the X-Forwarded-For request header field. For your Nginx web server to use the real customer IP address instead of the proxy address (or the CloudFlare server address), we will need to enable a module known as ngx_http_realip_module, which can be referred to as the RealIP module. This module is responsible for telling your Nginx server which information to use from incoming requests when determining the client IP address.
To start using ngx_http_realip_module, you will need to compile it with Nginx as it is not built by default. For all modules that are not included in Nginx, you will need to recompile your entire web server to include them.
You can enable ngx_http_realip_module in the Nginx build using the configuration parameter –with-http_realip_module when recompiling Nginx. Note that the previously installed Nginx will be overwritten, so you will need to make sure that when recompiling you do not forget to include all previous configuration parameters that you used in your setup.
Obtain the archived TAR file of your desired Nginx version (which can be found online at the Nginx downloads page) and unpack it in any directory. In the unpacked, newly-created Nginx directory, execute the following to build Nginx alongside with the RealIP module:
If you need to specify multiple modules for Nginx, you will instead need to use syntax like the following example when running the configuration script (the first code line in the step above). Notice how we separated each module we want to include in the Nginx build with a space. You can find more information about what options are available during the build process for Nginx in the official documentation:
./configure --with-http_realip_module --with-http_ssl_module
When Nginx has finished compiling and installing, you will be able to use the X-Forwarded-For header field. If your landscape uses a chain of proxies, this header field will contain information like the following:
X-Forwarded-For: client, first_proxy, second_proxy, n_proxy
Nginx Setup: Configuring Intermediary Service Addresses
To tell Nginx to start using X-Forwarded-For, you will have to edit the Nginx configuration file. This Nginx configuration file is named nginx.conf and by default is placed in one of the following three directories depending on your exact landscape:
Open the file in a text editor such as nano after navigating to its directory:
Within this file, we can add some lines to tell Nginx to use X-Fowarded-For as the client IP address. If we wanted to set the real IP address for traffic coming from a server with the IP address 192.168.1.10 for example, the lines we add would look as follows:
You can add as many definitions as you want for the proxy addresses by using the set_real_ip_from line. To add two proxies for example, your configuration file would contain something like the following:
When you are satisfied with the proxies you have added, save and close the file.
Nginx Setup: Verifying & Testing
To verify that the Nginx configuration has no issues, you can use a special command option provided by Nginx. The -t option tells Nginx to check the configuration file for proper syntax, try to open the files the configuration refers to, but not actually run the server. If you find errors, please go back and review that there are no spelling mistakes and all files are in the right place.
When you have confirmed that your configuration uses correct syntax, you will now need to reload the Nginx server for your changes to be made. Execute the following command to reload nginx as the root user. If you are not root, but are a user possessing superuser (sudoer) privileges, append the command sudo to the start of the line.
systemctl reload nginx
Depending on your landscape, you may instead need to use the following command to reload Nginx (again as root or using sudo):
service nginx reload
To test your setup is working correctly, simply visit your back end server from a different node a few times and then check its access logs. If the logs show your IP address instead of your intermediary service such as CloudFlare, your setup is successful.
Congratulations! Now that your Nginx server will be correctly identifying the originating client IP address as stated in the X-Forwarded-For header field instead of the possible proxy or other intermediary service IP address, your landscape is more resilient and able to handle consequences of using intermediaries. If this guide was helpful to you, share it with others who may also be interested in learning about using X-Forwarded-For.