Mailserver mit Dovecot, Postfix, MySQL und Rspamd unter Debian 10 Buster [v1.0]


Vorsicht - diese Anleitung befindet sich noch im Entwurfsstadium und wird noch immer ├╝berarbeitet und erg├Ąnzt. Solltest du Fehler finden oder Verbesserungsvorschl├Ąge haben, schreib’ mir bitte an mailserver@thomas-leister.de.

Hier ist sie - die von einigen Lesern sehns├╝chtig erwartete Aktualisierung meiner Mailserver-Anleitung f├╝r Debian Buster. Gro├če Teile der Vorg├Ąngerversion f├╝r Debian Stretch habe ich ├╝bernommen. Gleichzeitig sind Detailverbesserungen in das Setup eingeflossen. Ein vollst├Ąndiges Changelog findet sich am Ende dieses Beitrags.

Wie auch in den letzten Versionen ist mir wichtig, die Funktionsweise und das Zusammenspiel der Mailserver-Komponenten so zu erkl├Ąren, dass das Mailsystem als solches in den Grundz├╝gen verstanden werden kann. Ich setze dabei grundlegende Kenntnisse im Bereich Linux-Server voraus; trotzdem ist dieser Guide auch f├╝r Anf├Ąnger geeignet, die Interesse und Zeit mitbringen.

Wer lieber auf eine fertige L├Âsung setzt und sich die Handarbeit sparen will, sollte sich einmal Mailcow von Andr├ę Peters ansehen.
Werbung
Du m├Âchtest mich mit Setup, Update oder Pflege beauftragen? Gerne bin ich dir dabei behilflich!
Kontaktiere mich unter: https://leister-it.de/kontakt/

Mailserver-Funktionen

Damit ihr einen Eindruck vom Funktionsumfang des fertigen Mailsetups bekommt, hier einige Merkmale:

  • Senden und Empfangen von E-Mails f├╝r beliebige Domains
  • Flexible Einrichtung von Domains, Mailaccounts, Aliasen, Weiterleitungen und Regeln f├╝r die Transportverschl├╝sselung ├╝ber ein MySQL-Backend zur Laufzeit
  • Nutzer-spezifisch begrenztes Mailbox-Volumen
  • Einrichtung allgemeiner und Nutzer-spezifischer Sieve-Filterregeln zum Filtern und/oder Umsortieren eingehender E-Mails
  • Zuverl├Ąssige und moderne Spamerkennung via Rspamd (+ Weboberfl├Ąche f├╝r Spam-Statistiken)
  • “Send only” Accounts z.B. f├╝r NextCloud / Forensoftware / …
  • DKIM-und ARC-Signierung ausgehender E-Mails
  • Mailclient Autokonfiguration
  • Domain Catch-All

Eine Weboberfl├Ąche / ein Management-Tool zur Verwaltung dieses Setups biete ich selbst nach wie vor nicht an. In der Zwischenzeit haben aber andere User L├Âsungen ver├Âffentlicht, z.B.

Das Datenbank-Layout und die Struktur des /var/vmail-Verzeichnisses haben sich im Vergleich zur vorherigen Anleitung nicht ge├Ąndert. Ein Update ├Ąlterer Setups ist also einfach realisierbar.

Verwendete Software

  • Debian 10 “Buster”
  • Postfix
  • Dovecot
  • Rspamd
  • Redis
  • MariaDB
  • Nginx

Gegebenheiten

In dieser Anleitung kommen folgende Domains vor:

  • mysystems.tld: ├ťbergeordnete, prim├Ąre Domain
  • mail.mysystems.tld: Subdomain, unter der der Mailserver verf├╝gbar sein soll (FQDN des Mailsystems)
  • imap.mysystems.tld: Alias auf mail.mysystems.tld, wird von vielen Mailclient automatisch gesucht und gefunden
  • smtp.mysystems.tld: Dasselbe f├╝r den SMTP-Dienst
  • domain2.tld: Eine zweite Domain neben mysystems.tld, f├╝r die E-Mails gesendet und empfangen werden sollen
  • domain3.tld: Eine dritte Domain, f├╝r die E-Mails gesendet und empfangen werden sollen

Diese Domains m├╝ssen in der gesamten Anleitung selbstverst├Ąndlich durch eigene ersetzt werden!
Auf domain2.tld und domain3.tld kann verzichtet werden, wenn der Mailserver nur f├╝r eine Domain (nur f├╝r “@mysystems.tld”-Adressen) genutzt werden soll.

Folgende IP-Adressen werden beispielhaft in Konfigurationen genannt und m├╝ssen ebenfalls durch die IP-Adressen des jeweiligen Servers ersetzt werden:

  • 2001:db8::1 (IPv6-Adresse des Mailservers)
  • 203.0.113.1 (IPv4-Adresse des Mailservers)

Grundvoraussetzungen f├╝r den Mailserver

  • Ein virtueller oder dedizierter Server mit bereits installiertem Debian 10 Buster
    (“Standard-Systemwerkzeuge” und “SSH” bei der Installation angew├Ąhlt)
  • Mindestens eine eigene Domain + volle Kontrolle ├╝ber die DNS-Zone

Ein kleiner, virtueller Server auf KVM-Basis ist in den meisten F├Ąllen v├Âllig ausreichend. Ich empfehle f├╝r kleine, private Setups zwei CPU-Kerne und 1-2 GB RAM. Virtuelle Server kann man z.B. bei Servercow oder Hetzner preisg├╝nstig bekommen.

Komponenten eines vollst├Ąndigen Mailsystems

Mailserver Schema

Welche Softwarekomponenten verwendet werden, wisst ihr bereits. Doch welche Software ├╝bernimmt welche Aufgaben?

Dovecot

Dovecot ist ein weit verbreiteter MDA (Mail Delivery Agent) und IMAP-Server. Er sortiert ankommende E-Mails in die Postf├Ącher des jeweiligen Empf├Ąngers ein und stellt eine Schnittstelle zum Abrufen der Mailbox bereit (IMAP). Au├čerdem wird Dovecot in diesem Setup von Postfix als sog. SASL-Authentifizierungsserver genutzt: Postfix fragt Dovecot, ob ein bestimmter Benutzer berechtigt ist, sich am System anzumelden.

Postfix

Postfix wird oft zusammen mit Dovecot eingesetzt. Der popul├Ąre MTA (Mail Transfer Agent) k├╝mmert sich um alles, was mit dem Transport der E-Mail zu tun hat: Vom E-Mail Client zum eigenen Mailserver, und von dort aus zum jeweiligen Zielserver. Au├čerdem nimmt Postfix E-Mails von fremden Servern an und leitet sie an den MDA Dovecot weiter. Antispam-Software wird i.d.R. direkt in Postfix integriert, um eintreffende Spammails erst gar nicht in die Mailbox des Nutzers gelangen zu lassen.

Anmerkung: Postfix ist “der eigentliche Mailserver”. E-Mails k├Ânnen ohne weiteres einzig und allein mit Postfix gesendet und empfangen werden. Alle weiteren Komponenten wie Dovecot und Rspamd machen uns das Leben allerdings einfacher ;-)

MariaDB (MySQL-Datenbank)

Dovecot und Postfix werden so konfiguriert, dass sie eine MySQL-Datenbank als Backend (Datenbasis) nutzen. In der Datenbank werden zu nutzende Domains, Benutzer, Aliase und weitere Daten gespeichert. Durch einfaches Hinzuf├╝gen oder Entfernen von Datens├Ątzen in oder aus Datenbanktabellen k├Ânnen neue Benutzer oder Aliase angelegt oder gel├Âscht werden. Der Vorteil eines Datenbank-Backends ist, dass sich der Mailserver damit sehr einfach verwalten l├Ąsst: So lie├če sich zur Benutzerverwaltung beispielsweise eine Weboberfl├Ąche in PHP entwickeln, die die MySQL-Datenbank ver├Ąndert. Die Serverkonfiguration muss dann nicht manuell ge├Ąndert werden.

Rspamd

Rspamd ist ein Filtersystem, das in Postfix integriert wird und eingehende E-Mails ├╝berpr├╝ft. Spammails werden von Rspamd erkannt und nicht an den Benutzer zugestellt bzw. aussortiert. Au├čerdem f├╝gt Rspamd bei ausgehenden E-Mails eine DKIM-Signatur hinzu, sodass fremde Mailserver eigene Mails nicht als verd├Ąchtig einstufen.

Nginx

Nginx ist ein weit verbreiteter und schlanker Webserver / Webproxy. In diesem Setup hat er mehrere Aufgaben: Zum einen kann er als Endpunkt f├╝r den Ausstellungsprozess von Let’s Encrypt-Zertifikaten dienen, zum anderen als Proxy f├╝r die Rspamd-Weboberfl├Ąche, oder um die Autokonfigurationsdatei f├╝r Mailclients anzubieten.

Redis

Redis ist ein hochperformanter In-memory Key-Value-Store, also eine sehr einfache, schnelle Datenbank, welche Schl├╝ssel-Wert-Paare effizient im Speicher ablegen kann. Rspamd nutzt Redis, um einige Daten zwischenzuspeichern (wie z.B. zuletzt ├╝berpr├╝fte Mailserver).

Vorbereitungen

Tipp: Reinen Tisch machen

Wenn ihr den Server vorher schon f├╝r etwas anderes (oder sogar ein anderes Mail-Setup) verwendet habt, stellt sicher, dass Reste aus alten Installationen das neue Setup nicht behindern. Speziell vorherige Mailserver-Versuche sollten r├╝ckstandslos entfernt werden (inkl. der zugeh├Ârigen Konfigurationsdateien). Am besten ist nat├╝rlich ÔÇô falls m├Âglich ÔÇô eine komplette Neuinstallation des Servers. Ich empfehle, den Mailserver als eigenst├Ąndiges System zu betreiben und auf demselben Host keine anderen Dienste zu installieren, um die Integrit├Ąt des Mailsystems sicherzustellen.

Im Folgenden gehe ich von einem frisch installierten Debian 10 Buster aus (zus├Ątzlich nur “Standard-Systemwerkzeuge” und SSH installiert).

Login als Root

Bei der Installation von Debian wird ein normaler Benutzeraccount, z.B. “thomas” eingerichtet, zu dem ihr euch via Passwort verbinden k├Ânnt. Der Root-Account ist standardm├Ą├čig nicht direkt zug├Ąnglich, sondern nur ├╝ber den Umweg via “su”. F├╝r diese Anleitung werden permanent Root-Rechte ben├Âtigt. ├ľffnet nach dem Login am Server also am besten eine Root-Kommandozeile via

su -

Gebt dann das Passwort f├╝r euren root-User ein.

System aktualisieren

Bevor ihr neue Software-Pakete installiert, solltet ihr mittels

apt update && apt upgrade

sicherstellen, dass euer System aktuell ist. Bei der Gelegenheit bietet sich auch gleich ein Reboot an, um einen m├Âglicherweise aktualisierten Linux-Kernel zu laden.

Hostname und Server-FQDN setzen

Euer Server bekommt zwei Namen, ├╝ber die er identifiziert werden kann:

  • Lokalen Hostnamen: F├╝r die Identifizierung des Servers innerhalb der eigenen Infrastruktur, z.B. “mail”
  • FQDN (Fully Qualified Domain Name): F├╝r die weltweite Identifizierung im Internet, z.B. “mail.mysystems.tld”

Der FQDN muss nicht zwingend etwas mit den Domains zu tun haben, f├╝r die sp├Ąter E-Mails gesendet und empfangen werden sollen. Wichtig ist nur, dass euer k├╝nftiger Mailserver einen solchen Namen hat, der auch ├╝ber das DNS zur Server-IP-Adresse aufgel├Âst werden kann (dazu gleich mehr im Abschnitt “Einrichtung des DNS”). Den lokalen Hostnamen setzt ihr wie folgt:

hostnamectl set-hostname --static mail

In der Hosts-Datei /etc/hosts sollten FQDN und lokaler Hostname hinterlegt sein. Die Datei kann beispielsweise so aussehen:

127.0.0.1   localhost
127.0.1.1   mail.mysystems.tld  mail

::1         localhost ip6-localhost ip6-loopback
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters

Die Ausgaben der Kommandos hostname und hostname --fqdn sollten nach den Änderungen wie folgt aussehen:

root@mail:~# hostname
mail
root@mail:~# hostname --fqdn
mail.mysystems.tld

Der FQDN (in diesem Beispiel “mail.mysystems.tld”) wird au├čerdem nach /etc/mailname geschrieben:

echo $(hostname -f) > /etc/mailname

(Der Hostname im Shell-Prompt z.B. root@meinhost: passt sich erst nach einem erneuten Login an.)

Unbound DNS Resolver installieren

Das Mailsystem ben├Âtigt einen funktionierenden DNS-Server (Resolver), sodass die Herkunft von E-Mails ├╝berpr├╝ft werden kann. Auch der Rspamd-Spamfilter verl├Ąsst sich bei der Bewertung von Spammails auf DNS-Dienste. Eine schnelle Namesaufl├Âsung bringt also Performancevorteile f├╝r das ganze Mailsystem. F├╝r den Zugriff auf Spamhaus-Blocklists kann es sogar notwendig sein, seinen eigenen DNS-Resolver zu nutzen, weil z.B. Zugriffe ├╝ber das Google DNS blockiert werden. Deshalb (und um die Sicherheit im Bezug auf Abh├Ąngigkeiten zu fremden Systemen zu verbessern) empfehle ich die Nutzung eines eigenen, lokalen DNS-Resolvers.

Unbound installieren:

apt install unbound
F├╝r die n├Ąchsten Kommandos muss m├╝ssen die Pakete dnsutils und resolvconf installiert sein. Wenn bei der Installation von Debian die “Standard-Systemwerkzeuge” ausgew├Ąhlt wurden, sind die dnsutils schon installiert.

Ein dig @::1 denic.de +short +dnssec sollte eine ├Ąhnliche Ausgabe wie folgt erzeugen:

# dig @::1 denic.de +short +dnssec
A 8 2 3600 20170814090000 20170731090000 26155 denic.de. Jo90qnkLkZ6gI4qNHj19BMguFuGof9hCPhdeSh/fSePSQ/WXlWMmfjW1 sNDJ/bcITRMyz8DQdDzmWPDIeSJ/qPyfoZ+BjUZxtaXcs0BAl4KX8q7h R05TGmAbgPhrYBoUKJkU/q8T+jWKHAJRUeWbCd8QOJsJbneGcUKxRAPe i6Rq51/OL/id6zUCtalhclah2TfLLaqku9PmKwjbGdZm11BXSr8b56LB WX/rdLIrKWNpE+jHGAUMmDsZL84Kx3Oo

Wenn der dig-Befehl funktioniert hat, kann der lokale Resolver als prim├Ąrer Resolver gesetzt werden:

apt install resolvconf
echo "nameserver ::1" >> /etc/resolvconf/resolv.conf.d/head

ein nslookup denic.de | grep Server sollte nun

