Программирование, радиоэлектроника,
саморазвитие и частичка из моей жизни здесь...

Проверка IP адреса в черных списках (DNSBL) на PHP

Безопасноть IP адреса (проверка в DNSBL)Разрабатывая приложение на PHP появилась надобность просеивать IP адреса на предмет наличия их в черных списках (Black Lists, DNSBL). Как правило с таких IP адресов рассылают спам, за ними могут быть скрыты целые бот сети, сети фальшивых ботов и браузеров, хакеры и прочие ресурсы на которые жалуются пользователи. Для сбора таких нехороших IP были созданы множественные списки - черные списки. На нескольких примерах я расскажу и покажу как можно осуществить проверку любого IP адреса в интернете на предмет наличия в публичных черных списках, используя средства PHP.

Содержание:

  1. Предисловие
  2. Проверка IP на вхождение в черные списки через сайт whoer.net
  3. Проверка IP адреса на присутствие в списке DNSBL сервисов
  4. Полезности для разработки и тестирования DNSBL
  5. Заключение

Предисловие

Изначально, чтобы не тратить сильно много времени, было решено найти какой-то публичный сервис, который осуществляет проверку 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 и поменьше спама!

Если статья оказалась полезной - помочь проекту можно тут: 👍 ПОМОЩЬ, 🎁 DONATE
1 7508 PHP