如何在 nginx 中限制速率,但包括/排除某些 IP 地址?

Jas*_*hen 32 nginx rate-limiting

我可以使用limit_req速率限制对我的服务器的所有请求。

但是,我想取消对某些 IP 地址(即白名单)的速率限制,并对某些其他地址(即我希望低至 1r/s 的某些 IP)使用不同的速率限制。

我尝试使用条件(例如if ( $remote_addr = "1.2.3.4" ) {}),但这似乎只适用于重写规则,不适用于速率限制规则。

sho*_*ser 40

最好避免使用“if”指令。当 limit_req_zone(和 limit_conn_zone)中的键为空时,不应用限制。您可以将其与地图和地理模块结合使用,以创建未应用节流限制的 IP 白名单。

此示例显示如何为来自单个 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;
Run Code Online (Sandbox Code Playgroud)

区域指令必须放置在 http 级别,但是其他指令可以放置在更远的位置,例如在服务器或位置级别以限制其范围或进一步定制限制。

有关更多信息,请参阅 Nginx 文档ngx_http_limit_req_modulengx_http_limit_conn_module

  • 似乎 `geo` 无法映射到变量,因此如果您指定 `$binary_remote_addr` 作为映射值,这将转换为文字字符串 `"$binary_remote_addr"`,而不是变量的值。 (2认同)

小智 5

您可以安全地使用命名位置,例如 if() 块中的“@location”。

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

这样的事情应该工作:

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 / {
         ...
      }
   }
Run Code Online (Sandbox Code Playgroud)

填写“location @slowdown { }”,填写与“location / { } 相同的信息,例如proxy_pass,如果你使用nginx作为反向代理。

  • 哇,这确实有效!非常漂亮的“error_page”技巧,+1!@svrist,请参阅 https://serverfault.com/a/870170/110020 以获取有关此类内容如何工作以及原因的完整说明。 (3认同)