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 打开。

ping 分片

可以看到分片和重组的信息,其中 Wireshark 的显示偏移是计算后的,不是报文中原始内容。

总结

了解了网络层的分片,分片从网络层开始算,不包含链路层的物理地址和类型。

附录

posted @   jiangbo4444  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2020-08-13 【JavaScript】Object 实例属性
点击右上角即可分享
微信分享提示