pcapファイルをNetFlowに変換した際にフロー開始時刻が未来にずれた件と修正方法

この記事は、[Fujitsu Advent Calender](http://qiita.com/advent-calendar/2016/fujitsu)の7日目の記事です。
(注意）この記事は個人の見解であり、所属する会社、組織を代表するものではありません。
#前提
　pcap形式のパケットキャプチャファイルをNetFlowに変換し、通信フローをElasticsearch, Fluentd, Kibanaで可視化したい。

#不具合
　パケットキャプチャファイルをsoftflowdでNetFlow v9に変換し、fluent-plugin-netflow経由でFluentdに入力したところ、フロー開始時刻が49.7日の倍数だけ未来の日付になってしまう。

#原因
　パケットキャプチャファイルをsoftflowdでNetFlow v9に変換した場合、フロー開始時刻はfirst_switchedで通知される。first_switchedはマシンの起動時刻を起点とした符号無し32bitのミリ秒の相対時間である。
　パケットキャプチャファイルに記録されたパケットの通信開始時刻がマシンの起動時刻以前の場合、フロー開始時刻がマイナスの値になってしまい、49.7日(2の32乗ミリ秒)の倍数だけ未来の時刻になってしまう。詳細は下記URL参照。

Softflowd_49.7d_20160723
http://www.slideshare.net/TakashiUmeno/softflowd497d20160723

　なお、パケットキャプチャファイルをNetFlow v9に変換する際に、フロー開始時刻としてflowStartMillisecondsを用いた場合は正常に時刻が記録される。flowStartMillisecondsは1970/01/01 UTC 00:00:00(UNIX epoch)を起点としたミリ秒単位の時刻である。たいていのパケットキャプチャファイルに記録されたパケット通信時刻は1970/01/01 UTC 00:00:00より新しいので正常な時刻が記録される。

#問題例
- softflowdを動作させるマシンの起動時刻前に採取されたパケットキャプチャファイルからNetFlowに変換する場合に誤った時刻が記録される。

||JST(UTC+9)|UNIX epoch(1970/01/01 00:00:00 UTC)からの秒数|
|:-:|:-:|:-:|
|現在時刻|2016/07/03 12:00:00.000|1467514800|
|起動時刻|2016/07/02 12:00:00.000|1467428400|
|フロー開始時刻|2016/07/01 12:00:00.000|1467342000|
|フロー終了時刻|2016/07/01 12:00:01.000|1467342001|

- 時刻はいずれもJST(UTC+9)
- 現在時刻 2016/07/03 12:00:00.000→起動からの経過時間 86400000ms
- 起動時刻 2016/07/02 12:00:00.000→UNIX epochからの秒数 1467428400秒
- フロー開始時刻 2016/07/01 12:00:00.000→起動からの経過時間 -86400000ms
- 起動からの経過時間 -86400000msと言いたいが、0から2^32-1ms(= 4294967295ms)しか扱えない。
- 32bitでは-86400000 =0xFAD9A400
- unsigned int 32bitとして扱うと0xFAD9A400= 4208567296ms
- フロー開始時刻が起動時刻2016/07/02 12:00:00.000 + 4208567296ms
- UNIX epochからの秒数 1467428400秒 + 4208567.296秒= 1471636967.296秒→フロー開始時刻が2016/08/20 05:02:47.296 に見えてしまう。
- 同様にフロー終了時刻は 2016/08/20 05:02:48.296に見えてしまう
- 下記の誤ったフロー開始時刻、フロー終了時刻が記録されてしまう。

||JST(UTC+9)|UNIX epoch(1970/01/01 00:00:00 UTC)からの秒数|
|:-:|:-:|:-:|
|現在時刻|2016/07/03 12:00:00.000|1467514800|
|起動時刻|2016/07/02 12:00:00.000|1467428400|
|誤ったフロー開始時刻|2016/08/20 05:02:47.296|1471636967.296|
|誤ったフロー終了時刻|2016/08/20 05:02:48.296|1471636968.296|

#対策
##NetFlow exporter
　pmacct等のflowStartMillisecondsに対応したNetflow exporterを用いてパケットキャプチャファイルをNetflow v9に変換する。
##NetFlow collector
　fluent-plugin-netflow に対してflowStartMillisecondsに対応する改造を行った(Version 0.2.5でマージすみ)。
改造にあたっては既にflowStartMillisecondsに対応していたlogstash-codec-netflowの下記ソースを参考にさせていただいた。
https://github.com/logstash-plugins/logstash-codec-netflow/blob/master/lib/logstash/codecs/netflow/ipfix.yaml
https://github.com/logstash-plugins/logstash-codec-netflow/blob/master/lib/logstash/codecs/netflow.rb

改造の詳細は下記URL参照。
Support type 152 field (fieldflowStartMilliseconds) and type 153 field(flowEndMilliseconds) #24
https://github.com/repeatedly/fluent-plugin-netflow/pull/24

　マージにあたってはMasahiro Nakagawa様をはじめとするfluent-plugin-netflowの開発者の皆様には大変お世話になりました。ありがとうございました。

#参考
pmacct project: IP accounting iconoclasm
http://www.pmacct.net/

softflowd - fast software NetFlow probe
http://www.mindrot.org/projects/softflowd/

Netflow plugin for Fluentd
https://github.com/repeatedly/fluent-plugin-netflow

RFC 7012 - Information Model for IP Flow Information Export (IPFIX)
https://tools.ietf.org/html/rfc7012