Server:     ::1

zur├╝ckliefern. Damit ist der lokale DNS-Resolver als Haupt-Resolver einsatzbereit.

Einrichtung des DNS

Zu Beginn dieser Anleitung wurde f├╝r den Mailserver der FQDN “mail.mysystems.tld” festgelegt. F├╝r diesen Domain-Namen werden nun A-Records im DNS-Zonefile der Domain “mysystems.tld” erstellt. Loggt euch bei eurem Domain-Provider ein und legt die folgenden Eintr├Ąge an ÔÇô der erste f├╝r die IPv4-IP-Adresse des Mailservers, die zweite f├╝r die IPv6-Adresse. (Beispiel!):

Achtet im Folgenden vor allem auf den abschlie├čenden Punkt in den Domainnamen!

mail.mysystems.tld. 86400 IN A    203.0.113.1
mail.mysystems.tld. 86400 IN AAAA 2001:db8::1

“mail.mysystems.tld” ist damit im DNS bekannt. Wenn keine IPv6-Adresse genutzt wird, kann der zweite Record entfallen. Bleiben noch “imap.mysystems.tld” und “smtp.mysystems.tld”, die als Alias-Domains f├╝r “mail.mysystems.tld” angelegt werden. Sie sind nicht unbedingt notwendig, werden von vielen Mailclient aber gesucht und sind so ├╝blich:

imap.mysystems.tld. 86400 IN CNAME mail.mysystems.tld.
smtp.mysystems.tld. 86400 IN CNAME mail.mysystems.tld.

Mailclients k├Ânnen sich damit schon ├╝ber imap.mysystems.tld und smtp.mysystems.tld zum Mailserver verbinden. Andere Mailserver suchen bei der E-Mail-├ťbermittlung allerdings nicht nach A- oder CNAME-Records, sondern nach MX-Records. Ein MX-Record zeigt, welcher Mailserver f├╝r die E-Mails zu einer Domain zust├Ąndig ist. In meinem Beispiel soll sich unser Mailserver neben den E-Mails f├╝r mysystems.tld auch um die Mails f├╝r domain2.tld und domain3.tld k├╝mmern.

Im Zonefile der Domain “mysystems.tld” wird dazu dieser Record angelegt:

mysystems.tld. 86400 IN MX 0 mail.mysystems.tld.

In die Zonefiles der anderen Domains werden entsprechend die Records

domain2.tld. 86400 IN MX 0 mail.mysystems.tld.

und

domain3.tld. 86400 IN MX 0 mail.mysystems.tld.

angelegt.

Reverse DNS

Des weiteren muss ein sog. Reverse-DNS-Record / PTR f├╝r den FQDN des Mailservers angelegt werden. Dieser entspricht der Umkehrung eines normalen DNS-Records und ordnet einer IP-Adresse einen Hostnamen zu. Diesen Record kann nur der Inhaber des Netzes anlegen, aus dem eure IP-Adresse stammt. M├Âglicherweise k├Ânnt ihr so einen Reverse-DNS-Record in der Verwaltungsoberfl├Ąche eures Serveranbieters setzen, oder ihr bittet den Support, das zu tun. Der Domain-Name, der mit der IP-Adresse verkn├╝pft werden muss, ist der FQDN eures Mailservers. In meinem Beispiel mail.mysystems.tld. Denkt daran, f├╝r alle vom Mailserver genutzten, ├Âffentlichen IP-Adressen einen solchen Record zu erstellen. In dieser Anleitung wird eine IPv4- und eine IPv6-Adresse verwendet.

SPF-Records

Im Kampf gegen Spam und Phishing wurde das sog. Sender Policy Framework entwickelt (Siehe auch Beitrag: “Voraussetzungen f├╝r den Versand zu gro├čen E-Mail Providern”). Obwohl es sich nur als eingeschr├Ąnkt brauchbar erwiesen hat, erwarten die meisten Mailprovider g├╝ltige SPF-Records f├╝r andere Mailserver und pr├╝fen diese. SPF-Eintr├Ąge werden im Zonefile aller Domains erstellt, f├╝r die ein Mailserver E-Mails verschickt, und geben an, welche Server f├╝r eine Domain sendeberechtigt sind. F├╝r unsere Domain mysystems.tld wird der folgende Record im Zonefile von mysystems.tld angelegt:

mysystems.tld. 3600 IN TXT v=spf1 a:mail.mysystems.tld mx ?all

Hiermit erh├Ąlt nur der im A-Record “mail.msystems.tld” genannte Server f├╝r mysystems.tld eine Sendeberechtigung. Die Neutral-Einstellung “?all” sorgt daf├╝r, dass E-Mails von anderen Servern trotzdem angenommen werden sollen. Damit gehen wir Problemen beim Mail-Forwarding aus dem Weg. Wir erstellen den SPF-Record also eigentlich nur, damit andere Mailserver unseren Server wegen des existierenden Records positiv bewerten ÔÇô nicht, weil er seinen Nutzen entfalten soll.

In den Zonefiles der beiden Domains “domain2.tld” und “domain3.tld” wird (angepasst auf die Domain) jeweils dieser Record angelegt:

domain2.tld. 3600 IN TXT v=spf1 include:mysystems.tld ?all

├ťber das “include” wird der erste Record der Domain mysystems.tld eingebunden.

DMARC Records

DMARC-Eintr├Ąge bestimmen, was ein fremder Mailserver tun soll, wenn eine von ihm empfangene Mail nach SPF- und DKIM-Checks offenbar nicht vom korrekten Mailserver stammt (wenn der Absender also gef├Ąlscht wurde). Es ist vern├╝nftig, andere Mailserver anzuweisen, solche E-Mails nicht zu akzeptieren:

_dmarc.mysystems.tld.   3600    IN TXT    v=DMARC1; p=reject;

Der Record wird entsprechend auch f├╝r die anderen Domains gesetzt:

_dmarc.domain2.tld.   3600    IN TXT    v=DMARC1; p=reject;

Einen DMARC-Record mit einer abweichenden Policy k├Ânnt ihr euch unter https://elasticemail.com/dmarc/ selbst generieren lassen.

Erstkonfiguration Nginx Webserver

Wie bereits angemerkt, ├╝bernimmt Nginx in diesem Setup verschiedene Aufgaben. F├╝r’s erste dient er aber nur als HTTP-Endpunkt, um Let’s Encrypt Zertifikate zu beantragen. Das ist zwar prinzipiell auch ohne Nginx im standalone-Modus m├Âglich, macht uns aber das Leben einfacher, wenn wir ihn sowieso in Betrieb haben (=> belegte Ports durch Nginx, ACME client …).

Dazu wird Nginx installiert …

apt install nginx

… und unter /etc/nginx/sites-available/mail.mysystems.tld eine neue Konfiguration mit diesem Inhalt angelegt:

server {
        listen 80;
        listen [::]:80;
#       listen 443 ssl http2;
#       listen [::]:443 ssl http2;

        server_name mail.mysystems.tld imap.mysystems.tld smtp.mysystems.tld;

#       ssl_certificate /etc/acme.sh/mail.mysystems.tld/fullchain.pem;
#       ssl_certificate_key /etc/acme.sh/mail.mysystems.tld/privkey.pem;

#       add_header Strict-Transport-Security max-age=15768000;

#       if ($ssl_protocol = "") {
#           return 301 https://$server_name$request_uri;
#       }
}

Einige Zeilen sind zu diesem Zeitpunkt bewusst auskommentiert und werden sp├Ąter wieder aktiviert, sobald TLS-Zertifikate verf├╝gbar sind.

Der neue vHost kann nun aktiviert werden:

ln -s /etc/nginx/sites-available/mail.mysystems.tld /etc/nginx/sites-enabled/mail.mysystems.tld
systemctl reload nginx

Beantragung der TLS-Zertifikate (via Let’s Encrypt)

G├╝ltige TLS-Zertifikate von anerkannten Zertifizierungsstellen (CAs) sind heute f├╝r jeden Mailserver ein “muss”. Immer mehr Mailsysteme verweigern zurecht den Empfang ├╝ber ungesicherte Verbindungen. Was fr├╝her (vor allem f├╝r den privaten Einsatz) noch ein bedeutender Kostenfaktor war, bekommt man heute Dank Let’s Encrypt kostenlos und sehr unkompliziert. Im folgenden beziehe ich mich daher auf die Generierung von Let’s Encrypt-Zertifikaten. Selbstverst├Ąndlich k├Ânnen stattdessen auch Zertifikate anderer CAs genutzt werden.

F├╝r Postfix und Dovecot ben├Âtigen wir Zertifikate zu folgenden Domains:

  • mail.mysystems.tld
  • imap.mysystems.tld
  • smtp.mysystems.tld

Um die Zertifikate von der Let’s Encrypt Zertifizierungsstelle abholen, nutze ich das schlanke acme.sh Script. Dieses verf├╝gt ├╝ber einen “Nginx-Mode”, in dem das Script den Nginx Webserver automatisch so konfiguriert, dass die Domains von LE verifiziert werden k├Ânnen.

acme.sh installieren:

curl https://get.acme.sh | sh
Der Hinweis, welcher besagt, dass socat installiert werden solle, kann ignoriert werden. Socat wird in unserem Fall nicht ben├Âtigt.

Nach der Installation muss das Shell-Profil neu geladen werden, damit das “acme.sh” Kommando verf├╝gbar gemacht wird:

source ~/.profile

Zertifikate beantragen und herunterladen:

acme.sh --issue --nginx \
    -d mail.mysystems.tld \
    -d imap.mysystems.tld \
    -d smtp.mysystems.tld

Zertifikate installieren:

mkdir -p /etc/acme.sh/mail.mysystems.tld
acme.sh --install-cert -d mail.mysystems.tld \
    --key-file       /etc/acme.sh/mail.mysystems.tld/privkey.pem  \
    --fullchain-file /etc/acme.sh/mail.mysystems.tld/fullchain.pem \
    --reloadcmd     "systemctl reload nginx; systemctl restart dovecot; systemctl restart postfix;"

Infolge unseres Reload-Commands wird Acme.sh versuchen, Dovecot und Postfix neu zu laden. Da beide Softwarepakete noch nicht installiert sind, werden euch Fehler angezeigt. Ihr k├Ânnt diese zum gegenw├Ąrtigen Zeitpunkt aber ignorieren.

Die vorher im Nginx auskommentierten Zeilen in /etc/nginx/sites-available/mail.mysystems.tld k├Ânnen durch entfernen der Hashzeichen nun aktiviert und Nginx mittels

nginx -t
systemctl reload nginx

getestet und neu gestartet werden.

F├╝r die Autokonfiguration der Mailclients wird sp├Ąter noch ein Zertifikat f├╝r eine weitere Domain beantragt - doch das kann erst einmal warten.

Damit die automatische Zertifikatserneuerung funktioniert, wird noch der Cronjob f├╝r acme.sh aktiviert:

 acme.sh --install-cronjob

MySQL Datenbank einrichten

Informationen ├╝ber zu verwaltende Domains, Benutzer, Weiterleitungen und sonstige Einstellungen soll der Mailserver aus einer MySQL-Datenbank ziehen. Das hat den Vorteil, dass der Server im laufenden Betrieb flexibel angepasst werden kann, ohne die Konfigurationsdateien ├Ąndern zu m├╝ssen. Die Datenbank erm├Âglicht uns au├čerdem ein virtualisiertes Mailserver-Setup: Die Benutzer auf den Mailservern m├╝ssen nicht mehr als reale Linux-Benutzer im System registriert sein, sondern nur noch in der Datenbank eingetragen werden.

Als DBMS wird die neue Debian-Standard-MySQL-Datenbank “MariaDB” installiert:

apt install mariadb-server

Nach der Installation sollte MariaDB bereits gestartet sein. Den Status k├Ânnt ihr mittels systemctl status mysql (nicht “mariadb!”) ├╝berpr├╝fen. Falls das nicht der Fall ist, startet den Datenbankserver: systemctl start mysql.

Standardm├Ą├čig kann sich nur der root-Systemuser am Datenbankserver anmelden. Authentifiziert wird er dabei automatisch via PAM, sodass keine zus├Ątzliche Passworteingabe notwendig ist. Die einfache Eingabe von

mysql

bringt euch in eine MySQL Root Shell. ├ťber diese werden nun ein paar SQL-Befehle ausgef├╝hrt.

