fluent-plugin-netflowipfix 1.0.2 → 1.1.0

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: 4d367541e96f10fe8e2a3746029b5400606addc2
4
- data.tar.gz: 2c9d9cf3e5e73b608997468f6841e593acab2bb1
3
+ metadata.gz: '069c7af312866b4319eaa05bbf3a85b21dbe7284'
4
+ data.tar.gz: 347842300a58938ced6d12a552df6df416a74765
5
5
  SHA512:
6
- metadata.gz: 2ab9ec4274282f2ffd07adba1004dc9269a628e6a1256e2e9fbc2b8e66d829b532ed6174712df58c5fc264a18bf8399159ce57ff7034c39c47ad5488367f404f
7
- data.tar.gz: c4566318627dcd6a0181175912ea91f588a0a439587c10655c83cb44db09ed7d26acab539545df34f8d04c4daedd4ff49d829684af49c29eb35fc93f86cbccd9
6
+ metadata.gz: 5319acf004e86e279528485faa5ad760acaeb4b2a970aed0551a399ff34ef5b9a9692d3efd4c88072b65a76692ad96f46b19d1e84a8ede30cdce611d261cd16d
7
+ data.tar.gz: df25aa1db4ba2990a1428d99f9072c1c8f7ddd21fa9838d314d9acb218bfcd04808c9d129cc3be140508b8cf63f21550f1bffb41c6d49626f84ad5c711f4c622
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "fluent-plugin-netflowipfix"
6
- spec.version = "1.0.2"
6
+ spec.version = "1.1.0"
7
7
  spec.authors = ["Yves Desharnaus"]
8
8
  spec.email = ["yvesbd@gmail.com"]
9
9
 
@@ -1,5 +1,5 @@
1
1
  #
2
- # Copyright 2018 Yves Desharnais
2
+ # Copyright 2018-2019 Yves Desharnais
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
5
5
  # you may not use this file except in compliance with the License.
@@ -13,149 +13,291 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+
17
+ require "socket"
16
18
  require "fluent/plugin/input"
17
- require 'cool.io'
18
- require 'fluent/plugin/socket_util'
19
- # require_relative 'parser_netflowipfix'
19
+
20
20
  require_relative 'parser_netflow_v5'
21
21
  require_relative 'parser_netflow_v9'
22
22
  require_relative 'netflowipfix_records'
23
23
  require_relative 'vash'
24
24
 
25
+
25
26
  module Fluent
