Limitation du taux de demandes d'URL individuelles

8

J'ai une application Flask que je développe, qui repose fortement sur l'interaction avec un site Web externe et est lancée par l'utilisateur final. Si je quitte l'application sans aucune sorte de contrôle de bande passante / limitation de débit, cette application peut être utilisée abusivement par des acteurs aux intentions néfastes.

Mon objectif est une approche assez simple en 2 étapes:

  1. Le taux limite les sources IP individuelles d'effectuer plus de xnombre de connexions par minute. Cela peut être facilement réalisé avec iptables. Voici un exemple similaire à mon objectif:

     iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 \
       --connlimit-mask 32 -j REJECT --reject-with tcp-reset  
    
  2. Le taux limite la capacité des applications à effectuer plus de xnombre de recherches par URL . Exemple:

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

Pour autant que je sache, iptablesn'a aucun moyen de suivre des URL distinctes. Il ne peut que limiter la limite de ces connexions dans son ensemble. Cela ne semble pas non plus être la seule limitation à ce que j'essaie de réaliser. S'il y avait un moyen de procéder iptablesde cette manière, cela pourrait poser des problèmes avec mon application Web car ces demandes sont lancées par l'utilisateur.

J'utilise Flask, une option viable pourrait être d'utiliser un before_requestcrochet et de suivre manuellement ces destinations avec un magasin de données tel que Redis. Cependant, c'est assez haut dans la pile pour traiter les connexions de cette manière. Ce dont j'ai vraiment besoin (ou je pense le faire), c'est d'une application de pare-feu intelligente qui peut disséquer les demandes de manière personnalisée et fermer les connexions lorsque certains points d'arrêt ont été atteints.

Existe-t-il un moyen de réaliser ce que j'essaie de faire?

Si c'est le cas, comment?

Ryan Foley
la source

Réponses:

3

iptables traite des couches Internet et Transport (dans le modèle Internet) ou alternativement les couches 3 et 4 dans le modèle OSI, à quelques exceptions près (filtrage sur les adresses MAC, aides au protocole NAT).

Les URI font partie de la couche Application. iptablesne s'occupe pas d'eux.

Vous pouvez utiliser iptables pour diriger tout votre trafic sortant du port TCP 80 via un proxy Web, ce qui pourrait limiter votre débit (par exemple, les pools de retards de Squid pourraient le faire. Ou Apache peut probablement le faire avec mod_proxy.) Faire cela avec HTTPS est plus difficile ( mais peut-être pouvez-vous simplement configurer votre application pour utiliser un proxy Web, ce qui serait une meilleure approche qu'un proxy transparent de toute façon).

Mais vous devez vraiment déplacer vos deux limites de taux dans votre application. La raison étant l'UX que vous configurez est terrible ; "connexion refusée" n'explique pas du tout ce qui se passe. Ce serait bien mieux pour vos utilisateurs si vous donniez à la place une page d'erreur expliquant qu'ils font des demandes trop rapidement, qui contacter pour obtenir de l'aide, peut-être donner une option pour résoudre un CAPTCHA pour continuer, etc.

Il est raisonnable d'avoir une limite de débit de connexion sur les connexions entrantes, mais cela devrait être de protéger l'application contre les chutes en raison d'une attaque DoS - tant de demandes que votre application ne peut même pas servir la page d'erreur de taux dépassé à l'utilisateur. Il devrait être un peu plus élevé que lorsque vous commencez à diffuser la page d'erreur (et peut-être devrait être une limite globale, pas une limite IP par source). Notez que si votre application s'exécute via un serveur Web et / ou un proxy inverse, vous pouvez probablement y configurer des limites de débit entrantes (au lieu de via iptables) - et effectuer des rejets très bon marché en envoyant une page d'erreur statique et sans même passer la demande à votre application.

derobert
la source