网络层核心:IP协议与ICMP协议
网络层是整个TCP/IP协议栈的「交通枢纽」。说白了,它的任务就是把数据包从源主机送到目标主机,中间可能跨过几十个路由器。我经常跟团队里的新人说:你理解了网络层,才算真正入门了网络通信。
这一章我们聚焦两个核心协议:IP协议和ICMP协议。IP负责「怎么送」,ICMP负责「送没送到、出了什么问题」。两者配合,构成了网络层的骨架。
IPv4首部:20字节的「快递面单」
每个IP数据包都有一个首部,就像快递包裹上的面单。IPv4首部标准长度是20字节,但可以带选项,最长到60字节。我建议你把这20字节的结构刻在脑子里——排查网络问题时,它就是你手里的地图。
| 字段 | 长度(bit) | 说明 |
|---|---|---|
| 版本 | 4 | IPv4固定为4 |
| 首部长度 | 4 | 单位4字节,最小5(20字节) |
| 服务类型 | 8 | 现在主要用于DSCP(差分服务) |
| 总长度 | 16 | 首部+数据的总字节数,最大65535 |
| 标识 | 16 | 分片时用于重组 |
| 标志 | 3 | DF(不分片)、MF(更多分片) |
| 片偏移 | 13 | 分片在原包中的偏移量(单位8字节) |
| 生存时间 | 8 | 每经过一个路由器减1,为0时丢弃 |
| 协议 | 8 | 上层协议类型(TCP=6,UDP=17,ICMP=1) |
| 首部校验和 | 16 | 只校验首部,不校验数据 |
| 源IP地址 | 32 | 发送方IP |
| 目的IP地址 | 32 | 接收方IP |
这里面有几个字段我特别想强调一下。
生存时间(TTL)。很多人以为它是「时间」,其实它是「跳数」。每过一个路由器减1,减到0就丢弃,同时给源端发一个ICMP超时消息。我曾经在排查一个路由环路问题时,就是靠抓包看到TTL在几个路由器之间反复递减,才定位到配置错误。
协议字段。它告诉网络层:这个包里的数据应该交给上层的哪个协议。你想想看,如果没有这个字段,收到一个IP包,内核怎么知道该送给TCP还是UDP?
首部校验和。注意,它只校验首部,不校验数据。为什么?因为数据部分有上层协议(比如TCP)自己校验,没必要重复。而且路由器每转发一次就要重新计算校验和(因为TTL变了),如果连数据一起算,性能开销太大。
分片与重组:MTU的「妥协艺术」
每个物理网络都有最大传输单元(MTU)。以太网是1500字节,Wi-Fi通常是1500,但有些隧道网络只有1400甚至更少。如果IP包大于出口的MTU,路由器就必须把它切开——这就是分片。
分片的逻辑其实不复杂:
- 把原始IP数据包切成若干片,每片长度不超过MTU减去首部长度
- 每片都复制一份IP首部(只修改标志、片偏移、总长度、校验和)
- 接收端根据「标识」字段判断属于哪个原始包,根据「片偏移」排序,等所有分片到齐后重组
这里有个关键点:分片只在发送端或路由器上进行,重组只在最终接收端进行。中间路由器不会帮你重组——它没那个义务,也没那个必要。
分片带来的问题很明显:
- 一个分片丢了,整个包都得重传
- 分片增加了路由器的处理负担
- 分片攻击(如Teardrop攻击)可以利用分片偏移的漏洞搞垮系统
所以现代网络倾向于使用路径MTU发现(PMTUD)。发送端先发一个DF标志置1的包,如果某个路由器发现包太大,就返回ICMP「需要分片但DF置位」的消息,发送端据此调整包大小。嗯,这里要注意:有些防火墙会过滤这种ICMP消息,导致PMTUD失效——这也是个常见的坑。
ICMP协议:网络层的「信使」
ICMP全称是Internet Control Message Protocol,互联网控制报文协议。它不是用来传数据的,而是用来传控制信息和错误信息的。你可以把它理解为网络层的「信使」——出了问题,它负责通知你。
ICMP报文封装在IP数据包的数据部分,协议字段为1。它的首部很简单:类型(1字节)、代码(1字节)、校验和(2字节),后面跟着具体内容。
| 类型 | 代码 | 含义 |
|---|---|---|
| 0 | 0 | 回显应答(Ping回复) |
| 3 | 0 | 目标网络不可达 |
| 3 | 1 | 目标主机不可达 |
| 3 | 4 | 需要分片但DF置位 |
| 8 | 0 | 回显请求(Ping请求) |
| 11 | 0 | TTL超时 |
我个人觉得,ICMP最妙的地方在于:它虽然工作在IP之上,但它的目的却是帮助IP更好地工作。这种「自指」的设计在协议栈里并不多见。
Ping原理:你每天都在用的「心跳检测」
Ping基于ICMP的回显请求(类型8)和回显应答(类型0)。流程很简单:
- 发送端构造一个ICMP回显请求报文,里面包含标识符和序列号
- 接收端收到后,原封不动地返回一个回显应答报文
- 发送端计算发送和接收的时间差,就是RTT(往返时间)
Ping能告诉我们三件事:
- 目标是否可达——有回复就是通的
- 网络延迟——RTT值
- 丢包率——发了10个,回了8个,丢包20%
但Ping也有局限性。很多服务器会禁用ICMP回显应答,Ping不通不代表服务不可用。我建议你配合TCP端口检测(比如telnet或nc)一起使用。
Traceroute原理:画出网络路径的「地图」
Traceroute(Windows下叫tracert)利用的是ICMP的TTL超时消息。原理很巧妙:
- 发送一个TTL=1的UDP包(或ICMP回显请求)
- 第一个路由器收到后,TTL减1变成0,丢弃包,同时返回ICMP TTL超时消息(类型11)
- 发送端从ICMP消息的源IP地址知道第一个路由器的地址
- 然后发送TTL=2的包,第二个路由器返回超时消息
- 以此类推,直到到达目标
Windows的tracert默认使用ICMP回显请求,Linux的traceroute默认使用UDP包(目标端口从33434开始递增)。两者原理一样,只是探测包的类型不同。
你想想看,如果某个路由器不返回ICMP超时消息,Traceroute就会显示为* * *。这不一定是网络不通,可能是那个路由器配置了「不响应ICMP」的策略。
本章知识体系
下面这张图把IP分片、ICMP、Ping和Traceroute的关系串起来了。你可以看到,ICMP既是IP的「辅助协议」,又是Ping和Traceroute的「底层支撑」。
从这张图可以看得很清楚:IP协议是网络层的「主干」,ICMP是它的「辅助系统」,而Ping和Traceroute则是基于ICMP构建的「诊断工具」。IP分片则是IP协议在应对物理网络限制时的一种「妥协机制」。
- IPv4首部20字节,TTL、协议、校验和是排查问题的关键字段
- 分片由路由器执行,重组由接收端执行,尽量避免分片
- ICMP是控制报文协议,不是数据传输协议
- Ping检测连通性和延迟,Traceroute探测路径