ElastiFlowとKibanaを組み合わせてNetFlowのデータを分析してみる

目次

概要

今回は、ElastiFlow 環境を構築してネットワークのフロー情報の収集と可視化を行う環境を構築してみます。
OS は Ubuntu22.04 LTS です。

ElastiFlowとは

ElastiFlow とは、ネットワークのフロー情報を解析するためのツールの1つです。
OSS として提供されており、データの蓄積と解析を行う ElasticSearch 、データを可視化する WebUI を提供する Kibana を合わせて使用することでフロー情報の取得から解析・可視化を行うことができます。
この ElasticSearch に対して収集したデータを入れるツールとして以前は logstash が用いられていたようですが、今は ElastiFlow に内包された ElastiFlow Unified Flow Collector によってデータの収集と ElasticSearch 用データ形式への正規化が行われています。

準備

最初に、構築にあたって動作に必要なスペックを確認しておく必要があります。
フロー情報の分析などにそこそこの計算資源を消費しますので、公式サイトを参考にマシンスペックを決定します。

また、必要になる基本的なツールをインストールしておきます。

sudo apt install apt-transport-https unzip

Linux Kernelのチューニング

ElasticSearch はデフォルトで mmapfs ディレクトリを使用してデータを保存しますが、Linux のデフォルトの制限値が低すぎるためこの制限を 262114 に引き上げておく必要があります。

echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/70-elasticsearch.conf > /dev/null

また、ネットワーク関係のパラメーターについても変更を行います。
デフォルトでは大量の UDP パケットの受信に最適化されておらずパケットがドロップされる可能性があるため、チューニングを行っておく必要があります。

echo -e "net.core.netdev_max_backlog=4096\nnet.core.rmem_default=262144\nnet.core.rmem_max=67108864\nnet.ipv4.udp_rmem_min=131072\nnet.ipv4.udp_mem=2097152 4194304 8388608" | sudo tee /etc/sysctl.d/60-net.conf > /dev/null

これらの設定を適用するためにOSを再起動します。

【補足】再起動せずに適用する(一時的な適用)
sudo sysctl -w vm.max_map_count=262144
sudo sysctl -w net.core.netdev_max_backlog=4096
sudo sysctl -w net.core.rmem_default=262144
sudo sysctl -w net.core.rmem_max=67108864
sudo sysctl -w net.ipv4.udp_rmem_min=131072
sudo sysctl -w net.ipv4.udp_mem='2097152 4194304 8388608'

ElasticSearchのインストール

最初に、ElasticSearch の PGP キーを追加します。

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

続いて Elastic のリポジトリを追加します。

echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list > /dev/null

リポジトリの追加が出来たら ElasticSearch をインストールします。

sudo apt update
sudo apt install elasticsearch

ElasticSearchの設定

インストールが完了したら、ElasticSearch の設定を行います。

初めに、JVM のヒープサイズを設定します。
使用中に JVM のヒープサイズが動的に変更された場合にプロセスが一時停止する場合があるためです。
初期ヒープサイズと最大ヒープサイズを同じサイズに設定しておくことで回避することができます。
なお、今回は 12GB を割り当てていますが、システムのメモリ量の 1/3 の量に設定することが望ましいようですので、各自の環境に合わせて変更してください。

echo -e "-Xms12g\n-Xmx12g" | sudo tee /etc/elasticsearch/jvm.options.d/heap.options > /dev/null

続いて、systemd の設定ファイル内でシステム制限の引き上げを行います。

sudo mkdir /etc/systemd/system/elasticsearch.service.d
echo -e "[Service]\nLimitNOFILE=131072\nLimitNPROC=8192\nLimitMEMLOCK=infinity\nLimitFSIZE=infinity\nLimitAS=infinity" | sudo tee /etc/systemd/system/elasticsearch.service.d/elasticsearch.conf > /dev/null

ElasticSearch への接続に使用する証明書の生成を行います。
この処理を簡素にするために elasticsearch-certutil と呼ばれるツールが用意されていますのでこちらを利用します。
最初に CA を生成します。

sudo /usr/share/elasticsearch/bin/elasticsearch-certutil ca --pem

Please enter the desired output file [elastic-stack-ca.zip]: が表示されたらそのまま Enter を押下しデフォルトのまま進みます。
生成されたファイルは /usr/share/elasticsearch に配置されます。

生成されたファイルを解凍して移動します。

sudo mkdir /etc/elasticsearch/certs
sudo unzip /usr/share/elasticsearch/elastic-stack-ca.zip -d /etc/elasticsearch/certs

続いて、証明書を生成するのに必要な情報を記載したファイル /usr/share/elasticsearch/instances.yml 作成します。
このファイルに次の内容を書き込みます。 nameipdns の値は各自の環境に合わせて変更する必要があります。
なお、 dns についてはDNS名が無い場合は項目ごと設定しないでおくことができます。(下から2行分を削除)

