# 只允许已授权的 HTTP 方法:用 Nginx 通过 405/444 拦截无效请求 在运维过程中,查看 Web 应用日志时偶尔会遇到这样的情况。 * 我以为只使用 `GET / POST / PUT / DELETE`, * 日志里却出现了我从未见过的请求方法。 例如 `PROPFIND` 这类 WebDAV 方法会出现在日志中。应用会把它们视为“未支持的方法”来处理,但真正重要的是: **是否真的需要让繁忙的应用去处理这些无用请求?** 答案通常是“不要”。因此,**只允许已授权的方法,其他在 Nginx 前端直接拦截**,更为简洁。 --- ## 为什么要在 Nginx 层面拦截? {#sec-90b3911976bd} 可以在应用层拦截,但请求到达应用时已经产生了成本。 * WSGI/ASGI 入口 * 中间件/日志/认证逻辑部分已执行 * 应用日志被噪声污染,真正的问题被掩盖 * 流量增大时,额外的无用负载会累积 相反,在 Nginx 层拦截: * **最前端立即终止** → 成本最小 * **应用日志保持干净** → 运营更顺畅 * **攻击面缩小** → 直接剔除无用方法 一句话总结: > **应用负责业务,Nginx 负责守门。** --- ## 日志中偶尔出现的陌生方法大多不是“正常使用” {#sec-f102fcd518d6} `PROPFIND` 这类 DAV 方法是典型例子。 * 可能是扫描者粗略探测 WebDAV 是否开启 * 若 `PUT/MKCOL` 等方法被误配置为开放,扫描者会继续尝试 * User-Agent 为空或类似 HTTP/1.0 的简易请求也常见 核心点是: **如果我们的服务不使用该方法,几乎不可能是正常流量。** 此时就不必把请求送到应用层,友好响应也无意义。 --- ## 策略很简单:使用 Allowlist(白名单) {#sec-eacfac10c9aa} ![nginx 作为安全门卫的图示](/media/editor_temp/6/e09dd4fc-f987-43bf-b38f-9ac6c4c594f6.png) 原则是“只开放必要的,关闭其余”。 * 通用网页/静态资源:通常只需 `GET`、`HEAD` * API:仅在需要的端点上有限制性地允许 `POST/PUT/PATCH/DELETE` 其余方法(如 `PROPFIND`、`MKCOL`、`LOCK` 等) **如果我们不使用,全部拦截**,是最简洁的运维方式。 --- ## 405 vs 444:选择哪种响应方式? {#sec-593da51fcb33} 拦截有两种常见方式。 ### 1) 405 Method Not Allowed {#sec-be0627073a68} * 标准且易于理解 * 对正常客户端错误方法给出明确提示 ### 2) 444(Nginx 专用:无响应直接关闭连接) {#sec-d4f26b34d96b} * 直接断开连接,无任何信息 * 对扫描器/机器人提供更少线索 * 运营上更安静、干净(“把噪声掩埋”) 实际操作中常见的组合: * 对无意义的公开方法:使用 444 轻松拦截 * 对可能被正常客户端误用的路径:使用 405 明确告知 --- ## Nginx 配置示例:两种“只允许已授权方法”模式 {#sec-5bc19948ad1f} 以下示例便于直接复制使用。 ### 模式 A:默认仅允许 GET/HEAD,API 额外开放所需方法 {#sec-bfdd542a57ed} ```nginx server { # ... listen/server_name 等 ... # 1) 默认:网页/静态资源仅允许 GET/HEAD location / { if ($request_method !~ ^(GET|HEAD)$) { return 444; } # 或 405 proxy_pass http://app; } # 2) API:仅允许必要方法 location /api/ { if ($request_method !~ ^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS)$) { return 444; } proxy_pass http://app; } } ``` * `/` 通常只需 `GET/HEAD` 即可。 * `/api/` 由于 CORS 可能需要 `OPTIONS`,一并放行。 ### 模式 B:仅拦截“陌生方法”(轻量起步) {#sec-d1362ebe0b39} ```nginx location / { if ($request_method ~ ^(PROPFIND|PROPPATCH|MKCOL|COPY|MOVE|LOCK|UNLOCK)$) { return 444; } proxy_pass http://app; } ``` * 立即剔除常见噪声方法。 * 长期来看,**Allowlist(模式 A)** 更安全、更易维护。 > 注:虽然 Nginx 的 `if` 语句有滥用风险,但“立即 return 的简单条件”在实际中相当常见。若想更严格,可使用 `limit_except`。 --- ## 结论:只允许已授权方法让运维更轻松 {#sec-85a3150cf87a} 核心要点: * 陌生方法大多不是正常流量 * 送到应用层会产生成本并污染日志 * **在 Nginx 层只保留已授权方法,其余用 405/444 拦截** 只需应用一次此模式: * 应用资源消耗更低 * 日志更干净 * 运营更高效