IP 协议------ 网络层的"快递单号与物流追踪"
一、IP 协议全称是什么
IP = Internet Protocol,互联网协议。
当前主流版本是 IPv4 (IPv6 是下一代,本文聚焦 IPv4,后续可单独开篇)。简单说:IP 协议给每个网络设备分配一个全球唯一的"门牌号",路由器根据目的 IP 查路由表,把数据包从源网络逐跳转发到目的网络。
二、为什么需要 IP 协议
前面几篇我们讲了 Ethernet II(二层帧怎么封装)、ARP(IP 怎么解析成 MAC)、VLAN(怎么隔离广播域)、LLDP(设备怎么自动发现邻居)。但有一个核心问题一直没解决:
数据包从 A 网络到 B 网络,中间跨了无数个路由器和子网,怎么知道往哪走?
没有 IP 的世界:
|-------------|-------------------------------------------------|-----------------------------------------|
| 痛点 | 没有 IP 的世界 | 有 IP 之后 |
| 跨网通信 | 只能在同一个二层广播域内通信,跨网段就断了 | 路由器根据 IP 查路由表,逐跳转发到任意网络 |
| 寻址方式 | 靠 MAC 地址,但 MAC 是平面地址(无层次),无法聚合,路由器存不下全世界的 MAC 表 | IP 是层次化地址(网络号+主机号),可以路由聚合,全球路由器协同工作 |
| 路径选择 | 不知道"下一跳"是谁 | 每个路由器只看目的 IP 的网络部分,查路由表决定从哪个口扔出去 |
| 故障隔离 | 一个广播风暴全挂 | TTL 机制防止环路无限转发;分片机制适应不同链路的 MTU |
| 异构网络互联 | 不同二层技术(以太网、Wi-Fi、PPP、光网络)无法直接互通 | IP 作为"通用语言"跑在所有二层之上,屏蔽底层差异 |
一句话总结:IP 协议解决的是"跨网络通信时,数据包怎么从源主机经过多个路由器到达目的主机"的问题。它是整个 TCP/IP 协议栈的"物流调度中心"。
三、IP 协议的核心机制
3.1 快递类比:物流调度系统
把网络通信想象成寄快递:
|--------------|------------------------------------------------------|
| 网络概念 | 快递类比 |
| IP 地址 | 收件人/寄件人的详细地址(省市区街道门牌) |
| 源 IP | 寄件人地址 |
| 目的 IP | 收件人地址 |
| 路由器 | 分拣中心(看目的地址决定往哪个方向转运) |
| 路由表 | 分拣中心的"转运规则表"(北京来的件往北口扔,上海来的往南口扔) |
| TTL | 快递包裹上的"最大中转次数",每过一个分拣中心减 1,到 0 就被销毁(防止包裹在分拣中心之间无限循环) |
| IP 分片 | 大包裹拆成小箱(因为有些路段限重/限尺寸),到目的地再拼起来 |
| ICMP | 物流追踪短信("您的包裹已到达XX中转站""地址不存在,退回") |
关键区别 :快递是"端到端"的(从寄件人到收件人),但 IP 是**"逐跳"**的------每个路由器只负责把包扔给"下一跳",不保证整条路径都通。
3.2 IPv4 头部结构(20 字节固定部分 + 可选字段)
IPv4 头部是 IP 协议的核心,每个 IP 数据包前面都带着这个"快递单":

逐字段解读:
|----------------------------|------------|----------------------------------------------------------------------------|---------------------------|
| 字段 | 长度 | 含义 | 实验观察要点 |
| **版本 (Version)** | 4 bit | IPv4 = 4,IPv6 = 6 | Wireshark 里确认是 4 |
| **IHL (Header Length)** | 4 bit | 头部长度,单位 4 字节。无可选字段时 = 5(即 5×4=20 字节) | 有可选字段时会 >5 |
| DSCP + ECN | 8 bit | 服务质量标记(优先级/拥塞通知) | 普通流量通常为 0 |
| **总长度 (Total Length)** | 16 bit | 整个 IP 包的长度(头部+数据),最大 65535 字节 | ping -s 指定大小可观察变化 |
| **标识 (Identification)** | 16 bit | 同一个原始数据包分片后,所有分片的标识相同 | 分片实验中关键字段 |
| **标志 (Flags)** | 3 bit | bit 0 保留;bit 1 = DF(Don't Fragment,不许分片);bit 2 = MF(More Fragments,还有更多分片) | DF=1 且包超 MTU 会被丢弃并返回 ICMP |
| **片偏移 (Fragment Offset)** | 13 bit | 分片在原始数据包中的位置,单位 8 字节 | 第一个分片为 0 |
| **TTL (Time To Live)** | 8 bit | 存活跳数,每经过一个路由器减 1,到 0 丢弃并返回 ICMP 超时 | traceroute 的核心原理 |
| **协议号 (Protocol)** | 8 bit | 上层协议类型:1=ICMP,6=TCP,17=UDP | Wireshark 里看"Protocol"列 |
| 头部校验和 | 16 bit | 只校验 IP 头部(不校验数据),每跳重新计算 | 排障时偶发校验错误会导致丢包 |
| 源 IP 地址 | 32 bit | 发送方的 IP | 可伪造(IP 欺骗攻击) |
| 目的 IP 地址 | 32 bit | 接收方的 IP | 路由器根据它查路由表 |
| 可选字段 | 可变 | 记录路由、时间戳等(极少用) | 通常无 |
3.3 IP 地址的结构:网络号 + 主机号
IPv4 地址是 32 位,通常写成点分十进制(如 192.168.164.128)。它的核心设计是层次化编址:
IP 地址 = 网络号(Network) + 主机号(Host)
└── 标识"哪个网络" ──┘ └── 标识"网络内哪台设备" ──┘
**子网掩码(Subnet Mask)** 用来划分这两部分的边界:
|---------------------|---------------|-------------|---------------------------------------------|
| 表示法 | 网络号位数 | 主机数 | 示例 |
| /24 (255.255.255.0) | 前 24 位 | 254 台 | 192.168.10.0/24 → 网络号 192.168.10,主机号 0~255 |
| /16 (255.255.0.0) | 前 16 位 | 65534 台 | 172.16.0.0/16 |
| /8 (255.0.0.0) | 前 8 位 | 1677 万台 | 10.0.0.0/8 |
同网段判断:两台设备的 IP 分别和自己的子网掩码做"与运算",结果相同 = 同一网络 = 二层直连可达(不需要路由器)。
192.168.164.128 & 255.255.255.0 = 192.168.164.0
192.168.164.129 & 255.255.255.0 = 192.168.164.0
→ 相同,同网段,直接 ARP + 二层通信
3.4 TTL 递减机制(防环核心)
TTL 是 IP 协议里最精妙的设计之一:
纯文本
Host A (TTL=64) → Router1 → Router2 → Router3 → Host B
发送包 TTL:64→63 TTL:63→62 TTL:62→61 收到包(TTL=61)
- 源主机发包时设置初始 TTL(Linux 默认 64,Windows 默认 128)
- 每经过一个三层设备(路由器),TTL 减 1
- 如果 TTL 减到 0 还没到达目的地 → 路由器丢弃该包,并向源主机发送 ICMP 超时消息(Type 11)
这就是 traceroute的工作原理:故意发 TTL=1、2、3... 的包,看每个路由器返回的 ICMP 超时,从而画出完整路径。
3.5 IP 分片与 MTU
MTU (Maximum Transmission Unit) = 二层链路能承载的最大帧的数据部分大小。以太网默认 MTU = 1500 字节。
当 IP 包的总长度 > 出接口的 MTU 时:
|---------------------|----------------------------------------|
| 情况 | 行为 |
| DF=0(允许分片) | 路由器将大包拆成多个小包,每个 ≤ MTU,接收端根据"标识+片偏移"重组 |
| DF=1(禁止分片)且包 > MTU | 路由器丢弃包,向源发送 **ICMP 不可达(需要分片但 DF 置位)** |
分片示例:
纯文本
原始 IP 包:总长度 3000 字节(20 字节头部 + 2980 字节数据),DF=0,MTU=1500
分片 1:头部(20) + 数据(1480) → 总长度 1500,MF=1,片偏移=0
分片 2:头部(20) + 数据(1480) → 总长度 1500,MF=1,片偏移=185 (1480/8)
分片 3:头部(20) + 数据(20) → 总长度 40, MF=0,片偏移=370 (2960/8)
接收端根据"标识"相同归为一组,按"片偏移"排序,拼出原始数据。
四、VMware 实际抓包测试
4.1 实验环境
|------------|---------------------------|
| 项目 | 配置 |
| 虚拟机 | 两台 Ubuntu 22.04 桌面版 |
| VMware 网络 | 两台均设为"自定义:VMnet1(仅主机)" |
| Host A | ens33: 192.168.164.128/24 |
| Host B | ens33: 192.168.164.129/24 |
| 抓包工具 | Wireshark |
注:本实验用仅主机模式(同二层),验证 IP 头部字段。跨网段/路由实验需引入第三台虚拟机做路由器或物理路由器。
4.2 步骤一:基础 ping 抓包(观察 IP 头部)
4.2.1、在 Host A 上打开 Wireshark,选择 ens33,过滤 icmp,然后执行:
ping -c 4 192.168.164.129
4.2.2、 Wireshark 中 IPv4 头部展示:

关键字段对照:
- Version (4): 0100,表示 IPv4 协议。
- Header Length (20 bytes) : 0101(5 个 32 位字,5×4=20 字节)。说明没有可选字段(Options),是标准的默认头部。
- Differentiated Services (0x00) : DSCP 为 CS0,ECN 为 Not-ECT。表示普通优先级,无拥塞标记,常规 ping 报文默认如此。
- Total Length (84) : IP 头部 + 数据总长度为 84 字节。
- 推算:IP 头 20 字节 + ICMP 报文 64 字节(ping 默认 56 字节数据 + 8 字节 ICMP 头 = 64)。
- Identification (0xe39f / 58271): 标识号。由于未分片,此字段仅作为该数据包的唯一标识,接收端重组时才会大量用到。
- Flags (0x4000, Don't fragment) :
- DF(Don't Fragment)位被置 1,表示禁止分片。
- 结合你前序的 IP 协议文章,ping 默认常带 DF 标志,用于路径 MTU 探测。
- Fragment offset (0): 未分片,偏移量为 0。
- Time to live (64): TTL 初始值为 64。这是 Linux 系统的典型默认 TTL(Windows 常为 128)。每经过一个三层设备减 1,同网段直连不扣减(或仅作为出接口处理)。
- Protocol (1) : 上层协议号为 1,代表 ICMP。这告诉接收端将载荷交给 ICMP 模块处理。
- Header checksum (0x8cb6): 头部校验和(Wireshark 显示 Unverified 是因为常见校验和卸载功能,不影响实际解析)。
- Source (192.168.164.128): 源 IP,对应你的 Ubuntu(164 网段已修复)。
- Destination (192.168.164.129): 目的 IP,同网段目标。

4.3 步骤二:TTL 递减验证(traceroute 原理)
4.3.1、在 Host A 上执行(限制 TTL 观察逐跳行为):
# 方法:traceroute(需安装)
sudo apt install -y traceroute
执行命令:
traceroute 192.168.164.129
执行结果如下:

1 ) 命令与目标解析
- traceroute 192.168.164.129:探测从当前主机(.128)到目标(.129)的路径。
- 30 hops max:默认最大探测 30 跳(TTL 从 1 递增到 30)。
- 60 byte packets:探测包大小。通常包含 40 字节 IP 头 + 20 字节载荷(UDP/ICMP),属于小包,不会分片。
2 ) 结果逐行解读
1 ubuntu (192.168.164.129) 0.034 ms 0.006 ms 0.005 ms
- 第 1 跳(Hop 1):直接到达目标 192.168.164.129(主机名解析为 ubuntu)。
- 无中间路由 :因为 .128 和 .129 同属 192.168.164.0/24 网段,处于 VMnet8 NAT 的同一虚拟二层网络。系统查路由表发现是直连网段,直接走 ens33 发 ARP 获取 MAC 并转发(二层直连),不经过任何三层网关(无需找 .164.2)。
- TTL 机制体现:traceroute 首个包 TTL=1,但由于是直连,目标本机接收时 TTL 未经过三层转发扣减(或目标作为终点直接响应 ICMP Time Exceeded / Echo Reply),因此 1 跳即达。
- 延迟极低:0.034ms(首次)与 0.005ms(后续),属于虚拟机内部虚拟网卡通信的正常微秒级延迟,无网络拥堵。
- 三次探测:每行三个时间值,代表连续发送了 3 个探测包,响应均正常,链路稳定。
4.3.2、Wireshark 抓包观察:
- 过滤 icmp 或 ip.ttl <= 1
- 当 TTL=1 时,对端收到后 TTL 减为 0,返回 ICMP Time-to-live exceeded 消息
在129机器抓包结果如下:

4.3.2.1、 完整交互流程 :
① 终端表现
.128 执行 traceroute 192.168.164.129,由于同网段直连,TTL=1 的包直接到达 .129(第 1 跳即终点),耗时约 2ms,链路通畅。
② 抓包表现(在 .129 抓包)
- .128 向 .129 发送了 UDP 探测包(Wireshark 底部高亮的原始 IP 头:Src: .128, Dst: .129)。
- .129 收到后,发现目的端口是 33434+ 这种高位未监听端口(通常没服务在用)。
- 根据 UDP/ICMP 规则,目标主机会向源地址回送 ICMP Type 3, Code 3(Destination unreachable / Port unreachable),告诉对方:"IP 到了,但这个 UDP 端口没程序接"。
- 图中连续 6 个 ICMP 报错(源 .129 → 目的 .128),对应了 traceroute 默认每跳发 3 个包(你终端显示了 3 个时间值),加上可能的重传或 TTL 递增探测。
③ 为什么终端没报错?
traceroute 程序逻辑就是:收到 ICMP Port Unreachable = 到达最终目标,于是停止探测并打印出 1 192.168.164.129 ...,一切符合预期。
4.4 步骤三:IP 分片演示
1、 用 ping 发送大于 MTU ( 1500B ) 的包(DF=0 允许分片):
1) # 发送 3000 字节的 ICMP 包(不允许分片 → 应失败)
ping -c 1 -M do -s 3000 192.168.164.129
执行结果如下:

结果:报错 ping: local error: message too long, mtu=1500 发生在本地发送前:
- 接口(如 ens33)的 MTU 为 1500 字节(标准以太网)。
- 待发包总长 3028 字节 > 1500 字节,且 DF=1 不允许分片。
- 本地内核协议栈直接丢弃并拦截,未发出任何报文,因此统计显示 0 received, +1 errors。
2) # 发送 3000 字节(允许分片 → 成功)
ping -c 1 -s 3200 192.168.164.129

Wireshark 过滤 ip.fragment观察:
终端显示:ping -s 3200,3208 bytes from ...
- 原始数据 :ICMP 负载 3200 字节 + ICMP 头 8 字节 = 3208 字节。
- IP 总长度 :3208 + IP 头 20 字节 = 3228 字节(终端也显示了 3228)。
- MTU 限制 :以太网 MTU 1500,IP 头 20,因此每个分片最大数据载荷为 1480 字节(且必须是 8 的倍数,1480 刚好符合)。
- 分片拆解 :
- 分片 1:载荷 1480,IP总长 1500,偏移量 off=0,MF=1(后面还有)
-

- 分片 2:载荷 1480,IP总长 1500,偏移量 off=1480,MF=1(后面还有)
-

- 分片 3:剩余载荷 248(3208 - 1480 - 1480),IP总长 268,偏移量 off=2960,MF=0(最后一片)

