All Products
Search
Document Center

Web Application Firewall:Retrieve real client IP from an HTTP header

Last Updated:Sep 11, 2026

When you use CNAME integration for Web Application Firewall (WAF), the source IP address of requests received by your origin server is the IP of the last-hop proxy, not the real client IP. WAF adds the X-Forwarded-For HTTP request header to pass the real client IP to your server. This topic describes how to configure your backend web servers to extract the client's IP from this header, ensuring that your logging and security audits work correctly.

How it works

After you use CNAME access to connect your domain to WAF, client requests are first routed through WAF and possibly other intermediate proxies (such as CDN or Anti-DDoS Pro) before they reach the origin server. At this point, the source IP address of the TCP connection received by the origin server is the IP address of the last-hop proxy, not the actual client IP address.

When WAF forwards HTTP requests, it automatically adds the X-Forwarded-For header field. The initial value of this field is the client IP address. Each time the request passes through a proxy node, the IP address of that node is appended to the end of the field in the following format:

X-Forwarded-For: client IP, proxy 1 IP, proxy 2 IP, …

Therefore, you must configure the backend web server to extract the leftmost IP address from the X-Forwarded-For header, which is the original client IP address. The following sections describe the configuration methods for different platforms.

Step 1: Obtain the WAF back-to-origin IP ranges

Log on to the Web Application Firewall console. In the top navigation bar, select the resource group and region of your WAF instance (Chinese Mainland or Outside Chinese Mainland). Then, click Onboarding > CNAME Record > View Back-to-origin CIDR Blocks and record all WAF back-to-origin IP ranges for later configuration.

Step 2: Configure the origin server

Important

Before you configure the origin server, back up the environment by creating ECS snapshots or backing up configuration files to prevent configuration loss.

Configure Nginx

Nginx uses the http_realip_module module to parse X-Forwarded-For. Perform the following steps to modify the Nginx configuration.

Check whether http_realip_module is installed

Log on to the server and run the following command:

nginx -V 2>&1 | grep -o with-http_realip_module
Note

Versions installed using yum install nginx or apt install nginx typically include this module. Custom-compiled versions or minimal container images may not.

Add the realip module (only if missing)

Method 1: Reinstall using the system package manager

# For Alibaba Cloud Linux / CentOS / RHEL
sudo yum reinstall nginx -y
# For Ubuntu / Debian
sudo apt install --reinstall nginx-core nginx-full

Method 2: Compile from source code

  1. Install dependencies.

    # For Alibaba Cloud Linux / CentOS / RHEL
    sudo yum install -y gcc pcre-devel zlib-devel openssl-devel
    # For Ubuntu / Debian
    sudo apt update
    sudo apt install -y build-essential libpcre3-dev zlib1g-dev libssl-dev
  2. Check the installed Nginx version.

    # Check the version to download the matching source code.
    nginx -v
    # Check the current configure arguments.
    nginx -V 2>&1 | grep 'configure arguments' | sed 's/configure arguments: //'

    Record the output, for example, --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module.

  3. Download the Nginx source code for the corresponding version. Replace the version number with the actual one.

    cd /tmp
    wget http://nginx.org/download/nginx-1.26.0.tar.gz
    tar zxvf nginx-1.26.0.tar.gz
    cd nginx-1.26.0
  4. Configure the compilation arguments. Copy the original arguments from Step 2 and append --with-http_realip_module at the end.

    ./configure \
      --prefix=/usr/local/nginx \
      --with-http_ssl_module \
      --with-http_v2_module \
      --with-http_realip_module
  5. Compile and upgrade the service.

    make
    # The make command creates a new nginx binary in the objs/ directory.
    # Back up the old binary.
    sudo mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
    # Replace the old binary with the new one.
    sudo cp objs/nginx /usr/local/nginx/sbin/nginx
    # Get the PID of the old master process.
    OLD_PID=$(pgrep -f 'nginx: master' | head -1)
    # Start the new master process.
    sudo kill -USR2 $OLD_PID
    # Wait for the new process to start.
    sleep 2
    # Gracefully shut down the old worker processes.
    sudo kill -QUIT $OLD_PID

