fluent-plugin-netflowipfix 1.0.2 → 1.1.0
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '069c7af312866b4319eaa05bbf3a85b21dbe7284'
|
4
|
+
data.tar.gz: 347842300a58938ced6d12a552df6df416a74765
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5319acf004e86e279528485faa5ad760acaeb4b2a970aed0551a399ff34ef5b9a9692d3efd4c88072b65a76692ad96f46b19d1e84a8ede30cdce611d261cd16d
|
7
|
+
data.tar.gz: df25aa1db4ba2990a1428d99f9072c1c8f7ddd21fa9838d314d9acb218bfcd04808c9d129cc3be140508b8cf63f21550f1bffb41c6d49626f84ad5c711f4c622
|
@@ -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
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
#
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
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
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
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
|
-
|
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
|
-
|
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
|
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:
|
11
|
+
date: 2019-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|