Fluentdを使ってサーバへSSHログイン施行された通知をSlackに投げる

経緯

ふと、サーバのアクセスログどうなってるだろうなぁと思ってsyslogをチェックして見たときのことです

Aug  2 00:30:23 abyss sshd[2746]: Connection closed by invalid user postgres x.x.x.x port 43014 [preauth]
Aug  2 01:14:17 abyss sshd[5127]: Connection closed by invalid user mysql x.x.x.x port 56988 [preauth]
Aug  2 01:58:20 abyss sshd[6978]: Connection closed by invalid user databse x.x.x.x port 42794 [preauth]
Aug  2 02:42:41 abyss sshd[8365]: Connection closed by invalid user zabbix x.x.x.x port 56822 [preauth]
Aug  2 03:27:08 abyss sshd[9581]: Connection closed by invalid user zabbix x.x.x.x port 42636 [preauth]
Aug  2 04:11:52 abyss sshd[10680]: Connection closed by invalid user vagrant x.x.x.x port 56692 [preauth]
Aug  2 04:56:53 abyss sshd[11365]: Connection closed by invalid user gpadmin x.x.x.x port 42578 [preauth]
Aug  2 05:42:01 abyss sshd[12681]: Connection closed by invalid user testuser x.x.x.x port 56722 [preauth]
Aug  2 07:13:32 abyss sshd[16313]: Connection closed by invalid user default x.x.x.x port 56874 [preauth]
Aug  2 07:59:11 abyss sshd[18143]: Connection closed by invalid user server x.x.x.x port 42842 [preauth]
Aug  2 08:44:49 abyss sshd[19954]: Connection closed by invalid user user x.x.x.x port 57030 [preauth]
Aug  2 09:30:40 abyss sshd[21548]: Connection closed by invalid user tom x.x.x.x port 43002 [preauth]
Aug  2 10:16:42 abyss sshd[25537]: Connection closed by invalid user user1 x.x.x.x port 57218 [preauth]
Aug  2 11:02:58 abyss sshd[27489]: Connection closed by invalid user tomcat x.x.x.x port 43142 [preauth]
Aug  2 11:49:36 abyss sshd[30057]: Connection closed by invalid user user x.x.x.x port 57390 [preauth]
Aug  2 12:36:20 abyss sshd[775]: Connection closed by invalid user tomcat x.x.x.x port 43466 [preauth]
Aug  2 13:23:02 abyss sshd[3778]: Connection closed by invalid user tomcat x.x.x.x port 57706 [preauth]
Aug  2 14:10:11 abyss sshd[6332]: Connection closed by invalid user git x.x.x.x port 43814 [preauth]
Aug  2 14:57:30 abyss sshd[9167]: Connection closed by invalid user git x.x.x.x port 58116 [preauth]
Aug  2 15:45:06 abyss sshd[11630]: Connection closed by invalid user git x.x.x.x port 44248 [preauth]

見事に総当りでログイン試行されてました。
鍵認証で制限してるので適当なユーザで入ろうとしても無駄なわけですが、何となく気持ち悪いです。
せめて最近のWebサービスみたいな感じで、ログインされたら通知されるような仕組みがほしいですよね。

こんなかんじで。

ログイン施行されたら通知を出すという方法はいろいろありますが、今回はFluentd(td-agent)を使ってsyslogの認証ログを監視し、ログインに成功/失敗したログをSlackに投げるまでの流れを作ったので紹介します。

前提環境

Ubuntu18.04LTSでやります。ディストリビューションによっていくつかの手順は異なると思いますが、大雑把に同じ手順でいけると思います。
一応他の環境でやる場合の案内は軽く紹介します。

手順1.Fluentdを入れる

Fluentd(td-agent)はRuby製のログ集約ツールです。syslogやその他テキストログや、httpポートの監視等をして、フィルターをかけたログを別のサービス等に投げることができるプロダクトです。

手っ取り早く言えば、サーバログ監視版IFTTTみたいな感じです。類似のツールとして、Elastic社が開発しているLogstashなどがあります。

Ruby製なのでGemから入れることも出来ますが、今回はsyslogを監視する関係上、aptにリポジトリを追加してインストールする形で入れようと思います。

参考:Install by DEB Package (Debian/Ubuntu)
他のOSに導入したい場合は上記リンクから追いかけてください。

Ubuntuの場合、配布されているシェルスクリプトを実行するだけでaptリポジトリの追加からtd-agentのインストール、systemdの実行までしてくれるみたいです。

以下をrootで実行(Ubuntu18.04):

curl -L https://toolbelt.treasuredata.com/sh/install-ubuntu-bionic-td-agent3.sh | sh

手順2.fluentd-plugin-slackプラグインを導入する

Fluentdはプラグインを追加することで、様々なサービスと連携できるようになります。
今回はアウトプットにslackを利用するので、fluentd-plugin-slackを導入します。

以下をrootで実行:

td-agent-gem install fluent-plugin-slack

手順3.SlackのWebhook URLを取得する

SlackにHTTPリクエストを投げてチャンネルへ投稿できるようにするにはIncoming WebhookというAppを追加してやる必要があります。

自分は構築済みのIncoming Webhookを使用したのでスクリーンショットを撮ってません。代わりに以下のページを確認しながらWebhook URLを取得するまでやってみてください。
【Slack】これなら簡単!Webhookでメッセージ送信するまでの3ステップ

補足のざっくり手順
1. Slackのワークスペース管理ページからApp管理を選択
2. Incoming Webhookを検索し、追加する
3. カスタムインテグレーションからIncoming Webhookの設定を追加する
4. チャンネル名などを選択し、Webhook URLを生成する

手順4.Fluentdに設定を追加し、動作させてみる

コレまでの手順で連携させるための準備が整ったので、あとはFluentdの設定を追加し、実行させてみます。

/etc/td-agent/td-agent.conf をvimやnano等のテキストエディタで開き、ファイルの末尾に以下のコードを入力します。

<source>
 @type tail
 path /var/log/auth.log
 tag authwatch
 <parse>
   @type syslog
 </parse>
</source>

<filter authwatch.**>
 @type grep
 <regexp>
   key message
   pattern /session opened|Connection closed by invalid user|Did not receive identification string/
 </regexp>
 <exclude>
   key ident
   pattern /CRON/
 </exclude>
</filter>

<match authwatch.**>
 @type slack
 webhook_url https://hooks.slack.com/services/YOUR/WEBHOOK/URL
 channel YOUR_CHANNEL
 username SSH NOTIFICATION
 icon_emoji :exclamation:
 flush_interval 60s
</match>
​

後半の<match authwatch.**>ブロック内のパラメータは各環境に合わせて適宜修正してください。

保存して終了したら、サービスを再起動します。

systemctl restart td-agent.service

systemctl status td-agent.service

特にエラーがでなければ完了です。
後は実際にsshしてみて動作確認しましょう。

ログインに失敗した場合はちゃんとIPアドレスが表示されるので、どこからアクセスがあったかひと目で分かります。
sudo su - をした場合もログが出るので安心です。

こんな感じで、Fluentdを使ってsshログインの通知をSlackに投げるやつを導入してみました。

Fluentdは他にも様々なプラグインが用意されているので色々と試してみてください。syslogを確認する以外のことも出来ます。

サポートしてもいいことが有りません! 僕の酒代に消えます!!!