Почему у меня неправильно определяется IP пользователя?

Всю жизнь определял IP при помощи переменной окружения, и всегда это работало:

echo $_SERVER['REMOTE_ADDR'];

Тут недавно столкнулся с ситуацией, когда вдруг: $_SERVER['REMOTE_ADDR'], Ipconfig в командной строке и 2ip.ru показали мне 3 разных айпишника. Раньше показывали всегда один и тот же, сейчас корректно показывает только 2ip.ru, остальные - адреса каких-то промежуточных прокси, причем разные. И не у меня одного такая ситуация.

Нагуглил на SO функцию:

function get_ip()
{
    if (!empty($_SERVER['HTTP_CLIENT_IP']))
    {
        $ip=$_SERVER['HTTP_CLIENT_IP'];
    }
    elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
        $ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        $ip=$_SERVER['REMOTE_ADDR'];
    }
    return $ip;
}


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

Поэтому пара вопросов:
1) Я правильно понимаю, что Чебурнет уже совсем близко, навтыкли каких-то промежуточных прокси-серверов, что даже айпишник стало нормально не определить.

2) Ну и, собственно, как теперь все-таки правильно определять IP.
  • Вопрос задан
  • 4226 просмотров
Решения вопроса 1
@rPman
$_SERVER['REMOTE_ADDR'] устанавливает твой веб сервер, ему вы доверяете.
Но, если пользователь заходит через прокси сервер - то тут будет выходной ip адрес этого прокси.

Если прокси сервер не скрывает информацию о своих клиентах то
$_SERVER['HTTP_X_FORWARDED_FOR'] и $_SERVER['HTTP_CLIENT_IP'] должны содержать ожидаемое, но это значит нужно доверять этому прокси серверу.

Хочешь узнать реальный ip адрес, используй javascript в браузере пользователя (т.е. придется доверять уже пользователю в плане, а отреверсит ли он твой код и не подсунет что угодно).

Cамый известный и достаточно надежный способ (его сразу отключают любые адекватные анонимизеры) - это WebRTC. Технология позволяет двум браузерам открывать прямое соединение (да еще и udp) друг с другом, а веб сервер только организует процесс. Т.е. подняв соответствующего клиента WebRTC (погугли, правда я для php с ходу готовой библиотеки не нашел) и организовав подключение клиента с этим твоим сервером, который представляется обычным веб клиентом), ты сможешь по тому, с какого ip адреса пришло соответствующее соединение, определить настоящий, даже если пользователь использует прокси.

Это не защитит от vpn, тут никакими способами определить ip адрес пользователя не получится, потому что с точки зрения сетевых технологий, vpn - это как бы проводок пользовательского компьютера подключили к vpn-серверу, и никакие коммуникации не пойдут иначе, если пользователь не укажет иного (можно настроить маршрутизацию на выход через разные шлюзы в зависимости от геолокации, кстати этим можно воспользоваться, разместив кучу своих серверов в разных локациях и, обращаясь к ним из браузера клиента, сравнивать ip адреса)
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
ipatiev
@ipatiev Куратор тега PHP
Потомок старинного рода Ипатьевых-Колотитьевых
Чтобы определить IP адрес, надо сначала разобраться с кашей в своей голове.

Сначала надо задать себе вопрос, а какое вообще отношение имеет Ipconfig к адресу клиента. И после долгих мучительных размышлений вдруг сообразить, что все три адреса совпадают, когда разрабатываешь сайт на уютном домашнем компике, а при размещении у провайдера адрес в Ipconfig никогда не будет совпадать, поскольку внезапно там будет будет адрес сервера, а не клиента

После этого надо посмотреть на сам адрес. В котором, скорее всего, тоже будет адрес из приватной сети.
И нелепые фантазии про чебурнет вдруг превратятся в провайдера, который поставил нормальный веб-сервер проксировать запросы к ламерским сайтам хомячков.
После этого выяснить у провайдера, в каком именно НТТР заголовке передается исходный IP клиента, и использовать только его, а не перебирать наугад все возможные. Причем настроить на уровне веб-сервера (mod_remoteip / ngx_http_realip_module)
Ответ написан
Комментировать
@SvizzZzy
$_SERVER['REMOTE_ADDR'] может некорректно показать ip из за настроек самого сервера. Если например сервер находится в докер контейнере, то без дополнительных настроек, remote_addr покажет ip контейнера, не пользователя. Тоже самое если ваш сервер сидит за каким то натом, например nuxt фронтом и тд. Это тоже нужно учитывать. В интернете куча советов на тему "remote addr показывает неверный ip".
Ответ написан
@Damik996
Смотри на каком ip крутиться приложение в файле hosts, если сервер запущен на домашнем ПК.
Также смотри какой ip у провайдера если он статический, в настройках роутера обычно указан.
Ipconfig показывает локальный адрес ПК, провайдер глобальный. Перепиши ip провайдера в hosts и в конфиг сервера если на этом ip работает приложение, тогда в 2ip будет определяться нормально.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы