0224-网络层的分片
环境
- Time 2022-11-20
- WSL-Ubuntu 22.04
- Rust 1.65.0
- pnet 0.31.0
- tun-tap 0.1.3
前言
说明
参考:https://docs.rs/pnet/latest/pnet/index.html
目标
通过 ping 命令来认识网络层中的分片。
查看 MTU
可以看到最大的 MTU 为 1500。
root@jiangbo12490:~# ip addr show dev tun0
7: tun0: <NO-CARRIER,POINTOPOINT,MULTICAST,NOARP,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 500
link/none
inet 172.24.49.244/20 scope global tun0
valid_lft forever preferred_lft forever
不分片
其中的 t 参数指定的是生存期,I 参数指定的网卡。
s 指定的是发送数据包的大小,M do 表示禁止分片。
禁止分片的情况下,如果超出了最大的 MTU,会提示错误。
root@jiangbo12490:~# ping -t 44 -I tun0 172.24.49.106 -s 9999 -M do
PING 172.24.49.106 (172.24.49.106) from 172.24.49.244 tun0: 9999(10027) bytes of data.
ping: local error: message too long, mtu=1500
ping: local error: message too long, mtu=1500
ping: local error: message too long, mtu=1500
main.rs
use pnet::packet::ipv4::Ipv4Packet;
use tun_tap::{Iface, Mode};
fn main() -> std::io::Result<()> {
let iface = Iface::without_packet_info("tun0", Mode::Tun)?;
let mut buffer = vec![0; 1500];
loop {
let _size = iface.recv(&mut buffer)?;
let packet = Ipv4Packet::new(&buffer).unwrap();
if packet.get_version() == 6 {
println!("IPv6 packet, continue");
continue;
}
// 第五六个字节,分片标识
println!("Identification: {}", packet.get_identification());
// 第七八个字节,处理分片
// 3 位的标志
// Bit 0: reserved, must be zero 第一位必须为 0
// 可以分片还是不可以分片
// Bit 1: (DF) 0 = May Fragment, 1 = Don’t Fragment.
// 是否还有其余分片还是最后一个分片
// Bit 2: (MF) 0 = Last Fragment, 1 = More Fragments.
// 13 位的偏移,单位是 8 字节
println!(
"Flags: {}, Fragment Offset: {}",
packet.get_flags(),
packet.get_fragment_offset()
);
// 第九个字节,存活周期,为 0 则不被转发
println!("Time to Live: {}", packet.get_ttl());
}
}
程序输出
命令中指定的 ttl 生效了。
所有的包的表示都是 54589,表示它们是同一个包,只是被分片了。
Flags 为 1 表示还有剩余的分片,不是最后一个。最后一个的 Flags 为 0。
第一个分片的偏移从 0 开始,MTU 1500,减去 20 字节的 IP 协议头。
剩下 1480 字节,所以第二个分片的偏移应该从 1480 开始算。
185 * 8 = 1480 刚刚是算出来的偏移量。
Identification: 54589
Flags: 1, Fragment Offset: 0
Time to Live: 44
Identification: 54589
Flags: 1, Fragment Offset: 185
Time to Live: 44
Identification: 54589
Flags: 1, Fragment Offset: 370
Time to Live: 44
Identification: 54589
Flags: 1, Fragment Offset: 555
Time to Live: 44
Identification: 54589
Flags: 1, Fragment Offset: 740
Time to Live: 44
Identification: 54589
Flags: 1, Fragment Offset: 925
Time to Live: 44
Identification: 54589
Flags: 0, Fragment Offset: 1110
Time to Live: 44
抓包
抓包并保存到文件:tcpdump -i tun0 -w ping.pcap
,然后通过 Wireshark 打开。
可以看到分片和重组的信息,其中 Wireshark 的显示偏移是计算后的,不是报文中原始内容。
总结
了解了网络层的分片,分片从网络层开始算,不包含链路层的物理地址和类型。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2020-08-13 【JavaScript】Object 实例属性