はじめに
この記事は Medley(メドレー) Advent Calendar 2025 4日目の記事です。
医療プラットフォーム本部 プラットフォーム開発室 SRE グループの山田です。 医療機関向け SaaS である CLINICS の安定稼働とシステム信頼性の向上に取り組んでいます。
本記事では、VPCフローログ/Amazon Athena/ネットワークACLを用いてNATゲートウェイへの通信内容を調査する方法について紹介します。 タイトルにもありますが、かなり力技になりますので本番環境で実施は控えてください。
背景
CLINICSには外部サービスと連携して機能を提供するAPIが多く存在します。 また、システム間通信にもNATゲートウェイを経由して通信することがあるため、サービスの成長に伴いECS Taskのスケールアウトによって、NATゲートウェイを経由する通信量は着実に増えていきます。
日常の運用では問題が見えにくくても、万が一NATゲートウェイで障害が発生してしまった場合、その影響は広範囲に及び、サービスの復旧に時間を要する可能性があります。
特に懸念される障害シナリオの一つが、トラフィック集中による「ポート割り当てエラーの増加」です。 これにより、NATゲートウェイへの新規接続が失敗し、通信が遮断される可能性があります。
参考:Amazon VPC の NATゲートウェイで発生する「エラーポートアロケーション」エラーを解決するにはどうすればよいですか?
こうしたリスクを未然に防ぐためには、「NATゲートウェイの冗長化」や、「NATゲートウェイ経由の通信が必須か」を見直し、可能な通信はVPCエンドポイントへ移行させるといったアーキテクチャの最適化が求められます。
CLINICSでは、この課題への第一歩として、現状のNATゲートウェイの利用実態を詳細に把握する調査を実施しました。 具体的には、NATゲートウェイを介して通信しているシステムと通信先のサービスを洗い出すことに取り組みました。
次章からは、この調査で得られた具体的な知見と、それに基づきどのようにインフラアーキテクチャの改善を進めたのかを紹介します。
調査方法
ここからは、NATゲートウェイ経由でのトラフィックを調査し、CLINICSが通信している外部のサービスを特定する方法について紹介します。 大枠、以下のような流れで調査を進めていきました。
- VPCフローログを有効化
- Athena からVPCフローログを解析
- 通信先のAWSサービスを特定
- 通信先のAWS以外のサービスを特定
VPCフローログを有効化
VPCフローログはVPC内部の通信内容をキャプチャする機能です。 もちろん、「VPC内部の通信」にはNATゲートウェイの通信も含まれます。
ログはAmazon CloudWatch Logs、Amazon S3、Amazon Kinesis Data Firehoseへ保存することができますが、本記事ではS3へ保存する想定で解説していきます。
ログレコードの形式
VPCフローログのフォーマットはデフォルト設定でもある程度調査が可能ですが、調査をする上で追加で以下のフィールドを追加しました。
- tcp-flags: TCP接続の状態(SYN、ACK、FINなど)を確認するために使用します。NATゲートウェイはアイドルタイムアウト時にRSTパケットを送信するため、調査目的で追加しました
- pkt-srcaddr: NAT変換前の元の送信元IPアドレス。NATゲートウェイ経由の通信では、送信元を特定するために変換前のIPを追跡するために使用します
- pkt-dstaddr: NAT変換前の元の送信先IPアドレス。実際に通信しようとしている外部サービスのIPを特定するために使用します
- pkt-src-aws-service: 送信元IPがAWSサービスのIP範囲に該当する場合、そのサービス名が記録されます
- pkt-dst-aws-service: 送信先IPがAWSサービスのIP範囲に該当する場合、そのサービス名が記録されます。EC2やS3など、どのAWSサービスと通信しているかを判別できます
- traffic-path: トラフィックがどの経路を通っているかを確認できます。NATゲートウェイ経由かどうかの判定に役立ちます
参考: フローログレコード
フローログに追加できる情報はかなり種類があり定期的に更新されるので、設定するときは用途に合わせたフォーマットになるようドキュメントを一読することをお勧めします。 また、既存のフローログのフォーマットを変更することはできないので注意が必要です。
VPCフローログを分析するための基盤を作成
VPCフローログを有効化したので、S3にVPC内のトラフィックに関する情報が保存されるようになりました。 次に、これらのログを集計して通信内容に関するより詳細な情報を取得できるようにするためにAthenaテーブルを用意します。
Athena テーブル作成
CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs (
flowlog_version INT,
account_id STRING,
interface_id STRING,
srcaddr STRING,
dstaddr STRING,
srcport INT,
dstport INT,
protocol INT,
packets BIGINT,
bytes BIGINT,
start_time BIGINT,
end_time BIGINT,
traffic_action STRING,
log_status STRING,
tcp_flags INT,
pkt_srcaddr STRING,
pkt_dstaddr STRING,
pkt_src_aws_service STRING,
pkt_dst_aws_service STRING,
traffic_path INT
)
PARTITIONED BY (dt STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
LOCATION 's3://bucket-name/AWSLogs/XXXXXXXXXXXX/vpcflowlogs/region'
TBLPROPERTIES (
"skip.header.line.count" = "1"
);
作成したテーブルに対してパーティションを追加して、データを取り込ませたら準備完了です。
ALTER TABLE vpc_flow_logs
ADD PARTITION (dt='20YY-MM-DD')
LOCATION 's3://bucket-name/AWSLogs/XXXXXXXXXXXX/vpcflowlogs/region/20YY/MM/DD/';
通信対象の特定
実際にクエリを実行してNATゲートウェイを介してどこと通信しているかを調査します。
下記のクエリでは、特定の日付でNATゲートウェイを介した通信回数を通信元と通信先のIPで集計しています。
SELECT pkt_srcaddr, srcaddr, dstaddr, pkt_dstaddr, dstport, pkt_dst_aws_service, COUNT(1) AS c
FROM vpc_flow_logs
WHERE srcaddr LIKE 'x.x.%' -- VPC CIDR
AND dstaddr IN ('y.y.y.y', 'z.z.z.z') -- NAT Gateway IP
AND dt = '20YY-MM-DD'
GROUP BY pkt_srcaddr, srcaddr, dstaddr, pkt_dstaddr, dstport, pkt_dst_aws_service
ORDER BY c DESC;
すると以下のような結果が返ってきます。(もちろんダミーデータです。)
| # | pkt_srcaddr | srcaddr | dstaddr | pkt_dstaddr | dstport | pkt_dst_aws_service | c |
|---|---|---|---|---|---|---|---|
| 1 | x.x.a.a | x.x.a.a | y.y.y.y | a.a.a.a | 443 | EC2 | 1600 |
| 2 | x.x.b.b | x.x.b.b | z.z.z.z | b.b.b.b | 443 | AMAZON | 1500 |
| 3 | x.x.c.c | x.x.c.c | y.y.y.y | c.c.c.c | 443 | - | 700 |
| 4 | x.x.d.d | x.x.d.d | y.y.y.y | d.d.d.d | 443 | - | 400 |
通信先のAWSサービスを特定
通信先がAWSサービスの場合は、pkt_dst_aws_service を確認することで対象を特定することができます。
フローログに記載されるpkt-src-aws-serviceとpkt-dst-aws-serviceはEC2のように具体的なAWSサービスが記載されていることもあれば、AMAZONのようにどのエンドポイントと通信しているかわからない場合もあります。そのような場合は、AWS Route53 リゾルバーのクエリログ記録を確認することで特定できたりします。
参考: リゾルバーでのクエリのログ記録
また、EC2ダッシュボードから確認できるネットワークインターフェース一覧からパブリックIPで検索することで通信先のリソースを特定することも可能です。
通信先のAWS以外のサービスを特定
基本的にIPアドレスからどのサービスなのかを完全に特定することはできません。
逆引きDNS(PTRレコード)が設定されている場合はdigを使ったりwhoisでIP所有者の特定はできるかもしれませんが、外部サービスがIPアドレスの範囲を公開していなければどのサービスかを絞り込むのは難しいです。
では、AWS以外のサービスをどのように特定すれば良いでしょうか?
A. 「特定のIPアドレスへの通信を遮断すれば、システムアラートからどのサービスとの通信が確立できなかったか確認できるのでは?」
以下のような仕組みを考えてみました。
- CLINICS APIが外部サービス(IPがx.x.x.x)へリクエストを送信する
- 特定のIPアドレスへの通信を遮断する
- 外部サービスへのリクエストがタイムアウトすることでアラートが発報される
筋が良くはないかもしれませんがやってみました。冒頭にも記載しましたが、本番環境での実施は控えてください。
特定のIPアドレスへの通信を遮断する方法
特定のIPアドレスへの通信を遮断する手段として「ネットワークアクセスコントロールリスト(ネットワークACL)」があります。 ネットワークACLはサブネットレベルで特定のトラフィックを許可/拒否することができる仕組みです。
参考:ネットワークアクセスコントロールリストを使用して、サブネットのトラフィックを制御する
実際にネットワークACLを作成してみます。 先ほど実行したクエリ結果をもとにブロックしたいIPアドレスをアウトバウンドルールを設定していきます。

作成したネットワークACLをプライベートサブネットに関連付ければ、NATゲートウェイを介した通信が遮断されるようになります。
全てのIPアドレスをしらみつぶしに検証していくとキリがないので、トラフィックが特に多いものに絞って調査を進めました。
調査結果
上述した方法を用いて、NATゲートウェイを介して通信する外部サービスの特定ができました。 特にトラフィック量が多く、NATゲートウェイを経由しなくても良いサービスは以下のようになりました。
- Amazon Kinesis
- Datadog
NATゲートウェイを通らないアーキテクチャへ変更
ここからは、NATゲートウェイ経由で通信していたトラフィックをVPCエンドポイントへ逃していきます。 NATゲートウェイとVPCエンドポイントどちらを採用するかを検討する場合、損益分岐点を計算する必要がありますが本記事では割愛します。
Amazon Kinesis
Amazon Kinesis はインターフェイスVPCエンドポイントがサポートされているため、VPCエンドポイントを作成して向き先を変えてあげます。
参考: AWS のサービス と統合する AWS PrivateLink
Datadog
DatadogはPrivateLinkを提供しているため、これを採用します。
参考: AWS PrivateLink を介して Datadog に接続する
後になって知りましたが、DatadogさんはIPアドレスの範囲を公開されていたんですね。 以下から確認できました。
curl -X GET "https://ip-ranges.datadoghq.com/" -H "Accept: application/json"
参考: IP 範囲
効果検証
VPCエンドポイントやPrivateLinkへの移行が完了した後、実際にNATゲートウェイを経由するトラフィック量が削減されたかを確認しました。
NATゲートウェイ経由のトラフィック削減
VPCエンドポイントやPrivateLinkへの移行後、NATゲートウェイを経由するトラフィック量が大幅に削減されました。

VPCエンドポイントへトラフィックが流れた後のNATゲートウェイの送信先へのバイト数の変化
具体的には、移行前と比較して以下のような結果が得られました。
- 送信パケット数の削減: NATゲートウェイを経由するパケット数が約50%削減
- データ量の削減: NATゲートウェイを経由するデータ量が約82%削減
まとめ
本記事では、VPCフローログとAmazon Athenaを用いてNATゲートウェイを経由する通信内容を分析し、ネットワークACLを活用した力技で通信先のサービスを特定する方法を紹介しました。
調査の結果、NATゲートウェイを経由する主な通信先としてAmazon KinesisとDatadogが特定できました。これらをVPCエンドポイントやPrivateLinkに移行することで、NATゲートウェイを経由するトラフィック量を削減することができました。
NATゲートウェイのポート割り当てエラーなどのリスクを事前に回避するためには、定期的に通信内容を見直し、可能な限りVPCエンドポイントやPrivateLinkを活用したアーキテクチャに最適化していくことが重要です。 ただし、VPCエンドポイントやPrivateLinkを導入することでかえってインフラコストが増加する可能性もあるため、アーキテクチャの最適化によるリスク低減とインフラコストのバランスを慎重に検討する必要があります。 本記事が、同様の課題に取り組む方々の参考になれば幸いです。
We’re hiring!
メドレーでは、SREをはじめ「医療ヘルスケアの未来」を共に創っていくエンジニアを大募集中です!少しでもご興味をお持ちいただけましたらぜひ、ご応募お待ちしております!
※カジュアル面談も大歓迎です!ご希望の際は、「その他の項目(希望記入欄)」にてその旨をご記載ください。