logstash-codec-netflow 4.1.0 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07fee1cda04c3df1a3d1d2cb41fe75d6d4e10846
4
- data.tar.gz: 2dffcb11a2b8655606f14ffdd1994fb743f9e6de
3
+ metadata.gz: 05072723b2f9f9f78b2fb55268ddca4e189e641f
4
+ data.tar.gz: 0316e6c3a82fd2ac4355ef1cd7ede8a73b2b2e28
5
5
  SHA512:
6
- metadata.gz: f8aa23631113354571dd439f42fa626199a965c4b87d92a98dd7cb2c0e82c7bc86ea379bd5eaab1c1f4adecb6df53dcd2aa3c951d8499abd6b418354acbf0791
7
- data.tar.gz: 7b2dcdd89fd40653fc543c12f0b40bf6119b3a219cbb650f879a0dcda8abac5096b6d3f24192e2b2ceb9836b7b6056562eae4a02e10becd5b3d5f320e5d78bc2
6
+ metadata.gz: 145c03e3407507b71affae3b337b0afe489e474816c33836d6d0df632ac7b840418257aa20d18df31621c2d9bd73b02bc7aa7d032191115bcf4a20e128754045
7
+ data.tar.gz: d8b4cb2f0305d9a5d0f07132c466125480a41518ba5925f29bf2401117abb27d58f51e7e49698da283db8c11c0667c4630eaece7fd01d1db37ce5d776b3ffb98
@@ -1,3 +1,7 @@
1
+ ## 4.1.1
2
+
3
+ - Reduced complexity of creating, persisting, loading an retrieving template caches.
4
+
1
5
  ## 4.1.0
2
6
 
3
7
  - Added support for Netflow v9 devices with VarString fields (H3C Netstream)
@@ -32,6 +32,7 @@ Contributors:
32
32
  * Raju Nair (rajutech76)
33
33
  * Richard Pijnenburg (electrical)
34
34
  * Rob Cowart (robcowart)
35
+ * Ry Biesemeyer (yaauie)
35
36
  * Salvador Ferrer (salva-ferrer)
36
37
  * Vishal Solanki
37
38
  * Will Rigby (wrigby)
@@ -30,30 +30,32 @@ This codec supports:
30
30
  * Netflow v9
31
31
  * IPFIX
32
32
 
33
- The following Netflow/IPFIX exporters are known to work with the most recent version of the netflow codec:
33
+ The following Netflow/IPFIX exporters have been seen and tested with the most recent version of the Netflow Codec:
34
34
 
35
35
  [cols="6,^2,^2,^2,12",options="header"]
36
36
  |===========================================================================================
37
37
  |Netflow exporter | v5 | v9 | IPFIX | Remarks
38
- |Barracuda Firewall | | | y |
38
+ |Barracuda Firewall | | | y | With support for Extended Uniflow
39
39
  |Cisco ASA | | y | |
40
- |Cisco ASR 1k | | | n | Fails because of duplicate fields
40
+ |Cisco ASR 1k | | | N | Fails because of duplicate fields
41
41
  |Cisco ASR 9k | | y | |
42
42
  |Cisco IOS 12.x | | y | |
43
- |Cisco ISR w/ HSL | | n | | Fails because of duplicate fields, see: https://github.com/logstash-plugins/logstash-codec-netflow/issues/93
43
+ |Cisco ISR w/ HSL | | N | | Fails because of duplicate fields, see: https://github.com/logstash-plugins/logstash-codec-netflow/issues/93
44
44
  |Cisco WLC | | y | |
45
45
  |Citrix Netscaler | | | y | Still some unknown fields, labeled netscalerUnknown<id>
46
46
  |fprobe | y | | |
47
47
  |Fortigate FortiOS | | y | |
48
48
  |Huawei Netstream | | y | |
49
49
  |ipt_NETFLOW | y | y | y |
50
- |Juniper MX80 | y | | | SW > 12.3R8
50
+ |Juniper MX | y | | y | SW > 12.3R8. Fails to decode IPFIX from Junos 16.1 due to duplicate field names which we currently don't support.
51
51
  |Mikrotik | y | | y | http://wiki.mikrotik.com/wiki/Manual:IP/Traffic_Flow
