AWS帳號充值優惠 如何限制指定 IP 訪問 AWS S3

亞馬遜雲AWS / 2026-07-24 15:33:18

第一章:先想清楚,你要限制的是什麼

很多人看到「限制指定 IP 訪問 AWS S3」時,第一反應是用 Bucket Policy 擋住不該來的人。但現實是:你能控制的粒度,取決於「訪問路徑」與「你要防的攻擊型態」。

在 S3 的世界裡,常見的訪問方式大致分三類:

  • 直接存取 S3:使用公開 S3 endpoint(例如 https://bucket-name.s3.amazonaws.com),由用戶端 IP 直接連到 AWS。
  • 透過中介層存取:例如 CloudFront、API Gateway、或其他代理服務。
  • 透過 VPC Endpoint 存取:你的資源在 VPC 裡,使用 PrivateLink(S3 Gateway/Interface Endpoint)走私有路徑。

你要限制「指定 IP」時,答案通常是:先決定訪問是走哪條路。若是直接公開 endpoint,那 Bucket Policy 是核心;若是走 CloudFront 或 VPC Endpoint,還需要配合其他層的條件,才能做到真正可控且可驗證。

第二章:Bucket Policy 能不能依 IP 限制?能,但要理解條件

AWS S3 的 Bucket Policy 支援用 Condition 判斷請求來源 IP。常見的條件鍵是:

  • aws:SourceIp:依請求的來源 IP 判斷。
  • NotIpAddressIpAddress:配合允許/拒絕邏輯。

概念很簡單:你可以在 Bucket Policy 裡寫「只有特定 IP(或網段)可以執行某些動作,例如 s3:GetObjects3:PutObject」。

但要注意兩件事:

  1. 來源 IP 以你能看到的那個為準:如果你是從 CloudFront 進來,來源 IP 可能是 CloudFront 的地址,而不是使用者的真實 IP。這時直接用 aws:SourceIp 可能達不到你想像的效果。
  2. 不是所有請求都會同樣帶來可用的 IP:例如某些代理、特定 AWS 服務或特殊路徑,條件判斷的結果可能不是你期待的來源。

因此,做之前你應該先決定:你要限制的「IP」是用戶端的真實 IP,還是你實際能控制/可觀測的 IP(例如公司出口 NAT 的 IP)?多數公司情境下,限制公司出口 NAT 的 IP 最實際,因為你穩定掌握、也能驗證。

第三章:最常用的做法——在 Bucket Policy 以 IP 白名單限制

下面提供一個典型模板:只允許特定 IP 網段讀取某個 prefix 下的物件。你可以依需求改成允許寫入、或針對特定動作。

3.1 只允許指定 IP 下載物件(GetObject)

假設你的 Bucket 名稱是 my-bucket,你要限制的物件範圍是 public/ 目錄,允許的來源網段是:

  • 203.0.113.10/32
  • 198.51.100.0/24

你可以把 Bucket Policy 設定成類似以下內容(把資源 ARN 與動作改成你的實際需求):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowGetObjectFromAllowedIps",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/public/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    }
  ]
}

說明:這個政策表示:只有符合 IP 條件的請求才能進行 s3:GetObject。其他 IP 的讀取請求會因為缺乏 Allow 而被拒絕(前提是你的 Bucket 沒有其他更寬鬆的政策放行)。

如果你的 Bucket 目前可能已有允許公開讀取的 Statement,請先清掉或調整,否則「允許」會覆蓋你設定的限制邏輯。

3.2 只允許指定 IP 上傳物件(PutObject)

AWS帳號充值優惠 若你要限制上傳:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowPutObjectFromAllowedIps",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::my-bucket/upload/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    }
  ]
}

提醒:上傳通常還會受到 IAM Identity policy、以及是否使用 SSE、是否需要特定 ACL 或 Bucket 所有權設定等影響。Bucket Policy 只是其中一層;你要確保整體授權沒有互相打架。

第四章:更安全的策略——先拒絕其他 IP,再允許白名單

有些團隊喜歡用「先明確拒絕不在名單的來源」的方式,因為更容易看出意圖,也更不容易被其他政策意外放行。AWS 的評估規則通常採用顯式 Deny 優先於 Allow

4.1 使用 Deny NotIpAddress 把非白名單擋掉

例如:拒絕任何不在允許清單內的 IP 進行讀取:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyGetObjectFromNonAllowedIps",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/public/*",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    }
  ]
}

這樣做的邏輯是:只要來源 IP 不在白名單,就直接 Deny。白名單內是否允許,仍取決於你是否提供了 Allow(或是否存在其他 Allow)。

