Pull to refresh

Удобный просмотр syslog журнала межсетевого экрана D-Link DFL-860E c помощью скрипта на PHP

Reading time 13 min
Views 14K
В межсетевых экранах D-Link DFL есть несколько минусов в средстве просмотра журнала событий с помощью веб-интерфейса:
— большой поток данных переполняет отображаемый журнал событий и просмотреть логи обычно возможно только за маленький промежуток времени (несколько дней, чаще только за 1 день);
— чтобы посмотреть журнал нужно зайти в веб-панель маршрутизатора (ввести пароль и логин), выбрать статус и отображение журнала. Не имея доступа к веб-панели (не являясь админом устройства) посмотреть логи невозможно, а бывает нужно дать доступ на просмотр логов человеку, которому пароль и логин к устройству давать не нужно;
— в журнале логи разбиваются на маленькие странички, и если журнал большой перелистывать такие странички становится утомительно.

В DFL можно отправлять логи на syslog сервер, который будет писать журнал в файл, правда читать потом такой файл очень неудобно из-за его большого размера и неудобного поиска.

Для тех у кого есть возможность использовать web сервер, выполняющий скрипты на php можно просматривать журнал с помощью небольшого скрипта:


<?php
$starttime = microtime(true);
$start=0;  //Счетчик категорий
$ndstatus = "all";
$ndsearchred = "";
$ndqueueid = "";

##################
#SETTINGS
	//Путь до лога
	$default_log = "/mnt/WD1600BEVT/SYSLOG/syslog-dfl.log";
	// Максимум категорий
	$default_limit = 200;
#END SETTINGS
##################

if(isset($_GET["limit"]))
	$end = $_GET["limit"];
else
	$end = $default_limit;

if(isset($_GET["logfilename"]))
	$logfilename = $_GET["logfilename"];
else
	$logfilename = $default_log;

if(isset($_GET["queue"])) $ndqueueid = $_GET["queue"];
if(isset($_GET["ndsearchred"])) $ndsearchred = $_GET["ndsearchred"];
if(isset($_GET["status"])) $ndstatus = $_GET["status"];

//Лимитируем кол-во итераций если нужно вывести все записи
$readlimit = false;
if($ndstatus!=="errors" && $ndsearchred=="")	$readlimit = true;

$first=true;

//Временные ограничения
$monthfrom = date("m");
$monthto = date("m");
$dayfrom = date("d");
$dayto = date("d");
$ndtimefrom = mktime(0,0,0);
$ndtimeto = time();

//Указан ли месяц
if(isset($_GET["monthfrom"])) $monthfrom = $_GET["monthfrom"];
if(isset($_GET["monthto"])) $monthto = $_GET["monthto"];


//Указана ли дата
if(isset($_GET["dayfrom"])) $dayfrom = $_GET["dayfrom"];
if(isset($_GET["dayto"])) $dayto = $_GET["dayto"];


//Сгенерируем unixtime для периода сортировки
if(isset($_GET["timefrom"]))
{
	if(strlen($_GET["timefrom"])>0)
		$ndtimefrom = mktime($_GET["timefrom"],0,0,$_GET["monthfrom"],$_GET["dayfrom"]);
}

if(isset($_GET["timeto"]))
{
	if(strlen($_GET["timeto"])>0)
		$ndtimeto = mktime($_GET["timeto"],0,0,$_GET["monthto"],$_GET["dayto"]);
}
elseif(isset($_GET["monthto"]))
{
	if(strlen($_GET["monthto"])>0)
		$ndtimeto = mktime(23,59,59,$_GET["monthto"],$_GET["dayto"]);
}

?>
<html>

<head>
<script>function open_win1(){var myWin=window.open("help.txt","Window","scrollbars=yes, resizable=yes,width=1360, height=655")}</script>
<script>function open_win2(){var myWin=window.open("NetDefendOS_2.27.03_Log_Reference_Guide.pdf","Window","scrollbars=yes, resizable=yes,width=1360, height=655")}</script>
<meta http-equiv="content-type" content="text/html;  charset=utf-8" />
<title>Анализатор syslog файлов D-Link DFL-860e или аналогов</title>
<style>
	body, td
	{
		font-family:Tahoma,Verdana,Sans serif;
		font-size:13px;
	}
	.queue
	{
		border:1px #ccc solid;
		margin:5px;
		padding:5px;
	}
	small
	{
		color:#999;
	}
	a.email:link, a.email:visited
	{
		cursor:pointer;
		border-bottom:1px #000 dotted;
		text-decoration:none;
		color:#000;
	}