52
52
  |nProbe | y | y | y | L7 DPI fields now also supported
53
53
  |Nokia BRAS | | | y |
54
- |OpenBSD pflow | y | n | y | http://man.openbsd.org/OpenBSD-current/man4/pflow.4
54
+ |OpenBSD pflow | y | N | y | http://man.openbsd.org/OpenBSD-current/man4/pflow.4
55
+ |Riverbed | | N | | Not supported due to field ID conflicts. Workaround available in the definitions directory over at Elastiflow <https://github.com/robcowart/elastiflow>
55
56
  |Sandvine Procera PacketLogic| | | y | v15.1
56
57
  |Softflowd | y | y | y | IPFIX supported in https://github.com/djmdjm/softflowd
58
+ |Sophos UTM | | | y |
57
59
  |Streamcore Streamgroomer | | y | |
58
60
  |Palo Alto PAN-OS | | y | |
59
61
  |Ubiquiti Edgerouter X | | y | | With MPLS labels
@@ -50,11 +50,8 @@ class LogStash::Codecs::Netflow < LogStash::Codecs::Base
50
50
  FLOWSET_ID = "flowset_id"
51
51
 
52
52
  def initialize(params = {})
53
- @file_cache_mutex = Mutex.new
54
53
  super(params)
55
54
  @threadsafe = true
56
- @decode_mutex_netflow = Mutex.new
57
- @decode_mutex_ipfix = Mutex.new
58
55
  end
59
56
 
60
57
  def clone
@@ -63,8 +60,9 @@ class LogStash::Codecs::Netflow < LogStash::Codecs::Base
63
60
 
64
61
  def register
65
62
  require "logstash/codecs/netflow/util"
66
- @netflow_templates = Vash.new()
67
- @ipfix_templates = Vash.new()
63
+
64
+ @netflow_templates = TemplateRegistry.new(logger, @cache_ttl, @cache_save_path && "#{@cache_save_path}/netflow_templates.cache")
65
+ @ipfix_templates = TemplateRegistry.new(logger, @cache_ttl, @cache_save_path && "#{@cache_save_path}/ipfix_templates.cache")
68
66
 
69
67
  # Path to default Netflow v9 field definitions
70
68
  filename = ::File.expand_path('netflow/netflow.yaml', ::File.dirname(__FILE__))
@@ -73,32 +71,6 @@ class LogStash::Codecs::Netflow < LogStash::Codecs::Base
73
71
  # Path to default IPFIX field definitions
74
72
  filename = ::File.expand_path('netflow/ipfix.yaml', ::File.dirname(__FILE__))
75
73
  @ipfix_fields = load_definitions(filename, @ipfix_definitions)
76
-
77
- if @cache_save_path
78
- if @versions.include?(9)
79
- cache_save_file_netflow = "#{@cache_save_path}/netflow_templates.cache"
80
- if File.exists?(cache_save_file_netflow)
81
- raise "#{self.class.name}: Template cache file #{cache_save_file_netflow} not writable" unless File.writable?(cache_save_file_netflow)
82
- @netflow_templates_cache = load_templates_cache("#{@cache_save_path}/netflow_templates.cache")
83
- @netflow_templates_cache.each{ |key, fields| @netflow_templates[key, @cache_ttl] = BinData::Struct.new(:endian => :big, :fields => fields) }
84
- else
85
- raise "#{self.class.name}: Template cache directory #{cache_save_path} not writable" unless File.writable?(cache_save_path)
86
- @netflow_templates_cache = {}
87
- end
88
- end
89
-
90
- if @versions.include?(10)
91
- cache_save_file_ipfix = "#{@cache_save_path}/ipfix_templates.cache"
92
- if File.exists?(cache_save_file_ipfix)
93
- raise "#{self.class.name}: Template cache file #{cache_save_file_ipfix} not writable" unless File.writable?(cache_save_file_ipfix)
94
- @ipfix_templates_cache = load_templates_cache("#{@cache_save_path}/ipfix_templates.cache")
95
- @ipfix_templates_cache.each{ |key, fields| @ipfix_templates[key, @cache_ttl] = BinData::Struct.new(:endian => :big, :fields => fields) }
96
- else
97
- raise "#{self.class.name}: Template cache directory #{cache_save_path} not writable" unless File.writable?(cache_save_path)
98
- @ipfix_templates_cache = {}
99
- end
100
- end
101
- end
102
74
  end # def register
