WordPress.NewCitizen.io

How to obtain original/visitor IP address when using cloudflare as a CDN with wordpress

How to Obtain the Original IP/Visitor IP When Using the Cloudflare CDN with a WordPress Website

When using a CDN like Cloudflare, users do not receive the original visitor IP directly. Instead, what they see is the IP address of the Cloudflare server that acts as an intermediary between the visitor and the website. This happens because Cloudflare routes all incoming traffic through its network to provide various services like content caching, security, and load balancing.

As a result, the IP address that your website logs or sees in server headers is the Cloudflare IP rather than the true IP of the visitor. This can pose challenges for plugins that rely on the original IP for functionality, such as security monitoring, geolocation services, and analytics. Therefore, it’s crucial to configure your server and application to correctly capture the original visitor IP while using Cloudflare as your CDN.

Challenges Users usually Encounter When Trying to obtain the Original/Visitor IP in WordPress

It is important to note that Cloudflare offers an option that allows you to obtain the original visitor IP address. Cloudflare provides a header labeled “True-Client-IP,” which users can enable in their settings. Unfortunately, this feature is reserved for Enterprise plans. The cost of the Enterprise plan, which ranges from $2000 to $5000 per month, is prohibitive for most users.

Two Methods to Obtain the Original Client IP/Visitor IP in WordPress

I will show you two methods to log the original client IP in a WordPress environment. However, one of these methods requires root access to the server, which most hosting providers, especially those on shared hosting plans, do not grant to users. Therefore, we will begin with the first option, which is universal and works for anyone using WordPress, regardless of the web server they use, including Apache (with .htaccess) & NGINX.

First Method to Obtain Client IP/Visitor IP using a code snippet inserted in the functions.php file

				
					<?php
function set_real_ip() {
    if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
        $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
    } elseif (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
        $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_X_FORWARDED_FOR"];
    }
}
add_action('init', 'set_real_ip');
function get_real_ip() {
    return $_SERVER['REMOTE_ADDR'];
}

				
			

While this approach allows you to capture the real IP without server-level configurations, it is not as secure as using server modules like mod-remoteip (Apache), real-ip (NGINX), or similar. The main reason is that headers can be spoofed, meaning a malicious user could send fake CF-Connecting-IP  or  X-Forwarded-For headers to your server.

When headers can be spoofed, it means that a malicious user can send fake HTTP headers to your server to manipulate how your server interprets the request. In the context of IP addresses, this means they can falsify headers like CF-Connecting-IP or X-Forwarded-For to trick your server into thinking the request is coming from a different IP address than it actually is. Here’s a detailed explanation of the implications:

Implications of Header Spoofing
1. Misleading IP-Based Logs and Analytics:
  • False IP Logs: Your server logs could record fake IP addresses instead of the actual visitor IPs. This can mislead your analytics, making it difficult to track true user behavior or identify the source of traffic accurately.
  • Incorrect Geolocation: If your site personalizes content or ads based on the visitor’s location, spoofed IPs can lead to incorrect geolocation data, affecting the relevance of the content or ads shown to users.
2. Security Risks:
  • Circumventing Security Measures: If you use IP-based security measures, such as blocking certain IP addresses or rate limiting, a malicious user can bypass these measures by spoofing their IP address. This makes your site more vulnerable to attacks like DDoS, brute force, and other malicious activities.
  • Impersonation: Spoofing an IP address that you have whitelisted can allow a malicious user to gain unauthorized access to restricted areas of your site.
3. Compromised User Experience:
  • Unreliable User Data: Forms and other user interactions may log incorrect IP addresses, leading to issues in user support and service. For example, if you need to track and resolve user issues based on their IP address, spoofed IPs can lead to confusion and inefficiencies.
4. Legal and Compliance Issues:
  • Incorrect Record Keeping: For legal compliance, such as GDPR, you might need to maintain accurate records of user IP addresses. Spoofed IPs can lead to inaccurate records, which might complicate compliance efforts and legal reporting.

While it is possible to capture the original IP in the functions.php  file of a WordPress site, this method alone cannot prevent header spoofing. Therefore it is up to the end user to decide if this method should be used based on his/her individual needs.

The next method that I will share with you, does not have these security implications, but requires root access to your hosting providers server.

Second Method to Obtain The Original Client IP/Visitor IP (Requires Root Access To Server)

Obtaining the Original Client IP in Apache
1. Install mod_remoteip Module:
				
					sudo apt-get update
sudo apt-get install libapache2-mod-remoteip

				
			
				
					sudo yum install mod_remoteip

				
			
2. Enable mod_remoteip Module:
				
					sudo a2enmod remoteip

				
			
  • Open your Apache configuration file (typically located at /etc/httpd/conf/httpd.conf).
  • Add the following line:
				
					LoadModule remoteip_module modules/mod_remoteip.so

				
			
3. Configure mod_remoteip:
  • Edit your Apache configuration file (e.g., /etc/apache2/apache2.conf or /etc/httpd/conf/httpd.conf) to include the following configuration:
				
					<IfModule mod_remoteip.c>
    RemoteIPHeader CF-Connecting-IP
    RemoteIPTrustedProxy 103.21.244.0/22
    RemoteIPTrustedProxy 103.22.200.0/22
    RemoteIPTrustedProxy 103.31.4.0/22
    RemoteIPTrustedProxy 104.16.0.0/13
    RemoteIPTrustedProxy 104.24.0.0/14
    RemoteIPTrustedProxy 108.162.192.0/18
    RemoteIPTrustedProxy 131.0.72.0/22
    RemoteIPTrustedProxy 141.101.64.0/18
    RemoteIPTrustedProxy 162.158.0.0/15
    RemoteIPTrustedProxy 172.64.0.0/13
    RemoteIPTrustedProxy 173.245.48.0/20
    RemoteIPTrustedProxy 188.114.96.0/20
    RemoteIPTrustedProxy 190.93.240.0/20
    RemoteIPTrustedProxy 197.234.240.0/22
    RemoteIPTrustedProxy 198.41.128.0/17
    RemoteIPTrustedProxy 2400:cb00::/32
    RemoteIPTrustedProxy 2606:4700::/32
    RemoteIPTrustedProxy 2803:f800::/32
    RemoteIPTrustedProxy 2405:b500::/32
    RemoteIPTrustedProxy 2405:8100::/32
    RemoteIPTrustedProxy 2a06:98c0::/29
    RemoteIPTrustedProxy 2c0f:f248::/32
