Extra Systems Ban Software (ESBANS)

Система скриптов для мониторинга

На этой странице полностью описана система мониторинга ESBANS. Вот список скриптов, которые обеспечивают ее функционирование:

-rw-r--r-- 1 root   root   1417 апр 16 16:08 esbans_win.php
-rwxr--r-- 1 root   root    336 мар 26 23:17 fail2ban_create.sh
-rwxr--r-- 1 root   root   1366 апр  9 17:25 fail2ban_dbpost.sh
-rw-r--r-- 1 root   root   2222 апр 10 20:10 fail2ban_page.php
-rw-r--r-- 1 root   root   1586 апр  9 22:31 fail2ban_stat.php
-rw-r--r-- 1 root   root    158 апр  9 22:29 linux_db_connect.php
-rw-r--r-- 1 root   root    192 апр 10 15:44 win_db_connect.php

Для работы системы мониторинга в кроне создается две задачи (вместо "???" нужно, естественно, поставить правильный путь к месту расположения ваших скриптов):

9 * * * * /???/fail2ban_dbpost.sh
55 23 * * * /???/fail2ban_create.sh

Файл fail2ban_create.sh имеет такой вид:

#!/bin/bash
current_date=$(date +%Y-%m-%d)
for module_name in $(fail2ban-client status | grep "Jail list" | cut -d: -f2 | tr -d ',')
do
        count=$(fail2ban-client status "$module_name" | grep "Currently banned" | cut -d: -f2 | tr -d '[:space:]')
        echo "$current_date $module_name $count" >> /var/log/fail2ban_daily.log
done

Этот скрипт (под конец каждых суток) записывает в /var/log/fail2ban_daily.log количество заблокированных (на тот момент) каждым модулем fail2ban хостов. Это делается просто для порядка (чисто для поддержания традиций UNIX) и с работой других систем и модулей ESBANS никак не связано.

Скрипт fail2ban_dbpost.sh вызывается кроном каждый час и имеет такой код (вместо "*******" нужно, естественно поставить свои реквизиты для доступа к базе данных):

#!/bin/bash
DB_USER=*******
DB_PASS=*******
DB_NAME=fail2ban
for fail2ban_list_item in $(fail2ban-client status | grep "Jail list" | cut -d: -f2 | tr -d '\t,')
do
	count=$(fail2ban-client status $fail2ban_list_item | grep "Currently banned" | cut -d: -f2 | tr -d '\t')
	mysql -u$DB_USER -p$DB_PASS $DB_NAME -e "INSERT IGNORE INTO ban_service (ban_service_name) VALUES ('$fail2ban_list_item');" 2>/dev/null
	mysql -u$DB_USER -p$DB_PASS $DB_NAME -e "INSERT INTO fail_ban_stat (ban_count, ban_service_id) VALUES ($count, (SELECT ban_service_id FROM ban_service WHERE ban_service_name='$fail2ban_list_item'));" 2>/dev/null
done
php /XXX/fail2ban_stat.php
php /XXX/fail2ban_page.php > /var/www/???/esbans_stat.htm

Этот скрипт сначала документирует текущее состояние всех активных модулей fail2ban в таблицу fail_ban_stat, а затем вызывает скрипты fail2ban_stat.php и fail2ban_page.php. В его коде необходимо настроить "/var/www/???/esbans_stat.htm" под свою конкретную конфигурацию (то есть, правильно указать путь, по которому он должен создавать страницу статистики), а "XXX" заменить на путь, где у вас лежат эти скрипты.

Скрипт fail2ban_stat.php имеет такой код:

<?php
	include "linux_db_connect.php";
	$mysql_datetime = date("Y-m-d");
	$max_days   = 3;
	$max_months = 2;
	$main_result = mysqli_query($conn, "select ban_service_id from ban_service");
	foreach($main_result as $main_row)
	{
		$ban_service_id = $main_row["ban_service_id"];
		$step_result = mysqli_query($conn, "select AVG(ban_count) as ban_avg from fail_ban_stat where ban_service_id=$ban_service_id and ban_date > '$mysql_datetime'");
		foreach($step_result as $step_row) $ban_avg = intval($step_row["ban_avg"]);
		$step_result = mysqli_query($conn, "select count(*) as data_count from days_data where ban_service_id=$ban_service_id and ban_date='$mysql_datetime'");
		foreach($step_result as $step_row) $data_count = $step_row["data_count"];
		if ($data_count == 0)
		{
			mysqli_query($conn, "insert into days_data(ban_service_id, ban_date, ban_count) values($ban_service_id, '$mysql_datetime', $ban_avg)");
		} else {
			mysqli_query($conn, "update days_data set ban_count=$ban_avg where ban_service_id=$ban_service_id and ban_date='$mysql_datetime'");
		}
		mysqli_query($conn, "delete from fail_ban_stat where ban_service_id=$ban_service_id and ban_date < CURDATE() - INTERVAL $max_days DAY");
		mysqli_query($conn, "delete from days_data where ban_service_id=$ban_service_id and ban_date < CURDATE() - INTERVAL $max_months MONTH");
	}
?>

Суть его деятельности понятна из текста. Таблица fail_ban_stat является, по сути дела, временной, а на постоянной основе, для визуализации статистики по дням, в системе ESBANS используется таблица days_data. Этот скрипт перекачивает информацию из первой таблицы во вторую и заодно чистит их от устаревших записей (согласно значению параметров max_days и max_months).

Как это видно из его кода, для подключения к базе данных этот скрипт использует файл linux_db_connect.php, который имеет такой вид (здесь вместо "*******" нужно, естественно, поставить свои собственные реквизиты доступа к базе данных):

<?php
	$dbUser     = "*******";
	$dbPassword = "*******";
	$dbName     = "fail2ban";
	$conn = mysqli_connect("localhost","$dbUser","$dbPassword", "$dbName");
?>

Теперь рассмотрим скрипт fail2ban_page.php, который и формирует итог всех этих усилий - страницу статистики системы esbans_stat.htm. Он имеет такой код:

<!DOCTYPE html>
<html  lang="ru-RU"  class="no-js">
<head>
<?php
	$server_name = gethostname();
	echo "<title>$server_name | Extra Systems Ban Software</title>";
?>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>td {font-size:12px;font-family:arial}</style>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<?php
	include "linux_db_connect.php";
	$server_name = gethostname();
	echo "<h3>Сводная статистика ESBANS: нейтрализация попыток взлома сервера $server_name</h3>";
	echo "<hr />";
	$mysql_datetime = date("Y-m-d");
	$show_datetime = date("d.m.Y H:i:s");
	$show_days   = 21;
	$table_height = 200;
	$item_width = 24;
	$main_result = mysqli_query($conn, "select ban_service_id, ban_service_name from ban_service");
	foreach($main_result as $main_row)
	{
		$ban_service_id   = $main_row["ban_service_id"];
		$ban_service_name = $main_row["ban_service_name"];
		echo "<h4>Статистика модуля $ban_service_name</h4>";
		$max_ban_value = 1;
		$extra_result = mysqli_query($conn, "select * from days_data where ban_service_id=$ban_service_id and ban_date > CURDATE() - INTERVAL $show_days DAY ORDER BY ban_date ASC");
		foreach($extra_result as $extra_row)
		{
			$ban_date  = $extra_row["ban_date"];
			$ban_count = $extra_row["ban_count"];
			$day = date("j", strtotime($ban_date));
			$ban_array[$day] = $ban_count;
			if ($ban_count > $max_ban_value) $max_ban_value = $ban_count;
		}
		echo "<table width=\"100%\"><tr valign=\"bottom\">";
		foreach($ban_array as $key => $value)
		{
			$show_value = (int)(($value * $table_height) / $max_ban_value);
			if ($show_value == 0) $show_value = 1;
			echo "<td align=\"center\" width=\"$item_width\">$value<br><img src=\"/line.gif\" width=\"$item_width\" height=\"$show_value\"><br>$key</td>\n";
		}
		echo "</tr></table>";
		unset($ban_array);
		echo "<hr />";
	}
	include "esbans_win.php";
	echo "<table width=\"100%\"><tr><td>По состоянию на $show_datetime</td><td align=\"right\">© Extra Systems, 2026</td></tr></table>";
