Как получить IP-адрес клиента в PHP

avatar
Anup Prakash
9 июня 2010 в 04:50
1826709
29
1277

Как я могу получить IP-адрес клиента с помощью PHP?

Я хочу вести учет пользователей, которые вошли на мой веб-сайт через свой IP-адрес.

Источник
Patrick Mevzek
3 января 2018 в 20:05
1

См. RFC6302 с рекомендациями о том, что регистрировать, и особенно в настоящее время не забывайте регистрировать порт, а не только адрес.

Jonathan dos Santos
8 августа 2018 в 15:13
2

Предупреждение для тех, кто отслеживает пользователей, в нескольких регионах мира ISPS используют CGNAT, что значительно усложняет доверие простому IP-адресу.

user3562771
5 апреля 2020 в 12:30
0

функция getUserIpAddr () {если (! пусто ($ _ SERVER ['HTTP_CLIENT_IP'])) {$ ip = $ _SERVER ['HTTP_CLIENT_IP']; } elseif (! пусто ($ _ СЕРВЕР ['HTTP_X_FORWARDED_FOR'])) {$ ip = $ _SERVER ['HTTP_X_FORWARDED_FOR']; } еще {$ ip = $ _SERVER ['REMOTE_ADDR']; } return $ ip; }

johnson23
12 февраля 2021 в 10:56
0

Вы должны использовать Абстрактное обнаружение IP. Ценность заключается в том, что он сообщит вам, находится ли IP за прокси-сервером или VPN, что, на мой взгляд, важно. У них есть фрагмент PHP, из которого вы можете скопировать свой запрос.

Ответы (29)

avatar
jerryurenaa
3 декабря 2021 в 17:59
0

В PHP последний вариант получения общедоступного IP-адреса всегда должен быть $_SERVER["REMOTE_ADDR"] из соображений безопасности.

Вот обходной путь для получения подтвержденного IP-адреса клиента.

