diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index e3c4731c..9d01a693 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -106,7 +106,7 @@ class JailReader(ConfigReader): ["int", "maxretry", None], ["string", "findtime", None], ["string", "bantime", None], - ["string", "usedns", None], + ["string", "usedns", None], # be sure usedns is before all regex(s) in stream ["string", "failregex", None], ["string", "ignoreregex", None], ["string", "ignorecommand", None], diff --git a/fail2ban/server/failregex.py b/fail2ban/server/failregex.py index 12b8986a..7c512609 100644 --- a/fail2ban/server/failregex.py +++ b/fail2ban/server/failregex.py @@ -40,11 +40,11 @@ class Regex: # avoid construction of invalid object. # @param value the regular expression - def __init__(self, regex): + def __init__(self, regex, **kwargs): self._matchCache = None # Perform shortcuts expansions. # Resolve "" tag using default regular expression for host: - regex = Regex._resolveHostTag(regex) + regex = Regex._resolveHostTag(regex, **kwargs) # Replace "" with regular expression for multiple lines. regexSplit = regex.split("") regex = regexSplit[0] @@ -69,22 +69,29 @@ class Regex: # @return the replaced regular expression as string @staticmethod - def _resolveHostTag(regex): - # 3 groups instead of - separated ipv4, ipv6 and host - regex = regex.replace("", - r"""(?:(?:::f{4,6}:)?(?P(?:\d{1,3}\.){3}\d{1,3})|\[?(?P(?:[0-9a-fA-F]{1,4}::?|::){1,7}(?:[0-9a-fA-F]{1,4}|(?<=:):))\]?|(?P[\w\-.^_]*\w))""") + def _resolveHostTag(regex, useDns="yes"): # separated ipv4: + r_host = [] r = r"""(?:::f{4,6}:)?(?P(?:\d{1,3}\.){3}\d{1,3})""" regex = regex.replace("", r); # self closed regex = regex.replace("", r); # closed + r_host.append(r) # separated ipv6: r = r"""(?P(?:[0-9a-fA-F]{1,4}::?|::){1,7}(?:[0-9a-fA-F]{1,4}?|(?<=:):))""" regex = regex.replace("", r); # self closed regex = regex.replace("", r); # closed + r_host.append(r"""\[?%s\]?""" % (r,)); # enclose ipv6 in optional [] in host-regex + # 2 address groups instead of - in opposition to ``, + # for separate usage of 2 address groups only (regardless of `usedns`), `ip4` and `ip6` together + regex = regex.replace("", "(?:%s)" % ("|".join(r_host),)) # separated dns: r = r"""(?P[\w\-.^_]*\w)""" regex = regex.replace("", r); # self closed regex = regex.replace("", r); # closed + if useDns not in ("no",): + r_host.append(r) + # 3 groups instead of - separated ipv4, ipv6 and host (dns) + regex = regex.replace("", "(?:%s)" % ("|".join(r_host),)) # default failure-id as no space tag: regex = regex.replace("", r"""(?P\S+)"""); # closed # default failure port, like 80 or http : @@ -249,9 +256,9 @@ class FailRegex(Regex): # avoid construction of invalid object. # @param value the regular expression - def __init__(self, regex): + def __init__(self, regex, **kwargs): # Initializes the parent. - Regex.__init__(self, regex) + Regex.__init__(self, regex, **kwargs) # Check for group "dns", "ip4", "ip6", "fid" if not [grp for grp in FAILURE_ID_GROPS if grp in self._regexObj.groupindex]: raise RegexException("No failure-id group in '%s'" % self._regex) diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index 4c67470e..1c466c01 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -134,12 +134,12 @@ class Filter(JailThread): def addFailRegex(self, value): try: - regex = FailRegex(value) + regex = FailRegex(value, useDns=self.__useDns) self.__failRegex.append(regex) if "\n" in regex.getRegex() and not self.getMaxLines() > 1: logSys.warning( - "Mutliline regex set for jail '%s' " - "but maxlines not greater than 1") + "Mutliline regex set for jail %r " + "but maxlines not greater than 1", self.jail.name) except RegexException as e: logSys.error(e) raise e @@ -176,7 +176,7 @@ class Filter(JailThread): def addIgnoreRegex(self, value): try: - regex = Regex(value) + regex = Regex(value, useDns=self.__useDns) self.__ignoreRegex.append(regex) except RegexException as e: logSys.error(e) diff --git a/fail2ban/tests/fail2banclienttestcase.py b/fail2ban/tests/fail2banclienttestcase.py index 07bbd913..1ce35d92 100644 --- a/fail2ban/tests/fail2banclienttestcase.py +++ b/fail2ban/tests/fail2banclienttestcase.py @@ -58,7 +58,7 @@ SERVER = "fail2ban-server" BIN = dirname(Fail2banServer.getServerPath()) MAX_WAITTIME = 30 if not unittest.F2B.fast else 5 -MID_WAITTIME = MAX_WAITTIME / 2.5 +MID_WAITTIME = MAX_WAITTIME ## # Several wrappers and settings for proper testing: @@ -681,6 +681,7 @@ class Fail2banServerTest(Fail2banClientServerBase): _write_file(pjoin(cfg, "jail.conf"), "w", "[INCLUDES]", "", "[DEFAULT]", "", + "usedns = no", "maxretry = 3", "findtime = 10m", "failregex = ^\s*failure (401|403) from ",