【GCP】BeyondCorp Remote Access実装〜GCPを介してAzureへ接続〜

準備
テスト用のドメインを2つ用意（Azureのインスタンスにひもづけるもの、HTTPSロードバランサにひもづけるもの）お名前ドットコムなどで用意してください。

流れ
①GCP側のネットワークを設定する
②IAPconnectorをデプロイする
③Google Load BalacerのDNSを設定する
④Azure側でインスタンスを作成する
⑤Azure側のネットワークの設定をする
⑥GCP側でVPNの設定をする
⑦GCP側、Azure側にFWの設定をする

参考URL
https://yomon.hatenablog.com/entry/2019/10/gcp_azure_vpn
https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/tutorial-lamp-stack

手順
①GCP側のネットワークを設定する
※GCPの設定はCLIで行います。以下の設定値は参考例となりますので、こちらを元に作成してみてください。

# GCP 関連変数
GCP_PROJECT=YOUR_PROJECT_ID
GCP_REGION=asia-northeast1
GCP_PUBLIC_IP_NAME=mypubip
GCP_VPC_NAME=myvpc
GCP_VPC_PREFIX=10.1.0.0/16
GCP_SUBNET_NAME=mysubnet
GCP_SUBNET_RANGE=10.1.0.0/24
GCP_GW_NAME=vpn-gw-azure
GCP_TUNNEL_NAME=azure-tunnel
GCP_GW_ROUTE=azure-gw-route
IKE_PRE_SHARED_KEY=abcd1234

パブリックIPの取得
gcloud compute addresses create ${GCP_PUBLIC_IP_NAME} \
  --project=${GCP_PROJECT} \
  --region=${GCP_REGION}	

VPCネットワーク作成
gcloud compute --project=${GCP_PROJECT} networks create ${GCP_VPC_NAME} --subnet-mode=custom
gcloud compute --project=${GCP_PROJECT} networks subnets create ${GCP_SUBNET_NAME} \
  --network=${GCP_VPC_NAME} \
  --range=${GCP_SUBNET_RANGE} \
  --region=${GCP_REGION} 

Cloud VPNゲートウェイ作成・設定
# VPN Gatewayの作成
gcloud compute target-vpn-gateways create ${GCP_GW_NAME} \
  --network ${GCP_VPC_NAME} \
  --region ${GCP_REGION} \
  --project ${GCP_PROJECT} 

# Firewall Ruleの追加
gcloud compute  forwarding-rules create "${GCP_GW_NAME}-rule-esp" \
  --address ${GCP_PUBLIC_IP} \
  --target-vpn-gateway ${GCP_GW_NAME} \
  --ip-protocol "ESP" \
  --region ${GCP_REGION} \
  --project ${GCP_PROJECT} 
gcloud compute  forwarding-rules create "${GCP_GW_NAME}-rule-udp500" \
  --address ${GCP_PUBLIC_IP} \
  --ip-protocol "UDP" --ports "500" \
  --target-vpn-gateway ${GCP_GW_NAME} \
  --region ${GCP_REGION} \
  --project ${GCP_PROJECT} 
gcloud compute  forwarding-rules create "${GCP_GW_NAME}-rule-udp4500" \
  --address ${GCP_PUBLIC_IP} \
  --ip-protocol "UDP" --ports "4500" \
  --target-vpn-gateway ${GCP_GW_NAME} \
  --region ${GCP_REGION} \
  --project ${GCP_PROJECT} 


②IAPconnectorをデプロイする
PJを作成する
以下のAPIを有効化する
Compute Engine API
Google Kubernetes Engine API
Cloud Deployment Manager API V2
IAMに移動し、「Google APIサービスエージェント」というアカウントにGKE管理者の権限を追加。
用意していたHTTPSロードバランサにひもづけるドメインに以下のCAAレコードを追加する。
CAA 0 issue "letsencrypt.org"
0 issue "pki.goog"
Cloud Load Balnacingのページにて、「詳細設定メニュー」をクリック。
[証明書]タブをクリック。
[+ SSL証明書を作成]をクリック。
以下の項目を入力
名前：任意
作成モード：[Googleマネージドの証明書を作成する]にチェック
ドメイン：HTTPSロードバランサにひもづけるドメインを入力
cloud shellを起動
以下のコマンドを入力
git clone https://github.com/GoogleCloudPlatform/iap-connector
cd iap-connector/

vim iap-connector.yaml のコマンドを入力し、iap-connector.yamlを編集。
resources.properties.zone: GKEクラスタを展開するゾーンを入力します
resources.properties.serviceAccountName: 手順1で設定したGoogle APIサービスエージェントのアカウント名
resources.properties.routing.name: 任意の設定名。Deployment Managerのデプロイ名になります
resources.properties.routing.mapping.source: Cloud Load Balancingに割り当てるドメイン
resources.properties.routing.mapping.destination: 転送先（IPアドレスは不可。Azureのインスタンスにひもづけたドメインを記載）
resources.properties.tls: 手順1で作成したSSL証明書名
末尾3行はオプションのプロパティです。/iap-connector.py.schemaファイルに説明があります。今回は動作確認用途なので、GKEクラスタノードの利用料金をなるべく安くなるようにしてみました。

imports:
- path: iap-connector.py

resources:
- name: iap-connector
  type: iap-connector.py
  properties:
    zone: asia-northeast1-a
    serviceAccountName: xxxxxxxxxxx@cloudservices.gserviceaccount.com
    network: ${GCP_VPC_NAME}の値を入力してください
    subnetwork: ${GCP_SUBNET_NAME}の値を入力してください
    routing:
     - name: bcra-hogehoge-work
       mapping:
        - name: host
          source: bcra-hogehoge.work
          destination: bcra-hogehoge-azure.work/info.php
    tls:
     - bcra-hogehoge-work
    preemptible: true
    initialNodeCount: 1
    replicas: 1

