热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何读取tcpdump生成的包含大UDP数据包的pcap文件并重新组装IP碎片数据包?

我想读取由tcpdump生成的pcap文件,该文件包含经过IPV4分片的大型UDP数据包。原始数据包的大小约为22000字节。在C++中,我会使用li

我想读取由 tcpdump 生成的 pcap 文件,该文件包含经过IPV4 分片的大型 UDP 数据包。原始数据包的大小约为 22000 字节。

在 C++ 中,我会使用 libtins 和它的 IPV4Reassembler。有没有办法在 Rust 中做类似的事情?

目前在 Rust 中,这是我到目前为止所写的内容:高度不完整的第一次尝试(使用 crate pnet):

use pnet::packet::{
ethernet::{EtherTypes, EthernetPacket},
ip::IpNextHeaderProtocols,
ipv4::Ipv4Packet,
udp::UdpPacket,
Packet,
};
struct Ipv4Reassembler {
cap: pcap::Capture,
}
impl Iterator for Ipv4Reassembler {
type Item = Vec;
fn next(&mut self) -> Option {
let mut payload = Vec::::new();
while let Some(packet) = self.cap.next().ok() {
// todo: handle packets other than Ethernet packets
let ethernet = EthernetPacket::new(packet.data).unwrap();
match ethernet.get_ethertype() {
EtherTypes::Ipv4 => {
let ipv4_packet = Ipv4Packet::new(ethernet.payload()).unwrap();
// dbg!(&ipv4_packet);
// todo: discard incomplete packets
// todo: construct header for reassembled packet
// todo: check id, etc
let off: usize = 8 * ipv4_packet.get_fragment_offset() as usize;
let end = off + ipv4_packet.payload().len();
if payload.len() payload.resize(end, 0);
}
payload[off..end].clone_from_slice(ipv4_packet.payload());
if ipv4_packet.get_flags() & 1 == 0 {
return Some(payload);
}
}
_ => {}
}
}
None
}
}
fn main() {
let pcap_path = "os-992114000702.pcap";
let reass = Ipv4Reassembler {
cap: pcap::Capture::from_file(&pcap_path).unwrap(),
};
for payload in reass {
let udp_packet = UdpPacket::new(&payload).unwrap();
dbg!(&udp_packet);
dbg!(&udp_packet.payload().len());
}
}

在 C++ 中,这是我将使用的代码(使用 libtins):

#include
#include
#include
#include
#include
#include
#include
#include
void read_packets(const std::string &pcap_filename) {
Tins::IPv4Reassembler reassembler;
Tins::FileSniffer sniffer(pcap_filename);
while (Tins::Packet packet = sniffer.next_packet()) {
auto &pdu = *packet.pdu();
const Tins::Timestamp ×tamp = packet.timestamp();
if (reassembler.process(pdu) != Tins::IPv4Reassembler::FRAGMENTED) {
const Tins::UDP *udp = pdu.find_pdu();
if (!udp) {
continue;
}
const Tins::RawPDU *raw = pdu.find_pdu();
if (!raw) {
continue;
}
const Tins::RawPDU::payload_type &payload = raw->payload();
std::cout <<"Packet: " < // do something with the reassembled packet here
}
}
}
int main() {
const std::string pcap_path = "os-992114000702.pcap";
read_packets(pcap_path);
}

g++ -O3 -o pcap pcap.cpp -ltins

似乎一种解决方案是实现RFC815,但我不确定如何在 Rust 中做到这一点。我已经找到:


  • 这个旧的 smolltcp 拉取请求,但它似乎已被放弃。

  • Fuschia reassembly.rs但我不知道如何在 Fuschia 之外使用它。



推荐阅读
author-avatar
闌珊脃_
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有