Limite de taxa usando haproxy por URL por ip

3

Nossos servidores estão sendo atingidos constantemente por alguém. Não é DDOS. Apenas um ip atinge um URL mais de 200 vezes por segundo. Atualmente estou bloqueando o usuário por tabelas ip. Estamos usando o HAproxy para balanceamento de carga. Existe uma maneira de limitar um usuário com base em seu ip e a URL sendo atingida?

Eu não quero bloquear apenas com base no IP, já que os usuários NAT podem ser afetados. Vamos dizer que eu quero mostrar 503 página de erro se um determinado ip está atingindo o mesmo URL como www.example.com/somepage.php?some=option&other=option2 mais de 3000 vezes em 5 minutos? Isso significa que o mesmo ip pode acessar outros URLs, como www.example.com/somepage.php?another=someotheroption.

    
por pooamlairaj 06.10.2015 / 11:18

1 resposta

3

Esta solução requer pelo menos haproxy 1.6.

Primeiro, adicione o seguinte ao frontend:

http-request set-header X-DOS-Protect %[src];%[req.fhdr(host)]%[capture.req.uri]

Em seguida, adicione o seguinte ao back-end:

stick-table type integer size 1m expire 5m store http_req_rate(5m)
tcp-request inspect-delay 5s
tcp-request content track-sc0 req.fhdr(X-DOS-Protect),crc32(1) if HTTP
http-request tarpit if { sc0_http_req_rate gt 3000 }

Não consegui encontrar uma maneira de fazer o acompanhamento no frontend, pois não encontrei uma maneira de aplicar um conversor nessa string concatenada que compõe o cabeçalho X-DOS-Protect.

Estou aplicando a função hash para garantir que você não armazene uma cadeia enorme na tabela, já que ela poderia facilmente levar a uma negação de serviço. Se você acha que essa função hash não é adequada para você devido a muitas colisões possíveis, você também pode aumentá-la aplicando crc32 em cada um dos componentes concatenados (e, claro, removendo-a ao armazenar os dados e alternando para um maior armazenamento stick-table), assim:

http-request set-header X-DOS-Protect %[src,crc32(1)];%[req.fhdr(host),crc32(1)]%[capture.req.uri,crc32(1)]

stick-table type string len 30 size 1m expire 5m store http_req_rate(5m)
tcp-request inspect-delay 5s
tcp-request content track-sc0 req.fhdr(X-DOS-Protect) if HTTP
http-request tarpit if { sc0_http_req_rate gt 3000 }

Por favor, note que esta última solução usará mais de 7 vezes mais memória do que a primeira, para cada entrada na tabela. É claro que o risco de colisão também seria menor.

    
por 29.11.2015 / 04:38