103
75
 
104
76
  def decode(payload, metadata = nil, &block)
@@ -228,19 +200,11 @@ class LogStash::Codecs::Netflow < LogStash::Codecs::Base
228
200
  else
229
201
  key = "#{flowset.source_id}|#{template.template_id}"
230
202
  end
231
- # Prevent netflow_templates array from being concurrently modified
232
- @decode_mutex_netflow.synchronize do
233
- @netflow_templates[key, @cache_ttl] = BinData::Struct.new(:endian => :big, :fields => fields)
203
+ @netflow_templates.register(key, fields) do |bindata|
234
204
  @logger.debug("Received template #{template.template_id} with fields #{fields.inspect}")
235
- @logger.debug("Received template #{template.template_id} of size #{template_length} bytes. Representing in #{@netflow_templates[key].num_bytes} BinData bytes")
236
- if template_length != @netflow_templates[key].num_bytes
237
- @logger.warn("Received template #{template.template_id} of size #{template_length} bytes doesn't match BinData representation we built (#{@netflow_templates[key].num_bytes} bytes)")
238
- end
239
- # Purge any expired templates
240
- @netflow_templates.cleanup!
241
- if @cache_save_path
242
- @netflow_templates_cache[key] = fields
243
- save_templates_cache(@netflow_templates_cache, "#{@cache_save_path}/netflow_templates.cache")
205
+ @logger.debug("Received template #{template.template_id} of size #{template_length} bytes. Representing in #{bindata.num_bytes} BinData bytes")
206
+ if template_length != bindata.num_bytes
207
+ @logger.warn("Received template #{template.template_id} of size #{template_length} bytes doesn't match BinData representation we built (#{bindata.num_bytes} bytes)")
244
208
  end
245
209
  end
246
210
  end
@@ -255,7 +219,7 @@ class LogStash::Codecs::Netflow < LogStash::Codecs::Base
255
219
  key = "#{flowset.source_id}|#{record.flowset_id}"
256
220
  end
257
221
 
258
- template = @decode_mutex_netflow.synchronize { @netflow_templates[key] }
222
+ template = @netflow_templates.fetch(key)
259
223
 
260
224
  if !template
261
225
  @logger.warn("Can't (yet) decode flowset id #{record.flowset_id} from source id #{flowset.source_id}, because no template to decode it with has been received. This message will usually go away after 1 minute.")
@@ -338,23 +302,14 @@ class LogStash::Codecs::Netflow < LogStash::Codecs::Base
338
302
  end
339
303
  # FIXME Source IP address required in key
340
304
  key = "#{flowset.observation_domain_id}|#{template.template_id}"
341
- # Prevent ipfix_templates array from being concurrently modified
342
- @decode_mutex_ipfix.synchronize do
343
- @ipfix_templates[key, @cache_ttl] = BinData::Struct.new(:endian => :big, :fields => fields)
344
- # Purge any expired templates
345
- @ipfix_templates.cleanup!
346
- if @cache_save_path
347
- @ipfix_templates_cache[key] = fields
348
- save_templates_cache(@ipfix_templates_cache, "#{@cache_save_path}/ipfix_templates.cache")
349
- end
350
- end
305
+
306
+ @ipfix_templates.register(key, fields)
351
307
  end
352
308
  end
353
309
  when 256..65535
354
310
  # Data flowset
355
311
  key = "#{flowset.observation_domain_id}|#{record.flowset_id}"
