| |
момент. Определить, что данные кончились,
можно с помощью функции feof(), как это было сделано в примере из листин-
га 27.1.
Функции для работы с DNS
Здесь мы рассмотрим несколько очень полезных функций для работы с DNS-
серверами и IP-адресом.
Глава 27. Сетевые функции 383
Разрешение IP-адреса в доменное
имя и наоборот
string gethostbyaddr(string $ip_address)
Функция возвращает доменное имя хоста, заданного своим IP-адресом.
В случае ошибки возвращается $ip_address.
Функция не гарантирует, что полученное имя будет на самом деле соответ-
ствовать действительности. Она лишь опрашивает хост по адресу
$ip_address и просит его сообщить свое имя. Владелец хоста, таким
образом, может передать все, что ему заблагорассудится. Как обойти эту
проблему, см. чуть ниже.
string gethostbyname(string $hostname)
Функция получает в параметрах доменное имя хоста и возвращает его IP-адрес.
Если
адрес определить не удалось, возвращает $hostname.
array gethostbynamel(string $hostname)
Эта функция очень похожа на предыдущую, но возвращает не один, а все IP-адреса
хоста с именем $hostname. Как мы знаем, одному доменному имени может соответ-
ствовать сразу несколько IP-адресов, и в случае сильной загруженности серверов
DNS-сервер сам выбирает, по какому IP-адресу перенаправить запрос. Он выбирает
тот адрес, который использовался наиболее редко.
Обратите внимание на то, что в Интернете существует множество виртуальных хос-
тов, которые имеют различные доменные имена, но один и тот же IP-адрес. Таким
образом, если следующая последовательность команд для существующего хоста с IP-
адресом $ip всегда печатает этот же адрес:
$host=gethostbyaddr($ip);
echo gethostbyname($host);
то аналогичная последовательность для домена с DNS-именем $host, наоборот, мо-
жет напечатать не то же имя, а другое:
$ip=gethostbyname($host);
echo gethostbyaddr($ip);
Корректный перевод IP-адреса
в доменное имя
Функция gethostbyaddr() на первый взгляд проста и привлекательна, но с ней
связан один нюанс, который до недавнего времени было принято игнорировать. Дело
в том, что при поиске доменного имени машины по заданному IP-адресу PHP обра-
щается к хосту по этому адресу и запрашивает у него доменное имя. Если хостом
Часть IV. Стандартные функции PHP 384
владеет злоумышленник, он может перехватить эту операцию и возвратить вам все,
что ему (а не вам) будет угодно!
Рассмотрим это на примере. Пусть вам надо определить доменное имя компьютера,
расположенного по адресу 195.84.12.34. Давайте предположим, что эта машина
принадлежит симпатичному хакеру, который настроил свой DNS-сервер так, чтобы
он говорил: "Я являюсь хостом whitehouse.gov", если его об этом спросят по
адре-
су 195.84.12.34. Так что, выполнив код:
echo gethostbyaddr("195.84.12.34");
мы получим вывод whilehouse.gov. Произошла подмена!
Как же нам быть? А вот как. Предположим, мы получили от хоста с некоторым IP-
адресом информацию, что его "зовут" whitehouse.gov. Обратимся же к нему и по-
лучим его IP-адрес, а потом сравним, тот ли это адрес, который мы запрашивали
вна-
чале:
$ip="195.84.12.34";
$host=gethostbyaddr($ip);
// Если была ошибка, $host==$ip
if($host==$ip) die("Неверный ip-адрес $ip!");
$check_ip=gethostbyname($host);
// Если была ошибка, $check_ip==$host
if($check_ip==$host) die("Неверное доменное имя $host!");
// Ну вот, теперь сверяем данные
if($ip==$check_ip)
echo "По адресу $ip расположен хост $host";
else
echo "По адресу $ip расположен хост злоумышленника!!!";
Длинно? Да. Но это еще, к сожалению, не все. Ведь у одного и того же доменного
имени могут быть сразу несколько IP-адресов. Нас устроит, если хотя бы один из
них
совпадет с затребованным нами. Так что придется воспользоваться функцией
gethostbynamel() и циклом перебора списка IP-адресов. Вот что у нас получится:
Листинг 27.2. Безопасная функция получения доменного имени
// Аналог функции gethostbyaddr(), но всегда проверяет,
// не подменил ли злоумышленник по адресу $ip имя своего
// хоста на чужое. В последнем случае просто возвращает false.
function safe_gethostbyaddr($ip)
{ // Получаем предполагаемое имя
$host=gethostbyaddr($ip);
Глава 27. Сетевые функции 385
// Адреса не существует? Не фатально — вернем то, что есть.
if($host==$ip) return $host;
// Теперь спрашиваем $host, кто он такой.
$check_ips=gethostbynamel($host);
// Есть ли среди адресов, которые он вернул, затребованны
|
|