Configure Nginx to trust WAF back-to-origin IP ranges

  1. Edit the main configuration file nginx.conf (default location: /etc/nginx/nginx.conf) and add the following content to the http {} block.

    http {
      # Trust the X-Forwarded-For header from requests sent by WAF.
      # Replace the following placeholders with the WAF back-to-origin IP ranges you obtained from the console.
      # You must add all IP ranges. If any are missing, some requests might still log the WAF IP instead of the real client IP.
      set_real_ip_from    <ip_range1>;    
      set_real_ip_from    <ip_range2>;   
      ...
      set_real_ip_from    <ip_rangex>;
      # Tell Nginx to use the X-Forwarded-For header to find the real client IP.
      real_ip_header      X-Forwarded-For;
    }
  2. Reload the Nginx configuration:

    nginx -t && nginx -s reload

Verify the configuration

  1. Access the website. Replace http://your-domain.com/ with the domain name that is connected to WAF.

    curl http://your-domain.com/
  2. View the Nginx access logs. The real client IP address should be displayed.

    tail -f /var/log/nginx/access.log

Configure IIS 7 (applicable to IIS 7 and later)

When WAF acts as a reverse proxy, the c-ip field in the default IIS logs records the WAF back-to-origin IP instead of the actual client IP. You can use the W3C custom log field feature in IIS to write the X-Forwarded-For request header to the logs for auditing and troubleshooting purposes.

  1. Open IIS Manager. In the left-side Connections tree, expand the server node and select the target website (for example, Default Web Site).

  2. In the Features View pane on the right, double-click the Logging icon.

  3. In the Log Files section, make sure that the Format is set to W3C (the default value). If a different format is selected, change it to W3C.

  4. In the Log Files section, click Select Fields....

  5. At the bottom of the dialog box that appears, click Add Field....

  6. In the Add Custom Field dialog box, enter the following information and click OK.

    Parameter

    Description

    Field Name

    Enter X-FORWARDED-FOR

    Source Type

    Select Request Header

    Source

    Enter X-Forwarded-For

  7. Click OK to save the custom field.

  8. Click OK again to close the logging fields window, and then click Apply in the Actions pane to save the changes.

  9. Restart IIS for the changes to take effect.

  10. Access the website to verify the configuration, and view the access logs (default path: C:\inetpub\logs\LogFiles\W3SVC1\). The real client IP address should be displayed.

Configure Apache

Apache 2.4 and later includes the remoteip_module (mod_remoteip.so), which can be used to obtain the real client IP address.

Alibaba Cloud Linux / CentOS / RHEL

  1. Edit the main Apache configuration file.

    sudo vim /etc/httpd/conf/httpd.conf
  2. Add the following content to the end of the file.

    # Enable mod_remoteip.
    LoadModule remoteip_module modules/mod_remoteip.so
    # Specify that the real client IP is passed in the X-Forwarded-For header.
    RemoteIPHeader X-Forwarded-For
    # Add the WAF back-to-origin IP ranges as trusted proxies. 
    # Replace these with your actual IP ranges.
    RemoteIPTrustedProxy 100.xx.xx.0/10
    RemoteIPTrustedProxy 11.xx.xx.0/13
    RemoteIPTrustedProxy 112.xx.xx.0/16
  3. Navigate to the log format section of the configuration file and change %h to %a. %a represents the remote IP address of the connection (the real client IP address corrected by mod_remoteip), and %h is the original connection IP address (the WAF node IP address). An example of the modified configuration is shown below.

    <IfModule log_config_module>
        #
        # The following directives define some format nicknames for use with
        # a CustomLog directive (see below).
        #
        LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
        LogFormat "%a %l %u %t \"%r\" %>s %b" common
        <IfModule logio_module>
          # You need to enable mod_logio.c to use %I and %O
          LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
        </IfModule>
        #
        # The location and format of the access logfile (Common Logfile Format).
        # If you do not define any access logfiles within a <VirtualHost>
        # container, they will be logged here.  Contrariwise, if you *do*
        # define per-<VirtualHost> access logfiles, transactions will be
        # logged therein and *not* in this file.
        #
        #CustomLog "logs/access_log" common
        #
        # If you prefer a logfile with access, agent, and referer information
        # (Combined Logfile Format) you can use the following directive.
        #
        CustomLog "logs/access_log" combined
    </IfModule>
  4. Restart Apache for the changes to take effect.

    sudo systemctl restart httpd
  5. Access the website to verify the configuration, and view the access logs. The real client IP address should be displayed.

    tail -f /var/log/httpd/access_log

Ubuntu / Debian

  1. Enable the remoteip module.

    sudo a2enmod remoteip
  2. Edit the main Apache configuration file.

    sudo vim /etc/apache2/apache2.conf
  3. Add the following content to the end of the file.

    # Specify that the real client IP is passed in the X-Forwarded-For header.
    RemoteIPHeader X-Forwarded-For
    # Add the WAF back-to-origin IP ranges as trusted proxies.
    # Replace these with your actual IP ranges.
    RemoteIPTrustedProxy 100.xx.xx.0/10
    RemoteIPTrustedProxy 11.xx.xx.0/13
    RemoteIPTrustedProxy 112.xx.xx.0/16
  4. Navigate to the log format section of the configuration file and change %h to %a. %a represents the real client IP address that is corrected by mod_remoteip, while %h represents the original connection IP address (the IP address of the WAF node). An example of the modified configuration is shown below.

    #
    LogFormat "%v:%p %a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
    LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%a %l %u %t \"%r\" %>s %O" common
    LogFormat "%{Referer}i -> %U" referer
    LogFormat "%{User-agent}i" agent
  5. Restart Apache for the changes to take effect.

    sudo systemctl restart apache2
  6. Access the website to verify the configuration, and view the access logs. The real client IP address should be displayed.

    tail -f /var/log/apache2/access.log

Configure Tomcat

Tomcat can obtain the real client IP address by enabling the X-Forwarded-For feature.

  1. Go to the Tomcat installation directory and open the tomcat/conf/server.xml configuration file.

  2. Modify the AccessLogValve log configuration to the following:

    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    prefix="localhost_access_log." suffix=".txt"
    pattern="%{X-FORWARDED-FOR}i %l %u %t %r %s %b %D %q %{User-Agent}i %T" resolveHosts="false"/>
  3. Restart Tomcat.

    sudo systemctl restart tomcat
  4. Access the website to verify the configuration, and view the access logs. The real client IP address should be displayed.

    # Replace the following command with the actual Tomcat installation directory path and the actual log file
    tail -f /opt/tomcat/logs/localhost_access_log.2026-01-01.txt 

Configure a Kubernetes cluster

When a Kubernetes cluster that uses the Nginx Ingress Controller is connected to WAF, the real client IP address is added by WAF to the X-Forwarded-For request header. By default, the Nginx Ingress Controller does not trust this field, and business containers cannot obtain the real client IP address.

Perform the following steps to configure the Nginx Ingress Controller.

  1. Edit the ConfigMap of the Ingress Controller:

    kubectl -n kube-system edit cm nginx-configuration
  2. Add the following configuration items to the data field:

    compute-full-forwarded-for: "true"
    forwarded-for-header: "X-Forwarded-For"
    use-forwarded-headers: "true"
  3. Save and exit. The configuration automatically takes effect without the need to restart pods.

    After the configuration is complete, the Ingress Controller identifies the first IP address in X-Forwarded-For as the real client IP address and retains this value when forwarding requests.

Advanced optimization: Pass the real IP address by using a custom header

In complex network architectures, relying on the standard X-Forwarded-For (XFF) header carries risks such as spoofing and IP confusion across multiple proxy layers. You can use a custom HTTP header to pass the real client IP address to improve security and control.

The following example shows how to use a custom header to retrieve the real client IP.

