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.