From bf5f46c3d597c3914ba8fa138e172aa5db10ede2 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Wed, 30 Jan 2013 19:57:03 +0000 Subject: [PATCH 01/79] Warn if config file present but unreadable --- client/configreader.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/configreader.py b/client/configreader.py index 063484e8..e435b254 100644 --- a/client/configreader.py +++ b/client/configreader.py @@ -59,6 +59,16 @@ class ConfigReader(SafeConfigParserWithIncludes): bConf = basename + ".conf" bLocal = basename + ".local" if os.path.exists(bConf) or os.path.exists(bLocal): + if not os.access(bConf, os.R_OK) and not os.access(bLocal, os.R_OK): + logSys.warning( + "Unable to read either \"%s\" or \"%s\"" % (bConf, bLocal)) + return False + elif os.path.exists(bConf) and not os.access(bConf, os.R_OK): + logSys.warning( + "\"%s\" read, but unable to read \"%s\"" % (bLocal, bConf)) + elif os.path.exists(bLocal) and not os.access(bLocal, os.R_OK): + logSys.warning( + "\"%s\" read, but unable to read \"%s\"" % (bConf, bLocal)) SafeConfigParserWithIncludes.read(self, [bConf, bLocal]) return True else: From 9c2e0cbbc86569108fd729c9710e42b96b1c03fa Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Thu, 31 Jan 2013 18:36:23 +0000 Subject: [PATCH 02/79] Fix up for warning/error for inaccessible config files --- client/configreader.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client/configreader.py b/client/configreader.py index e435b254..4e783ebb 100644 --- a/client/configreader.py +++ b/client/configreader.py @@ -60,8 +60,13 @@ class ConfigReader(SafeConfigParserWithIncludes): bLocal = basename + ".local" if os.path.exists(bConf) or os.path.exists(bLocal): if not os.access(bConf, os.R_OK) and not os.access(bLocal, os.R_OK): - logSys.warning( - "Unable to read either \"%s\" or \"%s\"" % (bConf, bLocal)) + if os.path.exists(bConf) and not os.path.exists(bLocal): + logSys.error("Unable to read \"%s\" " % bConf) + elif os.path.exists(bLocal) and not os.path.exists(bConf): + logSys.error("Unable to read \"%s\" " % bLocal) + else: + logSys.error( + "Unable to read \"%s\" and \"%s\"" % (bConf, bLocal)) return False elif os.path.exists(bConf) and not os.access(bConf, os.R_OK): logSys.warning( From 52f952e6454d12fbe31dbd53bf2220c8b7658610 Mon Sep 17 00:00:00 2001 From: ArndRa Date: Mon, 11 Feb 2013 17:14:29 +0100 Subject: [PATCH 03/79] Update config/jail.conf Update to use the new sogo-auth filter --- config/jail.conf | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/config/jail.conf b/config/jail.conf index 1817ebd5..215e5b9a 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -201,6 +201,20 @@ filter = roundcube-auth action = iptables[name=RoundCube, port="http,https"] logpath = /var/log/roundcube/userlogins + +# Monitor SOGo groupware server + +[sogo-iptables] + +enabled = false +filter = sogo-auth +port = http, https +# without proxy this would be: +# port = 20000 + +action = iptables[name=SOGo, port="http,https"] +logpath = /var/log/sogo/sogo.log + # Ban attackers that try to use PHP's URL-fopen() functionality # through GET/POST variables. - Experimental, with more than a year # of usage in production environments. From 35bf84abadfc633e33a36bdcb32586f652fdadf3 Mon Sep 17 00:00:00 2001 From: ArndRa Date: Mon, 11 Feb 2013 08:19:48 -0800 Subject: [PATCH 04/79] Create sogo-auth.conf Regexp works with SOGo 2.0.5 or newer, following new feature implemented here: http://www.sogo.nu/bugs/view.php?id=2229 --- config/filter.d/sogo-auth.conf | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 config/filter.d/sogo-auth.conf diff --git a/config/filter.d/sogo-auth.conf b/config/filter.d/sogo-auth.conf new file mode 100644 index 00000000..e4d29c23 --- /dev/null +++ b/config/filter.d/sogo-auth.conf @@ -0,0 +1,19 @@ +# /etc/fail2ban/filter.d/sogo.conf +# +# Fail2Ban configuration file +# By Arnd Brandes +# SOGo +# + +[Definition] +# Option: failregex +# Filter Ban in /var/log/sogo/sogo.log +# Note: the error log may contain multiple hosts, whereas the first one +# is the client and all others are poxys. We match the first one, only + +failregex = Login from '.*' for user '.*' might not have worked + +# Option: ignoreregex +# Notes.: regex to ignore. If this regex matches, the line is ignored. +# Values: TEXT +# From 6cd358ee95dbeef5a07af25ee028df5cfe543731 Mon Sep 17 00:00:00 2001 From: ArndRa Date: Tue, 12 Feb 2013 10:45:37 +0100 Subject: [PATCH 05/79] Update config/filter.d/sogo-auth.conf Comment line in the top altered to fit file name. My local file was named differently... --- config/filter.d/sogo-auth.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/filter.d/sogo-auth.conf b/config/filter.d/sogo-auth.conf index e4d29c23..6a1abd3f 100644 --- a/config/filter.d/sogo-auth.conf +++ b/config/filter.d/sogo-auth.conf @@ -1,4 +1,4 @@ -# /etc/fail2ban/filter.d/sogo.conf +# /etc/fail2ban/filter.d/sogo-auth.conf # # Fail2Ban configuration file # By Arnd Brandes From 9ba27353b62bb20ae8aaeed45a274483ad67bd83 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Sun, 17 Feb 2013 17:03:23 -0500 Subject: [PATCH 06/79] NF: allow customization configuration under corresponding .d directories (Closes gh-114) Additional changes: ENH: make basedir for Config's a kwarg to the constructor ENH: improved analysis/reporting on presence/accessibility of config files. Got carried away and forgot about existing work done by Steven Hiscocks in the gh-115 -- will merge it in the next commit for the fair ack of his work Now for any X.conf configuration file we have following ways to provide customizations X.local -- read after .conf (kept for backward compatibility) X.d/ -- directory to contain additional .conf files, sorted alphabetically, e.g X.d/01_enable.conf - to enable the jail X.d/02_custom_port.conf - to change the port X could be a 'jail' or 'fail2ban' or any other configuration file in fail2ban. Mention that all files still must contain the corresponding sections (most of the time duplicating it across all of them). --- client/actionreader.py | 4 +- client/configreader.py | 70 ++++++++++++++++-------- client/fail2banreader.py | 4 +- client/filterreader.py | 4 +- client/jailreader.py | 11 ++-- client/jailsreader.py | 10 ++-- fail2ban-testcases | 4 +- testcases/clientreadertestcase.py | 89 ++++++++++++++++++++++++++++--- 8 files changed, 150 insertions(+), 46 deletions(-) diff --git a/client/actionreader.py b/client/actionreader.py index 581a1b3c..9ad1ef28 100644 --- a/client/actionreader.py +++ b/client/actionreader.py @@ -35,8 +35,8 @@ logSys = logging.getLogger("fail2ban.client.config") class ActionReader(ConfigReader): - def __init__(self, action, name): - ConfigReader.__init__(self) + def __init__(self, action, name, **kwargs): + ConfigReader.__init__(self, **kwargs) self.__file = action[0] self.__cInfo = action[1] self.__name = name diff --git a/client/configreader.py b/client/configreader.py index 063484e8..79c5b47b 100644 --- a/client/configreader.py +++ b/client/configreader.py @@ -27,7 +27,7 @@ __date__ = "$Date$" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import logging, os +import glob, logging, os from configparserinc import SafeConfigParserWithIncludes from ConfigParser import NoOptionError, NoSectionError @@ -35,36 +35,64 @@ from ConfigParser import NoOptionError, NoSectionError logSys = logging.getLogger("fail2ban.client.config") class ConfigReader(SafeConfigParserWithIncludes): + + DEFAULT_BASEDIR = '/etc/fail2ban' - BASE_DIRECTORY = "/etc/fail2ban/" - - def __init__(self): + def __init__(self, basedir=None): SafeConfigParserWithIncludes.__init__(self) + self.setBaseDir(basedir) self.__opts = None - #@staticmethod - def setBaseDir(folderName): - path = folderName.rstrip('/') - ConfigReader.BASE_DIRECTORY = path + '/' - setBaseDir = staticmethod(setBaseDir) - - #@staticmethod - def getBaseDir(): - return ConfigReader.BASE_DIRECTORY - getBaseDir = staticmethod(getBaseDir) + def setBaseDir(self, basedir): + if basedir is None: + basedir = ConfigReader.DEFAULT_BASEDIR # stock system location + if not (os.path.exists(basedir) and os.access(basedir, os.R_OK | os.X_OK)): + raise ValueError("Base configuration directory %s either does not exist " + "or is not accessible" % basedir) + self._basedir = basedir.rstrip('/') + + def getBaseDir(self): + return self._basedir def read(self, filename): - basename = ConfigReader.BASE_DIRECTORY + filename + basename = os.path.join(self._basedir, filename) logSys.debug("Reading " + basename) - bConf = basename + ".conf" - bLocal = basename + ".local" - if os.path.exists(bConf) or os.path.exists(bLocal): - SafeConfigParserWithIncludes.read(self, [bConf, bLocal]) + config_files = [ basename + ".conf", + basename + ".local" ] + + # choose only existing ones + config_files = filter(os.path.exists, config_files) + + # possible further customizations under a .conf.d directory + config_dir = basename + '.d' + if os.path.exists(config_dir): + if os.path.isdir(config_dir) and os.access(config_dir, os.X_OK | os.R_OK): + # files must carry .conf suffix as well + config_files += sorted(glob.glob('%s/*.conf' % config_dir)) + else: + logSys.warn("%s exists but not a directory or not accessible" + % config_dir) + + # check if files are accessible, warn if any is not accessible + # and remove it from the list + config_files_accessible = [] + for f in config_files: + if os.access(f, os.R_OK): + config_files_accessible.append(f) + else: + logSys.warn("%s exists but not accessible - skipping" % f) + + if len(config_files_accessible): + # at least one config exists and accessible + SafeConfigParserWithIncludes.read(self, config_files_accessible) return True else: - logSys.error(bConf + " and " + bLocal + " do not exist") + logSys.error("Found no accessible config files for %r " % filename + + (["", + "among existing ones: " + ', '.join(config_files)][bool(len(config_files))])) + return False - + ## # Read the options. # diff --git a/client/fail2banreader.py b/client/fail2banreader.py index ee097bd6..7115ec79 100644 --- a/client/fail2banreader.py +++ b/client/fail2banreader.py @@ -35,8 +35,8 @@ logSys = logging.getLogger("fail2ban.client.config") class Fail2banReader(ConfigReader): - def __init__(self): - ConfigReader.__init__(self) + def __init__(self, **kwargs): + ConfigReader.__init__(self, **kwargs) def read(self): ConfigReader.read(self, "fail2ban") diff --git a/client/filterreader.py b/client/filterreader.py index b7a72f9c..7dba3579 100644 --- a/client/filterreader.py +++ b/client/filterreader.py @@ -35,8 +35,8 @@ logSys = logging.getLogger("fail2ban.client.config") class FilterReader(ConfigReader): - def __init__(self, fileName, name): - ConfigReader.__init__(self) + def __init__(self, fileName, name, **kwargs): + ConfigReader.__init__(self, **kwargs) self.__file = fileName self.__name = name diff --git a/client/jailreader.py b/client/jailreader.py index f66dc010..ec73ce46 100644 --- a/client/jailreader.py +++ b/client/jailreader.py @@ -40,8 +40,8 @@ class JailReader(ConfigReader): actionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$") - def __init__(self, name): - ConfigReader.__init__(self) + def __init__(self, name, **kwargs): + ConfigReader.__init__(self, **kwargs) self.__name = name self.__filter = None self.__actions = list() @@ -53,7 +53,7 @@ class JailReader(ConfigReader): return self.__name def read(self): - ConfigReader.read(self, "jail") + return ConfigReader.read(self, "jail") def isEnabled(self): return self.__opts["enabled"] @@ -75,7 +75,8 @@ class JailReader(ConfigReader): if self.isEnabled(): # Read filter - self.__filter = FilterReader(self.__opts["filter"], self.__name) + self.__filter = FilterReader(self.__opts["filter"], self.__name, + basedir=self.getBaseDir()) ret = self.__filter.read() if ret: self.__filter.getOptions(self.__opts) @@ -87,7 +88,7 @@ class JailReader(ConfigReader): for act in self.__opts["action"].split('\n'): try: splitAct = JailReader.splitAction(act) - action = ActionReader(splitAct, self.__name) + action = ActionReader(splitAct, self.__name, basedir=self.getBaseDir()) ret = action.read() if ret: action.getOptions(self.__opts) diff --git a/client/jailsreader.py b/client/jailsreader.py index bedc5a3c..e1b8efa3 100644 --- a/client/jailsreader.py +++ b/client/jailsreader.py @@ -36,12 +36,12 @@ logSys = logging.getLogger("fail2ban.client.config") class JailsReader(ConfigReader): - def __init__(self): - ConfigReader.__init__(self) + def __init__(self, **kwargs): + ConfigReader.__init__(self, **kwargs) self.__jails = list() def read(self): - ConfigReader.read(self, "jail") + return ConfigReader.read(self, "jail") def getOptions(self, section = None): opts = [] @@ -49,7 +49,7 @@ class JailsReader(ConfigReader): if section: # Get the options of a specific jail. - jail = JailReader(section) + jail = JailReader(section, basedir=self.getBaseDir()) jail.read() ret = jail.getOptions() if ret: @@ -62,7 +62,7 @@ class JailsReader(ConfigReader): else: # Get the options of all jails. for sec in self.sections(): - jail = JailReader(sec) + jail = JailReader(sec, basedir=self.getBaseDir()) jail.read() ret = jail.getOptions() if ret: diff --git a/fail2ban-testcases b/fail2ban-testcases index 99fefd57..ff94cfad 100755 --- a/fail2ban-testcases +++ b/fail2ban-testcases @@ -130,8 +130,10 @@ tests.addTest(unittest.makeSuite(actiontestcase.ExecuteAction)) tests.addTest(unittest.makeSuite(failmanagertestcase.AddFailure)) # BanManager tests.addTest(unittest.makeSuite(banmanagertestcase.AddFailure)) -# ClientReader +# ClientReaders +tests.addTest(unittest.makeSuite(clientreadertestcase.ConfigReaderTest)) tests.addTest(unittest.makeSuite(clientreadertestcase.JailReaderTest)) +tests.addTest(unittest.makeSuite(clientreadertestcase.JailsReaderTest)) # Filter if not opts.no_network: diff --git a/testcases/clientreadertestcase.py b/testcases/clientreadertestcase.py index 83121345..55fb010d 100644 --- a/testcases/clientreadertestcase.py +++ b/testcases/clientreadertestcase.py @@ -27,20 +27,93 @@ __date__ = "$Date$" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import unittest +import os, shutil, tempfile, unittest +from client.configreader import ConfigReader from client.jailreader import JailReader +from client.jailsreader import JailsReader -class JailReaderTest(unittest.TestCase): +class ConfigReaderTest(unittest.TestCase): def setUp(self): """Call before every test case.""" + self.d = tempfile.mkdtemp(prefix="f2b-temp") + self.c = ConfigReader(basedir=self.d) + def tearDown(self): """Call after every test case.""" + shutil.rmtree(self.d) + + def _write(self, fname, value): + # verify if we don't need to create .d directory + if os.path.sep in fname: + d = os.path.dirname(fname) + d_ = os.path.join(self.d, d) + if not os.path.exists(d_): + os.makedirs(d_) + open("%s/%s" % (self.d, fname), "w").write(""" +[section] +option = %s +""" % value) + + def _remove(self, fname): + os.unlink("%s/%s" % (self.d, fname)) + self.assertTrue(self.c.read('c')) # we still should have some + + + def _getoption(self): + self.assertTrue(self.c.read('c')) # we got some now + return self.c.getOptions('section', [("int", 'option')])['option'] + + def testOptionalDotDDir(self): + self.assertFalse(self.c.read('c')) # nothing is there yet + self._write("c.conf", "1") + self.assertEqual(self._getoption(), 1) + self._write("c.conf", "2") # overwrite + self.assertEqual(self._getoption(), 2) + self._write("c.local", "3") # add override in .local + self.assertEqual(self._getoption(), 3) + self._write("c.d/98.conf", "998") # add 1st override in .d/ + self.assertEqual(self._getoption(), 998) + self._write("c.d/90.conf", "990") # add previously sorted override in .d/ + self.assertEqual(self._getoption(), 998) # should stay the same + self._write("c.d/99.conf", "999") # now override in a way without sorting we possibly get a failure + self.assertEqual(self._getoption(), 999) + self._remove("c.d/99.conf") + self.assertEqual(self._getoption(), 998) + self._remove("c.d/98.conf") + self.assertEqual(self._getoption(), 990) + self._remove("c.d/90.conf") + self.assertEqual(self._getoption(), 3) + self._remove("c.conf") # we allow to stay without .conf + self.assertEqual(self._getoption(), 3) + self._write("c.conf", "1") + self._remove("c.local") + self.assertEqual(self._getoption(), 1) + + +class JailReaderTest(unittest.TestCase): + + def testStockSSHJail(self): + jail = JailReader('ssh-iptables', basedir='config') # we are running tests from root project dir atm + self.assertTrue(jail.read()) + self.assertTrue(jail.getOptions()) + self.assertFalse(jail.isEnabled()) + self.assertEqual(jail.getName(), 'ssh-iptables') + + +class JailsReaderTest(unittest.TestCase): + + def testProvidingBadBasedir(self): + if not os.path.exists('/XXX'): + self.assertRaises(ValueError, JailsReader, basedir='/XXX') + + def testReadStockJailConf(self): + jails = JailsReader(basedir='config') # we are running tests from root project dir atm + self.assertTrue(jails.read()) # opens fine + self.assertTrue(jails.getOptions()) # reads fine + comm_commands = jails.convert() + # by default None of the jails is enabled and we get no + # commands to communicate to the server + self.assertEqual(comm_commands, []) - def testSplitAction(self): - action = "mail-whois[name=SSH]" - expected = ['mail-whois', {'name': 'SSH'}] - result = JailReader.splitAction(action) - self.assertEquals(expected, result) - From 2312b1d950826bebcedc0fef937afa9fb76f0602 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Sun, 17 Feb 2013 17:19:09 -0500 Subject: [PATCH 07/79] ENH: made log messages while parsing files more informative + test for inaccessible file (Closes: gh-24) --- client/configreader.py | 4 ++-- testcases/clientreadertestcase.py | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/client/configreader.py b/client/configreader.py index 79c5b47b..e1a2b69f 100644 --- a/client/configreader.py +++ b/client/configreader.py @@ -56,7 +56,7 @@ class ConfigReader(SafeConfigParserWithIncludes): def read(self, filename): basename = os.path.join(self._basedir, filename) - logSys.debug("Reading " + basename) + logSys.debug("Reading configs for %s under %s " % (basename, self._basedir)) config_files = [ basename + ".conf", basename + ".local" ] @@ -88,7 +88,7 @@ class ConfigReader(SafeConfigParserWithIncludes): return True else: logSys.error("Found no accessible config files for %r " % filename - + (["", + + (["under %s" % self.getBaseDir(), "among existing ones: " + ', '.join(config_files)][bool(len(config_files))])) return False diff --git a/testcases/clientreadertestcase.py b/testcases/clientreadertestcase.py index 55fb010d..389220ee 100644 --- a/testcases/clientreadertestcase.py +++ b/testcases/clientreadertestcase.py @@ -39,7 +39,6 @@ class ConfigReaderTest(unittest.TestCase): self.d = tempfile.mkdtemp(prefix="f2b-temp") self.c = ConfigReader(basedir=self.d) - def tearDown(self): """Call after every test case.""" shutil.rmtree(self.d) @@ -61,10 +60,19 @@ option = %s self.assertTrue(self.c.read('c')) # we still should have some - def _getoption(self): - self.assertTrue(self.c.read('c')) # we got some now + def _getoption(self, f='c'): + self.assertTrue(self.c.read(f)) # we got some now return self.c.getOptions('section', [("int", 'option')])['option'] + + def testInaccessibleFile(self): + f = os.path.join(self.d, "d.conf") # inaccessible file + self._write('d.conf', 0) + self.assertEqual(self._getoption('d'), 0) + os.chmod(f, 0) + self.assertFalse(self.c.read('d')) # should not be readable BUT present + + def testOptionalDotDDir(self): self.assertFalse(self.c.read('c')) # nothing is there yet self._write("c.conf", "1") From ec3080cba599832506723f1492de1150d19d2ca5 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Sun, 17 Feb 2013 17:21:03 -0500 Subject: [PATCH 08/79] Reincarnated removed (by mistake) test for SplitAction --- testcases/clientreadertestcase.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testcases/clientreadertestcase.py b/testcases/clientreadertestcase.py index 389220ee..d581a81f 100644 --- a/testcases/clientreadertestcase.py +++ b/testcases/clientreadertestcase.py @@ -109,6 +109,11 @@ class JailReaderTest(unittest.TestCase): self.assertFalse(jail.isEnabled()) self.assertEqual(jail.getName(), 'ssh-iptables') + def testSplitAction(self): + action = "mail-whois[name=SSH]" + expected = ['mail-whois', {'name': 'SSH'}] + result = JailReader.splitAction(action) + self.assertEquals(expected, result) class JailsReaderTest(unittest.TestCase): From 59c35bc44a175a672e084bc30511dfa3436ff052 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Fri, 1 Mar 2013 19:57:56 -0500 Subject: [PATCH 09/79] Downgrade log rotation detection message to DEBUG level from INFO. Closes: gh-129 This message useful only when debugging problems so it is more reasonable to have it suppressed otherwise --- server/filter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/filter.py b/server/filter.py index fb79fcbe..5b2b85e0 100644 --- a/server/filter.py +++ b/server/filter.py @@ -550,7 +550,7 @@ class FileContainer: stats = os.fstat(self.__handler.fileno()) # Compare hash and inode if self.__hash != myHash or self.__ino != stats.st_ino: - logSys.info("Log rotation detected for %s" % self.__filename) + logSys.debug("Log rotation detected for %s" % self.__filename) self.__hash = myHash self.__ino = stats.st_ino self.__pos = 0 From d17b415371d14f00c9b24fc3672733b6666fe345 Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 5 Mar 2013 00:02:39 +0100 Subject: [PATCH 10/79] invalid date recognition, irregular because of sorting template list (sometimes not reproducible by fail2ban-regex, cause will be not sorted) date in following log line (from nginx) will be wrong detected: 2012/10/11 02:37:17 [error] 18434#0: *947 user "test" was not found in "/www/...", client: 192.168.1.5, ... sometimes it is [correct] - 2012/10/11 (%Y/%m/%d) = 1349919861.71 sometimes it is [invalid] - 12/10/11 (%d/%m/%y) = 1349915838.06 and older as now - 1800 seconds (therefore will be not found) solution: regular expression fixed, cause date in log used always after non symbol (\W) character, so r"\d{2}/\d{2}/\d{2}" will be r"(? Date: Thu, 7 Mar 2013 13:03:49 -0500 Subject: [PATCH 11/79] refresh generated manpages (since 0.8.2 state) --- man/fail2ban-client.1 | 39 +++++++++++++++++++++++++-------------- man/fail2ban-regex.1 | 13 ++++++++----- man/fail2ban-server.1 | 13 ++++++++----- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/man/fail2ban-client.1 b/man/fail2ban-client.1 index 1bbddf09..431e690f 100644 --- a/man/fail2ban-client.1 +++ b/man/fail2ban-client.1 @@ -1,12 +1,12 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36. -.TH FAIL2BAN-CLIENT "1" "March 2008" "fail2ban-client v0.8.2" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.10. +.TH FAIL2BAN-CLIENT "1" "March 2013" "fail2ban-client v0.8.8" "User Commands" .SH NAME fail2ban-client \- configure and control the server .SH SYNOPSIS .B fail2ban-client [\fIOPTIONS\fR] \fI\fR .SH DESCRIPTION -Fail2Ban v0.8.2 reads log file that contains password failure report +Fail2Ban v0.8.8 reads log file that contains password failure report and bans the corresponding IP addresses using firewall rules. .SH OPTIONS .TP @@ -16,6 +16,9 @@ configuration directory \fB\-s\fR socket path .TP +\fB\-p\fR +pidfile path +.TP \fB\-d\fR dump configuration. For debugging .TP @@ -110,7 +113,7 @@ adds to the monitoring list of .TP \fBset dellogpath \fR -removes to the monitoring +removes from the monitoring list of .TP \fBset addfailregex \fR @@ -140,6 +143,15 @@ back for sets the number of seconds