ようへいの日々精進XP

よかろうもん

VPC Flow Logs Tutorial

tl;dr

www.slideshare.net

上記の資料を読んでいたら VPC Flow Logs というサービスがリリースされているのを知ったのでどのようなものかをチュートリアルしてみた。


VPC Flow Logs とは

参考

VPC Flow Logs の詳細、制限事項等については上記の記事にお任せ。ありがとうございます。

ユースケース

想定されるユースケースとしては...(Slide Share の記事より引用)

等。

flow log を見てみる

前後するけど flow log とはどげなもんなのかを AWS CLI で確認する。

#
# log group を確認
#
$ aws logs describe-log-groups
{
    "logGroups": [
        {
            "arn": "arn:aws:logs:ap-northeast-1:1234567890123:log-group:my-flow-log:*",
            "creationTime": 1441171757731,
            "metricFilterCount": 0,
            "logGroupName": "my-flow-log",
            "storedBytes": 295044
        }
    ]
}

#
# log stream の確認
#
$ aws logs describe-log-streams --log-group-name my-flow-log --limit 1
{
    "nextToken": "Kwfr0bfVKkYk4OrYazFRiV9H8rv4UGy1FbpS1glScpQSaNRo5QzdVDFjcfNhUHBLGZ2o2Gjxtlg9X4bBz7A4o1AZPXuMpUPe4rmZeTMdAPLFJzThySAcBa4y8klGKJgC9dwd4QyKSQ-f-VVvDFHxQ1Ir7MBofhZichsiaW_YEEaUFuvyLBWpElCBHPw1vXFlb1M8qpkQLoAgtyvr1_q9Icrbb-nio4DueZ-rV9osAPSNptfa6HktfykKubkWc-0ziWV1PZyBiA4SeXJjQ9MBY0IujbvmAgX0t2-ne58b_bXOa0LzKo6Tvl1dTqd_3HK1BGXnwwUuoxT18GqEkUGlqWPJb00xQrDjIvuDXWaZL5iluonc4Da-hp0XZpbLPGdtVTp9oC2nXlieJZSaUW380BiaQ609JGGoTofv0fhX2R8",
    "logStreams": [
        {
            "firstEventTimestamp": 1441198464000,
            "lastEventTimestamp": 1441204404000,
            "creationTime": 1441199107032,
            "uploadSequenceToken": "49545657805769367170690858206544188070413463828968768866",
            "logStreamName": "eni-75ba322d-all",
            "lastIngestionTime": 1441204508413,
            "arn": "arn:aws:logs:ap-northeast-1:1234567890123:log-group:my-flow-log:log-stream:eni-75ba322d-all",
            "storedBytes": 0
        }
    ]
}

#
# 実際の log の確認
#
$ aws logs get-log-events --log-group-name my-flow-log --log-stream-name eni-xxxxxx-all --limit 1
{
    "nextForwardToken": "f/32139928691387192232880068449704027033738899140716593658",
    "events": [
        {
            "ingestionTime": 1441204368952,
            "timestamp": 1441204247000,
            "message": "2 1234567890123 eni-xxxxxxxx xx.x.x.xxx yy.y.y.yyy 49907 80 6 4 216 1441204247 1441204306 ACCEPT OK"
        }
    ],
    "nextBackwardToken": "b/32139928691387192232880068449704027033738899140716593658"
}
  • nextForwardTokennextBackwardToken が気になる(後述)

教材

今回も Terraform にて教材を用意。

github.com

terraform apply を実行すると下図のような環境が作成される。(はず!)

f:id:inokara:20150904170441p:plain

尚、事前に AWS CLI にて CloudWatch Logs の log-group-name を作成しておく必要がある。

#
# aws cli のバージョン確認
#
$ aws --version
aws-cli/1.7.29 Python/2.7.9 Windows/8]

#
# CloudWatch Logs の log-group-name を作成
#
$ aws logs create-log-group --log-group-name my-flow-log

#
# 作成済みの log-group を確認
#
$ aws logs describe-log-groups
{
    "logGroups": [
        {
            "arn": "arn:aws:logs:ap-northeast-1:1234567890123:log-group:my-flow-log:*",
            "creationTime": 1441171757731,
            "metricFilterCount": 0,
            "logGroupName": "my-flow-log",
            "storedBytes": 295044
        }
    ]
}

