feat(notify): каскад telegram → zabbix → email, NOTIFY_ORDER, SMTP, v0.9.5

This commit is contained in:
ssh-monitor
2026-04-14 09:40:13 +10:00
parent 85c18be12e
commit 36dddb35d6
3 changed files with 337 additions and 177 deletions
+5 -32
View File
@@ -38,16 +38,16 @@ Bash-скрипт мониторинга **SSH**, **SUDO** и событий **`
- `LOG_FILE` — путь к основному лог-файлу скрипта.
- `LAST_HEARTBEAT_FILE` — файл с timestamp последнего heartbeat-сообщения.
- `LAST_REPORT_FILE` — дата последнего ежедневного отчёта в формате `YYYY-MM-DD` (старый формат Unix-времени при первом запуске будет автоматически интерпретирован).
- `LAST_SSH_CHECK_FILE` — файл с меткой времени последней проверки SSH-событий (unix-время, одна строка); см. раздел «Файлы-метки» ниже.
- `LAST_SUDO_CHECK_FILE`метка последней проверки sudo-событий; см. «Файлы-метки».
- `LAST_SECURITY_EVENTS_FILE` — метка последней проверки «тяжёлых» событий безопасности в журнале (логика первого запуска **отличается** от SSH/sudo/logind — см. там же).
- `LAST_LOGIND_CHECK_FILE` — метка последней обработки журнала `systemd-logind`; см. «Файлы-метки».
- `LAST_SSH_CHECK_FILE` — файл с меткой времени последней проверки SSH-событий.
- `LAST_SUDO_CHECK_FILE`файл с меткой времени последней проверки sudo-событий.
- `LAST_SECURITY_EVENTS_FILE` — метка последней проверки «тяжёлых» событий безопасности в журнале.
- `LAST_LOGIND_CHECK_FILE` — метка последней обработки журнала `systemd-logind` (unix-время); при первом запуске подтягивается около 30 минут истории.
- `BAN_LIST_FILE` — файл состояния банов (IP, время окончания бана и метаданные).
- `ENABLE_LOGIND_MONITOR``1` включает опрос `journalctl -u systemd-logind`, `0` полностью отключает этот блок.
- `LOGIND_NOTIFY_NEW``1` отправлять Telegram при появлении новой сессии в logind (строки вида *New session … of user …*).
- `LOGIND_NOTIFY_REMOVED``1` отправлять Telegram при завершении сессии (*Removed session …*); по умолчанию `0` (только запись в `LOG_FILE`, чтобы не заспамить канал).
- `LOGIND_NOTIFY_FAILED``1` отправлять Telegram по строкам logind, содержащим *failed* (широкий фильтр; при необходимости отключите).
- `LOGIND_SKIP_REMOTE``1` (по умолчанию): для новой сессии, если доступен `loginctl`, по свойствам сессии решается, не дублировать ли Telegram с `monitor_ssh`: пропуск при **`Type=ssh`** или если **`Service`** указывает на **sshd** (частый случай **`Type=tty` + `Service=sshd`**). При пустом ответе `loginctl` делается несколько коротких повторов (гонка с появлением строки в journal). Поставьте `0`, если нужны отдельные алерты logind и для SSH-сессий.
- `LOGIND_SKIP_REMOTE``1` (по умолчанию): для новой сессии, если доступен `loginctl`, запрашивается тип сессии; при `Type=ssh` **второе** уведомление в Telegram не отправляется (успешный SSH уже покрывает `monitor_ssh`), в лог пишется пояснение. Поставьте `0`, если нужны отдельные алерты logind и для SSH-сессий.
- `DAILY_REPORT_HOUR` — час (0..23), после наступления которого в **текущих календарных сутках** (в выбранной ниже зоне) отправляется не более одного ежедневного отчёта.
- `DAILY_REPORT_TZ` — необязательная **IANA**-зона (`Europe/Moscow`, `Asia/Yekaterinburg`, …). Если **пусто**, для отчёта используется та же зона, что и у команды `date` у процесса монитора (как правило, совпадает с `timedatectl` / `/etc/localtime` на сервере). Если сервис запускается с `TZ=UTC` в unit-файле, без `DAILY_REPORT_TZ` отчёт ориентируется на **UTC** — тогда задайте явную зону в конфиге.
- `DAILY_REPORT_TOP_IPS` — сколько IP показывать в топе неудачных попыток за 24 часа.
@@ -76,18 +76,6 @@ Bash-скрипт мониторинга **SSH**, **SUDO** и событий **`
Команда **`ssh-monitor --check-config`** выводит актуальные значения, в том числе параметры logind.
### Файлы-метки (`LAST_SSH_CHECK_FILE`, `LAST_SUDO_CHECK_FILE`, `LAST_LOGIND_CHECK_FILE`)
Для **SSH**, **sudo** и **logind** используется одна и та же политика:
1. **Файла ещё нет** — при первом же проходе создаётся файл с **текущим** unix-временем, в **`LOG_FILE`** пишется пояснение, **журнал за прошлое не разбирается** (нет лавины уведомлений).
2. **Файл есть, но пустой, не число, ноль или отрицательное значение** — содержимое считается ошибочным, файл **перезаписывается** текущим временем, бэклог **не** обрабатывается (та же защита, что и при первом запуске).
3. **В файле положительное unix-время** — с него строится окно `journalctl --since=@…` (или чтение лог-файлов для sudo при отсутствии journal), обрабатываются только события **после** этой метки.
Таким образом, «унифицирована» одна и та же модель: **либо валидная метка продолжения, либо безопасная инициализация без ретрансляции истории.**
Для **`LAST_SECURITY_EVENTS_FILE`** поведение другое: при отсутствии или невалидном значении окно начинается примерно с **часа назад** от текущего момента (чтобы не терять свежие тревоги и не тянуть весь журнал). Это отдельный блок (`monitor_security_events`).
## Режимы запуска
Обычный запуск (root):
@@ -108,21 +96,6 @@ sudo bash ./ssh-monitor --check-config
sudo bash ./ssh-monitor --dry-run
```
Версия (одна строка в stdout, **без** root и без чтения конфига):
```bash
bash ./ssh-monitor --version
# или краткий флаг: -V
```
### Версионирование
- В начале скрипта задаётся **`SSH_MONITOR_VERSION`** (семантическая версия). **Текущая линия — 0.9**, полный номер сейчас **`0.9.0`**; мелкие правки → **`0.9.1`**, **`0.9.2`**, …; стабильный релиз по плану — **`1.0.0`**.
- При запуске **из каталога git-репозитория** к строке версии добавляется **`+<короткий коммит>`**; при незакоммиченных изменениях — суффикс **`-dirty`**. Установленная копия в `/usr/local/bin` без `.git` рядом показывает только semver.
- Строка версии пишется в **`LOG_FILE`** после загрузки конфига, выводится в **`--check-config`**, в Telegram при **старте** сервиса и попадает в **`HEALTHCHECK_STATUS_FILE`** (поле JSON **`version`**), если файл health задан.
Перед релизом или значимым этапом обновляйте **`SSH_MONITOR_VERSION`** в `ssh-monitor` вручную (и при необходимости теги `v…` в git).
## Проверка синтаксиса
```bash