在結合 AWS CloudFront 與 WAF 以加強安全性時,我們遇到了一個奇怪的現象。
「明明應該被 WAF 阻擋的請求,為什麼還是返回 200 OK...?」
查看日誌後確認確實是被 WAF 阻擋,但瀏覽器卻顯示空白頁面,回應代碼卻是 200。究竟發生了什麼事?
本文將詳細解釋這一謎樣現象的原因和機制。
action: "BLOCK"
sc-status: "200"
CloudFront 設定:
- 有自定義錯誤頁面設定
- HTTP 錯誤代碼: 403 Forbidden
- 回應頁面路徑: /index.html
- HTTP 回應代碼: 200 OK # ← 這裡是重點
AWS WAF 設定:
- IP 地址限制規則進行阻擋
- 無自定義回應設定
Lambda@Edge 設定:
- 在 Viewer Request 事件下執行
- Cognito 重定向處理
分析實際的日誌時間戳後,發現以下處理順序:
CloudFront 接收請求
↓
WAF 阻擋請求(紀錄日誌時間)
CloudFront 開始處理自定義錯誤頁面
↓ 403→200 轉換產生內部請求
Lambda@Edge (Viewer Request) 開始執行
CloudFront 記錄最終回應(200 OK)
Lambda@Edge 處理完成
等等...明明被 WAF 阻擋,為什麼 Lambda@Edge 還在執行?
實際上,CloudFront 具有 無法區分「源伺服器的 403 錯誤」和「WAF 的 403 錯誤」的規範。由於此區分不清的規範,即使是被 WAF 阻擋的請求,內部請求仍會執行 Lambda@Edge,最終返回 200 OK。
CloudFront 無法區分來自源伺服器的 HTTP 狀態碼 403 與 AWS WAF 阻擋請求時返回的 HTTP 狀態碼 403
來自 AWS 官方文檔
WAF 返回 403 錯誤
action: "BLOCK"
CloudFront 誤認為「這是源伺服器的 403」
自定義錯誤頁面設定啟動
403 → 200 OK + /index.html
內部請求執行 Lambda@Edge
/index.html
最終返回 200 OK
服務 | 動作 | 日誌結果 |
---|---|---|
WAF | 阻擋請求 | action: "BLOCK" , responseCodeSent: null |
CloudFront | 執行自定義錯誤處理 | sc-status: "200" , x-edge-result-type: "Error" |
Lambda@Edge | ✅ 執行 | Cognito 重定向處理被執行 |
終端用戶 | 接收 200 OK(空白頁面) | 顯示空白頁面 |
用途: 支援 SPA(單頁應用程式)
服務 | 動作 | 日誌結果 |
---|---|---|
WAF | 返回自定義回應 | action: "BLOCK" , responseCodeSent: 403 |
CloudFront | 直接轉發 WAF 回應 | sc-status: "403" , x-edge-result-type: "Error" |
Lambda@Edge | ❌ 未執行 | 沒有日誌記錄 |
終端用戶 | 接收 403 Forbidden | 顯示拒絕訪問頁面 |
用途: 注重安全性
AWS 官方文檔中指出回應的優先順序如下:
此次現象發生的原因是因為 未設定 WAF 自定義回應,導致 CloudFront 自定義錯誤頁面發動。
WAF 自定義回應設定
CloudFront 自定義錯誤頁面
Lambda@Edge 的額外控制
透過設定 WAF 自定義回應,可防止不必要的 Lambda@Edge 執行。
當遇到此現象時的調查方法:
檢查 WAF 日誌
responseCodeSent
為 null
,則有可能是 CloudFront 自定義錯誤在運作。檢查 CloudFront 日誌
x-edge-result-type: "Error"
但 sc-status: "200"
,則表示自定義錯誤頁面正在運作。檢查 Lambda@Edge 日誌
請求 ID 的比對
request-id
追蹤服務間的日誌。「明明在 WAF 阻擋下卻返回 200 OK」 這一現象,是 CloudFront 的正常運作。
關鍵要點:
了解這一規範,可以使我們在支援 SPA 的同時妥善執行安全措施。
希望這對於遇到類似現象的讀者有所幫助!