nginx 请求限制会产生 404 响应,除了超出限制的情况

nginx 请求限制会产生 404 响应,除了超出限制的情况

给出以下配置(简化为相关部分):

/etc/nginx/nginx.conf:

http {
  # ... general configuration stuff here ...

  map $http_user_agent $isbot_ua {
    default 0;
    ~*(GoogleBot|bingbot|YandexBot|mj12bot|PetalBot|SemrushBot|AhrefsBot|DotBot|oBot) 1;
  }

  map $isbot_ua $limit_bot {
    0       "";
    1       $binary_remote_addr;
  }

  limit_req_zone $limit_bot zone=bots:10m rate=2r/m;
  limit_req_log_level warn;
  limit_req_status 429;

  include sites.d/vhost_*.conf;
}

/etc/nginx/sites.d/vhost_example.org.conf:

server {
  # ... general vhost config here ...

  location / {
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ ^(.+?\.php)(/.*)?$ {
    try_files /does-not-exist-099885c5caef6f8ea25d0ca26594465a.htm @php;
  }

  location @php {
    try_files $1 =404;

    include /etc/nginx/fastcgi_params;
    fastcgi_split_path_info ^(.+\.php)(/.+)\$;
    fastcgi_param SCRIPT_FILENAME $document_root$1;
    fastcgi_param PATH_INFO $2;
    fastcgi_param HTTPS on;
    fastcgi_pass unix:/var/lib/php/11-example.org-php-fpm.socket;
    fastcgi_index index.php;
  }
}

在/etc/nginx/fastcgi_params中:

limit_req zone=bots burst=5 nodelay;

# ... more fastcgi_param here ...

问题如下:

每个与机器人 UA 匹配的请求(无论是通过映射到的虚拟 URL/index.php还是直接指向的本机 URL index.php)都将导致响应代码 404 而不是预期代码 200 - 除非当它突然以预期代码 429 响应时我超出速率限制。

如果我将地图更改为:

  map $request_uri $is_req_limited {
    default 0;
#    ~*(GoogleBot|bingbot|YandexBot|mj12bot|PetalBot|SemrushBot|AhrefsBot|DotBot|oBot) 1;
  }

在这种情况下,所有请求都会得到 200 的答复。如果我没有匹配任何机器人,情况也是如此。

问题是:它在我们的部署前测试中运行正常,该测试具有更简单的 vhost 配置(我们limit_req在部署期间从全局配置移至 fastcgi 部分,因为我们只想匹配页面生成,缓存页面和静态资源都可以)。这完全毁掉了我们网站的 SEO 排名。

测试所用命令:

# Causes the problem:
for i in $(seq 1 30) do; curl -Is -A GoogleBot https://example.org/ | head -n1; done

# Does not cause the problem:
for i in $(seq 1 30) do; curl -Is -A ThisIsNotABot https://example.org/ | head -n1; done

这是错误还是配置错误?如果是错误,是否可以解决?

边注:几乎不可能阻止这种有点奇怪的配置,因为它是由主机管理软件(Froxlor)生成的,但我认为它可能会导致问题。我们也无法在此处添加或修改任何配置:

location ~ ^(.+?\.php)(/.*)?$ {
  try_files /does-not-exist-099885c5caef6f8ea25d0ca26594465a.htm @php;
}

location @php {
  try_files $1 =404;
  #...

我不知道是否limit_req将其放置在里面会更好location ~ ^(.+?\.php)(/.*)?$,但另一方面,location @php应该同样好。

答案1

哎呀,如果我理解正确的话,这个问题很难回答,尤其是因为配置是由 Froxlor 生成的。不过,我可以尝试引导您找到正确的方向,这样您就可以与 Froxlor 开发人员联系。

因此,这取决于我对 Nginx 的了解。据我从您的问题中了解到,这看起来不像是一个错误。但更像是一个配置/顺序问题。以下是我这么认为的原因:

当请求进入时/,Nginx 首先检查位置块以查看将请求路由到哪里。在您的配置中,@php由于您的try_file指令,此请求被路由到该位置。因此,limit_reqfastcgi_params 文件中应用的指令仅影响由 FastCGI 处理的请求。但正如您所描述的,机器人正在攻击/由 Nginx 直接处理的请求。

我的意见是,如果将limit_req指令移动到位置/配置块,如下所示:

location / {
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php$is_args$args;
    limit_req zone=bots burst=5 nodelay;
  }

您应该注意到,所有传入请求(无论是由 Nginx 还是 FastCGI 机器人处理)都受到速率限制。而且您不应该再收到突然出现的奇怪的 404 错误。

点击此处查看更多相关信息:Nginx 中的速率限制

相关内容