CloudFlare та реєстрація IP-адрес відвідувачів через PHP


82

Я намагаюся відстежувати та реєструвати користувачів / відвідувачів, які заходять на мій веб-сайт за допомогою PHP $_SERVER['REMOTE_ADDR']. Типовий метод відстеження IP-адрес у PHP.

Однак я використовую CloudFlare для кешування та ін. Та отримую їхні IP-адреси, як CloudFlare:

108.162.212. * - 108.162.239. *

Яким був би правильний метод отримання фактичної IP-адреси користувачів / відвідувачів при використанні CloudFlare?

Відповіді:


241

Додаткові змінні сервера, доступні для хмарного відблиску:

$_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"];
}

Якщо ви робите це, і дійсність відвідуваної IP-адреси важлива, можливо, вам доведеться перевірити, чи $_SERVER["REMOTE_ADDR"]містить вона дійсно дійсну IP-адресу cloudflare, оскільки кожен може підробити заголовок, якщо йому вдалося підключитися безпосередньо до IP-сервера.


16
+1 для заміни REMOTE_ADDR на справжній IP, тому інші зміни в коді не потрібні.
aalaap

11
Якщо питання безпеки є, слід перевірити, чи надходить запит із діапазону IP Cloudflare ( cloudflare.com/ips ). Як, наприклад, у цій Joomla! Плагін: github.com/piccaso/joomla-cf/blob/master/cf/cf.php
Флоріан Фіда

Цей код Cloudflare також має на своєму веб-сайті. support.cloudflare.com/hc/en-us/articles/…
C0nw0nk

Найкраща відповідь, але також похвала за включення HTTP_CF_IPCOUNTRY, я раніше не стикався з цим.
Девід Белл

http_cf_connecting_ip іноді дає такі речі, як: 2a01: 6500: a043: 33a6: b36a: 7259: 4de5: 2500, будь-яка ідея, чому?
Майкл

15

Оновлення : CloudFlare випустив модуль mod_cloudflareдля apache, модуль реєструватиме і відображатиме фактичні IP-адреси відвідувачів, а не ті, до яких отримує доступ Cloudflare! https://www.cloudflare.com/resources-downloads#mod_cloudflare (відповідь: olimortimer )

Якщо у вас немає доступу до середовища роботи apache, ви можете скористатися наведеним нижче сценарієм, це дозволить вам перевірити, чи було з'єднання через cloudflare, і отримати ip користувачів.

Я переписую свою відповідь, яку використовував для іншого запитання " CloudFlare DNS / прямий ідентифікатор IP "

IP-адреси Cloudflare зберігаються загальнодоступно, тому ви можете перейти до них, щоб переглянути їх тут, а потім перевірити, чи не ip від Cloudflare (це дозволить нам отримати справжній ip із заголовка http 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 чи ні!


Це правильна відповідь, однак, майте на увазі, що вам потрібно постійно оновлювати IP-адреси. Поточні в наведеному вище коді вже недійсні, і тому код не вдасться. Ви можете отримати найновіші IP-адреси тут: cloudflare.com/ips В ідеалі, ви повинні зберігати їх у файлі, щоб вам залишалося лише оновити зовнішній файл, або навіть краще, періодично отримувати їх звідси: cloudflare.com/ips-v4
rafark

11

Оскільки на це запитання було задано та mod_cloudflareотримано відповідь, CloudFlare випустив для Apache, який реєструє та відображає фактичну IP-адресу відвідувача, а не адресу CloudFlare:

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


2019 - Вони більше не підтримують mod_cloudflare, проте це можна використовувати. Є щось нове, що називається mod_remoteip. Довідково: support.cloudflare.com/hc/en-us/articles/…
sinaza

@sinaza, мабуть, найкраще створити нову відповідь, оскільки моя відповідь mod_cloudflareбула від 4 років тому
olimortimer

@sjagr стосовно ваших редагувань, вони неправильні - CloudFlare насправді є Cloudflare, як я спочатку
писав

10

Cloudflare надсилає деякі додаткові заголовки запитів на ваш сервер, включаючи CF-Connecting-IPякі ми можемо зберігати $user_ip, якщо це визначено, використовуючи цей простий однорядковий лайнер:

$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"])?$_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);

Проблема в тому, що це лише простий заголовок, тому кожен може просто встановити його на будь-який потрібний IP, що є величезною уразливістю безпеки.
rafark

@rafark Ні, якщо ваш сервер правильно налаштований і не відповідає Cloudflare.
Sainan

Так, звісно. Це хороше рішення як таке, але перевірки все-таки слід проводити перед використанням HTTP_CF_CONNECTING_IP, як у відповіді Каллума
rafark,

@rafark Я також погоджуюсь, але це надзвичайно багато PHP-коду, який вже присутній в іншій формі у вашому конфігурі Apache (я сподіваюся), і цей код більше для полегшення налагодження, і якщо зловмисник має доступ до вашого середовища налагодження, я думаю у вас є важливіші проблеми.
Sainan

2

Важко перетворити 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']);

Дізнайтеся більше тут


1

HTTP_CF_CONNECTING_IP працює, лише якщо ви використовуєте cloudflare, можливо, ви переносите свій сайт або видаляєте cloudflare, ви забудете значення, тому використовуйте цей код.

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

1

У Laravel додайте такий рядок до AppServiceProvider:

...
use Symfony\Component\HttpFoundation\Request;


...
public function boot()
{
    Request::setTrustedProxies(['REMOTE_ADDR'], Request::HEADER_X_FORWARDED_FOR);
}

Тепер ви можете отримати справжню IP-адресу клієнта за допомогою request()->ip().

Детальніше читайте тут .



0

Коли ви використовуєте CloudFlare, усі ваші запити між вашим сервером та користувачами направляються через сервери CloudFlare.

У цьому випадку існує два методи отримання реальної IP-адреси користувача:

  1. Через додаткові заголовки серверів, додані серверами CloudFlare
  2. Додавання модуля CloudFlare Apache / NGINX на ваш сервер.

Спосіб 1: Отримайте 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']

Спосіб 2: Встановлення модуля Cloudflare на ваш сервер

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.