WVD用にAzure Firewallを設定し、インターネットアクセスを制御する

Windows Virtual Desktop (WVD)のセッションホストから、許可されたサービスにのみ接続させる、またネットワークレベルで許可/拒否されたログを取る方法です。
下記のようなシンプルな構成で進めます。赤囲みしたコンポーネント以外のWVD環境はあるものとして進めます。(つまり、既存のWVD環境に後付けできます)
![Diagram1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/da68cdaa-0487-8da5-d49f-b80dfb1da2a2.png)

# 要件
- ホストプール内のセッションホスト(仮想デスクトップ)からのインターネットアクセスを制御したい
- 既定ではすべてのアクセスを禁止したい
- 許可されたサービスにのみ接続させたい
- ファイアウォールに来た通信は許可/拒否ともにログを取っておく

# Azure Firewallの設定
## ルールの設定
「[Windows Virtual Desktop へのホスト プールの送信アクセス](https://docs.microsoft.com/ja-jp/azure/firewall/protect-windows-virtual-desktop#host-pool-outbound-access-to-windows-virtual-desktop)」に従って設定します。
### アプリケーションルール
上のドキュメントに加え、以下の4つを追加します。

- FQDNタグ
 - `WindowsDiagnostics`
 - `WindowsUpdate`

- ターゲットのFQDN
 - `*xt.queue.core.windows.net`への`https`
 - `*.ingest.monitor.core.windows.net`への`https`

アプリケーションルールは最終的には下記のようになります。
![rule-wvd1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/a9a2faf2-9f9c-1a5f-a918-143fdfbcddaf.png)

### ネットワークルール
KMSのルールを追加します。
ネットワークルールは最終的には下記のようになります。
![rule-wvd2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/f8796556-5d99-772e-7b18-645620cdd027.png)
DNSは今回Firewallを通らずに、ルーティングテーブルで直送するため、ここでは記述していません。DNSがFirewallを通る環境では記述する必要があります。

> **参考**
>
> - [WVDで開けるべきURLリスト](https://docs.microsoft.com/ja-jp/azure/virtual-desktop/safe-url-list)

## ログの設定
![fw-log1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/a756e0d2-e978-ff8a-97f0-6b056eec44ae.png)

# ルーティングテーブルの設定
## ルートの作成
AD(DNS)など自分の管理下にあるサービスへは直接ルーティングし、それ以外はすべてAzure Firewall (仮想アプライアンスという扱いになります)にルーティングする設定を行います。

- 環境の例

| 名前 | ルーティング先 |
|:-:|:-:|
| default | Azure Firewallへのデフォルトルート |
| mgmt | AD DC (DNS) があるVNet |

![route1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/c709c5d7-2a15-172f-1c3b-647f7d76b05b.png)

## サブネットへの割り当て
ホストプールのあるサブネットに関連付けます。ホストプール以外のサブネットには関連付けません。
下記の例はhostという名前がついたサブネットがホストプールのあるサブネットになっています。NSGがあってもかまいません。
![route2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/43dab19f-d7f3-5597-da19-1396653cc71a.png)

# 動作確認
## セッションホストの再起動
ルーティングテーブルを設定するため、セッションホストを再起動します。
## WVDログイン
WVDのセッションホストにログインし、Edgeなどブラウザでどこかにアクセスして、つながらないことを確認します。
## ログの確認
拒否したログを確認してみます。

```
AzureDiagnostics
| where Category == "AzureFirewallApplicationRule"
| search "Deny"
| parse msg_s with Protocol " request from " SourceIP ":" SourcePort:int " to " FQDN ":" *
| project TimeGenerated,Protocol,FQDN
```
下記のような表示がされると思います。(環境によって違います)
![log1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/191006e6-c030-b825-6f28-be05d769940d.png)

ここまでで、インターネットに出られない環境ができました。
# Azure Monitorをファイアウォールで通す (オプション)
[Azure Monitor for WVD](https://docs.microsoft.com/ja-jp/azure/virtual-desktop/azure-monitor)を利用している場合は、セッションホストのエージェントからログをLog Analyticsのワークスペースに書き出せるようにする必要があります。ログは、ネットワーク通信で行われ、[ファイアウォールの要件](https://docs.microsoft.com/ja-jp/azure/azure-monitor/platform/log-analytics-agent#firewall-requirements)が定義されています。
これに従い、Azure Firewallのアプリケーションルールを定義します。
![rule-monitor1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/d79ad463-c3d2-6d34-0a63-77b757841967.png)

# Office 365をファイアウォールで通す
[Office 365 URL および IP アドレス範囲](https://docs.microsoft.com/ja-jp/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide)が公開されていますので、これに従ってルールを設定します。
[Microsoft 365 Common および Office Online](https://docs.microsoft.com/ja-jp/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide#microsoft-365-common-and-office-online)はすべての基礎になるものなので、これを設定し、必要なアプリケーションを足していきます。
例えばTeamsの場合は、このようにしてもよいでしょう。
![rule-office1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/3aa86ded-f3d9-d950-c755-e4244a2d872b.png)

# アプリケーションサイトを通す
例えばGoogleを通す場合は下記のようにします。(実際には、関連サイトなどを登録する必要があります)
![rule-google2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/15993a35-5919-dfca-e782-4e2d85859229.png)
![rule-google1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684720/67e9a8d0-0ebb-8cc4-0981-c60eaeffd8db.png)

# 留意点
- 実環境で必要なサービスへの許可ルール設定
ここではシンプルな構成で解説しましたので、実際の環境では足らないこともあると思います。例えばWVDのベース機能で見ても、FSLogixのプロファイル置き場に対して許可ルールを設定しないといけないことがあると思います。
事前にわかっていることは初めから設定できますが、それ以外はAzure FirewallでDenyしたパケットのログを見ながら通していくとよいでしょう。

- [RDP Shortpath](https://docs.microsoft.com/ja-jp/azure/virtual-desktop/shortpath)が使えない (今のところ)
「[RDP Shortpath の接続シーケンス](https://docs.microsoft.com/ja-jp/azure/virtual-desktop/shortpath#rdp-shortpath-connection-sequence)」や「[Azure VM の外部接続 (SNAT) オプション まとめ](https://jpaztech.github.io/blog/network/snat-options-for-azure-vm/)」を合わせて考えると、下記のようになってつながらないものと思われます。
    1. セッションホストにより、プライベートおよびパブリックの IPv4 と IPv6 のアドレスの一覧をペイロードに載せてクライアントに送信 (アドレスは変換されない)
    2. クライアントでは、バックグラウンド スレッドが開始され、提供されたホストの IP アドレスの 1 つに対して、UDP ベースの並列トランスポートを直接確立しようと試行 (クライアント -> ホスト)
    3. セッションホストではクライアントからのUDPパケットを受領
    4. セッションホストからクライアントに対してUDPパケットを送信
    5. ルーティングテーブルに従ってAzure Firewallにルーティング
    6. Azure FirewallでSNATがかかり、送信元アドレスが変更される
    7. クライアント(もしくは中間のNATルーター)では未知のアドレスからのUDP 3390が届くので破棄

# 参考

- [Azure Firewall ブックを使用してログを監視する](https://docs.microsoft.com/ja-jp/azure/firewall/firewall-workbook)
- [Azure FirewallにOffice 365のルールを自動設定してみた](https://www.softbank.jp/biz/future_stride/entry/techblog/202001209/)
- [【Windows Virtual Desktopのディープな技術情報を解説】 #2 WVDにおけるネットワークセキュリティ](https://zine.qiita.com/products/202010-wvd-2/)