實務上常見的做法是配合 IAM 使用:Bucket Policy 的 Allow 只開最必要的動作,並讓 Deny 作為「最終保險」。但如果你直接用 Deny 來「硬擋」,仍要確保你沒有其他會放行的公開政策。

4.2 Deny 與 Allow 並用的完整範例

假設目標是:白名單 IP 可以讀取;非白名單一律拒絕。你可以用:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyGetObjectFromNonAllowedIps",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/public/*",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    },
    {
      "Sid": "AllowGetObjectFromAllowedIps",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/public/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    }
  ]
}

AWS帳號充值優惠 這會把意圖寫得更明確:不在名單的直接拒絕,在名單的才允許。

AWS帳號充值優惠 第五章:常見坑位與排查方法

「貼了 Bucket Policy 但還是能存取」或「看起來擋了,但內網也被擋」是最常見的狀況。通常不是政策語法問題,而是你對條件判斷的前提不一致。

5.1 你以為限制的是用戶 IP,其實是出口 NAT 或代理 IP

最常見的狀況是:你的公司用戶在瀏覽器發起請求,但流量經過 NAT/防火牆,AWS 看到的來源 IP 是 NAT 的出口 IP。此時你應該把允許清單設成「公司出口 IP」,而不是用戶自己的內網地址。

AWS帳號充值優惠 如何確認?你可以在被允許/被拒絕時比較:

  • 用你的實際客戶端測試(從公司網路 vs 家用網路)
  • 看 AWS CloudTrail 或 S3 server access logs(如啟用)中顯示的請求來源(有些情境下會有線索)
  • 在測試時臨時允許你的 NAT 出口 IP,確認策略成立後再收斂

5.2 有其他 Bucket Policy 或 ACL 放行了

如果你的 Bucket 原本設定了「公開讀取」,那麼加一條白名單 Allow 不一定能達到你想要的效果。公開讀取可能是另一條 Statement 在允許。AWS 的政策評估中,Deny 會優先於 Allow,但如果你只用了 Allow,而且又存在其他 Allow,就會發生「看起來限制失效」。

解法:

  • 先檢查 Bucket Policy 的整份內容是否還有公開讀取、特定服務放行等。
  • 必要時改用 Deny + NotIpAddress 作最終保險。

5.3 忘了處理 ListBucket(列出物件)

很多人只限制了 s3:GetObject,但前端或程式實際使用的是:

  • s3:ListBucket(例如列出 prefix 下的檔案)
  • 然後再 s3:GetObject

