政策型路徑 (PBR) 程式碼研究室

1. 簡介

策略路徑

策略路徑可讓您依據封包目的地 IP 位址等條件選擇下一個躍點。此外,您也可以依通訊協定和來源 IP 位址比對流量。相符的流量會重新導向至內部網路負載平衡器。這可以協助您將防火牆等設備插入網路流量的路徑。

建立策略路徑時,您可以選取哪些資源可讓路徑處理流量。路徑可套用至下列項目:

  • 整個網路:所有虛擬機器 (VM) 執行個體、VPN 閘道和互連網路
  • 使用網路標記:選取虛擬私有雲中的 VM 執行個體
  • 互連網路區域:所有透過區域 VLAN 連結進入虛擬私有雲網路的所有流量

策略路徑的下一個躍點必須是有效的內部網路負載平衡器,且與策略路徑位於相同的虛擬私有雲網路。

內部網路負載平衡器預設使用對稱式雜湊,因此流量可在傳出和傳迴路徑上觸及同一個設備,而無須設定來源 NAT。

策略路徑的優先順序高於其他路徑類型,但特殊傳迴路徑除外。

如果兩個策略路的優先順序相同,Google Cloud 會使用確定性的內部演算法選取單一策略路徑,並忽略其他優先順序相同的路徑。策略路徑不會使用最長前置字串的比對,且只會選取優先順序最高的路徑。

您可以為單向流量建立單一規則,也可以為雙向流量建立多個規則。

如要搭配 Cloud Interconnect 使用策略路徑,必須將路徑套用至整個區域中的所有 Cloud Interconnect 連線。策略路徑無法只套用至個別 Cloud Interconnect 連線。

如果 VM 執行個體是從策略路徑接收流量,就必須啟用 IP 轉送功能。

產品上市業務計畫的相關考量事項

採用策略路徑須具有特殊設定,才能用於下列方式。

例如將 PBR 與 GKE、PSC 或 PGA/PSA 搭配使用。

如要進一步瞭解搭配 GKE 使用 PBR 的情況,請按這裡;如要查看 PBR 的一般限制,請按這裡

課程內容

  • 如何設定策略路徑

軟硬體需求

  • 具備部署執行個體與設定網路元件的知識
  • 虛擬私有雲防火牆設定知識

2. 測試環境

本程式碼研究室會使用單一虛擬私有雲。這個環境會有兩個運算資源 (Clienta 和 Clientb),將封包傳送至另一個伺服器資源。只要使用 PBR 和篩選器,我們就會透過其他運算資源強制執行來自 Clienta,以強制執行防火牆,同時用戶端流量則直接流向伺服器。下圖說明路徑。

bff32b01ada8e9ad.png

在上圖中,理論上應有 PBR 路徑的 ILB (網路內部負載平衡器)。為方便圖表,我們省略了這部分。

3. 事前準備

如要使用程式碼研究室,您必須有一個專案。

從 cloudshell:

export project_id=`gcloud config list --format="value(core.project)"`
export region=us-central1
export zone=us-central1-a
export prefix=codelab-pbr

4. 啟用 API

請啟用 API 來使用產品

從 cloudshell:

gcloud services enable compute.googleapis.com
gcloud services enable networkconnectivity.googleapis.com

5. 建立虛擬私有雲網路和子網路

虛擬私人雲端網路

建立程式碼研究室-pbr-vpc VPC:

從 cloudshell:

gcloud compute networks create $prefix-vpc --subnet-mode=custom 

子網路

在所選區域中建立個別的子網路:

從 cloudshell:

gcloud compute networks subnets create $prefix-vpc-subnet \
   --range=10.10.10.0/24 --network=$prefix-vpc --region=${region}

6. 建立防火牆規則

如要允許 IAP 連線至您的 VM 執行個體,請建立下列防火牆規則:

  • 適用於您要透過 IAP 存取的所有 VM 執行個體。
  • 允許來自 IP 範圍 35.235.240.0/20 的輸入流量。這個範圍包含 IAP 用於 TCP 轉送的所有 IP 位址。

