Files
infrastructure/roles/fail2ban/templates/firewallcmd-ipset-allports.conf.j2
Levente PolyakandChristian Heusel ff6c360a34 fail2ban: permanently store entries in firewalld to survive reload
The runtime and the permanent sets are distinct, which means if we only
keep adding them to the runtime ipset but later on need to restart or
reload firewalld, it means all entries are lost. This is quite a problem
as we have a diverged stateful ban between firewalld and fail2ban, which
leads to fail2ban thinking an ip is already banned while firewalld just
doesn't have the entry anymore.

Avoid this loophole by also adding all entries to the permanent set and
subsequently remove the window of opportunity for a state mismatch due
to reloads. Let fail2ban handle the stateful decision if an ip should be
removed or not, while firewalld should make sure it isn't silently
discarded without fail2ban being aware of it.
2025-10-13 19:09:13 +02:00

26 lines
1.2 KiB
Django/Jinja

#
# {{ansible_managed}}
#
[Definition]
# As we have two separate ipsets for IPv4 and IPv6 we need to specify two
# different ban actions.
# The 'sed' command below returns the following:
#
# echo "2a01:4f9:c010:6b1f::1/64" | sed "s/^.*:.*$/6/;s/^.*\..*//" => "6"
# echo "94.31.75.247" | sed "s/^.*:.*$/6/;s/^.*\..*//" => ""
#
# We can therefore use this output to select either the "fail2ban" or
# "fail2ban6" ipset.
#
# Afterwards, cut existing connections using conntrack as the firewalld ipset rules are
# only checked after the fast-track for ESTABLISHED,RELATED connection states.
actionban = firewall-cmd --ipset=fail2ban$(echo '<ip>' | sed "s/^.*:.*$/6/;s/^.*\..*//") --add-entry=<ip> ; \
firewall-cmd --ipset=fail2ban$(echo '<ip>' | sed "s/^.*:.*$/6/;s/^.*\..*//") --add-entry=<ip> --permanent ; \
conntrack -D -s '<ip>' -p tcp || true ; \
conntrack -D -d '<ip>' -p tcp || true
actionunban = firewall-cmd --ipset=fail2ban$(echo '<ip>' | sed "s/^.*:.*$/6/;s/^.*\..*//") --remove-entry=<ip> ;\
firewall-cmd --ipset=fail2ban$(echo '<ip>' | sed "s/^.*:.*$/6/;s/^.*\..*//") --remove-entry=<ip> --permanent