为 Nginx Ingress 中的特定位置设置 limit_req

Set limit_req for specific location in Nginx Ingress

我正在尝试为 Kubernetes ingress-nginx 中的特定路径设置速率限制选项 limit_req 以防止 brute-forcing 身份验证。

我已经使用 ConfigMap 定义了 limit_req_zone

http-snippet: |
      limit_req_zone $the_real_ip zone=authentication_ratelimit:10m rate=1r/s;

接下来,我将使用注释添加自定义位置块:

nginx.ingress.kubernetes.io/configuration-snippet: |
  location ~* "^/authenticate$" {
    limit_req zone=authentication_ratelimit nodelay;
    more_set_headers "x-test: matched";
  }

这会产生 nginx.conf:

server {
# - - 8< - -

  location / {
    # - - 8< - -

    location ~* "^/authenticate$" {
      limit_req zone=authentication_ratelimit nodelay;
      more_set_headers "x-test: matched";
    }

    proxy_pass http://upstream_balancer;

    proxy_redirect                          off;
}

结果是 /authenticate 总是 returns HTTP 503(x-test header)。来自入口访问日志的消息:

<ip> - [<ip>] - - [04/Jan/2019:15:22:07 +0000] "POST /authenticate HTTP/2.0" 503 197 "-" "curl/7.54.0" 172 0.000 [-] - - - - 1a63c9825c9795be1378b2547e29992d

我怀疑这可能是因为嵌套位置块和 proxy_pass 之间存在冲突(但这只是一个大胆的猜测)。

我还尝试过哪些其他选项?

问题是为什么自定义位置块以 503 响应?我该如何调试呢?增加 nginx 日志记录级别会提供有关 503 的更多详细信息吗? 或者更一般的问题:我可以在 ingress-nginx 中注入自定义位置块吗?

这可以通过使用地图和 Requests with an empty key value are not accounted.

这个事实来完成
http-snippets: |
  map $uri $with_limit_req {
    default 0;
    "~*^/authenticate$" 1;
  }
  map $with_limit_req $auth_limit_req_key {
    default '';
    '1'     $binary_remote_addr; # the limit key
  }
  limit_req_zone $auth_limit_req_key zone=authentication_ratelimit:10m rate=1r/s;

并使用注释添加自定义位置块:

nginx.ingress.kubernetes.io/configuration-snippet: |
  limit_req zone=authentication_ratelimit nodelay;

或者如果你使用来自 nginxinc 的入口

nginx.org/location-snippets:
  limit_req zone=authentication_ratelimit nodelay;

在这种情况下,请检查是否需要在地图级别对请求进行速率限制处理。

我的意见:最好在应用级别限制请求,就像在入口级别设置速率限制一样,这取决于入口的数量 pods。