356
-
357
- template = @decode_mutex_ipfix.synchronize { @ipfix_templates[key] }
312
+ template = @ipfix_templates.fetch(key)
358
313
 
359
314
  if !template
360
315
  @logger.warn("Can't (yet) decode flowset id #{record.flowset_id} from observation domain id #{flowset.observation_domain_id}, because no template to decode it with has been received. This message will usually go away after 1 minute.")
@@ -431,30 +386,6 @@ class LogStash::Codecs::Netflow < LogStash::Codecs::Base
431
386
  fields
432
387
  end
433
388
 
434
- def load_templates_cache(file_path)
435
- templates_cache = {}
436
- begin
437
- @logger.debug? and @logger.debug("Loading templates from template cache #{file_path}")
438
- file_data = @file_cache_mutex.synchronize { File.read(file_path)}
439
- templates_cache = JSON.parse(file_data)
440
- rescue Exception => e
441
- raise "#{self.class.name}: templates cache file could not be read @ (#{file_path}: #{e.class.name} #{e.message})"
442
- end
443
-
444
- templates_cache
445
- end
446
-
447
- def save_templates_cache(templates_cache, file_path)
448
- begin
449
- @logger.debug? and @logger.debug("Writing templates to template cache #{file_path}")
450
- @file_cache_mutex.synchronize do
451
- File.open(file_path, 'w') {|file| file.write templates_cache.to_json }
452
- end
453
- rescue Exception => e
454
- raise "#{self.class.name}: saving templates cache file failed (#{file_path}) with error #{e}"
455
- end
456
- end
457
-
458
389
  def uint_field(length, default)
459
390
  # If length is 4, return :uint32, etc. and use default if length is 0
460
391
  ("uint" + (((length > 0) ? length : default) * 8).to_s).to_sym
@@ -599,4 +530,144 @@ class LogStash::Codecs::Netflow < LogStash::Codecs::Base
599
530
  @logger.warn("Definition should be an array", :field => field)
600
531
  end
601
532
  end
