Cloudflare Zero Trust で Zoom IP レンジの Split Tunnel エントリを追加する

# Zoom の推奨確認
Zoom によると VPN 利用時は、以下の通信に対して VPN を通らないように Split Tunnel のリストに追加することが推奨されています。

- [VPN Split Tunneling Recommendations – Zoom Support](https://support.zoom.us/hc/en-us/articles/360053610731-VPN-Split-Tunneling-Recommendations)

> When VPN services are used, to optimize the traffic flow Zoom recommends enabling Split Tunneling with the following:
> - Allow UDP 8801-8810
> - Allow TCP 443
> - Destination to Zoom specific IP ranges (https://assets.zoom.us/docs/ipranges/ZoomMeetings.txt) and/or *.zoom.us. 

# Cloudflare Zero Trust で Split Tunnel エントリを追加するには？

上記の IP リストを見ると、300 以上の IP レンジを登録する必要があります。

- [wc -lでは文末に改行がないファイルの行数を正しく数えられない - grep Tips *](https://www.greptips.com/posts/1216/#:~:text=%E6%9C%80%E5%BE%8C%E3%81%AB%E6%94%B9%E8%A1%8C%E3%81%8C%E3%81%82%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AF%E4%BB%A5%E4%B8%8B%E3%81%AE%E9%80%9A%E3%82%8A%E5%95%8F%E9%A1%8C%E3%81%AA%E3%81%84%E3%80%82&text=wc%20%2Dl%20%E3%81%AF%E6%94%B9%E8%A1%8C%E3%81%AE,%E6%95%B0%E3%82%92%E8%BF%94%E3%81%97%E3%81%A6%E3%81%97%E3%81%BE%E3%81%86%E3%80%82)

```shell
% curl -s https://assets.zoom.us/docs/ipranges/ZoomMeetings.txt | grep -c '' 
310
```

ただ 2023年4月28日現在では、Cloudflare Zero Trust ダッシュボードからバルクでインポートする処理は見当たらないため、API から追加する方法が効率的です。

- [Split Tunnels · Cloudflare Zero Trust docs](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/configure-warp/route-traffic/split-tunnels/#configure-split-tunnels)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/3a5817c9-dbe8-ed33-89b8-b711acf5cb36.png)

# Split Tunnel エントリ追加 API

- [Set Split Tunnel Exclude List - Cloudflare API Documentation](https://developers.cloudflare.com/api/operations/devices-set-split-tunnel-exclude-list)

`PATCH` メソッドがないため、`PUT` メソッドによる上書きが必要です。

[Split Tunnel のデフォルトエントリ](#参考cloudflare-zero-trust-の-split-tunnel-のデフォルトエントリ) を含めて、`PUT` するのが以下のコマンドになります。

返答として、大量のエントリと `"success":true` が返ってきていれば OK です。

```shell
export ACCOUNT_ID='YOUR_ACCOUNT_ID'
export EMAIL='YOUR_EMAIL'
export APIKEY='YOUR_API_KEY'

curl -s https://assets.zoom.us/docs/ipranges/ZoomMeetings.txt | jq -Rs '[ split("\n")[] | select(length > 0) | split(",") | {address: .[0]} ] | . + [{"address":"10.0.0.0/8"},{"address":"100.64.0.0/10"},{"address":"169.254.0.0/16"},{"address":"172.16.0.0/12"},{"address":"192.0.0.0/24"},{"address":"192.168.0.0/16"},{"address":"224.0.0.0/24"},{"address":"240.0.0.0/4"},{"address":"255.255.255.255/32"},{"address":"fe80::/10"},{"address":"fd00::/8"},{"address":"ff01::/16"},{"address":"ff02::/16"},{"address":"ff03::/16"},{"address":"ff04::/16"},{"address":"ff05::/16"}]' | \
curl -X PUT https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/devices/policy/exclude \
     -H "X-Auth-Email: $EMAIL" \
     -H "X-Auth-Key: $APIKEY" \
     -H "Content-Type: application/json" \
     --data @-
```

API 操作が完了すると、エントリの数が 326（デフォルトエントリ 16 + Zoom IP レンジ 310）になっていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/db0b34f6-84e8-c421-00ef-37be15d106d6.png)

# プロファイル指定

- [Device profiles · Cloudflare Zero Trust docs](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/configure-warp/device-profiles/)

先ほどの例はデフォルトプロファイルに対しての設定になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/ad99ecb4-90b0-a25d-6a1b-eb2d5aa322ae.png)

デフォルトプロファイル以外にも、プロファイルがある場合には

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/a1dc5df7-87a5-1083-8e43-56faefa972cf.png)

以下の API からプロファイルの ID を取得し、

- [List Device Settings Policies - Cloudflare API Documentation](https://developers.cloudflare.com/api/operations/devices-list-device-settings-policies)

```shell
% curl -sX GET https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/devices/policies \
     -H "X-Auth-Email: $EMAIL" \
     -H "X-Auth-Key: $APIKEY" \
     -H "Content-Type: application/json" | jq -r '.result|map(. |= {policy_id, enabled, name, match, precedence, default}) |.[]'
{
  "policy_id": "f4475b76-1f90-489d-872a-f500a385cbdc",
  "enabled": true,
  "name": "Office User",
  "match": "network in {\"Tokyo Office Network\"}",
  "precedence": 1000,
  "default": false
}
{
  "policy_id": null,
  "enabled": true,
  "name": null,
  "match": null,
  "precedence": null,
  "default": true
}
```

ID を指定してエントリ追加のコマンドを実施すれば、個別のプロファイルにも対応できます

```she
export POLICY_ID='f4475b76-1f90-489d-872a-f500a385cbdc'

curl -s https://assets.zoom.us/docs/ipranges/ZoomMeetings.txt | jq -Rs '[ split("\n")[] | select(length > 0) | split(",") | {address: .[0]} ] | . + [{"address":"10.0.0.0/8"},{"address":"100.64.0.0/10"},{"address":"169.254.0.0/16"},{"address":"172.16.0.0/12"},{"address":"192.0.0.0/24"},{"address":"192.168.0.0/16"},{"address":"224.0.0.0/24"},{"address":"240.0.0.0/4"},{"address":"255.255.255.255/32"},{"address":"fe80::/10"},{"address":"fd00::/8"},{"address":"ff01::/16"},{"address":"ff02::/16"},{"address":"ff03::/16"},{"address":"ff04::/16"},{"address":"ff05::/16"}]' | \
curl -X PUT https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/devices/policy/$POLICY_ID/exclude \
     -H "X-Auth-Email: $EMAIL" \
     -H "X-Auth-Key: $APIKEY" \
     -H "Content-Type: application/json" \
     --data @-
```

# 【参考】Cloudflare Zero Trust の Split Tunnel のデフォルトエントリ
こちらになります。

https://gist.github.com/kyouheicf/b3a90942516ea6c06c739fa2b43cfa1c