CloudWatch LogsでSSHへの不正アクセスを検知し、通知を受ける。

こんにちは。
皆さんの多くはWebサーバを運用した経験がお有りですよね。
多くのサーバでは、リモートから接続するときにはSSHでログインします。
僕らがダイスキなAmazon Web Services、AWSでも、作成したサーバにSSHで接続可能です。
SSHでサーバを操作することで世の中に便利なソフトウェアサービスを提供することができます。

が、しかし、その便利なSSHを使って、悪い人がサーバにアクセスを仕掛けてきたらどうでしょう？もし万が一乗っ取られてしまったら？あなたの便利なソフトウェアやサービスが書き換えられ、世の中の害悪になってしまうかもしれません。
![ssh_watch.png](https://qiita-image-store.s3.amazonaws.com/0/25176/832469db-6349-7c3c-fc92-84663e210c2a.png)


# 不正アクセスを検知しましょう。AWSの機能を使って。
僕らがダイスキ（2回目）AWSの機能を使って、SSHへの不正アクセスがあった時にそれを検知して、通知を受け取ることができます。
本投稿では、その手順をご紹介します。
なお、この投稿を実施することですべての不正アクセスが検知できる/防止できるわけではもちろんありませんのでご了承ください。

# 本投稿で登場するAWSのサービス
- EC2 - この上でWebサーバを運用することを仮定します。EC2でなくても可ですが、本投稿とはCloudWatch Logsのエージェントインストール方式が替わります。
- CloudWatch Logs - ログ収集＋保持サービス
- IAM - EC2やAWSアカウントの権限管理。本投稿ではEC2にIAMロールを割り当てます。
- SNS 僕らがダイスキAWSの通知機能。本投稿ではメール通知するように設定したSNSに連携しています。本投稿では詳しくは説明しませんが、SNSを使えばHTTP発呼や、メールやスマフォに通知することができます。

# 不正アクセス検知手順
さて、実際の手順をご説明します。

## 概要
1. CloudWatch Logs投稿用IAMロールを作成
2. ロールを持ったEC2立てる。
3. 不正アクセス時のログ確認
4. EC2上にCloudWatch Logsをインストール・設定する。
5. SNSを作成する。（本投稿ではメールが飛ぶように。）
6. AWSコンソールからCloudWatch Logsを設定し、通知が飛ぶようにする。

## 手順
### 1. CloudWatch Logs投稿用IAMロールを作成
公式の手順は[こちら](http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/DeveloperGuide/QuickStartEC2Instance.html)で、こちらにそって実行していきます。
AWSコンソールにログインし、IAMロールを作成します。

コンソールに入り・・・
<img width="908" alt="スクリーンショット 2015-10-13 12.14.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/88283218-ab2a-6eaf-3cee-fbb7ce6495dc.png">

Identity & Access Management（IAM）を選択し、
<img width="225" alt="スクリーンショット 2015-10-13 12.15.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/f7a94113-9ef8-0e18-ef96-93d3517ed0c1.png">
ロールを選択し、
<img width="849" alt="スクリーンショット 2015-11-26 16.45.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/8deffd95-7a25-3638-47a6-08cac95f819e.png">
「新しいロールを作成」を押し、
<img width="888" alt="スクリーンショット 2015-11-26 16.46.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/541ffb85-4144-715b-6f37-7a6aa4c2ad59.png">
ロールタイプを適当に選択します。（ロールタイプはあとから削除するので適当につけます。本投稿ではAmazon EC2→ CloudWatchLogsFullAccessを選択しました。）
<img width="1126" alt="スクリーンショット 2015-11-26 16.50.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/ed6fb090-d4c6-48e9-b3e0-47e8502e53c9.png">
次の画面でロールの作成ボタンを押します。
作成したロールを選択し、インラインポリシーを押して、「ここをクリックしてください。」を押します。
<img width="1141" alt="スクリーンショット 2015-11-26 16.56.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/7cbb2ae2-9816-e8b1-5f6a-09ddd05d0c99.png">
カスタムポリシーの選択を押し、[こちら](http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/DeveloperGuide/QuickStartEC2Instance.html)のポリシーを入力します。
<img width="1146" alt="スクリーンショット 2015-11-26 16.58.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/9316e860-ae4d-8870-830d-18071adacb28.png">
ポリシーの適用を押します。
<img width="889" alt="スクリーンショット 2015-11-26 17.00.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/add05a67-a909-0542-7ac0-1c50e179c760.png">
CloudWatchLogsFullAccessの方は「ポリシーのデタッチ」をしておきます。
ロールポリシーを直接作りたかったのですが、やり方がワカリマセンでした。できた方はコメントください。
これでロールの作成は完了です。

引き続きまして、このロールをもつEC2を作成します。

### 2. ロールを持ったEC2立てる。
いろいろすっ飛ばしますが、IAMロールに先ほど作ったロールを設定しておきます。
<img width="1146" alt="スクリーンショット 2015-11-26 17.05.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/ea5f7fa7-7485-5b2a-bb1e-837907f73629.png">

引き続きまして、取得するログの確認です。

### 3. 不正アクセス時のログ確認
引き続きまして、今回引っ掛けたいログを確認しておきます。
作成したEC2にログインして、

```shell-session
[ec2-user@ip-10-0-0-169 ~]$ sudo tail -f /var/log/secure 
```
します。そして、他のサーバからSSHでアクセスします。
うまくいくと

```shell-session
Nov 26 08:23:07 ip-10-0-0-169 sshd[14178]: Accepted publickey for ec2-user from 10.0.0.167 port 52047 ssh2: RSA XXXXXXXXXXXXXXXXXXXXX
Nov 26 08:23:07 ip-10-0-0-169 sshd[14178]: pam_unix(sshd:session): session opened for user ec2-user by (uid=0)
```
のようなログが、
変な鍵やカギ無しでアクセスすると

```shell-session
Nov 25 08:21:45 ip-10-0-0-169 sshd[24078]: Connection closed by 10.0.0.167 [preauth]
```
のようなログが出ることがわかりました。
今回は[preauth]という文字を引っ掛けてエラーと判断します。

今回は説明の簡易化のために、未設定で出力されるログから引っ掛けるようにしていますが、本番設定するときは適切な設定及びログを設計してください。

### 4. EC2上にCloudWatch Logsをインストール・設定する。
EC2上で、以下のコマンドでインストールを行います。

```shell-session
[ec2-user@ip-10-0-0-169 ~]$ sudo yum update -y
[ec2-user@ip-10-0-0-169 ~]$ sudo yum install -y awslogs
```
これでインストールは完了、引き続き設定を行います。

```shell-session
sudo vi /etc/awslogs/awscli.conf
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1
```
regionはログを入れたいリージョンの場所を入れます。上記はみんな大好き東京です。

引き続きどのログを CloudWatch Logs で収集するかを設定します。

```shell-session
sudo vi /etc/awslogs/awslogs.conf
[/var/log/messages]
datetime_format = %b %d %H:%M:%S
file = /var/log/messages
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/messages
```
デフォルトでは[/var/log/messages]を収集しています。ここに[/var/log/secure]を設定します。以下を追記。

```shell-session
[/var/log/secure]
datetime_format = %b %d %H:%M:%S
file = /var/log/secure
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/secure
```

logsエージェントを起動、サービス化します。

```shell-session
sudo service awslogs start
sudo chkconfig awslogs on
```

これで/var/log/secureが収集されるようになりました。

### 5. SNSを作成する。（本投稿ではメールが飛ぶように。）
SNSを作成して、メールが来るようにします。
AWSコンソールのCloudWatchを開きます。
<img width="1211" alt="スクリーンショット 2015-11-27 17.58.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/fab3e651-8af3-f5e3-1439-d890b7f7c03d.png">
SNSを選択して、
<img width="1152" alt="スクリーンショット 2015-11-30 10.32.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/99115da7-f150-be2b-8c64-68cf5858b6be.png">
Create Topicを選択して、
<img width="895" alt="スクリーンショット 2015-11-30 10.32.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/0e8e65e3-66a7-324a-f5ce-14e08cd155b9.png">
適当な名前をつけます。この名前をあとからCloudWatch Logsのアラートにひも付けます。
Create topicを押して、
<img width="1153" alt="スクリーンショット 2015-11-30 10.33.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/98bbc066-28a3-1ece-1a44-b615d11003da.png">
Create Subscriptionを押します。
<img width="893" alt="スクリーンショット 2015-11-30 10.33.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/701e5a15-ec96-4d19-0267-29d49663cce9.png">
Emailを選択して、Endpointに送信したいメールアドレスを入力し、Create Subscriptionを押します。
Endpointに設定したメールアドレスに送信していいかを確認するメールが届いているので、メール中のConfirm subscriptionリンクを押して完成です。
これでSNSに通知があるとメールが送信されるようになります。

### 6. AWSコンソールからCloudWatch Logsを設定し、通知が飛ぶようにする。
AWSコンソールのCloudWatchを開きます。
<img width="1211" alt="スクリーンショット 2015-11-27 17.58.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/fab3e651-8af3-f5e3-1439-d890b7f7c03d.png">

ログを押します。
<img width="1210" alt="スクリーンショット 2015-11-27 17.59.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/668f43d9-bf1d-3610-d5a6-4d463cd97303.png">

/var/log/secureの「0フィルタ」リンクを押します。
<img width="1196" alt="スクリーンショット 2015-11-27 18.07.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/6b054405-b9cc-d166-4f51-1eb15099990b.png">

メトリックスフィルタの追加を押します。
<img width="865" alt="スクリーンショット 2015-11-27 18.08.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/dfa4821c-bb81-f744-e1e8-442390da6b8e.png">

フィルタパターンに引っ掛けたい文字を""でくくった、"[preauth]"を入力して、メトリックスの割当を押します。
<img width="1144" alt="スクリーンショット 2015-11-30 10.55.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/1a7e74d2-88df-12cf-4b47-e2f0776898a9.png">
メトリックス名を入れて、フィルタの作成ボタンを押します。
引き続いて、アラームの作成リンクを押します。
適切な入力します。キモは、「間隔」「統計」と「次の時」です。「間隔（１分）」の間に「統計（合計）」「次の時（１回以上）」を「次の時（１回連続したら）」のようなしきい値を設定し、それが発生したらアクションを起こします。アクションにはSNSを設定しておくと良いです。myTopicは予め設定しておいたSNSトピックです。私にメールが来るようになっています。
<img width="944" alt="スクリーンショット 2015-11-30 11.04.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/34a34fcc-bc8d-93ff-8c12-9febe04c83ce.png">

これで変なSSHアクセスが来たら私にメールが来るようになりました。

# 実験
カギ無しでsshしてみます。

```shell-session
ssh root@localhost
```

しばらくすると、私にメールが飛んできました。

```
Alarm Details:
- Name:                       変なSSHアクセスがありましたよ。
- Description:                
- State Change:               INSUFFICIENT_DATA -> ALARM
- Reason for State Change:    Threshold Crossed: 1 datapoint (6.0) was greater than or equal to the threshold (1.0).
- Timestamp:                  Monday 30 November, 2015 02:04:10 UTC
- AWS Account:                XXXXXXXXXXXX
```

いいですねいいですね。(XXXXXXXXは伏せ字)
これでサーバがやばそうな雰囲気だったら察知することができます。


# 応用編
本投稿で説明した手順を実行すると、ログ出力を拾って、サーバに集め、特定のログが特定の状況で発生していたら通知を受けることができます。したがって、SSHの不正アクセスだけではなく、Webサーバで500エラーがあった時や、sudoイベントを拾って変なsudoがされた時も検知することができます。応用してみてください。
ログ監視も簡単！そう、僕らがダイスキAWSならね！(何回目？)