feat: include host.ipv4 in SAC payload and release 1.2.7-SAC
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -71,6 +71,7 @@ Bash-скрипт мониторинга **SSH**, **SUDO** и событий **`
|
||||
- `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`.
|
||||
@@ -155,7 +156,7 @@ bash -n ./ssh-monitor
|
||||
|
||||
## Релизный архив
|
||||
|
||||
Версия задаётся в **`SSH_MONITOR_VERSION`** в файле **`ssh-monitor`** и дублируется в **`version.txt`** (сейчас **1.2.6-SAC**). Модуль **`sac-client.sh`** использует ту же версию для SAC `product_version`. Сборка tarball из текущего git-дерева:
|
||||
Версия задаётся в **`SSH_MONITOR_VERSION`** в файле **`ssh-monitor`** и дублируется в **`version.txt`** (сейчас **1.2.7-SAC**). Модуль **`sac-client.sh`** использует ту же версию для SAC `product_version`. Сборка tarball из текущего git-дерева:
|
||||
|
||||
```bash
|
||||
make dist
|
||||
|
||||
+2
-1
@@ -69,6 +69,7 @@ If `/etc/ssh-monitor.conf` is missing or some values are empty, script defaults
|
||||
- `DAILY_REPORT_TZ` — optional **IANA** zone (`Europe/Moscow`, …). If **empty**, report uses the monitor process zone (usually matches `timedatectl` / `/etc/localtime`). If the unit sets `TZ=UTC`, without `DAILY_REPORT_TZ` the report uses **UTC** — set an explicit zone in config.
|
||||
- `NOTIFY_TZ` — **IANA** zone for **«🕐 Время»** lines in Telegram/email. **Empty** — use **`DAILY_REPORT_TZ`** if set, else process zone. Common mismatch: **`ssh-monitor.service`** has **`Environment=TZ=UTC`** — set **`NOTIFY_TZ`** or **`DAILY_REPORT_TZ`** to your locale, e.g. `Asia/Vladivostok`.
|
||||
- `SERVER_DISPLAY_NAME` — label in **«🖥️ Server»** line on every alert. **Empty** — `hostname` plus primary IPv4 when available. Set a fixed name when many hosts share one Telegram chat. Details: [docs/notifications.ru.md](docs/notifications.ru.md) (Russian).
|
||||
- `SERVER_IPV4` — optional override for SAC `host.ipv4`. If empty, the script auto-detects host IPv4.
|
||||
- `SSH_ACCEPT_NOTIFY_DEDUP_SEC` — at most one Telegram per successful SSH (**Accepted**) per **user + IP** pair within **N** seconds (default **5**). Removes duplicates when journal has two lines with **different client ports** for one login. **`0`** disables this cross-iteration dedup (in-pass dedup by `user|ip|port` remains).
|
||||
- `DAILY_REPORT_TOP_IPS` — how many IPs in the failed-attempts top for 24 hours.
|
||||
- `BRUTE_WINDOW_SEC` — window (seconds) for “mass” brute-force evaluation via `journalctl`.
|
||||
@@ -153,7 +154,7 @@ bash -n ./ssh-monitor
|
||||
|
||||
## Release tarball
|
||||
|
||||
Version is set as **`SSH_MONITOR_VERSION`** in **`ssh-monitor`** and **`version.txt`** (currently **1.2.6-SAC**). **`sac-client.sh`** reports the same version to SAC. Build from the git tree:
|
||||
Version is set as **`SSH_MONITOR_VERSION`** in **`ssh-monitor`** and **`version.txt`** (currently **1.2.7-SAC**). **`sac-client.sh`** reports the same version to SAC. Build from the git tree:
|
||||
|
||||
```bash
|
||||
make dist
|
||||
|
||||
@@ -229,6 +229,7 @@ sac_send_event() {
|
||||
SAC_AGENT_ID="$(sac_agent_instance_id)" \
|
||||
SAC_PRODUCT_VERSION="${SSH_MONITOR_VERSION:-unknown}" \
|
||||
SAC_SERVER_DISPLAY_NAME="${SERVER_DISPLAY_NAME:-}" \
|
||||
SAC_HOST_IPV4="${SERVER_IPV4:-}" \
|
||||
python3 <<'PY'
|
||||
import json, os, socket, uuid
|
||||
from datetime import datetime, timezone
|
||||
@@ -239,8 +240,39 @@ def details():
|
||||
return None
|
||||
return json.loads(raw)
|
||||
|
||||
def valid_ipv4(value: str) -> bool:
|
||||
try:
|
||||
parts = value.split(".")
|
||||
return len(parts) == 4 and all(0 <= int(p) <= 255 for p in parts)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def detect_host_ipv4() -> str:
|
||||
manual = os.environ.get("SAC_HOST_IPV4", "").strip()
|
||||
if manual and valid_ipv4(manual):
|
||||
return manual
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.connect(("1.1.1.1", 53))
|
||||
ip = s.getsockname()[0]
|
||||
s.close()
|
||||
if valid_ipv4(ip) and not ip.startswith(("127.", "169.254.")):
|
||||
return ip
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
infos = socket.getaddrinfo(socket.gethostname(), None, family=socket.AF_INET)
|
||||
for info in infos:
|
||||
ip = info[4][0]
|
||||
if valid_ipv4(ip) and not ip.startswith(("127.", "169.254.")):
|
||||
return ip
|
||||
except Exception:
|
||||
pass
|
||||
return ""
|
||||
|
||||
host = socket.gethostname()
|
||||
display = os.environ.get("SAC_SERVER_DISPLAY_NAME", "").strip()
|
||||
host_ipv4 = detect_host_ipv4()
|
||||
etype = os.environ["SAC_EVENT_TYPE"]
|
||||
if etype.startswith(("ssh.", "auth.", "rdp.")):
|
||||
category = "auth"
|
||||
@@ -267,6 +299,7 @@ payload = {
|
||||
"hostname": host,
|
||||
"os_family": "linux",
|
||||
**({"display_name": display} if display else {}),
|
||||
**({"ipv4": host_ipv4} if host_ipv4 else {}),
|
||||
},
|
||||
"category": category,
|
||||
"type": os.environ["SAC_EVENT_TYPE"],
|
||||
|
||||
+3
-1
@@ -7,7 +7,7 @@ IFS=$'\n\t'
|
||||
# ============================================
|
||||
|
||||
CONFIG_FILE="/etc/ssh-monitor.conf"
|
||||
SSH_MONITOR_VERSION="1.2.6-SAC"
|
||||
SSH_MONITOR_VERSION="1.2.7-SAC"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
if [ -f "$SCRIPT_DIR/sac-client.sh" ]; then
|
||||
@@ -61,6 +61,8 @@ DAILY_REPORT_TZ=""
|
||||
NOTIFY_TZ=""
|
||||
# Подпись сервера в уведомлениях: пусто = hostname (+ IPv4); иначе фиксированное имя (удобно при одинаковых hostname).
|
||||
SERVER_DISPLAY_NAME=""
|
||||
# Явный IPv4 хоста для SAC payload (host.ipv4). Пусто = автоопределение.
|
||||
SERVER_IPV4=""
|
||||
# Не слать повтор «Accepted» для той же пары user+IP чаще, чем раз в N секунд (разные port в журнале — один вход).
|
||||
SSH_ACCEPT_NOTIFY_DEDUP_SEC=5
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@ DAILY_REPORT_TOP_IPS="5"
|
||||
NOTIFY_TZ=""
|
||||
# Подпись «🖥️ Сервер» в уведомлениях: пусто = hostname (+ IPv4); иначе фиксированное имя (например prod-web-01).
|
||||
# SERVER_DISPLAY_NAME="prod-web-01"
|
||||
# Явный IPv4 для SAC payload host.ipv4. Пусто = автоопределение.
|
||||
# SERVER_IPV4="10.10.20.31"
|
||||
# Не чаще 1 успешного SSH (Accepted) в Telegram на пару user+IP за N секунд (разные port в журнале). 0 = только дедуп внутри одного прохода.
|
||||
SSH_ACCEPT_NOTIFY_DEDUP_SEC="5"
|
||||
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.2.6-SAC
|
||||
1.2.7-SAC
|
||||
|
||||
Reference in New Issue
Block a user