533
+
534
+ class TemplateRegistry
535
+ ##
536
+ # @param logger [Logger]
537
+ # @param ttl [Integer]
538
+ # @param file_path [String] (optional)
539
+ def initialize(logger, ttl, file_path=nil)
540
+ @logger = logger
541
+ @ttl = Integer(ttl)
542
+ @file_path = file_path
543
+
544
+ @mutex = Mutex.new
545
+
546
+ @bindata_struct_cache = Vash.new
547
+ @bindata_spec_cache = Vash.new
548
+
549
+ do_load unless file_path.nil?
550
+ end
551
+
552
+ ##
553
+ # Register a Template by name using an array of type/name tuples.
554
+ #
555
+ # @param key [String]: the key under which to save this template
556
+ # @param field_tuples [Array<Array<String>>]: an array of [type,name] tuples, e.g., ["uint32","fieldName"]
557
+ # @return [BinData::Struct]
558
+ #
559
+ # If a block is given, the template is yielded to the block _before_ being saved in the cache.
560
+ #
561
+ # @yieldparam [BinData::Struct]
562
+ # @yieldreturn [void]
563
+ # @yieldthrow :invalid_template : if the template is deemed invalid within the block, throwing this symbol causes
564
+ # the template to not be cached.
565
+ #
566
+ # @threadsafe
567
+ def register(key, field_tuples, &block)
568
+ @mutex.synchronize do
569
+ do_register(key, field_tuples, &block)
570
+ end
571
+ end
572
+
573
+ ##
574
+ # Fetch a Template by name
575
+ #
576
+ # @param key [String]
577
+ # @return [BinData::Struct]
578
+ #
579
+ # @threadsafe
580
+ def fetch(key)
581
+ @mutex.synchronize do
582
+ do_fetch(key)
583
+ end
584
+ end
585
+
586
+ ##
587
+ # Force persist, potentially cleaning up elements from the file-based cache that have already been evicted from
588
+ # the memory-based cache
589
+ def persist()
590
+ @mutex.synchronize do
591
+ do_persist
592
+ end
593
+ end
594
+
595
+ private
596
+ attr_reader :logger
597
+ attr_reader :file_path
598
+
599
+ ##
600
+ # @see `TemplateRegistry#register(String,Array<>)`
601
+ # @api private
602
+ def do_register(key, field_tuples)
603
+ template = BinData::Struct.new(:fields => field_tuples, :endian => :big)
604
+
605
+ catch(:invalid_template) do
606
+ yield(template) if block_given?
607
+
608
+ @bindata_spec_cache[key] = field_tuples
609
+ @bindata_struct_cache[key] = template
610
+
611
+ do_persist
612
+
613
+ template
614
+ end
615
+ end
616
+
617
+ ##
618
+ # @api private
619
+ def do_load
620
+ unless File.exists?(file_path)
621
+ logger.warn('Template Cache does not exist', :file_path => file_path)
622
+ return
623
+ end
624
+
625
+ logger.debug? and logger.debug('Loading templates from template cache', :file_path => file_path)
626
+ file_data = File.read(file_path)
627
+ templates_cache = JSON.parse(file_data)
628
+ templates_cache.each do |key, fields|
629
+ do_register(key, fields)
630
+ end
631
+
632
+ logger.warn('Template Cache not writable', file_path: file_path) unless File.writable?(file_path)
633
+ rescue => e
634
+ logger.error('Template Cache could not be loaded', :file_path => file_path, :exception => e.message)
635
+ end
636
+
637
+ ##
638
+ # @see `TemplateRegistry#persist`
639
+ # @api private
640
+ def do_persist
641
+ return if file_path.nil?
642
+
643
+ logger.debug? and logger.debug('Writing templates to template cache', :file_path => file_path)
644
+
645
+ fail('Template Cache not writable') if File.exists?(file_path) && !File.writable?(file_path)
646
+
647
+ do_cleanup!
648
+
649
+ templates_cache = @bindata_spec_cache
650
+
651
+ File.open(file_path, 'w') do |file|
652
+ file.write(templates_cache.to_json)
653
+ end
654
+ rescue Exception => e
655
+ logger.error('Template Cache could not be saved', :file_path => file_path, :exception => e.message)
656
+ end
657
+
658
+ ##
659
+ # @see `TemplateRegistry#cleanup`
660
+ # @api private
661
+ def do_cleanup!
662
+ @bindata_spec_cache.cleanup!
663
+ @bindata_struct_cache.cleanup!
664
+ end
665
+
666
+ ##
667
+ # @see `TemplateRegistry#fetch(String)`
668
+ # @api private
669
+ def do_fetch(key)
670
+ @bindata_struct_cache[key]
671
+ end
672
+ end
602
673
  end # class LogStash::Filters::Netflow
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-codec-netflow'
4
- s.version = '4.1.0'
4
+ s.version = '4.1.1'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Reads Netflow v5, Netflow v9 and IPFIX data"
7
7
  s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+ require 'benchmark'
