def checkIPenabled(ip): _prefs = Prefs() _deny = _prefs.getGeneralPref('HOSTS_DENY').split(",") _allow = _prefs.getGeneralPref('HOSTS_ALLOW').split(",") # HOSTS_ALLOW is privileged to HOSTS_DENY for net in _allow: if ipaddress.ip_address(ip) in ipaddress.ip_network(net): #print("IP apriori allowed -> {}".format(ip)) return 1 for net in _deny: if ipaddress.ip_address(ip) in ipaddress.ip_network(net): #print("IP apriori denied -> {}".format(ip)) return 0 return 2
class Journald_watcher(Thread): def __init__(self, rule_list, name = "", retroactive = False, q = queue.Queue(10), loop_time = 1.0/60): print("Journald watcher [{}] initialized".format(name)) super(Journald_watcher, self).__init__() self._prefs = Prefs() self.db = Database() self.name = name self.q = q self.rules = rule_list #print(self.rules) self.retroactive = retroactive self.j = journal.Reader() self.j.log_level(journal.LOG_INFO) try: self.j.add_match(_SYSTEMD_UNIT="{}.service".format(rule_list[0].getNameOfBelongService())) except: return if self.retroactive == False: self.j.seek_tail() self.j.get_previous() pass def run(self): #rule = None if self.rules == [] or self.rules == None: return #for rule in self.rules: #print(rule) #break #print("Journald_watcher.run -> {}".format(rule.getRulename())) #print("Processing {}".format(rule.getNameOfBelongService())) p = select.poll() p.register(self.j, self.j.get_events()) if self.retroactive == True: # Send a message to journald to generate a I/O traffic # so that poll catches events in the past without having # to wait for journal.APPEND to occur naturally. journal.send("GGH") # Inspiration taken from https://yalis.fr/git/yves/pyruse/src/branch/master/pyruse/main.py # In accordance with § 31 odst. 1 písm. a) zákona č. 121/2000 Sb., autorský zákon while p.poll(): #print(self.j.process()) if self.j.process() != journal.APPEND: continue for entry in self.j: if entry['MESSAGE'] != "": # Print SYSTEMD messages for debugging #print(str(entry['__REALTIME_TIMESTAMP'])+ ' ' + entry['MESSAGE']) #print() for rule in self.rules: self.processRule(rule, entry['MESSAGE']) pass def processRule(self, rule, message): #print("{} - Processing the message for the rule {} ...".format(self.name, rule.getRulename())) regexyolo = re.compile(rule.getRegex()) r1 = regexyolo.search(message) if r1 is not None: print("Rule {} -> {} triggered".format(rule.getNameOfBelongService(), rule.getRulename())) try: ipaddr = r1.group(rule.getCriteriaToDistinguish()) if checkIPenabled(ipaddr) == 1: return dictx = rule.getIpXoccurDict() ipcnt = dictx.get(ipaddr, 0) # 0 is the default value if key does not exist #print("ipaddr {} / {}".format(ipaddr, ipcnt)) rule.updateIpXoccur(ipaddr, ipcnt + 1) except: pass # Sanction maybe? self.sanctionner(rule) def sanctionner(self, rule): threshold_count = rule.getThresholdCount() if rule.getThresholdCount() != None else self._prefs.getGeneralPref('THRESHOLDCOUNT') tempAction = rule.getAction() tempAntiaction = rule.getAntiaction() for element, cnt in rule.getIpXoccurDict().items(): if checkIPenabled(element) == 0 or cnt >= int(threshold_count): #print("Threshold count -> {}".format(threshold_count)) #print("OccurenceCount after this read -> {}".format(cnt)) # Replace CRITERIA_TO_DISTINGUISH group placeholder in Regex if tempAction != None: replaced1 = re.sub(rule.getCriteriaToDistinguish(), str(element), tempAction) rule.setAction(replaced1) # check if such a tuple (rule,distingueur) is already in database # if it is, we do not want to apply ACTION and ANTIACTION again # nor we want to log this event to events table, only eventlog if self._prefs.getGeneralPref('DO_NOT_DUPLICATE').lower() == 'true': if self.db.checkDistingueurDetectedForRule(element, rule.getRulename()) == False: # Run the action, let it roll baby print("FIRST TIME") print("Executing ACTION -> {}".format(rule.getAction())) Utils.execute_action(rule.getAction()) else: print("DO_NOT_DUPLICATE is ON -> skipping ACTION") else: # Run the action, let it roll baby print("Executing ACTION -> {}".format(rule.getAction())) Utils.execute_action(rule.getAction()) if tempAntiaction != None: replaced2 = re.sub(rule.getCriteriaToDistinguish(), str(element), tempAntiaction) rule.setAntiaction(replaced2) #print(rule.getAntiaction()) # Add event to DB # Here is important if Antiaction is set. If that is the case, the event is added both to events and eventlog tables # In events table are stored only events with antiaction if self._prefs.getGeneralPref('DO_NOT_DUPLICATE').lower() == 'true': if self.db.checkDistingueurDetectedForRule(element, rule.getRulename()) == False: print("FIRST TIME") # Add event to DB events table if rule.getAntiaction() != None: self.db.addEvent(rule.getNameOfBelongService(), rule.getRulename(), element, time.asctime(), rule.getJailtime() if rule.getJailtime() != None else self._prefs.getGeneralPref('JAILTIME'), rule.getAntiaction()) else: print("DO_NOT_DUPLICATE is ON -> skipping DB store to events.") # Add event to DB eventlog table self.db.addEventlog(rule.getNameOfBelongService(), rule.getRulename(), element, time.asctime()) # We imposed the sanction, now we reset the counter # Die Strafe wird getilgt, nehehe rule.updateIpXoccur(element, 0) print("{} : OCCURCNT DICT -> {}".format(rule.getRulename(), rule.getIpXoccurDict()))