</IfModule>

				
			
4. Restart Apache:
				
					sudo systemctl restart apache2

				
			
				
					sudo systemctl restart httpd

				
			
5. Configure .htaccess for Security:
  • Add the following code to your .htaccess file to ensure only Cloudflare IPs can set the CF-Connecting-IP header:

The following is a link to the full list of Cloudflare IP addresses, which is always up to date. in  Cloudflare IP addresses. It is highly recommended that you cross reference it with the current list. You can also use the Cloudflare API to access this list.

				
					<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REMOTE_ADDR} !^103\.21\.244\.
    RewriteCond %{REMOTE_ADDR} !^103\.22\.200\.
    RewriteCond %{REMOTE_ADDR} !^103\.31\.4\.
    RewriteCond %{REMOTE_ADDR} !^104\.16\.
    RewriteCond %{REMOTE_ADDR} !^104\.24\.
    RewriteCond %{REMOTE_ADDR} !^108\.162\.
    RewriteCond %{REMOTE_ADDR} !^131\.0\.72\.
    RewriteCond %{REMOTE_ADDR} !^141\.101\.
    RewriteCond %{REMOTE_ADDR} !^162\.158\.
    RewriteCond %{REMOTE_ADDR} !^172\.64\.
    RewriteCond %{REMOTE_ADDR} !^173\.245\.
    RewriteCond %{REMOTE_ADDR} !^188\.114\.
    RewriteCond %{REMOTE_ADDR} !^190\.93\.
    RewriteCond %{REMOTE_ADDR} !^197\.234\.
    RewriteCond %{REMOTE_ADDR} !^198\.41\.
    RewriteCond %{REMOTE_ADDR} !^2400:cb00:
    RewriteCond %{REMOTE_ADDR} !^2606:4700:
    RewriteCond %{REMOTE_ADDR} !^2803:f800:
    RewriteCond %{REMOTE_ADDR} !^2405:b500:
    RewriteCond %{REMOTE_ADDR} !^2405:8100:
    RewriteCond %{REMOTE_ADDR} !^2a06:98c0:
    RewriteCond %{REMOTE_ADDR} !^2c0f:f248:
    RewriteRule .* - [F,L]
</IfModule>

				
			
Obtaining the Original Client IP in NGINX
1. Install ngx_http_realip Module:
				
					sudo apt-get update
sudo apt-get install nginx-extras

				
			
  • This module is typically included by default with the NGINX package. If not, you may need to recompile NGINX with the –with-http_realip_module flag.
2. Configure NGINX:
  • Edit your NGINX configuration file (e.g., /etc/nginx/nginx.conf or /etc/nginx/conf.d/default.conf) to include the following configuration:

The following is a link to the full list of Cloudflare IP addresses, which is always up to date. in  Cloudflare IP addresses. It is highly recommended that you cross reference it with the current list. You can also use the Cloudflare API to access this list.

				
					http {
    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;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 104.24.0.0/14;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 131.0.72.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 2400:cb00::/32;
    set_real_ip_from 2606:4700::/32;
    set_real_ip_from 2803:f800::/32;
    set_real_ip_from 2405:b500::/32;
    set_real_ip_from 2405:8100::/32;
    set_real_ip_from 2a06:98c0::/29;
    set_real_ip_from 2c0f:f248::/32;
    real_ip_header CF-Connecting-IP;
}

				
			
3. Restart NGINX:
				
					sudo systemctl restart nginx

				
			
Security Snippet for NGINX (Equivalent to .htaccess in Apache)

To prevent header spoofing by ensuring only trusted Cloudflare IPs can set the CF-Connecting-IP header:

1. Edit the NGINX Configuration:

The following is a link to the full list of Cloudflare IP addresses, which is always up to date. in  Cloudflare IP addresses. It is highly recommended that you cross reference it with the current list. You can also use the Cloudflare API to access this list.

				
					server {
    location / {
        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;
        set_real_ip_from 104.16.0.0/13;
        set_real_ip_from 104.24.0.0/14;
        set_real_ip_from 108.162.192.0/18;
        set_real_ip_from 131.0.72.0/22;
        set_real_ip_from 141.101.64.0/18;
        set_real_ip_from 162.158.0.0/15;
        set_real_ip_from 172.64.0.0/13;
        set_real_ip_from 173.245.48.0/20;
        set_real_ip_from 188.114.96.0/20;
        set_real_ip_from 190.93.240.0/20;
        set_real_ip_from 197.234.240.0/22;
        set_real_ip_from 198.41.128.0/17;
        set_real_ip_from 2400:cb00::/32;
        set_real_ip_from 2606:4700::/32;
        set_real_ip_from 2803:f800::/32;
        set_real_ip_from 2405:b500::/32;
        set_real_ip_from 2405:8100::/32;
        set_real_ip_from 2a06:98c0::/29;
        set_real_ip_from 2c0f:f248::