123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- from json import loads, dumps
- from json.decoder import JSONDecodeError
- import pendulum
- from subprocess import run, PIPE, CalledProcessError
- from os.path import exists, join
- from pyinotify import WatchManager, Notifier, ProcessEvent
- from pyinotify import IN_MODIFY, IN_DELETE, IN_MOVE_SELF, IN_CREATE
- import sys
- from config import log, load_config, save_config, add_block, rm_block, check_blocks
- myConfig = load_config()
- myfile = myConfig["target"]
- last_run = myConfig["last_unblock"]
- bad_users = myConfig["bad_users"]
- target = open(myfile, 'r')
- target.seek(0,2)
- WM = WatchManager()
- dirmask = IN_MODIFY | IN_DELETE | IN_MOVE_SELF | IN_CREATE
- def blocker(ip):
-
- run(["iptables", "-I", "DOCKER-USER", "-i", "eth0", "-s", ip, "-j", "DROP"], stdout=PIPE, check=True)
-
- def unblocker(ip):
-
- try:
- run(["iptables", "-D", "DOCKER-USER", "-i", "eth0", "-s", ip, "-j", "DROP"], stdout=PIPE, check=True)
- except CalledProcessError:
- pass
-
- struct = {}
- state = 0
- def is_bad(line):
- global state, struct
- if state == 0 and line.startswith("SUSPECTED"):
- _, user, at = line.split("'")
- at = at.replace(" on ", "")
- struct = {"user": user.lower(), "time": at}
- state = 1
- print(struct)
- elif state == 1 and line.startswith("Using port"):
- _, ip = line.split("[")
- ip = ip.replace("]", "")
- struct["ip"] = ip
- state = 0
- print(struct)
- return struct
- def checkup():
-
- unblocks = check_blocks()
- if unblocks:
- for ip in unblocks:
- log.info("Unblocked {0}".format(ip))
- unblocker(ip)
- rm_block(ip)
- class EventHandler(ProcessEvent):
- def process_IN_MODIFY(self, event):
- if myfile not in join(event.path, event.name):
- return
- else:
-
- for line in target.readlines():
- luser = is_bad(line.rstrip())
- if(luser):
- for ip in myconfig["good_users"]:
- if luser["ip"] == ip:
- return
- blocker(luser["ip"])
- now = pendulum.now().to_atom_string()
- log.info("Blocked {0} at {1}".format(luser["ip"], now))
- add_block(luser["ip"], now)
- def process_IN_MOVE_SELF(self, event):
- log.debug("Log file moved... continuing read on stale log!")
- def process_IN_CREATE(self, event):
- global target
- if myfile in join(event.path, event.name):
- target.close()
- target = open(myfile, 'r')
- log.debug("Log file created... Catching up!")
- for line in target.readlines():
- luser = is_bad(line.rstrip())
- if(luser):
- for ip in myconfig["good_users"]:
- if luser["ip"] == ip:
- return
- blocker(luser["ip"])
- now = pendulum.now().to_atom_string()
- log.info("Blocked {0} at {1}".format(luser["ip"], now))
- add_block(luser["ip"], now)
- target.seek(0,2)
- return
- notifier = Notifier(WM, EventHandler())
- index = myfile.rfind("/")
- WM.add_watch(myfile[:index], dirmask)
- last = pendulum.parse(last_run)
- while True:
- try:
- now = pendulum.now()
- if now.diff(last).in_hours() > 1:
- last = now
- checkup()
- notifier.process_events()
- if notifier.check_events():
- notifier.read_events()
- except KeyboardInterrupt:
- break
- notifier.stop()
- target.close()
- myConfig["last_unblock"] = last.to_atom_string()
- myConfig["bad_users"] = bad_users
- save_config(myConfig)
- exit(0)
|