26
- module Plugin
27
- class NetflowipfixInput < Fluent::Plugin::Input
28
- Fluent::Plugin.register_input("netflowipfix", self)
29
-
30
- config_param :cache_ttl, :integer, default: 4000
31
- config_param :definitions, :string, default: nil
32
-
33
- config_param :debug, :bool, default: false
34
- config_param :port, :integer, default: 5140
35
- config_param :bind, :string, default: '0.0.0.0'
36
- config_param :tag, :string
37
- config_param :protocol_type, default: :udp do |val|
38
- case val.downcase
39
- when 'udp'
40
- :udp
41
- else
42
- raise ConfigError, "netflow input protocol type should be 'udp'"
43
- end
44
- end # config_param :protocol_type
45
-
46
- def configure(conf)
47
- super
48
- @nbpackets = 0
49
- @parser_v5 = ParserNetflowv5.new
50
- @parser_v9 = ParserNetflowv9.new
51
- @parser_v9.configure(@cache_ttl, @definitions)
52
- @parser_v10 = ParserIPfixv10.new
53
- @parser_v10.configure(@cache_ttl, @definitions)
54
- end # def configure
55
-
56
- def start
57
- @loop = Coolio::Loop.new
58
- @handler = listen(method(:receive_data))
59
- @loop.attach(@handler)
60
- @thread = Thread.new(&method(:run))
61
- end # def start
62
-
63
- def shutdown
64
- @loop.watchers.each { |w| w.detach }
65
- @loop.stop
66
- @handler.close
67
- @thread.join
68
- end # def shutdown
69
-
70
- def run
71
- @loop.run
72
- rescue => e
73
- log.error "unexpected error", error_class: e.class, error: e.message
74
- log.error_backtrace
75
- end # def run
76
-
77
- protected
78
-
79
- def receive_data(host, data)
80
- # if (@debug)
81
- # log.on_debug { log.debug "received logs", :host => host, :data => data }
82
- call(data, host) { |time, record|
83
- unless time && record
84
- log.warn "pattern not match: #{data.inspect}"
85
- return
27
+ module Plugin
28
+ class NetflowipfixInput < Fluent::Plugin::Input
29
+ Fluent::Plugin.register_input("netflowipfix", self)
30
+ include DetachMultiProcessMixin
31
+
32
+ class PortConnection
33
+ def initialize(bind, port, tag, cache_ttl, definitions, queuesleep)
34
+ @bind = bind
35
+ @port = port
36
+ @tag = tag
37
+ @cache_ttl = cache_ttl
38
+ @definitions = definitions
39
+ @eventQueue = Queue.new
40
+ @udpQueue = Queue.new
41
+ @queuesleep = queuesleep
42
+ end
43
+
44
+ def bind
45
+ @bind
46
+ end
47
+ def port
48
+ @port
49
+ end
50
+ def tag
51
+ @tag
52
+ end
53
+
54
+ def start
55
+ @thread_udp = UdpListenerThread.new(@bind, @port, @udpQueue, @tag)
56
+ @thread_parser = ParserThread.new(@udpQueue, @queuesleep, @eventQueue, @cache_ttl, @definitions)
57
+ @thread_udp.start
58
+ @thread_parser.start
59
+ end # def start
60
+ def stop
61
+ @thread_udp.close
62
+ @thread_udp.join
63
+ @thread_parser.close
64
+ @thread_parser.join
65
+ end # def stop
66
+
67
+ def event_pop
68
+ @eventQueue.pop
69
+ end
70
+
71
+ def event_queue_length
72
+ @eventQueue.length
73
+ end
74
+
75
+
76
+ # def udpqueue_pop
77
+ # @udpQueue.pop
78
+ # end
79
+
80
+ # def udpqueue_length
81
+ # @udpQueue.length
82
+ # end
83
+ end #class PortConnection
84
+
85
+ config_param :tag, :string
86
+ config_param :port, :integer, default: nil
87
+ config_param :bind, :string, :default => '0.0.0.0'
88
+ config_param :queuesleep, :integer, default: 10
89
+
90
+ def configure(conf)
91
+ super
92
+ $log.debug "NetflowipfixInput::configure: #{@bind}:#{@port}"
93
+ @@connections ||= {}
94
+ if @@connections.nil?
95
+ end
96
+ @@connections[@port] = PortConnection.new(@bind, @port, @tag, @cache_ttl, @definitions, @queuesleep)
97
+ log.debug "NetflowipfixInput::configure NB=#{@@connections.length}"
98
+ @total = 0
99
+ end
100
+
101
+ def start
102
+ super
103
+
104
+ $log.debug "NetflowipfixInput::start NB=#{@@connections.length}"
105
+ if @@connections.nil?
106
+ else
107
+ @@connections.each do | port, conn |
108
+ $log.debug "start listening UDP on #{conn.bind}:#{conn.port}"
109
+ conn.start
86
110
  end
111
+ end
112
+
113
+
114
+ # @eventQueue = Queue.new
115
+ # @udpQueue = Queue.new
116
+ # @thread_udp = UdpListenerThread.new(@bind, @port, @udpQueue)
117
+ # @thread_parser = ParserThread.new(@udpQueue, @queuesleep, @eventQueue, @cache_ttl, @definitions)
118
+ # @thread_udp.start
119
+ # @thread_parser.start
120
+ waitForEvents
121
+ end
87
122
 
88
- # if (@debug) log.info "ready to emit ", time:time, tag:@tag
89
-
90
- record['host'] = host
91
- router.emit(@tag, EventTime.new(time), record)
92
- } # call
93
- rescue => e
94
- log.warn "unexpected error on parsing", data: data.dump, error_class: e.class, error: e.message
95
- log.warn_backtrace
96
- end # def receive_data
97
-
98
- private
99
-
100
- def listen(callback)
101
- log.info "listening netflow socket on #{@bind}:#{@port} with #{@protocol_type}"
102
- if @protocol_type == :udp
103
- @usock = SocketUtil.create_udp_socket(@bind)
104
- @usock.bind(@bind, @port)
105
- UdpHandler.new(@usock, callback)
106
- else
107
- Coolio::TCPServer.new(@bind, @port, TcpHandler, log, callback)
123
+ def shutdown
124
+ super
125
+ $log.debug "NetflowipfixInput::shutdown NB=#{@@connections.length}"
126
+ if @@connections.nil?
127
+ else
128
+ # $log.debug "listening UDP on #{@bind}:#{@port}"
129
+ # @connections[@port].stop
130
+ @@connections.each do | port, conn |
131
+ $log.debug "shutdown listening UDP on #{conn.bind}:#{conn.port}"
132
+ conn.stop
108
133
  end
