TCP・IPのプロトコル階層とフォーマットの整理

最近このあたりの知識を使うタイミングがあったので、整理として残しておきます。

# プロトコル階層

### アプリケーション層

ユーザーが直接利用するアプリケーションにサービスを提供する層
HTTP, SMTP, FTPなど



### トランスポート層 
アプリケーション間のデータ転送を信頼性と効率性を持って提供する層

- **TCP (Transmission Control Protocol)**
    - コネクション型で信頼性の高いデータ転送を提供します。データの順序制御や再送制御を行い、ウェブブラウジングやメール送受信などに使用されます。
- **UDP (User Datagram Protocol)**
    - コネクションレス型で高速なデータ転送を提供します。信頼性よりも速度を重視するため、動画配信やオンラインゲームなどに使用されます。


### インターネット層 (IP)
異なるネットワーク間でデータを転送するための経路選択やアドレス指定を担当する層
- **IP (Internet Protocol)**
    - データをパケット（データグラム）として送受信し、送信元から目的地までの経路を決定します。現在、IPv4とIPv6が主に使用されています。
- **ICMP (Internet Control Message Protocol)**
    - ネットワークのエラーメッセージや診断情報を転送します。例えば、pingコマンドはICMPを使用しています。
- **ARP (Address Resolution Protocol)**
    - IPアドレスから対応するMACアドレスを取得するためのプロトコル。同一ネットワーク内での通信に使用されます。


### リンク層 (イーサネット(MACアドレス))
物理的なネットワーク媒体上でデータの伝送を行う層

- **イーサネット (Ethernet)**

# ■ ザックリTCPパケットの構造

<img width="518" alt="スクリーンショット 2025-02-19 9.26.35.png (14.1 kB)" src="https://img.esa.io/uploads/production/attachments/5809/2025/02/19/19598/b9aebdae-713b-40c5-ab20-9f0178290a20.png">


# ■ リンク層 
## イーサネットのフレームフォーマット


<img width="1000" alt="スクリーンショット 2025-02-17 0.11.03.png (44.0 kB)" src="https://img.esa.io/uploads/production/attachments/5809/2025/02/17/19598/ebe85a46-3e83-463b-95ce-ed58ff59fb3a.png">


※ 1オクテット = 1バイト


| フィールド               | サイズ  | 説明                                                                  |
|------------------------|--------------|---------------------------------------------------------------------|
| プリアンブル            | 7オクテット   | 1と0を交互に並べたフィールド。「イーサネットの始まり」を示します。       |
| SFD (Start Frame Delimiter) | 1オクテット   | `10101011` 。「フレームの開始」を表すフィールドです。                   |
| 宛先MACアドレス        | 6オクテット   | フレームの宛先MACアドレス。                                          |
| 送信元MACアドレス      | 6オクテット   | フレームの送信元MACアドレス。                                          |
| タイプ                  | 2オクテット   | データ部分のプロトコルを表す番号 (`0800`: IPv4, `0806`: ARP, `86DD`: IPv6, etc...)。 |
| データ                  | 46 ~ 1500オクテット | 上位層プロトコルのHeader + Data。46オクテット未満は0で埋めます。       |
| FCS                     | 4オクテット   | フレーム全体を特定のビット列で割った余りを格納し、エラー検出を行います。       |




















# ■ インターネット層 (IP)
## IPパケットのフォーマット


<img width="1000" alt="スクリーンショット 2025-02-18 23.12.15.png (52.5 kB)" src="https://img.esa.io/uploads/production/attachments/5809/2025/02/18/19598/eec6c5e8-cbd1-4b16-b3c9-331d74bded87.png">

| フィールド              | サイズ  | 説明                                                                                  |
|----------------------------|-----------|---------------------------------------------------------------------------------------|
| **Version**                | 4bit      | IPバージョン。IPv4なら `4` 、IPv6 なら `6`。                                          |
| **IHL (Internet Header Length)** | 4bit  | IPヘッダのサイズを4オクテット(32bit)単位で表します。オプションなしなら `5` (20オクテット)。 |
| **TOS (Type of Service)**  | 8bit      | 送信しているIPのサービス品質。現在はDSCP(6bit), ECN(2bit)として利用。                  |
| **Total Length**           | 16bit     | IPヘッダとIPデータを合計したパケット全体のサイズ(オクテット単位)。                    |
| **Identification**         | 16bit     | フラグメント復元用の識別子。パケット送信ごとにインクリメント。                         |
| **Flags**                  | 3bit      | パケット分割(フラグメント)に関する制御情報。                                          |
| **Fragment Offset**        | 13bit     | フラグメントが元のデータのどこに位置していたかを示す。                                |
| **Time to Live**           | 8bit      | パケットの生存期間。ルーター通過ごとにデクリメントされ、0で破棄。                     |
| **Protocol**               | 8bit      | データ部分のプロトコル。(ICMP=1, IPIP=4, TCP=6, UDP=17, IPv6=41)                     |
| **Header Checksum**        | 16bit     | IPヘッダのチェックサム。                                                             |
| **Source Address**         | 32bit     | 送信元IPアドレス。                                                                   |
| **Destination Address**    | 32bit     | 宛先IPアドレス。                                                                     |
| **Options**                | 可変長    | テスト・デバッグ用に利用。                                                           |
| **Padding**                | 可変長    | Optionを32bitの整数倍にするためのパディング。                                        |
| **Data**                   | 可変長    | IPの上位層プロトコルのHeader + Data                                                 |



























## ICMPパケットのフォーマット

<img width="1032" alt="スクリーンショット 2025-02-18 23.30.56.png (31.6 kB)" src="https://img.esa.io/uploads/production/attachments/5809/2025/02/18/19598/5051d724-c1c9-4368-93bc-0606547ff8c2.png">

