跳至主要內容
GCP 入門基礎 — 第 4/5 篇

GCP 網路基礎:看懂 VPC、Subnet、防火牆與 IAP

內文字級

GCP 網路基礎:看懂 VPC、Subnet、防火牆與 IAP
更新:2026-10-22

在 GCP 建好第一台 VM 後,下一個問題通常是網路:它為什麼能連上網際網路?HTTP 已經開了,SSH 還要不要對外開放?如果 VM 沒有外部 IP,又該怎麼登入?

這篇會沿著同一條連線路徑整理三件事:VM 放在哪個 VPC 與 Subnet、防火牆如何決定流量能不能通過,以及管理者如何透過 SSH 或 IAP 連進 VM。最後會建立一個沒有外部 IP 的練習環境,把這些設定串起來驗證。

先選閱讀路線:觀念、完整實作與清理
  • 只讀觀念:先讀第一到四節,再回答文末情境題;不用建立資源。7 天計畫 Day 3 的閱讀/推演也走這條路線。
  • 完整實作:第五節約 60–75 分鐘,從獨立專案準備、Custom VPC、IAP 連線,做到允許/拒絕/復原對照與清理。權限等待及排錯另計。
  • 中途停止:先停用本次測試拒絕規則,再清理本次資源。不要為了排錯開放公開 SSH 或更動組織政策。

教材核對:2026-10-22。實作可能產生 VM、磁碟及用量費用;試用資格、免費額度及帳戶限制需另外核對。

GCP VPC 網路模型:一個全球 VPC 包含不同 Region 的區域 Subnet,各自使用不重疊 CIDR;防火牆規則作用在 VM 網路介面,管理者可透過 IAP 隧道連到沒有外部 IP 的私有 VM;下方比較 Auto mode、Custom mode 與多環境 CIDR 規劃

先抓住邊界:VPC 是全球資源,Subnet 與它的 CIDR 是區域資源,VM 的網路介面落在某個 Subnet;防火牆依目標與來源判斷流量。IAP 能把管理連線送進沒有外部 IP 的 VM,而 Custom mode 讓正式環境能預先避開跨區域、跨環境與地端網段衝突。


一、VPC 與 Subnet 的範圍

VPC 是什麼?

VPC(Virtual Private Cloud,虛擬私有雲) 是 Project 裡的虛擬網路。Subnet、路由與防火牆規則都由設定定義,底層交換器與路由器則由 Google 維護。

先記住三個範圍:

  1. VPC 是全球資源:同一個 VPC 可以包含多個 Region 的 Subnet
  2. Subnet 是區域資源:同 Region 的多個 Zone 可以使用同一個 Subnet
  3. VM 網路介面屬於 Subnet:VM 會從所在 Subnet 取得內部 IP

和 AWS VPC 的差別

最容易混淆的是資源範圍:GCP VPC 是全球資源,AWS VPC 則屬於單一 Region。

特性GCP VPCAWS VPC說明
VPC 範圍全球區域GCP VPC 可包含多個 Region 的 Subnet
Subnet 範圍區域可用區GCP Subnet 可跨同 Region 內的多個 Zone
跨區域連線同一 VPC 內有系統路由需另外連接 VPC仍要檢查防火牆、路由模式與費用

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

假設要在台灣 asia-east1 與新加坡 asia-southeast1 部署服務,GCP 可以把兩個 Subnet 放在同一個 VPC:

1 個 VPC
├── asia-east1 Subnet (10.1.0.0/24)
└── asia-southeast1 Subnet (10.2.0.0/24)

而在 AWS 需要:

VPC-Taiwan (需手動建立 VPC Peering)
VPC-Singapore

這樣不需要先建立跨 Region 的 VPC Peering。不過「有路由」不代表應用一定能通,防火牆、名稱解析與服務本身仍要設定,跨區域流量也可能產生費用。

Default、Auto 與 Custom Mode

建立 VPC 時常看到以下三種情況:

模式子網路建立方式適用場景生產建議
Default專案建立時可能自動建立短期 Lab、測試先檢查預設規則
Auto Mode每個 Region 自動建立 Subnet快速建立多區網路留意網段衝突
Custom Mode手動決定 Region 與 CIDR正式環境、混合雲通常較好管理

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  START["準備建立新的 VPC 網路"] --> SCENARIO{"主要使用情境?"}
  SCENARIO -->|"正式環境、GKE、混合雲<br/>或未來跨網路整合"| CUSTOM["Custom Mode<br/>先做 IPAM 與環境切分"]
  SCENARIO -->|"可整個刪除的短期<br/>個人 Lab/PoC"| DEFAULT["Default VPC<br/>先限縮預設防火牆"]
  SCENARIO -->|"低風險多 Region 快速部署,<br/>且已確認不會網段衝突"| AUTO["Auto Mode<br/>記錄自動 CIDR 與轉換限制"]
  DEFAULT --> REVIEW["建立前審查 CIDR、防火牆、路由與擁有者"]
  AUTO --> REVIEW
  CUSTOM --> REVIEW
  REVIEW --> OPERATE["持續維護 IPAM 與規則基線"]
  AUTO --> CHANGE{"日後需要完全掌控網段?"}
  CHANGE -->|"是"| ONE_WAY["單向轉成 Custom Mode<br/>不能再回到 Auto"]
  CHANGE -->|"否"| OPERATE
  ONE_WAY --> OPERATE
需要自行規劃網段或連接其他網路時,Custom Mode 通常比較容易管理;Default/Auto 則適合範圍明確的短期環境。Auto 轉成 Custom 後不能切回,因此決定前要先確認網段與長期需求。

為什麼正式環境常用 Custom Mode?

  1. 能先避開網段衝突:建立前就能對照地端、其他 VPC 與合作夥伴使用的 CIDR
  2. 只建立需要的 Subnet:不會自動在每個 Region 配一段 IP
  3. 環境比較好區分:Dev、Staging、Prod 可以各自規劃範圍
  4. 方便納入 IPAM:網路團隊能追蹤每段位址的用途與擁有者

Auto Mode 建立得快,但自動分配的網段日後可能和地端或其他雲端環境重疊。短期 Lab 問題不大;只要環境準備長期使用或需要連接其他網路,就值得先做 CIDR 盤點,再用 Custom Mode 建立。

VPC 網路列表並排顯示兩個網路:default 為自動模式、45 個子網路、6 條防火牆規則;my-secure-vpc 為自訂模式、1 個子網路、3 條防火牆規則

圖中的 default 網路已經包含多個自動 Subnet 與預設防火牆規則;my-secure-vpc 則只有手動建立的 Subnet 與規則。Custom Mode 的重點不是比較安全的名稱,而是建立者必須明確決定每一段網路與存取規則。

模式可以單向轉換

Auto Mode 可以轉成 Custom Mode,轉換後不能再切回 Auto。準備轉換前,先確認後續 Subnet 都會改由團隊自行規劃與建立。


二、Subnet 與 CIDR 怎麼規劃?

Subnet 是什麼?

Subnet(子網路) 是 VPC 裡的一段 IP 位址範圍,VM 網路介面會從這裡取得內部 IP,部分服務也會使用額外的次要範圍。

它有幾個重要特性:

  • 屬於單一 Region:同 Region 的多個 Zone 可以使用
  • CIDR 不可重疊:同一個 VPC 裡,各個 Subnet 範圍不能互相重疊
  • 主要範圍只能擴大:建立後不能縮小或直接換成另一段 CIDR

