Проверка IP адреса в черных списках (DNSBL) на PHP
Разрабатывая приложение на PHP появилась надобность просеивать IP адреса на предмет наличия их в черных списках (Black Lists, DNSBL). Как правило с таких IP адресов рассылают спам, за ними могут быть скрыты целые бот сети, сети фальшивых ботов и браузеров, хакеры и прочие ресурсы на которые жалуются пользователи. Для сбора таких нехороших IP были созданы множественные списки - черные списки. На нескольких примерах я расскажу и покажу как можно осуществить проверку любого IP адреса в интернете на предмет наличия в публичных черных списках, используя средства PHP.
Содержание:
- Предисловие
- Проверка IP на вхождение в черные списки через сайт whoer.net
- Проверка IP адреса на присутствие в списке DNSBL сервисов
- Полезности для разработки и тестирования DNSBL
- Заключение
Предисловие
Изначально, чтобы не тратить сильно много времени, было решено найти какой-то публичный сервис, который осуществляет проверку IP адреса сразу в нескольких базах DNSBL. После этого для этого сервиса пишем несложный парсер на PHP и прикручиваем данный модуль в систему где нужна проверка IP адресов на наличие их в черных списках и потом уже на основе результата принимать решение что нам делать с плохим клиентом - блокировать или пропустить.
В интернете достаточно большое количество сервисов проверки по черным спискам DNSBL (Domain Name Service Black List). Их принцип работы - мы вводим IP для проверки, жмем кнопочку Проверить и после нескольких секунд получаем либо список сетей DNSBL с результатом для каждой, либо просто ответ о наличии - Да-Нет (Yes-No).
Проверка IP на вхождение в черные списки через сайт whoer.net
Один из сервисов, который проверяет IP адрес на наличие в черных списках DNSBL - это whoer.net.
Протестировав его я сразу перешел к делу. Алгоритм такой:
- загружаем страницу, в GET запросе сразу указываем для проверки нужный IP
- проверяем получили мы исходный код странички или нет, код ответа HTTP
- ищем в исходном коде кусок HTML где говорится о наличии или нет в DNSBL
- проверяем по шаблону и возвращаем результат работы.
URL для запроса выглядит вот так: http://whoer.net/check?host=xxx.xxx.xxx.xxx
Где xxx.xxx.xxx.xxx - IP Address, который будем проверять.
Сразу же протестировал функцию file_get_contents - но в результате получил код ответа 403 (Forbidden), то есть доступ запрещен. Ну тут понятно что стоит какая-то защита от простых подобных запросов, ведь используя функцию file_get_contents мы загружаем страничку с названием клиента-браузера по умолчанию (PHP...), значит такие методы на whoer.net просто присекаются.
Для загрузки странички нужно что-то более мощное и правдоподобное, будем использовать могущественный CURL. Детально останавливаться на возможностях CURL я не буде, скажу только что используя его можно работать с HTTP, FTP, SFTP, SMTP, SSH и другими протоколами.
Пишем функцию получения HTML кода странички используя CURL и эмулировать различные браузеры. Для эмуляции браузеров будем использовать массив с несколькими UserAgentString, случайно их выбирая оттуда. Хочу заметить что для генерации юзерагентов можно использовать мой класс, о нем я рассказывал в статье Класс PHP Class - User Agent String.
// Generate random UserAgent string
function get_random_useragent_strings() {
$agents = array(
'Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0',
'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0',
'Mozilla/5.0 (X11; OpenBSD amd64; rv:28.0) Gecko/20100101 Firefox/28.0',
'Mozilla/5.0 (X11; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0',
'Opera/12.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.02',
'Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00',
'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)',
);
return $agents[rand( 0, (count($agents)-1) )];
}
// Get page HTML code for specified URL
function curl_get_page_html($url = '', $user_agent = '') {
if($user_agent=='')
$user_agent = get_random_useragent_strings();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
curl_setopt ($ch, CURLOPT_USERAGENT, $user_agent);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 30);
$html = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($http_code!=200)
return false;
return $html;
}
Теперь, чтобы получить исходный код любой странички нам нужно вызвать функцию curl_get_page_html, указав ей URL. UserAgent можно не указывать, в таком случае он будет сгенерирован функцией get_random_useragent_strings.
Исходный код мы получили, нужно его разобрать на части и найти ту, где указано числится ли запрашиваемый IP адрес в черных списках или нет. Здесь нам помогут функции preg_match и strpos. Написанная нами функция в результате своей работы будет возвращать одномерный массив. Первый элемент массива - это есть ли ошибка при выполнении запроса к сайту(1-да, 0 - нет), а второй - это есть ли IP в черных списках (1-да, 0-нет).
// check IP for BL on service whoer.net
function whoer_net_check_ip($ip = '') {
$html = curl_get_page_html('http://whoer.net/check?host='.trim($ip));
if(!$html)
return array('error'=>1, 'inblack'=>0);
if(strpos($html, 'Invalid IP address'))
return array('error'=>1, 'inblack'=>0);
preg_match('#(.*?)#is', $html, $match);
if(!isset($match[1]) || $match[1]=='')
return array('error'=>1, 'inblack'=>0);
if(strpos($match[1], 'Yes'))
return array('error'=>0, 'inblack'=>1);
return array('error'=>0, 'inblack'=>0);
}
Здесь мы берем кусок кода, что расположен в полученном документе между строчками <!-- DSBL --> и <!-- TOR -->, а потом проверяем есть ли в этом кусочке кода подстрока Yes</span> что свидетельствует о наличии проверяемого IP в черных списках DNSBL. На текущий момент (23-09-2014) верстка у сервиса соответствует и функция 100% работает.
Пример использования всех функций:
$ip_address = '8.8.8.8';
$result = whoer_net_check_ip($ip_address);
echo 'IP Address to check: '.$ip_address.'
';
echo 'Error: '.($result['error'] ? 'Yes' : 'No').'
';
echo 'In Black List: '.($result['inblack'] ? 'Yes' : 'No').'
';
Результат работы:
IP Address to check: 8.8.8.8
Error: No
In Black List: No
Внимание, сорприз!!! После нескольких часов использования мои еще ранние догадки о том что может быть лимит на суточное количество запросов к сервису подтвердилось! Функция начала возвращать в своем результате флаг ошибки запроса к сервису - массив array('error'=>1, 'inblack'=>0).
Понятное дело что 10-20 запросов в сутки мне явно маловато для моих целей, нужно искать другое решение...
Проверка IP адреса на присутствие в списке DNSBL сервисов
В PHP есть такая функция: checkdnsrr - она осуществляет проверку записи DNS (A, MX, TXT...) на соответствие указанному имени хоста или IP. Ее то мы и будем использовать для прогона нашего IP по сервисах, делая поочередно к каждому запрос А записи. Такие запросы поддерживаются почти всеми DNSBl директориями, помню использовал их еще в спаморезке на UNIX сервере.
В этом примере будет две функции: первая будет возвращать массив с названиями DNSBL хостов, по которым будем проводить проверку, а вторая - осуществлять проверку по полученному списку хостов.
// get available DNSBL hosts array
function get_dnsbl_hosts() {
return array(
"b.barracudacentral.org", // http://barracudacentral.org/
"xbl.spamhaus.org", // http://spamhaus.org
"zen.spamhaus.org",
"cbl.spamhaus.org",
"pbl.spamhaus.org",
"sbl.spamhaus.org"
);
}
// check IP in DNSBL services
function dns_bl_check_ipaddress($ipaddress = '', $dnsbl_array = array()) {
if(!is_array($dnsbl_array) || !count($dnsbl_array))
$dnsbl_array = get_dnsbl_hosts();
$result = array('dnsbl_hosts' => array(), 'inblack' => 0);
if($ipaddress=='')
return false;
$reverse_ip = implode(".", array_reverse(explode(".", $ipaddress)));
foreach($dnsbl_array as $dnsbl_host) {
$is_listed = checkdnsrr($reverse_ip.".".$dnsbl_host.".", "A") ? 1 : 0;
$result['dnsbl_hosts'][$dnsbl_host] = $is_listed;
if($is_listed)
$result['inblack']++;
}
return $result;
}
Теперь, чтобы проверить IP на присутствие в черных списках DNSBL нам нужно вызвать функцию dns_bl_check_ipaddress, передав ей первым аргументов проверяемый IP. результатом работы функции будет ассоциативный массив из двух элементов:
- dnsbl_hosts - массив с названиями используемых DNSBL хостов и результатом для каждого.
- inblack - целое число, количество попаданий в черный список проверяемого IP адреса.
Вот пимер использования:
$result = dns_bl_check_ipaddress('8.8.8.8');
echo '<pre>'.print_r($result, true).'</pre>
';
Результат будет выведен на экран как текст:
Array
(
[dnsbl_hosts] => Array
(
[b.barracudacentral.org] => 0
[xbl.spamhaus.org] => 0
[zen.spamhaus.org] => 0
[cbl.spamhaus.org] => 0
[pbl.spamhaus.org] => 0
[sbl.spamhaus.org] => 0
)
[inblack] => 0
)
Полезности для разработки и тестирования DNSBL
На данном этапе хочу рассказать о некоторых полезностях, которые были найдены в процессе тестирования и разработки.
1) Где брать черные IP для теста? Для теста функций нужно было где-то брать IP адреса, которые точно есть в черных списках. Был найден сервис, который предоставляет список, целую базу IP адресов, которые попали в списки DNSBL по разным причинам.
http://myip.ms/browse/blacklist/Blacklist_IP_Blacklist_IP_Addresses_Live_Database_Real-time
Это актуальная база данных IP адресов, с которых ведется спам, рассылка вирусов, троянов, фальшивые сети, зомби и т.п. В базе есть IP из России, Германии, США и других стран, также можно сделать выборку по типу абузы или угрозы.
Самое то чтобы протестировать наши функции! Также можно базу скачать целиком, есть готовые шаблоны для htaccess-файлов и файрволов, в общем может пригодиться.
2) Актуальный список DNSBL хостов и проверка по ним. В нашу функцию проверки (массив в функции get_dnsbl_hosts) можно загрузить достаточно большой (сколько хотите) список DNSBL хостов, но примите к вниманию что проверка может занять длительное время. Поэтому нужно выбрать себе самые живые и эффективные DNSBL и работать с ними.
http://www.dnsbl.info/dnsbl-database-check.php
Достаточно неплохой сервис, который предоставляет не только список DNSBL хостов, но и производит проверку по ним указанного IP адреса - пользуйтесь! Здесь же можно выбрать для себя живые и актуальные DNSBL для использования в написанных выше функциях.
Заключение
Вот такой вот пост на тему программирования и информационной безопасности, надеюсь мой опыт пригодится другим!
Сегодня утром кто-то из России наспамил мне в блог ссылок и какой-то политической чепухи. Для уменьшения количества подобных инцидентов на блогах можно попробовать прикрутить блокировку для IP, которые есть в DNSBL, если сильно достали!
Желаю всем "чистых" IP и поменьше спама!