New upstream version 1.0.2

debian
Sylvestre Ledru 2022-11-09 17:42:26 +01:00
parent 42ade49724
commit a7775d4bfd
13 changed files with 117 additions and 39 deletions

View File

@ -7,6 +7,25 @@
Fail2Ban: Changelog Fail2Ban: Changelog
=================== ===================
ver. 1.0.2 (2022/11/09) - finally-war-game-test-tape-not-a-nuclear-alarm
-----------
### Fixes
* backend `systemd`: code review and several fixes:
- wait only if it is necessary, e. g. in operational mode and if no more entries retrieved (end of journal);
- ensure we give enough time after possible rotation, vacuuming or adding/removing journal files,
and move cursor back and forth to avoid entering dead space
* `filter.d/named-refused.conf`:
- support BIND named log categories, gh-3388
- allow `info:` as possible error prefix too ("query (cache) denied" may occur as info)
* `filter.d/dovecot.conf`:
- fixes regression introduced in gh-3210: resolve extremely long search by repeated apply of non-greedy RE-part
with following branches (it may be extremely slow up to infinite search depending on message), gh-3370
- fixes regression and matches new format in aggressive mode too (amend to gh-3210)
### New Features and Enhancements
ver. 1.0.1 (2022/09/27) - energy-equals-mass-times-the-speed-of-light-squared ver. 1.0.1 (2022/09/27) - energy-equals-mass-times-the-speed-of-light-squared
----------- -----------

View File

