SSH MONITOR - СКРИПТ ДЛЯ ОТСЛЕЖИВАНИЯ ПОДОЗРИТЕЛЬНЫХ ПОДКЛЮЧЕНИЙ

Модератор: padonki

Ответить
Аватара пользователя
Padonak
padonki
Сообщения: 3842
Зарегистрирован: 14 авг 2006, 20:43
Контактная информация:

SSH MONITOR - СКРИПТ ДЛЯ ОТСЛЕЖИВАНИЯ ПОДОЗРИТЕЛЬНЫХ ПОДКЛЮЧЕНИЙ

Сообщение Padonak »

ИНТЕРАКТИВНЫЙ УСТАНОВЩИК SSH MONITOR

Код: Выделить всё

#!/bin/bash
# ============================================================
# SSH MONITOR С АВТОБАНОМ
# Сервер: daemon
# Установлен: 2026-09-10
# ============================================================

# ==================== НАСТРОЙКИ ====================
EMAIL_TO="admin@padonak.su"
SERVER_NAME="daemon"
ALLOWED_IPS=(
    "93.95.101.238"
    "192.168.13.0/24"
    )

BAN_TIME="86400"        # 24 часа
AUTO_BLOCK="yes"
NOTIFY_SUSPICIOUS="yes"

# ==================== СЛУЖЕБНЫЕ ПЕРЕМЕННЫЕ ====================
EMAIL_FROM="ssh-alert@$SERVER_NAME"
LOG_FILE="/var/log/ssh-monitor.log"
BAN_LOG="/var/log/ssh-ban.log"
STATE_DIR="/var/lib/ssh-monitor"
STATE_FILE="$STATE_DIR/last_state"
PID_FILE="/var/run/ssh-monitor.pid"

# ==================== ФУНКЦИИ ====================
log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

log_ban() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$BAN_LOG"
}

send_email() {
    local subject="$1"
    local body="$2"
    
    local email_content="From: $EMAIL_FROM
To: $EMAIL_TO
Subject: $subject
Content-Type: text/plain; charset=UTF-8

$body

---
Server: $SERVER_NAME
IP: $(hostname -I | awk '{print $1}')
Time: $(date '+%Y-%m-%d %H:%M:%S')
"
    
    log_message "📧 Отправка письма на $EMAIL_TO"
    
    # Способ 1: msmtp
    if command -v msmtp >/dev/null 2>&1; then
        if echo "$email_content" | msmtp -t "$EMAIL_TO" 2>/dev/null; then
            log_message "  ✅ Отправлено через msmtp"
            return 0
        else
            log_message "  ❌ Ошибка msmtp"
        fi
    fi
    
    # Способ 2: sendmail
    if command -v sendmail >/dev/null 2>&1; then
        if echo "$email_content" | sendmail -t 2>/dev/null; then
            log_message "  ✅ Отправлено через sendmail"
            return 0
        fi
    fi
    
    # Способ 3: mail
    if command -v mail >/dev/null 2>&1; then
        if echo "$body" | mail -s "$subject" -a "From: $EMAIL_FROM" "$EMAIL_TO" 2>/dev/null; then
            log_message "  ✅ Отправлено через mail"
            return 0
        fi
    fi
    
    log_message "❌ ВСЕ СПОСОБЫ НЕ СРАБОТАЛИ!"
    return 1
}

# ==================== ФУНКЦИЯ ПРОВЕРКИ ПОДСЕТЕЙ ====================
is_ip_allowed() {
    local ip="$1"
    
    if [[ -z "$ip" ]] || [[ "$ip" == "unknown" ]]; then
        return 1
    fi
    
    for allowed in "${ALLOWED_IPS[@]}"; do
        # Точное совпадение
        if [[ "$ip" == "$allowed" ]]; then
            return 0
        fi
        
        # Проверка подсети (поддерживает /8, /16, /22, /24, /32 и т.д.)
        if [[ "$allowed" == *"/"* ]]; then
            local network=$(echo "$allowed" | cut -d'/' -f1)
            local mask=$(echo "$allowed" | cut -d'/' -f2)
            
            # Конвертируем IP в число
            ip_to_int() {
                local a b c d
                IFS=. read -r a b c d <<< "$1"
                echo "$((a * 256**3 + b * 256**2 + c * 256 + d))"
            }
            
            local ip_int=$(ip_to_int "$ip")
            local net_int=$(ip_to_int "$network")
            local mask_int=$((0xffffffff << (32 - mask) & 0xffffffff))
            
            if [[ $((ip_int & mask_int)) -eq $((net_int & mask_int)) ]]; then
                return 0
            fi
        fi
    done
    
    return 1
}

get_ip_for_pid() {
    local pid="$1"
    local ip=""
    
    if command -v ss >/dev/null 2>&1; then
        ip=$(ss -tnp 2>/dev/null | grep "pid=$pid" | head -1 | awk '{print $5}' | cut -d':' -f1)
        if [[ -n "$ip" ]] && [[ "$ip" != "0.0.0.0" ]] && [[ "$ip" != "::" ]] && [[ "$ip" != "*" ]]; then
            echo "$ip"
            return 0
        fi
    fi
    
    if command -v netstat >/dev/null 2>&1; then
        ip=$(netstat -tnp 2>/dev/null | grep "$pid/sshd" | head -1 | awk '{print $5}' | cut -d':' -f1)
        if [[ -n "$ip" ]] && [[ "$ip" != "0.0.0.0" ]] && [[ "$ip" != "::" ]] && [[ "$ip" != "*" ]]; then
            echo "$ip"
            return 0
        fi
    fi
    
    local tty=$(ps -o tty= -p "$pid" 2>/dev/null | tr -d ' ')
    if [[ -n "$tty" ]] && [[ "$tty" != "?" ]]; then
        ip=$(who -u 2>/dev/null | grep "$tty" | awk '{print $NF}' | sed 's/[()]//g')
        if [[ -n "$ip" ]] && [[ "$ip" != "0.0.0.0" ]] && [[ "$ip" != "::" ]] && [[ "$ip" != "*" ]]; then
            echo "$ip"
            return 0
        fi
    fi
    
    echo "unknown"
}

