站長阿川

站長阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

站長精心設計,帶你實作 63 個小專案,得到作品集!

立即開始免費試讀!

前言

在結合 AWS CloudFront 與 WAF 以加強安全性時,我們遇到了一個奇怪的現象。

「明明應該被 WAF 阻擋的請求,為什麼還是返回 200 OK...?」

查看日誌後確認確實是被 WAF 阻擋,但瀏覽器卻顯示空白頁面,回應代碼卻是 200。究竟發生了什麼事?

本文將詳細解釋這一謎樣現象的原因和機制。

🔍 問題現象

觀察到的症狀

  • WAF 日誌: 記錄為 action: "BLOCK"
  • CloudFront 日誌: 顯示 sc-status: "200"
  • 瀏覽器: 顯示空白頁面(內容為空)
  • Lambda@Edge: 不知為何仍在執行

設定情況

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 自定義錯誤頁面的機制

真相

實際上,CloudFront 具有 無法區分「源伺服器的 403 錯誤」和「WAF 的 403 錯誤」的規範。由於此區分不清的規範,即使是被 WAF 阻擋的請求,內部請求仍會執行 Lambda@Edge,最終返回 200 OK。

CloudFront 無法區分來自源伺服器的 HTTP 狀態碼 403 與 AWS WAF 阻擋請求時返回的 HTTP 狀態碼 403
來自 AWS 官方文檔

處理流程

  1. WAF 返回 403 錯誤

    • 請求符合 IP 地址限制規則
    • WAF: action: "BLOCK"
  2. CloudFront 誤認為「這是源伺服器的 403」

    • 實際上是來自 WAF 的 403,但 CloudFront 無法區分
  3. 自定義錯誤頁面設定啟動

    • 設定: 403 → 200 OK + /index.html
    • 這個「403→200 轉換」設定會產生新的內部請求
  4. 內部請求執行 Lambda@Edge

    • 請求 /index.html
    • 在 Viewer Request 事件下 Lambda@Edge 執行
  5. 最終返回 200 OK

    • 實際內容無法取得,故顯示空白頁面

📋 兩種動作模式比較

模式 A: 只有 CloudFront 自定義錯誤設定

WAF-a.png

服務 動作 日誌結果
WAF 阻擋請求 action: "BLOCK", responseCodeSent: null
CloudFront 執行自定義錯誤處理 sc-status: "200", x-edge-result-type: "Error"
Lambda@Edge 執行 Cognito 重定向處理被執行
終端用戶 接收 200 OK(空白頁面) 顯示空白頁面

用途: 支援 SPA(單頁應用程式)

模式 B: 同時使用 WAF 自定義回應 + CloudFront 自定義錯誤

WAF-b.png

服務 動作 日誌結果
WAF 返回自定義回應 action: "BLOCK", responseCodeSent: 403
CloudFront 直接轉發 WAF 回應 sc-status: "403", x-edge-result-type: "Error"
Lambda@Edge 未執行 沒有日誌記錄
終端用戶 接收 403 Forbidden 顯示拒絕訪問頁面

用途: 注重安全性

🏗️ AWS 官方的優先順序規則

AWS 官方文檔中指出回應的優先順序如下:

  1. WAF 自定義回應(最高優先)
  2. CloudFront 自定義錯誤頁面
  3. WAF 默認回應(403 Forbidden)

此次現象發生的原因是因為 未設定 WAF 自定義回應,導致 CloudFront 自定義錯誤頁面發動。

⚡ 解決方案與建議設定

🎯 若希望兼顧 SPA + 安全性

  1. WAF 自定義回應設定

    • 確保不當訪問返回 403
  2. CloudFront 自定義錯誤頁面

    • S3 源的 404/403(用於路由)返回 200 + index.html
  3. Lambda@Edge 的額外控制

    • 根據請求標頭或 IP 地址進行更細的判斷

💰 若重視成本優化

透過設定 WAF 自定義回應,可防止不必要的 Lambda@Edge 執行。

⚠️ 注意事項

  • 考慮安全性: 即使請求被 WAF 阻擋,Lambda@Edge 仍有可能執行,因此需在 Lambda@Edge 內也實施安全控制。
  • 成本因素: 若希望避免不必要的 Lambda@Edge 執行,則應設定 WAF 自定義回應。

🔍 偵錯要點

當遇到此現象時的調查方法:

  1. 檢查 WAF 日誌

    • 如果 responseCodeSentnull,則有可能是 CloudFront 自定義錯誤在運作。
  2. 檢查 CloudFront 日誌

    • 如果 x-edge-result-type: "Error"sc-status: "200",則表示自定義錯誤頁面正在運作。
  3. 檢查 Lambda@Edge 日誌

    • 如果 WAF 阻擋卻有日誌記錄,則表示生成了內部請求。
  4. 請求 ID 的比對

    • 通過同一 request-id 追蹤服務間的日誌。

總結

「明明在 WAF 阻擋下卻返回 200 OK」 這一現象,是 CloudFront 的正常運作。

關鍵要點:

  • CloudFront 無法區分 WAF 的 403 與源伺服器的 403
  • 「403→200 轉換」設定會產生內部請求
  • WAF 自定義回應設定可以控制這一行為

了解這一規範,可以使我們在支援 SPA 的同時妥善執行安全措施。

希望這對於遇到類似現象的讀者有所幫助!


參考資料


原文出處:https://qiita.com/kana_1166/items/fdcdc75883445669d293


共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
站長阿川

站長阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

站長精心設計,帶你實作 63 個小專案,得到作品集!

立即開始免費試讀!