PHP получает реальный IP (определение прокси)

Я действительно отслеживаю «реальный» IP-адрес пользователя, если у него есть прокси-сервер, который отправляет заголовок реального IP-адреса … имеет ли какое-либо решение лучше или даже больше заголовков?

Поскольку эта функция используется очень часто в скрипте, она должна быть очень быстрой, и она не кажется в этом созвездии: /

Несколько предложений, которые я придумал, но не мог понять:

  • поместите заголовки в порядке, что используется наиболее «в дикой природе», так как функции быстро заканчиваются
  • более быстрое обнаружение pre_match для IP

===

function get_real_ip() { $proxy_headers = array( 'CLIENT_IP', 'FORWARDED', 'FORWARDED_FOR', 'FORWARDED_FOR_IP', 'HTTP_CLIENT_IP', 'HTTP_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED_FOR_IP', 'HTTP_PC_REMOTE_ADDR', 'HTTP_PROXY_CONNECTION', 'HTTP_VIA', 'HTTP_X_FORWARDED', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED_FOR_IP', 'HTTP_X_IMFORWARDS', 'HTTP_XROXY_CONNECTION', 'VIA', 'X_FORWARDED', 'X_FORWARDED_FOR' ); foreach($proxy_headers as $proxy_header) { if(isset($_SERVER[$proxy_header]) && preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $_SERVER[$proxy_header])) /* HEADER ist gesetzt und dies ist eine gültige IP */ { return $_SERVER[$proxy_header]; } else if(stristr(',', $_SERVER[$proxy_header]) !== FALSE) /* Behandle mehrere IPs in einer Anfrage(zB: X-Forwarded-For: client1, proxy1, proxy2) */ { $proxy_header_temp = trim(array_shift(explode(',', $_SERVER[$proxy_header]))); /* Teile in einzelne IPs, gib die letzte zurück und entferne Leerzeichen */ if(($pos_temp = stripos($proxy_header_temp, ':')) !== FALSE) $proxy_header_temp = substr($proxy_header_temp, 0, $pos_temp); /* Entferne den Port */ if(preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $proxy_header_temp) return $proxy_header_temp; } } return $_SERVER['REMOTE_ADDR']; } 

Если прокси отправляет заголовок, вы можете получить исходный IP-адрес клиента. Если прокси-сервер этого не делает, то вы не можете. К сожалению (или, к счастью, в зависимости от вашей перспективы) это так просто.

То, что я сделал в нашей интрасети, перенаправляет «intranet.mydomain.com» на «интрасеть» на веб-сервере, последний не использует прокси-сервер из-за внутренней конфигурации сети / DNS … Не знаю, что вы хотите но это может быть полезно.

Вы также можете установить список исключений в браузере …

проверка правильности регулярных выражений не удастся для адресов ipv6; поэтому я скорее удалю это (или попытаюсь найти лучший Regex).

также stripos($proxy_header_temp, ':') приведет к ожидаемому поведению, например, для «:: 1» (localhost, ipv6).

мое предложение с упомянутыми изменениями:

 function getIp() { $proxy_headers = array( 'CLIENT_IP', 'FORWARDED', 'FORWARDED_FOR', 'FORWARDED_FOR_IP', 'HTTP_CLIENT_IP', 'HTTP_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED_FOR_IP', 'HTTP_PC_REMOTE_ADDR', 'HTTP_PROXY_CONNECTION', 'HTTP_VIA', 'HTTP_X_FORWARDED', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED_FOR_IP', 'HTTP_X_IMFORWARDS', 'HTTP_XROXY_CONNECTION', 'VIA', 'X_FORWARDED', 'X_FORWARDED_FOR' ); $regEx = "/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/"; foreach ($proxy_headers as $proxy_header) { if (isset($_SERVER[$proxy_header])) { /* HEADER ist gesetzt und dies ist eine gültige IP */ return $_SERVER[$proxy_header]; } else if (stristr(',', $_SERVER[$proxy_header]) !== false) { // Behandle mehrere IPs in einer Anfrage //(zB: X-Forwarded-For: client1, proxy1, proxy2) $proxy_header_temp = trim( array_shift(explode(',', $_SERVER[$proxy_header])) ); /* Teile in einzelne IPs, gib die letzte zurück und entferne Leerzeichen */ // if IPv4 address remove port if exists if (preg_match($regEx, $proxy_header_temp) && ($pos_temp = stripos($proxy_header_temp, ':')) !== false ) { $proxy_header_temp = substr($proxy_header_temp, 0, $pos_temp); } return $proxy_header_temp; } } return $_SERVER['REMOTE_ADDR']; }