$_SERVER['REMOTE_ADDR']
跟踪和记录访问我的网站的用户/访客。这是在PHP中跟踪IP地址的典型方法。然而,我正在使用CloudFlare进行缓存等操作,并收到他们的IP地址作为CloudFlare的地址:
在仍然使用CloudFlare的情况下,检索实际用户/访客的IP地址的正确方法是什么?108.162.212.* - 108.162.239.*
$_SERVER['REMOTE_ADDR']
跟踪和记录访问我的网站的用户/访客。这是在PHP中跟踪IP地址的典型方法。在仍然使用CloudFlare的情况下,检索实际用户/访客的IP地址的正确方法是什么?108.162.212.* - 108.162.239.*
Cloudflare可以使用的额外服务器变量包括:
$_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已经为Apache发布了一个模块mod_cloudflare
,该模块将记录并显示实际访问者的IP地址,而不是由Cloudflare访问的地址!https://www.cloudflare.com/resources-downloads#mod_cloudflare(回答者:olimortimer)
如果您无法访问Apache运行时,则可以使用以下脚本,这将允许您检查连接是否通过Cloudflare并获取用户的IP地址。
我正在重写我为另一个问题所使用的答案“CloudFlare DNS/direct IP identifier”
Cloudflare的IP地址是公开存储的,所以您可以在这里查看它们,然后检查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会向您的服务器发送一些额外的请求头,包括CF-Connecting-IP
,我们可以使用这个简单的单行命令将其存储到$user_ip
中(如果已定义):
$user_ip = $_SERVER["HTTP_CF_CONNECTING_IP"] ?? $_SERVER['REMOTE_ADDR'];
mod_cloudflare
,它记录并显示实际访问者的IP地址,而不是CloudFlare地址:https://www.cloudflare.com/resources-downloads#mod_cloudflare
mod_cloudflare
,但它仍然可以使用。现在有一个新的东西叫做mod_remoteip
。参考:https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs-Logging-visitor-IP-addresses-with-mod-cloudflare- - sinazamod_cloudflare
的回答是4年前的。 - olimortimer将HTTP_CF_CONNECTING_IP转换为REMOTE_ADDR可能很困难。因此,您可以使用apache(.htaccess)的自动前置来完成此操作。这样,您就不需要在所有PHP脚本中考虑$_SERVER ['REMOTE_ADDR']
是否具有正确的值。
.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']);
了解更多,请点击此处
最好在线检查Cloudflare IP范围(因为它可能随时更改),然后再检查是否来自Cloudflare。
如果来源是Cloudflare,您可以使用$_SERVER['HTTP_CF_CONNECTING_IP']
获取客户端请求的IP地址,但不建议在所有请求中都使用它,因为它可以由任何用户在请求头中发送以欺骗您。
您可以使用以下代码获取客户端请求的真实IP地址:
function _getUserRealIP() {
$ipaddress = '';
if(isset($_SERVER['REMOTE_ADDR']))
$ipaddress = $_SERVER['REMOTE_ADDR'];
else if (isset($_SERVER['HTTP_CLIENT_IP']))
$ipaddress = $_SERVER['HTTP_CLIENT_IP'];
else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
$ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_X_FORWARDED']))
$ipaddress = $_SERVER['HTTP_X_FORWARDED'];
else if(isset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
$ipaddress = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
$ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_FORWARDED']))
$ipaddress = $_SERVER['HTTP_FORWARDED'];
else
$ipaddress = 'UNKNOWN';
return $ipaddress;
}
function _readCloudflareIps()
{
$file = file("https://www.cloudflare.com/ips-v4",FILE_IGNORE_NEW_LINES);
return $file;
}
function _checkIpInRange($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 _checkIsCloudflare($ip) {
$cf_ips = _readCloudflareIps();
$is_cf_ip = false;
foreach ($cf_ips as $cf_ip) {
if (_checkIpInRange($ip, $cf_ip)) {
$is_cf_ip = true;
break;
}
}
return $is_cf_ip;
}
function getRealIp()
{
$httpIp = _getUserRealIP();
$check = _checkIsCloudflare($httpIp);
if ($check) {
return $_SERVER['HTTP_CF_CONNECTING_IP'];
}else{
return $httpIp;
}
}
getRealIp()
函数,如下所示:$userIp = getRealIp();
echo $userIp();
REMOTE_ADDR
始终包含有效数据,因此其他条件永远不会执行。$_SERVER['REMOTE_ADDR']
,这是检查用户真实IP并防止IP欺诈的最安全方式,但也有其他方法可以使用,我试图展示给你们看。 - Majid Jalilian您可以从Cloudflare的这篇文章中了解更多关于此功能的信息。该文章详细介绍了他们如何在IPv4的32位空间中尝试适应IPv6的128位地址空间。什么是伪IPv4?
为了加速IPv6的采用,Cloudflare提供了Pseudo IPv4,它支持在期望IPv4地址的旧应用程序中使用IPv6地址。目标是为每个IPv6地址提供一个几乎唯一的IPv4地址,使用类E IPv4地址空间,该地址空间被指定为实验性的,通常不会看到流量。要了解更多信息,请参见这里。
选项
- 添加标头:仅添加附加的
Cf-Pseudo-IPv4
标头- 覆盖标头:使用伪IPv4地址覆盖现有的
Cf-Connecting-IP
和X-Forwarded-For
标头。注意:我们建议将其设置为“关闭”,除非您有特定需求。
246.101.74.149
,但我的IP并不是这个。我查找了IP并得到了“bogon:true”和“Reserved RFC3330”。 - CHOO YJ$_SERVER["HTTP_CF_CONNECTING_IP"]
。如果存在,我们将把它视为用户的IP地址,否则我们将使用默认代码$_SERVER['REMOTE_ADDR']
。AppServiceProvider
中:...
use Symfony\Component\HttpFoundation\Request;
...
public function boot()
{
Request::setTrustedProxies(['REMOTE_ADDR'], Request::HEADER_X_FORWARDED_FOR);
}
现在你可以使用request()->ip()
来获取真实的客户端IP。
更多信息请查看这里。
Request::setTrustedProxies(['REMOTE_ADDR'], 'HTTP_CF_CONNECTING_IP');
? - Sᴀᴍ Onᴇᴌᴀ只有在使用 Cloudflare 时,HTTP_CF_CONNECTING_IP 才有效。如果你转移了你的网站或删除了 Cloudflare,你将会忘记这个值,所以请使用以下代码。
$ip=$_SERVER["HTTP_CF_CONNECTING_IP"];
if (!isset($ip)) {
$ip = $_SERVER['REMOTE_ADDR'];
}