Das ist ein eher langes Tutorial, ich hoffe aber mit den vielen Erklärungen alle Anwendungsfälle abzudecken. Das Thema ist für jeden Admin etwas das er 1x macht, dann vergisst, endlos aufschiebt oder letztendlich doch einen Dienstleister machen lässt. Ich habe leider (oder zum Glück) jeden Anwendungsfall den Postfix abdeckt zu lösen und hoffe mein Tutorial macht aus dem leidigen Thema ein erfolgreiches Wochenende!
mail.domain.tld
Der 📯 lokale Postbote in Ihrem Unternehmen oder daheim weiß wer mit Ihrer Domain als Absender Mails versenden darf und bringt Post bis an den Briefkasten.
Für einen 🏤 Post-Server direkt im Internet brauchen Sie zwingend einen guten Ruf und wahnsinnig spannende Dinge wie DKIM, Policy-SPF, DMARC etc. wenn Sie nicht sofort als SPAM aussortiert werden wollen. Es macht daher Sinn einen größeren Dienstleister mit der Weiterleitung an andere Domains zu beauftragen.
Natürlich können Sie das auch selbst mit einem Root-Server machen. Wir trennen die Zuständigkeiten hier so, dass Sie beides auch eine Maschine machen lassen können, ihr Root-Server also sowohl Mails als 🏤 globaler Post-Server verschickt oder annimmt, als auch lokal Mails als 📯 lokaler Postbote verteilt und Nutzer für den Versand authentifiziert.
Hier behandeln wir nur die Rolle als 📯 lokaler Postbote. Er darf als Dienst alle Namensschilder an den 📫 Briefkästen lesen und Post einwerfen, hat aber keine Schlüssel dafür. Zudem nimmt er Post zum 🏤 globalen Post-Server mit und prüft dabei Ihre Absender-Adresse.
Auch für Postfix nutze ich in diesem Beispiel wie bei Dovecot nur Debian.
apt install postfix postfix-ldap
Wählen Sie hier Satellite system
System mail name: mail.domain.tld
(ihr 📯 lokaler Postbote)
SMTP Relay host: mx.domain.tld
(🏤 globaler Post-Server der Ihre Mails im Internet annimmt oder weiterverteilt, das kann auch mx.krei.se
sein)
-->
🛰️ -->
📯 -->
📫Für 🛸 Krei.se-🛰️ Subdomains ist 🏤 mx.krei.se im 📇 Nameserver schon als 🥛 MX Eintrag hinterlegt und kennt auch bereits Ihre 🛰️ Subdomain.
Mails die an Ihre Subdomain kommen leiten wir so bereits an ihren 📯 lokalen Postboten mail.subdomain.krei.se
weiter (auch wenn der bei uns läuft).
-->
📯 -->
🛰️ -->
🏤 (📇!)Solange Sie von 📯 mail.subdomain.krei.se
schicken, also für 🏤 mx.krei.se
auch unter diesem Namen mit der IP die uns kontaktiert wiederzuerkennen sind wird 🏤 mx.krei.se
Ihre Mails annehmen und weiterversenden.
! Stellen Sie daher bei Eigenbetrieb des lokalen Postboten sicher, dass dieser 📇 Eintrag extern erreichbar und aktuell ist, z.B. mit Ihrem 🛸 Krei.se-🛰️ Subdomain-📡 RFC2136-Schlüssel. Fällt Ihre Heimleitung mal aus oder erhalten Sie eine neue IP liegt der Mail-Verkehr für maximal 5 Minuten brach, aber beide Server halten bis zur Wiederherstellung der Verbindung alle Mails vor.
💰 Auch hier wie immer 0€ Kosten für Sie und ⏳ Sie brauchen nicht mal eine Anmeldung in Ihrem Server zu hinterlegen, denn 🛸 Krei.se kennt seine Kunden ;) !
Für die meisten Postfix-Begriffe brauchen Sie Kenntnis über das Mail-Glossar. Dort sind alle Konfigurationsparameter bildlich und für beide Postfix-Server-Arten erklärt, eine Einzelerklärung hier würde Sie nur verwirren, es werden aber Parameter dorthin verlinkt. Ich habe leider keine komplett deutsche Anleitung gefunden und installiere diese Server häufiger, daher wird das Glossar und Tutorials regelmässig gepflegt.
Debian hat nach der Installation mydomain standard undefiniert, myhostname fest auf die Ausgabe von hostname -f
und myorigin auf /etc/mailname (System mail name aus der apt-installation).
Bitte prüfen Sie nach der Installation:
hostname -f
sollte server.domain.tld ausgeben
/etc/mailname
sollte mail.domain.tld ausgeben
Wir wollen in /etc/postfix/main.cf
:
myhostname
setzt Debian auf server.domain.tld
und kann so bleiben, daran denken dass wir mit diesem auch alle Nutzer im EHLO begrüßen, also sensibel nutzen oder (evtl. systemweit) ändern. Dieser hostname muss auch für SSL passen
mydomain
auf domain.tld
oder undefiniert lassen
myorigin
auf mail.domain.tld
, /etc/mailname
oder undefiniert lassen
mynetworks
sollte nur 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
enthalten
mydestination
erhält nur localhost
relayhost
ist immer der globale 🏤 Post-Server mx.domain.tld
Bitte prüfen Sie mit postconf | grep mydomain
etc. diese Parameter auf Korrektheit.
Wir nutzen nur virtuelle Postfächer, mydestination enthält daher nur localhost. Sie werden jetzt vielleicht denken es mache Sinn Mails an UNIX-User zuzustellen. Macht es NICHT und wird Sie maximal verwirren wenn Mails nicht 📬 einsortiert werden. Wir stellen Mails immer an mail.domain.tld zu wo Postfix und Dovecot mit LMTP schon begierig auf unsere Mails warten.
Das Equivalent zu mydestination ist die Einkaufsliste am Kühlschrank und der Zettel am Badspiegel mit der Bitte an den Gatten am Wochenende zu putzen - das liest kein Schwein und im Supermarkt bringt Ihnen die Einkaufsliste daheim exakt gar nix. Alle Server und Nutzer Ihrer Domain schicken und empfangen Mails an mail.domain.tld und haben dort Ihre 📫 Postfächer.
Schicken Sie Ihrem Gatten eine SMS mit Empfangsbestätigung, tragen Sie es im Kalender ein der dann auch während des Tatorts klingelt oder schreiben Sie eine Todo mit Caldav die auch im Supermarkt lesbar ist.
Wenn Sie allen Mail-Nutzern CAs verteilen können ist hier die Nutzung von 🏰 ED25519 denkbar, bequemer auch für BYOD ist natürlich 🛖 Letsencrypt.
main.cf
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.domain.tld/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.domain.tld/privkey.pem
main.cf
smtpd_tls_cert_file = /etc/ssl/certs/mail.domain.tld.crt
smtpd_tls_key_file = /etc/ssl/private/mail.domain.tld.key
smtpd_tls_CApath = /etc/ssl/certs
📝 .crt und .key sind in der Regel immer PEM-Format, eine Umbenennung, Umformung ist nicht notwendig. Auch ein FullChain im .crt was die CA mit enthält braucht man bei korrekter systemweiter Integration der ED25519-CA nicht, aber den smtpd_tls_CApath.
main.cf
# SSL-Server Parameter
# TLS zulassen, aber nicht erzwingen, denn manche wollen uns einfach per smtp Mails zukommen lassen
smtpd_tls_security_level = may
# Authentifizierung nur über TLS zulassen
smtpd_tls_auth_only = yes
# DH-Parameter
# ab Postfix 3.9 weglassen, deprecated
smtpd_tls_dh1024_param_file = /etc/postfix/dhparam/dh4096.pem
# Logging
smtpd_tls_loglevel = 1
# Gehärtete Voraussetzugen für SSl-Verbindungen
# Verhindert Angriffsvektoren wie BEAST, FREAK, POODLE, etc.
# Kein SSL Version 2 oder 3 zulassen
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
# Server, nicht Client legt Cipher-Reihenfolge fest
tls_preempt_cipherlist = yes
# Keine TLS-Workarounds zulassen
tls_disable_workarounds = 0xFFFFFFFFFFFFFFFF
# Sichere Cipher erzwingen
smtpd_tls_mandatory_ciphers = high
# Unsichere Cipher explizit ausschliessen
smtpd_tls_exclude_ciphers = aNULL, eNULL, EXPORT, DES, RC4, MD5, PSK, aECDH, EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CDB3-SHA, KRB5-DES, CBC3-SHA
# Nur ultra EECDH Kurven nutzen
# ab Postfix 3.9 weglassen, deprecated
smtpd_tls_eecdh_grade = ultra
# SSL-Client Parameter
# 🏤 Post-Server Zertifikate verifizieren und Mails an diese niemals unverschlüsselt senden
# Da der 📯 Postbote i.d.R. nur an einen 🏤 weiterleitet und dieser immer korrektes SSL anbietet ist ein erzwingen sinnvoll.
smtp_tls_security_level = verify
# sollte so unter Debian schon Standard sein
smtp_tls_CApath = /etc/ssl/certs
# Gehärtete Voraussetzungen und Logging von smtpd übernehmen
smtp_tls_loglevel = $smtpd_tls_loglevel
smtp_tls_mandatory_protocols = $smtpd_tls_mandatory_protocols
smtp_tls_mandatory_ciphers = $smtpd_tls_mandatory_ciphers
smtp_tls_exclude_ciphers = $smtpd_tls_exclude_ciphers
Anschliessend (< Postfix 3.9) noch die DH-Parameter erstellen: openssl dhparam -out /etc/postfix/dh4096.pem 4096
smtpd_sender_logins
überspringen und nur virtual_mailbox_domains = domain.tld
setztenDamit Postfix weiß welcher Nutzer angemeldet Mails von wo und wohin versenden darf brauchen wir 3 bis 7 Lookups nach LDAP. Das ist aufwändig, aber nötig.
Erstellen Sie dazu einen Ordner unter /etc/postfix/ldap_lookups
mit den lookup-Dateien. Alle(!) starten mit diesen Zeilen, man kann das leider nicht als Einzeldatei extern includen (bin sonst für Hinweise dankbar!):
server_host = ldaps://ldap.domain.tld
# Standard ist off und brauchen wir nicht
#start_tls = yes
version = 3
# OpenLDAP nutzt ED25519-CAs, sicherstellen, dass dieses systemweit installiert ist, dann liegt es unter Debian hier mit drin
tls_ca_cert_file = /etc/ssl/certs/ca-certificates.crt
tls_require_cert = yes
# cn=mail,ou=Dienste Mail-Nutzer der Userdaten lesen darf
bind = yes
bind_dn = cn=mail,ou=Dienste,dc=domain,dc=tld
bind_pw = xxxxxxxxxxxxxxxxxx
search_base = dc=domain,dc=tld
# bei mehreren LDAP-Datenbanken / BaseDNs können Sie %1, %2, etc. nutzen
# https://www.postfix.org/ldap_table.5.html --> ldap_table
# search_base = dc=2%,dc=1%
# sub ist Standard
scope = sub
Hier die Teile die dann in jede Datei zusätzlich kommen. Sie werden sicherlich nochmal Änderungen vornehmen, daher ist alles kommentiert und ich decke auch mit ab, dass Sie bei Bedarf auch an lokale UNIX-Nutzer mit /home/user/Maildir Mails zustellen könnten, nicht nur mit /var/vmail/domain.tld/user/Maildir.
virtual_alias Lookups brauchen Sie wenn Sie user@domain.tld --> user (lokaler Unix-Account) oder user@domain.tld --> user@yuhuu.com zuweisen wollen. Wir brauchen das in unserem Fall nicht, aber es ist für andere Domains die Sie mitverwalten u.U. praktisch. Sie können eine Domain aber immer nur als virtual_alias ODER als virtual_mailbox definieren, daher macht bei Angabe beider Lookups Sinn domains im Lookups selbst festzulegen (domain = )
virtual_alias_domains
# Sucht alle mailacceptinggeneralid und filtert den Domain-Teil raus
# dadurch kennen wir alle Domains die virtuelle -- Aliase -- haben
# und an lokale Unix-Nutzer oder andere externe Mail-Adressen gehen
# domain =
query_filter = mailacceptinggeneralid=*@%s
result_attribute = mailacceptinggeneralid
result_format = %d
virtual_alias_maps
# Sucht alle mail und mailacceptinggeneralid und gibt die den maildrop (user) zurück
# dadurch wissen wir in welches Postfach einsortiert wird
# der maildrop kann ein lokaler Nutzer sein oder eine mail@domain.tld zum Weiterleiten
👷👷👷 --- ab hier wird noch gebaut --- 👷👷👷
# (mailacceptinggeneralid=@%d) - können Sie hier als query mit in den | - OR-Operator einfügen
# Notiz an mich: Wieso hab ich das rausgelöscht??
👷👷👷 --- bis hier wird noch gebaut --- 👷👷👷
# domain =
query_filter = (&(objectClass=postfixUser)(|(mail=%s)(mailacceptinggeneralid=%s)))
result_attribute = maildrop
virtual_uid_maps
# Dieses Format brauchen Sie wenn das Maildir bestimmte Userrechte zum Schreiben benötigt
# hier die User-ID unter der das Heimverzeichnis läuft
query_filter = mail=%s
result_attribute = uidNumber
virtual_gid_maps
# Dieses Format brauchen Sie wenn das Maildir bestimmte Userrechte zum Schreiben benötigt
# hier die primäre Gruppen-ID unter der das Heimverzeichnis läuft
query_filter = maildrop=%s
result_attribute = gidNumber
Dieses Lookup brauchen Sie wenn Sie user@domain.tld --> /var/vmail/domain.tld/user zuweisen wollen. Das ist der einzige Domain-Typ den wir im lokalen Postboten behandeln um die Dinge einfach (...) zu halten.
virtual_mailbox_domains
# Sucht alle mailacceptinggeneralid und filtert den Domain-Teil raus
# dadurch kennen wir alle Domains die virtuelle -- Postfächer -- haben
# domain =
query_filter = mailacceptinggeneralid=*@%s
result_attribute = mailacceptinggeneralid
result_format = %d
virtual_mailbox_maps
# Sucht für jeden Mail-Adresse das passende Maildir,
# wir brauchen das Dank dovecot-lmtp eigentlich nicht
# aber falls Sie postfix selbst in /var/vmail/domain.tld/user/Maildir/
# speichern lassen wollen ist hier der Lookup dazu möglich.
# domain =
query_filter = (|(mail=%s)(mailacceptinggeneralid=%s)(mailacceptinggeneralid=@%d))
result_attribute = mail
result_format = /var/vmail/%d/%n/Maildir/
Nutzer holen Postfächer zwar per 📫 Dovecot, werden Mails aber immer über den 📯 lokalen Postboten versenden.
Dazu loggen Sie sich immer mit user@domain.tld ein, können aber auch Mails von erlaubten Aliases verschicken. Dazu prüft Postfix die Absender-Mail-Adresse als query und erhält den user-login zurück der damit versenden darf.
Für uns ist der user-login daher die volle Mail-Adresse. Sie könnten lokale Nutzer auch ohne @domain.tld anmelden lassen, da wir aber alle Nutzer per LDAP authentifizieren wird immer ein mail-attribut vorliegen (und das sieht auch schöner aus ;))
smtpd_sender_login_maps
query_filter = (&(objectClass=postfixUser)(|(mailacceptinggeneralid=%s)(mail=%s)))
# Für Logins mit user@domain.tld ist das mail
result_attribute = mail
# result_attribute = uid
Diese Lookups stellen wir jetzt in main.cf
ein:
# Lookups für lokale User wie root oder postmaster
# Diese am besten nur einmal von root auf admin@domain.tld setzen, einmap newaliases ausführen und vergessen ;)
alias_maps = hash:/etc/aliases
# Lookups für Domains die direkt nach /home/user speichern
#virtual_alias_domains = ldap:/etc/postfix/ldap_lookups/virtual_alias_domains
#virtual_alias_maps = ldap:/etc/postfix/ldap_lookups/virtual_alias_maps
#virtual_uid_maps = ldap:/etc/postfix/ldap_lookups/virtual_uid_maps
#virtual_gid_maps = ldap:/etc/postfix/ldap_lookups/virtual_gid_maps
# Lookups die nach /var/vmail/domain.tld/user speichern bzw an dovecot-lmtp weiterverschickt werden
# 🦥 Wer faul ist kann hier einfach virtual_mailbox_domains = domain.tld eintragen
virtual_mailbox_domains = ldap:/etc/postfix/ldap_lookups/virtual_mailbox_domains
# Das brauchen Sie nur wenn postfix selbst in /var/vmail speichern soll, ansonsten weiß das dovecot-lmtp
#virtual_mailbox_maps = ldap:/etc/postfix/ldap_lookups/virtual_mailbox_maps
#virtual_uid_maps = static:5000
#virtual_gid_maps = static:5000
# Lookups für authentifizierte Absender
smtpd_sender_login_maps = ldap:/etc/postfix/ldap_lookups/smtpd_sender_login_maps
Irgendwo muss Ihr lokaler Postbote von Ihnen versendete Mails abgeben - dafür können Sie:
einen 🏤 Dienstleister nutzen, er wird Ihnen dann Server und Zugangsdaten mitteilen.
🏤 mx.krei.se
nutzen - wenn Sie von einer uns bekannten Subdomain von einer bekannten IP senden
selbst einen globalen Post-Server betreiben (das kostet etwa 5€ im Monat für einen root-Server).
Stellen Sie in jedem Fall den sog. relayhost ein (im Debian-Setup bereits gemacht wenn Satellite System gewählt wurde):
main.cf
relayhost = mx.domain.tld
Für mx.krei.se
brauchen Sie nicht mehr, wir leiten anhand Ihrer IP alle Post mit @subdomain.krei.se als Absender weiter.
📝 Wenn Sie gern selbst penibel sind und im Eigenbetrieb bestimmten IPs den Versand von dazugehörigen Domains ohne Login zulassen wollen - das geht mit smtpd_client_restrictions = check_client_access
und smtpd_sender_restrictions = check_sender_access
mit Hash-tables. Postfix lädt die Hashtables neu wenn Sie extern einen Eintrag mit postmap aktualisieren. Denkbar ist auch ldap oder direkt im Nameserver nachschauen, da bin ich noch dran).
📝 Wenn sich ihre IP sehr häufig ändert und Sie doch einen login wollen können Sie sich aber auch auf mx.krei.se mit Ihren Subdomain-Passwort anmelden.
Wenn Sie für den Zugang einen Benutzer und Passwort brauchen, erstellen Sie diesen wie folgt:
root@server:/etc/postfix# echo [mx.domain.tld] [username]:[password] > /etc/postfix/relay_password
root@server:/etc/postfix# postmap /etc/postfix/relay_password
und setzen Sie in main.cf
# Beim Versenden per SMTP anmelden
smtp_sasl_auth_enable = yes
# dabei immer TLS nutzen
smtp_tls_security_level = encrypt
# Beschränkung aufheben, dass kein Passwort im Klartext übertragen werden darf
smtp_sasl_tls_security_level = noanonymous
# Passwörter für relayhosts
smtp_sasl_password_maps: hash:/etc/postfix/relay_password
# Brauchen Sie nur wenn Ihr Dienstleister auf Port 465 lauscht und nicht 25
# smtp_tls_wrappermode = yes
Mehr decke ich hier nicht ab - es ist noch möglich verschiedene Relays je nach Absender zu nutzen, etc.: https://www.postfix.org/SASL_README.html
Prüfen Sie als erstes ob der 📯 lokale Postbote (evtl. in Dovecot schon geschehen wenn selbe Maschine) bereits einen vmail-User hat oder legen Sie einen an. Sie brauchen diesen User für postfix aber nur wenn postfix selbst dort Mails speichern
groupadd -g 5000 vmail
useradd -m -d /var/vmail -s /bin/false -u 5000 -g vmail vmail
Postfix muss jetzt noch wissen welche transports genutzt werden. Transports sind Schnittstellen oder Programme die Mails letztendlich abspeichern.
main.cf
# Dovecot erlaubt LMTP nur für localhost und läuft auf derselben Maschine:
# IPs hier im Format: lmtp:inet:[1.2.3.4]:port angeben. [] schaltet DNS-Lookups aus.
virtual_transport = lmtp:inet:localhost:24
# Dovecot hat einen unix-lmtp-listener unter /var/spool/postfix/private/dovecot-lmtp
# auf derselben Maschine
# virtual_transport = lmtp:unix:private/dovecot-lmtp
# Dovecot erlaubt LMTP auch für andere IPs und läuft woanders:
# virtual_transport = lmtp:inet:mail.domain.tld:24
# virtual_transport = lmtp:inet:[1.2.3.4]:24
Dort fügen wir auch noch die Mailbox-Einstellungen ein wenn Postfix selbst einsortieren soll. Das ist immer hilfreich zu wissen, denn wer weiß ob Postfix nicht doch noch irgendwo eine Mail lokal zustellt ;)
mail_spool_directory = /var/vmail
# Hinweis zu mail_spool_directory, da verwirrend. Das ist nicht
# queue_directory = /var/spool/postfix
# wo Postfix Mails vorhält die noch nicht zugestellt werden konnten
# Maildir/ muss mit Slash angegeben werden, damit analog zu dovecot das Maildir-Format genutzt wird
# Wird ans Heimverzeichnis /home/user oder das Dovecot-Heimverzeichnis /var/vmail/domain.tld/user angehängt
home_mailbox = Maildir/
Postfix stellt zwar selbst keine Mails in Verzeichnisse zu, aber schaden wird es nicht wenn Sie es doch direkt machen wollen.
Den Port brauchen Sie eigentlich nicht, aber manche Mail-Programme erwarten Port 25 für den Einwurf von Post und 587 um angemeldet welche zu versenden (was auch Port 25 kann).
Da das aber ein Einzeler ist:
/etc/postfix/master.cf
submission inet n - y - - smtpd
Einfach das # entfernen. Fertig!
In den meisten Tutorials finden Sie jetzt den Hinweis über Dovecot einen Socket zu öffnen um Benutzer zu authentifizieren die Mails versenden. Wir machen das vorerst auch so, auf lange Sicht wollen wir aber wie immer trennen und Postfix direkt mit LDAP kommunizieren lassen, denn wer weiß ob wir später LMTP nicht über etwas anderes als Dovecot anbieten :D
main.cf
smtpd_sasl_type = dovecot
# Unix-Listener
# smtpd_sasl_path = private/auth
# Inet-Listener
smtpd_sasl_path = inet:[127.0.0.1]:26
smtpd_sasl_auth_enable = yes
Das genügt bereits für einen funktionierenden 📯 lokalen Postboten. Starten Sie postfix neu und schauen Sie in journalctl ob alles läuft.
👷👷👷 --- ab hier wird noch gebaut --- 👷👷👷
Was wir wollen, ist dass Postfix sich als der sendende User mit LDAP authentifiziert und das geht mit Cyrus SASL:
mailbox_transport, fallback_transport etc. brauchen wir alles nicht. Wenn Sie mögen können Sie als fallback aber noch luser_relay einstellen, dann werden lokale Mails IMMER mit einer domain versehen bevor Sie weiterverteilt werden:
luser_relay = $user@mail.domain.tld
Dafür setzen wir in main.cf
das mail_spool_directory und die home_mailbox:
Wir nutzen im Postboten nur "virtuelle" domains.
👷👷👷 --- ab hier wird noch gebaut --- 👷👷👷