c50bd6e9d8
Hardening state files under /var/log was applying chmod 700 to the parent directory, which broke syslog/logrotate and other services after agent update.
244 lines
26 KiB
Markdown
244 lines
26 KiB
Markdown
# ssh-monitor
|
||
|
||
**Версия:** `2.3.3-SAC`
|
||
|
||
Bash-мониторинг **SSH**, **sudo**, **systemd-logind**: Telegram/email, бан IP (ipset), ежедневный отчёт, heartbeat.
|
||
|
||
**Security Alert Center:** модуль **`sac-client.sh`**, режим `UseSAC` (`off` | `exclusive` | `dual` | `fallback`) — [контракт SAC](https://git.kalinamall.ru/PapaTramp/security-alert-center/src/branch/main/docs/agent-integration.md). Ingest / таймауты / fallback: [docs/sac-ingest.ru.md](docs/sac-ingest.ru.md). **Основной способ обновления на Linux** — кнопка **«Обновить ssh-monitor (SSH)»** в SAC: сервер передаёт `REPO_URL` / `GIT_BRANCH`, updater сам подтягивает git, выставляет права на конфиг/spool/state и перезапускает сервис. Cron/systemd timer — опционально.
|
||
|
||
**Безопасность (2.1.7+):** агент работает от root; доверяйте только своему git-зеркалу (`REPO_URL`) и `/etc/ssh-monitor.conf` (`chmod 600`). С **2.3.0** конфиг читается **без `source`** (whitelist ключей, без выполнения bash из файла). Updater дописывает обязательные ключи и **на каждом прогоне** применяет `chmod`/`chown` к конфигу, SAC-spool и state-файлам. Подробнее: [docs/security-roadmap.ru.md](docs/security-roadmap.ru.md).
|
||
|
||
## Состав репозитория
|
||
|
||
| Файл | Назначение |
|
||
|------|------------|
|
||
| **`ssh-monitor`** | Основной цикл: разбор журналов (**journalctl**: sshd, sudo, «тяжёлые» события, **systemd-logind**), цепочка уведомлений (Telegram, SMTP через **python3**), при **`ENABLE_IP_BAN=1`** — учёт неудачных попыток, бан в **ipset** и согласование с **iptables**/**ip6tables**, ежедневный отчёт, heartbeat, опционально **Prometheus** textfile и JSON health. Режимы: **`--check-config`**, **`--dry-run`**. |
|
||
| **`ssh-monitor-watchdog`** | Отдельный скрипт (обычно по **systemd timer**): проверяет, что сервис монитора активен и файл heartbeat не старше порога; при сбое выполняет **`systemctl restart`** и шлёт уведомление в Telegram. Читает `TELEGRAM_*` и watchdog-параметры из `/etc/ssh-monitor.conf`. |
|
||
| `update_ssh_monitor.sh` | Автообновление: git + manifest verify, `sac-client.sh`, перезапуск `ssh-monitor.service`. См. [docs/auto-update.ru.md](docs/auto-update.ru.md). |
|
||
|
||
**Системные пакеты и зависимости** (что поставить на сервер до запуска): пошагово в [docs/install-prerequisites.ru.md](docs/install-prerequisites.ru.md).
|
||
|
||
## Конфигурация
|
||
|
||
> **Закрытый инстанс Gitea:** в доверенном закрытом репозитории допустимо хранить **`ssh-monitor.conf`** с боевыми токенами (файл не в `.gitignore`). В публичном [GitHub](https://git.kalinamall.ru/PapaTramp/ssh-monitor) такой файл игнорируется — используйте только `ssh-monitor.conf.example`.
|
||
|
||
Скрипт читает параметры из `/etc/ssh-monitor.conf` в формате `KEY="value"` (парсер с whitelist ключей; произвольный bash в файле не выполняется).
|
||
|
||
1. Скопируйте пример:
|
||
- `sudo cp ./ssh-monitor.conf.example /etc/ssh-monitor.conf`
|
||
2. Ограничьте доступ:
|
||
- `sudo chmod 600 /etc/ssh-monitor.conf`
|
||
3. Заполните минимум — **хотя бы один канал доставки оповещений** (иначе скрипт сразу завершится с ошибкой; см. абзац **«Обязательное условие»** ниже и раздел **«Каналы оповещений и пустой NOTIFY_CHAIN»**):
|
||
- для **Telegram**: `TELEGRAM_BOT_TOKEN` и `TELEGRAM_CHAT_ID`;
|
||
- или настройте **почту (SMTP)** по переменным ниже при `NOTIFY_ORDER=""` (автовыбор каналов).
|
||
|
||
**Обязательное условие:** после загрузки конфигурации в цепочке **`NOTIFY_CHAIN`** должен быть **минимум один** канал (`telegram` или `email`). Если каналов **нет** (пустой `NOTIFY_ORDER` и ни Telegram, ни SMTP не удовлетворяют критериям «настроен», либо в `NOTIFY_ORDER` остались только неизвестные имена), скрипт **не входит** в основной цикл и завершается с кодом **1**, в stderr: **`Не настроен ни один канал отправки оповещений`**. Это же правило действует для **`--check-config`** и **`--dry-run`**.
|
||
|
||
Поддерживаемые параметры:
|
||
|
||
- `TELEGRAM_BOT_TOKEN`, `TELEGRAM_CHAT_ID`
|
||
- `NOTIFY_ORDER` — список каналов (`telegram`, `email` и сокращения **tg**, **mail**); при каждом оповещении скрипт **пытается отправить во все перечисленные** каналы по порядку (не «первый успешный — и стоп»). Пусто = в цепочку попадают только настроенные каналы (порядок по умолчанию см. в `ssh-monitor.conf.example`). Если итоговая цепочка пуста — скрипт не стартует (см. раздел **«Каналы оповещений и пустой NOTIFY_CHAIN»**).
|
||
- `MAIL_SMTP_HOST`, `MAIL_SMTP_PORT`, `MAIL_SMTP_USER`, `MAIL_SMTP_PASSWORD`, `MAIL_FROM`, `MAIL_TO`, `MAIL_SMTP_STARTTLS`, `MAIL_SMTP_SSL` — отправка почты через **python3** (см. таблицу каналов ниже)
|
||
- `LOG_FILE`, `LAST_HEARTBEAT_FILE`, `LAST_REPORT_FILE`, `LAST_SSH_CHECK_FILE`, `LAST_SUDO_CHECK_FILE`, `LAST_SECURITY_EVENTS_FILE`, `LAST_LOGIND_CHECK_FILE`, `BAN_LIST_FILE`
|
||
- `ENABLE_LOGIND_MONITOR`, `LOGIND_NOTIFY_NEW`, `LOGIND_NOTIFY_REMOVED`, `LOGIND_NOTIFY_FAILED`, `LOGIND_SKIP_REMOTE` — см. раздел «Мониторинг systemd-logind» ниже
|
||
- `DAILY_REPORT_HOUR` (0..23), `DAILY_REPORT_ENABLED` (1/0 — отчёт с агента; 0 = только SAC), `DAILY_REPORT_TZ` (опционально), `NOTIFY_TZ` (опционально), `SERVER_DISPLAY_NAME` (опционально), `SSH_ACCEPT_NOTIFY_DEDUP_SEC`, `DAILY_REPORT_TOP_IPS`
|
||
- `BRUTE_WINDOW_SEC`, `BRUTE_MIN_FAILS`, `BRUTE_NOTIFY_COOLDOWN_SEC`
|
||
- `PROMETHEUS_TEXTFILE_DIR` — каталог для `ssh_monitor.prom` (совместимость с node_exporter textfile collector)
|
||
- `HEALTHCHECK_STATUS_FILE` — путь к JSON-файлу с меткой последней итерации цикла
|
||
- `ENABLE_IP_BAN` — `1` (по умолчанию): мониторинг и автобан через ipset; `0`: только мониторинг и уведомления (без ipset/бана)
|
||
- `BAN_TIME`, `MAX_ATTEMPTS`, `BAN_CHECK_INTERVAL`, `MONITOR_INTERVAL`
|
||
- `WHITELIST_IPS`, `WHITELIST_SUBNETS` (CSV, например `ip1,ip2`)
|
||
- `WATCHDOG_MAX_HEARTBEAT_AGE`, `WATCHDOG_LOG_FILE`, `WATCHDOG_SERVICE_NAME`, `WATCHDOG_NOTIFY_ON_RECOVERY`
|
||
|
||
Если файл `/etc/ssh-monitor.conf` отсутствует или часть значений пустая, используются значения по умолчанию из скрипта.
|
||
|
||
### Описание переменных в `/etc/ssh-monitor.conf`
|
||
|
||
- `TELEGRAM_BOT_TOKEN` — токен Telegram-бота для отправки уведомлений.
|
||
- `TELEGRAM_CHAT_ID` — ID чата/пользователя, куда отправляются уведомления.
|
||
- `NOTIFY_ORDER` — CSV имён каналов (`telegram`, `email` или `tg`, `mail`). Для **каждого** оповещения выполняется попытка доставки **во все** перечисленные каналы (при ошибке одного остальные всё равно пробуются; неудачи пишутся в **`LOG_FILE`**). Пустая строка: автоматически собирается цепочка только из реально настроенных каналов (по умолчанию порядок telegram → email; критерии «настроен» — **таблица** в разделе **«Каналы оповещений и пустой NOTIFY_CHAIN»**). Если после сборки цепочки **нет ни одного** канала, скрипт **сразу завершается** с ошибкой: **«Не настроен ни один канал отправки оповещений»** (в том числе режим `--check-config` и `--dry-run`).
|
||
- `MAIL_SMTP_HOST`, `MAIL_SMTP_PORT`, `MAIL_SMTP_USER`, `MAIL_SMTP_PASSWORD`, `MAIL_FROM`, `MAIL_TO`, `MAIL_SMTP_STARTTLS`, `MAIL_SMTP_SSL` — параметры SMTP для канала `email` (отправка через **python3**; см. таблицу «настроен»).
|
||
- `LOG_FILE` — путь к основному лог-файлу скрипта.
|
||
- `LAST_HEARTBEAT_FILE` — файл с timestamp последнего heartbeat-сообщения.
|
||
- `LAST_REPORT_FILE` — дата последнего ежедневного отчёта в формате `YYYY-MM-DD` (старый формат Unix-времени при первом запуске будет автоматически интерпретирован).
|
||
- `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` (по умолчанию): для новой сессии logind, если доступен `loginctl`, не отправляется второе Telegram, если сессия уже учтена в **`monitor_ssh`**: при **`Type=ssh`** или если **`Service`** указывает на **sshd** (часто **`Type=tty` + `Service=sshd`**); при пустом ответе `loginctl` делаются короткие повторы. Поставьте `0`, если нужны отдельные алерты logind и для SSH-сессий.
|
||
- `DAILY_REPORT_HOUR` — час (0..23), после наступления которого в **текущих календарных сутках** (в выбранной ниже зоне) отправляется не более одного ежедневного отчёта.
|
||
- `DAILY_REPORT_ENABLED` — `1` (по умолчанию) отправлять `report.daily.ssh` с агента; **`0`** — не слать (суточный отчёт формирует только SAC, см. `SAC_DAILY_REPORT_*`).
|
||
- `DAILY_REPORT_TZ` — необязательная **IANA**-зона (`Europe/Moscow`, `Asia/Yekaterinburg`, …). Если **пусто**, для отчёта используется та же зона, что и у команды `date` у процесса монитора (как правило, совпадает с `timedatectl` / `/etc/localtime` на сервере). Если сервис запускается с `TZ=UTC` в unit-файле, без `DAILY_REPORT_TZ` отчёт ориентируется на **UTC** — тогда задайте явную зону в конфиге.
|
||
- `NOTIFY_TZ` — **IANA**-зона для строк **«🕐 Время»** в Telegram/email (и аналогичных текстах). **Пусто** — используется **`DAILY_REPORT_TZ`**, если она задана, иначе зона процесса. Частая причина «время в теле сообщения UTC, а в заголовке чата локальное»: в **`ssh-monitor.service`** задано **`Environment=TZ=UTC`** — тогда задайте **`NOTIFY_TZ`** (или **`DAILY_REPORT_TZ`**) на вашу локаль, например `Asia/Vladivostok`.
|
||
- `SERVER_DISPLAY_NAME` — подпись в строке **«🖥️ Сервер»** во всех уведомлениях. **Пусто** — `hostname` и при возможности основной IPv4 (`hostname (10.x.x.x)`). Задайте явное имя, если несколько хостов с одинаковым hostname шлют в один чат. Подробнее: [docs/notifications.ru.md](docs/notifications.ru.md).
|
||
- `SERVER_IPV4` — опциональный override для SAC `host.ipv4`. Если пусто, IPv4 определяется автоматически.
|
||
- `SSH_ACCEPT_NOTIFY_DEDUP_SEC` — не чаще одного Telegram по **успешному SSH (`Accepted`)** на одну пару **пользователь + IP** за указанное число **секунд** (по умолчанию **5**). Снимает дубли, когда в journal две строки с **разными портами клиента** за один вход. **`0`** — отключить этот антидубль (останется только дедупликация внутри одного прохода `monitor_ssh` по `user|ip|port`).
|
||
- `DAILY_REPORT_TOP_IPS` — сколько IP показывать в топе неудачных попыток за 24 часа.
|
||
- `BRUTE_WINDOW_SEC` — окно (секунды) для оценки «массового» брутфорса по `journalctl`.
|
||
- `BRUTE_MIN_FAILS` — минимум неудачных попыток за окно для тревоги.
|
||
- `BRUTE_NOTIFY_COOLDOWN_SEC` — пауза между повторными уведомлениями по одному и тому же IP.
|
||
- `PROMETHEUS_TEXTFILE_DIR` — если задан существующий каталог, на каждой итерации пишется `ssh_monitor.prom` с метрикой `ssh_monitor_last_loop_unixtime`.
|
||
- `HEALTHCHECK_STATUS_FILE` — если задан, на каждой итерации обновляется JSON `{ "ts", "hostname", "dry_run" }`.
|
||
- `ENABLE_IP_BAN` — включить автобан IP (`1`) или работать только как монитор с уведомлениями (`0`; **ipset** не требуется).
|
||
- `BAN_TIME` — длительность бана IP в секундах (используется при `ENABLE_IP_BAN=1`).
|
||
- `MAX_ATTEMPTS` — число неудачных SSH-попыток до автоматического бана.
|
||
- `BAN_CHECK_INTERVAL` — интервал проверки просроченных банов и аудита согласованности бан-листа с firewall (секунды).
|
||
- `MONITOR_INTERVAL` — пауза между итерациями основного цикла мониторинга (секунды).
|
||
- `WHITELIST_IPS` — белый список IP через запятую (IPv4 и IPv6 — точное совпадение).
|
||
- `WHITELIST_SUBNETS` — белый список подсетей **только IPv4** CIDR через запятую (например `10.0.0.0/24`).
|
||
- `WATCHDOG_MAX_HEARTBEAT_AGE` — через сколько секунд heartbeat считается устаревшим.
|
||
- `WATCHDOG_LOG_FILE` — лог-файл watchdog-скрипта.
|
||
- `WATCHDOG_SERVICE_NAME` — имя systemd-сервиса, который контролирует watchdog (по умолчанию `ssh-monitor.service`).
|
||
- `WATCHDOG_NOTIFY_ON_RECOVERY` — `1` включает служебные сообщения watchdog при штатном состоянии, `0` отключает.
|
||
|
||
### Каналы оповещений и пустой NOTIFY_CHAIN
|
||
|
||
Кратко, что считается **настроенным** каналом (только такие попадают в автоматическую цепочку при **`NOTIFY_ORDER=""`**):
|
||
|
||
| Канал | Условие «настроен» |
|
||
|--------|-------------------|
|
||
| `telegram` | заданы **`TELEGRAM_BOT_TOKEN`** и **`TELEGRAM_CHAT_ID`** |
|
||
| `email` | непустые **`MAIL_SMTP_HOST`**, **`MAIL_FROM`**, **`MAIL_TO`**, в PATH есть **`python3`** |
|
||
|
||
Если итоговый **`NOTIFY_CHAIN` пуст**, скрипт завершается с сообщением **`Не настроен ни один канал отправки оповещений`** (см. шаг 3 в разделе «Конфигурация» выше).
|
||
|
||
### Мониторинг systemd-logind
|
||
|
||
- Собираются сообщения юнита **`systemd-logind`** через **`journalctl`** (`-o cat`): новые и завершённые сессии, а также строки с подстрокой *failed* (если включено).
|
||
- Без **`journalctl`** на хосте этот блок **не работает** (как и часть других функций, завязанных на journal).
|
||
- Для разбора «новой сессии» используются типичные англоязычные форматы (`New session … of user …`). При несовпадении формата строка всё равно попадёт в лог с пометкой о неудачном разборе.
|
||
- **`loginctl`** нужен для **`LOGIND_SKIP_REMOTE`**: по `Type` и **`Service`** решается, не дублировать ли Telegram с **`monitor_ssh`** (см. описание `LOGIND_SKIP_REMOTE` выше).
|
||
- **`monitor_ssh`**: события **sshd** читаются из journal преимущественно как **`journalctl _COMM=sshd`** (запасные варианты — юниты `sshd` / `ssh`), строки **`sort -u`**, для **`Accepted`** в одном проходе — дедуп по **пользователь|IP|порт**; между проходами цикла — пауза **`SSH_ACCEPT_NOTIFY_DEDUP_SEC`** для той же пары **пользователь|IP** (см. переменную в конфиге).
|
||
|
||
Команда **`ssh-monitor --check-config`** выводит актуальные значения, в том числе параметры logind.
|
||
|
||
Ограничения на хостах **без journald** и нюансы **`/var/log/auth.log`**: см. раздел 4 в [docs/install-prerequisites.ru.md](docs/install-prerequisites.ru.md).
|
||
|
||
### Идентификация сервера в уведомлениях
|
||
|
||
Во **всех** оповещениях (SSH, sudo, бан IP, logind, heartbeat, ежедневный отчёт и т.д.) после заголовка автоматически добавляется строка **«🖥️ Сервер: …»** — формат `hostname (IPv4)` или только `hostname`, если IPv4 определить не удалось. Логика в `notify_send()`; дублирование в тексте сообщения не требуется.
|
||
|
||
- Утилиты **`hostname`** и **`ip`** (см. [docs/install-prerequisites.ru.md](docs/install-prerequisites.ru.md)).
|
||
- Опционально **`SERVER_DISPLAY_NAME`** в конфиге — фиксированная подпись вместо hostname (удобно при нескольких серверах в одном Telegram-чате).
|
||
- Типы сообщений и примеры: [docs/notifications.ru.md](docs/notifications.ru.md).
|
||
|
||
### Обновление агента
|
||
|
||
**Рекомендуемый путь — SAC:** в карточке Linux-хоста кнопка **«Обновить ssh-monitor (SSH)»**. Участие админа на сервере не требуется: SAC передаёт `REPO_URL`/`GIT_BRANCH`, updater выполняет `git pull`, синхронизирует `sac-client.sh`, дописывает ключи конфига, **выставляет права** на конфиг/spool/state и перезапускает `ssh-monitor.service`.
|
||
|
||
Скрипт **`update_ssh_monitor.sh`** также можно запускать вручную или по расписанию (cron/systemd timer) с тем же `REPO_URL` — поведение идентично.
|
||
|
||
Пошаговая настройка: [docs/auto-update.ru.md](docs/auto-update.ru.md).
|
||
|
||
## Режимы запуска
|
||
|
||
Обычный запуск (root):
|
||
|
||
```bash
|
||
sudo bash ./ssh-monitor
|
||
```
|
||
|
||
Проверка конфигурации и синтаксиса **без** запуска цикла, **без** изменений `iptables` и без обязательного Telegram:
|
||
|
||
```bash
|
||
sudo bash ./ssh-monitor --check-config
|
||
```
|
||
|
||
Режим **dry-run** (правила firewall не меняются; уведомления выводятся в stderr вместо отправки):
|
||
|
||
```bash
|
||
sudo bash ./ssh-monitor --dry-run
|
||
```
|
||
|
||
## Проверка синтаксиса
|
||
|
||
```bash
|
||
bash -n ./ssh-monitor
|
||
```
|
||
|
||
## Релизный архив
|
||
|
||
Версия задаётся в **`SSH_MONITOR_VERSION`** в файле **`ssh-monitor`** и дублируется в **`version.txt`** (та же строка, что в шапке README). Модуль **`sac-client.sh`** использует ту же версию для SAC `product_version`. **Release manifest** (`release/manifest-*.json`): [docs/release-manifest.ru.md](docs/release-manifest.ru.md) — после clone: `.\contrib\install-git-hooks.ps1` (Windows) или `./contrib/install-git-hooks.sh` (Linux/Git Bash).
|
||
|
||
Сборка tarball из текущего git-дерева:
|
||
|
||
```bash
|
||
make dist
|
||
```
|
||
|
||
Появится файл `ssh-monitor-<версия>.tar.gz` (через `git archive`). Готовые архивы для установки без клона репозитория прикладываются к [релизам на GitHub](https://git.kalinamall.ru/PapaTramp/ssh-monitor/releases).
|
||
|
||
## Установка скрипта, конфигурации и systemd
|
||
|
||
### Автоматическая установка (рекомендуется)
|
||
|
||
```bash
|
||
sudo ./first_deploy.sh
|
||
# или: sudo ./update_ssh_monitor.sh --deploy
|
||
```
|
||
|
||
См. [docs/auto-update.ru.md](docs/auto-update.ru.md) — клон из git, копирование в `/usr/local/bin/`, `sac-client.sh`, пример `/etc/ssh-monitor.conf`, unit systemd.
|
||
|
||
### Ручная установка
|
||
|
||
1. Скопируйте скрипт в постоянное место:
|
||
- `sudo install -m 750 ./ssh-monitor /usr/local/bin/ssh-monitor`
|
||
- `sudo install -m 644 ./sac-client.sh /usr/local/bin/sac-client.sh`
|
||
2. Убедитесь, что конфиг создан (см. раздел **«Конфигурация»** выше):
|
||
- `sudo cp ./ssh-monitor.conf.example /etc/ssh-monitor.conf`
|
||
- `sudo chmod 600 /etc/ssh-monitor.conf`
|
||
3. Создайте unit-файл `/etc/systemd/system/ssh-monitor.service` (или `sudo cp ssh-monitor.service.example ...`):
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=SSH Monitor with Telegram alerts
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
ExecStart=/usr/local/bin/ssh-monitor
|
||
Restart=always
|
||
RestartSec=5
|
||
User=root
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
4. Включите и запустите сервис:
|
||
|
||
```bash
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable ssh-monitor
|
||
sudo systemctl start ssh-monitor
|
||
```
|
||
|
||
5. Проверка состояния и логов:
|
||
|
||
```bash
|
||
sudo systemctl status ssh-monitor
|
||
sudo journalctl -u ssh-monitor -f
|
||
```
|
||
|
||
## Ротация логов
|
||
|
||
Пример для `logrotate` лежит в репозитории: `contrib/logrotate.d/ssh-monitor`. Скопируйте файл в `/etc/logrotate.d/` и при необходимости поправьте пути под ваши `LOG_FILE` / `WATCHDOG_LOG_FILE` и другие файлы состояния в `/var/log/` (в т.ч. `LAST_*`, если решите их ротировать отдельно).
|
||
|
||
## Watchdog (автоматическое восстановление)
|
||
|
||
Watchdog проверяет активность `ssh-monitor.service` и актуальность heartbeat (`LAST_HEARTBEAT_FILE`). При сбое выполняет `systemctl restart` и отправляет уведомление в Telegram.
|
||
|
||
Пошаговая установка скрипта **ssh-monitor-watchdog** и **timer** в **systemd**: раздел 6 в [docs/install-prerequisites.ru.md](docs/install-prerequisites.ru.md).
|
||
|
||
**Ключевые темы (для поиска):** мониторинг **SSH** и **sshd**, **bash**-скрипт для **Linux**-сервера, уведомления в **Telegram** и по **SMTP** / электронной почте, **systemd-logind**, **sudo**, **journalctl**, **iptables** / **ip6tables**, автоматический **бан IP** и **whitelist**, **systemd** unit, **ежедневный отчёт**, **heartbeat**, **OpenSSH**, безопасность сервера, **Prometheus** textfile, опционально **watchdog** для сервиса.
|
||
|
||
## Лицензия
|
||
|
||
Проект распространяется по лицензии **MIT** — см. файл [LICENSE](LICENSE).
|