[Dynatrace] NetFlow の情報をWorld map使って可視化する

## NetFlowの可視化について更新してみた
ちょうど一年ほどまえ、NetFlowの可視化についての[ブログ](https://qiita.com/yasusuzu/items/e3e24578f7ddb58f751d)を書きました。この時のブログは、どうやってNetFlow情報をDynatraceへ取り込むか？という視点で、まとめました。あれから1年たち、今回はその主眼をNetFlowに取り込んだあと、どうやってもっと見やすく可視化するか？という点におきたいと思います。というのも、Dynatrace SaaS Platform は常に進化し続けており、最近もダッシュボードとノートブックの可視化オプションが増えています。2025年3月25日にリリースされた[SaaS v1.311](https://docs.dynatrace.com/docs/whats-new/saas/sprint-311#maps)からgeo location情報を使って、Worldmap上にデータをプロットできるようになりました。パチパチ👏
今回は、この新しいDashboardを使って、NetFlowの情報に geo location メタデータを追加して、World map 上にデータをプロットしたいと思います。

## NetFlow情報をDynatraceに取り込む方法
まずは、おさらいからです。NetFlow情報はネットワーク機器情報を通過するパケット情報をサンプリングして、その統計データをNetFlowコレクターに送付することで集計されます。NetFlow情報には、SNMPデータにはない情報が沢山含まれるため、それを活用できると、どことどこの通信が多いのか、どのアプリケーションデータの通信量が多いのか？など、より一歩踏み込んだ情報を得ることができます。
DynatraceではNetFlowを取り込む方法として、fluentd をつかった方法を[ヘルプガイド](https://docs.dynatrace.com/docs/analyze-explore-automate/logs/lma-log-ingestion/lma-log-ingestion-via-api/lma-send-netflow-via-fluentd)で紹介しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/6b6d3975-7f91-451c-b7cb-73f97f660aeb.png)
ただ、今回はNetFlow情報に geo location 情報を追加したいので、fluentd ではなく logstash を使いたいと思います。もちろん、fluentd にも[geoip plugin](https://docs.fluentd.org/filter/geoip)が用意されていますが、このプラグインは最近メンテナンスされていないようですので、より頻度高く更新されている logstash に付随する[geoip plugin](https://www.elastic.co/docs/reference/logstash/plugins/plugins-filters-geoip)を使ったやりかたを今回は紹介します。 

## さっそく実装しましょう
インストールする手順は、下記のとおり。
1. netflow を生成し、その情報を受け付ける logstash を動かすVMの準備
2. logstash のインストールと geoip plugin のインストール
3. logstash の dynatrace output pluin のインストール
4. NetFlow情報の取り込み設定と geoip location 情報を追加する conf ファイルの作成
5. netflow client simulator の起動

### 1. netflow を生成し、その情報を受け付ける logstash を動かすVMの準備
いつものように自分の laptop 上に、VM を spin up します。私のお好みは[multipass](https://canonical.com/multipass)なので、使い慣れたツールを使ってVMを起動します。
```
❯ multipass launch --name netflow-vm --cpus 4 --memory 8G --disk 50G --bridged
Launched: netflow-vm

❯ multipass info netflow-vm
Name:           netflow-vm
State:          Running
Snapshots:      0
IPv4:           172.18.37.14
                192.168.1.7
Release:        Ubuntu 24.04.2 LTS
Image hash:     bc471ca49de0 (Ubuntu 24.04 LTS)
CPU(s):         2
Load:           0.34 0.12 0.04
Disk usage:     1.9GiB out of 48.4GiB
Memory usage:   473.4MiB out of 3.8GiB
Mounts:         --
```
VMが起動したら、忘れず `apt update; apt -y upgrade` を実行し、kernel を新しくしておきます。

### 2. logstash のインストールと geoip plugin のインストール
VMが起動したら、logstash をインストールしましょう。Logstashのインストール方法は、Elastic社のヘルプドキュメントに丁寧に記載されていますので、VMの linux distribution に合わせてベストなやりかたをチョイスします。ここでは `Package Repositories` 経由でインストールする[やりかた](https://www.elastic.co/docs/reference/logstash/installing-logstash#package-repositories)を紹介します。

**1\. まずは Public signed key をダウンロード**
```
ubuntu@netflow-vm:~$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elastic-keyring.gpg
ubuntu@netflow-vm:~$ 
```
**2\. `apt-transport-https` をインストール**
```
ubuntu@netflow-vm:~$ sudo apt-get install apt-transport-https
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  apt-transport-https
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 3974 B of archives.
After this operation, 35.8 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu noble/universe amd64 apt-transport-https all 2.7.14build2 [3974 B]
Fetched 3974 B in 1s (7458 B/s)
Selecting previously unselected package apt-transport-https.
(Reading database ... 106392 files and directories currently installed.)
Preparing to unpack .../apt-transport-https_2.7.14build2_all.deb ...
Unpacking apt-transport-https (2.7.14build2) ...
Setting up apt-transport-https (2.7.14build2) ...
Scanning processes...
Scanning linux images...

Pending kernel upgrade!
Running kernel version:
  6.8.0-58-generic
Diagnostics:
  The currently running kernel version is not the expected kernel version 6.8.0-59-generic.

Restarting the system to load the new kernel will not be handled automatically, so you should consider rebooting.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.
ubuntu@netflow-vm:~$ 
```
**3\. Repository definition を /etc/apt 配下に追加**
```
ubuntu@netflow-vm:~$ echo "deb [signed-by=/usr/share/keyrings/elastic-keyring.gpg] https://artifacts.elastic.co/packages/9.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-9.x.list
deb [signed-by=/usr/share/keyrings/elastic-keyring.gpg] https://artifacts.elastic.co/packages/9.x/apt stable main
ubuntu@netflow-vm:~$
```
**4\. Repository を update して、logstash をインストール**
```
ubuntu@netflow-vm:~$ sudo apt-get update && sudo apt-get install logstash
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Hit:2 http://archive.ubuntu.com/ubuntu noble-updates InRelease
Hit:3 http://security.ubuntu.com/ubuntu noble-security InRelease
Get:4 https://artifacts.elastic.co/packages/9.x/apt stable InRelease [3248 B]
Hit:5 http://archive.ubuntu.com/ubuntu noble-backports InRelease
Get:6 https://artifacts.elastic.co/packages/9.x/apt stable/main amd64 Packages [2456 B]
Fetched 5704 B in 1s (4860 B/s)  
Reading package lists... Done
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  logstash
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 434 MB of archives.
After this operation, 712 MB of additional disk space will be used.
Get:1 https://artifacts.elastic.co/packages/9.x/apt stable/main amd64 logstash amd64 1:9.0.0-1 [434 MB]
Fetched 434 MB in 1min 36s (4508 kB/s)
Selecting previously unselected package logstash.
(Reading database ... 106396 files and directories currently installed.)
Preparing to unpack .../logstash_1%3a9.0.0-1_amd64.deb ...
Unpacking logstash (1:9.0.0-1) ...
Setting up logstash (1:9.0.0-1) ...
Scanning processes...
Scanning linux images...

Pending kernel upgrade!
Running kernel version:
  6.8.0-58-generic
Diagnostics:
  The currently running kernel version is not the expected kernel version 6.8.0-59-generic.

Restarting the system to load the new kernel will not be handled automatically, so you should consider rebooting.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.
ubuntu@netflow-vm:~$
```
**5\. geoip filter のインストール確認**
```
ubuntu@netflow-vm:/usr/share/logstash/bin$ sudo ./logstash-plugin list --installed | grep geoip
Using bundled JDK: /usr/share/logstash/jdk
logstash-filter-geoip
ubuntu@netflow-vm:/usr/share/logstash/bin$
```
OKですね。デフォルトインストールなので、安心です。

### 3. logstash の dynatrace output pluin のインストール
dynatrace output plugin は、logstash-plugin ツールから直接インストールできますので、それを使って追加します。
```
ubuntu@netflow-vm:/usr/share/logstash/bin$ sudo ./logstash-plugin install logstash-output-dynatrace
Using bundled JDK: /usr/share/logstash/jdk
Validating logstash-output-dynatrace
Resolving mixin dependencies
Updating mixin dependencies logstash-mixin-http_client
Bundler attempted to update logstash-mixin-normalize_config_support but its version stayed the same
Bundler attempted to update logstash-mixin-http_client but its version stayed the same
Installing logstash-output-dynatrace
Installation successful
ubuntu@netflow-vm:/usr/share/logstash/bin$ sudo ./logstash-plugin list --installed | grep dynatrace
Using bundled JDK: /usr/share/logstash/jdk
logstash-output-dynatrace
ubuntu@netflow-vm:/usr/share/logstash/bin$
```

### 4. NetFlow情報の取り込み設定と geoip location 情報を追加する conf ファイルの作成
ここからが設定の本丸です。まずは、logstash が netflow 情報を取り込めるように、まずします。設定ファイルは、`/etc/logstash/conf.d`配下に作成します。ここで netflow.conf というファイルを作成しておくと、デフォルトで logstash が起動時にここのファイルを読み込んでくれます。設定のセクションは3つに大別されます。1つ目はNetFlow取り込むためのインプット設定、2つ目は取り込んだNetflow情報の何を見て geo location 情報を追加するかの設定、3つ目がJSON化されたNetFlow情報をDynatraceに送るための設定です。2つ目のセクションではNetFlowデータの source ipv4 address と destination ipv4 address の2つ情報を lookup して、geo location 情報を追加するよう、ここでは宣言してあります。Dynatraceにデータを送る先は自身のTenantID（例：abc12345）と自身のToken（スコープ：logs.ingest）の2つの情報が必要です。
```config
### netflow 情報を受け付けるUDPのポート番号指定
input {
  udp {
    port => 2055
    codec => netflow
  }
}

### geo location 情報を追加するためのフィルタ設定
filter {
  geoip {
    ecs_compatibility => disabled
    source => "[netflow][ipv4_dst_addr]" // ipv4の source ip address をlookup
    target => "geoip_dst"
  }
  geoip {
    ecs_compatibility => disabled
    source => "[netflow][ipv4_src_addr]" // ipv4の destination ip address をlookup
    target => "geoip_src"
  }
}

### 最終的にデータをDynatraceのテナントに送信するための設定
output {
  dynatrace {
    id => "dynatrace_output"
    ingest_endpoint_url => "https://<your tenantId>.live.dynatrace.com/api/v2/logs/ingest"
    api_key => "<your own token>"
  }
}
```
この conf ファイルが正しく logstash に読み込まれており、UDP：2055ポートが Listen されているか、このタイミングできちんと確認しましょう。
```
ubuntu@netflow-vm:~$ systemctl status logstash
● logstash.service - logstash
     Loaded: loaded (/usr/lib/systemd/system/logstash.service; enabled; preset: enabled)
     Active: active (running) since Fri 2025-05-02 15:44:21 JST; 53s ago
   Main PID: 5959 (java)
      Tasks: 50 (limit: 9485)
     Memory: 683.3M (peak: 688.2M)
        CPU: 31.958s
     CGroup: /system.slice/logstash.service
             └─5959 /usr/share/logstash/jdk/bin/java -Xms1g -Xmx1g -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djruby.compile.invokedynamic=true -XX:+HeapDumpOnOutOfMemoryError >

May 02 15:44:30 netflow-vm logstash[5959]: [2025-05-02T15:44:30,786][INFO ][logstash.filters.geoip.databasemanager][main] By not manually configuring a database path with `database >
May 02 15:44:30 netflow-vm logstash[5959]: [2025-05-02T15:44:30,787][INFO ][logstash.filters.geoip   ][main] Using geoip database {:path=>"/var/lib/logstash/geoip_database_managemen>
May 02 15:44:30 netflow-vm logstash[5959]: [2025-05-02T15:44:30,806][INFO ][logstash.filters.geoip.databasemanager][main] By not manually configuring a database path with `database >
May 02 15:44:30 netflow-vm logstash[5959]: [2025-05-02T15:44:30,806][INFO ][logstash.filters.geoip   ][main] Using geoip database {:path=>"/var/lib/logstash/geoip_database_managemen>
May 02 15:44:30 netflow-vm logstash[5959]: [2025-05-02T15:44:30,817][INFO ][logstash.javapipeline    ][main] Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>4, "pipelin>
May 02 15:44:31 netflow-vm logstash[5959]: [2025-05-02T15:44:31,213][INFO ][logstash.javapipeline    ][main] Pipeline Java execution initialization time {"seconds"=>0.4}
May 02 15:44:31 netflow-vm logstash[5959]: [2025-05-02T15:44:31,217][INFO ][logstash.javapipeline    ][main] Pipeline started {"pipeline.id"=>"main"}
May 02 15:44:31 netflow-vm logstash[5959]: [2025-05-02T15:44:31,221][INFO ][logstash.inputs.udp      ][main][dcdfdd8b2a7e6fb998cec7b3b1bc4e2f7e49ca9a5925e214ad78e5a14fc0f419] Starti>
May 02 15:44:31 netflow-vm logstash[5959]: [2025-05-02T15:44:31,224][INFO ][logstash.agent           ] Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipeli>
May 02 15:44:31 netflow-vm logstash[5959]: [2025-05-02T15:44:31,228][INFO ][logstash.inputs.udp      ][main][dcdfdd8b2a7e6fb998cec7b3b1bc4e2f7e49ca9a5925e214ad78e5a14fc0f419] UDP li>
ubuntu@netflow-vm:~$
```
と UDP 2055 ポートの LISTEN 確認
```
ubuntu@netflow-vm:~$ ss -apnu src :2055
State                Recv-Q               Send-Q                               Local Address:Port                               Peer Address:Port               Process
UNCONN               0                    0                                          0.0.0.0:2055                                    0.0.0.0:*
ubuntu@netflow-vm:~$
```
ということで、どちらもOKですので、netflow receiver 側の準備はこれで完了です♪

### 5. netflow client simulator の起動
前回と同様に netflow simulator を使って、netflow データを生成していきます。GitHub上の repository を git clone して、ローカル環境で simulator を compile していきます。Go の unbuntu 24.04 のインストールは[こちら](https://go.dev/doc/install)を参考にしてみて下さい。
```
ubuntu@netflow-vm:~$ ls
bin  go1.24.2.linux-amd64.tar.gz  nflow-generator
ubuntu@netflow-vm:~$ cd nflow-generator/
ubuntu@netflow-vm:~/nflow-generator$ ls
Dockerfile  LICENSE  README.md  binaries  go.mod  go.sum  nflow-generator.go  nflow_logging.go  nflow_payload.go  nflow_spike.go
ubuntu@netflow-vm:~/nflow-generator$ go build
go: downloading github.com/jessevdk/go-flags v1.5.0
go: downloading github.com/sirupsen/logrus v1.8.1
go: downloading golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4
ubuntu@netflow-vm:~/nflow-generator$ 
```
git clone を行ったのち、対象のディレクトリに移動し、`go build`コマンドを実行し netflow simulrator を build します。コンパイルが終わったら、コマンドを実行して、ヘルプが下記のように表示されるか確認しましょう。
```
ubuntu@netflow-vm:~/nflow-generator$ ./nflow-generator 

Usage:
  main [OPTIONS] [collector IP address] [collector port number]

  Send mock Netflow version 5 data to designated collector IP & port.
  Time stamps in all datagrams are set to UTC.

Application Options:
  -t, --target= target ip address of the netflow collector
  -p, --port=   port number of the target netflow collector
  -s, --spike run a second thread generating a spike for the specified protocol
    protocol options are as follows:
        ftp - generates tcp/21
        ssh  - generates tcp/22
        dns - generates udp/54
        http - generates tcp/80
        https - generates tcp/443
        ntp - generates udp/123
        snmp - generates ufp/161
        imaps - generates tcp/993
        mysql - generates tcp/3306
        https_alt - generates tcp/8080
        p2p - generates udp/6681
        bittorrent - generates udp/6682
  -f, --false-index generate a false snmp index values of 1 or 2. The default is 0. (Optional)
  -c, --flow-count set the number of flows to generate in each iteration. The default is 16. (Optional)

Example Usage:

    -first build from source (one time)
    go build

    -generate default flows to device 172.16.86.138, port 9995
    ./nflow-generator -t 172.16.86.138 -p 9995

    -generate default flows along with a spike in the specified protocol:
    ./nflow-generator -t 172.16.86.138 -p 9995 -s ssh

    -generate default flows with "false index" settings for snmp interfaces
    ./nflow-generator -t 172.16.86.138 -p 9995 -f

    -generate default flows with up to 256 flows
    ./nflow-generator -c 128 -t 172.16.86.138 -p 9995

Help Options:
  -h, --help    Show this help message
  ubuntu@netflow-vm:~/nflow-generator$
```
これで完全に準備完了です。あとは、この simulator を実行するだけですので、VMのIPアドレスを調べてトラフィックを生成しましょう。
```
ubuntu@netflow-vm:~/nflow-generator$ ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 52:54:00:e3:ac:90 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.7/24 metric 200 brd 192.168.1.255 scope global dynamic eth1
       valid_lft 13175sec preferred_lft 13175sec
    inet6 2405:6582:1b20:1100:5054:ff:fee3:ac90/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 14233sec preferred_lft 12433sec
    inet6 fe80::5054:ff:fee3:ac90/64 scope link
       valid_lft forever preferred_lft forever
ubuntu@netflow-vm:~/nflow-generator$ ./nflow-generator -t 192.168.1.7 -p 2055
INFO[0000] sending netflow data to a collector ip: 192.168.1.7 and port: 2055. 
Use ctrl^c to terminate the app.

```

## UIでデータを確認し、WorldMap上にマッピングしてみる
Dynatraceの `logs` アプリで、今回のNetFlow情報が取り込まれているか確認しましょう。いいですね、きちんと取り込まれていますね♪
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/d00502db-958f-4951-a1fd-162300ef4a12.png)
Geoip location 情報も付加されているか、詳細を見てみましょう。おおー、期待値通りですね。完璧です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/3e8eb0dc-4ac2-4344-8c56-444bab92d354.png)
早速、Dashboardで Bubble map を使って、NetFlowのデータを世界地図上にマッピングしてみましょう。いいですね、美しいし、見やすい！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/33d7b223-e220-4c99-b613-a7576edf0f61.png)
Bubble map を使う場合は、Latitude、longtitude、Radius value（データの大きさを表すもの）、Color value（データの大きさを表す際、どのデータを参照するか？）を Data mapping で指定する必要があるので、お忘れなく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/00460cb3-6c6d-4041-812d-d1ea818f30df.png)
最終的には、こんな配置のダッシュボードに仕上げてみました。良い感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778724/d0d9693d-ac7a-48d5-a4e7-07103b15c88b.png)

## まとめ
如何だったでしょうか？ Dynatrace の新しい world map を使って、NetFlow情報をより直感的に見やすくしてみました。SNMPデータとは異なり、NetFlowデータはより多くのメタ情報を含むため、ネットワークでやりとりされている情報をフローベースで見やすくできるメリットがあります。ぜひ、NetFlow情報やファイアウォールログなどを積極的にDynatraceに取り込み、インフラ監視もDynatraceで見やすくかつ監視基盤を一本化してみてはいかがでしょうか？

まだ、Dynatraceを触ったことがない方、このブログを見てやってみたいと思われた方は、下記フリートライアルにてお試し下さい。↓↓↓

Dynatraceフリートライアル → https://www.dynatrace.com/ja/trial/
## 補足
logstash はデフォルトで MaxMind のデータを自動的にローカルに取り込み参照しています。その際、ASNとCityの2つのデータベースをダウンロードしますが、デフォルトではCityを参照しています。別のデータベースを参照させたい場合は別途追加設定が必要ですので、ご注意下さい。Elastic社の[ヘルプガイド](https://www.elastic.co/docs/reference/logstash/plugins/plugins-filters-geoip#plugins-filters-geoip-database)にも記述がありますので、参考にしてみて下さい。なお、MaxMindのデータは `/var/lib/logstash/geoip_database_management/<id>` 配下にあります。
```
ubuntu@netflow-vm:/var/lib/logstash/geoip_database_management/1746168254$ ls -la
total 102968
drwxr-xr-x 2 logstash logstash     4096 May  2 15:44 .
drwxr-xr-x 3 logstash logstash     4096 May  2 15:44 ..
-rw-r--r-- 1 logstash logstash       55 May  2 15:44 COPYRIGHT.txt
-rw-r--r-- 1 logstash logstash 10056312 May  2 15:44 GeoLite2-ASN.mmdb <<<< これ（ASN用）
-rw------- 1 logstash logstash  5456478 May  2 15:44 GeoLite2-ASN.tgz
-rw-r--r-- 1 logstash logstash 60444647 May  2 15:44 GeoLite2-City.mmdb <<<< これ（City用）
-rw------- 1 logstash logstash 29445669 May  2 15:44 GeoLite2-City.tgz
-rw-r--r-- 1 logstash logstash      398 May  2 15:44 LICENSE.txt
-rw-r--r-- 1 logstash logstash      116 May  2 15:44 README.txt
-rw-r--r-- 1 logstash logstash      162 May  2 15:44 elastic-geoip-database-service-agreement-LICENSE.txt
ubuntu@netflow-vm:/var/lib/logstash/geoip_database_management/1746168254$
```