diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index 053ab60d..9fa2eb4b 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -361,25 +361,25 @@ class Actions(JailThread, Mapping): aInfo["failures"] = bTicket.getAttempt() aInfo["time"] = bTicket.getTime() aInfo["matches"] = "\n".join(bTicket.getMatches()) - btime = bTicket.getBanTime(self.__banManager.getBanTime()); + btime = bTicket.getBanTime(self.__banManager.getBanTime()) if self._jail.database is not None: - aInfo["ipmatches"] = lambda: "\n".join( - self._jail.database.getBansMerged( - ip=ip).getMatches()) - aInfo["ipjailmatches"] = lambda: "\n".join( - self._jail.database.getBansMerged( - ip=ip, jail=self._jail).getMatches()) - aInfo["ipfailures"] = lambda: "\n".join( - self._jail.database.getBansMerged( - ip=ip).getAttempt()) - aInfo["ipjailfailures"] = lambda: "\n".join( - self._jail.database.getBansMerged( - ip=ip, jail=self._jail).getAttempt()) + aInfo["ipmatches"] = lambda jail=self._jail: "\n".join( + jail.database.getBansMerged(ip=ip).getMatches() + ) + aInfo["ipjailmatches"] = lambda jail=self._jail: "\n".join( + jail.database.getBansMerged(ip=ip, jail=jail).getMatches() + ) + aInfo["ipfailures"] = lambda jail=self._jail: \ + jail.database.getBansMerged(ip=ip).getAttempt() + aInfo["ipjailfailures"] = lambda jail=self._jail: \ + jail.database.getBansMerged(ip=ip, jail=jail).getAttempt() try: # if not permanent, not restored and ban time was not set: if btime != -1 and not ticket.getRestored() and bTicket.getBanTime() is None: btime = self.incrBanTime(bTicket) - bTicket.setBanTime(btime); + bTicket.setBanTime(btime) + if bTicket.getRestored(): + ticket.setRestored(True) except Exception as e: logSys.error('%s', e, exc_info=logSys.getEffectiveLevel()<=logging.DEBUG) #logSys.error('%s', e, exc_info=True) @@ -393,10 +393,10 @@ class Actions(JailThread, Mapping): if self._jail.database is not None: # add to database always only after ban time was calculated an not yet already banned: # if ticked was not restored from database - put it into database: - if not ticket.getRestored() and not bTicket.getRestored(): + if not ticket.getRestored(): self._jail.database.addBan(self._jail, bTicket) logSys.notice("[%s] %sBan %s (%d # %s -> %s)" % ((self._jail.name, ('Resore ' if ticket.getRestored() else ''), - aInfo["ip"], bTicket.getBanCount()) + logtime)) + aInfo["ip"], bTicket.getBanCount()+1) + logtime)) for name, action in self._actions.iteritems(): try: action.ban(aInfo) diff --git a/fail2ban/server/database.py b/fail2ban/server/database.py index f752561c..db48e748 100644 --- a/fail2ban/server/database.py +++ b/fail2ban/server/database.py @@ -516,7 +516,7 @@ class Fail2BanDb(object): if not overalljails: query = "SELECT bancount, timeofban, bantime FROM bips" else: - query = "SELECT max(bancount), max(timeofban), max(bantime) FROM bips" + query = "SELECT sum(bancount), max(timeofban), sum(bantime) FROM bips" query += " WHERE ip = ?" queryArgs = [ip] if not overalljails and jail is not None: diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index d36474c7..70136392 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -422,6 +422,7 @@ class Filter(JailThread): # increase retry count for known (bad) ip, corresponding banCount of it (one try will count than 2, 3, 5, 9 ...) : banCount = 0 retryCount = 1 + timeOfBan = None db = self.jail.database if db is not None: try: @@ -434,13 +435,15 @@ class Filter(JailThread): except Exception as e: logSys.error('%s', e, exc_info=logSys.getEffectiveLevel()<=logging.DEBUG) #logSys.error('%s', e, exc_info=True) - try: - logSys.info( - ("[%s] Found %s - %s" % (self.jail.name, ip, datetime.datetime.fromtimestamp(unixTime).strftime("%Y-%m-%d %H:%M:%S"))) - + ((", %s # -> %s" % (banCount, retryCount)) if banCount != 1 or retryCount != 1 else '') - ) - except Exception as e: - logSys.error('%s', e, exc_info=True) + # check this ticket already known (line was already processed and in the database and will be restored from there): + if timeOfBan is not None and unixTime <= timeOfBan: + logSys.debug("Ignore line for %s before last ban %s < %s" + % (ip, unixTime, timeOfBan)) + continue + logSys.info( + ("[%s] Found %s - %s" % (self.jail.name, ip, datetime.datetime.fromtimestamp(unixTime).strftime("%Y-%m-%d %H:%M:%S"))) + + ((", %s # -> %s" % (banCount, retryCount)) if banCount != 1 or retryCount != 1 else '') + ) self.failManager.addFailure(FailTicket(ip, unixTime, lines), retryCount) ## diff --git a/fail2ban/tests/databasetestcase.py b/fail2ban/tests/databasetestcase.py index 07f80e45..dcf62b0b 100644 --- a/fail2ban/tests/databasetestcase.py +++ b/fail2ban/tests/databasetestcase.py @@ -506,5 +506,5 @@ class BanTimeIncr(unittest.TestCase): break # get max values for this ip (over all jails): for row in self.db.getBan(ip, overalljails=True): - self.assertEqual(row, (2, stime, 12000)) + self.assertEqual(row, (3, stime, 18000)) break