在Rust中使用pnet捕获网络数据包

656次阅读  |  发布于1年以前

捕获网络数据包是网络分析、安全和调试的重要组成部分。在这篇文章中,我们将探索如何使用Rust和pnet库构建网络数据包捕获工具。

创建一个新的Rust项目:

cargo new pnet_packet_capture

在Cargo.toml文件中添加pnet依赖项:

[dependencies]
pnet = "0.34.0"

在src/main.rs文件中,写入以下代码:

use pnet::{datalink::{self, Channel}, packet::ethernet::EthernetPacket};

fn main() {
    // 选取 'en0' 网络接口
    let interface = datalink::interfaces().into_iter()
        .find(|interface| interface.name == "en0")
        .unwrap();

    // 抓包需要数据链路通道,它建立了到网络接口'en0' 的底层链路。
    let (_, mut rx) = match datalink::channel(&interface, Default::default()) {
        Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
        Ok(_) => panic!("Unhandled channel type: {}", &interface),
        Err(e) => panic!("An error occurred when creating the datalink channel: {}", e),
    };

    println!("开始读取网络数据包: ");

    // 建立一个循环来连续读取传入的数据包
    loop {
        match rx.next() {
            Ok(packet) => {
                if let Some(ethernet_packet) = EthernetPacket::new(packet) {
                    println!("新数据包:");
                    println!(
                        "{} => {}: {}",
                        ethernet_packet.get_destination(),
                        ethernet_packet.get_source(),
                        ethernet_packet.get_ethertype()
                    );
                }
            },
            Err(e) => {
                panic!("An error occurred while reading: {}", e);
            }
        }
    }
}

包捕获通常需要以超级用户(根)权限运行:

sudo cargo run

开始读取网络数据包: 
新数据包:
04:43:fd:3e:ee:20 => a4:5e:60:ef:b6:73: Ipv4
新数据包:
04:43:fd:3e:ee:20 => a4:5e:60:ef:b6:73: Ipv4

使用以下代码可以获取网络数据包更详细信息:

fn main() {
    // 选取 'en0' 网络接口
    ......

    // 建立链路通道
    ......

    println!("开始读取网络数据包: ");
    loop {
        match rx.next() {
            Ok(packet) => {
                if let Some(ethernet_packet) = EthernetPacket::new(packet) {
                    println!("新数据包:");
                    ......

                    let packet = ethernet_packet.packet();
                    let payload = ethernet_packet.payload();
                    let from_packet = ethernet_packet.from_packet();
                    println!("---");
                    println!("packet: {:?}", packet);
                    // 将整个数据包打印为u8数组
                    println!("payload: {:?}", payload);
                    // 将有效负载打印为u8数组
                    println!("from_packet: {:?}", from_packet);
                    // 打印侦听器信息:MAC地址,以太类型等,有效载荷是u8的数组
                    println!("---");
                }
            }
            Err(e) => {
                panic!("An error occurred while reading: {}", e);
            }
        }
    }
}

使用超级用户权限运行程序时要小心,确保你理解代码并信任正在使用的库。

捕获网络数据包并不复杂,使用Rust和pnet库,可以构建一个安全高效的工具来捕获和分析网络流量。这为网络监控、网络安全和应用程序开发提供了极大的便利。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8