【问题标题】:How to set Nginx URI to fix empty URI in redirect to named location如何设置 Nginx URI 以修复重定向到命名位置的空 URI
【发布时间】:2017-03-21 16:51:41
【问题描述】:

问题:当使用包含“%”符号的无效 URL 访问我们的网站时,Nginx 会抛出 400 Bad Request 错误。

我们想将请求重写为(WordPress)404 页面,而不是 Nginx 页面。

我尝试了以下方法:

location @400 {
    rewrite ^ /404 break;
}

error_page 400 =307 @400;

但是,这会在 Nginx 上生成 500 Internal Server Error。

Nginx 错误日志说:'... 读取客户端请求行时重定向到命名位置“@400”的空 URI...,请求:“GET ”'。

这并不意外,因为原始 URL 无效。

所以我想我正在寻找的是为重写明确设置 URI。这个怎么做?还是有更好的方法?我对 Nginx 不是很熟悉。

【问题讨论】:

    标签: php wordpress nginx nginx-location


    【解决方案1】:

    我有相同的目标(返回 444 而不是自定义错误消息)并且使用@named_location 遇到了相同的问题(对于某些奇怪的请求,特别是当标头中没有设置 POST/GET/HEAD 方法时,Nginx 返回其默认值500错误页面和错误日志报告:empty URI in redirect to named location "@named_location" while reading client request)。

    Someone had opened a ticket with Nginx,这是回复:

    [...] 问题是您试图将出现在早期请求处理阶段的错误(当请求 URI 尚未解析时)重定向到指定位置。命名位置旨在保留现有的请求 URI,将这种不完整的请求重定向到命名位置可能会导致代码的其他部分出现严重问题。因此,尝试执行此类重定向会导致“重定向到指定位置的空 URI”错误。这反过来又可以防止使用您的自定义错误页面,因此会返回一个内部错误页面。 如果您想处理在早期请求处理阶段出现的错误,例如 400 Bad Request,请考虑使用带有明确设置 URI 的错误页面。或者您可以避免尝试重定向此类错误,因为这通常是更安全的方法。 请注意,服务器是 nginx 的事实并不是信息泄漏。无论如何,它以多种方式报告,包括服务器响应标头。如果你出于某种原因想要隐藏 nginx 版本,可以通过 server_tokens 指令来实现。

    所以我修改了错误自定义如下:

    error_page 301 400 403 404 500 502 503 504 =444 /444.html;
    location = /444.html {
            return 444;
    }
    
    # Instead of:
    # error_page 301 400 403 404 500 502 503 504 =444 @named_location;
    # location @named_locations {
    #         return 444;
    # }
    # which gives the above-mentioned error and returns Nginx's default 500 error page.
    
    

    这似乎解决了问题。

    【讨论】:

      【解决方案2】:

      根据documentation,代码应该有点不同。

      这是从文档中复制的重写:

      location /old/path.html {
          error_page 404 =301 http:/example.com/new/path.html;
      }
      

      问题是它是否会像这样工作:

      location 400 {
          error_page 400 =307 http:/example.com/400.html;
      }
      

      ...因为在您链接的 github-page 上写着:

      如果在配置中使用类似“error_page 400 @name”的内容,则 可以将请求传递到没有设置 URI 的命名位置,并且这个 反过来可能会导致分段错误或其他不良影响,因为 大多数代码都假定设置了 URI。

      有了这个改变,nginx 会在 ngx_http_named_location() 如果 URI 为 未设置,返回 500。

      如果这仍然是当前状态,则意味着 400 错误会在 nginx 中触发 500 错误。尽管如此,我还是可以触发 400 错误并仅使用此配置提供自定义 400 页面:

      error_page 400 /400.html;
      

      所以你也可以尝试配置一个自定义的错误 500 页面,但我从来没有运行过,而是只显示了 nginx 的常见 500er 页面。

      你可以试试这个配置

      error_page 400 /400.html;
      error_page 404 /404.html;
      error_page 500 /500.html;
      

      如果这有效,您可以调整 3xx 代码,使其更符合您的需要。 当然,您也可以在 400 错误时提供 404 错误页面,但我从未成功地像这样重写错误标题:

      error_page 404 =301 http:/example.com/new/path.html;
      

      【讨论】:

      • 不完全是我正在寻找的答案,但仍然是 OP 正在寻找的答案。
      • 我试图做的是为没有 Host 标头的请求返回 444(关闭连接)。这些请求都来自扫描仪,我什至不希望他们知道该端口上正在运行 NGINX 服务器(可能毫无意义,但 有趣)。这适用于大多数请求,除了一些扫描仪发送了奇怪的请求,导致 400 错误请求。对于这些请求,NGINX 会返回一个不错的错误页面,这是我不想要的。将error_page 400...return 444 结合起来可以,但会保持连接打开。 NGINX 试图对 444 资源进行内部重定向?不好。
      • @Gerben 所以 444 的触发器应该总是 400?
      • 一切都是 444。即没有Host 标头的任何请求都没有响应。包括格式错误的请求 (400)
      • @Gerben 正确的 444 仅由 Degradation Module 返回。您可能必须编译自己的版本,或者至少实现自己的模块。
      猜你喜欢
      • 2017-04-27
      • 1970-01-01
      • 1970-01-01
      • 2016-06-16
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      相关资源
      最近更新 更多