Account Protection
O Account Protection olha os formulários que os seus visitantes enviam, sem captcha no caminho. Ele faz três coisas:
- No login, confere se a senha digitada já apareceu num vazamento conhecido e avisa o seu app num cabeçalho. O app decide o que fazer, por exemplo pedir uma senha nova. Só 5 caracteres do hash da senha saem do conector.
- Limita as tentativas de login por conta, contadas pelo usuário digitado e não pelo IP. Uma botnet tentando uma conta a partir de mil endereços é barrada como uma só.
- Faz o formulário recusar robô. Um envio que preenche um campo-isca escondido, ou chega menos de 2 segundos depois de a página carregar, é devolvido.
O Account Protection faz parte do plano Pro.
Como ligar
Seção intitulada “Como ligar”Ele roda no conector: o proxy do Qlyne ou o Worker da Cloudflare. Com o conector instalado:
- No painel, abra o seu site e vá em Account Protection, Configuração.
- Escolha um nível de proteção (abaixo), depois abra Avançado e acrescente as suas rotas. Sem rota, nada é conferido.
- Deixe o conector em “Só observando” por alguns dias e olhe os Relatórios do Account Protection. Quando os números fizerem sentido, mude para “Aplicar” em Conector.
Na Cloudflare, as rotas do Worker precisam cobrir o endereço do login e as páginas dos formulários. As tentativas por conta usam o limite de requisições da Cloudflare, que exige o conector publicado com o Wrangler e o wrangler.toml do painel (veja Instale o conector). O aviso de senha vazada e os formulários funcionam também na instalação pelo painel da Cloudflare.
Configuração
Seção intitulada “Configuração”Proteção de login
Seção intitulada “Proteção de login”- Rotas de login: o endereço para onde o formulário de login ou o app envia, como
/login,/api/auth/loginou/wp-login.php.*casa com qualquer coisa. Só envios POST são conferidos. - Campo do usuário e Campo da senha: os nomes dos campos no formulário,
emailepasswordpor padrão. O WordPress usalogepwd. Em JSON, use ponto para entrar no objeto:user.email. Corpos de formulário, multipart e JSON de até 64 KB são lidos. - Avisar o meu app quando uma senha está num vazamento conhecido: ligado por padrão. Veja “O que o meu app recebe?” abaixo.
- Tentativas por conta: 10, 60 ou 300 por minuto, ou sem limite. Contadas pelo usuário digitado, de qualquer IP, em 60 segundos.
Formulários
Seção intitulada “Formulários”- Rotas de formulário protegidas: a página do formulário e o endereço para onde ele envia, como
/contact*,/signupou/newsletter*. Liste as duas: a página recebe os campos escondidos, o endereço confere. - Recusar envios sem os campos que o Qlyne adiciona: desligado por padrão. Ligado, o robô que envia sem nunca abrir a página também é recusado. Ligue só quando todo formulário dessas rotas for escrito em HTML puro.
Use formulário protegido onde a pessoa digita, como contato, cadastro e comentário. Formulário de um clique (adicionar ao carrinho) costuma sair em menos de 2 segundos e seria recusado.
Níveis de proteção
Seção intitulada “Níveis de proteção”Um nível preenche a configuração abaixo com um clique:
| Configuração | Básico | Equilibrado | Agressivo |
|---|---|---|---|
| Aviso de senha vazada | ligado | ligado | ligado |
| Tentativas por conta | sem limite | 60 por minuto | 10 por minuto |
| Recusar envios sem os campos que o Qlyne adiciona | desligado | desligado | ligado |
O nível nunca mexe nas suas rotas nem nos nomes dos campos. Se você muda uma configuração à mão, o nível aparece como Personalizado.
O que o visitante vê
Seção intitulada “O que o visitante vê”- Tentativas demais numa conta:
429comRetry-After: 60. O navegador recebe a página “Muitas requisições”, que recarrega sozinha. Uma chamada de API recebe{"code": "RATE_LIMITED"}. - Formulário recusado:
403. O navegador recebe a página “Formulário não enviado”, que diz “Volte, confira o formulário e envie de novo.” Uma chamada de API recebe{"code": "FORM_REJECTED"}. - Senha vazada: nada. O login segue para o seu app, e o app decide o que mostrar.
- A página com formulário protegido fica igual. Cada formulário POST ganha um campo-isca escondido e um carimbo de tempo, e a página sai com
Cache-Control: no-store, para cada visita receber um carimbo novo. Nenhum cookie é gravado. - No modo observar ninguém é barrado. O relatório conta o que teria sido limitado ou recusado.
Limites
Seção intitulada “Limites”- O aviso de senha vazada só vale se o seu app ler o cabeçalho
Qlyne-Leaked-Password. O Qlyne nunca recusa o login por conta própria. Se a consulta passa de 1,5 segundo ou o serviço de vazamentos está fora, o login segue sem o cabeçalho. - O formulário protegido funciona em formulário escrito em HTML puro na página. Formulário montado por JavaScript, ou enviado em JSON, não recebe os campos escondidos. Ele passa sem conferência, ou é recusado quando “Recusar envios sem os campos que o Qlyne adiciona” está ligado.
- O robô que abre a página, espera mais de 2 segundos e deixa a isca vazia passa. Um desafio na mesma página (Bot Management) faz cada tentativa custar trabalho.
- As tentativas por conta contam todo POST na rota de login, inclusive login certo. Muita gente usando a mesma conta pode chegar ao limite.
- No Next.js, o formulário protegido não funciona: o middleware nunca vê a página, então não consegue pôr os campos. Lá, use o captcha de formulário.
Perguntas frequentes
Seção intitulada “Perguntas frequentes”Vocês guardam a senha?
Seção intitulada “Vocês guardam a senha?”Não. O conector calcula o hash SHA-1 da senha e manda ao Have I Been Pwned só os 5 primeiros caracteres. Centenas de senhas têm esse mesmo começo, e a comparação acontece dentro do conector. A senha, o usuário e o formulário nunca vão ao Qlyne: o relatório recebe só a ação e a rota. As tentativas por conta são contadas sob um hash do usuário.
Funciona com o meu plugin de formulário?
Seção intitulada “Funciona com o meu plugin de formulário?”Se o plugin escreve um <form method="post"> normal na página, sim: liste a página e o endereço para onde ele envia. Alguns plugins mandam o formulário por JavaScript para outro endereço, como /wp-admin/admin-ajax.php no WordPress. Funciona quando o plugin manda todos os campos do formulário, os escondidos também, como formulário e não como JSON. Teste antes no modo observar: se os seus próprios envios aparecem como “Recusaria o formulário” no relatório, deixe essa rota de fora.
O que o meu app recebe?
Seção intitulada “O que o meu app recebe?”O login com senha vazada chega ao app com o cabeçalho Qlyne-Leaked-Password: 1, mesmo com os outros sinais desligados. Confira no código do login e, depois de aceitar a senha, peça uma nova:
// Nodeconst leaked = req.headers['qlyne-leaked-password'] === '1';// Laravel$leaked = $request->header('Qlyne-Leaked-Password') === '1';O formulário protegido chega ao app com dois campos a mais, qlyne_hp (vazio) e qlyne_ft (o carimbo). O app pode ignorar os dois. Envio recusado nunca chega ao app.
E credential stuffing de muitos endereços?
Seção intitulada “E credential stuffing de muitos endereços?”As tentativas por conta barram muitos endereços tentando adivinhar uma conta. O credential stuffing costuma tentar muitas contas, poucas vezes cada, e fica abaixo desse limite. Duas outras configurações cobrem esse caso. O aviso de senha vazada marca o login que usa senha de um vazamento conhecido, que é do que as listas de stuffing são feitas. Um limite por IP na rota de login, em WAF & Firewall, pega um endereço tentando muitas contas.
Tem no Free?
Seção intitulada “Tem no Free?”Não, o Account Protection faz parte do Pro. Toda conta nova tem 7 dias de Pro, sem cartão. No Free, as rotas que você salvou ficam no painel, mas o conector não as aplica até o site voltar ao Pro. Veja Planos.
Solução de problemas
Seção intitulada “Solução de problemas”Gente de verdade recebe “Formulário não enviado”
Seção intitulada “Gente de verdade recebe “Formulário não enviado””Três causas, da mais comum para a menos:
- A pessoa enviou em menos de 2 segundos, como acontece em formulário de um clique. Deixe essas rotas de fora.
- Só o endereço para onde o formulário envia está na lista, não a página, então o formulário não tem carimbo. Com “Recusar envios sem os campos que o Qlyne adiciona” ligado, ele é recusado. Liste a página também.
- O formulário é montado por JavaScript ou enviado em JSON, com essa mesma opção ligada. Desligue a opção, ou deixe a rota de fora.
Gente de verdade recebe 429 no login
Seção intitulada “Gente de verdade recebe 429 no login”Todo POST na rota de login conta, inclusive login certo, e a conta é por usuário. Uma conta compartilhada pode chegar a 10 por minuto. Escolha 60 ou 300 por minuto, ou sem limite. A contagem recomeça depois de 60 segundos.
As tentativas por conta não fazem nada na Cloudflare
Seção intitulada “As tentativas por conta não fazem nada na Cloudflare”O Worker conta as tentativas com o limite de requisições da Cloudflare, que a instalação pelo painel não configura. Publique com o Wrangler e o wrangler.toml do painel, e confira se uma rota do Worker cobre o endereço do login.