it-swarm.com.de

Ratenbeschränkung für einzelne URL-Anfragen

Ich habe eine Flask Anwendung, die ich entwickle und die stark von der Interaktion mit externen Websites abhängt und die vom Endbenutzer initiiert wird. Wenn ich die Anwendung ohne jegliche Bandbreitenkontrolle/Ratenbeschränkung lasse, wird diese Anwendung möglicherweise von Schauspielern mit schändlichen Absichten missbraucht.

Mein Ziel ist ein ziemlich einfacher zweistufiger Ansatz:

  1. Die Rate beschränkt einzelne IP-Quellen darauf, mehr als x Verbindungen pro Minute durchzuführen. Dies kann leicht mit iptables erreicht werden. Hier ist ein ähnliches Beispiel für mein Ziel:

     iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 \
       --connlimit-mask 32 -j REJECT --reject-with tcp-reset  
    
  2. Die Rate begrenzt die Fähigkeit der Anwendung, mehr als x Suchvorgänge pro URL durchzuführen. Beispiel:

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

Soweit ich das beurteilen kann, kann iptables keine einzelnen URLs verfolgen. Es ist nur möglich, diese Verbindungen als Ganzes einzuschränken. Das scheint auch nicht die einzige Einschränkung für das zu sein, was ich erreichen will. Wenn es eine Möglichkeit gibt, iptables auf diese Weise einzurichten, kann dies zu Problemen mit meiner Webanwendung führen, da diese Anforderungen vom Benutzer initiiert werden.

Ich verwende Flask. Möglicherweise können Sie einen before_request -Hook verwenden und diese Ziele manuell mit einem Datenspeicher wie Redis verfolgen. Dies ist jedoch ziemlich weit oben im Stapel, um mit Verbindungen auf diese Weise umzugehen. Was ich wirklich brauche (oder zu tun glaube), ist eine intelligente Firewall-Anwendung, die Anforderungen auf benutzerdefinierte Weise auflösen und Verbindungen schließen kann, wenn bestimmte Haltepunkte erreicht wurden.

Gibt es eine Möglichkeit, das zu erreichen, was ich versuche?

Wenn das so ist, wie?

8
Ryan Foley

iptables befasst sich mit den Schichten Internet und Transport (im Internetmodell) oder alternativ mit den Schichten 3 und 4 im OSI-Modell, mit wenigen Ausnahmen (Filtern nach MAC-Adressen, NAT Protokollhelfer).

URIs sind Teil der Anwendungsebene. iptables kümmert sich nicht um sie.

Sie können iptables verwenden, um den gesamten ausgehenden TCP Port 80-Datenverkehr über einen Web-Proxy zu leiten. Dies kann zu einer Geschwindigkeitsbegrenzung führen (z. B. Verzögerungspools von Squid oder Apache Dies kann wahrscheinlich mit mod_proxy geschehen.) Dies mit HTTPS zu tun ist schwieriger (obwohl Sie Ihre App möglicherweise nur für die Verwendung eines Web-Proxys konfigurieren können, was ohnehin ein besserer Ansatz als ein transparenter Proxy wäre).

Aber Sie sollten wirklich beide Ratenbegrenzungen in Ihre Anwendung verschieben. Der Grund dafür ist, dass Sie UX einrichten, schrecklich ; "Verbindung abgelehnt" kann überhaupt nicht erklären, was passiert. Es wäre viel besser für Ihre Benutzer, wenn Sie stattdessen eine Fehlerseite mit der Erklärung geben würden, dass sie Anfragen zu schnell stellen, wen Sie für Support kontaktieren können, und vielleicht eine Option zur Lösung angeben ein CAPTCHA um fortzufahren, etc.

Es ist sinnvoll, eine Verbindungsratenbeschränkung für eingehende Verbindungen festzulegen, diese sollte jedoch die App vor einem Absturz aufgrund einer DoS-Attacke schützen - so viele Anfragen, dass Ihre App nicht einmal die Rate liefern kann, überschritt die Fehlerseite für den Benutzer. Es sollte ein gutes Stück höher sein als zu Beginn der Bereitstellung der Fehlerseite (und möglicherweise ein globales Limit, kein Pro-Quelle-IP-Limit). Beachten Sie, dass Sie, wenn Ihre App über einen Webserver und/oder einen Reverse-Proxy ausgeführt wird, dort wahrscheinlich Grenzwerte für eingehende Raten konfigurieren können (anstatt über iptables) - und tun Sie very cheap rejects by Senden einer statischen Fehlerseite und nicht einmal Weiterleiten der Anforderung an Ihre App.

3
derobert