Pull to refresh

Доработка парсера логов Squid для корректного просмотра посещенных HTTPS ресурсов

Reading time5 min
Views18K
Всем привет! Я получал, и получаю множество писем от людей с вопросами по Squid, который работает на основе моей статьи. Наиболее часто возникает вопрос про просмотр логов Squid каким-либо парсером. Проблема в том, что версия Squid 3.5.8 с настроенным прозрачным проксированием HTTPS логирует посещаемые HTTPS ресурсы не в виде доменных имен, а в виде IP адресов с портами (прим. 164.16.43.56:443). Соответственно, при просмотре статистики посещений вместо человеческой информации проскакивают эти самые IP адреса. Собирать статистику с такими данными довольно сложно. Я связывался с разработчиками Squid по этому поводу, но внятного ответа так и не получил. Единственное, что я выяснил, нормальное логирование работает в более новых версиях Squid, но на них прозрачное проксирование лично у меня так и не заработало должным образом. Поэтому возник вопрос о том, как сделать резолв IP адресов в самом парсере логов.

Лично я пользуюсь парсером Screen Squid, и именно в нем я решил попробовать сделать нужные изменения. Так как мне подобный резолв бывает нужен просто при работе в терминале с Bash, я решил весь процесс резолва сделать в виде скрипта на Bash, а в Screen Squid уже средствами PHP его использовать, когда это будет нужно.

Итак, для всего задуманного нам нужны:

  1. собственно, сам парсер Screen Squid (инструкцию по его установке печатать не буду, все есть на оф.сайте).
  2. Grep
  3. Sed
  4. Nslookup
  5. Whois
  6. Прямые руки

Сам Bash-скрипт представляет из себя следующее:

#!/bin/bash

#Единственный входной параметр - ip адрес, запишем его в переменную
IP="$1";

#Пробуем резолвить IP адрес с помощью NSLOOKUP, применяя GREP и SED
#для извлечение из результата нужной нам информации
hostname=$(nslookup $IP | grep -m 1 "name"  | sed 's|.*= ||'|sed -r 's/ Auth.+//' | sed 's/^[ \t]*//;s/[ \t]*$//' );

#Если попытка резолва с помощью NSLOOKUP не удалась, 
#то узнаем информацию об IP адресе с помощью whois, опять же
#применяя GREP и SED для извлечение из результата нужной нам информации
if [[ "$hostname" == '' ]]; then
	hostname=$(whois $IP | grep -m 1 "owner\|OrgName\|orgname\|NetName\|netname\|origin" | sed 's|.*: ||'|sed -r 's/. Auth.+//' | sed 's/^[ \t]*//;s/[ \t]*$//')
fi

#Выводим на экран результат резолва
echo "$hostname"

exit 0;

В принципе, он уже откомментирован, описывать здесь особенно и нечего. Мы получаем информацию об IP адресе сначала с помощью Nslookup, параллельно фильтруя вывод команды с помощью grep и sed, чтобы исключить ненужную информацию. Дабы не писать кучу строк, были использованы возможности grep по включению нескольких условий для выборки (символы "\|"). Сохраняйте скрипт в любом удобном месте, назначайте ему права на выполнение. Допустим, он сохранен в /usr/bin под именем gethost.sh.

Скрипт можно использовать просто из терминала:

gethost.sh ip_address 

Далее расскажу, как этот скрипт прикрутить к Screen Squid. Допустим, что установлен он в /var/www/html. В этой папке будет подпапка reports, где находится файл reports.php. Вот именно в нем необходимо сделать изменения. В этом файле необходимо найти строки:

