commit | author | age
|
9f3540
|
1 |
#!/usr/bin/env python3
|
Y |
2 |
# -*- coding:Utf-8 -*-
|
df69e1
|
3 |
"""
|
T |
4 |
Author : Yax https://blogduyax.madyanne.fr/
|
|
5 |
"""
|
9f3540
|
6 |
|
Y |
7 |
import re
|
|
8 |
import sys
|
df69e1
|
9 |
import socket
|
9f3540
|
10 |
|
Y |
11 |
pattern = '(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+).*Blacklisting (\d+\.\d+\.\d+\.\d+), reason (.*), return'
|
|
12 |
regex = re.compile(pattern)
|
|
13 |
|
|
14 |
|
|
15 |
class CounterDict:
|
|
16 |
|
|
17 |
def __init__(self):
|
|
18 |
self._counters = dict()
|
|
19 |
|
|
20 |
def inc(self, k):
|
|
21 |
v = self._counters.get(k, 0) + 1
|
|
22 |
self._counters[k] = v
|
|
23 |
|
|
24 |
def get(self, k):
|
|
25 |
return self._counters.get(k, 0)
|
|
26 |
|
|
27 |
def keys(self):
|
|
28 |
return self._counters.keys()
|
|
29 |
|
|
30 |
def reset(self):
|
|
31 |
self._counters = dict()
|
|
32 |
|
|
33 |
def topitems(self):
|
|
34 |
return sorted(self._counters.items(), key=lambda x: x[1], reverse=True)
|
|
35 |
|
|
36 |
|
|
37 |
class Value:
|
|
38 |
|
|
39 |
def __init__(self):
|
|
40 |
self._value = ""
|
|
41 |
|
|
42 |
def __str__(self):
|
|
43 |
return self._value
|
|
44 |
|
|
45 |
def __eq__(self, other):
|
|
46 |
return str(self._value) == str(other)
|
|
47 |
|
|
48 |
def set(self, value):
|
|
49 |
self._value = value
|
|
50 |
|
|
51 |
|
|
52 |
last_day = Value()
|
|
53 |
|
|
54 |
# daily counters: key is reason
|
|
55 |
dcounters = CounterDict()
|
|
56 |
|
|
57 |
# global counters: key is reason
|
|
58 |
gcounters = CounterDict()
|
|
59 |
|
|
60 |
# hourly counters: key is hour
|
|
61 |
hcounters = CounterDict()
|
|
62 |
|
|
63 |
# top counters: key is IP
|
|
64 |
tcounters = CounterDict()
|
|
65 |
|
|
66 |
|
|
67 |
def plural(noun, count):
|
|
68 |
if count > 1:
|
|
69 |
return noun + "s"
|
|
70 |
else:
|
|
71 |
return noun
|
|
72 |
|
|
73 |
|
|
74 |
def process(m):
|
|
75 |
current_day = m.group(1) + "-" + m.group(2) + "-" + m.group(3)
|
|
76 |
current_hour = m.group(4)
|
|
77 |
full_time = m.group(4) + ":" + m.group(5) + ":" + m.group(6)
|
|
78 |
ip = m.group(7)
|
|
79 |
reason = m.group(8)
|
|
80 |
|
|
81 |
# new day
|
|
82 |
#print("({})-({}) => {}".format(last_day, current_day, last_day == current_day))
|
|
83 |
if last_day != current_day:
|
|
84 |
# display day counters
|
|
85 |
sys.stdout.write("\n")
|
|
86 |
for reason in dcounters.keys():
|
|
87 |
count = dcounters.get(reason)
|
|
88 |
sys.stdout.write("Probe '{}': {} {}\n".format(reason, count, plural("attack", count)))
|
|
89 |
last_day.set(current_day)
|
|
90 |
dcounters.reset()
|
|
91 |
sys.stdout.write("\n### Date {}\n".format(current_day))
|
|
92 |
|
|
93 |
# output current line
|
|
94 |
sys.stdout.write("{} blacklist IP {} ({})\n".format(full_time, ip, reason))
|
|
95 |
|
|
96 |
# increment counters
|
|
97 |
dcounters.inc(reason)
|
|
98 |
gcounters.inc(reason)
|
|
99 |
hcounters.inc(current_hour)
|
|
100 |
tcounters.inc(ip)
|
|
101 |
|
|
102 |
|
|
103 |
# parse stdin
|
|
104 |
for line in sys.stdin:
|
|
105 |
match = regex.match(line)
|
|
106 |
if match:
|
|
107 |
process(match)
|
|
108 |
|
|
109 |
# output counters
|
|
110 |
sys.stdout.write("\n")
|
|
111 |
for reason in dcounters.keys():
|
|
112 |
sys.stdout.write("Probe '{}' : {} attacks\n".format(reason, dcounters.get(reason)))
|
|
113 |
|
|
114 |
sys.stdout.write("\n### Attacks per probe\n")
|
|
115 |
for k in gcounters.keys():
|
|
116 |
count = gcounters.get(k)
|
|
117 |
sys.stdout.write("Probe '{}': {} {} \n".format(k, count, plural("attack", count)))
|
|
118 |
|
|
119 |
sys.stdout.write("\n### Hourly repartition\n")
|
|
120 |
for k in sorted(hcounters.keys()):
|
|
121 |
sys.stdout.write("Hour {} - {:02d}: {}\n".format(k, int(k) + 1, hcounters.get(k)))
|
|
122 |
|
|
123 |
sys.stdout.write("\n### Top attackers\n")
|
|
124 |
for k, v in tcounters.topitems():
|
|
125 |
if v < 2:
|
|
126 |
break
|
df69e1
|
127 |
try:
|
T |
128 |
ns = socket.gethostbyaddr(k.strip())[0]
|
|
129 |
except:
|
|
130 |
ns = '?'
|
|
131 |
sys.stdout.write("IP {:16}: {} - {}\n".format(k, v, ns))
|