IPv4协议详解:头部结构、分片与重组、IP路由原理
IPv4,说白了就是互联网的“门牌号系统”。没有它,数据包就不知道往哪儿送。我做了十几年网络排障,见过太多因为IP协议理解不透彻导致的诡异问题。今天咱们就把IPv4从头到脚拆开看看。
IPv4头部结构:20字节的硬核设计
IPv4头部固定部分只有20字节,但每个字段都有讲究。我当年刚入行时,觉得这些字段就是背背而已,直到有一次抓包分析一个丢包问题,才发现是TTL字段搞的鬼。
| 字段 | 长度(bit) | 说明 |
|---|---|---|
| Version | 4 | 固定为4,标识IPv4 |
| IHL | 4 | 头部长度,单位4字节,最小5 |
| Type of Service | 8 | 服务类型,现在常用DSCP |
| Total Length | 16 | 整个IP包长度,含头部 |
| Identification | 16 | 标识符,用于分片重组 |
| Flags | 3 | DF/MF位,控制分片 |
| Fragment Offset | 13 | 分片偏移量,单位8字节 |
| Time to Live | 8 | 生存时间,每跳减1 |
| Protocol | 8 | 上层协议,6=TCP,17=UDP |
| Header Checksum | 16 | 头部校验和 |
| Source Address | 32 | 源IP地址 |
| Destination Address | 32 | 目的IP地址 |
关键点:IHL字段如果值为5,表示头部20字节无选项。如果大于5,说明有IP选项字段,但实际网络中很少用。我曾经见过一个厂商设备默认加了IP时间戳选项,导致MTU计算异常,排查了两天才找到根因。
分片与重组:MTU的博弈
为什么需要分片?因为链路层有MTU限制。以太网MTU是1500字节,如果IP包超过这个值,就必须拆开。嗯,这里要注意——分片是IPv4的特性,IPv6已经把这个机制改了。
分片流程其实不复杂:
- 发送端检查IP包总长度是否超过出口MTU
- 如果超过,将数据部分拆成多个分片
- 每个分片复制原IP头部的Identification字段
- 设置MF位(More Fragments)和Fragment Offset
- 接收端根据Identification、源IP、目的IP识别属于同一原始包的分片
- 按Fragment Offset重组,MF=0表示最后一个分片
避坑指南:我曾经遇到过一个案例——某防火墙默认丢弃了所有分片包,导致大包传输失败。更坑的是,有些应用会设置DF位(Don't Fragment),如果路径MTU小于包大小,路由器会直接丢弃并返回ICMP错误。很多网络设备默认屏蔽了ICMP,结果就是连接超时,用户一脸懵。
分片在Wireshark里怎么看?抓包后找到IP层,看Identification字段是否相同。如果看到多个包有相同的Identification,且Fragment Offset递增,那就是分片了。
# Wireshark显示过滤表达式
ip.frag_offset > 0 # 显示所有分片包
ip.flags.mf == 1 # 显示MF位为1的包
ip.id == 0x1234 # 按标识符过滤特定分片组
IP路由原理:逐跳转发
路由说白了就是“问路”。每个路由器只知道下一跳怎么走,不知道完整路径。我刚开始学路由时,总觉得这效率太低,后来才明白——这种设计让互联网具备了极强的扩展性。
路由决策的核心步骤:
- 最长前缀匹配:路由器查找路由表时,选择掩码最长的匹配条目
- 默认路由:0.0.0.0/0,所有未匹配的流量走这里
- 直连路由:接口配置了IP后自动生成
- 静态路由:管理员手动配置
- 动态路由:通过OSPF、BGP等协议学习
实战技巧:用Wireshark抓路由协议包时,我习惯先过滤ospf或bgp。OSPF用IP协议号89,BGP用TCP端口179。抓BGP时记得抓在建立邻居的阶段,能看到完整的Open、Update、Keepalive、Notification消息。
你想想看,一个数据包从北京发到纽约,中间经过几十个路由器,每个路由器只查一下路由表就转发出去。这种设计是不是很巧妙?
Wireshark过滤与分析实战
IPv4相关的Wireshark过滤,我总结了几个最常用的:
# 基础过滤
ip.addr == 192.168.1.1 # 匹配源或目的IP
ip.src == 10.0.0.1 # 匹配源IP
ip.dst == 172.16.0.1 # 匹配目的IP
ip.ttl < 10 # TTL小于10的包
ip.proto == 6 # TCP协议
ip.proto == 17 # UDP协议
ip.flags.df == 1 # 设置了DF位的包
ip.hdr_len > 20 # 有IP选项的包
我个人习惯在分析网络问题时,先用ip.addr == x.x.x.x过滤出所有相关流量,然后逐步缩小范围。比如先看有没有分片,再看TTL是否异常。
案例分析:有一次客户反馈跨地域传输大文件经常中断。我抓包后发现大量ip.flags.df == 1且icmp.type == 3的包。嗯,典型的PMTUD问题——路径上有设备MTU小于1500,但发送端设置了DF位,导致包被丢弃。解决方案是在应用层调整MSS,或者在路由器上配置TCP MSS clamping。
IPv4头部结构图
下面这张图是我自己画的IPv4头部结构,方便你对照理解:
常见问题与排障思路
最后分享几个我实际工作中遇到的IPv4相关坑:
- TTL耗尽:traceroute就是利用TTL=1、2、3...逐跳探测路径。如果某个节点TTL设置过小,会导致包无法到达目的地
- IP分片性能问题:分片和重组消耗CPU资源,现在的网络设备都尽量规避分片。我建议应用层直接控制数据包大小不超过1460字节(1500-20-20)
- IP地址冲突:DHCP分配不当或手动配置错误会导致两个设备用同一个IP。Wireshark里看到大量ARP请求和重复IP通告就要警惕了
我的习惯:每次排查网络问题,第一件事就是抓包看IP层的TTL和Identification。TTL异常说明路径有问题,Identification重复说明可能是分片重组失败。这两个字段能快速定位80%的IP层问题。