2. 数据包结构解析:OSI与TCP/IP模型回顾、以太网帧结构、IP头部详解、TCP/UDP头部详解
各位同学,咱们今天聊点实在的。做网络分析这么多年,我最大的体会就是——不懂数据包结构,你就是在黑灯瞎火里修电路。你抓了一堆包,看着十六进制码发懵,那跟看天书没区别。
我个人习惯,拿到一个网络问题,第一件事就是拆包。拆开看看,到底是哪一层出了问题。今天我就带你把这几层结构彻底捋一遍。
2.1 OSI与TCP/IP模型:别被七层吓住
先说说这两个模型。OSI七层模型,教科书上的标准答案。但说实话,在实际工作中,没人天天念叨七层。大家更常用的是TCP/IP四层模型。
我给你们画个对比图,一目了然:
你看,TCP/IP模型把OSI的上三层(应用层、表示层、会话层)合并成了应用层,把底下两层(物理层、数据链路层)合并成了网络接口层。说白了,TCP/IP就是OSI的实战精简版。
2.2 以太网帧结构:数据链路层的"信封"
好,咱们从最底层开始拆。以太网帧,你可以把它想象成一个信封。数据要发出去,总得有个信封包着吧?
标准的以太网帧长这样:
| 前导码(7B) | 定界符(1B) | 目的MAC(6B) | 源MAC(6B) | 类型/长度(2B) | 数据(46-1500B) | FCS(4B) |
这里面有几个关键点,我重点说说:
- MAC地址:48位,6个字节。前3个字节是厂商代码,后3个字节是设备序列号。我在项目里查过不少ARP欺骗攻击,就是靠MAC地址溯源找到的。
- 类型字段:0x0800代表上层是IP协议,0x0806代表ARP协议。这个字段决定了数据链路层把数据交给谁。
- 最小帧长64字节:为什么?因为要防止"冲突检测"出问题。嗯,这个细节咱们后面讲CSMA/CD时再展开。
2.3 IP头部详解:网络层的"导航仪"
IP头部,说白了就是数据包的导航仪。它告诉网络:我从哪来,要到哪去,走哪条路。
标准的IPv4头部是20字节(不含选项字段):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|版本| 首部长度 | 服务类型(TOS) | 总长度(字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 标识(Identification) |标志| 片偏移 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 生存时间(TTL) | 协议 | 首部校验和 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源IP地址 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目的IP地址 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 选项(可选) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
我挑几个重点字段说说:
| 字段 | 长度 | 说明 | 实战意义 |
|---|---|---|---|
| 版本 | 4位 | IPv4或IPv6 | 现在IPv6占比已经超过30%了,别只会看IPv4 |
| TTL | 8位 | 最大跳数,每经过一个路由器减1 | TTL=1说明是局域网,TTL=64是Linux,TTL=128是Windows |
| 协议 | 8位 | 上层协议类型:6=TCP, 17=UDP, 1=ICMP | 抓包时看这个字段就知道上层是什么 |
| 首部校验和 | 16位 | 只校验头部,不校验数据 | 路由器每经过一次都要重新计算,所以别指望它防篡改 |
2.4 TCP头部详解:可靠的"快递员"
TCP,传输控制协议。它最大的特点就是可靠。怎么做到的?靠的是三次握手、确认重传、滑动窗口这一整套机制。
TCP头部标准20字节:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源端口 | 目的端口 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 序列号(Sequence Number) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 确认号(Acknowledgment Number) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据偏移 | 保留 |U|A|P|R|S|F| 窗口大小 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 校验和 | 紧急指针 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 选项(可选) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
这里面的标志位,我建议你背下来:
- SYN:发起连接。三次握手的第一次和第二次都用它。
- ACK:确认收到。除了第一次握手,后面所有包都带ACK。
- FIN:关闭连接。四次挥手的发起方用。
- RST:强制断开。端口不可达时,对方会回RST。
- PSH:立即推送。告诉接收方别缓存了,赶紧交给应用层。
- URG:紧急指针。说实话,我工作十年几乎没见过这个标志位被正常使用。
2.5 UDP头部详解:轻量级的"明信片"
UDP,用户数据报协议。跟TCP比起来,它就是个"裸奔"的协议。头部只有8个字节:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源端口 | 目的端口 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 长度 | 校验和 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
你没看错,就4个字段。没有序列号,没有确认机制,没有重传,什么都没有。发出去就不管了。
那UDP有什么用?你想想看:
- DNS查询:一个请求一个响应,用TCP建立连接太浪费了。
- 视频直播:丢一帧就丢一帧,用户看不出来。但要是卡住等重传,那体验就崩了。
- 游戏数据:你打游戏时,角色位置信息需要实时更新。等TCP确认?黄花菜都凉了。
2.6 数据包封装过程:从应用层到物理层
最后,咱们把整个过程串起来。数据从应用层发出,经过层层封装,最终变成比特流发送出去。这个过程叫封装:
应用层数据(如HTTP请求)
↓ 加上TCP头部(源端口、目的端口、序列号...)
TCP段
↓ 加上IP头部(源IP、目的IP、TTL、协议类型...)
IP数据报
↓ 加上以太网帧头部(源MAC、目的MAC、类型...)
以太网帧
↓ 物理层编码
比特流(010101...)
接收端收到后,反向操作——解封装。每一层只处理自己关心的头部信息,然后把数据交给上一层。
这就是整个数据包的生命周期。你想想看,一个简单的网页请求,背后经历了这么多层处理。网络工程师的价值,就在于能看懂每一层发生了什么,出了问题能精准定位到是哪一层。
公众号:蓝海资料掘金营,微信deep3321