メインコンテンツへスキップ
  1. Posts/

IP、MAC、ARP、TCP/UDP、NAT/PATは実際の通信でどのようにつながるか?

·17 分
NineKoo9
著者
NineKoo9
目次

このドキュメントは疑問に思っていた点をAIエージェントと対話しながらまとめたメモです。IPとMACの役割の違いからARP、TCP/UDP、NAT/PATまで実際のパケットの流れに合わせて整理します。

目次
#

  1. 基礎 — IPアドレス vs MACアドレス
  2. ARP(Address Resolution Protocol)
  3. TCP — 接続指向プロトコル
  4. TCP 3-Way Handshake(接続の確立)
  5. TCP 4-Way Handshake(接続の終了)
  6. UDP
  7. NAT(Network Address Translation)
  8. PATポート番号変換メカニズム

1. 基礎 — IPアドレス vs MACアドレス
#

例えで理解する
#

概念例え
IPアドレス家の道路名住所(論理アドレス、ネットワークによって変わる場合がある)
MACアドレス同じLANでフレームを転送する際に参照するインターフェースアドレス(通常はNICに割り当てられるが変更されることもある)
  • IPアドレス192.168.0.10のような形式。ネットワーク上で「どこへ送るか」経路を見つけるために使用
  • MACアドレスAA:BB:CC:DD:EE:FFのような形式。同じネットワーク(LAN)内でイーサネットフレームをどのインターフェースへ送るか識別する際に使用

💡 核心:インターネット全体のルーティングはIP基準で、イーサネットのようなローカルリンクで次のホップまでフレームを送る際にMACアドレスが使われる。


2. ARP(Address Resolution Protocol)
#

ARPはなぜ必要なのか?
#

イーサネットLANで同じリンクの相手や次のホップにフレームを送るためには、その対象のMACアドレスが必要だ。 アプリケーションやOSは通常まずIPアドレスを知っているため、このIPをMACアドレスに解決する過程が必要だ。

「IPはわかったけど、MACアドレスはどうやって知るの?」 → ARPが解決してくれる。


ARPの動作過程
#

シナリオ1:PCが初めて外部ネットワークに出ようとするとき(Gateway MACアドレス探索)
#

[PC] ─────────── [Gateway/ルーター] ─────── [インターネット]

Step 1. PCが外部との通信を試みる

  • PCは外部ネットワークに出ようとする時点でGateway(ルーター)のMACアドレスが必要になる場合がある
  • しかしGatewayのMACアドレスを知らない!

Step 2. ARP Request(要求) — Broadcast

PCがネットワーク全体に呼びかける:
「私は192.168.0.1(Gateway IP)を持つ装置を探しています!
 MACアドレスをお持ちの方は答えてください!」
  • これをBroadcastという → 同じネットワークのすべての装置に送信
  • Broadcastアドレス:FF:FF:FF:FF:FF:FF

Step 3. ARP Reply(応答) — 通常Unicast

Gatewayが応答:
「私だよ!私のMACアドレスはAA:BB:CC:DD:EE:FFだよ!」
  • 一般的な応答はUnicast → 要求したホストに1:1で送信

Step 4. ARPキャッシュへの保存

  • PCは受け取ったMACアドレスをARPキャッシュテーブルに保存
  • 次回はまた聞かなくてよい(一定時間後に期限切れ)
# WindowsでARPキャッシュを確認するコマンド
arp -a

シナリオ2:ネイバー(韓国の検索エンジン)にアクセスするとき
#

[PC] → [Gateway/ルーター] → [インターネット] → [ネイバーサーバー]

核心的な疑問:「ネイバーサーバーのMACアドレスに直接送るべきか?」

❌ 違う! 理由:

  • ネイバーサーバーは別のネットワークにある
  • MACアドレスは同じリンク/LAN内でのみ直接意味がある
  • 別のネットワークに出るには**Gateway(ルーター)**を経由しなければならない

したがってPCが実際にすること:

目的地IP  → ネイバーサーバーIP(203.xxx.xxx.xxx)
目的地MAC → GatewayのMACアドレス  ← 核心ポイント!

📌 別のサブネットへ出るパケットは、リモートサーバーのMACではなく、まずデフォルトゲートウェイのMACに転送する。

Gatewayは受け取ったパケットを見て:

  1. 目的地IPを確認
  2. どこにルーティングするか決定
  3. 次の経路に転送

同じサブネット内の別のホストに送る場合は、このとき相手ホストのMACアドレスをARPで探す。


シナリオ3:DHCP + ARPの組み合わせ
#

PCが起動時にIPを自動的に受け取る過程を単純化して見ると:

1. PC起動
2. DHCPDISCOVER → Broadcast
3. DHCPOFFER ← DHCPサーバーの応答
4. DHCPREQUEST → 使用するアドレスのリクエスト
5. DHCPACK ← IPアドレスと設定の確定
6. その後、同じリンクでGatewayのMACアドレスが必要な場合はARPを実行

💡 DHCPはデフォルトゲートウェイのIPアドレスをオプションとして提供できるが、ゲートウェイのMACアドレスまでは提供しない。 だからローカルリンクで実際にフレームを送る前には、やはりARPが必要だ。

毎回ARPをするのは無駄なのでARPキャッシングで保存して再使用する。


3. TCP — 接続指向プロトコル
#

TCP vs UDP の比較
#

特性TCPUDP
接続接続後に通信(Connection)接続なしで直接送信
信頼性高い(再送、順序保証)低い
速度相対的に遅い速い
使用場所Web、メール、ファイル転送ストリーミング、ゲーム、DNS
ヘッダーサイズ通常20〜60バイト8バイト

TCPの核心概念:シーケンス番号(Sequence Number)
#

TCPはデータを**断片(Segment)**に分けて送る。

シーケンス番号 1,    サイズ:1460バイト  → ACK番号 1461
シーケンス番号 1461, サイズ:1460バイト  → ACK番号 2921

このように動作する理由:

  • パケットが途中で消失したり順序が変わる場合がある
  • シーケンス番号で**「何番目のバイトまで正しく受け取ったか」**を追跡できる
  • 欠けた番号があれば → 再送要求

TCP接続自体は通常送信元IP/ポート + 目的地IP/ポートの組み合わせで区別され、Sequence番号はその接続内でバイトストリームの位置を追跡する。


4. TCP 3-Way Handshake(接続の確立)
#

なぜ3回もやり取りするのか?
#

両側が互いに確認しなければならない:

  1. 「私は送れる?」 → 「うん、あなたが送るの受け取ったよ」
  2. 「私も送れる?」 → 「うん、あなたが送るの受け取ったよ」

これを効率的にまとめると3回になる。


詳細な過程
#

Client                              Server
  |                                    |
  |  ① SYN(seq=100)                  |
  | ─────────────────────────────────> |
  |                                    |
  |  ② SYN+ACK(seq=300, ack=101)     |
  | <───────────────────────────────── |
  |                                    |
  |  ③ ACK(seq=101, ack=301)         |
  | ─────────────────────────────────> |
  |                                    |
  |         [接続の確立完了!]           |

① Client → Server:SYN
#

  • SYN:Synchronize(同期化)フラグ
  • Clientが言う:「私はseq=100から始めるよ。接続しよう!」

② Server → Client:SYN + ACK
#

  • SYN:「私はseq=300から始めるよ!」
  • ACK:「あなたの100番受け取ったよ。次は101番をちょうだい」(ack=100+1=101)
  • 2つを一度に送る → 効率的!

③ Client → Server:ACK
#

  • 「あなたの300番受け取ったよ。次は301番をちょうだい」(ack=300+1=301)
  • この時点から**接続完了!**データ転送が可能

3-Way Handshakeで交換するもの
#

TCP 3-way handshakeの核心は初期シーケンス番号の同期化で、SYN区間で必要な場合はMSSのようなTCPオプションも一緒に渡される。

1. Sequence Numberの交換

  • 互いの初期シーケンス番号を共有
  • これで今後やり取りするバイトを追跡

2. MSS(Maximum Segment Size)

  • 「私はこの接続でこのサイズまでのTCPデータの断片を受け取れる」
  • MSSはよく「ネゴシエーション」のように説明されるが、正確には各方向で自分が受信できるサイズを知らせる値
  • 実際の転送サイズは相手が広告したMSSとパスのMTUなどを合わせて考慮して決定される

5. TCP 4-Way Handshake(接続の終了)
#

なぜ4回も必要なのか?
#

3-Wayと違って、終了は一方向ずつ別々に閉じられるからだ。

