惡意機器人無法阻止,改在應用前切斷——在 nginx 階段整理奇怪 URL
nginx blackhole.conf整理奇怪 URL
當把網頁應用公開到網際網路時,無論使用哪個框架,奇怪的請求都會湧入。
- 連不存在的
/wp-admin/ - 沒寫任何 PHP 也會出現
/index.php、/xmlrpc.php .git、.env、/cgi-bin/等敏感檔案/目錄wso.php、shell.php、test.php…
這些不是你自己寫的服務,而是全球掃描器和機器人在「有沒有漏洞?」的 URL。說實話,沒有被這些請求影響的伺服器,幾乎不存在。
幸好如果應用層的防禦機制做得好,大多數會被 400/404 處理。問題在於之後。
- 日誌被污染。 真正使用者請求之前,先被奇怪請求佔滿一半。
- CPU 也被消耗。 「安全」的說法不夠,因為還在做不必要的運算。
- 心情疲憊。
每次查看日誌時,
/wp-login.php佔滿數百行……只看就累。
所以我把這些完全在應用前的 nginx切斷。讓它在主機層面就送進「黑洞」。
本文將整理:
- 為什麼「nginx 第一層阻斷」很有用
- 如何用
blackhole.conf這類檔案管理共通阻斷規則 - 實際可用的 nginx 設定範例
1. 只在應用層阻斷會遺憾的原因
我們常做的基本做法是:
- 路由/控制器不存在的 URL → 404
- 例外處理 → 400/500
- 日誌 → APM / log collector 收集
功能上沒問題,但從運營角度看,還是有幾個痛點。
-
日誌雜訊 * APM、日誌系統的錯誤/404 比例被掃描器拉高。 * 每次都要眼睛分辨「是真正使用者還是掃描器」。
-
層級太低才被阻斷 * 請求已經進到應用,意味著已經經過框架、middleware、路由層。 * 這時才想「為什麼要把它送進來?」。
-
雖小但累積的資源消耗 * 一兩次沒關係,但 24 小時不斷的掃描流量會佔用不少請求數。
因此我偏好在上層把「看不見也沒用」的請求盡量整理,讓它們不進去。
2. 在 nginx 裡做黑洞:直接用 444 斷開
nginx 有一個HTTP 標準之外的自訂狀態碼:
return 444;
- 不回傳任何回應標頭或內容
- 只靜靜地關閉 TCP 連線
- 客戶端只會看到「連線已斷開」的訊息
利用這個,我們可以把「100% 奇怪的 URL」完全不回應,直接斷開。
優點很簡單:
- 不會到達應用層(框架 CPU 0)
- 依設定可完全不寫入 access 日誌
- 所有「奇怪 URL」都在 nginx 一層過濾,應用日誌變得乾淨
3. 用一個 blackhole.conf 管理規則
不想每個 server block 都寫相同規則,我通常會放一個 blackhole.conf,把共通模式集中起來。
範例:
# /etc/nginx/blackhole.conf(路徑自行決定)
# === 1. 隱藏/配置目錄 (.git, .env, IDE 等) ===
location ~* (^|/)\.(git|hg|svn|bzr|DS_Store|idea|vscode)(/|$) { return 444; }
location ~* (^|/)\.env(\.|$) { return 444; }
location ~* (^|/)\.(?:bash_history|ssh|aws|npm|yarn)(/|$) { return 444; }
# === 2. 未使用的 CMS 管理/漏洞掃描 ===
location ^~ /administrator/ { return 444; } # Joomla 等
location ^~ /phpmyadmin/ { return 444; } # 未使用時
# === 3. PHP/CGI/WordPress 痕跡 ===
# 只建議在完全不使用 PHP 的堆疊(如純 Node、Go、Python)中使用
location ~* \.(?:php\d*|phtml|phps|phar)(/|$) { return 444; }
location ^~ /cgi-bin/ { return 444; }
location ~* ^/(wp-admin|wp-includes|wp-content)(/|$) { return 444; }
# === 4. 掃描器常抓的檔案/路徑 ===
location ~* ^/(?:info|phpinfo|test|wso|shell|gecko|moon|root|manager|system_log)\.php(?:/|$)? {
return 444;
}
location ~* ^/(?:autoload_classmap|composer\.(?:json|lock)|package\.json|yarn\.lock|vendor)(?:/|$) {
return 444;
}
location ~* ^/(?:_profiler|xmrlpc|xmlrpc|phpversion)\.php(?:/|$)? {
return 444;
}
# === 5. 備份/臨時/轉儲檔案 ===
location ~* \.(?:bak|backup|old|orig|save|swp|swo|tmp|sql(?:\.gz)?|tgz|zip|rar)$ {
return 444;
}
# === 6. well-known:只允許 ACME,其他全部斷開 ===
location ^~ /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
location ^~ /.well-known/ {
return 444;
}
# === 7. 方法保護(選項):幾乎不使用的方法先阻斷 ===
# TRACE、CONNECT、WebDAV 系列方法若不使用,提前阻斷
if ($request_method !~ ^(GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS)$) {
return 405;
}
把這個檔案放好後,只需在每個 server block 加一行:
http {
# ...
server {
listen 80;
server_name example.com;
include /etc/nginx/blackhole.conf;
# 其餘正常路由設定...
}
}
這樣大多數「未使用路徑的漏洞掃描」就會在 nginx 先以 444 結束,永遠不會到達應用。
4. 想進一步降低日誌雜訊(選項)
即使已經這樣做,若想讓這些進入黑洞的請求完全不寫入 access_log,可以用 map 來控制。
http {
# 想要被黑洞的模式,減少日誌
map $request_uri $drop_noise_log {
default 0;
~*^/(?:\.git|\.env) 1;
~*^/(wp-admin|wp-includes|cgi-bin) 1;
~*\.php(?:/|$) 1;
}
server {
listen 80;
server_name example.com;
include /etc/nginx/blackhole.conf;
# 只有 $drop_noise_log 為 0 時才寫入 access 日誌
access_log /var/log/nginx/access.log combined if=$drop_noise_log;
}
}
$drop_noise_log為 1 的請求不寫日誌。- 真正使用者請求、正常路由仍會乾淨記錄。
實際運營時,建議先開啟日誌,驗證模式無誤後,再改成 if=$drop_noise_log。
5. 避免誤封(正常請求被阻斷)的指引
這類阻斷規則最重要的是不要過度攻擊性。以下幾點可作參考:
-
只啟用符合堆疊的規則 * 完全不使用 PHP 的專案可直接封鎖
.php。 * 若實際使用 Laravel、WordPress,則必須把.php規則排除。 * 同理,若真的使用/cgi-bin,則不要封鎖。 -
先用 404/403 測試 * 先用
return 403;或return 404;,觀察幾天是否真的不會被正常使用者觸發,再改成 444。 -
對危險路徑保守 *
.git、.env、備份檔、phpinfo.php等,即使誤封也不會影響運營。 -
位置與優先順序 * nginx 的
location匹配優先順序(精確、前綴、正則)很重要。 * 通常把include blackhole.conf放在 server block 的最前面,之後再放主路由location / { ... },即可避免覆蓋。
6. 應用、WAF、nginx:各自擅長的地方
本文介紹的方式僅是「第一層噪音過濾」的手段。
- nginx 黑洞:剔除「不應存在」的路徑,減少不必要的連線。
- 應用層驗證:域名邏輯、權限、輸入驗證等服務專屬安全。
- WAF/安全解決方案:模式/簽名攻擊、L7 DDoS、精細機器人過濾。
各層不應互相取代,而是互補。nginx 黑洞是最簡單、最有效、成本低的技巧,值得先行部署。
結語
公開到網際網路的服務,無法完全避免「奇怪 URL」掃描。但可以改變觀點:
「不管怎樣都會來,先在 nginx 前靜靜地把它們切斷」
用一個 blackhole.conf 管理共通規則,並以 444 回應,能讓應用日誌更乾淨、監控更簡單、伺服器資源更寬裕。
最重要的是,當你凌晨 2 點打開日誌,看到的不是無盡的 /wp-login.php 行列,而是「真正使用者」的請求,這種感覺真的很愉快。
如果你已經有 nginx,趕快試試這個小技巧,幾天後你會想:「為什麼我沒早點做?」

目前沒有評論。