Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CloudFlare and logging visitor IP addresses via in PHP

I'm trying to track and log users/visitors that are accessing my website using PHP's $_SERVER['REMOTE_ADDR'] to do so. A typical method for IP address tracking in PHP.

However, I am using CloudFlare for caching and such and receiving their IP addresses as CloudFlare's:

108.162.212.* - 108.162.239.*

What would be a correct method of retrieving the actual users/visitors IP address while still using CloudFlare?

like image 718
tfont Avatar asked Feb 20 '13 16:02

tfont


People also ask

Does Cloudflare log IP addresses?

Since CloudFlare serves as a proxy, all visits to your website and web applications will, by default, be logged with the CloudFlare IP address — not the visitor's actual IP address. To remedy this, installing the Apache module mod_cloudflare will ensure that visitors' actual IP addresses are logged and displayed.


2 Answers

Extra server variables that are available to cloud flare are:

$_SERVER["HTTP_CF_CONNECTING_IP"] real visitor ip address, this is what you want

$_SERVER["HTTP_CF_IPCOUNTRY"] country of visitor

$_SERVER["HTTP_CF_RAY"]

$_SERVER["HTTP_CF_VISITOR"] this can help you know if its http or https

you can use it like this:

if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {   $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"]; } 

If you do this, and the validity of the visiting IP address is important, you might need to verify that the $_SERVER["REMOTE_ADDR"] contains an actual valid cloudflare IP address, because anyone can fake the header if he was able to connect directly to the server IP.

like image 196
sharp12345 Avatar answered Sep 19 '22 22:09

sharp12345


Update: CloudFlare has released a module mod_cloudflare for apache, the module will log and display the actual visitor IP Addresses rather than those accessed by cloudflare! https://www.cloudflare.com/resources-downloads#mod_cloudflare (Answer by: olimortimer)

If you dont have access to the apache runtime you can use the script below, this will allow you to check if the connection was through cloudflare and get the users ip.

I am rewriting my answer i used for another question "CloudFlare DNS / direct IP identifier"

Cloudflare's ips are stored in public so you can go view them here then check if the ip is from cloudflare (this will allow us to get the real ip from the http header HTTP_CF_CONNECTING_IP).

If you are using this to disable all non cf connections or vice versa, i recommend you to have a single php script file that gets called before every other script such as a common.php or pagestart.php etc.

function ip_in_range($ip, $range) {     if (strpos($range, '/') == false)         $range .= '/32';      // $range is in IP/CIDR format eg 127.0.0.1/24     list($range, $netmask) = explode('/', $range, 2);     $range_decimal = ip2long($range);     $ip_decimal = ip2long($ip);     $wildcard_decimal = pow(2, (32 - $netmask)) - 1;     $netmask_decimal = ~ $wildcard_decimal;     return (($ip_decimal & $netmask_decimal) == ($range_decimal & $netmask_decimal)); }  function _cloudflare_CheckIP($ip) {     $cf_ips = array(         '199.27.128.0/21',         '173.245.48.0/20',         '103.21.244.0/22',         '103.22.200.0/22',         '103.31.4.0/22',         '141.101.64.0/18',         '108.162.192.0/18',         '190.93.240.0/20',         '188.114.96.0/20',         '197.234.240.0/22',         '198.41.128.0/17',         '162.158.0.0/15',         '104.16.0.0/12',     );     $is_cf_ip = false;     foreach ($cf_ips as $cf_ip) {         if (ip_in_range($ip, $cf_ip)) {             $is_cf_ip = true;             break;         }     } return $is_cf_ip; }  function _cloudflare_Requests_Check() {     $flag = true;      if(!isset($_SERVER['HTTP_CF_CONNECTING_IP']))   $flag = false;     if(!isset($_SERVER['HTTP_CF_IPCOUNTRY']))       $flag = false;     if(!isset($_SERVER['HTTP_CF_RAY']))             $flag = false;     if(!isset($_SERVER['HTTP_CF_VISITOR']))         $flag = false;     return $flag; }  function isCloudflare() {     $ipCheck        = _cloudflare_CheckIP($_SERVER['REMOTE_ADDR']);     $requestCheck   = _cloudflare_Requests_Check();     return ($ipCheck && $requestCheck); }  // Use when handling ip's function getRequestIP() {     $check = isCloudflare();      if($check) {         return $_SERVER['HTTP_CF_CONNECTING_IP'];     } else {         return $_SERVER['REMOTE_ADDR'];     } } 

To use the script it's quite simple:

$ip = getRequestIP(); $cf = isCloudflare();  if($cf) echo "Connection is through cloudflare: <br>"; else    echo "Connection is not through cloudflare: <br>";  echo "Your actual ip address is: ". $ip; echo "The server remote address header is: ". $_SERVER['REMOTE_ADDR']; 

This script will show you the real ip address and if the request is CF or not!

like image 22
Callum Avatar answered Sep 19 '22 22:09

Callum