VPC内を流れるパケットが「どこから来て、どこへ向かったか」——オンプレで言えばNetFlowで可視化していた情報を、AWSではVPC Flow Logsで取得できます。ところが、EC2やRDSを立ち上げてもVPC Flow Logsはデフォルトで無効です。「何か不審な通信があっても、ログが残っていなかった」という事態は、クラウド移行直後のチームが経験しがちな落とし穴の一つです。
この記事では、VPC Flow Logsの基本的な仕組みから、CloudWatch LogsやS3へのログ転送設定、Amazon Athenaを使った実践的なクエリ分析、セキュリティ監視での活用パターン、そして料金の読み方まで、現場で使えるレベルで解説します。
VPC Flow Logsとは何か?オンプレのNetFlowと何が違う?
オンプレでは、Cisco製品などが対応するNetFlowやsFlowを使ってネットワークトラフィックを記録していた方も多いと思います。VPC Flow Logsは、これと同等の「IPトラフィックのフローデータ」を収集するAWSのマネージドサービスです。
ただし、両者には大きな違いが一つあります。NetFlowはルーター・スイッチの物理インターフェイスからフローを取得しますが、VPC Flow LogsはENI(Elastic Network Interface)単位で記録します。つまり、AWS上の仮想ネットワークインターフェイスが収集対象です。
| 比較項目 | オンプレ(NetFlow) | AWS(VPC Flow Logs) |
|---|---|---|
| 収集対象 | 物理インターフェイス(ルーター・スイッチ) | ENI(仮想ネットワークインターフェイス) |
| デフォルト有効 | 機器設定次第 | 無効(明示的に有効化が必要) |
| 保管先 | NetFlowコレクター | CloudWatch Logs または S3 |
| コスト構造 | 機器+コレクターのCapEx | ログ生成量×転送量×保管量のOpEx |
| ペイロードの閲覧 | 不可(フローデータのみ) | 不可(フローデータのみ) |
最後の行が重要です。VPC Flow Logsが記録するのは「接続元IP・接続先IP・ポート・プロトコル・送受信バイト数・許可/拒否判定」といったフロー情報であり、パケットの中身(ペイロード)は一切記録しません。HTTPSの通信内容を見ようとしても見られない点はNetFlowと同じ制約です。
Amazon VPC入門でVPCのサブネット設計やルーティングの基礎を押さえておくと、Flow Logsの収集対象をより直感的に理解できます。
ログの有効化:VPC・サブネット・ENIの3段階
VPC Flow Logsは3つの粒度で有効化できます。
・VPCレベル: そのVPC内のすべてのENIが対象。最も広範囲で、まず検討すべき設定。
・サブネットレベル: 特定サブネット内のENIのみ。パブリックサブネットだけ監視したい場合に有効。
・ENIレベル: 特定のEC2やRDSのインターフェイスのみ。ピンポイントなデバッグ向け。
1. VPCコンソールから有効化する手順
AWSコンソールから設定する手順です。
1. AWSコンソール → VPC → 「お使いのVPC」を選択
2. 対象VPCを選択 → 「フローログ」タブをクリック
3. 「フローログを作成」をクリック
4. 以下を設定する:
・フィルター: 「すべて」(承認・拒否両方を記録)または「拒否のみ」
・最大集計間隔: 1分 または 10分(コスト重視なら10分)
・送信先: 「CloudWatch Logsに送信」または「S3バケットに送信」
・IAMロール: Flow LogsがCloudWatch Logsに書き込むためのロールを指定
2. AWS CLIで有効化する(IaC対応)
# VPC IDとロールARNを変数に格納 VPC_ID="vpc-0123456789abcdef0" ROLE_ARN="arn:aws:iam::123456789012:role/flowlogs-role" LOG_GROUP="/vpc/flowlogs/your-vpc" # フローログを作成(CloudWatch Logs宛て・集計間隔60秒) aws ec2 create-flow-logs --resource-type VPC --resource-ids ${VPC_ID} --traffic-type ALL --log-destination-type cloud-watch-logs --log-group-name ${LOG_GROUP} --deliver-logs-permission-arn ${ROLE_ARN} --max-aggregation-interval 60 # 作成確認 aws ec2 describe-flow-logs --filter "Name=resource-id,Values=${VPC_ID}"
S3に直接送る場合は `–log-destination-type s3` と `–log-destination “arn:aws:s3:::your-bucket/prefix/”` を指定します。S3経由は保管コストが低く、大量ログの長期保管に向いています。
3. 必要なIAMロールの設定
CloudWatch Logsへ書き込むには、VPC Flow Logsサービス(`vpc-flow-logs.amazonaws.com`)がCloudWatch Logsを操作できるIAMロールが必要です。
# 信頼ポリシー(trust-policy.json) { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "vpc-flow-logs.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } # アクセス許可ポリシーで必要な権限(最小権限の原則) # logs:CreateLogGroup # logs:CreateLogStream # logs:PutLogEvents # logs:DescribeLogGroups # logs:DescribeLogStreams
ログフォーマットの読み方
VPC Flow Logsのログはスペース区切りのテキスト形式で出力されます。デフォルトフォーマットの主要フィールドを押さえましょう。
| フィールド | 内容 | 例 |
|---|---|---|
| version | フローログのバージョン | 2 |
| interface-id | ENIのID | eni-0a1b2c3d |
| srcaddr | 接続元IPアドレス | 203.0.113.5 |
| dstaddr | 接続先IPアドレス | 10.0.1.100 |
| srcport / dstport | 接続元・先のポート番号 | 54321 / 443 |
| protocol | プロトコル番号(6=TCP, 17=UDP, 1=ICMP) | 6 |
| packets / bytes | パケット数・バイト数 | 12 / 5120 |
| start / end | 集計開始・終了時刻(UNIXタイム) | 1720000000 |
| action | ACCEPT または REJECT | REJECT |
| log-status | OK / NODATA / SKIPDATA | OK |
`action` フィールドが `REJECT` の場合、セキュリティグループまたはネットワークACLによって拒否されたトラフィックです。セキュリティグループとネットワークACLの違いを理解しておくと、拒否されたトラフィックがどの層で弾かれているかの判断が速くなります。
ログの分析方法:CloudWatch Logs vs S3+Athena
送信先の選択によって分析手法が異なります。
1. CloudWatch Logsでの分析(リアルタイム寄り)
CloudWatch Logs Insightsを使えばコンソールから直接クエリを実行できます。アラートとの連携も設定しやすく、急いで調査したいときに便利です。
# 拒否されたトラフィックを件数の多い接続元IP順に集計 fields srcaddr, dstport, action | filter action = "REJECT" | stats count(*) as reject_count by srcaddr, dstport | sort reject_count desc | limit 20
ただし、CloudWatch Logsはデータ取込料金($0.76/GB、東京リージョン・2026年7月時点)が高めです。本番VPCのようにトラフィックが多い環境では費用が膨らみます。CloudWatch Logsのコスト削減方法も合わせて確認しておくことをお勧めします。
2. S3+Amazon Athenaでの分析(大量ログ向け)
ログをS3に送りAthenaでクエリする方法は、大量のフローログを低コストで分析できます。Athenaはクエリ実行時にスキャンしたデータ量に応じた課金($5/TB、2026年7月時点)なので、パーティション設計が肝心です。
-- Athenaテーブル作成(S3パスは実環境に合わせて変更) CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs ( version INT, account_id STRING, interface_id STRING, srcaddr STRING, dstaddr STRING, srcport INT, dstport INT, protocol INT, packets BIGINT, bytes BIGINT, start BIGINT, end BIGINT, action STRING, log_status STRING ) PARTITIONED BY (dt STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ' ' LOCATION 's3://your-bucket/flowlogs/AWSLogs/123456789012/vpcflowlogs/ap-northeast-1/' TBLPROPERTIES ('skip.header.line.count'='1'); -- パーティション追加(日付ごとに実行) ALTER TABLE vpc_flow_logs ADD PARTITION (dt='2026-07-25') LOCATION 's3://your-bucket/flowlogs/.../2026/07/25/'; -- 拒否トラフィックを接続元IP×ポート別に集計 SELECT srcaddr, dstport, count(*) as cnt FROM vpc_flow_logs WHERE action = 'REJECT' AND dt = '2026-07-25' GROUP BY srcaddr, dstport ORDER BY cnt DESC LIMIT 20;
セキュリティ監視への活用:現場で使える検知パターン
1. ポートスキャンの検知
同一の接続元IPから、多数の異なるポートへのREJECTが短時間に集中している場合、ポートスキャンの可能性があります。
# CloudWatch Logs Insights: 1つのIPが試みたユニークポート数を集計 fields srcaddr, dstport, action | filter action = "REJECT" | stats count_distinct(dstport) as unique_ports by srcaddr | filter unique_ports > 20 | sort unique_ports desc
2. 意図しない外部通信(データ持ち出し)の検知
プライベートサブネット内のEC2からパブリックIPへ向けて大量のバイトが送信されていないか、Athenaで確認できます。
-- プライベートIPから外部IPへの大量送信を検知(1GB以上) SELECT srcaddr, dstaddr, SUM(bytes) AS total_bytes FROM vpc_flow_logs WHERE srcaddr LIKE '10.%' AND dstaddr NOT LIKE '10.%' AND dstaddr NOT LIKE '172.16.%' AND dstaddr NOT LIKE '192.168.%' AND action = 'ACCEPT' AND dt = '2026-07-25' GROUP BY srcaddr, dstaddr HAVING SUM(bytes) > 1073741824 ORDER BY total_bytes DESC;
3. セキュリティグループ設定ミスの早期発見
特定ポートへのREJECTが急増している場合、アプリケーションが期待するポートへの通信がセキュリティグループで許可されていない可能性があります。設定変更の直後にこのクエリを走らせると、素早く原因を特定できます。
これらの検知をリアルタイムで行いたい場合は、CloudWatch Logsのメトリクスフィルターでアラームを設定するか、Amazon GuardDutyとの組み合わせが有効です。GuardDutyはVPC Flow Logsを自動で取り込み、脅威インテリジェンスとの照合まで行ってくれます。手動クエリの限界をGuardDutyで補完するのが現場での定番構成です。
料金の仕組みと最適化のポイント
VPC Flow Logsの料金は「データ取込料金」と「保管料金」の2要素で構成されます(東京リージョン・2026年7月時点)。
| コスト要素 | 単価 | 備考 |
|---|---|---|
| CloudWatch Logsへのデータ取込 | $0.76/GB | ログ生成量に比例して課金 |
| CloudWatch Logsの保管 | $0.033/GB/月 | 保持期間設定で削減可能 |
| S3への保管 | $0.025/GB/月程度(S3標準) | 取込自体は追加料金なし |
| Athenaクエリ | $5/TBスキャン | パーティション設計でコスト激減 |
コスト最適化のポイントは3つです。
・フィルターを「拒否のみ」にする: セキュリティ監視が主目的なら、ACCEPTログを捨てることでデータ量を大幅削減できます。通信量の多いVPCでは特に効果が大きい。
・集計間隔を10分にする: デフォルトは10分。1分間隔は約5倍のログ量になるので、秒単位のリアルタイム性が不要なら10分のままで十分です。
・S3保管+ライフサイクルルールを使う: S3はCloudWatch Logsより保管コストが低く、90日以降はGlacierへ移行するライフサイクルルールを設定すると長期保管コストを大きく抑えられます。
Athenaクエリのコスト削減については、Athenaコスト最適化ガイドでパーティション設計・データ圧縮・ファイル形式の選択まで詳しく解説しています。
よくあるトラブルと対処法
1. 有効化したのにログが届かない
最も多い原因はIAMロールの設定ミスです。信頼ポリシーのPrincipalが `vpc-flow-logs.amazonaws.com` になっているか、アクセス許可ポリシーに `logs:CreateLogStream` と `logs:PutLogEvents` が含まれているかを確認してください。コンソールの「フローログ」タブで「配信エラー」が表示されている場合はIAMが最初の確認ポイントです。
2. NODATAのレコードが大量に出る
`log-status` が `NODATA` のレコードは「集計間隔中にトラフィックがゼロだったENI」を示します。異常ではありませんが、集計クエリに `WHERE log_status = ‘OK’` を追加するだけでノイズが大幅に減ります。
3. S3に届くまでタイムラグがある
S3宛ての場合、ログが配信されるまで最大15分(デフォルト集計間隔10分+配信遅延)のタイムラグがあります。リアルタイムに近い監視が必要ならCloudWatch Logsへの転送を選択してください。
4. Athenaのクエリが遅い・コストが高い
パーティションが設定されていないと全データをフルスキャンします。`WHERE dt = ‘2026-07-25’` のような日付フィルターが効くよう、必ず日付パーティションを設定してからクエリを実行してください。
本記事のまとめ
VPC Flow Logsは、クラウドネットワークの「見える化」を実現する基本的かつ強力なツールです。要点をまとめます。
・デフォルトは無効: クラウド移行後は必ずVPCレベルで有効化する。後から設定しても過去のログは遡れない。
・送信先は用途で選ぶ: リアルタイム監視はCloudWatch Logs、大量ログの長期保管・分析はS3+Athena。
・REJECTフィルターが実用的: セキュリティ監視目的ならACCEPTを捨てるだけでコストが劇的に下がる。
・GuardDutyと組み合わせる: 手動クエリの限界をGuardDutyの自動分析で補完するのが現場の定番構成。
・コストの読み方: 「ログ生成量×CloudWatch Logs取込料金」が最大のコスト要素。S3経由+Glacierライフサイクルで長期保管コストを抑える。
PR
AWSではじめるクラウドセキュリティ(松本照吾ほか/日経BP)
IAM・VPC・暗号化・監査ログなどAWSセキュリティの全体像を体系的に解説。VPC Flow LogsやGuardDutyの活用事例も豊富で、本記事の内容をより深く掘り下げたい方に最適な一冊です。
