Docker Mailserver selbst betreiben | ein Erfahrungsbericht

Mit Hilfe eines geeigneten Docker-Images ist es relativ einfach einen Mailserver selbst zu betreiben. Ursprünglich habe ich den integrierten Mailserver des Hosteurope vServers (Plesk) verwendet und bin bei der Suche nach einem Ersatz auf einen sehr einfachen Docker-Container gestoßen. Der schlanke Container liefert einen Mailserver ohne grafische Verwaltungsoberfläche, kann aber mit wenigen einfachen Befehlen verwaltet werden. Für das Senden und Empfangen der Mails kann ein beliebiger Email-Client verwendet werden, dazu wird POP3 oder IMAP für das Empfangen und SMTP für das Versenden angeboten. Ob die Mails des eigenen Servers empfangen und zugestellt werden können hängt neben dem Setup auch von den richtigen DNS-Einstellungen ab.   

Docker Basics
Docker ermöglicht es, Applikationen per Befehl in einem sogenannten Container zu starten.
Ein Container ist eine vom Betriebssystem (OS) unabhängige isolierte Umgebung:
Das OS spielt also keine Rolle, vorausgesetzt Docker lässt sich installieren.
Beim ersten Start eines Containers, lädt Docker selbstständig alle notwendigen Quellen
aus dem Internet.
Docker kann unter Windows, macOS oder einer Linux-Distribution installiert werden,
siehe auch: Docker

Voraussetzung

Vorab habe ich Docker installiert, siehe: topic/docker und für die SSL-Zertifikate den nginx-proxy-companion im Einsatz: letsencrypt-nginx-proxy-companion.

Mailserver Inbetriebnahme

Als Mailserver habe ich das folgende GIT-Repository geklont:

git clone https://github.com/docker-mailserver/docker-mailserver.git mailserver
cd mailserver
wget -O .env https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/compose.env
chmod a+x ./setup.sh

Vor dem ersten Start sollte dann noch die .env Datei angepasst werden: Darin habe ich den Host-, Domain- und Container-Namen angepasst:

HOSTNAME=mailserver
DOMAINNAME=mailserver
CONTAINER_NAME=mailserver

Damit wäre der Server grundsätzlich einsatzbereit und könnte bereits gestartet werden. Könnte, denn für zusätzliche Einstellungen sollte auch noch kurz die Datei mailserver.env durchgesehen werden und darin benötigte Features aktiviert oder deaktiviert werden. Die Datei ist relativ gut kommentiert und dadurch weitestgehend selbsterklärend.

Der Start des Containers erfolgt dann mit dem Befehl "docker-compose up".

mailserver.env

Folgende Einstellungen habe ich in der mailserver.env - Datei angepasst:

OVERRIDE_HOSTNAME=domain.tld
POSTMASTER_ADDRESS=postmaster@domain.tld
ENABLE_FAIL2BAN=1
ENABLE_MANAGESIEVE=1
SSL_TYPE=letsencrypt
REPORT_RECIPIENT=1
ENABLE_SPAMASSASSIN=1
SRS_SENDER_CLASSES=envelope_sender,header_sender

Für SSL_TYPE=letsencrypt, siehe: ssl

Für ENABLE_MANAGESIEVE=1, siehe: SIEVE

Administration

Neue Email-Adressen oder Weiterleitungen können mit Hilfe des Setup-Skript erstellt werden. Das Script liefert beim Aufruf ohne Parameter eine kurze Hilfe: ./setup.sh 

Mail-Adressen anlegen

./setup.sh email add email@domain password

Nach dem ersten Anlegen einer Email-Adresse für eine neue Domain, kann der DKIM-Key für den DNS-Eintrag erstellt werden, siehe DKIM.

Alias anlegen (Weiterleitung)

./setup.sh alias add email@domain.tld weiterleitung@mail-adresse.ok

DKIM

Nachdem die ersten Mail-Adressen oder Weiterleitungen am System angelegt wurden, können mit folgendem Befehl DKIM Keys erzeugt werden:

./setup.sh config dkim

Die Keys werden für alle Domänen für die eine Email-Adresse oder Weiterleitung angelegt wurde in folgendem Ordner abgelegt: config/opendkim/keys/domain.tld/mail.txt. Die Keys sollten dann für den DNS-Eintrag verwendet werden:

DNS-Einträge

Für den Betrieb eines Mailservers sollte neben dem A- und MX-Record der DKIM-Key, ein SPF-Eintrag und eine DMARC-Policy im DNS erstellt werden. Der Domänenname: domain.tld  steht in folgenden Beispielen repräsentativ für die eigene Domäne. Die folgenden Einträge müssen in die DNS-Zone für domain.tld hinzugefügt werden:

A-Record

Type Name Value
A mail.domain.tld IP-Adresse des Webservers