$result=mysql_query($queryOneIpaddressTraffic) or die (mysql_error());
$numrow=1;
$totalmb=0;
while ($line = mysql_fetch_array($result,MYSQL_NUM)) {
echo "<tr>";
echo "<td>".$numrow."</td>";

if($enableUseiconv==1)
$line[0]=iconv("CP1251","UTF-8",urldecode($line[0]));

echo "<td><a href='http://".$line[0]."' target=blank>".$line[0]."</a></td>";

И вместо последней строки вставить следующее:

//Проверяем, HTTPS ресурс в строке или нет (по наличию символа ':')
//Если символа нет, значит это HTTP ресурс, сразу отображаем на страницу
$dv=strpos($line[0], ":") ;
if ($dv < 1) {
echo "<td><a href='http://".$line[0]."' target=blank>".$line[0]."</a></td>";
} else 
{

// Если же все таки символ ':' присутствует, следовательно это HTTPS ресурс, значит
// производим "колдовские" действия...

// Отделяем IP адрес от всей строки, т.е. все символы до ':'
$str1=strpos($line[0], ":");
$row1=substr($line[0], 0, $str1);
$ipaddress = ltrim($ipaddress);
$ipaddress = $row1;

// Производим резолв IP адреса с помощью скрипта gethost.sh
$hostname = shell_exec('/usr/bin/gethost.sh ' . $ipaddress);

// Выводим в таблицу полученную информацию об IP адресе
echo "<td><a href='https://".$ipaddress."' target=blank>".$hostname."</a></td>";
}

Код писАлся на скорую руку, но вполне работает. А срабатывает он, когда открывается просмотр отчета «Трафик пользователей IP адреса», лично мне по большей части необходим только такой отчет. При желании, можно добавить подобный код на любые другие отчеты.

Сам код довольно прост: сначала определяется, какой в данный момент ресурс выводится на экран в таблицу: HTTP или HTTPS, и если это HTTPS (определяется по наличию символа ":"), то отделяем IP адрес от порта, передаем IP адрес в скрипт gethost.sh, получаем вывод скрипта в виде информации об IP адресе, и выводим на экран.

Были мысли заносить в БД сразу нужные данные, но резолв вышеуказанным образом на этапе заполнения БД приводит к длительному процессу распития кофейных напитков, поэтому я от него отказался.

Ах да, чуть не забыл, скрипт должен быть на том же сервере, где расположен парсер Screen Squid. Ну это так, к слову.

Если есть предложения по улучшению, доработке, переделке данного скрипта, буду рад выслушать.

Дополнения:

Сделал немного по-другому, мне кажется более информативно, как здесь верно подметил товарищ kbool. Можно получить данные SSL сертификата нужного хоста прямо из PHP, считав оттуда интересующую информацию. Ниже код, который надо вставить в reports.php вместо вышепредложенного:

//Проверяем, HTTPS ресурс в строке или нет (по наличию символа ':')
//Если символа нет, значит это HTTP ресурс, сразу отображаем на страницу
$dv=strpos($line[0], ":") ;
if ($dv < 1) {
echo "<td><a href='http://".$line[0]."' target=blank>".$line[0]."</a></td>";
} else 
{

// Если же все таки символ ':' присутствует, следовательно это HTTPS ресурс, значит
// производим "колдовские" действия...

// Отделяем IP адрес от всей строки, т.е. все символы до ':'
$str1=strpos($line[0], ":");
$row1=substr($line[0], 0, $str1);
$ipaddress = ltrim($ipaddress);
$ipaddress = $row1;
// Производим резолв IP адреса 
///////////////////////////////////////////////////////////
$options = array( 
        "ssl" => array(
        "capture_peer_cert"       => true,
        "capture_peer_chain"      => true,
        "capture_peer_cert_chain" => false, 
        "verify_peer"             => false,
        "verify_peer_name"        => false, 
        "allow_self_signed"       => false )
);

$get = stream_context_create($options);
$read = stream_socket_client("ssl://".$ipaddress.":443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $get);
$cert = stream_context_get_params($read);
$certinfo = openssl_x509_parse($cert['options']['ssl']['peer_certificate']);
$certinfo = $certinfo['name'];
$CN=strpos($certinfo,"CN=")+3;
$CN_end=strlen($certinfo);
$hostname = substr($certinfo, $CN, $CN_end);
////////////////////////////////////////////////////////////
// Выводим в таблицу полученную информацию об IP адресе
echo "<td><a href='https://".$ipaddress."' target=blank>".$hostname."</a></td>";
}

Tags:
Hubs:
Total votes 12: ↑10 and ↓2+8
Comments46

Articles