PHP получить реальный IP (обнаружение прокси) - PullRequest
7 голосов
/ 24 марта 2011

Я отслеживаю «реальный» 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(z.B.: 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'];
}

Ответы [ 2 ]

2 голосов
/ 24 марта 2011

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

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

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

1 голос
/ 07 ноября 2014

проверка регулярного выражения не удалась для адресов 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
            //(z.B.: 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'];
}
...