get_ssh_sessions() {
    ps aux | grep -E 'sshd-session:.*@|sshd:.*@' | grep -v grep | grep -v "listener" | grep -v "accepted" | awk '{print $2}'
}

block_ip() {
    local ip="$1"
    
    log_ban "🔒 БЛОКИРОВКА IP: $ip"
    
    if iptables -L INPUT -n 2>/dev/null | grep -q "$ip"; then
        log_ban "ℹ️  IP $ip уже заблокирован"
        return 0
    fi
    
    if command -v iptables >/dev/null 2>&1; then
        if [[ "$BAN_TIME" -gt 0 ]]; then
            iptables -I INPUT -s "$ip" -m recent --set --name SSH_BAN 2>/dev/null
            iptables -I INPUT -s "$ip" -m recent --update --seconds $BAN_TIME --name SSH_BAN -j DROP 2>/dev/null
            log_ban "✅ IP $ip заблокирован на $BAN_TIME секунд ($(($BAN_TIME / 3600)) часов)"
        else
            iptables -I INPUT -s "$ip" -j DROP 2>/dev/null
            log_ban "✅ IP $ip заблокирован НАВСЕГДА"
        fi
        return 0
    fi
    
    if command -v ufw >/dev/null 2>&1; then
        ufw deny from "$ip" 2>/dev/null
        log_ban "✅ IP $ip заблокирован через ufw"
        return 0
    fi
    
    log_ban "❌ НЕ УДАЛОСЬ ЗАБЛОКИРОВАТЬ IP $ip"
    return 1
}

process_session() {
    local pid="$1"
    local user=$(ps -o user= -p "$pid" 2>/dev/null | tr -d ' ')
    local client_ip=$(get_ip_for_pid "$pid")
    local start_time=$(ps -o lstart= -p "$pid" 2>/dev/null | tr -d ' ')
    
    log_message "NEW SESSION: PID=$pid, USER=$user, IP=$client_ip"
    
    if [[ -z "$client_ip" ]] || [[ "$client_ip" == "unknown" ]]; then
        log_message "FAILED to get IP for PID $pid"
        return 1
    fi
    
    # Проверка IP с поддержкой подсетей
    if is_ip_allowed "$client_ip"; then
        log_message "✅ ALLOWED IP: $client_ip"
        return 0
    fi
    
    log_message "🚨 SUSPICIOUS IP: $client_ip"
    
    if [[ "$AUTO_BLOCK" == "yes" ]]; then
        block_ip "$client_ip"
    fi
    
    if [[ "$NOTIFY_SUSPICIOUS" == "yes" ]]; then
        local ban_text=""
        if [[ "$BAN_TIME" -gt 0 ]]; then
            ban_text="на $(($BAN_TIME / 3600)) часов"
        else
            ban_text="НАВСЕГДА"
        fi
        
        local subject="🚨 SSH БАН: IP $client_ip заблокирован!"
        local body="🚨 ПОДОЗРИТЕЛЬНОЕ SSH ПОДКЛЮЧЕНИЕ
========================================
СТАТУС: ❌ НЕ РАЗРЕШЕН!
Пользователь: $user
IP адрес: $client_ip
Время подключения: $start_time
Сервер: $SERVER_NAME
========================================

🔴 IP АДРЕС ЗАБЛОКИРОВАН $ban_text!

Причина: Подключение с неразрешенного IP

Действие: Автоматическая блокировка через iptables

Текущие активные сессии:
$(who -u 2>/dev/null || echo "Нет активных сессий")

Заблокированные IP:
$(iptables -L INPUT -n 2>/dev/null | grep -E "DROP|REJECT" | head -10 || echo "Нет блокировок")
========================================"
        send_email "$subject" "$body"
    fi
}

show_status() {
    echo "========================================="
    echo "SSH MONITOR WITH AUTO-BAN - STATUS"
    echo "========================================="
    echo ""
    echo "Server: $SERVER_NAME"
    echo "Email: $EMAIL_TO"
    echo "Allowed IPs:"
    for ip in "${ALLOWED_IPS[@]}"; do
        echo "  - $ip"
    done
    echo ""
    echo "Ban time: $BAN_TIME seconds ($(($BAN_TIME / 3600)) hours)"
    echo "Auto block: $AUTO_BLOCK"
    echo ""
    echo "Blocked IPs:"
    iptables -L INPUT -n 2>/dev/null | grep -E "DROP|REJECT" | head -20 || echo "  No blocked IPs"
    echo ""
    echo "Log: $LOG_FILE"
    echo "Ban log: $BAN_LOG"
    echo "========================================="
}

test_email() {
    echo "Sending test email to $EMAIL_TO..."
    
    local subject="🧪 Test from SSH Monitor with Auto-Ban"
    local body="TEST EMAIL
========================================
This is a test email from SSH Monitor.

System is working with AUTO-BAN enabled.

Server: $SERVER_NAME
IP: $(hostname -I | awk '{print $1}')
Time: $(date '+%Y-%m-%d %H:%M:%S')
========================================"
    
    if send_email "$subject" "$body"; then
        echo "✅ Test email sent!"
    else
        echo "❌ Failed to send test email"
    fi
}