Ein SQL-Kommando endet immer mit einem Semikolon ;. Mehrzeilige Befehle k├Ânnt ihr ohne weiteres einfach mit ENTER umbrechen, so wie sie im Folgenden dargestellt werden. Achtet auf den Unterschied zwischen “Tick” (') und “Backtick” (\ `) ÔÇô der Backtick wird mit Shift + 2x Accent-Taste erzeugt. Kopiert die SQL-Statements am besten direkt in eure Zwischenanlage, statt sie m├╝hsam abzutippen.

Im ersten Schritt wird eine neue Datenbank “vmail” angelegt.

create database vmail
    CHARACTER SET 'utf8';

Ein neuer DB-User vmail mit dem Passwort vmaildbpass bekommt Zugriff auf diese neue Datenbank (W├Ąhlt ein eigenes Passwort statt “vmaildbpass”!):

Nutzt f├╝r vmaildbpass nur die Zeichen 0-9 a-z und A-z. Einigen Berichten nach k├Ânnen Sonderzeichen zu Problemen f├╝hren.
grant select on vmail.* to 'vmail'@'localhost' identified by 'vmaildbpass';

Alle weiteren Kommandos zu Erstellung der Datenbank-Tabellen sollen sich auf die eben erzeugte Datenbank beziehen:

use vmail;

Das Mail-Setup soll 4 verschiedene Tabellen nutzen. Kopiert die SQL-Statements einzeln und nacheinander in die MySQL-Kommandozeile und best├Ątigt jedes mal mit [Enter]. Anpassungen sind nicht notwendig.

Domain-Tabelle

Die Domain-Tabelle enth├Ąlt alle Domains, die mit dem Mailserver genutzt werden sollen.

CREATE TABLE `domains` (
    `id` int unsigned NOT NULL AUTO_INCREMENT,
    `domain` varchar(255) NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY (`domain`)
);

Account-Tabelle

CREATE TABLE `accounts` (
    `id` int unsigned NOT NULL AUTO_INCREMENT,
    `username` varchar(64) NOT NULL,
    `domain` varchar(255) NOT NULL,
    `password` varchar(255) NOT NULL,
    `quota` int unsigned DEFAULT '0',
    `enabled` boolean DEFAULT '0',
    `sendonly` boolean DEFAULT '0',
    PRIMARY KEY (id),
    UNIQUE KEY (`username`, `domain`),
    FOREIGN KEY (`domain`) REFERENCES `domains` (`domain`)
);

Die Account-Tabelle enth├Ąlt alle Mailserver-Accounts. Das Feld “quota” enth├Ąlt die Volumenbegrenzung f├╝r die Mailbox in MB (Megabyte). Im Feld “enabled” wird ├╝ber einen boolÔÇÖschen Wert festgelegt, ob ein Account aktiv ist, oder nicht. So k├Ânnen einzelne User tempor├Ąr deaktiviert werden, ohne gel├Âscht werden zu m├╝ssen. “sendonly” wird auf “true” gesetzt, wenn der Account nur zum Senden von E-Mails genutzt werden soll ÔÇô nicht aber zum Empfang. Das kann beispielsweise f├╝r Foren- oder Blogsoftware sinnvoll sein, die mit ihrem Account nur E-Mails verschicken soll.

Alias-Tabelle

CREATE TABLE `aliases` (
    `id` int unsigned NOT NULL AUTO_INCREMENT,
    `source_username` varchar(64),
    `source_domain` varchar(255) NOT NULL,
    `destination_username` varchar(64) NOT NULL,
    `destination_domain` varchar(255) NOT NULL,
    `enabled` boolean DEFAULT '0',
    PRIMARY KEY (`id`),
    UNIQUE KEY (`source_username`, `source_domain`, `destination_username`, `destination_domain`),
    FOREIGN KEY (`source_domain`) REFERENCES `domains` (`domain`)
);

Die Alias-Tabelle enth├Ąlt alle Weiterleitungen / Aliase und ist eigentlich selbsterkl├Ąrend. Zur tempor├Ąren Deaktivierung von Weiterleitungsadressen gibt es wieder ein “enabled”-Feld.

TLS Policy-Tabelle

CREATE TABLE `tlspolicies` (
    `id` int unsigned NOT NULL AUTO_INCREMENT,
    `domain` varchar(255) NOT NULL,
    `policy` enum('none', 'may', 'encrypt', 'dane', 'dane-only', 'fingerprint', 'verify', 'secure') NOT NULL,
    `params` varchar(255),
    PRIMARY KEY (`id`),
    UNIQUE KEY (`domain`)
);

Mithilfe der TLS Policy Tabelle kann festgelegt werden, f├╝r welche Empf├Ąngerdomains bestimmte Sicherheitsbeschr├Ąnkungen beim Mailtransport gelten sollen. F├╝r einzelne Domains, z.B. “gmx.de” kann beispielsweise angegeben werden, dass diese E-Mails nur noch verschl├╝sselt ├╝bertragen werden d├╝rfen. Mehr dazu sp├Ąter.

Die Datenbank wird mit Datens├Ątzen bef├╝llt, sobald die Server fertig konfiguriert sind. Bis dahin k├Ânnt ihr die MySQL-Kommandozeile mit quit; verlassen.

vmail-Benutzer und -Verzeichnis einrichten

Alle Mailboxen werden direkt im Dateisystem des Debian Servers abgelegt. F├╝r die Zugriffe auf die Mailbox-Verzeichnisse wird ein eigener Benutzer “vmail” (“Virtual Mail”) erstellt, unter dem die Zugriffe von Dovecot und anderen Komponenten des Mailservers geschehen sollen. Einerseits wird so verhindert, dass Mailserver-Komponenten auf sensible Systemverzeichnisse Zugriff bekommen, andererseits k├Ânnen wir so die Mailboxen vor dem Zugriff von au├čen sch├╝tzen. Nur vmail (und root) d├╝rfen auf die Mailboxen zugreifen.

Das Verzeichnis /var/vmail/ soll alle Mailserver-relevanten Dateien (also Mailboxen und Filterscripts) enthalten und wird f├╝r den vmail-User als Home Directory festgelegt.

vmail-Benutzer erstellen:

useradd --create-home --home-dir /var/vmail --user-group --shell /usr/sbin/nologin vmail

vmail Unterverzeichnisse erstellen:

mkdir /var/vmail/mailboxes
mkdir -p /var/vmail/sieve/global

Verzeichnis /var/vmail rekursiv an vmail-User ├╝bereignen und Verzeichnisrechte passend setzen:

chown -R vmail /var/vmail
chgrp -R vmail /var/vmail
chmod -R 770 /var/vmail

Dovecot installieren und konfigurieren

Nachdem die Datenbank und der vmail-User angelegt wurden, widmen wir uns nun dem Dovecot-Server. Wie bereits erw├Ąhnt, verwaltet dieser Server die Mailboxen und bekommt daher (in der Gestalt des vmail-Users) exklusiv Zugriff auf /var/vmail/. Zuerst m├╝ssen jedoch alle Serverkomponenten installiert werden:

apt install dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysql dovecot-sieve dovecot-managesieved
  • dovecot-core: Dovecot-Kern
  • dovecot-imapd: F├╝gt IMAP-Funktionalit├Ąt hinzu
  • dovecot-lmtp: F├╝gt LMTP (Local Mail Transfer Protocol)-Funktionalit├Ąt hinzu; LMTP wird als MTP-Protokoll zwischen Postfix und Dovecot genutzt
  • dovecot-mysql: L├Ąsst Dovecot mit der MySQL-Datenbank zusammenarbeiten
  • dovecot-sieve: F├╝gt Filterfunktionalit├Ąt hinzu
  • dovecot-managesieved: Stellt eine Schnittstelle zur Einrichtung der Filter via Mailclient bereit

Nach der Installation wird Dovecot automatisch gestartet. Beendet Dovecot, solange wir keine fertige Konfiguration haben:

systemctl stop dovecot

Nun geht es an die Konfiguration. Die Dovecot-Konfigurationsdateien liegen im Verzeichnis /etc/dovecot/. Dort k├Ânnt ihr schon einige Konfigurationen sehen, die bei der Installation angelegt wurden. Wir werden die Konfiguration von Grund auf neu aufsetzen - deshalb wird zuerst einmal die gesamte Dovecot-Konfiguration gel├Âscht:

rm -r /etc/dovecot/*
cd /etc/dovecot

F├╝r Dovecot reichen die folgenden zwei Konfigurationsdateien (dovecot.conf und dovecot-sql.conf) aus. Erstellt die beiden Dateien im Verzeichnis /etc/dovecot/.

Hauptkonfigurationsdatei /etc/dovecot/dovecot.conf

##
## Aktivierte Protokolle
##

protocols = imap lmtp sieve 


##
## TLS Config
## Quelle: https://ssl-config.mozilla.org/#server=dovecot&version=2.3.9&config=intermediate&openssl=1.1.1d&guideline=5.4
##

ssl = required
ssl_cert = </etc/acme.sh/mail.mysystems.tld/fullchain.pem
ssl_key = </etc/acme.sh/mail.mysystems.tld/privkey.pem
ssl_dh = </etc/dovecot/dh4096.pem
ssl_min_protocol = TLSv1.2
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl_prefer_server_ciphers = no


##
## Dovecot services
##

service imap-login {
    inet_listener imap {
        port = 143
    }
}

service managesieve-login {
    inet_listener sieve {
        port = 4190
    }
}

service lmtp {
    unix_listener /var/spool/postfix/private/dovecot-lmtp {
        mode = 0660
        group = postfix
        user = postfix
    }

    user = vmail
}

service auth {
    ### Auth socket f├╝r Postfix
    unix_listener /var/spool/postfix/private/auth {
        mode = 0660
        user = postfix
        group = postfix
    }

    ### Auth socket f├╝r LMTP-Dienst
    unix_listener auth-userdb {
        mode = 0660
        user = vmail
        group = vmail
    }
}


##
##  Protocol settings
##

protocol imap {
    mail_plugins = $mail_plugins quota imap_quota imap_sieve
    mail_max_userip_connections = 20
    imap_idle_notify_interval = 29 mins
}

protocol lmtp {
    postmaster_address = postmaster@mysystems.tld
    mail_plugins = $mail_plugins sieve notify push_notification
}


##
## Client authentication
##

disable_plaintext_auth = yes
auth_mechanisms = plain login

passdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf
}

userdb {
    driver = sql
    args = /etc/dovecot/dovecot-sql.conf
}


##
## Address tagging
##
recipient_delimiter = +


##
## Mail location
##

mail_uid = vmail
mail_gid = vmail
mail_privileged_group = vmail

mail_home = /var/vmail/mailboxes/%d/%n
mail_location = maildir:~/mail:LAYOUT=fs


##
## Mailbox configuration
##

namespace inbox {
    inbox = yes

    mailbox Spam {
        auto = subscribe
        special_use = \Junk
    }

    mailbox Trash {
        auto = subscribe
        special_use = \Trash
    }

    mailbox Drafts {
        auto = subscribe
        special_use = \Drafts
    }

    mailbox Sent {
        auto = subscribe
        special_use = \Sent
    }
}


##
## Mail plugins
##

plugin {
    sieve_plugins = sieve_imapsieve sieve_extprograms
    sieve_before = /var/vmail/sieve/global/spam-global.sieve
    sieve = file:/var/vmail/sieve/%d/%n/scripts;active=/var/vmail/sieve/%d/%n/active-script.sieve

    ###
    ### Spam learning
    ###
    # From elsewhere to Spam folder
    imapsieve_mailbox1_name = Spam
    imapsieve_mailbox1_causes = COPY
    imapsieve_mailbox1_before = file:/var/vmail/sieve/global/learn-spam.sieve

    # From Spam folder to elsewhere
    imapsieve_mailbox2_name = *
    imapsieve_mailbox2_from = Spam
    imapsieve_mailbox2_causes = COPY
    imapsieve_mailbox2_before = file:/var/vmail/sieve/global/learn-ham.sieve

    sieve_pipe_bin_dir = /usr/bin
    sieve_global_extensions = +vnd.dovecot.pipe

    quota = maildir:User quota
    quota_exceeded_message = Benutzer %u hat das Speichervolumen ├╝berschritten. / User %u has exhausted allowed storage space.
}

Anzupassende Stellen:

  • ssl_cert: Pfad zur Zertifikatsdatei
  • ssl_key: Pfad zur Zertifikatsdatei
  • postmaster_address: Domain anpassen

Erkl├Ąrung

dovecot.conf ist die Hauptkonfigurationsdatei des Dovecot-Servers:

Dovecot Services: Im darauf folgenden Abschnitt werden die Dovecot Services konfiguriert. Dazu geh├Ârt z.B. der Dienst “imap-login”, der auf eingehende Verbindungen von E-Mail Clients auf Port 143 horcht. Auch “managesieve-login” kommuniziert mit dem Mailclient, wenn dieser eine Funktion zur Bearbeitung Server-seitiger Filterscripte mitbringt. Die anderen Dienste werden intern genutzt: Der lmtp-Dienst stellt eine Schnittstelle bereit, ├╝ber die Postfix empfangene Mails an die Mailbox ├╝bergeben kann. Der “auth” Dienst wird vom LMTP-Dienst genutzt, um die Existenz von Benutzern zu ├╝berpr├╝fen, aber auch von Postfix, um den Login am Postfix-Server zu ├╝berpr├╝fen. Mit “mode”, “user” und “group” wird bestimmt, welcher Systemuser Zugriff auf den Dienst haben soll (Analog zu den Dateirechten ÔÇô der Socket f├╝r den Dienst ist nichts anderes als eine Datei).

Protocol settings: F├╝r die verwendeten Protokolle k├Ânnen zus├Ątzliche Einstellungen gesetzt werden ÔÇô u.A. auch, welche Erweiterungen im Zusammenhang mit dem Protokoll genutzt werden sollen. “quota” und “imap_quota” sind notwendig, um das maximale Volumen einer Mailbox festsetzen zu k├Ânnen. Beim lmtp-Protokoll kann auf diese Erweiterungen verzichtet werden: Hier wird nur die Sieve-Erweiterung zum Filtern von E-Mails ben├Âtigt.

Client Authentication: Die Zeilen

disable_plaintext_auth = yes
auth_mechanisms = plain login

scheinen sich zu widersprechen, schlie├člich wird die Klartext-Authentifizierung abgeschaltet. Doch tats├Ąchlich wird sie das nur f├╝r unverschl├╝sselte Verbindungen. TLS-Verschl├╝sselte Verbindungen bleiben davon unber├╝hrt, sodass in der n├Ąchsten Zeile die “plain” Authentifizierung mit Klartext-Passw├Ârtern wieder angeboten werden kann. Das wird aus zwei Gr├╝nden getan:

  • “Klartext” tut uns hier nicht weh ÔÇô schlie├člich ist die Verbindung sowieso (zwingend) verschl├╝sselt.
  • Alle Mailclients unterst├╝tzen die Klartextauthentifizierung. Andere Loginmechanismen werden weniger gut unterst├╝tzt und sind aufwendiger.

Wir konzentrieren uns deshalb auf die klassische Klartextauthentifizierung. Wie bereits erw├Ąhnt: Da unsere Verbindung ohnehin verschl├╝sselt ist, ist das in diesem Fall nicht sicherheitsrelevant.

F├╝r passdb und userdb wird jeweils der Pfad zur SQL-Datei eingestellt. Dort befindt sich jeweils eine passende SQL-Query. Die “passdb” wird befragt, wenn es um die Authentifizierung von Usern geht, die “userdb”, wenn die Existenz eines bestimmten E-Mail Kontos ├╝berpr├╝ft werden soll, oder benutzerdefinierte Einstellungen geladen werden m├╝ssen, wie z.B. das Mailbox-Kontingent (“Quota”).

Mail location: In diesem Abschnitt wird definiert, unter welchem Systemuser Dovecot auf Dateisystem-Ebene mit E-Mails hantieren soll. Au├čerdem wird ein Pfad-Schema festgelegt, das bestimmt, nach welcher Struktur die Mailbox-Verzeichnisse angelegt werden sollen. %d steht f├╝r die Domain des Accounts und %n f├╝r den Benutzernamen vor dem @. Der Pfad zu einer Benutzermailbox lautet z.B.: /var/vmail/mailboxes/mysystems.tld/admin/mail/

Mailbox Configuration: In der Mailbox eines jeden Users soll sich standardm├Ą├čig ein “Spam”-Ordner befinden, in die ein passendes Sieve-Filterskript verd├Ąchtige E-Mails verschieben soll.

Mail Plugins: Hier werden die Details zu den Erweiterungen sieve, quota und imapsieve definiert. Das Script unter sieve_before wird f├╝r alle User (unabh├Ąngig von den eigenen Einstellungen) immer ausgef├╝hrt. Es hat die Aufgabe, durch Rspamd markierte Mails in den Spam-Ordner zu verschieben. sieve_dir definiert das Schema f├╝r den Ort, an dem benutzerdefinierte Scripts abgelegt werden. Das aktive Skript eines Nutzers soll jeweils ├╝ber den symbolischen Link active-script.sieve zug├Ąnglich sein. Die imapsieve Einstellungen lassen den IMAP-Server Verschiebevorg├Ąngezwischen Mailbox-Ordnern erkennen, sodass Rspamd aus einer Neuordnung lernen kann.

Diffie-Hellman Parameter f├╝r Dovecot generieren

In neueren Versionen generiert Dovecot die Diffie-Hellman-Parameter f├╝r TLS-Verbindungen nicht mehr selbst. Also m├╝ssen wir selbst Hand anlegen und die Parameter mittels OpenSSL-Tool generieren lassen:

openssl dhparam -out /etc/dovecot/dh4096.pem 4096 

Das kann je nach Auslastung des Mailservers durchaus eine viertel Stunde oder l├Ąnger dauern. Um den Vorhang zu beschleunigen, kann ein sog. Entropy Harvester wie z.B. haveged installiert werden (apt install haveged).

SQL-Konfgurationsdatei /etc/dovecot/dovecot-sql.conf

driver=mysql
connect = "host=localhost dbname=vmail user=vmail password=vmaildbpass"
default_pass_scheme = SHA512-CRYPT

password_query = SELECT username AS user, domain, password FROM accounts WHERE username = '%n' AND domain = '%d' and enabled = true;
user_query = SELECT concat('*:storage=', quota, 'M') AS quota_rule FROM accounts WHERE username = '%n' AND domain = '%d' AND sendonly = false;
iterate_query = SELECT username, domain FROM accounts where sendonly = false;

Anzupassende Stellen:

  • Datenbankpasswort “vmaildbpass”

dovecot-sql.conf enth├Ąlt sensible Datenbank-Zugangsdaten und wird deshalb gesch├╝tzt:

chmod 440 dovecot-sql.conf

Erkl├Ąrung

Die Konfigurationsdatei dovecot-sql.conf enth├Ąlt alle SQL-relevanten Einstellungen:

  • driver: Welcher Datenbank-Treiber soll genutzt werden?
  • connect: Informationen zur Datenbankverbindung
  • default_pass_scheme: Standardm├Ą├čig angenommenes Hash-Schema, wenn es in der Datenbank nicht explizit angegeben ist, z.B. mit vorangestelltem {SHA512-CRYPT}.
  • password_query: SQL Query f├╝r die ├ťberpr├╝fung des User-Logins. Stimmen Benutzername und Passwort ├╝berein? Existiert der Benutzer und ist er aktiviert?
  • user_query: SQL-Query zum Abholen aller Benutzer-spezifischen Einstellungen. In diesem Fall: Maximales Mailbox-Volumen (“Quota”).
  • iterate_query: SQL-Query zur Abfrage aller verf├╝gbarer Benutzer. Benutzer, die keine Mails empfangen k├Ânnen (sendonly=true) sind f├╝r Dovecot nicht interessant und werden nicht mit ausgegeben.

Globales Sieve-Filterscript f├╝r Spam

Unter /var/vmail/sieve/global/ wird das Sieve-Filterscript spam-global.sieve erstellt, das erkannte Spammails in den Unterordner “Spam” jeder Mailbox einsortiert. Rspamd markiert erkannte E-Mails mit einem speziellen Spam-Header, den das Script erkennt. Inhalt von spam-global.sieve:

require "fileinto";

if header :contains "X-Spam-Flag" "YES" {
    fileinto "Spam";
}

if header :is "X-Spam" "Yes" {
    fileinto "Spam";
}

Spam Learning mit Rspamd

Beim Verschieben von Spammails in den Spam-Ordner bzw. dem Herausverschieben falsch beurteilter Mails in den Posteingang soll ein Lernprozess von Rspamd ausgel├Âst werden, sodass der Filter aus falschen Einsch├Ątzungen lernt und so mit der Zeit immer besser wird.

Dazu werden zwei Sieve-Scripts in /var/vmail/sieve/global/ angelegt:

learn-spam.sieve

require ["vnd.dovecot.pipe", "copy", "imapsieve"];
pipe :copy "rspamc" ["learn_spam"];

learn-ham.sieve

require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];

if environment :matches "imap.mailbox" "*" {
    set "mailbox" "${1}";
}

if string "${mailbox}" "Trash" {
    stop;
}

pipe :copy "rspamc" ["learn_ham"];

Das learn-ham.sieve Script besitzt noch einen Check, der ├╝berpr├╝ft, ob eine E-Mail aus dem Spam in den Papierkorb verschoben wurde. In diesem Fall sollen die betroffenen Mails ja nicht wieder als “Ham” markiert werden, daher wird in so einem Fall die Ausf├╝hrung des Lernvorgangs verhindert.

Postfix installieren und konfigurieren

F├╝r unseren Postfix-Server ben├Âtigen wir nur zwei Pakete: Das Kernpaket postfix und die Komponente postfix-mysql, die Postfix mit der MySQL-Datenbank kommunizieren l├Ąsst.

apt install postfix postfix-mysql

W├Ąhrend der Installation werdet ihr nach der “Allgemeinen Art der Konfiguration” gefragt. W├Ąhlt an dieser Stelle “Keine Konfiguration” und beendet den Postfix-Server wieder:

systemctl stop postfix

Im Postfix-Konfigurationsverzeichnis /etc/postfix befinden sich trotz unserer Wahl “Keine Konfiguration” ein paar Konfigurationsdateien, die zun├Ąchst entfernt werden:

cd /etc/postfix
rm -r sasl
rm master.cf main.cf.proto master.cf.proto

Legt dann folgende Dateien im Verzeichnis /etc/postfix an:

/etc/postfix/main.cf

##
## Netzwerkeinstellungen
##

mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
inet_interfaces = 127.0.0.1, ::1, 203.0.113.1, 2001:db8::1
myhostname = mail.mysystems.tld


##
## Mail-Queue Einstellungen
##

maximal_queue_lifetime = 1h
bounce_queue_lifetime = 1h
maximal_backoff_time = 15m
minimal_backoff_time = 5m
queue_run_delay = 5m


##
## TLS Einstellungen
## Quelle: https://ssl-config.mozilla.org/#server=postfix&version=3.4.8&config=intermediate&openssl=1.1.1d&guideline=5.4
##

### Allgemein
tls_preempt_cipherlist = no
tls_ssl_options = NO_COMPRESSION
tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384

### Ausgehende SMTP-Verbindungen (Postfix als Sender)
smtp_tls_security_level = dane
smtp_dns_support_level = dnssec
smtp_tls_policy_maps = proxy:mysql:/etc/postfix/sql/tls-policy.cf
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_ciphers = medium
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt

### Eingehende SMTP-Verbindungen
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_ciphers = medium
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_cert_file=/etc/acme.sh/mail.mysystems.tld/fullchain.pem
smtpd_tls_key_file=/etc/acme.sh/mail.mysystems.tld/privkey.pem
smtpd_tls_dh1024_param_file = /etc/postfix/dh2048.pem


##
## Lokale Mailzustellung an Dovecot
##

virtual_transport = lmtp:unix:private/dovecot-lmtp


##
## Spamfilter und DKIM-Signaturen via Rspamd
##

smtpd_milters = inet:localhost:11332
non_smtpd_milters = inet:localhost:11332
milter_protocol = 6
milter_mail_macros =  i {mail_addr} {client_addr} {client_name} {auth_authen}
milter_default_action = accept



##
## Server Restrictions f├╝r Clients, Empf├Ąnger und Relaying
## (im Bezug auf S2S-Verbindungen. Mailclient-Verbindungen werden in master.cf im Submission-Bereich konfiguriert)
##

### Bedingungen, damit Postfix als Relay arbeitet (f├╝r Clients)
smtpd_relay_restrictions =      reject_non_fqdn_recipient
                                reject_unknown_recipient_domain
                                permit_mynetworks
                                reject_unauth_destination


### Bedingungen, damit Postfix ankommende E-Mails als Empf├Ąngerserver entgegennimmt (zus├Ątzlich zu relay-Bedingungen)
### check_recipient_access pr├╝ft, ob ein account sendonly ist
smtpd_recipient_restrictions = check_recipient_access proxy:mysql:/etc/postfix/sql/recipient-access.cf


### Bedingungen, die SMTP-Clients erf├╝llen m├╝ssen (sendende Server)
smtpd_client_restrictions =     permit_mynetworks
                                check_client_access hash:/etc/postfix/without_ptr
                                reject_unknown_client_hostname


### Wenn fremde Server eine Verbindung herstellen, m├╝ssen sie einen g├╝ltigen Hostnamen im HELO haben.
smtpd_helo_required = yes
smtpd_helo_restrictions =   permit_mynetworks
                            reject_invalid_helo_hostname
                            reject_non_fqdn_helo_hostname
                            reject_unknown_helo_hostname

# Clients blockieren, wenn sie versuchen zu fr├╝h zu senden
smtpd_data_restrictions = reject_unauth_pipelining


##
## Restrictions f├╝r MUAs (Mail user agents)
##

mua_relay_restrictions = reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_mynetworks,permit_sasl_authenticated,reject
mua_sender_restrictions = permit_mynetworks,reject_non_fqdn_sender,reject_sender_login_mismatch,permit_sasl_authenticated,reject
mua_client_restrictions = permit_mynetworks,permit_sasl_authenticated,reject


##
## MySQL Abfragen
##

proxy_read_maps =       proxy:mysql:/etc/postfix/sql/aliases.cf
                        proxy:mysql:/etc/postfix/sql/accounts.cf
                        proxy:mysql:/etc/postfix/sql/domains.cf
                        proxy:mysql:/etc/postfix/sql/recipient-access.cf
                        proxy:mysql:/etc/postfix/sql/sender-login-maps.cf
                        proxy:mysql:/etc/postfix/sql/tls-policy.cf

virtual_alias_maps = proxy:mysql:/etc/postfix/sql/aliases.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/accounts.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/domains.cf
local_recipient_maps = $virtual_mailbox_maps


##
## Sonstiges
##

### Maximale Gr├Â├če der gesamten Mailbox (soll von Dovecot festgelegt werden, 0 = unbegrenzt)
mailbox_size_limit = 0

### Maximale Gr├Â├če eingehender E-Mails in Bytes (50 MB)
message_size_limit = 52428800

### Keine System-Benachrichtigung f├╝r Benutzer bei neuer E-Mail
biff = no

### Nutzer m├╝ssen immer volle E-Mail Adresse angeben - nicht nur Hostname
append_dot_mydomain = no

### Trenn-Zeichen f├╝r "Address Tagging"
recipient_delimiter = +

### Keine R├╝ckschl├╝sse auf benutzte Mailadressen zulassen
disable_vrfy_command = yes

Anzupassen:

  • inet_interfaces: IP-Adressen 203.0.113.1, 2001:db8::1 m├╝ssen durch eigene IPv4- (und optional IPv6)-Adresse ersetzt werden.
  • myhostname: Ersetzen durch eigenen Hostnamen
  • smtpd_tls_cert_file: Pfad zur Zertifikatsdatei
  • smtpd_tls_key_file: Pfad zur Zertifikatsdatei

Diffie-Hellman-Parameter f├╝r Postfix generieren

Neben Dovecot bekommt auch Postfix “von Hand generierte” DH-Parameter. Hier allerdings nur 2048 Bit starke, um zu ├Ąlteren Mailservern kompatibel zu bleiben.

openssl dhparam -out /etc/postfix/dh2048.pem 2048

Wundert euch ├╝brigens nicht ├╝ber das 1024 in der Einstellung smtpd_tls_dh1024_param_file - das ist nur Teil des Namens und hat keine Bedeutung f├╝r die Schl├╝ssell├Ąnge.

Wenn der Mailserver (entgegen meiner Empfehlung) nicht einen mail.domain.tld Hostnamen hat, sondern unter dem Domainnamen l├Ąuft (domain.tld), muss zur Konfiguration eine Zeile mit

mydestination =

(ohne Inhalt nach dem “=”) hinzugef├╝gt werden, sonst werden E-Mails an der falschen Stelle gespeichert.

Erkl├Ąrung

Netzwerkeinstellungen:

  • mynetworks: Anfragen von diesen IP-Adressen / aus diesen IP-Adressbereichen werden von Postfix gesondert behandelt (Verwendung f├╝r “mynetworks” in den Restrictions). ├ťblicherweise werden hier die lokalen Adressbereiche und IP-Adressen aus dem eigenen Netz eingetragen, z.B. von anderen eigenen, vertrauensw├╝rdigen Servern.
  • inet_interfaces: Auf diesen IP-Adressen soll Postfix seine Ports ├Âffnen. Die IP-Adressen m├╝ssen an den eigenen Server angepasst werden.
  • myhostname: Der Hostname des Mailservers, wie er bei der Mailverarbeitung genutzt werden soll.

Mail-Queue Einstellungen:

E-Mails in Postfix werden “gequeued”, d.h. in eine Warteschlange eingetragen, die regelm├Ą├čig abgearbeitet wird. Wenn Mails nicht zustellbar sind, verbleiben sie eine gewisse Zeit in der Queue, bis ihre Lebenszeit abgelaufen ist, und sie aus der Queue entfernt werden. Der Absender der E-Mail bekommt dann eine entsprechende Nachricht, in der er ├╝ber die Unzustellbarkeit informiert wird.

  • maximal_queue_lifetime: Lebensdauer einer normalen Nachricht in der Queue. Wenn eine E-Mail innerhalb einer Stunde nicht zugestellt werden konnte, wird sie aus der Queue entfernt und der Absender benachrichtigt.
  • bounce_queue_lifetime: Lebensdauer einer Unzustellbarkeits-Benachrichtigung in der Queue.
  • maximal_backoff_time: Maximale Zeit, die verstreichen darf, bis f├╝r eine E-Mail ein neuer Zustellversuch gestartet wird.
  • minimal_backoff_time: Zeit, die mindestens verstrichen sein muss, bis ein neuer Zustellversuch gestartet wird.
  • queue_run_delay: Intervall, in dem die Queue nach nicht zustellbaren E-Mails durchsucht wird.

TLS-Einstellungen:

Kompression wird abgeschaltet und (wie bei Dovecot) eine Cipherlist vorgegeben, sodass die bestm├Âgliche Verschl├╝sselung zwischen Client und Server genutzt wird. Im ersten Teilabschnitt werden die “smtp”-spezifischen TLS-Einstellungen festgelegt ÔÇô d.h. die Einstellungen, die Postfix als sendenden Kommunikationspartner (Mail-Client) betreffen.

  • smtp_tls_security_level: Standard-TLS-Policy, wenn sie in der Datenbank f├╝r die Empf├Ąngerdomain nicht anders spezifiziert wurde: “dane” kontrolliert zun├Ąchst, ob f├╝r den Empf├Ąngerserver ein TLSA-Eintrag (DANE) im DNS vorliegt. Wenn das der Fall ist, wird eine verschl├╝sselte Verbindung erzwungen und das vorgezeigte Serverzertifikat mittels TLSA-Eintrag verifiziert. Sollte kein TLSA-Eintrag verf├╝gbar sein, f├Ąllt Postfix in die Policy “may” zur├╝ck und verschl├╝sselt nur, wenn der andere Server das unterst├╝tzt. Zertifikate werden dabei nicht validiert. Sollten vorhandene TLSA-Eintr├Ąge ung├╝ltig sein, wird stattdessen die “encrypt” Policy genutzt, welche zwar zwingend verschl├╝sselt, aber Zertifikate ebenfalls nicht validiert. Mehr zu den TLS-Policies folgt sp├Ąter.
  • smtp_dns_support_level: DNSSEC-gesicherte DNS-Lookups aktiveren und nutzen, falls m├Âglich
  • smtpd_tls_policy_maps: Verweist auf die SQL-Queries, mit denen Empf├Ąngerdomain-spezifische TLS-Einstellungen geladen werden
  • smtp_tls_protocols: Veraltete SSL/TLS-Protokolle werden deaktiviert

Nun zum zweiten TLS-Block: Dieser gilt f├╝r eingehende Verbindungen. Sowohl f├╝r andere Server, als auch Mailclients. Wieder werden SSL v2 und 3 deaktiviert und eine starke Cipherlist ausgew├Ąhlt. Eingehende Verbindungen k├Ânnen verschl├╝sselt sein, m├╝ssen aber nicht.

LMTP-Service:

virtual_transport ├╝bermittelt verarbeitete, eingehende E-Mails an den LMTP-Service von Dovecot, der sich dann um die Einordnung der Mail in die passende Mailbox k├╝mmert.

Spamfilter und DKIM-Signaturen via Rspamd:

Dieser Abschnitt definiert den Rspam-Daemon als Milter f├╝r ein- und ausgehende E-Mails. Eingehende E-Mails werden durch Rspamd auf ihre Seriosit├Ąt gepr├╝ft - ausgehende werden mit einem DKIM-Schl├╝ssel signiert.

Server Restrictions:

Die Bl├Âcke unter “Server restrictions” sind besonders wichtig f├╝r die Sicherheit des Mailservers. Falsch eingestellt erlauben sie den unberechtigten Versand von E-Mails (Stichwort “Open Relay”). Der Mailserver wird dann als Spam-Schleuder missbraucht und landet sehr schnell auf einer Blacklist. Damit das nicht passiert, sollten die Restrictions (Beschr├Ąnkungen) sorgf├Ąltig eingestellt und mit einem passenden Open Relay Detektor ├╝berpr├╝ft sein.

Die Restrictions werden in Leserichtung nacheinander abgearbeitet. Am Ende jeder Verarbeitung steht immer ein “permit” oder “reject”. F├╝r das bessere Verst├Ąndnis ein Beispiel:

smtpd_relay_restrictions =      reject_non_fqdn_recipient
                                reject_unknown_recipient_domain
                                permit_mynetworks
                                reject_unauth_destination

smtpd_relay_restrictions bestimmt die Bedingungen, unter der Postfix als Mail-Relay (“Vermittlungsstelle”) arbeitet. Unser Postfix soll nur in drei F├Ąllen auf eingehende E-Mails reagieren:

  • Wenn ein Mailclient eine E-Mail via Postfix ins Internet schicken will
  • Wenn ein fremder Mailserver eine E-Mail an unseren Postfix schickt
  • Wenn vom Mailserver selbst aus eine Mail verschickt werden soll

Um den ersten Fall wird sich in der master.cf Datei gek├╝mmert. Dort werden die Relay Restrictions im Submission-Bereich so ├╝berschrieben, dass Mailclients nicht am freien Versenden gehindert werden. Aktuell interessieren daher nur die letzten beiden Anfrage-Typen. Die erste Zeile der Restriction lautet reject_non_fqdn_recipien. Sollte die Empf├Ąngeradresse keine vollwertige E-Mail Adresse sein, wird die Anfrage an Postfix direkt mit einem reject abgewiesen. Alle anderen Checks finden dann nicht mehr statt. Das f├╝hrt dazu, dass Postfix eine Weiterverarbeitung nur akzeptiert, wenn die zu verarbeitende E-Mail einen g├╝ltigen Empf├Ąnger hat. ├ähnliches gilt f├╝r reject_unknown_recipient_domain: Wenn die Empf├Ąngerdomain keinen g├╝ltigen MX- oder A-Eintrag im DNS hat (und der Zielserver damit nicht feststeht), wird die E-Mail abgelehnt.

Die darauf folgende Zeile enth├Ąlt die “Restriction” permit_mynetwork. Wenn der Anfragesteller lokal ist (bzw. seine IP in mynetworks vermerkt ist), wird er mit einem permit durchgewunken und die E-Mail wird weiter verarbeitet. Weitere Checks finden dann nicht statt. Sollte er nicht in mynetworks vermerkt sein, wird der letzte Check durchgef├╝hrt: reject_unauth_destination kann nur bestanden werden, wenn die zu verarbeitende E-Mail an eine Empf├Ąngeradresse dieses Mailsystems geht. Sollte bis zum Ende der restriction-Definition noch kein permit oder reject ausgel├Âst worden sein, wird automatisch ein permit ausgel├Âst und die jeweilige Aktion erlaubt.

Alle anderen Restriction-Definitionen funktionieren ├Ąhnlich: Die Kriterien werden nacheinander ├╝berpr├╝ft. Beginnt ein Kriterium mit einem reject, wird bei Zutreffen ein reject ausgel├Âst, beginnt es mit einem permit, wird ein permit ausgel├Âst. In beiden F├Ąllen werden die nachfolgenden Kriterien nicht mehr ├╝berpr├╝ft.

  • smtpd_relay_restrictions: Kriterien, die ├╝berpr├╝ft werden, wenn Anfragen am Postfix-Server eintreffen (Von fremden Mailservern oder vom eigenen Server aus, z.B. via sendmail)
  • smtpd_recipient_restrictions: Kriterien, die zus├Ątzlich zu den relay_restrictions gepr├╝ft werden. Nur bei bestehen der Checks wird eine E-Mail auf dem lokalen System angenommen und an die Empf├Ąnger-Mailbox geschickt. An dieser Stelle wird ├╝ber eine SQL-Abfrage nachgefragt, ob ein bestimmter Empf├Ąnger E-Mails empfangen k├Ânnen soll (=> Siehe Option in der Datenbank, Accounts nur zum Versenden freizuschalten).
  • smtpd_client-restrictions: Kriterien, auf die hin andere Server ├╝berpr├╝ft werden, wenn Kontakt zum Postfix-Server hergestellt wird. (M├╝ssen g├╝ltigen Hostnamen und Reverse-DNS-Eintrag haben)
  • smtpd_helo_restrictions: Fremde Server m├╝ssen zu Beginn ihren g├╝ltigen Hostnamen nennen.
  • smtpd_data_restrictions: Ungeduldige Server sind oft Spammer.

MySQL-Abfragen:

Hier sind die Pfade zu den ├╝brigen SQL-Dateien angegeben, die Postfix ben├Âtigt, um Daten aus der Datenbank abfragen zu k├Ânnen.

/etc/postfix/master.cf

# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
###
### SMTP-Serverbindungen aus dem Internet
### Authentifizuerung hier nicht erlaubt (Anmeldung nur via smtps/submission!)
smtp      inet  n       -       y       -       1       smtpd     
    -o smtpd_sasl_auth_enable=no
###
### SMTPS Service (Submission mit implizitem TLS - ohne STARTTLS) - Port 465
### F├╝r Mailclients gelten andere Regeln, als f├╝r andere Mailserver (siehe smtpd_ in main.cf)
###
smtps     inet  n       -       y       -       -       smtpd
    -o syslog_name=postfix/smtps
    -o smtpd_tls_wrappermode=yes
    -o smtpd_tls_security_level=encrypt
    -o smtpd_sasl_auth_enable=yes
    -o smtpd_sasl_type=dovecot
    -o smtpd_sasl_path=private/auth
    -o smtpd_sasl_security_options=noanonymous
    -o smtpd_client_restrictions=$mua_client_restrictions
    -o smtpd_sender_restrictions=$mua_sender_restrictions
    -o smtpd_relay_restrictions=$mua_relay_restrictions
    -o milter_macro_daemon_name=ORIGINATING
    -o smtpd_sender_login_maps=proxy:mysql:/etc/postfix/sql/sender-login-maps.cf
    -o smtpd_helo_required=no
    -o smtpd_helo_restrictions=
    -o cleanup_service_name=submission-header-cleanup
###
### Submission-Zugang f├╝r Clients (mit STARTTLS - f├╝r R├╝ckw├Ąrtskompatibilit├Ąt) - Port 587
###
submission inet n       -       y       -       -       smtpd
    -o syslog_name=postfix/submission
    -o smtpd_tls_security_level=encrypt
    -o smtpd_sasl_auth_enable=yes
    -o smtpd_sasl_type=dovecot
    -o smtpd_sasl_path=private/auth
    -o smtpd_sasl_security_options=noanonymous
    -o smtpd_client_restrictions=$mua_client_restrictions
    -o smtpd_sender_restrictions=$mua_sender_restrictions
    -o smtpd_relay_restrictions=$mua_relay_restrictions
    -o milter_macro_daemon_name=ORIGINATING
    -o smtpd_sender_login_maps=proxy:mysql:/etc/postfix/sql/sender-login-maps.cf
    -o smtpd_helo_required=no
    -o smtpd_helo_restrictions=
    -o cleanup_service_name=submission-header-cleanup
###
### Weitere wichtige Dienste f├╝r den Serverbetrieb
###
pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
###
### Cleanup-Service um MUA header zu entfernen
###
submission-header-cleanup unix n - n    -       0       cleanup
    -o header_checks=regexp:/etc/postfix/submission_header_cleanup

Die /etc/postfix/master.cf Datei will ich euch nur im Groben erkl├Ąren. Wichtig zu wissen ist, dass hier die Definition und Konfiguration der verschiedenen Postfix-Dienste wie z.B. smtpd (eingehende SMTP-Verbindungen) und smtp (ausgehende SMTP-Verbindungen) passiert. Gut zu erkennen ist, dass ├╝ber ein -o weitere Parameter an einen Dienst ├╝bergeben werden. So beispielsweise beim smtps-Dienst, der auf Port 465 f├╝r die SMTP-Kommunikation mit den Mailclients bereitsteht: Die hier angegebenen Einstellungen z.B. zu smtpd_relay_restrictions ├╝berschreiben die Einstellungen in der main.cf ÔÇô allerdings nur f├╝r diesen einen spezifischen Dienst! Ein gutes Beispiel ist die Einstellung smtpd_tls_security_level=encrypt, die im Submission-Block steht. In der main.cf hatten wir hier “may” definiert, um keine Server auszuschlie├čen, die TLS nicht beherrschen. Da smtpd-Einstellungen aber sowohl f├╝r andere Server als auch f├╝r Mailclient gelten, w├Ąre damit auch zu den Mailclients gesagt: “Ihr k├Ânnt verschl├╝sselte Verbindungen herstellen ÔÇô m├╝sst aber nicht”. Das wollen wir selbstverst├Ąndlich nicht! Mailclients sollen eine verschl├╝sselte Verbindung herstellen m├╝ssen! Deshalb wird die smtpd-Einstellung speziell f├╝r den smtps-Dienst mithilfe der -o Option ├╝berschrieben und auf “encrypt” gesetzt.

Der smtps Service am Anfang der Datei ist der SMTP-Dienst, zu dem sich Mailclients sp├Ąter verbinden sollen. Eine Verbindung ist hier nur ├╝ber direktes TLS (nicht StartTLS!) m├Âglich. F├╝r Clients, die sich zu Port 587 verbinden wollen, steht weiterhin der submission Service darunter bereit (auch wenn er in vielen F├Ąllen nicht mehr notwendig sein sollte).

F├╝r besseren Datenschutz wird der “Received”-Header (+ weitere Datenschutz-relevante Header) bei eingehenden E-Mails entfernt, wenn sie ├╝ber den smtps-Port eintreffen. Die meisten E-Mail-Clients senden ihren Namen und die Version mit. Zus├Ątzlich vermerkt Postfix bei eingehenden E-Mails, von welcher IP-Adresse die E-Mail stammt. Auf diese Informationen k├Ânnen wir verzichten, deshalb werden sie mithilfe eines kleinen zus├Ątzlichen Dienstes submission-header-cleanup (am Ende der Konfiguration) aus der E-Mail gel├Âscht. Im smtps- und Submission-Bereich wird via cleanup_service_name festgelegt, dass bei eingehenden Mails auf diesen Services der Filter anzuwenden ist. Die Filterregeln befinden sich in der Datei /etc/postfix/submission_header_cleanup

Header Cleanup Regeln

Unter /etc/postfix/submission_header_cleanup wird eine Datei mit folgendem Inhalt angelegt:

### Entfernt Datenschutz-relevante Header aus E-Mails von MTUAs

/^Received:/            IGNORE
/^X-Originating-IP:/    IGNORE
/^X-Mailer:/            IGNORE
/^User-Agent:/          IGNORE

SQL-Konfiguration

Neben der Haupt-Konfiguration main.cf und der Service-Konfiguration master.cf werden noch ein paar Konfigurationsdateien innerhalb des Unterverzeichnisses sql/ angelegt, die die SQL-Queries f├╝r die Datenabfragen an die Datenbank enthalten:

mkdir /etc/postfix/sql && cd $_

Erstellt dann die folgenden Konfigurationsdateien mit dem zugeh├Ârigen Inhalt:

accounts.cf

user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = select 1 as found from accounts where username = '%u' and domain = '%d' and enabled = true LIMIT 1;

aliases.cf

user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = SELECT DISTINCT concat(destination_username, '@', destination_domain) AS destinations FROM aliases
        WHERE (source_username = '%u' OR source_username IS NULL) AND source_domain = '%d'
        AND enabled = true
        AND NOT EXISTS (SELECT id FROM accounts WHERE username = '%u' and domain = '%d');

domains.cf

user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = SELECT domain FROM domains WHERE domain='%s';

recipient-access.cf

user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = select if(sendonly = true, 'REJECT', 'OK') AS access from accounts where username = '%u' and domain = '%d' and enabled = true LIMIT 1;

sender-login-maps.cf

user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = select concat(username, '@', domain) as 'owns' from accounts where username = '%u' AND domain = '%d' and enabled = true union select 
        concat(destination_username, '@', destination_domain) AS 'owns' from aliases 
        where source_username = '%u' and source_domain = '%d' and enabled = true;

tls-policy.cf

user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = SELECT policy, params FROM tlspolicies WHERE domain = '%s';

Vergesst nicht, vmaildbpass in jeder der Dateien durch euer eigenes Passwort zu ersetzen!

Alle SQL-Konfgurationsdateien in /etc/postfix/sql werden vor dem Zugriff durch unberechtigte User gesch├╝tzt:

chown -R root:postfix /etc/postfix/sql
chmod g+x /etc/postfix/sql

Weitere Postfix-Konfigurationsdateien

Au├čerdem gibt es noch eine weitere Datei /etc/postfix/without_ptr, die zun├Ąchst leer bleiben kann:

touch /etc/postfix/without_ptr

Die Datei kann sp├Ąter einmal Eintr├Ąge wie den folgenden beinhalten:

[2001:db8::beef] OK

Der Server mit der IP 2001:db8::beef muss dann keinen gültigen PTR-Record (Reverse DNS) mehr besitzen und wird trotzdem akzeptiert. Die without_ptr-Datei muss dann nach jeder Änderung in eine Datenbankdatei umgewandelt und Postfix neu geladen werden:

postmap /etc/postfix/without_ptr
systemctl reload postfix

Im Moment reicht es aber aus, einfach nur eine leere Datenbankdatei zu generieren:

postmap /etc/postfix/without_ptr

Zum Schluss wird einmal

newaliases

ausgef├╝hrt, um die Alias-Datei /etc/aliases.db zu generieren, die Postfix standardm├Ą├čig erwartet.

Rspamd

Da die Rspamd-Pakete f├╝r Debian nicht besonders aktuell sind und offiziell davon abgeraten wird, diese zu nutzen, nutzen wir an dieser Stelle das Debian-Repository des Rspamd-Projekts:

apt install -y lsb-release wget
wget -O- https://rspamd.com/apt-stable/gpg.key | apt-key add -
echo "deb http://rspamd.com/apt-stable/ $(lsb_release -c -s) main" > /etc/apt/sources.list.d/rspamd.list
echo "deb-src http://rspamd.com/apt-stable/ $(lsb_release -c -s) main" >> /etc/apt/sources.list.d/rspamd.list

Paketquellen aktualisieren und Rspamd installieren

apt update
apt install rspamd

Rspamd stoppen:

systemctl stop rspamd

Rspamd Webinterface

Grundkonfiguration

Die Konfiguration von Rspamd wird im Verzeichnis /etc/rspamd/local.d/ abgelegt. Die folgenden Konfigurationsdateien werden darin erstellt:

/etc/rspamd/local.d/worker-controller.inc: Einstellung des Worker controllers: Passwort f├╝r den Zugriff via Weboberfl├Ąche, z.B.:

password = "$2$qecacwgrz13owkag4gqcy5y7yeqh7yh4$y6i6gn5q3538tzsn19ojchuudoauw3rzdj1z74h5us4gd3jj5e8y";

Der Passworthash ($2$qecacwg...) wird via

rspamadm pw

generiert und in die Datei eingef├╝gt. Vergesst nicht das abschlie├čende ";!

/etc/rspamd/local.d/logging.inc: Error logging

type = "syslog";
level = "warning";

Milter Headers /etc/rspamd/local.d/milter_headers.conf

use = ["x-spamd-bar", "x-spam-level", "authentication-results"];
authenticated_headers = ["authentication-results"];

Redis f├╝r den Bayes’schen Filter nutzen: /etc/rspamd/local.d/classifier-bayes.conf

backend = "redis";

…und in /etc/rspamd/local.d/redis.conf:

servers = "127.0.0.1";

F├╝r den Bayes’schen Filter (Textanalyse) wird “Auto-Learning” aktiviert:

/etc/rspamd/override.d/classifier-bayes.conf:

autolearn = true;

Wird eine E-Mail bereits beim Empfang abgelehnt, weil sie ausgrund der Metadaten offensichtlich von einem Spammer kommt, nutzt Rspamd die Gelegenheit und lernt, dass der Text in dieser E-Mail als Spam einzustufen ist. So wird die Erkennungsrate mit jeder Spammail besser. (https://rspamd.com/doc/configuration/statistic.html)

Manuell gepflegte Black-/Whitelists

├ťber das Multimap-Modul kann das Verhalten von Rspamd f├╝r bestimmte E-Mail-Merkmale personalisiert gesteuert werden. Merkmale k├Ânnen zum Beispiel die Absender-IP-Adresse oder die Absendermailadresse sein. F├╝r beide registrieren wir in /etc/rspamd/local.d/multimap.conf jeweils eine Black- und eine Whitelist:

WHITELIST_IP {
    type = "ip";
    map = "$CONFDIR/local.d/whitelist_ip.map";
    description = "Local ip whitelist";
    action = "accept";
}

WHITELIST_FROM {
        type = "from";
        map = "$CONFDIR/local.d/whitelist_from.map";
        description = "Local from whitelist";
        action = "accept";
}

BLACKLIST_IP {
        type = "ip";
        map = "$CONFDIR/local.d/blacklist_ip.map";
        description = "Local ip blacklist";
        action = "reject";
}

BLACKLIST_FROM {
        type = "from";
        map = "$CONFDIR/local.d/blacklist_from.map";
        description = "Local from blacklist";
        action = "reject";
}

F├╝r alle vier Listen werden nun Listendateien erstellt:

cd /etc/rspamd/local.d
touch whitelist_ip.map
touch whitelist_from.map
touch blacklist_ip.map
touch blacklist_from.map
cd - 

“IP”-Listen k├Ânnen IPv6- und IPv4-Adressen bzw. Adressbereiche enthalten - in jeder Zeile ein Eintrag. “From”-Listen enthalten vollst├Ąndige Absendermailadressen. Die Listen k├Ânnen zun├Ąchst leer bleiben. Sie eignen sich gut, wenn man sp├Ąter einmal f├╝r einzelne Absender oder Server Ausnahmen einstellen m├Âchte.

DKIM Signing

Rspamd ├╝bernimmt auch das Signieren von ausgehenden E-Mails. Damit signiert werden kann, muss zun├Ąchst ein Signing Key generiert werden. Der Parameter -s 2020 gibt den sogenannten Selektor an - einen Namen f├╝r den Key (hier das Erstellungsjahr).

mkdir /var/lib/rspamd/dkim/
rspamadm dkim_keygen -b 2048 -s 2020 -k /var/lib/rspamd/dkim/2020.key > /var/lib/rspamd/dkim/2020.txt
chown -R _rspamd:_rspamd /var/lib/rspamd/dkim
chmod 440 /var/lib/rspamd/dkim/*

Zum Signing Key (/var/lib/rspamd/dkim/2020.key) geh├Ârt ein dazu passender Public Key, welcher in Form eines vorbereiteten DNS-Records in der Datei /var/lib/rspamd/dkim/2020.txt liegt.

DKIM Record ausgeben lassen:

cat /var/lib/rspamd/dkim/2020.txt

Die Ausgabe sieht z.B. so aus:

2020._domainkey IN TXT ( "v=DKIM1; k=rsa; "
    "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2/al5HqXUpe+HUazCr6t9lv2VOZLR369PPB4t+dgljZQvgUsIKoYzfS/w9NagS32xZYxi1dtlDWuRfTU/ahHO2MYzE0zHE4lMfwb6VkNCG+pM6bAkCwc5cFvyRygwxAPEiHAtmtU5b0i9LY25Z/ZWgyBxEWZ0Wf+hLjYHvnvMqewPsduUqKVjDOdUqeBb1VAu3WFErOAGVUYfKqFX"
    "+yfz36Alb7/OMAort8A5Vo5t5k0vxTHzkYYg5KB6tLS8jngrNucGjyNL5+k0ijPs3yT7WpTGL3U3SEa8cX8WvOO1fIpWQz4yyZJJ1Mm62+FskSc7BHjdiMHE64Id/UBDDVjxwIDAQAB"
) ;

Der Werte-Abschnitt des Records (beginnend mit v=DKIM1 bis zum Ende der Zeichenkolonne - hier AQAB) muss in einen neuen DNS-Record gepflanzt werden. Dabei werden Zeilenumbr├╝che und Anf├╝hrungsstriche entfernt. Je nach DNS-Hoster muss ein neuer Eintrag geringf├╝gig anders formatiert werden. Ich habe den Schritt im Screenshot beispielhaft f├╝r den Hoster Core-Networks.de mit dem Selector “2020” und meiner Beispieldomain “mysystems.tld” durchgef├╝hrt:

core-networks.de Screenshot mit DKIM Record

Wichtig: Der Selektor “2020” wird im DNS-Record zusammen mit ._domainkey als Name verwendet! Der DKIM-Record muss f├╝r jede verwendete Domain (domain2.tld, domain2.tld) im jeweiligen Zonefile erstellt werden!

Sollte der Record vom DNS-Hoster nicht akzeptiert werden, hilft es in einigen F├Ąllen, die Schl├╝ssell├Ąnge von 2048 Bit auf 1024 Bit zu reduzieren. Dazu das rspamadm dkim_keygen Kommando nochmals mit -b 1024 statt mit -b 2048 ausf├╝hren.

Der erzeugte DKIM-Key und der verwendete Selektor werden in der Konfigurationsdatei /etc/rspamd/local.d/dkim_signing.conf angegeben:

path = "/var/lib/rspamd/dkim/$selector.key";
selector = "2020";

### Enable DKIM signing for alias sender addresses
allow_username_mismatch = true;

Diese Konfiguration wird in die Datei /etc/rspamd/local.d/arc.conf kopiert, sodass das ARC-Modul korrekt arbeiten kann. Es greift auf dieselben Einstellungen zur├╝ck:

cp -R /etc/rspamd/local.d/dkim_signing.conf /etc/rspamd/local.d/arc.conf

Redis als Cache und Key-Value Store f├╝r Rspamd-Module

Rspamd verwendet Redis als Cache. Die Installation ist trivial:

apt install redis-server

In der Rspamd-Konfiguration wurde Redis bereits als Caching-Datenbank eingetragen.

Rspamd starten

Rspamd kann nun gestartet werden:

systemctl start rspamd

Nginx Proxy f├╝r Rspamd Weboberfl├Ąche

F├╝r den bequemen und sicheren Zugriff auf die Rspamd-Weboberfl├Ąche kann dieser ein Nginx HTTP-Proxy vorgeschaltet werden. Nginx k├╝mmert sich dann um die Absicherung der Verbindung via HTTPS. Wer nur selten auf die Rspamd-Weboberfl├Ąche zugreift, kann auf diesen Schritt verzichten und stattdessen auch ├╝ber einen SSH-Tunnel auf das Interface zugreifen (siehe unten).

F├╝r den Rspamd-Webproxy wird in /etc/nginx/sites-available/mail.mysystems.tld ein location Block wie folgt hinzugef├╝gt:

server {
        listen 80;
        listen [::]:80;
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        server_name mail.mysystems.tld imap.mysystems.tld smtp.mysystems.tld;

        ssl_certificate /etc/acme.sh/mail.mysystems.tld/fullchain.pem;
        ssl_certificate_key /etc/acme.sh/mail.mysystems.tld/privkey.pem;

        add_header Strict-Transport-Security max-age=15768000;

        location /rspamd/ {
                proxy_pass http://localhost:11334/;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        if ($ssl_protocol = "") {
            return 301 https://$server_name$request_uri;
        }
}

Anzupassen:

  • ssl_certificate: Pfad zu Zertifikat
  • ssl_certificate_key: Pfad zu Zertifikat
  • server_name

Konfiguration testen und Nginx neu laden:

nginx -t
systemctl reload nginx

Weboberfl├Ąche aufrufen

Unter https://mail.mysystems.tld/rspamd/ ist die Rspamd-Weboberfl├Ąche nun erreichbar. Als Passwort wird das weiter oben erzeugte Passwort f├╝r die Weboberfl├Ąche verwendet.

Via SSH-Tunnel mit der Weboberfl├Ąche verbinden (Alternative)

Statt ├╝ber Nginx kann man auch mithilfe eines SSH-Tunnels eine sichere Verbindung zur Rspamd-Weboberfl├Ąche aufbauen. Dazu ben├Âtigt man auf dem lokalen Rechner allerdings einen SSH-Client. Der SSH-Befehl

ssh -L 8080:localhost:11334 benutzer@mail.mysystems.tld -N

verkn├╝pft den Port des Webinterfaces (11334) mit Port 8080 des lokalen Systems. Im lokalen Webbrowser kann die Oberfl├Ąche nun unter http://localhost:8080 erreicht werden. Mit STRG+C wird die Verbindung wieder getrennt.

Rspamd mit bestehenden Spam-E-Mails trainieren (optional)

Wer einige Mails im Maildir-Format (jede E-Mail ist eine Datei) vorliegen hat, kann Rspamd mit ├╝ber das rspamc-Werkzeug trainieren. Dabei ist es ist vorteilhaft, nicht nur Spammail-Beispiele zu trainieren, sondern auch Beispiele f├╝r erw├╝nschte E-Mails. Im folgenden Beispiel wurde das Mailbox-Verzeichnis eines ├Ąlteren Mailservers importiert:

E-Mails in einem Verzeichnis als Spam antrainieren:

find ./oldserver/var/vmail/mailboxes/*/*/mail/Spam/cur -type f -exec /usr/bin/rspamc learn_spam {} \;

E-Mails in einem Verzeichnis als Ham (harmlos) antrainieren:

find ./oldserver/var/vmail/mailboxes/*/*/mail/cur -type f -exec /usr/bin/rspamc learn_ham {} \;
find ./oldserver/var/vmail/mailboxes/*/*/mail/Sent/cur -type f -exec /usr/bin/rspamc learn_ham {} \;

Auf der Rspamd-Weboberfl├Ąche wird nach dem Training eine entsprechend h├Âhere Anzahl an gelernten E-Mails angezeigt.

Autoconfig f├╝r Mozilla Thunderbird (Optional)

Mozilla Thunderbird (und andere Mailclients) versuchen bei der Einrichtung eines neuen Mailkontos automatisch, die korrekten Adressen und Einstellungen f├╝r IMAP- und SMTP-Server zu ermitteln. Die Autokonfiguration gibt uns die M├Âglichkeit, unter einer festgelegten Adresse https://autoconfig.<maildomain>.tld/mail/config-v1.1.xml Informationen zum Mailserver zu hinterlegen, sodass der Benutzer bei der Verkn├╝pfung seines Mailkontos nichts anderes als seine Mailadresse und das Passwort anzugeben braucht. Alle weiteren Informationen wie z.B. Art der Verschl├╝sselung oder Port bezieht Thunderbird aus der XML-Datei.

Da die Servereinstellungen in diesem Setup f├╝r alle Domains identisch sind, soll die XML-Datei unter https://autoconfig.mysystems.tld/mail/config-v1.1.xml zentral auf dem Mailserver verf├╝gbar gemacht werden. Sollten neben der “mysystems.tld” Domain noch die Domains “domain1.tld” und “domain2.tld” f├╝r E-Mail mitgenutzt werden, kann mittels HTTP-Proxies auf den Zielservern dieser Domains auf die zentrale Adresse weitergeleitet werden. Doch zun├Ąchst soll es nur um den mail.mysystems.tld Mailserver gehen …

DNS-Record anlegen

F├╝r die neue autoconfig.mysystems.tld Subdomain wird ein passender CNAME-Record im DNS angelegt, welcher auf den Mailserver zeigt:

autoconfig.mysystems.tld. 86400 IN CNAME mail.mysystems.tld.

Autoconfig auf dem Mailserver einrichten

Um die Datei auf dem Server anzubieten, wird ein weiterer Virtual Host f├╝r den Nginx-Webserver angelegt:

/etc/nginx/sites-available/autoconfig.mysystems.tld

server {
        listen 80;
        listen [::]:80;
#        listen 443 ssl http2;
#        listen [::]:443 ssl http2;

        server_name autoconfig.mysystems.tld;

#        ssl_certificate /etc/acme.sh/autoconfig.mysystems.tld/fullchain.pem;
#        ssl_certificate_key /etc/acme.sh/autoconfig.mysystems.tld/privkey.pem;

#        add_header Strict-Transport-Security max-age=15768000;

#        if ($ssl_protocol = "") {
#            return 301 https://$server_name$request_uri;
#        }

        root /var/www/mysystems.tld/autoconfig.mysystems.tld;

        location / {
                add_header Content-Type text/xml;
                charset utf-8;
        }
}

Wie auch bei der ersten Nginx-Konfiguration sind hier zun├Ąchst ein paar Zeilen auskommentiert, weil noch keine passenden TLS-Zertifikate vorhanden sind.

Konfiguration aktivieren, Nginx Config pr├╝fen und neu laden:

ln -s /etc/nginx/sites-available/autoconfig.mysystems.tld /etc/nginx/sites-enabled/autoconfig.mysystems.tld
nginx -t
systemctl reload nginx

F├╝r den neuen vHost wird ein Webroot directory angelegt:

mkdir -p /var/www/mysystems.tld/autoconfig.mysystems.tld/mail/

und die XML-Konfiguration darin abgelegt:

config-v1.1.xml

<?xml version="1.0" encoding="UTF-8"?>

<clientConfig version="1.1">
  <emailProvider id="mysystems.tld">
    <domain>mysystems.tld</domain>
    <displayName>mysystems.tld Mail</displayName>
    <displayShortName>mysystems.tld</displayShortName>
    <incomingServer type="imap">
      <hostname>imap.mysystems.tld</hostname>
      <port>993</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </incomingServer>
    <outgoingServer type="smtp">
      <hostname>smtp.mysystems.tld</hostname>
      <port>465</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </outgoingServer>
  </emailProvider>
</clientConfig>

Nun wird f├╝r autoconfig.mysystems.tld noch ein DNS-Record angelegt:

autoconfig.mysystems.tld IN CNAME mail.mysystems.tld.

TLS-Zertifikat beantragen und installieren:

acme.sh --issue --nginx -d autoconfig.mysystems.tld
mkdir -p /etc/acme.sh/autoconfig.mysystems.tld
acme.sh --install-cert -d autoconfig.mysystems.tld \
    --key-file /etc/acme.sh/autoconfig.mysystems.tld/privkey.pem  \
    --fullchain-file /etc/acme.sh/autoconfig.mysystems.tld/fullchain.pem \
    --reloadcmd "systemctl reload nginx"

Die auskommentierten Zeilen k├Ânnen nun entfernt und Nginx neu geladen werden:

systemctl reload nginx

Optional: Autoconfig Proxy f├╝r weitere Maildomains einrichten

Auf den (Web-)Servern, auf welche die weiteren Domains “domain1.tld” und “domain2.tld” verweisen, wird im Nginx jeweils ein vHost f├╝r “autoconfig.domain1.tld” bzw. “autoconfig.domain2.tld” angelegt:

/etc/nginx/sites-available/autoconfig.domain1.tld

server {
        listen 80;
        listen [::]:80;
#       listen 443 ssl http2;
#       listen [::]:443 ssl http2;

        server_name autoconfig.domain1.tld;

#       ssl_certificate /etc/acme.sh/autoconfig.mysystems.tld/fullchain.pem;
#       ssl_certificate_key /etc/acme.sh/autoconfig.mysystems.tld/key.pem;

#       add_header Strict-Transport-Security max-age=15768000;

#       if ($ssl_protocol = "") {
#           return 301 https://$server_name$request_uri;
#       }      

        location / {
                proxy_pass https://[fd80::1]:443;
                proxy_set_header HOST $host;
        }
}

Anzupassen: * server_name * IP-Adresse des Mailsystems mail.mysytems.tld bei proxy_pass

Die proxy_pass Anweisung nutzt die IPv6-Adresse fd::80 statt des Hostnamens unseres Mailservers, da Nginx direkt nach dem Booten noch keinen DNS-Resolver zur Namensaufl├Âsung verf├╝gbar hat.

Ein DNS-Eintrag f├╝r die neue Subdomain darf nicht fehlen:

autoconfig.domain1.tld IN CNAME domain1.tld.

Auch dieser VirtualHost sollte mit einem passenden TLS-Zertifikat abgesichert werden:

acme.sh --issue --nginx -d autoconfig.domain1.tld
mkdir -p /etc/acme.sh/autoconfig.domain1.tld
acme.sh --install-cert -d autoconfig.domain1.tld \
    --key-file /etc/acme.sh/autoconfig.domain1.tld/privkey.pem  \
    --fullchain-file /etc/acme.sh/autoconfig.domain1.tld/fullchain.pem \
    --reloadcmd "systemctl reload nginx"

Die auskommentierten Zeilen in der Nginx Konfiguration k├Ânnen nun auskommentiert werden.

Aktivieren der Konfiguration und Neuladen des Webservers:

ln -s /etc/nginx/sites-available/autoconfig.domain1.tld /etc/nginx/sites-enabled/autoconfig.domain1.tld
nginx -t
systemctl reload nginx

Ein Aufruf von https://autoconfig.domain1.tld/mail/config-v1.1.xml sollte nun dieselbe XML-Datei anzeigen, die bereits auf dem Mailserver unter autoconfig.mysystems.tld hinterlegt wurde. Diese XML-Datei muss nun analog zu mysystems.tld um domain1.tld erweitert werden, z.B. so:

<?xml version="1.0" encoding="UTF-8"?>

<clientConfig version="1.1">
  <emailProvider id="mysystems.tld">
    <domain>mysystems.tld</domain>
    <displayName>mysystems.tld Mail</displayName>
    <displayShortName>mysystems.tld</displayShortName>
    <incomingServer type="imap">
      <hostname>imap.mysystems.tld</hostname>
      <port>993</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </incomingServer>
    <outgoingServer type="smtp">
      <hostname>smtp.mysystems.tld</hostname>
      <port>465</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </outgoingServer>
  </emailProvider>

  <emailProvider id="domain1.tld">
    <domain>domain1.tld</domain>
    <displayName>domain1.tld Mail</displayName>
    <displayShortName>domain1.tld</displayShortName>
    <incomingServer type="imap">
      <hostname>imap.mysystems.tld</hostname>
      <port>993</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </incomingServer>
    <outgoingServer type="smtp">
      <hostname>smtp.mysystems.tld</hostname>
      <port>465</port>
      <socketType>SSL</socketType>
      <authentication>password-cleartext</authentication>
      <username>%EMAILADDRESS%</username>
    </outgoingServer>
  </emailProvider>
</clientConfig>

F├╝r “domain2.tld” ist genauso vorzugehen.

Domains, Accounts, Aliase und TLS-Policies in Datenbank definieren

Bevor der Mailserver sinnvoll genutzt werden kann, m├╝ssen noch Domains und Benutzer im der MySQL-Datenbank registriert werden. Loggt euch wieder auf der MySQL-Kommandozeile ein:

mysql

ÔÇŽ und wechselt in die vmail-Datenbank:

use vmail;

Neue Domain anlegen

Damit ein neuer Benutzeraccount oder ein neuer Alias angelegt werden kann, muss die zu nutzende Domain zuvor im Mailsystem bekannt gemacht werden. Postfix verarbeitet nur E-Mails an Domains, die in der “domains”-Tabelle eingetragen sind:

insert into domains (domain) values ('mysystems.tld');

Neuen E-Mail-Account anlegen

Wenn die Benutzerdomain in der Domain-Tabelle angelegt ist, kann ein neuer Benutzeraccount f├╝r den Mailserver erstellt werden. Bevor das passende SQL-Kommando eingegeben und abgeschickt wird, wird jedoch zu n├Ąchst ein Passwort-Hash des gew├╝nschten Passworts f├╝r den Account erzeugt. Mit

doveadm pw -s SHA512-CRYPT

(in der Bash Shell! - Nicht in der MySQL Shell!) kann ein solcher Hash erzeugt werden. Beispiel f├╝r einen ausgegebenen Hash:

{SHA512-CRYPT}$6$wHyJsS.doo39xoCu$KI1N4l.Vd0ZWYj5BYLI8AdK7ACwAZaM18gSy7Bko0dG2Hvli4.KfAmLk2ztFVP.R4T7oqiu7clKBehCTc4GGw0

Dieser Hash ist f├╝r jedes Passwort einzigartig und ├Ąndert sich sogar bei jeder Generierung. Legt den Hash am besten gleich in eurer Zwischenablage oder einem Textdokument ab - ihr ben├Âtigt ihn gleich!

Verwendet auch an dieser Stelle m├Âglichst nur die Zeichen 0-9, a-z und A-z. Sonderzeichen k├Ânnen Probleme verursachen. Wenn eure Passw├Ârter einigerma├čen lang sind, reicht das v├Âllig aus. Sonderzeichen bringen dann ohnehin keinen nennenswerten Sicherheitsgewinn.

Das SQL-Kommando zum Erzeugen eines neuen Accounts lautet:

insert into accounts (username, domain, password, quota, enabled, sendonly) values ('user1', 'mysystems.tld', '{SHA512-CRYPT}$6$wHyJsS[...]', 2048, true, false);

In das “Password”-Feld wird der Hash vollst├Ąndig eingetragen (hier: gek├╝rzt).

Legt am besten gleich den postmaster@mysystems.tld Account an. Er sollte auf jedem Mailserver vorhanden sein, um den Administrator bei technischen Problemen mit dem Server erreichen zu k├Ânnen.

Neuen Alias anlegen

insert into aliases (source_username, source_domain, destination_username, destination_domain, enabled) values ('alias', 'mysystems.tld', 'user1', 'mysystems.tld', true);

… legt einen Alias f├╝r den Benutzer “user1@mysystems.tld” an. E-Mails an “alias@mysystems.tld” werden dann an die Mailbox dieses Users zugestellt.

Als Zieladressen k├Ânnen auch E-Mail-Konten auf fremden Servern angegeben werden. Postfix leitet diese E-Mails dann weiter. Dabei kann es allerdings zu Problemen mit SPF-Records kommen ÔÇô schlie├člich schickt Postfix unter bestimmten Umst├Ąnden E-Mails unter fremden Domains, f├╝r die er laut SPF-Record nicht zust├Ąndig ist. SRS (Sender Rewriting Scheme) ist eine L├Âsung f├╝r dieses Problem. Von Erweiterungen, die schwerwiegende Design-Fehler einer Technik wie SPF korrigieren, halte ich allerdings nicht besonders viel, sodass ich euch empfehle, den SPF-Record (wie oben) auf einem “?all” gestellt zu lassen und auf Weiterleitungen zu fremden Servern m├Âglichst zu verzichten. Aliase von lokalen Adressen auf andere lokale Adressen sind kein Problem.

Wenn ein E-Mail-Verteiler eingerichtet werden soll, werden mehrere Datens├Ątze mit derselben Quelladresse eingerichtet, also z.B. so:

team@domain.tld => user1@domain.tld
team@domain.tld => user2@domain.tld
team@domain.tld => user3@domain.tld

Ein Catch-All hingegen kann erreicht werden, indem der source_username auf null gesetzt wird, z.B. so:

insert into aliases (source_username, source_domain, destination_username, destination_domain, enabled) values (null, 'domain1.tld', 'catchall', 'mysystems.tld', true);

Ein Catch-All kann mit anderen Aliasen auf derselben Domain ko-existieren und “f├Ąngt” alle Benutzernamen auf der jeweiligen Domain auf, f├╝r die noch kein Alias gesetzt wurde. So kann man Mails zentral aufsammeln, welche an Mailboxen verschickt wurden, die auf dem Mailserver nicht existieren. Beachtet, dass dadurch das Spamaufkommen ggf. h├Âher ist.

Neue TLS-Policy anlegen (optional)

Mithilfe der TLS Policy-Tabelle kann festgelegt werden, mit welchen Sicherheitsfeatures mit den Mailservern einer bestimmten Domain kommuniziert werden soll. Wenn f├╝r die Domain “thomas-leister.de” beispielsweise “dane-only” in “policy” festgelegt wird, wird die Verbindung zu Mailservern dieser Domain nur noch g├╝ltig sein, wenn sie DANE-authentifiziert und verschl├╝sselt ist. M├Âgliche Policies sind:

  • none: Keine Verschl├╝sselung nutzen, auch wenn der andere Mailserver das unterst├╝tzt.
  • may: Verschl├╝sseln, wenn der andere Server dies unterst├╝tzt, aber keine Zertifikatspr├╝fung (self-signed Zertifikate werden akzeptiert).
  • encrypt: Zwingend Verschl├╝sseln, allerdings keine Zertifikatspr├╝fung (self-signed Zertifikate werden akzeptiert).
  • dane: Wenn g├╝ltige TLSA-Records gefunden werden, wird zwingend verschl├╝sselt und das Zertifikat mittels DANE verifiziert. Falls ung├╝ltige TLSA-Records gefunden werden, wird auf “encrypt” zur├╝ckgegriffen. Falls gar keine TLSA-Records gefunden werden, wird “may” genutzt.
  • dane-only: Nur verschl├╝sselte Verbindungen. G├╝ltige TLSA-Records f├╝r den Hostnamen m├╝ssen existieren (DANE)
  • verify: Nur verschl├╝sselte Verbindungen + Pr├╝fung der CA. Der Hostname aus dem MX DNS-Record muss im Zertifikat enthalten sein. (Basiert auf Vertrauen in korrekte DNS-Daten)
  • secure: Nur verschl├╝sselte Verbindungen + Pr├╝fung der CA. Der andere Mailserver muss (standardm├Ą├čig) einen Hostnamen haben, der “.domain.tld” oder nur “domain.tld” entspricht. Dieser Hostname muss im Zertifikat enthalten sein. Auf das DNS wird nicht zur├╝ckgegriffen (Sicherheitsvorteil gegen├╝ber “verify). Beispiel: Eine E-Mail an user@web.de soll gesendet werden. Der MX-Mailserver von Web.de d├╝rfte dann nur den Hostnamen “web.de” oder eine Subdomain davon als Hostnamen haben, z.B. mx.web.de. Eine Verbindung zu mx.web.net w├Ąre nicht zul├Ąssig.

F├╝r Domains der gro├čen Anbieter wie gmx.de, web.de und der Telekom kann man “secure” w├Ąhlen. Bei Posteo und Mailbox.org sogar “dane-only”. F├╝r alle Provider, die keine g├╝ltigen TLS-Zertifikate einsetzen, kann “encrypt” gew├Ąhlt werden. Standardeinstellung f├╝r alle anderen Mailserver ist “dane” (siehe main.cf der Postfix Config).

Das Feld “params” wird mit zus├Ątzlichen Infos gef├╝llt, wenn sie f├╝r einen Policy-Typ erforderlich sind, z.B. f├╝r einen “secure” Eintrag zu GMX:

insert into tlspolicies (domain, policy, params) values ('gmx.de', 'secure', 'match=.gmx.net');

Standardm├Ą├čig ├╝berpr├╝ft Postfix bei “secure” ÔÇô wie oben bereits erw├Ąhnt ÔÇô ob die Empf├Ąngerdomain (gmx.de) im Zertifikat des Zielservers vorhanden ist. Bei GMX (und vielen anderen gro├čen Anbietern) ist das allerdings nicht der Fall: Die Mailserver-Zertifikate von GMX sind nur f├╝r gmx.net + Subdomains g├╝ltig. Lie├če man den Datenbank-Eintrag f├╝r GMX ohne weitere Einstellungen auf “secure” stehen, k├Ânnten an GMX keine Mails mehr ├╝bermittelt werden. Deshalb ist es wichtig, f├╝r GMX festzulegen, dass im Zertifikat nicht nach “gmx.de” sondern nach “gmx.net” gesucht werden soll. Das k├Ânnen wir mithilfe des Felds “params” und der “match=ÔÇŽ” Zeichenkette tun. Wenn nach mehreren Domains gesucht werden soll, k├Ânnen auch mehrere angegeben werden, z.B. so: “match=.gmx.net:.gmx.ch”. Die zus├Ątzlichen Angaben in “params” sind allerdings nicht f├╝r jeden Mailprovider notwendig. GMX ist eine Ausnahme ÔÇô genauso wie z.B. Yahoo. Ob ihr in “params” einen “match”-String angeben m├╝sst, k├Ânnt ihr z.B. ├╝ber https://de.ssl-tools.net/ herausfinden. Wenn die 2-nd-Level-Domain des Mailservers von der Domain der Mailadressen abweicht, muss ein passender match-String angegeben werden.

Andere Einstellungen wie “dane-only” erfordern keine zus├Ątzlichen Angaben in “params”:

insert into tlspolicies (domain, policy) values ('mailbox.org', 'dane-only');

In diesem Fall wird mit den Mailservern von mailbox.org nur noch DANE-gesichert und verschl├╝sselt kommuniziert. Die MySQL-Kommandozeile kann mit einem quit; wieder verlassen werden.

Optional: Firewall konfigurieren

Wer vor / auf dem Mailserver eine Firewall betreibt, die den Zugriff auf Ports beschr├Ąnkt, sollte zuerst alle Mailserver-Ports freischalten:

IMAP:           143/tcp
IMAPS:          993/tcp
Submission:     587/tcp
SMTPS:          465/tcp
SMTP:            25/tcp
ManageSieve:   4190/tcp
Web HTTP:        80/tcp
Web HTTPS:      443/tcp

Denkt unbedingt daran, auch eure IPv6-Ports zu ├Âffnen! - Euer Mailsetup spricht IPv6! :-) Die Ports 143 und 587 k├Ânnen geschlossen bleiben, wenn keine StartTLS-basierenden Verbindung genutzt werden sollen (siehe Hinweis weiter unten).

