26个版本 (14个重大更改)
0.15.0 | 2024年5月26日 |
---|---|
0.14.2 | 2024年2月5日 |
0.13.0 | 2022年12月5日 |
0.12.0 | 2022年7月24日 |
0.1.4 | 2018年3月1日 |
#10 in 网络编程
每月60,743次下载
用于 57 个crates (47个直接使用)
2.5MB
49K SLoC
etherparse
一个用于解析和写入一系列基于数据包的协议(EthernetII、IPv4、IPv6、UDP、TCP ...)的无分配库。
目前支持的有
- Ethernet II
- IEEE 802.1Q VLAN标签头部
- IPv4
- IPv6(支持最常见的扩展头部,但不全部支持)
- UDP
- TCP
- ICMP & ICMPv6(不支持所有消息类型)
使用方法
将以下内容添加到您的 Cargo.toml
[dependencies]
etherparse = "0.15"
etherparse是什么?
Etherparse旨在提供基本网络解析功能,以便轻松分析、转换或生成记录的网络数据。
一些关键点包括
- 它完全用Rust编写并经过彻底测试。
- 特别关注不使用分配或系统调用。
- 该包仍在开发中,并将继续发生变化。
- 当前开发重点是互联网和传输层中最流行的协议。
如何解析网络数据包?
Etherparse提供了两种自动解析网络数据包的选项
切片数据包
在这里,数据包的不同组件被分离,而不解析它们的全部字段。为每个头部生成一个切片,允许访问头部的字段。
match SlicedPacket::from_ethernet(&packet) {
Err(value) => println!("Err {:?}", value),
Ok(value) => {
println!("link: {:?}", value.link);
println!("vlan: {:?}", value.vlan);
println!("net: {:?}", value.net); // contains ip
println!("transport: {:?}", value.transport);
}
}
如果您的代码不感兴趣于所有头部的所有字段,这是一个更快的选择。如果您只想基于头部或其字段的子集过滤或查找数据包,这是一个不错的选择。
根据您想要切片数据包的起点,请参阅以下函数
SlicedPacket::from_ethernet
用于从Ethernet II头部向下解析SlicedPacket::from_linux_sll
用于从 Linux Cooked Capture v1 (SLL) 向下进行解析SlicedPacket::from_ether_type
用于从 Ethernet II 头部之后开始解析切片SlicedPacket::from_ip
用于从 IPv4 或 IPv6 向下进行解析
如果您想解析截断的包(例如,ICMP 消息中返回的包),则可以使用 "lax" 解析方法
LaxSlicedPacket::from_ethernet
用于从 Ethernet II 头部向下进行解析LaxSlicedPacket::from_ether_type
用于从 Ethernet II 头部之后开始解析切片LaxSlicedPacket::from_ip
用于从 IPv4 或 IPv6 向下进行解析
将所有头部反序列化为结构体
此选项将反序列化所有已知头部,并将它们的内容传输到头部结构体中。
match PacketHeaders::from_ethernet_slice(&packet) {
Err(value) => println!("Err {:?}", value),
Ok(value) => {
println!("link: {:?}", value.link);
println!("vlan: {:?}", value.vlan);
println!("net: {:?}", value.net); // contains ip
println!("transport: {:?}", value.transport);
}
}
当只访问少量字段时,此选项比切片慢。但是,如果您对大多数字段都感兴趣,或者您想要以修改后的值重新序列化头部,它可能是更快的选择。
根据您想要向下解包的起点,查看以下函数
PacketHeaders::from_ethernet_slice
用于从 Ethernet II 头部向下进行解析PacketHeaders::from_ether_type
用于从 Ethernet II 头部之后开始解析切片PacketHeaders::from_ip_slice
用于从 IPv4 或 IPv6 向下进行解析
如果您想解析截断的包(例如,ICMP 消息中返回的包),则可以使用 "lax" 解析方法
LaxPacketHeaders::from_ethernet
用于从 Ethernet II 头部向下进行解析LaxPacketHeaders::from_ether_type
用于从 Ethernet II 头部之后开始解析切片LaxPacketHeaders::from_ip
用于从 IPv4 或 IPv6 向下进行解析
手动切片仅一个包层
还可以只切片一个包层
Ethernet2Slice::from_slice_without_fcs
&Ethernet2Slice::from_slice_with_crc32_fcs
LinuxSllSlice::from_slice
SingleVlanSlice::from_slice
&DoubleVlanSlice::from_slice
IpSlice::from_slice
&LaxIpSlice::from_slice
Ipv4Slice::from_slice
&LaxIpv4Slice::from_slice
Ipv6Slice::from_slice
&LaxIpv6Slice::from_slice
UdpSlice::from_slice
&UdpSlice::from_slice_lax
TcpSlice::from_slice
Icmpv4Slice::from_slice
Icmpv6Slice::from_slice
结果数据类型允许访问层和负载的头部,如果层有限制负载长度的长度字段,则自动限制负载长度(例如,IPv6数据包的负载将受IPv6头部中的“负载长度”字段限制)。
手动切片和解析仅头部
还可以仅解析头部。如果您只想切片头部,请参阅以下[NAME]HeaderSlice.from_slice方法的文档:
Ethernet2HeaderSlice::from_slice
LinuxSllHeaderSlice::from_slice
SingleVlanHeaderSlice::from_slice
DoubleVlanHeaderSlice::from_slice
Ipv4HeaderSlice::from_slice
Ipv4ExtensionsSlice::from_slice
Ipv6HeaderSlice::from_slice
Ipv6ExtensionsSlice::from_slice
Ipv6RawExtHeaderSlice::from_slice
IpAuthHeaderSlice::from_slice
Ipv6FragmentHeaderSlice::from_slice
UdpHeaderSlice::from_slice
TcpHeaderSlice::from_slice
对于反序列化到相应的头部结构,请参阅以下内容:
Ethernet2Header::read
&Ethernet2Header::from_slice
LinuxSllHeader::read
&LinuxSllHeader::from_slice
SingleVlanHeader::read
&SingleVlanHeader::from_slice
DoubleVlanHeader::read
&DoubleVlanHeader::from_slice
IpHeaders::read
&IpHeaders::from_slice
Ipv4Header::read
&Ipv4Header::from_slice
Ipv4Extensions::read
&Ipv4Extensions::from_slice
Ipv6Header::read
&Ipv6Header::from_slice
Ipv6Extensions::read
&Ipv6Extensions::from_slice
Ipv6RawExtHeader::read
&Ipv6RawExtHeader::from_slice
IpAuthHeader::read
&IpAuthHeader::from_slice
Ipv6FragmentHeader::read
&Ipv6FragmentHeader::from_slice
UdpHeader::read
&UdpHeader::from_slice
TcpHeader::read
&TcpHeader::from_slice
Icmpv4Header::read
&Icmpv4Header::from_slice
Icmpv6Header::read
&Icmpv6Header::from_slice
如何生成伪造的数据包?
数据包构建器
PacketBuilder 结构体提供了一个高级接口,可以快速创建网络数据包。PacketBuilder 将自动设置可以从数据包内容和组成推断出的字段(例如校验和、长度、以太网类型、IP协议号)。
use etherparse::PacketBuilder;
let builder = PacketBuilder::
ethernet2([1,2,3,4,5,6], //source mac
[7,8,9,10,11,12]) //destination mac
.ipv4([192,168,1,1], //source ip
[192,168,1,2], //destination ip
20) //time to life
.udp(21, //source port
1234); //destination port
//payload of the udp packet
let payload = [1,2,3,4,5,6,7,8];
//get some memory to store the result
let mut result = Vec::<u8>::with_capacity(builder.size(payload.len()));
//serialize
//this will automatically set all length fields, checksums and identifiers (ethertype & protocol)
//before writing the packet out to "result"
builder.write(&mut result, &payload).unwrap();
还有一个TCP数据包示例可供参考。
有关更多信息,请参阅PacketBuilder 文档。
手动序列化每个头部
另外,也可以手动构建一个数据包(示例)。一般来说,每个表示头部的结构体都有一个“write”方法,允许它被序列化。这些write方法有时会自动计算校验和并将它们填充进去。如果这种行为不希望发生(例如,如果你想生成一个校验和不正确的数据包),也可以调用一个“write_raw”方法,该方法将简单地序列化数据而不进行校验和计算。
阅读不同方法的文档以获取更多详细信息
Ethernet2Header::to_bytes
&Ethernet2Header::write
LinuxSllHeader::to_bytes
&LinuxSllHeader::write
SingleVlanHeader::to_bytes
&SingleVlanHeader::write
DoubleVlanHeader::to_bytes
&DoubleVlanHeader::write
Ipv4Header::to_bytes
&Ipv4Header::write
&Ipv4Header::write_raw
IPv4 扩展::write
Ipv6Header::to_bytes
&Ipv6Header::write
IPv6 扩展::write
Ipv6RawExtHeader::to_bytes
&Ipv6RawExtHeader::write
IpAuthHeader::to_bytes
&IpAuthHeader::write
Ipv6FragmentHeader::to_bytes
&Ipv6FragmentHeader::write
UdpHeader::to_bytes
&UdpHeader::write
TcpHeader::to_bytes
&TcpHeader::write
Icmpv4Header::to_bytes
&Icmpv4Header::write
Icmpv6Header::to_bytes
&Icmpv6Header::write
参考文献
- Darpa互联网程序协议规范 RFC 791
- 互联网协议第6版(IPv6)规范 RFC 8200
- IANA协议号
- 互联网协议第6版(IPv6)参数
- 维基百科 IEEE_802.1Q
- 用户数据报协议(UDP) RFC 768
- 传输控制协议 RFC 793
- 高性能TCP扩展 RFC 7323
- 向IP添加显式拥塞通知(ECN) RFC 3168
- 使用非ces的鲁棒显式拥塞通知(ECN)信号 RFC 3540
- IP认证头 RFC 4302
- IPv6中的移动性支持 RFC 6275
- 主机身份协议第2版(HIPv2) RFC 7401
- Shim6:IPv6的第3层多宿主Shim协议 RFC 5533
- 计算互联网校验和 RFC 1071
- 互联网控制消息协议 RFC 792
- IANA互联网控制消息协议(ICMP)参数
- 互联网主机要求 -- 通信层 RFC 1122
- IP版本4路由器要求 RFC 1812
- IP版本6(IPv6)的互联网控制消息协议(ICMPv6)规范 RFC 4443
- ICMP路由器发现消息 RFC 1256
- 互联网控制消息协议第6版(ICMPv6)参数
- IPv6的多播监听器发现(MLD) RFC 2710
- IPv6的邻居发现 RFC 4861
- LINKTYPE_LINUX_SLL 在tcpdump上
- LINUX_SLL 头定义 在libpcap
- Linux数据包类型定义 在Linux内核
- 地址解析协议(ARP)参数 硬件类型
- ARP硬件标识符定义 在Linux内核
许可
根据您的选择,受Apache许可证第2.0版或MIT许可证的许可。相应的许可证文本可以在LICENSE-APACHE文件和LICENSE-MIT文件中找到。
贡献
除非您明确声明,否则您有意提交以包含在您的工作中的任何贡献均应按上述方式许可,不附加任何额外条款或条件。