From ba44ff312b45502647c7ab367bcdff0a6609ac92 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Tue, 9 Sep 2014 14:55:34 +0800 Subject: [PATCH 01/14] grep IP at the start of lines I'm not sure if this regex works best, so I'm patching this single file as a sample. Don't forget to update `mail-whois-lines.conf` after this patch got merged. For the following logs, `grep '[^0-9]199.48.161.87[^0-9]'` will output nothing, while `grep '\([^0-9]\|^\)199.48.161.87[^0-9]'` works:
199.48.161.87 - - [09/Sep/2014:13:38:54 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:38:56 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:38:58 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:00 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:05 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:05 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:13 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:21 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:32 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:34 +0800] "POST /wp-login.php HTTP/1.1" 403 4674 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:34 +0800] "POST /wp-login.php HTTP/1.1" 403 168 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:34 +0800] "POST /wp-login.php HTTP/1.1" 403 168 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:35 +0800] "POST /wp-login.php HTTP/1.1" 403 168 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:35 +0800] "POST /wp-login.php HTTP/1.1" 403 168 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
199.48.161.87 - - [09/Sep/2014:13:39:35 +0800] "POST /wp-login.php HTTP/1.1" 403 168 "-" "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0" - hitsjapan.com
--- config/action.d/sendmail-whois-lines.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/action.d/sendmail-whois-lines.conf b/config/action.d/sendmail-whois-lines.conf index 270373e7..985d0048 100644 --- a/config/action.d/sendmail-whois-lines.conf +++ b/config/action.d/sendmail-whois-lines.conf @@ -26,7 +26,7 @@ actionban = printf %%b "Subject: [Fail2Ban] : banned from `uname -n` Here is more information about :\n `/usr/bin/whois || echo missing whois program`\n\n Lines containing IP: in \n - `grep '[^0-9][^0-9]' `\n\n + `grep '\([^0-9]\|^\)[^0-9]' `\n\n Regards,\n Fail2Ban" | /usr/sbin/sendmail -f From 518cc92ccc0866c1b82bedbf8b48f9a603b5c737 Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 23 Sep 2014 19:57:55 +0200 Subject: [PATCH 02/14] actions: bug fix in lambdas in checkBan, because getBansMerged could return None (purge resp. asynchronous addBan), make the logic all around more stable; test cases: extended with test to check action together with database functionality (ex.: to verify lambdas in checkBan); database: getBansMerged should work within lock, using reentrant lock (cause call of getBans inside of getBansMerged); --- fail2ban/server/actions.py | 51 ++++++++++--- fail2ban/server/database.py | 71 ++++++++++--------- fail2ban/tests/databasetestcase.py | 22 +++++- .../tests/files/action.d/action_checkainfo.py | 14 ++++ 4 files changed, 116 insertions(+), 42 deletions(-) create mode 100644 fail2ban/tests/files/action.d/action_checkainfo.py diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index c8e9c5d9..a36802bc 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -243,6 +243,44 @@ class Actions(JailThread, Mapping): logSys.debug(self._jail.name + ": action terminated") return True + def __getBansMerged(self, mi, idx): + """Helper for lamda to get bans merged once + + This function never returns None for ainfo lambdas - always a ticket (merged or single one) + and prevents any errors through merging (to guarantee ban actions will be executed). + [TODO] move merging to observer - here we could wait for merge and read already merged info from a database + + Parameters + ---------- + mi : dict + initial for lambda should contains {ip, ticket} + idx : str + key to get a merged bans : + 'all' - bans merged for all jails + 'jail' - bans merged for current jail only + + Returns + ------- + BanTicket + merged or self ticket only + """ + if idx in mi: + return mi[idx] if mi[idx] is not None else mi['ticket'] + try: + jail=self._jail + ip=mi['ip'] + mi[idx] = None + if idx == 'all': + mi[idx] = jail.database.getBansMerged(ip=ip) + elif idx == 'jail': + mi[idx] = jail.database.getBansMerged(ip=ip, jail=jail) + except Exception as e: + logSys.error( + "Failed to get %s bans merged, jail '%s': %s", + idx, jail.name, e, + exc_info=logSys.getEffectiveLevel()<=logging.DEBUG) + return mi[idx] if mi[idx] is not None else mi['ticket'] + def __checkBan(self): """Check for IP address to ban. @@ -264,14 +302,11 @@ class Actions(JailThread, Mapping): aInfo["time"] = bTicket.getTime() aInfo["matches"] = "\n".join(bTicket.getMatches()) if self._jail.database is not None: - 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() + mi4ip = lambda idx, self=self, mi={'ip':ip, 'ticket':bTicket}: self.__getBansMerged(mi, idx) + aInfo["ipmatches"] = lambda: "\n".join(mi4ip('all').getMatches()) + aInfo["ipjailmatches"] = lambda: "\n".join(mi4ip('jail').getMatches()) + aInfo["ipfailures"] = lambda: mi4ip('all').getAttempt() + aInfo["ipjailfailures"] = lambda: mi4ip('jail').getAttempt() if self.__banManager.addBanTicket(bTicket): logSys.notice("[%s] Ban %s" % (self._jail.name, aInfo["ip"])) for name, action in self._actions.iteritems(): diff --git a/fail2ban/server/database.py b/fail2ban/server/database.py index 351d1829..bbf7adad 100644 --- a/fail2ban/server/database.py +++ b/fail2ban/server/database.py @@ -27,7 +27,7 @@ import sqlite3 import json import locale from functools import wraps -from threading import Lock +from threading import RLock from .mytime import MyTime from .ticket import FailTicket @@ -123,7 +123,7 @@ class Fail2BanDb(object): def __init__(self, filename, purgeAge=24*60*60): try: - self._lock = Lock() + self._lock = RLock() self._db = sqlite3.connect( filename, check_same_thread=False, detect_types=sqlite3.PARSE_DECLTYPES) @@ -365,6 +365,10 @@ class Fail2BanDb(object): del self._bansMergedCache[(ticket.getIP(), jail)] except KeyError: pass + try: + del self._bansMergedCache[(ticket.getIP(), None)] + except KeyError: + pass #TODO: Implement data parts once arbitrary match keys completed cur.execute( "INSERT INTO bans(jail, ip, timeofban, data) VALUES(?, ?, ?, ?)", @@ -455,40 +459,41 @@ class Fail2BanDb(object): in a list. When `ip` argument passed, a single `Ticket` is returned. """ - cacheKey = None - if bantime is None or bantime < 0: - cacheKey = (ip, jail) - if cacheKey in self._bansMergedCache: - return self._bansMergedCache[cacheKey] + with self._lock: + cacheKey = None + if bantime is None or bantime < 0: + cacheKey = (ip, jail) + if cacheKey in self._bansMergedCache: + return self._bansMergedCache[cacheKey] - tickets = [] - ticket = None + tickets = [] + ticket = None - results = list(self._getBans(ip=ip, jail=jail, bantime=bantime)) - if results: - prev_banip = results[0][0] - matches = [] - failures = 0 - for banip, timeofban, data in results: - #TODO: Implement data parts once arbitrary match keys completed - if banip != prev_banip: - ticket = FailTicket(prev_banip, prev_timeofban, matches) - ticket.setAttempt(failures) - tickets.append(ticket) - # Reset variables - prev_banip = banip - matches = [] - failures = 0 - matches.extend(data['matches']) - failures += data['failures'] - prev_timeofban = timeofban - ticket = FailTicket(banip, prev_timeofban, matches) - ticket.setAttempt(failures) - tickets.append(ticket) + results = list(self._getBans(ip=ip, jail=jail, bantime=bantime)) + if results: + prev_banip = results[0][0] + matches = [] + failures = 0 + for banip, timeofban, data in results: + #TODO: Implement data parts once arbitrary match keys completed + if banip != prev_banip: + ticket = FailTicket(prev_banip, prev_timeofban, matches) + ticket.setAttempt(failures) + tickets.append(ticket) + # Reset variables + prev_banip = banip + matches = [] + failures = 0 + matches.extend(data['matches']) + failures += data['failures'] + prev_timeofban = timeofban + ticket = FailTicket(banip, prev_timeofban, matches) + ticket.setAttempt(failures) + tickets.append(ticket) - if cacheKey: - self._bansMergedCache[cacheKey] = tickets if ip is None else ticket - return tickets if ip is None else ticket + if cacheKey: + self._bansMergedCache[cacheKey] = tickets if ip is None else ticket + return tickets if ip is None else ticket @commitandrollback def purge(self, cur): diff --git a/fail2ban/tests/databasetestcase.py b/fail2ban/tests/databasetestcase.py index f0757e5b..aef7443f 100644 --- a/fail2ban/tests/databasetestcase.py +++ b/fail2ban/tests/databasetestcase.py @@ -32,18 +32,21 @@ import shutil from ..server.filter import FileContainer from ..server.mytime import MyTime from ..server.ticket import FailTicket +from ..server.actions import Actions from .dummyjail import DummyJail try: from ..server.database import Fail2BanDb except ImportError: Fail2BanDb = None +from .utils import LogCaptureTestCase TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") -class DatabaseTest(unittest.TestCase): +class DatabaseTest(LogCaptureTestCase): def setUp(self): """Call before every test case.""" + super(DatabaseTest, self).setUp() if Fail2BanDb is None and sys.version_info >= (2,7): # pragma: no cover raise unittest.SkipTest( "Unable to import fail2ban database module as sqlite is not " @@ -55,6 +58,7 @@ class DatabaseTest(unittest.TestCase): def tearDown(self): """Call after every test case.""" + super(DatabaseTest, self).tearDown() if Fail2BanDb is None: # pragma: no cover return # Cleanup @@ -267,6 +271,22 @@ class DatabaseTest(unittest.TestCase): tickets = self.db.getBansMerged(bantime=-1) self.assertEqual(len(tickets), 2) + def testActionWithDB(self): + # test action together with database functionality + self.testAddJail() # Jail required + self.jail.database = self.db; + actions = Actions(self.jail) + actions.add( + "action_checkainfo", + os.path.join(TEST_FILES_DIR, "action.d/action_checkainfo.py"), + {}) + ticket = FailTicket("1.2.3.4", MyTime.time(), ['test', 'test']) + ticket.setAttempt(5) + self.jail.putFailTicket(ticket) + actions._Actions__checkBan() + self.assertTrue(self._is_logged("ban ainfo %s, %s, %s, %s" % (True, True, True, True))) + + def testPurge(self): if Fail2BanDb is None: # pragma: no cover return diff --git a/fail2ban/tests/files/action.d/action_checkainfo.py b/fail2ban/tests/files/action.d/action_checkainfo.py new file mode 100644 index 00000000..eec9cc85 --- /dev/null +++ b/fail2ban/tests/files/action.d/action_checkainfo.py @@ -0,0 +1,14 @@ + +from fail2ban.server.action import ActionBase + +class TestAction(ActionBase): + + def ban(self, aInfo): + self._logSys.info("ban ainfo %s, %s, %s, %s", + aInfo["ipmatches"] != '', aInfo["ipjailmatches"] != '', aInfo["ipfailures"] > 0, aInfo["ipjailfailures"] > 0 + ) + + def unban(self, aInfo): + pass + +Action = TestAction From 8dbc04aa06e0cbcb951f489393e81638c150e577 Mon Sep 17 00:00:00 2001 From: sebres Date: Wed, 29 Oct 2014 13:30:24 +0100 Subject: [PATCH 03/14] Test cases fixed: testFail2BanExceptHook - use local sys.__excepthook__ to check was really executed and prevent write error in stderr. --- fail2ban/tests/servertestcase.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py index 062284f7..362f4253 100644 --- a/fail2ban/tests/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -804,7 +804,7 @@ class RegexTests(unittest.TestCase): class _BadThread(JailThread): def run(self): - int("ignore this exception -- raised for testing") + raise RuntimeError('run bad thread exception') class LoggingTests(LogCaptureTestCase): @@ -814,7 +814,13 @@ class LoggingTests(LogCaptureTestCase): self.assertEqual(testLogSys.name, "fail2ban.name") def testFail2BanExceptHook(self): + prev_exchook = sys.__excepthook__ + x = [] + sys.__excepthook__ = lambda *args: x.append(args) badThread = _BadThread() badThread.start() badThread.join() self.assertTrue(self._is_logged("Unhandled exception")) + sys.__excepthook__ = prev_exchook + self.assertEqual(len(x), 1) + self.assertEqual(x[0][0], RuntimeError) From 36abb5ed969d537bbdb5ab4959826f1ef23c2ae1 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Wed, 29 Oct 2014 13:08:51 -0400 Subject: [PATCH 04/14] BF: fix $ for % in jail.conf. Debian bug #767255 --- ChangeLog | 1 + config/jail.conf | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index ffddd52b..99480d57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,7 @@ ver. 0.9.2 (2014/XX/XXX) - wanna-be-released ----------- - Fixes: + * $ typo in jail.conf. Thanks Skibbi. Debian bug #767255 - New Features: diff --git a/config/jail.conf b/config/jail.conf index d31e70d7..d119d229 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -286,7 +286,7 @@ maxretry = 2 [apache-shellshock] port = http,https -logpath = $(apache_error_log)s +logpath = %(apache_error_log)s maxretry = 1 [nginx-http-auth] @@ -723,4 +723,4 @@ port = 2222 [portsentry] enabled = false logpath = /var/lib/portsentry/portsentry.history -maxretry = 1 \ No newline at end of file +maxretry = 1 From 46a8899f20b6513036bb62faf5d0eb7b02b0ad00 Mon Sep 17 00:00:00 2001 From: sebres Date: Wed, 29 Oct 2014 19:27:45 +0100 Subject: [PATCH 05/14] code review --- fail2ban/server/actions.py | 4 +++- fail2ban/tests/servertestcase.py | 12 +++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index a36802bc..d145f338 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -244,7 +244,7 @@ class Actions(JailThread, Mapping): return True def __getBansMerged(self, mi, idx): - """Helper for lamda to get bans merged once + """Gets bans merged once, a helper for lambda(s), prevents stop of executing action by any exception inside. This function never returns None for ainfo lambdas - always a ticket (merged or single one) and prevents any errors through merging (to guarantee ban actions will be executed). @@ -274,6 +274,8 @@ class Actions(JailThread, Mapping): mi[idx] = jail.database.getBansMerged(ip=ip) elif idx == 'jail': mi[idx] = jail.database.getBansMerged(ip=ip, jail=jail) + else: # pragma: no cover + raise ValueError("Unknown value %r for idx" % (idx,)) except Exception as e: logSys.error( "Failed to get %s bans merged, jail '%s': %s", diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py index 362f4253..e018ed2f 100644 --- a/fail2ban/tests/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -817,10 +817,12 @@ class LoggingTests(LogCaptureTestCase): prev_exchook = sys.__excepthook__ x = [] sys.__excepthook__ = lambda *args: x.append(args) - badThread = _BadThread() - badThread.start() - badThread.join() - self.assertTrue(self._is_logged("Unhandled exception")) - sys.__excepthook__ = prev_exchook + try: + badThread = _BadThread() + badThread.start() + badThread.join() + self.assertTrue(self._is_logged("Unhandled exception")) + finally: + sys.__excepthook__ = prev_exchook self.assertEqual(len(x), 1) self.assertEqual(x[0][0], RuntimeError) From 92ba5ae09c54aebd0a244fab634e301045610628 Mon Sep 17 00:00:00 2001 From: sebres Date: Wed, 29 Oct 2014 22:08:44 +0100 Subject: [PATCH 06/14] few confusing merge info helper --- fail2ban/server/actions.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index d145f338..a212aaf1 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -243,7 +243,7 @@ class Actions(JailThread, Mapping): logSys.debug(self._jail.name + ": action terminated") return True - def __getBansMerged(self, mi, idx): + def __getBansMerged(self, mi, overalljails=False): """Gets bans merged once, a helper for lambda(s), prevents stop of executing action by any exception inside. This function never returns None for ainfo lambdas - always a ticket (merged or single one) @@ -253,29 +253,28 @@ class Actions(JailThread, Mapping): Parameters ---------- mi : dict - initial for lambda should contains {ip, ticket} - idx : str - key to get a merged bans : - 'all' - bans merged for all jails - 'jail' - bans merged for current jail only + merge info, initial for lambda should contains {ip, ticket} + overalljails : bool + switch to get a merged bans : + False - (default) bans merged for current jail only + True - bans merged for all jails of current ip address Returns ------- BanTicket merged or self ticket only """ + idx = 'all' if overalljails else 'jail' if idx in mi: return mi[idx] if mi[idx] is not None else mi['ticket'] try: jail=self._jail ip=mi['ip'] mi[idx] = None - if idx == 'all': + if overalljails: mi[idx] = jail.database.getBansMerged(ip=ip) - elif idx == 'jail': + else: mi[idx] = jail.database.getBansMerged(ip=ip, jail=jail) - else: # pragma: no cover - raise ValueError("Unknown value %r for idx" % (idx,)) except Exception as e: logSys.error( "Failed to get %s bans merged, jail '%s': %s", @@ -304,11 +303,12 @@ class Actions(JailThread, Mapping): aInfo["time"] = bTicket.getTime() aInfo["matches"] = "\n".join(bTicket.getMatches()) if self._jail.database is not None: - mi4ip = lambda idx, self=self, mi={'ip':ip, 'ticket':bTicket}: self.__getBansMerged(mi, idx) - aInfo["ipmatches"] = lambda: "\n".join(mi4ip('all').getMatches()) - aInfo["ipjailmatches"] = lambda: "\n".join(mi4ip('jail').getMatches()) - aInfo["ipfailures"] = lambda: mi4ip('all').getAttempt() - aInfo["ipjailfailures"] = lambda: mi4ip('jail').getAttempt() + mi4ip = lambda overalljails=False, self=self, \ + mi={'ip':ip, 'ticket':bTicket}: self.__getBansMerged(mi, overalljails) + aInfo["ipmatches"] = lambda: "\n".join(mi4ip(True).getMatches()) + aInfo["ipjailmatches"] = lambda: "\n".join(mi4ip().getMatches()) + aInfo["ipfailures"] = lambda: mi4ip(True).getAttempt() + aInfo["ipjailfailures"] = lambda: mi4ip().getAttempt() if self.__banManager.addBanTicket(bTicket): logSys.notice("[%s] Ban %s" % (self._jail.name, aInfo["ip"])) for name, action in self._actions.iteritems(): From 01b2673e3406b770882b4c246e8f44a5582f4d6f Mon Sep 17 00:00:00 2001 From: Orion Poplawski Date: Wed, 29 Oct 2014 16:27:37 -0600 Subject: [PATCH 07/14] Use multiport for firewallcmd-new --- config/action.d/firewallcmd-new.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/action.d/firewallcmd-new.conf b/config/action.d/firewallcmd-new.conf index 9754e3f3..ac72a68a 100644 --- a/config/action.d/firewallcmd-new.conf +++ b/config/action.d/firewallcmd-new.conf @@ -10,9 +10,9 @@ before = iptables-common.conf actionstart = firewall-cmd --direct --add-chain ipv4 filter f2b- firewall-cmd --direct --add-rule ipv4 filter f2b- 1000 -j RETURN - firewall-cmd --direct --add-rule ipv4 filter 0 -m state --state NEW -p --dport -j f2b- + firewall-cmd --direct --add-rule ipv4 filter 0 -m state --state NEW -p -m multiport --dports -j f2b- -actionstop = firewall-cmd --direct --remove-rule ipv4 filter 0 -m state --state NEW -p --dport -j f2b- +actionstop = firewall-cmd --direct --remove-rule ipv4 filter 0 -m state --state NEW -p -m multiport --dports -j f2b- firewall-cmd --direct --remove-rules ipv4 filter f2b- firewall-cmd --direct --remove-chain ipv4 filter f2b- @@ -43,7 +43,7 @@ chain = INPUT_direct # success # $ firewall-cmd --direct --add-rule ipv4 filter fail2ban-name 1000 -j RETURN # success -# $ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -m state --state NEW -p tcp --dport 22 -j fail2ban-name +# $ sudo firewall-cmd --direct --add-rule ipv4 filter INPUT_direct 0 -m state --state NEW -p tcp -m multiport --dports 22 -j fail2ban-name # success # $ firewall-cmd --direct --get-chains ipv4 filter # fail2ban-name From 967485c2d00d9aff91aea535d2909deab0ed1ba4 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Wed, 29 Oct 2014 23:14:47 -0400 Subject: [PATCH 08/14] improving grepping --- ChangeLog | 2 ++ config/action.d/mail-whois-lines.conf | 2 +- config/action.d/sendmail-whois-lines.conf | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 99480d57..0e107735 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,8 @@ ver. 0.9.2 (2014/XX/XXX) - wanna-be-released - Fixes: * $ typo in jail.conf. Thanks Skibbi. Debian bug #767255 + * grep'ing for IP in *mail-whois-lines.conf should now match also + at the begginning and EOL. Thanks Dean Lee - New Features: diff --git a/config/action.d/mail-whois-lines.conf b/config/action.d/mail-whois-lines.conf index aa7d0950..5f760ac8 100644 --- a/config/action.d/mail-whois-lines.conf +++ b/config/action.d/mail-whois-lines.conf @@ -42,7 +42,7 @@ actionban = printf %%b "Hi,\n Here is more information about :\n `whois || echo missing whois program`\n\n Lines containing IP: in \n - `grep '[^0-9][^0-9]' `\n\n + `grep -E '(^|[^0-9])([^0-9]|$)' `\n\n Regards,\n Fail2Ban"|mail -s "[Fail2Ban] : banned from `uname -n`" diff --git a/config/action.d/sendmail-whois-lines.conf b/config/action.d/sendmail-whois-lines.conf index 985d0048..4169e82a 100644 --- a/config/action.d/sendmail-whois-lines.conf +++ b/config/action.d/sendmail-whois-lines.conf @@ -26,7 +26,7 @@ actionban = printf %%b "Subject: [Fail2Ban] : banned from `uname -n` Here is more information about :\n `/usr/bin/whois || echo missing whois program`\n\n Lines containing IP: in \n - `grep '\([^0-9]\|^\)[^0-9]' `\n\n + `grep -E '(^|[^0-9])([^0-9]|$)' `\n\n Regards,\n Fail2Ban" | /usr/sbin/sendmail -f From 21be98362070210fc12660370eafe2dd2e7f0b63 Mon Sep 17 00:00:00 2001 From: Orion Poplawski Date: Thu, 30 Oct 2014 16:11:34 -0600 Subject: [PATCH 09/14] ChangeLog for firewallcmd-new multiport support --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 99480d57..d2226201 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ ver. 0.9.2 (2014/XX/XXX) - wanna-be-released - New Features: - Enhancements: + * Enable multiport for firewallcmd-new action. Closes gh-834 ver. 0.9.1 (2014/10/29) - better, faster, stronger From 6dfddbcdf62553d56483d4990e84261845f46508 Mon Sep 17 00:00:00 2001 From: "Serg G. Brester" Date: Fri, 7 Nov 2014 01:21:38 +0100 Subject: [PATCH 10/14] Bug fix in formatJournalEntry, gh-851 Unhandled exception in fail2ban 0.9.1 #851 --- fail2ban/server/filtersystemd.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fail2ban/server/filtersystemd.py b/fail2ban/server/filtersystemd.py index ce89d65a..3a42f61c 100644 --- a/fail2ban/server/filtersystemd.py +++ b/fail2ban/server/filtersystemd.py @@ -167,9 +167,10 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover logelements.append(logentry['_HOSTNAME']) if logentry.get('SYSLOG_IDENTIFIER'): logelements.append(logentry['SYSLOG_IDENTIFIER']) - if logentry.get('SYSLOG_PID') or logentry.get('_PID'): - logelements[-1] += ("[%i]" % logentry.get( - 'SYSLOG_PID', logentry['_PID'])) + if logentry.get('SYSLOG_PID'): + logelements[-1] += ("[%i]" % logentry['SYSLOG_PID']) + elif logentry.get('_PID'): + logelements[-1] += ("[%i]" % logentry['_PID']) logelements[-1] += ":" elif logentry.get('_COMM'): logelements.append(logentry['_COMM']) From 9269664350656bbdbab0131754322a2a7b4a9739 Mon Sep 17 00:00:00 2001 From: Guillaume FRANCOIS Date: Wed, 12 Nov 2014 10:30:28 +0100 Subject: [PATCH 11/14] Add ignoreregex to avoid warning on start --- config/filter.d/named-refused.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/filter.d/named-refused.conf b/config/filter.d/named-refused.conf index 15eeedc4..eec3d667 100644 --- a/config/filter.d/named-refused.conf +++ b/config/filter.d/named-refused.conf @@ -38,6 +38,8 @@ failregex = ^%(__line_prefix)s( error:)?\s*client #\S+( \([\S.]+\))?: (vie ^%(__line_prefix)s( error:)?\s*client #\S+( \([\S.]+\))?: zone transfer '\S+/AXFR/\w+' denied\s*$ ^%(__line_prefix)s( error:)?\s*client #\S+( \([\S.]+\))?: bad zone transfer request: '\S+/IN': non-authoritative zone \(NOTAUTH\)\s*$ +ignoreregex = + # DEV Notes: # Trying to generalize the # structure which is general to capture general patterns in log From a6a2dc868b13be57fc986ca7c6986dac6e06185d Mon Sep 17 00:00:00 2001 From: Guillaume FRANCOIS Date: Wed, 12 Nov 2014 11:05:56 +0100 Subject: [PATCH 12/14] Add ignoreregex to avoid warning on start --- config/filter.d/recidive.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/filter.d/recidive.conf b/config/filter.d/recidive.conf index b38735ad..e2501cf6 100644 --- a/config/filter.d/recidive.conf +++ b/config/filter.d/recidive.conf @@ -29,6 +29,8 @@ _jailname = recidive failregex = ^(%(__prefix_line)s| %(_daemon)s%(__pid_re)s?:\s+)NOTICE\s+\[(?!%(_jailname)s\])(?:.*)\]\s+Ban\s+\s*$ +ignoreregex = + [Init] journalmatch = _SYSTEMD_UNIT=fail2ban.service PRIORITY=5 From d8867807f560838e70375cc9ca90585179700fe6 Mon Sep 17 00:00:00 2001 From: Orion Poplawski Date: Fri, 28 Nov 2014 22:04:09 -0700 Subject: [PATCH 13/14] Separate php-url-fopen logpath by newline --- config/jail.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/jail.conf b/config/jail.conf index d119d229..6a95aa12 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -302,7 +302,8 @@ logpath = %(nginx_error_log)s [php-url-fopen] port = http,https -logpath = %(nginx_access_log)s %(apache_access_log)s +logpath = %(nginx_access_log)s + %(apache_access_log)s [suhosin] From 9bab6d00094f01335269a89702fb5724324dc801 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Sat, 29 Nov 2014 09:52:25 -0500 Subject: [PATCH 14/14] Changelog entry for preceding fix --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 1cd21884..620ab0f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,8 @@ ver. 0.9.2 (2014/XX/XXX) - wanna-be-released * $ typo in jail.conf. Thanks Skibbi. Debian bug #767255 * grep'ing for IP in *mail-whois-lines.conf should now match also at the begginning and EOL. Thanks Dean Lee + * jail.conf + - php-url-fopen: separate logpath entries by newline - New Features: