Solicitudes de URL individuales con límite de velocidad

8

Tengo una aplicación Flask que estoy desarrollando que se basa en gran medida en la interacción del sitio web externo y es iniciada por el usuario final. Si dejo la aplicación sin ningún tipo de control de ancho de banda / limitación de velocidad, entonces esta aplicación puede ser abusada por actores con intenciones nefastas.

Mi objetivo es un enfoque bastante simple de 2 etapas:

  1. Limite la velocidad de las fuentes IP individuales para que no realicen más de un xnúmero de conexiones por minuto Esto se puede lograr fácilmente con iptables. Aquí hay un ejemplo similar a mi objetivo:

     iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 \
       --connlimit-mask 32 -j REJECT --reject-with tcp-reset  
    
  2. La tasa limita la capacidad de las aplicaciones para realizar más del xnúmero de búsquedas por URL . Ejemplo:

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

Hasta donde puedo decir, iptablesno tiene forma de rastrear URL separadas. Solo puede calificar el límite de estas conexiones como un todo. Eso tampoco parece ser la única limitación a lo que estoy tratando de lograr. Si hubiera una manera de configurar iptablesde esta manera, podría proporcionar algunos problemas con mi aplicación web ya que estas solicitudes son iniciadas por el usuario.

Estoy usando Flask, una opción viable podría ser usar un before_requestgancho y rastrear manualmente estos destinos con un almacén de datos como Redis. Sin embargo, esto es bastante alto en la pila para lidiar con las conexiones de esta manera. Lo que realmente necesito (o creo que necesito) es una aplicación de firewall inteligente que puede analizar las solicitudes de forma personalizada y cerrar las conexiones cuando se alcanzan ciertos puntos de interrupción.

¿Hay alguna forma de lograr lo que estoy tratando de hacer?

¿Si es así, cómo?

Ryan Foley
fuente

Respuestas:

3

iptables trata las capas de Internet y transporte (en el modelo de Internet) o, alternativamente, las capas 3 y 4 en el modelo OSI, con algunas excepciones (filtrado en direcciones MAC, ayudantes de protocolo NAT).

Los URI son parte de la capa de aplicación. iptablesno trata con ellos.

Podría usar iptables para dirigir todo el tráfico del puerto TCP 80 saliente a través de un proxy web, lo que podría limitar su velocidad (por ejemplo, quizás los grupos de retraso de Squid podrían hacerlo. O Apache probablemente pueda mod_proxyhacerlo). Hacer esto con HTTPS es más difícil ( aunque tal vez solo pueda configurar su aplicación para usar un proxy web, lo que sería un mejor enfoque que un proxy transparente de todos modos).

Pero realmente debe mover ambos límites de velocidad a su aplicación. La razón de ser el UX que está configurando es terrible ; "conexión rechazada" no explica en absoluto lo que está sucediendo. Sería mucho mejor para sus usuarios si, en su lugar, presentara una página de error que explicara que están haciendo solicitudes demasiado rápido, a quién contactar para obtener asistencia, tal vez dar una opción para resolver un CAPTCHA para continuar, etc.

Es razonable tener un límite de velocidad de conexión en las conexiones entrantes, pero debe ser para evitar que la aplicación se caiga debido a un ataque DoS, tantas solicitudes que su aplicación ni siquiera puede servir la página de error de velocidad excedida al usuario. Debería ser un poco más alto que cuando comienza a servir la página de error (y tal vez debería ser un límite global, no un límite de IP por fuente). Tenga en cuenta que si su aplicación se ejecuta a través de un servidor web y / o proxy inverso, es probable que pueda configurar los límites de velocidad entrantes allí (en lugar de a través de iptables), y hacer rechazos muy baratos enviando una página de error estático, y ni siquiera pasando la solicitud a su aplicación

derobert
fuente