網站日誌裡如果突然出現大量 404、400,常見原因不是正常使用者點錯連結,而是自動掃描器在探測 .env、.git、wp-admin、phpmyadmin、xmlrpc.php 這類路徑。
這類請求會帶來幾個問題:
- access log 被快速刷大
- 錯誤日誌裡充滿無意義記錄
- 靜態網站或反代服務被大量無效請求占用連線
- 真正的問題被掃描噪音淹沒
Nginx 可以用 limit_req 和 limit_conn 做限制。不過要先說明一點:Nginx 原生不能直接按「回應狀態碼是 404 或 400」再限速,因為限速發生在回應產生之前。
實際做法是:對容易產生 404 / 400 的掃描路徑、異常來源和全站高頻請求提前限速。
基本思路
推薦先分成三層:
- 全站溫和限速,避免單個 IP 高频刷站。
- 對常見掃描路徑嚴格限速,並直接返回
404。 - 對單 IP 併發連線數做限制。
更穩妥的上線順序是:先加掃描路徑規則和 access_log off,觀察一天;如果還有大量隨機路徑 404,再加全站 limit_req。
先在 http 裡定義限速池
limit_req_zone 和 limit_conn_zone 必須放在 http {} 裡,不能放進單個站點的 server {}。
可以直接寫到 /etc/nginx/nginx.conf 的 http {} 中:
|
|
也可以新建一個檔案:
|
|
寫入:
|
|
前提是你的 nginx.conf 裡確實在 http {} 中包含了:
|
|
再在 server 裡使用限速池
站點設定檔一般在 /etc/nginx/sites-enabled/www.example.com,裡面通常是 server {}。這裡不能再寫 limit_req_zone,只能使用前面已經定義好的 zone。
示例:
|
|
如果擔心全站限速誤傷,可以先只加掃描路徑這一段:
|
|
這些參數是什麼意思
這一行:
|
|
含義如下:
limit_req_zone:定義請求限速用的計數池。$binary_remote_addr:按客戶端 IP 做限速 key,比$remote_addr更省記憶體。zone=perip_general:20m:建立名為perip_general的共享記憶體區,大小為20m。rate=5r/s:每個 IP 平均每秒允許 5 個請求。
這一行:
|
|
和上面類似,只是更嚴格:
perip_scan:專門給疑似掃描路徑使用。rate=1r/s:每個 IP 每秒只允許 1 個請求。
這一行:
|
|
含義如下:
limit_conn_zone:定義併發連線限制用的計數池。$binary_remote_addr:仍然按客戶端 IP 統計。zone=addr_conn:20m:建立名為addr_conn的連線計數共享記憶體區。
真正限制併發連線數的是:
|
|
意思是:每個 IP 同時最多 20 個連線。
burst 和 nodelay 怎麼理解
例如:
|
|
可以這樣理解:
rate=5r/s:長期平均速率是每秒 5 個請求。burst=30:允許短時間多出來 30 個請求。nodelay:超過平均速率但還沒超過burst時,不排隊等待,直接處理;超過burst才拒絕。
沒有 nodelay 時,Nginx 會嘗試把部分請求排隊延遲處理。對普通網頁來說,nodelay 通常更直觀;對 API 或特別敏感的介面,可以按實際情況調整。
常見錯誤:limit_req_zone 放錯位置
如果看到這樣的報錯:
|
|
意思就是:limit_req_zone 寫進了不允許的位置。
常見錯誤寫法是把它放在 server {} 裡:
|
|
這不行。
一句話記憶:
limit_req_zone是「定義池子」,放http {}。limit_req是「使用池子」,放server {}或location {}。limit_conn_zone是「定義連線池子」,放http {}。limit_conn是「使用連線池子」,放server {}或location {}。
臨時封禁明顯異常 IP
如果日誌裡已經確認某幾個 IP 持續刷請求,也可以先臨時封掉:
|
|
這類 deny 可以放在 server {} 裡,也可以放在具體 location {} 裡。是否長期保留,要看誤傷風險和存取來源。
檢查並重載
改完先檢查設定:
|
|
沒有問題再重載:
|
|
不要直接重啟服務。reload 會讓 Nginx 平滑載入新設定,風險更小。
推薦參數
如果只是普通個人網站或靜態網站,可以先用下面這組:
- 普通頁面:
rate=5r/s到10r/s - 掃描路徑:
rate=1r/s - 掃描路徑
burst=5 - 全站
burst=30 - 單 IP 併發:
10到20
如果正常使用者流量很小,參數可以更嚴格;如果網站有大量圖片、腳本、介面請求,普通頁面限速要放寬一些,避免誤傷真實存取。
最穩的處理方式是分階段上線:
- 先對掃描路徑
access_log off+return 404。 - 再加
perip_scan嚴格限速。 - 觀察一天日誌。
- 如果隨機路徑 404 仍然很多,再開啟全站溫和限速。