Come limitare la velocità in nginx, ma includendo / escludendo determinati indirizzi IP?


27

Sono in grado di utilizzare limit_reqper limitare tutte le richieste al mio server.

Tuttavia, vorrei rimuovere la restrizione della tariffa per determinati indirizzi IP (ovvero la whitelist) e utilizzare una restrizione della tariffa diversa per alcuni altri (ovvero determinati IP che vorrei fino a 1r / s).

Ho provato a usare i condizionali (ad es. if ( $remote_addr = "1.2.3.4" ) {}) Ma sembra funzionare solo con le regole di riscrittura, non per le regole di limite di velocità.

Risposte:


33

È davvero meglio evitare di usare la direttiva "if". Quando la chiave in limit_req_zone (e limit_conn_zone) è vuota, i limiti non vengono applicati. Puoi usarlo insieme alla mappa e ai moduli geografici per creare una whitelist di IP in cui non vengono applicati i limiti di accelerazione.

Questo esempio mostra come configurare un limite sia per le richieste simultanee che per la frequenza delle richieste da un singolo 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;

Le direttive di zona devono essere posizionate a livello http, tuttavia le altre direttive possono essere posizionate più in basso, ad es. A livello del server o della posizione per limitarne l'ambito o personalizzare ulteriormente i limiti.

Per ulteriori informazioni consultare la documentazione di Nginx ngx_http_limit_req_module e ngx_http_limit_conn_module


Qual è la differenza tra questi 2 moduli?
mente

1
Secondo i commenti, il primo limita le connessioni simultanee, il secondo limita la velocità delle connessioni
utente Linux shonky

Puoi spiegare perché esegui la mappatura in due fasi, geoseguita da map, anziché utilizzare solo geoper impostare $limitdirettamente?
Marcus Downing,

2
Sembra che geonon possa essere $binary_remote_addrmappato su una variabile, quindi se specifichi come valore di mappatura questo si tradurrà nella stringa letterale "$binary_remote_addr", non nel valore della variabile.
ColinM,

1
Vorrei aggiungere che se l'IP in questione è già nella zona, è necessario riavviare nginx; una ricarica non è sufficiente.
Halfgaar,

5

È possibile utilizzare in sicurezza posizioni denominate, ad esempio "@location" in un blocco if ().

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

Qualcosa del genere dovrebbe funzionare:

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

Inserisci "location @slowdown {}" con le stesse informazioni di "location / {}, come proxy_pass se stai utilizzando nginx come proxy inverso.


Non sono sicuro di aver capito la parte 410? Il client vede effettivamente un codice di stato http 410?
svrist,

1
Caspita, funziona davvero! error_pageTrucco molto elegante , +1! @svrist, vedi serverfault.com/a/870170/110020 per una spiegazione completa di come funzionerebbe qualcosa del genere e perché.
primo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.