Merge pull request #4069 from sebres/init-param-to-cond-section

Setting of blocktype="DROP" via jail doesn't apply for IPv6 chain
master
Sergey G. Brester 2025-09-24 18:23:44 +02:00 committed by GitHub
commit 7bac839603
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 129 additions and 3 deletions

View File

@ -24,6 +24,10 @@ ver. 1.1.1-dev-1 (20??/??/??) - development nightly edition
in systemd module (see https://github.com/systemd/python-systemd/issues/143)
* fixes `systemd` causing "too many open files" error for a lot of journal files and large amount of systemd jails
(see new parameter `rotated` below, gh-3391);
* passing of arguments from jails to action or filter will affect conditional section too (gh-4069),
e. g. setting `blocktype="DROP"` via jail for action would now apply for IPv4 and IPv6 chains,
to submit different `blocktype` for IPv4 and IPv6 from jail, one can pass them like in this example:
`banaction = iptables-ipset[blocktype="...", blocktype?family=inet6="..."]`
* `jail.conf`:
- default banactions need to be specified in `paths-*.conf` (maintainer level) now
- since stock fail2ban includes `paths-debian.conf` by default, banactions are `nftables`

View File

@ -354,6 +354,11 @@ class DefinitionInitConfigReader(ConfigReader):
if v is None: v = getopt(opt)
self._initOpts['known/'+opt] = v
if opt not in self._initOpts:
# overwrite also conditional init options (from init?... section):
cond = SafeConfigParserWithIncludes.CONDITIONAL_RE.match(opt)
if cond:
optc, cond = cond.groups()
v = pOpts.get(optc, v)
if v is None: v = getopt(opt)
self._initOpts[opt] = v
if all and self.has_section("Definition"):

View File

@ -323,15 +323,17 @@ def _merge_copy_dicts(x, y):
# regex, to extract list of options:
OPTION_CRE = re.compile(r"^([^\[]+)(?:\[(.*)\])?\s*$", re.DOTALL)
# regex, matching option name (inclusive conditional option, like n?family=inet6):
OPTION_NAME_CRE = r'[\w\-_\.]+(?:\?[\w\-_\.]+=[\w\-_\.]+)?'
# regex, to iterate over single option in option list, syntax:
# `action = act[p1="...", p2='...', p3=...]`, where the p3=... not contains `,` or ']'
# since v0.10 separator extended with `]\s*[` for support of multiple option groups, syntax
# `action = act[p1=...][p2=...]`
OPTION_EXTRACT_CRE = re.compile(
r'\s*([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,\]]*))(?:,|\]\s*\[|$|(?P<wrngA>.+))|,?\s*$|(?P<wrngB>.+)', re.DOTALL)
r'\s*('+OPTION_NAME_CRE+r')=(?:"([^"]*)"|\'([^\']*)\'|([^,\]]*))(?:,|\]\s*\[|$|(?P<wrngA>.+))|,?\s*$|(?P<wrngB>.+)', re.DOTALL)
# split by new-line considering possible new-lines within options [...]:
OPTION_SPLIT_CRE = re.compile(
r'(?:[^\[\s]+(?:\s*\[\s*(?:[\w\-_\.]+=(?:"[^"]*"|\'[^\']*\'|[^,\]]*)\s*(?:,|\]\s*\[)?\s*)*\])?\s*|\S+)(?=\n\s*|\s+|$)', re.DOTALL)
r'(?:[^\[\s]+(?:\s*\[\s*(?:'+OPTION_NAME_CRE+r'=(?:"[^"]*"|\'[^\']*\'|[^,\]]*)\s*(?:,|\]\s*\[)?\s*)*\])?\s*|\S+)(?=\n\s*|\s+|$)', re.DOTALL)
def extractOptions(option):
match = OPTION_CRE.match(option)

View File