Start all the things!

Euer neuer Mailserver ist jetzt fertig konfiguriert. Zeit f├╝r einen ersten Start!

systemctl start dovecot
systemctl start postfix

Wegen des Bugs #877992 startet Postfix nach einem Reboot nicht mehr. Abhilfe schafft folgendes Kommando:

systemctl enable postfix@-

(beachte das Minuszeichen - am Ende!)

Kontrolliert am besten gleich die Logfiles nach auff├Ąlligen Fehlern. Ich empfehle das “tail” Tool in einer separaten Terminal-Sitzung. Neue Log-Eintr├Ąge erscheinen damit sofort auf dem Bildschirm:

tail -f /var/log/syslog

bzw.

tail -f /var/log/mail.log

Wenn ihr hier Fehler entdeckt, seht nach, ob ihr alle erforderlichen Änderungen an den Konfigurationsdateien durchgeführt habt (oder ob sich noch beispielhafte Hashes oder Beispieldomains darin befinden).

Eine Verbindung zum Mailserver herstellen

Mailserver Logindaten f├╝r Thunderbird

Eine Verbindung k├Ânnt ihr ├╝ber jeden IMAP-f├Ąhigen E-Mail-Client und den folgenden Verbindungsparametern herstellen:

  • IMAP(S)
    • Host: imap.mysystems.tld
    • Port: 993
    • Verschl├╝sselung: TLS
    • (dieser Server gilt auch f├╝r domain2 und domain3, falls vorhanden!)
  • SMTP(S)
    • Host: smtp.mysystems.tld
    • Port: 465
    • Verschl├╝sselung: TLS
    • (dieser Server gilt auch f├╝r domain2 und domain3, falls vorhanden!)
  • Managesieve (optional, zur Konfiguration der benutzerspezifischen Sieve-Filterregeln)
    • Host: imap.mysystems.tld
    • Port: 4190 *V erschl├╝sselung: StartTLS
  • Benutzername: Die vollst├Ąndige E-Mail-Adresse, also @
  • Passwort: Sollte bekannt sein ;-)

