Как получить ip адрес php
Перейти к содержимому

Как получить ip адрес php

  • автор:

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

Если вы пишите свой модуль статистики, боретесь с подозрительной активностью, например, через блокировку доступа к вашему ресурсу или решаете другую подобную задачу, IP-адрес – это тот параметр, за который можно «зацепиться», ведь он позволяет в какой-то степени отличить одного посетителя сайта от другого.

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

Итак, простое получение IP-адреса пользователя в PHP осуществляется через суперглобальный массив $_SERVER с ключом REMOTE_ADDR:

 echo $_SERVER['REMOTE_ADDR'];

Вполне рабочий вариант, но в случае, когда человек использует прокси, REMOTE_ADDR вернет нам не его (человека) реальный IP-адрес, а конечный этого прокси-сервера, через который он попал на сайт. Чтобы учесть это, воспользуйтесь следующей функцией:

 function getUserIP() { if(!empty($_SERVER['HTTP_CLIENT_IP'])) { $userIP = $_SERVER['HTTP_CLIENT_IP']; > elseif(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $userIP = $_SERVER['HTTP_X_FORWARDED_FOR']; > else { $userIP = $_SERVER['REMOTE_ADDR']; > return $userIP; >
 echo getUserIP();

Это (в общем) итоговый вариант, а теперь к нюансам.

1. Иногда нам может вернуться не один IP-адрес, а список из нескольких. Можете оставить как есть, это просто уточнение для вас, а можете получить один, например, последний:

 $userIP = explode(',', $_SERVER['REMOTE_ADDR']); // Разбиваем список IP-адресов на массив echo trim(end($userIP)); // Выводим последний элемент (IP-адрес) и удаляем у него пробелы по бокам

В случае с функцией выше эту конструкцию можно написать вместо строчки с return:

 $userIP = explode(',', $userIP); return trim(end($userIP));

2. По-хорошему, особенно если вы работаете с базой данных, полученный результат лучше фильтровать (об этом ниже).

3. Если ваш сайт подключен к Cloudflare, то стоит проверять IP, который он возвращает:

 if(isset($_SERVER['HTTP_CF_CONNECTING_IP'])) { // Если сайт подключен к Cloudflare echo $_SERVER['HTTP_CF_CONNECTING_IP']; > else { echo $_SERVER['REMOTE_ADDR']; >

Выше представленная функция тогда будет иметь следующий вид:

 function getUserIP() { if(!empty($_SERVER['HTTP_CLIENT_IP'])) { $userIP = $_SERVER['HTTP_CLIENT_IP']; > elseif(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $userIP = $_SERVER['HTTP_X_FORWARDED_FOR']; > elseif(isset($_SERVER['HTTP_CF_CONNECTING_IP'])) { // Если сайт подключен к Cloudflare $userIP = $_SERVER['HTTP_CF_CONNECTING_IP']; > else { $userIP = $_SERVER['REMOTE_ADDR']; > return $userIP; >

Когда я писал свой модуль статистики, именно этот момент «всплыл» у некоторых пользователей, которые начали его использовать.

Фильтрация (валидация) IP-адресов в PHP

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

В PHP на такой случай (фильтрация IP) существует функция filter_var.

Сама по себе функция умеет фильтровать не только IP-адреса. С ней мы уже сталкивались с вами при написании формы обратной связи (там мы с помощью неё фильтровали e-mail).

Простой пример использования:

 $userIP = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP); if($userIP) { echo $userIP; > else { echo 'IP-адрес невалиден'; >

В ранее написанной нами функции её можно использовать вместо строчки с return:

 $userIP = filter_var($userIP, FILTER_VALIDATE_IP); if($userIP) { return $userIP; > else { return 'IP-адрес невалиден'; >

Это общий вариант использования функции, который проверяет корректность IP-адреса (v4 или v6). Дополнительно можно использовать флаги:

  1. FILTER_FLAG_IPV4 – IP-адрес формата IPv4;
  2. FILTER_FLAG_IPV6 – IP-адрес формата IPv6;
  3. FILTER_FLAG_NO_PRIV_RANGE – IP-адрес не входит в диапазон частных адресов;
  4. FILTER_FLAG_NO_RES_RANGE – IP-адрес не входит в диапазон зарезервированных адресов.
 $userIP = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); if($userIP) { echo $userIP; > else { echo 'IP-адрес невалиден'; >

Флаги можно совмещать с помощью побитового оператора | (операция ИЛИ):

 $userIP = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE); if($userIP) { echo $userIP; > else { echo 'IP-адрес невалиден'; >

Таким образом, мы проверяем, что IP-адрес имеет формат IPv4 и он не входит в диапазон частных адресов.

А вот FILTER_FLAG_IPV4 и FILTER_FLAG_IPV6 между собой совмещать не стоит, поскольку функция это проверяет по умолчанию.

Как в PHP узнать IP пользователя и определить его страну?

Как в PHP узнать IP пользователя и определить его страну?

Получить IP адрес клиента в PHP можно через суперглобальный массив $_SERVER . В этом массиве IP адрес посетителя доступен через ключ REMOTE_ADDR .

// сохраним в переменную ip значение IP адреса клиента $ip = $_SERVER['REMOTE_ADDR'];

Но, если клиент использует прокси-сервер, то значение $_SERVER[‘REMOTE_ADDR’] будет содержать IP последнего прокси-сервера, через который клиент попал на сайт.

В этом случае, чтобы узнать IP посетителя можно попробовать использовать $_SERVER[‘HTTP_CLIENT_IP’] и $_SERVER[‘HTTP_X_FORWARDED_FOR’] . HTTP_CLIENT_IP и HTTP_X_FORWARDED_FOR – это заголовки, содержащие IP адрес пользователя. Данные заголовки устанавливает прокси-сервер. Обычно прокси-сервер устанавливает один из них. Данным в этих заголовках можно доверять, только если прокси-сервер надёжный. В противном случае, им доверять не стоит, т.к. их можно очень просто подделать. В этом случае лучше просто использовать $_SERVER[‘REMOTE_ADDR’] или сохранять в базу как $_SERVER[‘REMOTE_ADDR’] , так и заголовок, устанавливаемый прокси-сервером.

function getIp() { $keys = [ 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR' ]; foreach ($keys as $key) { if (!empty($_SERVER[$key])) { $ip = trim(end(explode(',', $_SERVER[$key]))); if (filter_var($ip, FILTER_VALIDATE_IP)) { return $ip; } } } } $ip = getIp(); // выведем IP клиента на экран echo 'ip = ' . $ip;

Определение страны по ip с помощью Sypex Geo

Основные шаги по созданию php скрипта, с помощью которого можно будет определять страну по ip:

1. Скачаем Sypex Geo для PHP и базу данных стран. Sypex Geo распространяется по лицензии BSD, т.е. является абсолютно бесплатным.

2. Распакуем архивы и загрузим на сервер файлы «SxGeo.php» и «SxGeo.dat». В качестве примера, создадим на сервере папку SxGeo и загрузим эти файлы в неё.

3. Создадим свой скрипт, например, «get_country_code.php».

4. Вставим в этот файл следующий код:

getCountry($ip);

5. Включим файл «get_country_code.php» в другие скрипты, в которых нужно реализовать выполнение кода в зависимости от принадлежности ip посетителя к той или иной стране.

require_once 'SxGeo/get_country_code.php'; if ($country_сode === 'RU') { // код для посетителей из России. } else { // код для посетителей из других стран. }

Определение города по ip с помощью Sypex Geo

Для определения города, потребуется загрузить архив с базой данных городов для Sypex Geo, распаковать его и загрузить на сервер.

Скрипт в этом случае будет следующий:

get($ip); // также можно использовать следующий код // $SxGeo->getCity($ip); // широта $lat = $city['city']['lat']; // долгота $lon = $city['city']['lon']; // название города на русском языке $city_name_ru = $city['city']['name_ru']; // название города на английском языке $city_name_en = $city['city']['name_en']; // ISO-код страны $country_code = $city['country']['iso']; // для получения информации более полной информации (включая регион) можно осуществить через метод getCityFull $city = $SxGeo->getCityFull($ip); // название региона на русском языке $region_name_ru = $city['region']['name_ru']; // название региона на английском языке $region_name_en = $city['city']['name_en']; // ISO-код региона $region_name_iso = $city['city']['iso'];

Для автоматического обновления баз можно воспользоваться этим архивом. В этом архиве находится php скрипт. Этот скрипт необходимо настроить, т.е. указать в нём URL для скачивания базы и пути к файлам на сервере. После этого загрузить его на сервер и настроить его запуск по расписанию с помощью cron.

Определение страны и города по ip через сервис через сервис ipstack

Рассмотрим ещё один вариант определения в php местоположения по ip посетителя, но уже не через Sypex Geo, а с помощью сервиса ipstack.

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

Планы сервиса ipstack для определения страны и города посетителя по его ip

Для получения бесплатного плана нажимаем на кнопку «GET FREE API KEY» и переходим на страницу, на которой нужно заполнить регистрационную карточку.

После регистрации, на личной странице ipstack вам будет назначен «API Access Key», который нужно скопировать. Он нам потребуется при создании php скрипта.

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

Узнать IP адрес сервера в PHP можно с помощью следующей инструкции:

// сохраним IP адрес сервера в переменную $ip_server $ip_server = $_SERVER['SERVER_ADDR']; // выведем IP адрес сервера на экран $echo $ip_server;

Пример реализации определения локации в CMS MODX

В качестве примере рассмотрим, как в CMS MODX Revolution можно очень просто без сторонних сервисов осуществить определение страны посетителя. Разработаем решение на базе Sypex Geo.

1. Для этого сначала нужно загрузить Sypex Geo в проект:

Загрузка библиотеки Sypex Geo в проект на CMS MODX Revolution с помощью которой организуем определение страны посетителя по его ip

Файл «SxGeo.php» – это основной скрипт, а «SxGeo.dat» – это база стран. Этих двух файлов достаточно для определения страны пользователя по его ip. Дополнительно в каталоге SxGeo ещё расположен файл «SxGeoCity.dat», данный файл в текущей реализации не нужен, он может потребовать, если в проекте потребуется определять не только страну пользователя, а ещё его регион и город.

2. Создадим сниппет, например «get_location.php». В качестве примера организуем это с помощью файлов. Для этого нужно чтобы был установлен pdoTools и в настройках включена опция «Использовать Fenom на страницах».

Код сниппета «get_location.php»:

getCountry($ip); unset($SxGeo); $modx->setPlaceholder('countrycode', $country); return;

Поместим файл «get_location.php» в каталог /core/elements/snippets/ .

Данный сниппет будет определять страну и помещать его код в плейсхолдер countrycode .

3. После этого в нужных шаблонах поместим код вызова сниппета и сохранение значение плейсхолдера countrycode в переменную $country_code .

{$_modx->runSnippet('@FILE snippets/get_location.php')} {set $country_code = $_modx->getPlaceholder('countrycode')}

Всё теперь чтобы написать логику достаточно использовать эту переменную.

{if $country_code === 'UA'} Код для Украины {else} Код для других стран {/if}

gethostbyname

Возвращает адрес IPv4 или строку, содержащую неизмененный hostname в случае возникновения ошибки.

Примеры

Пример #1 Простой пример использования gethostbyname()

$ip = gethostbyname ( ‘www.example.com’ );

Смотрите также

  • gethostbyaddr() — Получает доменное имя хоста, соответствующее переданному IP-адресу
  • gethostbynamel() — Получает список IPv4-адресов, соответствующих переданному доменному имени хоста
  • inet_pton() — Конвертирует читаемый IP-адрес в его упакованное представление in_addr
  • inet_ntop() — Конвертирует упакованный интернет-адрес в читаемый формат

User Contributed Notes 31 notes

10 years ago

If you do a gethostbyname() and there is no trailing dot after a domainname that does not resolve, this domainname will ultimately be appended to the server-FQDN by nslookup.

So if you do a lookup for nonexistentdomainname.be your server may return the ip for nonexistentdomainname.be.yourhostname.com, which is the server-ip.

To avoid this behaviour, just add a trailing dot to the domainname; i.e. gethostbyname(‘nonexistentdomainname.be.’)

9 years ago

This function says «Returns the IPv4 address or a string containing the unmodified hostname on failure.

This isn’t entirely true, any hostname with a null byte in it will only return the characters BEFORE the null byte.

$hostname = «foo\0bar» ;
var_dump ( $hostname );
var_dump ( gethostbyname ( $hostname ));
?>

Results:
string ‘foo�bar’ (length=7)
string ‘foo’ (length=3)

12 years ago

Important note: You should avoid its use in production.

DNS Resolution may take from 0.5 to 4 seconds, and during this time your script is NOT being executed.

Your customers may think that the server is slow, but actually it is just waiting for the DNS resolution response.

You can use it, but if you want performance, you should avoid it, or schedule it to some CRON script.

8 years ago

Options for the underlying resolver functions can be supplied by using the RES_OPTIONS environmental variable. (at least under Linux, see man resolv.conf)

Set timeout and retries to 1 to have a maximum execution time of 1 second for the DNS lookup:
putenv ( ‘RES_OPTIONS=retrans:1 retry:1 timeout:1 attempts:1’ );
gethostbyname ( $something );
?>

You should also use fully qualified domain names ending in a dot. This prevents the resolver from walking though all search domains and retrying the domain with the search domain appended.

19 years ago

For doing basic RBL (Real Time Blacklist) lookups with this function do:

$host = ‘64.53.200.156’ ;
$rbl = ‘sbl-xbl.spamhaus.org’ ;
// valid query format is: 156.200.53.64.sbl-xbl.spamhaus.org
$rev = array_reverse ( explode ( ‘.’ , $host ));
$lookup = implode ( ‘.’ , $rev ) . ‘.’ . $rbl ;
if ( $lookup != gethostbyname ( $lookup )) echo «ip: $host is listed in $rbl \n» ;
> else echo «ip: $host NOT listed in $rbl \n» ;
>
?>

Tomas V.V.Cox

17 years ago

gethostbyname and gethostbynamel does not ask for AAAA records. I have written two functions to implement this. gethostbyname6 and gethostbynamel6. I don’t believe this issue has been addressed yet.

They are made to replace gethostbyname[l], in a way that if $try_a is true, if it fails to get AAAA records it will fall back on trying to get A records.

Feel free to correct any errors, I realise that it is asking for *both* A and AAAA records, so this means two DNS calls.. probably would be more efficient if it checked $try_a before making the query, but this works for me so I’ll leave that up to someone else to implement in their own work.. the tip is out there now anyway..

Here is the code:

function gethostbyname6($host, $try_a = false) // get AAAA record for $host
// if $try_a is true, if AAAA fails, it tries for A
// the first match found is returned
// otherwise returns false

function gethostbynamel6($host, $try_a = false) // get AAAA records for $host,
// if $try_a is true, if AAAA fails, it tries for A
// results are returned in an array of ips found matching type
// otherwise returns false

$dns6 = dns_get_record($host, DNS_AAAA);
if ($try_a == true) $dns4 = dns_get_record($host, DNS_A);
$dns = array_merge($dns4, $dns6);
>
else < $dns = $dns6; >
$ip6 = array();
$ip4 = array();
foreach ($dns as $record) if ($record[«type»] == «A») $ip4[] = $record[«ip»];
>
if ($record[«type»] == «AAAA») $ip6[] = $record[«ipv6»];
>
>
if (count($ip6) < 1) if ($try_a == true) if (count($ip4) < 1) return false;
>
else return $ip4;
>
>
else return false;
>
>
else return $ip6;
>
>

Как узнать IP адрес пользователя вашего сайта?

Провайдер выделяет пользователю, постоянный или меняющийся IP адрес, но в пределах выделенных провайдеру диапазонов IP адресов. Узнав ваш IP, можно определить провайдера и его адрес со всеми вытекающими последствиями.

IP адрес становится известным серверу при установлении соединения, ваш компьютер сам его сообщает в надежде получить ответ. Если соединение происходит через прокси- сервер (сервер может быть с поддержкой анонимности), то ваш IP- адрес соответствует IP адресу этого прокси (и его сетевому имени). Довольно часто прокси- сервер «выдает» свое присутствие, передавая свои данные (и иногда ваш внутренний IP- адрес) в полях HTTP_FORWARDED, HTTP_X_FORWARDED_FOR, HTTP_VIA и других (нужно смотреть, например для PHP переменную $_SERVER).

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

PHP вывод IP адреса посетителя вашего сайта

 echo "IP-адрес клиента:
"
.$_SERVER['REMOTE_ADDR']."
"
; ?>

PHP Вывести IP, если пользователь использует прокси. Прокси позволяет увидеть IP пользователя (прозрачный/не анонимный). Однако стоит учитывать, что в заголовки HTTP_CLIENT_IP и HTTP_X_FORWARDED_FOR пользователь может записать что ему угодно.

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'];

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *