mirror of
https://github.com/jpec/fail2ban-report.git
synced 2024-12-22 05:22:13 +01:00
basic stuff
This commit is contained in:
parent
a6037e4218
commit
5a4bc8d9ad
5 changed files with 164 additions and 0 deletions
12
README.md
12
README.md
|
@ -1,2 +1,14 @@
|
||||||
# fail2ban-report
|
# fail2ban-report
|
||||||
Fail2ban report
|
Fail2ban report
|
||||||
|
|
||||||
|
Example :
|
||||||
|
|
||||||
|
Extract fail2ban logs in log.csv :
|
||||||
|
|
||||||
|
./fail2ban-getlog log.csv
|
||||||
|
|
||||||
|
Generate report.pdf from log.csv data using GeoLite2-Country.mmdb database :
|
||||||
|
|
||||||
|
./fail2ban-report log.csv GeoLite2-Country.mmdb report.pdf
|
||||||
|
|
||||||
|
You can download GeoLite2-Country database here :
|
||||||
|
|
30
fail2ban-getlog
Executable file
30
fail2ban-getlog
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
# coding: utf-8
|
||||||
|
# Julien Pecqueur <julien@peclu.net>
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
if len(argv) != 2:
|
||||||
|
print("Usage: fail2ban-getlog <file>")
|
||||||
|
print("Extract fail2ban logs to CSV file.")
|
||||||
|
else:
|
||||||
|
F_LOG = "/var/log/fail2ban.log"
|
||||||
|
f_old = open(argv[1], "r")
|
||||||
|
old = []
|
||||||
|
for l in f_old:
|
||||||
|
old.append(l[0:-1])
|
||||||
|
f_old.close()
|
||||||
|
print(len(old), "existing line(s).")
|
||||||
|
f_in = open(F_LOG, "r")
|
||||||
|
f_out = open(argv[1], "a+")
|
||||||
|
c = 0
|
||||||
|
for l in f_in:
|
||||||
|
l = l[0:-1].split(" ")
|
||||||
|
if "Ban" in l:
|
||||||
|
l = l[-1]+";"+l[0]+";"+l[1][0:-4]
|
||||||
|
if not l in old:
|
||||||
|
f_out.write(l+"\n")
|
||||||
|
c += 1
|
||||||
|
f_in.close()
|
||||||
|
f_out.close()
|
||||||
|
print("Added", c, "new line(s).")
|
82
fail2ban-report
Executable file
82
fail2ban-report
Executable file
|
@ -0,0 +1,82 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
# coding: utf-8
|
||||||
|
# Julien Pecqueur <julien@peclu.net>
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import matplotlib
|
||||||
|
matplotlib.use('Agg')
|
||||||
|
import geoip2.database
|
||||||
|
from matplotlib.backends.backend_pdf import PdfPages
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
|
||||||
|
def load_file(file):
|
||||||
|
data = []
|
||||||
|
f = open(file)
|
||||||
|
for l in f:
|
||||||
|
ip, date, time = l.split(";")
|
||||||
|
data.append([ip, date])
|
||||||
|
return(data)
|
||||||
|
|
||||||
|
def get_nb_ban_by_date(data):
|
||||||
|
d = {}
|
||||||
|
for ip, date in data:
|
||||||
|
if date in d.keys():
|
||||||
|
d[date] += 1
|
||||||
|
else:
|
||||||
|
d[date] = 1
|
||||||
|
return(d)
|
||||||
|
|
||||||
|
def get_nb_ban_by_ip(data):
|
||||||
|
d = {}
|
||||||
|
for ip, date in data:
|
||||||
|
if ip in d.keys():
|
||||||
|
d[ip] += 1
|
||||||
|
else:
|
||||||
|
d[ip] = 1
|
||||||
|
return(d)
|
||||||
|
|
||||||
|
def get_nb_ban_by_country(data, f_country):
|
||||||
|
reader = geoip2.database.Reader(f_country)
|
||||||
|
d = {}
|
||||||
|
for ip, date in data:
|
||||||
|
response = reader.country(ip)
|
||||||
|
country = response.country.name
|
||||||
|
if country in d.keys():
|
||||||
|
d[country] += 1
|
||||||
|
else:
|
||||||
|
d[country] = 1
|
||||||
|
reader.close()
|
||||||
|
return(d)
|
||||||
|
|
||||||
|
def generate_report(f_log, f_country, f_pdf):
|
||||||
|
|
||||||
|
data = load_file(f_log)
|
||||||
|
|
||||||
|
pp = PdfPages(f_pdf)
|
||||||
|
|
||||||
|
nb_ban_by_date = get_nb_ban_by_date(data)
|
||||||
|
df = pd.DataFrame.from_dict(nb_ban_by_date, orient='index').rename(columns={0:"Bans"}).sort_index()
|
||||||
|
plot = df.plot(title="Bans by date", figsize=(10.0,4.0))
|
||||||
|
fig = plot.get_figure()
|
||||||
|
fig.savefig(pp, format='pdf')
|
||||||
|
|
||||||
|
nb_ban_by_country = get_nb_ban_by_country(data, f_country)
|
||||||
|
df = pd.DataFrame.from_dict(nb_ban_by_country, orient='index').rename(columns={0:"Bans"}).sort_values(by='Bans', ascending=True) #.query('Bans > 1')
|
||||||
|
plot = df.plot(title="Bans by country", kind='pie', subplots=True, legend=False, figsize=(10.0,10.0))
|
||||||
|
fig = plot[0].get_figure()
|
||||||
|
fig.savefig(pp, format='pdf')
|
||||||
|
|
||||||
|
nb_ban_by_ip = get_nb_ban_by_ip(data)
|
||||||
|
df = pd.DataFrame.from_dict(nb_ban_by_ip, orient='index').rename(columns={0:"Bans"}).sort_values(by='Bans', ascending=True) #.query('Bans > 1')
|
||||||
|
plot = df.plot(title="Bans by IP", kind='pie', legend=False, subplots=True, figsize=(10.0,10.0))
|
||||||
|
fig = plot[0].get_figure()
|
||||||
|
fig.savefig(pp, format='pdf')
|
||||||
|
|
||||||
|
pp.close()
|
||||||
|
|
||||||
|
if len(argv) != 4:
|
||||||
|
print("Usage: fail2ban-report <fail2ban.csv> <GeoLite2-Country.mmdb> <report.pdf>")
|
||||||
|
print("Compute fail2ban CSV file and generate PDF report.")
|
||||||
|
else:
|
||||||
|
generate_report(argv[1], argv[2], argv[3])
|
40
log.csv
Normal file
40
log.csv
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
61.41.4.26;2017-08-22;06:33:24
|
||||||
|
61.41.4.26;2017-08-22;06:45:13
|
||||||
|
61.41.4.26;2017-08-22;06:57:36
|
||||||
|
91.197.232.109;2017-08-22;07:03:14
|
||||||
|
61.41.4.26;2017-08-22;07:09:54
|
||||||
|
61.41.4.26;2017-08-22;07:22:57
|
||||||
|
61.41.4.26;2017-08-22;07:34:47
|
||||||
|
61.41.4.26;2017-08-22;07:46:39
|
||||||
|
61.41.4.26;2017-08-22;07:58:55
|
||||||
|
61.41.4.26;2017-08-22;08:10:52
|
||||||
|
61.41.4.26;2017-08-22;08:22:44
|
||||||
|
61.41.4.26;2017-08-22;08:34:33
|
||||||
|
61.41.4.26;2017-08-22;08:46:44
|
||||||
|
61.41.4.26;2017-08-22;08:58:43
|
||||||
|
61.41.4.26;2017-08-22;09:10:45
|
||||||
|
61.41.4.26;2017-08-22;09:22:26
|
||||||
|
61.41.4.26;2017-08-22;09:34:24
|
||||||
|
61.41.4.26;2017-08-22;09:46:37
|
||||||
|
61.41.4.26;2017-08-22;09:59:33
|
||||||
|
61.41.4.26;2017-08-22;10:11:24
|
||||||
|
61.41.4.26;2017-08-22;10:23:16
|
||||||
|
103.89.88.102;2017-08-22;15:00:57
|
||||||
|
103.89.88.102;2017-08-23;00:45:33
|
||||||
|
103.89.88.102;2017-08-23;00:56:12
|
||||||
|
91.197.232.109;2017-08-23;04:07:52
|
||||||
|
91.197.232.107;2017-08-23;11:03:01
|
||||||
|
91.197.232.109;2017-08-23;11:41:29
|
||||||
|
103.89.88.102;2017-08-23;16:01:43
|
||||||
|
195.154.63.133;2017-08-23;20:26:55
|
||||||
|
91.197.232.109;2017-08-23;23:50:12
|
||||||
|
103.89.88.102;2017-08-24;02:44:35
|
||||||
|
195.154.63.133;2017-08-24;03:32:24
|
||||||
|
62.210.24.228;2017-08-24;10:57:14
|
||||||
|
103.89.88.102;2017-08-24;12:38:36
|
||||||
|
103.89.88.102;2017-08-24;21:20:16
|
||||||
|
91.197.232.109;2017-08-24;23:56:20
|
||||||
|
103.207.38.211;2017-08-25;01:19:37
|
||||||
|
193.201.224.214;2017-08-25;02:26:16
|
||||||
|
103.89.88.102;2017-08-25;03:27:00
|
||||||
|
91.197.232.109;2017-08-25;03:43:36
|
|
BIN
report.pdf
Normal file
BIN
report.pdf
Normal file
Binary file not shown.
Loading…
Reference in a new issue