以下のgcloud コマンドでCloud Deployment Managerのデプロイを実行します。
gcloud deployment-manager deployments create test-bcra-com --config=iap-connector.yaml
※test-bcra-comはresources.properties.routing.nameと合わせてください。
※作成まで5分ほどかかります。

コンソール画面にて、セキュリティ＞IAPに移動し、IAPを有効にしてください
「Oauthの同意」が表示されるため、ボタンをクリックし、設定をしてください

③Google Load BalacerのDNSを設定する
コンソール画面のネットワークサービス＞負荷分散をクリックし、さくせいされているLBの名前をクリック
HTTPSのLBが作成されているため、そこに表示されているIPアドレスを用意したドメインのAレコードに登録する。

※HTTPSのLBが作成されていない場合、手動で作成する。


④Azure側でインスタンスを作成する
https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/tutorial-lamp-stack

上記のサイトを元にAzureのVMを作成する

⑤Azure側のネットワークの設定をする
https://yomon.hatenablog.com/entry/2019/10/gcp_azure_vpn

# Azure 関連変数
AZURE_SUBSCRIPTION=YOUR_SUBSCRIPTION_ID
AZURE_RG_NAME=VPN_RG
AZURE_PUBLIC_IP_NAME=AzurePubIP
AZURE_LOCATION=japaneast
AZURE_VNET_NAME=MyVNet
AZURE_VNET_PREFIX=10.10.0.0/16
AZURE_SUBNET_NAME=MySubnet
AZURE_SUBNET_PREFIX=10.10.0.0/24
AZURE_GW_SUBNET_NAME=GatewaySubnet 
AZURE_GW_SUBNET_PREFIX=10.10.255.0/27
AZURE_LOCAL_GW_NAME=GCPGW
AZURE_GW_NAME=VNetGW
AZURE_GW_SKU=VpnGw1
AZURE_CONN_NAME=GCPTunnel
IKE_PRE_SHARED_KEY=abcd1234

リソースグループ作成
az group create --name VPN_RG --location japaneast 

以下を参照し、VMを作成
https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/tutorial-lamp-stack

az vm create \
    --resource-group VPN_RG \
    --name myVM \
    --image UbuntuLTS \
    --admin-username azureuser \
    --generate-ssh-keys

az vm open-port --port 80 --resource-group VPN_RG --name myVM


az network public-ip list --resource-group VPN_RG --query [].ipAddress

ssh azureuser@20.194.172.34
Webサーバを構築

仮想ネットワーク作成
az network vnet create --name MyVNet --resource-group VPN_RG --address-prefix 10.10.0.0/16 --location japaneast --subnet-name MySubnet --subnet-prefix 10.10.0.0/24

Gateway Subnet作成
az network vnet subnet create --address-prefix 10.10.255.0/27 --name GatewaySubnet --resource-group VPN_RG --vnet-name MyVNet 

ローカル ネットワーク ゲートウェイ作成
az network local-gateway create --gateway-ip-address 35.221.65.0 --name GCPGW --resource-group VPN_RG --local-address-prefixes 10.1.0.0/16

パブリックIPの取得
az network public-ip create --name AzurePubIP --resource-group VPN_RG --allocation-method Dynamic
※AzurePublicIPは付与されるまで時間がかかる。1時間位まったほうがいい。

仮想ネットワーク ゲートウェイ作成
az network vnet-gateway create --name VNetGW --public-ip-address AzurePubIP --resource-group VPN_RG --vnet MyVNet  --gateway-type Vpn --vpn-type RouteBased --sku VpnGw1 --no-wait

VPN接続作成
az network vpn-connection create -n GCPTunnel --vnet-gateway1 /subscriptions/c3099676-6a37-4ce0-810d-111281d00cfb/resourceGroups/VPN_RG/providers/Microsoft.Network/virtualNetworkGateways/VNetGW \
 --local-gateway2 /subscriptions/c3099676-6a37-4ce0-810d-111281d00cfb/resourceGroups/VPN_RG/providers/Microsoft.Network/localNetworkGateways/GCPGW \
 --shared-key abcd1234 \
 -g VPN_RG  -l japaneast


⑥GCP側でVPNの設定をする
Cloud VPNトンネル作成
gcloud compute vpn-tunnels create ${GCP_TUNNEL_NAME} \
    --peer-address ${AZURE_PUBLIC_IP} \
    --target-vpn-gateway ${GCP_GW_NAME}  \
    --shared-secret ${IKE_PRE_SHARED_KEY} \
    --local-traffic-selector=0.0.0.0/0 \
    --remote-traffic-selector=0.0.0.0/0 \
    --ike-version 2 \
    --region ${GCP_REGION} \
    --project ${GCP_PROJECT}

ルートテーブル設定
gcloud compute routes create ${GCP_GW_ROUTE} \
  --destination-range ${AZURE_VNET_PREFIX} \
  --next-hop-vpn-tunnel ${GCP_TUNNEL_NAME}  \
  --network ${GCP_VPC_NAME} \
  --next-hop-vpn-tunnel-region ${GCP_REGION} \
  --project ${GCP_PROJECT}

⑦GCP側、Azure側にFWの設定をする
Azure側に130.211.0.0/22　35.191.0.0/16　を許可するTCPのFWルールを受信側に設定
GCP側に下りの許可を設定する