case "$1" in
    --status|status)
        show_status
        exit 0
        ;;
    --test|test)
        test_email
        exit 0
        ;;
    --unban|unban)
        if [[ -z "$2" ]]; then
            echo "Usage: $0 --unban IP"
            exit 1
        fi
        iptables -D INPUT -s "$2" -j DROP 2>/dev/null
        iptables -D INPUT -s "$2" -m recent --update --name SSH_BAN -j DROP 2>/dev/null
        echo "✅ IP $2 разблокирован"
        exit 0
        ;;
    --help|help|-h)
        echo "Usage: $0 [OPTION]"
        echo "  --status  - Show status"
        echo "  --test    - Send test email"
        echo "  --unban IP - Unblock IP"
        echo "  --help    - Show this help"
        exit 0
        ;;
esac

mkdir -p "$(dirname "$LOG_FILE")" "$STATE_DIR"
touch "$LOG_FILE" "$BAN_LOG"

if [[ -f "$PID_FILE" ]]; then
    OLD_PID=$(cat "$PID_FILE" 2>/dev/null)
    if kill -0 "$OLD_PID" 2>/dev/null; then
        echo "❌ Script already running (PID: $OLD_PID)"
        exit 1
    fi
fi
echo $$ > "$PID_FILE"

log_message "========================================="
log_message "🚀 START SSH MONITOR WITH AUTO-BAN"
log_message "Server: $SERVER_NAME"
log_message "Email: $EMAIL_TO"
log_message "Allowed IPs: ${ALLOWED_IPS[*]}"
log_message "Ban time: $BAN_TIME seconds"
log_message "Auto block: $AUTO_BLOCK"
log_message "========================================="

EXISTING_SESSIONS=$(get_ssh_sessions)
if [[ -n "$EXISTING_SESSIONS" ]]; then
    log_message "Found existing sessions: $(echo "$EXISTING_SESSIONS" | wc -w)"
fi
echo "$EXISTING_SESSIONS" > "$STATE_FILE"
log_message "Initialization complete"

while true; do
    CURRENT_SESSIONS=$(get_ssh_sessions)
    if [[ -n "$CURRENT_SESSIONS" ]]; then
        PREVIOUS_SESSIONS=$(cat "$STATE_FILE" 2>/dev/null || echo "")
        for pid in $CURRENT_SESSIONS; do
            if ! echo "$PREVIOUS_SESSIONS" | grep -q "^$pid$"; then
                process_session "$pid"
            fi
        done
        echo "$CURRENT_SESSIONS" > "$STATE_FILE"
    else
        echo "" > "$STATE_FILE" 2>/dev/null
    fi
    sleep 5
done

# 1. Создайте файл установщика

Код: Выделить всё

vim install-ssh-monitor.sh
# 2. Скопируйте ВЕСЬ код выше и вставьте

# 3. Сделайте исполняемым

Код: Выделить всё

chmod +x install-ssh-monitor.sh
# 4. Запустите

Код: Выделить всё

./install-ssh-monitor.sh
ЧТО БУДЕТ ВО ВРЕМЯ УСТАНОВКИ:

Запросит email для уведомлений

Запросит разрешенные IP (можно добавить несколько)

Запросит интервал проверки (по умолчанию 5 секунд)

Спросит про автоблокировку (Да/Нет)

Спросит про уведомления (только подозрительные или все)

Покажет все настройки и запросит подтверждение

Остановит старый сервис (если был)

Установит новый скрипт и сервис

Отправит тестовое письмо (по желанию)

Покажет команды для управления
Моя характеристика с детского сада: Хорошо кушает, спит, гуляет! Прошло много лет, ничего не изменилось.
Изображение
Аватара пользователя
Padonak
padonki
Сообщения: 3842
Зарегистрирован: 14 авг 2006, 20:43
Контактная информация:

новая версия скрипта

Сообщение Padonak »

Код: Выделить всё

#!/bin/bash
# ============================================================
# SSH MONITOR С АВТОБАНОМ И АВТОНАСТРОЙКОЙ MSMTP
# Версия: 9.0
# ============================================================

if [[ $EUID -ne 0 ]]; then
   echo "❌ Ошибка: Запустите от root (sudo)"
   exit 1
fi

# ==================== ЦВЕТА ====================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

print_header() {
    echo ""
    echo -e "${BLUE}========================================${NC}"
    echo -e "${CYAN}  $1${NC}"
    echo -e "${BLUE}========================================${NC}"
    echo ""
}

print_success() { echo -e "${GREEN}✅ $1${NC}"; }
print_error() { echo -e "${RED}❌ $1${NC}"; }
print_info() { echo -e "${YELLOW}ℹ️  $1${NC}"; }
print_question() { echo -e "${CYAN}❓ $1${NC}"; }

# ==================== ФУНКЦИЯ ВВОДА ====================
get_input() {
    local prompt="$1"
    local default="$2"
    local input=""
    
    if [[ -n "$default" ]]; then
        read -p "$prompt [$default]: " input
        input="${input:-$default}"
    else
        read -p "$prompt: " input
    fi
    
    echo "$input"
}

# ==================== ПРОВЕРКА EMAIL ====================
validate_email() {
    local email="$1"
    [[ "$email" =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]]
}

