Zero-dependency PCAP capturing for Rust, powered by aya and eBPF.
Add rust-pcap to your Cargo.toml:
[dependencies]
rust-pcap = { git = "https://github.com/Nereuxofficial/rust-pcap" } # or git/crates.io once published
tokio = { version = "1", features = ["full"] }Note: requires root (or
CAP_BPF+CAP_NET_ADMIN) at runtime because it loads an eBPF program into the kernel.
use rust_pcap::{capture::Capture, device::Device};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let dev = Device::lookup("eth0")?;
let mut capture = Capture::from_device(dev).start().await?;
while let Ok(packet) = capture.next_packet().await {
println!("Received packet with length: {}", packet.data.len());
}
Ok(())
}use rust_pcap::{capture::Capture, device::Device, pcap_writer::PcapWriter};
use tokio::fs::File;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let file = File::create("capture.pcap").await?;
let mut writer = PcapWriter::new(file).await?;
let mut capture = Capture::from_device(Device::any()).start().await?;
for _ in 0..10 {
let packet = capture.next_packet().await?;
writer.write(&packet).await?;
}
Ok(())
}The output file is standard libpcap format and can be opened directly in Wireshark or inspected with tcpdump -r capture.pcap.
You can fetch capture statistics (forwarded and dropped packets) at any time:
let stats = capture.fetch_stats()?;
println!("Forwarded: {}, Dropped: {}", stats.forwarded, stats.dropped);A ready-to-use capture CLI is provided in rust-pcap/examples/capture.rs. See that file for usage instructions.
- Stable Rust toolchain:
rustup toolchain install stable - Nightly Rust toolchain (for eBPF):
rustup toolchain install nightly --component rust-src - bpf-linker:
cargo install bpf-linker(use--no-default-featureson macOS) - (cross-compiling only) rustup target:
rustup target add ${ARCH}-unknown-linux-musl - (cross-compiling only) LLVM: e.g.
brew install llvm - (cross-compiling only) musl C toolchain: e.g.
brew install filosottile/musl-cross/musl-cross
Cross-compilation works on both Intel and Apple Silicon Macs.
CC=${ARCH}-linux-musl-gcc cargo build --package rust-pcap --example capture --release \
--target=${ARCH}-unknown-linux-musl \
--config=target.${ARCH}-unknown-linux-musl.linker=\"${ARCH}-linux-musl-gcc\"Copy the resulting binary to a Linux server or VM and run it there:
scp target/${ARCH}-unknown-linux-musl/release/examples/capture user@host:~/
ssh user@host sudo ./capture capture.pcapWith the exception of eBPF code, rust-pcap is distributed under the terms of either the MIT license or the Apache License (version 2.0), at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
All eBPF code is distributed under either the terms of the GNU General Public License, Version 2 or the MIT license, at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the GPL-2 license, shall be dual licensed as above, without any additional terms or conditions.
- aya-rs/aya — eBPF library for Rust
- pythops/oryx — inspiration
- Wireshark — open the
.pcapoutput