Данная инструкция описывает процесс установки и настройки Fail2ban для защиты Nginx Proxy Manager от:
Рекомендуется: Используйте автоматический скрипт установки для быстрой настройки всей системы за один шаг.
nano install-fail2ban.sh
Скопируйте следующий код в файл:
#!/bin/bash ################################################################################ # Скрипт автоматической установки и настройки Fail2ban для Nginx Proxy Manager # Версия: 1.0 # Дата: 2025-11-30 ################################################################################ set -e # Остановка при ошибке # Цвета для вывода RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Функция вывода сообщений log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # Проверка прав root if [[ $EUID -ne 0 ]]; then log_error "Этот скрипт должен быть запущен с правами root" exit 1 fi log_info "Начало установки и настройки Fail2ban для Nginx Proxy Manager" echo "" ################################################################################ # НАСТРОЙКИ - ИЗМЕНИТЕ ПОД СВОИ НУЖДЫ ################################################################################ # Путь к логам Nginx Proxy Manager NPM_LOG_DIR="/opt/nginxpm/data/logs" # Имя контейнера Nginx Proxy Manager NPM_CONTAINER_NAME="nginxpm" # Директории Fail2ban FAIL2BAN_BASE="/opt/fail2ban" FAIL2BAN_SCRIPTS="${FAIL2BAN_BASE}/scripts" FAIL2BAN_LOGS="${FAIL2BAN_BASE}/logs" FAIL2BAN_CONFIG="${FAIL2BAN_BASE}/config" FAIL2BAN_JAIL_D="${FAIL2BAN_CONFIG}/jail.d" FAIL2BAN_FILTER_D="${FAIL2BAN_CONFIG}/filter.d" # Файл лога для fail2ban NGINX_ACCESS_LOG="${FAIL2BAN_LOGS}/nginx-access.log" # Игнорируемые IP (локальные сети) IGNORE_IP="127.0.0.1/8 ::1 192.168.0.0/24 172.16.0.0/12 10.0.0.0/8" ################################################################################ # Шаг 1: Проверка существования Nginx Proxy Manager ################################################################################ log_info "Проверка наличия контейнера Nginx Proxy Manager..." if ! docker ps --format "{{.Names}}" | grep -q "^${NPM_CONTAINER_NAME}$"; then log_error "Контейнер ${NPM_CONTAINER_NAME} не найден или не запущен" log_error "Убедитесь что Nginx Proxy Manager установлен и запущен" exit 1 fi if [ ! -d "$NPM_LOG_DIR" ]; then log_error "Директория логов ${NPM_LOG_DIR} не найдена" exit 1 fi log_info "Контейнер ${NPM_CONTAINER_NAME} найден и работает" echo "" ################################################################################ # Шаг 2: Установка Fail2ban ################################################################################ log_info "Установка Fail2ban..." apt update -qq apt install -y fail2ban >/dev/null 2>&1 log_info "Fail2ban успешно установлен" echo "" ################################################################################ # Шаг 3: Создание структуры каталогов ################################################################################ log_info "Создание структуры каталогов..." mkdir -p "${FAIL2BAN_SCRIPTS}" mkdir -p "${FAIL2BAN_LOGS}" mkdir -p "${FAIL2BAN_JAIL_D}" mkdir -p "${FAIL2BAN_FILTER_D}" log_info "Структура каталогов создана" echo "" ################################################################################ # Шаг 4: Создание скрипта парсера логов ################################################################################ log_info "Создание скрипта парсера логов..." cat > "${FAIL2BAN_SCRIPTS}/parse-nginx-logs.sh" << 'PARSER_EOF' #!/bin/bash # Скрипт парсинга логов nginx-proxy-manager для fail2ban LOG_DIR="/opt/nginxpm/data/logs" LOG_FILE="/opt/fail2ban/logs/nginx-access.log" CONTAINER_NAME="nginxpm" PARSER_LOG="/opt/fail2ban/logs/parser.log" mkdir -p "$(dirname "$LOG_FILE")" "$(dirname "$PARSER_LOG")" if ! docker ps --format "table {{.Names}}" | grep -q "^${CONTAINER_NAME}$"; then echo "$(date): Контейнер $CONTAINER_NAME не найден" >> "$PARSER_LOG" exit 1 fi if [ ! -d "$LOG_DIR" ]; then echo "$(date): Директория $LOG_DIR не найдена" >> "$PARSER_LOG" exit 1 fi > "$LOG_FILE" processed_files=0 total_lines=0 for logfile in "$LOG_DIR"/proxy-host-*_access.log; do if [ -f "$logfile" ]; then lines_from_file=$(tail -n 2000 "$logfile" | wc -l) tail -n 2000 "$logfile" >> "$LOG_FILE" processed_files=$((processed_files + 1)) total_lines=$((total_lines + lines_from_file)) echo "$(date): Обработан: $(basename "$logfile") - $lines_from_file строк" >> "$PARSER_LOG" fi done if [ $processed_files -eq 0 ]; then echo "$(date): Файлы логов не найдены" >> "$PARSER_LOG" touch "$LOG_FILE" fi chmod 644 "$LOG_FILE" MINUTE=$(date +%M) if [ "$MINUTE" = "00" ]; then final_lines=$(wc -l < "$LOG_FILE" 2>/dev/null || echo "0") echo "$(date): Обработано $processed_files файлов, $final_lines записей" >> "$PARSER_LOG" fi if [ -f "$PARSER_LOG" ] && [ $(stat -c%s "$PARSER_LOG" 2>/dev/null || echo 0) -gt 5242880 ]; then mv "$PARSER_LOG" "$PARSER_LOG.old" touch "$PARSER_LOG" chmod 644 "$PARSER_LOG" fi 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" echo "$(date): Ротация лог-файла" >> "$PARSER_LOG" fi exit 0 PARSER_EOF chmod +x "${FAIL2BAN_SCRIPTS}/parse-nginx-logs.sh" log_info "Скрипт парсера создан" echo "" ################################################################################ # Шаг 5: Первый запуск парсера ################################################################################ log_info "Первый запуск парсера..." "${FAIL2BAN_SCRIPTS}/parse-nginx-logs.sh" if [ -f "$NGINX_ACCESS_LOG" ]; then log_info "Лог-файл создан: ${NGINX_ACCESS_LOG}" log_info "Количество строк: $(wc -l < ${NGINX_ACCESS_LOG})" else log_error "Не удалось создать лог-файл" exit 1 fi echo "" ################################################################################ # Шаг 6: Создание фильтров Fail2ban ################################################################################ log_info "Создание фильтров Fail2ban..." cat > "${FAIL2BAN_FILTER_D}/nginx-scan-block.conf" << 'FILTER_SCAN_EOF' [Definition] failregex = ^\[.*\] - \d+ \d+ - GET https? .* ".*(/\.env|/\.git|/\.aws|/\.ssh|/config|/backup|wp-config|phpinfo|admin/config|server-status|server-info).*" \[Client <HOST>\] ^\[.*\] - 40\d \d+ - GET https? .* ".*\.(php|asp|jsp|cgi|pl|py).*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - GET https? .* ".*\.\.\/.*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - GET https? .* ".*(union|select|insert|update|delete|drop|create|alter).*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - (GET|POST) https? .* ".*(<script|javascript:|vbscript:|onload|onerror).*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - (GET|POST) https? .* ".*(\||`|;|<|>|\\|\{|\}|\[|\]).*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - GET https? .* ".*/(etc/|var/|bin/|usr/bin/|tmp/|proc/).*" \[Client <HOST>\] ignoreregex = FILTER_SCAN_EOF cat > "${FAIL2BAN_FILTER_D}/nginx-404-flood.conf" << 'FILTER_404_EOF' [Definition] failregex = ^\[.*\] - 404 \d+ - (GET|POST|HEAD) https? .* ".*" \[Client <HOST>\] ignoreregex = FILTER_404_EOF cat > "${FAIL2BAN_FILTER_D}/nginx-dos-block.conf" << 'FILTER_DOS_EOF' [Definition] failregex = ^\[.*\] - \d+ \d+ - (GET|POST|HEAD) https? .* ".*" \[Client <HOST>\] ignoreregex = ^\[.*\] - \d+ \d+ - (GET|POST) https? .* ".*\.(css|js|jpg|jpeg|png|gif|ico|woff|woff2|ttf|svg).*" \[Client <HOST>\] FILTER_DOS_EOF ln -sf "${FAIL2BAN_FILTER_D}/nginx-scan-block.conf" /etc/fail2ban/filter.d/nginx-scan-block.conf ln -sf "${FAIL2BAN_FILTER_D}/nginx-404-flood.conf" /etc/fail2ban/filter.d/nginx-404-flood.conf ln -sf "${FAIL2BAN_FILTER_D}/nginx-dos-block.conf" /etc/fail2ban/filter.d/nginx-dos-block.conf log_info "Фильтры созданы" echo "" ################################################################################ # Шаг 7: Создание конфигурации jail ################################################################################ log_info "Создание конфигурации jail..." cat > "${FAIL2BAN_JAIL_D}/nginx-protection.conf" << JAIL_EOF [DEFAULT] bantime = 3600 findtime = 300 ignoreip = ${IGNORE_IP} [nginx-scan-block] enabled = true port = http,https filter = nginx-scan-block logpath = ${NGINX_ACCESS_LOG} backend = polling 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 = ${NGINX_ACCESS_LOG} backend = polling 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 = ${NGINX_ACCESS_LOG} backend = polling maxretry = 10 bantime = 3600 findtime = 600 action = iptables-multiport[name=nginx-404, port="http,https", protocol=tcp] JAIL_EOF ln -sf "${FAIL2BAN_JAIL_D}/nginx-protection.conf" /etc/fail2ban/jail.d/nginx-protection.conf log_info "Конфигурация jail создана" echo "" ################################################################################ # Шаг 8: Тестирование ################################################################################ log_info "Тестирование конфигурации..." if fail2ban-client -t; then log_info "Конфигурация корректна" else log_error "Ошибка в конфигурации" exit 1 fi echo "" log_info "Тестирование фильтров..." fail2ban-regex "${NGINX_ACCESS_LOG}" "${FAIL2BAN_FILTER_D}/nginx-scan-block.conf" | grep -E "Failregex:|matched" fail2ban-regex "${NGINX_ACCESS_LOG}" "${FAIL2BAN_FILTER_D}/nginx-404-flood.conf" | grep -E "Failregex:|matched" fail2ban-regex "${NGINX_ACCESS_LOG}" "${FAIL2BAN_FILTER_D}/nginx-dos-block.conf" | grep -E "Failregex:|matched" echo "" ################################################################################ # Шаг 9: Добавление в cron ################################################################################ log_info "Добавление в cron..." CRON_ENTRY="*/2 * * * * ${FAIL2BAN_SCRIPTS}/parse-nginx-logs.sh" if crontab -l 2>/dev/null | grep -q "parse-nginx-logs.sh"; then log_warn "Уже добавлено в cron" else (crontab -l 2>/dev/null; echo "$CRON_ENTRY") | crontab - log_info "Добавлено в cron" fi echo "" ################################################################################ # Шаг 10: Запуск ################################################################################ log_info "Запуск Fail2ban..." systemctl enable fail2ban >/dev/null 2>&1 systemctl restart fail2ban sleep 5 if systemctl is-active --quiet fail2ban; then log_info "Fail2ban успешно запущен" else log_error "Не удалось запустить Fail2ban" exit 1 fi echo "" ################################################################################ # Проверка ################################################################################ log_info "Проверка jail..." echo "" fail2ban-client status echo "" fail2ban-client status nginx-scan-block echo "" fail2ban-client status nginx-404-flood echo "" fail2ban-client status nginx-dos-block echo "" ################################################################################ # Завершение ################################################################################ log_info "==========================================" log_info "Установка завершена успешно!" log_info "==========================================" echo "" echo "Создано:" echo " - Парсер: ${FAIL2BAN_SCRIPTS}/parse-nginx-logs.sh" echo " - Логи: ${NGINX_ACCESS_LOG}" echo " - Фильтры: ${FAIL2BAN_FILTER_D}/" echo " - Jail: ${FAIL2BAN_JAIL_D}/nginx-protection.conf" echo "" echo "Защита:" echo " ✅ nginx-scan-block (3 попытки, бан 2 часа)" echo " ✅ nginx-404-flood (10 попыток, бан 1 час)" echo " ✅ nginx-dos-block (50/мин, бан 10 минут)" echo " ✅ sshd" echo "" echo "Команды:" echo " fail2ban-client status" echo " fail2ban-client status nginx-scan-block" echo " iptables -L f2b-nginx-scan -n -v" echo " tail -f /var/log/fail2ban.log" echo " fail2ban-client unban IP" echo "" cat > "${FAIL2BAN_BASE}/README.md" << 'README_EOF' # Fail2ban для Nginx Proxy Manager ## Управление ### Проверка статуса ```bash fail2ban-client status fail2ban-client status nginx-scan-block ``` ### Разбан IP ```bash fail2ban-client unban 1.2.3.4 fail2ban-client set nginx-scan-block unbanip 1.2.3.4 ``` ### Ручной бан ```bash fail2ban-client set nginx-scan-block banip 1.2.3.4 ``` ### Перезапуск ```bash systemctl restart fail2ban ``` ### Просмотр логов ```bash tail -f /var/log/fail2ban.log tail -f /opt/fail2ban/logs/parser.log ``` ## Настройка Файл: `/opt/fail2ban/config/jail.d/nginx-protection.conf` - maxretry - попытки до бана - findtime - окно поиска (секунды) - bantime - время бана (секунды) - ignoreip - исключения После изменений: ```bash systemctl restart fail2ban ``` ## Мониторинг ### Забаненные IP ```bash iptables -L f2b-nginx-scan -n -v iptables -L f2b-nginx-404 -n -v iptables -L f2b-nginx-dos -n -v ``` ### Статистика ```bash for jail in nginx-scan-block nginx-404-flood nginx-dos-block; do echo "=== $jail ===" fail2ban-client status $jail echo "" done ``` README_EOF log_info "Установка завершена! Сервер защищен 🛡️"
Перед запуском вы можете изменить следующие параметры в начале скрипта:
NPM_LOG_DIR - путь к логам Nginx Proxy ManagerNPM_CONTAINER_NAME - имя контейнера NPMIGNORE_IP - список игнорируемых IP адресовchmod +x install-fail2ban.sh ./install-fail2ban.sh
Скрипт автоматически выполнит все необходимые действия:
После успешного выполнения скрипта вы увидите:
========================================== Установка и настройка завершена успешно! ========================================== Защита: ✅ nginx-scan-block (3 попытки, бан 2 часа) ✅ nginx-404-flood (10 попыток, бан 1 час) ✅ nginx-dos-block (50/мин, бан 10 минут) ✅ sshd
Если вы предпочитаете ручную установку с полным контролем каждого шага, следуйте инструкциям ниже.
apt update apt install fail2ban -y
mkdir -p /opt/fail2ban/{scripts,logs,config/{jail.d,filter.d}}
nano /opt/fail2ban/scripts/parse-nginx-logs.sh
Содержимое файла указано в автоматическом скрипте выше (раздел PARSER_EOF).
Установка прав:
chmod +x /opt/fail2ban/scripts/parse-nginx-logs.sh
Первый запуск:
/opt/fail2ban/scripts/parse-nginx-logs.sh ls -lh /opt/fail2ban/logs/nginx-access.log
Добавление в cron:
(crontab -l 2>/dev/null; echo "*/2 * * * * /opt/fail2ban/scripts/parse-nginx-logs.sh") | crontab - crontab -l
# Фильтр сканирования cat > /opt/fail2ban/config/filter.d/nginx-scan-block.conf << 'EOF' [Definition] failregex = ^\[.*\] - \d+ \d+ - GET https? .* ".*(/\.env|/\.git|/\.aws|/\.ssh|/config|/backup|wp-config|phpinfo|admin/config|server-status|server-info).*" \[Client <HOST>\] ^\[.*\] - 40\d \d+ - GET https? .* ".*\.(php|asp|jsp|cgi|pl|py).*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - GET https? .* ".*\.\.\/.*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - GET https? .* ".*(union|select|insert|update|delete|drop|create|alter).*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - (GET|POST) https? .* ".*(<script|javascript:|vbscript:|onload|onerror).*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - (GET|POST) https? .* ".*(\||`|;|<|>|\\|\{|\}|\[|\]).*" \[Client <HOST>\] ^\[.*\] - \d+ \d+ - GET https? .* ".*/(etc/|var/|bin/|usr/bin/|tmp/|proc/).*" \[Client <HOST>\] ignoreregex = EOF # Фильтр 404 cat > /opt/fail2ban/config/filter.d/nginx-404-flood.conf << 'EOF' [Definition] failregex = ^\[.*\] - 404 \d+ - (GET|POST|HEAD) https? .* ".*" \[Client <HOST>\] ignoreregex = EOF # Фильтр DoS cat > /opt/fail2ban/config/filter.d/nginx-dos-block.conf << 'EOF' [Definition] failregex = ^\[.*\] - \d+ \d+ - (GET|POST|HEAD) https? .* ".*" \[Client <HOST>\] ignoreregex = ^\[.*\] - \d+ \d+ - (GET|POST) https? .* ".*\.(css|js|jpg|jpeg|png|gif|ico|woff|woff2|ttf|svg).*" \[Client <HOST>\] EOF # Символические ссылки ln -sf /opt/fail2ban/config/filter.d/nginx-scan-block.conf /etc/fail2ban/filter.d/ ln -sf /opt/fail2ban/config/filter.d/nginx-404-flood.conf /etc/fail2ban/filter.d/ ln -sf /opt/fail2ban/config/filter.d/nginx-dos-block.conf /etc/fail2ban/filter.d/
ВАЖНО: Замените IP адреса в параметре ignoreip на свои.
cat > /opt/fail2ban/config/jail.d/nginx-protection.conf << 'EOF' [DEFAULT] bantime = 3600 findtime = 300 ignoreip = 127.0.0.1/8 ::1 192.168.0.0/24 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 backend = polling 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 backend = polling 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 backend = polling maxretry = 10 bantime = 3600 findtime = 600 action = iptables-multiport[name=nginx-404, port="http,https", protocol=tcp] EOF ln -sf /opt/fail2ban/config/jail.d/nginx-protection.conf /etc/fail2ban/jail.d/
# Тест конфигурации fail2ban-client -t # Тест фильтров fail2ban-regex /opt/fail2ban/logs/nginx-access.log /opt/fail2ban/config/filter.d/nginx-scan-block.conf # Запуск systemctl enable fail2ban systemctl start fail2ban systemctl status fail2ban
# Статус jail fail2ban-client status fail2ban-client status nginx-scan-block # Правила iptables iptables -L -n | grep nginx iptables -L f2b-nginx-scan -n -v
fail2ban-client status fail2ban-client status nginx-scan-block
fail2ban-client unban 1.2.3.4
fail2ban-client set nginx-scan-block unbanip 1.2.3.4
fail2ban-client set nginx-scan-block banip 1.2.3.4
tail -f /var/log/fail2ban.log tail -f /opt/fail2ban/logs/parser.log tail -100 /var/log/fail2ban.log | grep -E "Ban|Unban"
| Параметр | Описание | Значение |
|---|---|---|
| maxretry | Попытки до бана | 3-10 для scan, 50 для DoS |
| findtime | Окно поиска (секунды) | 300 (5 минут) |
| bantime | Время бана (секунды) | 3600-7200 (1-2 часа) |
Файл: /opt/fail2ban/config/jail.d/nginx-protection.conf
После изменений:
systemctl restart fail2ban
journalctl -xeu fail2ban fail2ban-client -d
fail2ban-client status nginx-scan-block
Должно быть: File list: /opt/fail2ban/logs/nginx-access.log
Если Journal matches - добавьте backend = polling в jail.
fail2ban-regex /opt/fail2ban/logs/nginx-access.log /opt/fail2ban/config/filter.d/nginx-scan-block.conf --print-all-matched head -3 /opt/fail2ban/logs/nginx-access.log
bash -x /opt/fail2ban/scripts/parse-nginx-logs.sh cat /opt/fail2ban/logs/parser.log ls -la /opt/nginxpm/data/logs/ docker ps | grep nginxpm
tar -czf fail2ban-backup-$(date +%Y%m%d).tar.gz \ /opt/fail2ban/config/ \ /opt/fail2ban/scripts/
systemctl stop fail2ban systemctl disable fail2ban apt remove --purge fail2ban -y rm -rf /opt/fail2ban rm -f /etc/fail2ban/jail.d/nginx-protection.conf rm -f /etc/fail2ban/filter.d/nginx-*.conf crontab -e # Удалить строку с parse-nginx-logs.sh iptables -F
Автор: Nick
Дата создания: 2025-11-30
Последнее обновление: 2025-11-30