Идентификация другого конца сокета
Проблема
Имеется сокет. Вы хотите идентифицировать компьютер, находящийся на другом конце.
Решение
Если вас интересует только IP-адрес удаленного компьютера, поступите следующим образом:
use Socket;
$other_end = getpeername(SOCKET)
or die "Couldn't identify other end: $!\n";
($port, $iaddr) = unpack_sockaddr_in($other_end);
$ip_address = inet_ntoa($iaddr);
Имя хоста определяется несколько иначе:
use Socket;
$other_end = getpeername(SOCKET)
or die "Couldn't identify other end: $!\n";
($port, $iaddr) = unpack_sockaddr_in($other_end);
$actual_ip = inet_ntoa($iaddr);
$claimed_hostname = gethostbyaddr($iaddr, AF_INET);
@name_lookup = gethostbyname($claimed_hostname)
or die "Could not look up $claimed_hostname : $!\n";
@resolved_ips = map { inet_ntoa($_) }
@name_lookup[ 4..$#ips_for_hostname ];
Комментарий
В течение долгого времени задача идентификации подключившихся компьютеров считалась
более простой, чем на самом деле. Функция getpeername возвращает IP-адрес удаленного
компьютера в упакованной двоичной структуре (или undef в случае ошибки). Распаковка
выполняется функцией inet_ntoa. Если вас интересует имя удаленного компьютера, достаточно
вызвать gethostbyaddr и поискать его в таблицах DNS, не так ли?
Не совсем. Это лишь половина решения. Поскольку поиск по имени выполняется на сервере
DNS владельца имени, а поиск по IP-адресу — на сервере DNS владельца адреса, приходится
учитывать возможность, что компьютер, к которому вы подключились, выдает неверные имена.
Например, компьютер evil.crackers.org может принадлежать злобным киберпиратам, которые
сказали своему серверу DNS, что их IP-адрес (1.2.3.4) следует идентифицировать как
trusted.dod.gov. Если ваша программа доверяет trusted.dod.gov, то при подключении с
evil.crackers.org функция getpeername вернет правильный IP-адрес (1.2.3.4), однако
gethostbyaddr вернет ложное имя.
Чтобы справиться с этой проблемой, мы берем имя (возможно, ложное), полученное от
gethostbyaddr, и снова вызываем для него функцию gethostbyname. В примере с evil.crackers.org
поиск для trusted.dod.gov будет выполняться на сервере DNS dod.gov и вернет настоящий IP-адрес
(адреса) trusted.dod.gov. Поскольку многие компьютеры имеют несколько IP-адресов
(очевидный пример — распределенные Web-серверы), мы не можем использовать упрощенную
форму gethostbyname:
$packed_ip = gethostbyname($name) or die "Couldn't look up $name : $!\n";
$ip_address = inet_ntoa($packed_ip);
До настоящего момента предполагалось, что мы рассматриваем приложение с сокетами
Интернета. Функцию getpeername также можно вызвать для сокета UNIX. Если на другом
конце была вызвана функция bind,
вы получите имя файла, к которому была выполнена привязка.
Однако если на другом конце функция bind не вызывалась, то getpeername может вернуть пустую
(неупакованную) строку, упакованную строку со случайным мусором, или
undef как признак ошибки,
или ваш компьютер перезагрузится (варианты перечислены по убыванию вероятности и возрастанию
неприятностей). В нашем компьютерном деле это называется «непредсказуемым поведением».
Но даже этого уровня паранойи и перестраховки недостаточно. При желании можно обмануть
сервер DNS, не находящийся в вашем непосредственном распоряжении, поэтому при идентификации
и аутентификации не следует полагаться на имена хостов. Настоящие параноики и мизантропы
обеспечивают безопасность с помощью криптографических методов.
См. также
Proverte kod v komentariyah gde pro list tam oshibki detskie
Оставить комментарий:
|
|