如何限制Nginx Auth_Basic重試?

如何限制Nginx Auth_Basic重試?

我使用 Nginx 的 Auth_Basic 模組保護了一個 Web 資料夾。問題是,我們可以嘗試多個密碼,直到它起作用(暴力攻擊)。有沒有辦法限制重試失敗的次數?

答案1

據我所知,身份驗證基礎模組不支援此功能,但您可以使用失敗2禁止

使用不存在的使用者進行測試,您將在錯誤日誌中看到類似以下內容:

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")令牌綁定到成功登入的使用者。

相關內容