188 lines
7.6 KiB
Markdown
188 lines
7.6 KiB
Markdown
|
|
---
|
|||
|
|
tags: [计算机网络, IPv4, IP首部, TTL, MTU, 分片]
|
|||
|
|
create time: 2026-05-17 23:40
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# IPv4 首部与分段重组
|
|||
|
|
|
|||
|
|
## 概述
|
|||
|
|
|
|||
|
|
IPv4 数据包是互联网的基本传输单元。理解其首部结构,有助于排查 MTU 问题、分析抓包工具输出、以及理解 IP 级故障恢复机制。
|
|||
|
|
|
|||
|
|
## IPv4 首部格式(32-bit fields)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Version(4b) │ IHL(4b) │ DSCP/ECN(8b) │ Total Length(16b) │
|
|||
|
|
├─────────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Identification(16b) │DF│ MF │Offset(13b)│
|
|||
|
|
├─────────────────────────────────────────────────────────────────┤
|
|||
|
|
│ TTL(8b) │ Protocol(8b) │ Header Checksum │
|
|||
|
|
├─────────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Source Address (32b) │
|
|||
|
|
├─────────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Destination Address (32b) │
|
|||
|
|
├─────────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Options (variable) │
|
|||
|
|
│ ...padding... │
|
|||
|
|
└─────────────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 各字段详解
|
|||
|
|
|
|||
|
|
| 字段 | 大小 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| **Version** | 4 bit | 版本号,IPv4 = `0100` |
|
|||
|
|
| **IHL** (Internet Header Length) | 4 bit | 首部长度,单位 4 bytes。**最小值 5**(20 bytes),最大 15(60 bytes) |
|
|||
|
|
| **DSCP** (Differentiated Services Code Point) | 6 bit | QoS 优先级标记;前 3 bit 为 ECN(Explicit Congestion Notification)|
|
|||
|
|
| **Total Length** | 16 bit | 整个 IP 包总长(含首部),最大 65535 字节 |
|
|||
|
|
| **Identification** | 16 bit | 唯一标识符。同一原始包的分片共享此 ID |
|
|||
|
|
| **DF** (Don't Fragment) | 1 bit | 置 1 则禁止分片;路由器不能分片的包如果 DF=1,直接丢弃并返回 ICMP "Fragmentation Needed" |
|
|||
|
|
| **MF** (More Fragments) | 1 bit | 置 1 表示后面还有分片;最后一个分片 MF=0 |
|
|||
|
|
| **Fragment Offset** | 13 bit | 该分片在原始数据中的偏移量(以 8 字节为单位) |
|
|||
|
|
| **TTL** (Time To Live) | 8 bit | 生存时间,每经过一个路由器减 1,归零时丢弃并发送 ICMP Timeout |
|
|||
|
|
| **Protocol** | 8 bit | 上层协议编号:TCP=6, UDP=17, ICMP=1, IGMP=2 |
|
|||
|
|
| **Header Checksum** | 16 bit | 仅校验首部的 CRC,**不校验 payload** |
|
|||
|
|
| **Source/Dest Address** | 各 32 bit | 源和目的 IP 地址 |
|
|||
|
|
|
|||
|
|
### 最小 vs 最大 IP 包
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
最小 IP 包: 20B 首部 + 0B 数据 = 20 bytes
|
|||
|
|
最小以太网帧承载: 20B 首部 + 8B ICMP Echo = 28 bytes
|
|||
|
|
→ 加上 14B EthHdr + 4B FCS = 46 bytes ≥ MTU 下限 ✅
|
|||
|
|
|
|||
|
|
最大 IP 包: 20B 首部 + 65515B 数据 = 65535 bytes
|
|||
|
|
受限于链路 MTU: 通常 1500B Payload → 最大常用包 1520 bytes
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## TTL 深度解析
|
|||
|
|
|
|||
|
|
### TTL 的常见误解
|
|||
|
|
|
|||
|
|
很多人以为 TTL 的单位是秒。其实在 IPv4 中它是**跳数计数器**——每经过一个路由器(三层转发节点)减 1,不是按时间递减。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart LR
|
|||
|
|
A["Source<br/>TTL=64"] -->|"路由器减1"| B["TTL=63"]
|
|||
|
|
B -->|"路由器减1"| C["TTL=62"]
|
|||
|
|
C -->|"路由器减1"| D["TTL=61"]
|
|||
|
|
D -->|"到目的地"| E["TTL=60<br/>继续处理"]
|
|||
|
|
|
|||
|
|
style A fill:#DDA0DD,color:#000
|
|||
|
|
style E fill:#98FB98,color:#000
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 查看 TTL 的实践
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# ping 默认从 64 或 128 开始,减去到达时的 TTL ≈ 经过了跳数
|
|||
|
|
$ ping -c 1 example.com
|
|||
|
|
PING example.com (93.184.216.34): 56 data bytes
|
|||
|
|
64 bytes from ... icmp_seq=0 ttl=55 time=23.1 ms
|
|||
|
|
# 64 - 55 = 9 跳
|
|||
|
|
|
|||
|
|
# Windows 默认 TTL=128
|
|||
|
|
$ tracert example.com
|
|||
|
|
1 1 ms 1 ms 1 ms 192.168.1.1
|
|||
|
|
2 2 ms 2 ms 2 ms 10.0.0.1
|
|||
|
|
...
|
|||
|
|
9 23 ms 23 ms 23 ms 93.184.216.34
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Linux 系统初始 TTL
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
$ sysctl net.ipv4.ip_default_ttl
|
|||
|
|
net.ipv4.ip_default_ttl = 64
|
|||
|
|
|
|||
|
|
# macOS / Windows 默认 128
|
|||
|
|
# 某些嵌入式设备可能用 32 或 60
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## MTU 与分片(Fragmentation)
|
|||
|
|
|
|||
|
|
### 什么是 MTU?
|
|||
|
|
|
|||
|
|
MTU(Maximum Transmission Unit)是链路层允许的最大 IP 包载荷大小。超出 MTU 的包需要被**分片**。
|
|||
|
|
|
|||
|
|
| 链路类型 | 典型 MTU | Jumbo Frame |
|
|||
|
|
|----------|---------|-------------|
|
|||
|
|
| Ethernet | 1500 bytes | 9000 bytes |
|
|||
|
|
| Wi-Fi (802.11n/ac/ax) | 1500 | ❌ 不支持 |
|
|||
|
|
| PPPoE (宽带拨号) | 1492 (预留 8B PPPoE头) | — |
|
|||
|
|
| IPv6 | 1280 (硬性最小) | 可选 |
|
|||
|
|
| GRE 隧道 | 1476 (预留 24B GRE头) | — |
|
|||
|
|
| VXLAN | 1450 (预留 50B VxLAN头) | — |
|
|||
|
|
|
|||
|
|
### 分片规则
|
|||
|
|
|
|||
|
|
当 IP 包 > MTU 且 DF=0 时,路由器将其切分为多个分片:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
原始 IP 包 (Payload = 3000 bytes) ── MTU=1500 ──→
|
|||
|
|
|
|||
|
|
分片 1: Headers + [Bytes 0..1479] Offset=0 MF=1
|
|||
|
|
分片 2: Headers + [Bytes 1480..2959] Offset=185*8=1480 MF=1
|
|||
|
|
分片 3: Headers + [Bytes 2960..2999] Offset=370*8=2960 MF=0 (最后一片)
|
|||
|
|
↑ offset × 8 = 实际偏移
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**关键限制:** 除最后一个分片外,每个分片的 payload 必须是 **8 字节的整数倍**。这就是为什么 offset 字段以 8 字节为单位。
|
|||
|
|
|
|||
|
|
### 分片的优缺点
|
|||
|
|
|
|||
|
|
| 优点 | 缺点 |
|
|||
|
|
|------|------|
|
|||
|
|
| 允许大应用层数据穿越小 MTU 链路 | 增加路由器的 CPU 负担 |
|
|||
|
|
| 透明(对应用层无感知) | 任一丢包导致整个原始包失效 |
|
|||
|
|
| — | 攻击者可以利用分片做碎片攻击(Teardrop 等) |
|
|||
|
|
| — | IPv6 已取消中间路由器分片,改由端到端 PMTUD |
|
|||
|
|
|
|||
|
|
### PMTUD(Path MTU Discovery)
|
|||
|
|
|
|||
|
|
现代网络推荐使用 **路径 MTU 发现**而非分片:
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant Src as 源主机
|
|||
|
|
participant R as 瓶颈路由器(MTU=1400)
|
|||
|
|
participant Dst as 目标服务器
|
|||
|
|
|
|||
|
|
Src->>Dst: IP Packet (size=1500, DF=1)
|
|||
|
|
Note over Src: DF(Do Not Fragment)=1
|
|||
|
|
R->>R: MTU=1400 < 1500, DF=1 → 无法分片!
|
|||
|
|
R->>Src: ICMP Type 3 Code 4 "Fragmentation Needed"
|
|||
|
|
Note over Src: Path MTU = 1400 - IP头(20) - Eth(14) = 1366
|
|||
|
|
Src->>Dst: IP Packet (size=1366, DF=1) ✅
|
|||
|
|
Dst-->>Src: ACK ✅
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 检查当前 PMTUD 状态
|
|||
|
|
$ ip route show | grep mtu
|
|||
|
|
default via 192.168.1.1 dev eth0 mtu 1500
|
|||
|
|
|
|||
|
|
# Linux 内核 PMTUD 控制
|
|||
|
|
$ sysctl net.ipv4.tcp_mtu_probing
|
|||
|
|
net.ipv4.tcp_mtu_probing = 0 # 0=关闭, 1=低速率, 2=始终开启
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 协议编号对照表
|
|||
|
|
|
|||
|
|
| Protocol 值 | 名称 | 用途 |
|
|||
|
|
|------------|------|------|
|
|||
|
|
| 1 | ICMP | 网络诊断(ping、traceroute) |
|
|||
|
|
| 2 | IGMP | 组播管理 |
|
|||
|
|
| 6 | TCP | 可靠面向连接传输 |
|
|||
|
|
| 17 | UDP | 无连接不可靠传输 |
|
|||
|
|
| 47 | GRE | 虚拟私有隧道 |
|
|||
|
|
| 50 | ESP | IPsec 加密封装安全载荷 |
|
|||
|
|
| 51 | AH | IPsec 认证头 |
|
|||
|
|
| 89 | OSPF | 动态路由协议 |
|
|||
|
|
|
|||
|
|
## 关联笔记
|
|||
|
|
|
|||
|
|
- [[hhs/NETWORK/CIDR与子网划分]] — IP 地址的子网分配方法
|
|||
|
|
- [[hhs/NETWORK/NAT原理与应用]] — NAT 如何处理 IP 包的 Checksum
|
|||
|
|
- [[hhs/NETWORK/ICMP与Ping-Traceroute]] — ICMP 协议细节
|