この記事では、Elasticsearch/Kibanaのver5.xをインストールしている。2019年6月時点での最新版 7.1 をインストールしたい方は Fluentd/Elasticsearch7/Kibana7でsyslogを管理してみる のほうをご覧いただきたい。
rsyslogとjournaldのことの回で、長いことsyslog管理をほったらかしにしていたことを告白したわけだが、これを機にFluentdで集めてKibanaで閲覧する環境を整えてみることにした。というわけでインストール手順と結果についてまとめてみる。
全体の構成はこんな感じだ。
受信サーバの準備
ではまず受信サーバを準備しよう。
Elasticsearch/Kibanaのインストール
Elasticsearch/Kibanaの運用にどれぐらいのスペックが必要なのかいまいちよく分からない。管理対象のサーバは10台になるかならないかぐらいなのだが、Zabbixサーバに同居させるのはちょっと不安だったので、新しく専用のサーバを立てることにした。というわけで何もないところからスタートだ。
最初に、yumのためにrepoファイルを作成する。面倒だが手動だ。コピペできるようにバッチ風に書いておこう。
cat <<EOL >/etc/yum.repos.d/elasticsearch.repo [elasticsearch-5.x] name=Elasticsearch repository for 5.x packages baseurl=https://artifacts.elastic.co/packages/5.x/yum gpgcheck=1 gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch enabled=1 autorefresh=1 type=rpm-md EOL
こうしておいて、yum installする。
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch yum install java-1.8.0-openjdk elasticsearch kibana
続いてBasic認証ぐらいさせたいのでx-packをインストールする。
/usr/share/elasticsearch/bin/elasticsearch-plugin install x-pack /usr/share/kibana/bin/kibana-plugin install x-pack
Elasticsearchの設定ファイルは /etc/elasticsearch/elasticsearch.yml だ。こんな風に書く。
cluster.name: クラスタ名 node.name: ノード名 network.host: 0.0.0.0 transport.host: localhost transport.tcp.port: 9300
もうひとつ、/etc/elasticsearch/jvm.options にメモリ量に応じてオプションを指定する。
-Xms2g -Xmx2g # メモリの半分を指定
Kibanaの設定ファイルは /etc/kibana/kibana.yml だ。
server.host: "0.0.0.0" elasticsearch.url: "http://受信サーバ名:9200"
次にファイアウォールを設定する。Kibanaにアクセスするだけなら5601ポートを開ければよい。
firewall-cmd --permanent --add-port=5601/tcp firewall-cmd --reload
続いて、ElasticsearchとKibanaを起動する。
systemctl start elasticsearch kibana systemctl enable elasticsearch kibana
ここから、急いでパスワードを設定する(本来コマンドラインで設定できるはずなのだが、マニュアル通りのコマンドが見つからず、やむを得ずGUIから設定している)。まずKibanaのコンパネにアクセスする。URLは「http://サーバのIP:5601」だ。するとログイン画面が出てくる。
困ったことに、Kibanaのデフォルトのユーザ名とパスワードは固定されている。ユーザ名が「elastic」、パスワードが「changeme」だ。他人に乗っ取られる前に、これを変更しなければならない。まずはログインして、左のサイドバーの「Management」をクリックして管理画面を表示させる。
「Security」セクションの「Users」を選択すると、予約ユーザ一覧が表示される。
「elastic」を選択し、続いて「Change Password」を選ぶ。
自分で決めた強固なパスワードを指定して「Save」をクリックすれば一安心だ。
なお、他に「kibana」と「logstash_system」が予約されているので、これらのパスワードも変更しておく。
注意書きにある通り、kibana.ymlに設定したパスワードを記述しなければならない。具体的には以下のような手順になる。まずコンソールから /etc/kibana/kibana.yml を編集して、次のように追記する。
elasticsearch.username: "kibana" elasticsearch.password: "設定したパスワード"
そうしておいて、Kibanaをリスタートする。
systemctl restart kibana
ユーザ「elastic」のパスワードもFluentdの設定時に使うのでメモしておく。
受信用のFluentdインストール
次に受信サーバでのFluentdの準備だ。インストールは次のone linerで行う。
curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent3.sh | sh
続いてElasticsearch用のプラグインを追加する。
td-agent-gem install fluent-plugin-elasticsearch
[2019年6月25日追記] Fluentdはport24224を使って通信するので、そのポートも開けておく。全部あけてしまうのも気が引けるので、ログを受け取る対象サーバを選んで受け取るルールにしておこう。
firewall-cmd --permanent --new-zone=fluentd firewall-cmd --permanent --zone=fluentd --set-target=ACCEPT firewall-cmd --permanent --zone=fluentd --add-port=24224/tcp firewall-cmd --permanent --zone=fluentd --add-source=送信サーバIP1 firewall-cmd --permanent --zone=fluentd --add-source=送信サーバIP2 firewall-cmd --reload
次に設定ファイルを書く。設定ファイルは/etc/td-agent/td-agent.confだが、インストール直後にデフォルトのファイルが置いてあるので、その末尾にこんな風に追記する。まずは送信サーバの設定を示す。途中にElasticsearchで設定したパスワードを指定する部分があるので、自分で設定したものを記述する。
<source> @type syslog port 5140 tag fluentd.syslog format syslog </source> <match fluentd.**> @type copy <store> @type elasticsearch logstash_format true include_timestamp true port 9200 user elastic password elasticのパスワード buffer_type file buffer_path /var/log/td-agent/buffer/fluentd.back </store> </match>
この設定ファイルは2つのディレクティブから成る。sourceはポート5140からsyslogメッセージを受信して解析することを指示する部分、matchは内外から受信するFluentdのメッセージをElasticsearchへ突っ込む設定だ。syslogの設定はちょっと後に回して、まずは設定ファイルを作っておこう。できたらFluentdを起動する。
systemctl enable td-agent systemctl start td-agent
さてsyslogメッセージだが、 Fluentdがログを送信する方法はいくつかある。たとえばログファイルを直接パースして送信することもできる(実際は/var/log/messagesのファイル権限の都合でうまくいかない)。だがsyslogを扱うなら本家のドキュメントが示す手段を使うのがよさそうだ。概要はこんな感じだ。
- rsyslogに設定を加えて、local port 5140にsyslogを送るようにする
- Fluentdでそれを捕まえて受信サーバへ送る
2のFluentdで捕まえるほうは、すでにtd-agent.confに記述済みなので、1のrsyslogの設定を行う。/etc/rsyslog.conf の末尾に、次の1行を追加する。
*.info;mail.none;authpriv.none;cron.none @127.0.0.1:5140
設定はお好みに合わせて変えていただきたい。上記の場合、/var/log/messagesと同じレベルの情報をFluentdに送る設定にしている。いったんこれで様子を見て、慣れてきたら情報を増やすとよい。syslogの出力全部を送り付けたい場合は
*.* @127.0.0.1:5140
と書けばよい。設定ができたら、rsyslogを再起動する。
systemctl restart rsyslog
これで受信側はできた。
送信サーバの準備
次に送信サーバ側の設定を示す。監視対象となるサーバの設定は、Fluentdをインストールした後、送信用の設定をいくつか施すことになる。
インストールは受信サーバと同じone linerで行う。
curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent3.sh | sh
rsyslogの設定と再起動も忘れずに行っておく。念のため記載しておこう。
*.info;mail.none;authpriv.none;cron.none @127.0.0.1:5140
または
*.* @127.0.0.1:5140
を追記しておいて、rsyslogを再起動する。
systemctl restart rsyslog
次にFluentdの設定ファイルを書く。送信サーバはこんな感じだ。
<source> @type syslog port 5140 tag fluentd.syslog format syslog </source> <match fluentd.**> @type forward <server> host 受信サーバのホスト名またはIPアドレス port 24224 </server> </match>
設定ファイルができたら、こちらのFluentdも起動する。
systemctl enable td-agent systemctl start td-agent
Kibanaの使い方
設定が完了したら、あらためてKibanaにアクセスしてみよう。ログインするとこんな画面になるはずだ。サイドメニューから順に呼び出すには、「Management」→「Kibana」→「Index Patterns」でたどり着ける。
td-agent.conf で logstash_format を指定しているので、syslogの受信がうまくいっていれば Index patternがアクティブ(認識できている状態)になっているはずだ。そして Time Filter field name にもデフォルトの「@timestamp」が入った状態になっている。 「Unable to fetch mapping…」と出ている場合は、何かがうまくいっていない。設定をチェックしてみて欲しい。 問題がなければ「Create」ボタンを押す。
次の画面では、読み込んだ情報の各フィールドを表示している。細かな設定を行うならここから操作するが、最初はやることがないので飛ばして構わない。次はサイドメニューの「Discover」をクリックする。
Discover画面では、時系列にイベントの数をカウントしたグラフとイベントの一覧を表示してくれる。スケールは右上の「Last 12 hours」などと表示されているところをクリックすると調整できるし、グラフを直接クリックするとそこを拡大できる。さて画面では試験的に1台のサーバのすべてのsyslogを12時間ほど集めた状態なのだが、すでに多数のログが集まっている。こういうとき、どういう種類のどんなメッセージが集まっているのかを調べたい。そういうときは左のサブメニューの「ident」をクリックする。すると受信しているメッセージ種別ごとにヒストグラムを表示してくれる。
例を見ると、Kibanaのログが92%を占めているのが分かる。他を見てみると、sshdのログが多いようだ。そこでこれを抽出してみよう。特定のidentを抽出するには、ルーペアイコンをクリックすればよい。
これで過去12時間に渡って記録されたsshdのメッセージを抽出できた。よく見るとこれは、サーバを設置した後に22番ポートへスキャンしに来ている不埒者のログだ。12時間のうちにこれほどの頻度でポートスキャンがあるということなのだ。ちなみにこれらのスキャンは、fail2banでブラックリスト送りにしてしまうので特に問題は起こっていない。
以上が簡単なKibanaの使い方だ。複数ホストのログを集約し始めたら、hostフィールドで分類やフィルタをすればよいし、個々のメッセージも確認できるので、気になるログは全部この画面からチェックできるようになる。何かアタックの兆しがあったら、個々に対処することになるが、それはまた別のお話ということで。
KibanaをHTTPS化する
Kibanaにアクセスすると、HTTPなので「保護されていない通信」と出る。実にうざったいのでLet’s Encryptを利用してHTTPS化したい。もしサーバにホスト名を割り当てられる方なら、次のような手順で実施できる。
まずサーバにcertbotをインストールする。
yum install certbot
firewall-cmdでHTTPをあけておく。
firewall-cmd --permanent --add-service=http firewall-cmd --reload
次にstandaloneモードでLet’s Encryptから証明書をもらう。
certbot --standalone certonly
certbotの使い方は説明しないが、メールアドレスや登録したいFQDNを聞かれるのできちんと答える。最後までうまくいけば、正しく証明書ファイルが作成される。/etc/letsencrypt/archive/登録したFQDN、というディレクトリにファイルが格納されているはずだ。
次がトリックなのだが、Kibanaはこのディレクトリを直接読めない。root権限で保護されてしまっているからだ。仕方がないのでこれをコピーする。適切な場所を選んで、次のようなバッチを設置する。たとえば /usr/local/bin/kibana-letsencrypt などとしておこう。
#!/bin/sh FQDN=登録したFQDN LETSENCRYPT_DIR=/etc/letsencrypt/archive KIBANA_DIR=/etc/kibana/ssl mkdir -p $KIBANA_DIR cp -rp $LETSENCRYPT_DIR/$FQDN $KIBANA_DIR chmod 750 $KIBANA_DIR/$FQDN chmod 640 $KIBANA_DIR/$FQDN/* chown -R root:kibana $KIBANA_DIR
このバッチを実行して、ファイルが適切な場所に適切なパーミッションでコピーされていることを確認する。
[root@syslog3 ~]# ll /etc/kibana/ssl/xxxxxxxxxxxxxxxxxxx/ total 16 -rw-r----- 1 root kibana 1948 Jun 18 16:38 cert1.pem -rw-r----- 1 root kibana 1647 Jun 18 16:38 chain1.pem -rw-r----- 1 root kibana 3595 Jun 18 16:38 fullchain1.pem -rw-r----- 1 root kibana 1704 Jun 18 16:38 privkey1.pem
次に /etc/kibana/kibana.yml を編集する。次の3行を追加する。
server.ssl.enabled: true server.ssl.certificate: /etc/kibana/ssl/登録したFQDN/fullchain1.pem server.ssl.key: /etc/kibana/ssl/登録したFQDN/privkey1.pem
最後にKibanaをリスタートする。
systemctl restart kibana
これで、https://サーバ名:5601 という名前でアクセスすることができるようになった。
なお Let’s Encrypt の証明書は3ヶ月ごとに更新が必要なので、cronを設定しておく。たとえば /etc/cron.d/cert-renew のようなバッチを用意する。これは毎週月曜日の9時30分に期限をチェックして、更新があればファイルのコピーも行ってくれる。
MAILTO= 30 9 * * mon root /usr/bin/certbot renew --standalone --post-hook "/usr/loal/bin/kibana-letsencrypt" | logger -t certbot-renew -p local0.info
ただ、このバッチはまだ期限を迎えていないのでテストできていない。3ヵ月後に本当に更新できたか確認しなければならない。
Kibanaのログがうざい場合
Kibanaはアクセスごとに大量のログをsyslogに流すので、受信サーバ自体を監視に含めると大変なことになる。Kibanaのフィルタを使って排除してもよいが、rsyslogにフィルタを入れる方法もある。具体的には /etc/rsyslog.d/ignore-kibana.conf というファイルを作成する。
if $programname == "kibana" then stop
そうしておいて rsyslog を再起動すれば kibana からのメッセージは記録されなくなる。
参考リンク
- https://www.elastic.co/guide/en/elasticsearch/reference/master/settings.html
- https://docs.fluentd.org/installation/install-by-rpm
- https://docs.fluentd.org/how-to-guides/parse-syslog
- https://www.elastic.co/guide/jp/x-pack/current/security-getting-started.html
- https://www.elastic.co/jp/blog/getting-started-with-security