</style>
</head>
<body>

<form name="filterform">
	<table border="0" cellpadding="5" cellspacing="5">
		<tr>
			<td colspan="2">
				<a name="begin" /></a>
				<h3>Анализатор syslog файлов D-Link DFL-860e или аналогов</h3>
			</td>
		</tr>
		<tr>
			<td width="200px">
				Укажите имя и расположение syslog файла :
				<br/><small>полный путь к log файлу</small>
			</td>
			<td>
				<input type="text" name="logfilename" value="<?=$logfilename; ?>" size="12" />
			</td>
		</tr>
		<tr>
			<td width="200px">
				Выберите какую показать категорию в журнале :
				<br/><small>Введите что нужно найти.<br/> CONN PPTP ALG ...</small>
			</td>
			<td>
				<input type="text" name="queue" value="<?=$ndqueueid; ?>" size="12" />
				<input type="button" title="6 (CONN) События State engine, например открытие/закрытие соединений" value="CONN" OnClick="document.filterform.queue.value='CONN'" />
				<input type="button" title="27 (PPTP) События PPTP-туннеля" value="PPTP" OnClick="document.filterform.queue.value='PPTP'" />
				<input type="button" title="2 (ALG) События от Application Layer Gateways" value="ALG" OnClick="document.filterform.queue.value='ALG'" />
				<input type="button" title="32 (SYSTEM) Системные события: запуск, выключение и т.д." value="SYSTEM" OnClick="document.filterform.queue.value='SYSTEM'" />
				<input type="button" title="42 (IGMP) События IGMP" value="IGMP" OnClick="document.filterform.queue.value='IGMP'" />
				<input type="button" title="33 (TCP_FLAG) События, относящиеся к флагам заголовка TCP" value="TCP_FLAG" OnClick="document.filterform.queue.value='TCP_FLAG'" />
				<input type="button" title="9 (DHCPSERVER) События DHCP-сервера" value="DHCPSERVER" OnClick="document.filterform.queue.value='DHCPSERVER'" />
				<input type="button" title="3 (ARP) События ARP" value="ARP" OnClick="document.filterform.queue.value='ARP'" />
				<input type="button" title="49 (SESMGR) События управления сессиями" value="SESMGR" OnClick="document.filterform.queue.value='SESMGR'" />
				<input type="button" title="34 (TCP_OPT) События, относящиеся к опциям заголовка TCP" value="TCP_OPT" OnClick="document.filterform.queue.value='TCP_OPT'" />
				<input type="button" title="60 (RULE) События, переключаемые правилами" value="RULE" OnClick="document.filterform.queue.value='RULE'" />
				<input type="button" title="70 (IP_PROTO) События проверки IP-протокола" value="IP_PROTO" OnClick="document.filterform.queue.value='IP_PROTO'" />
				<input type="button" title="18 (IPSEC)	События IPsec (VPN)" value="IPSEC" OnClick="document.filterform.queue.value='IPSEC'" />
				<input type="button" title="37 (USERAUTH)	События аутентификации пользователей (например, RADIUS)" value="USERAUTH" OnClick="document.filterform.queue.value='USERAUTH'" />
				<input type="button" title="35 (TIMESYNC)	События синхронизации времени межсетевого экрана" value="TIMESYNC" OnClick="document.filterform.queue.value='TIMESYNC'" />
				<input type="button" title="25 (PPP)	События PPP-туннеля" value="PPP" OnClick="document.filterform.queue.value='PPP'" />
				<input type="button" title="31 (SNMP)	Разрешенный и запрещенный доступ SNMP" value="SNMP" OnClick="document.filterform.queue.value='SNMP'" />
				<input type="button" title="41 (RFO)	События Route fail over" value="RFO" OnClick="document.filterform.queue.value='RFO'" />				
			</td>
		</tr>
		<tr>
			<td>
				Введите дату День/Месяц (от до) :
				<br/><small>по умолчанию текущая дата</small>
			</td>
			<td>
				<input type="text" name="dayfrom" value="<?=$dayfrom; ?>" size="3" />
				<input type="text" name="monthfrom" value="<?=$monthfrom; ?>" size="3" />
				-
				<input type="text" name="dayto" value="<?=$dayto;?>" size="3" />
				<input type="text" name="monthto" value="<?=$monthto; ?>" size="3" />
			</td>
		</tr>
		<tr>
			<td>
				Введите время Часы (от до) :
				<br/><small>только часы 00-24</small>
			</td>
			<td>
				<input type="text" name="timefrom" value="<?php if(!isset($_GET["timefrom"])){echo "00";}else{echo $_GET["timefrom"];} ?>" size="3" />
				-
				<input type="text" name="timeto" value="<?php if(isset($_GET["timeto"])) echo $_GET["timeto"]; ?>" size="3" />
			</td>
		</tr>
		<tr>
			<td>
				Найти в журнале данный текст :
				<br/><small>текст для поиска и выделения цветом</small>
			</td>
			<td>
				<input type="text" name="ndsearchred" value="<?=$ndsearchred; ?>" size="12" />
			</td>
		</tr>
		<tr>
			<td>
				Лимит показа найденых категорий :
			</td>
			<td>
				<input type="text" name="limit" value="<?php echo $end; ?>" size="4" />
			</td>
		</tr>
		<tr>
			<td colspan="2">
				<input type="submit" value="Показать отсортированый по категории журнал за указаное время" />
				<input type="button" value="Просмотр всего журнала за сегодня" OnClick="window.location.href='index.php'" />
				<input  type="button" value="Справка по всем категориям" onclick="open_win1()">
				<input  type="button" value="NetDefendOS_2.27.03_Log_Reference_Guide.pdf" onclick="open_win2()">
			</td>
		</tr>
	</table>