109
- end # def listen
110
-
111
- def call(payload, host=nil, &block)
134
+ @@connections = nil
135
+ end
136
+
137
+ # @thread_udp.close
138
+ # @thread_udp.join
139
+ # @thread_parser.close
140
+ # @thread_parser.join
141
+ end
142
+
143
+
144
+ def waitForEvents
145
+ # puts "Main::run begin #{@eventQueue.length}"
146
+ loop do
147
+ @@connections.each do | port, conn |
148
+ if (conn.event_queue_length > 0)
149
+ $log.debug "waitForEvents: #{conn.bind}:#{conn.port}"
150
+ ar = conn.event_pop
151
+ time = ar[0]
152
+ record = ar[1]
153
+ router.emit(conn.tag, EventTime.new(time.to_i), record)
154
+ end
155
+ end
156
+ sleep(@queuesleep)
157
+
158
+ # if @eventQueue.length > 0
159
+
160
+
161
+ # ar = @eventQueue.pop
162
+ # time = ar[0]
163
+ # record = ar[1]
164
+ # router.emit(@tag, EventTime.new(time.to_i), record)
165
+
166
+
167
+ # puts "Main::pop before #{@eventQueue.length} #{@tag} #{time}" # #{record.to_s}"
168
+ # puts "Main::pop after #{@eventQueue.length}"
169
+ # else
170
+ # end
171
+ end
172
+ # puts "Main::run end #{@eventQueue.length}"
173
+
174
+ end
175
+
176
+ private
177
+
178
+
179
+ class UdpListenerThread
180
+
181
+ def initialize(bind, port, udpQueue, tag)
182
+ @port = port
183
+ @udpQueue = udpQueue
184
+ @udp_socket = UDPSocket.new
185
+ @udp_socket.bind(bind, port)
186
+ @total = 0
187
+ @tag = tag
188
+ end
189
+
190
+ def start
191
+ @thread = Thread.new(&method(:run))
192
+ puts "UdpListenerThread::start"
193
+ end
194
+
195
+ def close
196
+ @udp_socket.close
197
+ end
198
+
199
+ def join
200
+ @thread.join
201
+ end
202
+
203
+
204
+ def run
205
+ loop do
206
+ msg, sender = @udp_socket.recvfrom(4096)
207
+ @total = @total + msg.length
208
+ # puts "UdpListenerThread::recvfrom #{msg.length} bytes for #{@total} total on UDP/#{@port}"
209
+ # log.debug "Received #{msg.length} bytes for #{@total} total"
210
+ record = {}
211
+ record["message"] = msg
212
+ record["length"] = msg.length
213
+ record["total"] = @total
214
+ record["sender"] = sender
215
+ record["port"] = @port
216
+ # time = EventTime.new()
217
+ time = Time.now.getutc
218
+ # router.emit(@tag, EventTime.new(), record)
219
+ @udpQueue << [time, record]
220
+ end
221
+ end
222
+ end # class UdpListenerThread
223
+
224
+ class ParserThread
225
+ def initialize(udpQueue, queuesleep, eventQueue, cache_ttl, definitions)
226
+ @udpQueue = udpQueue
227
+ @queuesleep = queuesleep
228
+ @eventQueue = eventQueue
229
+
230
+ @parser_v5 = NetflowipfixInput::ParserNetflowv5.new
231
+ @parser_v9 = NetflowipfixInput::ParserNetflowv9.new
232
+ @parser_v10 = NetflowipfixInput::ParserIPfixv10.new
233
+
234
+ @parser_v9.configure(cache_ttl, definitions)
235
+ @parser_v10.configure(cache_ttl, definitions)
236
+ end
237
+ def start
238
+ @thread = Thread.new(&method(:run))
239
+ puts "ParserThread::start"
240
+ end
241
+
242
+ def close
243
+ end
244
+
245
+ def join
246
+ @thread.join
247
+ end
248
+
249
+ def run
250
+ # puts "ParserThread::run start #{@udpQueue.length}"
251
+
252
+ loop do
253
+ if @udpQueue.length == 0
254
+ # puts "ParserThread::run sleep #{@queuesleep}"
255
+ sleep(@queuesleep)
256
+
257
+ else
258
+ block = method(:emit)
259
+ #block = nil
260
+ ar = @udpQueue.pop
261
+ time = ar[0]
262
+ msg = ar[1]
263
+ payload = msg["message"]
264
+ host = msg["sender"]
265
+
112
266
  version,_ = payload[0,2].unpack('n')
