Herencia de Nginx limit_conn

Herencia de Nginx limit_conn

Estoy intentando proteger Drupal que se ejecuta en Nginx de DDoS simples con limit_conn y limit_req. Pero encontré un comportamiento extraño con la herencia de limit_conndirectiva que no puedo explicar.

He reducido mi configuración de nginx (1.8.0) a este mínimo, lo que muestra el problema:

limit_conn_zone $binary_remote_addr zone=perip:10m;

server {
    server_name test.dev;
    root /var/nginx/drupal; ## <-- Your only path reference.

    #Allow not more than 10 simultaneous connections from one address.
    limit_conn perip  10;

    location / {
        #limit_conn perip 1;
        # This is cool because no php is touched for static content
        try_files $uri @rewrite;
    }

    location @rewrite {
        # Clean URLs are handled in drupal_environment_initialize().
        rewrite ^ /index.php;
    }

    location ~ \.php$ {
        #Allow not more than 1 simultaneous *connection_to_PHP* from one address.
        limit_conn perip 1; 

        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi.conf;
        fastcgi_intercept_errors on;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
    }
}

Como puede ver, quiero limitar el número de conexiones simultáneas a 10 para todas las solicitudes y a 4 para el backend de php.(En este ejemplo he modificado la conexión 4 a 1, por lo que sería más fácil de activar)

La documentación de Nginx enhttp://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_connEstablece que:

Estas directivas se heredan del nivel anterior si y sólo si no hay limit_conndirectivas en el nivel actual.

Pero sucede algo extraño en mis pruebas, parece que nginx está ignorando la directiva limit_conndentro del location ~ \.php$bloque:

  1. Cuando pruebo esta configuración con 5 conexiones simultáneas ab -n 100 -c 5 http://test.dev/, no se produce ningún bloqueo. Tan pronto como elevo el
    límite a 11, -c 11nginx comienza a bloquear solicitudes.
  2. Si modifico el límite de conexiones globales de 10 a 5, nginx limita más de 6 conexiones ( -c 6); parece que location ~ \.php$se ignora la directiva en el bloque.
  3. Si elimino la conn_limitdirectiva a nivel de servidor, la directiva en location ~ \.php$bloque, ¡de repente comienza a funcionar!
  4. Aún más confuso: si agrego la conn_limitdirectiva location /bloquear, ¡sobrescribe correctamente la global!

¿Quizás el problema esté en try_filesla directiva o en múltiples redirecciones? Estaría muy agradecido si alguien pudiera explicar por qué la conn_limitdirectiva no se sobrescribe, como se esperaba.

Respuesta1

Gracias a @AlexeyTen, espero poder responder la pregunta.

Importantes son dos puntos:

  • ¡La limit_conndirectiva se procesa solo una vez por solicitud!
  • Estas directivas se heredan del nivel anterior si y sólo si no hay limit_conndirectivas en el nivel actual.

TL;DR: si hay una limit_conndirectiva, nginx mira el bloque secundario en la cadena de ejecución, si no la hay limit_conn, se procesa el principal. Después de eso limit_conn, se ignoran todas las demás directivas.

Intento explicarlo con mi ejemplo:

En el ejemplo que publiqué, cuando un "http://test.dev/"La solicitud llega, al principio, nginx no está procesando limit_conna servernivel, pero espera para buscar la ubicación coincidente location /. Pero en este nivel no hay ninguna limit_conndirectiva, por lo que nginx procesa la que está en el servernivel. Después de eso, todas limit_connlas directivas se ignoran, porque ya fue procesado. Eso explica mis pruebas 1-3.

En la prueba 4, nginx encuentra una limit_conndirectiva en la ubicación location /y la procesa, pero nuevamente, en la ubicación location @rewriteno se encuentra, por lo que se procesa limit_connla directiva en . location /Nuevamente estamos ignorando el location ~ \.php$bloqueo.

información relacionada