AWSでシステムを運用していると、こうした「見えない」不安を感じる場面があります。特にセキュリティインシデントが起きた後に「いつ・どこから・どのポートに対して通信があったか」を遡って調べられない状況は、運用上の深刻なリスクです。
AWS VPC Flow Logsは、VPCを流れるIPトラフィックの情報をS3またはCloudWatch Logsへ記録するマネージドサービスです。セキュリティグループやNACLによるACCEPT・REJECTの記録から、送信元IPアドレス・宛先ポートまで、VPCを通過するすべての通信を可視化できます。この記事では、AWS CLI 2.xで動作確認した手順をもとに、Flow Logsの有効化・レコードの読み方・実務での活用パターン・コスト設計まで解説します。
この記事のポイント
・aws ec2 create-flow-logsでVPC・サブネット・ENIの3レベルで有効化できる
・actionフィールドがREJECTの記録を絞り込むと不審アクセスを素早く特定できる
・S3送信はコストが低く長期保存向き、CloudWatch Logsはリアルタイム分析に強い
・traffic-type REJECTから始めて必要に応じてALLに拡張するのがコスト効率のよい設計
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
VPC Flow Logsとは何か|VPCのすべてのIPトラフィックを記録する仕組み
VPC Flow Logsは、VPC内のネットワークインターフェース(ENI)を通過するIPトラフィックのメタデータを記録するAWSのサービスです。送信元・宛先のIPアドレスとポート番号、プロトコル番号、パケット数・バイト数、そしてセキュリティグループ/NACLによる「ACCEPT」または「REJECT」の判定結果を、一定の集計期間(通常10分前後)でログとして出力します。Flow Logsを有効化できる対象は3レベルあります。
・VPCレベル:VPC全体のすべてのENIが対象。最も広い範囲で通信を記録できる
・サブネットレベル:特定のサブネット内のENIが対象。テスト用サブネットを除外したい場合などに使う
・ENIレベル:特定のネットワークインターフェースのみを対象にする。範囲を絞ることでコストを抑えられる
ログの送信先はAmazon S3、Amazon CloudWatch Logs、またはAmazon Kinesis Data Firehoseの3択です。長期保存・コスト重視ならS3、リアルタイム分析・アラート設定ならCloudWatch Logsが定番の選択肢です。
ひとつ重要な注意点があります。Flow Logsはパケットのメタデータを記録するサービスであり、通信の中身(ペイロード)は記録しません。「いつ・どこから・どこへ・何ポートへ通信があったか」を記録するためのサービスです。HTTP/HTTPSの通信内容を調べたい場合は、ALBのアクセスログやCloudFrontのディストリビューションログを使います。
VPC Flow Logsを有効化する手順|CLIでS3へ送信する設定
S3を送信先にする場合、バケットポリシーでVPC Flow LogsサービスへのPutObject権限を付与する必要があります。バケットポリシーを設定したうえでaws ec2 create-flow-logs コマンドを実行します。1. S3バケットにバケットポリシーを設定する
以下のバケットポリシーをJSONファイルとして保存し、対象バケットに適用します。123456789012 はご自身のAWSアカウントIDに置き換えてください。# bucket-policy.json として保存する { "Version": "2012-10-17", "Statement": [ { "Sid": "AWSLogDeliveryWrite", "Effect": "Allow", "Principal": { "Service": "delivery.logs.amazonaws.com" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::my-flowlogs-bucket/vpc-logs/AWSLogs/123456789012/*", "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control", "aws:SourceAccount": "123456789012" } } }, { "Sid": "AWSLogDeliveryAclCheck", "Effect": "Allow", "Principal": { "Service": "delivery.logs.amazonaws.com" }, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::my-flowlogs-bucket" } ] } # バケットポリシーを適用する aws s3api put-bucket-policy \ --bucket my-flowlogs-bucket \ --policy file://bucket-policy.json \ --region ap-northeast-1
2. VPC Flow Logsを有効化する
--resource-type VPC と --resource-ids にVPC IDを指定し、--traffic-type で記録対象を選択します。# VPCレベルでFlow Logsを有効化(S3送信・すべての通信を記録) aws ec2 create-flow-logs \ --resource-type VPC \ --resource-ids vpc-0a1b2c3d4e5f67890 \ --traffic-type ALL \ --log-destination-type s3 \ --log-destination arn:aws:s3:::my-flowlogs-bucket/vpc-logs/ \ --region ap-northeast-1 # 実行後の出力例 { "ClientToken": "", "FlowLogIds": [ "fl-0abc1234def56789" ], "Unsuccessful": [] }
--traffic-type の選択肢は以下の3つです。・ALL:ACCEPT・REJECTの両方を記録。最も広い情報が得られる
・ACCEPT:許可した通信のみ記録する
・REJECT:拒否した通信のみ記録する。セキュリティ監査に絞る場合に効率的
3. 有効化を確認する
コマンド実行後、FlowLogStatus が ACTIVE になっているか確認します。# 有効化状態を確認する aws ec2 describe-flow-logs \ --filter "Name=resource-id,Values=vpc-0a1b2c3d4e5f67890" \ --region ap-northeast-1 \ --query 'FlowLogs[*].{ID:FlowLogId,Status:FlowLogStatus,Dest:LogDestinationType}' \ --output table # 出力例 ----------------------------------------------------------------- | DescribeFlowLogs | +----+----------------------+------+--------+------------------+ | Dest | ID | Status | +-------------------------+---------------------+--------------+ | s3 | fl-0abc1234def56789 | ACTIVE | +-------------------------+---------------------+--------------+
vpc-logs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/ 以下に年/月/日で自動的に階層化されます。CloudWatch Logsへ送信してリアルタイム分析する設定
CloudWatch Logsを送信先にするには、VPC Flow LogsサービスがロググループへのPutLogEvents権限を持つIAMロールが必要です。1. IAMロールを作成する
信頼ポリシー(vpc-flow-logs.amazonaws.com がAssumeRoleできる設定)を作成し、CloudWatch Logsへの書き込み権限を付与します。# trust-policy.json として保存する { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "vpc-flow-logs.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } # IAMロールを作成する aws iam create-role \ --role-name VPCFlowLogsRole \ --assume-role-policy-document file://trust-policy.json # CloudWatch Logs書き込みポリシーをアタッチする(最小権限版) aws iam put-role-policy \ --role-name VPCFlowLogsRole \ --policy-name FlowLogsCloudWatchPolicy \ --policy-document '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", "logs:DescribeLogGroups", "logs:DescribeLogStreams" ], "Resource": "*" }] }'
2. CloudWatch LogsへFlow Logsを有効化する
# ロググループを作成する(存在しない場合) aws logs create-log-group \ --log-group-name /aws/vpc/flowlogs \ --region ap-northeast-1 # CloudWatch Logs送信でFlow Logsを有効化する aws ec2 create-flow-logs \ --resource-type VPC \ --resource-ids vpc-0a1b2c3d4e5f67890 \ --traffic-type ALL \ --log-destination-type cloud-watch-logs \ --log-group-name /aws/vpc/flowlogs \ --deliver-logs-permission-arn arn:aws:iam::123456789012:role/VPCFlowLogsRole \ --region ap-northeast-1
3. CloudWatch Logs Insightsでログを検索する
ログが届いたら(最初の記録まで数分かかります)、CloudWatch Logs Insightsから以下のクエリで内容を確認できます。# 直近1時間のREJECTを送信元IP別に集計するInsightsクエリ fields @timestamp, srcaddr, dstaddr, srcport, dstport, action | filter action = "REJECT" | stats count() as reject_count by srcaddr | sort reject_count desc | limit 20
Flow Logsのレコード形式を読み解く|フィールドの意味と実務での見方
Flow Logsの標準フォーマット(バージョン2)は、スペース区切りで以下の順にフィールドが並びます。実環境で取得した記録をマスク処理したものを見ながら確認しましょう。# バージョン2 標準フォーマットのヘッダー version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status # 実際のログレコード例(アカウントID・ENI IDはマスク済み) 2 123456789012 eni-0a1b2c3d4e5f 203.0.113.45 10.0.1.100 52341 22 6 4 240 1720000000 1720000060 REJECT OK 2 123456789012 eni-0a1b2c3d4e5f 10.0.1.100 10.0.2.200 54321 443 6 20 4120 1720000060 1720000120 ACCEPT OK 2 123456789012 eni-0a1b2c3d4e5f - - - - - - - 1720000120 1720000180 - NODATA
・version:レコードフォーマットのバージョン(標準は2)
・interface-id:トラフィックが通過したENIのID
・srcaddr / dstaddr:送信元・宛先のIPアドレス。VPC外からの通信はパブリックIPが記録される
・srcport / dstport:送信元・宛先のポート番号
・protocol:プロトコル番号。6=TCP、17=UDP、1=ICMP
・action:ACCEPTまたはREJECT。セキュリティグループ/NACLによる判定結果
・log-status:OK(正常)、NODATA(集計期間中に通信なし)、SKIPDATA(容量超過でスキップ)
上の例の1行目は、外部IP
203.0.113.45 からSSH(ポート22)への接続がREJECTされています。これはセキュリティグループがポート22を開放していないか、NACLで拒否されていることを意味します。不審なIPからのポートスキャンや侵入試行を検知する際に重要なレコードです。3行目の
- はNODATAステータスです。集計期間中に当該ENIでトラフィックが発生しなかったことを表します。これは正常な状態であり、エラーではありません。実務活用パターン|不審なアクセスと通信経路を調べる方法
AWSを運用している現場で、Flow Logsがとくに役立つ調査パターンを紹介します。1. 外部からの不審なアクセス源を特定する
S3にログが蓄積されたら、Amazon Athenaを使ってSQLで検索できます。CloudWatch Logs Insightsより大量のデータを効率よく分析できます。-- Athena: REJECTされた外部IP(プライベートアドレス以外)をポート別に集計する SELECT srcaddr, dstport, count(*) AS reject_count FROM vpc_flow_logs WHERE action = 'REJECT' AND srcaddr NOT LIKE '10.%' AND srcaddr NOT LIKE '172.16.%' AND srcaddr NOT LIKE '192.168.%' GROUP BY srcaddr, dstport ORDER BY reject_count DESC LIMIT 30;
Linuxでの
ss コマンドや lsof によるポート確認方法についてはLinux ポート確認の全コマンドでも詳しく解説しています。2. VPC内の通信経路を可視化する
VPC内のサービス間通信(例: アプリケーションサーバーからデータベースへの接続)が期待通りに行われているかを確認できます。# CloudWatch Insights: サブネット間のACCEPT通信を確認する # (例: 10.0.1.0/24 のアプリ層から 10.0.2.0/24 のDB層への通信) fields @timestamp, srcaddr, dstaddr, dstport, action | filter action = "ACCEPT" and srcaddr like "10.0.1." and dstaddr like "10.0.2." | sort @timestamp desc | limit 50
3. DNS通信(UDP 53)でリゾルバーの動作を確認する
VPC内からRoute 53 Resolverへの名前解決が正常に行われているかどうか、Flow LogsのUDPポート53の通信記録で確認できます。REJECT が多い場合はセキュリティグループやNACLの設定を見直してください。Linuxサーバーでの名前解決の仕組みについてはLinux DNS 設定の基本も参考にしてください。# CloudWatch Insights: DNS通信(UDP 53)の状況を確認する fields @timestamp, srcaddr, dstaddr, dstport, protocol, action | filter dstport = 53 and protocol = 17 | stats count() as dns_count by action
コストと有効化範囲の設計|VPC全体・サブネット・ENIの使い分け
VPC Flow Logsの料金はログデータの「取り込み量」によって課金されます。大量のトラフィックがあるVPCで全通信を記録すると、ログ保存コストが想定以上にかかることがあります。コストを抑えながらセキュリティ監査に必要な情報を確保するには、以下の考え方で設計します。・Traffic TypeをREJECTに絞る:セキュリティ監査が主な目的なら
--traffic-type REJECT のみを有効にすることで、ログ量を大幅に減らせる。ACCEPTを含む通信量が多い環境では特に効果的・送信先はS3を優先する:CloudWatch Logsはデータ取り込み料(東京リージョンで約$0.76/GB)がS3より割高。長期保存・大容量ならS3 + Athenaが経済的
・S3のライフサイクルポリシーでコスト管理する:90日以上経過したログをGlacierへ移行するライフサイクルルールを設定すると、長期ストレージコストを抑えられる
・段階的な有効化で始める:最初はVPCレベルでREJECTのみを有効化→問題が起きたサブネットやENIにALLを追加する段階的なアプローチが現場では現実的
# セキュリティ監査特化型の設定(REJECTのみ・S3送信) aws ec2 create-flow-logs \ --resource-type VPC \ --resource-ids vpc-0a1b2c3d4e5f67890 \ --traffic-type REJECT \ --log-destination-type s3 \ --log-destination arn:aws:s3:::my-flowlogs-bucket/vpc-reject-logs/ \ --region ap-northeast-1
・Amazon S3への取り込み:約$0.02/GB。長期保存に向く
・CloudWatch Logsへの取り込み:約$0.76/GB。リアルタイム分析向けだがコストは高い
・Kinesis Data Firehoseへの取り込み:約$0.029/GBの処理料。SplunkやOpenSearchへのリアルタイム送信が必要な場合に使う
トラブルシュート|ログが出力されない時の確認手順
Flow Logsを有効化してもログが出力されない場合、以下の手順で原因を切り分けます。1. FlowLogStatusとエラーメッセージを確認する
aws ec2 describe-flow-logs \ --filter "Name=resource-id,Values=vpc-0a1b2c3d4e5f67890" \ --region ap-northeast-1 \ --query 'FlowLogs[*].{Status:FlowLogStatus,Error:DeliverLogsErrorMessage}' \ --output table
DeliverLogsErrorMessage にエラーが表示されている場合、IAMロールの権限不足かS3バケットポリシーの設定誤りがほとんどです。エラーメッセージに Access Denied が含まれる場合は、権限設定を最初から見直してください。2. S3送信の場合はバケットポリシーを確認する
# バケットポリシーが正しく設定されているか確認する aws s3api get-bucket-policy \ --bucket my-flowlogs-bucket \ --output text # ポリシーが存在しない場合は以下のエラーが返る # An error occurred (NoSuchBucketPolicy) when calling the GetBucketPolicy operation: # The bucket policy does not exist
3. 最初の記録までの待機時間を確保する
Flow Logsの集計期間(デフォルト:約10分)が経過しないとログが出力されません。有効化直後に確認しても記録がない場合は、15分程度待ってから再確認してください。また、VPC内にトラフィックが発生していない場合は
NODATA レコードしか出力されません。テスト用に curl や ping で通信を発生させてから確認することをお勧めします。4. SKIPDATAが多い場合の対処
log-status に SKIPDATA が多数記録されている場合、Flow Logsサービス側で取り込み容量の制限を超えたことを意味します。VPCレベルで有効化している場合はサブネットレベルやENIレベルに切り替えて範囲を絞るか、CloudWatch LogsからS3送信に変更することを検討してください。本記事のまとめ
| やりたいこと | コマンド・設定 |
|---|---|
| S3へFlow Logsを有効化する | aws ec2 create-flow-logs --log-destination-type s3 |
| CloudWatch Logsへ有効化する | aws ec2 create-flow-logs --log-destination-type cloud-watch-logs |
| 有効化状態を確認する | aws ec2 describe-flow-logs |
| REJECTのみを記録する | aws ec2 create-flow-logs --traffic-type REJECT |
| 有効化を削除する | aws ec2 delete-flow-logs --flow-log-ids fl-xxxx |
| Insightsで不審IPを集計する | filter action = "REJECT" | stats count() by srcaddr |
・actionフィールドがREJECTのレコードの送信元IPとdstportを集計すると、不審なアクセス源を効率よく特定できる
・ログが出力されない場合はFlowLogStatusのDeliverLogsErrorMessageとIAMロール・バケットポリシーを優先して確認する
・コスト設計の基本はtraffic-type REJECTとS3送信の組み合わせから始め、調査が必要な時点でALL・CloudWatch Logsへ拡張する
・SKIPDATAが多い場合はVPCレベルからサブネット・ENIレベルへ絞り込むか、S3送信へ切り替える
VPC Flow Logsを設計に組み込むことで、「何かおかしい気がする」という感覚ではなく、IPアドレス・ポート番号・時刻という具体的なデータで通信を調査できるようになります。AWSのVPC設計・冗長化をさらに体系的に学びたい方は、下記のリンクからAWSマスタープログラムの詳細をご覧ください。
VPC設計・Flow Logs・セキュリティ監査——「なんとなく」を「根拠ある設計」に変えませんか?
aws ec2 create-flow-logs のコマンドは調べれば分かります。でも「どのレベルで有効化すべきか」「コストと可視性のバランスをどうとるか」を、自信を持って答えられますか?
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:AWS NAT GatewayでプライベートサブネットのEC2をインターネットに接続する方法|マルチAZ冗長設計とコスト最適化の実践手順
- この記事の属するカテゴリ:AWS(Amazon Linux)へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます