はじめに
本記事では、VPC Flow Logs を S3 に出力し、Athena でクエリすることで EC2 の通信内容を可視化するハンズオンを実施します。
ハンズオンの目的
- VPC Flow Logs の基本仕様を理解する
- S3 に出力されるログ構造を理解する
- Athena を使って通信ログを分析できるようになる
- NAT Gateway 経由通信を VPC Flow Logs で追えるようになる
構成概要
使用リソース
| リソース | 内容 |
|---|---|
| VPC | Public Subnet , Private Subnet |
| EC2 | Private Subnet に配置 |
| NAT Gateway | Public Subnet に配置(EIP 付与) |
| Interface Endpoint |
ssm / ec2messages / ssmmessages
|
| VPC Flow Logs | VPC 単位で有効化 |
| S3 | VPC Flow Logs 保存先 |
| Athena | ログ分析用 |
ネットワーク構成イメージ
EC2 (Private Subnet)
↓
NAT Gateway (EIP)
↓
Internet
実施手順
Step 1:S3 バケット作成
Step 2:VPC Flow Logs 作成
Step 3:EC2 + NAT Gateway 作成
Step 4:通信を発生させる
Step 5:S3 に出力される構造を確認
Step 6:Athena テーブル作成(パーティション対応)
Step 7:Athena クエリ実行結果
Step 8:通信の解説
Step 1:S3 バケット作成
VPC Flow Logs の出力先となる S3 バケットを作成します。
- バケット名:任意(例:
vpc-flowlogs-athena-handson) - リージョン:ap-northeast-1
※ VPC Flow Logs は S3 に直接出力できます(CloudWatch Logs 経由ではない)。
Step 2:VPC Flow Logs 作成
VPC Flow Logs 作成
- 対象:VPC
- フィルター:ALL
- 送信先:S3(S3 バケット ARN を指定)
- フォーマット:デフォルト(Version 2)
Step 3:EC2 + NAT Gateway 作成
EC2
- Private Subnet に配置
- Internet Gateway への直接ルートなし
- SSM 接続
NAT Gateway
- Public Subnet に配置
- Elastic IP を関連付け
ルートテーブル(Private Subnet)
| 宛先 | ターゲット |
|---|---|
| 0.0.0.0/0 | NAT Gateway |
Step 4:通信を発生させる
EC2 に SSM 接続し、以下の通信を実行します。
curl https://ifconfig.me
curl https://example.com
この通信は
- 送信元:EC2(Private IP)
- 送信先:Internet
- 経路:NAT Gateway(EIP)
となります。
Step 5:S3 に出力される構造を確認
フォルダ構造例
.../vpcflowlogs/ap-northeast-1/2026/01/15/
重要ポイント
- 日付フォルダは UTC 基準
- 日本時間 0:00〜8:59 に発生したログは「前日」フォルダに格納される
- オブジェクトの「更新日時」は JST でも、フォルダは UTC
Step 6:Athena テーブル作成(パーティション対応)
CREATE EXTERNAL TABLE vpc_flow_logs (
version int, --カラム定義開始↓ FlowLogsフォーマットversion2
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 (year string, month string, day string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
LOCATION 's3://vpc-flowlogs-athena-handson/AWSLogs/<account-id>/vpcflowlogs/ap-northeast-1/'
TBLPROPERTIES (
'projection.enabled'='true',
'projection.year.type'='integer',
'projection.year.range'='2025,2030',
'projection.month.type'='integer',
'projection.month.range'='1,12',
'projection.month.digits'='2',
'projection.day.type'='integer',
'projection.day.range'='1,31',
'projection.day.digits'='2',
'storage.location.template'='s3://vpc-flowlogs-athena-handson/AWSLogs/<account-id>/vpcflowlogs/ap-northeast-1/${year}/${month}/${day}/'
);
S3 に保存されている VPC Flow Logs を Athena で直接クエリできるようにする定義
-
end は SQL の予約語
そのまま書くと構文エラーになるため、バッククォートで囲む必要がある。 -
PARTITIONED BY
S3 のディレクトリ構造を “検索条件” として使うための仕組み
year=2026, month=01, day=15 に対応 -
projection.enabled = true
新しい日付フォルダが増えても自動認識してパーティションが適用される -
projection.year / month / day
S3のフォルダ名(日付)を、どのように数値として計算・生成するかを定義
2025〜2030年 / 01〜12月 / 01〜31日 -
storage.location.template
WHERE 句の値をS3 パスに動的に当てはめる
/\${year}/\${month}/${day}/
Step 7:Athena クエリ実行結果
①EC2(Private IP)からの通信ログ確認
SELECT
from_unixtime(start) AS start_time,
srcaddr,
dstaddr,
srcport,
dstport,
action,
bytes
FROM vpc_flow_logs
WHERE
srcaddr = '172.32.21.19'
AND dstport = 443
AND protocol = 6
ORDER BY start DESC;
クエリ結果(一部抜粋)
EC2 の ENI に記録される VPC Flow Logs 上では、
送信元が Private IP のままインターネット宛に通信しているように見える
| start_time | srcaddr | dstaddr | srcport | dstport | action | bytes |
|---|---|---|---|---|---|---|
| 2026-01-15 23:06:12 | 172.32.21.19 | 34.160.111.145 | 60038 | 443 | ACCEPT | 1507 |
| 2026-01-15 23:06:49 | 172.32.21.19 | 104.18.26.120 | 60326 | 443 | ACCEPT | 1507 |
② NAT Gateway(EIP)からの通信ログ確認
SELECT
from_unixtime(start) AS start_time,
srcaddr,
dstaddr,
srcport,
dstport,
protocol,
action,
packets,
bytes
FROM vpc_flow_logs
WHERE
srcaddr = '54.248.89.189'
AND dstport = 443
AND protocol = 6
ORDER BY start DESC
クエリ結果(一部抜粋)
インターネットから見ると通信元は EC2 ではなく NAT Gateway
- dstaddr / bytes が EC2 視点のログと一致
-
srcport が毎回変化している
→ NAT によるポート変換(NAPT)
| start_time | srcaddr | dstaddr | srcport | dstport | action | bytes |
|---|---|---|---|---|---|---|
| 2026-01-15 23:05:58 | 54.248.89.189 | 34.160.111.145 | 56059 | 443 | ACCEPT | 1507 |
| 2026-01-15 23:07:20 | 54.248.89.189 | 104.18.26.120 | 12585 | 443 | ACCEPT | 1507 |
Step 8:通信の解説
通信の実際の流れ
EC2 (172.32.21.19)
↓ ① Private IP のまま送信
NAT Gateway
↓ ② IP / ポート変換
Internet (example.com / ifconfig.me)
VPC Flow Logs に記録される視点の違い
| 視点 | srcaddr |
|---|---|
| EC2 → NAT | 172.32.21.19 |
| NAT → Internet | 54.248.89.189 |
VPC Flow Logs は ENI(ネットワークインターフェース)単位で記録されるため、
- EC2 の ENI を通過する通信
- NAT Gateway の ENI を通過する通信
両方が別々のログとして出力される
なぜ srcport が変わるのか?
NAT Gateway は複数の Private IP 通信を 1つの EIP で捌くため、
- 送信元 IP を EIP に変換
- 送信元ポートを一時的な値に変換
IP + ポートの組み合わせで通信を識別
今回の学び
- VPC Flow Logs の日付フォルダは UTC 基準
- NAT Gateway 経由通信でも EC2 側 ENI の VPC Flow Logs を見ることで送信元 Private IP は追跡可能
- Athena を使うことで「通信の証跡」を SQL で確認できる
- Flow Logs は「リアルタイム監視」ではなく、
事後解析・通信経路理解のためのログとして使うのが重要だと理解した。