看懂 CIDR 表示法

CIDR(Classless Inter-Domain Routing) 用來表示一段 IP 範圍:

10.0.1.0/24
│       │
IP 起點 │
        子網路遮罩(表示多少位元固定)

常見 CIDR 範圍對照表:

CIDR可用 IP 數量適用場景範例
/321單一 IP10.0.1.5/32
/2816極小型子網路10.0.1.0/28
/24256小型應用(標準)10.0.1.0/24
/204,096中型應用10.0.0.0/20
/1665,536大型應用10.0.0.0/16
/816,777,216企業級超大網段10.0.0.0/8

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

記得扣掉保留位址

/24 總共有 256 個位址,但 GCP 會保留主要範圍中的 4 個,因此可分配給資源的是 252 個。估算容量時不要只看 CIDR 的總數,還要把成長、維護期間的額外資源與 GKE Pod 等需求一起算進去。

私有 IP 範圍選擇

根據 RFC 1918,可用於私有網路的 IP 範圍為:

類別CIDR 範圍可用 IP 總數建議用途
Class A10.0.0.0/816,777,216大型企業、多環境
Class B172.16.0.0/121,048,576中型組織
Class C192.168.0.0/1665,536小型專案、家用網路

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

表中的 Class A、B、C 是舊稱,現代網路規劃以 CIDR 為準。172.16.0.0/12 也不等同傳統 Class B,只要記住三段 RFC 1918 私有範圍即可。

規劃時可以照這個順序:

  • 先盤點地端、其他 VPC、VPN 與合作夥伴已使用的網段
  • 再按 Region 和環境切分,保留未來擴充空間
  • 如果會使用 VPC-native GKE,另外預留 Pod 與 Service 的 Secondary Range

範例:規劃多環境 Subnet

假設你要在 asia-east1 開 Dev / Staging / Prod 三個環境:

VPC: my-company-vpc(VPC 本身沒有單一 CIDR;以下是 Subnet 規劃)

├── asia-east1-dev (10.1.0.0/20)       → 4,096 IPs
├── asia-east1-staging (10.2.0.0/20)   → 4,096 IPs
└── asia-east1-prod (10.3.0.0/20)      → 4,096 IPs
    ├── Primary Range: 10.3.0.0/20       → 4,096 IPs (VMs)
    ├── Secondary Range 1: 10.3.16.0/24  → 256 IPs (GKE Pods)
    └── Secondary Range 2: 10.3.17.0/24  → 256 IPs (GKE Services)

這個範例想表達的是:

  1. Dev、Staging、Prod 使用不同範圍,規則和路由比較容易閱讀
  2. 每個環境預留成長空間,不要只按今天的 VM 數量切到剛剛好
  3. GKE 的 Pod 與 Service 使用獨立 Secondary Range,避免和 VM 位址混在一起
查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  subgraph DISCOVER["盤點與容量估算"]
    direction LR
    INVENTORY["盤點地端、VPN、其他 VPC/專案<br/>與合作夥伴已使用的 CIDR"] --> CONFLICT["排除重疊與不可路由<br/>的候選範圍"]
  end
  CONFLICT --> DEMAND["估算各 Region/環境的資源<br/>與成長量"]
  subgraph CAPACITY["容量與成長"]
    direction LR
    DEMAND --> RESERVED["扣除保留位址<br/>並加入成長緩衝"]
  end
  RESERVED --> GKE{"是否使用 VPC-native GKE<br/>或其他需要 Secondary Range 的服務?"}
  GKE -->|"是"| SECONDARY["分開規劃 Pod 與 Service<br/>Secondary CIDR"]
  GKE -->|"否"| SPLIT
  subgraph ALLOCATE["分配與預留"]
    direction LR
    SECONDARY --> SPLIT["按 Region 與 Dev/Staging/Prod<br/>切出不重疊區塊"]
  end
  SPLIT --> FUTURE["預留未來 Region、環境、併購<br/>與混合雲空間"]
  FUTURE --> VALIDATE{"所有 Primary/Secondary/地端網段<br/>是否不重疊且容量足夠?"}
  VALIDATE -->|"否"| DEMAND
  VALIDATE -->|"是"| IPAM["記錄到 IPAM/架構文件<br/>指定擁有者與變更流程"]
  IPAM --> CREATE["建立 Subnet,驗證路由、<br/>Private Google Access 與防火牆"]
Subnet 建立後只能擴大、不能縮小或換掉主要 CIDR,所以規劃要從全域網段盤點開始。除了 VM 數量,還要預留 GKE Secondary Range、成長與未來連線空間,最後把結果納入 IPAM 管理。

用 gcloud 建立 Subnet

先把網路、位置、主要與次要範圍列清楚。以下是方案推演,不會建立雲端資源;完整可執行指令在第五節,會明確帶入本次專案與名稱。

設定規劃範例核對方式
VPC/Regionmy-company-vpc/asia-east1確認網路擁有者與可用區域
Primary range10.3.0.0/20盤點其他 Subnet、地端與互連網段是否重疊
Secondary rangesPods 10.3.16.0/24、Services 10.3.17.0/24依實際 GKE 模式與容量另行規劃,不把示例當正式尺寸
Private Google Access依服務需求啟用核對支援的 API、DNS、路由及防火牆,與 IAM 授權分開驗證

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

--range、--secondary-range 與 --enable-private-ip-google-access 分別對應這些設定。VPC 沒有一個可直接分配給 VM 的總 CIDR;位址範圍設定在 Subnet 上。


三、防火牆規則怎麼設計?

GCP 防火牆基礎

GCP 的 VPC 防火牆會控制進出 VM 網路介面的流量。它是有狀態的(Stateful):一條連線若被允許建立,對應的回程流量會自動放行,不需要再為回應方向另開一條規則。

判斷規則時要留意:

  • 規則屬於 VPC,但可以用 Network Tag 或 Service Account 限定目標 VM
  • 在匹配的 VPC firewall rules 中,Priority 數字越小,優先權越高
  • 沒有其他匹配規則時,會套用隱含的 Ingress 拒絕與 Egress 允許
  • 同一個 Priority 同時匹配 ALLOW 和 DENY 時,DENY 生效

防火牆規則的組成元素

一條防火牆規則包含以下關鍵元素:

元素說明範例
Direction流量方向INGRESS (進入) / EGRESS (出去)
Action動作ALLOW / DENY
Priority優先權 (0-65535)1000 (數字越小優先權越高)
Source/Destination來源/目的地IP 範圍、Service Account、Tag
Protocol & Port協定與連接埠tcp:22 (SSH), tcp:80 (HTTP)
Target套用對象特定 VM Tag、Service Account

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

多條規則同時匹配時怎麼判斷?

下圖只描述 VPC firewall rules 之間的判斷。 先確認規則已啟用且匹配方向、來源、目標、協定與 port,再比較 Priority。