結果就是:你可以下載某個檔案,但列目錄失敗。若你要全面限制,應該把需要的動作一起管理,例如:

  • 限制 arn:aws:s3:::my-bucket(ListBucket 通常是 Bucket ARN,不是 object ARN)
  • 限制 arn:aws:s3:::my-bucket/prefix/*(GetObject/PutObject 通常是 object ARN)

5.4 分區端點、地區與 ARN 寫錯

Policy 的 ARN 如果寫錯(例如 bucket 名稱或 prefix 目標),會導致條件根本沒有匹配到你想管的資源。建議你在套用政策前,先把這兩件事核對:

  • Resource 的 ARN 是否正確:arn:aws:s3:::bucket vs arn:aws:s3:::bucket/*
  • prefix 的路徑是否符合你實際物件存放位置

第六章:如果你用的是 CloudFront,IP 限制要換思路

在很多網站架構中,S3 不會直接暴露給瀏覽器,而是由 CloudFront 轉發。這時「指定 IP 訪問 S3」的直覺就會失效:CloudFront 到 S3 的來源 IP 可能是 CloudFront 的網段,而不是使用者的真實 IP。

AWS帳號充值優惠 此時你要做的通常是:

  • 把 IP 限制放在 CloudFront 層(例如搭配 WAF),或
  • 使用可以判斷真實來源的機制(需看你如何設定原始請求頭與 WAF 規則)。

換句話說:當訪問路徑被中介層包住,你就不要硬在 S3 用 aws:SourceIp 期待看到用戶端 IP。要在最靠近真實來源的層做控管。

第七章:若你的服務在 VPC,優先用 VPC Endpoint 把路徑鎖死

有另一種更乾淨的安全策略:不是讓流量到公網 endpoint,再靠 IP 條件判斷,而是讓請求根本只能走你的私有路徑。

對 S3 來說,你可以使用 VPC Gateway Endpoint(或在特定情境使用 Interface Endpoint 的方案)。當流量走 VPC Endpoint,你可以搭配端點的路由與安全規則,把外部來源大幅排除。

這樣做的優點是:

  • 你控制的是「網路可達性」,不只是「授權判斷」。
  • 可降低你對 SourceIp 觀測誤差的依賴。

當然,若你仍希望精準限制「哪些來源主機可以用端點存取」,你可能還需要搭配 IAM 條件(例如要求特定角色、或在端點政策中限制)。

第八章:實際落地步驟(建議流程)

以下是一套可操作、也比較不容易翻車的流程。你不需要照單全抄,但邏輯值得沿用。

8.1 建立目標清單:動作、物件範圍、允許來源

把需求拆成三欄:

  • 動作s3:GetObjects3:PutObjects3:ListBucket、或其他。
  • 物件範圍:例如 public/*upload/*
  • 允許來源 IP:單一 IP 用 /32,網段用 /24、/20 等。

很多失敗不是因為策略寫得不夠厲害,而是你其實漏了某個動作或路徑。

8.2 先用只允許(Allow)測試,再進階到 Deny 保險

建議從最小變更開始:

  • 先確定你的 Allow 能命中目標資源與動作
  • 再加入 Deny(NotIpAddress)讓效果更穩定

尤其是你不確定 SourceIp 會不會是你想像的 IP 時,先用 Allow + 實測會更快找到差距。

8.3 用同一條路徑驗證:兩邊都測(允許與拒絕)

驗證不要只測「能不能存取」。你也要測「不能存取」是否真被拒絕。

測試方式可用:

  • 從允許網路環境請求(例如公司網路)下載一個物件
  • 從非允許環境請求(例如家用網路、手機熱點)下載同一個物件

如果兩邊都能存取,通常代表你仍有公開 Allow 或其他政策在放行。

AWS帳號充值優惠 8.4 開啟存取紀錄與告警(可選但很有價值)

要讓限制真正可維運,你需要知道「有人試了什麼」與「被拒的原因是什麼」。

你可以考慮:

  • 啟用 S3 access logs 或用 CloudTrail 配合審計
  • 把常見拒絕模式納入監控(例如短時間大量 403)

當你往後調整 IP 清單或重構架構時,這些訊號能幫你快速定位是政策問題還是來源 IP 變動。

第九章:範例整合——限制整個 Bucket 的讀寫(依你的情境調整)

AWS帳號充值優惠 如果你需要更「一口氣」的限制,例如:整個 Bucket 的 object 只允許特定 IP 讀取或寫入。以下提供示意,但你仍應根據你 Bucket 的現況調整(尤其是是否已有公開策略)。

9.1 只允許指定 IP 做讀取(GetObject),其他動作不放行

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyGetObjectFromNonAllowedIps",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    },
    {
      "Sid": "AllowGetObjectFromAllowedIps",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    }
  ]
}

9.2 只允許指定 IP 做讀寫(GetObject/PutObject),同時限制 ListBucket

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyListBucketFromNonAllowedIps",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::my-bucket",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    },
    {
      "Sid": "AllowListBucketFromAllowedIps",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::my-bucket",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    },
    {
      "Sid": "DenyGetPutFromNonAllowedIps",
      "Effect": "Deny",
      "Principal": "*",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    },
    {
      "Sid": "AllowGetPutFromAllowedIps",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-bucket/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "203.0.113.10/32",
            "198.51.100.0/24"
          ]
        }
      }
    }
  ]
}

再次提醒:如果你還允許匿名訪問、或使用預簽 URL(Presigned URL),就要重新評估限制策略能否符合你的目的。

第十章:最後確認——你想要的是「安全」還是「可用性」

IP 限制能有效降低風險,但它不是魔法。它的強度來自「你掌握來源網段的穩定性」以及「你的訪問路徑不會把 SourceIp 換掉」。

如果你的團隊常見情況是:辦公室網路固定、公司出口 IP 可控,那用 Bucket Policy 做白名單/黑名單是合理且經濟的。

若你的場景牽涉多地辦公、臨時網路、或透過 CloudFront 等中介層,單純在 S3 用 aws:SourceIp 可能會讓你反覆調參。這時應該把控管放到更接近真實來源的層(例如 WAF),或改走 VPC Endpoint 讓網路可達性先被鎖住。

做完策略後,最重要的不是把政策寫得多漂亮,而是能否在真實環境中穩定運作:允許的人能用、禁止的人真的被擋、而且你能在半年後仍然看懂為什麼要這樣設。

把目標講清楚、把測試做完整、把例外處理好,限制指定 IP 訪問 S3 就會變成一個可靠的安全機制,而不是一段需要猜的防火牆。

Telegram售前客服
客服ID
@cloudcup
联系
Telegram售后客服
客服ID
@yanhuacloud
联系