理由:TCPは双方向通信のため、各方向を独立的に終了できる。

以下の例はClientが先に終了を開始するActive Closeの状況だ。実際にはどちらの側でも先に終了を開始できる。


詳細な過程
#

Client(Active Close)              Server(Passive Close)
  |                                    |
  |  ① FIN(seq=1000)                 |
  | ─────────────────────────────────> |
  |                                    |
  |  ② ACK(ack=1001)                 |
  | <───────────────────────────────── |
  |                                    |
  |  (FIN_WAIT_2状態で待機)          |  ← サーバーが残りのデータを
  |                                    |     送信し終える時間
  |  ③ FIN(seq=2000)                 |
  | <───────────────────────────────── |
  |                                    |
  |  ④ ACK(ack=2001)                 |
  | ─────────────────────────────────> |
  |                                    |
  |(TIME_WAIT待機後に完全終了)       |  完全終了

① Client → Server:FIN
#

  • 「私はこれ以上送るデータがない。接続を切ろう」
  • しかしまだ受け取ることは可能な状態(Half-Close)

② Server → Client:ACK
#

  • 「わかった、あなたのFIN受け取ったよ」
  • Serverはまだ送るデータが残っている可能性がある
  • この間にServerが残りのデータを送信

③ Server → Client:FIN
#

  • 「私も今すべて送り終えた。接続を切ろう」

④ Client → Server:ACK
#

  • 「わかった、完全に終了するよ」
  • Clientはすぐに終了せずTIME_WAIT状態でしばらく待機
    • 理由:最後のACKの再送が必要な場合があり、遅延した重複セグメントがネットワークに残っている可能性があるため

FIN + ACKがなぜよく別々に見えるのか?
#

説明の便宜上FIN → ACK → FIN → ACKの4段階をよく描くが、常に4つの個別パケットに分かれるわけではない。

3-WayでSYN+ACKを一度にまとめたのと違って、終了区間は以下のように動作する場合がある。

  • ServerはClientのFINを受け取るとまずACKで受信の事実を知らせなければならない
  • しかしServerの側にまだ送るデータが残っていれば、自分のFINは後で送る
  • 逆に送るデータがこれ以上なければ、ACKとFINを同じセグメントに乗せて送ることもできる

つまり、代表的な状態遷移は4-way closeとして説明するが、実際のパケット数は状況によってまとまる場合がある。


6. UDP
#

UDPヘッダーがシンプルな理由
#

TCPヘッダー:送信元ポート、目的地ポート、シーケンス番号、ACK番号、
          フラグ、ウィンドウサイズ、チェックサム、緊急ポインター...(通常20〜60バイト)

UDPヘッダー:送信元ポート、目的地ポート、長さ、チェックサム(8バイト)

UDPの特徴
#

  • 内蔵の再送/順序保証/フロー制御がない:TCPのように相手がどれだけ受け取れるか確認しながら転送速度を調整する機能がプロトコルの基本に含まれていない
  • 必要な制御はアプリケーションレベルで実装しなければならない
  • マルチメディアによく使われる理由:映像/音声ストリーミングはわずかな損失よりリアルタイム性の方が重要な場合が多い

7. NAT(Network Address Translation)
#

NATが必要な理由 — IPv4アドレス不足の問題
#

IPv4アドレスの総数:   約43億個
世界のインターネット機器:数十億台以上

IPv4アドレスが限られているため生まれた代表的な解決策の一つ: 「公開IP1つで複数の機器がインターネットを使おう」 → NAT

💡 ここで言うNAT/PATは主に家庭用IPv4環境基準の説明だ。


公開IP vs プライベートIP
#

区分公開IP(Public IP)プライベートIP(Private IP)
付与主体ISP(KT、SKTなど)通常は内部DHCPサーバー/ルーター
インターネット通信グローバルインターネットで直接ルーティング可能グローバルインターネットで直接ルーティングされない
一意性世界中で唯一同じプライベートネットワーク内でのみ唯一
203.245.10.5192.168.0.x10.x.x.x172.16.x.x172.31.x.x
[インターネット]
   |
   | ← 公開IP:203.245.10.5(ISPが自宅に付与)
   |
[ルーター/Gateway] ← 公開IP + プライベートIP の両方を持つ!
   |
   |── 192.168.0.2(自分のノートPC)
   |── 192.168.0.3(自分のスマホ)
   |── 192.168.0.4(自分のTV)

