悪魔は「往復の経路」に宿る:クラウドネットワークにおける非対称ルーティングとNATセッション破綻の深淵
SREの現場にいると、「なぜか特定のパケットだけが帰ってこない」「TCPコネクションがSYNで止まる」という不可解な事象に遭遇することがあります。ログを見てもアプリケーションに到達していない。パケットキャプチャをとると、確かにSYNは出ているのに、ACKが永遠に返ってこない……。
この「通信の死」の多くは、ネットワークの設計図上は正しいように見えて、実態としては非対称ルーティング(Asymmetric Routing)という罠に陥っていることが原因です。今日は、クラウドインフラを設計・運用するエンジニアなら避けて通れない、NATゲートウェイとステートフルファイアウォールの「静かな喧嘩」について解説します。
—
1. なぜ「往路」と「復路」が食い違うのか
ネットワークの教科書では、パケットは最短ルートを通るように書かれています。しかし、クラウド環境では「冗長化」や「マルチAZ構成」のために複数の出口(NAT GatewayやVPN Gateway)を用意することが一般的です。
ここで発生する典型的な非対称ルーティングのシナリオを見てみましょう。
1. 往路: プライベートサブネットのサーバーからインターネットへ、NAT Gateway A を経由してパケットを送出する。
2. 復路: インターネットからのレスポンスパケットが、何らかのルーティング設定(BGPのコスト設定や、単純なルートテーブルのミス)により、NAT Gateway B に戻ってきてしまう。
このとき、NAT Gateway B はどう反応するでしょうか?
答えは非常に冷徹です。「私はこの通信の行き(SYN)を見ていないので、帰りのパケット(ACK)が来ても誰の許可も得ていない不正なパケットだ」と判断し、容赦なくドロップします。これが、ステートフルなファイアウォールやNATの「セッションテーブル」による破綻です。
—
2. ステートフルな防壁のメカニズム
NATゲートウェイやクラウド上の仮想ファイアウォール(AWSのSecurity GroupやGCPのCloud Armorなど)は、ステートフルに動作します。これは、通信の「状態」を記憶していることを意味します。
- SYN(往路): 送信元NATがテーブルに
Source IP: 10.0.1.5 -> Dest IP: 8.8.8.8というマッピングを記録する。 - SYN/ACK(復路): テーブルに記録された情報と一致するパケットのみを通過させる。
もし復路が別のNATデバイスに到達すると、そのデバイスのNATテーブルには該当する通信の「状態」が存在しません。結果、パケットは「未知のトラフィック」として弾かれます。
デバッグ時のリアルな視点
実際にこの現象が起きているかを確認するには、tcpdump よりもクラウドネイティブなフローログを確認するのが一番です。
# AWS VPC Flow Logsで確認すべき項目
# action: REJECT
# pkt-srcaddr: (戻りの送信元IP)
# pkt-dstaddr: (サーバーのプライベートIP)
# tcp-flags: (ACKやSYN/ACKなど)
このとき、action が REJECT になっているパケットの interface-id を見てください。本来通るべきNATゲートウェイのインターフェースを通っていないことが発覚するはずです。
—
3. コードで再現する「沈黙のタイムアウト」
例えば、Pythonの requests や curl を使って、このようなネットワーク環境でAPIを叩いた場合、アプリケーション側では単なる「タイムアウト」として観測されます。
import requests
# 非対称ルーティングが発生している環境では、
# 接続確立後のACKが戻らず、以下のタイムアウトエラーが頻発する
try:
response = requests.get('https://api.external-service.com', timeout=5)
print(response.status_code)
except requests.exceptions.ConnectTimeout:
# 実際にはここには到達せず、TCP Handshakeでスタックする
print("ネットワーク経路のどこかでパケットが破棄されています")
クライアント側で curl -v を実行すると、Trying [IP]... の後に Operation timed out が続くはずです。これは「相手にパケットは届いているが、こちらの返事を受け取れていない」ことを示唆しています。
—
4. 現場での解決策:どう設計すべきか
非対称ルーティングを防ぐための黄金律は、「往復の経路を論理的に一致させること」です。
1. ルートテーブルの集中管理:
サブネットごとのルートテーブル設定を厳格化し、デフォルトゲートウェイへの経路を固定します。複数のNATを使う場合は、サブネットごとに NAT Gateway を紐付け、AZ跨ぎの通信で経路がねじれないように設計します。
2. ソースNAT(SNAT)の強制:
戻りパケットが意図したゲートウェイに返るよう、送信元IPアドレスを制御します。
3. Firewallの「ステートレス」化を検討(最終手段):
どうしても非対称ルーティングを避けられない特殊なネットワーク構成(例:複雑なオンプレミスとのハイブリッド構成)では、ステートフルな機能を無効化できるデバイスや、対称性を保証するルーティングポリシー(PBR: Policy Based Routing)を検討しますが、運用コストが跳ね上がるため推奨しません。
—
最後に:SREとしての一言
非対称ルーティングは、クラウドネットワークにおける「隠れた殺人鬼」です。パケットは常に自分の通った道を覚えているわけではありません。しかし、NATやファイアウォールは、その道筋を厳格に記憶しています。
トラブルシューティングの際は、必ず「往路と復路のパケットが同じゲートウェイを通っているか?」を設計図と照らし合わせて確認してください。ネットワークの「魔法」を信じるのではなく、パケットが物理的・論理的にどう流れるかという「現実」を直視すること。それこそが、堅牢なインフラを守る唯一の道です。
次回は、この非対称ルーティングを意図的に引き起こすような「マルチホーム構成」の設計パターンと、それを安全に捌くための高度なルーティング設定について掘り下げていきたいと思います。それでは、良いデバッグライフを!
コメント