Блог


Определение IP пользователя.

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

 
Однако не все умеют делать это правильно. И в силу этого рискуют получить неверное значение IP, а в результате получить по морде лица, если по этому неверному адресу окажется не тщедушный ботаник, а какой-нибудь Чак Норрис.

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

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

По этому протоколу каждой подсети, объединенной в глобальную сеть, присваивается индивидуальный адрес. Тот самый, который в простонародье и принято называть IP. Адрес этот уникален, как и любой почтовый адрес. Соответственно, зная его и имея доступ к базе IP-адресов, можно легко вычислить и покарать обидчика, например.

В настоящее время используется версия IPv4, она использует адреса длиной 4 байта. Но интернет так бурно развивается, что этого стало недостаточно, чтобы присвоить адреса всем желающим. И сейчас вводится в эксплуатацию версия IPv6 с 6-ти байтовыми адресами соответственно. Это сейчас не столь важно, просто для ремарки.

Так вот, IP-адрес содержится в заголовках любого HTTP запроса, а по сему его не представляется труда узнать на сервере. Однако важно знать еще одну деталь. IP-адреса бывают двух типов - статический и динамический. Статический присваивается подсети на постоянной основе и никогда не меняется. Динамический присваивается провайдером в момент подключения и он будет разным для каждого сеанса. Это сделано в целях экономии IP адресов, так как позволяет использовать список свободных в данный момент. Статический адрес будет "простаивать", если подсеть не подключена к интернету, динамические используются более рационально. Найти обидчика с динамическим IP бывает гораздо сложнее, тут как раз и можно нарваться на Чака вместо ожидаемого ботаника.

Ну а теперь серьёзно. Не для выяснения отношений же мы хотим "вычислить" IP-адрес. Это нужно для совершенно других целей. Вот основные четыре:

1. Ограничить доступ к ресурсу пользователя с определенным IP (пресловутый бан)
2. Разрешить доступ только с доверенных IP  допустим в админку.
3. Привязать текущую сессию к IP, дабы усложнить вход в аккаунт с нескольких компьютеров одновременно.
4. Слогировать попытки доступа, чтобы посмотреть потом, кто и откуда ломился.

На нормально настроенных серверах IP-адрес можно (и должно) узнать из переменной окружения PHP 
$_SERVER['REMOTE_ADDR']
Однако изредка встречаются криворукие админы, которые настраивают сервер так, что IP адрес находится в
$_SERVER['HTTP_X_FORWARDED_FOR'], 
$_SERVER['HTTP_CLIENT_IP'] ,
$_SERVER['HTTP_VIA']

и еще чёрти где. А в рассово верную $_SERVER['REMOTE_ADDR'] помещают IP самого сервера. С этим не стоит мириться, особенно в первых 3 случаях из списка, это нужно заставить исправить. Почему так. Дело в том, что все элементы суперглобального массива $_SERVER, начинающиеся с префикса HTTP_ - это клиентские заголовки. Те, которые можно легко подделать. 

Так что запомните, как Отче наш: если нужно узнать реальный IP-адрес, не нужно мудрить. Он находится в REMOTE_ADDR  и нигде иначе. Аппач к примеру для своих логов берет значение именно оттуда. Не стоит думать, что можно сделать скрипт, "вычисляющий" IP круче, чем у них. 

Для чего же тогда все остальные переменные? А бис его знает. А если серьёзно, то их можно использовать только для справочной информации. Допустим в
$_SERVER['HTTP_X_FORWARDED_FOR']
может через запятую находится цепочка IP-адресов прокси-серверов, которые использовались для организации маршрута. Это бывает полезно для логирования или для других, узкоспецифических задач. Однако слепо верить ему никак нельзя.

Так что для верного определения IP-адреса клиента нужно сделать два важных шага.

1. Определить, что именно находится в REMOTE_ADDR и если там не то, что нужно, покарать админа. 
2. Узнать IP-адрес вот по такой незамысловатой схеме:

1
 2
 3

    $ip
$_SERVER['REMOTE_ADDR'];


Ну а можно применить более замысловатую:

1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
<?php

    
function getIpAdress($opion ''$ban false)
    {
        if(empty(
$opion) || $opion == 'REMOTE_ADDR' || is_array($opion))
            
$header 'REMOTE_ADDR';
        
        
$ip = @$_SERVER[$header];
     
        if(
is_array($opion) && in_array($ip$opion))
            return 
$ban;
       
        return 
$ip;        
    }


Эта простенькая функция позволит:
1. Узнать настоящий IP-адрес пользователя:

1
 2
 3
 4
 
// Без аргументов узнаем IP-адрес
    
$ip getIpAdress();


2. Для справочной информации получить значение из любой переменной окружения:

1
 2
 3
 4
 5
 6
 7
 8

// Для справки можем получить допустим цепочку прокси
    
$ips getIpAdress('HTTP_X_FORWARDED_FOR');

// Или еще чего-нибудь, допустим:
    
$ip getIpAdress('HTTP_X_REAL_IP');


3. Отфильтровать неугодные IP-адреса

1
 2
 3
 4
 5
 6
 7
 8

// Массив забаненных IP
    
$ban_ips = array('127.0.0.1');
    
    if(!
getIpAdress($ban_ips))
        echo 
'БАН!';


или наоборот, разрешить доступ доверенным:

1
 2
 3
 4
 5
 6
 7
 8

// Массив доверенных IP
    
$trasted_ips = array('127.0.0.1');
// Вторым аргументом то, чего ждем на выходе    
    
if(getIpAdress($trasted_ipstrue))
        echo 
'Добро пожаловать!';


Этого вполне достаточно в 99,99% случаев. Продвинутые фреймворки кроме этого еще имеют возможность организовать так называемые Тrusted Proxies. То есть доверенную цепочку прокси серверов. Но это сегодня все больше решается на уровне "железа", на программном уровне очень редко. К тому же, как я писал раньше, это вовсе не панацея, а потенциальная дырка.  Поэтому не стоит усложнять ради усложнения. Ну а кому интересно, можно посмотреть допустим этот класс из ZEND-фреймворка.
Я же на сим откланяюсь.

 

 

Николай aka twin

Теги: PHP | Флейм

Комментарии (0)


 
Наверх