一个底层的网络库,可以查看 数据链路层、网络层、传输层的内容。
use pnet::datalink::{self, Channel::Ethernet};use pnet::packet::{ethernet::{EtherTypes, EthernetPacket},ip::IpNextHeaderProtocols,ipv4::Ipv4Packet,tcp::TcpPacket,Packet,};use std::env;fn main() {// 从命令行接收一个网卡的名称let interface_name = env::args().nth(1).unwrap();// 选择指定名字的链路层显卡let interfaces = datalink::interfaces();let interface = interfaces.into_iter().filter(|iface| iface.name == interface_name).next().expect("error get interface");// 从链路层创建一个 channel,只使用接收端let (_tx, mut rx) = match datalink::channel(&interface, Default::default()) {Ok(Ethernet(tx, rx)) => (tx, rx),Ok(_) => panic!("Other"),Err(error) => panic!("error: {}", error),};loop {// 获取链路层的包match rx.next() {Ok(packet) => {let packet = EthernetPacket::new(packet).unwrap();handle_packet(&packet);}Err(e) => println!("error: {}", e),}}}fn handle_packet(ethernet: &EthernetPacket) {match ethernet.get_ethertype() {// 解析链路层协议,忽略 ipv4 以外的其他协议EtherTypes::Ipv4 => {let header = Ipv4Packet::new(ethernet.payload());if let Some(header) = header {// 解析下一层, 网络层协议match header.get_next_level_protocol() {IpNextHeaderProtocols::Tcp => {let tcp = TcpPacket::new(header.payload());if let Some(tcp) = tcp {println!("tcp packet {}:{} to {}:{}",header.get_source(),tcp.get_source(),header.get_destination(),tcp.get_destination());}}_ => println!("ignore not tcp"),}}}_ => println!("ignore not ipv4"),}}
执行方式: sudo cargo run --bin pnet en0
注:
- 需要使用 root 权限
- 需要提供一个网卡名字