3
+ require 'bindata'
4
+
5
+
6
+ Benchmark.bm do |x|
7
+ x.report {
8
+ # Original IPFIX version, simplified
9
+ k = 'flowStartMilliseconds'
10
+ data = '1000'
11
+ v = BinData::String.new(:read_length => 4)
12
+ v.read(data)
13
+ 2000000.times do
14
+ case k.to_s
15
+ when /^flow(?:Start|End)Seconds$/
16
+ event = 'blah'
17
+ when /^flow(?:Start|End)(Milli|Micro|Nano)seconds$/
18
+ case $1
19
+ when 'Milli'
20
+ event = v.snapshot.to_f / 1_000
21
+ end
22
+ end
23
+ end }
24
+
25
+ x.report {
26
+ # Verion that omits v.snapshot, simplified
27
+ k = 'flowStartMilliseconds'
28
+ data = '1000'
29
+ v = BinData::String.new(:read_length => 4)
30
+ v.read(data)
31
+ 2000000.times do
32
+ case k.to_s
33
+ when /^flow(?:Start|End)Seconds$/
34
+ event = 'blah'
35
+ when /^flow(?:Start|End)(Milli|Micro|Nano)seconds$/
36
+ case $1
37
+ when 'Milli'
38
+ event = data.to_f / 1_000
39
+ end
40
+ end
41
+ end }
42
+
43
+ x.report {
44
+ # Original Netflow9 version, simplified
45
+ class MockFlowset < BinData::Record
46
+ endian :little
47
+ uint8 :uptime
48
+ uint8 :unix_sec
49
+ end
50
+ SWITCHED = /_switched$/
51
+ data1 = 'AB'
52
+ flowset = MockFlowset.read(data1)
53
+ k = 'first_switched'
54
+ v = 20
55
+ 2000000.times do
56
+ case k.to_s
57
+ when SWITCHED
58
+ millis = flowset.uptime - v
59
+ seconds = flowset.unix_sec - (millis / 1000)
60
+ # v9 did away with the nanosecs field
61
+ micros = 1000000 - (millis % 1000)
62
+ event = v
63
+ else
64
+ event = 'blah'
65
+ end
66
+ end }
67
+
68
+ end
69
+
70
+ # user system total real
71
+ # 4.730000 0.000000 4.730000 ( 4.731333)
72
+ # 2.400000 0.000000 2.400000 ( 2.401072)
73
+ # 2.750000 0.000000 2.750000 ( 2.747525)
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env python2
2
+ import socket
3
+ import sys
4
+ import time
5
+
6
+
7
+ # IPFIX template
8
+ tpl = "000a00585b6b5242000010bda07e8c0000020048010000100001000400020004000400010008000400070002000a0004000b0002000c0004000e0004000f0004001500040016000400e1000400e2000400e3000200e40002".decode("hex")
9
+ '''
10
+ Cisco NetFlow/IPFIX
11
+ Version: 10
12
+ Length: 88
13
+ Timestamp: Aug 8, 2018 14:27:46.000000000 MDT
14
+ ExportTime: 1533760066
15
+ FlowSequence: 4285
16
+ Observation Domain Id: 2692647936
17
+ Set 1 [id=2] (Data Template): 256
18
+ FlowSet Id: Data Template (V10 [IPFIX]) (2)
19
+ FlowSet Length: 72
20
+ Template (Id = 256, Count = 16)
21
+ Template Id: 256
22
+ Field Count: 16
23
+ Field (1/16): BYTES
24
+ 0... .... .... .... = Pen provided: No
25
+ .000 0000 0000 0001 = Type: BYTES (1)
26
+ Length: 4
27
+ Field (2/16): PKTS
28
+ 0... .... .... .... = Pen provided: No
29
+ .000 0000 0000 0010 = Type: PKTS (2)
30
+ Length: 4
31
+ Field (3/16): PROTOCOL
32
+ 0... .... .... .... = Pen provided: No
33
+ .000 0000 0000 0100 = Type: PROTOCOL (4)
34
+ Length: 1
35
+ Field (4/16): IP_SRC_ADDR
36
+ 0... .... .... .... = Pen provided: No
37
+ .000 0000 0000 1000 = Type: IP_SRC_ADDR (8)
38
+ Length: 4
39
+ Field (5/16): L4_SRC_PORT
40
+ 0... .... .... .... = Pen provided: No
41
+ .000 0000 0000 0111 = Type: L4_SRC_PORT (7)
42
+ Length: 2
43
+ Field (6/16): INPUT_SNMP
44
+ 0... .... .... .... = Pen provided: No
45
+ .000 0000 0000 1010 = Type: INPUT_SNMP (10)
46
+ Length: 4
47
+ Field (7/16): L4_DST_PORT
48
+ 0... .... .... .... = Pen provided: No
49
+ .000 0000 0000 1011 = Type: L4_DST_PORT (11)
50
+ Length: 2
51
+ Field (8/16): IP_DST_ADDR
52
+ 0... .... .... .... = Pen provided: No
53
+ .000 0000 0000 1100 = Type: IP_DST_ADDR (12)
54
+ Length: 4
55
+ Field (9/16): OUTPUT_SNMP
56
+ 0... .... .... .... = Pen provided: No
57
+ .000 0000 0000 1110 = Type: OUTPUT_SNMP (14)
58
+ Length: 4
59
+ Field (10/16): IP_NEXT_HOP
60
+ 0... .... .... .... = Pen provided: No
61
+ .000 0000 0000 1111 = Type: IP_NEXT_HOP (15)
62
+ Length: 4
63
+ Field (11/16): LAST_SWITCHED
64
+ 0... .... .... .... = Pen provided: No
65
+ .000 0000 0001 0101 = Type: LAST_SWITCHED (21)
66
+ Length: 4
67
+ Field (12/16): FIRST_SWITCHED
68
+ 0... .... .... .... = Pen provided: No
69
+ .000 0000 0001 0110 = Type: FIRST_SWITCHED (22)
70
+ Length: 4
71
+ Field (13/16): postNATSourceIPv4Address
72
+ 0... .... .... .... = Pen provided: No
73
+ .000 0000 1110 0001 = Type: postNATSourceIPv4Address (225)
74
+ Length: 4
75
+ Field (14/16): postNATDestinationIPv4Address
76
+ 0... .... .... .... = Pen provided: No
77
+ .000 0000 1110 0010 = Type: postNATDestinationIPv4Address (226)
78
+ Length: 4
79
+ Field (15/16): postNAPTSourceTransportPort
80
+ 0... .... .... .... = Pen provided: No
81
+ .000 0000 1110 0011 = Type: postNAPTSourceTransportPort (227)
82
+ Length: 2
83
+ Field (16/16): postNAPTDestinationTransportPort
84
+ 0... .... .... .... = Pen provided: No
85
+ .000 0000 1110 0100 = Type: postNAPTDestinationTransportPort (228)
86
+ Length: 2
87
+ '''
88
+
89
+ data = "000a011d5b6b86c50000acf0a07e8c000100010d0010d49a000002fa06acd9022501bb00000002a3290a0000ed000000010a00000100dedac800debb88acd90225c0a8a84101bbdd690000009d00000001114b4b4b4b003500000002222c0a0000ed000000010a00000100de715000de71504b4b4b4bc0a8a8410035398f0000024600000005114a7d8a7101bb00000002d3d10a0000ed000000010a00000100de715000de71504a7d8a71c0a8a84101bb9ca40000038300000004114a7d8a7101bb0000000268920a0000ed000000010a00000100de715000de71504a7d8a71c0a8a84101bba46b000001c6000000040623a8ede501bb000000023d1b0a0000ed000000010a00000100de753800023a5023a8ede5c0a8a84101bbeb10".decode("hex")
90
+
91
+ '''
92
+ Cisco NetFlow/IPFIX
93
+ Version: 10
94
+ Length: 285
95
+ Timestamp: Aug 8, 2018 18:11:49.000000000 MDT
96
+ ExportTime: 1533773509
97
+ FlowSequence: 44272
98
+ Observation Domain Id: 2692647936
99
+ Set 1 [id=256] (5 flows)
100
+ FlowSet Id: (Data) (256)
101
+ FlowSet Length: 269
102
+ [Template Frame: 54]
103
+ Flow 1
104
+ Octets: 1103002
105
+ Packets: 762
106
+ Protocol: TCP (6)
107
+ SrcAddr: 172.217.2.37
108
+ SrcPort: 443 (443)
109
+ InputInt: 2
110
+ DstPort: 41769 (41769)
111
+ DstAddr: 10.0.0.237
112
+ OutputInt: 1
113
+ NextHop: 10.0.0.1
114
+ [Duration: 8.000000000 seconds (switched)]
115
+ StartTime: 14597.000000000 seconds
116
+ EndTime: 14605.000000000 seconds
117
+ Post NAT Source IPv4 Address: 172.217.2.37
118
+ Post NAT Destination IPv4 Address: 192.168.168.65
119
+ Post NAPT Source Transport Port: 443
120
+ Post NAPT Destination Transport Port: 56681
121
+ Flow 2
122
+ Octets: 157
123
+ Packets: 1
124
+ Protocol: UDP (17)
125
+ SrcAddr: 75.75.75.75
126
+ SrcPort: 53 (53)
127
+ InputInt: 2
128
+ DstPort: 8748 (8748)
129
+ DstAddr: 10.0.0.237
130
+ OutputInt: 1
131
+ NextHop: 10.0.0.1
132
+ [Duration: 0.000000000 seconds (switched)]
133
+ StartTime: 14578.000000000 seconds
134
+ EndTime: 14578.000000000 seconds
135
+ Post NAT Source IPv4 Address: 75.75.75.75
136
+ Post NAT Destination IPv4 Address: 192.168.168.65
137
+ Post NAPT Source Transport Port: 53
138
+ Post NAPT Destination Transport Port: 14735
139
+ Flow 3
140
+ Octets: 582
141
+ Packets: 5
142
+ Protocol: UDP (17)
143
+ SrcAddr: 74.125.138.113
144
+ SrcPort: 443 (443)
145
+ InputInt: 2
146
+ DstPort: 54225 (54225)
147
+ DstAddr: 10.0.0.237
148
+ OutputInt: 1
149
+ NextHop: 10.0.0.1
150
+ [Duration: 0.000000000 seconds (switched)]
151
+ StartTime: 14578.000000000 seconds
152
+ EndTime: 14578.000000000 seconds
153
+ Post NAT Source IPv4 Address: 74.125.138.113
154
+ Post NAT Destination IPv4 Address: 192.168.168.65
155
+ Post NAPT Source Transport Port: 443
156
+ Post NAPT Destination Transport Port: 40100
157
+ Flow 4
158
+ Octets: 899
159
+ Packets: 4
160
+ Protocol: UDP (17)
161
+ SrcAddr: 74.125.138.113
162
+ SrcPort: 443 (443)
163
+ InputInt: 2
164
+ DstPort: 26770 (26770)
165
+ DstAddr: 10.0.0.237
166
+ OutputInt: 1
167
+ NextHop: 10.0.0.1
168
+ [Duration: 0.000000000 seconds (switched)]
169
+ StartTime: 14578.000000000 seconds
170
+ EndTime: 14578.000000000 seconds
171
+ Post NAT Source IPv4 Address: 74.125.138.113
172
+ Post NAT Destination IPv4 Address: 192.168.168.65
173
+ Post NAPT Source Transport Port: 443
174
+ Post NAPT Destination Transport Port: 42091
175
+ Flow 5
176
+ Octets: 454
177
+ Packets: 4
178
+ Protocol: TCP (6)
179
+ SrcAddr: 35.168.237.229
180
+ SrcPort: 443 (443)
181
+ InputInt: 2
182
+ DstPort: 15643 (15643)
183
+ DstAddr: 10.0.0.237
184
+ OutputInt: 1
185
+ NextHop: 10.0.0.1
186
+ [Duration: 14433.000000000 seconds (switched)]
187
+ StartTime: 146.000000000 seconds
188
+ EndTime: 14579.000000000 seconds
189
+ Post NAT Source IPv4 Address: 35.168.237.229
190
+ Post NAT Destination IPv4 Address: 192.168.168.65
191
+ Post NAPT Source Transport Port: 443
192
+ Post NAPT Destination Transport Port: 60176
193
+ '''
194
+
195
+ host = sys.argv[1]
196
+ port = 2055
197
+ N = 150000
198
+ flowsPerPacket = 5
199
+
200
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
201
+ sock.sendto(tpl, (host, port))
202
+ time.sleep(0.2)
203
+
204
+ ts = time.time()
205
+ print("%d: started sending %d SonicWALL IPFIX flows in %d packets totaling %d bytes" % (ts,N*flowsPerPacket, N, N*len(data)))
206
+ print("%d: flow size %d, packet size %d" % (ts, len(data) / flowsPerPacket, len(data)))
207
+
208
+ for i in range(0, N):
209
+ sock.sendto(data, (host, port))