- 结论 :3208 = 1480 + 1480 + 248,刚好 3 个分片。
展开任意一个分片,看 Flags: 0x20 (More Fragments) 和 Fragment Offset 的变化。
4.5 步骤四:观察路由表
4.5.1、 查看路由表
ip route
4.5.2、输出:

解读如下:
① 默认路由(走外网/其他网段)
default via 192.168.164.2 dev ens33 proto dhcp metric 100
- 含义:当目标 IP 不匹配任何具体网段时,全部走这条"兜底"路由。
- 下一跳:网关 192.168.164.2。
- 出接口:ens33(你的网卡)。
- 来源与优先级:由 DHCP 自动获取(proto dhcp),优先级度量值为 100。
② 链路本地路由(APIPA)
169.254.0.0/16 dev ens33 scope link metric 1000
- 含义:处理 169.254.x.x 网段(Windows/Linux 自动配置地址)。
- 特性:仅链路生效(scope link),且度量值 1000(优先级最低),通常备用,日常实验可忽略。
③ 直连网段路由(核心:解释同网段直连)
192.168.164.0/24 dev ens33 proto kernel scope link src 192.168.164.128 metric 100
4.5.2、 添加静态路由(模拟跨网段)
sudo ip route add 10.0.0.0/24 via 192.168.164.129
ip route get 10.0.0.1
输出:

