📜 ⬆️ ⬇️

Parsing NetFlow v.9 C # Packages

NetFlow is a network protocol created by Cisco Systems to account for network traffic. The most common versions of this protocol are 5 and 9. The ninth version is more flexible because it uses templates according to which the data is sent. In the fifth version of the data are sent according to the specification.
image

NetFlow 's traffic information collection system consists of the following components:


I will tell you about the development of some functions of the analyzer in C # , and more precisely the analysis of NetFlow packets
')
As the sensor was used MikroTik router.

We enable NetFlow on it for ether1 interface:
/ip traffic-flow set enabled=yes interfaces=ether1

And we add a collector (as a rule, the collector listens on port 2055, 9555 or 9995):
/ip traffic-flow target add disabled=no version=9 address=192.168.0.100:9995

Or the same thing through WinBox :
image

Now, NetFlow 9 version packets will come to the computer with IP address 192.168.0.100 on port 9995 via UDP (or SCTP ). Packages come and have something to work with.

Parsing incoming packages



Having studied the protocol specification, we learn that each NetFlow packet (N bytes) consists of:
  1. Packet Header (20 bytes) - packet header, in a single copy with the fields:
    • Version Number ( UInt16 - 2 bytes) - the version number of NetFlow , we always have 9;
    • Count ( UInt16 - 2 bytes) - the total number of records. Further, in the text of the articles with this field was an adventure ;
    • sysUpTime ( UInt32 - 4 bytes) - time in milliseconds from the start of the device - UpTime;
    • UNIX Secs ( UInt32 - 4 bytes) - time in seconds since 0000 UTC 1970, at which the packet was sent;
    • Sequence Number ( UInt32 - 4 bytes) - the counter of transmitted packets, it is constantly increasing from packet to packet, thus you can check whether packets are lost between them;
    • Source ID ( UInt32 - 4 bytes) - the number of data stream, in fact, that from the side of the sensor there can be several data streams.

  2. FlowSet (N-20 bytes) - templates, data ... FlowSet`s can be several or one. In each FlowSet there are two unchanged fields of the type of data transmitted (template, data):
    • FlowSet ID ( UInt16 2 bytes) - for the template it is always 0, for the optional template 1, for data it is equal to the Template ID and therefore more than 255 (from 256 to 65535);
    • Length ( UInt16 2 bytes) - the size of the entire FlowSet along with the FlowSet ID and Length fields;
    • Other fields depending on the type of data transmitted.



Look at the FlowSet ID containing the template, it starts with the fields FlowSet ID , then Length , then:


We look at the FlowSet ID containing the data, start with the fields FlowSet ID , then Length , then:


There is also a so-called optional template and data on it. I will not consider them, they have not met me, for this reason there are no libraries in the library implementation, but everything can be added.

Compiled UML class diagram (using NClass ):
image
or in pdf
And wrote a library for parsing incoming packages.
The main class that starts it all is Packet . Its only constructor accepts an incoming NetFlow packet in bytes and an object of the Templates class, which is a list of current Templates .

Next, in the constructor of the Packet class, the Parse function is called, which takes an object of the Templates class.
In this function, the packet is divided into a header - 20 bytes and further work with it through the Header class; on FlowSet`s and transfer of each FlowSet`s and processing to the appropriate class FlowSet .

Due to the fact that FlowSet`s can be several, the second part of the packet (without 20 bytes of the header) has to be analyzed and divided into different FlowSet`s . It is noteworthy that in MikroTik ` FlowSet`s in a single copy in the package, but using Netflow Simulator in C # it was possible to work with packages with several FlowSet`s in the package. In addition, thanks to him, a funny bug was found in the implementation of NetFlow v9 on MikroTik `s, what more here .

Netflow Simulator in C # :
image

Here is the code section breaking part of the package at FlowSet`s :
 this._flowset = new List<FlowSet>(); Int32 length = _bytes.Length - 20; Byte[] flowset = new Byte[length]; Array.Copy(_bytes, 20, flowset, 0, length); byte[] reverse = flowset.Reverse().ToArray(); int templengh = 0; while ((templengh + 2) < flowset.Length) { UInt16 lengths = BitConverter.ToUInt16(reverse, flowset.Length - sizeof(Int16) - (templengh+2)); Byte[] bflowsets = new Byte[lengths]; Array.Copy(flowset, templengh, bflowsets, 0, lengths); FlowSet flowsets = new FlowSet(bflowsets, templates); this._flowset.Add(flowsets); templengh += lengths; } 


In the Header class, the packet header is parsed into its fields. Before you do this, the header is reversed:
 this._bytes.Reverse().ToArray(); 


Next, convert the bits to the type of field it is, for example the version field:
 this._version = BitConverter.ToUInt16(reverse, this._bytes.Length - sizeof(Int16) - 0); 


