Как узнать IP пользователя в PHP и не ошибиться с прокси

Короткий ответ: самый базовый способ узнать IP пользователя в PHP — взять значение $_SERVER['REMOTE_ADDR']. Но если сайт работает за прокси, CDN или балансировщиком, реальный клиентский IP может передаваться в отдельных заголовках, и с ними нужно быть осторожным

Для простого сайта без прокси начните с REMOTE_ADDR. Для продакшн-сайта за Cloudflare, Nginx proxy или другим промежуточным сервером сначала настройте доверенные прокси, а уже потом читайте forwarded-заголовки

Простой пример

Создайте файл ip.php

<?php

$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';

echo 'Ваш IP: ' . htmlspecialchars($ip, ENT_QUOTES, 'UTF-8');

Откройте файл через сайт или локальный сервер. На локальном компьютере вы можете увидеть 127.0.0.1 или ::1, потому что запрос идет с вашего же компьютера

Почему на localhost виден 127.0.0.1

Если вы тестируете файл локально, браузер обращается к серверу на той же машине. Поэтому PHP видит локальный адрес, а не внешний IP из интернета

Это нормально. Чтобы увидеть реальный внешний сценарий, файл должен быть открыт с публичного сайта, а не только с локального сервера

Валидация IP

Данные из серверных переменных лучше проверять

<?php

$ip = $_SERVER['REMOTE_ADDR'] ?? '';

if (filter_var($ip, FILTER_VALIDATE_IP)) {
    echo 'IP определен: ' . htmlspecialchars($ip, ENT_QUOTES, 'UTF-8');
} else {
    echo 'IP определить не удалось';
}

filter_var() проверит, что строка действительно похожа на IP-адрес

Что такое X-Forwarded-For

Если сайт стоит за прокси, запрос к PHP приходит не напрямую от пользователя, а от промежуточного сервера. В таком случае REMOTE_ADDR может показать IP прокси, а настоящий IP пользователя может быть в заголовке X-Forwarded-For

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

Безопасный общий подход

Используйте forwarded-заголовки только если запрос пришел от доверенного прокси. В учебном виде логика выглядит так

<?php

function getClientIp(array $trustedProxies = []): string
{
    $remoteAddr = $_SERVER['REMOTE_ADDR'] ?? '';

    if (!filter_var($remoteAddr, FILTER_VALIDATE_IP)) {
        return 'unknown';
    }

    if (in_array($remoteAddr, $trustedProxies, true)) {
        $forwardedFor = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
        $parts = array_map('trim', explode(',', $forwardedFor));
        $firstIp = $parts[0] ?? '';

        if (filter_var($firstIp, FILTER_VALIDATE_IP)) {
            return $firstIp;
        }
    }

    return $remoteAddr;
}

echo getClientIp(['203.0.113.10']);

В реальном проекте вместо 203.0.113.10 должен быть IP вашего доверенного прокси. Если прокси нет, не используйте X-Forwarded-For

IPv4 и IPv6

IP может выглядеть так

192.0.2.10

А может так

2001:db8::1

Оба варианта нормальны. Не пишите проверку только под IPv4, если нет жесткой причины. FILTER_VALIDATE_IP умеет работать и с IPv4, и с IPv6

Для чего можно использовать IP

IP можно использовать для грубой аналитики, ограничения частоты запросов, журналирования безопасности и диагностики. Но IP не стоит считать надежным идентификатором человека: он может меняться, быть общим для сети, скрываться за прокси или принадлежать мобильному оператору

Если вы сохраняете IP, учитывайте правила приватности и не храните лишние данные без необходимости

Мини-практика

Создайте файл ip.php, выведите REMOTE_ADDR, затем добавьте проверку через filter_var(). После этого откройте файл локально и на хостинге, если он у вас есть. Сравните результат: локальный адрес и публичный сценарий будут отличаться

Частые ошибки

Берут только X-Forwarded-For Этот заголовок можно подделать, если сервер не проверяет доверенный прокси

Считают 127.0.0.1 ошибкой На локальном сервере это нормальный результат

Не поддерживают IPv6 Пользовательский IP не всегда выглядит как четыре числа через точки

Выводят IP без экранирования Даже технические строки лучше выводить через htmlspecialchars()

Что почитать дальше по PHP

Если нужен общий маршрут по теме, откройте рубрику PHP. Для соседних задач пригодятся эти разборы:

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x