Dev Study
← ネットワークの仕組み
レッスン 8 / 13·約 14 分·第2期 ネットワークの仕組み

ポートという多重化 — 1本の線に何本もの会話

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理今ここ
  7. DB保存

第18週までで「どのホストへ届けるか」が決まりました。ここからは第21〜24週で、届いた先の「どのアプリのどの会話か」を扱う段に入ります。今回はその入口である宛名の付け方です。

まず結論

1本の回線の上で何十本もの通信が同時に成立しているのは、宛先を「どのホストか」だけでなく「そのホストのどの窓口か」まで細かくしたからです。この窓口の番号がポートで、届いたデータをどの会話に振り分けるかを決めます。

ただし「ポート番号が会話を識別している」という言い方は不正確です。RFC 9293 は接続を「ソケットのペア」で定義しており、ソケットとはIPアドレスとポートの組です。識別に使われているのは片方のポートではなく、両端のIPとポートを合わせた値です。

? 読む前に予測

エフェメラルポート(通信のたびに自動で割り当てられる一時的なポート)の範囲は、OSが違っても同じでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

IPアドレスだけでは、宛先が粗すぎる

第18週までで、宛先IPアドレスを見て次の行き先を決める仕組みを見ました。これで荷物は目的のホストまで届きます。

しかし、届いた先で困ります。1台のPCでは、同時にいくつものプログラムが通信しています。 ブラウザで何枚ものタブを開き、裏でメールが受信され、エディタが更新を確認している。これらは全部、同じ1本の回線と同じ1つのIPアドレスを使っています。届いたデータがどのプログラムのどの会話のものかを決めなければなりませんが、IPアドレスは「この建物宛て」までしか言っていません。

そこで宛名をもう一段細かくします。それがポート番号です。16ビットの数値で、0から65535まで。「どのホストか」の下に「そのホストのどの窓口か」を付け足すわけです。

1本の共有された線の上に、複数の独立した会話を同時に載せる。この考え方を多重化と呼びます。ポートは、TCPやUDPにおける多重化の実現手段です。

具体実物

では、会話を見分けているのはポート番号か

ここで自然に浮かぶ疑問があります。ポート番号が会話を識別しているのなら、同じポートに複数の接続は来られないのではないか。

しかし現実には、1台のWebサーバの443番ポートに、何千もの接続が同時に張られています。矛盾しているように見えます。

答えは、識別に使われているのがポート番号だけではないことです。RFC 9293 の §3.4.1 に、こう書かれています。

A connection is defined by a pair of sockets. (接続はソケットのペアによって定義される)

そして同文書の用語集が、ソケットをこう定義しています。

the concatenation of an Internet Address with a TCP port (インターネットアドレスとTCPポートを連結したもの)

ソケット1つがIPアドレスとポートの組で、接続はそのペアです。展開すると、識別に使われているのは次の4つの値になります。

同じサーバの443番に来ている3本の接続表
送信元IP 送信元ポート 宛先IP 宛先ポート
203.0.113.5 51234 198.51.100.9 443
203.0.113.5 51235 198.51.100.9 443
192.0.2.77 49800 198.51.100.9 443

3本とも宛先は同じ 198.51.100.9 の443番です。それでも取り違えは起きません。1行目と2行目は送信元ポートが違い、3行目は送信元IPが違うので、組み合わせとしては全部別物だからです。

サーバ側の443番は「入口の看板」であって、会話の識別子ではありません。識別しているのは4つの値の組み合わせです。

✓ ここまでの確認

あるサーバの 443番ポートに、2台の別のPCから同時に接続が来ています。サーバ側はどちらも同じ443番を使っているのに、2つの通信を取り違えずに扱えるのはなぜですか。

抽象原理

「4つ組」という呼び方は、どこから来たのか

上の4つの値を、解説記事やAIの説明では four-tuple(4つ組) と呼ぶことがよくあります。便利な呼び方ですし、指している内容も正しいものです。ただし、本教材の主題に関わる注意があります。

もう一点、章番号にも注意が要ります。接続の識別について書かれているのは §3.4.1 と用語集であり、§3.1 はヘッダフォーマットの節です。第14週で引用した疑似ヘッダの話が §3.1 だったので、混同しやすい場所です。出典は文書番号だけでなく節まで合っているかが問われます。節がずれていると、確認しようとした人が「書いていない」ことに気づいて、説明全体の信用が落ちます。

⇄ 2つを見比べる
具体例 A

TCPの接続を識別する組

サーバ側の443番という番号だけでは、どの会話かは決まりません。同じ443番に何千もの接続が同時に来るからです。番号が意味を持つのは「相手のIPと相手のポートで区切られた1本の接続の中」であり、その外に出すと一意性を失います。だから接続の識別には、両端のIPとポートを合わせた組が必要になります。

443という番号だけでは決まらない表
見ている値 一意に決まるか
宛先ポート 443 だけ 決まらない(何千本も該当)
宛先IP + 宛先ポート 決まらない(相手が複数いる)
両端のIPとポート(4値) 決まる
具体例 B

OSのファイルディスクリプタ(第13週)

第13週で見たシステムコールでは、開いたファイルを番号で指しました。fd の 3番はそのプロセスの中でだけ意味を持ちます。別のプロセスの3番はまったく別のファイルを指しますし、その番号を他のプロセスに伝えても通じません。番号が有効なのは「そのプロセス」という範囲の中だけです。

プロセスごとに独立した fd の番号追跡ログ
プロセスA fd 3 → /var/log/app.log
プロセスB fd 3 → /etc/hosts
プロセスC fd 3 → ソケット
※ 同じ「3番」が3つの別のものを指している