メモ

実際のログを見てみる

  • ログストリームの確認
$ aws logs describe-log-streams --log-group-name my-flow-log
{
    "logStreams": [
        {
            "firstEventTimestamp": 1441325286000,
            "lastEventTimestamp": 1441341377000,
            "creationTime": 1441325893365,
            "uploadSequenceToken": "49545657805903171641881967696867665731736007865060558786",
            "logStreamName": "eni-a969e3f1-all",
            "lastIngestionTime": 1441341496403,
            "arn": "arn:aws:logs:ap-northeast-1:123456789012:log-group:my-flow-log:log-stream:eni-a969e3f1-all",
            "storedBytes": 277212
        },
        {
            "firstEventTimestamp": 1441325567000,
            "lastEventTimestamp": 1441341717000,
            "creationTime": 1441326209899,
            "uploadSequenceToken": "49545657805635562699499671795513147378461817750733979906",
            "logStreamName": "eni-c26fe59a-all",
            "lastIngestionTime": 1441341812948,
            "arn": "arn:aws:logs:ap-northeast-1:123456789012:log-group:my-flow-log:log-stream:eni-c26fe59a-all",
            "storedBytes": 62674
        },
        {
            "firstEventTimestamp": 1441325390000,
            "lastEventTimestamp": 1441341480000,
            "creationTime": 1441325991488,
            "uploadSequenceToken": "49545657805724765680293733998369590602400046244230595906",
            "logStreamName": "eni-c46ee49c-all",
            "lastIngestionTime": 1441341594125,
            "arn": "arn:aws:logs:ap-northeast-1:123456789012:log-group:my-flow-log:log-stream:eni-c46ee49c-all",
            "storedBytes": 53253
        }
    ]
}

上記の通り ENI 毎にストリームが作成されていることが判る。また、プロトコルは指定していないのでストリーム名が eni-xxxxxxx-all となっている。

  • ログの確認
$ aws logs get-log-events --log-group-name my-flow-log --log-stream-name eni-c46ee49c-all --limit 1
{
    "nextForwardToken": "f/32142989089553022185885816715984568394922307628562055307",
    "events": [
        {
            "ingestionTime": 1441341594125,
            "timestamp": 1441341480000,
            "message": "2 123456789012 eni-c46ee49c 10.0.1.218 10.0.1.63 80 54033 6 2 112 1441341480 1441341532 ACCEPT OK"
        }
    ],
    "nextBackwardToken": "b/32142989089553022185885816715984568394922307628562055307"
}

message のスペースで句切られた値が実際のログメッセージとなる。尚、各フィールドについては以下のとおり(ドキュメントより抜粋)。

フィールド 説明
バージョン VPC フローログバージョン。
account-id フローログの AWS アカウント ID。
interface-id ログストリームが適用されるネットワークインターフェイスの ID。
srcaddr 送信元 IP アドレス。ネットワークインターフェイスの IP アドレスは常にそのプライベート IP アドレスです。
dstaddr 送信先 IP アドレス。ネットワークインターフェイスの IP アドレスは常にそのプライベート IP アドレスです。
srcport トラフィックの送信元ポート。
dstport トラフィックの送信先ポート。プロトコル トラフィックの IANA プロトコル番号。詳細については、「割り当てられたインターネットプロトコル番号」を参照してください。
packets キャプチャウィンドウ中に転送されたパケットの数。
bytes キャプチャウィンドウ中に転送されたバイト数。
start キャプチャウィンドウの開始時刻(Unix 時間)。
end キャプチャウィンドウの終了時刻(Unix 時間)。
action トラフィックに関連付けられたアクション: ACCEPT: 記録されたトラフィックは、セキュリティグループまたはネットワーク ACL で許可されています。REJECT: 記録されたトラフィックは、セキュリティグループまたはネットワーク ACL で許可されていません。
log-status フローログのロギングステータス。OK: データは正常に CloudWatch Logs に記録されています。NODATA: キャプチャウィンドウ中にネットワークインターフェイスとの間で行き来するネットワークトラフィックはありませんでした。SKIPDATA: 一部のフローログレコードはキャプチャウィンドウ中にスキップされました。これは、内部的なキャパシティー制限、または内部エラーが原因である可能性があります。

