Taxa que limita solicitações de URL individuais

8

Estou desenvolvendo um aplicativo Flask que depende muito da interação de sites externos e é iniciado pelo usuário final. Se eu deixar o aplicativo sem nenhum tipo de controle de largura de banda / limitação de taxa, esse aplicativo poderá ser abusado por atores com intenções nefastas.

Meu objetivo é uma abordagem em duas etapas bastante simples:

  1. A taxa limita que fontes IP individuais executem mais do que o xnúmero de conexões por minuto. Isso pode ser facilmente alcançado com iptables. Aqui está um exemplo semelhante ao meu objetivo:

     iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 \
       --connlimit-mask 32 -j REJECT --reject-with tcp-reset  
    
  2. A taxa limita a capacidade dos aplicativos de executar mais do que o xnúmero de pesquisas por URL . Exemplo:

     APP ---- 10 pps --->  stackexchange.com   PERMIT
     APP ---- 25 pps --->  google.com          DENY / 15 SECOND BACKOFF
    

Até onde sei, iptablesnão há como rastrear URLs separados. Só é capaz de classificar o limite dessas conexões como um todo. Isso também não parece ser a única limitação para o que estou tentando alcançar. Se houvesse uma maneira de configurar iptablesdessa maneira, isso poderia fornecer alguns problemas ao meu aplicativo Web, pois essas solicitações são iniciadas pelo usuário.

Estou usando o Flask, uma opção viável pode estar usando um before_requestgancho e rastreando manualmente esses destinos com um armazenamento de dados como o Redis. No entanto, isso é muito alto na pilha para lidar com conexões dessa maneira. O que realmente preciso (ou acho que preciso) é de um aplicativo de firewall inteligente que possa dissecar solicitações de maneira personalizada e fechar conexões quando determinados pontos de interrupção forem atingidos.

Existe alguma maneira de conseguir o que estou tentando fazer?

Se sim, como?

Ryan Foley
fonte

Respostas:

3

iptables lida com as camadas Internet e Transporte (no modelo da Internet) ou alternativamente as camadas 3 e 4 no modelo OSI, com algumas exceções (filtragem em endereços MAC, auxiliares do protocolo NAT).

URIs fazem parte da camada Aplicativo. iptablesnão lida com eles.

Você pode usar o iptables para direcionar todo o tráfego da porta TCP de saída 80 por meio de um proxy da Web, o que pode limitar sua taxa (por exemplo, talvez os pools de atraso do Squid possam fazê-lo. Ou o Apache provavelmente pode fazê-lo mod_proxy.) Fazer isso com HTTPS é mais difícil ( embora talvez você possa apenas configurar seu aplicativo para usar um proxy da web, o que seria uma abordagem melhor do que um proxy transparente).

Mas você realmente deve mover os dois limites de taxa para seu aplicativo. A razão de ser o UX que você está configurando é terrível ; "conexão recusada" falha em explicar o que está acontecendo. Seria muito melhor para seus usuários se você desse uma página de erro explicando que eles estão fazendo solicitações muito rapidamente, com quem entrar em contato para obter suporte, talvez dê uma opção para resolver um CAPTCHA para continuar etc.

É razoável ter um limite de taxa de conexão nas conexões de entrada, mas deve ser para evitar que o aplicativo caia devido a um ataque de negação de serviço - tantas solicitações que seu aplicativo não consegue nem mesmo exibir a página de erro de taxa excedida ao usuário. Deve ser um pouco mais alto do que quando você começa a exibir a página de erro (e talvez deva ser um limite global, não um limite por IP de origem). Observe que, se seu aplicativo estiver sendo executado por meio de um servidor Web e / ou proxy reverso, é possível que você configure limites de taxa de entrada lá (em vez de via iptables) - e faça rejeições muito baratas enviando uma página de erro estática e nem mesmo passando a solicitação para o seu aplicativo.

derobert
fonte