CloudFlare并通过PHP记录访客IP地址

tfo*_*ont 76 php logging ip-address cloudflare

我正在尝试使用PHP来跟踪和记录访问我网站的用户/访问者$_SERVER['REMOTE_ADDR'].PHP中IP地址跟踪的典型方法.

但是,我使用CloudFlare进行缓存等,并将其IP地址作为CloudFlare接收:

108.162.212.* - 108.162.239.*

在使用CloudFlare的同时检索实际用户/访客IP地址的正确方法是什么?

sha*_*345 223

可用于云计算的额外服务器变量包括:

$_SERVER["HTTP_CF_CONNECTING_IP"] 真正的访客IP地址,这就是你想要的

$_SERVER["HTTP_CF_IPCOUNTRY"] 访客的国家

$_SERVER["HTTP_CF_RAY"] 看这里的描述

$_SERVER["HTTP_CF_VISITOR"] 这可以帮助您了解其http或https

你可以像这样使用它:

if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
  $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
Run Code Online (Sandbox Code Playgroud)

如果您这样做,并且访问IP地址的有效性很重要,您可能需要验证其中$_SERVER["REMOTE_ADDR"]包含实际有效的cloudflare IP地址,因为如果他能够直接连接到服务器IP,任何人都可以伪造标头.

  • +1用于将REMOTE_ADDR替换为真实IP,因此不需要对代码进行其他修改. (14认同)
  • 如果安全很重要,请_should_检查请求是否来自Cloudflare IP Range(https://www.cloudflare.com/ips).就像,例如在这个Joomla!插件:https://github.com/piccaso/joomla-cf/blob/master/cf/cf.php (10认同)

oli*_*mer 11

自从提出并回答了这个问题以来,CloudFlare已经发布mod_cloudflare了Apache,它记录并显示实际的访问者IP地址而不是CloudFlare地址:

https://www.cloudflare.com/resources-downloads#mod_cloudflare

  • 2019 - 他们不再支持 `mod_cloudflare`,但可以使用。有一个新的东西叫做“mod_remoteip”。参考:https://support.cloudflare.com/hc/en-us/articles/200170786-Restoring-original-visitor-IPs-Logging-visitor-IP-addresses-with-mod-cloudflare- (2认同)

Cal*_*lum 9

我正在重写我用于另一个问题的答案" CloudFlare DNS/direct IP identifier "

Cloudflare的ips存储在公共场所,因此你可以在这里查看它们然后检查ip是否来自cloudflare(这将允许我们从http头部获取真正的ip mod_cloudflare).

如果你使用它来禁用所有非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'];
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用脚本,这很简单:

$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'];
Run Code Online (Sandbox Code Playgroud)

此脚本将显示真实的IP地址以及请求是否为CF!


tim*_*yRS 8

Cloudflare会向您的服务器发送一些额外的请求标头,包括CF-Connecting-IP我们可以$user_ip使用这个简单的单行方式存储到哪个请求标头:

$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"])?$_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);
Run Code Online (Sandbox Code Playgroud)

  • @rafark 如果您的服务器配置正确且位于 Cloudflare 后面,则不会。 (2认同)