若環境另外套用階層式、全域或區域 Firewall Policy,先依實際政策評估順序判斷政策層與委派行為。全域/區域政策相對於 classic VPC rules 的順序也能設定;不能把不同政策的所有 Priority 混在一起排序。

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  PACKET["已依環境評估適用政策<br/>進入 VPC rules 的判斷"] --> SCOPE{"規則啟用、方向、VPC、目標 VM、<br/>來源/目的地、協定與<br/>Port 是否落在規則範圍?"}
  SCOPE -->|"否"| NEXT["排除該規則,<br/>繼續尋找匹配項"]
  NEXT --> MATCH{"還有其他可能匹配的規則?"}
  MATCH -->|"有"| SCOPE
  SCOPE -->|"是"| COLLECT["收集所有匹配規則"]
  COLLECT --> PRIORITY["選 Priority 數字最小的一組"]
  PRIORITY --> TIE{"同一 Priority 是否同時有<br/>ALLOW 與 DENY?"}
  TIE -->|"是"| DENY["DENY 勝出,<br/>拒絕封包"]
  TIE -->|"否"| ACTION["依該規則的 ALLOW<br/>或 DENY 執行"]
  MATCH -->|"沒有"| DIRECTION{"封包方向?"}
  DIRECTION -->|"Ingress"| IMPLIED_DENY["套用隱含<br/>DENY ALL"]
  DIRECTION -->|"Egress"| IMPLIED_ALLOW["套用隱含<br/>ALLOW ALL"]
  ACTION --> STATEFUL["已允許的連線由<br/>Stateful 防火牆<br/>自動放行對應回程流量"]
範圍是已啟用的 VPC firewall rules:先匹配再比較 Priority,同值衝突由 DENY 勝出;適用政策與沒有其他匹配時的隱含規則也必須納入。跨政策不能只比數字。

例如:

規則PriorityActionSourcePort
Rule A1000ALLOW0.0.0.0/0tcp:80
Rule B900DENY10.0.0.0/8tcp:80

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

假設兩條 VPC rules 都已啟用、方向與目標相同,且沒有先終止評估的政策:來自 10.0.0.5 的 HTTP 請求會被 Rule B 拒絕,因為 900 比 1000 更優先。文件示例來源 203.0.113.1 不符合 Rule B,才會由 Rule A 允許。這是規則判讀題,不要求開放真實 HTTP 服務。

簡單記法

先確認政策層與規則是否啟用,再比較匹配的 VPC rules。隱含 Ingress 拒絕/Egress 允許是回退規則,不等於所有現有專案的完整設定。

八個實際管理規則時會用到的原則

1. 最小權限原則 (Least Privilege)

只允許服務真正需要的來源、目標與 port。

先比較設計,還不建立規則:

設計欄位範圍過大較符合本次管理需求
來源所有 IPv4 0.0.0.0/0IAP IPv4 35.235.240.0/20
協定與連接埠TCP、UDP 全部連接埠與 ICMPTCP 22
目標整個網路的 VM僅本次 VM 的專用標記
身分驗證誤以為網路放行即可登入另外核對 IAP 與 Linux SSH 權限

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

不要為了觀察「錯誤示範」而真的建立允許全部流量的規則。第五節使用兩條範圍相同的 SSH 規則做對照,並有獨立復原入口。

2. 明確 IP 範圍與連接埠

0.0.0.0/0 代表所有 IPv4 來源,適合公開網站的 HTTP/HTTPS,不適合直接套用到 SSH、RDP 或資料庫 port。管理入口可以限制在辦公室固定 IP、透過 VPN 進入,或改走後面介紹的 IAP。

常見做法:

  • 使用公司辦公室的固定 IP 作為管理入口
  • 透過 Cloud VPN 或 Cloud Interconnect 連接 On-Premise
  • 對外服務僅開放必要連接埠(80, 443)

3. 選擇 Network Tags 或 Service Accounts

Network Tag 設定方便,但只要有權修改 VM Tag,就可能讓其他 VM 套用同一條規則。使用目標 Service Account 時,還能搭配 IAM 控制誰可以把身分附加到 VM。

方法優點缺點
Network Tags設定直觀能修改 Tag 的人可改變規則套用範圍
Service Accounts可搭配 IAM 管理身分使用設定與權限關係較多

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

選擇前先核對信任邊界:

  • 使用 Network Tags:控制誰能修改 VM 的標記;標記被複用時,其他 VM 也可能被規則選中。
  • 使用目標 Service Account:控制誰能把該身分附加到 VM,並檢查此服務帳號自身的 API 權限;防火牆選取器不會自動限縮其 IAM 權限。
  • 不因為想選取防火牆目標,就替不需要呼叫 API 的 VM 新增高權限服務帳號。本篇 Lab 使用本次專用標記與不附掛服務帳號的 VM。

這些 Network Tags 與 Firewall Policy 的 Secure Tags 是不同機制;IAP TCP forwarding 的 IAM 授權也不會因為 VM 加上網路標記就自動取得。

4. 階層化策略 (Hierarchical Firewall Policies)

多個 Project 共用安全基線時,可以在 Organization 或 Folder 層級集中管理規則。要讓後續層級補上應用流量,必須先確認上層如何終止或委派評估;上層終止性的 DENY 不能被下層較小的 Priority 推翻。

Organization Level
├── DENY all RDP (tcp:3389) globally  ← 全公司禁止 RDP
│
Folder Level (Production)
├── DENY outbound to public internet   ← 生產環境禁止對外連線
│
Project Level
└── ALLOW specific application traffic  ← 僅在上層委派/未終止評估的範圍內適用

這樣做的好處是:

  • 安全基線一致:例如統一禁止公開 RDP
  • 降低 Project 誤設影響:應用團隊不能輕易繞過上層政策
  • 責任較清楚:安全團隊管基線,應用團隊管服務需求

5. 優先權數值規劃

先訂一套 Priority 區間,避免每個人都隨手填 1000,最後無法看出規則用途。

Priority 範例作用需要確認
100經核實的緊急阻擋來源、目標與協定必須匹配,且有解除條件
1000業務允許限定應用真正需要的來源、目標與 port
65534明確拒絕並視需求記錄不覆蓋較高優先序的允許;Logging 另評估用量與費用

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

這張表是管理慣例的示意,不會建立規則,也不是跨政策的全域排序。

以下只是一種範例,團隊可以依自己的變更流程調整:

優先權範圍用途
0-999緊急阻擋規則(惡意 IP、漏洞連接埠)
1000-9999正常業務規則
10000-64999低優先權允許規則
65000-65534團隊保留的顯式拒絕規則;65535 另有平台隱含規則

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

6. 啟用日誌與監控

對需要稽核或排錯的規則啟用 Logging,再用 Firewall Insights 協助找出未使用或過寬的規則。

建立或更新經核准的規則時,可用 --enable-logging 啟用;先確認 Project、network、來源與目標,不把開啟日誌當成縮小網路存取範圍。日誌可能產生費用,本篇 Lab 不要求啟用 Logging。官方規格也列明:只記錄 TCP/UDP 連線、不支援隱含規則,並非逐封包完整紀錄;沒有日誌不代表沒有流量。

日誌可以用來:

  • 稽核追蹤:查看已啟用 Logging 的規則所產生的連線紀錄;不能把它當成所有封包或所有規則的完整紀錄
  • 異常偵測 - 發現非預期的流量模式
  • 合規要求 - 有助於滿足 PCI-DSS、HIPAA 等的稽核紀錄要求(合規是一整套控制措施,單靠開 log 不等於就「符合」,但 log 通常是其中跑不掉的一項)

Firewall Insights 可協助找出:

  • 觀測期間未命中的規則:核對資料來源、觀測期間與使用情境;未命中不等於不再需要,還可能是備援或定期工作使用
  • 需檢查範圍的規則:來源過寬、陰影或重複等情況應配合服務需求判讀;公開 HTTP 的必要來源與公開 SSH 不應直接視為同一個風險
  • 重複規則 - 邏輯上重複的規則

