Как ограничить повторные попытки Nginx Auth_Basic?

Как ограничить повторные попытки Nginx Auth_Basic?

Я защитил веб-папку с помощью модуля Auth_Basic от Nginx. Проблема в том, что мы можем перебрать несколько паролей, пока это не сработает (атаки методом подбора). Есть ли способ ограничить количество неудачных попыток?

решение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 есть некоторыешаблоны, специфичные для 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")таким, чтобы токен был привязан к пользователю, который успешно вошел в систему.

Связанный контент