.htaccess RewriteCond %{REMOTE_ADDR} not working

We are trying to only allow a specific IP to access /wp-admin/ but we can’t because REMOTE_ADDR in .htaccess seems to show the Cloudflare IP (162.158.158.114 for example) not the client IP (shown as 123.123.123.123 in the example below.

Is there something we should use instead of REMOTE_ADDR?

Only allow css, svg and index.php from the wp-admin directory unless logged in or local

RewriteCond %{REQUEST_URI} “^/wp-admin/” [NC]
RewriteCond %{REMOTE_ADDR} “!^123.123.123.123$”
RewriteCond %{REMOTE_ADDR} "!^127.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" RewriteCond %{REQUEST_FILENAME} !\.(css|svg) [NC]
RewriteCond %{REQUEST_URI} “!^/wp-admin/" [NC] RewriteCond %{REQUEST_URI} "!^/wp-admin/index\.php” [NC]
RewriteCond %{REQUEST_URI} “!^/wp-admin/admin-ajax.php$” [NC]
RewriteRule . - [L,F]

https://support.cloudflare.com/hc/en-us/sections/200805497-Restoring-Visitor-IPs

Sorry, I should have explained that this is for a Wordpress plugin where mod_cloudflare cannot be installed.

In that case you could try %{HTTP:CF-Connecting-IP} instead.

Great, I’ll give that a go. We tried %{HTTP:X-FORWARDED-FOR} but that didn’t work. Thanks.

That should actually work too.

Though it might be susceptible to tampering by the user.

Interesting, thank you. It’s confusing as PHP is returning _SESSION('REMOTE_ADDR') as the client IP, _SESSION(‘HTTP_X_FORWARDED_FOR’) as Cloudflare IP and $_SESSION(‘HTTP_CF_CONNECTING_IP’) also as the CLIENT IP rather than the Cloudflare IP.

This appears to be different to .htaccess which is showing HTTP_X_FORWARDED_FOR and REMOTE_ADDR as the Cloudflare IP.

Strange that the behaviour would be so different between PHP and .htaccess. Hopefully we’ll see %{HTTP:CF-Connecting-IP} as showing the client IP.

Thanks again.

$_SESSION? You did mean $_SERVER, right?

If REMOTE_ADDR shows the client IP, the request either didnt come via Cloudflare or the address is already being rewritten as mentioned in my first response.

Forwarded-For, however, shouldnt contain the Cloudflare IP address, unless there is an additional proxy inbetween to which Cloudflare proxies first.

Yes, sorry, exactly that. print_r() of $_SERVER shows exactly the behaviour I mention whilst .htaccess doesn’t seem to see the same values!

Surely for HTTP_CF_CONNECTING_IP to exist in $_SERVER then the request must come via Cloudflare. And if the mod_cloudflare had been installed on the server (not within our control and highly unlikely) then surely REMOTE_ADDR in .htaccess would also show the client IP rather than the Cloudflare IP?

It could be that the Cloudflare Wordpress plugin has configured Cloudflare not to cache wp-admin traffic. I’ll investigate. Thank you.

Also check the log files. If they show Cloudflare addresses, whereas your PHP code gets the actual addresses it would seem some PHP code (e.g. the plugin) is rewriting that on a PHP level only.

Yes, understood. I’ve changed the .htaccess as follows (for when HTTP_CF_CONNECTING_IP isset in PHP) and so far it looks like it works so thank you again for your help …

RewriteCond %{REQUEST_URI} “^/wp-admin/” [NC]
RewriteCond %{HTTP:CF-CONNECTING-IP} “!^123.123.123.123$”
RewriteCond %{REMOTE_ADDR} "!^127.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" RewriteCond %{REQUEST_FILENAME} !\.(css|svg) [NC]
RewriteCond %{REQUEST_URI} “!^/wp-admin/" [NC] RewriteCond %{REQUEST_URI} "!^/wp-admin/index\.php” [NC]
RewriteCond %{REQUEST_URI} “!^/wp-admin/admin-ajax.php$” [NC]
RewriteRule . - [L,F]