Als Servername sollte in der Reverse-Lookup-Zone zudem mail.domain.tld hinterlegt werden, damit die IP-Adresse des Webservers auch auf mail.domain.tld auflöst. Bei einem vServer oder Cloud-Server eines Providers kann der Servername in der Admin Oberfläche des Providers festgelegt werden.

MX

Type Name Value
MX mail.domain.tld IP-Adresse des Webservers

Der MX-Record ist für das Zustellen der Mails zuständig. Alle Mails die @domain.tld als Domäne haben, werden an diesen Server zugestellt.

Der zuvor erstellte DKIM Key:

Type Name Value
TXT mail._domainkey.domain.tld "v=DKIM1; h=sha256; k=rsa; p=Inhalt-von-config/opendkim/keys/domain.tld/mail.txt

DKIM (DomainKeys Identified Mail) ist eine Signatur die den Mails hinzugefügt wird um das Fälschen des Absenders zu erschweren. DKIM wird für das Versenden von Mails verwendet.

SPF-Eintrag

Type Name Value
TXT @ "v=spf1 ip4:IP-Adresse-des-Webservers -all"

Auch der SPF-Eintrag (Sender Policy Framework) ist eine Maßnahme um das Fälschen von Email-Adressen zu erschweren. Der SPF-Eintrag gibt vor welche Server für das Senden der Emails berechtigt sind, in dem Beispiel die IP-Adresse unseres Mailservers.

DMARC

Type Name Value
TXT _dmarc.domain.tld "v=DMARC1; p=reject; rua=mailto:report@domain.tld"

DMARC baut auf SPF und DKIM auf und gibt vor, wie der Server an dem eine Mail geschickt wird, das Email authentifizieren soll.

DNS überprüfen

Am einfachsten können die DNS-Einträge auf der Seite mxtoolbox.com getestet werden: mxtoolbox.com/MXLookup.aspx

Als Beispiel für die Domain: domain.tld

MX Lookup

Der MX-Lookup auf der Seite mxtoolbox sollte ca. so aussehen:

Pref Hostname IP Address TTL  
10 mail.domain.tld xxx.xxx.xxx.xxx 24 hrs Blacklist Check      SMTP Test
  Test Result
DMARC Record Published DMARC Record found
DMARC Policy Not Enabled DMARC Quarantine/Reject policy enabled
DNS Record Published DNS Record found

SMTP Test

Hier ein SMTP-Test auf mxtoolbox:

smtp:IP-AdresseMailserver

220 mail.domain.tld ESMTP

  Test Result
SMTP Reverse DNS Mismatch OK - xxx.xxx.xxx.xxx resolves to domain.tld
SMTP Valid Hostname OK - Reverse DNS is a valid Hostname
SMTP Banner Check OK - Reverse DNS matches SMTP Banner
SMTP TLS OK - Supports TLS.
SMTP Connection Time 0.303 seconds - Good on Connection time
SMTP Open Relay OK - Not an open relay.
SMTP Transaction Time 1.006 seconds - Good on Transaction Time

Email an eine Google-Adresse

Als Beispiel kann das Email vom eigenen Webserver auch an ein Google-Konto gesendet werden:

Auch hier taucht unter "Original anzeigen" dann ein Status zu SPF, DKIM und DMARC auf:

Originalnachricht

Nachrichten-ID <xxxxxx.xxxxxx.xxxx.xxxx@mx.google.com>
Erstellt am: 29. März 2021 um 17:55 (Nach 2 Sekunden zugestellt)
Von: Vorname Nachname <user@domain.tld>
An: "Vorname Nachname (gmailuser@gmail.com)" <gmailuser@gmail.com>
Betreff: test - dns
SPF: PASS mit IP-Adresse xxx.xxx.xxx.xxx 
DKIM: 'PASS' mit Domain domain.tld
DMARC: 'PASS'

 

SSL-Zertifikate

Als Setup für SSL-Zertifikate verwende ich LetsEncrypt und nginx, siehe: nginx-LetsEncrypt Reverse Proxy in der Praxis. Damit die Zertifikatsverwaltung vom Proxy-Companion verwendet werden kann, habe ich das docker-compose.yml-File wie folgt angepasst:

version: '3.8'

