Protegi uma pasta da web com o módulo Auth_Basic do Nginx. O problema é que podemos tentar várias senhas até funcionar (ataques de força bruta). Existe uma maneira de limitar o número de novas tentativas com falha?
Responder1
Até onde sei,Autenticação Básicamódulo não suporta esse recurso, mas você pode fazer isso usandoFail2ban.
Testando com um usuário inexistente, você verá algo como abaixo no log de erros:
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"
Em seguida, crie o filtro necessário:
/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
Testando regras do 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: Como o Fail2ban busca arquivos de log para banir, certifique-se logpath
de que corresponda à sua configuração.
Responder2
Estou surpreso que ninguém mais tenha fornecido essa solução/solução alternativa.
Nginx basic-auth e htpasswd
suporta criptografia de senha bcrypt com uma variável de custo opcional. O Bcrypt foi projetado para ser lento, fornecendo assim um limite rígido de quão rápido você pode tentar senhas diferentes.
Ao criar seu nome de usuário/senha de autenticação básica, use
htpasswd -B -C 12 path/to/users.db <username>
Com um custo de 12, seu servidor provavelmente não será capaz de tentar senhas mais do que algumas vezes por segundo, aumente para 14 e você provavelmente verá cerca de 1s por tentativa de senha.
Com isso configurado, qualquer senha razoável ficará imune a ataques de força bruta, mesmo que o invasor tente senhas continuamente por anos.
Por exemplo, com 10 tentativas de senha por segundo, um ataque de força bruta a uma senha alfanumérica de 8 caracteres levaria 692.351 anos: 62**8 / (10*3600*24*365)
.
Isso é muito mais fácil de configurar e mais infalível do que configurar uma limitação de solicitação "inteligente".
Responder3
Não acredito que o nginx tenha algum recurso interno para fazer isso. Opágina de documentaçãonão sugere que seja possível.
Você pode usar Fail2Ban para bloquear endereços IP que repetiram tentativas de login malsucedidas.
O wiki Fail2Ban tem algunspadrões específicos do nginx.
Fail2Ban deve estar disponível como pacote na maioria das grandes distros.
Responder4
Isso pode ser conseguido com uma combinação de autenticação básica NGINX e limitação de taxa.
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";
}
}
Este trecho foi extraído da minha configuração de trabalho, mas o trecho em si não foi testado.
O conceito básico é que você crie um cookie que permita ignorar o limite de taxa e defina o cookie assim que alguém autenticar com sucesso. Dessa forma, alguém tem taxa limitada até fazer login, momento em que poderá realizar quantas solicitações quiser.
A principal desvantagem dessa abordagem é que o cookie é estático, uma vez que alguém está logado em qualquer conta, ele pode usar o token para forçar outras contas. Este não é um grande problema se seus usuários forem confiáveis para não usar força bruta na senha de outros usuários. No entanto, não acho que você possa fazer melhor do que isso na configuração do NGINX. Idealmente, o cookie seria hash("$remote_user-SomeRandomBytes")
para que o token fosse vinculado ao usuário que efetuou login com sucesso.