vm:n8n:04-fail2ban

Вот пошаговая инструкция по настройке fail2ban для защиты от сканирования Папки все создадутся по этому адресу /opt/fail2ban:

Создать файл в папке /opt/ install-fail2ban-complete.sh и вставить в него скрипт

#!/bin/bash

# Полная автоматическая установка и настройка fail2ban для Docker nginx-proxy
# Все файлы будут созданы в /opt/fail2ban/
# Запуск: sudo bash install-fail2ban-complete.sh

set -e

# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
echo_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
echo_error() { echo -e "${RED}[ERROR]${NC} $1"; }

# Проверка прав root
if [[ $EUID -ne 0 ]]; then
   echo_error "Этот скрипт должен запускаться с правами root"
   echo "Использование: sudo bash $0"
   exit 1
fi

echo_info "=== Начинаем установку fail2ban в /opt/fail2ban ==="

# 1. Создание структуры директорий
echo_info "Создаем структуру директорий..."
mkdir -p /opt/fail2ban/{config,logs,scripts}
mkdir -p /opt/fail2ban/config/{filter.d,jail.d,action.d}

# 2. Установка fail2ban и зависимостей
echo_info "Устанавливаем fail2ban..."
apt update
apt install -y fail2ban iptables-persistent

# 3. Создание скрипта парсинга логов Docker
echo_info "Создаем скрипт парсинга логов..."
cat > /opt/fail2ban/scripts/parse-nginx-logs.sh << 'EOF'
#!/bin/bash

# Скрипт парсинга логов nginx-proxy Docker контейнера
LOG_FILE="/opt/fail2ban/logs/nginx-access.log"
CONTAINER_NAME="nginx-proxy"
TEMP_FILE="/tmp/nginx-logs-temp"

# Проверяем, что контейнер запущен
if ! docker ps --format "table {{.Names}}" | grep -q "^${CONTAINER_NAME}$"; then
    echo "$(date): Контейнер $CONTAINER_NAME не найден или не запущен" >> /opt/fail2ban/logs/parser.log
    exit 1
fi

# Получаем последние 2000 строк логов
docker logs "$CONTAINER_NAME" --tail 2000 2>/dev/null > "$TEMP_FILE"

# Фильтруем только nginx.1 записи и убираем префикс
grep 'nginx\.1.*"[A-Z]' "$TEMP_FILE" | \
sed 's/nginx\.1[[:space:]]*|[[:space:]]*//' | \
grep -E '"(GET|POST|PUT|DELETE|HEAD|OPTIONS)' > "$LOG_FILE"

# Устанавливаем права доступа
chmod 644 "$LOG_FILE"

# Логируем успешное выполнение (раз в час)
MINUTE=$(date +%M)
if [ "$MINUTE" = "00" ]; then
    LINES=$(wc -l < "$LOG_FILE" 2>/dev/null || echo "0")
    echo "$(date): Обработано $LINES записей из контейнера $CONTAINER_NAME" >> /opt/fail2ban/logs/parser.log
fi

# Очищаем временный файл
rm -f "$TEMP_FILE"

# Ротация логов (если файл больше 10MB)
if [ -f "$LOG_FILE" ] && [ $(stat -c%s "$LOG_FILE" 2>/dev/null || echo 0) -gt 10485760 ]; then
    mv "$LOG_FILE" "$LOG_FILE.old"
    touch "$LOG_FILE"
    chmod 644 "$LOG_FILE"
fi
EOF

# 4. Создание фильтра для сканирования
echo_info "Создаем фильтры fail2ban..."
cat > /opt/fail2ban/config/filter.d/nginx-scan-block.conf << 'EOF'
# Фильтр для блокировки сканирования nginx
[Definition]

# Блокировка попыток доступа к конфигурационным файлам
failregex = ^.* <HOST> - - .*"GET (/\.env|/\.git|/\.aws|/\.ssh|/config|/backup|wp-config|phpinfo|admin/config|server-status|server-info).*" [0-9]{3}
            ^.* <HOST> - - .*"GET .*\.(php|asp|jsp|cgi|pl|py).*" 40[0-9]
            ^.* <HOST> - - .*"GET.*\.\./.*" [0-9]{3}
            ^.* <HOST> - - .*"GET.*(union|select|insert|update|delete|drop|create|alter).*" [0-9]{3}
            ^.* <HOST> - - .*"GET.*(<script|javascript:|vbscript:|onload|onerror).*" [0-9]{3}
            ^.* <HOST> - - .*"(GET|POST).* .*(\||`|;|<|>|'|\\|\{|\}|\[|\]).*" [0-9]{3}
            ^.* <HOST> - - .*"GET.*/\.(htaccess|htpasswd|passwd|shadow|hosts).*" [0-9]{3}
            ^.* <HOST> - - .*"GET.*/(etc/|var/|bin/|usr/bin/|tmp/|proc/).*" [0-9]{3}

ignoreregex = ^.* <HOST> - - .*"GET / HTTP.*" 200
              ^.* <HOST> - - .*"GET /favicon\.ico HTTP.*"
              ^.* <HOST> - - .*"GET /robots\.txt HTTP.*"
EOF

# 5. Создание фильтра для DoS атак
cat > /opt/fail2ban/config/filter.d/nginx-dos-block.conf << 'EOF'
# Фильтр для блокировки DoS атак
[Definition]

# Слишком много запросов с одного IP
failregex = ^.* <HOST> - - .*"(GET|POST).*" [0-9]{3}

# Игнорируем изображения и статические файлы
ignoreregex = ^.* <HOST> - - .*"GET .+\.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg).*" [0-9]{3}
EOF

# 6. Создание фильтра для 404 флуда
cat > /opt/fail2ban/config/filter.d/nginx-404-flood.conf << 'EOF'
# Фильтр для блокировки 404 флуда
[Definition]

# Много 404 ошибок подряд
failregex = ^.* <HOST> - - .*"(GET|POST).*" 404

ignoreregex = ^.* <HOST> - - .*"GET /(favicon\.ico|robots\.txt|sitemap\.xml).*" 404
EOF

# 7. Создание jail конфигурации
cat > /opt/fail2ban/config/jail.d/nginx-protection.conf << 'EOF'
# Jail конфигурация для nginx защиты
[DEFAULT]
# Время бана в секундах (1 час = 3600)
bantime = 3600
# Время поиска нарушений (5 минут = 300)
findtime = 300
# Игнорировать локальные IP
ignoreip = 127.0.0.1/8 ::1 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8

[nginx-scan-block]
enabled = true
port = http,https
filter = nginx-scan-block
logpath = /opt/fail2ban/logs/nginx-access.log
maxretry = 3
bantime = 7200
findtime = 300
action = iptables-multiport[name=nginx-scan, port="http,https", protocol=tcp]

[nginx-dos-block]
enabled = true
port = http,https  
filter = nginx-dos-block
logpath = /opt/fail2ban/logs/nginx-access.log
maxretry = 50
bantime = 600
findtime = 60
action = iptables-multiport[name=nginx-dos, port="http,https", protocol=tcp]

[nginx-404-flood]
enabled = true
port = http,https
filter = nginx-404-flood
logpath = /opt/fail2ban/logs/nginx-access.log
maxretry = 10
bantime = 3600
findtime = 600
action = iptables-multiport[name=nginx-404, port="http,https", protocol=tcp]
EOF

# 8. Создание скрипта управления
echo_info "Создаем скрипт управления..."
cat > /opt/fail2ban/scripts/manage-fail2ban.sh << 'EOF'
#!/bin/bash

# Скрипт управления fail2ban

case "$1" in
    status)
        echo "=== Статус fail2ban ==="
        fail2ban-client status
        echo ""
        echo "=== Детальная информация ==="
        for jail in nginx-scan-block nginx-dos-block nginx-404-flood; do
            if fail2ban-client status | grep -q "$jail"; then
                echo "--- $jail ---"
                fail2ban-client status $jail 2>/dev/null || echo "Jail $jail недоступен"
                echo ""
            fi
        done
        ;;
    
    logs)
        echo "=== Последние 50 записей nginx логов ==="
        tail -50 /opt/fail2ban/logs/nginx-access.log 2>/dev/null || echo "Лог файл не найден"
        ;;
    
    banned)
        echo "=== Заблокированные IP ==="
        iptables -L -n | grep f2b || echo "Нет заблокированных IP"
        ;;
    
    unban)
        if [ -z "$2" ]; then
            echo "Использование: $0 unban <IP>"
            exit 1
        fi
        echo "Разблокируем IP: $2"
        fail2ban-client unban $2
        ;;
    
    ban)
        if [ -z "$2" ] || [ -z "$3" ]; then
            echo "Использование: $0 ban <jail> <IP>"
            echo "Пример: $0 ban nginx-scan-block 1.2.3.4"
            exit 1
        fi
        echo "Блокируем IP $3 в jail $2"
        fail2ban-client set $2 banip $3
        ;;
    
    reload)
        echo "Перезагружаем fail2ban..."
        systemctl restart fail2ban
        sleep 3
        fail2ban-client status
        ;;
    
    parse)
        echo "Запускаем парсинг логов..."
        /opt/fail2ban/scripts/parse-nginx-logs.sh
        LINES=$(wc -l < /opt/fail2ban/logs/nginx-access.log 2>/dev/null || echo "0")
        echo "Парсинг завершен. Строк в логе: $LINES"
        ;;
    
    test)
        echo "=== Тестирование конфигурации ==="
        fail2ban-client -t && echo "Конфигурация корректна!" || echo "Ошибка в конфигурации!"
        ;;
        
    block-suspicious)
        echo "Блокируем подозрительные IP из ваших логов..."
        SUSPICIOUS_IPS=("109.202.99.36" "213.152.176.252" "185.177.72.10" "193.46.255.46" "103.246.146.203")
        for ip in "${SUSPICIOUS_IPS[@]}"; do
            echo "Блокируем $ip"
            iptables -I INPUT -s $ip -j DROP 2>/dev/null || echo "IP $ip уже заблокирован или ошибка"
        done
        iptables-save > /etc/iptables/rules.v4 2>/dev/null || echo "Не удалось сохранить правила iptables"
        echo "Заблокировано IP адресов: ${#SUSPICIOUS_IPS[@]}"
        ;;
        
    *)
        echo "Использование: $0 {status|logs|banned|unban|ban|reload|parse|test|block-suspicious}"
        echo ""
        echo "Команды:"
        echo "  status            - Показать статус всех jail"
        echo "  logs              - Показать последние логи nginx"
        echo "  banned            - Показать заблокированные IP"
        echo "  unban <IP>        - Разблокировать IP"
        echo "  ban <jail> <IP>   - Заблокировать IP в определенном jail"
        echo "  reload            - Перезагрузить fail2ban"
        echo "  parse             - Запустить парсинг логов вручную"
        echo "  test              - Проверить конфигурацию"
        echo "  block-suspicious  - Заблокировать подозрительные IP из логов"
        exit 1
        ;;
esac
EOF

# 9. Установка прав доступа
echo_info "Устанавливаем права доступа..."
chmod +x /opt/fail2ban/scripts/*.sh
chmod 644 /opt/fail2ban/config/filter.d/*
chmod 644 /opt/fail2ban/config/jail.d/*
chown -R root:root /opt/fail2ban/

# 10. Создание символических ссылок
echo_info "Создаем символические ссылки..."
ln -sf /opt/fail2ban/config/filter.d/* /etc/fail2ban/filter.d/
ln -sf /opt/fail2ban/config/jail.d/* /etc/fail2ban/jail.d/

# 11. Создание cron задачи
echo_info "Настраиваем cron для парсинга логов..."
(crontab -l 2>/dev/null; echo "*/2 * * * * /opt/fail2ban/scripts/parse-nginx-logs.sh") | crontab -

# 12. Первоначальный парсинг логов
echo_info "Запускаем первоначальный парсинг логов..."
/opt/fail2ban/scripts/parse-nginx-logs.sh || echo_warn "Не удалось запустить парсинг (возможно контейнер nginx-proxy не запущен)"

# 13. Перезапуск fail2ban
echo_info "Перезапускаем и включаем fail2ban..."
systemctl restart fail2ban
systemctl enable fail2ban

# 14. Ожидание запуска
sleep 5

# 15. Проверка статуса
echo_info "Проверяем статус fail2ban..."
fail2ban-client status || echo_warn "fail2ban запущен, но возможны проблемы с jail"

# 16. Создание алиаса для удобства
echo_info "Создаем алиас для управления..."
echo 'alias f2b="/opt/fail2ban/scripts/manage-fail2ban.sh"' >> /root/.bashrc

# 17. Блокировка подозрительных IP из логов
echo_info "Блокируем подозрительные IP из ваших логов..."
SUSPICIOUS_IPS=("109.202.99.36" "213.152.176.252" "185.177.72.10" "193.46.255.46" "103.246.146.203")
for ip in "${SUSPICIOUS_IPS[@]}"; do
    echo "Блокируем $ip"
    iptables -I INPUT -s $ip -j DROP 2>/dev/null || echo_warn "IP $ip уже заблокирован или ошибка"
done

# Сохранение правил iptables
iptables-save > /etc/iptables/rules.v4 2>/dev/null || echo_warn "Не удалось сохранить правила iptables"

echo ""
echo_info "=== УСТАНОВКА ЗАВЕРШЕНА УСПЕШНО! ==="
echo ""
echo "📁 Структура файлов:"
echo "   /opt/fail2ban/scripts/          - Скрипты управления"
echo "   /opt/fail2ban/config/           - Конфигурации"
echo "   /opt/fail2ban/logs/             - Логи"
echo ""
echo "🚀 Полезные команды:"
echo "   /opt/fail2ban/scripts/manage-fail2ban.sh status     - Статус"
echo "   /opt/fail2ban/scripts/manage-fail2ban.sh logs       - Просмотр логов"
echo "   /opt/fail2ban/scripts/manage-fail2ban.sh banned     - Заблокированные IP"
echo "   f2b status                                          - Алиас (после перелогина)"
echo ""
echo "🛡️  Защита активна для:"
echo "   - Сканирования конфигурационных файлов (.env, .git, wp-config, etc)"
echo "   - DoS атак (более 50 запросов в минуту)"  
echo "   - 404 флуда (более 10 ошибок 404 за 10 минут)"
echo ""
echo "⚠️  Заблокированы подозрительные IP из ваших логов: ${#SUSPICIOUS_IPS[@]} адресов"
echo ""
echo "Для проверки статуса выполните: /opt/fail2ban/scripts/manage-fail2ban.sh status"

Далее запустить скрипт:

cd /opt/
sudo bash install-fail2ban-complete.sh

Проверить статус

/opt/fail2ban/scripts/manage-fail2ban.sh status
  • vm/n8n/04-fail2ban.txt
  • Последнее изменение: 2025/08/31 00:18
  • admin