こんにちは!SREとして日々クラウドの荒波と格闘している筆者です。
インフラやネットワークの世界に足を踏み入れたばかりの頃って、専門用語の壁にぶつかって「うっ…」となってしまいますよね。特に、TCPのような「通信相手としっかり握手をしてから会話を始める行儀の良いプロトコル」ならまだしも、「コネレス型」を自称するUDPに出会ったとき、「お前、相手が誰だかわかってないのにどうやって通信してるんだよ!」と突っ込みたくなった方も多いはずです。
今回は、そんな自由奔放なUDPトラフィックが、パブリッククラウドの門番であるNATゲートウェイを通過するときに、裏側でどうやってスマートに管理されているのかを、現実世界の例えを交えながら一歩ずつ優しく紐解いていきましょう!
—
1. そもそもUDPってどんなやつ?(郵便配達に例えてみよう)
TCP通信が「電話」だとすれば、UDPはズバリ「手紙やハガキ」です。
TCP(電話)の場合:
1. 「もしもし?今から話せる?」と相手を呼び出す(コネクション確立)
2. 「はい、大丈夫です」と返事が来てから会話が始まる
3. 話し終わったら「じゃあ切るね」とお互いに確認する
これに対して、UDP(手紙)はこんな感じです:
1. 便箋にメッセージを書いて、宛先(IPアドレスとポート番号)を封筒に書き、ポストにポンと投函する
2. 相手が今留守だろうが、そもそも宛先の住所に家があろうがなかろうが、お構いなしに送り出す
3. 返事が来るかどうかは、相手の優しさに全賭け!
この「一方通行で気楽」な性格が、オンラインゲームのリアルタイムな位置情報送信や、ライブ配信の音声・映像データ(VoIP)などで大活躍しています。一刻を争う世界では、いちいち「今届いた?」「もう一回送って」と確認している暇がないからです。
—
2. プライベート空間から外の世界へ:NATゲートウェイの登場
さて、ここで問題が発生します。
私たちがAWSやGCPなどのクラウド上で構築するサーバーの多くは、セキュリティを高めるためにプライベートサブネットという「外の世界からは直接見えない秘密基地」の中に配置されます。
この秘密基地にいるサーバーたちが、インターネット上の外部サービスにUDPでデータを送りたいとき、どうすればよいでしょうか?
プライベートIPアドレスは「内輪の住所」なので、そのままではインターネットの荒海に出ることができません。そこで登場するのが、海の玄関口で住所を書き換えてくれるNATゲートウェイ(NAT GW)です。
現実世界で例えるなら、NATゲートウェイは「巨大なオフィスの総務部(受付)」のような存在です。
秘密基地(プライベートサブネット)にいる平社員(サーバー)が、外の取引先に向けて手紙を出そうとします。しかし、会社の外に出るには、会社の代表住所(パブリックIPアドレス)に書き換えてもらわなければなりません。
—
3. ここが本番!UDPにおける「ステートフルセッション管理」の魔法
TCPであれば、「今から通信を始めます」という合図(SYNパケット)があるため、NATゲートウェイも「あ、新しい通信が始まったんだな」と簡単に察知できます。
しかし、合図なしでいきなり手紙を投げつけてくるUDPにおいて、NATゲートウェイはどのように往来を管理しているのでしょうか?ここに、クラウドの賢い仕組みである「ステートフルセッション管理」の秘密があります。
往路:プライベートから外部へ(手紙の投函)
1. 秘密基地のサーバー(例: 10.0.1.100 のポート 50000)が、外の宛先(例: 8.8.8.8 のポート 53)に向けてUDPパケットを送り出します。
2. パケットがNATゲートウェイを通過するとき、NAT GWはこう考えます。
> 「おっ、内側の 10.0.1.100:50000 から外の 8.8.8.8:53 宛てのUDPパケットが来たぞ。これは新しい旅立ちだな。よし、自分の持っている外向けの住所(パブリックIP 203.0.113.5)の適当なポート(例えば 40000)をこの通信専用に割り当てて、帳面にメモしておこう!」
3. NAT GWは、送信元IPを自分のパブリックIPに書き換えて、インターネットへ送り出します。これがステートフル(状態を覚えている)の第一歩です。
復路:外部からプライベートへ(返事の到着)
1. インターネットの向こうにいる相手から、お返しのUDPパケットがやってきました。宛先は、NAT GWが外に向けて名乗った住所(203.0.113.5:40000)です。
2. NAT GWは、自分の手元にある「帳面(セッションテーブル)」をチラッと確認します。
> 「ええと、40000番ポート宛ての荷物だな……。あ、これはさっき社内の 10.0.1.100さんの50000番ポート が出張させたやつだ!」
3. NAT GWは、宛先を元のプライベートIP (10.0.1.100:50000) に書き換えて、秘密基地の中へ無事に届けてあげます。
このように、UDPという「本来は行きっぱなしの通信」であっても、NATゲートウェイが水面下で「誰が・どこに・どのポートで通信したか」というセッション(状態)を記憶・管理しているからこそ、無事に往復のやり取りが成り立つんです。
—
4. 一歩進んだ実務の知見:UDPタイムアウトの罠
ここで、現場のSREとして一つ、とても大切な実務上の注意点(ハマりポイント)をお伝えしておきます。
TCPには接続を切る明確な手順がありますが、UDPには「通信終わりました」という公式の合図がありません。そのため、NATゲートウェイは「最後にパケットが流れてから、一定時間動きがなかったら、このセッションの記憶を消去しよう」というタイマーを持っています。これをUDPタイムアウト(アイドルタイムアウト)と呼びます。
例えば、AWSのNATゲートウェイの場合、UDPのアイドルタイムアウトはデフォルトで30秒に設定されています(※GCPのCloud NATなどでも同様のタイムアウトが存在します)。
現場でよくあるトラブル
「あれ? リアルタイム通信のアプリを作ったんだけど、数分間放置すると、向こうからのデータがピタッと届かなくなるんだよね……」
これは、30秒間UDPパケットのやり取りがなかったため、NATゲートウェイが「もうこの通信は終わったな」と判断して帳面の記憶(セッション)をシュレッダーにかけてしまったのが原因です。その後に外から返事が来ても、NAT GWは「そんな人知りません」とパケットを捨てて(ドロップして)しまいます。
これを防ぐためには、アプリケーション側やインフラ側で「キープアライブ(死活監視)パケット」を定期的に(例えば20秒おきなどに)飛ばし、NATゲートウェイのタイマーをリフレッシュし続ける泥臭い工夫が必要になります。
—
5. インフラ構築時の設定例(Terraformのイメージ)
それでは最後に、AWS環境でこのNATゲートウェイとプライベートサブネットをどのように定義するのか、実際のコード(Terraform)のイメージを覗いてみましょう。
# =================================================================
ニッチな設定も怖くない!パブリックサブネットとNATゲートウェイの定義
=================================================================
# 1. パブリックサブネット(外の世界の出入り口)
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-northeast-1a"
tags = {
Name = "blog-sample-public-subnet"
}
}
# 2. 外部通信用の固定パブリックIP(EIP)の確保
resource "aws_eip" "nat" {
domain = "vpc"
depends_on = [aws_internet_gateway.igw]
tags = {
Name = "blog-sample-nat-eip"
}
}
# 3. NATゲートウェイの作成(ここでUDPステートフルセッション管理が行われます)
resource "aws_nat_gateway" "gw" {
allocation_id = aws_eip.nat.id
subnet_id = aws_subnet.public.id
tags = {
Name = "blog-sample-nat-gateway"
}
# コメント:NAT GWは、TCPだけでなくUDPのポートマッピングとステート管理も自動で処理してくれます
}
# 4. プライベートサブネット(秘密基地)からのデフォルトルート設定
resource "aws_route_table" "private" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.gw.id
}
tags = {
Name = "blog-sample-private-route-table"
}
}
このように、インフラ側の設定としては「外に出るための門(NAT GW)」をきちんと用意してルートを向けておくだけで、クラウドの基盤側がよしなにUDPのステートフル管理を行ってくれます。しかし、その裏側で「NAT GWがセッションを覚えてくれているおかげで返事が返ってくるんだな」「タイムアウトには気をつけなきゃいけないんだな」という仕組みを知っているだけで、トラブルシューティングのスピードが何倍も変わってくるのです。
—
まとめ
今回は、UDPトラフィックにおけるNATゲートウェイのステートフルセッション管理について、郵便配達の例えを交えながら解説しました。
- UDPは手紙のようなもの(気楽だけど相手の返事は保証されない)。
- プライベートサブネットから外に出るとき、NATゲートウェイが総務部の受付のように「誰がどの通信をしたか」を帳面(セッションテーブル)に記憶(ステートフル管理)している。
- この記憶があるおかげで、外からの返り討ち(復路パケット)も正しいサーバーの元に届く。
- ただし、UDPには終わりの合図がないため、タイムアウト(無言の時間が続くと記憶が消える仕様)には注意が必要!
難しく見えたクラウドのネットワークも、一つひとつの挙動を身近なものに置き換えてみると、ぐっと身近に感じられるようになりますよね。
それでは、また次回のインフラ解説記事でお会いしましょう!SREの筆者でした。
コメント