VyOS から Cloudflare Magic WAN に IPsec トンネルを接続する

# Cloudflare Magic WAN とは

Cloudflare を通じて [RFC 1918](https://www.nic.ad.jp/ja/translation/rfc/1918.html) にあるようなプライベートネットワーク通信を制御できるサービスです。

例えば、拠点間のルーティング、バックボーンを経由した高速化などの機能がありますが、

プライベート通信制御に Magic Firewall を活用したり、インターネットへの出口に Cloudflare Zero Trust をセキュアに経由させることができたりと、Magic WAN 単体で使うより他サービスと組み合わせて使うこともできます。

感覚としては、Cloudflare の全ての POP が地球規模の1つのルータとして機能するイメージです。

- [Cloudflare Magic WAN · Cloudflare Magic WAN docs](https://developers.cloudflare.com/magic-wan/)

![magicwan](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/magicwan.png)

# Magic WAN への接続方法（オンランプ）

ユーザのプライベートネットワークから、以下の方法で接続できます。

今回は、インターネットを経由した IPsec トンネルを通じて Cloudflare Magic WAN を構成します。

- [Types of interconnect · Cloudflare Network Interconnect docs](https://developers.cloudflare.com/network-interconnect/about/interconnect-types/)

![magiconramp](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/magiconramp.png)

# Magic WAN 構成

以下のような構成で実施します。VyOS はこちらの記事で準備したものを使います。

- [Google Cloud で VyOS を使う - Qiita](https://qiita.com/khayama/items/0773f9f9efd2ba1ecddb)

![mwan-vyos-qiita-gcp](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/mwan-vyos-qiita-gcp.png)

# IPsec パラメータシート

こちらのパラメータを使って設定します。

| **Tunnel Configuration** | **Tunnel name** | **Customer edge IP**     | **Cloudflare Anycast IP**      | **Site Private subnet**                           | **Customer Tunnel IP**         | **Cloudflare Tunnel IP**      |
| ------------------------ | --------------- | ------------------------ | ------------------------------ | ------------------------------------------------- | ------------------------------ | ----------------------------- |
| Tokyo                    | 任意            | External IP<br />y.y.y.y | x.x.x.x<br />(Cloudflare 提供) | サイトのプライベートサブネット<br />10.200.0.0/20 | 10.10.10.100/31<br /> （任意） | 10.10.10.101/31<br />（任意） |
| Osaka                    | 任意            | External IP<br />z.z.z.z | x.x.x.x<br />(Cloudflare 提供) | サイトのプライベートサブネット<br />10.202.0.0/20 | 10.10.10.102/31<br />（任意）  | 10.10.10.103/31<br />（任意） |

# ダッシュボードから Magic WAN IPsec トンネルを作成

まず Cloudflare のダッシュボードから上記パラメータを使って、IPsec トンネルを作成します。

https://dash.cloudflare.com/?to=/:account/magic-wan/configuration/tunnels/ipsec-tunnels/form 

- [Configure tunnel endpoints · Cloudflare Magic WAN docs](https://developers.cloudflare.com/magic-wan/get-started/configure-tunnels/#add-tunnels)

![image-20230314003937140](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20230314003937140.png)

その後、作成されたトンネル情報から「キー ID」をメモして、次のステップで使います。

![image-20230314004218006](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20230314004218006.png)

# VyOS で Cloudflare Magic WAN 用 IPsec トンネルを設定

`tokyo-vyos` を例に設定します。

先ほど取得した「キー ID」で `YOUR_KEY_ID` を置換して実行してください。

- [VyOS · Cloudflare Magic WAN docs](https://developers.cloudflare.com/magic-wan/tutorials/vyos/)

- MTU は Google Cloud デフォルトの 1460 に設定
    - [MTU に関する考慮事項  |  Cloud VPN  |  Google Cloud](https://cloud.google.com/network-connectivity/docs/vpn/concepts/mtu-considerations?hl=ja)
    - [What is MTU (maximum transmission unit)? | Cloudflare](https://www.cloudflare.com/learning/network-layer/what-is-mtu/)
- MSS は、下記リンクを参考に 1360 に設定
    - [Cloud VPN interoperability guide for Juniper SRX  |  Google Cloud Platform Community](https://cloud.google.com/community/tutorials/using-cloud-vpn-with-juniper-srx)
    - [Route-Based Site-to-Site VPN to Azure (BGP over IKEv2/IPsec) — VyOS 1.3.x (equuleus) documentation](https://docs.vyos.io/en/equuleus/configexamples/azure-vpn-bgp.html)
    - [What is MSS (maximum segment size)? | Cloudflare](https://www.cloudflare.com/learning/network-layer/what-is-mss/)

```shell
export CUST_TUN_IP='10.10.10.100/31'
export CF_ANYCAST_IP='x.x.x.x'
export AUTH_KEY_ID='YOUR_KEY_ID'
export LOCAL_ADDR='10.200.0.3'
configure
set interfaces ethernet eth0 mtu 1460
set interfaces vti vti0 address $CUST_TUN_IP
set interfaces vti vti0 mtu 1460
set firewall options interface vti0 adjust-mss 1360
set vpn ipsec esp-group cloudflare compression 'disable'
set vpn ipsec esp-group cloudflare lifetime '14400'
set vpn ipsec esp-group cloudflare mode 'tunnel'
set vpn ipsec esp-group cloudflare pfs 'enable'
set vpn ipsec esp-group cloudflare proposal 1 encryption 'aes256gcm128'
set vpn ipsec esp-group cloudflare proposal 1 hash 'sha512'
set vpn ipsec ike-group cloudflare close-action 'none'
set vpn ipsec ike-group cloudflare dead-peer-detection action 'restart'
set vpn ipsec ike-group cloudflare dead-peer-detection interval '30'
set vpn ipsec ike-group cloudflare dead-peer-detection timeout '120'
set vpn ipsec ike-group cloudflare ikev2-reauth 'no'
set vpn ipsec ike-group cloudflare key-exchange 'ikev2'
set vpn ipsec ike-group cloudflare lifetime '14400'
set vpn ipsec ike-group cloudflare mobike 'disable'
set vpn ipsec ike-group cloudflare proposal 1 dh-group '14'
set vpn ipsec ike-group cloudflare proposal 1 encryption 'aes256gcm128'
set vpn ipsec ike-group cloudflare proposal 1 hash 'sha512'
set vpn ipsec ipsec-interfaces interface eth0
set vpn ipsec logging log-level '2'
set vpn ipsec options disable-route-autoinstall
set vpn ipsec site-to-site peer $CF_ANYCAST_IP authentication id $AUTH_KEY_ID
set vpn ipsec site-to-site peer $CF_ANYCAST_IP authentication pre-shared-secret TESTSECRET
set vpn ipsec site-to-site peer $CF_ANYCAST_IP authentication remote-id $CF_ANYCAST_IP
set vpn ipsec site-to-site peer $CF_ANYCAST_IP connection-type 'initiate'
set vpn ipsec site-to-site peer $CF_ANYCAST_IP ike-group cloudflare
set vpn ipsec site-to-site peer $CF_ANYCAST_IP ikev2-reauth 'no'
set vpn ipsec site-to-site peer $CF_ANYCAST_IP local-address $LOCAL_ADDR
set vpn ipsec site-to-site peer $CF_ANYCAST_IP vti bind vti0
set vpn ipsec site-to-site peer $CF_ANYCAST_IP vti esp-group cloudflare
commit
save
exit

```

# VyOS で anti-replay protection を無効化

Cloudflare Magic WAN と IPsec トンネルを接続するには「[Anti-replay protection](https://developers.cloudflare.com/magic-wan/reference/anti-replay-protection/)」の無効化が必須です。

2023年3月14日時点で VyOS の CLI で anti-replay protection を無効化する方法は確認できていないため、内部実装となっている strongSwan の `replay_window=0` を設定します。

- [ipsec.conf: conn Reference - ipsec.conf: conn Reference - strongSwan](https://wiki.strongswan.org/projects/strongswan/wiki/connsection)

> replay_window = -1 | <number>
>
> The IPsec replay window size for this connection. With the default of -1 the value configured with charon.replay_window in
> strongswan.conf is used. Larger values than 32 are supported using the Netlink backend only, **a value of 0 disables IPsec**
> **replay protection.** Available since 5.2.0.

具体的には以下のコマンドで設定します。

```shell
sudo cp /etc/ipsec.conf /config/scripts/
sudo vi /config/scripts/ipsec.conf
```

```conf:/config/scripts/ipsec.conf
conn peer-x.x.x.x-tunnel-vti
	left=10.200.0.3
  ...
	keyingtries=%forever
  replay_window=0      # <--- この行を追加
```

再起動なしに適用するには以下のコマンドを実施します。

```shell
sudo sysctl -w net.ipv4.conf.all.accept_local=1
sudo cp /config/scripts/ipsec.conf /etc/ipsec.conf
sudo ipsec restart
```

再起動毎に適用されるようにするためには `/config/scripts/vyos-postconfig-bootup.script` を作成します。

```shell:/config/scripts/vyos-postconfig-bootup.script
#!/bin/sh
# This script is executed at boot time after VyOS configuration is fully applied.
# Any modifications required to work around unfixed bugs
# or use services not available through the VyOS CLI system can be placed here.
 
sysctl -w net.ipv4.conf.all.accept_local=1  ### Make reply style health checks work
 
cp /config/scripts/ipsec.conf /etc/ipsec.conf
ipsec restart
```

## 参考：anti-replay protection が無効化されていない場合の動作

anti-replay protection が無効化されていないと、ping 応答し始めるのに数分の時間がかかるなど、かなり動作が不安定となり、サポート対象外の設定になります。

似たような動作となった場合は、anti-replay protection が無効化されているか確認しましょう。

> - [Anti-replay protection · Cloudflare Magic WAN docs](https://developers.cloudflare.com/magic-wan/reference/anti-replay-protection/)
>
> Keeping the thousands of possible senders in sync across continents introduces unacceptable delay and throughput problems and is generally intractable.
> 大陸をまたぐ何千もの送信者を同期させることは、許容できない遅延やスループットの問題を引き起こし、一般に難題です。

```
vyos@kyouhei-tokyo-vyos:~$ while true; do mtr -rwb -c 100 10.10.10.101 && sleep 5; done
Start: 2023-03-10T06:36:11+0000
HOST: kyouhei-tokyo-vyos Loss%   Snt   Last   Avg  Best  Wrst StDev
Start: 2023-03-10T06:38:02+0000
HOST: kyouhei-tokyo-vyos Loss%   Snt   Last   Avg  Best  Wrst StDev
Start: 2023-03-10T06:39:53+0000
HOST: kyouhei-tokyo-vyos Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 10.10.10.101       64.0%   100    2.2   2.3   2.2   2.4   0.0
Start: 2023-03-10T06:41:43+0000
HOST: kyouhei-tokyo-vyos Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 10.10.10.101        0.0%   100    2.3   2.3   2.2   2.7   0.1
Start: 2023-03-10T06:43:32+0000
HOST: kyouhei-tokyo-vyos Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 10.10.10.101        0.0%   100    2.3   2.3   2.2   2.9   0.1
```

# IPsec トンネル状態確認

以下のような状態であれば、問題ないです。

```shell
$ show vpn ike sa && show vpn ipsec sa
Peer ID / IP                            Local ID / IP               
------------                            -------------
x.x.x.x                          10.200.0.3                             

    State  IKEVer  Encrypt  Hash    D-H Group      NAT-T  A-Time  L-Time
    -----  ------  -------  ----    ---------      -----  ------  ------
    up     IKEv2   aes16_256 n/a     14(MODP_2048)  no     7200    14400  
    
Connection                      State    Uptime    Bytes In/Out    Packets In/Out    Remote address    Remote ID    Proposal
------------------------------  -------  --------  --------------  ----------------  ----------------  -----------  ------------------------
peer-x.x.x.x-tunnel-vti  up       1h9m41s   5M/0B           74K/0             x.x.x.x    N/A          AES_GCM_16_256/MODP_2048

$ ping 10.10.10.101
PING 10.10.10.101 (10.10.10.101) 56(84) bytes of data.
64 bytes from 10.10.10.101: icmp_seq=1 ttl=64 time=2.47 ms
64 bytes from 10.10.10.101: icmp_seq=2 ttl=64 time=2.24 ms
64 bytes from 10.10.10.101: icmp_seq=3 ttl=64 time=2.26 ms
64 bytes from 10.10.10.101: icmp_seq=4 ttl=64 time=2.29 ms
64 bytes from 10.10.10.101: icmp_seq=5 ttl=64 time=2.24 ms
^C
--- 10.10.10.101 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 10ms
rtt min/avg/max/mdev = 2.241/2.300/2.469/0.100 ms
```

また、ダッシュボードの Network Analytics 画面からも実際のトラフィックが見えているかを確認できます。

https://dash.cloudflare.com/?to=/:account/network-analytics/all-traffic

![image-20230314011516910](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20230314011516910.png)

# トンネルヘルスチェックの構成

実は Cloudflare ダッシュボードから IPsec トンネルを作成した段階で、トンネルヘルスチェックが走ります。

トンネルヘルスチェックは、Cloudflare 側で ICMP reply (or request) パケットを作って、IPsec で包んで送られます。

IPsec トンネルを渡り切ると、対向側で  ICMP reply (or request) パケットが処理され、Cloudflare に送出されます。

> - [Probe construction · Cloudflare Magic WAN docs](https://developers.cloudflare.com/magic-wan/reference/probe-construction/)
>
> A tunnel health check probe contains an [ICMP (Internet Control Message Protocol)Open external link](https://www.cloudflare.com/learning/ddos/glossary/internet-control-message-protocol-icmp/) reply packet that originates from an IP address on the origin side of the tunnel and whose destination address is a public Cloudflare IP.
>
> Cloudflare encapsulates the ICMP reply packet and sends the probe across the tunnel to the origin. When the probe reaches the origin router, the router decapsulates the ICMP reply and forwards it to the specified destination IP. The probe is successful when Cloudflare receives the reply.
>
> Every Cloudflare data center configured to process your traffic sends tunnel health check probes. The rate at which these health check probes are sent varies based on tunnel and location. This rate can also be tuned up or down on a per tunnel basis by modifying the `health_check` rate of a tunnel [with the API](https://developers.cloudflare.com/api/operations/magic-gre-tunnels-update-gre-tunnel).

以下のコマンドでみると、多数のエッジ拠点からかなりの数が送られて処理されていることがわかります。

```shell
$ sudo tcpdump -n -i vti0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vti0, link-type RAW (Raw IP), capture size 262144 bytes
16:37:31.086225 IP y.y.y.y > 172.71.209.90: ICMP echo reply, id 59098, seq 0, length 64
16:37:31.097285 IP y.y.y.y > 141.101.66.141: ICMP echo reply, id 29928, seq 0, length 64
16:37:31.112366 IP y.y.y.y > 172.70.133.79: ICMP echo reply, id 28514, seq 0, length 64
16:37:31.135833 IP y.y.y.y > 172.70.121.116: ICMP echo reply, id 28702, seq 0, length 64
16:37:31.146509 IP y.y.y.y > 172.71.217.51: ICMP echo reply, id 31300, seq 0, length 64
...
```

ただし、このままだとトンネルヘルスチェックがダウンのままとなっています。

![image-20230314014544267](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20230314014544267.png)

そこでログ `/var/log/messages` をみてみると、`martian source` と判定されていることがわかります。

```
$ tail -f /var/log/messages
Mar 13 03:51:09 kyouhei-tokyo-vyos kernel: [297464.540253] IPv4: martian source 172.69.141.20 from y.y.y.y, on dev vti0
Mar 13 03:51:09 kyouhei-tokyo-vyos kernel: [297464.822106] IPv4: martian source 162.158.173.82 from y.y.y.y, on dev vti0
Mar 13 03:51:09 kyouhei-tokyo-vyos kernel: [297465.065180] IPv4: martian source 172.70.133.234 from y.y.y.y, on dev vti0
Mar 13 03:51:09 kyouhei-tokyo-vyos kernel: [297465.131223] IPv4: martian source 172.69.165.37 from y.y.y.y, on dev vti0
Mar 13 03:51:09 kyouhei-tokyo-vyos kernel: [297465.434259] IPv4: martian source 172.68.185.14 from y.y.y.y, on dev vti0
```

これは本来 `vti0` インターフェースに割り当てられていないアドレスを送信元としたパケットが送信されようとしているので、`rp_filter` に引っかかって、ICMP reply が Cloudflare に送られていません。

> - [13.10 SNMPトラップが受信できない](https://software.fujitsu.com/jp/manual/manualfiles/m190003/j2x12061/14z204/j2061-00-13-10-00.html)
>   注) **rp_filter**(reverse path filtering)とは、パケットを受信したときに、そのパケットの送信元IPアドレスに対する返信ルートがそのパケットを受信したネットワークインタフェースではない場合、そのパケットを破棄するというものです。

そのため、以下のコマンドを実行して `vti0` の `rp_filter` を無効化します。

```shell
sudo sysctl -a | grep rp_filter
sudo sysctl -w net.ipv4.conf.vti0.rp_filter=0
sudo sysctl -w net.ipv4.conf.all.rp_filter=0
sudo sysctl -a | grep rp_filter
```

すると、 `martian source` のログが無くなり、トンネルヘルスチェック結果が正しく見られるようになりました。

![image-20230313130127818](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20230313130127818.png)

![hcup](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/hcup.png)

## 参考：トンネルヘルスチェック設定の確認

```shell
% curl -X GET "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/magic/ipsec_tunnels" \
     -H "X-Auth-Email: $EMAIL" \
     -H "X-Auth-Key: $APIKEY" \
     -H "Content-Type: application/json" | jq
     
...
"health_check": {
          "enabled": true,
          "target": "x.x.x.x",
          "type": "reply",
          "rate": "mid"
        }
```

## 参考：トンネルヘルスチェック設定の変更

```shell
export ACCOUNT_ID='YOUR_ACCOUNT_ID'
export TUNNEL_ID='YOUR_TUNNEL_ID'

curl --request PUT \
--url https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/magic/ipsec_tunnels/$TUNNEL_ID \
--header 'Content-Type: application/json' \
-H "X-Auth-Email: $EMAIL" \
-H "X-Auth-Key: $APIKEY" \
--data '{"health_check": {"target": "x.x.x.x","type": "reply","rate":"low"}}'
```

# Magic WAN 静的ルートの設定

Cloudflare 内での静的ルートをダッシュボードから設定します。

https://dash.cloudflare.com/?to=/:account/magic-wan/configuration/static-routes

![image-20230314022015802](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20230314022015802.png)

![image-20230314021937044](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20230314021937044.png)

# VyOS 静的ルートの構成

以下の静的ルートを構成します。

```shell:tokyo-vyos
set protocols static route 10.10.10.102/31 next-hop 10.10.10.101
set protocols static route 10.202.0.0/20 next-hop 10.10.10.101
```

```shell:osaka-vyos
set protocols static route 10.10.10.100/31 next-hop 10.10.10.103
set protocols static route 10.200.0.0/20 next-hop 10.10.10.103
```

# エンドツーエンド通信確認用サーバー準備

VPC A と B に `tokyo-mwan` と `osaka-mwan` サーバーをそれぞれ準備します。

```shell
gcloud compute images create debian-11-multi-ip-subnet \
--source-image-family=debian-11 \
--source-image-project=debian-cloud \
--guest-os-features MULTI_IP_SUBNET

PROJECT='your-project'
ZONE=asia-northeast2-b
SUBNET=kyouhei-osaka-mwan                         
NAME=kyouhei-osaka-mwan

gcloud compute instances create $NAME \
--project=$PROJECT --zone=$ZONE \
--machine-type=e2-medium \
--network-interface=subnet=$SUBNET,private-network-ip=10.202.0.6 \
--maintenance-policy=MIGRATE \
--service-account=xxx-compute@developer.gserviceaccount.com \
--scopes=https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/trace.append \
--create-disk=auto-delete=yes,boot=yes,device-name=$NAME,image=projects/$PROJECT/global/images/debian-11-multi-ip-subnet,mode=rw,size=10,type=projects/$PROJECT/zones/$ZONE/diskTypes/pd-balanced \
--no-shielded-secure-boot \
--shielded-vtpm \
--shielded-integrity-monitoring \
--reservation-affinity=any --can-ip-forward
```

# VPC Route の構成

`tokyo-mwan` のネクストホップが `tokyo-vyos`、`osaka-mwan` のネクストホップが `osaka-vyos` となるように VPC Route を構成します。

```shell:tokyo-mwan
gcloud compute instances add-tags kyouhei-tokyo-mwan --tags=tokyo-mwan --zone=asia-northeast1-b
gcloud compute routes create tokyo-mwan-route --network=vpc-a --priority=100 --tags=tokyo-mwan \
--destination-range=10.202.0.0/20 --next-hop-instance=kyouhei-tokyo-vyos --next-hop-instance-zone=asia-northeast1-b
```

```shell:osaka-mwan
gcloud compute instances add-tags kyouhei-osaka-mwan --tags=osaka-mwan --zone=asia-northeast2-b
gcloud compute routes create osaka-mwan-route --network=vpc-b --priority=100 --tags=osaka-mwan \
--destination-range=10.200.0.0/20 --next-hop-instance=kyouhei-osaka-vyos --next-hop-instance-zone=asia-northeast2-b
```

# エンドツーエンド通信確認

最後に VyOS と同じネットワークにいる `tokyo-mwan` と `osaka-mwan` サーバー間の通信を確認します。

## ping

`vti0` インターフェースを経由して、VPC 間の通信がおこなわれていることがわかります。

```shell:osaka-mwan
osaka-mwan:~$ ping 10.200.0.5 -c 4
PING 10.200.0.5 (10.200.0.5) 56(84) bytes of data.
64 bytes from 10.200.0.5: icmp_seq=1 ttl=61 time=11.8 ms
64 bytes from 10.200.0.5: icmp_seq=2 ttl=61 time=11.8 ms
64 bytes from 10.200.0.5: icmp_seq=3 ttl=61 time=11.6 ms
64 bytes from 10.200.0.5: icmp_seq=4 ttl=61 time=11.8 ms

--- 10.200.0.5 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 11.634/11.745/11.798/0.065 ms
```

```shell:osaka-vyos
osaka-vyos:~$ sudo tcpdump -n -i vti0 host \(10.200.0.5 or 10.202.0.6\) and icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vti0, link-type RAW (Raw IP), capture size 262144 bytes
16:54:29.265479 IP 10.202.0.6 > 10.200.0.5: ICMP echo request, id 46015, seq 1, length 64
16:54:29.278605 IP 10.200.0.5 > 10.202.0.6: ICMP echo reply, id 46015, seq 1, length 64
16:54:30.266459 IP 10.202.0.6 > 10.200.0.5: ICMP echo request, id 46015, seq 2, length 64
16:54:30.278015 IP 10.200.0.5 > 10.202.0.6: ICMP echo reply, id 46015, seq 2, length 64
16:54:31.267617 IP 10.202.0.6 > 10.200.0.5: ICMP echo request, id 46015, seq 3, length 64
16:54:31.279080 IP 10.200.0.5 > 10.202.0.6: ICMP echo reply, id 46015, seq 3, length 64
16:54:32.269668 IP 10.202.0.6 > 10.200.0.5: ICMP echo request, id 46015, seq 4, length 64
16:54:32.281181 IP 10.200.0.5 > 10.202.0.6: ICMP echo reply, id 46015, seq 4, length 64
...
16:54:41.218017 IP 10.200.0.5 > 10.202.0.6: ICMP echo request, id 43144, seq 1, length 64
16:54:41.219678 IP 10.202.0.6 > 10.200.0.5: ICMP echo reply, id 43144, seq 1, length 64
16:54:42.218531 IP 10.200.0.5 > 10.202.0.6: ICMP echo request, id 43144, seq 2, length 64
16:54:42.218864 IP 10.202.0.6 > 10.200.0.5: ICMP echo reply, id 43144, seq 2, length 64
16:54:43.219630 IP 10.200.0.5 > 10.202.0.6: ICMP echo request, id 43144, seq 3, length 64
16:54:43.219992 IP 10.202.0.6 > 10.200.0.5: ICMP echo reply, id 43144, seq 3, length 64
16:54:44.220675 IP 10.200.0.5 > 10.202.0.6: ICMP echo request, id 43144, seq 4, length 64
16:54:44.220991 IP 10.202.0.6 > 10.200.0.5: ICMP echo reply, id 43144, seq 4, length 64
```

```shell:tokyo-vyos
tokyo-vyos:~$ sudo tcpdump -n -i vti0 host \(10.200.0.5 or 10.202.0.6\) and icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vti0, link-type RAW (Raw IP), capture size 262144 bytes
17:16:15.348674 IP 10.202.0.6 > 10.200.0.5: ICMP echo request, id 16990, seq 1, length 64
17:16:15.350367 IP 10.200.0.5 > 10.202.0.6: ICMP echo reply, id 16990, seq 1, length 64
17:16:16.349054 IP 10.202.0.6 > 10.200.0.5: ICMP echo request, id 16990, seq 2, length 64
17:16:16.349510 IP 10.200.0.5 > 10.202.0.6: ICMP echo reply, id 16990, seq 2, length 64
17:16:17.351048 IP 10.202.0.6 > 10.200.0.5: ICMP echo request, id 16990, seq 3, length 64
17:16:17.351346 IP 10.200.0.5 > 10.202.0.6: ICMP echo reply, id 16990, seq 3, length 64
17:16:18.352982 IP 10.202.0.6 > 10.200.0.5: ICMP echo request, id 16990, seq 4, length 64
17:16:18.353313 IP 10.200.0.5 > 10.202.0.6: ICMP echo reply, id 16990, seq 4, length 64

17:16:23.461073 IP 10.200.0.5 > 10.202.0.6: ICMP echo request, id 52171, seq 1, length 64
17:16:23.472878 IP 10.202.0.6 > 10.200.0.5: ICMP echo reply, id 52171, seq 1, length 64
17:16:24.462409 IP 10.200.0.5 > 10.202.0.6: ICMP echo request, id 52171, seq 2, length 64
17:16:24.474453 IP 10.202.0.6 > 10.200.0.5: ICMP echo reply, id 52171, seq 2, length 64
17:16:25.463758 IP 10.200.0.5 > 10.202.0.6: ICMP echo request, id 52171, seq 3, length 64
17:16:25.475155 IP 10.202.0.6 > 10.200.0.5: ICMP echo reply, id 52171, seq 3, length 64
17:16:26.465677 IP 10.200.0.5 > 10.202.0.6: ICMP echo request, id 52171, seq 4, length 64
17:16:26.477048 IP 10.202.0.6 > 10.200.0.5: ICMP echo reply, id 52171, seq 4, length 64
```

```shell:tokyo-mwan
tokyo-mwan:~$ ping 10.202.0.6 -c 4
PING 10.202.0.6 (10.202.0.6) 56(84) bytes of data.
64 bytes from 10.202.0.6: icmp_seq=1 ttl=61 time=11.7 ms
64 bytes from 10.202.0.6: icmp_seq=2 ttl=61 time=11.7 ms
64 bytes from 10.202.0.6: icmp_seq=3 ttl=61 time=11.6 ms
64 bytes from 10.202.0.6: icmp_seq=4 ttl=61 time=11.4 ms

--- 10.202.0.6 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3006ms
rtt min/avg/max/mdev = 11.448/11.600/11.678/0.090 ms
```

## iperf

VPC -- Cloudflare -- VPC という構成で、数百 Mbps は問題なく出ることが確認できます。

```shell:tokyo-mwan
sudo apt install iperf -y

$ iperf -s -B 10.200.0.5
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size:  128 KByte (default)
------------------------------------------------------------
[  4] local 10.200.0.5 port 5001 connected with 10.202.0.6 port 53378
[ ID] Interval       Transfer     Bandwidth
[  4] 0.0000-60.0563 sec  3.37 GBytes   481 Mbits/sec
```

```shell:osaka-mwan
$ iperf -c 10.200.0.5 -i 10 -t 60 -m
------------------------------------------------------------
Client connecting to 10.200.0.5, TCP port 5001
TCP window size: 45.0 KByte (default)
------------------------------------------------------------
[  3] local 10.202.0.6 port 53378 connected with 10.200.0.5 port 5001 (MSS=1348)
[ ID] Interval       Transfer     Bandwidth
[  3] 0.0000-10.0000 sec   567 MBytes   476 Mbits/sec
[  3] 10.0000-20.0000 sec   629 MBytes   528 Mbits/sec
[  3] 20.0000-30.0000 sec   553 MBytes   464 Mbits/sec
[  3] 30.0000-40.0000 sec   568 MBytes   477 Mbits/sec
[  3] 40.0000-50.0000 sec   535 MBytes   449 Mbits/sec
[  3] 50.0000-60.0000 sec   593 MBytes   497 Mbits/sec
[  3] 60.0000-60.0168 sec   256 KBytes   125 Mbits/sec
[  3] 0.0000-60.0168 sec  3.37 GBytes   482 Mbits/sec
```

以下のグラフは `iperf` を30分程度実施して、GraphQL API から取得したデータを Grafana で描画した結果です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/b923cbfb-f8ff-cb32-9156-cfc9123b1ec4.png)

```graphql
{
  viewer {
    accounts(filter: {accountTag: "YOUR_ACCOUNT_TAG"}) {
        magicTransitNetworkAnalyticsAdaptiveGroups (orderBy:[datetime_ASC], limit:10000, filter:{date_geq:"2023-03-17"}) {
          avg {
            bitRate
          }
          dimensions {
            datetime
            ingressTunnelName
          }
        }
      }
  }
}
```

# まとめ

今回は、異なる VPC 間の通信を Cloudflare Magic WAN で構成できることがわかりましたが、

これは VPC 間という構成に限らず、マルチクラウド間やオンプレミス拠点間の通信に対しても構成ができます。

また、Magic WAN から Zero Trust サービスを経由させてインターネットに出たり、Magic Firewall による通信制御をおこなうこと等ができるので、Cloudflare を経由させることでさまざまなネットワーク機能を柔軟に付加することができます。

オンプレミスにある諸々のアプライアンス機能は、今後 Cloudflare に寄せて、オンプレミスにはシンプルな IPsec ルータがあればよい、という形でシンプル化できてくると思います。

![image-20230318023108153](https://cdn.jsdelivr.net/gh/kyouheicf/image@master/uPic/image-20230318023108153.png)

# 参考： WARP <--> Magic WAN のルーティングを構成する

WARP デバイスに一意に振られる Virtual Network では、`100.64.0.0/10` の [CGNAT](https://www.nic.ad.jp/ja/basics/terms/cgn.html) 領域が使われるので、それに関するルーティングを構成します。

- [Use WARP as an on-ramp · Cloudflare Magic WAN docs](https://developers.cloudflare.com/magic-wan/tutorials/warp/)

以下の静的ルートを構成します。

```shell:tokyo-vyos
set protocols static route 100.64.0.0/10 next-hop 10.10.10.101
```

```shell:osaka-vyos
set protocols static route 100.64.0.0/10 next-hop 10.10.10.103
```

以下の VPC Route を構成します。

```shell:tokyo-mwan
gcloud compute routes create tokyo-mwan-warp --network=vpc-a --priority=100 --tags=tokyo-mwan \
--destination-range=100.64.0.0/10 --next-hop-instance=kyouhei-tokyo-vyos --next-hop-instance-zone=asia-northeast1-b
```

```shell:osaka-mwan
gcloud compute routes create osaka-mwan-warp --network=vpc-b --priority=100 --tags=osaka-mwan \
--destination-range=100.64.0.0/10 --next-hop-instance=kyouhei-osaka-vyos --next-hop-instance-zone=asia-northeast2-b
```

あとは Zero Trust ダッシュボード > My Team > Device からわかる `100.96.x.x` のアドレスに対して疎通確認をおこなう。

# 参考：VPN プロセス再起動と状態確認

```shell
restart vpn
show vpn ike sa && show vpn ipsec sa
```

```
Restarting IPsec process...
---
Peer ID / IP                            Local ID / IP               
------------                            -------------
x.x.x.x                                 y.y.y.y                            

    State  IKEVer  Encrypt  Hash    D-H Group      NAT-T  A-Time  L-Time
    -----  ------  -------  ----    ---------      -----  ------  ------
    up     IKEv2   aes16_256 n/a     14(MODP_2048)  no     3600    14400  

 
Connection                      State    Uptime    Bytes In/Out    Packets In/Out    Remote address    Remote ID    Proposal
------------------------------  -------  --------  --------------  ----------------  ----------------  -----------  --------------
peer-x.x.x.x-tunnel-vti         up       4s        3K/4K           47/49             x.x.x.x           N/A          AES_GCM_16_256
```

# 参考

- [tcpdumpのフィルターのまとめ | 猫型iPS細胞研究所](https://ips.nekotype.com/2182/)
- [Bluemix Infrastructure(SoftLayer)におけるネットワークツールを使った通信問題の判別方法 - Qiita](https://qiita.com/testnin2/items/935f46d3874a04f2b4d8)
- [ESXiホストでiperfを使う方法 - Qiita](https://qiita.com/khayama/items/d76c27ee60c1537a0577)