從 cloudshell:

gcloud compute firewall-rules create $prefix-allow-iap-proxy \
--direction=INGRESS \
--priority=1000 \
--network=$prefix-vpc \
--action=ALLOW \
--rules=tcp:22 \
--source-ranges=35.235.240.0/20

如要允許將標準 HTTP 通訊埠 (TCP 80) 和 ICMP 通訊協定傳送至伺服器,請按照以下步驟操作:

  • 適用於網路標記為「server」的資源
  • 允許所有來源的輸入流量

從 cloudshell:

gcloud compute firewall-rules create $prefix-allow-http-icmp \
--direction=INGRESS \
--priority=1000 \
--network=$prefix-vpc \
--action=ALLOW \
--rules=tcp:80,icmp \
--source-ranges=0.0.0.0/0 \
--target-tags=server

如要允許 FW 接收封包,請允許所有通訊協定和通訊埠的輸入。

  • 適用於網路標記為「fw」的資源
  • 允許來自 10.10.10.0/24 來源的輸入流量

從 cloudshell:

gcloud compute firewall-rules create $prefix-fw-allow-ingress \
--direction=INGRESS \
--priority=1000 \
--network=$prefix-vpc \
--action=ALLOW \
--rules=all \
--source-ranges=10.10.10.0/24 \
--target-tags=fw

允許健康狀態檢查探測

  • 適用於具有「fw」網路標記的資源
  • 允許來自健康狀態檢查範圍的輸入流量

從 cloudshell:

gcloud compute firewall-rules create $prefix-allow-hc-ingress \
--direction=INGRESS \
--priority=1000 \
--network=$prefix-vpc \
--action=ALLOW \
--rules=tcp:80 \
--source-ranges=130.211.0.0/22,35.191.0.0/16 \
--target-tags=fw

7. 建立 Cloud Router 路由器並Cloud NAT

本節的目的是讓私人虛擬機器從網際網路下載適當的軟體套件。

建立 Cloud Router

從 cloudshell:

gcloud compute routers create ${prefix}-cr \
--region=${region} \
--network=${prefix}-vpc

建立 Cloud NAT 閘道

從 cloudshell:

gcloud compute routers nats create ${prefix}-nat-gw-${region} \
--router=${prefix}-cr \
--router-region=${region} \
--auto-allocate-nat-external-ips \
--nat-all-subnet-ip-ranges

8. 建立運算執行個體

建立運算執行個體 ClientA、ClientB、FW 和 Server:

從 cloudshell:

gcloud compute instances create clienta \
   --subnet=$prefix-vpc-subnet \
   --no-address \
   --private-network-ip=10.10.10.10 \
   --zone $zone \
   --tags client \
   --metadata startup-script='#! /bin/bash
apt-get update'

從 cloudshell:

gcloud compute instances create clientb \
   --subnet=$prefix-vpc-subnet \
   --no-address \
   --private-network-ip=10.10.10.11 \
   --zone $zone \
   --tags client \
   --metadata startup-script='#! /bin/bash
apt-get update'

從 cloudshell:

gcloud compute instances create server \
   --subnet=$prefix-vpc-subnet \
   --no-address \
   --private-network-ip=10.10.10.200 \
   --zone $zone \
   --tags server \
   --metadata startup-script='#! /bin/bash
sudo su
apt-get update
apt-get -y install tcpdump
apt-get -y install nginx
cat > /var/www/html/index.html << EOF
<html><body><p>Server</p></body></html>
EOF'

從 cloudshell:

gcloud compute instances create fw \
   --subnet=$prefix-vpc-subnet \
   --can-ip-forward \
   --no-address \
   --private-network-ip=10.10.10.75 \
   --zone $zone \
   --tags fw \
   --metadata startup-script='#! /bin/bash
