Làm cách nào để giới hạn tỷ lệ trong nginx, nhưng bao gồm / không bao gồm các địa chỉ IP nhất định?


27

Tôi có thể sử dụng limit_reqđể giới hạn tỷ lệ tất cả các yêu cầu đến máy chủ của mình.

Tuy nhiên, tôi muốn xóa giới hạn tốc độ cho một số địa chỉ IP nhất định (ví dụ như danh sách trắng) và sử dụng hạn chế tốc độ khác nhau cho một số địa chỉ khác (ví dụ: một số IP nhất định tôi muốn ở mức thấp nhất là 1r / s).

Tôi đã thử sử dụng các điều kiện (ví dụ if ( $remote_addr = "1.2.3.4" ) {}) nhưng dường như chỉ hoạt động với các quy tắc viết lại, không phải cho các quy tắc giới hạn tỷ lệ.

Câu trả lời:


33

Nó thực sự tốt hơn để tránh sử dụng chỉ thị "nếu". Khi khóa trong giới hạn numq_zone (và giới hạn_conn_zone) trống, các giới hạn không được áp dụng. Bạn có thể sử dụng kết hợp với các mô-đun bản đồ và địa lý để tạo danh sách trắng các IP nơi giới hạn bướm ga không được áp dụng.

Ví dụ này cho thấy cách định cấu hình giới hạn cho cả yêu cầu đồng thời và tốc độ yêu cầu từ một 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;

Các chỉ thị vùng phải được đặt ở cấp http, tuy nhiên các chỉ thị khác có thể được đặt xuống phía dưới, ví dụ như ở máy chủ hoặc cấp vị trí để giới hạn phạm vi của chúng hoặc điều chỉnh thêm các giới hạn.

Để biết thêm thông tin, hãy tham khảo tài liệu Nginx ngx_http_limit_Vq_modulengx_http_limit_conn_module


Sự khác biệt giữa 2 mô-đun này là gì?
Mente

1
Theo các bình luận, lần đầu tiên giới hạn các kết nối đồng thời, lần thứ hai giới hạn tốc độ kết nối
người dùng linux shonky

Bạn có thể giải thích lý do tại sao bạn thực hiện ánh xạ theo hai giai đoạn, geotheo sau là mapthay vì chỉ sử dụng geođể đặt $limittrực tiếp không?
Marcus Downing

2
Dường như geokhông thể ánh xạ tới một biến vì vậy nếu bạn chỉ định $binary_remote_addrlàm giá trị ánh xạ, nó sẽ dịch thành chuỗi ký tự "$binary_remote_addr"chứ không phải giá trị của biến.
ColinM

1
Tôi muốn thêm rằng nếu IP trong câu hỏi đã có trong vùng, bạn phải khởi động lại nginx; tải lại là không đủ.
Halfgaar

5

Bạn có thể sử dụng các vị trí được đặt tên một cách an toàn, chẳng hạn như "@location" trong khối if ().

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

Một cái gì đó như thế này sẽ hoạt động:

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

Điền vào "location @slowdown {}" với cùng thông tin như "location / {}, chẳng hạn như proxy_pass nếu bạn đang sử dụng nginx làm proxy ngược.


Tôi không chắc là tôi hiểu phần 410? Khách hàng có thực sự thấy mã trạng thái http 410 không?
Svrist

1
Wow, điều này thực sự hoạt động! error_pageThủ thuật rất tiện lợi , +1! @svrist, xem serverfault.com/a/870170/110020 để được giải thích đầy đủ về cách thức hoạt động của một cái gì đó như thế này, và tại sao.
cnst
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.