# ==================== ПРОВЕРКА IP ====================
validate_ip() {
    local ip="$1"
    if [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        return 0
    elif [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then
        return 0
    else
        return 1
    fi
}

# ==================== УСТАНОВКА И НАСТРОЙКА MSMTP ====================
setup_msmtp() {
    print_header "📦 НАСТРОЙКА ПОЧТОВОЙ СИСТЕМЫ"
    
    echo -e "${YELLOW}Для отправки уведомлений нужен почтовый клиент.${NC}"
    echo ""
    echo -e "${CYAN}Выберите вариант:${NC}"
    echo "  1) Установить и настроить msmtp (рекомендуется)"
    echo "  2) Использовать уже установленный sendmail/mail"
    echo "  3) Пропустить настройку почты (только логи)"
    read -p "Выберите [1-3]: " mail_choice
    
    case "$mail_choice" in
        1)
            # Установка msmtp
            print_info "Проверка msmtp..."
            if command -v msmtp >/dev/null 2>&1; then
                print_success "msmtp уже установлен"
            else
                print_info "Устанавливаю msmtp..."
                apt update -qq
                apt install -y msmtp msmtp-mta ca-certificates >/dev/null 2>&1
                if command -v msmtp >/dev/null 2>&1; then
                    print_success "msmtp установлен"
                else
                    print_error "Не удалось установить msmtp"
                    return 1
                fi
            fi
            
            echo ""
            print_info "Настройка SMTP"
            echo ""
            
            # Запрашиваем настройки
            SMTP_HOST=$(get_input "🌐 SMTP сервер" "smtp.padonak.su")
            SMTP_PORT=$(get_input "🔌 SMTP порт" "587")
            
            echo ""
            echo -e "${YELLOW}Тип шифрования:${NC}"
            echo "  1) STARTTLS (порт 587) - рекомендуется"
            echo "  2) SSL/TLS (порт 465)"
            echo "  3) Без шифрования (порт 25)"
            read -p "Выберите [1-3]: " tls_choice
            
            case "$tls_choice" in
                1) SMTP_TLS="on"; SMTP_STARTTLS="on"; SMTP_TLS_TEXT="STARTTLS" ;;
                2) SMTP_TLS="on"; SMTP_STARTTLS="off"; SMTP_TLS_TEXT="SSL/TLS" ;;
                *) SMTP_TLS="off"; SMTP_STARTTLS="off"; SMTP_TLS_TEXT="Без шифрования" ;;
            esac
            print_success "Шифрование: $SMTP_TLS_TEXT"
            echo ""
            
            SMTP_USER=$(get_input "👤 SMTP логин" "axtung@padonak.su")
            
            # Пароль без эха
            read -sp "🔑 SMTP пароль: " SMTP_PASS
            echo ""
            if [[ -z "$SMTP_PASS" ]]; then
                print_error "Пароль не может быть пустым!"
                return 1
            fi
            
            SMTP_FROM=$(get_input "📧 Email отправителя" "$SMTP_USER")
            
            # Создаём конфиг
            print_info "Создаю /etc/msmtprc..."
            
            cat > /etc/msmtprc << EOF
# ============================================================
# MSMTP Configuration
# Создан: $(date '+%Y-%m-%d %H:%M:%S')
# ============================================================

defaults
auth           on
tls            $SMTP_TLS
tls_starttls   $SMTP_STARTTLS
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        /var/log/msmtp.log

account        default
host           $SMTP_HOST
port           $SMTP_PORT
from           $SMTP_FROM
user           $SMTP_USER
password       $SMTP_PASS
EOF

            chmod 600 /etc/msmtprc
            chown root:root /etc/msmtprc
            print_success "Конфиг создан: /etc/msmtprc"
            
            # Тест
            echo ""
            print_question "Отправить тестовое письмо для проверки?"
            read -p "(y/n): " -n 1 -r
            echo ""
            if [[ $REPLY =~ ^[Yy]$ ]]; then
                TEST_EMAIL=$(get_input "📧 Email для теста" "$SMTP_FROM")
                
                print_info "Отправка тестового письма на $TEST_EMAIL..."
                if echo -e "Subject: Test MSMTP\n\nТестовое письмо\nСервер: $(hostname -f)\nВремя: $(date)" | msmtp -t "$TEST_EMAIL" 2>/dev/null; then
                    print_success "Письмо отправлено!"
                else
                    print_error "Не удалось отправить"
                    echo ""
                    print_info "Логи msmtp:"
                    tail -10 /var/log/msmtp.log 2>/dev/null || echo "  Логи не найдены"
                    echo ""
                    print_question "Продолжить установку?"
                    read -p "(y/n): " -n 1 -r
                    echo ""
                    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
                        exit 1
                    fi
                fi
            fi
            ;;
        2)
            print_info "Используем существующие почтовые клиенты"
            SMTP_HOST=""
            SMTP_PORT=""
            SMTP_USER=""
            SMTP_PASS=""
            SMTP_FROM="ssh-alert@$(hostname -f)"
            ;;
        *)
            print_info "Настройка почты пропущена"
            SMTP_HOST=""
            SMTP_PORT=""
            SMTP_USER=""
            SMTP_PASS=""
            SMTP_FROM="ssh-alert@$(hostname -f)"
            ;;
    esac
    
    return 0
}

# ==================== ЗАГОЛОВОК ====================
clear
print_header "🔐 SSH MONITOR - ИНТЕРАКТИВНАЯ УСТАНОВКА"

echo -e "${YELLOW}Этот скрипт установит систему мониторинга SSH подключений.${NC}"
echo -e "${YELLOW}Подозрительные IP будут автоматически заблокированы!${NC}"
echo ""

# ==================== 0. НАСТРОЙКА ПОЧТЫ ====================
setup_msmtp

# ==================== 1. ИМЯ СЕРВЕРА ====================
print_header "🏷️  ИМЯ СЕРВЕРА"

CURRENT_HOSTNAME=$(cat /etc/hostname 2>/dev/null || echo "unknown")
CURRENT_FQDN=$(hostname -f 2>/dev/null || echo "unknown")

echo -e "${CYAN}Текущее имя сервера:${NC}"
echo -e "  /etc/hostname: ${GREEN}$CURRENT_HOSTNAME${NC}"
echo -e "  hostname -f:   ${YELLOW}$CURRENT_FQDN${NC}"
echo ""

DEFAULT_NAME="$CURRENT_HOSTNAME"
if [[ "$CURRENT_FQDN" != "localhost" ]] && [[ "$CURRENT_FQDN" != "localhost.localdomain" ]]; then
    DEFAULT_NAME="$CURRENT_FQDN"
