Очень частая задача на любом сайте, это определить IP адрес пользователя. Однако многие сталкиваются с проблемой, когда это не всегда получается. Ведь многие пользователи сейчас используют VPN, прокси и другие сетевые настройки, которые могут влиять на получение реального IP адреса.

Прокси-серверы и VPN обычно скрывают реальный IP-адрес пользователя и заменяют его IP-адресом прокси-сервера. Если попытаться получить IP-адрес с помощью $_SERVER['REMOTE_ADDR'] в PHP, то вы получите не реальный адрес пользователя, а IP прокси-сервера.

Когда ваш сайт находится за прокси-сервером или балансировщиком нагрузки, то к запросам добавляются заголовки X-Forwarded-For или X-Real-IP, в которых будет указан реальный IP-адрес пользователя. Конечно, если пользователь сам не использует VPN или проксирующие сервисы на вашем сайте.

Простой пример функции, реализующий получение IP адреса с помощью этих заголовков:

function getRealIpAddress() {
   if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
       $ipAddresses = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
       return trim(end($ipAddresses));
   } elseif (!empty($_SERVER['HTTP_X_REAL_IP'])) {
       return $_SERVER['HTTP_X_REAL_IP'];
   } elseif (!empty($_SERVER['HTTP_X_FORWARDED'])) {
       return $_SERVER['HTTP_X_FORWARDED'];
   }
   
   return $_SERVER['REMOTE_ADDR'];
}

$realIpAddress = getRealIpAddress();
echo "Реальный IP адрес пользователя: " . $realIpAddress;

С содержимым этих заголовков нужно быть осторожным, поскольку их можно легко подделать, передав какое угодно значение. Поэтому, чтобы получить правильный IP адрес пользователя, а также убедиться, что значение можно безопасно использовать, всегда делайте проверку заголовков X-Forwarded-For, X-Real-IP или X-Forwarded. Убедитесь, что на вашем сервере настроена проверка этих заголовком только от доверенных прокси-серверов.

Простой пример, проверки доверенных прокси-серверов:

function getRealIpAddress($trustedProxies = []) {

    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ipAddresses = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        $ipAddress = trim(end($ipAddresses));

        if (in_array($ipAddress, $trustedProxies)) {
            return $ipAddress;
        }
    }

    return $_SERVER['REMOTE_ADDR'];
}


$trustedProxies = ['192.168.1.1', '192.168.1.2']; 
$realIpAddress = getRealIpAddress($trustedProxies);
echo "Реальный IP адрес пользователя: " . $realIpAddress;

Если ваш сайт использует CloudFlare, то вы можете настроить получение реального IP адреса пользователя с помощью nginx, и используя только $_SERVER['REMOTE_ADDR']

На этом, пожалуй, все. Теперь вы знаете, почему IP пользователя может неправильно определяться и что нужно, чтобы это исправить.