ぶろとよ

ネットワーク系クラウドエンジニア(AWS)の技術ブログ。自動化に興味があるためAWS CLIを勉強&アウトプット中。

AWS CloudShell:VPCフローログを設定する

以前、PowerShellを使ってVPC~EC2インスタンスまでの作成記事を書いて、その中にVPCフローログ設定も書いていたのですが、、、、久しぶりに読み返してみたら量が多くてみづらい・・・。VPCフローログ設定どこが必要なものなのかが分からない(汗

blog.toyokky.com

そのため、VPCフローログ部分を分割するとともに、AWS CloudShellを利用しての作成方法へと修正していきます。


本記事では、AWS CloudShellを利用して以下のVPC系リソースを作成します。

リソース種別 用途 Name 個別情報
IAMロール VPCフローログへ割り当てる権限 system-Pxx-Irl-Mnt-Vpcflowlogs ポリシーは「インラインポリシー」へ記載
インラインポリシー CloudWatch Logsの操作権限を記載 system-Pxx-Ipl-Mnt-Vpcflowlogs IAMロール内へポリシーを直接記載
CloudWatchロググループ VPCフローログのログ保管 /aws/vpc/flowlogs/blog-P1x-Vpc ログ保持期間: 1週間
VPCフローログ VPCの通信ログを取得する blog-P1x-Vfl-All 対象VPC: P1x-Vfl-All

※Nameの命名規則は自分ルール「AWSリソースの命名規則について」を使用します。
※本手順を利用する際は、上表「Name」や、文中「★」の置換をすると思います。


目次

検証環境

  • 検証日: 2022/09/24
  • 実行環境
    • PC
      • Windows10 Home Ver21H1
        • Google Chrome: バージョン: 105.0.5195.127(Official Build) (64 ビット)
    • AWSマネジメントコンソール
      • AWS CloudShell
        • AWS CLI: aws-cli/2.7.33 Python/3.9.11 Linux/4.14.287-215.504.amzn2.x86_64 exec-env/CloudShell exe/x86_64.amzn.2 prompt/off

注意事項

  • 本記事の内容はAWS CloudShellで検証しています。
  • AWS CLIはバージョン2を使用しています(CloudShellのデフォルトがバージョン2)。
  • コマンド内の変数やパラメータやは検証で使用したものを記載しています。ご自身の環境に合わせ、書き換えて使用してください。
  • 個人で検証しているため実行結果に責任は持てません。必ずご自身でも検証してから使用してください。


1. VPCフローログとは

VPC フローログは、VPC内のネットワークインターフェイスをモニタして、IPトラフィックの通信ログを記録する機能です。ログは CloudWatch Logs や S3 に保存できます。

VPC フローログを取得していると以下のようなシーンで役立ちます。

  • AWSの通信制御(セキュリティグループ/ネットワークACL)で通信が許可されてるかどうか
    • 対象のIP通信が「REJECT(拒否)」されている場合、AWSの通信制御で許可されていない
    • 対象のIP通信が「ACCEPT(許可)」なのに通信できない場合は、EC2内のOSで通信制御してたりする
  • インスタンスに到達するトラフィックをモニタリングできるため、「このIPがREJECT(拒否)されてるけど、必要だから許可しなきゃ」などの判断ができる
  • インターフェイスに出入りするトラフィックの方向が分かる
    • Outbound通信のみでInbound(戻り通信)が無い場合は、途中で通信がロストしてる、とか
  • VPC全体ではなく、サブネットやインターフェース単位でも通信ログが取れる

ただし、VPC内の通信を見ているため「DirectConnect」や「Site-to-Site VPN」などの通信は見れません。


VPCフローログの詳細は、公式AWSドキュメントに記載されています。

docs.aws.amazon.com


2. IAMロール

VPCフローログ用のIAMロールを作成します。
IAMポリシーを作成してからIAMロールへ割り当てる方法が一般的ですが、今回は「IAMロールを作成して、インラインポリシーとして直接ポリシーを書き込む」方法で行います。

※インラインポリシーにしている理由は、VPCフローログ毎にこのIAMロールを使い廻すから固定で良いのと、個人の趣味です。
※2022/09/24時点:以前はGUIでVPCフローログを作成する際、ついでにIAMロールの作成が出来たのですが、今は出来なくなってる!?


2.1. JSONファイルの作成

以下のJSONファイルを作成し、CloudShellのHomeディレクトリへ出力します。

ファイル名 用途
VpcFlologs_AssumeRole.json AssumeRole(信頼関係)の設定用
VpcFlologs_Policy.json VPCフローログへ適用するインラインポリシーの中身


2.1.1. JSONファイルの作成: AssumeRole(信頼関係)

AssumeRoleは、混乱する代理問題 に対応する形にしているため、AWSアカウントIDを採取しています。

# JSONファイル名を変数へ格納
jsonfile_assumerole="VpcFlologs_AssumeRole.json"

# AWSアカウントID
account_id=`aws sts get-caller-identity \
    --query "Account" \
    --output text` \
     && echo ${account_id}

# JSONファイルの作成
cat << EOF > ${jsonfile_assumerole}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "vpc-flow-logs.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "${account_id}"
        },
        "ArnLike": {
          "aws:SourceArn": "arn:aws:ec2:region:${account_id}:vpc-flow-log/*"
        }
      }
    }
  ]
}
EOF

