Azure ネットワーク 通信ログのまとめ

Azure と接続する際にネットワークサービスの利用 (Virtual Netowrk, Public IP, ExpressRoute , NSG, WAF 等) は多くのシナリオで必須となりますが、様々なリソースでアクセスログ、通信ログを取得することができます。そこでどのリソースでどういったログが取得可能で、どう使い分けるべきかをまとめていきたいと思います。一応ログは取っているが、どういったときに使い分けたらいいかわからないといった際のヒントになれば幸いです。
この記事ではネットワークサービスについて記載しているため PaaS (WebApps, Storage, SQL Database 等) に直接インターネット経由でアクセスするケースは考慮しておりません。

## 通信ログ、アクセスログが取得可能な製品一覧
以下のような製品がありますが、どれも Azure への入り口または出口として利用しているケースが多いのではないかと思います。

- Azure Firewall
- Network Security Group
- Virutal Network ~~([2023/08/16 パブリックプレビュー](https://azure.microsoft.com/ja-jp/updates/public-preview-azure-vnet-flow-logs/)~~ [2024/04/24 GA 詳細はこちら](https://qiita.com/Isato-Hiyama/items/1830ed4e8921b57b4204))
- Application Gateway (WAF 含む)
- Bastion
- Azure Front Door (WAF 含む)
- Azure CDN (MS SKU のみ)　※ Verizon/Akamai でアクセスログは取得できません。

また、ExpressRoute の Traffic Collector はサンプリングで出力されるため、除外してます。

https://learn.microsoft.com/ja-jp/azure/expressroute/traffic-collector

## 通信ログ、アクセスログの取得ができない製品

よくご質問いただく代表的なものを記載します。

- ExpressRoute 回線
- 仮想ネットワーク ゲートウェイ (ER/VPN)
- Azure Load Balander
- NAT Gateway

上記の製品ではメトリックにてスループット等の通信の利用状況を確認することはできますが、送信元、宛先アドレスなど各トラフィックの詳細を確認するようなログは提供されておりません。

## ログの機能一覧
ネットワーク系の機能で取得可能な診断ログを比較した表です。診断ログまたはメトリックのどちらかで取得できる項目は 〇 としています。
単一の通信のサイズは "Bytes per traffic"、リソース単位でのスループットは "Throughput" 列で表現しています。

<table frame="box" border="1">
  <caption></caption>
    <tr>
        <td rowspan="2">リソース名</td>
        <td rowspan="2">Layer</td>
        <td colspan="6">ログの記録対象</td>
        <td rowspan="2">備考</td>
    </tr>
    <tr>
        <td>Src IP</td>
        <td>Src Port</td>
        <td>Dst IP/FQDN</td>
        <td>Dest Port</td>
        <td>Bytes per traffic</td>
        <td>Throughput</td>
    </tr>
    <tr>
        <td>Azure Load Balancer</td>
        <td>L4</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>メトリックのみ</td>
    </tr>
    <tr>
        <td>NAT Gateway</td>
        <td>L4</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>メトリックのみ</td>
    </tr>
    <tr>
        <td>Private Endpoint</td>
        <td>L4</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>メトリックのみ</td>
    </tr>
    <tr>
        <td>Azure DNS (Private DNS 含む)</td>
        <td>L4</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>クエリ数のメトリックのみ</td>
    </tr>
    <tr>
        <td>Private DNS Resolver</td>
        <td>L4</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>クエリ数のメトリックのみ</td>
    </tr>
    <tr>
        <td>仮想ネットワーク ゲートウェイ (ER/VPN)</td>
        <td>L4</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>メトリックのみ</td>
    </tr>
    <tr>
        <td>ExpressRoute 回線</td>
        <td>L4</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td>メトリックのみ</td>
    </tr>
    <tr>
        <td>NSG フローログ</td>
        <td>L4</td>
        <td>〇</td>
        <td>〇</td>
        <td>IP</td>
        <td>〇</td>
        <td>〇</td>
        <td>×</td>
        <td>非対応シナリオあり(詳細は後述)</td>
    </tr>
　　<tr>
        <td>VNet フローログ</td>
        <td>L4</td>
        <td>〇</td>
        <td>〇</td>
        <td>IP</td>
        <td>〇</td>
        <td>〇</td>
        <td>×</td>
        <td></td>
    </tr>
    <tr>
        <td >NSG フローログ Traffic 分析</td>
        <td>L4</td>
        <td>〇</td>
        <td>x</td>
        <td>IP</td>
        <td>〇</td>
        <td>〇</td>
        <td>〇</td>
        <td>非対応シナリオあり(詳細は後述)</td>
    </tr>
    <tr>
        <td >VNet フローログ Traffic 分析</td>
        <td>L4</td>
        <td>〇</td>
        <td>x</td>
        <td>IP</td>
        <td>〇</td>
        <td>〇</td>
        <td>〇</td>
        <td></td>
    </tr>
    <tr>
        <td> DDoS Standard</td>
        <td>L4</td>
        <td>〇</td>
        <td>〇</td>
        <td>IP</td>
        <td>〇</td>
        <td>〇</td>
        <td>×</td>
        <td>攻撃中のトラフィックが対象</td>
    </tr>
    <tr>
        <td> Bastion </td>
        <td>L4</td>
        <td>〇</td>
        <td>〇</td>
        <td>IP</td>
        <td>〇</td>
        <td>×</td>
        <td>×</td>
        <td></td>
    </tr>
    <tr>
        <td>Azure Firewall DNAT Rule</td>
        <td>L4</td>
        <td>〇</td>
        <td>〇</td>
        <td>IP</td>
        <td>〇</td>
        <td>×</td>
        <td>〇</td>
        <td>ルール種別ごとのスループットは確認不可</td>
    </tr>
    <tr>
        <td>Azure Firewall Network Rule</td>
        <td>L4</td>
        <td>〇</td>
        <td>〇</td>
        <td>IP</td>
        <td>〇</td>
        <td>×</td>
        <td>〇</td>
        <td>ルール種別ごとのスループットは確認不可</td>
    </tr>
    <tr>
        <td>Azure Firewall Application Rule</td>
        <td>L7</td>
        <td>〇</td>
        <td>〇</td>
        <td>FQDN</td>
        <td>〇</td>
        <td>×</td>
        <td>〇</td>
        <td>ルール種別ごとのスループットは確認不可</td>
    </tr>
    <tr>
        <td> Application Gateway </td>
        <td>L7</td>
        <td>〇</td>
        <td>〇</td>
        <td>FQDN or IP</td>
        <td>〇</td>
        <td>〇</td>
        <td>〇</td>
        <td></td>
    </tr>
    <tr>
        <td> Application Gateway WAF</td>
        <td>L7</td>
        <td>〇</td>
        <td>〇</td>
        <td>FQDN or IP</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td></td>
    </tr>
    <tr>
        <td> Azure Front Door </td>
        <td>L7</td>
        <td>〇</td>
        <td>〇</td>
        <td>FQDN</td>
        <td>〇</td>
        <td>〇</td>
        <td>〇</td>
        <td></td>
    </tr>
    <tr>
        <td> Azure Front Door WAF</td>
        <td>L7</td>
        <td>〇</td>
        <td>〇</td>
        <td>FQDN</td>
        <td>×</td>
        <td>×</td>
        <td>〇</td>
        <td></td>
    </tr>
    <tr>
        <td> Azure CDN (MS)</td>
        <td>L7</td>
        <td>〇</td>
        <td>〇</td>
        <td>FQDN</td>
        <td>〇</td>
        <td>〇</td>
        <td>×</td>
        <td></td>
    </tr>
</table>

各ログで取得できる情報をまとめた結果、言えることとして、Hub&Spoke のような構成において、~~**送信元、宛先の情報と共に送受信データのサイズ情報も一元的に取得できる機能がありません。**~~ <font color="Red">VNet フローログを利用することで送信元、宛先の情報と共に送受信データのサイズ情報も一元的取得できます。</front>

例えば以下のようなトラフィックパターンにおいて、Azure Firewall の診断ログにて送信元、宛先の情報を一元管理できますが、データサイズも取得する場合、NSG/VNet のフローログや各リソースのログの取得を行う必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/f40b4d92-39ca-b4f3-bbf4-b5e7b18505a2.png)



## シナリオに応じたログ取得
様々なケースで通信ログを取得しておきたいといった要件があると思いますが、どのような方法があるかを以下にまとめてみました。
前提としてはそれなりの規模の環境かつ以下の様な Hub&Spoke の構成を対象としています。

#### North-South (Inbound)

- Web traffic については Front Door (Global) や Application Gateway (Regional) でログ取得
- VM への接続 (SSH, RDP) は Bastion でログ取得
- その他の通信は Azure Firewall でログ取得
- DDoS に対する 攻撃分析、アラート対応、コスト補償等が必要である場合、DDoS Protection を検討
- トラフィックサイズのログも取得したい場合、以下のどちらかで対応可能かを確認
    - NSG/VNet フローログ
    - 各種リソースの診断ログのアクセスログ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/de7ea0ed-420b-99d5-b7e1-fc612f8b81a8.png)


#### North-South (Outbound)

- Azure Firewall でログ取得
- トラフィックサイズも取得したい場合、NSG/VNet フローログを検討

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/a1b0f7b4-050d-5d02-1ab6-da2b94052cde.png)

#### East-West

- Azure Firewall でログ取得
- Azure Firewall を経由しない通信については Application Gateway や NSG/VNet フローログを検討
- トラフィックサイズも取得したい場合、NSG/VNet フローログまたはリソースの診断ログ取得を検討

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/f40b4d92-39ca-b4f3-bbf4-b5e7b18505a2.png)


## 各リソースのログについて

### NSG フローログ、Trrafic 分析
NSG フローログは NSG のルールで評価されたトラフィックの詳細をログとして出力する機能です。送信元、宛先の情報に加えて、対象トラフィックのパケットのバイト数も取得ができます。

#### 制限事項

- ユーザーが追加した NSG ルールではログがパケットサイズが出力されない可能性があり。詳細は後述。
- Private Endpoint の通信はサポートされていない
- 以下のようないくつかのリソースはサポートされていない ([Link](https://learn.microsoft.com/ja-jp/azure/network-watcher/network-watcher-nsg-flow-logging-overview#network-security-group-on-an-expressroute-gateway-subnet))
    - Application Gateway
    - Bastion
    - Azure Firewall (サブネットに NSG の適用がサポートされてない)
    - 仮想ネットワークゲートウェイ (サブネットに NSG の適用がサポートされてない)
    - Azure Container Instances
    - Azure Logic Apps
    - Azure Functions
    - Azure DNS Private Resolver
    - App Service
    - Azure Database for MariaDB
    - Azure Database for MySQL
    - Azure Database for PostgreSQL

#### ユーザー定義の NSG ルールのフローログについて

[ユーザー定義の受信 TCP 規則](https://learn.microsoft.com/ja-jp/azure/network-watcher/network-watcher-nsg-flow-logging-overview#user-defined-inbound-tcp-rules) に記載があるように、ユーザーが追加した受信ルールではバイト数、パケット数が記載されない可能性があります。

:::note info
ユーザー定義の受信規則が影響を与えるフローは、終了しないフローになります。 また、これらのフローのバイト数やパケット数は記録されません。 これらの要因により、NSG フローログ (および Network Watcher トラフィック分析) で報告されるバイト数とパケット数は、実際の数とは異なる可能性があります。
:::

どういった動作になるかというと、以下の様に通信した際のログ自体は記録がありますが、パケット数、バイト数が 0 となります。

**トラフィック分析用のログ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/e1762db5-33c3-820d-b99e-9104532bfd09.png)

フローログにも、以下の様に記録自体はありますが、Flow State が **B** (Begin) で、パケット数、サイズがないログのみが出力されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/b084d84e-ba0c-e930-de52-04fdd27fa82b.png)

この動作に対応するためには仮想ネットワークのプロパティ `FlowTimeoutInMinutes` を明示的に 4-30 (分) に設定する必要があります。この設定は NSG 等のリソースで無通信状態の時にどのくらい通信 (フロー) を保持しておくかの設定となります。既定値は 4 分となりますので、4 分以上の無通信状態の時に該当の通信が切断される可能性があります。

`FlowTimeoutInMinutes` の設定方法は、以下の様に仮想ネットワークの "概要" -> "フローのタイムアウト" -> "フローのタイムアウトを有効にする" から設定することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/df1bc23a-fcf9-8aec-7fe5-0a2524ff0324.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/7afa6edf-7573-9bed-f92a-3a6b688daea0.png)

