AzureでNSGフローログを作成してログを解析してみました。
今回やること
構成図のようにリソースを作成して、以下の3点を見ていきます。
環境の構築は以下の「[参考] 今回の環境をAzureCLIで作成」でAzureCLIを利用して作成しているので参考にしてみてください。
NSGフローログを作成
・フローログを有効化したいNSGの画面に移動して [NSGフローログ]>[作成] をクリックします。
・[基本] のタブでフローログ名などを入力していきます。
ストレージアカウントが無い場合には新規作成してください。
また、「リテンション期間」は今回は検証なので最小値の1を設定します。
リテンション期間の設定値は0~365まで設定することができ、0を設定した場合は永続的にログを保持し続けます。
・[分析] のタブではフローログのバージョンなどを選択します。
今回は検証ということで Traffic Analytics も有効にしてみます。
有効にしたい場合には事前にログアナリティクスの作成が必要となります。
「TrafficAnalyticsの処理間隔」の設定値は1時間か10分かの2択なので、今回は10分間隔でログを見ていきたいと思います。
この設定でフローログを作成します。
1.VM-VM間の通信のログを見る
フローログはストレージアカウントとログアナリティスクに格納されているので今回はログアナリティクスで確認していきます。
ログアナリティスクで以下のKQLを実行することでログを確認できます。
AzureNetworkAnalytics_CL
今回はクライアント用VMからWeb用VMに対してweb通信を発生させてから確認します。
※実際の通信が発生してからログが連携されるまで少し時間がかかります。
ログとしては以下のように出力されました。
TenantId | ————————— |
SourceSystem | Azure |
TimeGenerated [ローカル時刻] | 2024/9/19 15:16 |
FASchemaVersion_s | 2 |
FlowIntervalStartTime_t [ローカル時刻] | 2024/9/19 15:00 |
FlowIntervalEndTime_t [ローカル時刻] | 2024/9/19 15:10 |
FlowStartTime_t [ローカル時刻] | 2024/9/19 14:59 |
FlowEndTime_t [ローカル時刻] | 2024/9/19 14:59 |
FlowType_s | IntraVNet |
SrcIP_s | 10.8.0.4 |
DestIP_s | 10.8.0.68 |
DestPort_d | 80 |
L4Protocol_s | T |
L7Protocol_s | http |
FlowDirection_s | I |
IsFlowCapturedAtUDRHop_b | FALSE |
FlowStatus_s | A |
NSGList_s | —————————/rg-test-nsgflow/nsg-test-web |
NSGRules_s | 0|allowvnetinbound|I|A|0 |
NSGRule_s | allowvnetinbound |
NSGRuleType_s | Default |
Subscription1_g | ————————— |
Subscription2_g | ————————— |
Region1_s | japaneast |
Region2_s | japaneast |
NIC1_s | rg-test-nsgflow/nic-vm-test-client |
NIC2_s | rg-test-nsgflow/nic-vm-test-web |
VM1_s | rg-test-nsgflow/vm-test-client |
VM2_s | rg-test-nsgflow/vm-test-web |
AllowedInFlows_d | 0 |
DeniedInFlows_d | 0 |
AllowedOutFlows_d | 0 |
DeniedOutFlows_d | 0 |
FlowCount_d | 0 |
InboundPackets_d | 0 |
OutboundPackets_d | 10 |
InboundBytes_d | 0 |
OutboundBytes_d | 1120 |
CompletedFlows_d | 2 |
MACAddress_s | 7C-1E-52-23-B8-1E |
Subnet1_s | rg-test-nsgflow/vnet-test-nsgflow/subnet-client |
Subnet2_s | rg-test-nsgflow/vnet-test-nsgflow/subnet-web |
Region_s | japaneast |
SubType_s | FlowLog |
Subscription_g | ————————— |
TimeProcessed_t [ローカル時刻] | 2024/9/19 15:16 |
Type | AzureNetworkAnalytics_CL |
ログの中身を見ていきます。
通信内容を確認
FlowType_s からVnet間の通信であることが分かり、送信元は SrcIP_s から10.8.0.4、宛先はDestIP_s から10.8.0.68であることが分かります。
また、L4Protocol_s と L7Protocol_s と DestPort_d からTCPのhttp:80の通信であることも分かります。
[参考] FlowType_sの種類
インターネットからの通信の場合には「AzurePublic」「ExternalPublic」「MaliciousFlow」が表示されます。
それぞれの種類の詳細についてはMicrosoft公式ドキュメントの記載を参照ください。
AllowかDenyかの確認
FlowStatus_s が A なので、通信は許可(Allow)されていることが分かります。
D だと通信拒否(Deny)となります。
また、NSGRules_s でも確認が可能です。
[参考] NSGRules_s の見方
0|allowvnetinbound|I|A|0
右から2番目の項目が A となっていればAllow、D となっていればDenyです。
また、その隣の I はInbound(=受信規則)を示していて、Outboundルールの場合には O が入ります。
左から2番目の項目には NSGRule_s と同じNSGルール名が入っています。
対象のNSGルールを確認
上述の通り NSGRules_s もしくは NSGRule_s でallowvnetinboundであることが分かります。
通信された時間を確認
実際の通信の時間は FlowStartTime_t や FlowEndTime_t で分かります。
似たような項目に、FlowIntervalStartTime_t と FlowIntervalEndTime_t がありますが、これらはフローログの取得間隔を示しており、今回フローログ作成時に10分間隔を選択したのでこれらの値が10分間隔となっています。
FlowIntervalStartTime_t [ローカル時刻] | 2024/9/19 15:00 |
FlowIntervalEndTime_t [ローカル時刻] | 2024/9/19 15:10 |
FlowStartTime_t [ローカル時刻] | 2024/9/19 14:59 |
FlowEndTime_t [ローカル時刻] | 2024/9/19 14:59 |
1時間間隔を設定すると1時間単位でログが出力されます。
この場合ログアナリティクスに連携されるのも1時間毎となるのでこの点は少し注意が必要です。
10分間隔と1時間間隔の設定変更はいつでも可能
10分間隔と1時間間隔の設定変更はNSGフローログのリソースからいつでも変更可能です。
2.インターネットからVMに対するログを見る
フローログを有効化するとわかると思いますが、仮想マシンは常に攻撃されており、パブリックIPを仮想マシンに付与するだけで不特定多数の様々な送信元からいろんなポートで通信が来ていることが分かります。
そのうちの1つを取り出して見てみます。
TenantId | ————————— |
SourceSystem | Azure |
TimeGenerated [ローカル時刻] | 2024/9/19 15:53 |
FASchemaVersion_s | 2 |
FlowIntervalStartTime_t [ローカル時刻] | 2024/9/19 15:40 |
FlowIntervalEndTime_t [ローカル時刻] | 2024/9/19 15:50 |
FlowStartTime_t [ローカル時刻] | 2024/9/19 15:49 |
FlowEndTime_t [ローカル時刻] | 2024/9/19 15:49 |
FlowType_s | ExternalPublic |
DestIP_s | 10.8.0.68 |
VMIP_s | 10.8.0.68 |
DestPort_d | 23 |
L4Protocol_s | T |
L7Protocol_s | telnet |
FlowDirection_s | I |
IsFlowCapturedAtUDRHop_b | FALSE |
FlowStatus_s | D |
NSGList_s | —————————/rg-test-nsgflow/nsg-test-web |
NSGRules_s | 0|denyallinbound|I|D|1 |
NSGRule_s | denyallinbound |
NSGRuleType_s | Default |
Subscription2_g | ————————— |
Region2_s | japaneast |
NIC_s | rg-test-nsgflow/nic-vm-test-web |
NIC2_s | rg-test-nsgflow/nic-vm-test-web |
VM_s | rg-test-nsgflow/vm-test-web |
VM2_s | rg-test-nsgflow/vm-test-web |
Subnet_s | rg-test-nsgflow/vnet-test-nsgflow/subnet-web |
Country_s | cn |
AllowedInFlows_d | 0 |
DeniedInFlows_d | 1 |
AllowedOutFlows_d | 0 |
DeniedOutFlows_d | 0 |
FlowCount_d | 1 |
InboundPackets_d | 0 |
OutboundPackets_d | 0 |
InboundBytes_d | 0 |
OutboundBytes_d | 0 |
CompletedFlows_d | 0 |
PublicIPs_s | 113.4.137.244|1|0|0|0|0|0 |
SrcPublicIPs_s | 113.4.137.244|1|0|0|0|0|0 |
MACAddress_s | 7C-1E-52-23-B8-1E |
Subnet2_s | rg-test-nsgflow/vnet-test-nsgflow/subnet-web |
Region_s | japaneast |
SubType_s | FlowLog |
Subscription_g | ————————— |
TimeProcessed_t [ローカル時刻] | 2024/9/19 15:53 |
Type | AzureNetworkAnalytics_CL |
上記のログでは SrcPublicIPs_s より送信元が113.4.137.244であること、DestPort_d、L7Protocol_s よりポート23のtelnetでアクセスしていることが分かります。
この他のアクセスのポートとしては 62078、5180、113 などがあり、そして 3389 のアクセス試行もありました。
また、プロトコルも EtherNet-IP-1や amberon、blackjack など聞きなじみのないプロトコルが利用されていました。
パブリックIPをリソースに付与する際には、Azureリソースは常に攻撃されているという意識をもって取り扱っていくことが大切だということが今回の検証からも分かります。
3.Traffic Analyticsで可視化されたログを見る
Traffic Analyticsを確認する際には「Network Watcher」のリソースから確認します。
検索BOXで Network Watcher と検索してリソースを表示し [トラフィック分析] を開きます。
赤枠で囲ったリソースの指定では、Traffic Analyticsと関係ない別のリソースが選択されていることがあるので、Traffic Analyticsを有効にしたログアナリティクスを選択するようにしてください。
また、最新の情報が反映されるまで時間がかかります。
検証した際には3.5時間前のログの情報までしか表示されていませんでした。
トラフィックの視覚化
トラフィックの視覚化ではTraffic Analyticsを有効化したNSGにおけるフロー数、バイト数、パケット数などのサマリを確認することができます。
サブネット単位でシステムを分けている場合に、どのシステムにどれだけ通信量が流れているかなどを確認する際には効果的です。
ただ、当たり前ですがTraffic Analyticsが有効化されていないリソースに関する情報は出力されません。
環境
ここではリソースに関する情報が記載されます。
個人的に重要だと思ったのは右上の「TAが有効なNSG」の項目で、ここで保有している環境の中でTraffic Analyticsが有効になっていないリソースを確認することができます。
キャプチャで「1/4」となっている部分をクリックすると詳細情報のクエリが実行されログで見ることができます。
以下のように[IsFlowEnabled]がfalseになっているNSGがTraffic Analyticsが有効化されていないNSGとなります。
トラフィックの分布
トラフィックの分布ではIPやサブネット、Vnetの単位における合計フロー数、バイト数、パケット数を見ることができます。
フロー数、バイト数、パケット数のどの値を表示するかは上記「トラフィックの視覚化」でのプルダウンで選択できます。
今回はNSGフローログを有効化したサブネットにvm-test-webという仮想マシンしか所属していないので、この仮想マシンの情報のみが「IP」という項目で確認することができます。
NSG ヒット
NSGヒットではその名の通り、NSGにヒットした数を見ることができますが、特に一番右の「上位のルール」を見るとNSGルールのヒット数上位20件を確認することができます。
ただ、個人的には効果的な使い方が分からなかった項目でした。
アプリケーション ポート
アプリケーションポートではポートやプロトコルの分析ができます。
今回は「ブロックされたトラフィック」を見ていますが、telnetが4件あり、送信元もポーランドや韓国、ウクライナなど海外からの通信であることが分かります。
画面の「すべて表示」をクリックするとより詳細な情報が見れます。
グラフで各時間ごとのポートごとのアクセス件数を確認でき、下部ではそのグラフの合計値などが確認できます。
telnetの通信などは悪意しかないと思うのですが、テーブルを見るとこのTraffic Analyticsではその通信全てが「悪意のある通信」とは見なしていないようなので、「悪意のある通信」の仕分けについてはこの機能を信頼しない方がいいのかなと思いました。
ネットワーク アプリケーション リソース
今回はVPNゲートウェイやExpressRouteやロードバランサーなどを利用していないため何も表示されていません。
もしそれらのリソースを利用した場合には、リソースにおけるトラフィックの情報が表示されるかと思います。
[参考] 今回の環境をAzureCLIで作成
NAGフローログ以外のリソースを以下のCLIで構築します。
#任意のパラメータを定義
$rg_name = "RG-Test-NSGflow"
$location = "japaneast"
$vnet_name = "Vnet-Test-NSGflow"
$vnet_address = "10.8.0.0/24"
$subnet1_name = "Subnet-Client"
$subnet1_address = "10.8.0.0/26"
$subnet2_name = "Subnet-Web"
$subnet2_address = "10.8.0.64/26"
$nsg1_name = "NSG-Test-Client"
$nsg2_name = "NSG-Test-Web"
$nsgrule_name = "AllowRDP"
$nsgrule_sourceip = "xxx.xxx.xxx.xxx/32"
$nsgrule_port = 3389
$nsgrule_priority = 200
$pip1_name = "PIP-VM-Test-Client"
$nic1_name = "NIC-VM-Test-Client"
$pip2_name = "PIP-VM-Test-Web"
$nic2_name = "NIC-VM-Test-Web"
$vm1_name = "VM-Test-Client"
$vm2_name = "VM-Test-Web"
$vm_image = "Win2022Datacenter"
$vm_size = "Standard_B2ms"
$vm_authtype = "password"
$vm_adminname = "xxxxxxx"
$storage_name = "satestflowlog95263831"
$workspace_name = "LogAna-NSGflow"
#リソースグループの作成
az group create `
-l $location `
-g $rg_name
#仮想ネットワークの作成とクライアント用サブネットの追加
az network vnet create `
-n $vnet_name `
-g $rg_name `
-l $location `
--address-prefix $vnet_address `
--subnet-name $subnet1_name `
--subnet-prefix $subnet1_address
#web用サブネットの追加
az network vnet subnet create `
-g $rg_name `
--vnet-name $vnet_name `
-n $subnet2_name `
--address-prefixes $subnet2_address
#NSGの作成
az network nsg create `
-n $nsg1_name `
-g $rg_name
az network nsg create `
-n $nsg2_name `
-g $rg_name
#NSGのルール追加
az network nsg rule create `
-g $rg_name `
--nsg-name $nsg1_name `
-n $nsgrule_name `
--source-address-prefixes $nsgrule_sourceip `
--destination-port-range $nsgrule_port `
--priority $nsgrule_priority
az network nsg rule create `
-g $rg_name `
--nsg-name $nsg2_name `
-n $nsgrule_name `
--source-address-prefixes $nsgrule_sourceip `
--destination-port-range $nsgrule_port `
--priority $nsgrule_priority
#NSGをサブネットに適用
az network vnet subnet update `
-g $rg_name `
-n $subnet1_name `
--vnet-name $vnet_name `
--network-security-group $nsg1_name
az network vnet subnet update `
-g $rg_name `
-n $subnet2_name `
--vnet-name $vnet_name `
--network-security-group $nsg2_name
#パブリックIPの作成
az network public-ip create `
-n $pip1_name `
-g $rg_name
az network public-ip create `
-n $pip2_name `
-g $rg_name
#ネットワークインターフェースの作成
az network nic create `
-n $nic1_name `
-g $rg_name `
--vnet-name $vnet_name `
--subnet $subnet1_name `
--public-ip-address $pip1_name
az network nic create `
-n $nic2_name `
-g $rg_name `
--vnet-name $vnet_name `
--subnet $subnet2_name `
--public-ip-address $pip2_name
#仮想マシンの作成
az vm create `
-n $vm1_name `
-g $rg_name `
--image $vm_image `
--size $vm_size `
--nics $nic1_name `
--authentication-type $vm_authtype `
--admin-username $vm_adminname
az vm create `
-n $vm2_name `
-g $rg_name `
--image $vm_image `
--size $vm_size `
--nics $nic2_name `
--authentication-type $vm_authtype `
--admin-username $vm_adminname
#ストレージアカウントの作成
az storage account create `
-n $storage_name `
-g $rg_name `
-l $location `
--kind StorageV2
#LogAnalyticsの作成
az monitor log-analytics workspace create `
-n $workspace_name `
-g $rg_name
web用VMのIISは以下の記事を参考にpowershellで設定しました。