自己過去比較少在看 runtime log,除非有接到 error 的通知才會稍微看一下。直到後來我在後端 service 的 log,突然注意到大量異常的請求進來,才意識到網站可能正遭受攻擊。本文將分享我如何透過 Cloudflare WAF 建立完整的防護機制,有效阻擋惡意流量。
Written by: Chia1104 CC BY-NC-SA 4.0
當我檢視後端 service 的 log 時,發現了這類異常的請求:


其中這個 wp的路徑就是 WordPress 的路徑,由於自己的網站是用 Next.js 跟 Hono 寫的,也沒有 PHP 的程式碼,所以當下接收到這請求也是挺納悶的。
後來自己稍微觀察後很多都是針對 .php、.git、.env 做訪問,我們之後可以特別針對這幾個路徑寫防火牆的規則。這些都是攻擊者常用來探測網站漏洞的路徑。
但原本沒想太多,以為請求次數不多並且都用 GET 在打,就以為沒什麼問題。直到後來次數開始越來越多,而且連我的前後台(www、dashboard)都有觀察到這些 log 才意識到不太對勁。並且那時候最多一次有 600 多筆進來(雖然比不上真正的 DDoS XDD),當下是先開啟了 Vercel 的 Attack Challenge Mode。

一開始先在 Vercel 設定防火牆的規則,但他們能設定的相對簡單。比如說我想要一個規則是「直接忽略(一律允許)Google 或 Bing SEO Bot」,這裡就沒有對應的選項,而 Cloudflare 有直接提供已知的機器人選項來避免影響 SEO。

所以後來我就透過 Cloudflare CNAME 的 Proxy 來限流,希望可以透過調整 WAF 的規則來阻擋非正常的流量。

Cloudflare 在 Proxy 流量的時候有一個固定的處理順序,我們可以依照這個順序去調整自己想要的規則:

我主要從以下四個層面來建立防護機制:
DDoS 攻擊可能會減緩或關閉服務,一秒內進來原點的請求量甚至可以高達好幾億。但 Cloudflare 都可以幫忙阻擋這部分的攻擊。
自動化 DDoS 保護也能持續分析流量並即時產生流量簽章,來緩解整個網路及應用程式層的攻擊。

這裡直接點右上角的 部署 DDoS 覆寫 即可設定 DDoS 的防禦方式,我們就直接開啟就可以了。

這裡我們可以特別針對對應的 IP、國家跟 ASN 做限制。
自主系統(AS)是具有單一路由原則的大型網路或網路群組。每一個 AS 都會被指派一個唯一的 ASN,這是識別 AS 的號碼。類似於每個企業都擁有帶有唯一官方編號的營業執照,但與企業不同,外部各方通常僅透過其號碼來引用 AS。 - 什麽是自發系統| 什麼是 ASN?
我這裡是直接把部分主機的識別碼給封鎖了。至於為什麼呢?只能說當今天如果是真人來訪問你的網站時,總不可能是用 AWS 機房的電腦來訪問吧 XDD,所以當如果看到類似的請求就直接列入黑名單。

不過這裡提醒一下,建議在這裡把少數列進來就行了,例如:DIGITALOCEAN - AS14061。主要是我們也需要允許 Google 或 Bing 等的 SEO Bot 進來,我們可以到防火牆那層做更細部的設定。
這裡的 機器人對抗模式 也是我想要換來 Cloudflare 的其中一個原因,它可以自動解析那些進來的請求是不是不良的機器人。



以這兩個請求來看,可能只有第一個的 User-Agent 不太正常。如果單就 log 第一時間可能也不會注意到第二個有問題,而這裡我們透過 Cloudflare 自動篩選出來做驗證,更能大幅減少不必要的流量。
Cloudflare 透過機器學習的方式來辨識更為分散的 IP 請求,特別是針對使用住宅代理(Residential Proxy)的攻擊。這類攻擊較難偵測,因為它們使用真實住宅 IP 地址,但 Cloudflare 的機器學習模型能夠識別其行為模式。
詳細資訊請參考:Using machine learning to detect bot attacks that leverage residential proxies - Cloudflare
其實 cloudflare 這裡可以透過機器學習的方式來辨識更為分散的 IP 請求
最後就是我們的防火牆設定,這邊能設定的規則就比較多,其中免費的方案能設定 5 條規則。
這邊也記錄一下我這裡設定的幾個方法:

這次的攻擊幾乎都是針對 .php 的路徑做請求,雖然網站本身不包含這些頁面,但這些無效請求若是一直進來,除了影響網站原有的 log 資料,更是會讓第三方的分析工具記錄到不必要的資訊,所以後來直接選擇封鎖這類的請求。
cf.waf.score(WAF 攻擊分數)是 Cloudflare 透過機器學習演算法評估請求惡意程度的分數,範圍從 1 到 99,其中 1 表示幾乎確定是惡意請求,99 表示幾乎確定是正常請求。

重要提醒:舊版的 cf.threat_score 已於 2025 年棄用,目前該分數永遠返回 0,請改用 cf.waf.score 作為評估指標。
一般建議是查問分數低於 50 的請求,並可考慮阻止分數低於 20 的請求。但實際設定時需要監控是否有誤判情況,避免封鎖合法使用者。

就如同前面所提的,我們可以調整細部的 ASN 規則,如以下常見的雲平台:
不過這裡的規則記得要判斷是不是 已知的機器人 因為部分 SEO Bot 的 ASN 也來自同樣的地方
| 名稱 | ASN 編號 |
|---|---|
| MICROSOFT-CORP-MSN-AS-BLOCK(Azure) | AS8075 |
| AMAZON-02(AWS) | AS16509 |
| GOOGLE-CLOUD-PLATFORM(GCP) | AS396982 |
透過 ASN 的阻擋是我覺得最有效的,有時候上一層的 機器人對抗模式 不一定都擋得掉。後來我這裡剩下到防火牆的流量至少有 7 成是這個規則幫忙擋掉的。
剛剛上面那張圖大家應該有注意到我特別檢查了請求的網址是否包含 /.well-known/acme-challenge,這路徑主要是我們跟 Vercel 或 Zeabur 續訂 SSL 證書用的。
Vercel 使用 Let's Encrypt 提供的 ACME HTTP-01 挑戰來驗證域名所有權。當 SSL 證書快過期時,Vercel 會發送請求到 <YOUR_DOMAIN>/.well-known/acme-challenge 做驗證。
這裡不用擔心流量會因為這裡而炸掉,因為這個路徑是 Vercel 自家的 proxy server 的路徑。
Cloudflare 防火牆的規則有提供判斷已知的機器人功能。

但在某些情境若未正確允許 SEO Bot,則會導致網頁做 index 的時候被 403 拒絕。

以這個情境我們想要限制所有的路徑都被受控查問,但這就會導致 SEO Bot index 被拒絕,當他們要做 index 的時候會先被 cloudflear 403

這裡的修改方式其實直接多寫一個判斷,若也不是「已知機器人」就可以了:
and not cf.client.bot
我們可以直接透過 Google Search Consol 的搜尋審查來檢查該網址是否被 403

其實自己一直以來部署的網頁應用都是透過其他的 PaaS 平台部署的,像是 Zeabur 或是 Vercel
很多 proxy 或防 DDoS 的方式其實內部都幫忙實作掉了,平常也比較少去調研這塊,這次也藉了這機會嘗試 cloudflare 的不同設定並加強網站的防護以減少不必要的流量
