#netflow #parser #v5 #ipfix #version #v9 #packet

netflow_parser

Cisco V5, V7, V9, IPFIX 解析器

28 个版本

0.4.0 2024 年 8 月 11 日
0.3.6 2024 年 7 月 3 日
0.3.5 2024 年 6 月 17 日
0.2.4 2024 年 3 月 21 日
0.1.8 2023 年 11 月 21 日

#1#v5

Download history 421/week @ 2024-04-23 139/week @ 2024-04-30 342/week @ 2024-05-07 52/week @ 2024-05-14 352/week @ 2024-05-21 400/week @ 2024-05-28 75/week @ 2024-06-04 206/week @ 2024-06-11 136/week @ 2024-06-18 139/week @ 2024-07-02 6/week @ 2024-07-09 19/week @ 2024-07-23 187/week @ 2024-07-30 79/week @ 2024-08-06

每月 285 次下载

MIT/Apache

180KB
4K SLoC

netflow_parser

用于 Cisco V5, V7, V9, IPFIX 的 netflow_parser 库。支持在同一流中链接多个版本。({v5 数据包}, {v7数据包}, {v5数据包}, {v9数据包}, 等。)

参考

见: https://en.wikipedia.org/wiki/NetFlow

示例

V5

use netflow_parser::{NetflowParser, NetflowPacket};

let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
match NetflowParser::default().parse_bytes(&v5_packet).first() {
    Some(NetflowPacket::V5(v5)) => assert_eq!(v5.header.version, 5),
    Some(NetflowPacket::Error(e)) => println!("{:?}", e),
    _ => (),
}

需要像 JSON 这样的序列化吗?

结构完全支持序列化。以下是一个使用 serde_json 宏的示例

use serde_json::json;
use netflow_parser::NetflowParser;

let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
println!("{}", json!(NetflowParser::default().parse_bytes(&v5_packet)).to_string());

输出

[{"V5":{"header":{"count":1,"engine_id":7,"engine_type":6,"flow_sequence":33752069,"sampling_interval":2057,"sys_up_time":{"nanos":672000000,"secs":50332},"unix_nsecs":134807553,"unix_secs":83887623,"version":5},"sets":[{"d_octets":66051,"d_pkts":101124105,"dst_addr":"4.5.6.7","dst_as":515,"dst_mask":5,"dst_port":1029,"first":{"nanos":87000000,"secs":67438},"input":515,"last":{"nanos":553000000,"secs":134807},"next_hop":"8.9.0.1","output":1029,"pad1":6,"pad2":1543,"protocol_number":8,"protocol_type":"Egp","src_addr":"0.1.2.3","src_as":1,"src_mask":4,"src_port":515,"tcp_flags":7,"tos":9}]}}]

针对特定版本的过滤

use netflow_parser::{NetflowParser, NetflowPacket};

let v5_packet = [0, 5, 2, 0, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,];
let parsed = NetflowParser::default().parse_bytes(&v5_packet);

let v5_parsed: Vec<NetflowPacket> = parsed.into_iter().filter(|p| p.is_v5()).collect();

重新导出流

Netflow 解析器现在支持解析 V5, V7, V9, IPFix,可以将解析后的数据重新导出为字节。

let packet = [
    0, 5, 0, 1, 3, 0, 4, 0, 5, 0, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
    4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
    2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
];
if let NetflowPacket::V5(v5) = NetflowParser::default()
    .parse_bytes(&packet)
    .first()
    .unwrap()
{
    assert_eq!(v5.to_be_bytes(), packet);
}

V9/IPFix 注意事项

解析数据('&[u8]' 与其他版本相同。解析器(NetflowParser)保留已解析的模板,因此只需发送一个头部/数据流组合,它就会使用缓存的模板。)要查看缓存的模板,只需使用正确版本的解析器(v9_parser 用于 v9,ipfix_parser 用于 IPFix。)

use netflow_parser::NetflowParser;
let parser = NetflowParser::default();
dbg!(parser.v9_parser.templates);
dbg!(parser.v9_parser.options_templates);

要访问处理后的 V9/IPFix 流组合的模板流组合,可以在解析记录上找到 flowsets 属性。在那里您可以找到 TemplatesOption TemplatesData 流组合。

特性

  • parse_unknown_fields - 当启用时,未在此库中列出的字段将尝试以 Vec of bytes 和 field_number 列表的形式解析。当禁用时,在尝试解析这些字段时将引发错误。默认启用。

示例

一些示例已包括,主要针对那些想要使用此解析器从套接字读取并解析 netflow 的人。在这些情况下,对于 V9/IPFix,最好为每个路由器创建一个新的解析器。示例目录中包含单线程和多线程示例。

运行

cargorun --examplenetflow_udp_listener_multi_threaded

cargorun --examplenetflow_udp_listener_single_threaded

cargorun --examplenetflow_udp_listener_tokio

依赖项

~1.3–2.6MB
~49K SLoC