Sollten Verbindungen ├╝ber die IMAPS (993) und SMTPS (465) Ports nicht m├Âglich sein, kann auch auf die StartTLS-Ports zur├╝ckgegriffen werden:

  • IMAP-Server:
    • Host: mail.mysystems.tld
    • Port: 143
    • Verschl├╝sselung: StartTLS
  • SMTP-Server:
    • Host: mail.mysystems.tld
    • Port: 587
    • Verschl├╝sselung: StartTLS

Die IETF (Internet Engineering Task Force) empfiehlt seit 2018 allerdings, auf StartTLS Verbindungen zu verzichten, und auf native TLS-Verbindungen zu setzen: https://tools.ietf.org/html/rfc8314

Der erste Login kann ein paar Sekunden in Anspruch nehmen - habt etwas Gedult. Dovecot legt im Hintergrund die Verzeichnisstruktur f├╝r den neuen Benutzer an.

Spamfilter testen

Schickt einfach eine E-Mail mit dem Text

XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X

an einen Account eures neuen Mailservers. Die E-Mail sollte nicht ankommen und im Rspamd-Webinterface erscheint ein entsprechender rot markierter Eintrag in der History.

Debugging

Sollten Probleme auftreten, hilft ein Blick ins Log!

Das Rspamd Log kannst du z.B. so einsehen und live mitlesen:

journalctl -f -u rspamd

Postfix so:

journalctl -f -u postfix@-.service

… und Dovecot so:

journalctl -f -u dovecot

Das war’s auch schon! Hat dir diese Anleitung geholfen?

Wenn ich dir mit dieser Anleitung helfen konnte, deinen Mailserver aufzusetzen, ist dir das vielleicht ein paar Euro wert.

Wie du dir sicherlich vorstellen kannst, war es eine Menge Arbeit, diese Anleitung zu schreiben und zu erproben. Daher freue ich mich nat├╝rlich riesig ├╝ber eine Motivationsst├╝tze und finanzielle Hilfe, um Testserver und -Umgebungen bezahlen zu k├Ânnen, oder mir nach getaner Arbeit ein k├╝hles Bier zu leisten.

Wie du mir etwas zukommen lassen kannst, erf├Ąhrst du hier: Unterst├╝tzen

Herzlichen Dank!


Fragen und Antworten

“Darf ich deine Anleitung ├╝bernehmen?”

Nein. Du kannst dir sicherlich vorstellen, dass hinter meiner Anleitung viel M├╝he und Arbeit steckt. Ich stelle sie nicht frei zur Verf├╝gung und bitte darum, meinen Text nicht ohne ausdr├╝ckliche Zustimmung zu re-publizieren (auch nicht in privaten, aber ├Âffentlich zug├Ąnglichen Blogs!). Also ein klares “Nein” zu Copy & Paste + Wiederver├Âffentlichung. Private, nicht-├Âffentliche Kopien oder Kopien f├╝r den Firmen-internen Gebrauch sind nat├╝rlich erlaubt. Es geht mir auch darum, diesen Beitrag nicht auf irgendeinem fremden Blog wiederzufinden, der wom├Âglich sogar noch Geld mit fremden Content verdient. Verlinken ist nat├╝rlich absolut erlaubt und ausdr├╝cklich erw├╝nscht ;-)

