GCP に Cloud Router を構築して自宅ラボと HA VPN で接続して BGP での経路交換

## はじめに
GCP に CloudRouter を構築して、自宅ラボのルータと VPN 越しに BGP での経路交換を実施する
CloudVPN のゲートウェイのタイプは Classic ではなく HA VPN で構築する (ClassicVPN / CloudRouter 未使用での構築例は[こちら](https://qiita.com/suzuyui/items/cfea1dc3d51a2e3be462))
自宅ラボルータには Edgerouter-X (ER-X) を使用する

記載順序は、内容・仕様把握として CloudRouter と CloudVPN についての内容をまとめて、次に実際の構築手順を記載する

## CloudRouter について
CloudRouter の内容・仕様を把握するために概要をまとめたものを記載する

### 概要
下記、2020年9月時点での [GCP ドキュメント](https://cloud.google.com/router/docs/concepts/overview?hl=ja)から抜粋し、振り返りやすいように項目ごとに表にした
利用し設計する上で、ベースとして最初に理解しておかないといけないことになる (ある程度の BGP の知識が必要)
ドキュメントは日本語が一部誤訳がありそうで、正確には英語を参照しないといけないパターンがありそう
更新は都度されるので、正確な情報は最新のドキュメントを参照すべき

| 項目 | 内容 |
|:--|:--|
| 概要 | 完全に分散され管理された Google Cloud サービス<br>ネットワーク トラフィックに合わせてスケーリングし、物理ではなくボトルネックを引き起こさない|
|  必要になる状況 | 必須：Cloud NAT, Cloud Interconnect, HA VPN 使用・作成時 <br>推奨：クラシック VPN のオプション |
| オンプレミス向けの動作 |  Google Cloud ネットワークとオンプレミス ネットワークの間のルートを動的に交換 |
| ルーティングプロトコル | Border Gateway Protocol（BGP） |
| BGP ピアリング | オンプレミスの VPN ゲートウェイまたはルーターとピアリング |
| ASN | Cloud Router を作成するときに、Google 側の ASN を設定可能 |
| 設置場所 | 特定の VPC のリージョン内. 接続点が複数リージョンの場合は、リージョンごとに作成する必要がある |
| ピアリング接続アドレス | IP アドレス範囲 169.254.0.0/16 に属するリンクローカル IP アドレス. このアドレスは伝搬されない |
| 動的ルーティング モード | CloudRouter によって VPC 内に経路を伝搬する範囲選択 (デフォルト：リージョン) <br>グローバル：全リージョンに伝搬し、全リージョンの GCP ルートを対向に BGP で伝搬 <br>リージョン：リージョン内にのみ伝搬し、リージョン内の GCP ルートのみ対向に BGP で伝搬 |

**補足**
冗長が必要な場合は、デフォルトで冗長されているわけではないそうで、2つ以上の設置が必要となる
ドキュメントのどこに記載あるか見当たらず、見つけたら載せておきたい

#### ルートアドバタイズ

| 項目 | 内容 |
|:--|:--|
| ルートアドバタイズの種類 |  デフォルト と カスタム がある|
| デフォルト時の新しいサブネット広報 | 自動的にアドバタイズ |
| デフォルト時の動的ルーティングモード別アドバタイズ |  グローバル：VPC ネットワークのすべてのサブネットをアドバタイズ<br> リージョン：リージョンのサブネットをアドバタイズ|
| ルートアドバタイズ種類別 BGP セッション動作 | デフォルト : ルート アドバタイズをすべての BGP セッションに伝播 <br>カスタム : BGP セッションはカスタム アドバタイズを継承 |
| カスタム が必要な場合 | サブネットの IP 範囲外にある IP アドレスをアドバタイズする場合<br>VPC ネットワークに接続された別の VPC ネットワークからの IP をルート アドバタイズする場合<br>サブネットの一部を選択してアドバタイズしたい場合 |
| カスタム | アドバタイズするルートを明示的に指定<br>デフォルト：アドバタイズの対象としてすべてのサブネットを選択<br>カスタム：特定のサブネットやサブネット内の特定の CIDR ブロックに限定 (新規は手動で設定が必要) |
| 上限値 | CIDR: 200 <br> BGP セッション: 200 |

#### ルートメトリクス

| 項目 | 内容 |
|:--|:--|
| BGP パラメータ・優先度 | AS パス長 > MED 値 (ただし、下記の通り、ASパス長は単一 Cloud Router 内のみ) |
| AS パス長 : 評価されるパターン | 1 つの Cloud Router : AS パス長が最も短いものが Best Path <br> 2 つ以上の Cloud Router : AS パス長は考慮されない ( Cloud Router 内でしか評価されない) |
| ピアルータからの MED 値を使用した基本優先度 (base advertied priority) | MED 値が 0 から 231 -1 (2147483647) まで :  Cloud Router は基本優先度を MED 値に設定 <br> MED 値が  231 (2147483648) 以上 :  Cloud Router は基本優先度を 231 -1 (2147483647) に設定 |
| BGP 制限 | 現在、ある BGP セッションから学習したオンプレミス ルートを、別の BGP セッションへのアドバタイズすることは、サポートしていない (ハブにはならない) |
| リージョンコスト(regional cost) | リージョン間、リージョン跨ぎのオンプレミスへ伝搬されるときに付加される <br> 値の範囲 : 201～9999  <br>2 つのリージョン間の距離やレイテンシなどの要因で異なり、Google によって決められている |
| 基本優先度デフォルト値 | 100 <br>リージョン内のすべてのルートの優先度が等しい場合デフォルト値が採用される |
| ルート指標(ルートメトリクス, Route metrics) | Cloud Router によって、基本優先度 (base advertied priority) とリージョンコスト(regional cost) の 2 つの値が加算され、ルート指標が生成される<br>この値は、MED 値と等価 |
| 推奨値 | リージョン内のルートをリージョン外より優先： 201 以下の値 ※1 <br> VPC ネットワーク内のルートの優先度をグローバルより下げたい場合： 10,200 以上の値を使用 ※2 |

※1 別のリージョンからのルートは regional cost が 201 からなので、 201 より小さい値は設定されないため
※2 regional cost が最大 9999 であり、リージョン内の推奨値が 201 以下のため、合計値で 10,200 = 9999 + 201

#### BGP タイマー
下記が[ドキュメント](https://cloud.google.com/router/docs/concepts/overview?hl=ja#timer-settings)に記載がある、タイマー値・推奨値

| タイマー | オンプレミス側推奨値 |
|:--|:--|
| keep-alive | 20 秒 |
| hold | 60 秒 ※ |
| graceful-restart | 1秒 |
| Stalepath | 300 秒 |
※ネゴシエーションによって低い方に合わせるが、Cloud Router 側は 60 秒で、アップグレード時間に伴い推奨

#### アップグレード
下記[ドキュメント](https://cloud.google.com/network-connectivity/docs/router/concepts/overview?hl=ja#upgrade_cycles)から抜粋

| 項目 | 内容 |
|:--|:--|
| 実行タイミング | 定期的 |
| 処理時間 | 60 秒以内 |
| アップグレード中 | Cloud Router 利用不可 |

## CloudVPN について
CloudVPN の内容・仕様を把握するために概要をまとめたものを記載する

### 概要
HA VPN と Classic VPN の 2種類がサポートされている
[ドキュメントに比較表](https://cloud.google.com/network-connectivity/docs/vpn/concepts/overview?hl=ja#comparison_table)があったので、抜粋して下記記載している

| 機能 | HA VPN | Classic VPN |
|:--|:--|:--|
| SLA | 2 つのインターフェースと 2 つの外部 IP で構成した場合、99.99% の SLA を提供 | 99.9% の SLA を提供 |
| 外部 IP と転送ルールの作成 | プールから作成された外部 IP。転送ルールは必要ありません。	| 外部 IP と転送ルールを作成する必要があります|
|サポートされているルーティング オプション	| 動的ルーティング（BGP）のみ | 静的ルーティング（ポリシーベース、ルートベース）または BGP を使用した動的ルーティング|
| 1 つの Cloud VPN ゲートウェイから同じピア ゲートウェイへの 2 つのトンネル | サポート対象	 | サポート対象外 |
| API リソース | VPN ゲートウェイ リソースとして知られています。 | ターゲット VPN ゲートウェイ リソースとして知られています。 |

#### VPN 仕様
VPN 仕様について[ドキュメント](https://cloud.google.com/network-connectivity/docs/vpn/concepts/overview?hl=ja#specifications)から抜粋等で下記表にまとめる

| 項目 | 内容 |
|:--|:--|
| サポート形式 | サイト間の IPsec VPN 接続のみがサポート|
| VPN 種別 | IPsec のみをサポート |
| プロトコル | ESP、UDP 500、UDP 4500 のトラフィックのみアサインされる Public IP 向けに許可される|
| 限定公開の Google アクセス | 利用可能|
|  ピア側アドレス・プロトコル | ESP（IPsec）プロトコルと IKE（UDP 500 および UDP 4500）トラフィックを通過させる必要がある <br>NAT-T は 1:1 NAT のみがサポートされる|
| パケット断片化 | 事前分割をサポートするようピア VPN ゲートウェイを構成する必要がある <br>パケットは、カプセル化する前に断片化する必要がある|
| リプレイ検出 | 4,096 パケットのウィンドウでリプレイ検出を使用. これをオフにすることはできない|

#### メンテナンス
下記[ドキュメント](https://cloud.google.com/network-connectivity/docs/vpn/concepts/overview?hl=ja#vpn-maintenance-cycles)から抜粋

| 項目 | 内容 |
|:--|:--|
| 実行タイミング | 予告なしにいつでも発生する可能性のある通常の運用上の作業 |
| 処理時間 | Cloud VPN SLA に影響を与えないように十分短く設計 |
| メンテナンス中 | Cloud VPN トンネルはオフラインにある<br>メンテナンスが完了すると、Cloud VPN トンネルが自動的に再確立 |

## 構築
パラメータと構成概要図を最初に示し、構築ステップごとに gcloud コマンドと自宅ラボルータの config 例を記載する

### 構築環境について
実施環境(自宅ラボ)は Router 1台、 Public IP が 1つしかないので下記のような構成とした。

### 概要図・パラメータ

構築する上で、構築する各リソースなどを構成概要図およびパラメータにまとめたものを記載する。
パラメータについては今回記載する例となる。
※ 自宅ラボ側の VPN ルータは [Edgerouter-X](https://www.ui.com/edgemax/edgerouter-x/) (ER-X /ホスト名 ERX01) を使用している 

![GCP_CloudRouter_HAVPN_2tunnels.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/357deccd-529a-b849-6ae5-fabe492f4e17.png)


| 項目 | 本例での設定パラメータ名称 |
|:--|:--|
| CloudRouter Name  | cloudrouter01 |
| Region | us-west1 |
| 所属 VPC 名 | vpc01 |
| GCP 側 ASN | 65101 |
| 自宅ラボ側 ASN | 65001 |
| HA VPN Gateway 名 | home-vpn-gateway |
| 外部 VPN ゲートウェイ名 <br>(GCP 対向 PublicIP 指定時に使用) | home-erx01-eth0 |
| VPN Tunnel 1 名| home-vpn-tunnel01 |
| VPN Tunnel 2 名| home-vpn-tunnel02 |
| CloudRouter VPN BGP Interface 1 名 | home-vpn-if01 |
| CloudRouter VPN BGP Interface 2 名 | home-vpn-if02 |
| CloudRouter VPN BGP Interface 1 IP | 169.254.0.1 |
| CloudRouter VPN BGP Interface 2 IP | 169.254.1.1 |
| 自宅ラボ側 VTI (Virtual Tunnel Interface) 1 IP | 169.254.0.2 |
| 自宅ラボ側 VTI (Virtual Tunnel Interface) 2 IP | 169.254.1.2 |
| CloudRouter BGP Peer 1 名 | home-bgp-peer01 |
| CloudRouter BGP Peer 2 名 | home-bgp-peer02 |
| 自宅ラボ側 PublicIP | x.x.x.x |
| VPN Gateway 側 PublicIP 1 | y.y.y.y |
| VPN Gateway 側 PublicIP 2 | z.z.z.z |

BGP 周りの論議概要図は下記の通り
MED値を 1系 100, 2系 200 にして片寄の設計にしている

![GCP_CloudRouter_HAVPN_BGPabsut.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/fe7d22bb-d1a7-329d-c66c-0003956c3ad6.png)

### 作業ステップ
下記ステップで記載する

1. [GCP] Cloud Router の構築
2. [GCP] HA VPN Gateway の作成
3. [GCP] 外部 VPN ゲートウェイ の登録
4. [GCP] VPN Tunnel の作成
5. [GCP] Cloud Router インターフェースと BGP ピアの作成
6. [自宅ラボ] Home Lab 側の VPN/BGP/FW設定
7. [GCP/自宅ラボ] ルーティング確認
8. [GCP] Cloud Router のアドバタイズモードの変更(&オンプレミスホスト用の限定公開セグメントの広報)
9. [GCP/自宅ラボ] ルーティング確認(限定公開セグメント)

1~5.は GCP 側で CloudRouter/CloudVPN の設定・構築を実施する. (参考：[GCP のマニュアル](https://cloud.google.com/network-connectivity/docs/vpn/how-to/creating-ha-vpn?hl=ja#creating-ha-gw-peer-tunnel))
6.は自宅ラボ側のルータの設定を実施する
7.で状態の確認を実施する
8~9.は追加作業として、CloudRouter のアドバタイズモードの変更と限定公開セグメントの広報について試しに実施し、CUSTUMモードでの経路広報を確認している

### 1. [GCP] Cloud Router の構築
VPC 内にルータとして Cloud Router を構築する
※ここではルートアドバタイズモードは特に指定してないため`デフォルト`になる。後述ステップでカスタムにすることも試す。

実行コマンド例は下記通り

```
gcloud compute routers create cloudrouter01 --network vpc01 --asn 65101 --region us-west1
```

実行後の出力例が下記となる
![スクリーンショット 2020-09-20 13.57.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/00daf357-1f2a-23fa-3da4-bd6a2e367470.png)


### 2. [GCP] HA VPN Gateway の作成
自宅ラボと VPN を張る HA VPN Gateway (CloudVPN) を作成する

実行コマンド例は下記の通り

```
gcloud compute vpn-gateways create home-vpn-gateway \
    --network vpc01 \
    --region us-west1
```

実行後の出力例が下記となる
**INTERFACE0** と **INTERFACE1** の IP が自宅ラボと VPN を張る PublicIP となるので**メモしておく** (以降の記載は y.y.y.y, z.z.z.z のアドレス箇所) 
![スクリーンショット 2020-09-20 14.32.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/883e8cb4-2ee5-180c-674b-bd72517394f5.png)
※`gcloud compute vpn-gateways list `でもアサイン IP は確認可能

### 3. [GCP] 外部 VPN ゲートウェイ の登録
自宅ラボ側の VPN IP (外部 VPN ゲートウェイ) を登録する

実行コマンド例は下記の通り

```sh:[x.x.x.x]は対向PublicIP
gcloud compute external-vpn-gateways create home-erx01-eth0 \
    --interfaces 0=x.x.x.x
```

※参考に削除コマンドも載せておく

```sh:切り戻しConfig
gcloud compute external-vpn-gateways delete home-erx01-eth0
```

### 4. [GCP] VPN Tunnel の作成

まず、事前共有keyを GCP のドキュメントの[強力な事前共有キーの生成](https://cloud.google.com/network-connectivity/docs/vpn/how-to/generating-pre-shared-key?hl=ja)を参考に作成する

```sh:事前共有keyのランダム生成
openssl rand -base64 24
```

VPN Tunnel を作成する
実行コマンド例は下記の通り
上記で作成した事前共有 key を `--shared-secre` の値として使用する

VPN Tunnel 1つ目の、実行コマンド例は下記の通り

```
gcloud compute vpn-tunnels create home-vpn-tunnel01 \
    --peer-external-gateway home-erx01-eth0 \
    --peer-external-gateway-interface 0  \
    --region us-west1 \
    --ike-version 2 \
    --shared-secret [4. [GCP] VPN Tunnel の作成. openssl で作成した事前共有key] \
    --router cloudrouter01 \
    --vpn-gateway home-vpn-gateway \
    --interface 0
```

VPN Tunnel 2つ目の、実行コマンド例は下記の通り

```
gcloud compute vpn-tunnels create home-vpn-tunnel02 \
    --peer-external-gateway home-erx01-eth0 \
    --peer-external-gateway-interface 0  \
    --region us-west1 \
    --ike-version 2 \
    --shared-secret [4. [GCP] VPN Tunnel の作成. openssl で作成した事前共有key] \
    --router cloudrouter01 \
    --vpn-gateway home-vpn-gateway \
    --interface 1
```

※参考に削除コマンドも載せておく

```sh:切り戻しconfig
gcloud compute vpn-tunnels delete home-vpn-tunnel02 --region=us-west1
gcloud compute vpn-tunnels delete home-vpn-tunnel01 --region=us-west1
```

### 5. [GCP] Cloud Router インターフェースと BGP ピアの作成
Cloud Router に VPN 向けの Interface の追加と、BGP 設定を実施する

tunnel 1つ目の、実行コマンド例は下記の通り

```
gcloud compute routers add-interface cloudrouter01 \
    --interface-name home-vpn-if01 \
    --mask-length 30 \
    --vpn-tunnel home-vpn-tunnel01 \
    --ip-address 169.254.0.1 \
    --region us-west1
gcloud compute routers add-bgp-peer cloudrouter01 \
    --peer-name home-bgp-peer01 \
    --peer-asn 65001 \
    --interface home-vpn-if01 \
    --peer-ip-address 169.254.0.2 \
    --region us-west1
```

tunnel 2つ目の、実行コマンド例は下記の通り

```
gcloud compute routers add-interface cloudrouter01 \
    --interface-name home-vpn-if02 \
    --mask-length 30 \
    --vpn-tunnel home-vpn-tunnel02 \
    --ip-address 169.254.1.1 \
    --region us-west1
gcloud compute routers add-bgp-peer cloudrouter01 \
    --peer-name home-bgp-peer02 \
    --peer-asn 65001 \
    --interface home-vpn-if02 \
    --peer-ip-address 169.254.1.2 \
    --region us-west1
```

このままだと、両方同じ MED (デフォルト100) となるため、
片寄設計にする場合は、下記を実施し、MEDを変更しておく。(ここでは 200 に変更)

```
gcloud compute routers update-bgp-peer cloudrouter01 \
    --region us-west1 \
    --peer-name home-bgp-peer02 \
    --advertised-route-priority 200
```

以上で、**GCP 側の VPN/BGP 設定が完了**

※参考に削除コマンドも載せておく

```sh:切り戻しconfig
gcloud compute routers remove-bgp-peer cloudrouter01 --region=us-west1 --peer-name home-bgp-peer01
gcloud compute routers remove-bgp-peer cloudrouter01 --region=us-west1 --peer-name home-bgp-peer02
gcloud compute routers remove-interface cloudrouter01 \
    --region=us-west1 \
    --interface-name home-vpn-if01
gcloud compute routers remove-interface cloudrouter01 \
    --region=us-west1 \
    --interface-name home-vpn-if02
```

### 6. [自宅ラボ] Home Lab 側の VPN/BGP/FW設定

GCP向けの VPN, BGP の設定を実施する
合わせて ZoneBaseFirewall も実施しているため、合わせて実施する (zonebasefirewall の詳細は省略する)

コンフィグ設定モードに移行する

```
$ confire
# 
```

VPN(ipsec)、VTI 設定を実施する

 - ipsec 設定概要
    - auto-firewall-nat-exclude enable
        - VPN越しはNATから除外するようにする
    - vti
        - VPN での仮想Interface を定義する
    - mss-clamp
        - MSS Clamp 設定が可能
        - 値(ここでは 1292) は、環境による
    - pre-shared-secret
        - 4. [GCP] VPN Tunnel の作成. openssl で作成した事前共有key を指定する
    - その他
        - Classic VPN での [VyOS のパラメータ例](https://cloud.google.com/files/CloudVPNGuide-UsingCloudVPNwithVyOS.pdf?hl=ja)を参考にしている
        - また、AWS だが [EdgeRouter側のドキュメント](https://help.ui.com/hc/en-us/articles/115016128008-EdgeRouter-Route-Based-Site-to-Site-VPN-to-AWS-VPC-BGP-over-IKEv1-IPsec-)も参考にできる

```EdgeRouer_VPN設定例[x.x.x.xは自宅ラボのPublicIP.y.y.y.y,z.z.z.zはGCP側のPublicIP].config
set vpn ipsec auto-firewall-nat-exclude enable 
set vpn ipsec esp-group gcp-esp compression disable
set vpn ipsec esp-group gcp-esp lifetime 10800
set vpn ipsec esp-group gcp-esp mode tunnel
set vpn ipsec esp-group gcp-esp pfs enable
set vpn ipsec esp-group gcp-esp proposal 1 encryption aes256
set vpn ipsec esp-group gcp-esp proposal 1 hash sha1
set vpn ipsec ike-group gcp-ike dead-peer-detection action restart
set vpn ipsec ike-group gcp-ike dead-peer-detection interval 30
set vpn ipsec ike-group gcp-ike dead-peer-detection timeout 120
set vpn ipsec ike-group gcp-ike ikev2-reauth no
set vpn ipsec ike-group gcp-ike key-exchange ikev2
set vpn ipsec ike-group gcp-ike lifetime 36000
set vpn ipsec ike-group gcp-ike proposal 1 dh-group 14
set vpn ipsec ike-group gcp-ike proposal 1 encryption aes256
set vpn ipsec ike-group gcp-ike proposal 1 hash sha1
set interfaces vti vti0 address 169.254.0.2/30
set interfaces vti vti0 mtu '1332'
set firewall options mss-clamp interface-type vti
set firewall options mss-clamp mss 1292
set vpn ipsec site-to-site peer y.y.y.y authentication id x.x.x.x
set vpn ipsec site-to-site peer y.y.y.y authentication mode pre-shared-secret
set vpn ipsec site-to-site peer y.y.y.y authentication pre-shared-secret [4. [GCP] VPN Tunnel の作成. openssl で作成した事前共有key]
set vpn ipsec site-to-site peer y.y.y.y connection-type initiate
set vpn ipsec site-to-site peer y.y.y.y local-address x.x.x.x (NAT配下の場合はprivateアドレス)
set vpn ipsec site-to-site peer y.y.y.y ike-group gcp-ike
set vpn ipsec site-to-site peer y.y.y.y ikev2-reauth inherit
set vpn ipsec site-to-site peer y.y.y.y vti bind 'vti0'
set vpn ipsec site-to-site peer y.y.y.y vti esp-group 'gcp-esp'
set interfaces vti vti1 address 169.254.1.2/30
set interfaces vti vti1 mtu '1332'
set vpn ipsec site-to-site peer z.z.z.z authentication id x.x.x.x
set vpn ipsec site-to-site peer z.z.z.z authentication mode pre-shared-secret
set vpn ipsec site-to-site peer z.z.z.z authentication pre-shared-secret [4. [GCP] VPN Tunnel の作成. openssl で作成した事前共有key]
set vpn ipsec site-to-site peer z.z.z.z connection-type initiate
set vpn ipsec site-to-site peer z.z.z.z local-address x.x.x.x (NAT配下の場合はprivateアドレス)
set vpn ipsec site-to-site peer z.z.z.z ike-group gcp-ike
set vpn ipsec site-to-site peer z.z.z.z ikev2-reauth inherit
set vpn ipsec site-to-site peer z.z.z.z vti bind 'vti1'
set vpn ipsec site-to-site peer z.z.z.z vti esp-group 'gcp-esp'
```

次に、BGP の設定を実施する
GCP へ広報したい自宅ラボのアドレスは本例では `192.168.129.0/24` で記載している
広報経路と MED 値の制御のため、`prefix-list` + `route-map` を使用している
BGP Timer の値は、前述の GCP 側のパラメータに合わせている

```EdgeRouer_BGP設定例.config
set policy prefix-list gcp-export rule 100 action permit 
set policy prefix-list gcp-export rule 100 prefix 192.168.129.0/24
set policy prefix-list gcp-export rule 100 le 32
set policy route-map TO-GCP-OUT-1 rule 1 action permit
set policy route-map TO-GCP-OUT-1 rule 1 match ip address prefix-list gcp-export
set policy route-map TO-GCP-OUT-1 rule 1 set metric 100
set policy route-map TO-GCP-OUT-2 rule 1 action permit
set policy route-map TO-GCP-OUT-2 rule 1 match ip address prefix-list gcp-export
set policy route-map TO-GCP-OUT-2 rule 1 set metric 200
set protocols bgp 65001 network 192.168.129.0/24
set protocols bgp 65001 parameters graceful-restart stalepath-time 300
set protocols bgp 65001 parameters router-id 192.168.129.254
set protocols bgp 65001 neighbor 169.254.0.1 capability graceful-restart
set protocols bgp 65001 neighbor 169.254.0.1 remote-as 65101
set protocols bgp 65001 neighbor 169.254.0.1 route-map export TO-GCP-OUT-1
set protocols bgp 65001 neighbor 169.254.0.1 timers holdtime 60
set protocols bgp 65001 neighbor 169.254.0.1 timers keepalive 20
set protocols bgp 65001 neighbor 169.254.1.1 capability graceful-restart
set protocols bgp 65001 neighbor 169.254.1.1 remote-as 65101
set protocols bgp 65001 neighbor 169.254.1.1 route-map export TO-GCP-OUT-2
set protocols bgp 65001 neighbor 169.254.1.1 timers holdtime 60
set protocols bgp 65001 neighbor 169.254.1.1 timers keepalive 20

```

次に、Firewall の追加設定を実施する
Zone-policy で自宅ラボルータが設定しているので Zone, Policy の追加をする (Firewall 設定方法の詳細は記載しない)
GCP zone は VPN の vti0, vti1 インターフェース向けとしている
既存セグメントは Trust zone 側にすでに設定されている
GCP -> Trust へはセグメント限定で SSH 許可. Trust -> GCP は全て許可のポリシーとしている

```EdgeRouer_ZoneFirewall追加設定例(既存セグメントがTrustでの例).config
set zone-policy zone GCP default-action drop
set zone-policy zone GCP from Trust firewall name Trust-GCP
set zone-policy zone GCP interface vti0
set zone-policy zone GCP interface vti1
set zone-policy zone Trust from GCP firewall name GCP-Trust
set firewall name GCP-Trust default-action drop
set firewall name GCP-Trust rule 1 action accept
set firewall name GCP-Trust rule 1 state established enable
set firewall name GCP-Trust rule 1 state related enable
set firewall name GCP-Trust rule 100 action accept
set firewall name GCP-Trust rule 100 destination address 192.168.129.0/24
set firewall name GCP-Trust rule 100 destination port 22
set firewall name GCP-Trust rule 100 log enable
set firewall name GCP-Trust rule 100 protocol tcp
set firewall name GCP-Trust rule 100 source address 10.10.0.0/20
set firewall name GCP-Trust rule 100 state new enable
set firewall name GCP-Trust rule 9999 action drop
set firewall name GCP-Trust rule 9999 log enable
set firewall name Trust-GCP default-action drop
set firewall name Trust-GCP rule 1 action accept
set firewall name Trust-GCP rule 1 log enable
set firewall name Trust-GCP rule 1 state established enable
set firewall name Trust-GCP rule 1 state new enable
set firewall name Trust-GCP rule 1 state related enable
set firewall name Trust-GCP rule 9999 action drop
set firewall name Trust-GCP rule 9999 log enable
```

設定の commit (反映)および、save (保存) を実施する 

```
# commit; save
# exit
$
```

以上で、**自宅ラボ側の VPN/BGP/FW 設定が完了**

### 7. [GCP/自宅ラボ] ルーティング確認

1~6. にて VPN 越しに BGP ピアが張れたので、状態確認を実施する

#### GCP 側での BGP の確認

下記コマンドの出力結果から BGP 状態とルーティングが確認できる

 - bestRoutes, bestRoutesForRouter
    - **受信経路**でのベストパスが確認できる
    - priority: 100,200 で MED の値が反映されていることが確認できる
 - bgpPeerStatus
    - advertisedRoutes
        - GCP から広報しているルートが出力される
        - vpc01 では subnet で `10.10.0.0/20` を設定しているので、今回 default のため自動で広報されている
        - priority: 100(default),200 の値が反映されていることが確認できる
    - state: **Established** となっていれば BGP ピアが確立されていることが確認できる
 
```
$ gcloud compute routers get-status cloudrouter01 --region=us-west1
kind: compute#routerStatusResponse
result:
  bestRoutes:
  - creationTimestamp: '2020-09-27T01:37:10.787-07:00'
    destRange: 192.168.129.0/24
    kind: compute#route
    nextHopIp: 169.254.0.2
    priority: 100
  - creationTimestamp: '2020-09-27T00:35:24.002-07:00'
    destRange: 192.168.129.0/24
    kind: compute#route
    nextHopIp: 169.254.1.2
    priority: 200
  bestRoutesForRouter:
  - creationTimestamp: '2020-09-27T01:37:10.786-07:00'
    destRange: 192.168.129.0/24
    kind: compute#route
    nextHopIp: 169.254.0.2
    priority: 100
  - creationTimestamp: '2020-09-27T00:35:24.002-07:00'
    destRange: 192.168.129.0/24
    kind: compute#route
    nextHopIp: 169.254.1.2
    priority: 200
  bgpPeerStatus:
  - advertisedRoutes:
    - destRange: 10.10.0.0/20
      kind: compute#route
      nextHopIp: 169.254.0.1
      priority: 100
    ipAddress: 169.254.0.1
    linkedVpnTunnel: https://www.googleapis.com/compute/v1/projects/[project name]/regions/us-west1/vpnTunnels/home-vpn-tunnel01
    name: home-bgp-peer01
    numLearnedRoutes: 1
    peerIpAddress: 169.254.0.2
    state: Established
    status: UP
    uptime: 1 minutes, 1 seconds
    uptimeSeconds: '61'
  - advertisedRoutes:
    - destRange: 10.10.0.0/20
      kind: compute#route
      nextHopIp: 169.254.1.1
      priority: 200
    ipAddress: 169.254.1.1
    linkedVpnTunnel: https://www.googleapis.com/compute/v1/projects/[project name]/regions/us-west1/vpnTunnels/home-vpn-tunnel02
    name: home-bgp-peer02
    numLearnedRoutes: 1
    peerIpAddress: 169.254.1.2
    state: Established
    status: UP
    uptime: 1 hours, 3 minutes, 15 seconds
    uptimeSeconds: '3795'
  network: https://www.googleapis.com/compute/v1/projects/[project name]/global/networks/vpc01
```

#### 自宅ラボ(ERX) 側での BGP の確認

`show ip bgp summary` :  BGP の状態が確認可能
`show ip bgp neighbors 169.254.0.1`: 1つめの BGP state を確認可能。**Established**なら確立
`show ip bgp neighbors 169.254.1.1`: 2つめの BGP state を確認可能。**Established**なら確立
`show ip route bgp`: BGP で採用したルーティングテーブルが見れる(本例では GCP の vpc01 にあるサブネットの 10.10.0.0/20 が見れてればOK)
`show ip bgp`: BGP Table を確認し、MED 100, 200 で受けてることが確認できる (100が優先経路/ベストパス)

```sh:bgp確認例
$ show ip bgp summary 
~中略~
Neighbor                 V   AS   MsgRcv    MsgSen TblVer   InQ   OutQ    Up/Down   State/PfxRcd
169.254.0.1              4 65101 4452       4450      14      0      0  00:03:38               1
169.254.1.1              4 65101  735        733      14      0      0  01:05:53               1

$ show ip bgp neighbors 169.254.0.1 | match state
  BGP state = Established, up for 00:04:03
     Forwarding states are being preserved

$ show ip bgp neighbors 169.254.1.1 | match state
  BGP state = Established, up for 01:06:23
     Forwarding states are being preserved

$ show ip route bgp 
IP Route Table for VRF "default"
B    *> 10.10.0.0/20 [20/100] via 169.254.0.1, vti0, 00:00:14

Gateway of last resort is not set
$ show ip bgp 
BGP table version is 14, local router ID is 192.168.129.254
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, l - labeled
              S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete

    Network          Next Hop            Metric    LocPrf       Weight Path
*>  10.10.0.0/20     169.254.0.1          100                   0       65101 ?
*                    169.254.1.1          200                   0       65101 ?
*>  192.168.129.0    0.0.0.0                       100          32768    i

Total number of prefixes 2
```

### 8. [GCP] Cloud Router のアドバタイズモードの変更(&オンプレミスホスト用の限定公開セグメントの広報)
Cloud Router の**ルートアドバタイズのモード**を**カスタム**に変更してみる
また変更時に、オンプレミスホスト用の限定公開セグメント (private.googleapis.com) のアドレスを広報する([参照ドキュメント](https://cloud.google.com/vpc/docs/configure-private-google-access-hybrid?hl=ja))

下記、`CUTOM モードへの変更`と `private.googleapis.com セグメントの広報`コマンド例

```
gcloud compute routers update cloudrouter01 \
    --region=us-west1 \
    --advertisement-mode=CUSTOM \
    --set-advertisement-groups=ALL_SUBNETS \
    --set-advertisement-ranges=199.36.153.8/30
```

```sh:切り戻しコマンド
gcloud compute routers update cloudrouter01 \
    --region=us-west1 \
    --advertisement-mode=DEFAULT
```

### 9. [GCP/自宅ラボ] ルーティング確認(CUSTOM)

カスタムモードで追加広報した`199.36.153.8/30`が経路広報・受信できていることを確認する

#### GCP 側での広報ルーティング確認

下記状態が確認でき、経路広報できていることを確認できる
`bgpPeerStatus: advertisedRoutes: destRange: 199.36.153.8/30`

下記、確認コマンド例と出力例

```
$ gcloud compute routers get-status cloudrouter01 --region=us-west1
~中略~
  bgpPeerStatus:
  - advertisedRoutes:
    - destRange: 199.36.153.8/30
      kind: compute#route
      nextHopIp: 169.254.0.1
      priority: 100
~中略~
  - advertisedRoutes:
    - destRange: 199.36.153.8/30
      kind: compute#route
      nextHopIp: 169.254.1.1
      priority: 200
~中略~
```

#### オンプレ側での受信経路確認

受信経路を`show ip route bgp` で確認できる

```
$ show ip route bgp 
IP Route Table for VRF "default"
B    *> 10.10.0.0/20 [20/100] via 169.254.0.1, vti0, 00:00:05
B    *> 199.36.153.8/30 [20/100] via 169.254.0.1, vti0, 00:00:05
```


## おわりに
CloudRouter を構築して BGP で自宅ラボと経路交換ができるようになった
今後この経路を使用して、自宅ラボからの GCP 利用などを試していきたい
[VPN 利用料は Classic 時](https://qiita.com/suzuyui/items/cfea1dc3d51a2e3be462#vpn-%E6%96%99%E9%87%91)とほぼ同じで 1 tunnel 1日当たり127円だった (為替影響で微増減あり)

### [追加] 2系のみ削除・追加コマンド
Tunnel が 2つになったため、料金が 2倍になってしまった
やはり金額的に痛いので、2系は普段冗長不要であれば削除として、2系の削除・復旧コマンドを用意する(記載済みの中から 2系箇所のコマンド抜粋したのみ)

```sh:2系削除コマンド
gcloud compute routers remove-bgp-peer cloudrouter01 --region=us-west1 --peer-name home-bgp-peer02
gcloud compute routers remove-interface cloudrouter01 --region=us-west1 --interface-name home-vpn-if02
gcloud compute vpn-tunnels delete home-vpn-tunnel02 --region=us-west1
```

```sh:2系復旧コマンド
gcloud compute vpn-tunnels create home-vpn-tunnel02 \
    --peer-external-gateway home-erx01-eth0 \
    --peer-external-gateway-interface 0  \
    --region us-west1 \
    --ike-version 2 \
    --shared-secret [4. [GCP] VPN Tunnel の作成. openssl で作成した事前共有key] \
    --router cloudrouter01 \
    --vpn-gateway home-vpn-gateway \
    --interface 1
gcloud compute routers add-interface cloudrouter01 \
    --interface-name home-vpn-if02 \
    --mask-length 30 \
    --vpn-tunnel home-vpn-tunnel02 \
    --ip-address 169.254.1.1 \
    --region us-west1
gcloud compute routers add-bgp-peer cloudrouter01 \
    --peer-name home-bgp-peer02 \
    --peer-asn 65001 \
    --interface home-vpn-if02 \
    --peer-ip-address 169.254.1.2 \
    --region us-west1
```

## 参考
Cloud Router の概要
https://cloud.google.com/router/docs/concepts/overview?hl=ja
Cloud VPN の概要
https://cloud.google.com/network-connectivity/docs/vpn/concepts/overview
HA VPN ゲートウェイからピア VPN ゲートウェイの作成
https://cloud.google.com/network-connectivity/docs/vpn/how-to/creating-ha-vpn?hl=ja#manual
強力な事前共有キーの生成
https://cloud.google.com/network-connectivity/docs/vpn/how-to/generating-pre-shared-key?hl=ja
アドバタイズされたルートの基本優先度の更新
https://cloud.google.com/network-connectivity/docs/router/how-to/updating-priority?hl=ja
Google Cloud VPN Interop Guide Using Cloud VPN With VyOS
https://cloud.google.com/files/CloudVPNGuide-UsingCloudVPNwithVyOS.pdf?hl=ja
EdgeRouter - Route-Based Site-to-Site VPN to AWS VPC (BGP over IKEv1/IPsec)
https://help.ui.com/hc/en-us/articles/115016128008-EdgeRouter-Route-Based-Site-to-Site-VPN-to-AWS-VPC-BGP-over-IKEv1-IPsec-