Mailserver mit Dovecot, Postfix, MySQL und Rspamd unter Debian 9 Stretch

Ziel dieser für Debian 9 “Stretch” aktualisierten Anleitung ist ein fertig installierter und konfigurierter Mailserver auf einem eigens dafür bereitgestellten Host. Der Beitrag basiert im wesentlichen auf dem zuvor für Ubuntu 16.04 vorgestellten Setup. In dieser aktualisierten Version wird statt eines Amavis-Spamassassin-Razor Stacks und OpenDKIM allerdings Rspamd genutzt, um die Komplexität und Fehleranfälligkeit des Setups zu reduzieren und gleichzeitig von der hervorragenden Funktion des Rspam Daemons zu profitieren. Außerdem wurden in diese Anleitung einige kleine Verbesserungen eingebracht, die mir von Lesern in den letzten Monaten vorgeschlagen wurden.

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.

Eine neue Anleitung für Debian 10 “Buster” steht in den Startlöchern! Ich habe einige Detailverbesserungen in die Anleitung einfließen lassen. Datenbankgeschema und Dateisystemstruktur bleiben erhalten, sodass ein einfacher Umstieg auf das neue Setup möglich ist. Das neue Setup befindet sich noch in der Erprobungsphase. Wenn du es trotzdem ausprobieren möchtest, kannst du die neue Anleitung hier finden: https://thomas-leister.de/mailserver-debian-buster/
Wer lieber auf eine fertige Lösung setzt und sich die Handarbeit sparen will, sollte sich einmal Mailcow von André Peters ansehen.

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 von eingehenden E-Mails
  • Hochperformante Spam-Früherkennung via Postscreen
  • Erweiterte Spamerkennung via Rspamd (+ Weboberfläche für Spam-Statistiken)
  • “Send only” Accounts z.B. für NextCloud / Forensoftware / …
  • DKIM-Signierung ausgehender E-Mails

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 9 “Stretch”
  • Postfix
  • Dovecot
  • Rspamd
  • Redis
  • MariaDB
  • Nginx (optional)
Dieses Setup ist standardmäßig nicht vollständig kompatibel mit Ubuntu Server! Die Distribution liefert aktuell (Stand Januar 2018) eine ältere Version von Dovecot mit, sodass beispielsweise imap_sieve nicht verfügbar ist. Das Problem kann behoben werden, indem für Ubuntu Server das PPA https://launchpad.net/%7Epdoes/+archive/ubuntu/dovecot für eine aktuellere Dovecot-Version hinzugefügt wird.

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.

Grundvoraussetzungen für den Mailserver

  • Ein virtueller oder dedizierter Server mit bereits installiertem Debian 9 Stretch
    (“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 Hetzner bekommen.

Komponenten eines vollständigen Mailsystems

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.

Aufgaben: Verwaltung der Mailbox, Bereitstellung einer Schnittstelle zum Abrufen erhaltener E-Mails, SASL-Authentifizierungsserver (überprüft Benutzeranmeldung)

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.

Aufgaben: E-Mail-Transport und -Filterung

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.

Aufgaben: Bereitstellung Betriebsdaten für Postfix und Dovecot

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.

Aufgaben: Filtern von Spam, DKIM-Signierung

Nginx (optional)

Nginx ist ein beliebter und schlanker Webserver / Webproxy. Hier wird er als HTTP-Proxy vor Rspamd verwendet, um die Weboberfläche des Spamfilters abgesichert nach außen hin zugänglich zu machen.

Aufgaben: Proxying für Rspamd-Weboberfläche

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).

Aufgaben: Caching, Memory

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 9 Stretch 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.)

Tipp: 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 (wie sie später verwendet werden) 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

DNSSEC Root Key aktualisieren und Unbound neu laden:

su -c "unbound-anchor -a /var/lib/unbound/root.key" - unbound
systemctl reload unbound
Für die nächsten Kommandos muss das Paket “dnsutils” installiert sein. Wenn bei der Installation von Debian die “Standard-Systemwerkzeuge” ausgewählt wurden, sind die Tools schon installiert.

