环境
- 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
参考:RFC 791
目标
上一篇已经看过了 IP 协议的一部分字段,这里继续了解剩下的部分。
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;}// 第七八个字节,处理分片// 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.println!("Flags: {}", packet.get_flags());// 13 位的偏移,单位是 8 字节println!("Fragment Offset: {}", packet.get_fragment_offset());// 第九个字节,存活周期,为 0 则不被转发println!("Time to Live: {}", packet.get_ttl());// 第十个字节,下一级的协议类型println!("Protocol: {}", packet.get_next_level_protocol());// 第十一,十二个字节,头部校验和println!("Header Checksum: {}", packet.get_checksum());println!("length: {}, {:?}", size, &buffer[..size]);}
}
抓包结果
抓包并保存到文件:tcpdump -X -i tun0 -w tun0.pcap
,然后通过 Wireshark 打开。
通过 Wireshark 能清楚看到 IP 层的信息。
程序输出
Flags: 2
Fragment Offset: 0
Time to Live: 64
Protocol: Icmp
Header Checksum: 2908
length: 84, [69, 0, 0, 84, 111, 53, 64, 0, 64, 1, 11, 92, 172, 24, 51, 244, 172, 24, 51, 243, 8, 0, 248, 133, 165, 217, 0, 1, 139, 235, 124, 99, 0, 0, 0, 0, 136, 125, 10, 0, 0, 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55]
总结
了解了网络层的 IP 协议,认识了其中几个字节的数据所代表的含义。