“Wieso ver├Âffentlichst du deine Anleitung auf deinem Blog und nicht in einem Wiki?”

Weil ich hier die volle Kontrolle habe. Was hier steht, ist in sich konsistent und kein Flickenteppich. In den g├Ąngigen Wikis darf dieser Beitrag nat├╝rlich gerne erg├Ąnzend verlinkt werden.

Ich habe das nicht getestet!

Welche Daten sollte ich f├╝r Backups Sichern?

Folgende Verzeichnisse sollten ins Backup aufgenommen werden:

  • /etc/postfix (Postfix Konfiguration)
  • /etc/dovecot (Dovecot Konfiguration)
  • /etc/rspamd (Rspamd Konfiguration)
  • /var/vmail (E-Mails, Benutzerkonteneinstellungen und Sieve-Filter)
  • /var/lib/rspamd/dkim (DKIM-Schl├╝ssel)
  • /var/www/mysystems.tld/autoconfig.mysystems.tld (Autoconfig-Datei)

Au├čerdem sollte unbedingt regelm├Ą├čig ein MySQL-Dump der vmail Datenbank generiert, in eine Datei geschrieben und ins Backup aufgenommen werden:

mysqldump vmail > /root/backups/vmail.sql

H├Ąufige Fehler

“fatal: no SASL authentication mechanisms” / “SASL: Connect to private/auth failed: No such file or directory”

