ログ収集分析基盤 Rsyslog + Elasticsearch + Kibana (Rsyslog構築)
はじめに
以前なんちゃってセキュリティレポートを書いた.
これは ddwrt のログを使っているのだけれど,手動で分析するのは面倒なので,昨今流行りの(?) Elasticsearch を使ってみようと思う.
構成としては表題の通り,Rsyslog でログ収集して,Elasticsearch に蓄積して,Kibana で可視化する.
最初は Fluentd を使おうと思って適当に設定してみたものの, あまり直感的じゃないし,絶賛発展途上中という印象を受けたのでやめた.
Logstash を使えばいいじゃないかという気もするが, OS標準っぽい Rsyslog を使ってみたくなったのでこれを使う.
長そうなので今回は Rsyslog の構築部分について書く.
公式ドキュメントももちろん参照するべきだが,以下さくらのナレッジも非常に参考になるので Rsyslog なにそれな人は一読するといい.
ちなみに OS は例のごとく CentOS7 を使う.
$ cat /etc/centos-release CentOS Linux release 7.7.1908 (Core)
Rsyslog について
Rsyslog は様々な形式のログの収集と配信ができる. Logstash 風に言うとデータ処理パイプラインである.
公式の説明では以下の特徴がある.
- Multi-threading
- TCP, SSL, TLS, RELP
- MySQL, PostgreSQL, Oracle and more
- Filter any part of syslog message
- Fully configurable output format
- Suitable for enterprise-class relay chains
つまり,いろいろできると.
今回 Rsyslog でやりたいのは dd-wrt のログを Elasticsearch に入れることなので,Rsyslog の機能で十分に実現できそう.
Rsyslog 構築
インストール
$ rsyslogd -v rsyslogd 8.24.0-41.el7_7.2, compiled with: PLATFORM: x86_64-redhat-linux-gnu PLATFORM (lsb_release -d): FEATURE_REGEXP: Yes GSSAPI Kerberos 5 support: Yes FEATURE_DEBUG (debug build, slow code): No 32bit Atomic operations supported: Yes 64bit Atomic operations supported: Yes memory allocator: system default Runtime Instrumentation (slow code): No uuid support: Yes Number of Bits in RainerScript integers: 64 See http://www.rsyslog.com for more information.
デフォルトの Rsyslog は古すぎて使い物にならないので最新にする必要がある.
公式の手順 1 に従い最新の安定版とその他必要な物をインストールする.
# cd /etc/yum.repos.d/ # wget http://rpms.adiscon.com/v8-stable/rsyslog.repo # yum install rsyslog rsyslog-elasticsearch liblognorm liblognorm5-utils
- rsyslog
- Rsyslog 本体
- rsyslog-elasticsearch
- Elasticsearch 用モジュール
- liblognorm
- メッセージを正規化するモジュール 2
- liblognorm5-utils
- メッセージの正規化ルールを作成するときのコマンドラインツール
- あとで出てくる
lognormalizer
コマンドで使う
設定
今回設定する必要があるのは以下3つ.
/etc/rsyslog.conf # Rsyslog全体の設定 /etc/rsyslog.d/ ├ ddwrt.rulebase # 個別設定のメッセージ正規化ルール └ ddwrt.conf # 個別設定
rsyslog.conf
デフォルトでは以下のようにな設定になっていた. 適当に整形して,今回関係ある部分だけコメントをつけた.
$ cat /etc/rsyslog.conf # モジュール読み込み $ModLoad imuxsock # provides support for local system logging (e.g. via logger command) $ModLoad imjournal # provides access to the systemd journal $WorkDirectory /var/lib/rsyslog $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat # デフォルトの出力フォーマット指定 $IncludeConfig /etc/rsyslog.d/*.conf # 個別設定読み込み $OmitLocalLogging on $IMJournalStateFile imjournal.state # ファシリティとプライオリティ毎に出力先変更 *.info;mail.none;authpriv.none;cron.none /var/log/messages authpriv.* /var/log/secure mail.* -/var/log/maillog cron.* /var/log/cron *.emerg :omusrmsg:* uucp,news.crit /var/log/spooler local7.* /var/log/boot.log
ややこしいことに Rsyslog の設定ファイルのフォーマットは3種類ある3. obsolete legacy は廃止されたファーマットなので使わないほうがいい. 単純な設定には basic,複雑な設定には advanced を使うといいが, 設定サンプルを参考に設定を書いていけば問題ないので,最初のうちはフォーマットは気にしなくてもいい.
- basic
- advanced
- obsolete legacy
とか言いながら,デフォルトからフォーマットをがらっと変更して適当に設定した. 入力はとりあえず syslog 標準の 514/udp に設定.
$ cat /etc/rsyslog.conf ############################# # GLOBAL DIRECTIVES ############################## global(workDirectory="/var/lib/rsyslog") ############################## # MODULES ############################## module( load="imuxsock" SysSock.Use="on" SysSock.Name="/run/systemd/journal/syslog" ) module( load="imjournal" StateFile="imjournal.state" ) module(load="imudp") module(load="mmnormalize") # 正規化モジュール module(load="omelasticsearch") # Elasticsearchモジュール ############################## # RULES ############################## ## INPUT input(type="imudp" port="514" ruleset="ddwrt") # 入力ポート ## USER CUSTOMIZED include(file="/etc/rsyslog.d/*.conf") ## DEFAULTS *.info;mail.none;authpriv.none;cron.none /var/log/messages authpriv.* /var/log/secure mail.* -/var/log/maillog cron.* /var/log/cron *.emerg :omusrmsg:* uucp,news.crit /var/log/spooler local7.* /var/log/boot.log ############################## # forwarding rule ##############################
ddwrt.conf
個別の設定についてはあまり需要ないと思うので, 設定する上で知っておくべきポイントだけ書いておく.
ここで設定する必要があるのは以下の通り.
- Elasticsearch へ出力するためのテンプレートの設定する
- mmnormalize モジュールを使ってメッセージを正規化する
- omelasticsearch モジュールを使って Elasticsearch へ出力する
設定のイメージはこんな感じ.
$ cat ddwrt.conf # TEMPLATE template(name="elast_insert" type="list" option.json="on") { constant(value="{") constant(value="\"timereported\":\"") property(name="timereported" dateFormat="rfc3339") constant(value="\",") constant(value="\"hostname\":\"") property(name="hostname") constant(value="\",") constant(value="\"syslogfacility-text\":\"") property(name="syslogfacility-text") constant(value="\",") constant(value="\"syslogpriority-text\":\"") property(name="syslogpriority-text") constant(value="\",") constant(value="\"syslogtag\":\"") property(name="syslogtag") constant(value="\",") constant(value="\"ab\":\"") property(name="$!ab") constant(value="\",") constant(value="\"cd\":\"") property(name="$!cd") constant(value="\"") constant(value="}\n") } template(name="debug" type="string" string="TMP: %msg%\n" #string="TMP: %rawmsg%\n" ) ruleset(name="ddwrt"){ # NORMALIZE action(type="mmnormalize" ruleBase="/etc/rsyslog.d/ddwrt.rulebase") #action(type="mmnormalize" ruleBase="/etc/rsyslog.d/ddwrt.rulebase" useRawMsg="on") # OUTPUT #action(type="omfile" dirCreateMode="0700" FileCreateMode="0644" File="/tmp/debug.log" Template="elast_insert") #action(type="omfile" dirCreateMode="0700" FileCreateMode="0644" File="/tmp/debug_json.log" Template="debug") action(type="omelasticsearch" server="localhost:9200" template="elast_ins_tcp" dynSearchIndex="on" bulkmode="on" queue.type="linkedlist" queue.size="5000" queue.dequeuebatchsize="300" action.resumeretrycount="-1") & stop }
Rsyslog では Message Properties 4 といって,メッセージなどの情報を保持する変数があり,
定義済みのプロパティもいくつか存在する.
Rsyslog に入力されたメッセージは msg
や rawmsg
に格納されている.
mmnormalize の正規化処理はデフォルトで msg
を対象としている.
useRawMsg="on"
のオプションを使うと正規化対象を rawmsg
に変更出来る.
正規化ルールを作成する際には debug テンプレートを使って,どんなメッセージが送られてきているか確認するといい.
Elasticsearch への出力が終わったら,& stop
で以降の処理を止める.
ddwrt.rulebase
ここでもポイントだけ書いておく.
正規化ルールは入力されたメッセージから必要な部分だけを抽出することが出来る.
例えばこんなルールを書いたとすると,
TEST1 ab=123 cd=456
というメッセージの数字部分だけをプロパティに格納することが出来る.
$ cat ddwrt.rulebase rule=:TEST1 ab=%ab:word% cd=%cd:word%
正しくプロパティが抽出できているかは lognormalizer
コマンドで確認することが出来る.
$ # 設定が正しい場合 $ echo 'TEST1 ab=123 cd=456' | lognormalizer -r ./sample.rulebase { "cd": "456", "ab": "123" }
$ # 設定が間違っている場合 $ echo ' TEST1 ab=123 cd=456' | lognormalizer -r ./sample.rulebase { "originalmsg": " TEST1 ab=123 cd=456", "unparsed-data": " TEST1 ab=123 cd=456" } $ echo 'TEST1 ab=123 cd=456' | lognormalizer -r ./sample.rulebase { "originalmsg": "TEST1 ab=123 cd=456", "unparsed-data": " cd=456" }
半角スペース1つでもルールに反するものはパースできない.
途中でパースが失敗していたらunparsed-data
部分で表示される.
こんな感じで目的のメッセージに合わせてルールを作り込んでいく.
ここでパースしたプロパティは ddwrt.conf で設定しているテンプレートで利用される.
サービス起動
$ sudo systemctl restart rsyslog.service
start なり restart なりで起動する. ただし,まだ Elasticsearch の構築前なので,Elasticsearch への出力部分はコメントアウトしておいたほうがいい.
まとめ
Rsyslog で設定するまでの流れを大まかに書いた. ポイントだけつかめれば他の用途でも使いやすそう.
設定の過程でプロパティが正常に参照できないバグにハマって結構時間を取られてしまった事以外は概ね満足.
ツイッターの使い方はまだ良くわかっていない.