こんにちは!クラウドの海原をコンテナの帆船で日々航海しているSREの皆さん、そしてインフラの世界に足を踏み入れたばかりの初学者の皆さん、いつもお疲れ様です。
クラウドの世界って、本当に便利ですよね。ボタンをポチッと押すだけで、あっという間に頑丈なサーバーが立ち上がり、世界中とつながるネットワークが完成します。でも、時々こんなミステリーに遭遇しませんか?
「あれ? セキュリティグループもルートテーブルも完璧なはずなのに、なぜか通信が片方向しか通らない……?」
パケットキャプチャを取ってみると、おかしな現象が起きています。行きと帰りで通っている道がバラバラなんです。そう、これが今回メスを入れる「非対称ルーティング(Asymmetric Routing)」という、ネットワークエンジニア泣かせの厄介な現象です。
今回は、この非対称ルーティングがなぜ恐ろしいのか、そして私たちのクラウド環境でどうやってNAT(Network Address Translation)セッションを破壊してしまうのかを、身近な例えを交えながら優しく紐解いていきたいと思います。一歩ずつ、じっくり理解していきましょう!
—
1. 郵便配達で例える「ステートフル」と「非対称ルーティング」
まずは、難しいネットワークの専門用語をいったん脇に置いて、私たちが普段使っている「郵便配達」の世界に置き換えて考えてみましょう。
記憶力抜群の受付係(ステートフルファイアウォール・NAT)
あなたが海外の友人にお手紙を出すとします。日本の郵便局の窓口(NATゲートウェイやファイアウォール)には、すごく記憶力の良い受付係が座っています。
あなたが手紙を出すとき、受付係はこうメモします。
> *「Aさん(プライベートIP)が、海外のBさん(パブリックIP)宛てに手紙を出したな。よし、返事が来たら必ずAさんに渡せるように、この『やり取りの記録(セッション)』を机の引き出しにしまっておこう」*
これが、通信の往復を記憶している「ステートフル(Stateful)」な仕組みです。
往復の道が違うと、どうなる?
さて、海外のBさんからお返事が届きました。本来なら、行きと同じ窓口を通ってあなたの元に手紙が届くはずです。しかし、会社のネットワークが複雑だったり、複数の出口(NATインスタンス)があったりすると、こんなことが起きます。
1. 行きは 「東の窓口(NATインスタンスA)」 から手紙を海外へ出した。
2. でも、帰りのトラックはなぜか 「西の窓口(NATインスタンスB)」 に到着してしまった!
西の窓口に座っている受付係は、こう言います。
> *「は? 私の机の引き出しには、Bさんからの手紙に対する『やり取りの記録』なんて入っていませんが? どちら様ですか?」*
そして、受付係は容赦なくその手紙をゴミ箱にポイっと捨ててしまいます。……これが、非対称ルーティングによるNATセッションの破綻(通信のドロップ)の正体です。
—
2. クラウド(AWS/GCP)で非対称ルーティングが起きるシチュエーション
クラウドインフラを構築していると、うっかりこの非対称ルーティングの罠を踏んでしまうことがあります。代表的なシナリオを見てみましょう。
シチュエーション:冗長化されたNATインスタンス(ルーター)の迷子
可用性を高めるために、プライベートサブネットからのインターネット抜け道として、2台のルーター(NAT-A と NAT-B)を並べて置いたとします。
- 往路のパケット: プライベートサブネットのサーバーから出たパケットは、ルートテーブルの指示によって
NAT-Aを経由してインターネットへ飛び出しました。この時、NAT-Aの内部メモリには「この通信のセッション情報」がしっかり記録されます。 - 復路のパケット: インターネット側からの返答パケットが返ってきましたが、なぜかルーティングの気まぐれ(あるいは非対称なルーティング設定)により、
NAT-Bめがけて飛んできました。
NAT-B からすれば、「お前、誰だっけ?」です。セッション情報を持たない NAT-B は、パケットを無情にもドロップ(破棄)します。サーバー側からすると「通信がタイムアウトした!」という現象になって現れます。
—
3. 実務で遭遇するトラブルと、その対策・コード例
では、こうした非対称ルーティングやNATのトラブルに直面したとき、現場のSREやインフラエンジニアはどうやって解決すればよいのでしょうか?
基本中の基本は、「パケットの往路と復路が、必ず同じゲートウェイ(または同じステートフル機器)を通るようにルートを対称(Symmetric)にする」ことです。
対策例:Terraformでのルートテーブル設計(AWSの例)
複数のNATゲートウェイやカスタムルーター(EC2インスタンス等)を配置する場合、可用性ゾーン(AZ)ごとに完全に独立したルートテーブルを割り当て、通信がクロスしないように設計するのが鉄則です。
以下は、Terraformを用いて、プライベートサブネットからの通信を「同じAZ内にあるNATゲートウェイ」に確実にルーティングする設定のサンプルです。
# プライベートサブネット(AZ-a用)のルートテーブル
# 往路も復路も、必ず同じAZ-aにあるNATゲートウェイを通るように固定します
resource "aws_route_table" "private_az_a" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.gw_az_a.id # AZ-a専用のNATゲートウェイを指定
}
tags = {
Name = "rt-private-az-a"
}
}
# プライベートサブネット(AZ-c用)のルートテーブル
resource "aws_route_table" "private_az_c" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.gw_az_c.id # AZ-c専用のNATゲートウェイを指定
}
tags = {
Name = "rt-private-az-c"
}
}
このように、インフラを構築する段階で「パケットが迷子にならない一本道」を丁寧に設計してあげることで、非対称ルーティングの発生を未然に防ぐことができます。
—
4. トラブルシューティングの現場:どうやって見つけるの?
もし「なんだか特定の通信だけが時々おかしいぞ」という現場に遭遇したら、以下のステップで調査を進めてみましょう。
1. VPCフローログを確認する
REJECT や DROP されたパケットがないか、ログをAWS AthenaやGCPのCloud Loggingで検索します。送信元と宛先のIPポートが記録されているので、どの経路で消えているかの当たりをつけます。
2. パケットキャプチャ(tcpdumpなど)を仕掛ける
怪しいルーターやインスタンスのネットワークインターフェースにログインし、tcpdump -nnvvS などのコマンドを使って、本当にパケットが往来しているか、片方向だけになっていないかをリアルタイムで覗き見します。
# 例: eth0インターフェースを通る外部との通信(ポート443)をキャプチャする
sudo tcpdump -i eth0 -nnvv 'port 443'
このコマンドを叩いたときに、リクエストの「プッシュ([P.])」は見えているのに、相手からの応答([S.] や [.])が全く返ってこない場合、途中のルーターやファイアウォール(またはNAT)でパケットが握りつぶされている可能性が非常に高いと言えます。
—
まとめ
今回は、非対称ルーティングの恐ろしいメカニズムと、それがNATセッションをいかにして破綻させるかを、郵便配達の例えを交えて解説しました。
- ポイントのおさらい
- ステートフルなファイアウォールやNATは「往路の記憶」を持っている。
- 復路のパケットが別のルート(別の機器)を通ると、記憶がないためパケットが容赦なく捨てられる。
- 対策の基本は「往路と復路を同じ道に通す(ルートテーブルの対称性を守る)」こと。
クラウドやKubernetesのネットワークは、目に見えないからこそ、こうした論理的な「データの流れ」を頭の中でイメージできるかどうかが、一人前のエンジニアへの分かれ道になります。
「あれ、変だな?」と思ったときは、パケットの気持ちになって「私はどこから来て、どこへ帰ろうとしているのだろう?」と優しく想像してあげてくださいね。
それでは、次回のクラウド航海日誌でお会いしましょう!ステキなインフラライフを!
コメント