¿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.