VPCフローログを使ってみたメモ。
また、Lambdaなどで使えるようにNode.jsで使えるログパーサーも作ったのでメモ
参考
事前準備
- EC2を起動する
- EC2にはssh(ポート22)のINBOUNDを許可したセキュリティグループを設定
VPCフローログとは
- VPC、サブネットもしくはEC2の特定のネットワークインターフェースでの通信ログをCloudWatchLogsに出力することができる機能
- キャプチャできるのは「許可されたトラフィック」、「拒否されたトラフィック」、「全てのトラフィック」の3種類
- 拒否されたトラフィックというのはセキュリティグループもしくはネットワークACLによってアクセスが拒否されたトラフィック
- パケットの中身についてはキャプチャできない(TCPプロトコルのACKやSYNの何が有効になったのかなど)
- 転送されたパケット数やパケットのバイト数はキャプチャできる
フローログ用のIAMロールを作成する
フローログの結果はCloudWatchLogsに出力されます。
ということでCloudWatchLogsへ出力するIAMロールを設定する必要があるので作成します。
- マネージメントコンソールからIAMを選択する
- Roles->Create New Role
- RoleNameに任意の名前を設定「VPCFlowLogRole」
- AWS Service RolesでEC2を選択
- Attach Policyで「CloudWatchLogsFullAccess」を選択
作成後、作成したロールにTrust Relationshipを設定します。
- マネージメントコンソールからIAMを選択する
- Roles->VPFlowFlogRoleを選択
- Trust Relationshipsタブを選択し、Edit Trust Relationshipを選択
- 以下のJSONをコピペして、Update Trust Policyを選択
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "vpc-flow-logs.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
フローログを有効化してみる
今回はEC2に設定された特定のNICのログを取得する方法でやってみます。
- マネージメントコンソールからEC2を選択
- Network Interfacesから検査対象にしたいEC2のネットワークインターフェースを選択する
- Flow Logsタブを選択し「Create Flow Log」ボタンを選択する
以下を選択します。
- Filter->All(RejectもAcceptも全てキャプチャ)
- IAMRole->VPCFlowLogRole
- DestinationLogGroup->/var/log/vpcflowlog
これでEC2の特定のネットワークインターフェースに対するフローログができました。
簡単ですね。
VPCフローログを見てみる
とりあえずsshログインして、少し待ちます。
数分時間が経つと取得できました。
上記よりわかる事。
- NTP(ポート123)の通信を行っている。セキュリティグループでINBOUNDの許可はしていないがOUTBOUNDは全て許可しているためEC2が送信元の通信トラフィックは可能であるため。(セキュリティグループはステートフルである)
- SSH(ポート22)でログインをしたのでそのトラフィックが記録されている
- 8080や3389ポートによるアクセスがされているが、セキュリティグループで許可していないので拒否(reject)した事が記録されている
- TCPの3ウェイハンドシェイクや切断、ACKによる通信確認のトラフィックは取得されていないように見える
Node.jsでログのパーサーを作ってみた
LambdaからElasticSearchなどに流す時に使えるようにログのパーサーを作ってnpmにあげてます。コードはGithubに置いてます。
ELBアクセスログのLmabda->ElasticSearchは以前記事でまとめたので同じようにやればできるかと思います。
Lambda+Elasticsearch(Amazon Elasticsearch Service)でELBのログをサーバーレスでKibanaで可視化する
インストールは以下でできます。
$npm install vpc-flow-log-parser
特徴としては以下です。
- それぞれの値をName:value形式にパースする
- プロトコル番号が出力されるので「protocol_name: 'TCP'」というように文字列でも出力。プロトコル番号はこちらを参照 Protocol Numbers
- キャプチャウィンドウの開始時間、終了時間がUnix時間で返却されるのでYYYY-MM-DD HH
ssフォーマットのUTCで「start_utc」及び「end_utc」として出力
言葉だと分かりにくいので実際に使ってみたものを確認下さい。
$node
> var parse = require('./index');
undefined
> parse('2 11111 eni-901258d8 133.130.120.204 172.31.23.15 123 123 17 3 228 1460005175 1460005449 ACCEPT OK')
{ version: '2',
account_id: '11111',
interface_id: 'eni-901258d8',
srcaddr: '133.130.120.204',
dstaddr: '172.31.23.15',
srcport: '123',
dstport: '123',
protocol: '17',
packets: '3',
byte: '228',
start: '1460005175',
end: '1460005449',
action: 'ACCEPT',
log_status: 'OK',
protocol_name: 'UDP',
start_utc: '2016-04-07 04:59:35',
end_utc: '2016-04-07 05:04:09' }
>
良かったら使ってみてください。