netflow_parser

A netflow_parser library for V5, V7, V9, IPFIX written in Rust. Supports chaining of multple versions in the same stream. ({v5 packet}, {v7packet}, {v5packet}, {v9packet}, etc.)

References

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

Example:

V5:

```rust use netflow_parser::{NetflowParser, NetflowPacket};

let v5packet = [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().parsebytes(&v5packet).first() { Some(NetflowPacket::V5(v5)) => asserteq!(v5.header.version, 5), _ => (), } ```

Want Serialization such as JSON?

Structures fully support serialization. Below is an example using the serdejson macro: ```rust use serdejson::json; use netflow_parser::NetflowParser;

let v5packet = [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().parsebytes(&v5packet)).tostring()); ```

Output:

json [{"V5":{"body":{"d_octets":66051,"d_pkts":101124105,"dst_addr":"4.5.6.7","dst_as":515,"dst_mask":5,"dst_port":1029,"first":67438087,"input":515,"last":134807553,"next_hop":"8.9.0.1","output":1029,"pad1":6,"pad2":1543,"protocol":"EGP","src_addr":"0.1.2.3","src_as":1,"src_mask":4,"src_port":515,"tcp_flags":7,"tos":9},"header":{"count":512,"engine_id":7,"engine_type":6,"flow_sequence":33752069,"sampling_interval":2057,"sys_up_time":50332672,"unix_nsecs":134807553,"unix_secs":83887623,"unix_time":{"nanos_since_epoch":134807553,"secs_since_epoch":83887623},"version":5}}}]

Filtering for a specific version

```rust use netflow_parser::{NetflowParser, NetflowPacket};

let v5packet = [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().parsebytes(&v5_packet);

let v5parsed: Vec = parsed.iter().filter(|p| p.isv5()).map(|p| p.clone()).collect(); ```

V9/IPFix notes:

Parse the data ('&[u8]' as any other versions. The parser (NetflowParser) holds onto already parsed templates, so you can just send a header/data flowset combo and it will use the cached templates.) To see cached templates simply use the parser for the correct version (v9parser for v9, ipfixparser for IPFix.)

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

To access templates flowset of a processed V9/IPFix flowset you can find the flowsets attribute on the Parsed Record. In there you can find Templates, Option Templates, and Data Flowsets.

Examples

Some examples has been included mainly for those who want to use this parser to read from a Socket and parse netflow. In those cases with V9/IPFix it is best to create a new parser for each router. There are both single threaded and multi-threaded examples in the examples directory.

To run:

cargo run --example netflow_udp_listener_multi_threaded

or

cargo run --example netflow_udp_listener_single_threaded