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
每月 285 次下载
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
属性。在那里您可以找到 Templates
、Option Templates
和 Data
流组合。
特性
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