fix: Telegram newlines instead of literal %0A

This commit is contained in:
PTah
2026-04-12 20:03:25 +10:00
parent e93fde7f52
commit 75f1a1c841
2 changed files with 60 additions and 62 deletions
+53 -54
View File
@@ -332,8 +332,7 @@ send_backup_webhook_raw() {
if ! command -v python3 >/dev/null 2>&1; then if ! command -v python3 >/dev/null 2>&1; then
return 1 return 1
fi fi
local plain local plain="$message"
plain="$(printf '%s' "$message" | sed 's/%0A/\n/g')"
local payload local payload
payload="$(BACKUP_MSG="$plain" python3 - <<'PY' payload="$(BACKUP_MSG="$plain" python3 - <<'PY'
import json, os import json, os
@@ -351,7 +350,7 @@ PY
notify_send() { notify_send() {
local message="$1" local message="$1"
if [ "${DRY_RUN:-0}" = "1" ]; then if [ "${DRY_RUN:-0}" = "1" ]; then
printf '[DRY-RUN notify] %s\n' "$(printf '%s' "$message" | sed 's/%0A/ | /g')" >&2 printf '[DRY-RUN notify] %s\n' "$(printf '%s' "$message" | tr '\n' ' ')" >&2
return 0 return 0
fi fi
if send_telegram_raw "$message"; then if send_telegram_raw "$message"; then
@@ -518,10 +517,10 @@ block_ip() {
save_iptables_rules save_iptables_rules
local ban_time_hours=$((BAN_TIME / 3600)) local ban_time_hours=$((BAN_TIME / 3600))
local message=" 🚫 IP ЗАБЛОКИРОВАН АВТОМАТИЧЕСКИ %0A" local message=" 🚫 IP ЗАБЛОКИРОВАН АВТОМАТИЧЕСКИ "$'\n'
message="${message}🌐 IP: ${ip}%0A" message="${message}🌐 IP: ${ip}"$'\n'
message="${message}📊 Неудачных попыток: ${attempts}%0A" message="${message}📊 Неудачных попыток: ${attempts}"$'\n'
message="${message}⏱️ Блокировка на: ${ban_time_hours} час(ов)%0A" message="${message}⏱️ Блокировка на: ${ban_time_hours} час(ов)"$'\n'
message="${message}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')" message="${message}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$message" notify_send "$message"
write_log "AUTO-BAN: IP $ip заблокирован на $ban_time_hours часов ($attempts попыток)" write_log "AUTO-BAN: IP $ip заблокирован на $ban_time_hours часов ($attempts попыток)"
@@ -545,8 +544,8 @@ unblock_expired_ips() {
do_firewall_del_drop "$ip" do_firewall_del_drop "$ip"
write_log "UNBAN: IP $ip разблокирован (время блокировки истекло)" write_log "UNBAN: IP $ip разблокирован (время блокировки истекло)"
local message=" 🔓 IP РАЗБЛОКИРОВАН %0A" local message=" 🔓 IP РАЗБЛОКИРОВАН "$'\n'
message="${message}🌐 IP: ${ip}%0A" message="${message}🌐 IP: ${ip}"$'\n'
message="${message}🕐 Время разблокировки: $(date '+%d.%m.%Y %H:%M:%S')" message="${message}🕐 Время разблокировки: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$message" notify_send "$message"
@@ -685,15 +684,15 @@ monitor_ssh() {
user=$(sed -nE 's/.* for ([^ ]+) from .*/\1/p' <<<"$line") user=$(sed -nE 's/.* for ([^ ]+) from .*/\1/p' <<<"$line")
ip="$(extract_ssh_client_ip "$line")" ip="$(extract_ssh_client_ip "$line")"
if [ -n "$user" ]; then if [ -n "$user" ]; then
local message=" ✅ УСПЕШНОЕ SSH ПОДКЛЮЧЕНИЕ %0A" local message=" ✅ УСПЕШНОЕ SSH ПОДКЛЮЧЕНИЕ "$'\n'
message="${message}👤 Пользователь: ${user}%0A" message="${message}👤 Пользователь: ${user}"$'\n'
message="${message}🌐 IP адрес: ${ip:-local}%0A" message="${message}🌐 IP адрес: ${ip:-local}"$'\n'
message="${message}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')" message="${message}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$message" notify_send "$message"
write_log "SSH успешный вход: $user с IP ${ip:-local}" write_log "SSH успешный вход: $user с IP ${ip:-local}"
if [ "$user" = "root" ]; then if [ "$user" = "root" ]; then
local rmsg=" 🔑 SSH ВХОД ПОД ROOT %0A" local rmsg=" 🔑 SSH ВХОД ПОД ROOT "$'\n'
rmsg="${rmsg}🌐 IP: ${ip:-local}%0A" rmsg="${rmsg}🌐 IP: ${ip:-local}"$'\n'
rmsg="${rmsg}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')" rmsg="${rmsg}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$rmsg" notify_send "$rmsg"
fi fi
@@ -719,10 +718,10 @@ monitor_ssh() {
unset "FAIL_COUNTS[$ip]" unset "FAIL_COUNTS[$ip]"
else else
if [ "$current_attempts" -ge 2 ]; then if [ "$current_attempts" -ge 2 ]; then
local message=" ❌ НЕУДАЧНАЯ ПОПЫТКА SSH %0A" local message=" ❌ НЕУДАЧНАЯ ПОПЫТКА SSH "$'\n'
message="${message}👤 Пользователь: ${user}%0A" message="${message}👤 Пользователь: ${user}"$'\n'
message="${message}🌐 IP адрес: ${ip}%0A" message="${message}🌐 IP адрес: ${ip}"$'\n'
message="${message}📊 Попытка ${current_attempts} из ${MAX_ATTEMPTS}%0A" message="${message}📊 Попытка ${current_attempts} из ${MAX_ATTEMPTS}"$'\n'
message="${message}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')" message="${message}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$message" notify_send "$message"
fi fi
@@ -768,10 +767,10 @@ monitor_sudo() {
pwd=$(sed -nE 's/.*PWD=([^ ]+).*/\1/p' <<<"$line") pwd=$(sed -nE 's/.*PWD=([^ ]+).*/\1/p' <<<"$line")
if [ -n "$user" ] && [ -n "${sudo_cmd:-}" ]; then if [ -n "$user" ] && [ -n "${sudo_cmd:-}" ]; then
local message=" ⚠️ ИСПОЛЬЗОВАНИЕ SUDO %0A" local message=" ⚠️ ИСПОЛЬЗОВАНИЕ SUDO "$'\n'
message="${message}👤 Пользователь: ${user}%0A" message="${message}👤 Пользователь: ${user}"$'\n'
message="${message}💻 Команда: ${sudo_cmd}%0A" message="${message}💻 Команда: ${sudo_cmd}"$'\n'
message="${message}📁 Директория: ${pwd:-unknown}%0A" message="${message}📁 Директория: ${pwd:-unknown}"$'\n'
message="${message}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')" message="${message}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$message" notify_send "$message"
write_log "SUDO: $user выполнил $sudo_cmd" write_log "SUDO: $user выполнил $sudo_cmd"
@@ -812,8 +811,8 @@ monitor_security_events() {
if echo "$chunk" | grep -Eqi "REMOTE HOST IDENTIFICATION HAS CHANGED"; then if echo "$chunk" | grep -Eqi "REMOTE HOST IDENTIFICATION HAS CHANGED"; then
local hk local hk
hk="$(echo "$chunk" | grep -Ei "REMOTE HOST IDENTIFICATION HAS CHANGED" | head -n 3)" hk="$(echo "$chunk" | grep -Ei "REMOTE HOST IDENTIFICATION HAS CHANGED" | head -n 3)"
local m=" 🔐 ВНИМАНИЕ: изменение SSH host key / MITM? %0A" local m=" 🔐 ВНИМАНИЕ: изменение SSH host key / MITM? "$'\n'
m="${m}$(printf '%s' "$hk" | sed 's/$/%0A/g' | tr -d '\n')%0A" m="${m}$(printf '%s\n' "$hk")"
m="${m}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')" m="${m}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$m" notify_send "$m"
write_log "SECURITY: обнаружено сообщение об изменении host key" write_log "SECURITY: обнаружено сообщение об изменении host key"
@@ -832,9 +831,9 @@ monitor_security_events() {
lastn="${BRUTE_LAST_NOTIFY[$ip]:-0}" lastn="${BRUTE_LAST_NOTIFY[$ip]:-0}"
if [ $((nowc - lastn)) -ge "$BRUTE_NOTIFY_COOLDOWN_SEC" ]; then if [ $((nowc - lastn)) -ge "$BRUTE_NOTIFY_COOLDOWN_SEC" ]; then
BRUTE_LAST_NOTIFY[$ip]=$nowc BRUTE_LAST_NOTIFY[$ip]=$nowc
local bm=" 🧨 ВОЗМОЖНЫЙ МАССОВЫЙ БРУТФОРС SSH %0A" local bm=" 🧨 ВОЗМОЖНЫЙ МАССОВЫЙ БРУТФОРС SSH "$'\n'
bm="${bm}🌐 IP: ${ip}%0A" bm="${bm}🌐 IP: ${ip}"$'\n'
bm="${bm}📊 Неудачных попыток за ~${BRUTE_WINDOW_SEC}s: ${count}%0A" bm="${bm}📊 Неудачных попыток за ~${BRUTE_WINDOW_SEC}s: ${count}"$'\n'
bm="${bm}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')" bm="${bm}🕐 Время: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$bm" notify_send "$bm"
write_log "SECURITY: массовый брутфорс? IP=$ip fails=${count} за окно ${BRUTE_WINDOW_SEC}s" write_log "SECURITY: массовый брутфорс? IP=$ip fails=${count} за окно ${BRUTE_WINDOW_SEC}s"
@@ -918,29 +917,29 @@ send_daily_report() {
done <"$BAN_LIST_FILE" done <"$BAN_LIST_FILE"
fi fi
local message=" 📊 ЕЖЕДНЕВНЫЙ ОТЧЕТ SSH МОНИТОРИНГА %0A" local message=" 📊 ЕЖЕДНЕВНЫЙ ОТЧЕТ SSH МОНИТОРИНГА "$'\n'
message="${message}🖥️ Сервер: $(hostname)%0A" message="${message}🖥️ Сервер: $(hostname)"$'\n'
message="${message}🕐 Время отчета: ${current_time}%0A" message="${message}🕐 Время отчета: ${current_time}"$'\n'
message="${message}%0A" message="${message}"$'\n'
message="${message} 📈 СТАТИСТИКА ЗА ПОСЛЕДНИЕ 24 ЧАСА: %0A" message="${message} 📈 СТАТИСТИКА ЗА ПОСЛЕДНИЕ 24 ЧАСА: "$'\n'
message="${message} ✅ Успешных SSH подключений: ${successful_logins:-0}%0A" message="${message} ✅ Успешных SSH подключений: ${successful_logins:-0}"$'\n'
message="${message} ❌ Неудачных попыток SSH: ${failed_logins:-0}%0A" message="${message} ❌ Неудачных попыток SSH: ${failed_logins:-0}"$'\n'
message="${message} ⚠️ Команд через sudo: ${sudo_commands:-0}%0A" message="${message} ⚠️ Команд через sudo: ${sudo_commands:-0}"$'\n'
message="${message} 🚫 Заблокировано IP: ${active_bans}%0A" message="${message} 🚫 Заблокировано IP: ${active_bans}"$'\n'
message="${message}%0A" message="${message}"$'\n'
message="${message} 🧾 ТОП-${DAILY_REPORT_TOP_IPS} IP ПО НЕУДАЧНЫМ ПОПЫТКАМ:%0A" message="${message} 🧾 ТОП-${DAILY_REPORT_TOP_IPS} IP ПО НЕУДАЧНЫМ ПОПЫТКАМ:"$'\n'
if [ -n "$top_lines" ]; then if [ -n "$top_lines" ]; then
message="${message}$(printf '%s' "$top_lines" | sed 's/$/%0A/g' | tr -d '\n')%0A" message="${message}${top_lines}"$'\n'
else else
message="${message} (нет данных)%0A" message="${message} (нет данных)"$'\n'
fi fi
message="${message}%0A" message="${message}"$'\n'
message="${message} 👥 АКТИВНЫЕ ПОЛЬЗОВАТЕЛИ (${active_count}): %0A" message="${message} 👥 АКТИВНЫЕ ПОЛЬЗОВАТЕЛИ (${active_count}):"$'\n'
if [ -n "$active_sessions" ]; then if [ -n "$active_sessions" ]; then
message="${message}$(printf '%s' "$active_sessions" | sed 's/$/%0A/g' | tr -d '\n')%0A" message="${message}${active_sessions}"$'\n'
else else
message="${message} Нет активных пользователей%0A" message="${message} Нет активных пользователей"$'\n'
fi fi
notify_send "$message" notify_send "$message"
@@ -998,8 +997,8 @@ send_heartbeat() {
local timestamp_human local timestamp_human
timestamp_human=$(date '+%d.%m.%Y %H:%M:%S') timestamp_human=$(date '+%d.%m.%Y %H:%M:%S')
local message=" ❤️ Heartbeat - скрипт мониторинга работает %0A" local message=" ❤️ Heartbeat - скрипт мониторинга работает "$'\n'
message="${message}🖥️ Сервер: $(hostname)%0A" message="${message}🖥️ Сервер: $(hostname)"$'\n'
message="${message}🕐 Время: ${timestamp_human}" message="${message}🕐 Время: ${timestamp_human}"
notify_send "$message" notify_send "$message"
@@ -1056,12 +1055,12 @@ send_startup_notification() {
timestamp=$(date '+%d.%m.%Y %H:%M:%S') timestamp=$(date '+%d.%m.%Y %H:%M:%S')
local whitelist_count=$((${#WHITELIST_IPS[@]} + ${#WHITELIST_SUBNETS[@]})) local whitelist_count=$((${#WHITELIST_IPS[@]} + ${#WHITELIST_SUBNETS[@]}))
local message=" ✅ СКРИПТ МОНИТОРИНГА ЗАПУЩЕН %0A" local message=" ✅ СКРИПТ МОНИТОРИНГА ЗАПУЩЕН "$'\n'
message="${message}🖥️ Сервер: $(hostname)%0A" message="${message}🖥️ Сервер: $(hostname)"$'\n'
message="${message}🕐 Время запуска: ${timestamp}%0A" message="${message}🕐 Время запуска: ${timestamp}"$'\n'
message="${message}📊 Мониторинг SSH и SUDO активирован%0A" message="${message}📊 Мониторинг SSH и SUDO активирован"$'\n'
message="${message}🚫 Автоблокировка IP после ${MAX_ATTEMPTS} попыток на ${BAN_TIME} секунд%0A" message="${message}🚫 Автоблокировка IP после ${MAX_ATTEMPTS} попыток на ${BAN_TIME} секунд"$'\n'
message="${message}⚪ Белый список: ${whitelist_count} IP/подсетей%0A" message="${message}⚪ Белый список: ${whitelist_count} IP/подсетей"$'\n'
message="${message}❤️ Heartbeat будет отправляться каждые 12 часов" message="${message}❤️ Heartbeat будет отправляться каждые 12 часов"
notify_send "$message" notify_send "$message"
@@ -1071,8 +1070,8 @@ send_startup_notification() {
send_shutdown_notification() { send_shutdown_notification() {
local timestamp local timestamp
timestamp=$(date '+%d.%m.%Y %H:%M:%S') timestamp=$(date '+%d.%m.%Y %H:%M:%S')
local message=" ⚠️ СКРИПТ МОНИТОРИНГА ОСТАНОВЛЕН %0A" local message=" ⚠️ СКРИПТ МОНИТОРИНГА ОСТАНОВЛЕН "$'\n'
message="${message}🖥️ Сервер: $(hostname)%0A" message="${message}🖥️ Сервер: $(hostname)"$'\n'
message="${message}🕐 Время остановки: ${timestamp}" message="${message}🕐 Время остановки: ${timestamp}"
notify_send "$message" notify_send "$message"
+7 -8
View File
@@ -45,8 +45,7 @@ send_backup_webhook_raw() {
if ! command -v python3 >/dev/null 2>&1; then if ! command -v python3 >/dev/null 2>&1; then
return 1 return 1
fi fi
local plain local plain="$message"
plain="$(printf '%s' "$message" | sed 's/%0A/\n/g')"
local payload local payload
payload="$(BACKUP_MSG="$plain" python3 - <<'PY' payload="$(BACKUP_MSG="$plain" python3 - <<'PY'
import json, os import json, os
@@ -105,16 +104,16 @@ restart_monitor() {
local reason="$1" local reason="$1"
write_log "Watchdog: перезапуск $WATCHDOG_SERVICE_NAME, причина: $reason" write_log "Watchdog: перезапуск $WATCHDOG_SERVICE_NAME, причина: $reason"
if systemctl restart "$WATCHDOG_SERVICE_NAME"; then if systemctl restart "$WATCHDOG_SERVICE_NAME"; then
local msg=" ⚠️ WATCHDOG: монитор перезапущен %0A" local msg=" ⚠️ WATCHDOG: монитор перезапущен "$'\n'
msg="${msg}Сервис: ${WATCHDOG_SERVICE_NAME}%0A" msg="${msg}Сервис: ${WATCHDOG_SERVICE_NAME}"$'\n'
msg="${msg}Причина: ${reason}%0A" msg="${msg}Причина: ${reason}"$'\n'
msg="${msg}Время: $(date '+%d.%m.%Y %H:%M:%S')" msg="${msg}Время: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$msg" notify_send "$msg"
else else
write_log "Watchdog: ошибка перезапуска $WATCHDOG_SERVICE_NAME" write_log "Watchdog: ошибка перезапуска $WATCHDOG_SERVICE_NAME"
local msg=" ❌ WATCHDOG: не удалось перезапустить монитор %0A" local msg=" ❌ WATCHDOG: не удалось перезапустить монитор "$'\n'
msg="${msg}Сервис: ${WATCHDOG_SERVICE_NAME}%0A" msg="${msg}Сервис: ${WATCHDOG_SERVICE_NAME}"$'\n'
msg="${msg}Причина: ${reason}%0A" msg="${msg}Причина: ${reason}"$'\n'
msg="${msg}Время: $(date '+%d.%m.%Y %H:%M:%S')" msg="${msg}Время: $(date '+%d.%m.%Y %H:%M:%S')"
notify_send "$msg" notify_send "$msg"
return 1 return 1