fi

SERVER_NAME=$(get_input "🌐 Имя сервера для уведомлений" "$DEFAULT_NAME")
print_success "Имя сервера: $SERVER_NAME"
echo ""

# ==================== 2. EMAIL ====================
print_header "📧 НАСТРОЙКИ ПОЧТЫ"

while true; do
    EMAIL_TO=$(get_input "📧 Ваш email для уведомлений" "admin@padonak.su")
    if validate_email "$EMAIL_TO"; then
        print_success "Email принят: $EMAIL_TO"
        break
    else
        print_error "Неверный формат email. Попробуйте снова."
    fi
done
echo ""

# ==================== 3. РАЗРЕШЕННЫЕ IP ====================
print_header "🛡️ РАЗРЕШЕННЫЕ IP АДРЕСА"

echo -e "${YELLOW}Укажите IP адреса, с которых разрешены подключения.${NC}"
echo -e "${YELLOW}Можно указать отдельные IP или подсети (например, 192.168.1.0/24).${NC}"
echo -e "${YELLOW}Если ничего не ввести, будет добавлен текущий IP сервера.${NC}"
echo ""

CURRENT_IP=$(hostname -I | awk '{print $1}')
if [[ -z "$CURRENT_IP" ]]; then
    CURRENT_IP="127.0.0.1"
fi

ALLOWED_IPS=()
IP_COUNT=0

while true; do
    IP_COUNT=$((IP_COUNT + 1))
    echo -e "${CYAN}────────────────────────────────────────${NC}"
    echo -e "${CYAN}IP #$IP_COUNT:${NC}"
    
    if [[ $IP_COUNT -eq 1 ]]; then
        echo -e "${YELLOW}💡 Рекомендуется добавить ваш текущий IP: $CURRENT_IP${NC}"
    fi
    
    read -p "Введите IP (или Enter для завершения): " ip_input
    
    if [[ -z "$ip_input" ]]; then
        if [[ $IP_COUNT -eq 1 ]]; then
            print_info "Добавляю текущий IP: $CURRENT_IP"
            ALLOWED_IPS+=("$CURRENT_IP")
        else
            break
        fi
    else
        if validate_ip "$ip_input"; then
            ALLOWED_IPS+=("$ip_input")
            print_success "✅ Добавлен IP: $ip_input"
        else
            print_error "❌ Неверный формат IP"
            IP_COUNT=$((IP_COUNT - 1))
        fi
    fi
    echo ""
done

echo ""
print_info "📋 Добавлено разрешенных IP: ${#ALLOWED_IPS[@]}"
for ip in "${ALLOWED_IPS[@]}"; do
    echo -e "  ${GREEN}•${NC} $ip"
done
echo ""

# ==================== 4. НАСТРОЙКИ БАНА ====================
print_header "🔒 НАСТРОЙКИ АВТОБЛОКИРОВКИ"

echo -e "${CYAN}⏱️  Время блокировки:${NC}"
echo "  1) Навсегда"
echo "  2) На 1 час"
echo "  3) На 24 часа (рекомендуется)"
echo "  4) На 7 дней"
read -p "Выберите [1-4]: " ban_time_choice

case "$ban_time_choice" in
    2) BAN_TIME="3600"; BAN_TEXT="1 час" ;;
    3) BAN_TIME="86400"; BAN_TEXT="24 часа" ;;
    4) BAN_TIME="604800"; BAN_TEXT="7 дней" ;;
    *) BAN_TIME="0"; BAN_TEXT="Навсегда" ;;
esac
print_success "Время блокировки: $BAN_TEXT"
echo ""

echo -e "${CYAN}⚡ Действие при подозрительном подключении:${NC}"
echo "  1) Блокировать и отправить уведомление (рекомендуется)"
echo "  2) Только блокировать (без уведомлений)"
echo "  3) Только уведомление (без блокировки)"
read -p "Выберите [1-3]: " action_choice

case "$action_choice" in
    2) AUTO_BLOCK="yes"; NOTIFY_SUSPICIOUS="no"; ACTION_TEXT="Только блокировка" ;;
    3) AUTO_BLOCK="no"; NOTIFY_SUSPICIOUS="yes"; ACTION_TEXT="Только уведомление" ;;
    *) AUTO_BLOCK="yes"; NOTIFY_SUSPICIOUS="yes"; ACTION_TEXT="Блокировка + уведомление" ;;
esac
print_success "Действие: $ACTION_TEXT"
echo ""

# ==================== 5. ПОДТВЕРЖДЕНИЕ ====================
print_header "📋 ПРОВЕРЬТЕ НАСТРОЙКИ"

if [[ -n "$SMTP_HOST" ]]; then
    echo -e "${CYAN}📧 SMTP:${NC} $SMTP_HOST:$SMTP_PORT ($SMTP_TLS_TEXT)"
    echo -e "${CYAN}👤 SMTP пользователь:${NC} $SMTP_USER"
fi
echo -e "${CYAN}🏷️  Имя сервера:${NC} $SERVER_NAME"
echo -e "${CYAN}📧 Email для уведомлений:${NC} $EMAIL_TO"
echo -e "${CYAN}🛡️ Разрешенные IP (${#ALLOWED_IPS[@]} шт.):${NC}"
for ip in "${ALLOWED_IPS[@]}"; do
    echo -e "  ${GREEN}•${NC} $ip"
done
echo -e "${CYAN}🔒 Время блокировки:${NC} $BAN_TEXT"
echo -e "${CYAN}⚡ Действие:${NC} $ACTION_TEXT"
echo ""

read -p "Продолжить установку? (y/n): " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    print_error "Установка отменена"
    exit 1
fi

# ==================== 6. ОСТАНОВКА СТАРОГО СЕРВИСА ====================
print_header "🛑 ОСТАНОВКА СТАРОГО СЕРВИСА"

systemctl stop ssh-monitor 2>/dev/null
systemctl stop ssh-monitor-final 2>/dev/null
systemctl disable ssh-monitor 2>/dev/null
systemctl disable ssh-monitor-final 2>/dev/null
rm -f /etc/systemd/system/ssh-monitor.service
rm -f /etc/systemd/system/ssh-monitor-final.service
rm -f /usr/local/bin/ssh-monitor.sh
rm -f /usr/local/bin/ssh-monitor-final.sh
systemctl daemon-reload
print_success "Старый сервис удален"

# ==================== 7. СОЗДАНИЕ СКРИПТА ====================
print_header "📝 СОЗДАНИЕ СКРИПТА"

ALLOWED_IPS_STR=""
for ip in "${ALLOWED_IPS[@]}"; do
    ALLOWED_IPS_STR+="    \"$ip\"\n"
done

cat > /usr/local/bin/ssh-monitor.sh << SCRIPT_EOF
#!/bin/bash
# ============================================================
# SSH MONITOR С АВТОБАНОМ
# Сервер: $SERVER_NAME
# Установлен: $(date '+%Y-%m-%d %H:%M:%S')
# ============================================================

# ==================== НАСТРОЙКИ ====================
EMAIL_TO="$EMAIL_TO"
SERVER_NAME="$SERVER_NAME"
ALLOWED_IPS=(
$(echo -e "$ALLOWED_IPS_STR")
)
BAN_TIME="$BAN_TIME"
AUTO_BLOCK="$AUTO_BLOCK"
NOTIFY_SUSPICIOUS="$NOTIFY_SUSPICIOUS"

EMAIL_FROM="$SMTP_FROM"
LOG_FILE="/var/log/ssh-monitor.log"
BAN_LOG="/var/log/ssh-ban.log"
STATE_DIR="/var/lib/ssh-monitor"
STATE_FILE="\$STATE_DIR/last_state"
PID_FILE="/var/run/ssh-monitor.pid"

log_message() {
    echo "[\$(date '+%Y-%m-%d %H:%M:%S')] \$1" | tee -a "\$LOG_FILE"
}

log_ban() {
    echo "[\$(date '+%Y-%m-%d %H:%M:%S')] \$1" | tee -a "\$BAN_LOG"
}

send_email() {
    local subject="\$1"
    local body="\$2"
    
    local email_content="From: \$EMAIL_FROM
To: \$EMAIL_TO
Subject: \$subject
Content-Type: text/plain; charset=UTF-8

\$body

---
Server: \$SERVER_NAME
IP: \$(hostname -I | awk '{print \$1}')
Time: \$(date '+%Y-%m-%d %H:%M:%S')
"
    
    log_message "📧 Отправка письма на \$EMAIL_TO"
    
    # Способ 1: msmtp
    if command -v msmtp >/dev/null 2>&1; then
        if echo "\$email_content" | msmtp -t "\$EMAIL_TO" 2>/dev/null; then
            log_message "  ✅ Отправлено через msmtp"
            return 0
        else
            log_message "  ❌ Ошибка msmtp"
        fi
    fi
    
    # Способ 2: sendmail
    if command -v sendmail >/dev/null 2>&1; then
        if echo "\$email_content" | sendmail -t 2>/dev/null; then
            log_message "  ✅ Отправлено через sendmail"
            return 0
        fi
    fi
    
    # Способ 3: mail
    if command -v mail >/dev/null 2>&1; then
        if echo "\$body" | mail -s "\$subject" -a "From: \$EMAIL_FROM" "\$EMAIL_TO" 2>/dev/null; then
            log_message "  ✅ Отправлено через mail"
            return 0
        fi
    fi
    
    log_message "❌ ВСЕ СПОСОБЫ НЕ СРАБОТАЛИ!"
    return 1
}

is_ip_allowed() {
    local ip="\$1"
    if [[ -z "\$ip" ]] || [[ "\$ip" == "unknown" ]]; then
        return 1
    fi
    for allowed in "\${ALLOWED_IPS[@]}"; do
        if [[ "\$ip" == "\$allowed" ]]; then
            return 0
        fi
    done
    return 1
}

get_ip_for_pid() {
    local pid="\$1"
    local ip=""
    
    if command -v ss >/dev/null 2>&1; then
        ip=\$(ss -tnp 2>/dev/null | grep "pid=\$pid" | head -1 | awk '{print \$5}' | cut -d':' -f1)
        if [[ -n "\$ip" ]] && [[ "\$ip" != "0.0.0.0" ]] && [[ "\$ip" != "::" ]] && [[ "\$ip" != "*" ]]; then
            echo "\$ip"
            return 0
        fi
    fi
    
    if command -v netstat >/dev/null 2>&1; then
        ip=\$(netstat -tnp 2>/dev/null | grep "\$pid/sshd" | head -1 | awk '{print \$5}' | cut -d':' -f1)
        if [[ -n "\$ip" ]] && [[ "\$ip" != "0.0.0.0" ]] && [[ "\$ip" != "::" ]] && [[ "\$ip" != "*" ]]; then
            echo "\$ip"
            return 0
        fi
    fi
    
    local tty=\$(ps -o tty= -p "\$pid" 2>/dev/null | tr -d ' ')
    if [[ -n "\$tty" ]] && [[ "\$tty" != "?" ]]; then
        ip=\$(who -u 2>/dev/null | grep "\$tty" | awk '{print \$NF}' | sed 's/[()]//g')
        if [[ -n "\$ip" ]] && [[ "\$ip" != "0.0.0.0" ]] && [[ "\$ip" != "::" ]] && [[ "\$ip" != "*" ]]; then
            echo "\$ip"
            return 0
        fi
    fi
    
    echo "unknown"
}

get_ssh_sessions() {
    ps aux | grep -E 'sshd-session:.*@|sshd:.*@' | grep -v grep | grep -v "listener" | grep -v "accepted" | awk '{print \$2}'
}

block_ip() {
    local ip="\$1"
    
    log_ban "🔒 БЛОКИРОВКА IP: \$ip"
    
    if iptables -L INPUT -n 2>/dev/null | grep -q "\$ip"; then
        log_ban "ℹ️  IP \$ip уже заблокирован"
        return 0
    fi
    
    if command -v iptables >/dev/null 2>&1; then
        if [[ "\$BAN_TIME" -gt 0 ]]; then
            iptables -I INPUT -s "\$ip" -m recent --set --name SSH_BAN 2>/dev/null
            iptables -I INPUT -s "\$ip" -m recent --update --seconds \$BAN_TIME --name SSH_BAN -j DROP 2>/dev/null
            log_ban "✅ IP \$ip заблокирован на \$BAN_TIME секунд (\$((\$BAN_TIME / 3600)) часов)"
        else
            iptables -I INPUT -s "\$ip" -j DROP 2>/dev/null
            log_ban "✅ IP \$ip заблокирован НАВСЕГДА"
        fi
        return 0
    fi
    
    if command -v ufw >/dev/null 2>&1; then
        ufw deny from "\$ip" 2>/dev/null
        log_ban "✅ IP \$ip заблокирован через ufw"
        return 0
    fi
    
    log_ban "❌ НЕ УДАЛОСЬ ЗАБЛОКИРОВАТЬ IP \$ip"
    return 1
}

process_session() {
    local pid="\$1"
    local user=\$(ps -o user= -p "\$pid" 2>/dev/null | tr -d ' ')
    local client_ip=\$(get_ip_for_pid "\$pid")
    local start_time=\$(ps -o lstart= -p "\$pid" 2>/dev/null | tr -d ' ')
    
    log_message "NEW SESSION: PID=\$pid, USER=\$user, IP=\$client_ip"
    
    if [[ -z "\$client_ip" ]] || [[ "\$client_ip" == "unknown" ]]; then
        log_message "FAILED to get IP for PID \$pid"
        return 1
    fi
    
    if is_ip_allowed "\$client_ip"; then
        log_message "✅ ALLOWED IP: \$client_ip"
        return 0
    fi
    
    log_message "🚨 SUSPICIOUS IP: \$client_ip"
    
    if [[ "\$AUTO_BLOCK" == "yes" ]]; then
        block_ip "\$client_ip"
    fi
    
    if [[ "\$NOTIFY_SUSPICIOUS" == "yes" ]]; then
        local ban_text=""
        if [[ "\$BAN_TIME" -gt 0 ]]; then
            ban_text="на \$((\$BAN_TIME / 3600)) часов"
        else
            ban_text="НАВСЕГДА"
        fi
        
        local subject="🚨 SSH БАН: IP \$client_ip заблокирован!"
        local body="🚨 ПОДОЗРИТЕЛЬНОЕ SSH ПОДКЛЮЧЕНИЕ
========================================
СТАТУС: ❌ НЕ РАЗРЕШЕН!
Пользователь: \$user
IP адрес: \$client_ip
Время подключения: \$start_time
Сервер: \$SERVER_NAME
========================================

🔴 IP АДРЕС ЗАБЛОКИРОВАН \$ban_text!

Причина: Подключение с неразрешенного IP

Текущие активные сессии:
\$(who -u 2>/dev/null || echo "Нет активных сессий")

Заблокированные IP:
\$(iptables -L INPUT -n 2>/dev/null | grep -E "DROP|REJECT" | head -10 || echo "Нет блокировок")
========================================"
        send_email "\$subject" "\$body"
    fi
}

show_status() {
    echo "========================================="
    echo "SSH MONITOR WITH AUTO-BAN - STATUS"
    echo "========================================="
    echo ""
    echo "Server: \$SERVER_NAME"
    echo "Email: \$EMAIL_TO"
    echo "Allowed IPs:"
    for ip in "\${ALLOWED_IPS[@]}"; do
        echo "  - \$ip"
    done
    echo ""
    echo "Ban time: \$BAN_TIME seconds (\$((\$BAN_TIME / 3600)) hours)"
    echo "Auto block: \$AUTO_BLOCK"
    echo ""
    echo "Blocked IPs:"
    iptables -L INPUT -n 2>/dev/null | grep -E "DROP|REJECT" | head -20 || echo "  No blocked IPs"
    echo ""
    echo "Log: \$LOG_FILE"
    echo "Ban log: \$BAN_LOG"
    echo "========================================="
}

test_email() {
    echo "Sending test email to \$EMAIL_TO..."
    
    local subject="🧪 Test from SSH Monitor with Auto-Ban"
    local body="TEST EMAIL
========================================
This is a test email from SSH Monitor.

System is working with AUTO-BAN enabled.

Server: \$SERVER_NAME
IP: \$(hostname -I | awk '{print \$1}')
Time: \$(date '+%Y-%m-%d %H:%M:%S')
========================================"
    
    if send_email "\$subject" "\$body"; then
        echo "✅ Test email sent!"
    else
        echo "❌ Failed to send test email"
    fi
}

case "\$1" in
    --status|status)
        show_status
        exit 0
        ;;
    --test|test)
        test_email
        exit 0
        ;;
    --unban|unban)
        if [[ -z "\$2" ]]; then
            echo "Usage: \$0 --unban IP"
            exit 1
        fi
        iptables -D INPUT -s "\$2" -j DROP 2>/dev/null
        iptables -D INPUT -s "\$2" -m recent --update --name SSH_BAN -j DROP 2>/dev/null
        echo "✅ IP \$2 разблокирован"
        exit 0
        ;;
    --help|help|-h)
        echo "Usage: \$0 [OPTION]"
        echo "  --status  - Show status"
        echo "  --test    - Send test email"
        echo "  --unban IP - Unblock IP"
        echo "  --help    - Show this help"
        exit 0
        ;;