Yes, in the Header of the sysUpTime field, it has a TimeSpan type, we cast it to this type:
 get { return new TimeSpan((long)this._uptime * 10000); } 


and the UNIX Secs field is of type DateTime :
 get { return new DateTime(1970, 1, 1).AddSeconds(this._secs); } 


Let us turn to processing FlowSet`s . After receiving the FlowSet ID and Length fields, the remaining fields are parsed depending on the FlowSet ID . If it is 0 or 1, then this is a pattern, and if it is a number from 256 to 65535, then this is data.

If this is a template, then we transfer its processing to the Template class and then check our template storage (object of the Templates class) for the presence of a template with the same ID and replace it, otherwise we simply add the template.

If this is data, then we check if there is such a template ( FlowSet ID == Template ID ) in the storage (object of the Templates class) and if there is, then copy this template with the DeepClone function and fill its fields - Field , otherwise we do nothing, because without a template it’s just set of bytes.

DeepClone function:
 public static object DeepClone(object obj) { object objResult = null; using (MemoryStream ms = new MemoryStream()) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(ms, obj); ms.Position = 0; objResult = bf.Deserialize(ms); } return objResult; } 


Field is a field, it has the following parameters:


Moreover, the Field in Template in the repository is without Value parameters, i.e. Value is empty, but when processing Template packages in a FlowSet in a Packet object, it already contains Value fields.

Besides all this, there is also the FieldType enumeration - an enumeration in which the type name corresponds to the number of this type. ( Type parameter in Field )

An example was written for the work of this library:
 using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.NetFlow; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace Consoles { class Program { static void Main(string[] args) { Templates _templates = new Templates(); Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9995); sock.Bind(iep); EndPoint ep = (EndPoint)iep; byte[] data = new byte[2048]; while (true) { int recv = sock.ReceiveFrom(data, ref ep); Console.ReadKey(); Console.Clear(); byte[] bytes = new byte[recv]; for (int i = 0; i < recv; i++) bytes[i] = data[i]; Packet packet = new Packet(bytes, _templates); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(packet.ToString()); } sock.Close(); Console.ReadKey(); } } } 


We create a socket and listen on UDP port 9995 on our PC. _templates is our template repository. Each incoming packet we feed to the packet object of the Packet class passing also our template storage. And then we execute packet. ToString () This overloaded function outputs the contents of the packet to us and is only needed to check that everything works out for us.

This is all with the library; now it can be used to further write the NetFlow traffic analyzer.

Example with MikroTik :

Received a package without a template in the repository:
image

Received the template from the sensor:
image

Received data for which there is a template in the repository:
image

Error implementing NetFlow v9 in MikroTik `e


In the process of analyzing this topic, an error was found in the implementation of NetFlow v9 in MikroTik `e. The essence of the error:
The Count field in the packet header ( Packet Header ) carries:
Count
The total number of records in the Export Packet, which is
sum of Options FlowSet records, Template FlowSet records, and
Data FlowSet records.

those. contains all records in all FlowSets, ah, and in MicroTik , this field is always 1 (see screenshots above), even if several templates or data are transmitted. those. according to the logic of MikroTik `and the Count field = the number of FlowSet`s (what they wrote to me in the letter and can be seen on the screen), but should be equal to the total number of all templates and data, as it sounds in the specification. For this reason, the use of the Count field in packet parsing is fraught.

Here is an example from Netflow Simulator in C # (I would like to receive data from Cisco as well , but I don’t have such an opportunity, can a reader check this):

Received a package without a template in the repository (note the Count ):
image

Received a template from the sensor (here at the same time two FlowSet `and it came that in MikroTik` e does not happen. Pay attention to the Count it is equal to 7 = 1 template and 6 data records. According to the logic of MikroTik `and the Count would have been equal to 2 = 2 FlowSet a):
image

Received data for which there is a template in the repository (note the Count ):
image

Well, once again the package in Wireshark Marked field Count :
image

Once again: I will be very grateful to everyone who will send a screen with Wireshark `from Cisco . I'll put it in here.

Source code is available here .

When creating guided:
Wikipedia: Netflow
Caligare: WHAT IS NETFLOW?
Protocol Specification Version 9

Today (19:05 07/30/2013)

MikroTik replied:

MikroTik support [Dzintars] support@mikrotik.com
Hello,

Thank you for reporting a problem.
that count is not set correctly in the netflow packet header). The
problem will be fixed in the next version of RouterOS.

Regards,
Dzintars


UPD: This bug has been fixed in RouterOS 6.2.
Today (13:22 13/09/2013)

MikroTik wrote:

MikroTik support [Dzintars] support@mikrotik.com
Hello,

The NetFlow V9 count field problem was fixed in version 6.2

Regards,
Dzintars

Source: https://habr.com/ru/post/187820/


All Articles