VyOS で Cloudflare Magic WAN の IPsec トンネルに双方向ヘルスチェックを構成する

# 目的
以下の記事で Cloudflare Magic WAN の IPsec トンネルを構成しました。

- [VyOS から Cloudflare Magic WAN に IPsec トンネルを接続する - Qiita](https://qiita.com/khayama/items/20a0b49458a2296f92dc)

その際に [Tunnel health checks](https://developers.cloudflare.com/magic-wan/how-to/run-tunnel-health-checks/) を構成して、トンネルの状態を監視できます。

Magic WAN のように Ingress / Egress の双方向で通信利用する場合には、ヘルスチェックも双方向にトンネルを経由させることが推奨なため、設定をおこなってみます。

# 片方向ヘルスチェック

- [Configure bidirectional tunnel health checks for egresss traffic · Cloudflare Magic Transit docs](https://developers.cloudflare.com/magic-transit/how-to/run-tunnel-health-checks/)

例えば、Magic Transit で DSR (Direct Server Return) 型の場合には、 Ingress のときにトンネルを経由し、Egress のときはトンネルを経由せず ISP へのアップリンクから直接インターネットを経由する非対称な経路となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/ba60c3c3-d765-6d95-9fa9-74e47d961715.png)

その際は、顧客ルータのグローバル IP をターゲットとした、片方向ヘルスチェックで問題ありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/3a1fa5a3-1841-734e-2d02-5e90649bc1fb.png)

```mermaid:
flowchart LR
  subgraph Tunnel[GRE Tunnel]
    ICMP["ICMP Probe<br>(Ingress)"]
  end
  subgraph ISP[ISP]
    Reply["ICMP Echo Reply<br>(Egress)"]
  end
  Edge[Cloudflare] --- ICMP & Reply
  ICMP & Reply --- Router["Router<br>Global IP<br>(Health check target)"]
```

# 双方向ヘルスチェック
- [Configure tunnel health checks · Cloudflare Magic WAN docs](https://developers.cloudflare.com/magic-wan/how-to/run-tunnel-health-checks/)

ターゲットアドレスに `172.64.240.252/30` の中からアドレスを指定して使用することで、双方向なヘルスチェックを実現できます。

顧客ルータでは、ソースアドレス `172.64.240.252/30` からの ICMP Echo Reply がトンネルを経由するように構成する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/5831ced9-05ae-a910-69bf-c2de2cf2b905.png)

```mermaid:
flowchart LR
  subgraph Tunnel[IPsec Tunnel]
    ICMP["ICMP Probe<br>(Ingress)"]
    Reply["ICMP Echo Reply<br>(Egress)"]
  end
  Edge[Cloudflare] --- ICMP & Reply
  ICMP & Reply --- Router["Router<br>ex.) 172.64.240.253/32<br>(Health check target)"]
```

# ヘルスチェックタイプ：Reply と Request
トンネルヘルスチェックのタイプには Reply と Request の2つがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/a1530b6d-b8e9-9f80-1bf7-36bd0d8a7b93.png)

Reply タイプがデフォルトですが、カプセル化された ICMPリプライパケットがルータに届いた瞬間に Cloudflare に送り返されるような仕組みです。

そのため、ICMP における非対称性がルータにて許容されている必要があります。

- [Probe construction · Cloudflare Magic WAN docs](https://developers.cloudflare.com/magic-wan/reference/probe-construction/)
> CloudflareはICMPリプライパケットをカプセル化し、プローブをトンネルを越えてオリジンに送信します。プローブがオリジンのルーターに到達すると、ルーターはICMPリプライをカプセル化解除し、指定された宛先IPに転送する。Cloudflareがリプライを受信すると、プローブは成功します。
>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/30305855-fdda-3be2-d91f-171d06dc5384.png)

一方で、Request タイプに変更することも可能です。

>オリジンネットワークによって強制される制御プレーンポリシーを回避するために、トンネルヘルスチェックはICMPエコーリクエストの代わりにカプセル化されたICMPリプライを使用します。エコーリクエストのパケットもタイプ設定により変更可能です。

Reply と Request のヘルスチェックタイプは、環境に応じて設定が入れやすい方を選択します。

# VyOS で双方向ヘルスチェック (Reply) を設定
VyOS で双方向ヘルスチェック (Reply) を設定する場合は、

- ソースアドレスが `172.64.240.252/30` の ICMP パケットは IPsec トンネルインターフェース `vti0` からルーティングされるように PBR (Policy Based Routing) を構成します。

```cisco_ios:
set protocols static table 100 interface-route 0.0.0.0/0 next-hop-interface vti0

set policy route pbr rule 1000 set table '100'
set policy route pbr rule 1000 protocol icmp 
set policy route pbr rule 1000 source address 172.64.240.252/30

set interfaces vti vti0 policy route 'pbr'
```

以下のコマンドでヘルスチェックパケット（`ICMP echo reply` のみ）を確認できます。

