From 72c7d8214e6a7b4cfc9068554bed33151eb7b7c3 Mon Sep 17 00:00:00 2001 From: Thuban <thuban@yeuxdelibad.net> Date: Mon, 26 Feb 2018 08:47:25 +0000 Subject: [PATCH] last updt --- vilain.py | 67 +++++++++++++++++++-------------- 1 files changed, 39 insertions(+), 28 deletions(-) diff --git a/vilain.py b/vilain.py index 6294620..44f8fdb 100755 --- a/vilain.py +++ b/vilain.py @@ -1,21 +1,22 @@ #!/usr/bin/env python3 -# -*- coding:Utf-8 -*- +# -*- coding:Utf-8 -*- """ -Author : thuban <thuban@yeuxdelibad.net> +Author : thuban <thuban@yeuxdelibad.net> Vincent <vincent.delft@gmail.com> + Yax https://blogduyax.madyanne.fr/ Licence : MIT Require : python >= 3.5 Description : Mimic fail2ban with pf for OpenBSD. Inspired from http://www.vincentdelft.be/post/post_20161106 - In pf.conf, add : + In pf.conf, add : table <vilain_bruteforce> persist - block quick from <vilain_bruteforce> + block quick from <vilain_bruteforce> - To see banned IP : + To see banned IP : pfctl -t vilain_bruteforce -T show """ @@ -24,12 +25,13 @@ import configparser import re import logging +import logging.handlers import subprocess import asyncio import time CONFIGFILE = "/etc/vilain.conf" -VERSION = "0.5" +VERSION = "0.7" vilain_table = "vilain_bruteforce" LOGFILE = "/var/log/daemon" @@ -37,12 +39,19 @@ print("Only root can use this tool") sys.exit(1) -# Configure logging +# declare logger logger = logging.getLogger(__name__) -logging.basicConfig(filename=LOGFILE, - format='%(asctime)s %(module)s:%(funcName)s:%(message)s', - datefmt='%H:%M:%S') -logger.setLevel(logging.INFO) + +def configure_logging(): + print('Log file : {}'.format(LOGFILE)) + log_handler = logging.handlers.WatchedFileHandler(LOGFILE) + formatter = logging.Formatter( + '%(asctime)s %(module)s:%(funcName)s:%(message)s', + '%Y-%m-%d %H:%M:%S') + log_handler.setFormatter(formatter) + logger.addHandler(log_handler) + logger.setLevel(logging.INFO) + # functions def readconfig(): @@ -53,11 +62,9 @@ config = configparser.ConfigParser() config.read(CONFIGFILE) - return(config) + return (config, config.defaults()) -def load_config(): - c = readconfig() - d = c.defaults() +def load_config(c, d): watch_while = int(d['watch_while']) VILAIN_TABLE = d['vilain_table'] default_maxtries = int(d['maxtries']) @@ -68,8 +75,7 @@ ignoreips = [ i[1] for i in c.items('ignoreip') if i[0] not in c.defaults()] return(watch_while, default_maxtries, vilain_table, ignoreips, sleeptime) -def load_sections(): - c = readconfig() +def load_sections(c): for s in c.sections(): if c.has_option(s,'logfile'): LOGFILE = c.get(s,'logfile') @@ -83,15 +89,15 @@ yield d class Vilain(): - def __init__(self): + def __init__(self, config, config_dict): logger.info('Start vilain version {}'.format(VERSION)) self.loop = asyncio.get_event_loop() - self.watch_while, self.default_maxtries, self.vilain_table, self.ignore_ips, self.sleeptime = load_config() + self.watch_while, self.default_maxtries, self.vilain_table, self.ignore_ips, self.sleeptime = load_config(config, config_dict) self.ip_seen_at = {} self.load_bad_ips() self.bad_ip_queue = asyncio.Queue(loop=self.loop) - for entry in load_sections(): + for entry in load_sections(config): logger.info("Start vilain for {}".format(entry)) asyncio.ensure_future(self.check_logs(entry['logfile'], entry['maxtries'], entry['regex'], entry['name'])) @@ -107,7 +113,7 @@ for res in ret.split(): ip = res.strip().decode('utf-8') logger.info('Add existing banned IPs in your pf table: {}'.format(ip)) - #we assign the counter to 1, but for sure we don't know the real value + #we assign the counter to 1, but for sure we don't know the real value self.ip_seen_at[ip]={'time':time.time(),'count':1} @@ -164,7 +170,7 @@ record time when this IP has been seen in ip_seen_at = { ip:{'time':<time>,'count':<counter} } and ban with pf """ - logger.info('ban_ips sarted') + logger.info('ban_ips started') while True: ip_item = await self.bad_ip_queue.get() logger.debug('ban_ips awake') @@ -177,7 +183,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)) @@ -185,7 +191,7 @@ """ check old ip in ip_seen_at : remove older than watch_while """ - logger.info('clean_ips sarted with sleeptime={}'.format(self.sleeptime)) + logger.info('clean_ips started with sleeptime={}'.format(self.sleeptime)) while True: await asyncio.sleep(self.watch_while) to_remove = [] @@ -202,9 +208,9 @@ -def main(): +def main(config, config_dict): os.chdir(os.path.dirname(os.path.abspath(__file__))) - v = Vilain() + v = Vilain(config, config_dict) v.start() return 0 @@ -225,11 +231,16 @@ if args.version: print("Version: ", VERSION) sys.exit(0) - main() + # read config + config, config_dict = readconfig() + logfile = config_dict.get('vilain_log', None) + if logfile: + LOGFILE = logfile + configure_logging() + main(config, config_dict) # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 - -- Gitblit v1.9.3