前面幾篇整理了 AWS 的治理與身分管理,接下來進入網路設計,開始看另一個問題:哪些來源可以透過網路連到這些資源?
部署應用程式時,常會看到「ALB 放公有子網、EC2 和資料庫放私有子網」這種架構,把資源放進 Private Subnet,確實可以降低直接暴露在網際網路上的機會,但不代表它就不會被其他資源連到,也不代表所有不必要的流量都已經被擋住。
要判斷一套架構是否符合安全需求,可以先確認兩件事:
這條連線有沒有路可以走?有路之後,又有沒有被允許通過?
前者主要由 Route Table 決定,後者則會牽涉 Security Group、NACL 等網路控制。
先用一個簡單的訂單網站作為例子。
架構中有三個主要元件:
實際需要的連線如下:
| 來源 | 目的地 | Port | 用途 |
|---|---|---|---|
| Internet 使用者 | ALB | TCP 443 | 存取網站 |
| ALB | Application EC2 | TCP 8080 | 轉送請求與健康檢查 |
| Application EC2 | PostgreSQL | TCP 5432 | 存取訂單資料 |
這張表同時也說明了哪些連線不需要存在。
使用者不需要直接連到 Application EC2 或資料庫;ALB 也沒有直接連資料庫的需求。
因此,設計網路時可以先把真正需要的通訊關係列出來,再決定 Subnet、Route Table 與 Security Group,而不是先把所有資源放進 Private Subnet,之後才逐一思考要開哪些 Port。
AWS 並沒有一個「Public Subnet / Private Subnet」的類型開關。
一般所說的 Public Subnet,是指該 Subnet 關聯的 Route Table 中,具有直接通往 Internet Gateway(IGW) 的路由;沒有這條直接路由的 Subnet,通常稱為 Private Subnet。
例如,假設 VPC CIDR 是 10.20.0.0/16,Public Subnet 的 Route Table 可能是:
| Destination | Target |
|---|---|
10.20.0.0/16 |
local |
0.0.0.0/0 |
Internet Gateway |
其中:
0.0.0.0/0 → Internet Gateway
表示沒有符合更明確路由的 IPv4 流量,可以送往 Internet Gateway。
這裡可以注意的是:0.0.0.0/0 出現在 Route Table,不代表允許所有 Internet 流量連進來。
Route Table 和 Security Group 解決的是不同問題:
Route Table
→ 這個封包有沒有路可以走?下一站在哪裡?
Security Group / NACL
→ 有路之後,這個流量允不允許通過?
所以,路由存在只代表網路上有一條可達路徑,不代表連線一定會成功。
也不是絕對的,以 IPv4 為例,一台 EC2 即使位於 Public Subnet,若要直接透過 Internet Gateway 與 Internet 通訊,仍需要 Public IPv4 或 Elastic IP;如果 Internet 想主動連入,也還需要 Security Group 等網路控制允許對應流量。
可以先用下面這個關係理解:
Public Subnet
+
Public IPv4 / Elastic IP
+
Internet Gateway 路由
+
Security Group 允許
↓
才可能直接從 Internet 連入
因此:
Public Subnet ≠ 一定公開。
同樣地:
Private Subnet ≠ 一定安全。
Subnet 解決的主要是網路路徑問題,並不能取代後面的存取控制。
回到前面的訂單網站。
假設 Application EC2 與 PostgreSQL 分別放在不同的 Private Subnet:
Private App Subnet
│
▼
Private DB Subnet
看起來已經分成兩層,但如果它們仍然位於同一個 VPC,在一般 VPC 路由設定下,Route Table 中會有一條 local route,提供 VPC CIDR 內的通訊路徑。
例如:
10.20.0.0/16 → local
因此,把 Application 與 Database 分到不同 Subnet,不代表兩邊自動無法互相連線。
Subnet Route Table 仍可能讓封包有路可走,實際是否允許連線,還需要其他網路控制。
參考:AWS 官方文件|Subnet route tables
假設資料庫 Security Group 直接開放:
TCP 5432
Source: 10.20.0.0/16
那麼 VPC 中其他具備可達路徑的資源,也可能有機會連到資料庫的 5432。
這已經超過原本的需求。
我們真正需要的是:
Application EC2 → PostgreSQL : 5432
而不是:
整個 VPC → PostgreSQL : 5432
這就是為什麼「放進 Private Subnet」還不足以完成網路安全設計。
Security Group 是 AWS 中很重要的資源層級網路控制機制。
它可以關聯至 EC2、ALB、RDS 等資源的網路介面,並透過規則控制允許的流量。
回到前面的訂單網站,可以建立三個 Security Group:
| Security Group | 關聯資源 | Inbound 來源 | Port |
|---|---|---|---|
alb-sg |
ALB | 0.0.0.0/0 |
TCP 443 |
app-sg |
Application EC2 | alb-sg |
TCP 8080 |
db-sg |
PostgreSQL | app-sg |
TCP 5432 |
整體關係會變成:

這裡不是讓 Application EC2 接受:
TCP 8080 from 0.0.0.0/0
而是只接受:
TCP 8080 from alb-sg
資料庫也不是允許整個 VPC CIDR,而是:
TCP 5432 from app-sg
Security Group 可以引用另一個 Security Group 作為來源,用來識別哪些資源被允許建立連線,不需要依賴固定的 EC2 Private IP。
未來即使 VPC 中增加其他 EC2,只要沒有使用 app-sg,就不會因為「同樣位於這個 VPC」而自動符合資料庫的來源規則。
這也是最小權限原則套用到網路層時的一種做法:只允許真正需要存在的連線。
另外如果 ALB 使用 8080 對 EC2 進行 Health Check,也要確認 ALB 與 EC2 的 Security Group 規則允許對應的健康檢查流量。
參考:AWS 官方文件|Security group rules
Security Group 是 Stateful(有狀態) 的。
假設 Application EC2 被允許連到 PostgreSQL 的 TCP 5432:
EC2 → PostgreSQL : 5432
資料庫回傳查詢結果時,這段回應流量會被視為已建立連線的一部分,不需要再額外新增一條 Security Group 規則允許回程。
這也是 Security Group 與接下來要介紹的 NACL 很大的差異之一。
除了 Security Group,AWS VPC 還有 Network ACL(NACL)。
兩者的控制層級不同:
| 比較項目 | Security Group | NACL |
|---|---|---|
| 控制範圍 | ENI / 資源層級 | Subnet 層級 |
| 規則 | Allow | Allow + Deny |
| 規則判斷 | 評估所有適用的允許規則 | 依 Rule Number 由小到大比對 |
| 狀態 | Stateful | Stateless |
| 回程流量 | 已允許連線的回應自動允許 | 必須另外符合對應規則 |
NACL 可以搭配 Security Group,作為 Subnet 層級的額外防護。
由於 NACL 是 Stateless,如果使用比較嚴格的自訂 NACL,不只要考慮服務使用的 443、8080 或 5432,還要一起處理回程流量與暫時通訊埠。
因此,在這個網站情境中,可以先使用 Security Group 精確限制 ALB → Application → Database 的連線,再依照是否真的需要 Subnet-level 的 Deny 或其他額外限制,決定是否建立自訂 NACL。
不需要為了「多一層安全」就把相同的應用程式規則重新複製一份到 NACL,否則反而會增加網路規則的維護與除錯成本。
回到文章一開始列出的需求,可以整理出:
| 資源 | 放置位置 | 網路需求 |
|---|---|---|
| Internet-facing ALB | Public Subnet | 接受 Internet HTTPS 請求 |
| Application EC2 | Private Subnet | 接受 ALB 連線,不需要直接接受 Internet 流量 |
| PostgreSQL | Private DB Subnet | 只接受 Application EC2 連線 |
架構可以整理成:

這裡把 Application EC2 放在 Private Subnet,原因不是「Private 比較安全」這麼簡單。
而是因為:
Application EC2 根本沒有接受 Internet 直接連線的業務需求,所以沒有必要提供這條網路路徑。
同樣地,使用者也沒有直接連資料庫的需求,因此資料庫只需要接受 Application Layer 的連線。
前面的 Application EC2 雖然不需要接受 Internet 主動連入,但未來可能仍然需要:
因此,它可能還需要某種 outbound path。
但 Database 的情況可能完全不同。
如果 PostgreSQL 不需要主動連往 Internet,可以進一步讓 Database 所在的 Subnet 沒有一般的 Internet Default Route:
10.20.0.0/16 → local
這類設計有時會稱為 Isolated Subnet。
所以實務上不一定只有:
Public
Private
也可以依照不同工作負載需要的網路路徑,再細分成:
Public Subnet
Private Application Subnet
Isolated Data Subnet
重點仍然不是 Subnet 的名稱,而是:
這個工作負載真正需要哪些網路路徑?
回到這篇一開始的問題:
資源放進 Private Subnet,就代表安全了嗎?
即使因 Private Subnet 移除了資源直接透過 Internet Gateway 與 Internet 通訊的路徑,可以有效降低直接暴露在 Internet 的機會。
但如果:
攻擊者仍可能利用原本存在的路徑繼續存取其他資源。
因此,Private Subnet 是降低網路暴露面的一層措施,而不是完整的安全邊界。
設計 AWS 網路時,可以先問:
先把必要的連線畫出來,再建立對應的 Route 與安全規則,通常比單純依照「Public / Private」分類,更容易設計出清楚且可維護的網路架構。
這篇可以先記住兩個核心概念:
Route Table
→ 決定「有沒有路、下一站在哪裡」
Security Group / NACL
→ 決定「有路之後,這個流量能不能通過」
以及:
Private Subnet
≠ 沒有任何網路連線
≠ 自動阻擋 VPC 內其他資源
≠ 資源已經安全
Private Subnet 的價值,在於移除不需要的 Internet 直接路徑;真正的網路安全,則需要配合實際的通訊需求,透過 Route Table、Security Group 與必要的 NACL 限制可達範圍。
Application EC2 放進 Private Subnet 後,雖然不需要接受 Internet 主動連入,但它可能仍然需要下載套件、呼叫外部 API,或存取 S3 等 AWS 服務。
下一篇將繼續從 Private Subnet 的 outbound connectivity 出發,看看不同目的地需要哪些網路元件,以及什麼情況需要經過 NAT、什麼情況可以直接透過 AWS 的私有連線路徑存取服務。