Como limitar a taxa no nginx, mas incluindo / excluindo determinados endereços IP?


27

Eu posso usar limit_reqpara limitar a taxa de todas as solicitações ao meu servidor.

No entanto, eu gostaria de remover a restrição de taxa para determinados endereços IP (por exemplo, lista de permissões) e usar uma restrição de taxa diferente para outros (por exemplo, certos IPs que eu gostaria que fosse de 1r / s).

Tentei usar condicionais (por exemplo if ( $remote_addr = "1.2.3.4" ) {}), mas isso parece funcionar apenas com regras de reescrita, não para regras de limite de taxa.

Respostas:


33

É realmente melhor evitar o uso da diretiva "if". Quando a chave em limit_req_zone (e limit_conn_zone) estiver vazia, os limites não serão aplicados. Você pode usar isso em conjunto com os módulos de mapa e geográfico para criar uma lista de permissões de IPs em que os limites da aceleração não são aplicados.

Este exemplo mostra como configurar um limite para solicitações simultâneas e taxa de solicitações de um único 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;

As diretivas de zona devem ser colocadas no nível http, no entanto, as outras diretivas podem ser colocadas mais abaixo, por exemplo, no servidor ou no nível do local para limitar seu escopo ou adequar ainda mais os limites.

Para obter mais informações, consulte a documentação Nginx ngx_http_limit_req_module e ngx_http_limit_conn_module


Qual a diferença entre esses 2 módulos?
Mente

11
De acordo com os comentários, o primeiro limita as conexões simultâneas, o segundo limita a taxa de conexões
shonky linux user

Você pode explicar por que você faz o mapeamento em dois estágios, geoseguido por map, em vez de apenas usar geopara definir $limitdiretamente?
Marcus Downing

2
Parece geoque não é possível mapear para uma variável, portanto, se você especificar $binary_remote_addrcomo um valor de mapeamento, isso será traduzido para a cadeia literal "$binary_remote_addr", não para o valor da variável.
ColinM

11
Gostaria de acrescentar que, se o IP em questão já estiver na zona, você deve reiniciar o nginx; uma recarga não é suficiente.
Halfgaar

5

Você pode usar com segurança locais nomeados, como "@location" em um bloco if ().

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

Algo assim deve 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 / {
         ...
      }
   }

Preencha "location @slowdown {}" com as mesmas informações que "location / {}, como proxy_pass se você estiver usando o nginx como proxy reverso.


Não sei se entendi a parte 410? O cliente realmente vê um código de status http 410?
svrist

11
Uau, isso realmente funciona! error_pageTruque muito bacana , +1! @svrist, consulte serverfault.com/a/870170/110020 para obter uma explicação completa de como algo assim funcionaria e por quê.
CNST
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.