apt-get update
sudo apt-get -y install tcpdump
sudo apt-get -y install nginx
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -I FORWARD -d 10.10.10.200 -j REJECT'

9. 測試連線但不使用 PBR

透過 SSH 連線至我們最近建立的用戶端運算 VM,並驗證兩個用戶端與伺服器之間的連線。

從 cloudshell1 登入 clienta:

gcloud compute ssh clienta --zone=$zone --tunnel-through-iap

執行下列指令:

ping 10.10.10.200 -c 5
curl 10.10.10.200/index.html

連線偵測 (ping) 和 curl 要求應該會成功。

輸出:

root@clienta:~$ ping 10.10.10.200 -c 5
PING 10.10.10.200 (10.10.10.200) 56(84) bytes of data.
64 bytes from 10.10.10.200: icmp_seq=1 ttl=64 time=1.346 ms
64 bytes from 10.10.10.200: icmp_seq=2 ttl=64 time=0.249 ms
64 bytes from 10.10.10.200: icmp_seq=3 ttl=64 time=0.305 ms
64 bytes from 10.10.10.200: icmp_seq=4 ttl=64 time=0.329 ms
64 bytes from 10.10.10.200: icmp_seq=5 ttl=64 time=0.240 ms
root@clienta:~$ curl 10.10.10.200/index.html
<html><body><p>Server</p></body></html>

按一下「+」即可開啟其他 Cloud Shell 分頁。

3722d8574c3812b1.png

透過 cloudshell2 設定要使用的變數:

export project_id=`gcloud config list --format="value(core.project)"`
export region=us-central1
export zone=us-central1-a
export prefix=codelab-pbr

從 cloudshell2 SSH 到 Clientb:

gcloud compute ssh clientb --zone=$zone --tunnel-through-iap

執行下列指令:

ping 10.10.10.200 -c 5
curl 10.10.10.200/index.html

連線偵測 (ping) 和 curl 要求應該會成功。

輸出:

root@clientb:~$ ping 10.10.10.200 -c 5
PING 10.10.10.200 (10.10.10.200) 56(84) bytes of data.
64 bytes from 10.10.10.200: icmp_seq=1 ttl=64 time=1.346 ms
64 bytes from 10.10.10.200: icmp_seq=2 ttl=64 time=0.249 ms
64 bytes from 10.10.10.200: icmp_seq=3 ttl=64 time=0.305 ms
64 bytes from 10.10.10.200: icmp_seq=4 ttl=64 time=0.329 ms
64 bytes from 10.10.10.200: icmp_seq=5 ttl=64 time=0.240 ms
root@clientb:~$ curl 10.10.10.200/index.html
<html><body><p>Server</p></body></html>

接著退出 VM 終端機,然後返回 Cloud Shell。

10. 建立執行個體群組

為實際工作環境 VM 建立非代管執行個體群組。

從 cloudshell:

gcloud compute instance-groups unmanaged create pbr-uig --zone=$zone

將 fw 執行個體新增至非代管執行個體群組。

從 cloudshell:

gcloud compute instance-groups unmanaged add-instances pbr-uig --instances=fw --zone=$zone

11. 建立健康狀態檢查

為後端服務建立健康狀態檢查。我們會進行簡單的 TCP 通訊埠 80 健康狀態檢查。

從 cloudshell:

gcloud compute health-checks create tcp $prefix-hc-tcp-80 --region=$region --port 80

12. 建立後端服務

建立要附加至轉送規則的後端服務。

從 cloudshell:

gcloud compute backend-services create be-pbr --load-balancing-scheme=internal --protocol=tcp --region=$region --health-checks=$prefix-hc-tcp-80 --health-checks-region=$region

現在,請將執行個體群組新增至後端服務。

從 cloudshell:

gcloud compute backend-services add-backend be-pbr --region=$region --instance-group=pbr-uig --instance-group-zone=$zone

13. 建立轉送規則

從 cloudshell:

gcloud compute forwarding-rules create fr-pbr --region=$region --load-balancing-scheme=internal --network=$prefix-vpc --subnet=$prefix-vpc-subnet --ip-protocol=TCP --ports=ALL --backend-service=be-pbr --backend-service-region=$region --address=10.10.10.25 --network-tier=PREMIUM

14. 建立 PBR 規則

這項 PBR 規則適用於用戶端。如果來源 IP 為 10.10.10.10/32 (用戶端的位址),且目的地 IP 為 10.10.10.0/24,這個設定會將所有 IPv4 流量轉送至轉送規則 10.10.10.25。

這表示 Clienta 會比對 PBR,而不是 clientb。

從 cloudshell:

gcloud network-connectivity policy-based-routes create pbr-client \
   --network=projects/$project_id/global/networks/$prefix-vpc \
   --next-hop-ilb-ip=10.10.10.25 \
   --source-range=10.10.10.10/32 \
   --destination-range=10.10.10.0/24 \
   --protocol-version=IPv4 \
   --priority=1000 \
   --tags=client

這項 PBR 規則適用於伺服器。如果來源 IP 為 10.10.10.200/32,目的地 IP 為 10.10.10.10/32,這個設定會將所有 IPv4 流量轉送至轉送規則 10.10.10.25。

從 cloudshell:

gcloud network-connectivity policy-based-routes create pbr-server \
   --network=projects/$project_id/global/networks/$prefix-vpc \
   --next-hop-ilb-ip=10.10.10.25 \
   --source-range=10.10.10.200/32 \
   --destination-range=10.10.10.10/32 \
   --protocol-version=IPv4 \
   --priority=2000 \
   --tags=server

15. 測試與 PBR 的連線

我們將驗證 PBR 功能。「fw」執行個體具有 iptable 設定,可拒絕目的地為伺服器的要求。如果 PBR 可以運作,先前在 clienta 上的要求現在就會失敗,而 Clientb 則仍在成功。

透過 SSH 連線至 clienta 運算 VM,並執行相同的測試。

從 cloudshell1:

gcloud compute ssh clienta --zone=$zone --tunnel-through-iap

執行下列指令:

ping 10.10.10.200 -c 5
curl 10.10.10.200/index.html

輸出:

root@clienta:~$ ping 10.10.10.200 -c 5
PING 10.10.10.200 (10.10.10.200) 56(84) bytes of data.
From 10.10.10.75 icmp_seq=1 Destination Port Unreachable
From 10.10.10.75 icmp_seq=2 Destination Port Unreachable
From 10.10.10.75 icmp_seq=3 Destination Port Unreachable
From 10.10.10.75 icmp_seq=4 Destination Port Unreachable
From 10.10.10.75 icmp_seq=5 Destination Port Unreachable
root@clienta:~$ curl 10.10.10.200/index.html
curl: (7) Failed to connect to 10.10.10.200 port 80: Connection refused

要求失敗,因此我們可以確認 PBR 正主動將 clienta 的流量轉送至設為封鎖此流量的 fw 執行個體。

透過 SSH 連線至 Clientb,並執行相同的連線能力測試。

從 cloudshell2:

gcloud compute ssh clientb --zone=$zone --tunnel-through-iap

執行下列指令:

ping 10.10.10.200 -c 5
curl 10.10.10.200/index.html

輸出:

root@clientb:~$ ping 10.10.10.200 -c 5
PING 10.10.10.200 (10.10.10.200) 56(84) bytes of data.
64 bytes from 10.10.10.200: icmp_seq=1 ttl=63 time=0.361 ms
64 bytes from 10.10.10.200: icmp_seq=2 ttl=63 time=0.475 ms
64 bytes from 10.10.10.200: icmp_seq=3 ttl=63 time=0.379 ms
root@clientb:~$ curl 10.10.10.200
<html><body><p>Server</p></body></html>

如您所見,從用戶端對伺服器發出的要求已成功。這是因為要求與來源 IP 的 PBR 規則不符。

16. [選用] 使用防火牆擷取進行驗證

在本節中,您可以在防火牆 VM 上執行封包擷取,藉此驗證 PBR。

您應該會在 cloudshell1 和 cloudshell2 中,有 SSH 連線至 clienta 和 clientb。

按一下「+」即可開啟其他 Cloud Shell 分頁。

5eb3a9956f7e41a2.png

透過 cloudshell3 設定變數:

export project_id=`gcloud config list --format="value(core.project)"`
export region=us-central1
export zone=us-central1-a
export prefix=codelab-pbr

透過 SSH 連接 fw:

gcloud compute ssh fw --zone=$zone --tunnel-through-iap

在 fw (cloudshell3) 上執行下列指令:

sudo tcpdump -i any icmp -nn

從 clienta (cloudshell1) 執行連線偵測 (ping) 測試:

ping 10.10.10.200 -c 5

從 clientb (cloudshell2) 執行連線偵測 (ping) 測試:

ping 10.10.10.200 -c 5

fw 的輸出內容 (cloudshell 3):

root@fw:~$ sudo tcpdump -i any icmp -nn
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
17:07:42.215297 ens4  In  IP 10.10.10.10 > 10.10.10.200: ICMP echo request, id 25362, seq 1, length 64
17:07:42.215338 ens4  Out IP 10.10.10.75 > 10.10.10.10: ICMP 10.10.10.200 protocol 1 port 51064 unreachable, length 92
17:07:43.216122 ens4  In  IP 10.10.10.10 > 10.10.10.200: ICMP echo request, id 25362, seq 2, length 64
17:07:43.216158 ens4  Out IP 10.10.10.75 > 10.10.10.10: ICMP 10.10.10.200 protocol 1 port 30835 unreachable, length 92
17:07:44.219064 ens4  In  IP 10.10.10.10 > 10.10.10.200: ICMP echo request, id 25362, seq 3, length 64
17:07:44.219101 ens4  Out IP 10.10.10.75 > 10.10.10.10: ICMP 10.10.10.200 protocol 1 port 2407 unreachable, length 92

PBR 不適用,因此 tcpdump 不會顯示來自 clientb (10.10.10.11) 的封包。

返回 Cloud Shell 清理資源。

17. 清除步驟

在 Cloud Shell 中,移除 PBR 規則、轉送規則、後端服務、健康狀態檢查、執行個體群組、運算執行個體、NAT、Cloud Router 和防火牆規則。

gcloud -q network-connectivity policy-based-routes delete pbr-client

gcloud -q network-connectivity policy-based-routes delete pbr-server

gcloud -q compute forwarding-rules delete fr-pbr --region=$region

gcloud -q compute backend-services delete be-pbr --region=$region

gcloud -q compute health-checks delete $prefix-hc-tcp-80 --region=$region

gcloud -q compute instance-groups unmanaged delete pbr-uig --zone=$zone

gcloud -q compute instances delete clienta --zone=$zone
gcloud -q compute instances delete clientb --zone=$zone
gcloud -q compute instances delete server --zone=$zone
gcloud -q compute instances delete fw --zone=$zone


gcloud -q compute routers nats delete ${prefix}-nat-gw-${region} \
--router=$prefix-cr --router-region=$region

gcloud -q compute routers delete $prefix-cr --region=$region

gcloud -q compute firewall-rules delete $prefix-allow-iap-proxy
gcloud -q compute firewall-rules delete $prefix-allow-http-icmp
gcloud -q compute firewall-rules delete $prefix-fw-allow-ingress
gcloud -q compute firewall-rules delete $prefix-allow-hc-ingress

移除子網路和虛擬私有雲:

gcloud -q compute networks subnets delete $prefix-vpc-subnet \
    --region $region

gcloud -q compute networks delete $prefix-vpc

18. 恭喜!

恭喜您完成本程式碼研究室。

涵蓋內容

  • 策略路徑