build replacement of `<HOST>` substitution corresponding parameter `usedns` - dns-part will be added only if `usedns` is not `no`;

new replacement for `<ADDR>` in opposition to `<HOST>`, for separate usage of 2 address groups only (regardless of `usedns`), `ip4` and `ip6` together, without host (dns)
pull/1557/head
sebres 2016-09-08 15:38:36 +02:00
parent 8c26cada27
commit d2ddc59c40
4 changed files with 22 additions and 14 deletions

View File

@ -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],

View File

@ -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 "<HOST>" tag using default regular expression for host:
regex = Regex._resolveHostTag(regex)
regex = Regex._resolveHostTag(regex, **kwargs)
# Replace "<SKIPLINES>" with regular expression for multiple lines.
regexSplit = regex.split("<SKIPLINES>")
regex = regexSplit[0]
@ -69,22 +69,29 @@ class Regex:
# @return the replaced regular expression as string
@staticmethod
def _resolveHostTag(regex):
# 3 groups instead of <HOST> - separated ipv4, ipv6 and host
regex = regex.replace("<HOST>",
r"""(?:(?:::f{4,6}:)?(?P<ip4>(?:\d{1,3}\.){3}\d{1,3})|\[?(?P<ip6>(?:[0-9a-fA-F]{1,4}::?|::){1,7}(?:[0-9a-fA-F]{1,4}|(?<=:):))\]?|(?P<dns>[\w\-.^_]*\w))""")
def _resolveHostTag(regex, useDns="yes"):
# separated ipv4:
r_host = []
r = r"""(?:::f{4,6}:)?(?P<ip4>(?:\d{1,3}\.){3}\d{1,3})"""
regex = regex.replace("<IP4>", r); # self closed
regex = regex.replace("<F-IP4/>", r); # closed
r_host.append(r)
# separated ipv6:
r = r"""(?P<ip6>(?:[0-9a-fA-F]{1,4}::?|::){1,7}(?:[0-9a-fA-F]{1,4}?|(?<=:):))"""
regex = regex.replace("<IP6>", r); # self closed
regex = regex.replace("<F-IP6/>", r); # closed
r_host.append(r"""\[?%s\]?""" % (r,)); # enclose ipv6 in optional [] in host-regex
# 2 address groups instead of <ADDR> - in opposition to `<HOST>`,
# for separate usage of 2 address groups only (regardless of `usedns`), `ip4` and `ip6` together
regex = regex.replace("<ADDR>", "(?:%s)" % ("|".join(r_host),))
# separated dns:
r = r"""(?P<dns>[\w\-.^_]*\w)"""
regex = regex.replace("<DNS>", r); # self closed
regex = regex.replace("<F-DNS/>", r); # closed
if useDns not in ("no",):
r_host.append(r)
# 3 groups instead of <HOST> - separated ipv4, ipv6 and host (dns)
regex = regex.replace("<HOST>", "(?:%s)" % ("|".join(r_host),))
# default failure-id as no space tag:
regex = regex.replace("<F-ID/>", r"""(?P<fid>\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)

View File

@ -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)

View File

@ -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 <HOST>",