如何限制 Nginx Auth_Basic 重试次数?

如何限制 Nginx Auth_Basic 重试次数?

我使用 Nginx 的 Auth_Basic 模块保护了一个 Web 文件夹。问题是,我们可以尝试多个密码直到成功(暴力攻击)。有没有办法限制重试失败的次数?

答案1

据我所知,基本认证模块不支持此功能,但你可以使用Fail2ban

使用不存在的用户进行测试,您将在错误日志中看到类似下面的内容:

2012/08/25 10:07:01 [error] 5866#0: *1 no user/password was provided for basic authentication, client: 127.0.0.1, server: localhost, request: "GET /pma HTTP/1.1", host: "localhost:81" 2012/08/25 10:07:04 [error] 5866#0: *1 user "ajfkla" was not found in "/etc/nginx/htpasswd", client: 127.0.0.1, server: localhost, request: "GET /pma HTTP/1.1", host: "localhost:81"

然后创建必要的过滤器:

/etc/fail2ban/filter.d/nginx-auth.conf

[Definition]
failregex = no user/password was provided for basic authentication.*client: <HOST>
              user .* was not found in.*client: <HOST>
              user .* password mismatch.*client: <HOST>
ignoreregex = </host></host></host> 

/etc/fail2ban/jail.conf

[nginx-auth]
enabled = true
filter = nginx-auth
action = iptables[name=NoAuthFailures, port=80, protocol=tcp]
logpath = /var/log/nginx*/*error*.log
bantime = 3600 # 1 hour
maxretry = 3

测试Fail2Ban规则:

fail2ban-regex /var/log/nginx/localhost.error_log /etc/fail2ban/filter.d/nginx-auth.conf

Failregex
|- Regular expressions:
|  [1] no user/password was provided for basic authentication.*client: <HOST>
|  [2] user .* was not found in.*client: <HOST>
|  [3] user .* password mismatch.*client: <HOST>
|
`- Number of matches:
   [1] 1 match(es)
   [2] 2 match(es)
   [3] 0 match(es)

Ignoreregex
|- Regular expressions:
|
`- Number of matches:

Summary
=======

Addresses found:
[1]
    127.0.0.1 (Sat Aug 25 10:07:01 2012)
[2]
    127.0.0.1 (Sat Aug 25 10:07:04 2012)
    127.0.0.1 (Sat Aug 25 10:07:07 2012)
[3]

PS:由于 Fail2ban 会获取日志文件来禁止,请确保logpath与您的配置相匹配。

答案2

我很惊讶没有其他人给出这个解决方案/解决方法。

Nginx basic-auth 并htpasswd支持带有可选成本变量的 bcrypt 密码加密。Bcrypt 的设计速度较慢,因此对您尝试不同密码的速度提供了硬性限制。

创建基本身份验证用户名/密码时使用

htpasswd -B -C 12 path/to/users.db <username>

如果成本为 12,您的服务器可能无法在一秒钟内尝试输入密码超过几次,如果将其增加到 14,则每次密码尝试可能需要花费大约 1 秒的时间。

通过该配置,任何合理的密码都将免受暴力攻击,即使攻击者多年来不断尝试密码。

例如,以每秒 10 次密码尝试的频率对 8 个字符的字母数字密码进行暴力攻击将花费 692,351 年:62**8 / (10*3600*24*365)

这比设置“智能”请求限制更容易配置,也更可靠。

答案3

我不相信 nginx 有任何内部工具可以做到这一点。文档页面并不意味着这是可能的。

您可以使用 Fail2Ban 来阻止重复登录失败的 IP 地址。

Fail2Ban wiki 上有一些nginx 特定模式

Fail2Ban 应该作为一个软件包在大多数大型发行版中提供。

答案4

这可以通过结合 NGINX 基本身份验证和速率限制来实现。

http {
    map $http_cookie $rate_limit_key {
        default $binary_remote_addr;
        "~__Secure-rl-bypass=SomeRandomBytes" "";
    }
    limit_req_status 429;
    limit_req_zone $rate_limit_key zone=auth:10m rate=1r/m;

    server {
            auth_basic "Private Content";
            auth_basic_user_file your-auth-file.txt;

            limit_req zone=auth burst=20 delay=10;

            add_header Set-Cookie "__Secure-rl-bypass=SomeRandomBytes;Max-Age=${toString (3600*24*180)};Domain=$host;Path=/;Secure;HttpOnly";
    }
}

该代码片段是从我的工作配置中提取的,但代码片段本身并未经过测试。

基本概念是创建一个允许绕过速率限制的 cookie,然后在某人成功验证后设置该 cookie。这样,某人的速率就会受到限制,直到他们登录,此时他们可以执行任意数量的请求。

这种方法的主要缺点是 cookie 是静态的,一旦有人登录任何帐户,他们就可以使用令牌暴力破解其他帐户。如果您信任用户不会暴力破解其他用户的密码,那么这不是一个大问题。但是,我认为在 NGINX 的配置中,您无法做得比这更好。理想情况下,cookie 应该将令牌hash("$remote_user-SomeRandomBytes")绑定到成功登录的用户。

相关内容