yy16ki’s diary


スポンサードリンク

AWS CLIでVPC フローログを取得する

業務でAWSVPCフローログを扱う場面があったので,その基礎とCLIでのログ取得までを記事としました.

概要

VPCフローログは,VPCとネットワークインターフェース間を行き来するIPトラフィックに関する情報を取得できる機能です.下記に,公式ドキュメントより概要を引用します.

docs.aws.amazon.com

ログ取得対象
VPC
・サブネット
・ネットワークインターフェース

VPCやサブネットを対象とする場合は,それぞれのVPC/サブネット内の各ネットワークインターフェースがモニタリングの対象となります.
※ネットワークインターフェース:物理的な環境におけるNIC(Network Interface Card)に相当.インスタンスに付け替えることができる.(一つのEC2インスタンスに,複数のIPアドレスを付与したりできる.)

ログ保管場所
・CloudWatch Logs
Amazon S3

ログの形式

集約間隔
特定のフローがキャプチャされ、フローログレコードに集約される期間.デフォルトでは,600秒(10分)間隔.集約間隔内に取得されたログは,指定したサービス(CloudWatch Logs またはAmazon S3)に送信されます.送信には,それぞれ5~10分程度要するようです.

デフォルト形式
デフォルトの形式は,ドキュメントより確認できます.送信元/先のポート番号やIPアドレス,action(対象のトラフィックに対する処理 ACCEPT/REJECT)などを確認できます.

docs.aws.amazon.com

使いどころ

VPCフローログ自体は,ログを取得するサービスなので,監視という意味では他のサービスとの連携が必要となります.
・Guard DutyをONにして,異常検知時の詳細をVPCフローログで確認する.
・CloudWatch Alarmと連携し,特定の状況時に管理者に通知する. など

構成

今回は,下記の構成でVPCフローログの取得までを行います.
対象
・EC2インスタンス(ネットワークインターフェース)
ログ保管場所
・CloudWatch Logs

CLIでの環境構築

VPC~EC2インスタンスの構成までは,下記のコードで実施しました.

github.com

ここで,EC2作成時にuser-dataを指定し,Apacheを起動させています.

#!/bin/bash
yum update -y
yum install httpd -y
sudo systemctl start httpd.service

また,セキュリティグループを下記の通り設定しています.

IPバージョン タイプ ポート範囲 ソース
IPv4 HTTP 80 ${MYIP}/32
IPv4 SSH 22 ${MYIP}/32

手元の環境から,SSH接続とApacheの画面を確認出来たらフローログ作成に取り掛かります.

VPCフローログの取得

Cloud watch logs ロググループの作成

Cloud watch logs をログの送信先とするので,まずはロググループを作成します.
ログの作成後に,put-retention-policコマンドでログの保持期間を1日に変更しています.(デフォルトでは,保持期間が設定されない)

# Variables
PREFIX="blog"

# cloudwatch logs log group
aws logs create-log-group \
    --log-group-name "flow-logs" \
    --tags "Key=Name,Value=${PREFIX}-log-group"

aws logs put-retention-policy \
    --log-group-name "flow-logs" \
    --retention-in-days 1

VPCフローログの作成

EC2インスタンス(ネットワークインターフェース)に対するログを取得するので,そのIDを取得しcreate-flow-logsresource-idsに指定します.また,VPCフローログにCloud watch logs にログを送信するために必要な権限をIAMロールのArnを指定する形で付与します.

ENI_ID=$(aws ec2 describe-instances \
    --filters "Name=tag:Name,Values=${PREFIX}-instance" \
    --query "Reservations[].Instances[].NetworkInterfaces[].NetworkInterfaceId" \
    --output text) && echo ${ENI_ID}

aws ec2 create-flow-logs \
    --deliver-logs-permission-arn "arn:aws:iam::XXXXX:role/VpcFowlogsRole" \
    --log-group-name "flow-logs" \
    --resource-ids ${ENI_ID} \
    --resource-type "NetworkInterface" \
    --max-aggregation-interval 60 \
    --traffic-type ALL \
    --tag-specifications "ResourceType=vpc-flow-log,Tags=[{Key=Name,Value=${PREFIX}-flow-logs}]"

IAMロールは,下記の内容で作成しておきます.

CloudWatch Logs へのフローログの発行 - Amazon Virtual Private Cloud

その他の基本的なオプションは下記の通りです.

引数 内容
deliver-logs-permission-arn VPCフローログに設定するIAMロールのArn
log-group-name CloudWatch Logs logのロググループ名
resource-ids フローログ作成対象のID
resource-type フローログ作成対象のリソースタイプ(VPC,サブネット,ネットワークインターフェース等)
max-aggregation-interval パケットのフローをキャプチャし、フローログのレコードに集約する時間の最大間隔(60または600秒)
traffic-type ログ取得対象のトラフィックタイプ(ACCEPT,REJECT,ALL)

docs.aws.amazon.com

ログの確認

フローログを作成後,対象のEC2インスタンスに対し,SSH接続・HTTPリクエストを送り,ログを確認します.
デフォルトのログは下記のような形式です.送信先IP(dstaddr)は,プライベートIPアドレスとなります.MYIP(srcaddr)からEC2のプライベートIPアドレスの22/80番ポート宛に通信が走っていることが確認できます.

上:HTTPリクエスト 下:SSH接続

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/flow-logs.html

ログの形式を変更する

VPCフローログ作成後に,ログ形式の変更はできず,再作成する必要があります.先のVPCフローログを削除し,下記の通りlog-formatを指定することで,今度はログの形式を指定し作成します.

aws ec2 create-flow-logs \
    --deliver-logs-permission-arn "arn:aws:iam::XXXXX:role/VpcFowlogsRole" \
    --log-group-name "flow-logs" \
    --resource-ids ${ENI_ID} \
    --resource-type "NetworkInterface" \
    --max-aggregation-interval 60 \
    --traffic-type ALL \
    --log-format '${version} ${srcaddr} ${dstaddr} ${srcport}
     ${dstport} ${protocol} ${type} ${pkt-srcaddr} ${pkt-dstaddr} ${flow-direction} ${traffic-path} ${action}' \
    --tag-specifications "ResourceType=vpc-flow-log,Tags=[{Key=Name,Value=${PREFIX}-flow-logs}]"

新しくキャプチャされたログは下記のようになります.必要な情報のみを選択できるので,ログ保管のコスト削減も期待できそうです.

上:HTTPリクエスト 下:SSH接続

アクセス内容の確認
下記のブログにも記載がある内容ですが,フローログを確認すると多数のIPアドレスから様々なポート宛てにリクエストがあることがわかります.CloudWatch Logs Insightsで,今回作成したインスタンスに対し,セキュリティグループで拒否された通信の宛先ポート番号の一部を図にしています.利用環境に応じては,セキュリティグループをしっかりと設定しておくことは必須に感じます.

filter @message like /REJECT/
|parse  @message '* * * * * * * * * * * *' as version,srcaddr,dstaddr,srcport,dstport,protocol,type,pkt_srcaddr,pkt_dstaddr,flow_direction,traffic_path,action
| stats count(*) as Ports by dstport
| sort Ports desc
| limit 15

セキュリティグループでREJECTされた通信の接続先ポート番号
dev.classmethod.jp

まとめ

今回は,CLIでフローログを取得するところまでをまとめましたが,実運用ではこのログを監視し,異常があればアラートをあげる等あると思います.次回以降,簡単なイベント通知なども検証してみようと思います.今回は以上になります.


スポンサードリンク