Как правильно использовать HTTP_X_FORWARDED_FOR?
Хорошо, у меня небольшая проблема с аутентификацией. Моя веб-служба позволяет подключаться к моему API через HTTP с именем пользователя и паролем, но это соединение также может быть ограничено конкретным IP-адресом.
Это означает, что $_SERVER['REMOTE_ADDR']
может быть неправильным. Я уже знаю, что на любую IP-информацию нельзя действительно полагаться - у меня есть ограничение только в попытке добавить еще один уровень безопасности.
Если это общий обзор запроса на мой веб-сервер:
clientSERVER => clientPROXY => myPROXY => mySERVER
Тогда это означает, что mySERVER показывает REMOTE_ADDR
myPROXY, а не клиента и отправляет фактический IP-адрес клиента как HTTP_X_FORWARDED_FOR
.
Чтобы преодолеть это, моя веб-служба имеет список IP-адресов доверенного прокси, и если REMOTE_ADDR
находится на одном из этих надежных IP-адресов, он сообщает моей веб-службе, что фактический IP-адрес является значением HTTP_X_FORWARDED_FOR
.
Теперь проблема связана с clientPROXY. Это означает, что (довольно часто) mySERVER получает значение HTTP_X_FORWARDED_FOR
, которое имеет несколько IP-адресов. Согласно документации HTTP_X_FORWARDED_FOR
, это список разделенных запятыми IP-адресов, где первый IP-адрес действительного истинного клиента и каждый другой IP-адрес - это прокси-сервер.
Итак, если HTTP_X_FORWARDED_FOR
имеет несколько значений, а моя служба ограничена IP, мне нужно проверить "последнее" значение HTTP_X_FORWARDED_FOR
на мой разрешенный список IP и просто игнорировать фактический IP-адрес клиента?
Я предполагаю, что в системе, где я должен установить список разрешенных IP-адресов, белый IP-адрес должен быть адресом прокси-сервера, а не IP-адресом за прокси-сервером (поскольку это может быть какой-то IP-адрес localhost и часто меняются).
А что из HTTP_CLIENT_IP
?
Ответы
Ответ 1
Мне нравится Hrishikesh answer, к которому у меня есть только это, чтобы добавить... потому что мы видели строку с разделителями-запятыми, встречающуюся при использовании нескольких прокси на пути, мы обнаружили, что необходимо добавить взрыв и захватить окончательный значение, например:
$IParray=array_values(array_filter(explode(',',$_SERVER['HTTP_X_FORWARDED_FOR'])));
return end($IParray);
array_filter находится там, чтобы удалить пустые записи.
Ответ 2
Вы можете использовать эту функцию для получения правильного IP-адреса клиента:
public function getClientIP(){
if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)){
return $_SERVER["HTTP_X_FORWARDED_FOR"];
}else if (array_key_exists('REMOTE_ADDR', $_SERVER)) {
return $_SERVER["REMOTE_ADDR"];
}else if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) {
return $_SERVER["HTTP_CLIENT_IP"];
}
return '';
}
Ответ 3
В свете последних httpoxy, действительно существует необходимость в полном примере, как использовать HTTP_X_FORWARDED_FOR
должным образом.
Итак, вот пример, написанный на PHP, как определить IP-адрес клиента, если вы знаете, что клиент может находиться за прокси-сервером, и вы знаете, что этому доверенному лицу можно доверять. Если вы не знаете доверенных доверенных лиц, просто используйте REMOTE_ADDR
<?php
function get_client_ip ()
{
// Nothing to do without any reliable information
if (!isset ($_SERVER['REMOTE_ADDR'])) {
return NULL;
}
// Header that is used by the trusted proxy to refer to
// the original IP
$proxy_header = "HTTP_X_FORWARDED_FOR";
// List of all the proxies that are known to handle 'proxy_header'
// in known, safe manner
$trusted_proxies = array ("2001:db8::1", "192.168.50.1");
if (in_array ($_SERVER['REMOTE_ADDR'], $trusted_proxies)) {
// Get the IP address of the client behind trusted proxy
if (array_key_exists ($proxy_header, $_SERVER)) {
// Header can contain multiple IP-s of proxies that are passed through.
// Only the IP added by the last proxy (last IP in the list) can be trusted.
$proxy_list = explode (",", $_SERVER[$proxy_header]);
$client_ip = trim (end ($proxy_list));
// Validate just in case
if (filter_var ($client_ip, FILTER_VALIDATE_IP)) {
return $client_ip;
} else {
// Validation failed - beat the guy who configured the proxy or
// the guy who created the trusted proxy list?
// TODO: some error handling to notify about the need of punishment
}
}
}
// In all other cases, REMOTE_ADDR is the ONLY IP we can trust.
return $_SERVER['REMOTE_ADDR'];
}
print get_client_ip ();
?>
Ответ 4
Вы также можете решить эту проблему через конфигурацию Apache, используя mod_remoteip, добавив следующее в файл conf.d:
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 172.16.0.0/12
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
Ответ 5
Если вы используете его в базе данных, это хороший способ:
Установите ip-поле в базе данных в varchar (250), а затем используйте это:
$theip = $_SERVER["REMOTE_ADDR"];
if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$theip .= '('.$_SERVER["HTTP_X_FORWARDED_FOR"].')';
}
if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
$theip .= '('.$_SERVER["HTTP_CLIENT_IP"].')';
}
$realip = substr($theip, 0, 250);
Затем вы просто проверяете $realip на поле ip базы данных
Ответ 6
HTTP_CLIENT_IP - самый надежный способ получения IP-адреса пользователя. Далее HTTP_X_FORWARDED_FOR, за которым следует REMOTE_ADDR. Проверьте все три в этом порядке, считая, что первый, который установлен (isset($_SERVER['HTTP_CLIENT_IP'])
возвращает true, если эта переменная установлена) является правильной. Вы можете самостоятельно проверить, использует ли пользователь прокси-сервер, используя различные методы. Проверьте этот вне.