mirror of https://github.com/fail2ban/fail2ban
introduced new options: `dbmaxmatches` (fail2ban.conf) and `maxmatches` (jail.conf);
setting `maxmatches` and `dbmaxmatches` to 0 saves memory usage and database size (closes gh-2118).pull/2402/head
parent
1083788e70
commit
0386df0042
|
@ -68,6 +68,12 @@ dbfile = /var/lib/fail2ban/fail2ban.sqlite3
|
|||
# Values: [ SECONDS ] Default: 86400 (24hours)
|
||||
dbpurgeage = 1d
|
||||
|
||||
# Options: dbmaxmatches
|
||||
# Notes.: Number of matches stored in database per ticket (resolvable via
|
||||
# tags <ipmatches>/<ipjailmatches> in actions)
|
||||
# Values: [ INT ] Default: 10
|
||||
dbmaxmatches = 10
|
||||
|
||||
[Thread]
|
||||
|
||||
# Options: stacksize
|
||||
|
|
|
@ -69,6 +69,9 @@ findtime = 10m
|
|||
# "maxretry" is the number of failures before a host get banned.
|
||||
maxretry = 5
|
||||
|
||||
# "maxmatches" is the number of matches stored in ticket (resolvable via tag <matches> in actions).
|
||||
maxmatches = %(maxretry)s
|
||||
|
||||
# "backend" specifies the backend used to get files modification.
|
||||
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".
|
||||
# This option can be overridden in each jail as well.
|
||||
|
|
|
@ -54,6 +54,7 @@ class Fail2banReader(ConfigReader):
|
|||
["string", "logtarget", "STDERR"],
|
||||
["string", "syslogsocket", "auto"],
|
||||
["string", "dbfile", "/var/lib/fail2ban/fail2ban.sqlite3"],
|
||||
["int", "dbmaxmatches", None],
|
||||
["string", "dbpurgeage", "1d"]]
|
||||
self.__opts = ConfigReader.getOptions(self, "Definition", opts)
|
||||
if updateMainOpt:
|
||||
|
@ -73,7 +74,7 @@ class Fail2banReader(ConfigReader):
|
|||
# Also dbfile should be set before all other database options.
|
||||
# So adding order indices into items, to be stripped after sorting, upon return
|
||||
order = {"thread":0, "syslogsocket":11, "loglevel":12, "logtarget":13,
|
||||
"dbfile":50, "dbpurgeage":51}
|
||||
"dbfile":50, "dbmaxmatches":51, "dbpurgeage":51}
|
||||
stream = list()
|
||||
for opt in self.__opts:
|
||||
if opt in order:
|
||||
|
|
|
@ -93,6 +93,7 @@ class JailReader(ConfigReader):
|
|||
opts = [["bool", "enabled", False],
|
||||
["string", "backend", "auto"],
|
||||
["int", "maxretry", None],
|
||||
["int", "maxmatches", None],
|
||||
["string", "findtime", None],
|
||||
["string", "bantime", None],
|
||||
["string", "usedns", None], # be sure usedns is before all regex(s) in stream
|
||||
|
|
|
@ -443,6 +443,12 @@ class Server:
|
|||
def getUseDns(self, name):
|
||||
return self.__jails[name].filter.getUseDns()
|
||||
|
||||
def setMaxMatches(self, name, value):
|
||||
self.__jails[name].filter.failManager.maxMatches = value
|
||||
|
||||
def getMaxMatches(self, name):
|
||||
return self.__jails[name].filter.failManager.maxMatches
|
||||
|
||||
def setMaxRetry(self, name, value):
|
||||
self.__jails[name].filter.setMaxRetry(value)
|
||||
|
||||
|
|
|
@ -183,6 +183,15 @@ class Transmitter:
|
|||
else:
|
||||
if self.__quiet: return
|
||||
return db.filename
|
||||
elif name == "dbmaxmatches":
|
||||
db = self.__server.getDatabase()
|
||||
if db is None:
|
||||
logSys.msg("dbmaxmatches setting was not in effect since no db yet")
|
||||
return None
|
||||
else:
|
||||
db.maxMatches = int(command[1])
|
||||
if self.__quiet: return
|
||||
return db.maxMatches
|
||||
elif name == "dbpurgeage":
|
||||
db = self.__server.getDatabase()
|
||||
if db is None:
|
||||
|
@ -310,6 +319,11 @@ class Transmitter:
|
|||
self.__server.setLogTimeZone(name, value)
|
||||
if self.__quiet: return
|
||||
return self.__server.getLogTimeZone(name)
|
||||
elif command[1] == "maxmatches":
|
||||
value = command[2]
|
||||
self.__server.setMaxMatches(name, int(value))
|
||||
if self.__quiet: return
|
||||
return self.__server.getMaxMatches(name)
|
||||
elif command[1] == "maxretry":
|
||||
value = command[2]
|
||||
self.__server.setMaxRetry(name, int(value))
|
||||
|
@ -398,6 +412,12 @@ class Transmitter:
|
|||
return None
|
||||
else:
|
||||
return db.filename
|
||||
elif name == "dbmaxmatches":
|
||||
db = self.__server.getDatabase()
|
||||
if db is None:
|
||||
return None
|
||||
else:
|
||||
return db.maxMatches
|
||||
elif name == "dbpurgeage":
|
||||
db = self.__server.getDatabase()
|
||||
if db is None:
|
||||
|
@ -433,6 +453,8 @@ class Transmitter:
|
|||
return self.__server.getDatePattern(name)
|
||||
elif command[1] == "logtimezone":
|
||||
return self.__server.getLogTimeZone(name)
|
||||
elif command[1] == "maxmatches":
|
||||
return self.__server.getMaxMatches(name)
|
||||
elif command[1] == "maxretry":
|
||||
return self.__server.getMaxRetry(name)
|
||||
elif command[1] == "maxlines":
|
||||
|
|
|
@ -881,18 +881,20 @@ class JailsReaderTest(LogCaptureTestCase):
|
|||
self.assertTrue(
|
||||
find_set('syslogsocket') < find_set('loglevel') < find_set('logtarget')
|
||||
)
|
||||
# then dbfile should be before dbpurgeage
|
||||
# then dbfile should be before dbmaxmatches and dbpurgeage
|
||||
self.assertTrue(find_set('dbpurgeage') > find_set('dbfile'))
|
||||
self.assertTrue(find_set('dbmaxmatches') > find_set('dbfile'))
|
||||
|
||||
# and there is logging information left to be passed into the
|
||||
# server
|
||||
self.assertSortedEqual(commands,
|
||||
[['set', 'dbfile',
|
||||
'/var/lib/fail2ban/fail2ban.sqlite3'],
|
||||
['set', 'dbpurgeage', '1d'],
|
||||
['set', 'loglevel', "INFO"],
|
||||
['set', 'logtarget', '/var/log/fail2ban.log'],
|
||||
['set', 'syslogsocket', 'auto']])
|
||||
self.assertSortedEqual(commands,[
|
||||
['set', 'syslogsocket', 'auto'],
|
||||
['set', 'loglevel', "INFO"],
|
||||
['set', 'logtarget', '/var/log/fail2ban.log'],
|
||||
['set', 'dbfile', '/var/lib/fail2ban/fail2ban.sqlite3'],
|
||||
['set', 'dbmaxmatches', 10],
|
||||
['set', 'dbpurgeage', '1d'],
|
||||
])
|
||||
|
||||
# and if we force change configurator's fail2ban's baseDir
|
||||
# there should be an error message (test visually ;) --
|
||||
|
|
|
@ -179,6 +179,7 @@ def _start_params(tmp, use_stock=False, use_stock_cfg=None,
|
|||
"pidfile = " + pjoin(tmp, "f2b.pid"),
|
||||
"backend = polling",
|
||||
"dbfile = " + db,
|
||||
"dbmaxmatches = 100",
|
||||
"dbpurgeage = 1d",
|
||||
"",
|
||||
)
|
||||
|
|
|
@ -374,6 +374,12 @@ class Transmitter(TransmitterBase):
|
|||
self.assertLogged("Ban 192.0.2.2", wait=True)
|
||||
self.assertNotLogged("Ban 192.0.2.1")
|
||||
|
||||
def testJailMaxMatches(self):
|
||||
self.setGetTest("maxmatches", "5", 5, jail=self.jailName)
|
||||
self.setGetTest("maxmatches", "2", 2, jail=self.jailName)
|
||||
self.setGetTest("maxmatches", "-2", -2, jail=self.jailName)
|
||||
self.setGetTestNOK("maxmatches", "Duck", jail=self.jailName)
|
||||
|
||||
def testJailMaxRetry(self):
|
||||
self.setGetTest("maxretry", "5", 5, jail=self.jailName)
|
||||
self.setGetTest("maxretry", "2", 2, jail=self.jailName)
|
||||
|
|
Loading…
Reference in New Issue