Bartman
Новичок
Определение IP-адреса пользователя
Приветствую!
Некоторое время назад мне потребовалось написать функцию, определяющую IP-адрес пользователя. Потратив некоторое время на поиски факторов, от которых может зависеть определение IP, я в конце-концов их нашел. Предлагаю всем желающим ознакомится с моими выкладками, оценить их и покритиковать. Буду признателен, если будут внесены поправки и дополния.
Итак, мы разбираем переменные CGI окружения. Тут возможно всего 2 варианта: пользователь работает напрямую (1) и пользователь работает через прокси-сервер (2).
Рассмотрим ПЕРВЫЙ вариант.
Если пользователь работает напрямую, то у нас будет только переменная REMOTE_ADDR, и в ней будет содержаться IP-адрес, с которого пользователь просматривает текущую страницу. То есть, другими словами, IP адрес пользователя, вызвавшего скрипт. Что касается переменной HTTP_X_FORWARDED_FOR, то она будет не определена.
Рассмотрим ВТОРОЙ вариант.
Если пользователь использует proxy сервер, то мы точно будем иметь переменую REMOTE_ADDR - в ней в этом случае хранится адрес прокси-сервера (эта переменная возвращается вместе с заголовком).
В этом варианте возможны несколько вариаций в зависимости от типа прокси-сервера (анализируем HTTP-заголовки).
1. Если используется не анонимный прокси-сервер, то он (прокси-сервер) кладет IP-адрес пользователя в хедер запроса "HTTP_CLIENT_IP" или "HTTP_X_FORWARDED_FOR". Никаких жестких стандартов на это нет и один прокси-сервер может посылать IP пользователя используя переменную "CLIENT_IP", а другой - используя переменную "HTTP_X_FORWARDED_FOR". Между ними нет большой разницы, но они никогда не используются вместе - либо одна, либо другая. Что касается переменной HTTP_X_FORWARDED_FOR - в ней указывается оригинальный адрес посетителя, т.е. с которого он пошел на proxy-server. Но не все прокси его проставляют. Переменная HTTP_X_FORWARDED_FOR может содержать более двух адресов - сколько проксей было пройдено, столько адресов и будет. В случает, если в HTTP_X_FORWARDED_FOR хранится два IP адреса, то первый - это адрес прокси-сервера, а второй адрес клиента.
2. Если proxy-server "полу-анонимный" может быть установлена переменная HTTP_X_FORWARDED - т.е. запрос шел через прокси, но откуда не скажу.
3. Если proxy-server анонимный (или лучше сказать "анонимизирующий" - anonimizer), получателю не будет известно, что используется прокси, и в этом случае HTTP_X_FORWARDED_FOR появляться не будет - IP proxy-сервера будет хранится в REMOTE_ADDR как будто запрос был инициирован оттуда. В поле HTTP_X_FORWARDED_FOR возможно появление значения "unknown" (если в файле конфигурации Squid - squid.conf - установлен параметр "forwarded_for on" - разрешить показывать в посылаемых заголовках адрес клиента сквида. Например, если запрос пришел с машины 192.1.2.3, то в заголовок будет включена строка X-Forwarded-For: 192.1.2.3, если поставить этот параметр в off, то будет включена строка X-Forwarded-For: unknown).
Подытоживая, код функции привожу ниже:
Приветствую!
Некоторое время назад мне потребовалось написать функцию, определяющую IP-адрес пользователя. Потратив некоторое время на поиски факторов, от которых может зависеть определение IP, я в конце-концов их нашел. Предлагаю всем желающим ознакомится с моими выкладками, оценить их и покритиковать. Буду признателен, если будут внесены поправки и дополния.
Итак, мы разбираем переменные CGI окружения. Тут возможно всего 2 варианта: пользователь работает напрямую (1) и пользователь работает через прокси-сервер (2).
Рассмотрим ПЕРВЫЙ вариант.
Если пользователь работает напрямую, то у нас будет только переменная REMOTE_ADDR, и в ней будет содержаться IP-адрес, с которого пользователь просматривает текущую страницу. То есть, другими словами, IP адрес пользователя, вызвавшего скрипт. Что касается переменной HTTP_X_FORWARDED_FOR, то она будет не определена.
Рассмотрим ВТОРОЙ вариант.
Если пользователь использует proxy сервер, то мы точно будем иметь переменую REMOTE_ADDR - в ней в этом случае хранится адрес прокси-сервера (эта переменная возвращается вместе с заголовком).
В этом варианте возможны несколько вариаций в зависимости от типа прокси-сервера (анализируем HTTP-заголовки).
1. Если используется не анонимный прокси-сервер, то он (прокси-сервер) кладет IP-адрес пользователя в хедер запроса "HTTP_CLIENT_IP" или "HTTP_X_FORWARDED_FOR". Никаких жестких стандартов на это нет и один прокси-сервер может посылать IP пользователя используя переменную "CLIENT_IP", а другой - используя переменную "HTTP_X_FORWARDED_FOR". Между ними нет большой разницы, но они никогда не используются вместе - либо одна, либо другая. Что касается переменной HTTP_X_FORWARDED_FOR - в ней указывается оригинальный адрес посетителя, т.е. с которого он пошел на proxy-server. Но не все прокси его проставляют. Переменная HTTP_X_FORWARDED_FOR может содержать более двух адресов - сколько проксей было пройдено, столько адресов и будет. В случает, если в HTTP_X_FORWARDED_FOR хранится два IP адреса, то первый - это адрес прокси-сервера, а второй адрес клиента.
2. Если proxy-server "полу-анонимный" может быть установлена переменная HTTP_X_FORWARDED - т.е. запрос шел через прокси, но откуда не скажу.
3. Если proxy-server анонимный (или лучше сказать "анонимизирующий" - anonimizer), получателю не будет известно, что используется прокси, и в этом случае HTTP_X_FORWARDED_FOR появляться не будет - IP proxy-сервера будет хранится в REMOTE_ADDR как будто запрос был инициирован оттуда. В поле HTTP_X_FORWARDED_FOR возможно появление значения "unknown" (если в файле конфигурации Squid - squid.conf - установлен параметр "forwarded_for on" - разрешить показывать в посылаемых заголовках адрес клиента сквида. Например, если запрос пришел с машины 192.1.2.3, то в заголовок будет включена строка X-Forwarded-For: 192.1.2.3, если поставить этот параметр в off, то будет включена строка X-Forwarded-For: unknown).
Подытоживая, код функции привожу ниже:
PHP:
function get_ip()
{
if ($ip = getenv("HTTP_CLIENT_IP")) return $ip;
if ($ip = getenv("HTTP_X_FORWARDED_FOR"))
{
if ($ip == '' || $ip == "unknown")
{
$ip = getenv("REMOTE_ADDR");
}
return $ip;
}
if ($ip = getenv("REMOTE_ADDR")) return $ip;
}