FreeBSD の syslog と fluentd の組み合わせ

fluentd でログを集めたい

なにも Elasticsearch で Kibana でふがほげとかは考えていなくて、何か所か借りている VPS への ssh とか http な攻撃のログをまとめて、共通した blacklist を作って、それぞれのインスタンスに配布したい。 攻撃側が分散処理をやっているのだから、しょぼいけど守る側も分散データを集めて処理したっていいじゃないか。

そんなことを考えている時に、ちょっと古い記事だけど Fluentdとはどのようなソフトウェアなのか - たごもりすメモ を読んだので、ログデータを集めるのは fluentd でやってみようと思ったのだった。

FreeBSD の syslog からローカルの fluentd に送る

httpd のログは file を tail するプラグインを使ってあっさり行った。問題は、sshd の認証関連のログが syslog に吐かれていることだけど、以下の設定でいけそうである。

fluent.conf

<source>
  @type syslog
  bind 127.0.0.1
  port 5020
</source>

/usr/local/etc/syslog.d/fluent.conf

auth.info;authpriv.info                     @127.0.0.1:5020

/etc/rc.conf で syslog_flags="-ss" とかになっててはまったけど、まあそれはおいておく。

問題

この設定で動かすと、syslog からのメッセージを処理した結果の "host" の値が "sshd[12345]:" のように "ident" に入るべき内容になり、"ident" にはメッセージの最初の語が入ってしまう。でも /var/log/auth.log に記録されるログは次のように RFC3164 フォーマットになっている。

May 11 07:56:07 example sshd[6804]: Accepted keyboard-interactive/pam for cugel from 192.168.0.10 port 54764 ssh2

さんざん悩んだ挙句 tcpdump してみたら以下のようになっていて、RFC3164フォーマットにあるべき host のカラムが抜けていた。 /var/log/auth.log の方はちゃんと RFC3164 フォーマットなのに。

        Facility auth (4), Severity info (6)
        Msg: May 10 01:45:33 sshd[20808]: Received disconnect from 115.69.232.33 port 12935:11: disconnected by user
01:45:33.844456 IP6 (hlim 64, next-header UDP (17) payload length: 94) localhost.syslog > localhost.5020: [bad udp cksum 0x0071 -> 0x0ea1!] SYSLOG, length: 86

解決方法

syslogd のオプションをごにょごにょしたら RFC3164フォーマットでなんとかならないかと思ったが無理だった。 それならというわけで、RFC5424フォーマットに なるように /etc/rc.conf で指定してみた。

syslogd_flags="-s -O rfc5424"

fluent.conf の方にも RFC5424フォーマットを指定した。

<source>
  @type syslog
  bind 127.0.0.1
  port 5020
  <parse>
    message_format rfc5424
  </parse>
</source>

tcpdump で見ても host がちゃんと含まれていて、それを受ける fluentd の方も、データを out_file フォーマットで保存してみたら次のようにきちんと処理されている。

2019-05-11T02:17:37+09:00       system.auth.info        {"host":"example.ne.jp","ident":"sshd","pid":"24374","msgid":"-","extradata":"-","message":"reverse mapping checking getaddrinfo for 106.xxx.xxx.xxx.isp.timbrasil.com.br [xxx.xsx.xxx.106] failed."}

この先

それぞれのメッセージから IP アドレスと認証の成功/失敗/ワン切りを判別して、時刻付きで DB に入れてカウントするということをしたい。まあそのうち。