diff --git a/config/jail.conf b/config/jail.conf index 1ee0e08c..361ea758 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -60,15 +60,17 @@ before = paths-debian.conf # "bantimeextra.maxtime" is the max number of seconds using the ban time can reach (don't grows further) #bantimeextra.maxtime = 24*60*60 -# "bantimeextra.factor" is a coefficient to calculate exponent growing of the formula, -# for formula solution by default value of factor is "2.0 / 2.885385" and with default value of formula, the ban time +# "bantimeextra.factor" is a coefficient to calculate exponent growing of the formula or common multiplier, +# default value of factor is 1 and with default value of formula, the ban time # grows by 1, 2, 4, 8, 16 ... -# for multipliers solution by default value of factor is "1" and the ban time grows by specified multipliers -# corresponding ban count only -#bantimeextra.factor = 2.0 / 2.885385 +#bantimeextra.factor = 1 -# "bantimeextra.formula" used to calculate next value of ban time; -#bantimeextra.formula = banTime * math.exp(float(banCount)*banFactor)/math.exp(1*banFactor) +# "bantimeextra.formula" used by default to calculate next value of ban time, default value bellow, +# the same ban time growing will be reached by multipliers 1, 2, 4, 8, 16, 32... +#bantimeextra.formula = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor +# +# more aggressive example of formula has the same values only for factor "2.0 / 2.885385" : +#bantimeextra.formula = ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor) # "bantimeextra.multipliers" used to calculate next value of ban time instead of formula, coresponding # previously ban count and given "bantimeextra.factor" (for multipliers default is 1); diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index 962ecd2b..9a2dfa13 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -272,14 +272,13 @@ class Actions(JailThread, Mapping): be['evmultipliers'] = [int(i) for i in (value.split(' ') if value is not None and value != '' else [])] # if we have multifiers - use it in lambda, otherwise compile and use formula within lambda multipliers = be.get('evmultipliers', []) + banFactor = eval(be.get('factor', "1")) if len(multipliers): - banFactor = eval(be.get('factor', "1")) evformula = lambda ban, banFactor=banFactor: ( ban.Time * banFactor * multipliers[ban.Count if ban.Count < len(multipliers) else -1] ) else: - banFactor = eval(be.get('factor', "2.0 / 2.885385")) - formula = be.get('formula', 'ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)') + formula = be.get('formula', 'ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor') formula = compile(formula, '~inline-conf-expr~', 'eval') evformula = lambda ban, banFactor=banFactor, formula=formula: max(ban.Time, eval(formula)) # extend lambda with max time : diff --git a/fail2ban/tests/actionstestcase.py b/fail2ban/tests/actionstestcase.py index f3a2ceae..d246c144 100644 --- a/fail2ban/tests/actionstestcase.py +++ b/fail2ban/tests/actionstestcase.py @@ -161,21 +161,29 @@ class BanTimeIncr(LogCaptureTestCase): super(BanTimeIncr, self).tearDown() os.remove(self.__tmpfilename) - def testMultipliers(self): + def testDefault(self, multipliers = None): a = self.__actions; a.setBanTimeExtra('maxtime', '24*60*60') a.setBanTimeExtra('rndtime', None) a.setBanTimeExtra('factor', None) - a.setBanTimeExtra('multipliers', '1 2 4 8 16 32 64 128 256') + # tests formulat or multipliers: + a.setBanTimeExtra('multipliers', multipliers) + # test algorithm and max time 24 hours : self.assertEqual( [a.calcBanTime(600, i) for i in xrange(1, 11)], [1200, 2400, 4800, 9600, 19200, 38400, 76800, 86400, 86400, 86400] ) # with extra large max time (30 days): a.setBanTimeExtra('maxtime', '30*24*60*60') + # using formula the ban time grows always, but using multipliers the growing will stops with last one: + arr = [1200, 2400, 4800, 9600, 19200, 38400, 76800, 153600, 307200, 614400] + if multipliers is not None: + multcnt = len(multipliers.split(' ')) + if multcnt < 11: + arr = arr[0:multcnt-1] + ([arr[multcnt-2]] * (11-multcnt)) self.assertEqual( [a.calcBanTime(600, i) for i in xrange(1, 11)], - [1200, 2400, 4800, 9600, 19200, 38400, 76800, 153600, 153600, 153600] + arr ) a.setBanTimeExtra('maxtime', '24*60*60') # change factor : @@ -184,6 +192,12 @@ class BanTimeIncr(LogCaptureTestCase): [a.calcBanTime(600, i) for i in xrange(1, 11)], [2400, 4800, 9600, 19200, 38400, 76800, 86400, 86400, 86400, 86400] ) + # factor is float : + a.setBanTimeExtra('factor', '1.33'); + self.assertEqual( + [int(a.calcBanTime(600, i)) for i in xrange(1, 11)], + [1596, 3192, 6384, 12768, 25536, 51072, 86400, 86400, 86400, 86400] + ) a.setBanTimeExtra('factor', None); # change max time : a.setBanTimeExtra('maxtime', '12*60*60') @@ -207,13 +221,21 @@ class BanTimeIncr(LogCaptureTestCase): a.setBanTimeExtra('maxtime', '24*60*60') a.setBanTimeExtra('rndtime', None) + def testMultipliers(self): + # this multipliers has the same values as default formula, we test stop growing after count 9: + self.testDefault('1 2 4 8 16 32 64 128 256') + # this multipliers has exactly the same values as default formula, test endless growing (stops by count 31 only): + self.testDefault(' '.join([str(1<