1. 简介
基于政策的路由
基于政策的路由允许您根据多个数据包的目的地 IP 地址选择下一个跃点。您还可以按协议和源 IP 地址匹配流量。匹配的流量会重定向到内部网络负载平衡器。这有助于您将防火墙等设备插入到网络流量路径中。
创建基于政策的路由时,您可以选择哪些资源可通过该路由处理其流量。路由可以应用于以下各项:
- 整个网络:所有虚拟机 (VM) 实例、VPN 网关和互联
- 使用网络标记:选择 VPC 中的虚拟机实例
- 互连区域:通过相应区域的 VLAN 连接进入 VPC 网络的所有流量
基于政策的路由的下一个跃点必须是与基于政策的路由位于同一 VPC 网络中的有效内部网络负载平衡器。
内部网络负载平衡器默认使用对称哈希,因此流量可以在不配置来源 NAT 的情况下在传出和返回路径上到达同一个设备。
基于政策的路由的优先级高于其他路由类型,但特殊返回路径除外。
如果两个基于政策的路由具有相同的优先级,Google Cloud 会使用确定性的内部算法来选择单个基于政策的路由,并忽略具有相同优先级的其他路由。基于政策的路由不使用最长前缀匹配,只会选择优先级最高的路由。
您可以为单向流量创建单个规则,也可以创建多个规则来处理双向流量。
如需将基于政策的路由与 Cloud Interconnect 搭配使用,必须将该路由应用于整个区域中的所有 Cloud Interconnect 连接。基于政策的路由不能仅应用于单个 Cloud Interconnect 连接。
接收来自基于政策的路由的流量的虚拟机实例必须启用 IP 转发。
PBR 注意事项
如需采用以下方式使用基于政策的路由,必须进行特殊配置。
例如,将 PBR 与 GKE、PSC 或 PGA/PSA 搭配使用。
如需详细了解 GKE 的 PBR,请点击此处;如需了解一般 PBR 限制,请点击此处。
学习内容
- 如何配置基于政策的路由
所需条件
- 了解如何部署实例和配置网络组件
- VPC 防火墙配置知识
2. 测试环境
此 Codelab 将利用单个 VPC。在此环境中,将有两个计算资源(clienta 和 clientb)向另一个服务器资源发送数据包。通过使用 PBR 和过滤器,我们将强制 clienta 的流量通过另一个计算资源进行防火墙强制执行,而 clientb 的流量则直接流向服务器。下图说明了该路径。

在上图中,从技术上讲,PBR 路径应有一个 ILB(网络内部负载平衡器)。为简化图表,此处已省略。
3. 准备工作
Codelab 需要单个项目。
在 Cloud Shell 中:
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
在 Cloud Shell 中:
gcloud services enable compute.googleapis.com gcloud services enable networkconnectivity.googleapis.com
5. 创建 VPC 网络和子网
VPC 网络
创建 codelab-pbr-vpc VPC:
在 Cloud Shell 中:
gcloud compute networks create $prefix-vpc --subnet-mode=custom
子网
在所选区域中创建相应的子网:
在 Cloud Shell 中:
gcloud compute networks subnets create $prefix-vpc-subnet \
--range=10.10.10.0/24 --network=$prefix-vpc --region=${region}
6. 创建防火墙规则
如需允许 IAP 连接到您的虚拟机实例,请创建一个防火墙规则,该规则应:
- 适用于您希望使用 IAP 可访问的所有虚拟机实例。
- 允许来自 IP 范围 35.235.240.0/20 的入站流量。此范围包含 IAP 用于 TCP 转发的所有 IP 地址。
在 Cloud Shell 中:
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”的资源
- 允许来自所有来源的入站流量
在 Cloud Shell 中:
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”的资源
- 允许来自 10.10.10.0/24 来源的入站流量
在 Cloud Shell 中:
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”的资源
- 允许来自健康检查范围的入站流量
在 Cloud Shell 中:
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
在 Cloud Shell 中:
gcloud compute routers create ${prefix}-cr \
--region=${region} \
--network=${prefix}-vpc
创建 Cloud NAT 网关
在 Cloud Shell 中:
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. 创建 Compute 实例
创建计算实例 ClientA、ClientB、FW 和 Server:
在 Cloud Shell 中:
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'
在 Cloud Shell 中:
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'
在 Cloud Shell 中:
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'
在 Cloud Shell 中:
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 连接到我们最近创建的客户端计算虚拟机,并验证从两个客户端到服务器的连接。
从 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 标签页。

在 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>
现在,退出虚拟机终端并返回到 Cloud Shell。
10. 创建实例组
为防火墙虚拟机创建一个非托管式实例组。
在 Cloud Shell 中:
gcloud compute instance-groups unmanaged create pbr-uig --zone=$zone
将 fw 实例添加到非托管式实例组。
在 Cloud Shell 中:
gcloud compute instance-groups unmanaged add-instances pbr-uig --instances=fw --zone=$zone
11. 创建健康检查
为后端服务创建健康检查。我们将执行简单的 TCP 端口 80 健康检查。
在 Cloud Shell 中:
gcloud compute health-checks create tcp $prefix-hc-tcp-80 --region=$region --port 80
12. 创建后端服务
创建要附加到转发规则的后端服务。
在 Cloud Shell 中:
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
现在,将实例组添加到后端服务。
在 Cloud Shell 中:
gcloud compute backend-services add-backend be-pbr --region=$region --instance-group=pbr-uig --instance-group-zone=$zone
13. 创建转发规则
在 Cloud Shell 中:
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(clienta 的地址),且目的地 IP 为 10.10.10.0/24,则会将所有 IPv4 流量路由到转发规则 10.10.10.25。
这意味着 clienta 将匹配 PBR,而 clientb 不会匹配。
在 Cloud Shell 中:
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。
在 Cloud Shell 中:
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”实例已配置 iptables,以拒绝发往服务器的请求。如果 PBR 正常运行,之前在 clienta 上有效的请求现在将失败,而 clientb 仍会成功。
通过 SSH 连接到 clienta 计算虚拟机,然后运行相同的测试。
从 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 的流量路由到配置为阻止此流量的防火墙实例。
通过 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>
如图所示,从 clientb 到服务器的请求成功。这是因为请求与来源 IP 的 PBR 规则不匹配。
16. [可选] 使用防火墙上的捕获进行验证
在此可选部分中,您有机会通过在防火墙虚拟机上捕获数据包来验证 PBR。
您应该仍然在 cloudshell1 和 cloudshell2 中与 clienta 和 clientb 保持着 SSH 连接。
点击“+”打开另一个 Cloud Shell 标签页。

在 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 连接到防火墙:
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 不适用,因此您不会在来自 clientb (10.10.10.11) 的 tcpdump 上看到任何数据包。
退出并返回到 Cloud Shell 以清理资源。
17. 清理步骤
在 Cloud Shell 中,移除 PBR 规则、转发规则、后端服务、健康检查、实例组、Compute 实例、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
移除子网和 VPC:
gcloud -q compute networks subnets delete $prefix-vpc-subnet \
--region $region
gcloud -q compute networks delete $prefix-vpc
18. 恭喜!
恭喜您完成此 Codelab。
所学内容
- 基于政策的路由