Ein dig @127.0.0.1 denic.de +short +dnssec sollte eine ähnliche Ausgabe wie folgt erzeugen:

dig @127.0.0.1 denic.de +short +dnssec
81.91.170.12
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 127.0.0.1" >> /etc/resolvconf/resolv.conf.d/head

ein nslookup denic.de | grep Server sollte nun

Server:		127.0.0.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    5.1.76.155
mail.mysystems.tld. 86400 IN AAAA 2a00:f820:417::be19:7b23

“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 ?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.

Einrichtung der TLS-Zertifikate (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.

Abholen neuer Zertifikate

Der kürzeste Weg zu neuen Zertifikaten führt über den offiziellen Let’s Encrypt Client “Certbot”:

apt install certbot
certbot certonly --standalone --rsa-key-size 4096 -d mail.mysystems.tld -d imap.mysystems.tld -d smtp.mysystems.tld

Nach Zustimmung der Nutzungsbedingungen sind innerhalb von wenigen Sekunden neue, gültige TLS-Zertifikate auf dem System installiert. Mit dem neuen Zertifikat unter /etc/letsencrypt/live/mail.mysystems.tld sind die drei Domains

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

abgesichert. Im oben genannten Verzeichnis befinden sich drei Dateien:

  • cert.pem: Das eigentliche Zertifikat
  • chain.pem: CA Zertifikat
  • fullchain.pem: Das Zertifikat + CA Zertifikat
  • privkey.pem: Der geheime Zertifikats-Schlüssel

später werden nur die letzten beiden Zertifikatsdateien verwendet.

Automatische Erneuerung

Let’s Encrypt-Zertifikate laufen nach 90 Tagen aus und sind dann ungültig. Deshalb sollten die Zertifikate regelmäßig erneuert werden - zum Beispiel über den folgenden CronJob:

@weekly certbot renew --pre-hook "systemctl stop nginx" --post-hook "systemctl start nginx" --renew-hook "systemctl reload nginx; systemctl reload dovecot; systemctl reload postfix" --quiet

Dieser Eintrag wird nach der Eingabe von

crontab -e

(und der anschließenden Wahl des bevorzugten Editors - Empfehlung: nano) in die Cron-Datei unten eingetragen und gespeichert.

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”!):

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) NOT NULL,
    `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-Verzeichnis erstellen:

mkdir /var/vmail

vmail-Systembenutzer erstellen:

adduser --disabled-login --disabled-password --home /var/vmail vmail

vmail Unterverzeichnisse erstellen:

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

Verzeichnis /var/vmail 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 dovecot.conf

###
### Aktivierte Protokolle
#############################

protocols = imap lmtp sieve



###
### TLS Config
#######################

ssl = required
ssl_cert = </etc/letsencrypt/live/mail.mysystems.tld/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.mysystems.tld/privkey.pem
ssl_cipher_list = EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA
ssl_prefer_server_ciphers = yes



###
### 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
}



###
### 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
}


###
### 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”).

Maillocation: 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.

SQL-Konfgurationsdatei dovecot-sql.conf

driver=mysql
connect = "host=127.0.0.1 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"];

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:

main.cf

##
## Netzwerkeinstellungen
##

mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
inet_interfaces = 127.0.0.1, ::1, 5.1.76.152, 2a00:f820:417::7647:b2c2
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
###

tls_preempt_cipherlist = yes
tls_ssl_options = NO_COMPRESSION
tls_high_cipherlist = EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA

### Ausgehende SMTP-Verbindungen (Postfix als Sender)

smtp_tls_security_level = dane
smtp_dns_support_level = dnssec
smtp_tls_policy_maps = mysql:/etc/postfix/sql/tls-policy.cf
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_protocols = !SSLv2, !SSLv3
smtp_tls_ciphers = high
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt


### Eingehende SMTP-Verbindungen

smtpd_tls_security_level = may
smtpd_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_ciphers = high
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache

smtpd_tls_cert_file=/etc/letsencrypt/live/mail.mysystems.tld/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.mysystems.tld/privkey.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 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


##
## Postscreen Filter
##

### Postscreen Whitelist / Blocklist
postscreen_access_list =        permit_mynetworks
                                cidr:/etc/postfix/postscreen_access
postscreen_blacklist_action = drop


# Verbindungen beenden, wenn der fremde Server es zu eilig hat
postscreen_greet_action = drop


### DNS blocklists
postscreen_dnsbl_threshold = 2
postscreen_dnsbl_sites =    ix.dnsbl.manitu.net*2
                            zen.spamhaus.org*2
postscreen_dnsbl_action = drop


##
## MySQL Abfragen
##

virtual_alias_maps = mysql:/etc/postfix/sql/aliases.cf
virtual_mailbox_maps = mysql:/etc/postfix/sql/accounts.cf
virtual_mailbox_domains = 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 = +

Anzupassen:

  • inet_interfaces: IP-Adressen 5.1.76.152, 2a00:f820:417::7647:b2c2 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

Wichtiger Hinweis für Hetzner CX- vServer Kunden:

Die CX-vServer-Modelle von Hetzner haben ihre öffentliche IP-Adresse nicht direkt an der Netzwerkschnittstelle anliegen. Wenn ihr ein “ip addr” ausführt, seht ihr statt der öffentlichen IP-Adresse eine private Adresse. Das liegt daran, dass Hetzner die öffentliche Adresse auf die private Adresse “NATet”. (Mehr dazu unter “Warum hat meine VM die IP 172.31.1.100?”. Verwendet in der Postfix-Konfiguration und allen übrigen Konfigurationen also nicht die öffentliche Adresse, sondern die private!

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.
  • 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 Plicy “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: SSL v2 und v3 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_recipient”. 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_mynetworks”. 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.

Postscreen Filter:

Der Postscreen-Filter ist ein mächstiges Werkzeug, um Spammer-Server zu blockieren. Bevor ein fremder Server überhaupt eine E-Mail zustellen kann, überprüft Postscreen einige Merkmale des sendenden Servers und kann in den meisten Fällen zuverlässig zwischen gutem und bösen Server unterscheiden.

  • postscreen_access_list: In der Datei /etc/postfix/postscreen_access können Ausnahmen für den Postscreen-Filter definiert werden.
  • DNS Blocklist: Postscreen kann anhand von Blacklists / Blocklists entscheiden, ob von einer bestimmten IP-Adresse häufig Spam ausgeht. Dazu werden die bekannten Blocklists unter “dnsbl_sites” befragt. Die zahl hinter dem Stern * ist dabei eine Gewichtung. Besonders zuverlässig arbeitende Blacklists bekommen eine höhere Gewichtung, damit der Schwellwert “dnsbl_threshold” schneller erreicht ist. Sobald der Schwellwert bei einem Server überschritten wird, wird die Verbindung abgebrochen.
Vorsicht mit der zen.spamhaus.org-Blocklist! Spamhaus lässt Anfragen aus dem Google DNS nicht zu. Installiert am besten einen eigenen DNS-Resolver, um dem Problem aus dem Weg zu gehen (daher die Empfehlung, Unbound zu installieren!)

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.

master.cf

# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================

###
### Postscreen-Service: Prüft eingehende SMTP-Verbindungen auf Spam-Server
###
smtp      inet  n       -       y       -       1       postscreen
    -o smtpd_sasl_auth_enable=no
###
### SMTP-Daemon hinter Postscreen.
###
smtpd     pass  -       -       y       -       -       smtpd
###
### dnsblog führt DNS-Abfragen für Blocklists durch
###
dnsblog   unix  -       -       y       -       0       dnsblog
###
### tlsproxy gibt Postscreen TLS support
###
tlsproxy  unix  -       -       y       -       0       tlsproxy
###
### Submission-Zugang für Clients: Für Mailclients gelten andere Regeln, als für andere Mailserver (siehe smtpd_ in main.cf)
###
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=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. postscreen, smtpd und smtp passiert. Gut zu erkennen ist, dass über ein -o weitere Parameter an einen Dienst übergeben werden. So beispielsweise beim Submission-Dienst, der auf Port 587 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 Submission-Dienst mithilfe der -o Option überschrieben und auf “encrypt” gesetzt.

Für besseren Datenschutz wird der “Received”-Header (+ weitere Datenschutz-relevante Header) bei eingehenden E-Mails entfernt, wenn sie über den Submission-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 Submission-Bereich wird via cleanup_service_name festgelegt, dass bei eingehenden Mails auf dem Submission-Port (wird nur von Mailclients benutz) 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 = 127.0.0.1
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 = 127.0.0.1
dbname = vmail
query = select concat(destination_username, '@', destination_domain) as destinations from aliases where source_username = '%u' and source_domain = '%d' and enabled = true;

domains.cf

user = vmail
password = vmaildbpass
hosts = 127.0.0.1
dbname = vmail
query = SELECT domain FROM domains WHERE domain='%s'

recipient-access.cf

user = vmail
password = vmaildbpass
hosts = 127.0.0.1
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 = 127.0.0.1
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 = 127.0.0.1
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:

chmod -R 640 /etc/postfix/sql

Weitere Postfix-Konfigurationsdateien

Außerdem gibt es noch zwei weitere Dateien in /etc/postfix, die zunächst leer bleiben können:

touch /etc/postfix/without_ptr
touch /etc/postfix/postscreen_access

Die Datei without_ptr kann Einträge wie den folgenden beinhalten:

1.2.3.3 OK

Der Server mit dem IP 1.2.3.3 muss dann keinen gültigen PTR-Record mehr besitzen und wird trotzdem akzeptiert. Die without_ptr-Datei muss nach jeder Änderung in eine Datenbankdatei umgewandelt und Postfix neu geladen werden:

postmap /etc/postfix/without_ptr
systemctl reload postfix

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

postmap /etc/postfix/without_ptr

Die Datei postscreen_access kann Ausnahme-IP-Adressen enthalten, die nicht von Postscreen überprüft werden sollen. Der Inhalt könnte beispielsweise so aussehen:

1.2.3.3 permit

Ein Server mit der IP-Adresse “1.2.3.3” wird dann nicht mehr von Postscreen kontrolliert. Hängt man statt des “permit” ein “reject” an, wird der Server mit der jeweiligen IP-Adresse auf jeden Fall von Postscreen blockiert.

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, 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

Grundkonfiguration

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

/etc/rspamd/local.d/options.inc: Netzeinstellungen. Definition des lokalen Netzes und des zu nutzenden DNS-Resolvers.

local_addrs = "127.0.0.0/8, ::1";

dns {
    nameserver = ["127.0.0.1:53:10"];
}

/etc/rspamd/local.d/worker-normal.inc: Einstellungen für den normalen Rspamd Worker.

bind_socket = "localhost:11333";
### Anzahl der zu nutzenden Worker. Standard: Anzahl der virtuellen Prozessorkerne.
# count = 1

/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$ …") wird via

rspamadm pw

(…dann gewünschtes Passwort eingeben) generiert und muss in der Konfigurationsdatei angepasst werden!

/etc/rspamd/local.d/worker-proxy.inc: Worker Proxy (Milter-Modul für Postfix)

bind_socket = "localhost:11332";
milter = yes;
timeout = 120s;
upstream "local" {
    default = yes;
    self_scan = yes;
}

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

type = "file";
filename = "/var/log/rspamd/rspamd.log";
level = "error";
debug_modules = [];

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";

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 2017 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 2017 -k /var/lib/rspamd/dkim/2017.key > /var/lib/rspamd/dkim/2017.txt
chown -R _rspamd:_rspamd /var/lib/rspamd/dkim
chmod 440 /var/lib/rspamd/dkim/*

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

DKIM Record ausgeben lassen:

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

Die Ausgabe sieht z.B. so aus:

2017._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 und meine Domain “security-enforced.de” (an Stelle von mysystems.tld) durchgeführt:

core-networks.de Screenshot mit DKIM Record

Wichtig: Der Selektor “2017” 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 = "2017";

### 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 und Einrichtung ist trivial:

apt install redis-server

/etc/rspamd/local.d/redis.conf

servers = "127.0.0.1";

Rspamd starten

Rspamd kann nun gestartet werden:

systemctl start rspamd

Nginx Proxy für Rspamd Weboberfläche (optional)

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).

Installation:

apt install nginx
nano /etc/nginx/sites-available/mail.mysystems.tld

Inhalt der neuen Konfigurationsdatei /etc/nginx/sites-available/mail.mysystems.tld

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

    ssl_certificate /etc/letsencrypt/live/mail.mysystems.tld/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mail.mysystems.tld/privkey.pem;

    server_name mail.mysystems.tld;

    root /var/www/default;

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

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

Anzupassen:

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

Seite aktivieren, Konfiguration testen und Nginx neu laden:

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

Apache Proxy für Rspamd Weboberfläche (optional, nicht überprüft!)

Apache2 installieren:

apt install apache2

Proxy-Modul aktivieren und neu starten:

a2enmod proxy
a2enmod proxy_http
systemctl restart apache2

Konfiguration /etc/apache2/sites-available/mailserver.conf:

<VirtualHost *:80>
    ServerName mail.mysystems.tld
    Redirect / https://mail.mysystems.tld/
</VirtualHost>


<VirtualHost *:443>
    ServerName mail.mysystems.tld
    ServerPath /
    DocumentRoot /var/www
    DirectoryIndex index.html

    SSLEngine on
    SSLHonorCipherOrder on
    SSLCertificateFile /etc/letsencrypt/live/mail.mysystems.tld/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mail.mysystems.tld/privkey.pem


    ###
    ### Rspamd
    ###

    RewriteEngine on
    RewriteRule ^/rspamd$ /rspamd/ [R]
    ProxyPreserveHost On
    ProxyPass /rspamd http://localhost:11334/
    ProxyPassReverse /rspamd http://localhost:11334/
</VirtualHost>

Neue Konfiguration aktivieren und Apache neu laden:

a2ensite mailserver
systemctl reload apache2

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.

Rspamd gibt im Log und auf der Weboberfläche Fehler aus: "/var/lib/rspamd/ [...]: map file is unavailable for reading". Dabei handelt es sich im einen Bug, der ignoriert werden kann. (Siehe auch: https://github.com/vstakhov/rspamd/issues/1474)

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.

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!

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).

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

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.

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 “-” 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

Eine Verbindung könnt ihr über jeden IMAP-fähigen E-Mail-Client und den folgenden Verbindungsparametern herstellen:

  • IMAP-Server: mail.mysystems.tld | Port: 143 | STARTTLS (dieser Server gilt auch für domain2 und domain3!)
  • SMTP-Server: mail.mysystems.tld | Port: 587 | STARTTLS (dieser Server gilt auch für domain2 und domain3!)
  • (optional Managesieve: mail.mysystems.tld | Port: 4190 | STARTTLS) (auch für domain2 und domain3!)
  • Benutzername: Die vollständige E-Mail-Adresse
  • Passwort: Sollte bekannt sein ;-)
Der erste Login kann einige Zeit in Anspruch nehmen!

Mailserver Logindaten für Thunderbird

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.

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 erproben und zu formulieren. 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

“Danke für die Anleitung. Kann ich mich irgendwie revanchieren?”

Über ein “Dankeschön” via E-Mail freue ich mich, aber z.B. auch über eine kleine Finanzspritze für meinen Blog via Bitcoin, PayPal oder auf anderem Wege. Damit kann ich beispielsweise meine Server bezahlen. Vielleicht magst du diesen Beitrag auch weiterempfehlen? Auch dafür bin ich dankbar :-) => Blog Unterstützen

“Wieso noch eine Mailserver-Anleitung? Es gibt doch schon so viele!”

Tatsächlich kann man den Eindruck haben, zu jedem Linux-Blog gehöre mittlerweile ein E-Mail Tutorial. Natürlich habe ich darüber nachgedacht, ob es überhaupt sinnvoll ist, den Aufwand zu betreiben, und die tausendste Anleitung dazu zu schreiben. Aber natürlich habe ich gute Gründe: Ich bin während meiner ersten Schritte zum eigenen Mailserver fast verzweifelt: Es gibt zwar Unmengen an Mailserver-Anleitungen im Netz, und trotzdem gibt es zu viele How-Tos, die nie wirklich getestet wurden oder schon veraltet sind. Diese Anleitung wurde mehrmals auf einem frisch installierten Debian Server getestet. Ich kann also bis zu einem gewissen Grad garantieren, dass euer Mailserver funktioniert, wenn ihr die Anleitung exakt durcharbeitet. Einige Artikel zum Thema finde ich auch nicht ausführlich genug. Wie Eingangs schon erklärt, geht es mir bei diesem Beitrag auch darum, ein wenig zu erklären, was hier eigentlich passiert. Und nicht zuletzt: Es gibt diese Anleitung, weil ich der Meinung bin, dass es nicht genug geben kann. Jeder Autor erklärt etwas anders, jeder stellt ein leicht verändertes Setup vor. Ich hatte Lust, mein eigenes Setup in diesem Beitrag zu erklären, weil es gut funktioniert.

“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.

“Gibt es für dieses neue Mailserver-Setup schon einen Web-Client zur Verwaltung?”

Aktuell ist WebMUM nicht mit dieser Anleitung kompatibel. Solltet ihr das ändern wollen – nur zu. Der Code ist auf GitHub unter der MIT Lizenz frei verfügbar. Ansonsten steht es natürlich jedem frei, selbst ein solches Werkzeug zu entwickeln und vielleicht sogar frei verfügbar zu machen. Im Wesentlichen müssen nur Datensätze erstellt, bearbeitet und gelöscht werden. Das kann man z.B. auch als PHP-Anfänger gut umsetzen.

Andreas Bresch hat übrigens schon ein Webinterface zu dieser Anleitung entwickelt: https://github.com/Andreas-Bresch/vmailManage/

Wie kann ich mit diesem Setup Catch-All Adressen realisieren?

Dazu sind ein paar Änderungen notwendig. Ich habe mich mit der Thematik noch nicht selbst befasst, aber ein Leser hatte hiermit Erfolg:

  1. source_username in aliases Tabelle als nullable (= null bei catchall) konfigurieren. In der MySQL-Kommandozeile:

    alter table aliases modify source_username varchar(64) null;

  2. Die Query in aliases.cf anpassen

    query = SELECT concat(destination_username, ‘@’, destination_domain) as destinations FROM aliases WHERE source_username =’%u’ and source_domain =’%d’ and enabled = true UNION ALL SELECT concat(destination_username, ‘@’, destination_domain) as destinations FROM aliases WHERE source_username is null and source_domain =’%d’ and enabled = true AND not exists (SELECT id FROM aliases WHERE source_username =’%u’ and source_domain =’%d’ and enabled = true);

Ich habe das nicht getestet!

“Wieso Port 587 und 143 mit STARTTLS?”

Postfix verwendet Port 587 für die Verbindung zu MUAs (Mail User Agents - “Mailprogramme”), weil Port 25 nur für den Transfer der E-Mails zwischen den Servern zuständig sein soll. Während auf Port 25 von jedem Sender E-Mails ohne Authentifizierung empfangen werden können, wird auf Port 587 eine vorherige Authentifizierung des Endnutzers erzwungen. Port 587 wird daher auch als “Submission”-Port bezeichnet und ist üblicherweise in Firewalls freigeschaltet (siehe auch: RFC 6409 Submission). Port 25 hingegen wird beispielsweise in Unternehmensfirewalls und von manchen DSL-Routern blockiert, um das Spam-Problem einzudämmen. Aus einem solchen Netz können dann nur noch E-Mails zum zuständigen Mailserver gesendet werden - nicht mehr an jeden beliebigen Mailserver direkt. Da 587 als “universeller” Port (mit und ohne TLS-Verschlüsselung) definiert wurde, wird hier STARTTLS eingesetzt. Der ehem. “nur-TLS”-Port 465 ist nicht mehr als Standard festgelegt!

Für Dovecot verwende ich ebenfalls einen STARTTLS-Port. Dieser ist als Port 143 in RFC 3501 definiert. Prinzipiell ließe sich zwar als “TLS only” Port der weiterhin spezifizierte “imaps”-Port 993 verwenden, aber aus Gründen der Einheitlichkeit (und weil auch mit STARTTLS Verschlüsselung erzwungen werden kann) habe ich mich für 143 entschieden.

Kurz: Die Ports habe ich aus Abwägungen bezüglich der geltenden IANA-Standards und der Einheitlichkeit gewählt. Durch den Einsatz von STARTTLS entstehen (bei meiner Konfiguration) keine Nachteile.

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 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 Port 587 nicht. Mailclients sollten immer Port 587 für den Versand 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)

Changelog

  • (Erstveröffentlichung am 04.08.2017)

  • 29.08.2017

    • vmail MySQL user bekommt nur noch “select” Rechte statt allen Rechten
    • Überarbeitete Version der master.cf (vor allem submission-Bereich und mehr Dienste laufen nun im chroot für mehr Sicherheit), “mua”-Ergänzung in der main.cf
  • 31.08.2017

    • Hinzugefügt: dkim_signing.conf zu arc.conf kopieren, um Fehler cannot load dkim key /var/lib/rspamd/arc/domain.tld.arc.key zu verhindern.
    • Hinzugefügt: non_smtpd_milters = inet:localhost:11332, sodass auch e-mails vom Mailserver selbst (lokal erstellt) DKIM signiert werden.
  • 25.10.2017

    • Nicht mehr gepflegtes Dovecot Antispam-Plugin ersetzt durch ImapSieve (Änderungen an Dovecot-Config und zusätzliche Sieve Scripts)
  • 27.10.2017

    • ADSP records entfernt, stattdessen sollten DMARC-Records eingerichtet werden. Entsprechenden Abschnitt hinzugefügt.
  • 06.11.2017

  • 12.11.2017

    • Hinweis zu “Mailman” Weboberfläche ergänzt.
  • 05.12.2017

    • Apache2-Konfiguration für Rspamd Proxy hinzugefügt.
  • 19.01.2018

    • dovecot.conf: ssl_dh_parameters_length und ssl_protocols entfernt; werden nicht mehr benötigt
    • /etc/rspamd/local.d/classifier-bayes.conf hinzugefügt
    • Kleinere Style-verbesserungen, Ergänzungen im Text
    • Warning bzgl. Ubuntu Server hinzugefügt.
  • 20.01.2018

    • Hinweis zu Henrik Halbritters “MailAdmin” hinzugefügt.
  • 22.01.2018

    • Dovecot PPA für Ubuntu Server hinzugefügt.
  • 02.02.2018

    • tls_preempt_cipherlist = yes zu Postfix main.cf hinzugefügt.
  • 30.03.2018

    • Hinweis ergänzt: DKIM-Record muss für alle verwendeten Maildomains im jeweiligen Zonefile hinzugefügt werden!
  • 02.03.2019

    • learn-ham gefixt