网络层核心: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,路由器就必须把它切开——这就是分片。

分片的逻辑其实不复杂:

  1. 把原始IP数据包切成若干片,每片长度不超过MTU减去首部长度
  2. 每片都复制一份IP首部(只修改标志、片偏移、总长度、校验和)
  3. 接收端根据「标识」字段判断属于哪个原始包,根据「片偏移」排序,等所有分片到齐后重组

这里有个关键点:分片只在发送端或路由器上进行,重组只在最终接收端进行。中间路由器不会帮你重组——它没那个义务,也没那个必要。

我曾经踩过的坑:有一次做VoIP优化,发现语音包偶尔卡顿。抓包一看,有些UDP包被分片了。问题是,如果其中一个分片丢了,整个原始包都无法重组,应用层直接丢包。后来我强制在应用层把包大小控制在1400字节以内,问题就解决了。记住:分片是网络层的「最后手段」,能避免就避免。

分片带来的问题很明显:

  • 一个分片丢了,整个包都得重传
  • 分片增加了路由器的处理负担
  • 分片攻击(如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)。流程很简单:

  1. 发送端构造一个ICMP回显请求报文,里面包含标识符和序列号
  2. 接收端收到后,原封不动地返回一个回显应答报文
  3. 发送端计算发送和接收的时间差,就是RTT(往返时间)

Ping能告诉我们三件事:

  • 目标是否可达——有回复就是通的
  • 网络延迟——RTT值
  • 丢包率——发了10个,回了8个,丢包20%
实战经验:有一次客户反馈「网络慢」,我Ping了一下网关,延迟2ms,正常。但Ping外网服务器,延迟200ms,偶尔还有丢包。这说明问题不在内网,在出口或运营商链路。Ping是最快的「故障隔离」工具,没有之一。

但Ping也有局限性。很多服务器会禁用ICMP回显应答,Ping不通不代表服务不可用。我建议你配合TCP端口检测(比如telnet或nc)一起使用。

Traceroute原理:画出网络路径的「地图」

Traceroute(Windows下叫tracert)利用的是ICMP的TTL超时消息。原理很巧妙:

  1. 发送一个TTL=1的UDP包(或ICMP回显请求)
  2. 第一个路由器收到后,TTL减1变成0,丢弃包,同时返回ICMP TTL超时消息(类型11)
  3. 发送端从ICMP消息的源IP地址知道第一个路由器的地址
  4. 然后发送TTL=2的包,第二个路由器返回超时消息
  5. 以此类推,直到到达目标

Windows的tracert默认使用ICMP回显请求,Linux的traceroute默认使用UDP包(目标端口从33434开始递增)。两者原理一样,只是探测包的类型不同。

你想想看,如果某个路由器不返回ICMP超时消息,Traceroute就会显示为* * *。这不一定是网络不通,可能是那个路由器配置了「不响应ICMP」的策略。

我的建议:排查网络问题时,先用Ping确认连通性,再用Traceroute看路径。如果发现某个跳点延迟突然飙升(比如从5ms跳到200ms),那大概率就是那个节点出了问题。

本章知识体系

下面这张图把IP分片、ICMP、Ping和Traceroute的关系串起来了。你可以看到,ICMP既是IP的「辅助协议」,又是Ping和Traceroute的「底层支撑」。

网络层核心协议关系图 IP协议(核心) IP分片与重组 ICMP协议 MTU限制导致 协议字段=1 错误报告 查询功能 Ping 基于ICMP回显 Traceroute 基于TTL超时 ICMP是IP的辅助协议,Ping和Traceroute都是基于ICMP实现的网络诊断工具 IP分片是应对MTU限制的机制,但应尽量避免

从这张图可以看得很清楚:IP协议是网络层的「主干」,ICMP是它的「辅助系统」,而Ping和Traceroute则是基于ICMP构建的「诊断工具」。IP分片则是IP协议在应对物理网络限制时的一种「妥协机制」。

核心要点:
  • IPv4首部20字节,TTL、协议、校验和是排查问题的关键字段
  • 分片由路由器执行,重组由接收端执行,尽量避免分片
  • ICMP是控制报文协议,不是数据传输协议
  • Ping检测连通性和延迟,Traceroute探测路径