### VNet フローログ、Trrafic 分析
[詳細はこちら](https://qiita.com/Isato-Hiyama/items/1830ed4e8921b57b4204)

### Bastion

Bastion を利用することで、以下のような情報のログを取得することができます。

| 項目 | 内容 | 備考 |
|-|-|-|
| Time  | 接続日時 ||
| UserName | OS のログインユーザー | ネイティブクライアントの場合、出力なし |
| ClientIpAddress | クライアント端末の IP ||
| UserEmail | Bastion を利用した Microsoft Entra ID ユーザー ||
| TargetResourceId | 接続先 VM のリソース ID ||
| Message | ログイン成功または失敗 ||


https://learn.microsoft.com/ja-jp/azure/bastion/diagnostic-logs#view

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/2859eb3f-54e2-30b0-1063-7b0689e8a792.png)

### Azure Firewall
各通信の送信元、宛先の IP アドレス、ポート、拒否・許可等の情報が取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/1d87020e-4fa5-4d74-8df8-7e5759c534db.png)

Azure Firewall の診断ログ AZFWFatFlow というテーブルにて帯域消費レートの情報をとれる機能がプレビューでありますが、Azure Firewall インスタンスの CPU 使用率があがるため、主にトラブルシューティングのみで有効化することが推奨されています。

https://learn.microsoft.com/ja-jp/azure/firewall/enable-top-ten-and-flow-trace

また、今まで Azure Firewall のログは AzureDiagnostics テーブルに出力されておりましたが、現在は構造化されたリソース固有のテーブルによるログ取得もサポートされております。

https://learn.microsoft.com/ja-jp/azure/firewall/firewall-structured-logs#resource-specific-mode

以下のようなメリットがありますので、これから作成される環境ではリソース固有のテーブルによるログ取得もご検討ください。

:::note info
次の理由により、この方法をお勧めします。

- ログ クエリ内のデータの操作がはるかに容易になる
- スキーマとその構造の検出が容易になる
- インジェストの待ち時間とクエリ時間の両方でパフォーマンスが向上する
- 特定のテーブルに対する Azure RBAC 権限を付与できる
:::

以下は各ルールのログ出力の違いですが、主に異なる点は Azure Diagnostics テーブルでは通信の詳細がすべて、msg_s の中にまとめられておりましたが、リソース固有テーブルでは Policy, RuleCollection, Rule 等がすべて別の列として出力されております。そのためクエリの操作も容易になります。

**Nat Rule (AzureDiagnostics/AZFWNatRule)**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/79f3a766-60d1-c685-5152-956e2f8cac73.png)

**Network Rule (AzureDiagnostics/AZFWNetworkRule)**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/b9381c30-2b6a-c6c9-0f9f-5398cd09752e.png)

**Application Rule (AzureDiagnostics/AZFWApplicationRule)**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/567c723d-df61-09b1-1ece-a4d9b8b206b6.png)

### Application Gateway

ApplicationGateway V2 のアクセスログでは以下のような情報が取れます。(主な項目のみ抜粋)

| 項目 | 内容 | 備考 |
|-|-|-|
| clientIP_s  | クライアント端末の IP||
| receivedBytes_d | クライアントから受信したパケットのサイズ  (バイト単位) | |
| sentBytes_d | クライアントへ送信したパケットのサイズ  (バイト単位) ||
| timeTaken_d | クライアントへ応答が返るまでの時間 | TimeGenerated は timeTaken の時間も含まれているため注意が必要|
| httpStatus | Application Gateway が返した Status コード ||
| WAFPolicyID_s | WAP Policy のリソース ID ||
| WAFEvaluationTime_s | WAF の処理時間 ||
| WAFMode_s | Detection または Prevention モード ||
| serverRouted_s | 振り分けられたバックエンドサーバー ||
| serverStatus_s | バックエンドが返した Status コード ||
| serverResponseLatency_s | バックエンドからの応答時間 | timeTaken_d と比較することで AppGW, バックエンドどちらで時間がかかってるか見当がつく |
| upstreamSourcePort_s | AppGW 側のソースポート ||
| transactionId_g | リクストの一意識別子 | HTTP ヘッダーにも X-AppGW-Trace-Id として付与される |

https://learn.microsoft.com/ja-jp/azure/application-gateway/application-gateway-diagnostics#for-application-gateway-and-waf-v2-sku

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/2d5c5b3b-5e39-96ec-790a-d92fda019fa9.png)

### Azure Front Door

Azure Front Door のアクセスログでは以下のような情報が取れます。(主な項目のみ抜粋)

| 項目 | 内容 | 備考 |
|-|-|-|
| ClientIp_s  | クライアント端末の IP| X-Forwarded-For がある場合、その値になります|
| SocketIp_s  | Azure Front Door エッジへ接続した IP アドレス||
| RequestBytes_s | HTTP Request のサイズ (バイト単位)| |
| ResponseBytes_s | HTTP Response のサイズ  (バイト単位) ||
| timeTaken_d | クライアントへ応答が返るまでの時間 (応答の最後のバイトを送るまで) | TimeGenerated は timeTaken の時間も含まれているため注意が必要|
| timeToFirstByte_s | クライアントへ応答の最初のバイトが返るまでの時間 | |
| OriginIP_s | リクエストを転送した配信元の IP アドレス ||
| httpStatusCode_s | FrontDoor が返した HTTP の Status コード ||


https://learn.microsoft.com/ja-jp/azure/frontdoor/front-door-diagnostics?pivots=front-door-standard-premium#access-log

以下はアクセスログのサンプルです。X-Forwarded-For を意図的に設定したため、clientIp_s と socketIp_s が異なる IP アドレスになってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2266293/1306debf-d78e-c899-2f62-adf3eabc8f5c.png)

### Azure CDN (MS SKU)

Azure CDN (MS) のアクセスログでは以下のような情報が取れます。(主な項目のみ抜粋)
その他の SKU (Verizon, Akamai) ではこの粒度でアクセスログを取得する機能はありません。

| 項目 | 内容 | 備考 |
|-|-|-|
| ClientIp  | クライアント端末の IP| X-Forwarded-For がある場合、その値になります|
| RequestBytes | HTTP Request のサイズ (バイト単位)| |
| ResponseBytes | HTTP Response のサイズ  (バイト単位) ||
| timeTaken | クライアントへ応答が返るまでの時間 (応答の最後のバイトを送るまで) | TimeGenerated は timeTaken の時間も含まれているため注意が必要|
| timeToFirstByte | クライアントへ応答の最初のバイトが返るまでの時間 | |
| httpStatusCode_s | CDN が返した HTTP の Status コード ||


https://learn.microsoft.com/ja-jp/azure/cdn/monitoring-and-access-log#raw-logs-properties

### DDoS Protection

DDoS Protction を利用することで攻撃中に削除されたトラフィック、転送されたトラフィックの詳細をほぼリアルタイムで確認することができます。

https://learn.microsoft.com/ja-jp/azure/ddos-protection/ddos-view-diagnostic-logs#ddos-mitigation-flowlogs

DDoS の軽減フローログでは以下のような情報が確認できます。(主な項目のみ抜粋)

| 項目 | 内容 | 備考 |
|-|-|-|
| SourcePublicIpAddress  | クライアントの IP | |
| DestPublicIpAddress | 宛先の パブリック IP | |
| Message | 攻撃、トラフィックの詳細 ||
| Protocol | プロトコル ||