Как правильно использовать 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-адрес и частое изменение) ,

А что из HTTP_CLIENT_IP ?

Мне нравится ответ Хришикеша, к которому у меня есть только это, чтобы добавить … потому что мы видели строку с разделителями-запятыми, встречающуюся при использовании нескольких прокси-серверов по пути, мы обнаружили, что необходимо добавить взрыв и получить окончательное значение, например это:

 $IParray=array_values(array_filter(explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']))); return end($IParray); 

array_filter находится там, чтобы удалить пустые записи.

Вы можете использовать эту функцию для получения правильного 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 ''; } 

В свете последних уязвимостей 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 (); ?> 

Вы также можете решить эту проблему через конфигурацию 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 

Если вы используете его в базе данных, это хороший способ:

Установите 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 базы данных

HTTP_CLIENT_IP – самый надежный способ получить IP-адрес пользователя. Далее HTTP_X_FORWARDED_FOR, за которым следует REMOTE_ADDR. Проверьте все три в указанном порядке, считая, что первый из них установлен ( isset($_SERVER['HTTP_CLIENT_IP']) возвращает true, если эта переменная установлена) является правильной. Вы можете самостоятельно проверить, использует ли пользователь прокси-сервер, используя различные методы. Проверьте это .