mirror of
https://github.com/docker-mailserver/docker-mailserver.git
synced 2024-01-19 02:48:50 +00:00
firewall: replace iptables
with nftables
(#2505)
* first adjustments to use Fail2Ban with nftables * replace `iptables` -> `nftables` and adjust tests nftables lists IPs a bit differently , so the order was adjusted for the tests to be more flexible. * line correction in mailserver.env * change from `.conf` -> `.local` and remove redundant config * revert HEREDOC to `echo` Co-authored-by: Casper <casperklein@users.noreply.github.com>
This commit is contained in:
parent
7c150402a0
commit
a9305a073f
|
@ -55,10 +55,10 @@ RUN \
|
||||||
dovecot-ldap dovecot-lmtpd dovecot-managesieved dovecot-pop3d \
|
dovecot-ldap dovecot-lmtpd dovecot-managesieved dovecot-pop3d \
|
||||||
dovecot-sieve dovecot-solr dumb-init \
|
dovecot-sieve dovecot-solr dumb-init \
|
||||||
# E - O
|
# E - O
|
||||||
ed fetchmail file gamin gnupg gzip iproute2 iptables \
|
ed fetchmail file gamin gnupg gzip iproute2 \
|
||||||
locales logwatch lhasa libdate-manip-perl libldap-common liblz4-tool \
|
locales logwatch lhasa libdate-manip-perl libldap-common liblz4-tool \
|
||||||
libmail-spf-perl libnet-dns-perl libsasl2-modules lrzip lzop \
|
libmail-spf-perl libnet-dns-perl libsasl2-modules lrzip lzop \
|
||||||
netcat-openbsd nomarch opendkim opendkim-tools opendmarc \
|
netcat-openbsd nftables nomarch opendkim opendkim-tools opendmarc \
|
||||||
# P - Z
|
# P - Z
|
||||||
pax pflogsumm postgrey p7zip-full postfix-ldap postfix-pcre \
|
pax pflogsumm postgrey p7zip-full postfix-ldap postfix-pcre \
|
||||||
postfix-policyd-spf-python postsrsd pyzor \
|
postfix-policyd-spf-python postsrsd pyzor \
|
||||||
|
@ -194,11 +194,6 @@ COPY target/opendmarc/opendmarc.conf /etc/opendmarc.conf
|
||||||
COPY target/opendmarc/default-opendmarc /etc/default/opendmarc
|
COPY target/opendmarc/default-opendmarc /etc/default/opendmarc
|
||||||
COPY target/opendmarc/ignore.hosts /etc/opendmarc/ignore.hosts
|
COPY target/opendmarc/ignore.hosts /etc/opendmarc/ignore.hosts
|
||||||
|
|
||||||
RUN \
|
|
||||||
# switch iptables and ip6tables to legacy for Fail2Ban
|
|
||||||
update-alternatives --set iptables /usr/sbin/iptables-legacy && \
|
|
||||||
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
|
|
||||||
|
|
||||||
# -----------------------------------------------
|
# -----------------------------------------------
|
||||||
# --- Fetchmail, Postfix & Let'sEncrypt ---------
|
# --- Fetchmail, Postfix & Let'sEncrypt ---------
|
||||||
# -----------------------------------------------
|
# -----------------------------------------------
|
||||||
|
|
|
@ -16,6 +16,6 @@
|
||||||
#ignoreip = 127.0.0.1/8
|
#ignoreip = 127.0.0.1/8
|
||||||
|
|
||||||
# Default ban action
|
# Default ban action
|
||||||
# iptables-multiport: block IP only on affected port
|
# nftables-multiport: block IP only on affected port
|
||||||
# iptables-allports: block IP on all ports
|
# nftables-allports: block IP on all ports
|
||||||
#banaction = iptables-allports
|
#banaction = nftables-allports
|
||||||
|
|
|
@ -100,7 +100,7 @@ cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
```
|
```
|
||||||
|
|
||||||
Otherwise, `iptables` won't be able to ban IPs.
|
Otherwise, `nftables` won't be able to ban IPs.
|
||||||
|
|
||||||
##### FAIL2BAN_BLOCKTYPE
|
##### FAIL2BAN_BLOCKTYPE
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ Example configuration volume bind:
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! attention
|
!!! attention
|
||||||
`docker-mailserver` must be launched with the `NET_ADMIN` capability in order to be able to install the iptable rules that actually ban IP addresses.
|
`docker-mailserver` must be launched with the `NET_ADMIN` capability in order to be able to install the nftables rules that actually ban IP addresses.
|
||||||
|
|
||||||
Thus either include `--cap-add=NET_ADMIN` in the `docker run` command, or the equivalent in `docker-compose.yml`:
|
Thus either include `--cap-add=NET_ADMIN` in the `docker run` command, or the equivalent in `docker-compose.yml`:
|
||||||
|
|
||||||
|
@ -38,16 +38,6 @@ Example configuration volume bind:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
```
|
```
|
||||||
|
|
||||||
If you don't you will see errors the form of:
|
|
||||||
|
|
||||||
```log
|
|
||||||
iptables -w -X f2b-postfix -- stderr: "getsockopt failed strangely: Operation not permitted\niptables v1.4.21: can't initialize iptabl
|
|
||||||
es table `filter': Permission denied (you must be root)\nPerhaps iptables or your kernel needs to be upgraded.\niptables v1.4.21: can'
|
|
||||||
t initialize iptables table `filter': Permission denied (you must be root)\nPerhaps iptables or your kernel needs to be upgraded.\n"
|
|
||||||
2016-06-01 00:53:51,284 fail2ban.action [678]: ERROR iptables -w -D INPUT -p tcp -m multiport --dports smtp,465,submission -
|
|
||||||
j f2b-postfix
|
|
||||||
```
|
|
||||||
|
|
||||||
## Running fail2ban in a rootless container
|
## Running fail2ban in a rootless container
|
||||||
|
|
||||||
[`RootlessKit`][rootless::rootless-kit] is the _fakeroot_ implementation for supporting _rootless mode_ in Docker and Podman. By default RootlessKit uses the [`builtin` port forwarding driver][rootless::port-drivers], which does not propagate source IP addresses.
|
[`RootlessKit`][rootless::rootless-kit] is the _fakeroot_ implementation for supporting _rootless mode_ in Docker and Podman. By default RootlessKit uses the [`builtin` port forwarding driver][rootless::port-drivers], which does not propagate source IP addresses.
|
||||||
|
|
|
@ -112,7 +112,7 @@ ENABLE_DNSBL=0
|
||||||
# If you enable Fail2Ban, don't forget to add the following lines to your `docker-compose.yml`:
|
# If you enable Fail2Ban, don't forget to add the following lines to your `docker-compose.yml`:
|
||||||
# cap_add:
|
# cap_add:
|
||||||
# - NET_ADMIN
|
# - NET_ADMIN
|
||||||
# Otherwise, `iptables` won't be able to ban IPs.
|
# Otherwise, `nftables` won't be able to ban IPs.
|
||||||
ENABLE_FAIL2BAN=0
|
ENABLE_FAIL2BAN=0
|
||||||
|
|
||||||
# Fail2Ban blocktype
|
# Fail2Ban blocktype
|
||||||
|
|
|
@ -3,26 +3,12 @@
|
||||||
# shellcheck source=../scripts/helpers/index.sh
|
# shellcheck source=../scripts/helpers/index.sh
|
||||||
source /usr/local/bin/helpers/index.sh
|
source /usr/local/bin/helpers/index.sh
|
||||||
|
|
||||||
if ! IPTABLES_OUTPUT=$(iptables -L -n 2>&1)
|
|
||||||
then
|
|
||||||
_exit_with_error "IPTables is not functioning correctly
|
|
||||||
|
|
||||||
The output of \`iptables -L\` was:
|
|
||||||
|
|
||||||
${IPTABLES_OUTPUT}
|
|
||||||
|
|
||||||
Possible causes for this error are
|
|
||||||
|
|
||||||
1. Missing capabilities (you need CAP_NET_RAW & CAP_NET_ADMIN, see \`capsh --print\`)
|
|
||||||
2. Modifications caused by user-patches.sh
|
|
||||||
3. Host is configured incorrectly
|
|
||||||
"
|
|
||||||
fi
|
|
||||||
|
|
||||||
function __usage { echo "Usage: ${0} [<unban> <ip-address>]" ; }
|
function __usage { echo "Usage: ${0} [<unban> <ip-address>]" ; }
|
||||||
|
|
||||||
unset JAILS
|
unset JAILS
|
||||||
declare -a JAILS
|
declare -a JAILS
|
||||||
|
IP_REGEXP='((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
|
||||||
|
|
||||||
for LIST in $(fail2ban-client status | grep "Jail list" | cut -f2- | sed 's/,/ /g')
|
for LIST in $(fail2ban-client status | grep "Jail list" | cut -f2- | sed 's/,/ /g')
|
||||||
do
|
do
|
||||||
JAILS+=("${LIST}")
|
JAILS+=("${LIST}")
|
||||||
|
@ -30,25 +16,22 @@ done
|
||||||
|
|
||||||
if [[ -z ${1} ]]
|
if [[ -z ${1} ]]
|
||||||
then
|
then
|
||||||
|
IPS_BANNED=0
|
||||||
IP_COUNT=0
|
|
||||||
|
|
||||||
for JAIL in "${JAILS[@]}"
|
for JAIL in "${JAILS[@]}"
|
||||||
do
|
do
|
||||||
BANNED_IP="$(iptables -L "f2b-${JAIL}" -n 2>/dev/null | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -v '0.0.0.0')"
|
BANNED_IPS=$(fail2ban-client status "${JAIL}" \
|
||||||
|
| grep 'Banned IP list' \
|
||||||
|
| grep -oE "${IP_REGEXP}")
|
||||||
|
|
||||||
if [[ -n ${BANNED_IP} ]]
|
if [[ -n ${BANNED_IPS} ]]
|
||||||
then
|
then
|
||||||
echo "Banned in ${JAIL}: ${BANNED_IP//$'\n'/, }"
|
echo "Banned in ${JAIL}: ${BANNED_IPS//$'\n'/, }"
|
||||||
IP_COUNT=$(( IP_COUNT + 1 ))
|
IPS_BANNED=1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ ${IP_COUNT} -eq 0 ]]
|
[[ ${IPS_BANNED} -eq 0 ]] && _log 'info' "No IPs have been banned"
|
||||||
then
|
|
||||||
_log 'info' 'No IPs have been banned'
|
|
||||||
fi
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
case "${1}" in
|
case "${1}" in
|
||||||
|
|
|
@ -15,10 +15,10 @@ maxretry = 3
|
||||||
# can be defined using space (and/or comma) separator.
|
# can be defined using space (and/or comma) separator.
|
||||||
ignoreip = 127.0.0.1/8
|
ignoreip = 127.0.0.1/8
|
||||||
|
|
||||||
# Default ban action
|
# default ban action
|
||||||
# iptables-multiport: block IP only on affected port
|
# nftables-multiport: block IP only on affected port
|
||||||
# iptables-allports: block IP on all ports
|
# nftables-allports: block IP on all ports
|
||||||
banaction = iptables-allports
|
banaction = nftables-allports
|
||||||
|
|
||||||
[dovecot]
|
[dovecot]
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
|
@ -1144,7 +1144,7 @@ function _setup_fail2ban
|
||||||
_log 'debug' 'Setting up Fail2Ban'
|
_log 'debug' 'Setting up Fail2Ban'
|
||||||
if [[ ${FAIL2BAN_BLOCKTYPE} != 'reject' ]]
|
if [[ ${FAIL2BAN_BLOCKTYPE} != 'reject' ]]
|
||||||
then
|
then
|
||||||
echo -e '[Init]\nblocktype = DROP' >/etc/fail2ban/action.d/iptables-common.local
|
echo -e '[Init]\nblocktype = drop' >/etc/fail2ban/action.d/nftables-common.local
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,6 @@ findtime = 321
|
||||||
maxretry = 2
|
maxretry = 2
|
||||||
|
|
||||||
# Default ban action
|
# Default ban action
|
||||||
# iptables-multiport: block IP only on affected port
|
# nftables-multiport: block IP only on affected port
|
||||||
# iptables-allports: block IP on all ports
|
# nftables-allports: block IP on all ports
|
||||||
banaction = iptables-multiport
|
banaction = nftables-multiport
|
||||||
|
|
|
@ -64,14 +64,14 @@ function teardown_file() {
|
||||||
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client get ${FILTER} maxretry"
|
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client get ${FILTER} maxretry"
|
||||||
assert_output 2
|
assert_output 2
|
||||||
|
|
||||||
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client -d | grep -F \"['set', 'dovecot', 'addaction', 'iptables-multiport']\""
|
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client -d | grep -F \"['set', 'dovecot', 'addaction', 'nftables-multiport']\""
|
||||||
assert_output "['set', 'dovecot', 'addaction', 'iptables-multiport']"
|
assert_output "['set', 'dovecot', 'addaction', 'nftables-multiport']"
|
||||||
|
|
||||||
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client -d | grep -F \"['set', 'postfix', 'addaction', 'iptables-multiport']\""
|
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client -d | grep -F \"['set', 'postfix', 'addaction', 'nftables-multiport']\""
|
||||||
assert_output "['set', 'postfix', 'addaction', 'iptables-multiport']"
|
assert_output "['set', 'postfix', 'addaction', 'nftables-multiport']"
|
||||||
|
|
||||||
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client -d | grep -F \"['set', 'postfix-sasl', 'addaction', 'iptables-multiport']\""
|
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client -d | grep -F \"['set', 'postfix-sasl', 'addaction', 'nftables-multiport']\""
|
||||||
assert_output "['set', 'postfix-sasl', 'addaction', 'iptables-multiport']"
|
assert_output "['set', 'postfix-sasl', 'addaction', 'nftables-multiport']"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +96,9 @@ function teardown_file() {
|
||||||
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status postfix-sasl | grep '${FAIL_AUTH_MAILER_IP}'"
|
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status postfix-sasl | grep '${FAIL_AUTH_MAILER_IP}'"
|
||||||
assert_success
|
assert_success
|
||||||
|
|
||||||
# Checking that FAIL_AUTH_MAILER_IP is banned by iptables and blocktype set to DROP
|
# Checking that FAIL_AUTH_MAILER_IP is banned by nftables and blocktype set to DROP
|
||||||
run docker exec mail_fail2ban /bin/sh -c "iptables -n -L f2b-postfix-sasl"
|
run docker exec mail_fail2ban /bin/sh -c "nft list set inet f2b-table addr-set-postfix-sasl 2>/dev/null"
|
||||||
assert_output --regexp "DROP.+all.+${FAIL_AUTH_MAILER_IP}"
|
assert_output --regexp "${FAIL_AUTH_MAILER_IP}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "checking fail2ban: unban ip works" {
|
@test "checking fail2ban: unban ip works" {
|
||||||
|
@ -111,9 +111,9 @@ function teardown_file() {
|
||||||
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status postfix-sasl | grep 'IP list:.*${FAIL_AUTH_MAILER_IP}'"
|
run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status postfix-sasl | grep 'IP list:.*${FAIL_AUTH_MAILER_IP}'"
|
||||||
assert_failure
|
assert_failure
|
||||||
|
|
||||||
# Checking that FAIL_AUTH_MAILER_IP is unbanned by iptables
|
# Checking that FAIL_AUTH_MAILER_IP is unbanned by nftables
|
||||||
run docker exec mail_fail2ban /bin/sh -c "iptables -L f2b-postfix-sasl -n | grep REJECT | grep '${FAIL_AUTH_MAILER_IP}'"
|
run docker exec mail_fail2ban /bin/sh -c "nft list set inet f2b-table addr-set-postfix-sasl 2>/dev/null"
|
||||||
assert_failure
|
refute_output "${FAIL_AUTH_MAILER_IP}"
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -128,13 +128,15 @@ function teardown_file() {
|
||||||
sleep 10
|
sleep 10
|
||||||
|
|
||||||
run ./setup.sh -c mail_fail2ban debug fail2ban
|
run ./setup.sh -c mail_fail2ban debug fail2ban
|
||||||
assert_output --regexp "^Banned in dovecot: 192.0.66.5, 192.0.66.4.*"
|
assert_output --partial 'Banned in dovecot:'
|
||||||
|
assert_output --partial '192.0.66.5'
|
||||||
|
assert_output --partial '192.0.66.4'
|
||||||
|
|
||||||
run ./setup.sh -c mail_fail2ban debug fail2ban unban 192.0.66.4
|
run ./setup.sh -c mail_fail2ban debug fail2ban unban 192.0.66.4
|
||||||
assert_output --partial "Unbanned IP from dovecot: 1"
|
assert_output --partial "Unbanned IP from dovecot: 1"
|
||||||
|
|
||||||
run ./setup.sh -c mail_fail2ban debug fail2ban
|
run ./setup.sh -c mail_fail2ban debug fail2ban
|
||||||
assert_output --regexp "^Banned in dovecot: 192.0.66.5.*"
|
assert_output --regexp "^Banned in dovecot:.*192.0.66.5.*"
|
||||||
|
|
||||||
run ./setup.sh -c mail_fail2ban debug fail2ban unban 192.0.66.5
|
run ./setup.sh -c mail_fail2ban debug fail2ban unban 192.0.66.5
|
||||||
assert_output --partial "Unbanned IP from dovecot: 1"
|
assert_output --partial "Unbanned IP from dovecot: 1"
|
||||||
|
|
Loading…
Reference in a new issue