Короткий ответ: самый базовый способ узнать 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. Для соседних задач пригодятся эти разборы:
- PHP-регистрация пользователя: форма, база данных и безопасный пароль
- Как сделать, чтобы PHP-сайт узнавал пользователя: cookie, session и логин
- Как узнать параметры PHP на хостинге через phpinfo и код
- Composer в PHP: установка пакетов без ручного копирования



