Nginx的auth_basic暴力破解行为必须通过error.log精准捕获,因其认证失败(如用户不存在、凭据未提供、密码错误)由内核直接记录在error.log中,而access.log仅显示401状态码,无法区分爆破与误操作;需确保error_log路径与fail2ban配置一致、启用log_not_found off避免404干扰、并保障Nginx运行用户对日志目录有写权限。

直接用 Nginx 的 auth_basic 做登录保护时,暴力破解行为会在错误日志(error.log)中留下明确痕迹——不是靠访问日志猜,而是靠认证失败的原生记录精准捕获。
为什么必须盯 error.log,而不是 access.log
Nginx 自身的 Basic Auth 失败(如用户名不存在、密码错误、未提供凭据)不会写入 access.log,而是统一记到 error.log 中,典型日志行如下:
user "admin" was not found in "/etc/nginx/.htpasswd"no user/password was provided for basic authentication-
password mismatch for user "test"(部分版本或模块扩展支持)
这些是 Nginx 内核级认证失败输出,真实、不可绕过、无需后端参与。而 access.log 里只看到 401 状态码,无法区分是用户手误、脚本误配,还是系统性爆破。
确保日志能被 fail2ban 正确识别的关键配置
三件事缺一不可:
-
确认 error_log 路径一致:Nginx 配置中
error_log /var/log/nginx/error.log warn;必须与 fail2ban 的logpath完全匹配 -
关闭无关干扰项:在受保护的 location 中添加
log_not_found off;,避免 404 请求冲刷 error.log,掩盖真实爆破线索 -
权限可写:确保 nginx worker 进程用户(如
nginx或www-data)对 error.log 所在目录有写权限,否则失败日志根本不会落盘
用命令快速筛查当前攻击线索
不依赖工具,几条 shell 就能定位异常:
- 查最近 1 小时内所有 Basic Auth 失败记录:
awk '/was not found|no user\/password/ && $3 > strftime("%d/%b/%Y:%H:%M:%S", systime()-3600) {print}' /var/log/nginx/error.log - 统计高频攻击 IP(按失败次数倒序):
awk '/was not found|no user\/password/ {for(i=1;i - 检查是否集中爆破某个用户名(如 admin、root、test):
grep "was not found" /var/log/nginx/error.log | grep -o 'user "[^"]*"' | sort | uniq -c | sort -nr
配合 fail2ban 实现自动封禁
在 /etc/fail2ban/jail.local 中启用内置规则即可:
[nginx-http-auth] enabled = true filter = nginx-http-auth logpath = /var/log/nginx/error.log maxretry = 3 findtime = 600 bantime = 3600 action = iptables-ipset-proto6[name=nginx-http-auth, port="http,https"]
该 filter 已预置匹配上述三种典型失败文本,无需改写正则。上线后,同一 IP 10 分钟内失败 3 次,即刻封禁 1 小时。


