7. 定期稽核與自動化清理

規則也需要退場流程,否則幾年後只會剩下一堆沒人敢刪的設定。

建議流程:

  1. 每季稽核 - 使用 Firewall Insights 檢視未使用規則
  2. 標記移除 - 將未使用規則標記為 “To-Be-Removed”
  3. 測試期 - 保留 30 天觀察是否有影響
  4. 確認後移除 - 透過 IaC 或受控流程刪除並更新文件

8. 上線前測試

先在 Staging 或隔離環境同時測試應該允許與應該拒絕的流量,再套用到正式環境。

測試時確認:

  • 允許規則是否生效?(測試正常流量)
  • 拒絕規則是否生效?(測試異常流量)
  • 優先權順序是否正確?(測試衝突規則)
  • 日誌記錄是否正常?(檢查 Cloud Logging)
查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  subgraph DESIGN["設計最小規則"]
    direction LR
    NEED["提出網路存取需求"] --> DEFINE["定義來源、目標、方向、Port、<br/>理由、擁有者與到期條件"]
    DEFINE --> MINIMIZE["限縮 CIDR、目標與 Priority<br/>避免公開管理入口"]
  end
  MINIMIZE --> STAGING["在 Staging 同時測試<br/>應允許、應拒絕與衝突規則"]
  STAGING --> PASS{"行為與 Firewall Logs 是否符合預期?"}
  PASS -->|"否"| DEFINE
  PASS -->|"是"| DEPLOY["經審查後部署,啟用 Logging<br/>並留下變更與回復方式"]
  subgraph OPERATE["觀測與稽核"]
    direction LR
    DEPLOY --> OBSERVE["觀察命中、拒絕、異常流量<br/>與 Firewall Insights"]
    OBSERVE --> REVIEW{"規則仍被使用、<br/>必要且不過寬?"}
  end
  REVIEW -->|"是"| OBSERVE
  REVIEW -->|"否或即將到期"| DISABLE["先停用或標記待移除<br/>保留觀察窗口"]
  subgraph RETIRE["安全退場"]
    direction LR
    DISABLE --> IMPACT{"觀察期出現<br/>必要流量受影響?"}
    IMPACT -->|"沒有"| DELETE["刪除規則並更新文件/IaC"]
  end
  IMPACT -->|"有"| DEFINE
防火牆不是建立後永久放著的設定。每條規則都應有理由、擁有者與到期條件,先在 Staging 驗證允許與拒絕案例;上線後靠日誌和 Insights 稽核,退場時則先觀察再刪除。

四、SSH、OS Login 與 IAP 怎麼選?

管理 VM 時,除了確認「連不連得上」,也要看 VM 是否需要外部 IP、登入權限如何撤銷,以及能不能留下稽核紀錄。直接把 SSH 開到網際網路會多出幾項管理負擔:

  • 外部 IP 和 TCP 22 會被持續掃描
  • SSH 金鑰要分發、輪替與撤銷
  • 人員離職或換職務時,要確認權限真的已移除
  • 登入與操作紀錄需要另外整理

下面三種方式解決的問題不完全相同:SSH Key 是 Linux 登入憑證,OS Login 用 IAM 管理作業系統登入,IAP 則提供不經外部 IP 的 TCP 轉送路徑。它們也可以組合使用。

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  CONNECT["管理者需要連入 Compute Engine VM"] --> PRIVATE{"VM 是否禁止外部 IP,<br/>或屬於正式/高敏感環境?"}
  PRIVATE -->|"是"| IAP["使用 Cloud IAP TCP Forwarding<br/>無外部 IP、IAM 驗證與集中稽核"]
  PRIVATE -->|"否"| TEAM{"是否為多人協作,並希望用 IAM<br/>統一加入、撤銷與 2FA?"}
  TEAM -->|"是"| OSLOGIN["使用 gcloud compute ssh + OS Login<br/>仍需可到達 VM 的連線路徑"]
  TEAM -->|"否,短期個人 Lab/PoC"| KEY["可使用傳統 SSH Key<br/>限縮來源 IP 並設定金鑰輪替/清理"]
  IAP --> CONTROLS["允許 35.235.240.0/20 到必要 Port<br/>授予 IAP 與 OS Login 最小角色"]
  OSLOGIN --> CONTROLS2["限縮 tcp:22 來源、防火牆目標<br/>並用 IAM 管理登入權限"]
  KEY --> CONTROLS3["避免 0.0.0.0/0 開放 SSH<br/>記錄並撤銷 Metadata 金鑰"]
  CONTROLS --> TEST["測試授權使用者可連線、<br/>未授權者與非必要來源應被拒絕"]
  CONTROLS2 --> TEST
  CONTROLS3 --> TEST
VM 不配置外部 IP 時,可以用 IAP 提供管理路徑;OS Login 負責 IAM 與登入資格,但不會自動移除公開連線路徑。若短期 Lab 使用傳統 SSH Key,仍要限縮來源並在結束後撤銷金鑰。

方法一:傳統 SSH Key

這裡先理解流程,不執行變更:產生公私鑰 → 將公鑰交給核准的 VM 登入機制 → 經可到達的 SSH 路徑連線 → 結束時撤銷不再需要的授權。

直接覆寫 VM 的 ssh-keys metadata 可能移除別人的金鑰;啟用 OS Login 的 VM 也不會以 metadata SSH 金鑰作為同一套登入設定。不要把這兩種模式混在一起操作。後面的獨立 Lab 透過 gcloud compute ssh 使用環境允許的登入方式,不更改整個專案的 SSH 模式。

優點:

  • 設定直接,標準 SSH 工具都能使用
  • 適合範圍有限、生命週期短的個人 Lab

要自行處理:

  • 金鑰分發、輪替與撤銷
  • 外部 IP 或其他可到達 VM 的網路路徑
  • 防火牆來源限制與登入稽核

短期個人練習可以使用;多人或正式環境通常改用集中管理的身分方式。

方法二:gcloud CLI 搭配 OS Login

實際設定前由管理者確認目標 VM 的有效 OS Login 設定與登入角色。專案層級啟用會影響多台 VM,不能把它當作個人 Lab 的必做準備;資源層級設定也必須符合組織政策。

本篇不提供自動變更專案 metadata 或自我授權的片段。若使用 OS Login,先依官方角色需求確認登入資格;附掛服務帳號、跨組織使用者或需要 sudo 時,還有相應的額外條件。

OS Login 的價值在於:

  • 用 IAM 角色管理誰可以登入 VM
  • 人員權限異動時,不必逐台移除 metadata 金鑰
  • 可搭配 OS Login 兩步驟驗證與稽核功能

要注意的是:

  • OS Login 解決的是登入身分,不會自動建立私有連線路徑
  • 若不使用 IAP、VPN 或內部網路,VM 仍需要可到達的 SSH 路徑

它適合團隊協作,也常和 IAP 一起使用。

方法三:透過 Cloud IAP 轉送 SSH

IAP TCP forwarding 會先驗證 IAM,再把 TCP 流量轉送到內部 IP。這表示 VM 可以不配置外部 IP,也不用自己維護 Bastion Host。