# 作成確認
ls -l
    # > VpcFlologs_AssumeRole.json があること

cat ${jsonfile_assumerole}
     # > 入力した内容が表示され、エラーが無いこと


2.1.2. JSONファイルの作成: インラインポリシー用

# JSONファイル名を変数へ格納
jsonfile_policy="VpcFlologs_Policy.json"

# JSONファイルの作成
cat << EOF > ${jsonfile_policy}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
EOF

# 作成確認
ls -l
    # > VpcFlologs_Policy.json があること

cat ${jsonfile_policy}
     # > 入力した内容が表示され、エラーが無いこと


2.2. IAMロールの作成

# 変数の指定
iam_role_name="system-Pxx-Irl-Mnt-Vpcflowlogs"  #★環境により修正
iam_role_description="Allows VPCflowlogs to call CloudWatch Logs on your behalf."
jsonfile_assumerole="VpcFlologs_AssumeRole.json"

# IAMロールの作成
aws iam create-role \
    --role-name ${iam_role_name} \
    --description "${iam_role_description}" \
    --assume-role-policy-document file://${jsonfile_assumerole} \
    --tags "Key=Name,Value=${iam_role_name}"


2.3. IAMロールへインラインポリシーを適用する

# 変数の指定
iam_role_name="system-Pxx-Irl-Mnt-Vpcflowlogs"  #★環境により修正
iam_policy_name="system-Pxx-Ipl-Mnt-Vpcflowlogs"  #★環境により修正
jsonfile_policy="VpcFlologs_Policy.json"

# IAMロールへインラインポリシーを適用する
aws iam put-role-policy \
    --role-name ${iam_role_name} \
    --policy-name ${iam_policy_name} \
    --policy-document file://${jsonfile_policy}


2.4. 確認コマンド

# IAMロール
## すべて表示する
aws iam list-roles

## 名前を指定して表示
iam_role_name="system-Pxx-Irl-Mnt-Vpcflowlogs"  #★環境により修正
aws iam get-role \
    --role-name ${iam_role_name}

## IAMロールにアタッチされているインラインポリシーを表示
iam_role_name="system-Pxx-Irl-Mnt-Vpcflowlogs"  #★環境により修正
aws iam list-role-policies \
    --role-name ${iam_role_name}

## IAMロールにアタッチされているインラインポリシーの中身を表示
iam_role_name="system-Pxx-Irl-Mnt-Vpcflowlogs"  #★環境により修正
policy_name="system-Pxx-Ipl-Mnt-Vpcflowlogs"  #★環境により修正
aws iam get-role-policy \
    --role-name ${iam_role_name} \
    --policy-name ${policy_name}


3. CloudWatch Logs

3.1. ロググループの作成

# 変数の指定
loggroup_name="/aws/vpc/flowlogs/blog-P1x-Vpc"  #★環境により修正

