Emailserver mit Postfix und Dovecot

From Linuxwiki
Revision as of 20:57, 25 March 2023 by Sunflower (talk | contribs)
Jump to navigation Jump to search

Postfix

Postfix ist ein MTA (Mail Transfer Agent), der eine gute Alternative zu anderen gängigen MTAs (Sendmail, Exim) darstellt, da seine Konfiguration gut lesbar ist. In unserem Beispiel soll der MTA mit einem IMAPd (Dovecot) verknüpft werden, so dass Benutzer eine Mailbox direkt auf dem System haben. Das Abholen der Mails erfolgt per IMAPs.

Installation

Zunächst muss das Paket „postfix“ installiert werden. Dabei sind noch ein paar Fragen zu beantworten:

  • Art des Servers: Internet Site
  • Root and postmaster mail recipient: ein Postfach eintragen, z.B.postmaster@example.de
  • Other destinations to accept mail for (blank for none): z.B. mail.example.de, localhost, $mydomain (kann man erstmal die defaults belassen)
  • Force synchronous updates on mail queue: no
  • Local subnets: 127.0.0.1/8, 192.168.63.0/24 (hier das eigene Netz ergänzen)
  • Mailbox size limit: 0 (unbegrenzt)
  • Local address extension character: + (i.a. als default ausreichend)
  • Internet protocols to use: all (wenn man nicht explizit ipv4 oder ipv6 sprechen will)

Diese Einstellungen lassen sich jederzeit mit

 # dpkg-reconfigure postfix

ändern.

Danach befinden sich alle relevanten Dateien im Verzeichnis /etc/postfix.

Konfiguration

Bevor wir zur Postfixconfig kommen, überprüfen wir den Inhalt der Datei /etc/mailname:

 $ cat /etc/mailname

Dort darf nur der Domainname stehen, nicht der Hostname (e.g. example.com). Andernfalls kann das Auswirkungen auf den Emailversand haben, v.a. wenn in der main.cf (s.u.) auf die Datei referenziert wird.

Die wichtigeste Datei zum Anpassen ist zunächst die main.cf. Hier ein Beispiel für den Server „mx“ in der Domain example.de. Folgende Parameter sollten konfiguriert sein (exemplarisch):

 myhostname
 mydomain
 myorigin
 mydestination

Meistens gibt es schon ein paar brauchbare defaults. Der Parameter mynetworks erlaubt es bestimmten Netzen, Emails ohne weitere Einschränkungen einzuliefern.

Beispielconfig:

myhostname = mx01.example.de 
mydomain = example.de 
myorigin = $mydomain 
mydestination = $myhostname, localhost, localhost.$mydomain
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 192.168.99.0/24 [2001:780:11b::/48] 214.94.24.154 [2004:780:8:0:5ff0:c5ff:fe09:98f9]

Vor allem der Parameter mynetworks sollte mit Bedacht gewählt werden, denn dies sind alle Hosts und Netze, von denen jegliche Emails angenommen werden (auch von und nach Fremddomains). Fehlkonfigurationen führen hier schnell zum OpenRelay.

Beachte: ipv6-Adressen müssen in [eckigen Klammern] geschrieben werden, sonst werden keine Emails ausgeliefert! Fehler im Logfile:

postfix/smtpd[21928]: warning: smtpd_client_event_limit_exceptions: 2a01:40f8:c013:5050::0/64: table lookup problem

Nach jeder Änderung ist der Dienst zu reloaden mit dem Befehl

 # postfix reload

Ob der Restart ordentlich funktioniert hat, kann man z.B. anhand des Logs überprüfen:

 # tail /var/log/mail.log

master.cf

Das Kernstück des Postfixdaemons. Hier werden die Transports festgelegt Bedeutung der Spalten:

  • service-Feld: Name des Dienstes (smtp, local, procmail, ...) (str)
  • typ-Feld: Verbindungstyp (inet, fifo, unix) (str)
  • Zugriffsrecht: Zugriff auch für externe Programme (default: y) (bool)
  • unpriv-Feld: Start als unprivilegierter Benutzer (default: y) oder root (n) (bool)
  • chroot: Soll der Dienst in einer chroot-Umgebung gestartet werden (default: y) (bool)
  • wakeup-Feld: Sekunden zwischen 2 Aufrufen (default: 0) (int)
  • Prozessmaximum: Wie viele Prozesse maximal gleichzeitig (default: 50) (int)