113
- @nbpackets += 1
114
- # nb = @nbpackets
115
- if (@debug)
116
- log.debug "Packet #{@nbpackets} with version #{version}"
117
- end
267
+ # puts "ParserThread::pop #{@udpQueue.length} v#{version}"
268
+
269
+
118
270
  case version
119
271
  when 5
120
- packet = Netflow5Packet.read(payload)
272
+ packet = NetflowipfixInput::Netflow5Packet.read(payload)
121
273
  @parser_v5.handle_v5(host, packet, block)
122
274
  when 9
123
- packet = Netflow9Packet.read(payload)
275
+ packet = NetflowipfixInput::Netflow9Packet.read(payload)
124
276
  @parser_v9.handle_v9(host, packet, block)
125
277
  when 10
126
- packet = Netflow10Packet.read(payload)
278
+ packet = NetflowipfixInput::Netflow10Packet.read(payload)
127
279
  @parser_v10.handle_v10(host, packet, block)
128
280
  else
129
- $log.warn "Unsupported Netflow version v#{version}: #{version.class}"
281
+ # $log.warn "Unsupported Netflow version v#{version}: #{version.class}"
130
282
  end # case
131
- end # def call
132
-
133
- end # class NetflowipfixInput
134
283
 
135
- class UdpHandler < Coolio::IO
136
- def initialize(io, callback)
137
- super(io)
138
- @io = io
139
- @callback = callback
140
- end # def initialize
284
+ # parent_call(time, record)
285
+ # @eventQueue << [time, record]
286
+ end
287
+ end # loop do
288
+ end # def run
289
+ def emit(time, event, host = nil)
290
+ if !host.nil?
291
+ event["host"] = host
292
+ end
293
+ @eventQueue << [time, event]
294
+ # puts "ParserThread::emit #{@eventQueue.length}"
295
+ end # def emit
141
296
 
142
- def on_readable
143
- msg, addr = @io.recvfrom_nonblock(4096)
144
- @callback.call(addr[3], msg)
145
- rescue => e
146
- log.error "unexpected error on reading from socket", error_class: e.class, error: e.message
147
- log.error_backtrace
148
- end # def on_readable
149
- end # class UdpHandler
297
+ end # class ParserThread
150
298
 
151
299
 
152
- end # module Plugin
300
+ end # class DnsCacheOuput
301
+ end # module Plugin
153
302
  end # module Fluent
154
303
 
155
-
156
-
157
-
158
-
159
-
160
- =begin
161
- =end
@@ -71,7 +71,6 @@ module Fluent
71
71
 
72
72
 
73
73
 
74
-
75
74
  def handle_v5(host, packet, block)
76
75
  packet.records.each do |flowset|
77
76
  # handle_flowset_data(host, packet, flowset, block, null, null)
@@ -111,7 +110,7 @@ module Fluent
111
110
  end # unless
112
111
 
113
112
  time = Time.at(packet.unix_sec, packet.unix_nsec / 1000).to_i # TODO: Fluent::EventTime
114
- block.call(time, record)
113
+ block.call(time, record, host)
115
114
  end # do flowset
116
115
  end # def handle_v5
117
116
 
@@ -219,7 +219,13 @@ module Fluent
219
219
  # end
220
220
  #end
221
221
 
222
- block.call(time, event)
222
+ # block.call(time, event)
223
+ # if (defined?(block)).nil?
224
+ # log.error "*** handle_flowset_data block is blank"
225
+ # else
226
+ # end
227
+ block.call(time, event, host)
228
+
223
229
  end # fields = array.read
224
230
  end # def handle_flowset_data
225
231
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-netflowipfix
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yves Desharnaus
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-08 00:00:00.000000000 Z
11
+ date: 2019-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake