Frage Wie Rate-Limit in Nginx, aber einschließlich / Ausschluss bestimmter IP-Adressen?


Ich kann es benutzen limit_req um alle Anfragen auf meinen Server zu begrenzen.

Allerdings möchte ich die Ratenbeschränkung für bestimmte IP-Adressen (d. H. Whitelist) entfernen und eine andere Ratenbeschränkung für bestimmte andere verwenden (d. H. Bestimmte IPs, die so niedrig wie 1r / s sein sollen).

Ich habe versucht, Bedingungen (z. if ( $remote_addr = "1.2.3.4" ) {}) aber das scheint nur mit Rewrite-Regeln zu funktionieren, nicht für Rate-Limit-Regeln.


26
2017-09-02 19:11


Ursprung




Antworten:


Es ist wirklich besser, die "if" -Richtlinie zu vermeiden. Wenn der Schlüssel in limit_req_zone (und limit_conn_zone) leer ist, werden die Limits nicht angewendet. Sie können dies in Verbindung mit den Karten- und Geo-Modulen verwenden, um eine Whitelist von IPs zu erstellen, bei denen die Drosselgrenzen nicht angewendet werden.

In diesem Beispiel wird gezeigt, wie ein Limit für gleichzeitige Anfragen und die Anfragerate von einer einzelnen IP-Adresse konfiguriert wird.

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;

Die Zonen-Direktiven müssen auf der http-Ebene platziert werden, die anderen Direktiven können jedoch weiter unten platziert werden, z. auf dem Server oder der Standort-Ebene, um ihren Umfang zu begrenzen oder die Grenzen weiter zuzuschneiden.

Weitere Informationen finden Sie in der Nginx-Dokumentation ngx_http_limit_req_module und ngx_http_limit_conn_module


31
2017-11-06 01:06



Was ist der Unterschied zwischen diesen 2 Modulen? - mente
Gemäß den Kommentaren begrenzt der erste gleichzeitige Verbindungen, der zweite begrenzt die Verbindungsrate - shonky linux user
Können Sie erklären, warum Sie das Mapping in zwei Schritten durchführen, mit geo gefolgt von map, anstatt nur zu benutzen geo einstellen $limit direkt? - Marcus Downing
Es scheint geo kann also nicht zu einer Variablen zugeordnet werden, wenn Sie angeben $binary_remote_addr Als Mapping-Wert wird dies in die Literal-Zeichenkette übersetzt "$binary_remote_addr", nicht der Wert der Variablen. - ColinM
Ich möchte hinzufügen, dass, wenn die fragliche IP bereits in der Zone ist Muss neustart nginx; ein Nachladen ist nicht genug. - Halfgaar


Sie können benannte Orte wie "@ location" in einem if () -Block sicher verwenden.

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

So etwas sollte funktionieren:

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

Geben Sie "location @slowdown {}" mit denselben Informationen wie "location / {}" ein, z. B. "proxy_pass", wenn Sie nginx als Reverse-Proxy verwenden.


5
2018-02-24 22:44



Ich bin mir nicht sicher, ob ich den 410 Teil verstehe? Sieht der Client tatsächlich einen HTTP 410-Statuscode? - svrist
Wow, das funktioniert tatsächlich! Sehr geschickt error_page Trick, +1! @svrist, siehe serverfault.com/a/870170/110020 für eine vollständige Erklärung, wie etwas wie das funktionieren würde und warum. - cnst