</form>

<?php
if($ndtimefrom>$ndtimeto){die("Error: Invalid time period");}

$filearray = @file($logfilename);
if(!$filearray){die("Error: Can't open file. Check permissions.");}

//Отсортируем массив в обратном порядке
krsort($filearray);
reset($filearray);
$array = array();

//Перебираем строчки с конца
foreach($filearray as $string)
{
	//Выбирать только с QUEUEID
	$regexp = "'.+: ([0-9_A-Z]*): (.+)$'";
	
	//Поиск по QUEUEID
	if(strlen($ndqueueid)>0){$regexp = "'^(.+): (".$ndqueueid."[0-9_A-Z]*): (.+)$'";}
	
	//Создание массива
	if(preg_match($regexp,$string))
	{
		$time = trim(preg_replace("'^(\w*)\s*(\d*) (\d\d:\d\d:\d\d).+$'","$1 $2 $3",$string));
		$unixtime = strtotime($time);
		//По времени
		if($unixtime<$ndtimefrom)break; //Чтобы не молотить все строчки
		if($unixtime>$ndtimeto)continue;
		
		$queueid = trim(preg_replace("'^(.+): ([0-9_A-Z]*): (.+)$'","$2",$string));
		$mess = htmlspecialchars(preg_replace("'(.+)($queueid):(.+)'","$3",$string));
		
		if(!isset($array["$queueid"]["message"])) $array["$queueid"]["message"] ="";
		$array["$queueid"]["time"]= $unixtime;
		$array["$queueid"]["message"]= $time.$mess."<br/>".$array["$queueid"]["message"];
		
		//Время лога
		if($first==true){$endperiod = $unixtime; $first=false;}
		$startperiod = $unixtime;
		
		//Лимит не должен быть превышен
		if($readlimit){if(count($array)>=$end){break;}}
	}
}

//Ничего не нашел
if(count($array)==0){die("Ничего с данными условиями не найдено в log файле, измените параметры поиска.");}

//Отсортируем массив по времени в обратном порядке
arsort($array);
reset($array);

//Статистическая инфа
echo "<b>Всего найдено категорий : ".count($array)."</b><br/>";
echo "<b>Ограничение категорий : ".$end."</b><br/>";
printf("<b>Размер log файла: %.2f Kb</b><br/>",filesize($logfilename)/1024);
echo "<b>Выбранный период времени: ".date("d.M H:i",$startperiod)." - ".date("d.M H:i",$endperiod)."</b><br/>";

//Вывод
foreach($array as $k => $sarray)
{
	$process = "Выбраная категория сообщений при поиске в логе:";
	
	//Поиск что нужно подсветить красным
	if(strlen($ndsearchred)>0)
	{
		if(!stripos($array[$k]["message"],$ndsearchred)){continue;}
		else $array[$k]["message"] = str_ireplace($ndsearchred,"<font color=\"#DB8040\">$ndsearchred</font>",$array[$k]["message"]);
	}
	
	
	//Подсветка
	$array[$k]["message"] = preg_replace("'srcip='","<font color=\"green\">srcip=</font>",$array[$k]["message"]);
	$array[$k]["message"] = preg_replace("'destip'","<font color=\"green\">destip</font>",$array[$k]["message"]);
	$array[$k]["message"] = preg_replace("'srcport='","<font color=\"green\">srcport=</font>",$array[$k]["message"]);
	$array[$k]["message"] = preg_replace("'destport='","<font color=\"green\">destport=</font>",$array[$k]["message"]);
	$array[$k]["message"] = preg_replace("'action=reject'","<font color=\"#DBBE00\">action=reject</font>",$array[$k]["message"]);
	$array[$k]["message"] = preg_replace("'user='","<font color=\"blue\">user=</font>",$array[$k]["message"]);
	$array[$k]["message"] = preg_replace("'remotegw='","<font color=\"blue\">remotegw=</font>",$array[$k]["message"]);
	$array[$k]["message"] = preg_replace("'uptime='","<font color=\"green\">uptime=</font>",$array[$k]["message"]);

	$start++;
	echo "<div class=\"queue\"><b>$process ".$k." </b><br/>\n";
	
	
	//Вывод
	echo $array[$k]["time"]."<br/>".$array[$k]["message"]."<br/>\n";

	echo "</div>";
	
	if($start>=$end){break;}
}

printf("<script>document.title='Time %.2f s'</script>",microtime(true)-$starttime);
?>
</body>
</html>


Основа для данного скрипта была взята тут kirsenn.ru/postfix-log-parser-php и переделана для работы с syslog файлом, который отдает D-Link DFL-860E. В настройках скрипта нужно указать путь к syslog файлу и ограничение для работы скрипта на максимально число категорий выводимых на экран. При запуске скрипта нужно указать путь (если он есть в настройках не обязательно) и выбрать какую категорию показать (по умолчанию выводит все категории), также возможно выбрать дату и время в журнале и текст для поиска (он будет подсвечен красным в выводимом тексте).

