diff --git a/.gitignore b/.gitignore index 20cfed61..b7eb58c0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,3 @@ docker-compose.yml postfix/ssl/* letsencrypt/ .idea -config/tmp \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 6689ddb4..0887f092 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,8 +34,6 @@ RUN (crontab; echo "0 1 * * * /usr/bin/freshclam --quiet") | sort - | uniq - | c RUN freshclam # Configure DKIM (opendkim) -RUN mkdir -p /etc/opendkim/keys -ADD target/opendkim/TrustedHosts /etc/opendkim/TrustedHosts # DKIM config files ADD target/opendkim/opendkim.conf /etc/opendkim.conf ADD target/opendkim/default-opendkim /etc/default/opendkim diff --git a/Makefile b/Makefile index 4d44510c..669afa3f 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,7 @@ run: # Run containers docker run -d --name mail \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test/config/test-opendkim":/tmp/docker-mailserver/opendkim \ - -v "`pwd`/test":/tmp/docker-mailserver/test \ + -v "`pwd`/test":/tmp/docker-mailserver-test \ -e SA_TAG=1.0 \ -e SA_TAG2=2.0 \ -e SA_KILL=3.0 \ @@ -25,19 +24,19 @@ run: sleep 15 docker run -d --name mail_pop3 \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver/test \ + -v "`pwd`/test":/tmp/docker-mailserver-test \ -e ENABLE_POP3=1 \ -h mail.my-domain.com -t $(NAME) sleep 15 docker run -d --name mail_smtponly \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver/test \ + -v "`pwd`/test":/tmp/docker-mailserver-test \ -e SMTP_ONLY=1 \ -h mail.my-domain.com -t $(NAME) sleep 15 docker run -d --name mail_fail2ban \ -v "`pwd`/test/config":/tmp/docker-mailserver \ - -v "`pwd`/test":/tmp/docker-mailserver/test \ + -v "`pwd`/test":/tmp/docker-mailserver-test \ -e ENABLE_FAIL2BAN=1 \ -h mail.my-domain.com -t $(NAME) # Wait for containers to fully start @@ -45,12 +44,12 @@ run: fixtures: # Sending test mails - docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver/test/email-templates/amavis-spam.txt" - docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver/test/email-templates/amavis-virus.txt" - docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver/test/email-templates/existing-alias-external.txt" - docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver/test/email-templates/existing-alias-local.txt" - docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver/test/email-templates/existing-user.txt" - docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver/test/email-templates/non-existing-user.txt" + docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/amavis-spam.txt" + docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/amavis-virus.txt" + docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-alias-external.txt" + docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-alias-local.txt" + docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user.txt" + docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/non-existing-user.txt" # Wait for mails to be analyzed sleep 10 @@ -61,4 +60,4 @@ tests: clean: # Remove running test containers docker rm -f mail mail_pop3 mail_smtponly mail_fail2ban fail-auth-mailer - rm -rf config/opendkim config/test-opendkim config/tmp + rm -rf "$(pwd)/test/config/empty" && mkdir -p "$(pwd)/test/config/empty" diff --git a/target/bin/generate-dkim-config b/target/bin/generate-dkim-config index 07e79fe7..19e6be9d 100644 --- a/target/bin/generate-dkim-config +++ b/target/bin/generate-dkim-config @@ -1,10 +1,12 @@ #!/bin/sh +touch /tmp/vhost.tmp + # Getting domains from mail accounts while IFS=$'|' read login pass do domain=$(echo ${login} | cut -d @ -f2) - echo ${domain} >> /tmp/docker-mailserver/tmp/vhost.tmp + echo ${domain} >> /tmp/vhost.tmp done < /tmp/docker-mailserver/postfix-accounts.cf # Getting domains from mail aliases @@ -14,15 +16,15 @@ do uname=$(echo ${from} | cut -d @ -f1) domain=$(echo ${from} | cut -d @ -f2) # if they are equal it means the line looks like: "user1 other@domain.tld" - test "$uname" != "$domain" && echo ${domain} >> /tmp/docker-mailserver/tmp/vhost.tmp + test "$uname" != "$domain" && echo ${domain} >> /tmp/vhost.tmp done < /tmp/docker-mailserver/postfix-virtual.cf # Keeping unique entries -if [ -f /tmp/docker-mailserver/tmp/vhost.tmp ]; then - cat /tmp/docker-mailserver/tmp/vhost.tmp | sort | uniq > /etc/postfix/vhost && rm /tmp/docker-mailserver/tmp/vhost.tmp +if [ -f /tmp/vhost.tmp ]; then + cat /tmp/vhost.tmp | sort | uniq > /tmp/vhost && rm /tmp/vhost.tmp fi -grep -vE '^(\s*$|#)' /etc/postfix/vhost | while read domainname; do +grep -vE '^(\s*$|#)' /tmp/vhost | while read domainname; do mkdir -p /tmp/docker-mailserver/opendkim/keys/$domainname if [ ! -f "/tmp/docker-mailserver/opendkim/keys/$domainname/mail.private" ]; then @@ -53,3 +55,10 @@ grep -vE '^(\s*$|#)' /etc/postfix/vhost | while read domainname; do fi done +# Creates TrustedHosts if missing +if [ ! -f "/tmp/docker-mailserver/opendkim/TrustedHosts" ]; then + echo "Creating DKIM TrustedHosts"; + echo "127.0.0.1" > /tmp/docker-mailserver/opendkim/TrustedHosts + echo "localhost" >> /tmp/docker-mailserver/opendkim/TrustedHosts +fi + diff --git a/target/start-mailserver.sh b/target/start-mailserver.sh index e9d7a763..f8503633 100644 --- a/target/start-mailserver.sh +++ b/target/start-mailserver.sh @@ -5,12 +5,6 @@ die () { exit 1 } -# -# Preparing -# - -mkdir -p /tmp/docker-mailserver/tmp - # # Users # @@ -57,7 +51,7 @@ if [ -f /tmp/docker-mailserver/postfix-accounts.cf ]; then touch "/var/mail/${domain}/${user}/.Sent/maildirfolder" fi - echo ${domain} >> /tmp/docker-mailserver/tmp/vhost.tmp + echo ${domain} >> /tmp/vhost.tmp done < /tmp/docker-mailserver/postfix-accounts.cf else echo "==> Warning: 'config/docker-mailserver/postfix-accounts.cf' is not provided. No mail account created." @@ -75,14 +69,14 @@ if [ -f /tmp/docker-mailserver/postfix-virtual.cf ]; then uname=$(echo ${from} | cut -d @ -f1) domain=$(echo ${from} | cut -d @ -f2) # if they are equal it means the line looks like: "user1 other@domain.tld" - test "$uname" != "$domain" && echo ${domain} >> /tmp/docker-mailserver/tmp/vhost.tmp + test "$uname" != "$domain" && echo ${domain} >> /tmp/vhost.tmp done < /tmp/docker-mailserver/postfix-virtual.cf else echo "==> Warning: 'config/postfix-virtual.cf' is not provided. No mail alias/forward created." fi -if [ -f /tmp/docker-mailserver/tmp/vhost.tmp ]; then - cat /tmp/docker-mailserver/tmp/vhost.tmp | sort | uniq > /etc/postfix/vhost && rm /tmp/docker-mailserver/tmp/vhost.tmp +if [ -f /tmp/vhost.tmp ]; then + cat /tmp/vhost.tmp | sort | uniq > /etc/postfix/vhost && rm /tmp/vhost.tmp fi echo "Postfix configurations" diff --git a/test/config/test-opendkim/KeyTable b/test/config/opendkim/KeyTable similarity index 100% rename from test/config/test-opendkim/KeyTable rename to test/config/opendkim/KeyTable diff --git a/test/config/test-opendkim/SigningTable b/test/config/opendkim/SigningTable similarity index 100% rename from test/config/test-opendkim/SigningTable rename to test/config/opendkim/SigningTable diff --git a/target/opendkim/TrustedHosts b/test/config/opendkim/TrustedHosts similarity index 100% rename from target/opendkim/TrustedHosts rename to test/config/opendkim/TrustedHosts diff --git a/test/config/test-opendkim/keys/localhost.localdomain/mail.private b/test/config/opendkim/keys/localhost.localdomain/mail.private similarity index 100% rename from test/config/test-opendkim/keys/localhost.localdomain/mail.private rename to test/config/opendkim/keys/localhost.localdomain/mail.private diff --git a/test/config/test-opendkim/keys/localhost.localdomain/mail.txt b/test/config/opendkim/keys/localhost.localdomain/mail.txt similarity index 100% rename from test/config/test-opendkim/keys/localhost.localdomain/mail.txt rename to test/config/opendkim/keys/localhost.localdomain/mail.txt diff --git a/test/config/test-opendkim/keys/otherdomain.tld/mail.private b/test/config/opendkim/keys/otherdomain.tld/mail.private similarity index 100% rename from test/config/test-opendkim/keys/otherdomain.tld/mail.private rename to test/config/opendkim/keys/otherdomain.tld/mail.private diff --git a/test/config/test-opendkim/keys/otherdomain.tld/mail.txt b/test/config/opendkim/keys/otherdomain.tld/mail.txt similarity index 100% rename from test/config/test-opendkim/keys/otherdomain.tld/mail.txt rename to test/config/opendkim/keys/otherdomain.tld/mail.txt diff --git a/test/tests.bats b/test/tests.bats index 63d0690f..5c5ca49e 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -57,7 +57,7 @@ } @test "checking imap: authentication works" { - run docker exec mail /bin/sh -c "nc -w 1 0.0.0.0 143 < /tmp/docker-mailserver/test/auth/imap-auth.txt" + run docker exec mail /bin/sh -c "nc -w 1 0.0.0.0 143 < /tmp/docker-mailserver-test/auth/imap-auth.txt" [ "$status" -eq 0 ] } @@ -71,7 +71,7 @@ } @test "checking pop: authentication works" { - run docker exec mail_pop3 /bin/sh -c "nc -w 1 0.0.0.0 110 < /tmp/docker-mailserver/test/auth/pop3-auth.txt" + run docker exec mail_pop3 /bin/sh -c "nc -w 1 0.0.0.0 110 < /tmp/docker-mailserver-test/auth/pop3-auth.txt" [ "$status" -eq 0 ] } @@ -109,22 +109,22 @@ # @test "checking smtp: authentication works with good password (plain)" { - run docker exec mail /bin/sh -c "nc -w 5 0.0.0.0 25 < /tmp/docker-mailserver/test/auth/smtp-auth-plain.txt | grep 'Authentication successful'" + run docker exec mail /bin/sh -c "nc -w 5 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/smtp-auth-plain.txt | grep 'Authentication successful'" [ "$status" -eq 0 ] } @test "checking smtp: authentication fails with wrong password (plain)" { - run docker exec mail /bin/sh -c "nc -w 20 0.0.0.0 25 < /tmp/docker-mailserver/test/auth/smtp-auth-plain-wrong.txt | grep 'authentication failed'" + run docker exec mail /bin/sh -c "nc -w 20 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/smtp-auth-plain-wrong.txt | grep 'authentication failed'" [ "$status" -eq 0 ] } @test "checking smtp: authentication works with good password (login)" { - run docker exec mail /bin/sh -c "nc -w 5 0.0.0.0 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login.txt | grep 'Authentication successful'" + run docker exec mail /bin/sh -c "nc -w 5 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login.txt | grep 'Authentication successful'" [ "$status" -eq 0 ] } @test "checking smtp: authentication fails with wrong password (login)" { - run docker exec mail /bin/sh -c "nc -w 20 0.0.0.0 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt | grep 'authentication failed'" + run docker exec mail /bin/sh -c "nc -w 20 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login-wrong.txt | grep 'authentication failed'" [ "$status" -eq 0 ] } @@ -249,18 +249,15 @@ [ "$output" -eq 2 ] } -@test "checking opendkim: /etc/opendkim/KeyTable should not exist because not provided" { - run docker exec mail_smtponly /bin/sh -c "cat /etc/opendkim/KeyTable" - [ "$status" -eq 1 ] -} - -@test "checking opendkim: generator works as expected" { +@test "checking opendkim: generator creates keys, tables and TrustedHosts" { run docker run --rm \ - -v "$(pwd)/config":/tmp/docker-mailserver \ - -v "$(pwd)/config/test-opendkim":/tmp/docker-mailserver/opendkim \ + -v "$(pwd)/test/config/empty/":/tmp/docker-mailserver/ \ + -v "$(pwd)/test/config/postfix-accounts.cf":/tmp/docker-mailserver/postfix-accounts.cf \ + -v "$(pwd)/test/config/postfix-virtual.cf":/tmp/docker-mailserver/postfix-virtual.cf \ -ti tvial/docker-mailserver:v2 generate-dkim-config | wc -l [ "$status" -eq 0 ] - [ "$output" -eq 4 ] + [ "$output" -eq 5 ] + rm -rf "$(pwd)/test/config/empty" && mkdir -p "$(pwd)/test/config/empty" } # @@ -317,12 +314,12 @@ # 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 - docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' - docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' - docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' - docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' - docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver/test/auth/smtp-auth-login-wrong.txt' + 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 + docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login-wrong.txt' + docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login-wrong.txt' + docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login-wrong.txt' + docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login-wrong.txt' + docker exec fail-auth-mailer /bin/sh -c 'nc $MAIL_FAIL2BAN_IP 25 < /tmp/docker-mailserver-test/auth/smtp-auth-login-wrong.txt' sleep 5 # Checking that FAIL_AUTH_MAILER_IP is banned in mail_fail2ban FAIL_AUTH_MAILER_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' fail-auth-mailer)