@ -1676,6 +1676,106 @@ class ServerConfigReaderTests(LogCaptureTestCase):
r"`ipset -exist del f2b-j-w-iptables-ipset-ap6 2001:db8::`",
),
}),
# iptables-ipset (allports + drop) --
('j-w-ipt-ipset-ap-drp', 'iptables-ipset[name=%(__name__)s, type="allports", blocktype="DROP"]', {
'ip4': (' f2b-j-w-ipt-ipset-ap-drp ',), 'ip6': (' f2b-j-w-ipt-ipset-ap-drp6 ',),
'*-start-stop-check': (
# iterator over protocol is same for both families:
"`for chain in $(echo 'INPUT' | sed 's/,/ /g'); do for proto in $(echo 'tcp' | sed 's/,/ /g'); do`",
"`done; done`",
),
'ip4-start': (
"`ipset -exist create f2b-j-w-ipt-ipset-ap-drp hash:ip timeout 0 maxelem 65536 `",
"`{ iptables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp src -j DROP >/dev/null 2>&1; } || "
"{ iptables -w -I $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp src -j DROP; }",
),
'ip6-start': (
"`ipset -exist create f2b-j-w-ipt-ipset-ap-drp6 hash:ip timeout 0 maxelem 65536 family inet6`",
"`{ ip6tables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp6 src -j DROP >/dev/null 2>&1; } || "
"{ ip6tables -w -I $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp6 src -j DROP; }",
),
'flush': (
"`ipset flush f2b-j-w-ipt-ipset-ap-drp`",
"`ipset flush f2b-j-w-ipt-ipset-ap-drp6`",
),
'stop': (
"`iptables -w -D $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp src -j DROP`",
"`ipset flush f2b-j-w-ipt-ipset-ap-drp`",
"`ipset destroy f2b-j-w-ipt-ipset-ap-drp 2>/dev/null || { sleep 1; ipset destroy f2b-j-w-ipt-ipset-ap-drp; }`",
"`ip6tables -w -D $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp6 src -j DROP`",
"`ipset flush f2b-j-w-ipt-ipset-ap-drp6`",
"`ipset destroy f2b-j-w-ipt-ipset-ap-drp6 2>/dev/null || { sleep 1; ipset destroy f2b-j-w-ipt-ipset-ap-drp6; }`",
),
'ip4-check': (
r"""`iptables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp src -j DROP`""",
),
'ip6-check': (
r"""`ip6tables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-drp6 src -j DROP`""",
),
'ip4-ban': (
r"`ipset -exist add f2b-j-w-ipt-ipset-ap-drp 192.0.2.1 timeout 0`",
),
'ip4-unban': (
r"`ipset -exist del f2b-j-w-ipt-ipset-ap-drp 192.0.2.1`",
),
'ip6-ban': (
r"`ipset -exist add f2b-j-w-ipt-ipset-ap-drp6 2001:db8:: timeout 0`",
),
'ip6-unban': (
r"`ipset -exist del f2b-j-w-ipt-ipset-ap-drp6 2001:db8::`",
),
}),
# iptables-ipset (allports + REJECT with icmp?6? host-unreachable) --
('j-w-ipt-ipset-ap-rwhu', 'iptables-ipset[name=%(__name__)s, type="allports", '
+'blocktype="REJECT --reject-with icmp-host-unreachable", '
+'blocktype?family=inet6="REJECT --reject-with icmp6-host-unreachable"]', {
'ip4': (' f2b-j-w-ipt-ipset-ap-rwhu ',), 'ip6': (' f2b-j-w-ipt-ipset-ap-rwhu6 ',),
'*-start-stop-check': (
# iterator over protocol is same for both families:
"`for chain in $(echo 'INPUT' | sed 's/,/ /g'); do for proto in $(echo 'tcp' | sed 's/,/ /g'); do`",
"`done; done`",
),
'ip4-start': (
"`ipset -exist create f2b-j-w-ipt-ipset-ap-rwhu hash:ip timeout 0 maxelem 65536 `",
"`{ iptables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu src -j REJECT --reject-with icmp-host-unreachable >/dev/null 2>&1; } || "
"{ iptables -w -I $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu src -j REJECT --reject-with icmp-host-unreachable; }",
),
'ip6-start': (
"`ipset -exist create f2b-j-w-ipt-ipset-ap-rwhu6 hash:ip timeout 0 maxelem 65536 family inet6`",
"`{ ip6tables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu6 src -j REJECT --reject-with icmp6-host-unreachable >/dev/null 2>&1; } || "
"{ ip6tables -w -I $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu6 src -j REJECT --reject-with icmp6-host-unreachable; }",
),
'flush': (
"`ipset flush f2b-j-w-ipt-ipset-ap-rwhu`",
"`ipset flush f2b-j-w-ipt-ipset-ap-rwhu6`",
),
'stop': (
"`iptables -w -D $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu src -j REJECT --reject-with icmp-host-unreachable`",
"`ipset flush f2b-j-w-ipt-ipset-ap-rwhu`",
"`ipset destroy f2b-j-w-ipt-ipset-ap-rwhu 2>/dev/null || { sleep 1; ipset destroy f2b-j-w-ipt-ipset-ap-rwhu; }`",
"`ip6tables -w -D $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu6 src -j REJECT --reject-with icmp6-host-unreachable`",
"`ipset flush f2b-j-w-ipt-ipset-ap-rwhu6`",
"`ipset destroy f2b-j-w-ipt-ipset-ap-rwhu6 2>/dev/null || { sleep 1; ipset destroy f2b-j-w-ipt-ipset-ap-rwhu6; }`",
),
'ip4-check': (
r"""`iptables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu src -j REJECT --reject-with icmp-host-unreachable`""",
),
'ip6-check': (
r"""`ip6tables -w -C $chain -p $proto -m set --match-set f2b-j-w-ipt-ipset-ap-rwhu6 src -j REJECT --reject-with icmp6-host-unreachable`""",
),
'ip4-ban': (
r"`ipset -exist add f2b-j-w-ipt-ipset-ap-rwhu 192.0.2.1 timeout 0`",
),
'ip4-unban': (
r"`ipset -exist del f2b-j-w-ipt-ipset-ap-rwhu 192.0.2.1`",
),
'ip6-ban': (
r"`ipset -exist add f2b-j-w-ipt-ipset-ap-rwhu6 2001:db8:: timeout 0`",
),
'ip6-unban': (
r"`ipset -exist del f2b-j-w-ipt-ipset-ap-rwhu6 2001:db8::`",
),
}),
# iptables (oneport) --
('j-w-iptables', 'iptables[name=%(__name__)s, bantime="10m", port="http", protocol="tcp", chain="<known/chain>"]', {
'ip4': ('`iptables ', 'icmp-port-unreachable'), 'ip6': ('`ip6tables ', 'icmp6-port-unreachable'),

View File

@ -245,8 +245,23 @@ Arguments can be passed to actions to override the default values from the [Init
[name=value,name2=value,name3="values,values"]
.RE
Values can also be quoted (required when value includes a ","). More that one action can be specified (in separate lines).
Values can also be quoted (required when value includes a "," or space). More that one action can be specified (in separate lines).
.br
The action specific arguments can also affect conditional parameters, so for instance to submit different values to different chains
firstly pass the argument affecting all chains, e.g. \fIblocktype\fR, then for IPv6 chain, e. g. \fIblocktype?family=inet6\fR.
Examples:
.RS
.nf
# pass blocktype to DROP for all chains:
banaction_allports = iptables-ipset[type=allports, blocktype=DROP]
# pass different blocktype for IPv4 and IPv6 chains:
banaction = iptables-ipset[type=multiport, blocktype="REJECT --reject-with icmp-host-unreachable", blocktype?family=inet6="REJECT --reject-with icmp6-host-unreachable"]
.fi
.RE
.RE
.TP
.B ignoreself
boolean value (default true) indicates the banning of own IP addresses should be prevented