¿Cómo limitar la velocidad en nginx, pero incluyendo / excluyendo ciertas direcciones IP?


27

Puedo usar limit_reqpara limitar todas las solicitudes a mi servidor.

Sin embargo, me gustaría eliminar la restricción de velocidad para ciertas direcciones IP (es decir, la lista blanca) y usar una restricción de velocidad diferente para ciertas otras (es decir, ciertas direcciones IP que me gustaría tan bajas como 1r / s).

Intenté usar condicionales (por ejemplo if ( $remote_addr = "1.2.3.4" ) {}), pero parece funcionar solo con reglas de reescritura, no para reglas de límite de velocidad.

Respuestas:


33

Es realmente mejor evitar usar la directiva "if". Cuando la clave en limit_req_zone (y limit_conn_zone) está vacía, los límites no se aplican. Puede usar esto junto con los módulos de mapa y geo para crear una lista blanca de IP donde no se aplican los límites de aceleración.

Este ejemplo muestra cómo configurar un límite para las solicitudes concurrentes y la velocidad de solicitud desde una sola IP.

http {
    geo $whitelist {
       default 0;
       # CIDR in the list below are not limited
       1.2.3.0/24 1;
       9.10.11.12/32 1;
       127.0.0.1/32 1;
    }

    map $whitelist $limit {
        0     $binary_remote_addr;
        1     "";
    }

    # The directives below limit concurrent connections from a 
    # non-whitelisted IP address to five

    limit_conn_zone      $limit    zone=connlimit:10m;

    limit_conn           connlimit 5;
    limit_conn_log_level warn;   # logging level when threshold exceeded
    limit_conn_status    503;    # the error code to return

    # The code below limits the number requests from a non-whitelisted IP
    # to one every two seconds with up to 3 requests per IP delayed 
    # until the average time between responses reaches the threshold. 
    # Further requests over and above this limit will result 
    # in an immediate 503 error.

    limit_req_zone       $limit   zone=one:10m  rate=30r/m;

    limit_req            zone=one burst=3;
    limit_req_log_level  warn;
    limit_req_status     503;

Las directivas de zona deben colocarse en el nivel http, sin embargo, las otras directivas pueden ubicarse más abajo, por ejemplo, en el servidor o en el nivel de ubicación para limitar su alcance o adaptar aún más los límites.

Para obtener más información, consulte la documentación de Nginx ngx_http_limit_req_module y ngx_http_limit_conn_module


¿Cuál es la diferencia entre estos 2 módulos?
mente

1
Según los comentarios, el primero limita las conexiones concurrentes, el segundo limita la velocidad de las conexiones
usuario de shonky linux el

¿Puede explicar por qué hace el mapeo en dos etapas, geoseguidas por map, en lugar de solo usar geopara establecer $limitdirectamente?
Marcus Downing

2
Parece geoque no se puede asignar a una variable, por lo que si especifica $binary_remote_addrcomo valor de asignación, esto se traducirá en la cadena literal "$binary_remote_addr", no en el valor de la variable.
ColinM

1
Me gustaría agregar que si la IP en cuestión ya está en la zona, debe reiniciar nginx; una recarga no es suficiente.
Halfgaar

5

Puede usar ubicaciones con nombre de forma segura, como "@location" en un bloque if ().

Ver: http://wiki.nginx.org/IfIsEvil

Algo como esto debería funcionar:

http {

   limit_req_zone $binary_remote_addr zone=delay:10m rate=1r/m;

   server {
      ...

      error_page 410 = @slowdown;

      if( $remote_addr != "1.2.3.4" ) {
         return 410;
      }

      location @slowdown {
         limit_req zone=delay burst 5;
         ...
      }

      location / {
         ...
      }
   }

Complete "location @slowdown {}" con la misma información que "location / {}, como proxy_pass si está usando nginx como proxy inverso.


¿No estoy seguro de entender la parte 410? ¿El cliente realmente ve un código de estado http 410?
svrist

1
Wow, esto realmente funciona! error_pageTruco muy ingenioso , +1! @svrist, consulte serverfault.com/a/870170/110020 para obtener una explicación completa de cómo funcionaría algo así y por qué.
Cnst
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.