| フィールド         | サイズ  | 説明 |
|-------------------|--------|------------------------------------------------|
| **Type**         | 8bit   | 通知メッセージの種類 (`0`: Echo Reply, `8`: Echo, etc...) |
| **Code**         | 8bit   | サブタイプ情報 |
| **Checksum**     | 16bit  | ICMPヘッダとデータのチェックサム |
| **Identifier**   | 16bit  | Echo Reply時にEcho要求と同じ値を格納し、要求を識別 |
| **Sequence Number** | 16bit  | Echo Reply時にEcho要求と同じ値を格納し、要求を識別 |
| **Data**         | 可変   | 送信元が任意のデータを格納可能 |













## ARPパケットのフォーマット

<img width="1030" alt="スクリーンショット 2025-02-19 9.27.35.png (58.5 kB)" src="https://img.esa.io/uploads/production/attachments/5809/2025/02/19/19598/85a25d99-418f-4e5a-a79c-e3412bd99202.png">

ARP要求: IPアドレスからMACアドレスを知るためにブロードキャストで送信
ARP応答: 要求されたIPアドレスが自身のものであった場合に、自身のMACを知らせるために返送

| フィールド           | サイズ   | 説明 |
|---------------------|--------|------------------------------------------------|
| **Hardware Type**   | 16bit  | リンク層プロトコルの種類 (`1`: Ethernet) |
| **Protocol Type**   | 16bit  | Ethernetヘッダで使用されているプロトコルの種類 (`0x0800`: IPv4) |
| **Hardware Size**   | 8bit   | ハードウェアアドレスのサイズ。Ethernetの場合はMACアドレスなので `6` |
| **Protocol Size**   | 8bit   | プロトコルアドレスのサイズ。IPv4の場合は `4` |
| **Opcode**         | 16bit  | ARPリクエストなのか、ARPリプライなのか (`1`: Request, `2`: Reply) |
| **Sender MAC Address** | 48bit  | 送信元のMACアドレス |
| **Sender IP Address**  | 32bit  | 送信元のIPアドレス |
| **Target MAC Address** | 48bit  | 宛先のMACアドレス<br>リクエスト時はブロードキャストになるので `00:00:00:00:00:00` や `ff:ff:ff:ff:ff:ff`  |
| **Target IP Address**  | 32bit  | 宛先のIPアドレス |






















# ■ トランスポート層 

## TCPパケットのフォーマット

<img width="1000" alt="スクリーンショット 2025-02-18 23.23.07.png (51.4 kB)" src="https://img.esa.io/uploads/production/attachments/5809/2025/02/18/19598/7ab77113-8fa2-4c83-990c-148e84f26a7f.png">

| **Field Name**           | ビット数  | 説明                                                                                  |
|-------------------------|-----------|---------------------------------------------------------------------------------------|
| **Source Port**         | 16bit     | 送信元ポート番号。                                                                    |
| **Destination Port**    | 16bit     | 宛先ポート番号。                                                                      |
| **Sequence Number**     | 32bit     | データの順序を管理するための番号。抜けがあると再送を依頼します。                                          |
| **Acknowledgment Number** | 32bit  | 確認応答番号。受信側が次に受信を期待するシーケンス番号を格納します。(シーケンス番号+受信したデータのバイト数)                                            |
| **Data Offset**         | 4bit      | TCPヘッダの長さを4オクテット(32bit)単位で表します。データがTCPパケットの先頭のどこから始まるのかを意味します。                                                   |
| **Reserved**            | 4bit      | 将来の利用のための予約。常に `000`。                                                   |
| **Flags**               | 8bit      | 制御ビット 。8bitそれぞれが `CWR, ECE, URG, ACK, PSH, RST, SYN, FIN` の意味を持ちます。                                     |
| **Window Size**         | 16bit     | 受信側が `Acknowledgment Number` の位置から受信可能なデータサイズ(オクテット数)を格納します。            |
| **Checksum**            | 16bit     | ヘッダとデータのチェックサム。途中のルーターの故障によってデータが破損していないかを確認する目的。       |
| **Urgent Pointer**      | 16bit     | 緊急データ位置。<br> `Flags` の URGが `1` の場合に有効になり、`Data` の先頭から`Urgent Pointer`に格納されている数値(オクテット長)までのデータが緊急データとなります。<br>主に通信を途中で中断する場合に利用されます。(webブラウザの中止ボタン, TELNETでCTRL+Cを入力した場合)                                 |
| **Options**             | 可変長    | 拡張オプション<br>タイプ1: Maximum Segment Size(MSS): コネクション確立時に最大セグメント長を決定<br>タイプ3: WSOPT-Window Scale: Window Sizeを最大1Gオクテットに拡張(通常は64kオクテット)。スループット改善<br> など                      |
| **Padding**             | 可変長    | Optionを32bitの倍数に揃えるためのパディング。                                                |
| **Data**                | 可変長    | TCPセグメントのペイロード。                                                           |























## UDPデータグラムのフォーマット

<img width="1000" alt="スクリーンショット 2025-02-19 8.49.06.png (28.3 kB)" src="https://img.esa.io/uploads/production/attachments/5809/2025/02/19/19598/c337417f-371c-44df-9191-5356d78f40d7.png">

| フィールド      | サイズ | 説明 |
|--------------------|----------------|----------------------------|
| **Source Port**    | 16 bit            | 送信元ポート番号 |
| **Destination Port** | 16 bit            | 送信先ポート番号 |
| **Length**         | 16 bit            | ヘッダ＋データの合計バイト数 |
| **Checksum**       | 16 bit            | エラー検出のためのチェックサム（IPv4ではオプション、IPv6では必須） |
| **Data**           | 可変           | 送信するペイロード（最大65,507バイト） |