它可以減少公開管理入口,但仍要正確設定來源範圍、IAP 角色與 OS Login/SSH 權限。IAP 是連線通道,不會取代 VM 端的登入驗證。

先逐項核對:

  1. IAP API 與控制平面存取已就緒。
  2. 防火牆允許 IAP IPv4 35.235.240.0/20 到指定 VM 的 TCP 22。
  3. 操作者具備通道與必要的 Compute 查詢權限。
  4. VM 的 OS Login/metadata SSH 登入模式與角色正確。

完整建立、連線與清理指令集中在下一節。Network Tag 限定的是防火牆目標,不是 IAP 的 IAM 授權範圍;需要限制可連線的 VM 時,管理者應核對 IAP 的資源授權方式。

連線過程如下:

當你執行 gcloud compute ssh --tunnel-through-iap 時:

  1. gcloud 連到 IAP Proxy(tunnel.cloudproxy.app)並建立 HTTPS 隧道
  2. IAP 檢查使用者是否有 iap.tunnelResourceAccessor 角色
  3. IAP 把 SSH 流量轉送到目標 VM
  4. VM 再透過 SSH Key 或 OS Login 驗證登入身分

IAP 負責授權與轉送,VM 端仍會驗證 SSH 或 OS Login 身分。排錯時要把這兩層分開看:IAP 角色不足會卡在建立隧道,OS Login 或 SSH 權限不足則會卡在登入 VM。

三種方式放在一起看

方式外部 IP身分管理連線路徑常見用途
傳統 SSH Key視路徑而定手動管理金鑰公開 IP、VPN 或內部網路個人 Lab
gcloud + OS Login視路徑而定Google IAM公開 IP、IAP 或內部網路團隊管理
Cloud IAP + OS Login不需要IAM 加 VM 端登入IAP TCP forwarding私有 VM 管理

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

別把身分與連線路徑混在一起

OS Login 管理「誰能登入」,IAP 提供「怎麼連到沒有外部 IP 的 VM」。如果需求是 VM 不配置外部 IP,又要讓管理者從外部登入,通常會把 IAP 和 OS Login 搭配使用。

IAP 還能搭配什麼?

情境感知存取(Context-Aware Access)

如果組織有更細的存取需求,可以依裝置狀態、來源位置等條件限制連線。實際可用條件會受到授權版本與組織設定影響。

IAP Desktop

IAP Desktop 是開源桌面工具(官方頁面註明非 Google 官方支援的產品),可集中管理 Windows RDP、Linux SSH 與檔案傳輸。如果平常不想一直下 gcloud 指令,可以評估是否符合團隊的操作習慣。

稽核記錄

需要追查誰在什麼時間建立連線時,可以從 Cloud Audit Logs 查看 IAP 相關活動,再依組織需求串接告警或後續分析流程。


五、實作:建立 Custom VPC 並透過 IAP 連線

這次要完成的環境

預留 60–75 分鐘,包含前置檢查、第一次 SSH、拒絕對照、復原與清理;等待權限或排錯另計。使用 Cloud Shell Bash,需要 gcloud、GNU timeout 與 grep。VM、磁碟及相關用量可能收費,不能把 e2-micro 當成無條件免費。

本次只建立獨立 VPC、us-central1 的 Subnet、一台沒有外部 IP/服務帳號的 Debian VM,以及兩條只套用本次 VM 標記的 TCP 22 規則:

規則Priority動作初始狀態用途
本次名稱加 -iap1000ALLOW啟用IAP 來源到本次 VM 的 SSH
本次名稱加 -block900DENY停用短暫阻擋同一路徑,觀察對照後停用

表格超出欄寬時,可左右捲動;鍵盤可聚焦表格後用左右方向鍵查看。

這裡不放行整個內網、不公開 HTTP、不建立 NAT、不執行自我授權或專案 IAM Binding 變更指令。VM 不呼叫需要服務身分的 API,因此不附掛服務帳號。Subnet 會啟用 Private Google Access;這只是支援服務的網路前提,不是 IAM 授權或一般 Internet 出站能力。

先確認自己有建立/刪除這些資源、啟用 API、讀取專案與 Billing,以及 IAP 通道與 SSH 登入所需權限。 Metadata SSH 與 OS Login 的權限不同;本練習不變更專案 SSH 模式。若組織要求 OS Login,使用既有核准權限;若禁止本次網路、映像或位置,停止並記錄待辦,不修改組織政策。

IAP 通道與 SSH 權限表 與 OS Login 設定 可供管理者核對。不要為了 Lab 直接把自己升成 Owner。

提前中止或連線失敗時: 不要重做準備產生新名稱。保留本次設定檔,先用停用測試拒絕規則恢復路徑,再到清理本次資源逐項處理。

舊版使用的 my-secure-vpc、asia-east1-prod、secure-vm、secure-vm-sa 與專案 IAM Binding 不會被新設定檔接管。曾做過舊版時,先查回舊專案與實際資源/授權來源,依用途確認後處理;不要因為本次新名稱查無資料,就當成舊資源已清理。

一次準備與設定恢復

改好第一行 Project ID,再執行整段。這一步只查詢雲端狀態並寫入本機設定,不建立雲端資源。括號內出錯會停止該段,不會關閉 Cloud Shell。

export NET_LAB_PROJECT='YOUR_PROJECT_ID'
export NET_LAB_CONTEXT="$HOME/cloudon-network-labs/net04-$(date -u +%Y%m%d-%H%M%S)-$RANDOM/context.env"
(
  set -eu
  case "$NET_LAB_PROJECT" in
    ''|'YOUR_PROJECT_ID'|'(unset)') echo '請先填入自己的 Project ID。' >&2; exit 1 ;;
  esac
  command -v timeout >/dev/null
  command -v grep >/dev/null
  NET_LAB_ACCOUNT="$(gcloud config get-value account)"
  case "$NET_LAB_ACCOUNT" in
    ''|'(unset)') echo '請先確認 Cloud Shell 的登入帳號。' >&2; exit 1 ;;
  esac
  gcloud projects describe "$NET_LAB_PROJECT" --format='yaml(projectId,name,projectNumber)'
  NET_LAB_BILLING="$(gcloud billing projects describe "$NET_LAB_PROJECT" --format='value(billingEnabled)')"
  if [ "$NET_LAB_BILLING" != 'True' ]; then
    echo 'Billing 尚未啟用,請先確認練習環境。' >&2
    exit 1
  fi
  NET_LAB_REGION='us-central1'
  NET_LAB_ZONE='us-central1-a'
  NET_LAB_NAME="$(basename "$(dirname "$NET_LAB_CONTEXT")")"
  NET_LAB_NETWORK="$NET_LAB_NAME-net"
  NET_LAB_SUBNET="$NET_LAB_NAME-subnet"
  NET_LAB_ALLOW="$NET_LAB_NAME-iap"
  NET_LAB_BLOCK="$NET_LAB_NAME-block"
  mkdir -p "$(dirname "$NET_LAB_CONTEXT")"
  (
    umask 077
    for field in NET_LAB_PROJECT NET_LAB_REGION NET_LAB_ZONE NET_LAB_NAME \
      NET_LAB_NETWORK NET_LAB_SUBNET NET_LAB_ALLOW NET_LAB_BLOCK; do
      printf 'export %s=%q\n' "$field" "${!field}"
    done > "$NET_LAB_CONTEXT"
  )
  printf '帳號:%s\n本次設定檔:%s\n' "$NET_LAB_ACCOUNT" "$NET_LAB_CONTEXT"
)