Danach erfolgt ein Kommando mit Flags und Parametern (optional).

TLS

Optional kann man mit Zertifikaten verschlüsselte Übertragung von Emails konfigurieren. das funktioniert aber nur dann, wenn der Mailserver der Gegenstelle das Zertifikat auch einbindet. Man kann das Zertifikat auch in einen Mailclient einbinden (s. später). Die Zertifikatserzeugung kann mit mit letsencrypt erfolgen. Clients zur Zertifikatserzeugung sind certbot oder dehydrated.

Zertifikatsgenerierung in Kürze

# echo $HOSTNAME > /etc/dehydrated/domains.txt
# dehydrated –register –accept-terms
# dehydrated -c

Dies setzt allerdings einen Webserver voraus, der auf Port 80 lauscht. Gibt es diesen nicht, kann mal alternativ letsencrypt via DNS verwenden (https://letsencrypt.org/docs/challenge-types).

Alternative eigene CA (nicht empfohlen)

Wer unbedingt eine eigene CA betreiben will, kann das mit folgender Anleitung tun. Achtung: Das Vorgehen sollte nur gewählt werden, wenn ein zwingender Grund dafür besteht. Viele Browser und MUAs haben Probleme damit, erzeugen hässliche Warnings oder lassen die Seite nicht zu.

CA erstellen

Wenn noch kein Zertifikat vorhanden ist, kann man sich selbst eines erstellen oder einen CSR (Certificate Signing Request) erstellen und diesen an eine offizielle CA schicken. Soll ein kommerziell genutzter Mailserver entstehen, ist dies der realistische Weg.

Achtung: Dieser Schritt wird nicht gebraucht, wenn es schon eine CA gibt.

Schritte:
Key erstellen (+Passwort dafür vergeben), Zertifkatsrequest für die CA erstellen, CA erstellen

$ openssl genrsa -out ca.key -des3 4096
 
$ openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
Enter pass phrase for ca.key: 
You are about to be asked to enter information that will be incorporated 
into your certificate request. 
What you are about to enter is what is called a Distinguished Name or a DN. 
There are quite a few fields but you can leave some blank 
For some fields there will be a default value, 
If you enter '.', the field will be left blank. 
----- 
Country Name (2 letter code) [AU]:DE 
State or Province Name (full name) [Some-State]:Bavaria 
Locality Name (eg, city) []:Nuernberg 
Organization Name (eg, company) [Internet Widgits Pty Ltd]:example.de 
Organizational Unit Name (eg, section) []:Hostmaster 
Common Name (e.g. server FQDN or YOUR name) []:*.example.de 
Email Address []:postmaster@example.de

Zertifikat mit der neuen CA erstellen

Schritte:

   • Key erstellen
   • Request erstellen 
   • Zertifikat erstellen und signen
 $ openssl genrsa -out mx.example.de.key 4096

(kein Passwort festlegen)

$ openssl req -new -key mx.example.de.key -out mx.example.de.csr

(wieder das Formular ausfüllen as usual)

$ openssl x509 -req -days 365 -in mx.example.de.csr -CA  ca.crt -CAkey ca.key -set_serial 01 -out mx.example.de.crt

Beim Erneuern des Zertifikats fallen die Schritte „Erstellen der CA“ und Erzeugen des Keys weg. Ferner muss man auch keine Serial mehr angeben. Der Renew-Befehl lautet also folgendermaßen:

$ openssl x509 -req -days 730 -in mx.example.de.csr -CA ca.crt -CAkey ca.key -out mx.example.de.crt

Einbinden in die Config-Datei

Dieser Schritt gilt wieder für alle Zertifikate, egal wie sie erzeugt wurden. Die Pfade müssen natürlich entsprechend angepasst werden,

Zertifikate an die entsprechende Stelle kopieren und in der Konfig einbinden:

smtpd_tls_cert_file=/etc/ssl/certs/mx.example.de.crt 
smtpd_tls_key_file=/etc/ssl/private/mx.example.de.key 
smtpd_tls_CAfile=/etc/postfix/ca.crt 
smtpd_use_tls=yes 
smtpd_tls_session_cache_database = btree: 
  ${data_directory}/smtpd_cache
smtp_tls_session_cache_database = btree:  
  ${data_directory}/smtp_scache

Der Parameter smtpd_tls_Cafile entfällt, wenn eine offizielle CA vorhanden ist (z.B. letsencrypt).
Die Pfade zu den Zertifikaten können abweichen, bei letsencrypt liegen diese z.B. unter /var/lib/dehydrated/certs/. Überprüfung:

$ openssl s_client -connect mx.example.de:25 -starttls smtp

oder https://www.checktls.com/

Ergänzung: Manche MTAs wollen ein Zertifikat in pfx-Form. Dieses kann man aus dem cert file wie folgt erzeugen:

$ openssl pkcs12 -export -out mx.example.de.pfx -inkey mx.example.de.key -in mx.example.de.crt

pfx-File und Passwort dem User zukommen lassen.

SASL

Zur Vermeidung eines Open Relays ist dringend anzuraten, per default nur das Einliefern mit dem Absender @example.de von bestimmten Netzen zu erlauben. Dieses passiert mit dem Parameter mynetworks (s.o.). Nun kann es natürlich passieren, dass Benutzer von einem Mailclient irgendwo im Internet Mails verschicken wollen. Diese wären laut Konfig nicht berechtigt. Da die meisten PCs mit dynamischen Adressen im Internet unterwegs sind, macht es hier auch keinen Sinn, die jeweilige IP-Adresse in der Konfig zu ergänzen.
Das Problem kann umgangen werden, indem Emails versenden dann erlaubt wird, wenn sich der Benutzer einmal erfolgreich am IMAP-Server authentifiziert hat. Hierfür gibt es SASL. Die entsprechenden Eintragungen in der main.cf sind:

smtpd_relay_restrictions = permit_mynetworks  
permit_sasl_authenticated defer_unauth_destination
smtpd_sasl_auth_enable = yes 
smtpd_sasl_type = dovecot 
smtpd_sasl_local_domain = $mydomain 
smtpd_sasl_security_options = noanonymous 
smtpd_sasl_path = private/auth

Im Mailclient äußert sich das Verhalten so, dass man beim ersten Senden einer Nachricht sein Mailbox-Passwort angeben muss. Bevor dieses Feature aktiviert wird, muss es einen IMAP-Server geben (s. nächstes Kapitel).

Maps

Um besser unterscheiden zu können, was mit welchen Absender-/Zieladressen passiert, wird die Konfiguration in sogenannte „Maps“ aufgeteilt. Diese können als Klartext-File oder als Berkley DB vorliegen. In letzterem Fall müssen diese mit dem Kommando postmap nach jeder Bearbeitung umgewandelt werden.
Ausnahme: Die Datei /etc/aliases.db (nur relevant für lokale Emailauslieferung) wird mit dem Kommando postalias oder newaliases generiert.

alias_maps = hash:/etc/aliases 
alias_database = hash:/etc/aliases 

Hier werden aliase eingerichtet, die auf eine andere Mailbox mappen. Beispiel:

postmaster:    root

Access

smtpd_sender_restrictions = hash:/etc/postfix/access 

Hier können für Aktionen für spezielle Absenderadressen eingerichtet werden. Beispiel:

example.com     DISCARD

Relocated

relocated_maps = hash:/etc/postfix/relocated 

Abweisen der Mail mit einem Hinweis. Beispiel:

testy.test      "Mails bitte statt an diese Adresse an ich@hier.de senden"

Ergebnis:

<testy.test@example.de>: Recipient address rejected: User has 
moved to "Mails bitte statt an diese Adresse an ich@hier.de
senden"

Canonical

Sender

sender_canonical_maps = hash:/etc/postfix/sender_canonical 

Bestimmte Adressen werden auf ein übliches Standardformat umgeschrieben:

sunflower@example.de   petra.sonne@example.de
phun@work.de		   peter.hun@example.de

Recipient

recipient_canonical_maps = hash:/etc/postfix/recipient_canonical 

Arbeitet genauso wie sender_canonical, nur für Empfängeradressen.

Virtual Mailbox

virtual_mailbox_maps = hash:/etc/postfix/virtual

Locations der Mailboxen des imap-Servers (näheres unter #Dovecot)

sunflower@example.de   	example.de/sunflower/ 
testy@example.de		example.de/testy 
test@example.de		example.de/test 
lmaa@ihr-koennt-mich-alle.de	ihr-koennt-mich-alle.de/lmaa

Virtual Aliases

virtual_alias_maps = hash:/etc/postfix/virtual_maps

Adressen die auf andere Adressen umgebogen werden (ähnlich wie die aliases), kann auch domainübergreifend passieren. So können mehrere Empfängeradressen in dieselbe Mailbox laufen.

anrufbeantworter@example.de      sunflower@example.de,H.Hirsch@gmx.de,harry1999@yahoo.de
info@example.de        sunflower@example.de
postmaster    root 
webmaster     root 
administrator root
root    sunflower

fortune:  fortune Letzteres ist eine Pipe. Dazu später mehr.

Umwandeln von Text in DB-File und in Postfix einlesen:

postmap <aliases|access|canonical|...>
postfix reload

Einfaches Beispiel: Emails von einer Domain auf eine andere weiterleiten

Nehmen wir an, wir haben einen Emailserver1 in der Domain example.com. Dieser soll alle Email die an <userXY>@example.com eintreffen, an <userXY>@example.de weiterleiten. Auch hier ist eine Eintrag in der o.g. virtual_maps Datei nötig:

@example.com	@example.de

Nun werden alle example.com-Emails zum zuständigen Emailserver für example.de weitergeleitet. Der user part bleibt unverändert.

Transports

Transports sind die Art und Weise, wie eine eingehende Mail behandelt wird, z.B. lokal in eine Datei speichern, an einen imap-Server weiterreichen oder ein Script ausführen.

Hier ein Beispiel:
Wenn auf eine bestimmte Adresse geschickt wird, soll ein Script ausgeführt werden, das dem Absender einen Zufallsspruch zurücksendet und die Mail gleichzeitig in ein Postfach einliefert. Schritte:

1. Alias definieren (virtual_maps):

fortune@example.de           fortune

2. Alias auf einen Transport mappen (transports):

fortune@example.de     randomphrase:

3. Transport definieren (master.cf):

 randomphrase      unix  - n n - - pipe 
  flags=h user=vmail:vmail argv=/usr/local/bin/randomphrase.pl ${sender}

(Den User vmail muss es natürlich in der passwd geben, z.B. so:

vmail:x:4000:4000::/home/vmail:/user/sbin/nologin

)

4. Script hinterlegen:

/usr/local/bin/randomphrase.pl

für alle ausführbar machen

Mit dem Script randomphrase.pl wird ein Zufallsspruch erzeugt. Dafür muss das Paket fortune-mod installiert sein. Zum Weiterschicken der Email wird das Script /usr/local/bin/deliver_mail.sh aufgerufen. (File:Deliver mail.sh)
Hierfür muss der User vmail in der Datei /etc/sudoers.d/vmail berechtigt werden:

vmail ALL=(root) NOPASSWD: /usr/local/bin/deliver_mail

Eine Email an die Adresse fortune@example.de erzeugt nun eine Antwort an die Absenderadresse mit einem Zufallsspruch.

Multidomain

Natürlich kann Postfix auch Emails für mehrere Domains annehmen. Dafür gibt es den Parameter „virtual_mailbox_domains“:

virtual_mailbox_domains = example.de  example.com  ihr-koennt-mich-alle.de

Die Variable $mydomain sollte dann aus mydestination entfernt werden.

Dovecot

Erweiterungen

Postgrey