Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c50bd6e9d8 | |||
| b0abf99d1b |
@@ -1,10 +1,10 @@
|
|||||||
# ssh-monitor
|
# ssh-monitor
|
||||||
|
|
||||||
**Версия:** `2.3.0-SAC`
|
**Версия:** `2.3.3-SAC`
|
||||||
|
|
||||||
Bash-мониторинг **SSH**, **sudo**, **systemd-logind**: Telegram/email, бан IP (ipset), ежедневный отчёт, heartbeat.
|
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). **Основной способ обновления на Linux** — кнопка **«Обновить ssh-monitor (SSH)»** в SAC: сервер передаёт `REPO_URL` / `GIT_BRANCH`, updater сам подтягивает git, выставляет права на конфиг/spool/state и перезапускает сервис. Cron/systemd timer — опционально.
|
**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).
|
**Безопасность (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).
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Smoke-test sac-fail.count suppress on shutdown flag. Run from repo root.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
tmpdir="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$tmpdir"' EXIT
|
||||||
|
|
||||||
|
write_log() { :; }
|
||||||
|
ssh_monitor_secure_file() { :; }
|
||||||
|
ssh_monitor_secure_dir() { mkdir -p "$1"; }
|
||||||
|
|
||||||
|
# shellcheck source=sac-client.sh
|
||||||
|
source "$ROOT/sac-client.sh"
|
||||||
|
|
||||||
|
export SAC_FAIL_COUNT_FILE="${tmpdir}/sac-fail.count"
|
||||||
|
|
||||||
|
sac_write_fail_count 0
|
||||||
|
sac_increment_fail_count
|
||||||
|
[ "$(sac_read_fail_count)" = "1" ] || {
|
||||||
|
echo "FAIL: expected count 1 after increment" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
SAC_SUPPRESS_FAIL_COUNT=1
|
||||||
|
sac_increment_fail_count || true
|
||||||
|
[ "$(sac_read_fail_count)" = "1" ] || {
|
||||||
|
echo "FAIL: count changed under SAC_SUPPRESS_FAIL_COUNT" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "OK sac-fail.count suppress"
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Smoke-test: hardening must not chmod system dirs like /var/log.
|
||||||
|
set -euo pipefail
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$ROOT/ssh-monitor-perms.sh"
|
||||||
|
|
||||||
|
fail=0
|
||||||
|
assert_true() {
|
||||||
|
if "$@"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
printf 'FAIL: expected true: %s\n' "$*" >&2
|
||||||
|
fail=1
|
||||||
|
}
|
||||||
|
assert_false() {
|
||||||
|
if "$@"; then
|
||||||
|
printf 'FAIL: expected false: %s\n' "$*" >&2
|
||||||
|
fail=1
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_true ssh_monitor_is_system_dir /var/log
|
||||||
|
assert_true ssh_monitor_is_system_dir /var/log/
|
||||||
|
assert_true ssh_monitor_is_system_dir /etc
|
||||||
|
assert_true ssh_monitor_is_system_dir /var
|
||||||
|
assert_true ssh_monitor_is_system_dir /
|
||||||
|
assert_false ssh_monitor_is_system_dir /var/lib/ssh-monitor
|
||||||
|
assert_false ssh_monitor_is_system_dir /var/lib/ssh-monitor/sac-spool
|
||||||
|
|
||||||
|
tmpdir="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$tmpdir"' EXIT
|
||||||
|
# Private dir still gets 700 (на настоящем Linux; в Git Bash/Windows mode может не примениться)
|
||||||
|
ssh_monitor_secure_dir "$tmpdir/owned"
|
||||||
|
mode="$(stat -c '%a' "$tmpdir/owned" 2>/dev/null || stat -f '%OLp' "$tmpdir/owned" 2>/dev/null || echo "")"
|
||||||
|
if [ -n "$mode" ] && [ "$mode" != "700" ] && [ "$mode" != "0700" ]; then
|
||||||
|
if [[ "$(uname -s 2>/dev/null || true)" == Linux ]]; then
|
||||||
|
printf 'FAIL: owned dir mode=%s (want 700)\n' "$mode" >&2
|
||||||
|
fail=1
|
||||||
|
else
|
||||||
|
printf 'WARN: skip mode assert on non-Linux (mode=%s)\n' "$mode" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$fail" -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
printf 'OK: system-dir hardening guards\n'
|
||||||
@@ -31,7 +31,7 @@ Watchdog и таймеры watchdog **не изменяются** при обы
|
|||||||
5. Ищет **`ssh-monitor`** в клоне (GitLab layout или плоский репозиторий).
|
5. Ищет **`ssh-monitor`** в клоне (GitLab layout или плоский репозиторий).
|
||||||
6. Сравнивает **SHA256** с **`LOCAL_SCRIPT_PATH`** (`/usr/local/bin/ssh-monitor`).
|
6. Сравнивает **SHA256** с **`LOCAL_SCRIPT_PATH`** (`/usr/local/bin/ssh-monitor`).
|
||||||
7. **Всегда** синхронизирует **`sac-client.sh`**, **`ssh-monitor-perms.sh`**, watchdog.
|
7. **Всегда** синхронизирует **`sac-client.sh`**, **`ssh-monitor-perms.sh`**, watchdog.
|
||||||
8. Дописывает ключи конфига; **`apply_runtime_security_hardening`**: `chmod 600` конфиг, `700` spool, `600` state/SAC-файлы, whitelist.
|
8. Дописывает ключи конфига; **`apply_runtime_security_hardening`**: `chmod 600` конфиг, `700` spool (`/var/lib/ssh-monitor`), `600` state/SAC-файлы (в т.ч. под `/var/log/` **без** `chmod` на сам `/var/log`), whitelist.
|
||||||
9. При изменении **`ssh-monitor`**, **`sac-client.sh`** или конфига — **`systemctl restart ssh-monitor.service`**.
|
9. При изменении **`ssh-monitor`**, **`sac-client.sh`** или конфига — **`systemctl restart ssh-monitor.service`**.
|
||||||
10. Лог: **`/var/log/update_script.log`** (блок «Итог обновления», строки `manifest` и `security hardening`).
|
10. Лог: **`/var/log/update_script.log`** (блок «Итог обновления», строки `manifest` и `security hardening`).
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# SAC ingest: таймауты и fallback
|
||||||
|
|
||||||
|
Документ для эксплуатации **ssh-monitor** с `UseSAC=fallback` или `exclusive` при нагрузке на SAC (массовый update агентов, deploy backend).
|
||||||
|
|
||||||
|
См. также: [ingest-mass-update-backlog.ru.md](https://git.kalinamall.ru/PapaTramp/security-alert-center/src/branch/main/docs/ingest-mass-update-backlog.ru.md) (SAC + ops).
|
||||||
|
|
||||||
|
## `SAC_TIMEOUT_SEC`
|
||||||
|
|
||||||
|
Таймаут **connect** и **max-time** для `curl` к SAC (`/health`, `POST /api/v1/events`).
|
||||||
|
|
||||||
|
| Сценарий | Рекомендация |
|
||||||
|
|----------|--------------|
|
||||||
|
| Обычная нагрузка | **45** (дефолт в `ssh-monitor.conf.example` и при миграции с 12) |
|
||||||
|
| Массовый restart агентов, тяжёлый ingest на SAC | **60–90** на время окна обслуживания |
|
||||||
|
| SAC на том же хосте перезапускается (`sac-deploy`) | Кратковременные отказы POST — норма; не поднимать таймаут «навсегда» без причины |
|
||||||
|
|
||||||
|
На стороне SAC (nginx) для ingest задан `proxy_read_timeout 120s` на `POST /api/v1/events`. Агентский таймаут **не обязан** равняться 120: достаточно, чтобы POST не обрывался раньше типичного ответа API. При `SAC_TIMEOUT_SEC` меньше nginx-лимита агент уйдёт в spool и `sac-fail.count`, а не «висит» минутами.
|
||||||
|
|
||||||
|
Проверка после смены:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ssh-monitor --check-config
|
||||||
|
sudo ssh-monitor --check-sac
|
||||||
|
```
|
||||||
|
|
||||||
|
## `sac-fail.count` и режим `fallback`
|
||||||
|
|
||||||
|
При ошибке POST ingest счётчик в `SAC_FAIL_COUNT_FILE` увеличивается. После **`SAC_FALLBACK_FAILURES`** подряд (по умолчанию 5) агент перестаёт слать в SAC и шлёт только в локальный Telegram, пока `/health` снова не станет OK.
|
||||||
|
|
||||||
|
**Сброс счётчика:** любой успешный POST (в т.ч. heartbeat) обнуляет `sac-fail.count`.
|
||||||
|
|
||||||
|
**Shutdown / SIGTERM (с 2.3.2-SAC):** при остановке монитора (`systemctl stop`, restart во время SAC-update) неудачный lifecycle POST **не увеличивает** счётчик — иначе после штатного restart пачки хостов агент ложно уходит в Telegram-fallback.
|
||||||
|
|
||||||
|
Lifecycle при SAC-update по-прежнему **пропускается**, если существует state-file `agent-update-in-progress` (см. `update_ssh_monitor.sh`).
|
||||||
|
|
||||||
|
## Операционные правила
|
||||||
|
|
||||||
|
1. Не совмещать `sudo /opt/sac-deploy.sh` и массовое «Обновить ssh-monitor» по многим хостам в одно окно.
|
||||||
|
2. Обновлять Linux-хосты **пачками по 2–3**.
|
||||||
|
3. На зрелых хостах — **`UseSAC=exclusive`**, если локальный Telegram при fallback не нужен.
|
||||||
@@ -25,7 +25,8 @@
|
|||||||
| **2.1.7-SAC** | Фаза 1 + выбранное из Фазы 4 | Права, `REPO_URL` обязателен, webhook, docs | ✅ реализовано |
|
| **2.1.7-SAC** | Фаза 1 + выбранное из Фазы 4 | Права, `REPO_URL` обязателен, webhook, docs | ✅ реализовано |
|
||||||
| **2.1.8-SAC** | Дополнение к 1.1 | SAC-first update: hardening прав на каждом прогоне updater | ✅ реализовано |
|
| **2.1.8-SAC** | Дополнение к 1.1 | SAC-first update: hardening прав на каждом прогоне updater | ✅ реализовано |
|
||||||
| **2.1.9-SAC** | Дополнение к 1.x | Watchdog: `🖥️ Сервер:` в Telegram (как у агента) | ✅ реализовано |
|
| **2.1.9-SAC** | Дополнение к 1.x | Watchdog: `🖥️ Сервер:` в Telegram (как у агента) | ✅ реализовано |
|
||||||
| **2.3.0-SAC** | **Фаза 3** | Парсер конфига без `source`, валидация, удаление BACKUP_WEBHOOK | ✅ реализовано |
|
| **2.3.2-SAC** | **Фаза 4.2** | Shutdown: не крутить `sac-fail.count`; docs `SAC_TIMEOUT_SEC` | ✅ реализовано |
|
||||||
|
| **2.3.1-SAC** | Hotfix | `--check-config` + whitelist IPv4 | ✅ реализовано |
|
||||||
| **2.2.3-SAC** | Дополнение к 2.2.x | Подавление sudo TG при SAC bootstrap/update | ✅ реализовано |
|
| **2.2.3-SAC** | Дополнение к 2.2.x | Подавление sudo TG при SAC bootstrap/update | ✅ реализовано |
|
||||||
| **2.2.1-SAC** | Дополнение к 2.2.0 | Подавление lifecycle/watchdog TG при SAC-update | ✅ реализовано |
|
| **2.2.1-SAC** | Дополнение к 2.2.0 | Подавление lifecycle/watchdog TG при SAC-update | ✅ реализовано |
|
||||||
| **2.2.0-SAC** | **Фаза 2** | Manifest, pinned ref, без слепого `reset --hard` | ✅ реализовано |
|
| **2.2.0-SAC** | **Фаза 2** | Manifest, pinned ref, без слепого `reset --hard` | ✅ реализовано |
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
|
|
||||||
Bump: `ssh-monitor` (`SSH_MONITOR_VERSION`) + `version.txt` в каждом релизе.
|
Bump: `ssh-monitor` (`SSH_MONITOR_VERSION`) + `version.txt` в каждом релизе.
|
||||||
|
|
||||||
**Текущий статус (2026-07-08):** фаза 3 закрыта (2.3.0-SAC). **Дальше — ingest backlog (SAC) и опционально GPG / GIT_REF=tag на проде.**
|
**Текущий статус (2026-07-08):** фаза **4.2** закрыта (2.3.2-SAC). Дальше — ops (`UseSAC=exclusive`, пачки update) и опционально GPG / `GIT_REF=tag` на проде.
|
||||||
Backlog по ingest при массовом update (SAC + ops): [ingest-mass-update-backlog.ru.md](https://git.kalinamall.ru/PapaTramp/security-alert-center/src/branch/main/docs/ingest-mass-update-backlog.ru.md) (отдельный ToDo).
|
Backlog по ingest при массовом update (SAC + ops): [ingest-mass-update-backlog.ru.md](https://git.kalinamall.ru/PapaTramp/security-alert-center/src/branch/main/docs/ingest-mass-update-backlog.ru.md) (отдельный ToDo).
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -43,6 +44,7 @@ Backlog по ingest при массовом update (SAC + ops): [ingest-mass-upd
|
|||||||
### 1.1 Права на state / spool (M4)
|
### 1.1 Права на state / spool (M4)
|
||||||
|
|
||||||
- [x] При создании каталогов и файлов состояния: `chown root:root`, каталоги `chmod 700`, файлы `chmod 600`
|
- [x] При создании каталогов и файлов состояния: `chown root:root`, каталоги `chmod 700`, файлы `chmod 600`
|
||||||
|
- [x] **2.3.3:** не делать `chmod 700` на системные каталоги (`/var/log`, `/etc`, …) при hardening файлов вроде `/var/log/last_heartbeat.txt`
|
||||||
- [x] Затронуть: `SAC_SPOOL_DIR`, `SAC_FAIL_COUNT_FILE`, heartbeat / last_* (где создаёт `ssh-monitor` / `sac-client.sh` / deploy)
|
- [x] Затронуть: `SAC_SPOOL_DIR`, `SAC_FAIL_COUNT_FILE`, heartbeat / last_* (где создаёт `ssh-monitor` / `sac-client.sh` / deploy)
|
||||||
- [x] **2.1.8:** `update_ssh_monitor.sh` → `apply_runtime_security_hardening` на **каждом** update (SAC, cron, вручную): retrofit `chmod`/`chown` существующих путей из конфига
|
- [x] **2.1.8:** `update_ssh_monitor.sh` → `apply_runtime_security_hardening` на **каждом** update (SAC, cron, вручную): retrofit `chmod`/`chown` существующих путей из конфига
|
||||||
- [x] В `--check-config`: предупреждение, если существующие пути с ослабленными правами
|
- [x] В `--check-config`: предупреждение, если существующие пути с ослабленными правами
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "2.3.2-SAC",
|
||||||
|
"git_commit": "",
|
||||||
|
"files": {
|
||||||
|
"ssh-monitor": "sha256:ca64d1b2cfda29451704e43d6d5995dbdd5cac44f7e4d85f52d8f54429083c0f",
|
||||||
|
"sac-client.sh": "sha256:e3b561280d1c146f565a1fa73e4df29f07b4ffdf149c2b30074fac98722ee9b3",
|
||||||
|
"update_ssh_monitor.sh": "sha256:76c610ed229d510c41ddd0d10db2b68d48c08b89eb1c8252341ce85f088bf6cd",
|
||||||
|
"ssh-monitor-watchdog": "sha256:c03c50162b552a7790dd0a63eecec08d672ee04955281b5ec434ed92af5e0e2f",
|
||||||
|
"ssh-monitor-perms.sh": "sha256:19531b61ebac2e2f9a19fcd9fa40b6fca4651a979dfc6ab9a347a0398ce5e012"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "2.3.3-SAC",
|
||||||
|
"git_commit": "",
|
||||||
|
"files": {
|
||||||
|
"ssh-monitor": "sha256:589ae92dc0e9656d51ca35f1eace1941ff8e292f8d5f0a4b8d2a72060610414c",
|
||||||
|
"sac-client.sh": "sha256:e3b561280d1c146f565a1fa73e4df29f07b4ffdf149c2b30074fac98722ee9b3",
|
||||||
|
"update_ssh_monitor.sh": "sha256:76c610ed229d510c41ddd0d10db2b68d48c08b89eb1c8252341ce85f088bf6cd",
|
||||||
|
"ssh-monitor-watchdog": "sha256:c03c50162b552a7790dd0a63eecec08d672ee04955281b5ec434ed92af5e0e2f",
|
||||||
|
"ssh-monitor-perms.sh": "sha256:3e411951f25fb8d708c11775925985bc45a861c28eb97932fe04012d3c9ffe5b"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -119,8 +119,20 @@ sac_reset_fail_count() {
|
|||||||
sac_write_fail_count 0
|
sac_write_fail_count 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Внутренний флаг: при shutdown/SIGTERM не крутить счётчик (restart во время SAC-deploy).
|
||||||
|
sac_fail_count_increment_suppressed() {
|
||||||
|
case "${SAC_SUPPRESS_FAIL_COUNT:-0}" in
|
||||||
|
1 | yes | true | on) return 0 ;;
|
||||||
|
esac
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
sac_increment_fail_count() {
|
sac_increment_fail_count() {
|
||||||
local n max
|
local n max
|
||||||
|
if sac_fail_count_increment_suppressed; then
|
||||||
|
write_log "SAC: пропуск sac-fail.count (shutdown/maintenance)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
max="${SAC_FALLBACK_FAILURES:-5}"
|
max="${SAC_FALLBACK_FAILURES:-5}"
|
||||||
n="$(sac_read_fail_count)"
|
n="$(sac_read_fail_count)"
|
||||||
n=$((n + 1))
|
n=$((n + 1))
|
||||||
|
|||||||
+2
-1
@@ -7,7 +7,7 @@ IFS=$'\n\t'
|
|||||||
# ============================================
|
# ============================================
|
||||||
|
|
||||||
CONFIG_FILE="/etc/ssh-monitor.conf"
|
CONFIG_FILE="/etc/ssh-monitor.conf"
|
||||||
SSH_MONITOR_VERSION="2.3.1-SAC"
|
SSH_MONITOR_VERSION="2.3.3-SAC"
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
if [ -f "$SCRIPT_DIR/ssh-monitor-perms.sh" ]; then
|
if [ -f "$SCRIPT_DIR/ssh-monitor-perms.sh" ]; then
|
||||||
@@ -2065,6 +2065,7 @@ send_shutdown_notification() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
SHUTDOWN_NOTIFIED=1
|
SHUTDOWN_NOTIFIED=1
|
||||||
|
SAC_SUPPRESS_FAIL_COUNT=1
|
||||||
|
|
||||||
local timestamp
|
local timestamp
|
||||||
timestamp=$(notification_date '+%d.%m.%Y %H:%M:%S')
|
timestamp=$(notification_date '+%d.%m.%Y %H:%M:%S')
|
||||||
|
|||||||
+28
-1
@@ -215,6 +215,7 @@ ssh_monitor_validate_config_values() {
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
for item in "${WHITELIST_IPS[@]:-}"; do
|
for item in "${WHITELIST_IPS[@]:-}"; do
|
||||||
|
item="$(_ssh_monitor_config_trim "$item")"
|
||||||
[ -z "$item" ] && continue
|
[ -z "$item" ] && continue
|
||||||
if ! ssh_monitor_validate_ipv4 "$item"; then
|
if ! ssh_monitor_validate_ipv4 "$item"; then
|
||||||
printf 'ERROR: WHITELIST_IPS: некорректный IPv4 %s\n' "$item" >&2
|
printf 'ERROR: WHITELIST_IPS: некорректный IPv4 %s\n' "$item" >&2
|
||||||
@@ -222,6 +223,7 @@ ssh_monitor_validate_config_values() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
for item in "${WHITELIST_SUBNETS[@]:-}"; do
|
for item in "${WHITELIST_SUBNETS[@]:-}"; do
|
||||||
|
item="$(_ssh_monitor_config_trim "$item")"
|
||||||
[ -z "$item" ] && continue
|
[ -z "$item" ] && continue
|
||||||
if ! ssh_monitor_validate_cidr_v4 "$item"; then
|
if ! ssh_monitor_validate_cidr_v4 "$item"; then
|
||||||
printf 'ERROR: WHITELIST_SUBNETS: некорректный CIDR %s\n' "$item" >&2
|
printf 'ERROR: WHITELIST_SUBNETS: некорректный CIDR %s\n' "$item" >&2
|
||||||
@@ -258,10 +260,33 @@ ssh_monitor_is_root_owned() {
|
|||||||
[ "$own" = "root:root" ]
|
[ "$own" = "root:root" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Каталоги ОС: не chmod 700 / chown при hardening файлов вроде /var/log/last_heartbeat.txt.
|
||||||
|
# Иначе update ломает /var/log (syslog, logrotate, чужие сервисы).
|
||||||
|
ssh_monitor_is_system_dir() {
|
||||||
|
local dir="$1"
|
||||||
|
[ -n "$dir" ] || return 1
|
||||||
|
while [ "$dir" != "/" ] && [[ "$dir" == */ ]]; do
|
||||||
|
dir="${dir%/}"
|
||||||
|
done
|
||||||
|
case "$dir" in
|
||||||
|
/ | /bin | /boot | /dev | /etc | /home | /lib | /lib32 | /lib64 | /libx32 | \
|
||||||
|
/media | /mnt | /opt | /proc | /root | /run | /sbin | /srv | /sys | /tmp | \
|
||||||
|
/usr | /usr/bin | /usr/sbin | /usr/local | /usr/local/bin | /usr/local/sbin | \
|
||||||
|
/var | /var/log | /var/tmp | /var/cache | /var/run | /var/spool)
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
ssh_monitor_secure_dir() {
|
ssh_monitor_secure_dir() {
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
[ -n "$dir" ] || return 1
|
[ -n "$dir" ] || return 1
|
||||||
mkdir -p "$dir" 2>/dev/null || return 1
|
mkdir -p "$dir" 2>/dev/null || return 1
|
||||||
|
# Только «свои» каталоги (spool, /var/lib/ssh-monitor, …). /var/log и т.п. не трогаем.
|
||||||
|
if ssh_monitor_is_system_dir "$dir"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
chmod 700 "$dir" 2>/dev/null || true
|
chmod 700 "$dir" 2>/dev/null || true
|
||||||
chown root:root "$dir" 2>/dev/null || true
|
chown root:root "$dir" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
@@ -271,6 +296,7 @@ ssh_monitor_secure_file() {
|
|||||||
local dir
|
local dir
|
||||||
[ -n "$file" ] || return 1
|
[ -n "$file" ] || return 1
|
||||||
dir="$(dirname "$file")"
|
dir="$(dirname "$file")"
|
||||||
|
# mkdir родителя; chmod 700 — только если родитель не системный (/var/log, /etc, …).
|
||||||
ssh_monitor_secure_dir "$dir" || true
|
ssh_monitor_secure_dir "$dir" || true
|
||||||
if [ ! -f "$file" ]; then
|
if [ ! -f "$file" ]; then
|
||||||
: >"$file" 2>/dev/null || touch "$file" 2>/dev/null || return 1
|
: >"$file" 2>/dev/null || touch "$file" 2>/dev/null || return 1
|
||||||
@@ -279,7 +305,8 @@ ssh_monitor_secure_file() {
|
|||||||
chown root:root "$file" 2>/dev/null || true
|
chown root:root "$file" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Существующий файл или каталог: 600/700 root:root; для отсутствующего пути — только родительский каталог.
|
# Существующий файл или каталог: 600/700 root:root; для отсутствующего пути — только родительский каталог
|
||||||
|
# (без chmod 700 на системных родителях вроде /var/log).
|
||||||
ssh_monitor_harden_path() {
|
ssh_monitor_harden_path() {
|
||||||
local path="$1"
|
local path="$1"
|
||||||
[ -n "$path" ] || return 0
|
[ -n "$path" ] || return 0
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ SAC_API_KEY="sac_UkOsAT3UWiQS54KK5OJPBDCSucysQDrKFju28wmYiz8"
|
|||||||
SAC_SPOOL_DIR="/var/lib/ssh-monitor/sac-spool"
|
SAC_SPOOL_DIR="/var/lib/ssh-monitor/sac-spool"
|
||||||
SAC_FAIL_COUNT_FILE="/var/lib/ssh-monitor/sac-fail.count"
|
SAC_FAIL_COUNT_FILE="/var/lib/ssh-monitor/sac-fail.count"
|
||||||
SAC_FALLBACK_FAILURES="5"
|
SAC_FALLBACK_FAILURES="5"
|
||||||
|
# Таймаут curl к SAC (health + ingest). При burst ingest на сервере — 60–90; см. docs/sac-ingest.ru.md
|
||||||
SAC_TIMEOUT_SEC="45"
|
SAC_TIMEOUT_SEC="45"
|
||||||
SAC_SPOOL_FLUSH_MAX_FILES="50"
|
SAC_SPOOL_FLUSH_MAX_FILES="50"
|
||||||
SAC_SPOOL_MAX_AGE_HOURS="72"
|
SAC_SPOOL_MAX_AGE_HOURS="72"
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
2.3.1-SAC
|
2.3.3-SAC
|
||||||
|
|||||||
Reference in New Issue
Block a user