NATの動作原理
#

📤 出るとき(内部 → 外部)
#

[ノートPC 192.168.0.2 : ポート5000]
[ルーター] 送信元IP/ポートを入れ替え!
送信元:192.168.0.2:5000  →  203.245.10.5:12345(公開IP)
目的地:ネイバーサーバー

ルーターがNATテーブルに記録:

プライベートIP:ポート          公開IP:ポート
192.168.0.2:5000  ↔  203.245.10.5:12345
192.168.0.3:6000  ↔  203.245.10.5:12346
192.168.0.4:7000  ↔  203.245.10.5:12347

📥 入るとき(外部 → 内部)
#

[ネイバーサーバー] → 203.245.10.5:12345 に応答を送信
[ルーター] NATテーブルを検索!
「12345ポートは192.168.0.2:5000だった」
目的地を192.168.0.2:5000に復元して転送

💡 ポート番号でどの機器のリクエストかを区別するのが核心! これをPAT(Port Address Translation)またはNAPTとも呼ぶ


NATの種類
#

種類説明使用例
Static NATプライベートIP 1個 ↔ 公開IP 1個の固定マッピング社内サーバーの外部公開
Dynamic NAT公開IPプールから動的に割り当て企業環境
PAT(最も一般的)公開IP 1個 + ポートで複数の機器を区別家庭用ルーター

NATのメリット・デメリット
#

✅ メリット

  • IPアドレスの節約 — 公開IP 1個で複数の機器がインターネットを使用できる
  • アドレスの秘匿 — 内部のプライベートIP体系が外部に直接露出しない

❌ デメリット

  • 外部から内部への直接アクセスが難しい
    • 従来のoutbound-initiated NATでは、NATテーブルや静的マッピングがなければ外部から内部ホストに先にアクセスするのが難しい
    • これがゲームをするとき**「ポートフォワーディング」**が必要な代表的な理由
  • 追跡が難しい — 同じ公開IPから複数のユーザーが出てくるのでログ分析が複雑

📌 NATはアドレス変換機能だ。実務ではステートフルフィルタリングと一緒に動作する場合が多いが、NAT自体がファイアウォールと同じ概念ではない。


ポートフォワーディング(NATの応用)
#

「外部から自分のサーバーにアクセスしたい」

外部ユーザー → 203.245.10.5:8080 にアクセス
ルーター設定:「8080ポートに来たものは192.168.0.2:8080に転送して」
自分のノートPCサーバーに到達 ✅

ルーターの管理ページでポートフォワーディングルールを直接作成すればよい。


8. PATポート番号変換メカニズム
#

核心的な問題状況
#

ノートPC  192.168.0.2:51234  →  ネイバー:443
スマホ    192.168.0.3:51234  →  ネイバー:443  ← ポートまで同じ!
TV        192.168.0.4:51234  →  ネイバー:443

ルーターの視点からこれを公開IP一つで送り出すと誰のもの? → 応答が返ってきたときに誰に渡せばいいかわからない


クライアントポート番号の特性
#

TCP/UDPでクライアントが使用するポートは通常Ephemeral Port(一時ポート)

Well-Known Port:  0     〜 1023   (HTTP:80、HTTPS:443などサーバー用)
Registered Port:  1024  〜 49151  (登録されたアプリケーション用)
Ephemeral Port:   49152 〜 65535  ← クライアントが動的に使用

クライアントはサーバーに接続するとき、この範囲からOSが動的にポートを一つ選んで使う。


ポート変換方式 — 3つのケース
#

✅ ケース1:衝突がない場合(そのまま通過)
#

ノートPC  192.168.0.2:51234  →  ルーター  203.245.10.5:51234  →  ネイバー
スマホ    192.168.0.3:62891  →  ルーター  203.245.10.5:62891  →  ネイバー

送信元ポートが違えばそのまま同じ外部ポートにマッピングされる場合がある。 NATテーブルに記録しておくだけでOK。

NATテーブル:
プライベート側              公開側
192.168.0.2:51234  ↔  203.245.10.5:51234
192.168.0.3:62891  ↔  203.245.10.5:62891

🔥 ケース2:ポートの衝突が発生(核心!)
#

