diff --git a/Dockerfile b/Dockerfile index a9e211cc..8f3cb5cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,9 +24,12 @@ RUN adduser clamav amavis RUN adduser amavis clamav RUN useradd -u 5000 -d /home/docker -s /bin/bash -p $(echo docker | openssl passwd -1 -stdin) docker +# Configure Fail2ban +ADD target/fail2ban/jail.conf /etc/fail2ban/jail.conf + # Enables Clamav RUN chmod 644 /etc/clamav/freshclam.conf -RUN (crontab -l ; echo "0 1 * * * /usr/bin/freshclam --quiet") | sort - | uniq - | crontab - +RUN (crontab; echo "0 1 * * * /usr/bin/freshclam --quiet") | sort - | uniq - | crontab - RUN freshclam # Configure DKIM (opendkim) diff --git a/Makefile b/Makefile index e9af7d82..f62c1a8b 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ NAME = tvial/docker-mailserver:$(BRANCH) all: build-no-cache run fixtures tests clean all-fast: build run fixtures tests clean +no-build: run fixtures tests clean build-no-cache: docker build --no-cache -t $(NAME) . @@ -58,4 +59,4 @@ tests: clean: # Remove running test containers - docker rm -f mail mail_pop3 mail_smtponly mail_fail2ban + docker rm -f mail mail_pop3 mail_smtponly mail_fail2ban fail-auth-mailer diff --git a/target/fail2ban/jail.conf b/target/fail2ban/jail.conf new file mode 100644 index 00000000..37c39af9 --- /dev/null +++ b/target/fail2ban/jail.conf @@ -0,0 +1,163 @@ +# Fail2Ban configuration file. +# +# This file was composed for Debian systems from the original one +# provided now under /usr/share/doc/fail2ban/examples/jail.conf +# for additional examples. +# +# Comments: use '#' for comment lines and ';' for inline comments +# +# To avoid merges during upgrades DO NOT MODIFY THIS FILE +# and rather provide your changes in /etc/fail2ban/jail.local +# + +# The DEFAULT allows a global definition of the options. They can be overridden +# in each jail afterwards. + +[DEFAULT] + +# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not +# ban a host which matches an address in this list. Several addresses can be +# defined using space separator. +ignoreip = 127.0.0.1/8 + +# "bantime" is the number of seconds that a host is banned. +bantime = 10800 + +# A host is banned if it has generated "maxretry" during the last "findtime" +# seconds. +findtime = 10800 +maxretry = 3 + +# "backend" specifies the backend used to get files modification. +# Available options are "pyinotify", "gamin", "polling" and "auto". +# This option can be overridden in each jail as well. +# +# pyinotify: requires pyinotify (a file alteration monitor) to be installed. +# If pyinotify is not installed, Fail2ban will use auto. +# gamin: requires Gamin (a file alteration monitor) to be installed. +# If Gamin is not installed, Fail2ban will use auto. +# polling: uses a polling algorithm which does not require external libraries. +# auto: will try to use the following backends, in order: +# pyinotify, gamin, polling. +backend = gamin + +# "usedns" specifies if jails should trust hostnames in logs, +# warn when reverse DNS lookups are performed, or ignore all hostnames in logs +# +# yes: if a hostname is encountered, a reverse DNS lookup will be performed. +# warn: if a hostname is encountered, a reverse DNS lookup will be performed, +# but it will be logged as a warning. +# no: if a hostname is encountered, will not be used for banning, +# but it will be logged as info. +usedns = warn + +# +# Destination email address used solely for the interpolations in +# jail.{conf,local} configuration files. +destemail = root@localhost + +# +# Name of the sender for mta actions +sendername = Fail2Ban + +# +# ACTIONS +# + +# Default banning action (e.g. iptables, iptables-new, +# iptables-multiport, shorewall, etc) It is used to define +# action_* variables. Can be overridden globally or per +# section within jail.local file +banaction = iptables-multiport + +# email action. Since 0.8.1 upstream fail2ban uses sendmail +# MTA for the mailing. Change mta configuration parameter to mail +# if you want to revert to conventional 'mail'. +mta = sendmail + +# Default protocol +protocol = tcp + +# Specify chain where jumps would need to be added in iptables-* actions +chain = INPUT + +# +# Action shortcuts. To be used to define action parameter + +# The simplest action to take: ban only +action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + +# ban & send an e-mail with whois report to the destemail. +action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s", sendername="%(sendername)s"] + +# ban & send an e-mail with whois report and relevant log lines +# to the destemail. +action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + %(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s", sendername="%(sendername)s"] + +# Choose default action. To change, just override value of 'action' with the +# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local +# globally (section [DEFAULT]) or per specific section +action = %(action_)s + +# +# JAILS +# + +[ssh] + +enabled = true +port = ssh +filter = sshd +logpath = /var/log/auth.log +maxretry = 6 + +# +# Mail servers +# + +[postfix] + +enabled = true +port = smtp,ssmtp,submission +filter = postfix +logpath = /var/log/mail/mail.log + +# +# Mail servers authenticators: might be used for smtp,ftp,imap servers, so +# all relevant ports get banned +# + +[sasl] + +enabled = true +port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s +filter = postfix-sasl +# You might consider monitoring /var/log/mail.warn instead if you are +# running postfix since it would provide the same log lines at the +# "warn" level but overall at the smaller filesize. +logpath = /var/log/mail/mail.log + +[dovecot] + +enabled = true +port = smtp,ssmtp,submission,imap2,imap3,imaps,pop3,pop3s +filter = dovecot +logpath = /var/log/mail/mail.log + +# Jail for more extended banning of persistent abusers +# !!! WARNING !!! +# Make sure that your loglevel specified in fail2ban.conf/.local +# is not at DEBUG level -- which might then cause fail2ban to fall into +# an infinite loop constantly feeding itself with non-informative lines +[recidive] + +enabled = false +filter = recidive +logpath = /var/log/fail2ban.log +action = iptables-allports[name=recidive] + sendmail-whois-lines[name=recidive, logpath=/var/log/fail2ban.log] +bantime = 10800 +findtime = 10800 +maxretry = 5 diff --git a/test/tests.bats b/test/tests.bats index 02df01ae..d2a4a179 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -292,27 +292,33 @@ # fail2ban # -@test "checking fail2ban: localhost is not banned" { +@test "checking fail2ban: localhost is not banned because ignored" { run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status sasl | grep 'IP list:.*127.0.0.1'" [ "$status" -eq 1 ] + run docker exec mail_fail2ban /bin/sh -c "grep 'ignoreip = 127.0.0.1/8' /etc/fail2ban/jail.conf" + [ "$status" -eq 0 ] } @test "checking fail2ban: ban ip on multiple failed login" { - docker exec mail_fail2ban fail2ban-client status sasl - docker exec mail_fail2ban fail2ban-client set sasl delignoreip 127.0.0.1/8 - docker exec mail_fail2ban /bin/sh -c 'nc -w 1 0.0.0.0 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' - docker exec mail_fail2ban /bin/sh -c 'nc -w 1 0.0.0.0 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' - docker exec mail_fail2ban /bin/sh -c 'nc -w 1 0.0.0.0 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' - sleep 5 - run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status sasl | grep 'IP list:.*127.0.0.1'" + # Getting mail_fail2ban container IP + MAIL_FAIL2BAN_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mail_fail2ban) + # Create a container which will send wront authentications and should banned + docker run --name fail-auth-mailer -e MAIL_FAIL2BAN_IP=$MAIL_FAIL2BAN_IP -v "$(pwd)/test":/tmp/docker-mailserver/test -d tvial/docker-mailserver:v2 tail -f /var/log/faillog + FAIL_AUTH_MAILER_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' fail-auth-mailer) + docker exec fail-auth-mailer /bin/sh -c 'nc -w 1 $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' + docker exec fail-auth-mailer /bin/sh -c 'nc -w 1 $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' + docker exec fail-auth-mailer /bin/sh -c 'nc -w 1 $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' + docker exec fail-auth-mailer /bin/sh -c 'nc -w 1 $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' + sleep 10 + # Checking that FAIL_AUTH_MAILER_IP is banned in mail_fail2ban + run docker exec mail_fail2ban /bin/sh -c "export FAIL_AUTH_MAILER_IP=$FAIL_AUTH_MAILER_IP && fail2ban-client status sasl | grep '$FAIL_AUTH_MAILER_IP' " [ "$status" -eq 0 ] } @test "checking fail2ban: unban ip works" { - docker exec mail_fail2ban fail2ban-client set sasl addignoreip 127.0.0.1/8 - docker exec mail_fail2ban fail2ban-client set sasl unbanip 127.0.0.1 + docker exec mail_fail2ban fail2ban-client set sasl unbanip $FAIL_AUTH_MAILER_IP sleep 5 - run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status sasl | grep 'IP list:.*127.0.0.1'" + run docker exec mail_fail2ban /bin/sh -c "fail2ban-client status sasl | grep 'IP list:.*$FAIL_AUTH_MAILER_IP'" [ "$status" -eq 1 ] }