diff --git a/ChangeLog b/ChangeLog index 6cb5aad5..fb43190f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -41,7 +41,7 @@ code-review and minor additions from Yaroslav Halchenko. * [..e019ab7] Multiple instances of the same action are allowed in the same jail -- use actname option to disambiguate. -ver. 0.8.9 (2013/05/XX) - wanna-be-stable +ver. 0.8.9 (2013/05/13) - wanna-be-stable ---------- Originally targeted as a bugfix release, it incorporated many new diff --git a/MANIFEST b/MANIFEST index 9ead6241..8ad73b5c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -54,6 +54,7 @@ fail2ban/tests/actiontestcase.py fail2ban/tests/servertestcase.py fail2ban/tests/sockettestcase.py fail2ban/tests/utils.py +fail2ban/tests/misctestcase.py fail2ban/tests/files/testcase01.log fail2ban/tests/files/testcase02.log fail2ban/tests/files/testcase03.log @@ -62,6 +63,26 @@ fail2ban/tests/files/testcase-usedns.log fail2ban/tests/files/logs/bsd/syslog-plain.txt fail2ban/tests/files/logs/bsd/syslog-v.txt fail2ban/tests/files/logs/bsd/syslog-vv.txt +fail2ban/tests/files/logs/apache-overflows +fail2ban/tests/files/logs/assp +fail2ban/tests/files/logs/asterisk +fail2ban/tests/files/logs/dovecot +fail2ban/tests/files/logs/exim +fail2ban/tests/files/logs/lighttpd +fail2ban/tests/files/logs/mysqld.log +fail2ban/tests/files/logs/named-refused +fail2ban/tests/files/logs/pam-generic +fail2ban/tests/files/logs/postfix +fail2ban/tests/files/logs/proftpd +fail2ban/tests/files/logs/pure-ftpd +fail2ban/tests/files/logs/roundcube-auth +fail2ban/tests/files/logs/sasl +fail2ban/tests/files/logs/sogo-auth +fail2ban/tests/files/logs/sshd +fail2ban/tests/files/logs/sshd-ddos +fail2ban/tests/files/logs/vsftpd +fail2ban/tests/files/logs/webmin-auth +fail2ban/tests/files/logs/wu-ftpd setup.py setup.cfg fail2ban/__init__.py @@ -103,6 +124,9 @@ config/filter.d/dropbear.conf config/filter.d/lighttpd-auth.conf config/filter.d/recidive.conf config/filter.d/roundcube-auth.conf +config/filter.d/assp.conf +config/filter.d/mysqld-auth.conf +config/filter.d/sogo-auth.conf config/action.d/bsd-ipfw.conf config/action.d/dummy.conf config/action.d/iptables-blocktype.conf @@ -155,3 +179,7 @@ files/cacti/README files/nagios/check_fail2ban files/nagios/f2ban.txt files/bash-completion +files/fail2ban-tmpfiles.conf +files/fail2ban.service +files/ipmasq-ZZZzzz_fail2ban.rul +files/nagios/README diff --git a/README.Solaris b/README.Solaris index 49056062..10a5f88c 100644 --- a/README.Solaris +++ b/README.Solaris @@ -71,7 +71,7 @@ OPT: Create /etc/fail2ban/fail2ban.local containing: # Fail2Ban main configuration file # -# Comments: use '#' for comment lines and ';' for inline comments +# Comments: use '#' for comment lines and ';' (following a space) for inline comments # # Changes: in most of the cases you should not modify this # file, but provide customizations in fail2ban.local file, e.g.: diff --git a/README.md b/README.md index d8e81c9e..6ea1e9b1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ / _|__ _(_) |_ ) |__ __ _ _ _ | _/ _` | | |/ /| '_ \/ _` | ' \ |_| \__,_|_|_/___|_.__/\__,_|_||_| - v0.9.0a0 2013/05/02 + v0.9.0a0 2013/05/?? ## Fail2Ban: ban hosts that cause multiple authentication errors @@ -30,8 +30,8 @@ Optional: To install, just do: - tar xvfj fail2ban-0.8.8.tar.bz2 - cd fail2ban-0.8.8 + tar xvfj fail2ban-0.8.9.tar.bz2 + cd fail2ban-0.8.9 python setup.py install This will install Fail2Ban into /usr/share/fail2ban. The executable scripts are @@ -56,7 +56,7 @@ the website: http://www.fail2ban.org Code status: ------------ -* [![tests status](https://secure.travis-ci.org/fail2ban/fail2ban.png)](https://travis-ci.org/fail2ban/fail2ban) travis-ci.org (master branch) +* [![tests status](https://secure.travis-ci.org/fail2ban/fail2ban.png?branch=master)](https://travis-ci.org/fail2ban/fail2ban) travis-ci.org (master branch) * [![Coverage Status](https://coveralls.io/repos/fail2ban/fail2ban/badge.png?branch=master)](https://coveralls.io/r/fail2ban/fail2ban) diff --git a/config/fail2ban.conf b/config/fail2ban.conf index 1888eddb..4094c8cd 100644 --- a/config/fail2ban.conf +++ b/config/fail2ban.conf @@ -1,6 +1,6 @@ # Fail2Ban main configuration file # -# Comments: use '#' for comment lines and ';' for inline comments +# Comments: use '#' for comment lines and ';' (following a space) for inline comments # # Changes: in most of the cases you should not modify this # file, but provide customizations in fail2ban.local file, e.g.: diff --git a/config/jail.conf b/config/jail.conf index af21167a..414cc101 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -3,7 +3,7 @@ # WARNING: heavily refactored in 0.9.0 release. Please review and # customize settings for your setup. # -# Comments: use '#' for comment lines and ';' for inline comments +# Comments: use '#' for comment lines and ';' (following a space) for inline comments # # Changes: in most of the cases you should not modify this # file, but provide customizations in jail.local file, diff --git a/fail2ban/helpers.py b/fail2ban/helpers.py index dba4c9d6..c0cf052e 100644 --- a/fail2ban/helpers.py +++ b/fail2ban/helpers.py @@ -17,11 +17,7 @@ # along with Fail2Ban; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# Author: Cyril Jaquier -# Author: Arturo 'Buanzo' Busleiman -# - -__author__ = "Cyril Jaquier" +__author__ = "Cyril Jaquier, Arturo 'Buanzo' Busleiman" __copyright__ = "Copyright (c) 2009 Cyril Jaquier" __license__ = "GPL" @@ -33,6 +29,12 @@ def formatExceptionInfo(): excName = cla.__name__ try: excArgs = exc.__dict__["args"] + # Assure that we always return a string, without unneeded + # 'decorations' with python <= 2.5 where args would be a tuple + if isinstance(excArgs, tuple) and len(excArgs) == 1: + excArgs = excArgs[0] + excArgs = str(excArgs) except KeyError: + # And always provide a string output excArgs = str(exc) return (excName, excArgs) diff --git a/fail2ban/server/asyncserver.py b/fail2ban/server/asyncserver.py index 86c161c9..aff33a60 100644 --- a/fail2ban/server/asyncserver.py +++ b/fail2ban/server/asyncserver.py @@ -81,8 +81,8 @@ class RequestHandler(asynchat.async_chat): self.close_when_done() def handle_error(self): - e1,e2 = helpers.formatExceptionInfo() - logSys.error("Unexpected communication error: "+e2) + e1, e2 = helpers.formatExceptionInfo() + logSys.error("Unexpected communication error: %s" % str(e2)) logSys.error(traceback.format_exc().splitlines()) self.close() diff --git a/fail2ban/server/filterpoll.py b/fail2ban/server/filterpoll.py index 3ca6ded0..305adf4e 100644 --- a/fail2ban/server/filterpoll.py +++ b/fail2ban/server/filterpoll.py @@ -104,7 +104,8 @@ class FilterPoll(FileFilter): time.sleep(self.getSleepTime()) else: time.sleep(self.getSleepTime()) - logSys.debug((self.jail and self.jail.getName() or "jailless") + + logSys.debug( + (self.jail is not None and self.jail.getName() or "jailless") + " filter terminated") return True @@ -130,7 +131,7 @@ class FilterPoll(FileFilter): self.__file404Cnt[filename] += 1 if self.__file404Cnt[filename] > 2: logSys.warning("Too many errors. Setting the jail idle") - if self.jail: + if self.jail is not None: self.jail.setIdle(True) else: logSys.warning("No jail is assigned to %s" % self) diff --git a/fail2ban/server/filterpyinotify.py b/fail2ban/server/filterpyinotify.py index 03623ddb..2296f1ca 100644 --- a/fail2ban/server/filterpyinotify.py +++ b/fail2ban/server/filterpyinotify.py @@ -23,19 +23,28 @@ __author__ = "Cyril Jaquier, Lee Clemens, Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2012 Lee Clemens, 2012 Yaroslav Halchenko" __license__ = "GPL" +import time, logging, pyinotify + from distutils.version import LooseVersion +from os.path import dirname, sep as pathsep from failmanager import FailManagerEmpty from filter import FileFilter from mytime import MyTime -import time, logging, pyinotify if not hasattr(pyinotify, '__version__') \ or LooseVersion(pyinotify.__version__) < '0.8.3': raise ImportError("Fail2Ban requires pyinotify >= 0.8.3") -from os.path import dirname, sep as pathsep +# Verify that pyinotify is functional on this system +# Even though imports -- might be dysfunctional, e.g. as on kfreebsd +try: + manager = pyinotify.WatchManager() + del manager +except Exception, e: + raise ImportError("Pyinotify is probably not functional on this system: %s" + % str(e)) # Gets the instance of the logger. logSys = logging.getLogger(__name__) diff --git a/fail2ban/server/jail.py b/fail2ban/server/jail.py index fa2a8fa5..4df4d42e 100644 --- a/fail2ban/server/jail.py +++ b/fail2ban/server/jail.py @@ -38,7 +38,7 @@ class Jail: _BACKENDS = ['pyinotify', 'gamin', 'polling'] def __init__(self, name, backend = "auto"): - self.__name = name + self.setName(name) self.__queue = Queue.Queue() self.__filter = None logSys.info("Creating new jail '%s'" % self.__name) @@ -102,6 +102,10 @@ class Jail: self.__filter = FilterPyinotify(self) def setName(self, name): + if len(name) >= 20: + logSys.warning("Jail name %r might be too long and some commands " + "might not function correctly. Please shorten" + % name) self.__name = name def getName(self): diff --git a/fail2ban/server/server.py b/fail2ban/server/server.py index 0ed6292d..e2f5892e 100644 --- a/fail2ban/server/server.py +++ b/fail2ban/server/server.py @@ -396,11 +396,12 @@ class Server: handler.flush() handler.close() except (ValueError, KeyError): # pragma: no cover - if (2,6) <= sys.version_info < (3,) or \ + # Is known to be thrown after logging was shutdown once + # with older Pythons -- seems to be safe to ignore there + # At least it was still failing on 2.6.2-0ubuntu1 (jaunty) + if (2,6,3) <= sys.version_info < (3,) or \ (3,2) <= sys.version_info: raise - # is known to be thrown after logging was shutdown once - # with older Pythons -- seems to be safe to ignore there # tell the handler to use this format hdlr.setFormatter(formatter) logger.addHandler(hdlr) diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 61101aa5..1ee5d675 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -296,6 +296,15 @@ class JailsReaderTest(unittest.TestCase): self.assertEqual(opts['socket'], '/var/run/fail2ban/fail2ban.sock') self.assertEqual(opts['pidfile'], '/var/run/fail2ban/fail2ban.pid') + configurator.getOptions() + configurator.convertToProtocol() + commands = configurator.getConfigStream() + # and there is logging information left to be passed into the + # server + self.assertEqual(commands, + [['set', 'loglevel', 3], + ['set', 'logtarget', '/var/log/fail2ban.log']]) + # and if we force change configurator's fail2ban's baseDir # there should be an error message (test visually ;) -- # otherwise just a code smoke test) diff --git a/testcases/files/logs/assp b/fail2ban/tests/files/logs/assp similarity index 100% rename from testcases/files/logs/assp rename to fail2ban/tests/files/logs/assp diff --git a/testcases/files/logs/bsd/syslog-plain.txt b/fail2ban/tests/files/logs/bsd/syslog-plain.txt similarity index 100% rename from testcases/files/logs/bsd/syslog-plain.txt rename to fail2ban/tests/files/logs/bsd/syslog-plain.txt diff --git a/testcases/files/logs/bsd/syslog-v.txt b/fail2ban/tests/files/logs/bsd/syslog-v.txt similarity index 100% rename from testcases/files/logs/bsd/syslog-v.txt rename to fail2ban/tests/files/logs/bsd/syslog-v.txt diff --git a/testcases/files/logs/bsd/syslog-vv.txt b/fail2ban/tests/files/logs/bsd/syslog-vv.txt similarity index 100% rename from testcases/files/logs/bsd/syslog-vv.txt rename to fail2ban/tests/files/logs/bsd/syslog-vv.txt diff --git a/fail2ban/tests/misctestcase.py b/fail2ban/tests/misctestcase.py new file mode 100644 index 00000000..d2e2f02b --- /dev/null +++ b/fail2ban/tests/misctestcase.py @@ -0,0 +1,169 @@ +# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*- +# vi: set ft=python sts=4 ts=4 sw=4 noet : + +# This file is part of Fail2Ban. +# +# Fail2Ban is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Fail2Ban is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Fail2Ban; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +__author__ = "Yaroslav Halchenko" +__copyright__ = "Copyright (c) 2013 Yaroslav Halchenko" +__license__ = "GPL" + +import logging +import os, sys, unittest +import tempfile +import shutil + +from glob import glob + +from utils import mbasename, TraceBack, FormatterWithTraceBack +from fail2ban.helpers import formatExceptionInfo + +class HelpersTest(unittest.TestCase): + + def testFormatExceptionInfoBasic(self): + try: + raise ValueError("Very bad exception") + except: + name, args = formatExceptionInfo() + self.assertEqual(name, "ValueError") + self.assertEqual(args, "Very bad exception") + + def testFormatExceptionConvertArgs(self): + try: + raise ValueError("Very bad", None) + except: + name, args = formatExceptionInfo() + self.assertEqual(name, "ValueError") + # might be fragile due to ' vs " + self.assertEqual(args, "('Very bad', None)") + +# based on +# http://stackoverflow.com/questions/2186525/use-a-glob-to-find-files-recursively-in-python +def recursive_glob(treeroot, pattern): + import fnmatch, os + results = [] + for base, dirs, files in os.walk(treeroot): + goodfiles = fnmatch.filter(dirs + files, pattern) + results.extend(os.path.join(base, f) for f in goodfiles) + return results + +class SetupTest(unittest.TestCase): + + def setUp(self): + setup = os.path.join(os.path.dirname(__file__), '..', 'setup.py') + self.setup = os.path.exists(setup) and setup or None + if not self.setup and sys.version_info >= (2,7): # running not out of the source + raise unittest.SkipTest( + "Seems to be running not out of source distribution" + " -- cannot locate setup.py") + + def testSetupInstallRoot(self): + if not self.setup: return # if verbose skip didn't work out + tmp = tempfile.mkdtemp() + os.system("%s %s install --root=%s >/dev/null" + % (sys.executable, self.setup, tmp)) + + def addpath(l): + return [os.path.join(tmp, x) for x in l] + + def strippath(l): + return [x[len(tmp)+1:] for x in l] + + got = strippath(sorted(glob('%s/*' % tmp))) + need = ['etc', 'usr', 'var'] + + # if anything is missing + if set(need).difference(got): + # below code was actually to print out not missing but + # rather files in 'excess'. Left in place in case we + # decide to revert to such more strict test + files = {} + for missing in set(got).difference(need): + missing_full = os.path.join(tmp, missing) + files[missing] = os.path.exists(missing_full) \ + and strippath(recursive_glob(missing_full, '*')) or None + + self.assertEqual( + got, need, + msg="Got: %s Needed: %s under %s. Files under new paths: %s" + % (got, need, tmp, files)) + + # Assure presence of some files we expect to see in the installation + for f in ('etc/fail2ban/fail2ban.conf', + 'etc/fail2ban/jail.conf'): + self.assertTrue(os.path.exists(os.path.join(tmp, f)), + msg="Can't find %s" % f) + + # clean up + shutil.rmtree(tmp) + +class TestsUtilsTest(unittest.TestCase): + + def testmbasename(self): + self.assertEqual(mbasename("sample.py"), 'sample') + self.assertEqual(mbasename("/long/path/sample.py"), 'sample') + # this one would include only the directory for the __init__ and base files + self.assertEqual(mbasename("/long/path/__init__.py"), 'path.__init__') + self.assertEqual(mbasename("/long/path/base.py"), 'path.base') + self.assertEqual(mbasename("/long/path/base"), 'path.base') + + def testTraceBack(self): + # pretty much just a smoke test since tests runners swallow all the detail + + for compress in True, False: + tb = TraceBack(compress=compress) + + def func_raise(): + raise ValueError() + + def deep_function(i): + if i: deep_function(i-1) + else: func_raise() + + try: + print deep_function(3) + except ValueError: + s = tb() + + # if we run it through 'coverage' (e.g. on travis) then we + # would get a traceback + if 'coverage' in s: + self.assertTrue('>' in s, msg="no '>' in %r" % s) + else: + self.assertFalse('>' in s, msg="'>' present in %r" % s) # There is only "fail2ban-testcases" in this case, no true traceback + self.assertTrue(':' in s, msg="no ':' in %r" % s) + + + def testFormatterWithTraceBack(self): + from StringIO import StringIO + strout = StringIO() + Formatter = FormatterWithTraceBack + + # and both types of traceback at once + fmt = ' %(tb)s | %(tbc)s : %(message)s' + logSys = logging.getLogger("fail2ban_tests") + out = logging.StreamHandler(strout) + out.setFormatter(Formatter(fmt)) + logSys.addHandler(out) + logSys.error("XXX") + + s = strout.getvalue() + self.assertTrue(s.rstrip().endswith(': XXX')) + pindex = s.index('|') + + # in this case compressed and not should be the same (?) + self.assertTrue(pindex > 10) # we should have some traceback + self.assertEqual(s[:pindex], s[pindex+1:pindex*2 + 1]) diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py index 6e07eaaf..113bd0b2 100644 --- a/fail2ban/tests/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -27,6 +27,7 @@ __license__ = "GPL" import unittest, socket, time, tempfile, os, locale from fail2ban.server.server import Server +from fail2ban.server.jail import Jail from fail2ban.exceptions import UnknownJailException TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") @@ -535,3 +536,12 @@ class TransmitterLogging(TransmitterBase): self.setGetTest("loglevel", "-1", -1) self.setGetTest("loglevel", "0", 0) self.setGetTestNOK("loglevel", "Bird") + + +class JailTests(unittest.TestCase): + + def testLongName(self): + # Just a smoke test for now + longname = "veryveryverylongname" + jail = Jail(longname) + self.assertEqual(jail.getName(), longname) diff --git a/fail2ban/tests/utils.py b/fail2ban/tests/utils.py index 37301e07..8870c349 100644 --- a/fail2ban/tests/utils.py +++ b/fail2ban/tests/utils.py @@ -65,11 +65,12 @@ class TraceBack(object): def __call__(self): ftb = traceback.extract_stack(limit=100)[:-2] - entries = [[mbasename(x[0]), str(x[1])] for x in ftb] - entries = [ e for e in entries - if not e[0] in ['unittest', 'logging.__init__' ]] + entries = [[mbasename(x[0]), dirname(x[0]), str(x[1])] for x in ftb] + entries = [ [e[0], e[2]] for e in entries + if not (e[0] in ['unittest', 'logging.__init__'] + or e[1].endswith('/unittest'))] - # lets make it more consize + # lets make it more concise entries_out = [entries[0]] for entry in entries[1:]: if entry[0] == entries_out[-1][0]: @@ -131,6 +132,7 @@ def gatherTests(regexps=None, no_network=False): from fail2ban.tests import datedetectortestcase from fail2ban.tests import actiontestcase from fail2ban.tests import sockettestcase + from fail2ban.tests import misctestcase if not regexps: # pragma: no cover tests = unittest.TestSuite() @@ -150,6 +152,7 @@ def gatherTests(regexps=None, no_network=False): # Server #tests.addTest(unittest.makeSuite(servertestcase.StartStop)) tests.addTest(unittest.makeSuite(servertestcase.Transmitter)) + tests.addTest(unittest.makeSuite(servertestcase.JailTests)) tests.addTest(unittest.makeSuite(actiontestcase.ExecuteAction)) # FailManager tests.addTest(unittest.makeSuite(failmanagertestcase.AddFailure)) @@ -162,6 +165,10 @@ def gatherTests(regexps=None, no_network=False): tests.addTest(unittest.makeSuite(clientreadertestcase.JailsReaderTest)) # CSocket and AsyncServer tests.addTest(unittest.makeSuite(sockettestcase.Socket)) + # Misc helpers + tests.addTest(unittest.makeSuite(misctestcase.HelpersTest)) + tests.addTest(unittest.makeSuite(misctestcase.SetupTest)) + tests.addTest(unittest.makeSuite(misctestcase.TestsUtilsTest)) # Filter if not no_network: diff --git a/fail2ban/version.py b/fail2ban/version.py index 10ec17ee..d268c025 100644 --- a/fail2ban/version.py +++ b/fail2ban/version.py @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Author: Cyril Jaquier -# +# __author__ = "Cyril Jaquier, Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko" diff --git a/man/fail2ban-client.1 b/man/fail2ban-client.1 index 431e690f..d7d620bc 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.40.10. -.TH FAIL2BAN-CLIENT "1" "March 2013" "fail2ban-client v0.8.8" "User Commands" +.TH FAIL2BAN-CLIENT "1" "May 2013" "fail2ban-client v0.8.9" "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.8 reads log file that contains password failure report +Fail2Ban v0.8.9 reads log file that contains password failure report and bans the corresponding IP addresses using firewall rules. .SH OPTIONS .TP @@ -62,6 +62,9 @@ server .TP \fBping\fR tests if the server is alive +.TP +\fBhelp\fR +return this output .IP LOGGING .TP diff --git a/man/fail2ban-regex.1 b/man/fail2ban-regex.1 index 09b9d6b0..a42d96d5 100644 --- a/man/fail2ban-regex.1 +++ b/man/fail2ban-regex.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.10. -.TH FAIL2BAN-REGEX "1" "March 2013" "fail2ban-regex v0.8.8" "User Commands" +.TH FAIL2BAN-REGEX "1" "May 2013" "fail2ban-regex v0.8.9" "User Commands" .SH NAME fail2ban-regex \- test Fail2ban "failregex" option .SH SYNOPSIS .B fail2ban-regex [\fIOPTIONS\fR] \fI \fR[\fIIGNOREREGEX\fR] .SH DESCRIPTION -Fail2Ban v0.8.8 reads log file that contains password failure report +Fail2Ban v0.8.9 reads log file that contains password failure report and bans the corresponding IP addresses using firewall rules. .PP This tools can test regular expressions for "fail2ban". diff --git a/man/fail2ban-server.1 b/man/fail2ban-server.1 index 3f6b013f..43e9d6d4 100644 --- a/man/fail2ban-server.1 +++ b/man/fail2ban-server.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.10. -.TH FAIL2BAN-SERVER "1" "March 2013" "fail2ban-server v0.8.8" "User Commands" +.TH FAIL2BAN-SERVER "1" "May 2013" "fail2ban-server v0.8.9" "User Commands" .SH NAME fail2ban-server \- start the server .SH SYNOPSIS .B fail2ban-server [\fIOPTIONS\fR] .SH DESCRIPTION -Fail2Ban v0.8.8 reads log file that contains password failure report +Fail2Ban v0.8.9 reads log file that contains password failure report and bans the corresponding IP addresses using firewall rules. .PP Only use this command for debugging purpose. Start the server with