TCPの接続を識別する組と、OSのファイルディスクリプタ。層も用途もまったく違うこの2つに共通している構造は何でしょうか。そしてその構造は、番号を扱ううえでどんな注意を要求するでしょうか。

「その番号は、どこまで持ち出すと通じなくなるか」に注目して比べてください。

抽象原理

ここが山場 — 規格の範囲と、OSが実際に使う範囲は違う

ポート番号は0から65535まであり、用途によって区分されています。この区分の呼び方が、通説と公式で食い違っている箇所です。

IANAによるポート範囲(RFC 6335 §6)表
範囲 第一の名称 併記されている別名
0-1023 System Ports Well Known Ports
1024-49151 User Ports Registered Ports
49152-65535 Dynamic Ports Private / Ephemeral Ports

数値の区分は通説どおりで正しく、違うのは呼称だけです。 教科書や記事では Well-known / Registered / Private を見ることが多いので、「公式名称は Well-known だ」と思い込んでいることがあります。どちらも間違いではありませんが、IANAが第一に使っているのは System / User / Dynamic の方なので、両方を併記するのがいちばん正確です。

割り当ての手続きも範囲ごとに違います。System Ports は IETF Review または IESG Approval、User Ports はそれに Expert Review を加えた手続きが必要です。そして Dynamic Ports は、IANAが割り当てを行いません。 誰のものでもない領域として空けてあります。

これは「Linuxが規格違反をしている」という話ではありません。Dynamic Ports はIANAが割り当てを行わない領域で、各ホストが自分の都合で使ってよい場所だからです。

押さえてほしいのは、「エフェメラルポートは 49152-65535 です」という一文が、どのOSの話かによって正しくも誤りにもなるということです。

✓ ここまでの確認

「エフェメラルポートは 49152-65535 と決まっている」という説明の評価として、最も正確なのはどれですか。

具体実物

この差が実務で効く場面

範囲の違いは、知識の細部ではなく計算結果を変えます。

同時に張れる接続の数を見積もる場面を考えてください。1台のクライアントから同じ宛先(同じIP・同じポート)へ接続するとき、区別の材料になるのは送信元ポートだけです。したがってエフェメラルポートの本数が、そのままの上限になります。

使えるポートの本数(同一の宛先IP・宛先ポートに対して)表
範囲 本数
IANA基準 49152-65535 16384
Linux 既定 32768-60999 28232
macOS 既定 49152-65535 16384

同じ構成のはずのサーバでも、OSが違えば見積もりが変わります。「16384本で頭打ちになるはず」という前提でLinuxの挙動を説明しようとすると、数字が合いません。

そして、この差は規格を読んだだけでは分かりません。RFC 6335 を何度読んでも、Linuxが 32768 から始めることは書かれていないからです。手元の値は、手元で読むしかありません。

この章のまとめ

  • IPアドレスは「どのホストか」までしか決めない。同じホストの中の複数の会話を見分けるために、ポート番号という16ビットの窓口番号を足した。これが多重化の実現手段。
  • 会話を識別しているのは片方のポート番号ではない。RFC 9293 §3.4.1 は接続を「ソケットのペア」で定義し、用語集はソケットを「インターネットアドレスとTCPポートの連結」としている。実質的に両端のIPとポートの4つの値で識別される。
  • ★RFC 9293 に "four-tuple" という語は無い。 内容は正しくても「RFC 9293 が4つ組と呼んでいる」は出典の誤帰属になる。また接続の識別は §3.4.1 と用語集であり、§3.1 はヘッダフォーマットの節。
  • IANAの第一の名称は System(0-1023)/ User(1024-49151)/ Dynamic(49152-65535)。Well Known / Registered / Private(Ephemeral)は RFC 6335 が併記する別名。数値区分は通説どおりで、違うのは呼称だけ。
  • Dynamic Ports はIANAが割り当てを行わない領域なので、使い方は各OSが決める。
  • ★その結果、エフェメラルポートの範囲はOSによって違う。Linux既定は 32768-60999 でIANAの範囲と一致せず(下に食い込み、上は届かない)、macOS は 49152-65535 で一致する(実測。FreeBSD は 10000-65535)。
  • 「規格にこう書いてある」と「手元の機械がそう動く」は別の問い。範囲は手元で読む(/proc/sys/net/ipv4/ip_local_port_range / sysctl net.inet.ip.portrange.*)。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 4正解: 0

「RFC 9293 は、TCPの接続を four-tuple(4つ組)と呼んで定義している」という説明の評価はどれですか。

用語集(5語)
ポート番号
ホストの中のどの窓口宛てかを示す16ビットの番号。0から65535まで。IPアドレスが「どのホストか」を決めるのに対し、ポートは「そのホストのどの会話か」を決める。
ソケット (socket)
RFC 9293 の用語集では「インターネットアドレスとTCPポートを連結したもの」。IPアドレスとポート番号の組を1つの宛名として扱ったもので、接続はこのソケットのペアで定義される。
多重化 (multiplexing)
1本の共有された経路の上に、複数の独立した通信を同時に載せること。受け取った側がどの通信のものかを見分けられるよう、宛名を細かくすることで成り立つ。
System / User / Dynamic Ports
IANAによるポート範囲の第一の名称。順に 0-1023 / 1024-49151 / 49152-65535。RFC 6335 は別名として Well Known / Registered / Private(Ephemeral)も併記している。
エフェメラルポート
クライアントが接続するたびにOSが自動で割り当てる一時的な送信元ポート。範囲はOSの設定で決まり、Linuxの既定 32768-60999 はIANAの Dynamic Ports と一致しない。