instances:
  - name: "hostname" 
    ip: 
      - "192.168.1.2"
    dns: 
      - "hostname.dns.local"

先ほどの生成ツールを利用して証明書を生成します。

sudo /usr/share/elasticsearch/bin/elasticsearch-certutil cert --silent --in instances.yml --out certs.zip --pem --ca-cert /etc/elasticsearch/certs/ca/ca.crt --ca-key /etc/elasticsearch/certs/ca/ca.key

生成された ZIP ファイルを再度解凍しておきます。

sudo unzip /usr/share/elasticsearch/certs.zip -d /etc/elasticsearch/certs

設定ファイルを編集します。
設定ファイルは /etc/elasticsearch/elasticsearch.yml に存在します。
xpack.security.http.ssl.keyxpack.security.http.ssl.certificate にある証明書のパスは必ず各自の環境に合わせて変更しておく必要があります。
その他項目についても設定を変更する必要がある場合は調整してください。

cluster.name: elastiflow

path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch

bootstrap.memory_lock: true

network.host: 0.0.0.0
http.port: 9200

discovery.type: 'single-node'

indices.query.bool.max_clause_count: 8192
search.max_buckets: 250000

action.destructive_requires_name: 'true'

xpack.security.http.ssl.enabled: 'true'
xpack.security.http.ssl.verification_mode: 'none'
xpack.security.http.ssl.certificate_authorities: /etc/elasticsearch/certs/ca/ca.crt
xpack.security.http.ssl.key: /etc/elasticsearch/certs/hostname/myhohostnamest.key
xpack.security.http.ssl.certificate: /etc/elasticsearch/certs/hostname/hostname.crt

xpack.monitoring.enabled: 'true'
xpack.monitoring.collection.enabled: 'true'
xpack.monitoring.collection.interval: 30s

xpack.security.enabled: 'true'
xpack.security.audit.enabled: 'false'

設定ファイルの編集が完了したら ElasticSearch サービスを起動します。
なお、初期状態ではOS起動時に自動的に起動する設定にはなっていないため、合わせて設定しておきます。

sudo systemctl daemon-reload
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch

ElasticSearch の各種パスワードを設定します。

sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive

インタラクティブ形式で設定項目が出てきますので、それぞれ設定します。

ここまで完了したら、curl コマンドを利用して正しく動作しているか確認します。
<PASSWORD> は適宜変更してください。
下記のようなレスポンスが返ってくれば正しく動作しています。
レスポンスエラーになる場合は証明書のパス設定が正しいか、ElasticSearch が起動しているかなどを再度確認してみてください。

