只允許已授權的 HTTP 方法:用 Nginx 以 405/444 封鎖雜訊請求

在運營過程中 tail 伺服器日誌時,偶爾會遇到這樣的情況。

  • 我以為只使用 GET / POST / PUT / DELETE
  • 日誌中卻出現了我從未見過的請求方法。

例如 PROPFIND 這類 WebDAV 方法會顯示在日誌中。雖然應用程式會把它視為「不支援的方法」來處理,但重點是:

是否真的需要讓辛苦開發的應用程式去處理這些雜訊? 答案通常是「不需要」。因此,只允許已授權的方法,將其餘在 Nginx 前端即時切斷,是一個乾淨的做法。


為什麼要在 Nginx 先行攔截?{#sec-b5d4f5f6dfc2}

可以在應用層攔截,但當請求已到達應用時,成本已產生:

  • WSGI/ASGI 進入點
  • 中介層/日誌/認證邏輯部分執行
  • 應用日誌被雜訊污染,真正的問題被掩蓋
  • 流量增加時,無用負載也隨之累積

相反地,在 Nginx 先行攔截:

  • 最前端即時終止 → 成本最小
  • 應用日誌保持乾淨 → 運維更輕鬆
  • 攻擊面縮小 → 直接移除不必要的方法

一句話總結:

應用程式負責產生產品,Nginx 則扮演門衛角色。


日誌中偶爾出現的陌生方法大多不是「正常使用」{#sec-7f5126fc3fdf}

PROPFIND 這類 DAV 方法是「看起來合理」的代表案例。

  • 可能是掃描者隨意測試 WebDAV 是否開啟
  • 若設定失誤,PUT/MKCOL 等方法被開啟,接著嘗試進一步操作
  • User-Agent 可能為空,或像 HTTP/1.0 那樣隨意發送

核心點是:

如果我們的服務不使用該方法,則它幾乎不可能是正常流量。 此時就不需要把請求送到應用層,友善回應也不必要。


策略很簡單:以 Allowlist(允許清單)運營{#sec-84ef31ae1a20}

nginx 這位安全衛士管理出入口的圖像

原則是「只開啟必要的,其他全部關閉」。

  • 通用網頁/靜態資源:通常只需要 GETHEAD
  • API:僅對必要的端點允許 POST/PUT/PATCH/DELETE

其餘方法(如 PROPFINDMKCOLLOCK 等) 若我們不使用,全部封鎖,這是最方便的運營方式。


405 vs 444:選擇哪種回應來切斷?{#sec-967ed2222242}

封鎖方式主要有兩種。

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

  • 標準且易於理解
  • 正常客戶端使用錯誤方法時,明確告知「不允許」

2) 444(Nginx 專用:無回應即斷開連線){#sec-fe4e18cb7c1d}

  • 直接斷開,無任何訊息
  • 減少掃描器/機器人得到線索
  • 運維角度更安靜、乾淨(「把雜訊藏起來」)

實務上常見的做法:

  • 對公開網頁中無意義的方法:使用 444 靜默切斷
  • 對正常客戶端可能犯錯的路徑:使用 405 明確回應

Nginx 設定範例:兩種「允許方法以外即切斷」的模式{#sec-3c7629273a8a}

以下範例提供「直接複製貼上」的格式。

模式 A) 基本只允許 GET/HEAD,API 只允許必要方法{#sec-42bc13636133}

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-fa0b2940f799}

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-35fe67d750b5}

重點很簡單:

  • 陌生方法大多不是正常流量
  • 把請求送到應用層會產生成本,且日誌會被污染
  • 因此在 Nginx 只保留允許的方法,其他以 405/444 切斷

只要套用這個模式:

  • 應用資源消耗減少
  • 日誌更乾淨
  • 運維更順暢