На этой странице полностью описана система мониторинга 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 |
|