Cloudflare Zero Trust の Dedicated Egress IP オプションについて整理

# 目的
Cloudflare Zero Trust の Enterprise オプションである Dedicated Egress IP について挙動を整理します。

- [Cloudflare Gateway専用エグレスとエグレスポリシー](https://blog.cloudflare.com/ja-jp/gateway-dedicated-egress-policies-ja-jp/)

出口 IP を固定化したい場合、アーキテクチャ上、Dedicated Egress IP オプションを購入するやり方が最もシンプルでおすすめです。

出口 IP を固定化する他のやり方については、以下の記事を参考にしてください。

- [Cloudflare を経由し、固定の IP から Internet にアクセスをする - Qiita](https://qiita.com/KeioCF/items/1cf77ddd77dc143c2a47#5-%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%B3%E3%82%BF%E3%83%BC%E3%81%AE%E5%9B%BA%E5%AE%9A-ip-%E3%81%AE%E4%BB%A3%E3%82%8F%E3%82%8A%E3%81%ABgateway-%E3%81%AE-dedicated-egress-ip-%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AB%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E3%82%8B)

# Dedicated egress IP 

- [Dedicated egress IPs · Cloudflare Zero Trust docs](https://developers.cloudflare.com/cloudflare-one/policies/gateway/egress-policies/dedicated-egress-ips/)

特徴

- Static = 出口 IP は動的に変わらず、固定
    - 通常は Cloudflare Default IP Pool から動的に割り当てられた出口 IP が使用される
- Dedicated = 購入したアカウントだけで専有
    - 通常は、他のアカウントと共有の Shared IP が出口 IP として使用される
- 1 IP は 1 データセンタに対して紐づき、その地理情報が適用される
    - 最小単位で、Cloudflareは2つの異なるデータセンターに対応する2つのDedicated Egress IPをアカウントに提供。追加の Dedicated Egress IP も購入可。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/cd4218d1-f951-f54f-0b89-7384638372cb.png)

# No Egress Policy Match

Egress ポリシーがない、もしくはマッチしない場合、デフォルトの挙動としては、**接続ユーザーに最も近い** Dedicated Egress IP を使って出ていく形になります。
ただし、IPv4/IPv6 による接続か、サイトが Cloudflare によってプロキシされているか（Grey/Orange）によって挙動が異なります。

## IPv4 Grey Web Sites

宛先が IPv4 かつ Cloudflare によってプロキシされていない場合、以下の挙動になります。

| 宛先 IP | 宛先サイトが Cloudflare によってプロキシされているか | 物理的な Egress 場所                                         | ソース IP と地理情報             |
| ------- | ---------------------------------------------------- | ------------------------------------------------------------ | -------------------------------- |
| IPv4    | No (Grey)                                            | Dedicated Egress IP が紐づけられたデータセンターから出ていく | Dedicated Egress IP の情報を使用 |

```mermaid:
---
title: No Egress Policy Match (IPv4 Grey Web Sites)
---
flowchart BT
    SU["Singapore Users"]-->|Anycast Routing|ZT2["ZT Services"]
    OU["Osaka Users"]-->|Anycast Routing|ZT3["ZT Services"]
    TU["Tokyo Users"]-->|Anycast Routing|ZT1["ZT Services"]
    subgraph Cloudflare
    subgraph Singapore PoP
    ZT2-->DEIP2[Dedicated Egress IP #2]
    end
    subgraph Osaka PoP
    ZT3
    end
    ZT3-->|Proximity</br>Routing</br>by latency|DEIP1[Dedicated Egress IP #1]
    subgraph Tokyo PoP
    ZT1-->DEIP1[Dedicated Egress IP #1]
    end
    end
    DEIP2-->|Egress|WSS["IPv4 Grey Web Sites"]
    DEIP1-->|Egress|WSS
```

## IPv4 Orange Web Sites (IPv6 の場合も含む)

一方で、宛先が IPv4 かつ Cloudflare によってプロキシされている場合、以下の挙動になります。

（宛先が IPv6 のケースも同様の挙動となるため、省略します。）

| 宛先 IP | 宛先サイトが Cloudflare によってプロキシされているか | 物理的な Egress 場所                           | ソース IP と地理情報             |
| ------- | ---------------------------------------------------- | ---------------------------------------------- | -------------------------------- |
| IPv4    | Yes (Orange)                                         | ローカルに接続されたデータセンターから出ていく | Dedicated Egress IP の情報を使用 |
| IPv6    | No (Grey)                                            | ローカルに接続されたデータセンターから出ていく | Dedicated Egress IP の情報を使用 |
| IPv6    | Yes (Orange)                                         | ローカルに接続されたデータセンターから出ていく | Dedicated Egress IP の情報を使用 |

```mermaid:
---
title: No Egress Policy Match (IPv4 Orange Web Sites)
---
flowchart BT
    SU["Singapore Users"]-->|Anycast Routing|ZT2["ZT Services"]
    OU["Osaka Users"]-->|Anycast Routing|ZT3["ZT Services"]
    TU["Tokyo Users"]-->|Anycast Routing|ZT1["ZT Services"]
    subgraph Cloudflare
    subgraph Singapore PoP
    ZT2-->|Egresses</br>locally|RP2["Reverse Proxy"]
    DEIP2[Dedicated </br>Egress IP #2]-.->|Source IP</br>+ Geolocation|RP2
    end
    subgraph Osaka PoP
    ZT3-->|Egresses</br>locally|RP3["Reverse Proxy"]
    RP3
    end
    ZT3
    subgraph Tokyo PoP
    DEIP1[Dedicated </br>Egress IP #1]-.->|Source IP</br>+ Geolocation|RP3
    ZT1-->|Egresses</br>locally|RP1["Reverse Proxy"]
    DEIP1-.->|Source IP</br>+ Geolocation|RP1
    end
    end
    RP2-->|Origin Pull|WSS["IPv4 Orange Web Sites"]
    RP3-->|Origin Pull|WSS
    RP1-->|Origin Pull|WSS
```

また、一旦 Reverse Proxy サービスに入ってしまえば、[Smart Routing](https://developers.cloudflare.com/argo-smart-routing/) や [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) 機能により、PoP 同士の横のつながり Cloudflare Backbone Network を経由して、実際の Origin Pull PoP が変わることも考えられます。

# Egress ポリシー
Egress ポリシーを使って、条件にマッチした場合に特定の Egress 挙動をさせることが可能です。

- [Egress policies · Cloudflare Zero Trust docs](https://developers.cloudflare.com/cloudflare-one/policies/gateway/egress-policies/#value)

ポリシーは上から順番に評価され、最初にマッチしたものが実行されます。

> - [Order of enforcement · Cloudflare Zero Trust docs](https://developers.cloudflare.com/cloudflare-one/policies/gateway/order-of-enforcement/#order-of-precedence)
>Gatewayでは、優先順位は最初の一致の原則に従います - サイトがAllowまたはBlockポリシーに一致すると、評価は停止され、後続のポリシーは決定を上書きできません。したがって、最も具体的なポリシーと例外をリストの一番上に、最も一般的なポリシーを一番下に置くことをお勧めします。

Egress メソッドとしては、以下の2つを選べます。
> - **Default Cloudflare egress**
>    - すべてのZero Trustアカウントで共有されるデフォルトのソースIPレンジを使用します。ユーザーのトラフィックが最も近いCloudflareデータセンターから排出されるため、最もパフォーマンスの高いインターネット体験を保証します。
> - **Dedicated Cloudflare egress IPs**
>    - ドロップダウンメニューで選択されたプライマリIPv4アドレスとIPv6範囲を使用します。オプションで別のデータセンターのセカンダリIPv4アドレスを指定できます。プライマリデータセンターがダウンした場合、ゲートウェイはセカンダリデータセンターからイグジットし、リルート中のトラフィック低下を回避します。IPv6トラフィックはどのCloudflareデータセンターからもイグジットできるため、セカンダリIPv6は必要ありません。

例えば、以下のような設定が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/65c56309-0217-378b-5213-a41fdcaa7f52.png)

## IPv4 Grey Web Sites
宛先が IPv4 かつ Cloudflare によってプロキシされていない場合、以下の挙動になります。

| 宛先 IP | 宛先サイトが Cloudflare によってプロキシされているか | 物理的な Egress 場所                                         | ソース IP と地理情報             |
| ------- | ---------------------------------------------------- | ------------------------------------------------------------ | -------------------------------- |
| IPv4    | No (Grey)                                            | Dedicated Egress IP が紐づけられたデータセンターから出ていく | Dedicated Egress IP の情報を使用 |

```mermaid:
---
title: Egress Policy Matched (IPv4 Grey Web Sites)
---
flowchart BT
    SU["Singapore Users"]-->|Anycast Routing|ZT2["ZT Services"]
    OU["Osaka Users"]-->|Anycast Routing|ZT3["ZT Services"]
    TU["Tokyo Users"]-->|Anycast Routing|ZT1["ZT Services"]
    subgraph Cloudflare
    subgraph Singapore PoP
    ZT2-->EP2[Egress Policy]
    EP2-->|Primary|DEIP2[Dedicated</br>Egress IP #2]
    end
    subgraph Osaka PoP
    ZT3
    ZT3-->EP3[Egress Policy]
    end
    EP3-->|Primary|DEIP2
    subgraph Tokyo PoP
    ZT1-->EP1[Egress Policy]
    DEIP1[Dedicated</br>Egress IP #1]
    EP1-->DEIP2
    end
    EP2-.->DEIP1
    EP3-.->|Secondary|DEIP1
    EP1-.->|Secondary|DEIP1
    end
    DEIP2-->|Primary</br>Egress|WSS["IPv4 Grey Web Sites"]
    DEIP1-.->|Secondary</br>Egress|WSS
```

## IPv4 Orange Web Sites (IPv6 の場合も含む)

一方で、宛先が IPv4 かつ Cloudflare によってプロキシされている場合、以下の挙動になります。

（宛先が IPv6 のケースも同様の挙動となるため、省略します。）

| 宛先 IP | 宛先サイトが Cloudflare によってプロキシされているか | 物理的な Egress 場所                           | ソース IP と地理情報             |
| ------- | ---------------------------------------------------- | ---------------------------------------------- | -------------------------------- |
| IPv4    | Yes (Orange)                                         | ローカルに接続されたデータセンターから出ていく | Dedicated Egress IP の情報を使用 |
| IPv6    | No (Grey)                                            | ローカルに接続されたデータセンターから出ていく | Dedicated Egress IP の情報を使用 |
| IPv6    | Yes (Orange)                                         | ローカルに接続されたデータセンターから出ていく | Dedicated Egress IP の情報を使用 |

```mermaid:
---
title: Egress Policy Matched (IPv4 Orange Web Sites)
---
flowchart BT
    SU["Singapore Users"]-->|Anycast Routing|ZT2["ZT Services"]
    OU["Osaka Users"]-->|Anycast Routing|ZT3["ZT Services"]
    TU["Tokyo Users"]-->|Anycast Routing|ZT1["ZT Services"]
    subgraph Cloudflare
    subgraph Singapore PoP
    ZT2-->EP2[Egress</br>Policy]
    EP2-->|Egresses</br>locally|RP2["Reverse Proxy"]
    DEIP2[Dedicated</br>Egress IP #2]-->|Primary</br>Source IP</br>+ Geolocation|RP2
    end
    subgraph Osaka PoP
    ZT3-->EP3[Egress</br>Policy]
    EP3-->|Egresses</br>locally|RP3["Reverse Proxy"]
    RP3
    DEIP2[Dedicated</br>Egress IP #2]-->|Primary|RP3
    end
    ZT3
    subgraph Tokyo PoP
    DEIP1[Dedicated </br>Egress IP #1]-.->|Secondary|RP3
    ZT1-->EP1[Egress</br>Policy]
    DEIP2[Dedicated</br>Egress IP #2]-->RP1["Reverse Proxy"]
    DEIP1-.->|Secondary</br>Source IP</br>+ Geolocation|RP1
    DEIP1-.->RP2
    EP1-->|Egresses</br>locally|RP1["Reverse Proxy"]
    end
    end
    RP2-->|Origin Pull|WSS["IPv4 Orange Web Sites"]
    RP3-->|Origin Pull|WSS
    RP1-->|Origin Pull|WSS
```

## `catch-all` シナリオ

一般的なインターネット体験を確実にするには、リストの一番下に `catch-all` ポリシーを配置する設定が推奨されます。

Dedicated Egress IP を使う必要がない場合には、すべてのZero Trustアカウントで共有されるデフォルトの Egress IPレンジを使用して、ユーザーの接続元ソースIPの地理情報を維持する形で、近いCloudflareデータセンターから排出されるような設定です。

基本的には、ユーザが接続されたデータセンターからそのまま排出されることがほとんどですが、
例えば、ユーザの接続元ソースIPがメキシコで、ユーザがロサンゼルスに接続した場合には、共有 Egress IP プールの中でメキシコの地理情報を持つデータセンターから排出されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/cbdd2869-3b21-6dfa-e85a-ae0442b7a937.png)

```mermaid:
---
title: Catch-all Egress Policy Matched (IPv4 Grey/Orange Web Site)
---
flowchart BT
    AU2["Any Users"]-->|Anycast Routing|ZT2["ZT Services"]
    AU1["Any Users"]-->|Anycast Routing|ZT1["ZT Services"]
    subgraph Cloudflare
    subgraph Any PoP
    ZT2-->EP2[Egress</br>Policy</br>#catch-all]
    EP2-->|Egresses</br>locally|RP2["Reverse Proxy"]
    RP2
    SIP2["Default Cloudflare egress</br>(Shared IP Pool)"]
    end
    subgraph Any PoP
    ZT1-->EP1[Egress</br>Policy</br>#catch-all]
    EP1-->|Egresses</br>locally|RP1["Reverse Proxy"]
    RP1
    SIP1["Default Cloudflare egress</br>(Shared IP Pool)"]
    end
    EP1-->SIP2
    EP2-->SIP2
    EP1-->SIP1
    EP2-->SIP1
    end
    WS4G["IPv4 Grey</br>Web Sites"]
    SIP1-->|"Egress with respecting</br>user's source IP geo"|WS4G
    SIP2-->|"Egress with respecting</br>user's source IP geo"|WS4G
    RP1-->|Origin Pull|WS4O1["IPv4 Orange</br>Web Sites"]
    RP2-->|Origin Pull|WS4O2["IPv4 Orange</br>Web Sites"]
```

# Dedicated Egress IP ジオロケーション情報
以下のサイトで確認できます。

- [GeoIP2 Web Service Demo | MaxMind](https://www.maxmind.com/en/geoip2-precision-demo)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/f76d916d-8e53-2112-b542-ae9b85cd8cdc.png)

# ログ
Network Session Logs を Logpush することで確認できます。

- [Zero Trust Network Session Logs · Cloudflare Logs docs](https://developers.cloudflare.com/logs/reference/log-fields/account/zero_trust_network_sessions/)

例えば以下のログだと `"EgressRuleName": ""` マッチがなく
ユーザは大阪 PoP `"IngressColoName": "KIX"` に接続し
東京 PoP `"EgressColoName": "NRT"` から
`"EgressIP": "x.x.x.x"` を使って
`"OriginIP": "y.y.y.y"` に通信をおこなったことがわかります。

```json:zero_trust_network_sessions.json
{
  "AccountID": "xxx",
  "BytesReceived": 158443,
  "BytesSent": 214346,
  "ClientTCPHandshakeDurationMs": 0,
  "ClientTLSCipher": "",
  "ClientTLSHandshakeDurationMs": 0,
  "ClientTLSVersion": "none",
  "ConnectionCloseReason": "UNKNOWN",
  "ConnectionReuse": false,
  "DestinationTunnelID": "00000000-0000-0000-0000-000000000000",
  "DetectedProtocol": "",
  "DeviceID": "76e2f2a9-5da5-11ee-a515-deeb8ec3d15a",
  "DeviceName": "my-osaka-device",
  "EgressColoName": "NRT",
  "EgressIP": "x.x.x.x",
  "EgressPort": 48963,
  "EgressRuleID": "00000000-0000-0000-0000-000000000000",
  "EgressRuleName": "",
  "Email": "non_identity@xxx.cloudflareaccess.com",
  "IngressColoName": "KIX",
  "Offramp": "INTERNET",
  "OriginIP": "y.y.y.y",
  "OriginPort": 7844,
  "OriginTLSCertificateIssuer": "",
  "OriginTLSCertificateValidationResult": "NONE",
  "OriginTLSCipher": "",
  "OriginTLSHandshakeDurationMs": 0,
  "OriginTLSVersion": "none",
  "Protocol": "UDP",
  "RuleEvaluationDurationMs": 0,
  "SessionEndTime": 1695869611744000000,
  "SessionID": "1b7b315a7500000a7646525400000001",
  "SessionStartTime": 1695867748982000000,
  "SourceIP": "100.96.0.29",
  "SourceInternalIP": "",
  "SourcePort": 55395,
  "UserID": "b7761faf-27e6-4d08-a35a-802db584b739",
  "VirtualNetworkID": "604aa865-1642-405c-a745-3d448f69b8f1"
}
```

# まとめ

Dedicated Egress IP オプションを使えば、Cloudflare Zero Trust 全体としてパフォーマンスを最適化しつつ、固定 IP のニーズをシンプルなアーキテクチャで満たすことができることを確認できました。

アーキテクチャを複雑にしたくない場合は、ぜひ Enterprise プランもご検討ください。