From 9120747a0773123eb41ef55d5e131f1789e1bad5 Mon Sep 17 00:00:00 2001 From: Thuban <thuban@yeuxdelibad.net> Date: Sat, 09 Sep 2017 07:27:07 +0000 Subject: [PATCH] Merge branch 'master' into 'master' --- vilain.py | 6 +- Makefile | 8 ++ vilainreport.py | 123 +++++++++++++++++++++++++++++++++++++++++ vilain | 2 vilainreport | 11 +++ 5 files changed, 145 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 26060f0..92f620b 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # See LICENSE file for copyright and license details. # # vilain version -VERSION = 0.6 +VERSION = 0.7 # Customize below to fit your system # paths @@ -13,10 +13,14 @@ @echo installing executable file to ${DESTDIR}${PREFIX}/bin @mkdir -p ${DESTDIR}${PREFIX}/bin @cp -f vilain ${DESTDIR}${PREFIX}/bin + @cp -f vilainreport ${DESTDIR}${PREFIX}/bin @echo installing script file to ${DESTDIR}${PREFIX}/sbin @cp -f vilain.py ${DESTDIR}${PREFIX}/sbin + @cp -f vilainreport.py ${DESTDIR}${PREFIX}/sbin @chmod 755 ${DESTDIR}${PREFIX}/bin/vilain + @chmod 755 ${DESTDIR}${PREFIX}/bin/vilainreport @chmod 644 ${DESTDIR}${PREFIX}/sbin/vilain.py + @chmod 644 ${DESTDIR}${PREFIX}/sbin/vilainreport.py @echo installing init script in /etc/rc.d @cp -f vilain.rc /etc/rc.d/vilain @chmod 755 /etc/rc.d/vilain @@ -29,7 +33,9 @@ uninstall: @echo removing executable file from ${DESTDIR}${PREFIX}/bin @rm -f ${DESTDIR}${PREFIX}/bin/vilain + @rm -f ${DESTDIR}${PREFIX}/bin/vilainreport @rm -f ${DESTDIR}${PREFIX}/sbin/vilain.py + @rm -f ${DESTDIR}${PREFIX}/sbin/vilainreport.py @echo removing manual page to ${DESTDIR}${MANPREFIX}/ @rm -f ${DESTDIR}${MANPREFIX}/vilain.1 diff --git a/vilain b/vilain index d385066..9c2841c 100755 --- a/vilain +++ b/vilain @@ -1,5 +1,5 @@ #!/bin/sh -# script to launch vilain with the latest python3 version avaiable +# script to launch vilain with the latest python3 version available PYTHONVERSION=$(ls -l /usr/local/bin/python3.* |grep -Eo "3\.[0-9]" |tail -n1) PYTHON="/usr/local/bin/python$PYTHONVERSION" diff --git a/vilain.py b/vilain.py index eb3a608..082b15f 100755 --- a/vilain.py +++ b/vilain.py @@ -30,7 +30,7 @@ import time CONFIGFILE = "/etc/vilain.conf" -VERSION = "0.6" +VERSION = "0.7" vilain_table = "vilain_bruteforce" LOGFILE = "/var/log/daemon" @@ -46,7 +46,7 @@ log_handler = logging.handlers.WatchedFileHandler(LOGFILE) formatter = logging.Formatter( '%(asctime)s %(module)s:%(funcName)s:%(message)s', - '%b %d %H:%M:%S') + '%Y-%m-%d %H:%M:%S') log_handler.setFormatter(formatter) logger.addHandler(log_handler) logger.setLevel(logging.INFO) @@ -182,7 +182,7 @@ logger.info("{} detected, reason {}, count: {}, maxtries: {}".format(ip, reason, n_ip, maxtries)) if n_ip >= maxtries: ret = subprocess.call(["pfctl", "-t", self.vilain_table, "-T", "add", ip]) - logger.info("Blacklisting {}, return code:{}".format(ip, ret)) + logger.info("Blacklisting {}, reason {}, return code:{}".format(ip, reason, ret)) #for debugging, this line allow us to see if the script run until here logger.debug('ban_ips end:{}'.format(self.ip_seen_at)) diff --git a/vilainreport b/vilainreport new file mode 100644 index 0000000..7d6e7a8 --- /dev/null +++ b/vilainreport @@ -0,0 +1,11 @@ +#!/bin/sh +# script to launch vilainreport with the latest python3 version available + +PYTHONVERSION=$(ls -l /usr/local/bin/python3.* |grep -Eo "3\.[0-9]" |tail -n1) +PYTHON="/usr/local/bin/python$PYTHONVERSION" +if [ -x $PYTHON ]; then + $PYTHON /usr/local/sbin/vilainreport.py +else + echo "Error : no python3 executable found" +fi +exit diff --git a/vilainreport.py b/vilainreport.py new file mode 100644 index 0000000..5a259dd --- /dev/null +++ b/vilainreport.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +# -*- coding:Utf-8 -*- + +import re +import sys + +pattern = '(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+).*Blacklisting (\d+\.\d+\.\d+\.\d+), reason (.*), return' +regex = re.compile(pattern) + + +class CounterDict: + + def __init__(self): + self._counters = dict() + + def inc(self, k): + v = self._counters.get(k, 0) + 1 + self._counters[k] = v + + def get(self, k): + return self._counters.get(k, 0) + + def keys(self): + return self._counters.keys() + + def reset(self): + self._counters = dict() + + def topitems(self): + return sorted(self._counters.items(), key=lambda x: x[1], reverse=True) + + +class Value: + + def __init__(self): + self._value = "" + + def __str__(self): + return self._value + + def __eq__(self, other): + return str(self._value) == str(other) + + def set(self, value): + self._value = value + + +last_day = Value() + +# daily counters: key is reason +dcounters = CounterDict() + +# global counters: key is reason +gcounters = CounterDict() + +# hourly counters: key is hour +hcounters = CounterDict() + +# top counters: key is IP +tcounters = CounterDict() + + +def plural(noun, count): + if count > 1: + return noun + "s" + else: + return noun + + +def process(m): + current_day = m.group(1) + "-" + m.group(2) + "-" + m.group(3) + current_hour = m.group(4) + full_time = m.group(4) + ":" + m.group(5) + ":" + m.group(6) + ip = m.group(7) + reason = m.group(8) + + # new day + #print("({})-({}) => {}".format(last_day, current_day, last_day == current_day)) + if last_day != current_day: + # display day counters + sys.stdout.write("\n") + for reason in dcounters.keys(): + count = dcounters.get(reason) + sys.stdout.write("Probe '{}': {} {}\n".format(reason, count, plural("attack", count))) + last_day.set(current_day) + dcounters.reset() + sys.stdout.write("\n### Date {}\n".format(current_day)) + + # output current line + sys.stdout.write("{} blacklist IP {} ({})\n".format(full_time, ip, reason)) + + # increment counters + dcounters.inc(reason) + gcounters.inc(reason) + hcounters.inc(current_hour) + tcounters.inc(ip) + + +# parse stdin +for line in sys.stdin: + match = regex.match(line) + if match: + process(match) + +# output counters +sys.stdout.write("\n") +for reason in dcounters.keys(): + sys.stdout.write("Probe '{}' : {} attacks\n".format(reason, dcounters.get(reason))) + +sys.stdout.write("\n### Attacks per probe\n") +for k in gcounters.keys(): + count = gcounters.get(k) + sys.stdout.write("Probe '{}': {} {} \n".format(k, count, plural("attack", count))) + +sys.stdout.write("\n### Hourly repartition\n") +for k in sorted(hcounters.keys()): + sys.stdout.write("Hour {} - {:02d}: {}\n".format(k, int(k) + 1, hcounters.get(k))) + +sys.stdout.write("\n### Top attackers\n") +for k, v in tcounters.topitems(): + if v < 2: + break + sys.stdout.write("IP {:16}: {}\n".format(k, v)) -- Gitblit v1.9.3