В директории в которой будет находится сам скрипт можно положить файлик help.txt (он дает подсказку по категориям):
1 (ПРИНЯТЬ)	Пакеты, принятые для дальнейшей передачи
2 (ALG)	События от Application Layer Gateways
3 (ARP)	События ARP
4 (BIGPOND)	События клиента BigPond
5 (BUFFERS)	События, относящиеся к использованию буфера
6 (CONN)	События State engine,например, открытие/закрытие соединений
7 (DHCP)	События DHCP-клиента
8 (DHCPRELAY)	События DHCP relayer
9 (DHCPSERVER)	События DHCP-сервера
10 (ОТБРОСИТЬ)	Запрещенные пакеты / соединения
11 (ДИНМАРШРУТИЗАЦИЯ)	Динамическая маршрутизация
12 (HA)	События High Availability
13 (IDP)	События предотвращения/обнаружения вторжения
14 (ОБНОВЛЕНИЕIDP)	Обновления БД IDP
15 (IP_ОШИБКА)	Пакеты, отброшенные из-за ошибок/ошибки в IP-заголовке
16 (IP_ФЛАГ)	События, относящиеся к флагам IP-заголовка
17 (IP_OPT)	События, относящиеся к опциям IP-заголовка
18 (IPSEC)	События IPsec (VPN)
19 (IP_ПУЛ)	События IP-пула
20 (FRAG)	События фрагментации
21 (FWD)	Пакеты, пересылаемые в неизменном виде
22 (GRE)	События GRE
23 (NETCON)	События Netcon (удаленное упр-е)
24 (OSPF)	События OSPF
25 (PPP)	События PPP-туннеля
26 (PPPOE)	События PPPoE-туннеля
27 (PPTP)	События PPTP-туннеля
28 (L2TP)	События L2TP-туннеля
29 (SLB)	События SLB
30 (SMTPLOG)	События SMTPLOG
31 (SNMP)	Разрешенный и запрещенный доступ SNMP
32 (SYSTEM)	Системные события: запуск, выключение и т.д.
33 (TCP_FLAG)	События, относящиеся к флагам заголовка TCP
34 (TCP_OPT)	События, относящиеся к опциям заголовка TCP
35 (TIMESYNC)	События синхронизации времени межсетевого экрана
36 (ИСПОЛЬЗОВАНИЕ)	Отчет об использовании системы: полоса пропускания, соединения..
37 (USERAUTH)	События аутентификации пользователей (например, RADIUS)
38 (ZONEDEFENSE)	События ZoneDefense
39 (IFACEMON)	События мониторинга интерфейса
40 (HWM)	События мониторинга аппаратного обеспечения
41 (RFO)	События Route fail over
42 (IGMP)	События IGMP
44 (TRANSPARENCY)	События, относящиеся к Transparent Mode
46 (BLACKLIST)	События Черного списка
47 (SSHD)	События SSH-сервера
48 (REASSEMBLY)	События, относящиесяк сборке данных
49 (SESMGR)	События управления сессиями
50 (AVUPDATE)	Обновление антивирусных сигнатур
51 (AVSE)	События антивирусного сканирования
52 (VFS)	События обработки файлов VFS
53 (THRESHOLD)	События правил порога
56 (NATPOOL)	События, относящиеся к пулам NAT
58 (ANTIVIRUS)	События, относящиеся к антивирусу
59 (ANTISPAM)	События, относящиеся к антиспаму
60 (RULE)	События, переключаемые правилами
70 (IP_PROTO)	События проверки IP-протокола


Также я туда же закинул файлик NetDefendOS_2.27.03_Log_Reference_Guide.pdf (полное подробное описание всех категорий), которой можно скачать с ftp D-Link ftp.dlink.ru/pub/FireWall чтобы можно было быстро подглядеть подсказку если что-то непонятно в логе.

Данный скрипт работает на web сервере lighttpd в системе freebsd 9.2.0.1 (nas4free). Для вывода журнала с DFL в файл нужно настроить syslog сервер чтобы он принимал с DFL информацию и писал ее в файл. Для freebsd настройка как это сделать тут niknav.ru/?p=266
В nas4free к сожалению я не нашел демона newsyslog, поэтому очистку раздувшегося журнала я буду делать вручную (хотя размер моего лог файла за пару недель всего около 4 Мбайт, я отключил вывод некоторых ненужным мне событий в лог в DFL).
Испытано на DFL-860E c русской прошивкой 2.27.06.10. Думаю для других устройств серии DFL скрипт тоже будет работоспособен, нужно лишь будет добавить (изменить) категории поиска тут:

input type="text" name="queue" value="<?=$ndqueueid; ?>" size="12" />
				<input type="button" title="6 (CONN) События State engine, например открытие/закрытие соединений" value="CONN" OnClick="document.filterform.queue.value='CONN'" />


В результате получится примерно такой вывод журнала (на мониторе 1920х1080 переносов строк почти нет, просмотр комфортнее, на меньших разрешениях монитора нужно уменьшать размер шрифта чтобы строки не переносились и было удобнее читать):

image

Надеюсь данный скрипт поможет владельцам DFL в просмотре и анализе логов с устройства. Удачи!
Tags:
Hubs:
+4
Comments 0
Comments Leave a comment

Articles