@ -7,19 +7,21 @@ before = common.conf
[Definition] [Definition]
_daemon = (?:dovecot(?:-auth)?|auth)
_auth_worker = (?:dovecot: )?auth(?:-worker)? _auth_worker = (?:dovecot: )?auth(?:-worker)?
_auth_worker_info = (?:conn \w+:auth(?:-worker)? \([^\)]+\): auth(?:-worker)?<\d+>: )? _auth_worker_info = (?:conn \w+:auth(?:-worker)? \([^\)]+\): auth(?:-worker)?<\d+>: )?
_daemon = (?:dovecot(?:-auth)?|auth) _bypass_reject_reason = (?:: (?:\w+\([^\):]*\) \w+|[^\(]+))*
prefregex = ^%(__prefix_line)s(?:%(_auth_worker)s(?:\([^\)]+\))?: )?(?:%(__pam_auth)s(?:\(dovecot:auth\))?: |(?:pop3|imap|managesieve|submission)-login: )?(?:Info: )?%(_auth_worker_info)s<F-CONTENT>.+</F-CONTENT>$ prefregex = ^%(__prefix_line)s(?:%(_auth_worker)s(?:\([^\)]+\))?: )?(?:%(__pam_auth)s(?:\(dovecot:auth\))?: |(?:pop3|imap|managesieve|submission)-login: )?(?:Info: )?%(_auth_worker_info)s<F-CONTENT>.+</F-CONTENT>$
failregex = ^authentication failure; logname=<F-ALT_USER1>\S*</F-ALT_USER1> uid=\S* euid=\S* tty=dovecot ruser=<F-USER>\S*</F-USER> rhost=<HOST>(?:\s+user=<F-ALT_USER>\S*</F-ALT_USER>)?\s*$ failregex = ^authentication failure; logname=<F-ALT_USER1>\S*</F-ALT_USER1> uid=\S* euid=\S* tty=dovecot ruser=<F-USER>\S*</F-USER> rhost=<HOST>(?:\s+user=<F-ALT_USER>\S*</F-ALT_USER>)?\s*$
^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)(?:: (?:[^\(]+|\w+\([^\)]*\))+)? \((?:auth failed, \d+ attempts(?: in \d+ secs)?|tried to use (?:disabled|disallowed) \S+ auth|proxy dest auth failed)\):(?: user=<<F-USER>[^>]*</F-USER>>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$ ^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)%(_bypass_reject_reason)s \((?:auth failed, \d+ attempts(?: in \d+ secs)?|tried to use (?:disabled|disallowed) \S+ auth|proxy dest auth failed)\):(?: user=<<F-USER>[^>]*</F-USER>>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
^pam\(\S+,<HOST>(?:,\S*)?\): pam_authenticate\(\) failed: (?:User not known to the underlying authentication module: \d+ Time\(s\)|Authentication failure \([Pp]assword mismatch\?\)|Permission denied)\s*$ ^pam\(\S+,<HOST>(?:,\S*)?\): pam_authenticate\(\) failed: (?:User not known to the underlying authentication module: \d+ Time\(s\)|Authentication failure \([Pp]assword mismatch\?\)|Permission denied)\s*$
^[a-z\-]{3,15}\(\S*,<HOST>(?:,\S*)?\): (?:[Uu]nknown user|[Ii]nvalid credentials|[Pp]assword mismatch) ^[a-z\-]{3,15}\(\S*,<HOST>(?:,\S*)?\): (?:[Uu]nknown user|[Ii]nvalid credentials|[Pp]assword mismatch)
<mdre-<mode>> <mdre-<mode>>
mdre-aggressive = ^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)(?::(?: [^ \(]+)+)? \((?:no auth attempts|disconnected before auth was ready,|client didn't finish \S+ auth,)(?: (?:in|waited) \d+ secs)?\):(?: user=<[^>]*>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$ mdre-aggressive = ^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)%(_bypass_reject_reason)s \((?:no auth attempts|disconnected before auth was ready,|client didn't finish \S+ auth,)(?: (?:in|waited) \d+ secs)?\):(?: user=<[^>]*>,)?(?: method=\S+,)? rip=<HOST>(?:[^>]*(?:, session=<\S+>)?)\s*$
mdre-normal = mdre-normal =

View File

@ -30,11 +30,14 @@ __pid_re=(?:\[\d+\])
__daemon_re=\(?%(_daemon)s(?:\(\S+\))?\)?:? __daemon_re=\(?%(_daemon)s(?:\(\S+\))?\)?:?
__daemon_combs_re=(?:%(__pid_re)s?:\s+%(__daemon_re)s|%(__daemon_re)s%(__pid_re)s?:) __daemon_combs_re=(?:%(__pid_re)s?:\s+%(__daemon_re)s|%(__daemon_re)s%(__pid_re)s?:)
_category = (?!error|info)[\w-]+
_category_re = (?:%(_category)s: )?
# hostname daemon_id spaces # hostname daemon_id spaces
# this can be optional (for instance if we match named native log files) # this can be optional (for instance if we match named native log files)
__line_prefix=(?:\s*\S+ %(__daemon_combs_re)s\s+)? __line_prefix=\s*(?:\S+ %(__daemon_combs_re)s\s+)?%(_category_re)s
prefregex = ^%(__line_prefix)s(?: error:)?\s*client(?: @\S*)? <HOST>#\S+(?: \([\S.]+\))?: <F-CONTENT>.+</F-CONTENT>\s(?:denied|\(NOTAUTH\))\s*$ prefregex = ^%(__line_prefix)s(?:(?:error|info):\s*)?client(?: @\S*)? <HOST>#\S+(?: \([\S.]+\))?: <F-CONTENT>.+</F-CONTENT>\s(?:denied|\(NOTAUTH\))\s*$
failregex = ^(?:view (?:internal|external): )?query(?: \(cache\))? failregex = ^(?:view (?:internal|external): )?query(?: \(cache\))?
^zone transfer ^zone transfer

View File

@ -312,20 +312,37 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
except OSError: except OSError:
pass # Reading failure, so safe to ignore pass # Reading failure, so safe to ignore
wcode = journal.NOP
line = None line = None
while self.active: while self.active:
# wait for records (or for timeout in sleeptime seconds): # wait for records (or for timeout in sleeptime seconds):
try: try:
## wait for entries using journal.wait:
if wcode == journal.NOP and self.inOperation:
## todo: find better method as wait_for to break (e.g. notify) journal.wait(self.sleeptime), ## todo: find better method as wait_for to break (e.g. notify) journal.wait(self.sleeptime),
## don't use `journal.close()` for it, because in some python/systemd implementation it may ## don't use `journal.close()` for it, because in some python/systemd implementation it may
## cause abnormal program termination ## cause abnormal program termination (e. g. segfault)
#self.__journal.wait(self.sleeptime) != journal.NOP
## ##
## wait for entries without sleep in intervals, because "sleeping" in journal.wait: ## wait for entries without sleep in intervals, because "sleeping" in journal.wait,
if not logentry: ## journal.NOP is 0, so we can wait for non zero (APPEND or INVALIDATE):
Utils.wait_for(lambda: not self.active or \ wcode = Utils.wait_for(lambda: not self.active and journal.APPEND or \
self.__journal.wait(Utils.DEFAULT_SLEEP_INTERVAL) != journal.NOP, self.__journal.wait(Utils.DEFAULT_SLEEP_INTERVAL),
self.sleeptime, 0.00001) self.sleeptime, 0.00001)
## if invalidate (due to rotation, vacuuming or journal files added/removed etc):
if self.active and wcode == journal.INVALIDATE:
if self.ticks:
logSys.log(logging.DEBUG, "[%s] Invalidate signaled, take a little break (rotation ends)", self.jailName)
time.sleep(self.sleeptime * 0.25)
Utils.wait_for(lambda: not self.active or \
self.__journal.wait(Utils.DEFAULT_SLEEP_INTERVAL) != journal.INVALIDATE,
self.sleeptime * 3, 0.00001)
if self.ticks:
# move back and forth to ensure do not end up in dead space by rotation or vacuuming,
# if position beyond end of journal (gh-3396)
try:
if self.__journal.get_previous(): self.__journal.get_next()
except OSError:
pass
if self.idle: if self.idle:
# because journal.wait will returns immediatelly if we have records in journal, # because journal.wait will returns immediatelly if we have records in journal,
# just wait a little bit here for not idle, to prevent hi-load: # just wait a little bit here for not idle, to prevent hi-load:
@ -360,11 +377,13 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
self.processLineAndAdd(line, tm) self.processLineAndAdd(line, tm)
self.__modified += 1 self.__modified += 1
if self.__modified >= 100: # todo: should be configurable if self.__modified >= 100: # todo: should be configurable
wcode = journal.APPEND; # don't need wait - there are still unprocessed entries
break break
else: else:
# "in operation" mode since we don't have messages anymore (reached end of journal): # "in operation" mode since we don't have messages anymore (reached end of journal):
if not self.inOperation: if not self.inOperation:
self.inOperationMode() self.inOperationMode()
wcode = journal.NOP; # enter wait - no more entries to process
break break
self.__modified = 0 self.__modified = 0
if self.ticks % 10 == 0: if self.ticks % 10 == 0:
@ -384,6 +403,7 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
except Exception as e: # pragma: no cover except Exception as e: # pragma: no cover
if not self.active: # if not active - error by stop... if not self.active: # if not active - error by stop...
break break
wcode = journal.NOP
logSys.error("Caught unhandled exception in main cycle: %r", e, logSys.error("Caught unhandled exception in main cycle: %r", e,
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG) exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
# incr common error counter: # incr common error counter:
@ -392,15 +412,20 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
logSys.debug("[%s] filter terminated", self.jailName) logSys.debug("[%s] filter terminated", self.jailName)
# close journal: # close journal:
self.closeJournal()
logSys.debug("[%s] filter exited (systemd)", self.jailName)
return True
def closeJournal(self):
try: try:
if self.__journal: jnl, self.__journal = self.__journal, None
self.__journal.close() if jnl:
jnl.close()
except Exception as e: # pragma: no cover except Exception as e: # pragma: no cover
logSys.error("Close journal failed: %r", e, logSys.error("Close journal failed: %r", e,
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG) exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
logSys.debug("[%s] filter exited (systemd)", self.jailName)
return True
def status(self, flavor="basic"): def status(self, flavor="basic"):
ret = super(FilterSystemd, self).status(flavor=flavor) ret = super(FilterSystemd, self).status(flavor=flavor)
@ -422,6 +447,8 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
def onStop(self): def onStop(self):
"""Stop monitoring of journal. Invoked after run method. """Stop monitoring of journal. Invoked after run method.
""" """
# close journal:
self.closeJournal()
# ensure positions of pending logs are up-to-date: # ensure positions of pending logs are up-to-date:
if self._pendDBUpdates and self.jail.database: if self._pendDBUpdates and self.jail.database:
self._updateDBPending() self._updateDBPending()

View File

@ -36,7 +36,7 @@ from .utils import CONFIG_DIR
fail2banregex.logSys = logSys fail2banregex.logSys = logSys
def _test_output(*args): def _test_output(*args):
logSys.notice(args[0]) logSys.notice('output: %s', args[0])
fail2banregex.output = _test_output fail2banregex.output = _test_output
@ -360,57 +360,57 @@ class Fail2banRegexTest(LogCaptureTestCase):
def testFrmtOutput(self): def testFrmtOutput(self):
# id/ip only: # id/ip only:
self.assertTrue(_test_exec('-o', 'id', STR_00, RE_00_ID)) self.assertTrue(_test_exec('-o', 'id', STR_00, RE_00_ID))
self.assertLogged('kevin') self.assertLogged('output: %s' % 'kevin')
self.pruneLog() self.pruneLog()
# multiple id combined to a tuple (id, tuple_id): # multiple id combined to a tuple (id, tuple_id):
self.assertTrue(_test_exec('-o', 'id', '-d', '{^LN-BEG}EPOCH', self.assertTrue(_test_exec('-o', 'id', '-d', '{^LN-BEG}EPOCH',
'1591983743.667 192.0.2.1 192.0.2.2', '1591983743.667 192.0.2.1 192.0.2.2',
r'^\s*<F-ID/> <F-TUPLE_ID>\S+</F-TUPLE_ID>')) r'^\s*<F-ID/> <F-TUPLE_ID>\S+</F-TUPLE_ID>'))
self.assertLogged(str(('192.0.2.1', '192.0.2.2'))) self.assertLogged('output: %s' % str(('192.0.2.1', '192.0.2.2')))
self.pruneLog() self.pruneLog()
# multiple id combined to a tuple, id first - (id, tuple_id_1, tuple_id_2): # multiple id combined to a tuple, id first - (id, tuple_id_1, tuple_id_2):
self.assertTrue(_test_exec('-o', 'id', '-d', '{^LN-BEG}EPOCH', self.assertTrue(_test_exec('-o', 'id', '-d', '{^LN-BEG}EPOCH',
'1591983743.667 left 192.0.2.3 right', '1591983743.667 left 192.0.2.3 right',
r'^\s*<F-TUPLE_ID_1>\S+</F-TUPLE_ID_1> <F-ID/> <F-TUPLE_ID_2>\S+</F-TUPLE_ID_2>')) r'^\s*<F-TUPLE_ID_1>\S+</F-TUPLE_ID_1> <F-ID/> <F-TUPLE_ID_2>\S+</F-TUPLE_ID_2>'))
self.assertLogged(str(('192.0.2.3', 'left', 'right'))) self.assertLogged('output: %s' % str(('192.0.2.3', 'left', 'right')))
self.pruneLog() self.pruneLog()
# id had higher precedence as ip-address: # id had higher precedence as ip-address:
self.assertTrue(_test_exec('-o', 'id', '-d', '{^LN-BEG}EPOCH', self.assertTrue(_test_exec('-o', 'id', '-d', '{^LN-BEG}EPOCH',
'1591983743.667 left [192.0.2.4]:12345 right', '1591983743.667 left [192.0.2.4]:12345 right',
r'^\s*<F-TUPLE_ID_1>\S+</F-TUPLE_ID_1> <F-ID><ADDR>:<F-PORT/></F-ID> <F-TUPLE_ID_2>\S+</F-TUPLE_ID_2>')) r'^\s*<F-TUPLE_ID_1>\S+</F-TUPLE_ID_1> <F-ID><ADDR>:<F-PORT/></F-ID> <F-TUPLE_ID_2>\S+</F-TUPLE_ID_2>'))
self.assertLogged(str(('[192.0.2.4]:12345', 'left', 'right'))) self.assertLogged('output: %s' % str(('[192.0.2.4]:12345', 'left', 'right')))
self.pruneLog() self.pruneLog()
# ip is not id anymore (if IP-address deviates from ID): # ip is not id anymore (if IP-address deviates from ID):
self.assertTrue(_test_exec('-o', 'ip', '-d', '{^LN-BEG}EPOCH', self.assertTrue(_test_exec('-o', 'ip', '-d', '{^LN-BEG}EPOCH',
'1591983743.667 left [192.0.2.4]:12345 right', '1591983743.667 left [192.0.2.4]:12345 right',
r'^\s*<F-TUPLE_ID_1>\S+</F-TUPLE_ID_1> <F-ID><ADDR>:<F-PORT/></F-ID> <F-TUPLE_ID_2>\S+</F-TUPLE_ID_2>')) r'^\s*<F-TUPLE_ID_1>\S+</F-TUPLE_ID_1> <F-ID><ADDR>:<F-PORT/></F-ID> <F-TUPLE_ID_2>\S+</F-TUPLE_ID_2>'))
self.assertNotLogged(str(('[192.0.2.4]:12345', 'left', 'right'))) self.assertNotLogged('output: %s' % str(('[192.0.2.4]:12345', 'left', 'right')))
self.assertLogged('192.0.2.4') self.assertLogged('output: %s' % '192.0.2.4')
self.pruneLog() self.pruneLog()
self.assertTrue(_test_exec('-o', 'ID:<fid> | IP:<ip>', '-d', '{^LN-BEG}EPOCH', self.assertTrue(_test_exec('-o', 'ID:<fid> | IP:<ip>', '-d', '{^LN-BEG}EPOCH',
'1591983743.667 left [192.0.2.4]:12345 right', '1591983743.667 left [192.0.2.4]:12345 right',
r'^\s*<F-TUPLE_ID_1>\S+</F-TUPLE_ID_1> <F-ID><ADDR>:<F-PORT/></F-ID> <F-TUPLE_ID_2>\S+</F-TUPLE_ID_2>')) r'^\s*<F-TUPLE_ID_1>\S+</F-TUPLE_ID_1> <F-ID><ADDR>:<F-PORT/></F-ID> <F-TUPLE_ID_2>\S+</F-TUPLE_ID_2>'))
self.assertLogged('ID:'+str(('[192.0.2.4]:12345', 'left', 'right'))+' | IP:192.0.2.4') self.assertLogged('output: %s' % 'ID:'+str(('[192.0.2.4]:12345', 'left', 'right'))+' | IP:192.0.2.4')
self.pruneLog() self.pruneLog()
# row with id : # row with id :
self.assertTrue(_test_exec('-o', 'row', STR_00, RE_00_ID)) self.assertTrue(_test_exec('-o', 'row', STR_00, RE_00_ID))
self.assertLogged("['kevin'", "'ip4': '192.0.2.0'", "'fid': 'kevin'", all=True) self.assertLogged('output: %s' % "['kevin'", "'ip4': '192.0.2.0'", "'fid': 'kevin'", all=True)
self.pruneLog() self.pruneLog()
# row with ip : # row with ip :
self.assertTrue(_test_exec('-o', 'row', STR_00, RE_00_USER)) self.assertTrue(_test_exec('-o', 'row', STR_00, RE_00_USER))
self.assertLogged("['192.0.2.0'", "'ip4': '192.0.2.0'", "'user': 'kevin'", all=True) self.assertLogged('output: %s' % "['192.0.2.0'", "'ip4': '192.0.2.0'", "'user': 'kevin'", all=True)
self.pruneLog() self.pruneLog()
# log msg : # log msg :
self.assertTrue(_test_exec('-o', 'msg', STR_00, RE_00_USER)) self.assertTrue(_test_exec('-o', 'msg', STR_00, RE_00_USER))
self.assertLogged(STR_00) self.assertLogged('output: %s' % STR_00)
self.pruneLog() self.pruneLog()
# item of match (user): # item of match (user):
self.assertTrue(_test_exec('-o', 'user', STR_00, RE_00_USER)) self.assertTrue(_test_exec('-o', 'user', STR_00, RE_00_USER))
self.assertLogged('kevin') self.assertLogged('output: %s' % 'kevin')
self.pruneLog() self.pruneLog()
# complex substitution using tags (ip, user, family): # complex substitution using tags (ip, user, family):
self.assertTrue(_test_exec('-o', '<ip>, <F-USER>, <family>', STR_00, RE_00_USER)) self.assertTrue(_test_exec('-o', '<ip>, <F-USER>, <family>', STR_00, RE_00_USER))
self.assertLogged('192.0.2.0, kevin, inet4') self.assertLogged('output: %s' % '192.0.2.0, kevin, inet4')
self.pruneLog() self.pruneLog()
def testStalledIPByNoFailFrmtOutput(self): def testStalledIPByNoFailFrmtOutput(self):

View File

@ -115,6 +115,17 @@ Aug 28 06:38:51 s166-62-100-187 dovecot: imap-login: Disconnected (auth failed,
# failJSON: { "time": "2004-08-28T06:38:52", "match": true , "host": "192.0.2.4", "desc": "open parenthesis in optional part between Disconnected and (auth failed ...), gh-3210" } # failJSON: { "time": "2004-08-28T06:38:52", "match": true , "host": "192.0.2.4", "desc": "open parenthesis in optional part between Disconnected and (auth failed ...), gh-3210" }
Aug 28 06:38:52 s166-62-100-187 dovecot: imap-login: Disconnected: Connection closed: read(size=1003) failed: Connection reset by peer (auth failed, 1 attempts in 0 secs): user=<test@example.com>, rip=192.0.2.4, lip=127.0.0.19, session=<Lsz0Oo7WXti3b7xe> Aug 28 06:38:52 s166-62-100-187 dovecot: imap-login: Disconnected: Connection closed: read(size=1003) failed: Connection reset by peer (auth failed, 1 attempts in 0 secs): user=<test@example.com>, rip=192.0.2.4, lip=127.0.0.19, session=<Lsz0Oo7WXti3b7xe>
# failJSON: { "time": "2004-08-29T01:49:33", "match": false , "desc": "avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[459]: imap-login: Disconnected: Connection closed: read(size=1026) failed: Connection reset by peer (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1, TLS handshaking: read(size=1026) failed: Connection reset by peer
# failJSON: { "time": "2004-08-29T01:49:33", "match": false , "desc": "avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[459]: imap-login: Disconnected: Connection closed: SSL_accept() failed: error:1408F10B:SSL routines:ssl3_get_record:wrong version number (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1, TLS handshaking: SSL_accept() failed: error:1408F10B:SSL routines:ssl3_get_record:wrong version number
# failJSON: { "time": "2004-08-29T01:49:33", "match": false , "desc": "avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[459]: managesieve-login: Disconnected: Too many invalid commands. (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1
# failJSON: { "time": "2004-08-29T01:49:33", "match": false , "desc": "avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[459]: managesieve-login: Disconnected: Connection closed: read(size=1007) failed: Connection reset by peer (no auth attempts in 1 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1
# failJSON: { "time": "2004-08-29T01:49:33", "match": false , "desc": "avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[472]: imap-login: Disconnected: Connection closed: SSL_accept() failed: error:14209102:SSL routines:tls_early_post_process_client_hello:unsupported protocol (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1, TLS handshaking: SSL_accept() failed: error:14209102:SSL routines:tls_early_post_process_client_hello:unsupported protocol
# failJSON: { "time": "2004-08-29T03:17:18", "match": true , "host": "192.0.2.133" } # failJSON: { "time": "2004-08-29T03:17:18", "match": true , "host": "192.0.2.133" }
Aug 29 03:17:18 server dovecot: submission-login: Client has quit the connection (auth failed, 1 attempts in 2 secs): user=<user1>, method=LOGIN, rip=192.0.2.133, lip=0.0.0.0 Aug 29 03:17:18 server dovecot: submission-login: Client has quit the connection (auth failed, 1 attempts in 2 secs): user=<user1>, method=LOGIN, rip=192.0.2.133, lip=0.0.0.0
# failJSON: { "time": "2004-08-29T03:53:52", "match": true , "host": "192.0.2.169" } # failJSON: { "time": "2004-08-29T03:53:52", "match": true , "host": "192.0.2.169" }
@ -128,6 +139,17 @@ Aug 29 15:33:53 server dovecot: managesieve-login: Disconnected: Too many invali
# filterOptions: [{"mode": "aggressive"}] # filterOptions: [{"mode": "aggressive"}]
# failJSON: { "time": "2004-08-29T01:49:33", "match": true , "host": "192.0.2.5", "desc": "matches in aggressive mode, avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[459]: imap-login: Disconnected: Connection closed: read(size=1026) failed: Connection reset by peer (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1, TLS handshaking: read(size=1026) failed: Connection reset by peer
# failJSON: { "time": "2004-08-29T01:49:33", "match": true , "host": "192.0.2.5", "desc": "matches in aggressive mode, avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[459]: imap-login: Disconnected: Connection closed: SSL_accept() failed: error:1408F10B:SSL routines:ssl3_get_record:wrong version number (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1, TLS handshaking: SSL_accept() failed: error:1408F10B:SSL routines:ssl3_get_record:wrong version number
# failJSON: { "time": "2004-08-29T01:49:33", "match": true , "host": "192.0.2.5", "desc": "matches in aggressive mode, avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[459]: managesieve-login: Disconnected: Too many invalid commands. (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1
# failJSON: { "time": "2004-08-29T01:49:33", "match": true , "host": "192.0.2.5", "desc": "matches in aggressive mode, avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[459]: managesieve-login: Disconnected: Connection closed: read(size=1007) failed: Connection reset by peer (no auth attempts in 1 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1
# failJSON: { "time": "2004-08-29T01:49:33", "match": true , "host": "192.0.2.5", "desc": "matches in aggressive mode, avoid slow RE, gh-3370" }
Aug 29 01:49:33 server dovecot[472]: imap-login: Disconnected: Connection closed: SSL_accept() failed: error:14209102:SSL routines:tls_early_post_process_client_hello:unsupported protocol (no auth attempts in 0 secs): user=<>, rip=192.0.2.5, lip=127.0.0.1, TLS handshaking: SSL_accept() failed: error:14209102:SSL routines:tls_early_post_process_client_hello:unsupported protocol
# failJSON: { "time": "2004-08-29T16:06:58", "match": true , "host": "192.0.2.5" } # failJSON: { "time": "2004-08-29T16:06:58", "match": true , "host": "192.0.2.5" }
Aug 29 16:06:58 s166-62-100-187 dovecot: imap-login: Disconnected (disconnected before auth was ready, waited 0 secs): user=<>, rip=192.0.2.5, lip=192.168.1.2, TLS handshaking: SSL_accept() syscall failed: Connection reset by peer Aug 29 16:06:58 s166-62-100-187 dovecot: imap-login: Disconnected (disconnected before auth was ready, waited 0 secs): user=<>, rip=192.0.2.5, lip=192.168.1.2, TLS handshaking: SSL_accept() syscall failed: Connection reset by peer
# failJSON: { "time": "2004-08-31T16:15:10", "match": true , "host": "192.0.2.6" } # failJSON: { "time": "2004-08-31T16:15:10", "match": true , "host": "192.0.2.6" }

View File

@ -27,6 +27,11 @@ Aug 27 16:58:31 vhost1-ua named[29206]: client 176.9.92.38#42592 (simmarket.com.
# failJSON: { "time": "2004-08-27T16:59:00", "match": true , "host": "192.0.2.1", "desc": "new log format, 9.11.0 (#2406)" } # failJSON: { "time": "2004-08-27T16:59:00", "match": true , "host": "192.0.2.1", "desc": "new log format, 9.11.0 (#2406)" }
Aug 27 16:59:00 host named[28098]: client @0x7f6450002ef0 192.0.2.1#23332 (example.com): bad zone transfer request: 'test.com/IN': non-authoritative zone (NOTAUTH) Aug 27 16:59:00 host named[28098]: client @0x7f6450002ef0 192.0.2.1#23332 (example.com): bad zone transfer request: 'test.com/IN': non-authoritative zone (NOTAUTH)
# failJSON: { "match": true , "host": "192.0.2.8", "desc": "log message with category (security), gh-3388" }
Oct 23 02:06:39 security: info: client @0x7f4e446fd6e8 192.0.2.8#53 (example.io): query (cache) 'example.io/A/IN' denied
# failJSON: { "match": true , "host": "192.0.2.237", "desc": "log message with category, gh-3388" }
Oct 23 03:35:40 update-security: error: client @0x7f4e45c07a48 192.0.2.237#55956 (example.ca): zone transfer 'example.ca/AXFR/IN' denied
# filterOptions: {"logtype": "journal"} # filterOptions: {"logtype": "journal"}
# failJSON: { "match": true , "host": "192.0.2.1", "desc": "systemd-journal entry" } # failJSON: { "match": true , "host": "192.0.2.1", "desc": "systemd-journal entry" }

View File

@ -24,7 +24,7 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko, Steven Hiscocks, Daniel Black"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2005-2016 Yaroslav Halchenko, 2013-2014 Steven Hiscocks, Daniel Black" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2005-2016 Yaroslav Halchenko, 2013-2014 Steven Hiscocks, Daniel Black"
__license__ = "GPL-v2+" __license__ = "GPL-v2+"
version = "1.0.1" version = "1.0.2"
def normVersion(): def normVersion():
""" Returns fail2ban version in normalized machine-readable format""" """ Returns fail2ban version in normalized machine-readable format"""

View File

@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1.
.TH FAIL2BAN-CLIENT "1" "September 2022" "Fail2Ban v1.0.1" "User Commands" .TH FAIL2BAN-CLIENT "1" "November 2022" "Fail2Ban v1.0.2" "User Commands"
.SH NAME .SH NAME
fail2ban-client \- configure and control the server fail2ban-client \- configure and control the server
.SH SYNOPSIS .SH SYNOPSIS
.B fail2ban-client .B fail2ban-client
[\fI\,OPTIONS\/\fR] \fI\,<COMMAND>\/\fR [\fI\,OPTIONS\/\fR] \fI\,<COMMAND>\/\fR
.SH DESCRIPTION .SH DESCRIPTION
Fail2Ban v1.0.1 reads log file that contains password failure report Fail2Ban v1.0.2 reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules. and bans the corresponding IP addresses using firewall rules.
.SH OPTIONS .SH OPTIONS
.TP .TP

View File

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1.
.TH FAIL2BAN-PYTHON "1" "September 2022" "fail2ban-python 1.0.1" "User Commands" .TH FAIL2BAN-PYTHON "1" "November 2022" "fail2ban-python 1.0.2" "User Commands"
.SH NAME .SH NAME
fail2ban-python \- a helper for Fail2Ban to assure that the same Python is used fail2ban-python \- a helper for Fail2Ban to assure that the same Python is used
.SH DESCRIPTION .SH DESCRIPTION

View File

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1.
.TH FAIL2BAN-REGEX "1" "September 2022" "fail2ban-regex 1.0.1" "User Commands" .TH FAIL2BAN-REGEX "1" "November 2022" "fail2ban-regex 1.0.2" "User Commands"
.SH NAME .SH NAME
fail2ban-regex \- test Fail2ban "failregex" option fail2ban-regex \- test Fail2ban "failregex" option
.SH SYNOPSIS .SH SYNOPSIS

View File

@ -1,12 +1,12 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1.
.TH FAIL2BAN-SERVER "1" "September 2022" "Fail2Ban v1.0.1" "User Commands" .TH FAIL2BAN-SERVER "1" "November 2022" "Fail2Ban v1.0.2" "User Commands"
.SH NAME .SH NAME
fail2ban-server \- start the server fail2ban-server \- start the server
.SH SYNOPSIS .SH SYNOPSIS
.B fail2ban-server .B fail2ban-server
[\fI\,OPTIONS\/\fR] [\fI\,OPTIONS\/\fR]
.SH DESCRIPTION .SH DESCRIPTION
Fail2Ban v1.0.1 reads log file that contains password failure report Fail2Ban v1.0.2 reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules. and bans the corresponding IP addresses using firewall rules.
.SH OPTIONS .SH OPTIONS
.TP .TP

View File

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1. .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.48.1.
.TH FAIL2BAN-TESTCASES "1" "September 2022" "fail2ban-testcases 1.0.1" "User Commands" .TH FAIL2BAN-TESTCASES "1" "November 2022" "fail2ban-testcases 1.0.2" "User Commands"
.SH NAME .SH NAME
fail2ban-testcases \- run Fail2Ban unit-tests fail2ban-testcases \- run Fail2Ban unit-tests
.SH SYNOPSIS .SH SYNOPSIS