核對帳號、專案與設定檔完整路徑。後續每段都從這份檔案讀回位置與名稱,不修改 gcloud 預設專案或 Zone。同一次練習只做一次準備。

Cloud Shell 重新連線後,如何恢復設定?

只載入自己在本篇產生的設定檔。先列出候選檔案,再把第二行換成記錄的完整路徑;檔案沒有登入權杖,但 source 會執行其內容,不要載入陌生來源的檔案。

ls -lt "$HOME/cloudon-network-labs"/*/context.env
export NET_LAB_CONTEXT="$HOME/cloudon-network-labs/替換成本次目錄/context.env"
(
  set -eu
  source "${NET_LAB_CONTEXT:?請先指定本次設定檔路徑}"
  printf 'Project=%s\nZone=%s\nVM=%s\nBlock rule=%s\n' \
    "$NET_LAB_PROJECT" "$NET_LAB_ZONE" "$NET_LAB_NAME" "$NET_LAB_BLOCK"
)

若家目錄未保留,請從自己的筆記與 Console 找回舊專案、位置和名稱。不要重跑準備後用另一組名稱查詢。

步驟 1:建立 Custom VPC

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud services enable compute.googleapis.com iap.googleapis.com --project="$NET_LAB_PROJECT"
  gcloud compute networks create "$NET_LAB_NETWORK" \
    --project="$NET_LAB_PROJECT" --subnet-mode=custom
)

本次網路沒有自動建立的 Subnet,也不依賴 default VPC。若後面任何建立步驟失敗,前面成功建立的資源仍在,應依同一份設定清理。

步驟 2:建立 Subnet

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute networks subnets create "$NET_LAB_SUBNET" \
    --project="$NET_LAB_PROJECT" --region="$NET_LAB_REGION" \
    --network="$NET_LAB_NETWORK" --range=10.91.0.0/24 \
    --enable-private-ip-google-access
  gcloud compute networks subnets describe "$NET_LAB_SUBNET" \
    --project="$NET_LAB_PROJECT" --region="$NET_LAB_REGION" \
    --format='yaml(name,network,region,ipCidrRange,privateIpGoogleAccess)'
)

核對網路、Region、10.91.0.0/24 與 privateIpGoogleAccess: true。這證明設定已存在,尚未證明任一 API 請求成功;實際連線還受 DNS、路由、防火牆及服務支援範圍影響。

步驟 3:建立防火牆規則

先建立允許規則,再建立尚未啟用的拒絕規則。兩者都只匹配 IAP IPv4 來源、本次標記與 TCP 22;Priority 900 的拒絕規則啟用時,才會比 1000 的允許規則優先。

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute firewall-rules create "$NET_LAB_ALLOW" \
    --project="$NET_LAB_PROJECT" --network="$NET_LAB_NETWORK" \
    --direction=INGRESS --action=ALLOW --rules=tcp:22 \
    --source-ranges=35.235.240.0/20 --target-tags="$NET_LAB_NAME" --priority=1000
  gcloud compute firewall-rules create "$NET_LAB_BLOCK" \
    --project="$NET_LAB_PROJECT" --network="$NET_LAB_NETWORK" \
    --direction=INGRESS --action=DENY --rules=tcp:22 \
    --source-ranges=35.235.240.0/20 --target-tags="$NET_LAB_NAME" --priority=900 --disabled
  gcloud compute firewall-rules describe "$NET_LAB_BLOCK" --project="$NET_LAB_PROJECT" \
    --format='yaml(name,network,direction,priority,sourceRanges,targetTags,denied,disabled)'
)

此時拒絕規則的 disabled 應為 true。target-tags 是防火牆的目標選擇器,不是 IAP IAM 授權,也不等於 Firewall Policy 使用的 Secure Tags。

步驟 4:建立沒有外部 IP 的 VM

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute instances create "$NET_LAB_NAME" \
    --project="$NET_LAB_PROJECT" --zone="$NET_LAB_ZONE" \
    --machine-type=e2-micro --image-family=debian-12 --image-project=debian-cloud \
    --boot-disk-type=pd-standard --boot-disk-size=10GB \
    --subnet="$NET_LAB_SUBNET" --no-address --no-service-account --no-scopes \
    --metadata=block-project-ssh-keys=TRUE \
    --tags="$NET_LAB_NAME" --labels="coa-lab=network04,coa-run=$NET_LAB_NAME"
  gcloud compute instances describe "$NET_LAB_NAME" \
    --project="$NET_LAB_PROJECT" --zone="$NET_LAB_ZONE" \
    --format='yaml(name,status,zone,networkInterfaces,serviceAccounts,disks,tags)'
)

核對 VM 為 RUNNING、Zone 正確、網路介面屬於本次 Subnet、沒有外部 natIP,且沒有服務帳號。block-project-ssh-keys 阻擋專案 metadata 金鑰,不會停用組織要求的 OS Login。

沒有外部 IP 要看網路設定,不能用 curl ifconfig.me 逾時推論。 逾時也可能來自 DNS、服務故障或防火牆;有 NAT、代理或其他出口時,沒有外部 IP 的 VM 仍可能連到 Internet。

步驟 5:透過 IAP 連線

在 Cloud Shell 執行,登入後只執行 hostname 再結束連線:

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute ssh "$NET_LAB_NAME" \
    --project="$NET_LAB_PROJECT" --zone="$NET_LAB_ZONE" \
    --tunnel-through-iap --command='hostname'
)

第一次可能會提示建立/解鎖 SSH 金鑰、確認 host key,或等待 VM 的 SSH 服務就緒。依提示處理;成功輸出本次 VM 的 hostname 才能繼續拒絕測試。IAP 權限失敗、Linux 登入被拒或 VM 尚未就緒時,先排錯,不要用後面的失敗掩蓋原本就不能登入。

驗證結果

接下來會短暫啟用拒絕規則。指令使用新的 SSH 連線,並限制等待時間;EXIT trap 會嘗試停用本次拒絕規則,即使測試出錯或收到一般中斷訊號,也會先做復原。

設定傳播需要時間。 啟用後若新連線仍成功,或超過 45 秒、出現其他權限錯誤,都不算取得對照證據。待確認狀態後沿用同一份設定重試,不要改公開 SSH。強制關閉 Cloud Shell、斷線或程序被強制終止時,trap 不能保證執行,需使用下一節的獨立復原指令。

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  NET_LAB_LOG="$(mktemp)"
  restore_iap() {
    if ! gcloud compute firewall-rules update "$NET_LAB_BLOCK" \
      --project="$NET_LAB_PROJECT" --disabled; then
      echo '復原失敗:請使用下方獨立指令停用本次拒絕規則。' >&2
      exit 1
    fi
    rm -f "$NET_LAB_LOG"
  }
  trap restore_iap EXIT
  trap 'exit 130' INT
  trap 'exit 143' TERM
  trap 'exit 129' HUP
  gcloud compute firewall-rules update "$NET_LAB_BLOCK" \
    --project="$NET_LAB_PROJECT" --no-disabled
  gcloud compute firewall-rules describe "$NET_LAB_BLOCK" --project="$NET_LAB_PROJECT" \
    --format='yaml(name,priority,sourceRanges,targetTags,denied,disabled)'
  set +e
  timeout 45s gcloud compute ssh "$NET_LAB_NAME" \
    --project="$NET_LAB_PROJECT" --zone="$NET_LAB_ZONE" \
    --tunnel-through-iap --command='hostname' \
    --ssh-flag='-oConnectTimeout=10' --ssh-flag='-oConnectionAttempts=1' \
    > "$NET_LAB_LOG" 2>&1
  NET_LAB_SSH_STATUS=$?
  set -e
  cat "$NET_LAB_LOG"
  if [ "$NET_LAB_SSH_STATUS" -eq 0 ]; then
    echo '連線仍成功,尚未觀察到拒絕;先確認規則與設定傳播。' >&2
    exit 1
  fi
  if [ "$NET_LAB_SSH_STATUS" -eq 124 ] || \
    ! grep -Eiq '\[4003:|failed to connect to backend' "$NET_LAB_LOG"; then
    echo '尚未取得可判讀的 IAP backend 失敗證據;請分辨逾時、IAM 與 SSH 登入錯誤。' >&2
    exit 1
  fi
  echo '觀察到 IAP backend 連線失敗;仍需完成停用與重新連線核對。'
)

IAP 錯誤 4003 代表連線/防火牆問題,也可能是客體服務沒在監聽,不能只憑錯誤碼就宣稱規則測試通過。需要保留「變更前成功、拒絕啟用時失敗、停用後恢復」三份證據,以及這次變更的精確規則名稱與時間。

停用測試拒絕規則

這段也是失敗後的獨立復原入口。它從 Cloud Shell 呼叫控制平面,不依賴 SSH 通道;先恢復自己的設定檔路徑,再執行:

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute firewall-rules update "$NET_LAB_BLOCK" \
    --project="$NET_LAB_PROJECT" --disabled
  gcloud compute firewall-rules describe "$NET_LAB_BLOCK" --project="$NET_LAB_PROJECT" \
    --format='yaml(name,disabled)'
  gcloud compute ssh "$NET_LAB_NAME" \
    --project="$NET_LAB_PROJECT" --zone="$NET_LAB_ZONE" \
    --tunnel-through-iap --command='hostname'
)

核對 disabled: true 且 hostname 再次成功。若仍失敗,先確認設定傳播、適用政策、IAP 與登入模式;不要追加專案級 Owner、把 SSH 開給 0.0.0.0/0 或停用組織安全政策。

查看流程與節點文字

箭頭表示流程方向;方括號與引號內是節點名稱,可搭配下方圖解閱讀。

flowchart TB
  A["專用 VPC、Subnet、VM<br/>只有 IAP 來源的 TCP 22"] --> B["基準:hostname 成功"]
  B --> C["短暫啟用 priority 900 拒絕<br/>本次標記、IAP 來源、TCP 22"]
  C --> D["新 SSH 連線失敗<br/>核對 backend 錯誤與變更時間"]
  D --> E["trap/獨立指令停用拒絕規則"]
  E --> F["復原:hostname 再次成功"]
  F --> G["依本次設定清理<br/>VM、磁碟、兩條規則、Subnet、VPC"]
  C -. "逾時、權限錯誤或意外成功<br/>都先復原,不算通過" .-> E
失敗本身不是成功標準。對照測試需要變更前後都能登入,以及變更期間可解釋的網路失敗;最後仍須確認資源清理。

清理本次資源

在 Cloud Shell 逐段執行,先核對本次 VM 與磁碟,再於 CLI 提示時確認刪除。不要同時執行多段;不要略過確認或刪整個專案。若已加入重要資料、其他磁碟或別的工作負載,先另外評估。

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute instances describe "$NET_LAB_NAME" \
    --project="$NET_LAB_PROJECT" --zone="$NET_LAB_ZONE" --format='yaml(name,labels,disks)'
  gcloud compute instances delete "$NET_LAB_NAME" \
    --project="$NET_LAB_PROJECT" --zone="$NET_LAB_ZONE" --delete-disks=boot
)

再分別刪除兩條規則、Subnet 與 VPC:

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute firewall-rules delete "$NET_LAB_BLOCK" --project="$NET_LAB_PROJECT"
)
(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute firewall-rules delete "$NET_LAB_ALLOW" --project="$NET_LAB_PROJECT"
)
(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute networks subnets delete "$NET_LAB_SUBNET" \
    --project="$NET_LAB_PROJECT" --region="$NET_LAB_REGION"
)
(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute networks delete "$NET_LAB_NETWORK" --project="$NET_LAB_PROJECT"
)

中途建立失敗或已做過部分清理時,只有查明是本次名稱的 NOT_FOUND 才跳到下一段。權限不足、查詢失敗、資源使用中都不是已刪除;記下仍待處理的完整名稱,不要忽略錯誤。

如果 VM 建立失敗,卻留下本次同名開機磁碟?

先從下方最後核對確認磁碟仍存在,再描述它。僅在名稱、Zone、用途均為本次練習,且不再附掛重要資源時執行刪除;正常刪除 VM 與 boot disk 後不必再做這一步。

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  gcloud compute disks describe "$NET_LAB_NAME" \
    --project="$NET_LAB_PROJECT" --zone="$NET_LAB_ZONE" --format='yaml(name,zone,users,labels)'
  gcloud compute disks delete "$NET_LAB_NAME" --project="$NET_LAB_PROJECT" --zone="$NET_LAB_ZONE"
)

最後核對六個本次名稱。每個查詢必須成功且沒有剩餘項目;函式會把查詢錯誤與仍有資源分別回報,不能將空白畫面當成查詢成功。

(
  set -eu
  source "${NET_LAB_CONTEXT:?請先完成準備或恢復設定檔}"
  require_absent() {
    local remaining
    if ! remaining="$(gcloud "$@")"; then
      echo '查詢失敗,無法確認已清理。' >&2
      return 1
    fi
    if [ -n "$remaining" ]; then
      printf '仍有本次資源,請核對後清理:\n%s\n' "$remaining" >&2
      return 1
    fi
  }
  require_absent compute instances list --project="$NET_LAB_PROJECT" \
    --zones="$NET_LAB_ZONE" --filter="name=$NET_LAB_NAME" --format='value(name)'
  require_absent compute disks list --project="$NET_LAB_PROJECT" \
    --zones="$NET_LAB_ZONE" --filter="name=$NET_LAB_NAME" --format='value(name)'
  for rule in "$NET_LAB_ALLOW" "$NET_LAB_BLOCK"; do
    require_absent compute firewall-rules list --project="$NET_LAB_PROJECT" \
      --filter="name=$rule" --format='value(name)'
  done
  require_absent compute networks subnets list --project="$NET_LAB_PROJECT" \
    --regions="$NET_LAB_REGION" --filter="name=$NET_LAB_SUBNET" --format='value(name)'
  require_absent compute networks list --project="$NET_LAB_PROJECT" \
    --filter="name=$NET_LAB_NETWORK" --format='value(name)'
  echo '六個本次資源名稱均未列出。'
)

保留設定檔、三段連線結果與清理輸出。本篇不另外建立 NAT、保留 IP、快照或應用服務帳號,也不在清理時停用 API;若自行加過其他資源,需另外核對。停止 VM 不等於刪除磁碟;Billing 資料也可能延遲,不能以即時零元代替資源清單。

自我檢核:完成操作後,能說明這三件事嗎?
  1. 為何 priority 900 的 DENY 沒有一開始就擋住? 它先以 disabled 建立;停用的規則不參與比對,數字小也不會生效。
  2. 4003 一定代表這條防火牆擋住嗎? 不一定,也可能是客體沒在監聽。要核對新連線、規則範圍、變更時間,以及前後的成功基準。
  3. Subnet 開了 Private Google Access,就能讀任何 bucket 嗎? 不能;還需網路條件、服務支援與該資源的授權。沒有服務帳號的 VM 也不會自動獲得物件讀取權。

若只有建立成功、尚未取得三段證據或仍有資源未清理,請保留未完成項目;不要只因為指令跑過就勾選整份實作完成。


六、做完後整理一下

這篇的主線其實只有一條:先決定資源位於哪個網路範圍,再用路由與防火牆控制資料路徑,最後替管理者提供一條不必公開 VM 的連線方式。

VPC 與 Subnet

  • GCP VPC 是全球資源,Subnet 是區域資源
  • Custom Mode 讓團隊自行決定 Region 與 CIDR
  • Auto Mode 可以轉成 Custom Mode,但不能切回 Auto

CIDR 規劃

  • GCP 會在主要範圍保留 4 個位址,估算時要另外留成長空間
  • 用 RFC 1918 私有 IP 範圍(10.x.x.x、172.16.x.x、192.168.x.x)
  • 為容器環境預留 Secondary IP Range

防火牆

  • 防火牆有狀態,允許連線後會自動放行對應回程流量
  • 在同一組匹配的 VPC rules 中比較 Priority;跨政策先查評估順序,同值衝突由 DENY 生效
  • 每條規則都應有用途、擁有者與退場條件

管理連線

  • OS Login 管理誰能登入,IAP 提供抵達私有 VM 的連線路徑
  • 使用 IAP 仍要設定 IAM、防火牆與 VM 端登入權限

下一步學習資源

官方文件

實驗室實作

Qwiklabs 已經併進 Google Skills(原 Google Cloud Skills Boost),舊的 qwiklabs.com 連結大多失效或重導了。直接到 Google Skills 上搜尋對應的 hands-on lab 即可:

  • 在 Google Skills 搜尋「VPC Networks」,練習建立 VPC 與 Subnet
  • 搜尋「Firewall Rules」,練習設定與驗證防火牆規則
  • 搜尋「Cloud IAP」或「IAP for TCP forwarding」,練習連線到沒有外部 IP 的 VM

進階主題

  • VPC Peering:連接兩個 VPC
  • Shared VPC:讓多個專案共用集中管理的網路
  • Cloud VPN 與 Cloud Interconnect:連接地端與 Google Cloud
  • Private Service Connect:透過私有 IP 使用服務

系列文章連結


常見問題 FAQ

Q1: VPC 與 Subnet 有什麼差異?

A: VPC 是全球性的虛擬網路容器,Subnet 是 VPC 內特定區域的 IP 地址範圍。一個 VPC 可包含多個跨區域的 Subnet。

Q2: 為什麼 Cloud IAP 不需要外部 IP?

A: IAP Proxy 會把通過授權的 TCP 流量轉送到 VM 的內部 IP,所以 VM 本身不必配置外部 IP。防火牆仍要允許 IAP 的來源範圍連到指定連接埠。

Q3: 防火牆規則的優先權如何運作?

A: 先確認政策評估順序,再在適用且已啟用的 VPC rules 內比較匹配規則的 Priority。數字較小者優先;同值且 ALLOW、DENY 同時匹配時由 DENY 生效。停用規則不參與比對,跨政策不能直接混排數字。團隊預留數字區間是管理慣例,不是平台限制。

Q4: Auto Mode VPC 可以轉換成 Custom Mode 嗎?

A: 可以,但只能從 Auto Mode 轉成 Custom Mode,不能再切回 Auto Mode。轉換既有網路需核對實際專案、網路與影響範圍,依核准的網路變更流程處理;本篇實作直接建立新的 Custom VPC,不轉換既有網路。

Q5: 如何監控防火牆規則是否被使用?

A: 可以先啟用 Firewall Rules Logging,再用 Firewall Insights 檢查規則的使用狀況。看到長期沒有命中的規則時,先確認擁有者與用途,再依變更流程停用或移除,不要只看一次報表就直接刪除。

Q6: GCP VPC vs AWS VPC 的主要差異是什麼?

A: GCP VPC 是全球資源,Subnet 是區域資源,可涵蓋同一 Region 內的多個 Zone;AWS VPC 則是區域資源,Subnet 位於單一 Availability Zone。哪一種較適合,要看既有架構、維運方式與跨區需求。

Q7: IAP TCP forwarding 防火牆如何設定?

A: IPv4 的 IAP TCP forwarding 需允許 35.235.240.0/20 到目標 VM 的指定 port(如 TCP 22)。可用 Network Tag 或服務帳號限定防火牆目標;操作者的 IAP IAM 與 SSH 登入權限仍需另外核對。

Q8: OS Login 是什麼?

A: OS Login 把 Linux VM 的 SSH 登入資格交給 IAM 管理,減少逐台維護 metadata SSH Key 的工作。它也可以搭配兩步驟驗證,相關管理活動則可透過稽核記錄追查。


準備 ACE 時可以怎麼記?

先掌握這幾個判斷點:

  1. GCP VPC 是全球資源,Subnet 是區域資源——跟 AWS 不同
  2. 先確認政策評估順序,再比較匹配的 VPC rules;已啟用規則中 Priority 越小越優先,同值衝突由 DENY 生效
  3. 隱含規則是 Ingress 拒絕、Egress 允許,不是所有專案的實際完整政策
  4. Cloud IAP TCP forwarding 可連到沒有外部 IP 的 VM,防火牆需允許 35.235.240.0/20
  5. Private Google Access 提供無外部 IP 的 VM 到支援 API 的網路路徑;仍需 DNS、路由、防火牆與資源授權
  6. 題目涉及成本時,要分開看網路資源本身、流量方向與是否跨區,不要只憑「用了 VPC」判斷

三個常見題型

Q:Custom VPC 可以改成 Auto Mode 嗎? A:不行。Auto Mode 可以轉 Custom(單向不可逆),但 Custom 不能轉回 Auto。

Q:同一個 VPC 的兩條已啟用規則都匹配,一條 ALLOW tcp:80 priority 1000,一條 DENY tcp:80 priority 1000,且沒有先終止評估的政策,結果是? A:DENY。同 Priority 的匹配 VPC rules 由 DENY 勝出。

Q:VM 沒有外部 IP,但需要存取 Cloud Storage API,怎麼做? A:可在 Subnet 啟用 Private Google Access,並核對支援服務、DNS、路由與防火牆;呼叫 Cloud Storage 的身分仍須具有對應資源權限。啟用 PGA 本身不會授權讀取物件。


下一篇會接著看 GCP-105:看懂身分、角色與權限繼承,把「誰可以對哪些資源做什麼」這件事拆開說清楚。

GCP 入門基礎 — 第 4 篇/共 5 篇 查看系列全覽 →

讀完後,留一個學習紀錄

試著用自己的話說出一個重點,以及你會如何運用。實作文章請先核對結果與清理資源,再標記為讀完。

文章進度以你確認讀完的標記為準,可隨時取消。舊版造訪紀錄保留,但不計入讀完;這份自評不代表已掌握內容。

留言討論

文章目錄與系列

徽章解鎖!