一个底层的网络库,可以查看 数据链路层、网络层、传输层的内容。

    1. use pnet::datalink::{self, Channel::Ethernet};
    2. use pnet::packet::{
    3. ethernet::{EtherTypes, EthernetPacket},
    4. ip::IpNextHeaderProtocols,
    5. ipv4::Ipv4Packet,
    6. tcp::TcpPacket,
    7. Packet,
    8. };
    9. use std::env;
    10. fn main() {
    11. // 从命令行接收一个网卡的名称
    12. let interface_name = env::args().nth(1).unwrap();
    13. // 选择指定名字的链路层显卡
    14. let interfaces = datalink::interfaces();
    15. let interface = interfaces
    16. .into_iter()
    17. .filter(|iface| iface.name == interface_name)
    18. .next()
    19. .expect("error get interface");
    20. // 从链路层创建一个 channel,只使用接收端
    21. let (_tx, mut rx) = match datalink::channel(&interface, Default::default()) {
    22. Ok(Ethernet(tx, rx)) => (tx, rx),
    23. Ok(_) => panic!("Other"),
    24. Err(error) => panic!("error: {}", error),
    25. };
    26. loop {
    27. // 获取链路层的包
    28. match rx.next() {
    29. Ok(packet) => {
    30. let packet = EthernetPacket::new(packet).unwrap();
    31. handle_packet(&packet);
    32. }
    33. Err(e) => println!("error: {}", e),
    34. }
    35. }
    36. }
    37. fn handle_packet(ethernet: &EthernetPacket) {
    38. match ethernet.get_ethertype() {
    39. // 解析链路层协议,忽略 ipv4 以外的其他协议
    40. EtherTypes::Ipv4 => {
    41. let header = Ipv4Packet::new(ethernet.payload());
    42. if let Some(header) = header {
    43. // 解析下一层, 网络层协议
    44. match header.get_next_level_protocol() {
    45. IpNextHeaderProtocols::Tcp => {
    46. let tcp = TcpPacket::new(header.payload());
    47. if let Some(tcp) = tcp {
    48. println!(
    49. "tcp packet {}:{} to {}:{}",
    50. header.get_source(),
    51. tcp.get_source(),
    52. header.get_destination(),
    53. tcp.get_destination()
    54. );
    55. }
    56. }
    57. _ => println!("ignore not tcp"),
    58. }
    59. }
    60. }
    61. _ => println!("ignore not ipv4"),
    62. }
    63. }

    执行方式: sudo cargo run --bin pnet en0
    注:

    • 需要使用 root 权限
    • 需要提供一个网卡名字