解读如下:
1) 命令解析:添加静态路由
sudo ip route add 10.0.0.0/24 via 192.168.164.129
- 动作:手动(静态)添加一条目标网段为 10.0.0.0/24 的路由。
- 下一跳:指定网关为 192.168.164.129(即你之前实验中的直连目标 .129)。
- 隐含条件:因为 .129 在你的 192.168.164.0/24 直连网段内,内核允许将其设为下一跳,路由添加成功。
2) 路由查询解析:实际选路结果
ip route get 10.0.0.1 输出:10.0.0.1 via 192.168.164.129 dev ens33 src 192.168.164.128 cache
- 匹配网段:访问 10.0.0.1 命中了你刚加的 10.0.0.0/24 路由。
- 转发路径 :流量不会走默认网关 .2,而是走下一跳.129。
- 出接口:dev ens33(直连二层发出)。
- 源地址:src 192.168.164.128(本机 IP,与直连路由一致)。
- 缓存:cache 表示内核路由缓存生效,后续同路径包加速处理。
五、故障排查
5.1 IP 通信不通的七大常见原因
|------------------------------|----------------------------|-----------------------------|
| 故障现象 | 可能原因 | 排查方法 |
| Destination Host Unreachable | 同网段但 ARP 失败(对端不在线/不在同一二层) | arp -n 看是否有 MAC |
| Destination Net Unreachable | 路由表中没有到目的网络的路由 | ip route 检查 |
| Request timeout + TTL 正常 | 对端在线但不响应(防火墙/ICMP 被禁) | tcpdump -i ens33 icmp 看是否收到 |
| Time to live exceeded | 路由环路(包在两个路由器之间来回跳) | traceroute 看路径是否出现重复跳 |
| Frag needed and DF set | 包超 MTU 且 DF=1(路径 MTU 发现触发) | ping -M do -s 1472 测试 MTU |
| 大包不通小包通 | MTU 不匹配(中间链路 MTU < 1500) | tracepath 或逐步增大 ping 包大小 |
| IP 冲突 | 两台设备配了同一个 IP | arp -n 看同一 IP 对应多个 MAC |
5.2 排障速查流程
纯文本
ping 不通?按这个顺序查:
- 网卡 UP 吗?
→ ip link show ens33
- IP 配了吗?同网段吗?
→ ip addr show ens33
→ ipcalc 192.168.164.128/24 (算网络号)
- ARP 解析成功吗?
→ arp -n (看目的 IP 有没有 MAC)
- 有路由吗?
→ ip route (看有没有到目的网络的路由)
- 防火墙拦了吗?
→ sudo iptables -L -n -v
→ sudo ufw status
- MTU 问题?
→ ping -M do -s 1472 目的IP
- 路由环路?
→ traceroute 目的IP
5.3 一个真实排障案例
现象:某服务器 ping 外部 IP 小包(56 字节)通,但大包(>1400 字节)超时。SSH 能连上但传输文件卡死。
排查:ping -M do -s 1472 失败,-s 1400 成功。说明路径 MTU 小于 1500。
原因:中间某台路由器接口 MTU 被误配为 1400(可能是 GRE 隧道或 VPN 封装吃掉了部分 MTU)。
解决:调整中间设备 MTU 为 1500+,或在服务器上降低 MTU:sudo ip link set ens33 mtu 1400。
六、总结
|--------------|---------------------------------------------------|
| 要点 | 说明 |
| IP 协议作用 | 网络层寻址与路由,让数据包跨网络从源到目的 |
| IPv4 头部 | 20 字节固定部分,含版本、长度、标识、标志、TTL、协议号、源/目的 IP |
| IP 地址结构 | 网络号 + 主机号,子网掩码划分边界 |
| TTL 机制 | 每跳减 1,防环路,traceroute 的核心原理 |
| IP 分片 | 大包拆小包适应 MTU,接收端重组;DF=1 时超 MTU 丢弃并返回 ICMP |
| 路由表 | 决定"从哪个接口发给哪个下一跳" |
| 与二层关系 | IP 跑在 Ethernet 之上,Ethernet 负责同一链路内的帧传输,IP 负责端到端寻址 |
下一篇预告
第 06 篇:ICMP 协议------ 网络层的"诊断医生"
IP 协议只管"尽力而为"地转发,不保证送达。ICMP 就是 IP 的"配套诊断工具"------当网络出问题时,ICMP 告诉你"为什么不通""卡在哪""怎么绕"。ping 和 traceroute 都是 ICMP 的应用。下篇讲 ICMP 报文类型(回显请求/应答、目的不可达、超时、重定向)、每种类型的排障含义,以及 ping/traceroute 背后的完整交互流程。
附录:命令速查
|------------------|---------------------------------------------------|
| 操作 | 命令 |
| 查看 IP 地址 | ip addr show |
| 查看路由表 | ip route 或 route -n |
| 查询到某 IP 的路由 | ip route get 192.168.164.129 |
| 添加静态路由 | sudo ip route add 10.0.0.0/24 via 192.168.164.129 |
| 删除路由 | sudo ip route del 10.0.0.0/24 |
| 添加默认网关 | sudo ip route add default via 192.168.95.1 |
| ping(指定包大小) | ping -c 4 -s 1000 192.168.164.129 |
| ping(指定 TTL) | ping -c 1 -t 3 192.168.164.129 |
| ping(禁止分片) | ping -M do -s 3000 192.168.164.129 |
| traceroute | traceroute 192.168.164.129 |
| 查看 MTU | ip link show ens33 |
| 修改 MTU | sudo ip link set ens33 mtu 1400 |
| 查看 ARP 表 | arp -n 或 ip neigh |
| 清 ARP 缓存 | sudo ip neigh flush all |
| Wireshark 过滤 IP | ip.addr == 192.168.164.128 |
| Wireshark 过滤分片 | ip.fragment 或 ip.flags.mf == 1 |
| Wireshark 过滤 TTL | ip.ttl <= 1 |