services:
  mailserver:
    image: docker.io/mailserver/docker-mailserver:latest
    hostname: ${HOSTNAME}
    domainname: ${DOMAINNAME}
    container_name: ${CONTAINER_NAME}
    env_file: mailserver.env
    ports:
      - "25:25"
      - "143:143"
      - "587:587"
      - "993:993"
      - "4190:4190"
    volumes:
      - ./maildata:/var/mail
      - ./mailstate:/var/mail-state
      - ./maillogs:/var/log/mail
      - ./config/:/tmp/docker-mailserver/${SELINUX_LABEL}
      - ../webproxy/nginx-data/certs:/etc/letsencrypt/live/:ro
    restart: always
    cap_add: [ "NET_ADMIN", "SYS_PTRACE" ]
  cert-companion:
    image: nginx
    environment:
      - "VIRTUAL_HOST=${HOSTNAME}"
      - "VIRTUAL_NETWORK=nginx-proxy"
      - "LETSENCRYPT_HOST=${HOSTNAME}"
      - "LETSENCRYPT_EMAIL=mail@tld.domain"
    networks:
      - proxy-tier
    restart: always

networks:
   proxy-tier:
           external:
                   name: webproxy

Der Pfad zum nginx-data-Ordner des Webproxy unter "Volumes" muss natürlich entsprechend angepasst werden. Zudem habe ich, anders als beim originalen docker-compose-File, die anderen Volumes in das Dateisystem umgeleitet. 

SIEVE - Filterregeln

Mit Hilfe von Sieve-Filtern ist es möglich bestimmte Regeln auf die Inbox anzuwenden, z.B. bestimmte Absender in einen Ordner zu verschieben. Hier ein Beispiel, meiner in NextCloud verwendeten Filterregeln:

require ["fileinto", "mailbox","envelope","reject"];
if anyof (address :contains "From" [
          "@spamdomain1.tld",
          "@spamdomain2.tld"
    ],
    header :contains "Subject" [
          "Viagra",
          "other SPAM-Keyword",
    ]
    )
{
     fileinto :create "Junk";
}
elsif anyof (address :matches "From" [
     "noreply@domain.tld",
     "newsletter@domain.tld"
    ]
    )
{
     fileinto :create "Newsletter";
}

Debug - Fail2ban

Sollte der Service Fail2ban aktiviert sein, werden fehlgeschlagene Anmeldeversuche bestraft in dem der Absender für einige Zeit blockiert wird. Die blockierten IP-Adressen können wie folgt angezeigt und wieder freigegeben werden:

 ./setup.sh debug fail2ban
Banned in dovecot: xxx.xxx.xxx.xxx
Banned in postfix-sasl: 60.171.17.185, 61.182.227.245, 117.50.65.112, 116.196.112.146, 119.62.142.225, 113.31.104.89
root@ubuntu-4gb-nbg1-2:/var/web/mailserver# ./setup.sh debug fail2ban unban xxx.xxx.xxx.xxx
Unbanned IP from dovecot: xxx.xxx.xxx.xxx
root@ubuntu:/var/web/mailserver# 

Troubleshooting: DNS-Einträge

Policy Reasons

Mail Delivery Subsystem 

Returned mail: see transcript for details

This message was created automatically by mail delivery software.

Deny to deliver the message you sent to one or more recipients.

Reasons for deny are as follows:



REASONS: Policy Reasons



RECIPIENTS:
xxx@xxx.xx

Mögliche Ursache: fehlender SPF-Record

Domain unbekannt

Ein Email an eine unbekannte Domain wird ca. so vom Mail Delivery Subsystem präsentiert:

Mail Delivery Subsystem 

Returned mail: see transcript for details

Undelivered Mail Returned to Sender

This is the mail system at host mail.domain.tld.

I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.

For further assistance, please send mail to postmaster.

If you do so, please include this problem report. You can
delete your own text from the attached returned message.

                   The mail system

<gibts-nicht@ungültige.domain
Zitierter Text
>: Host or domain name not found. Name service error
    for name=ungültige.domain type=AAAA: Host not found

Delivery report

postmaster@xxx.xxx.xxx

Delivery report

Hello, this is the mail server on xxx.xxx.xxx



I am sending you this message to inform you on the delivery status of a

message you previously sent.  Immediately below you will find a list of

the affected recipients;  also attached is a Delivery Status Notification

(DSN) report in standard format, as well as the headers of the original

message.



  <user@xxx.xxx.xxx

Zitierter Text

>  delivery failed; will not continue trying

Fazit

Zugegeben, die Verwaltung über Befehle im Terminal ist sicher nicht jedermanns Sache. Der Vorteil dieses Setups ist aber, dass sich die Konfiguration und die Daten des kompletten Mailservers dank Docker in einem Ordner befinden und der Server somit ganz einfach auf einen anderen Server kopiert und dort gestartet werden kann, siehe auch: topic/docker

positive Bewertung({{pro_count}})
Beitrag bewerten:
{{percentage}} % positiv
negative Bewertung({{con_count}})

DANKE für deine Bewertung!



Fragen / Kommentare


Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und die Zugriffe auf unsere Website zu analysieren. Außerdem geben wir Informationen zu Ihrer Nutzung unserer Website an unsere Partner für soziale Medien, Werbung und Analysen weiter. Details anzeigen.