ネットワークの可視化
GREE Advent Calendar 2015 の23日目担当の上竹です。普段はアプライアンスLB やネットワークの構築/運用をしております。
概要
バックボーンネットワークを設計運用していると、実際どのようなトラフィックがどのくらい流れているか中身を知りたい(見たい)ことがよくあります。
どのISP からどの回線へどのくらい流入があるのかだったり、どんなAS からどのくらいアクセスがきているか、これら様々な情報を正しく把握することは、Transit 回線やIX 回線をコントロールし今後のネットワーク戦略を考えるうえで非常に有益です。
また、昨今我々を悩ましているDDoS 対策の第一歩として、今流れているトラフィックをまず"知る"ということが必要だと思います。
そこで、今回ネットワークの見える化を、「NetFlow」、「Fluentd + ElasticSearch + Kibana」を利用して実現しました。
背景
まずトラフィックの中身を覗く手段が必要です。これを担うのがNetFlow です。
NetFlow とは、Cisco が1996 年に開発したネットワーク上を流れているトラフィックをモニターする機能です。
モニターしたトラフィックをフローごとに分類し、それらを任意の宛先へエクスポートします。
エクスポートされたフロー情報をキャッチし解析する基盤が必要です。この解析基盤を用意するには大きく以下の選択肢があります。
- アプライアンス製品を購入する
- 公開されているツールを導入する
- 自前で用意する
グリーでは、flow-tools という公開されているNetFlow 解析ツールを導入していましたが、メンテナー不在だったこと、使いにくく自由度が低いこともあって、今回新たにOSS であるFluentd + ElasticSearch + Kibana を使用して解析基盤を構築しました。
NetFlow とは
まず最初に、簡単にNetFlow とは何かについて触れておきます。
トラフィック分析には、他にSNMP という技術がよく使用されますが、こちらがある期間にどのくらいパケットが流れていたかの総量を計測するのに対して、NetFlow はある期間にどんなパケットがどのくらい流れていたか種別ごとに計測します。
その種別の識別には以下の7つ のキーを使用します。
- 送信元IP アドレス
- 宛先IP アドレス
- 送信元ポート番号
- 宛先ポート番号
- L3 プロトコル
- TOS
- 入力インターフェース
これら7 つのキーが全て同一である場合、同じフローとして識別されます。(※ NetFlow version 9 では、このキーを指定できます。)
フローは様々なフィールドを持っています。上記7つのキーはもちろんのこと、送信元AS 番号やネクストホップやパケットのbytes など様々な有用な情報を得ることができます。
システム概要
使用したもの
- ルーター
- Cisco Catalyst 6500-E シリーズスイッチ
- NetFlow にFlexible NetFlow 機能を使用します
- (グリーでは様々なメーカーのNW 機器を運用しておりますが、今回は上記を例にご説明します)
- Cisco Catalyst 6500-E シリーズスイッチ
- 以下インストール済みのLinux サーバー (インストール方法は割愛させて頂きます)
- fluentd
- fluent-plugin-elasticsearch, fluent-plugin-geoip の2つのプラグインを使用します
- elasticsearch
- kibana4
- fluentd
何をするか
- ルーターで取得したフロー情報をfluentd に流し込みelasticsearch で解析しkibana4 で表示する
- 送信元アドレスからGeoIP データベースを使って位置情報を取得して、kibana4 のTile Map に表示する
Flexible Flow の設定
最初にFlexible Flow の設定をします。
まず 、exporter の設定をします。ここではデータをエクスポートする宛先を定義します。
弊社では、一部ルーターにて伝統的なNetflow v5 を使用している経緯があり、そちらに分析する際のデータスキーマにあわせるため、Flexible Flow でも netflow-v5
と指定しています。(※ v9 には、v5 との下位互換性がありません。)
flow exporter exporter-name
destination {ip-address | hostname}
source interface-type interface-number
transport udp udp-port
export-protocol netflow-v5
次に、monitor をカスタマイズします。上記で設定したexporter を適用し、どのrecord を使用するか定義します。
v5 を使用する場合、あらかじめ用意されているrecord である platform-original
しか使用できません。IPv4 の全てのフローフィールドを取得できるように ipv4 full
と指定しています。
v9 を使用する場合、flow record
を使用して、ユーザ定義のrecord を作成し適用できます。何をキーとするか、どのフィールド取得するかを任意に設定できます。
flow monitor monitor-name
exporter exporter-name
record platform-original ipv4 full
最後に、sampler を作成します。
ここではサンプリング率を指定できます。ルーターの負荷を考慮して、設定します。
flow sampler sampler-name
mode random 1 out of rate
以上で必要なものは揃ったので、インターフェースに適用していきます。
今回はインターネットから自網内に入ってくるフローを分析したいため、対象のインターフェースのin に適用します。
ip flow monitor monitor-name input sampler sampler-name
fluentd の設定
まずは、<source> でルーターからエクスポートされたフローをfluentd でキャッチします。Flexible NetFlow のexporter で設定したUDP ポート番号を指定します。 こちらでfluent-plugin-elasticsearchを使用しています。
1 2 3 4 5 |
<source> type netflow tag geo.netflow port {udp_port} </source> |
次に、fluent-plugin-geoip を使用して、送信元アドレスをキーとして geoip_lookup_key ipv4_src_addr
GeoIP データベースを検索し、国コードや緯度経度をフィールドに追加します。
ここで重要なのは、Kibana4 のTile Map を使用するにはelasticsearch のGeo Point Type が必要となるため、そのフォーマットに従ったフィールドを用意する必要があります。
下の例では、 geoip_pin
フィールドを追加して lat,lon
というフォーマットを採用しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<match geo.netflow> type geoip geoip_lookup_key ipv4_src_addr geoip_country ${country_code['ipv4_src_addr']} geoip_city ${city['ipv4_src_addr']} geoip_lat ${latitude['ipv4_src_addr']} geoip_lon ${longitude['ipv4_src_addr']} geoip_pin ${latitude["ipv4_src_addr"]},${longitude["ipv4_src_addr"]} remove_tag_prefix geo. add_tag_prefix es. skip_adding_null_record </match> |
最後に、データをelasticsearch へnetflow タイプとして送ります。
1 2 3 4 5 6 7 8 9 |
<match es.netflow> type elasticsearch host {elasticsearch host} port {elasticsearch port} type_name netflow logstash_format true logstash_prefix flow logstash_dateformat %Y%m%d </match> |
elasticsearch の設定
elasticsearch の設定は特に必要ありません。
td-agent から送られてきたデータが日次index (flow-20151223とか)に自動的にどんどん蓄積されていきます。
ただ、fluentd で追加したgeoip_pin
フィールドがgeo_point type 型であることをelasticsearch に知らせてやらなければいけません。
(その他のフィールドについては、自動的にstring 型やnumber 型と認識されます。)
このため、flow-* というindex に適用されるテンプレートを登録します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
curl -XPUT {elasticsearch host}:{elasticsearch port}/_template/flow -d ' { "template" : "flow-*", "mappings" : { "netflow" : { "properties" : { "@timestamp" : { "type" : "date", "format" : "dateOptionalTime" }, "ipv4_src_addr" : { "type" : "string" : : "geoip_pin" : { "type" : "geo_point" }, : : } } }' |
kibana4 の設定
以下のようにindex pattern を設定します。
あとは好きな様にポチポチして楽しく可視化するだけです。
geo_point 型であるgeoip_pin
フィールドを追加したことで、送信元アドレスを元にした様々なヒートマップやマーカーマッピングを簡単に表示することができます。
まとめ
今回、Netflow とOSS ツールを利用して、ネットワークの可視化を実現する方法を簡単に紹介しました。「見える化」をすることで、今まで簡単に得ることができなかった情報をリアルタイムに直感的に得ることができるようになりました。そして何より目に見える形に何かをアウトプットすることは楽しいです。ただし、ネットワークを"知る"ことで満足せず、次のアクションに活かしていこうと思います。
明日は渡部さんの消滅都市のお話です。お楽しみに。