logstash-codec-netflow 4.1.0 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
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))