ポリシーベースのルート(PBR)に関する Codelab

1. はじめに

ポリシーベースのルート

ポリシーベースのルートを使用すると、パケットの宛先 IP アドレス以外の要素に基づいてネクストホップを選択できます。プロトコルと送信元 IP アドレスでトラフィックを照合することもできます。一致するトラフィックは、内部ロードバランサにリダイレクトされます。これは、ファイアウォールなどのアプライアンスをネットワークトラフィックのパスに挿入するのに役立ちます。

ポリシーベースのルートを作成するときに、ルートでトラフィックを処理できるリソースを選択します。このルートは次のものに適用できます。

  • ネットワーク全体: すべての仮想マシン(VM)インスタンス、VPN ゲートウェイ、相互接続
  • ネットワーク タグの使用: VPC 内の VM インスタンスの選択
  • 相互接続リージョン: リージョンの VLAN アタッチメント経由で VPC ネットワークに到達するすべてのトラフィック

ポリシーベースのルートのネクストホップは、ポリシーベースのルートと同じ VPC ネットワークにある有効な内部ネットワーク ロードバランサである必要があります。

内部ロードバランサはデフォルトで対称ハッシュを使用するため、送信元 NAT を構成することなく、トラフィックが送信パスとリターンパスで同じアプライアンスに到達できます。

ポリシーベースのルートは、特別なリターンパスを除き、他のルートタイプよりも優先度が高くなります。

2 つのポリシーベースのルートの優先度が同じ場合、Google Cloud は決定論的な内部アルゴリズムを使用して 1 つのポリシーベースのルートを選択し、同じ優先度の他のルートを無視します。ポリシーベースのルートは最長プレフィックス マッチングを使用せず、優先度が最も高いルートのみを選択します。

一方向のトラフィックを処理するルールを 1 つ作成することも、双方向のトラフィックを処理する複数のルールを作成することもできます。

Cloud Interconnect でポリシーベースのルートを使用するには、リージョン内のすべての Cloud Interconnect 接続にルートを適用する必要があります。ポリシーベースのルートは、個々の Cloud Interconnect 接続にのみ適用することはできません。

ポリシーベースのルートからトラフィックを受信する VM インスタンスで、IP 転送を有効にする必要があります。

PBR に関する考慮事項

次の方法でポリシーベースのルートを使用するには、特別な構成が必要です。

たとえば、GKE、PSC、または PGA/PSA で PBR を使用します。

GKE を使用した PBR の詳細についてはこちらを、一般的な PBR の制限事項についてはこちらをご覧ください。

学習内容

  • ポリシーベースのルートの構成方法

必要なもの

  • インスタンスのデプロイとネットワーキング コンポーネントの構成に関する知識
  • VPC ファイアウォール構成に関する知識

2. テスト環境

この Codelab では単一の VPC を使用します。この環境には、別のサーバー リソースにパケットを送信する、clienta と clientb の 2 つのコンピューティング リソースがあります。PBR とフィルタを使用して、clientb のトラフィックはサーバーに直接送信され、clientb のトラフィックは別のコンピューティング リソースを経由してファイアウォールが適用されます。次の図にパスを示します。

bff32b01ada8e9ad.png

上の図では、技術的には PBR パス用の ILB(ネットワーク内部ロードバランサ)が必要です。図をわかりやすくするため、ここでは省略しています。

3. 始める前に

Codelab に必要なプロジェクトは 1 つです。

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 に VM インスタンスへの接続を許可するには、次のファイアウォール ルールを作成します。

  • IAP を使用してアクセスできるようにするすべての VM インスタンスに適用します。
  • 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 がパケットを受信できるようにするには、すべてのプロトコルとポートで上り(内向き)を許可します。

  • ネットワーク タグ「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. コンピューティング インスタンスを作成する

コンピューティング インスタンス 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 なしで接続をテストする

先ほど作成したクライアント コンピューティング VM に 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 タブを開きます。

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. インスタンス グループを作成する

fw VM に非マネージド インスタンス グループを作成します。

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(クライアントのアドレス)、宛先 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 が機能している場合、clientb は引き続き成功しますが、clienta で以前動作していたリクエストは失敗します。

クライアント Compute VM に SSH で接続し、同じテストを実行します。

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 がこのトラフィックをブロックするように構成された fw インスタンスに clienta のトラフィックをアクティブにルーティングしていることがわかります。

clientb に SSH で接続し、同じ接続テストを実行します。

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 から server へのリクエストは成功しています。これは、リクエストが送信元 IP の PBR ルールと一致しないためです。

16. [省略可] ファイアウォールでのキャプチャによる検証

このオプションのセクションでは、ファイアウォール VM でパケット キャプチャを行って PBR を検証できます。

cloudshell1 と cloudshell2 で clienta と clientb に SSH で接続しているはずです。

[+] をクリックして追加の 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

fw に 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 ルール、転送ルール、バックエンド サービス、ヘルスチェック、インスタンス グループ、コンピューティング インスタンス、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 は完了です。

学習した内容

  • ポリシーベースのルート