?>
</body>
</html>

В коде этого скрипта есть ссылка на файл line.gif, который вы должны поместить в тот каталог того сервера, где формируется файл статистики esbans_stat.htm. Взять этот файл можно на странице esbans_stat.htm данного сайта - вы можете загрузить его в своем браузере из любого столбика присутствующих там гистограмм.

Теперь рассмотрим файл esbans_win.php (ссылка на который присутствует в этом скрипте). Он вынесен отдельно по той причине, что у вас может быть ES-RDP, а может и не быть. Если вы используете ESBANS только для fail2ban и не занимаетесь защитой удаленного рабочего стола Windows, то esbans_win.php будет просто заглушкой:

<?php
?>

Если же ES-RDP в вашей системе присутствует, то этот файл должен иметь такой код:

<?php
	include "win_db_connect.php";
	$win_server_name = gethostbyaddr("$dbHost");
	echo "<h4>Статистика модуля ES-RDP на $win_server_name</h4>";
	$ban_types = ['short' => 1, 'long' => 2, 'net' => 3, 'bot' => 4];
	$ban_names = ['short' => 'тюрьма', 'long' => 'карцер', 'net' => 'концлагерь', 'bot' => 'крематорий'];
	foreach ($ban_types as $key => $ban_type)
	{
		$ban_name = $ban_names[$key];
		echo "<h5>Состояние объекта \"$ban_name\"</h5>";
		$max_ban_value = 1;
		$ban_array = [];
		$extra_result = mysqli_query($win_conn, "select * from days_data where ban_type=$ban_type and ban_date > CURDATE() - INTERVAL $show_days DAY ORDER BY ban_date ASC");
		foreach($extra_result as $extra_row)
		{
			$ban_date  = $extra_row["ban_date"];
			$ban_count = $extra_row["ban_count"];
			$day = date("j", strtotime($ban_date));
			$ban_array[$day] = $ban_count;
			if ($ban_count > $max_ban_value) $max_ban_value = $ban_count;
		}
		echo "<table width=\"100%\"><tr valign=\"bottom\">";
		foreach($ban_array as $key => $value)
		{
			$show_value = (int)(($value * $table_height) / $max_ban_value);
			if ($show_value == 0) $show_value = 1;
			echo "<td align=\"center\" width=\"$item_width\">$value<br><img src=\"/line.gif\" width=\"$item_width\" height=\"$show_value\"><br>$key</td>\n";
		}
		echo "</tr></table>";
		unset($ban_array);
	}
	echo "<hr />";
?>

Упомянутый в коде файл win_db_connect.php имеет такой вид:

<?php
	$dbHost     = "*******";
	$dbUser     = "*******";
	$dbPassword = "*******";
	$dbName     = "rdp_ban";
	$win_conn   = mysqli_connect("$dbHost","$dbUser","$dbPassword", "$dbName");
?>

В этом файле, как обычно, вместо "*******" нужно поставить свои параметры доступа к базе данных ES-RDP.

И, напоследок, приводим структуру базы данных fail2ban, которая нужна для работы этой системы мониторинга:

CREATE DATABASE IF NOT EXISTS fail2ban;
USE fail2ban;

-- Справочник сервисов
CREATE TABLE ban_service (
  ban_service_id int NOT NULL AUTO_INCREMENT,
  ban_service_name varchar(64) UNIQUE,
  PRIMARY KEY (ban_service_id)
);

-- Таблица ежедневной статистики (для гистограмм)
CREATE TABLE days_data (
  ban_service_id int,
  ban_date date,
  ban_count int,
  KEY (ban_service_id, ban_date)
);

-- Таблица оперативной статистики (почасовая)
CREATE TABLE fail_ban_stat (
  ban_service_id int,
  ban_count int NOT NULL,
  ban_date timestamp DEFAULT CURRENT_TIMESTAMP,
  KEY (ban_service_id, ban_date)
);

© Extra Systems, 2026 Extra Web Top