esac

mkdir -p "\$(dirname "\$LOG_FILE")" "\$STATE_DIR"
touch "\$LOG_FILE" "\$BAN_LOG"

if [[ -f "\$PID_FILE" ]]; then
    OLD_PID=\$(cat "\$PID_FILE" 2>/dev/null)
    if kill -0 "\$OLD_PID" 2>/dev/null; then
        echo "❌ Script already running (PID: \$OLD_PID)"
        exit 1
    fi
fi
echo \$\$ > "\$PID_FILE"

log_message "========================================="
log_message "🚀 START SSH MONITOR WITH AUTO-BAN"
log_message "Server: \$SERVER_NAME"
log_message "Email: \$EMAIL_TO"
log_message "Allowed IPs: \${ALLOWED_IPS[*]}"
log_message "Ban time: \$BAN_TIME seconds"
log_message "Auto block: \$AUTO_BLOCK"
log_message "========================================="

EXISTING_SESSIONS=\$(get_ssh_sessions)
if [[ -n "\$EXISTING_SESSIONS" ]]; then
    log_message "Found existing sessions: \$(echo "\$EXISTING_SESSIONS" | wc -w)"
fi
echo "\$EXISTING_SESSIONS" > "\$STATE_FILE"
log_message "Initialization complete"

while true; do
    CURRENT_SESSIONS=\$(get_ssh_sessions)
    if [[ -n "\$CURRENT_SESSIONS" ]]; then
        PREVIOUS_SESSIONS=\$(cat "\$STATE_FILE" 2>/dev/null || echo "")
        for pid in \$CURRENT_SESSIONS; do
            if ! echo "\$PREVIOUS_SESSIONS" | grep -q "^\$pid\$"; then
                process_session "\$pid"
            fi
        done
        echo "\$CURRENT_SESSIONS" > "\$STATE_FILE"
    else
        echo "" > "\$STATE_FILE" 2>/dev/null
    fi
    sleep 5
done
SCRIPT_EOF

chmod +x /usr/local/bin/ssh-monitor.sh
print_success "Скрипт создан: /usr/local/bin/ssh-monitor.sh"

# ==================== 8. СОЗДАНИЕ СЕРВИСА ====================
print_header "📝 СОЗДАНИЕ СИСТЕМНОГО СЕРВИСА"

cat > /etc/systemd/system/ssh-monitor.service << 'EOF'
[Unit]
Description=SSH Monitor with Auto-Ban
After=network.target
Wants=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/ssh-monitor.sh
Restart=always
RestartSec=10
User=root

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable ssh-monitor
systemctl restart ssh-monitor

print_success "Сервис создан и запущен"

# ==================== 9. ТЕСТИРОВАНИЕ ====================
print_header "🧪 ТЕСТИРОВАНИЕ"

sleep 2

if systemctl is-active --quiet ssh-monitor; then
    print_success "Сервис работает!"
else
    print_error "Сервис не запущен"
    systemctl status ssh-monitor --no-pager
fi

echo ""
print_question "Отправить тестовое письмо на $EMAIL_TO?"
read -p "(y/n): " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
    /usr/local/bin/ssh-monitor.sh --test
    echo ""
fi

# ==================== 10. ИНФОРМАЦИЯ ====================
print_header "✅ УСТАНОВКА ЗАВЕРШЕНА!"

echo -e "${CYAN}📋 ВАШИ НАСТРОЙКИ:${NC}"
if [[ -n "$SMTP_HOST" ]]; then
    echo -e "  📧 SMTP: ${GREEN}$SMTP_HOST:$SMTP_PORT ($SMTP_TLS_TEXT)${NC}"
    echo -e "  👤 SMTP пользователь: ${GREEN}$SMTP_USER${NC}"
fi
echo -e "  🏷️  Имя сервера: ${GREEN}$SERVER_NAME${NC}"
echo -e "  📧 Email: ${GREEN}$EMAIL_TO${NC}"
echo -e "  🛡️ Разрешенные IP (${#ALLOWED_IPS[@]} шт.):"
for ip in "${ALLOWED_IPS[@]}"; do
    echo -e "     • ${GREEN}$ip${NC}"
done
echo -e "  🔒 Время блокировки: ${GREEN}$BAN_TEXT${NC}"
echo -e "  ⚡ Действие: ${GREEN}$ACTION_TEXT${NC}"
echo ""

echo -e "${CYAN}📝 КОМАНДЫ:${NC}"
echo -e "  ${BLUE}systemctl status ssh-monitor${NC}   - Статус"
echo -e "  ${BLUE}systemctl restart ssh-monitor${NC}  - Перезапуск"
echo -e "  ${BLUE}tail -f /var/log/ssh-monitor.log${NC} - Логи"
echo -e "  ${BLUE}tail -f /var/log/msmtp.log${NC}     - Логи почты"
echo ""
echo -e "  ${BLUE}/usr/local/bin/ssh-monitor.sh --test${NC}    - Тест почты"
echo -e "  ${BLUE}/usr/local/bin/ssh-monitor.sh --status${NC}  - Статус"
echo -e "  ${BLUE}/usr/local/bin/ssh-monitor.sh --unban IP${NC} - Разблокировка"
echo ""

print_success "SSH Monitor успешно установлен!"
echo ""

exit 0
Моя характеристика с детского сада: Хорошо кушает, спит, гуляет! Прошло много лет, ничего не изменилось.
Изображение
Ответить