Nginx'te oran sınırı (bazı IP adresleri dahil / hariç) nasıl yapılır?


27

limit_reqSunucuma yapılan tüm istekleri derecelendirmek için kullanabiliyorum .

Bununla birlikte, bazı IP adresleri (beyaz listedeki) için fiyat kısıtlamasını kaldırmak ve bazı başkaları için farklı bir fiyat kısıtlaması kullanmak istiyorum (örneğin, 1r / s kadar düşük olan belirli IP'ler).

Koşullu ifadeleri (örneğin if ( $remote_addr = "1.2.3.4" ) {}) kullanmayı denedim , ancak oran sınırı kuralları için değil, yalnızca yeniden yazma kuralları ile çalışıyor gibi görünüyor.

Yanıtlar:


33

"If" direktifini kullanmaktan kaçınmak gerçekten daha iyidir. Limit_req_zone (ve limit_conn_zone) içindeki anahtar boş bırakıldığında sınırlar uygulanmaz. Gaz sınırlarının uygulanmadığı bir IP beyaz listesi oluşturmak için bunu harita ve coğrafi modüller ile birlikte kullanabilirsiniz.

Bu örnek hem eşzamanlı istekler hem de tek bir IP'den gelen talep oranı için bir limitin nasıl yapılandırıldığını gösterir.

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;

Bölge direktifleri http seviyesine yerleştirilmelidir, ancak diğer direktifler kapsamlarını sınırlamak veya limitleri daha da uyarlamak için örneğin sunucu veya yer seviyesine yerleştirilebilir.

Daha fazla bilgi için Nginx belgelerine bakın ngx_http_limit_req_module ve ngx_http_limit_conn_module


Bu 2 modül arasındaki fark nedir?
Mente

1
Yorumlara göre, ilk eşzamanlı bağlantıları sınırlar, ikincisi bağlantı oranlarını sınırlandırır
shonky linux kullanıcısı

Haritalamayı neden sadece iki aşamalı olarak yaptığınızı ve geoardından doğrudan ayarlamak mapyerine kullanmak geogerektiğini açıklayabilir misiniz $limit?
Marcus Downing,

2
geoBir değişkene eşlenemiyor gibi görünüyor , bu nedenle $binary_remote_addrbir eşleme değeri olarak belirtirseniz "$binary_remote_addr", değişkenin değeri değil, değişmez dizeye çevrilir .
ColinM

1
Söz konusu IP zaten bölgedeyse, nginx'i yeniden başlatmanız gerektiğini ; yeniden yükleme yeterli değil.
Halfgaar

5

Bir if () bloğunda "@location" gibi adlandırılmış konumları güvenle kullanabilirsiniz.

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

Böyle bir şey çalışması gerekir:

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

Ters bir vekil olarak nginx kullanıyorsanız, "location @slowdown {}" ile "location / {} ile aynı bilgiyi, proxy_pass gibi doldurun.


410 bölümünü anladığımdan emin değilim? Müşteri gerçekten bir http 410 durum kodu görüyor mu?
svrist

1
Vay, bu gerçekten işe yarıyor! Çok şık error_pagenumara, +1! @svrist, böyle bir şeyin nasıl işe yarayacağına ve neden işe yarayacağının tam bir açıklaması için serverfault.com/a/870170/110020 adresine bakın .
cnst
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.