public static function getPublicIP() : string
    {
        $realIP = "Invalid IP Address";

        $activeHeaders = [];

        $headers = [
            "HTTP_CLIENT_IP",
            "HTTP_PRAGMA",
            "HTTP_XONNECTION",
            "HTTP_CACHE_INFO",
            "HTTP_XPROXY",
            "HTTP_PROXY",
            "HTTP_PROXY_CONNECTION",
            "HTTP_VIA",
            "HTTP_X_COMING_FROM",
            "HTTP_COMING_FROM",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "ZHTTP_CACHE_CONTROL",
            "REMOTE_ADDR" #this should be the last option
        ];

        #Find active headers
        foreach ($headers as $key)
        {
            if (array_key_exists($key, $_SERVER))
            {
                $activeHeaders[$key] = $_SERVER[$key];
            }
        }

         #Reemove remote address since we got more options to choose from
        if(count($activeHeaders) > 1)
        {
            unset($activeHeaders["REMOTE_ADDR"]);
        }

        #Pick a random item now that we have a secure way.
        $realIP = $activeHeaders[array_rand($activeHeaders)];

        #Validate the public IP
        if (filter_var($realIP, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
        {
            return $realIP;
        }

        return $realIP;
    }

Как видите, $ _SERVER ["REMOTE_ADDR"] - это наш последний вариант IP. После получения IP-адреса мы также проверяем IP-адрес для обеспечения качества и безопасности.

avatar
HRM
22 июля 2021 в 14:02
-1

Чтобы получить IP-адрес клиента, используйте getenv("REMOTE_ADDR").

Например,

$ip_address = getenv("REMOTE_ADDR");
echo $ip_address;

Если вы вызовете свой сервер с помощью localhost, он распечатает ::1. Поэтому звоните на свой сервер, используя прямой IP-адрес сервера или домен.

avatar
Stergios Zg.
23 июня 2019 в 08:04
23

Быстрое решение (без ошибок)

function getClientIP():string
{
    $keys=array('HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','HTTP_X_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED','REMOTE_ADDR');
    foreach($keys as $k)
    {
        if (!empty($_SERVER[$k]) && filter_var($_SERVER[$k], FILTER_VALIDATE_IP))
        {
            return $_SERVER[$k];
        }
    }
    return "UNKNOWN";
}
hanshenrik
2 ноября 2019 в 15:06
3

предупреждение, хакеры могут легко подделать IP, отправив поддельные HTTP-заголовки X-FORWARDED-FOR: fakeip

Stergios Zg.
14 декабря 2020 в 12:17
0

Конечно, но если вы используете NGINX, clientIP обычно находится на "HTTP_X_FORWARDED_FOR"

Jonathan Rosa
18 января 2021 в 19:50
1

Это может работать не так, как вы ожидаете: 1. все заголовки здесь допускают использование запятых и / или точек с запятой, поэтому вы должны токенизировать строку (т. Е. strtok($k, '; ')); 2. HTTP_X_FORWARDED не существует; 3. Использование здесь HTTP_FORWARDED (стандартизованное) всегда не пройдёт проверку filter_var, потому что он использует собственный синтаксис (т. Е. for=1.1.1.1;by=1.1.1.0).

avatar
SIE
11 июня 2019 в 10:14
9

Одно из этих:

    $ip = $_SERVER['REMOTE_ADDR'];
    $ip = $_SERVER['HTTP_CLIENT_IP'];
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    $ip = $_SERVER['HTTP_X_FORWARDED'];
    $ip = $_SERVER['HTTP_FORWARDED_FOR'];
    $ip = $_SERVER['HTTP_FORWARDED'];
Jsowa
10 мая 2020 в 09:24
0

Документация по серверным переменным: php.net/manual/en/reserved.variables.server.php

avatar
ws-ono
2 июня 2019 в 07:12
12

Вот небольшой код, который должен выбрать действительный IP-адрес путем проверки из различных источников.

Сначала он проверяет, является ли REMOTE_ADDR публичным IP-адресом или нет (а не одним из ваших доверенных обратных прокси-серверов), затем просматривает один из заголовков HTTP, пока не найдет общедоступный IP-адрес и не вернет его. (PHP 5.2+)

Он должен быть надежным, пока обратный прокси-сервер является доверенным или если сервер напрямую связан с клиентом.

//Get client's IP or null if nothing looks valid
function ip_get($allow_private = false)
{
  //Place your trusted proxy server IPs here.
  $proxy_ip = ['127.0.0.1'];

  //The header to look for (Make sure to pick the one that your trusted reverse proxy is sending or else you can get spoofed)
  $header = 'HTTP_X_FORWARDED_FOR'; //HTTP_CLIENT_IP, HTTP_X_FORWARDED, HTTP_FORWARDED_FOR, HTTP_FORWARDED

  //If 'REMOTE_ADDR' seems to be a valid client IP, use it.
  if(ip_check($_SERVER['REMOTE_ADDR'], $allow_private, $proxy_ip)) return $_SERVER['REMOTE_ADDR'];

  if(isset($_SERVER[$header]))
  {
    //Split comma separated values [1] in the header and traverse the proxy chain backwards.
    //[1] https://en.wikipedia.org/wiki/X-Forwarded-For#Format
    $chain = array_reverse(preg_split('/\s*,\s*/', $_SERVER[$header]));
    foreach($chain as $ip) if(ip_check($ip, $allow_private, $proxy_ip)) return $ip;
  }

   return null;
}

//Check for valid IP. If 'allow_private' flag is set to truthy, it allows private IP ranges as valid client IP as well. (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
//Pass your trusted reverse proxy IPs as $proxy_ip to exclude them from being valid.
function ip_check($ip, $allow_private = false, $proxy_ip = [])
{
  if(!is_string($ip) || is_array($proxy_ip) && in_array($ip, $proxy_ip)) return false;
  $filter_flag = FILTER_FLAG_NO_RES_RANGE;

  if(!$allow_private)
  {
    //Disallow loopback IP range which doesn't get filtered via 'FILTER_FLAG_NO_PRIV_RANGE' [1]
    //[1] https://www.php.net/manual/en/filter.filters.validate.php
    if(preg_match('/^127\.$/', $ip)) return false;
    $filter_flag |= FILTER_FLAG_NO_PRIV_RANGE;
  }

  return filter_var($ip, FILTER_VALIDATE_IP, $filter_flag) !== false;
}
Buffalo
10 декабря 2020 в 08:34
4

Я не понимаю, почему кто-то тратит столько времени на написание бесполезных комментариев вместо того, чтобы сделать свой код читабельным.

avatar
Keaser
20 мая 2019 в 13:58
12
function get_client_ip()
{
    foreach (array(
                'HTTP_CLIENT_IP',
                'HTTP_X_FORWARDED_FOR',
                'HTTP_X_FORWARDED',
                'HTTP_X_CLUSTER_CLIENT_IP',
                'HTTP_FORWARDED_FOR',
                'HTTP_FORWARDED',
                'REMOTE_ADDR') as $key) {
        if (array_key_exists($key, $_SERVER)) {
            foreach (explode(',', $_SERVER[$key]) as $ip) {
                $ip = trim($ip);
                if ((bool) filter_var($ip, FILTER_VALIDATE_IP,
                                FILTER_FLAG_IPV4 |
                                FILTER_FLAG_NO_PRIV_RANGE |
                                FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }
    }
    return null;
}

Или сжатая версия:

function get_ip() {
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key) {
        if (array_key_exists($key, $_SERVER) === true) {
            foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip) {
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                    return $ip;
                }
            }
        }
    }
}

avatar
vr_driver
29 апреля 2019 в 04:51
1

Просто об этом, и я удивлен, что об этом еще не упоминалось, заключается в получении правильных IP-адресов тех сайтов, которые расположены за подобной инфраструктурой CloudFlare. Это сломает ваши IP-адреса и присвоит им одинаковое значение. К счастью, у них тоже есть заголовки серверов. Вместо того, чтобы переписывать то, что уже было написано, посмотрите здесь, чтобы получить более сжатый ответ, и да, я тоже прошел через этот процесс давным-давно. https://coderhelper.com/a/14985633/1190051

avatar
user8031209
1 апреля 2019 в 07:42
4

<?php
/**
 * Function to get the client ip address
 *
 * @return string The Ip address
 */
function getIp(): string {
    if (! empty($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }

    if (! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        return $_SERVER['HTTP_X_FORWARDED_FOR'];
    }

    return $_SERVER['REMOTE_ADDR'] ?? '?';
}

Еще меньше

/**
 * Function to get the client ip address
 *
 * @return string The Ip address
 */
function getIp(): string {
    return $_SERVER['HTTP_CLIENT_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '';
}
avatar
Mohamad Hamouday
1 марта 2019 в 06:38
2

Эта функция должна работать должным образом

function Get_User_Ip()
{
    $IP = false;
    if (getenv('HTTP_CLIENT_IP'))
    {
        $IP = getenv('HTTP_CLIENT_IP');
    }
    else if(getenv('HTTP_X_FORWARDED_FOR'))
    {
        $IP = getenv('HTTP_X_FORWARDED_FOR');
    }
    else if(getenv('HTTP_X_FORWARDED'))
    {
        $IP = getenv('HTTP_X_FORWARDED');
    }
    else if(getenv('HTTP_FORWARDED_FOR'))
    {
        $IP = getenv('HTTP_FORWARDED_FOR');
    }
    else if(getenv('HTTP_FORWARDED'))
    {
        $IP = getenv('HTTP_FORWARDED');
    }
    else if(getenv('REMOTE_ADDR'))
    {
        $IP = getenv('REMOTE_ADDR');
    }

    //If HTTP_X_FORWARDED_FOR == server ip
    if((($IP) && ($IP == getenv('SERVER_ADDR')) && (getenv('REMOTE_ADDR')) || (!filter_var($IP, FILTER_VALIDATE_IP))))
    {
        $IP = getenv('REMOTE_ADDR');
    }

    if($IP)
    {
        if(!filter_var($IP, FILTER_VALIDATE_IP))
        {
            $IP = false;
        }
    }
    else
    {
        $IP = false;
    }
    return $IP;
}
avatar
Alexander Yancharuk
5 октября 2018 в 08:14
5

Безопасный и предупреждающий фрагмент кода для получения IP-адреса:

$ip = filter_input(INPUT_SERVER, 'HTTP_CLIENT_IP', FILTER_VALIDATE_IP)
    ?: filter_input(INPUT_SERVER, 'HTTP_X_FORWARDED_FOR', FILTER_VALIDATE_IP)
    ?: $_SERVER['REMOTE_ADDR']
    ?? '0.0.0.0'; // Or other value fits "not defined" in your logic
avatar
K.Suthagar
29 декабря 2016 в 15:18
52

За Интернетом находятся разные типы пользователей, поэтому мы хотим получить IP-адрес из разных частей. Это:

1. $_SERVER['REMOTE_ADDR'] - Он содержит реальный IP-адрес клиента. Это самое надежное значение, которое вы можете найти у пользователя.

2. $_SERVER['REMOTE_HOST'] - Это получит имя хоста, с которого пользователь просматривает текущую страницу. Но для того, чтобы этот сценарий работал, необходимо настроить поиск имени хоста внутри httpd.conf.

3. $_SERVER['HTTP_CLIENT_IP'] - При этом будет получен IP-адрес, когда пользователь находится в общих интернет-службах.

4. $_SERVER['HTTP_X_FORWARDED_FOR'] - это будет получать IP-адрес от пользователя, когда он / она находится за прокси.

Таким образом, мы можем использовать следующую комбинированную функцию для получения реального IP-адреса от пользователей, просматривающих в разных позициях,

// Function to get the user IP address
function getUserIP() {
    $ipaddress = '';
    if (isset($_SERVER['HTTP_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_X_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    else if(isset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    else if(isset($_SERVER['REMOTE_ADDR']))
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}

user5147563
10 августа 2017 в 12:50
10

Действительно легко подделать. Я только что попробовал на своем веб-сайте с расширением Requestly Chrome, установив заголовок Client-ip на «111.111.111.111».

avatar
oriadam
16 ноября 2016 в 18:15
1

Вот простой лайнер

$ip = $_SERVER['HTTP_X_FORWARDED_FOR']?: $_SERVER['HTTP_CLIENT_IP']?: $_SERVER['REMOTE_ADDR'];

РЕДАКТИРОВАТЬ:

Приведенный выше код может возвращать зарезервированные адреса (например, 10.0.0.1), список адресов всех прокси-серверов на пути и т. Д. Для обработки этих случаев используйте следующий код:

function valid_ip($ip) {
    // for list of reserved IP addresses, see https://en.wikipedia.org/wiki/Reserved_IP_addresses
    return $ip && substr($ip, 0, 4) != '127.' && substr($ip, 0, 4) != '127.' && substr($ip, 0, 3) != '10.' && substr($ip, 0, 2) != '0.' ? $ip : false;
}

function get_client_ip() {
    // using explode to get only client ip from list of forwarders. see https://en.wikipedia.org/wiki/X-Forwarded-For
    return
    @$_SERVER['HTTP_X_FORWARDED_FOR'] ? explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'], 2)[0] :
    @$_SERVER['HTTP_CLIENT_IP'] ? explode(',', $_SERVER['HTTP_CLIENT_IP'], 2)[0] :
    valid_ip(@$_SERVER['REMOTE_ADDR']) ?:
    'UNKNOWN';
}

echo get_client_ip();
avatar
Ivan Barayev
19 июня 2016 в 00:09
6

Эта функция компактна, и ее можно использовать везде. Но!

Не забывайте об этом! В этом типе функций или кодовых блоков нет гарантии для записи реального IP-адреса пользователя, потому что некоторые пользователи могут использовать прокси или другой безопасный шлюз для невидимости или не могут отслеживать

Функция PHP:

function GetIP()
{
    if ( getenv("HTTP_CLIENT_IP") ) {
        $ip = getenv("HTTP_CLIENT_IP");
    } elseif ( getenv("HTTP_X_FORWARDED_FOR") ) {
        $ip = getenv("HTTP_X_FORWARDED_FOR");
        if ( strstr($ip, ',') ) {
            $tmp = explode(',', $ip);
            $ip = trim($tmp[0]);
        }
    } else {
        $ip = getenv("REMOTE_ADDR");
    }
    return $ip;
}

Использование:

$IP = GetIP(); или напрямую GetIP();

avatar
Siamak
26 мая 2016 в 10:49
11

Как уже говорилось ранее, вы можете использовать $_SERVER['REMOTE_ADDR']; для получения IP-адреса клиента.

Кроме того, если вам нужна дополнительная информация о пользователе, вы можете использовать это:

<?php
    $ip = '0.0.0.0';
    $ip = $_SERVER['REMOTE_ADDR'];
    $clientDetails = json_decode(file_get_contents("http://ipinfo.io/$ip/json"));
    echo "You're logged in from: <b>" . $clientDetails->country . "</b>";
?>

Более подробная информация о клиенте содержится в $ clientDetails.
Вы можете получить элементы JSON, хранящиеся в переменной $ clientDetails, следующим образом: $ clientDetails-> PostalCode / hostname / region / loc ...

Я использую ipinfo.io для получения дополнительной информации.

avatar
Akam
27 апреля 2016 в 01:28
6

Следующая функция определяет все возможности и возвращает значения в формате, разделенном запятыми (ip, ip и т. Д.).

Он также имеет дополнительную функцию проверки (первый параметр, который по умолчанию отключен) для проверки IP-адреса (частный диапазон и зарезервированный диапазон).

<?php
echo GetClientIP(true);

function GetClientIP($validate = False) {
  $ipkeys = array(
  'REMOTE_ADDR',
  'HTTP_CLIENT_IP',
  'HTTP_X_FORWARDED_FOR',
  'HTTP_X_FORWARDED',
  'HTTP_FORWARDED_FOR',
  'HTTP_FORWARDED',
  'HTTP_X_CLUSTER_CLIENT_IP'
  );

  /*
  Now we check each key against $_SERVER if containing such value
  */
  $ip = array();
  foreach ($ipkeys as $keyword) {
    if (isset($_SERVER[$keyword])) {
      if ($validate) {
        if (ValidatePublicIP($_SERVER[$keyword])) {
          $ip[] = $_SERVER[$keyword];
        }
      }
      else{
        $ip[] = $_SERVER[$keyword];
      }
    }
  }

  $ip = ( empty($ip) ? 'Unknown' : implode(", ", $ip) );
  return $ip;
}

function ValidatePublicIP($ip){
  if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
    return true;
  }
  else {
    return false;
  }
}
avatar
Yash Kumar Verma
24 февраля 2016 в 09:21
10

Что ж, это можно просто сделать, используя переменную GLOBAL с именем $_SERVER.

$_SERVER - это массив с именем атрибута REMOTE_ADDR.

Просто назначьте его так:

$userIp = $_SERVER['REMOTE_ADDR'];

Или используйте его напрямую, например, echo $_SERVER['REMOTE_ADDR']; или echo ($_SERVER['REMOTE_ADDR']);.

avatar
Mahfuz Ahmed
28 декабря 2015 в 10:50
10
$ip = "";

if (!empty($_SERVER["HTTP_CLIENT_IP"]))
{
    // Check for IP address from shared Internet
    $ip = $_SERVER["HTTP_CLIENT_IP"];
}
elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]))
{
    // Check for the proxy user
    $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}
else
{
    $ip = $_SERVER["REMOTE_ADDR"];
}
echo $ip;
Robin Kanters
8 января 2016 в 14:29
0

Как первый сниппет возвращает IP-адрес клиента? Мне кажется, он будет повторять адрес сервера.

Mahfuz Ahmed
10 января 2016 в 05:36
0

Спасибо, Робин. Да, иногда вы не получите правильного результата. Пожалуйста, используйте второе решение.

Daksh B
18 января 2016 в 10:20
0

@MahfuzAhmed, можешь сказать, что делает file_get_contents ()? и как получить IP через file_get_contents ()

Maciej Paprocki
18 января 2016 в 14:09
0

file_get_contents здесь совершенно бесполезен :)

Mahfuz Ahmed
19 января 2016 в 05:29
0

Дакш Б. Это был сторонний API. Я удалил это. так как это небезопасный способ .... Если вам нужно попробовать приведенный выше код сейчас.

Yash Kumar Verma
8 апреля 2016 в 12:10
1

Зачем нужно было инициализировать $ip в строке 1. Если все условия не пройдут, то также будет запущен $ip = $_SERVER['REMOTE_ADDR'].

Mahfuz Ahmed
9 апреля 2016 в 06:19
0

Да, друг Яш Верма, ты прав. И вы знаете, что для использования переменной в качестве вывода мы должны инициализировать это здесь, у меня есть инициализация как "" (пустая строка).

avatar
GYANENDRA PRASAD PANIGRAHI
26 мая 2015 в 10:49
6

Попробуйте это:

 $_SERVER['REMOTE_ADDR'];
kenorb
26 мая 2015 в 11:23
29

Об этом уже упоминалось несколько раз, и ваш ответ не добавляет ничего полезного.

Chris
10 сентября 2015 в 13:40
0

«вы отвечаете», на самом деле ничего полезного не добавляет »- не понимаю, что вы имеете в виду, оно отвечает на заданный вопрос. как это бесполезно?

Mg Thar
12 октября 2015 в 14:29
11

потому что он отвечает на вопрос пятилетней давности, и уже даны ответы на многие такие же и гораздо лучшие ответы.

Hector
16 мая 2016 в 06:49
1

@ gyanendra-prasad-panigrahi постарайтесь включить в свой ответ полезные ссылки, такие как документация по функциям.

avatar
manuelbcd
29 января 2015 в 14:37
39

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

function get_ip_address() {

    // Check for shared Internet/ISP IP
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && validate_ip($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }

    // Check for IP addresses passing through proxies
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {

        // Check if multiple IP addresses exist in var
        if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false) {
            $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            foreach ($iplist as $ip) {
                if (validate_ip($ip))
                    return $ip;
            }
        }
        else {
            if (validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
                return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED']) && validate_ip($_SERVER['HTTP_X_FORWARDED']))
        return $_SERVER['HTTP_X_FORWARDED'];
    if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
        return $_SERVER['HTTP_FORWARDED_FOR'];
    if (!empty($_SERVER['HTTP_FORWARDED']) && validate_ip($_SERVER['HTTP_FORWARDED']))
        return $_SERVER['HTTP_FORWARDED'];

    // Return unreliable IP address since all else failed
    return $_SERVER['REMOTE_ADDR'];
}

/**
 * Ensures an IP address is both a valid IP address and does not fall within
 * a private network range.
 */
function validate_ip($ip) {

    if (strtolower($ip) === 'unknown')
        return false;

    // Generate IPv4 network address
    $ip = ip2long($ip);

    // If the IP address is set and not equivalent to 255.255.255.255
    if ($ip !== false && $ip !== -1) {
        // Make sure to get unsigned long representation of IP address
        // due to discrepancies between 32 and 64 bit OSes and
        // signed numbers (ints default to signed in PHP)
        $ip = sprintf('%u', $ip);

        // Do private network range checking
        if ($ip >= 0 && $ip <= 50331647)
            return false;
        if ($ip >= 167772160 && $ip <= 184549375)
            return false;
        if ($ip >= 2130706432 && $ip <= 2147483647)
            return false;
        if ($ip >= 2851995648 && $ip <= 2852061183)
            return false;
        if ($ip >= 2886729728 && $ip <= 2887778303)
            return false;
        if ($ip >= 3221225984 && $ip <= 3221226239)
            return false;
        if ($ip >= 3232235520 && $ip <= 3232301055)
            return false;
        if ($ip >= 4294967040)
            return false;
    }
    return true;
}
tobltobs
29 января 2016 в 00:59
9

Это не правильно. HTTP_CLIENT_IP более ненадежен, чем REMOTE_ADDR, а функция проверки IP - ерунда.

Mike Q
31 августа 2017 в 01:19
0

@tobltobs. забавно, что вы так говорите, но это единственный набор функций, который действительно работал у меня за окном лака при загрузке страницы перенаправления. Я показываю ему большие пальцы.

Peter Mortensen
2 марта 2019 в 23:32
0

Ссылка (фактически) не работает.

manuelbcd
29 апреля 2019 в 14:10
0

ссылка удалена, похоже страница исчезла. Спасибо

FabianoLothor
3 мая 2019 в 20:47
0

Это лучший способ получить ip в 2019 году?

avatar
B.F.
6 декабря 2014 в 10:41
0

Как следующий?

if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', validate_ip)) === false or empty($ip)) {
    exit;
}
echo $ip;

PS

if (($ip=filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP|FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE)) === false) {
    header('HTTP/1.0 400 Bad Request');
    exit;
}

Все заголовки, начинающиеся с «HTTP_» или «X-», могут быть подделаны, соответственно, определяется пользователем. Если вы хотите отслеживать, используйте файлы cookie и т. Д.

avatar
josh123a123
8 октября 2014 в 16:20
128

Вот более понятный пример кода хорошего способа получить IP-адрес пользователя.

$ip = $_SERVER['HTTP_CLIENT_IP'] 
   ? $_SERVER['HTTP_CLIENT_IP'] 
   : ($_SERVER['HTTP_X_FORWARDED_FOR'] 
        ? $_SERVER['HTTP_X_FORWARDED_FOR'] 
        : $_SERVER['REMOTE_ADDR']);

Вот более короткая версия, в которой используется оператор elvis:

$_SERVER['HTTP_CLIENT_IP'] 
   ? : ($_SERVER['HTTP_X_FORWARDED_FOR'] 
   ? : $_SERVER['REMOTE_ADDR']);

Вот версия, которая использует isset для удаления уведомлений (спасибо, @shasi kanth):

$ip = isset($_SERVER['HTTP_CLIENT_IP']) 
    ? $_SERVER['HTTP_CLIENT_IP'] 
    : isset($_SERVER['HTTP_X_FORWARDED_FOR']) 
      ? $_SERVER['HTTP_X_FORWARDED_FOR'] 
      : $_SERVER['REMOTE_ADDR'];
josh123a123
25 ноября 2014 в 03:50
12

Всегда не забывайте дезинфицировать любой ввод, который мог быть изменен пользователем. Это один из тех моментов.

DavidTaubmann
23 июня 2016 в 23:11
7

Я считаю, что в коде отсутствует какое-то выражение, а порядок приоритетов обратный, поэтому он должен быть таким: $ip = $_SERVER['HTTP_CLIENT_IP']?$_SERVER['HTTP_CLIENT_IP']:($_SERVER['HTTP_X_FORWARDED_FOR']?$_SERVER['HTTP_X_FORWARDED_FOR']:$_SERVER['REMOTE_ADDR']); Тем не менее, очень хорошее.

josh123a123
27 июня 2016 в 20:51
1

Хороший улов. Пост поправил. Спасибо!

SpYk3HH
7 сентября 2016 в 21:44
0

Как функция, с фильтрацией: function getUserIP() { $client = @$_SERVER['HTTP_CLIENT_IP']; $forward = @$_SERVER['HTTP_X_FORWARDED_FOR']; return filter_var($client, FILTER_VALIDATE_IP) ? $client : filter_var($forward, FILTER_VALIDATE_IP) ? $forward : $_SERVER['REMOTE_ADDR']; }

oriadam
16 ноября 2016 в 18:07
0

Вы проверяете один заголовок и возвращаете другой ... Похоже на ошибку.

josh123a123
16 ноября 2016 в 20:02
0

@ SpYk3HH Прекратите редактировать это, если не знаете, что делаете.

SpYk3HH
16 ноября 2016 в 20:40
0

Я так и сделал, я просто дурачился в своем первом редактировании. кстати, это не сработает, но делайте то, что вам нравится. лучший рабочий код: $ip = $_SERVER['HTTP_CLIENT_IP']?$_SERVER['HTTP_CLIENT_IP']:($_SERVER['HTTP_X_FORWARDE‌​D_FOR']?$_SERVER['HTTP_X_FORWARDED_FOR']:$_SERVER['REMOTE_ADDR']);

josh123a123
17 ноября 2016 в 14:54
0

@ SpYk3HH, вы понимаете, что это тот же код, что и у меня в посте, верно?

SpYk3HH
18 ноября 2016 в 15:43
0

Не совсем так, в вашем посте плохие персонажи. я пытался это прокомментировать. может я пропустил это, может ты пропустил. Я не пытался ничего навредить, но нельзя скопировать и вставить ваш код как есть. или, по крайней мере, я столкнулся с этой проблемой.

josh123a123
21 ноября 2016 в 15:11
0

отлично работает в phpstorm, какую IDE вы используете?

shasi kanth
29 ноября 2017 в 12:18
6

Просто добавлен isset () для удаления уведомлений: $ ip = isset ($ _ SERVER ['HTTP_CLIENT_IP'])? $ _ SERVER ['HTTP_CLIENT_IP']: isset ($ _ SERVER ['HTTP_X_FORWARDE‌ D_FOR'])? $ _ SERVER [ 'HTTP_X_FORWARDED_FOR']: $ _ SERVER ['REMOTE_ADDR'];

Toskan
15 февраля 2018 в 22:34
0

чувак, ваша версия isset полна пробелов и синтаксических ошибок там, где их не должно быть. Просто скопируйте версию и вставьте ее в phptester.net

Frank
19 февраля 2018 в 11:46
2

Как кто-то указал, все три примера НАПОЛНЕНЫ СКРЫТЫМИ ПЕРСОНАЖАМИ (U + 200C и U + 200B). Не вставляйте их в свой php-скрипт, иначе вы получите ОШИБКИ ПОСАДКИ. Если вы хотите увидеть все скрытые символы, вставьте эти строки сюда: soscisurvey.de/tools/view-chars.php. Пожалуйста, очистите этот код!

bormat
25 февраля 2018 в 21:58
0

Пришлось заменить?: На ?? и это решает проблему неопределенного индекса $ _SERVER ['HTTP_CLIENT_IP'] ?? ($ _SERVER ['HTTP_X_FORWARDE‌ D_FOR'] ?? $ _SERVER ['REMOTE_ADDR']);

Curtis
28 марта 2019 в 05:16
0

Для меня HTTP_X_FORWARDED_FOR - это IP-адрес сервера, а HTTP_CLIENT_IP не установлен. Так что это не работает. Только REMOTE_ADDR имеет IP-адрес пользователя.

hiburn8
26 сентября 2019 в 09:36
0

Вложенные тернарные операторы - это дьявол. Либо используйте метод elvis, либо просто вложенные IF.

aFeijo
11 октября 2019 в 15:47
0

с php 7.x вы можете использовать следующий синтаксис: $ ip = $ _SERVER ['HTTP_CLIENT_IP'] ?? $ _SERVER ['HTTP_X_FORWARDED_FOR'] ?? $ _SERVER ['HTTP_X_REAL_IP'] ?? $ _SERVER ['REMOTE_ADDR'];

avatar
algorhythm
7 июля 2014 в 09:02
58

Моим любимым решением является способ использования Zend Framework 2. Он также учитывает свойства $_SERVER, HTTP_X_FORWARDED_FOR, HTTP_CLIENT_IP, REMOTE_ADDR, но объявляет класс для установки некоторых доверенных прокси и возвращает один IP-адрес, а не массив. Я думаю, что это решение, которое ближе всего к нему:

class RemoteAddress
{
    /**
     * Whether to use proxy addresses or not.
     *
     * As default this setting is disabled - IP address is mostly needed to increase
     * security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
     * just for more flexibility, but if user uses proxy to connect to trusted services
     * it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
     *
     * @var bool
     */
    protected $useProxy = false;

    /**
     * List of trusted proxy IP addresses
     *
     * @var array
     */
    protected $trustedProxies = array();

    /**
     * HTTP header to introspect for proxies
     *
     * @var string
     */
    protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';

    // [...]

    /**
     * Returns client IP address.
     *
     * @return string IP address.
     */
    public function getIpAddress()
    {
        $ip = $this->getIpAddressFromProxy();
        if ($ip) {
            return $ip;
        }

        // direct IP address
        if (isset($_SERVER['REMOTE_ADDR'])) {
            return $_SERVER['REMOTE_ADDR'];
        }

        return '';
    }

    /**
     * Attempt to get the IP address for a proxied client
     *
     * @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
     * @return false|string
     */
    protected function getIpAddressFromProxy()
    {
        if (!$this->useProxy
            || (isset($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'], $this->trustedProxies))
        ) {
            return false;
        }

        $header = $this->proxyHeader;
        if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
            return false;
        }

        // Extract IPs
        $ips = explode(',', $_SERVER[$header]);
        // trim, so we can compare against trusted proxies properly
        $ips = array_map('trim', $ips);
        // remove trusted proxy IPs
        $ips = array_diff($ips, $this->trustedProxies);

        // Any left?
        if (empty($ips)) {
            return false;
        }

        // Since we've removed any known, trusted proxy servers, the right-most
        // address represents the first IP we do not know about -- i.e.  we do
        // not know if it is a proxy server, or a client. As such, we treat it
        // as the originating IP.
        // @see http://en.wikipedia.org/wiki/X-Forwarded-For
        $ip = array_pop($ips);
        return $ip;
    }

    // [...]
}

Полный код см. Здесь: https://raw.githubusercontent.com/zendframework/zend-http/master/src/PhpEnvironment/RemoteAddress.php

jnhghy - Alexandru Jantea
19 января 2015 в 14:19
3

Отличный ответ! Использование кода, протестированного в производственной среде, разработанного и используемого в таком большом фреймворке, - одна из лучших вещей, которые вы можете сделать :)

M H
19 июля 2015 в 05:57
2

Так подождите, зенд ничего не фильтрует? Я должен увидеть что-то вроде: filter_var ($ _SERVER ['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);

Marius.C
10 августа 2015 в 10:37
0

@Hanoncs, зачем тебе это делать? очень сложно подделать удаленный адрес

algorhythm
10 августа 2015 в 16:33
1

@Hanoncs Я думаю, вам нужно проверить значение после получения его с помощью этого класса. Это не часть логики. Он просто получает значение из переменной $_SERVER как есть и перепрыгивает через некоторые определенные и хорошо известные прокси-серверы. Вот и все. Если вы считаете, что возвращаемое значение небезопасно, проверьте его или сообщите об ошибке разработчикам PHP.

nu everest
10 декабря 2016 в 16:50
0

@algorhythm Как определить, что такое известный прокси-сервер?

avatar
carbontwelve
13 февраля 2014 в 14:47
10

Это метод, который я использую, и он проверяет ввод IPv4:

// Get user IP address
if ( isset($_SERVER['HTTP_CLIENT_IP']) && ! empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif ( isset($_SERVER['HTTP_X_FORWARDED_FOR']) && ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
}

$ip = filter_var($ip, FILTER_VALIDATE_IP);
$ip = ($ip === false) ? '0.0.0.0' : $ip;
deceze♦
27 апреля 2014 в 06:21
24

Спасибо, что позволили мне подделать мой IP-адрес, просто установив HTTP-заголовок!

avatar
Johan Wikström
10 мая 2011 в 12:00
11

Мне нравится этот код сниппет:

function getClientIP() {

    if (isset($_SERVER)) {

        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
            return $_SERVER["HTTP_X_FORWARDED_FOR"];

        if (isset($_SERVER["HTTP_CLIENT_IP"]))
            return $_SERVER["HTTP_CLIENT_IP"];

        return $_SERVER["REMOTE_ADDR"];
    }

    if (getenv('HTTP_X_FORWARDED_FOR'))
        return getenv('HTTP_X_FORWARDED_FOR');

    if (getenv('HTTP_CLIENT_IP'))
        return getenv('HTTP_CLIENT_IP');

    return getenv('REMOTE_ADDR');
}
Pacerier
2 октября 2011 в 02:23
2

я имею в виду, в чем смысл ... разве getenv не дает то же самое, что $_SERVER?

Mavelo
8 января 2015 в 18:55
0

@Pacerier, я предполагаю, что это более старые версии PHP, где $ _SERVER еще не был доступен;)

nu everest
10 декабря 2016 в 16:39
0

@Johan Почему бы просто не вернуть массив со всеми тремя?

StackOverflowed
17 декабря 2016 в 21:07
0

@nueverest Потому что пользователь не получает доступ к вашему сайту с 3 разных IP-адресов (обычно). Вы хотите вернуть тот, который к нему относится.

avatar
Emil Vikström
9 июня 2010 в 05:15
1410

Что бы вы ни делали, не доверяйте данным, отправленным от клиента. $_SERVER['REMOTE_ADDR'] содержит реальный IP-адрес подключающейся стороны. Это самое надежное значение, которое вы можете найти.

Однако они могут находиться за прокси-сервером, и в этом случае прокси может установить $_SERVER['HTTP_X_FORWARDED_FOR'], но это значение легко подделать. Например, он может быть установлен кем-то без прокси, или IP может быть внутренним IP из локальной сети за прокси.

Это означает, что если вы собираетесь сохранить $_SERVER['HTTP_X_FORWARDED_FOR'], убедитесь, что вы также сохранили значение $_SERVER['REMOTE_ADDR']. Например. сохраняя оба значения в разных полях базы данных.

Если вы собираетесь сохранить IP-адрес в базе данных в виде строки, убедитесь, что у вас есть место как минимум для 45 символов . IPv6 здесь, чтобы остаться, и эти адреса больше, чем старые адреса IPv4.

(Обратите внимание, что IPv6 обычно использует не более 39 символов, но также существует специальная нотация IPv6 для адресов IPv4, которая в полной форме может содержать до 45 символов. Итак, если вы знаете, что делаете вы можете использовать 39 символов, но если вы просто хотите установить и забыть, используйте 45).

Blue
22 декабря 2014 в 21:46
4

Хороший ответ! Я уже использую $ _SERVER ['REMOTE_ADDR'] для своего сервера, и мне нравится, что вы включили другой способ, плюс его преимущества и недостатки.

Pacerier
29 июня 2015 в 04:26
53

Примечание: REMOTE_ADDR может не содержать реальный IP-адрес TCP-соединения. Это полностью зависит от вашего SAPI. Убедитесь, что ваш SAPI настроен правильно, так что $_SERVER['REMOTE_ADDR'] фактически возвращает IP-адрес TCP-соединения. В противном случае могут возникнуть серьезные уязвимости, например, StackExchange предоставил доступ администратора , проверив REMOTE_ADDR, чтобы увидеть, соответствует ли он "localhost", к сожалению, конфигурация SAPI ....... .................................................. ..................

Pacerier
29 июня 2015 в 04:26
40

.................................................. ........................ имел уязвимость (требуется HTTP_X_FORWARDED_FOR в качестве входных данных), которая позволяет пользователям, не являющимся администраторами, получить доступ администратора, изменив HTTP_X_FORWARDED_FOR заголовок. См. Также blog.ircmaxell.com/2012/11/anatomy-of-attack-how-i-hacked.html

avatar
kainosnous
9 июня 2010 в 04:56
30

Ответ - использовать переменную $_SERVER. Например, $_SERVER["REMOTE_ADDR"] вернет IP-адрес клиента.

avatar
lemon
9 июня 2010 в 04:51
220
Anup Prakash
9 июня 2010 в 05:00
1

На самом деле я хочу знать IP-адрес клиента, который использует мой веб-сайт. Не IP-адреса серверов, на которые загружены или выполняются мои страницы. Пожалуйста, помогите мне.

Artefacto
9 июня 2010 в 05:01
51

@Anup Prakash Вот и все - отсюда и «ДИСТАНЦИОННЫЙ» (с точки зрения сценария).

Si8
4 октября 2013 в 14:09
14

Я получаю это, когда использую ваш код: ::1

Ussama Dahnin
8 октября 2013 в 08:33
88

Потому что вы на localhost;)

Camilo Martin
30 декабря 2013 в 00:17
91

@ SiKni8 ::1 - это IPv6-эквивалент 127.0.0.1

Kristian
17 октября 2015 в 03:25
15

@CamiloMartin, ты только что научил меня чему-то. здорово!

Ken Sharp
18 февраля 2016 в 15:54
0

Это возвращает IP-адрес прокси.

JFK
25 января 2019 в 18:16
0

Для тех, кто получил ::1, см. coderhelper.com/questions/10517371/…

avatar
Tim Kennedy
11 сентября 2008 в 04:01
496

$_SERVER['REMOTE_ADDR'] на самом деле может не содержать реальных IP-адресов клиентов, так как, например, он даст вам прокси-адрес для клиентов, подключенных через прокси. Это может Впрочем, будь тем, чего ты действительно хочешь, в зависимости от того, что ты делаешь с IP-адресами. Чей-то частный адрес RFC1918 может не принести вам никакой пользы, если вы скажете, пытаетесь увидеть, откуда исходит ваш трафик, или помните, с какого IP-адреса последний раз подключался пользователь, где общедоступный IP-адрес прокси или шлюза NAT может быть более значительным. подходит для хранения.

Существует несколько заголовков HTTP, например X-Forwarded-For, которые могут быть установлены или не установлены различными прокси-серверами. Проблема в том, что это просто заголовки HTTP, которые может установить кто угодно. Нет никаких гарантий относительно их содержания. $_SERVER['REMOTE_ADDR'] - это фактический физический IP-адрес, с которого веб-сервер получил соединение и на который будет отправлен ответ. Все остальное - просто произвольная и добровольная информация. Есть только один сценарий, в котором вы можете доверять этой информации: вы управляете прокси, который устанавливает этот заголовок. Это означает, что только если вы на 100% знаете, где и как был установлен заголовок, вам следует обращать внимание на что-либо важное.

Сказав это, вот пример кода:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

Примечание редактора: Использование приведенного выше кода имеет последствия для безопасности . Клиент может установить всю информацию заголовка HTTP (т. Е. $_SERVER['HTTP_...) на любое произвольное значение. Таким образом, гораздо надежнее использовать $_SERVER['REMOTE_ADDR'], поскольку он не может быть установлен пользователем.

От: http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html

Janos Pasztor
25 июня 2013 в 14:37
197

НЕ используйте приведенный выше код, если вы ТОЧНО не знаете, что он делает! Я видел БОЛЬШИЕ дыры в безопасности из-за этого. Клиент может установить заголовок X-Forwarded-For или Client-IP на любое произвольное значение. Если у вас нет доверенного обратного прокси-сервера, вам не следует использовать какие-либо из этих значений.

lostphilosopher
27 января 2014 в 21:28
28

Что касается комментария Яношена, одним из вариантов является PHP filter_var ($ _ SERVER ['REMOTE_ADDR'], FILTER_VALIDATE_IP).

Martin Tournoij
13 февраля 2014 в 14:51
8

X-Forwarded-For может содержать несколько IP-адресов, разделенных запятыми; и действительно должен быть "проанализирован", а не приниматься за чистую монету (AFAIK, он почти никогда не содержит единственный IP-адрес).

Tim Seguine
16 апреля 2014 в 08:14
3

@lostphilosopher - это разумный поступок, который сделает его более надежным, но, к сожалению, он все равно позволит спуфинг.

Marin Sagovac
16 апреля 2014 в 15:06
0

Не используйте этот код выше. Это может быть подделка из HTTP_X_FORWARDED_FOR, откуда взято с поддельного адреса с использованием прокси. Пожалуйста, не используйте приведенный выше код!

Geo C.
21 мая 2014 в 21:13
0

@TimSeguine Нет, remote_addr берет ip от TCP. Невозможно подделать ip через tcp, так как для этого требуется рукопожатие.

Tim Seguine
22 мая 2014 в 10:51
0

@GeoC. Ты прав. Если я помню свое настроение, я просто имел в виду, что это предложение не помогает вам решить, действительно ли это клиент. Не думаю, что я думал о поддельных пакетах, но, честно говоря, не помню.

Tim Kennedy
22 мая 2014 в 12:49
0

@TimSeguine, ты тоже прав. Это не поможет вам решить, клиент ли это. Это может быть шлюз 6to4, или шлюз NAT, или прокси-сервер TOR, или любое количество устройств или прокси, которые не будут предоставлять действительный заголовок X-Forwarded-For:, и даже если они это сделают, нет способа проверить это. это правильный, поскольку это ненадежные данные. Вот почему этот тип данных следует использовать только для аналитики, где допустимы точные числа.

Jon Watte
1 декабря 2014 в 06:31
8

Для сайта увеличенного размера перед серверами веб-приложений будут находиться балансировщики нагрузки и / или обратные прокси. Вы должны настроить эти балансировщики нагрузки или прокси-серверы, чтобы удалить любой внешний заголовок X-Forwarded-For и вместо этого вставить свой собственный IP-адрес, который они видят для подключающегося клиента.

Jon Watte
1 декабря 2014 в 06:32
0

Кроме того, если ваш сервер приложений обслуживается CDN (Akamai, CloudFlare или что-то еще), то удаленный IP-адрес, который вы видите, может быть из CDN. Затем вам нужно будет убедиться, что CDN вставляет заголовок, которому вы можете доверять, и который не может быть подделан вредоносными клиентами, высовывающимися непосредственно на ваш сервер.

SolidSnake
5 февраля 2019 в 06:35
0

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

hiburn8
26 сентября 2019 в 09:46
0

На комментарий lostphilosopher. Вам не нужно проверять формат $ _SERVER ['REMOTE_ADDR']. Он берется из соединения с сервером, поэтому злоумышленник не может его контролировать. Вы также не можете подделать это значение (иначе вы не сможете завершить рукопожатие TCP). И проблемы безопасности, о которых упоминает Янош Пастор, в первую очередь не являются недостатками проверки ввода, такими как XSS ... более насущной проблемой было бы тестирование 127.0.0.1 для представления панели администратора локальным пользователям. С помощью приведенного выше кода злоумышленник может поместить 127.0.0.1 в заголовок HTTP_CLIENT_IP, чтобы обойти это ограничение и получить доступ.

avatar
Kyle Cronin
11 сентября 2008 в 03:38
98

Он должен содержаться в переменной $_SERVER['REMOTE_ADDR'].