('

只允许已授权的 HTTP 方法:用 Nginx 通过 405/444 拦截无效请求

\n

在运维过程中,查看 Web 应用日志时偶尔会遇到这样的情况。

\n
    \n
  • 我以为只使用 GET / POST / PUT / DELETE
  • \n
  • 日志里却出现了我从未见过的请求方法。
  • \n
\n

例如 PROPFIND 这类 WebDAV 方法会出现在日志中。应用会把它们视为“未支持的方法”来处理,但真正重要的是:

\n

是否真的需要让繁忙的应用去处理这些无用请求?\n答案通常是“不要”。因此,只允许已授权的方法,其他在 Nginx 前端直接拦截,更为简洁。

\n
\n

为什么要在 Nginx 层面拦截?{#sec-b5d4f5f6dfc2}

\n

可以在应用层拦截,但请求到达应用时已经产生了成本。

\n
    \n
  • WSGI/ASGI 入口
  • \n
  • 中间件/日志/认证逻辑部分已执行
  • \n
  • 应用日志被噪声污染,真正的问题被掩盖
  • \n
  • 流量增大时,额外的无用负载会累积
  • \n
\n

相反,在 Nginx 层拦截:

\n
    \n
  • 最前端立即终止 → 成本最小
  • \n
  • 应用日志保持干净 → 运营更顺畅
  • \n
  • 攻击面缩小 → 直接剔除无用方法
  • \n
\n

一句话总结:

\n
\n

应用负责业务,Nginx 负责守门。

\n
\n
\n

日志中偶尔出现的陌生方法大多不是“正常使用”{#sec-7f5126fc3fdf}

\n

PROPFIND 这类 DAV 方法是典型例子。

\n
    \n
  • 可能是扫描者粗略探测 WebDAV 是否开启
  • \n
  • PUT/MKCOL 等方法被误配置为开放,扫描者会继续尝试
  • \n
  • User-Agent 为空或类似 HTTP/1.0 的简易请求也常见
  • \n
\n

核心点是:

\n

如果我们的服务不使用该方法,几乎不可能是正常流量。\n此时就不必把请求送到应用层,友好响应也无意义。

\n
\n

策略很简单:使用 Allowlist(白名单){#sec-84ef31ae1a20}

\n

nginx 作为安全门卫的图示

\n

原则是“只开放必要的,关闭其余”。

\n
    \n
  • 通用网页/静态资源:通常只需 GETHEAD
  • \n
  • API:仅在需要的端点上有限制性地允许 POST/PUT/PATCH/DELETE
  • \n
\n

其余方法(如 PROPFINDMKCOLLOCK 等)\n如果我们不使用,全部拦截,是最简洁的运维方式。

\n
\n

405 vs 444:选择哪种响应方式?{#sec-967ed2222242}

\n

拦截有两种常见方式。

\n

1) 405 Method Not Allowed{#sec-c79f33550d87}

\n
    \n
  • 标准且易于理解
  • \n
  • 对正常客户端错误方法给出明确提示
  • \n
\n

2) 444(Nginx 专用:无响应直接关闭连接){#sec-fe4e18cb7c1d}

\n
    \n
  • 直接断开连接,无任何信息
  • \n
  • 对扫描器/机器人提供更少线索
  • \n
  • 运营上更安静、干净(“把噪声掩埋”)
  • \n
\n

实际操作中常见的组合:

\n
    \n
  • 对无意义的公开方法:使用 444 轻松拦截
  • \n
  • 对可能被正常客户端误用的路径:使用 405 明确告知
  • \n
\n
\n

Nginx 配置示例:两种“只允许已授权方法”模式{#sec-3c7629273a8a}

\n

以下示例便于直接复制使用。

\n

模式 A:默认仅允许 GET/HEAD,API 额外开放所需方法{#sec-42bc13636133}

\n
server {\n    # ... listen/server_name 等 ...\n\n    # 1) 默认:网页/静态资源仅允许 GET/HEAD\n    location / {\n        if ($request_method !~ ^(GET|HEAD)$) { return 444; }  # 或 405\n        proxy_pass http://app;\n    }\n\n    # 2) API:仅允许必要方法\n    location /api/ {\n        if ($request_method !~ ^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS)$) { return 444; }\n        proxy_pass http://app;\n    }\n}\n
\n
    \n
  • / 通常只需 GET/HEAD 即可。
  • \n
  • /api/ 由于 CORS 可能需要 OPTIONS,一并放行。
  • \n
\n

模式 B:仅拦截“陌生方法”(轻量起步){#sec-fa0b2940f799}

\n
location / {\n    if ($request_method ~ ^(PROPFIND|PROPPATCH|MKCOL|COPY|MOVE|LOCK|UNLOCK)$) { return 444; }\n    proxy_pass http://app;\n}\n
\n
    \n
  • 立即剔除常见噪声方法。
  • \n
  • 长期来看,Allowlist(模式 A) 更安全、更易维护。
  • \n
\n
\n

注:虽然 Nginx 的 if 语句有滥用风险,但“立即 return 的简单条件”在实际中相当常见。若想更严格,可使用 limit_except

\n
\n
\n

结论:只允许已授权方法让运维更轻松{#sec-35fe67d750b5}

\n

核心要点:

\n
    \n
  • 陌生方法大多不是正常流量
  • \n
  • 送到应用层会产生成本并污染日志
  • \n
  • 在 Nginx 层只保留已授权方法,其余用 405/444 拦截
  • \n
\n

只需应用一次此模式:

\n
    \n
  • 应用资源消耗更低
  • \n
  • 日志更干净
  • \n
  • 运营更高效
  • \n
', '/media/editor_temp/6/e09dd4fc-f987-43bf-b38f-9ac6c4c594f6.png')