我正在尝试跟踪和记录使用PHP$_SERVER['REMOTE_ADDR']
来访问我的网站的用户/访问者。PHP中IP地址跟踪的一种典型方法。
但是,我正在使用CloudFlare进行缓存等,并以CloudFlare的方式接收其IP地址:
108.162.212。*-108.162.239。*
在仍然使用CloudFlare的同时检索实际用户/访问者IP地址的正确方法是什么?
Answers:
云耀斑可用的其他服务器变量是:
$_SERVER["HTTP_CF_CONNECTING_IP"]
真正的访客IP地址,这就是您想要的
$_SERVER["HTTP_CF_IPCOUNTRY"]
访客所在国家
$_SERVER["HTTP_CF_VISITOR"]
这可以帮助您知道它的http还是https
您可以像这样使用它:
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
如果这样做,并且访问IP地址的有效性很重要,则可能需要验证$_SERVER["REMOTE_ADDR"]
包含一个实际有效的cloudflare IP地址,因为如果有人能够直接连接到服务器IP,则任何人都可以伪造该报头。
更新:CloudFlare发布了一个mod_cloudflare
针对Apache的模块,该模块将记录并显示实际的访客IP地址,而不是cloudflare访问的IP地址!https://www.cloudflare.com/resources-downloads#mod_cloudflare(回答:olimortimer)
如果您无权访问apache运行时,则可以使用以下脚本,这将允许您检查连接是否通过cloudflare并获取用户ip。
我正在重写我用于另一个问题“ CloudFlare DNS /直接IP标识符”的答案
Cloudflare的ips是公开存储的,因此您可以在此处查看它们,然后检查ip是否来自cloudflare(这将使我们能够从http标头中获取真实ip HTTP_CF_CONNECTING_IP
)。
如果您使用它来禁用所有非cf连接,反之亦然,我建议您有一个单独的php脚本文件,该文件在每个其他脚本(例如common.php或pagestart.php等)之前被调用。
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'];
}
}
要使用脚本,它非常简单:
$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'];
该脚本将显示您的真实IP地址,以及请求是否为CF!
自问及回答此问题以来,CloudFlare已mod_cloudflare
针对Apache发布,该日志记录并显示实际的访问者IP地址,而不是CloudFlare地址:
https://www.cloudflare.com/resources-downloads#mod_cloudflare
mod_cloudflare
来自4年前
Cloudflare将一些其他请求标头发送到您的服务器,其中包括CF-Connecting-IP
我们可以$user_ip
使用以下简单的单行存储到的请求标头:
$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"])?$_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);
很难将HTTP_CF_CONNECTING_IP转换为REMOTE_ADDR。因此,您可以使用apache(.htaccess)自动添加。这样您就不必考虑$_SERVER['REMOTE_ADDR']
所有PHP脚本中的值是否正确。
.htaccess代码
php_value auto_prepend_file "/path/to/file.php"
php代码(file.php)
<?php
define('CLIENT_IP', isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : $_SERVER['REMOTE_ADDR']);
在这里了解更多
对于magento 1.x用户(我还没有尝试过magento 2.0),请查看https://tall-paul.co.uk/2012/03/13/magento-show-remote-ip-in-cloudflare-the-向右/需要更改app / etc / local.xml并添加:HTTP_CF_CONNECTING_IP
使用CloudFlare时,服务器和用户之间的所有请求都将通过CloudFlare服务器进行路由。
在这种情况下,有两种获取用户的真实IP地址的方法:
您可以使用以下代码获取用户的IP地址:
$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"]) $_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);
CloudFlare在请求中添加了一些额外的服务器变量,如下所示:
$_SERVER["HTTP_CF_CONNECTING_IP"]
-用户的真实IP地址
$_SERVER["HTTP_CF_IPCOUNTRY"]
-用户的ISO2国家
$_SERVER["HTTP_CF_RAY"]
用于登录目的的特殊字符串
在上面的代码中,我们正在检查是否$_SERVER["HTTP_CF_CONNECTING_IP"]
设置了。如果存在,我们将认为这是用户的IP地址,否则我们将使用默认代码作为$_SERVER['REMOTE_ADDR']