image
  1. Configure CDN

    By default, CDN carries the Ali-Cdn-Real-Ip HTTP request header in back-to-origin requests, which indicates the real IP address of the client when it connects to the CDN node. You can use Add a custom outbound request header to pass this IP address to WAF. The following table shows an example of the CDN console configuration.

    Parameter

    Example

    Operation

    Add

    Request Header

    Custom back-to-origin request header

    Header Name

    Enter a custom name, for example, TrueIP

    Header Value

    $http_Ali_Cdn_Real_Ip

    Allow Duplicates

    Not Allowed

    Rule Condition

    Not used

  2. Configure WAF

    Complete the following two configurations in the WAF console:

    • Is a Layer 7 proxy such as Anti-DDoS Proxy or CDN deployed in front of WAF: Enable this option so that WAF correctly identifies the real client IP address.

    • Enable Traffic Tagging: Enable this option so that the origin server can obtain the real client IP address.

    For more information about how to configure these options, see Real client information.

    Parameter

    Example

    Is a Layer 7 proxy such as Anti-DDoS Proxy or CDN deployed in front of WAF

    Select Yes, and then select [Recommended] Use the First IP Address in Specified Header Field as Actual IP Address of Client to Prevent X-Forwarded-For Forgery. Enter the Header Name that you specified in the CDN configuration, for example, TrueIP.

    Enable Traffic Tagging

    Select Originating IP Address, and enter the Header Name that you specified in the CDN configuration, for example, TrueIP.

  3. Configure the origin server

    Take Nginx as an example. Edit the main configuration file nginx.conf and add the following content to the http {} block. For more information, see Configure Nginx.

    http {
      # Trust request headers from the WAF back-to-origin IP addresses.
      # Replace the following placeholders with the WAF back-to-origin IP ranges you obtained from the console.
      # You must add all IP ranges. If any are missing, some requests might still log the WAF IP instead of the real client IP.
      set_real_ip_from    <ip_range1>;    
      set_real_ip_from    <ip_range2>;   
      ...
      set_real_ip_from    <ip_rangex>;
      # Tell Nginx to get the real IP from your custom header, TrueIP in this example.
      real_ip_header      TrueIP;
    }

    We recommend that you configure the security group of the origin server to only allow traffic from WAF back-to-origin IP ranges. This ensures that only WAF can communicate with the origin server, preventing attackers from bypassing WAF and directly accessing the public IP address of the origin server.

FAQ

What is the difference between the real IP address configuration on the origin server (described in this topic) and the Is a Layer 7 proxy such as Anti-DDoS Proxy or CDN deployed in front of WAF option in the WAF console?

  • Real IP address configuration on the origin server (described in this topic)

    • Purpose: After you use CNAME integration to connect your domain to WAF, this configuration enables the origin server (such as Nginx) to record the real client IP address in its access logs (such as access.log) instead of the WAF back-to-origin IP address.

    • Required: Only required if you need to view or process the real client IP address on the origin server.

  • The Is a Layer 7 proxy such as Anti-DDoS Proxy or CDN deployed in front of WAF option in the WAF console

    • Applicable scenario: Other Layer 7 proxies (such as CDN or Anti-DDoS Pro) are deployed in front of WAF.

    • Purpose: Instructs WAF to extract the real client IP address from a specific HTTP request header (such as Ali-Cdn-Real-Ip or X-Forwarded-For) to ensure that security reports and attack identification are based on the real source IP address.

    • Required: Only required if a Layer 7 proxy is deployed in front of WAF. If no front-end proxy exists, keep the default value No.

What is X-Forwarded-For spoofing and how do I prevent it?

X-Forwarded-For (XFF) spoofing refers to an attack where an attacker constructs or tampers with the X-Forwarded-For request header in an HTTP request to inject a fake client IP address, with the goal of bypassing IP-based access controls, log auditing, or security policies. X-Forwarded-For is a non-standard request header that can be arbitrarily set by clients. If a backend service directly trusts this field without validation, security risks arise.

Example: XFF spoofing attack command
An attacker can use the curl command to forge an X-Forwarded-For header, spoofing the IP address as 1.2.3.4:

curl -H "X-Forwarded-For: 1.2.3.4" https://example.com/

To prevent XFF spoofing, use a custom trusted request header to pass the real IP address:
Configure CDN or WAF to use a predefined custom HTTP request header to pass the real client IP address when sending requests back to the origin server. The origin server then only parses this custom header. This request header is injected by trusted middleware (such as WAF) and cannot be directly controlled by clients, effectively preventing spoofing.