ノートPC  192.168.0.2:51234  →  すでにNATテーブルにある!
スマホ    192.168.0.3:51234  →  同じ外部ポートを使おうとしているがすでに使用中!

このときルーターがすること:

1. NATテーブルで該当の外部ポートの使用状況を確認
2. 衝突を検知
3. 使用可能な別の外部ポートを選択
4. 例:51235が空いている → スマホのパケットのポートを51235に置き換え
5. 変換して送り出す
NATテーブル:
プライベート側              公開側
192.168.0.2:51234  ↔  203.245.10.5:51234  (元のまま維持)
192.168.0.3:51234  ↔  203.245.10.5:51235  ← ポート番号が変更された

どの外部ポートを選ぶかはNATの実装によって異なる。


ケース3:NATテーブルは思ったより多くの情報を参照する
#

実際のNATの実装はポートだけを見るのではなく、セッション情報をより精密に追跡する。

RFC 4787はUDP NATの動作を説明する際にセッションを以下のようなendpoint tupleの観点から見ている。

(送信元IP : 送信元ポート : 目的地IP : 目的地ポート)

例えば:

192.168.0.2:51234 → ネイバー:443
192.168.0.2:51234 → Google:443

同じ内部ポートを使っていても目的地が違えば別のセッションとして管理される場合がある。 ただし外部ポートの再使用方式はendpoint-independent / address-dependent / address-and-port-dependentのようにNATの実装によって異なる場合がある。


全体の流れの例
#

① ノートPC(192.168.0.2:51234) → ネイバー:443 リクエスト
   ルーター:テーブル確認 → 空いている → そのまま51234を使用
   NATテーブル登録:0.2:51234 ↔ 公開:51234 → ネイバー:443

② スマホ(192.168.0.3:51234) → ネイバー:443 リクエスト
   ルーター:テーブル確認 → 公開:51234→ネイバー:443 はすでに使用中
   → 別の外部ポートを選択 → 例:51235に変換
   NATテーブル登録:0.3:51234 ↔ 公開:51235 → ネイバー:443

③ ネイバー → 公開:51234 に応答
   ルーター:51234 → ノートPC(192.168.0.2:51234)に転送 ✅

④ ネイバー → 公開:51235 に応答
   ルーター:51235 → スマホ(192.168.0.3:51234)に転送 ✅

限界 — ポートの空間は有限だ
#

使用可能なポート番号の範囲:0 〜 65535

公開IP 1個だけで維持できる同時セッション数にはポート空間の限界がある。 実際に使用可能な数は予約ポート、実装方式、プロトコル別の分離などによって変わる場合がある。

大型企業/ISP環境ではこれも足りなくなって:

  • 公開IPを複数プールで運用
  • または**Carrier-Grade NAT(CGNAT)**のようにNATを大規模に運用

全体像の最終整理
#

PC起動
  └─→ DHCPでIPを取得
  └─→ ARPでGatewayのMACアドレスを取得
  └─→ NATでプライベートIP → 公開IPに変換
  └─→ TCP 3-Way Handshakeでサーバーと接続
  └─→ データのやり取り(Seq/ACKで信頼性を保証)
  └─→ TCP 4-Way Handshakeで接続終了
世界中のインターネット
      |
   公開IP(203.245.10.5)
      |
   [ルーター] ← NAT/PATを実行
   /   |   \
  スマホ  PC   TV
192.  192.  192.
168.  168.  168.
0.3   0.2   0.4
(プライベートIPたち)

核心まとめカード
#

概念一行まとめ
ARPIPアドレスからリンク層アドレスを見つけ出すプロトコル
MACアドレス同じLAN内でフレームを転送する際に参照するインターフェースアドレス
TCP 3-WaySYN → SYN+ACK → ACK で接続を確立、初期Seq番号の同期化とSYNオプションの交換
TCP 4-Way代表的にFIN → ACK → FIN → ACK で接続終了、実際のパケットは状況によってまとまる場合がある
NATプライベートIP ↔ 公開IPの変換でIPv4プライベートネットワークが外部と通信できるようにする方式
PATポート番号も一緒に変換して複数のプライベートホストを公開IP 1個にマッピング
ポートの衝突ルーターが別の外部ポートを選択してNATテーブルに記録
UDP接続なしで最小限のヘッダーで転送し、信頼性制御はアプリケーションが担当

参考資料
#