```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
15:46:28.206027 IP 172.64.240.253 > 141.101.70.193: ICMP echo reply, id 61957, seq 0, length 64
15:46:28.206074 IP 172.64.240.253 > 141.101.70.193: ICMP echo reply, id 61957, seq 0, length 64
15:46:28.234231 IP 172.64.240.253 > 172.70.221.63: ICMP echo reply, id 24420, seq 0, length 64
15:46:28.234273 IP 172.64.240.253 > 172.70.221.63: ICMP echo reply, id 24420, seq 0, length 64
15:46:28.236154 IP 172.64.240.253 > 172.69.21.167: ICMP echo reply, id 54534, seq 0, length 64
```

また、Magic Firewall の Network Analytics 画面からもヘルスチェックパケットを確認できます。
https://dash.cloudflare.com/?to=/:account/network-analytics/magic-firewall
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/bd425d45-675d-3c41-1da9-567aabb40121.png)

# VyOS で双方向ヘルスチェック (Request) を設定
VyOS で双方向ヘルスチェック (Request) を設定する場合は、

- `ICMP echo request` を受け取って返答できるようにループバックインターフェースに `172.64.240.253/32` を設定します。
- また、ソースアドレスが [Cloudflare IP Ranges](https://www.cloudflare.com/ips/) の ICMP パケットは IPsec トンネルインターフェース `vti0` からルーティングされるよう、ループバックインターフェースに PBR (Policy Based Routing) を構成します。


```cisco_ios:
set interfaces loopback lo address 172.64.240.253/32
set protocols static table 100 interface-route 0.0.0.0/0 next-hop-interface vti0
set policy local-route rule 1000 set table 100
set policy local-route rule 1000 source 173.245.48.0/20
set policy local-route rule 1000 source 103.21.244.0/22
set policy local-route rule 1000 source 103.22.200.0/22
set policy local-route rule 1000 source 103.31.4.0/22
set policy local-route rule 1000 source 141.101.64.0/18
set policy local-route rule 1000 source 108.162.192.0/18
set policy local-route rule 1000 source 190.93.240.0/20
set policy local-route rule 1000 source 188.114.96.0/20
set policy local-route rule 1000 source 197.234.240.0/22
set policy local-route rule 1000 source 198.41.128.0/17
set policy local-route rule 1000 source 162.158.0.0/15
set policy local-route rule 1000 source 104.16.0.0/13
set policy local-route rule 1000 source 104.24.0.0/14
set policy local-route rule 1000 source 172.64.0.0/13
set policy local-route rule 1000 source 131.0.72.0/22
```

以下のコマンドでヘルスチェックパケット（`ICMP echo request` と `ICMP echo reply` の両方）を確認できます。

```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
15:52:27.509669 IP 162.158.165.8 > 172.64.240.253: ICMP echo request, id 16932, seq 0, length 64
15:52:27.510556 IP 172.64.240.253 > 162.158.165.8: ICMP echo reply, id 16932, seq 0, length 64
15:52:27.510577 IP 198.41.136.75 > 172.64.240.253: ICMP echo request, id 60642, seq 0, length 64
15:52:27.510590 IP 172.64.240.253 > 198.41.136.75: ICMP echo reply, id 60642, seq 0, length 64
15:52:27.527028 IP 172.69.66.16 > 172.64.240.253: ICMP echo request, id 20760, seq 0, length 64
15:52:27.527106 IP 172.64.240.253 > 172.69.66.16: ICMP echo reply, id 20760, seq 0, length 64
15:52:27.543709 IP 162.158.157.28 > 172.64.240.253: ICMP echo request, id 4125, seq 0, length 64
15:52:27.543789 IP 172.64.240.253 > 162.158.157.28: ICMP echo reply, id 4125, seq 0, length 64
```

また、Magic Firewall の Network Analytics 画面からもヘルスチェックパケットを確認できます。
https://dash.cloudflare.com/?to=/:account/network-analytics/magic-firewall
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/bd425d45-675d-3c41-1da9-567aabb40121.png)

# まとめ

最近、ダッシュボード上でもヘルスチェック設定を確認・変更できるようになったため、ユーザにもわかりやすくなりました。

- [Check for tunnel health in the dashboards](https://developers.cloudflare.com/magic-wan/how-to/run-tunnel-health-checks/#check-for-tunnel-health-in-the-dashboard)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Cloudflare Magic WAN / Transit で使う GRE / IPsec トンネルのヘルスチェックが UI でも構成可能になりました <a href="https://t.co/UVEChkn0T6">pic.twitter.com/UVEChkn0T6</a></p>&mdash; kyhayama (@kyhayama) <a href="https://twitter.com/kyhayama/status/1657956924330250240?ref_src=twsrc%5Etfw">May 15, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

また、このトンネルヘルスチェックの結果を用いて転送先トンネルが決められ、Healthy なトンネルにのみ転送することができます。

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

Cloudflare Magic WAN の IPsec トンネル構成と同時に、双方向ヘルスチェックを構成することをおすすめします。