установка:
Код: Выделить всё
vim /usr/local/bin/dovecot_failed_auth.shКод: Выделить всё
#!/bin/bash
# ============================================================
# Скрипт для анализа неудачных попыток входа с геолокацией
# ============================================================
# === UTF-8 ===
export LANG=ru_RU.UTF-8
export LC_ALL=ru_RU.UTF-8
export LANGUAGE=ru_RU.UTF-8
# === НАСТРОЙКИ ===
EMAIL_TO="admin@padonak.su"
HOSTNAME=$(hostname -f)
# Пути к логам
DOVECOT_LOG="/var/log/dovecot/dovecot_info.log"
POSTFIX_LOG="/var/log/mail.log"
REPORT_FILE=$(mktemp)
TEMP_GEOCACHE="/tmp/geo_cache_$$.txt"
# === ФУНКЦИЯ ДЛЯ ПОЛУЧЕНИЯ ГЕОЛОКАЦИИ ===
get_geo() {
local ip=$1
if [ -f "$TEMP_GEOCACHE" ]; then
local cached=$(grep "^$ip|" "$TEMP_GEOCACHE" 2>/dev/null | cut -d'|' -f2-)
if [ -n "$cached" ]; then
echo "$cached"
return
fi
fi
if [[ "$ip" == 127.0.0.1 || "$ip" == ::1 || "$ip" == 192.168.* || "$ip" == 10.* || "$ip" == 172.16.* || "$ip" == 93.95.101.238 ]]; then
echo "Локальный"
echo "$ip|Локальный" >> "$TEMP_GEOCACHE"
return
fi
local geo=$(curl -s --connect-timeout 3 --max-time 5 "http://ip-api.com/line/$ip?fields=country,city" 2>/dev/null)
if [ -n "$geo" ]; then
local country=$(echo "$geo" | sed -n '1p' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
local city=$(echo "$geo" | sed -n '2p' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [ -n "$country" ] && [ "$country" != "fail" ] && [ "$country" != "private" ]; then
local result="${country:-Неизв}"
[ -n "$city" ] && [ "$city" != "fail" ] && result="$result, $city"
echo "$result"
echo "$ip|$result" >> "$TEMP_GEOCACHE"
return
fi
fi
echo "Неизвестно"
echo "$ip|Неизвестно" >> "$TEMP_GEOCACHE"
}
# === ФУНКЦИЯ ДЛЯ ФОРМАТИРОВАНИЯ ДАТЫ ===
format_date() {
date '+%Y-%m-%d %H:%M:%S'
}
# === ФУНКЦИЯ ОТПРАВКИ ПИСЬМА ===
send_report() {
mail -s "[Dovecot/Postfix] Отчёт о неудачных входах на $HOSTNAME" "$EMAIL_TO" < "$REPORT_FILE"
}
# === ГЛАВНАЯ ЛОГИКА ===
{
echo "============================================================"
echo " 📊 ОТЧЁТ ПО НЕУДАЧНЫМ ПОПЫТКАМ ВХОДА"
echo " Сервер: $HOSTNAME"
echo " Дата: $(format_date)"
echo "============================================================"
echo ""
# ============================================================
# 1. НЕУДАЧНЫЕ ПОПЫТКИ IMAP (Dovecot) С ГЕОЛОКАЦИЕЙ
# ============================================================
echo "📧 1. НЕУДАЧНЫЕ ПОПЫТКИ IMAP (Dovecot) — за 24 часа"
echo "------------------------------------------------------------------------------------------"
printf " %-30s %-18s %-35s %5s\n" "ПОЛЬЗОВАТЕЛЬ" "IP АДРЕС" "ГЕОЛОКАЦИЯ" "ПОПЫТКИ"
echo "------------------------------------------------------------------------------------------"
if [ -f "$DOVECOT_LOG" ]; then
# Парсим логи Dovecot - формат: user=<test@padonak.su>, ... rip=127.0.0.1
grep -E "auth failed.*auth_failed" "$DOVECOT_LOG" 2>/dev/null | \
grep -v "user=<>" | \
awk -F'user=<|>.*rip=' '
{
if (NF >= 3) {
user = $2
ip = $3
# Обрезаем ip до первого пробела или запятой
split(ip, arr, "[ ,]")
if (arr[1] != "") {
print user "|" arr[1]
}
}
}' | \
sort | uniq -c | sort -rn | head -20 | \
while read count user_ip; do
username=$(echo "$user_ip" | cut -d'|' -f1)
ip=$(echo "$user_ip" | cut -d'|' -f2)
if [ -n "$ip" ] && [ -n "$username" ] && [ "$ip" != " " ] && [ "$ip" != "" ]; then
geo=$(get_geo "$ip")
printf " %-30s %-18s %-35s %5d\n" "$username" "$ip" "$geo" "$count"
fi
done
else
echo " ⚠️ Лог-файл не найден: $DOVECOT_LOG"
fi
echo "------------------------------------------------------------------------------------------"
echo ""
# ============================================================
# 2. НЕУДАЧНЫЕ ПОПЫТКИ SASL (Postfix) С ГЕОЛОКАЦИЕЙ
# ============================================================
echo "📨 2. НЕУДАЧНЫЕ ПОПЫТКИ SASL (Postfix SMTP) — за 24 часа"
echo "------------------------------------------------------------------------------------------"
printf " %-30s %-18s %-35s %5s\n" "ПОЛЬЗОВАТЕЛЬ" "IP АДРЕС" "ГЕОЛОКАЦИЯ" "ПОПЫТКИ"
echo "------------------------------------------------------------------------------------------"
if [ -f "$POSTFIX_LOG" ]; then
# Парсим логи Postfix - формат: unknown[37.208.46.130]: ... sasl_username=pfcnfdf@npomis.ru
grep "SASL PLAIN authentication failed" "$POSTFIX_LOG" 2>/dev/null | \
sed -n 's/.*unknown\[\([0-9.]*\)\].*sasl_username=\([^,]*\).*/\2|\1/p' | \
sort | uniq -c | sort -rn | head -20 | \
while read count user_ip; do
username=$(echo "$user_ip" | cut -d'|' -f1)
ip=$(echo "$user_ip" | cut -d'|' -f2)
if [ -n "$ip" ] && [ -n "$username" ]; then
geo=$(get_geo "$ip")
printf " %-30s %-18s %-35s %5d\n" "$username" "$ip" "$geo" "$count"
fi
done
else
echo " ⚠️ Лог-файл не найден: $POSTFIX_LOG"
fi
echo "------------------------------------------------------------------------------------------"
echo ""
# ============================================================
# 3. ГЕОЛОКАЦИЯ АТАКУЮЩИХ IP (топ-10)
# ============================================================
echo "🌍 3. ГЕОЛОКАЦИЯ АТАКУЮЩИХ IP (топ-10)"
echo "------------------------------------------------------------"
printf " %-18s %-35s %8s\n" "IP АДРЕС" "ГЕОЛОКАЦИЯ" "ПОПЫТКИ"
echo "------------------------------------------------------------"
if [ -f "$POSTFIX_LOG" ]; then
grep "SASL PLAIN authentication failed" "$POSTFIX_LOG" 2>/dev/null | \
grep -oE '\[[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\]' | \
tr -d '[]' | \
sort | uniq -c | sort -rn | head -10 | \
while read count ip; do
geo=$(get_geo "$ip")
printf " %-18s %-35s %8d\n" "$ip" "$geo" "$count"
done
fi
echo "------------------------------------------------------------"
echo ""
# ============================================================
# 4. ОБЩАЯ СТАТИСТИКА
# ============================================================
echo "📊 4. ОБЩАЯ СТАТИСТИКА"
echo "------------------------------------------------------------"
IMAP_TOTAL=0
SASL_TOTAL=0
UNIQ_IMAP_USERS=0
UNIQ_SASL_USERS=0
if [ -f "$DOVECOT_LOG" ]; then
IMAP_TOTAL=$(grep -E "auth failed.*auth_failed" "$DOVECOT_LOG" 2>/dev/null | grep -v "user=<>" | wc -l)
UNIQ_IMAP_USERS=$(grep -E "auth failed.*auth_failed" "$DOVECOT_LOG" 2>/dev/null | grep -v "user=<>" | sed -n 's/.*user=<\([^>]*\)>.*/\1/p' | sort -u | wc -l)
fi
if [ -f "$POSTFIX_LOG" ]; then
SASL_TOTAL=$(grep "SASL PLAIN authentication failed" "$POSTFIX_LOG" 2>/dev/null | wc -l)
UNIQ_SASL_USERS=$(grep "SASL PLAIN authentication failed" "$POSTFIX_LOG" 2>/dev/null | sed -n 's/.*sasl_username=\([^,]*\).*/\1/p' | sort -u | wc -l)
fi
echo " 📧 IMAP: $IMAP_TOTAL попыток, $UNIQ_IMAP_USERS уникальных пользователей"
echo " 📨 SASL: $SASL_TOTAL попыток, $UNIQ_SASL_USERS уникальных пользователей"
TOTAL_ATTEMPTS=$((IMAP_TOTAL + SASL_TOTAL))
echo " 📊 Всего попыток: $TOTAL_ATTEMPTS"
echo "------------------------------------------------------------"
echo ""
# ============================================================
# 5. СОВЕТЫ ПО БЕЗОПАСНОСТИ
# ============================================================
echo "🛡️ 5. РЕКОМЕНДАЦИИ ПО БЕЗОПАСНОСТИ"
echo "------------------------------------------------------------"
if [ $SASL_TOTAL -gt 100 ]; then
echo " ⚠️ Обнаружено более 100 неудачных попыток SASL!"
echo " Рекомендации:"
echo " • Включите fail2ban для Postfix"
echo " • Ограничьте количество соединений с одного IP"
echo " • Используйте сложные пароли"
elif [ $SASL_TOTAL -gt 50 ]; then
echo " ⚠️ Обнаружено более 50 неудачных попыток SASL."
echo " Рекомендуется проверить настройки безопасности."
else
echo " ✅ Уровень атак в пределах нормы."
fi
echo "------------------------------------------------------------"
echo ""
echo "============================================================"
echo "Отчёт сгенерирован: $(format_date)"
echo "============================================================"
} > "$REPORT_FILE"
# === ОТПРАВЛЯЕМ ПИСЬМО ===
send_report
# === ЧИСТИМ ВРЕМЕННЫЕ ФАЙЛЫ ===
rm -f "$REPORT_FILE" "$TEMP_GEOCACHE" 2>/dev/null
echo "✅ Отчёт отправлен на $EMAIL_TO в $(format_date)"
Код: Выделить всё
chmod +x /usr/local/bin/dovecot_failed_auth.shКод: Выделить всё
sudo crontab -eКод: Выделить всё
0 8 * * * /usr/local/bin/dovecot_failed_auth.shКод: Выделить всё
3. ГЕОЛОКАЦИЯ АТАКУЮЩИХ IP (топ-10)
------------------------------------------------------------
IP ADDRESS COUNTRY/CITY ATTEMPTS
------------------------------------------------------------
210.0.90.82 Australia, Forest Lodge 10
222.117.0.253 South Korea, Anyang-si 8
210.0.90.81 Australia, Forest Lodge 6
111.0.81.84 China, Hangzhou 5
45.178.227.0 Brazil, Paquetá 4
131.0.190.152 Brazil, Santa Luzia 4
49.0.82.4 Thailand, Bangkok 3
31.173.0.140 Russia, Moscow 3
201.46.124.0 Colombia, Bogotá 3
180.111.0.21 China, Nanjing 3
------------------------------------------------------------
📊 4. ОБЩАЯ СТАТИСТИКА
------------------------------------------------------------
📧 IMAP: 5 попыток, 3 уникальных пользователей
📨 SASL: 1161 попыток, 116 уникальных пользователей
------------------------------------------------------------
============================================================
Отчёт сгенерирован: 2026-09-05 16:56:09
============================================================