Das Problem: Postfix kann Benutzer nicht authentifizieren, weil in /var/spool/postfix/private kein “auth” Socket verf├╝gbar ist. Eigentlich sollte Dovecot diesen Socket bereitstellen. Der Fehler ist also bei Dovecot zu suchen ÔÇô nicht bei Postfix. Leider hat die Erfahrung gezeigt, dass ein Vertipper nicht zwingend in der Socket-Konfiguration

unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
}

vorhanden sein muss. Es kommt immer wieder vor, dass der Fehler irgendwo anders in der Dovecot-Konfiguration liegt. Dovecot verschweigt einem dann den Fehler und erstellt den auth-Socket f├╝r Postfix nicht. Es lohnt sich in so einem Fall, noch einmal die ganze Dovecot-Konfiguration nach Fehlern abzusuchen.

“5.7.1 Service unavailable; client [1.3.3.7] blocked using zen.spamhaus.org”

Das Problem: Der Mailserver akzeptiert keine E-Mails vom Mailclient und gibt die oben genannte Fehlermeldung zur├╝ck.

Das Problem l├Ąsst sich sehr einfach l├Âsen, indem statt SMTP-Port 25 der SMTS-Port 465 oder Submission-Port 587 f├╝r den Mailversand im Mailclient konfiguriert wird. Auf Port 25 ist eine Blacklist aktiv, welche viele IP-Adressen z.B. aus DSL-Adressbereichen enth├Ąlt. Diese Einschr├Ąnkung gilt f├╝r die beiden anderen Ports nicht. Mailclients sollten niemals Port 25 zum versenden Nutzen.

Mailclient verbindet sich nicht zum Server

  • Evtl. blockiert der Virenschutz die Verbindung?
  • Blockiert die Server-Firewall die Verbindung von au├čen?
  • Ist die richtige Serveradresse angegeben? (siehe Verbindungseinstellungen oben)
  • Werden die richtigen Ports genutzt und ist der Verschl├╝sselungstyp richtig eingestellt?

Danksagung

Danke an alle, die sich an dem Schaffensprozess beteiligt haben! Durch Feedback, durch Testen oder durch kritisches Nachfragen ;-)

Besonders:

  • Simon Hoffmann, der die erste Fassung meiner Anleitung getestet hat.
  • t.b.c.

Changelog

├änderungen seit Ver├Âffentlichung

  • Erstver├Âffentlichung am xx.04.2020

├änderungen zur Vorg├Ąngerversion “Mailserver unter Debian Stretch”

  • Postfix: “VRFY” Funktion entfernt, um genutzte Mailadressen nicht zu leaken (disable_vrfy_command = no in der main.cf)
  • Dovecot: Push Notifications aktiviert (LMTP Plugins: notify push_notification in dovecot.conf hinzugef├╝gt)
  • Unbound: Root-Key muss nicht mehr von Hand angelegt werden. Keine weiteren Schritte nach Installation notwendig.
  • Postfix: smtp(d)_tls_protocols = !SSLv2, !SSLv3 entfernt, da diese nun default sind.
  • ACME.sh statt Certbot als Letsencrypt Client
  • Postfix + Dovecot: Aktualisierung der Ciphersuites und TLS-Einstellungen, DH-Parameter selbst generiert und explizit konfiguriert.
  • Postfix: Submission auch auf Port 465 (Implicit TLS / “SMTPS”) angeboten - siehe master.cf “smtps” Service. Auf Dovecot-Seite war IMAPS (Port 993) bereits verf├╝gbar. Dazu siehe auch: https://tools.ietf.org/html/rfc8314
  • Postfix: Postscreen abgeschaltet. Rspamd ├╝bernimmt nun DNS Blacklist checks, um gleichzeitig besser lernen zu k├Ânnen (siehe n├Ąchster Punkt). ├änderungen in master.cf und main.cf
  • Rspamd Autolearning aktiviert (/etc/rspamd/override.d/classifier-bayes.conf: autolearn = true;)
  • Nginx: Nginx als fester Bestandteil des Setups
  • Postfix: In allen SQL-Dateien: hosts = unix:/run/mysqld/mysqld.sock
    chgrp -R postfix /etc/postfix/sql
    chmod g+x /etc/postfix/sql
    vor alle mysql: deklarationen ein proxy: schreiben (in master.cf und main.cf)
    in main.cf: proxy_read_maps definiert.
  • Dovecot: /etc/dovecot/dovecot-sql.conf host=localhost gesetzt, um UNIX Socket zu benutzen.
  • Rspamd: Eigene Konfiguration in /etc/rspamd/local.d reduziert.
  • Rspamd: Logging jetzt via syslog. Auslesen z.B. via journalctl -f -u rspamd. Loglevel auf “warning”.
  • Rspamd: Black- und Whitelists f├╝r IP-Adressen und Absendermailadressen hinzugef├╝gt.
  • Domain Catch-All per default erm├Âglicht, indem in der Alias-Tabelle source_username “nullable” gemacht wurde (Umstellung: ALTER TABLE aliases MODIFY source_username VARCHAR(64) null;). Au├čerdem /etc/postfix/aliases.cf angepasst.
  • Vmail-User: Shell deaktiviert (auf “nologin” gesetzt) - wird nicht ben├Âtigt. Nachtr├Ąglich m├Âglich via chsh -s /usr/sbin/nologin vmail.
  • dovecot.conf: recipient_delimiter gesetzt, um address tagging zu unterst├╝tzen (wird von Postfix bereits unterst├╝tzt)

Ideenkiste