Хосты: webserver.local, u1.webserver.local, u2.webserver.local. Требования itsec.
Требования
- Basic Auth на прокси, логины и пароли внешних клиентов в
.htpasswd. - Запрос уходит на frontend только после успешной авторизации.
- 5 неудачных попыток с одного IP за 5 минут: IP блокируется.
- Блокировка только по IP, учётная запись клиента не блокируется.
1. Файл паролей
# htpasswd: httpd-tools (RHEL/RedOS) или apache2-utils (Astra)
htpasswd -c -B /etc/nginx/.htpasswd client1
htpasswd -B /etc/nginx/.htpasswd client2
chown root:nginx /etc/nginx/.htpasswd # на Astra группа www-data
chmod 640 /etc/nginx/.htpasswd
2. Конфиг NGINX
/etc/nginx/conf.d/webserver.local.conf
server {
listen 443 ssl;
server_name webserver.local u1.webserver.local u2.webserver.local;
access_log /var/log/nginx/webserver.local.access.log;
error_log /var/log/nginx/webserver.local.error.log error;
auth_basic "Restricted area";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://frontend_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Authorization "";
}
}
auth_basic стоит на уровне server, поэтому действует на все три имени.
Если перед wproxysrv1 есть балансировщик, в error.log будет его IP, а не клиентский, и fail2ban забанит не того. Тогда нужен
set_real_ip_from <IP>; real_ip_header X-Forwarded-For;(модульngx_http_realip_module).
3. Фильтр fail2ban
/etc/fail2ban/filter.d/nginx-basic-auth.conf
[Definition]
failregex = ^\s*\[error\] \d+#\d+: \*\d+ user "[^"]*":? (?:password mismatch|was not found in "[^"]*"), client: <HOST>,
ignoreregex =
Секция
[Definition]обязательна, без неё fail2ban ругается на синтаксис. Сообщениеno user/password was providedв фильтр не входит: оно пишется при каждом открытии окна ввода и не является неверной попыткой.
4. Jail
/etc/fail2ban/jail.d/nginx-basic-auth.local
[nginx-basic-auth]
enabled = true
filter = nginx-basic-auth
logpath = /var/log/nginx/webserver.local.error.log
port = http,https
maxretry = 5
findtime = 300
bantime = 3600
# RedOS/RHEL: banaction = firewallcmd-ipset
# Astra: banaction = iptables-multiport
Время в секундах: fail2ban 0.9.x не понимает 5m и 1h. Bantime в требованиях не указан, 1 час взят по умолчанию, нужно уточнить у itsec. Свой IP можно защитить через ignoreip.
5. Применение
nginx -t && systemctl reload nginx
systemctl enable --now fail2ban && systemctl restart fail2ban
6. Проверка
# регулярка на реальном логе
fail2ban-regex /var/log/nginx/webserver.local.error.log /etc/fail2ban/filter.d/nginx-basic-auth.conf
# тест: 6 неверных попыток (с тестового хоста)
for i in {1..6}; do curl -k -s -o /dev/null -w "%{http_code}\n" -u bad:bad https://u1.webserver.local/; done
# статус: Currently failed / Total failed / Banned IP list
fail2ban-client status nginx-basic-auth
# события Found / Ban / Unban
tail -f /var/log/fail2ban.log
# бан в файрволе
ipset list | grep -A5 f2b-nginx-basic-auth # firewalld + ipset
iptables -L -n | grep -A5 f2b-nginx-basic-auth # iptables
# разбан
fail2ban-client set nginx-basic-auth unbanip <IP>
Первые 5 запросов дают 401, затем таймаут или reset: бан сработал.