なるほど、なるほど。

上記の例だと...

  • 対象のネットワークインターフェースは eni-c46ee49c
  • 送信元は 10.0.1.218
  • 宛先は 10.0.1.63
  • 送信元ポートは 80
  • 宛先ポートは 54033

で許可された通信と読み取ることが出来る。

メトリクスフィルタ

尚、CloudWatch Logs にはフィルタを定義した上で、設定したフィルタにマッチしたログをモニタリングすることが出来る。

  • メトリクスフィルタのテスト

フィルタ定義のテストをすることが出来る。

aws logs test-metric-filter \
        --filter-pattern '[version,account_id,interface_id,srcaddr,dstaddr,srcport,dstport=80,protocol,packets,bytes,start,end,action,log_status]' \
        --log-event-messages '2 1234567890123 eni-xxxxxxxx xx.x.x.xxx yy.y.y.yyy 49907 80 6 4 216 1441204247 1441204306 ACCEPT OK'

以下のように出力される。

{
    "matches": [
        {
            "eventNumber": 1,
            "eventMessage": "2 1234567890123 eni-xxxxxxxx xx.x.x.xxx yy.y.y.yyy 49907 80 6 4 216 1441204247 1441204306 ACCEPT OK",
            "extractedValues": {
                "$dstaddr": "yy.y.y.yyy",
                "$dstport": "80",
                "$start": "1441204247",
                "$account_id": "1234567890123",
                "$action": "ACCEPT",
                "$packets": "4",
                "$protocol": "6",
                "$interface_id": "eni-xxxxxxxx",
                "$bytes": "216",
                "$version": "2",
                "$srcaddr": "xx.x.x.xxx",
                "$log_status": "OK",
                "$srcport": "49907",
                "$end": "1441204306"
            }
        }
    ]
}
  • メトリクスフィルタの定義

テストしたフィルタを定義する。

aws --region ap-northeast-1 logs put-metric-filter \
    --log-group-name "my-flow-log" \
    --filter-name "SSHAccess" \
    --filter-pattern '[version,account_id,interface_id,srcaddr,dstaddr,srcport,dstport=22,protocol,packets,bytes,start,end,action,log_status]' \
    --metric-transformations 'metricValue=1,metricNamespace=foo,metricName=bar'
  • メトリクスフィルタの確認
$ aws --region ap-northeast-1 logs describe-metric-filters --log-group-name my-flow-log
{
    "metricFilters": [
        {
            "filterName": "SSHAccess",
            "metricTransformations": [
                {
                    "metricValue": "1",
                    "metricNamespace": "LogMetrics",
                    "metricName": "SSHAccess"
                }
            ],
            "creationTime": 1441343985034,
            "filterPattern": "[version,account_id,interface_id,srcaddr,dstaddr,srcport,dstport=22,protocol,packets,bytes,start,end,action,log_status]"
        },
        {
            "filterName": "version-account-id-interface-id-srcaddr-dstaddr-srcport-dstport-80-protocol-packets-bytes-start-end-action-log-status",
            "metricTransformations": [
                {
                    "metricValue": "1",
                    "metricNamespace": "LogMetrics",
                    "metricName": "HTTPAccess"
                }
            ],
            "creationTime": 1441343592012,
            "filterPattern": "[version,account_id,interface_id,srcaddr,dstaddr,srcport,dstport=80,protocol,packets,bytes,start,end,action,log_status]"
        }
    ]
}                                                                                                                                                   

フィルタを定義するとフィルタに対するアラートを設定することが出来る。

f:id:inokara:20150904143610p:plain

暫くすると CloudWatch のメトリクスとしても確認することが出来るようになる。

f:id:inokara:20150904143703p:plain

なるほど。


ということで

ざくっと VPC Flow Logs と CloudWatch Logs を弄ってみたけどログなのでリアルタイム処理をしてみたいので CloudWatch Logs Subscriptions を利用して VPC Flow Logs のログを弄ってみたいと思う。

つづく。