長期戦のデバッグ用途で、変なパケットが来ていないかをモニタリングしたくなった。tcpdump
と mtail
で実装してみた。
ログファイルを書いて、それを mtail
で監視するという一般的な構成に落ち着いた。
tcpdump_logger.service
[Unit]
Description=tcpdump logger
[Service]
ExecStart=/bin/sh -c '/usr/sbin/tcpdump -i eth0 -tttt -n -l src net 192.168.0.0/16 | /usr/bin/rotatelogs -n 5 /var/log/tcpdump.out 5M'
[Install]
WantedBy=multi-user.target
tcpdump_scraper.service
[Unit]
Description=tcpdump scraper
[Service]
ExecStart=/usr/local/bin/mtail -progs /usr/local/etc/mtail -logs /var/log/tcpdump.out -logtostderr
[Install]
WantedBy=multi-user.target
mtail program
tcpdump
の時刻表現は出力オプションによって変化する。mtail
での共通処理になるのでデコレーターにまとめてみた。
hidden gauge delta
counter packets_total by delta
def timef {
# none
## 17:03:44.379393
/^(?P<tm>\d{2}:\d{2}:\d{2}\.\d+) / {
strptime($tm, "15:04:05.000000")
next
}
# -tt
## 1533024241.471384
/^(?P<tm>\d+)\.\d+ / {
settime($tm + 0)
next
}
# -ttt -ttttt
## 00:00:00.040176
/^ (?P<h>\d{2}):(?P<m>\d{2}):(?P<s>\d{2}).(?P<x>\d{6}) / {
delta = "" + (($h * 3600 + $m * 60 + $s) * 1000 + $x)
next
}
# -tttt
## 2018-07-31 17:16:30.196173
/^(?P<tm>\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2}\.\d{6}) / {
strptime($tm, "2006-01-02 15:04:05.000000")
next
}
# -t
otherwise {
next
}
}
@timef {
/$/ {
packets_total[delta]++
}
}
補足
tcpdump を log に書き出す部分は、unit ファイルを二つに分けて、間を systemd に結んでもらう方法もある。fifo をあらかじめ作って使ってもいいし、 socket activation を使ってもよさそう。ここでは簡単に済ませるために shell を呼び出してパイプで結んだ。
mtail も pipe で結べそうなものだけれども、実際にはできない。mtail を安定的に使おうとするなら、やはりファイルに書かざるを得なかった。
mtail のプログラムは実はかなり hacky なことをやっていて、settime($tm + 0)
やら delta = "" + ...
といった型変換のための小細工が入れてあります。このへんも本来は mtail 自身で吸収してほしかった…。
-
settime
の引数は整数でなければならない - ラベルの部分には文字列しかとらない