# ロググループの作成
aws logs create-log-group \
    --log-group-name ${loggroup_name} \
    --tags "Name=${loggroup_name}"


3.2. ログの保管期間(Retention)設定

何日経過したらログを削除するかを設定します。
個人用の設定なので、とりあえず「7日」で設定しています。

# 変数の指定
loggroup_name="/aws/vpc/flowlogs/blog-P1x-Vpc"  #★環境により修正
retention_days="7"  #★環境により修正
    # 選択値: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653

# ログの保管期間(Retention)設定
aws logs put-retention-policy \
    --log-group-name ${loggroup_name} \
    --retention-in-days ${retention_days}


3.3. 確認コマンド

# すべて表示する
aws logs describe-log-groups

# 名前を指定して表示
loggroup_name="/aws/vpc/flowlogs/blog-P1x-Vpc"  #★環境により修正
aws logs describe-log-groups \
    --log-group-name-prefix ${loggroup_name}


4. VPCフローログ

「対象VPC: P1x-Vfl-All」へVPCフローログを設定します。

4.1. ログ形式(log-format)

ログ形式はデフォルトが使いづらいのでカスタム形式にしています。
日頃、インスタンスへ通信が来ているか、拒否されていないかを見ているので、あまり細かいものは見ていないです。

# ログ形式(デフォルト)
${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}

# カスタム形式 ← これで設定します。
${interface-id} ${srcaddr} ${srcport} ${dstaddr} ${dstport} ${protocol} ${action} ${log-status}
※ENI-ID, 送信元IP, 送信元ポート, 宛先IP, 宛先ポート,プロトコル, アクション, ログ状態
  • プロトコル${protocol}の番号は コチラ を参照
  • アクション${action}
    • ACCEPT : トラフィックが承認されました。
    • REJECT : トラフィックが拒否されました。 例)セキュリティグループまたはネットワーク ACL により許可されていない
  • フローログのロギングステータス${log-status}
    • OK : データは送信先に正常に記録された
    • NODATA : 集約間隔内(1分 or 10分)にネットワークトラフィックが無い
    • SKIPDATA : 集約間隔内(1分 or 10分)に一部のフローログレコードがスキップされた
      • 内部的なキャパシティー制限、または内部エラーが原因である可能性がある


4.2. VPCフローログの作成

# 対象VPCのIDを変数へ格納する
vpc_name="blog-P1x-Vpc"  #★環境により修正、対象VPCのNameタグ
vpc_id=`aws ec2 describe-vpcs \
    --filters "Name=tag:Name,Values=${vpc_name}" \
    --query "Vpcs[].VpcId" \
    --output text` \
    && echo ${vpc_id}

# IAMロールのARNを変数へ格納
iam_role_name="system-Pxx-Irl-Mnt-Vpcflowlogs"  #★環境により修正
iam_role_arn=`aws iam get-role \
    --role-name ${iam_role_name} \
    --query "Role.Arn" \
    --output text` \
    && echo ${iam_role_arn}

# VPCフローログの作成
flowlog_name="blog-P1x-Vfl-All"  #★環境により修正
loggroup_name="/aws/vpc/flowlogs/blog-P1x-Vpc"  #★環境により修正
log_format='${interface-id} ${srcaddr} ${srcport} ${dstaddr} ${dstport} ${protocol} ${action} ${log-status}'  #★環境により修正

aws ec2 create-flow-logs \
    --resource-type VPC \
    --resource-ids ${vpc_id} \
    --traffic-type ALL \
    --max-aggregation-interval 600 \
    --log-destination-type cloud-watch-logs \
    --log-group-name ${loggroup_name} \
    --deliver-logs-permission-arn ${iam_role_arn} \
    --log-format "${log_format}" \
    --tag-specifications "ResourceType=vpc-flow-log, \
        Tags=[{Key=Name,Value=${flowlog_name}}]"


4.3. 確認コマンド

# すべて表示する
aws ec2 describe-flow-logs

# 名前を指定して表示
flowlog_name="blog-P1x-Vfl-All"  #★環境により修正
aws ec2 describe-flow-logs \
    --filter "Name=tag:Name,Values=${flowlog_name}"