@@ -99,9 +99,10 @@ def parse(line)
99
99
values [ name . to_sym ] = value
100
100
}
101
101
102
- method , path = values [ :req ] . split ( ' ' )
102
+ method , path , version = values [ :req ] . split ( ' ' )
103
103
values [ :method ] = method
104
104
values [ :path ] = path
105
+ values [ :version ] = version
105
106
values [ :date ] = parse_datetime ( values [ :time ] )
106
107
107
108
values
@@ -144,16 +145,18 @@ def get(field)
144
145
145
146
class Template
146
147
147
- def initialize ( head , body , foot )
148
+ def initialize ( head , body , foot , serr )
148
149
@re_field = Regexp . new ( "\\ $[a-z]+" )
149
150
150
151
h = head || "$host\\ t$count\\ t$ua"
151
152
b = body || "$date\\ t$path\\ t$referer"
152
153
f = foot || ""
154
+ s = serr || "$host\\ t$count\\ t$ua\\ n$date\\ t$path\\ t$referer"
153
155
154
156
@head = parse_value ( h )
155
157
@body = parse_value ( b )
156
158
@foot = parse_value ( f )
159
+ @serr = parse_value ( s )
157
160
end
158
161
159
162
def parse_value ( value )
@@ -182,22 +185,26 @@ def parse_value(value)
182
185
vals
183
186
end
184
187
185
- def print_head ( ops , count , row )
188
+ def print_head ( count , row )
186
189
if @head
187
- print_row ( @head , ops , count , row )
190
+ print_row ( @head , STDOUT , count , row )
188
191
end
189
192
end
190
193
191
- def print_body ( ops , row )
192
- print_row ( @body , ops , "" , row )
194
+ def print_body ( row )
195
+ print_row ( @body , STDOUT , "" , row )
193
196
end
194
197
195
- def print_foot ( ops , count , row )
198
+ def print_foot ( count , row )
196
199
if @foot
197
- print_row ( @foot , ops , count , row )
200
+ print_row ( @foot , STDOUT , count , row )
198
201
end
199
202
end
200
203
204
+ def print_serr ( count , row )
205
+ print_row ( @serr , STDERR , count , row )
206
+ end
207
+
201
208
def print_row ( templ , ops , count , row )
202
209
templ . each do |val |
203
210
if val . instance_of? ( String )
@@ -221,6 +228,7 @@ class DetectionProcessor
221
228
222
229
attr :interval_threshold , true
223
230
attr :sequence_threshold , true
231
+ attr :notify , true
224
232
attr :exc_hosts , true
225
233
attr :exc_ua , true
226
234
attr :exc_path , true
@@ -235,6 +243,8 @@ def initialize(template)
235
243
@exc_ua = nil
236
244
@exc_path = nil
237
245
246
+ @realtime_notify = false
247
+
238
248
@pre_access_map = Hash . new
239
249
@ops = STDOUT
240
250
end
@@ -254,6 +264,10 @@ def proc(row)
254
264
if ( date_ts - ts ) <= @interval_threshold
255
265
al . push ( row )
256
266
@pre_access_map . store ( host , [ date_ts , al ] )
267
+
268
+ if @notify and al . count >= @sequence_threshold
269
+ @template . print_serr ( al . count , row )
270
+ end
257
271
else
258
272
if al . count >= @sequence_threshold
259
273
print_access ( host , al )
@@ -277,13 +291,13 @@ def finalize
277
291
def print_access ( host , al )
278
292
fl = al [ 0 ]
279
293
280
- @template . print_head ( @ops , al . count , fl )
294
+ @template . print_head ( al . count , fl )
281
295
282
296
al . each do |row |
283
- @template . print_body ( @ops , row )
297
+ @template . print_body ( row )
284
298
end
285
299
286
- @template . print_foot ( @ops , al . count , fl )
300
+ @template . print_foot ( al . count , fl )
287
301
end
288
302
end
289
303
@@ -292,12 +306,14 @@ def print_access(host, al)
292
306
def get_opts
293
307
# Settting from Arguments
294
308
295
- opts = { :parser => 'combined' , :max_interval => 3 , :min_seq => 8 }
309
+ opts = { :parser => 'combined' , :max_interval => 3 , :min_seq => 8 , :notify => false }
296
310
297
311
opt = OptionParser . new
298
312
299
313
opt . on ( '-ltsv' , 'Log type is LTSV' ) { |v | opts [ :parser ] = "ltsv" }
300
314
315
+ opt . on ( '-n' , 'notify when detecting attack' ) { |v | opts [ :notify ] = true }
316
+
301
317
opt . on ( '-s COUNT' , 'Specify minimum sequential count' ) do |count |
302
318
opts [ :min_seq ] = count . to_i
303
319
end
@@ -327,11 +343,12 @@ def main
327
343
328
344
conf = Configuration . new ( opts [ :conf_file ] )
329
345
330
- template = Template . new ( conf . get ( :head ) , conf . get ( :body ) , conf . get ( :foot ) )
346
+ template = Template . new ( conf . get ( :head ) , conf . get ( :body ) , conf . get ( :foot ) , conf . get ( :serr ) )
331
347
332
348
processor = DetectionProcessor . new ( template )
333
349
processor . interval_threshold = opts [ :max_interval ]
334
350
processor . sequence_threshold = opts [ :min_seq ]
351
+ processor . notify = opts [ :notify ]
335
352
336
353
exc_hosts = conf . get ( :exc_hosts )
337
354
if exc_hosts
@@ -340,7 +357,7 @@ def main
340
357
341
358
exc_ua = conf . get ( :exc_ua_match )
342
359
if exc_ua
343
- processor . exc_ua = Regexp . new ( exc_ua , "i" )
360
+ processor . exc_ua = Regexp . new ( exc_ua , Regexp :: IGNORECASE )
344
361
end
345
362
346
363
exc_path = conf . get ( :exc_path_match )
0 commit comments