$ curl -XGET -k "https://elastic:<PASSWORD>@127.0.0.1:9200"
{
  "name" : "elastiflow",
  "cluster_name" : "elastiflow",
  "cluster_uuid" : "askEKLTJgskl4wNKL",
  "version" : {
    "number" : "7.17.6",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "f65e9d338dc1d07b642e14a27f338990148ee5b6",
    "build_date" : "2022-08-23T11:08:48.893373482Z",
    "build_snapshot" : false,
    "lucene_version" : "8.11.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

Kibanaのインストール

続いて Kibana をインストールしていきます。

sudo apt update
sudo apt install -y kibana

先ほど作成した ElasticSearch の証明書をコピーします。

sudo cp -r /etc/elasticsearch/certs /etc/kibana

Kibana の設定ファイルを編集します。
設定ファイルは /etc/kibana/kibana.yml に存在します。
環境に合わせて変更する必要があるのは次の箇所です。

  • server.publicBaseUrl
  • server.ssl.key
  • server.ssl.certificate
  • elasticsearch.hosts
    • localhost では証明書エラーで接続できませんので必ずIPで設定します。
  • elasticsearch.password
  • elasticsearch.ssl.key
  • elasticsearch.ssl.certificate
  • xpack.encryptedSavedObjects.encryptionKey
    • 変更しなくても動作しますがランダム文字列に変えておくとよいでしょう。
telemetry.enabled: false
telemetry.optIn: false
newsfeed.enabled: false

server.host: '0.0.0.0'
server.port: 5601
server.maxPayload: 8388608
server.publicBaseUrl: 'https://192.168.2.1:5601'

server.ssl.enabled: true
server.ssl.certificateAuthorities: /etc/kibana/certs/ca/ca.crt
server.ssl.key: /etc/kibana/certs/myhost/myhost.key
server.ssl.certificate: /etc/kibana/certs/myhost/myhost.crt

elasticsearch.hosts: ['https://192.168.2.1:9200']
elasticsearch.username: 'kibana_system'
elasticsearch.password: 'PASSWORD'
elasticsearch.ssl.certificateAuthorities: /etc/kibana/certs/ca/ca.crt
elasticsearch.ssl.key: /etc/kibana/certs/myhost/myhost.key
elasticsearch.ssl.certificate: /etc/kibana/certs/myhost/myhost.crt
elasticsearch.ssl.verificationMode: 'certificate'

elasticsearch.requestTimeout: 132000
elasticsearch.shardTimeout: 120000

kibana.autocompleteTimeout: 2000
kibana.autocompleteTerminateAfter: 500000

monitoring.enabled: true
monitoring.kibana.collection.enabled: true
monitoring.kibana.collection.interval: 30000

monitoring.ui.enabled: true
monitoring.ui.min_interval_seconds: 20

xpack.maps.showMapVisualizationTypes: true

xpack.security.enabled: true
xpack.security.audit.enabled: false

xpack.encryptedSavedObjects.encryptionKey: 'THIS_IS_A_RANDOM_STRINGS'

Kibana を起動します。
こちらも ElasticSearch と同様に初期状態ではOS起動時に自動的に起動する設定にはなっていないので合わせて設定しておきます。

sudo systemctl daemon-reload
sudo systemctl enable kibana
sudo systemctl start kibana

サービスが正常に起動しているか確認します。

sudo systemctl status kibana

正常に起動できていれば、ブラウザで https://<IP>:5601 にアクセスするとログイン画面が表示されます。
証明書エラーが表示されますが、自己証明書を使用しているためです。自己責任で続行することができます。

ElastiFlow Unified Flow Collectorのインストール

続いて、NetFlow のデータを利用するために Elastic Unified Flow Collector をインストールします。

wget https://elastiflow-packages.s3.amazonaws.com/flow-collector/flow-collector_5.6.0_linux_amd64.deb
sudo apt install ./flow-collector_5.6.0_linux_amd64.deb

ElastiFlow Unified Flow Collectorの設定

コレクターの設定をしていきます。

まずは、証明書をコピーして利用できるようにします。

sudo mkdir /etc/elastiflow/ca
sudo cp /etc/elasticsearch/certs/ca/ca.crt /etc/elastiflow/ca

続いて、せっかくなので無償で使用できる Basic ライセンスを取得しておきます。
こちらのページからリクエストすることができます。
ライセンスをリクエストすると30分程度でライセンス情報が記載されたメールが届きます。

ライセンスを取得出来たら、必要な設定をしていきます。
設定ファイルは /etc/systemd/system/flowcoll.service.d/flowcoll.conf に存在しています。
必要な項目をコメントアウトするなどして編集します。

ライセンス関連

EF_FLOW_LICENSED_UNITS はライセンス形態により異なりますが今回は BASIC ライセンスですので 1 を設定します。

Environment="EF_FLOW_ACCOUNT_ID=<メールに記載のあるACCOUNT_ID>"
Environment="EF_FLOW_LICENSE_KEY=<メールに記載のあるLICENSE_KEY>"
Environment="EF_FLOW_LICENSED_UNITS=1"
ネットワーク関連

本来は 0.0.0.0 で良いはずなのですが、私の環境ではその設定では IPv6 でしか Listen してくれなかったので明示的に IPv4 インターフェースのアドレスを指定しておきます。

Environment="EF_FLOW_SERVER_UDP_IP=192.168.1.2"
ElasticSearch関連

下記項目は環境に合わせて変更します。

  • EF_FLOW_OUTPUT_ELASTICSEARCH_ADDRESSES
  • EF_FLOW_OUTPUT_ELASTICSEARCH_PASSWORD
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_ENABLE=true"
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_ECS_ENABLE=true"
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_TIMESTAMP_SOURCE=end"
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_INDEX_TEMPLATE_SHARDS=1"
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_INDEX_TEMPLATE_REPLICAS=0"
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_INDEX_PERIOD=rollover"
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_ADDRESSES=192.168.1.2:9200"
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_USERNAME=elastic"
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_PASSWORD=changeme"

なお、 EF_FLOW_OUTPUT_ELASTICSEARCH_TIMESTAMP_SOURCE の設定について詳細が公式ドキュメントに記載されていますので、必要な場合は変更します。

証明書関連

ElastiFlow に使用する証明書の設定を行います。

Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_TLS_ENABLE=true"
Environment="EF_FLOW_OUTPUT_ELASTICSEARCH_TLS_CA_CERT_FILEPATH=/etc/elastiflow/ca/ca.crt"

設定が完了したら ElastiFlow Unifed Flow Collector を起動します。
こちらも初期状態では OS 起動時に起動する設定にはなっていないので、合わせて設定しておきます。

sudo systemctl daemon-reload
sudo systemctl enable flowcoll
sudo systemctl start flowcoll

サービスが正常に起動しているか確認します。

sudo systemctl status flowcoll

GEOIPとASNのデータベース設定

別途データベースをダウンロードすることで GeoIP の情報と ASN(Autonomous System Number) の情報を利用することができます。
最新のデータベースはこちらから取得することができます。

cd /etc/elastiflow/maxmind
wget https://github.com/P3TERX/GeoLite.mmdb/releases/download/2022.09.16/GeoLite2-ASN.mmdb
wget https://github.com/P3TERX/GeoLite.mmdb/releases/download/2022.09.16/GeoLite2-City.mmdb
wget https://github.com/P3TERX/GeoLite.mmdb/releases/download/2022.09.16/GeoLite2-Country.mmdb

続いて、このデータベースを利用するように ElastiFlow の設定ファイルである /etc/systemd/system/flowcoll.service.d/flowcoll.conf を編集します。

Environment="EF_FLOW_DECODER_ENRICH_MAXMIND_ASN_ENABLE=true"
Environment="EF_FLOW_DECODER_ENRICH_MAXMIND_ASN_PATH=maxmind/GeoLite2-ASN.mmdb"
Environment="EF_FLOW_DECODER_ENRICH_MAXMIND_GEOIP_ENABLE=true"
Environment="EF_FLOW_DECODER_ENRICH_MAXMIND_GEOIP_PATH=maxmind/GeoLite2-City.mmdb"
Environment="EF_FLOW_DECODER_ENRICH_MAXMIND_GEOIP_LANG=en"

設定が完了したら反映のため ElastiFlow サービスを再起動しておきます。
なお、適用には daemon-reload を実施する必要があります。

sudo systemctl daemon-reload
sudo systemctl restart flowcoll

Kibanaの設定

Kibana の設定をしていきます。
まずは ElastiFlow 用の Kibana Object をインポートします。
インポートに必要なオブジェクトはここから取得することができます。
今回、ElasticSearch は Version7.17.6、Schema としてデフォルトの CODEX を使用しているので、 kibana-7.14.x-codex-light.ndjson を使用します。
事前にダウンロードしておきます。

まず、ブラウザで https://<IP>:5601 にアクセスしてログインします。
デフォルトのユーザー名は elastic でパスワードは先ほど設定したものを使用します。

ログイン出来たら左側のメニューから Stack Management から Saved Objects を開きます。
画面右上の import から import を押すとファイル選択画面が出てくるので、先ほどダウンロードしたファイルを選択し Import を押します。

しばらくするとインポートされたオブジェクトが表示されます。

NetFlowでフロー情報を流してみる

ここまで設定できれば ElastiFlow の環境構築は一通り完了です。
ルーターに NetFlow の設定をしてフロー情報を流して動作を確認しましょう。
ElastiFlow Unified Flow Collector のデフォルトの NetFlow ポートは 9995 です。

今回は Ubiquiti Networks 社のルーターである EdgeRouter に設定を入れて動作を確認しました。
各自の環境に合わせて設定方法は調べてください。

EdgeRouter への NetFlow 設定の例

set system flow-accounting disable-memory-table
set system flow-accounting ingress-capture pre-dnat
set system flow-accounting interface eth0
set system flow-accounting netflow enable-egress engine-id 1
set system flow-accounting netflow engine-id 0
set system flow-accounting netflow server 192.168.2.1 port 9995
set system flow-accounting netflow timeout expiry-interval 60
set system flow-accounting netflow timeout flow-generic 60
set system flow-accounting netflow timeout icmp 60
set system flow-accounting netflow timeout max-active-life 60
set system flow-accounting netflow timeout tcp-fin 10
set system flow-accounting netflow timeout tcp-generic 60
set system flow-accounting netflow timeout tcp-rst 10
set system flow-accounting netflow timeout udp 60
set system flow-accounting netflow version 9
set system flow-accounting syslog-facility daemon

Dashboardを見てみる

ここまで正しく設定できていれば、Kibana 上でフロー情報が見えるようになるはずです。
いくつかダッシュボード画面を紹介します。

Overview

フロー情報の概要を確認することができます。

TOP-N

通信量順に送信元・宛先の情報を確認することができます。

Flows

フロー情報を Sankey Diagram 形式で確認することができます。

Geo IP

送信元・宛先の GeoIP 情報を確認することができます。

AS Traffic

送信元・宛先の ASN 情報を確認することができます。

まとめ

今回は、ElastiFlow 環境を構築してネットワークのフロー情報の可視化環境を構築しました。
こういったフロー情報を可視化するツールが OSS で無償で利用できるのはとても便利です。
アクセス元の国や ASN を確認できることで、サーバーの利用状況などを確認することができます。

About

インフラエンジニア
主に作業ログ

About Me

Archives