netflow/tests/test_ipfix.py
Dominik Pataky 547792c5c2 Tests: move packets into each version test file; add tests for IPFIX
The previously introduced tests/lib.py contained the NetFlow v9 packets
and then the IPFIX packets, those were split and put into their
respective test files again. The lib now contains shared objects only.

For IPFIX tests were added. Two new packets were added, one with
templates and one without (again, real exports from softflowd).
Different cases are checked: no template, template and later template.
Fields of flows are also checked, especially IPv6 addresses.

Note: exports made with softflowd were created by softflowd 1.0.0,
compiled from https://github.com/irino/softflowd
2020-04-01 14:15:53 +02:00

107 lines
6.8 KiB
Python

#!/usr/bin/env python3
"""
This file belongs to https://github.com/bitkeks/python-netflow-v9-softflowd.
Copyright 2016-2020 Dominik Pataky <dev@bitkeks.eu>
Licensed under MIT License. See LICENSE.
"""
# TODO: tests with 500 packets fail with delay=0. Probably a problem with UDP sockets buffer
import ipaddress
import unittest
from tests.lib import *
# Example export for IPFIX (v10) with 4 templates, 1 option template and 8 data flow sets
PACKET_IPFIX_TEMPLATE = "000a05205e8465fd0000001300000000000200400400000e00080004000c00040016000400150004" \
"0001000400020004000a0004000e000400070002000b00020004000100060001003c000100050001" \
"000200340401000b00080004000c000400160004001500040001000400020004000a0004000e0004" \
"00200002003c000100050001000200400800000e001b0010001c0010001600040015000400010004" \
"00020004000a0004000e000400070002000b00020004000100060001003c00010005000100020034" \
"0801000b001b0010001c001000160004001500040001000400020004000a0004000e0004008b0002" \
"003c0001000500010003001e010000050001008f000400a000080131000401320004013000020100" \
"001a00000a5900000171352e67210000000100000000000104000054976500dfac110002ff7ed688" \
"ff7ed73a000015c70000000d000000000000000001bbe1a6061b0400ac110002976500dfff7ed688" \
"ff7ed73a0000074f000000130000000000000000e1a601bb061f04000401004cac110002ac110001" \
"ff7db9e0ff7dc1d0000000fc00000003000000000000000008000400ac110001ac110002ff7db9e0" \
"ff7dc1d0000000fc0000000300000000000000000000040008010220fde66f14e0f1960900000242" \
"ac110002ff0200000000000000000001ff110001ff7dfad6ff7e0e95000001b00000000600000000" \
"0000000087000600fde66f14e0f1960900000242ac110002fde66f14e0f196090000000000000001" \
"ff7e567fff7e664a0000020800000005000000000000000080000600fde66f14e0f1960900000000" \
"00000001fde66f14e0f1960900000242ac110002ff7e567fff7e664a000002080000000500000000" \
"0000000081000600fe800000000000000042aafffe73bbfafde66f14e0f1960900000242ac110002" \
"ff7e6aaaff7e6aaa0000004800000001000000000000000087000600fde66f14e0f1960900000242" \
"ac110002fe800000000000000042aafffe73bbfaff7e6aaaff7e6aaa000000400000000100000000" \
"0000000088000600fe800000000000000042acfffe110002fe800000000000000042aafffe73bbfa" \
"ff7e7eaaff7e7eaa0000004800000001000000000000000087000600fe800000000000000042aaff" \
"fe73bbfafe800000000000000042acfffe110002ff7e7eaaff7e7eaa000000400000000100000000" \
"0000000088000600fe800000000000000042aafffe73bbfafe800000000000000042acfffe110002" \
"ff7e92aaff7e92aa0000004800000001000000000000000087000600fe800000000000000042acff" \
"fe110002fe800000000000000042aafffe73bbfaff7e92aaff7e92aa000000400000000100000000" \
"000000008800060008000044fde66f14e0f1960900000242ac110002fd41b7143f86000000000000" \
"00000001ff7ec2a0ff7ec2a00000004a000000010000000000000000d20100351100060004000054" \
"ac1100027f000001ff7ed62eff7ed68700000036000000010000000000000000c496003511000400" \
"7f000001ac110002ff7ed62eff7ed687000000760000000100000000000000000035c49611000400" \
"08000044fde66f14e0f1960900000242ac110002fd41b7143f8600000000000000000001ff7ef359" \
"ff7ef3590000004a000000010000000000000000b1e700351100060004000054ac1100027f000001" \
"ff7f06e4ff7f06e800000036000000010000000000000000a8f90035110004007f000001ac110002" \
"ff7f06e4ff7f06e8000000a60000000100000000000000000035a8f911000400"
# Example export for IPFIX with two data sets
PACKET_IPFIX = "000a00d05e8465fd00000016000000000801007cfe800000000000000042acfffe110002fde66f14" \
"e0f196090000000000000001ff7f0755ff7f07550000004800000001000000000000000087000600" \
"fde66f14e0f196090000000000000001fe800000000000000042acfffe110002ff7f0755ff7f0755" \
"000000400000000100000000000000008800060008000044fde66f14e0f1960900000242ac110002" \
"2a044e42020000000000000000000223ff7f06e9ff7f22d500000140000000040000000000000000" \
"e54c01bb06020600"
class TestFlowExportIPFIX(unittest.TestCase):
"""Test IPFIX packet parsing
"""
def test_recv_ipfix_packet(self):
# send packet without any template, must fail to parse (packets are queued)
pkts, _, _ = send_recv_packets([PACKET_IPFIX])
self.assertEqual(len(pkts), 0) # no export is parsed due to missing template
# send packet with 5 templates and 20 flows, should parse correctly since the templates are known
pkts, _, _ = send_recv_packets([PACKET_IPFIX_TEMPLATE])
self.assertEqual(len(pkts), 1)
p = pkts[0]
self.assertEqual(p.client[0], "127.0.0.1")
self.assertEqual(len(p.export.flows), 1 + 2 + 2 + 9 + 1 + 2 + 1 + 2) # count flows
self.assertEqual(len(p.export.templates), 4 + 1) # count new templates
# Inspect contents of specific flows
flow = p.export.flows[0]
self.assertEqual(flow.meteringProcessId, 2649)
self.assertEqual(flow.selectorAlgorithm, 1)
self.assertEqual(flow.systemInitTimeMilliseconds, 1585735165729)
flow = p.export.flows[1] # HTTPS flow from web server to client
self.assertEqual(flow.destinationIPv4Address, 2886795266)
self.assertEqual(ipaddress.ip_address(flow.destinationIPv4Address),
ipaddress.ip_address("172.17.0.2"))
self.assertEqual(flow.protocolIdentifier, 6) # TCP
self.assertEqual(flow.sourceTransportPort, 443)
self.assertEqual(flow.destinationTransportPort, 57766)
flow = p.export.flows[17] # IPv6 flow
self.assertEqual(flow.protocolIdentifier, 17) # UDP
self.assertEqual(flow.sourceIPv6Address, 337491164212692683663430561043420610562)
self.assertEqual(ipaddress.ip_address(flow.sourceIPv6Address), # Docker ULA
ipaddress.ip_address("fde6:6f14:e0f1:9609:0:242:ac11:2"))
# send template and multiple export packets
pkts, _, _ = send_recv_packets([PACKET_IPFIX, PACKET_IPFIX_TEMPLATE, PACKET_IPFIX])
self.assertEqual(len(pkts), 3)
self.assertEqual(pkts[0].export.header.version, 10)
# check amount of flows across all packets
total_flows = 0
for packet in pkts:
total_flows += len(packet.export.flows)
self.assertEqual(total_flows, 2 + 1 + (1 + 2 + 2 + 9 + 1 + 2 + 1 + 2) + 2 + 1)