Dies ist eine alte Version des Dokuments!
Dovecot, Anbindung an einen Frontend-Mailserver (Postfix-SMTP-Server)
In der Regel werden wir hinter unserem eigentlichen SMTP-Mailserver ein Backend System, eben unser Dovecot-Server, bereithalten, von welchem unsere User ihre elektronische Post abholen. Damit unser Mailserver Postfix, der die Nachrichten von fremden Mailserver annimmt, bewertet und prüft, auch an unser internes Postoffice weiterleiten kann, sind noch Ergänzungen an der Konfiguration des Postfix-Mailservers notwendig.
Egal ob nun unsere beiden Mailserverkomponenten auf getrennten Hosts oder auf einem Host laufen, der Konfigurationsaufwand ist dabei fast identisch.
Dovecot
Konfiguration
Zur Anbindung des MUA1) Dovecot an unseren MTA2) Postfix nutzen wir das Protokoll LMTP. In der Konfigurationsdatei /etc/dovecot/conf.d/10-master.conf sind im Abschnitt service lmtp bereits verschiedene Dovecot-Listener enthalten.
Statt der vorbereiteten Variante über einen Unix-Datei-Socket, werden wir aber einen TCP/IP-Socket verwenden. Zum einen gibt es dabei keine großen Probleme in chroot-Umgebungen, bzw. können wir so recht einfach und schnell, den IMAP-Server von einem all-in-one-Host auf mehrere Maschinen aufteilen. Hierzu werden wir den LMTP-Port 24 auf eine eigene IP-Adresse binden, die der Postfix-Mailserver dann exclusiv ansprechen darf. Damit der LMTP-Port nicht von anderen Maschinen aus erreichbar ist, werden wir mit einer geeigneten firewalld-Regel, den Zugriff streng reglemetieren.
Als erstes werden wir nun die nötige LMTP-Konfiguration in der 10-master.conf festlegen.
# vim /etc/dovecot/conf.d/10-master.conf
- /etc/dovecot/conf.d/10-master.conf
... service lmtp { unix_listener lmtp { #mode = 0666 } # Create inet listener only if you can't use the above UNIX socket #inet_listener lmtp { # Avoid making LMTP visible for the entire internet #address = #port = #} # Django : 2014-07-22 # Einlieferung der Nachrichten via LMTP inet_listener lmtp { address = 10.0.0.70 port = 24 } } ...
Aktivierung
Zum Aktivieren unserer Konfigurationsänderung führen wir einen reload des dovecot-Daemons durch.
# systemctl reload dovecot.service
Der Reload wurde im maillog dokumentiert. Bei Bedarf können wir den Status unseres Dovecot_Servers abfragen.
# systemctl status dovecot.service
dovecot.service - Dovecot IMAP/POP3 email server Loaded: loaded (/usr/lib/systemd/system/dovecot.service; enabled) Active: active (running) since Tue 2014-07-22 21:35:37 CEST; 24h ago Process: 23610 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS) Main PID: 22063 (dovecot) CGroup: /system.slice/dovecot.service ├─22063 /usr/sbin/dovecot -F ├─22065 dovecot/anvil [0 connections] ├─23613 dovecot/log └─23615 dovecot/config Jul 23 21:32:16 vml000070.dmz.nausch.org dovecot[23587]: imap-login: Login: user=<michael@nausch.org>, method=PLAIN, rip=10.0.0.20, mpid=23601, TLS, TLSv1 with ciphe...YQAKAAAU> Jul 23 21:47:21 vml000070.dmz.nausch.org systemd[1]: Reloading Dovecot IMAP/POP3 email server. Jul 23 21:47:21 vml000070.dmz.nausch.org dovecot[22063]: master: Warning: SIGHUP received - reloading configuration Jul 23 21:47:21 vml000070.dmz.nausch.org systemd[1]: Reloaded Dovecot IMAP/POP3 email server. Jul 23 21:47:21 vml000070.dmz.nausch.org dovecot[23587]: imap: Server shutting down. in=548 out=1966 Hint: Some lines were ellipsized, use -l to show in full.
Mit dem Befehl netstat überprüfen wir nun als nächstes, ob unser Port auf der richtigen Adresse gebunden ist.
# netstat -tulpen
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name tcp 0 0 10.0.0.70:993 0.0.0.0:* LISTEN 0 80047 22063/dovecot tcp 0 0 10.0.0.70:995 0.0.0.0:* LISTEN 0 80010 22063/dovecot tcp 0 0 10.0.0.70:3659 0.0.0.0:* LISTEN 0 80092 22063/dovecot tcp 0 0 10.0.0.70:110 0.0.0.0:* LISTEN 0 80009 22063/dovecot tcp 0 0 10.0.0.70:143 0.0.0.0:* LISTEN 0 80046 22063/dovecot tcp 0 0 10.0.0.70:24 0.0.0.0:* LISTEN 0 93699 22063/dovecot
Verbindungstest
Somit können wir einen ersten Verbindungstest zu unserem LMTP-Port durchführen.
# telnet 10.0.0.70 24
Unser Dovecot-Server akzeptiert die Verbindung und gibt das Server-Greeting aus.
Trying 10.0.0.70... Connected to 10.0.0.70. Escape character is '^]'. 220 imap.nausch.org Dovecot ready.
Mit dem LMTP-Kommando quit loggen wir uns aus und beenden die Verbindung:
quit
Der Server Bestätigt den Befehl mit einem 2xx-Code und beendet die Verbindung.
221 2.0.0 OK Connection closed by foreign host.
Paketfilterregel
Damit nun nicht jeder fremde Host sich mit dem LMTP-Port verbinden kann, regeln wir den Zugriff über eine Firewall-Regel so, dass nur der vorgeschaltete MTA Postfix-Mailserver sich mit unserem Dovecot-Server auf Port 24 verbinden kann.
Unter CentOS 7 wird als Standard-Firewall die dynamische firewalld verwendet. Ein großer Vorteil der dynamischen Paketfilterregeln ist unter anderem, dass zur Aktivierung der neuen Firewall-Regel(n) nicht der Daemon durchgestartet werden muss und somit alle aktiven Verbiundungen kurz getrennt werden. Sondern unsere Änderungen können on-the-fly aktiviert oder auch wieder deaktiviert werden.
In unserem Konfigurationsbeispiel hat unser Postfix-Server die IP-Adresse 10.0.0.80 und unser Dovecot-Server die 10.0.0.70. Wir brauchen also eine Firewall-Definition, die ausschließlich Verbindungen von der Source-IP 10.0.0.80 auf die Destination-IP 10.0.0.70 auf Port 24 gestattet.
Mit Hilfe des Programms firewall-cmd legen wir nun eine permanente Regel in der Zone public, dies entspricht in unserem Beispiel das Netzwerk-Interface eth0 mit der IP 10.0.0.70 an. Als Source-IP geben wir die IP-Adresse unseres Postfix-Servers also die 10.0.0.80 an. Genug der Vorrede, mit nachfolgendem Befehl wird diese restriktive Regel angelegt.
# firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="10.0.0.80/32" port protocol="tcp" port="24" accept"
Zum Aktivieren brauchen wir nun nur einen reload des Firewall-Daemon vornehmen.
# firewall-cmd --reload
Fragen wir nun den Regelsatz unserer iptables-basieten Firewall ab, finden wir in der Chain IN_public_allow unsere aktive Regel.
# iptables -nvL
... Chain IN_public_allow (1 references) pkts bytes target prot opt in out source destination 0 0 ACCEPT tcp -- * * 10.0.0.80 0.0.0.0/0 tcp dpt:24 ctstate NEW ...
abschließender Test
Somit steht einem abschließenden Test nun nichts mehr im Wege. Als erstes versuchen wir vom Postfix-server aus eine LMTP-Verbindung herzustellen.
$ telnet 10.0.0.70 24
Trying 10.0.0.70... Connected to 10.0.0.70. Escape character is '^]'. 220 imap.nausch.org Dovecot ready. quit 221 2.0.0 OK Connection closed by foreign host.
Die Verbindung wurde im Maillog entsprechend dokumentiert:
# tail -n2 /var/log/maillog
Jul 23 22:18:16 vml000070 dovecot: lmtp(24316): Connect from 10.0.0.80 Jul 23 22:18:18 vml000070 dovecot: lmtp(24316): Disconnect from 10.0.0.80: Successful quit
Ein Verbindungsaufbau von einem anderen Netzwerk-Host wird hingegen von der Firewall erfolgreich weggeblockt.
# telnet 10.0.0.70 24
Trying 10.0.0.70... telnet: connect to address 10.0.0.70: No route to host
Postfix
Da unser Mailserver nicht nur für die Hauptdomäne nausch.org eMails annehmen soll, sondern auch für die anderen (sub)Domains, erweiteren wir unsere Postfix-Konfiguration um ein paar Optionen.
Postfix nimmt immer dann Post außerhalb unseres $mynetworks an, wenn er sich zuständig fühlt. Hierzu kennt Postfix drei Klassen von Domains:
- echte Domains $mydestination
Diese Variante haben wir schon bei der Installation eines sicheren Mailservers mit Postfix unter CentOS 6.x erschlagen. - zu relayende Domains $relay_domains
Mit diese Variante haben wir uns bereits bei der Anbingung unseres Mailservers an ein Backend-Mailgateway im Kapitel Anbindung an einem Backend-Mailserver (Cyrus-IMAP-Server) befasst. - virtuelle Domains $virtual_alias_domains
Eine alternative Einbindung virtueller Domains ist die Verwendung von virtual_alias_domains und virtual_alias_maps
Wichtig: Dabei ist es logisch ausgeschlossen, daß eine Domain mehreren dieser Klassen angehört. Also immer nur einer, aber niemals zwei oder gar drei!
Da wir unsere Maildomänen und Nutzerkonten mit Hilfe von Postfixadmin zur Verwaltung des Dovecot-IMAP-Server unter CentOS 7.x nutzen, werden wir die Option 3, also $virtual_alias_domains verwenden.
Konfiguration
In der Postfix-Konfigurationsdatei /etc/postfix/main.cf definieren wir also die nötigen Optionen zur Nutzung der virtuelle Mailboxen.
Für den Transport definieren wir nun den virtual_transport in Richtung Dovecot-Server, in unserem Konfigurationsbeispiel der Host mit der IP-adresse 10.0.0.70.
# vim /etc/postfix/main.cf
- /etc/postfix/main.cf
... # Django : 2013-02-07 # virtuelle Mailboxen virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql_virtual_domains_maps.cf virtual_alias_maps = proxy:mysql:/etc/postfix/mysql_virtual_alias_maps.cf, proxy:mysql:/etc/postfix/mysql_virtual_alias_domain_maps.cf, proxy:mysql:/etc/postfix/mysql_virtual_alias_domain_catchall_maps.cf virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf, proxy:mysql:/etc/postfix/mysql_virtual_alias_domain_mailbox_maps.cf virtual_transport = lmtp:[10.0.0.70]:24 ...
Aktivierung
Zum aktivieren unserer Konfigurationsänderung führen wir nun einen Reload unseres Postfix-Mailservers durch.
# systemctl reload postfix.service
Im Maillog unseres Servers wird dieser Reload entsprechend dokumentiert.
# tail -n2 /var/log/maillog
Jul 23 23:30:21 vml000070 postfix/postfix-script[24353]: refreshing the Postfix mail system Jul 23 23:30:21 vml000070 postfix/master[2578]: reload -- version 2.10.1, configuration /etc/postfix
Der Reload wurde im maillog dokumentiert. Bei Bedarf können wir den Status unseres Dovecot_Servers abfragen.
# postfix.service - Postfix Mail Transport Agent
Loaded: loaded (/usr/lib/systemd/system/postfix.service; enabled) Active: active (running) since Mon 2014-07-21 15:28:29 CEST; 2 days ago Process: 24347 ExecReload=/usr/sbin/postfix reload (code=exited, status=0/SUCCESS) Main PID: 2578 (master) CGroup: /system.slice/postfix.service ├─ 2578 /usr/libexec/postfix/master -w ├─24358 qmgr -l -t unix -u └─24359 pickup -l -t unix -u Jul 21 15:28:29 vml000070.dmz.nausch.org postfix/master[2578]: daemon started -- version 2.10.1, configuration /etc/postfix Jul 21 15:28:29 vml000070.dmz.nausch.org systemd[1]: Started Postfix Mail Transport Agent. Jul 23 23:30:21 vml000070.dmz.nausch.org systemd[1]: Reloading Postfix Mail Transport Agent. Jul 23 23:30:21 vml000070.dmz.nausch.org postfix/postfix-script[24353]: refreshing the Postfix mail system Jul 23 23:30:21 vml000070.dmz.nausch.org postfix/master[2578]: reload -- version 2.10.1, configuration /etc/postfix Jul 23 23:30:21 vml000070.dmz.nausch.org systemd[1]: Reloaded Postfix Mail Transport Agent.
Dynamische Empfänger-Verifizierung
Im vorgenannten Konfigurationsbeispiel werden für alle Empfänger Nachrichten angenommen, die in der statischen Lookup-Tabelle gelistet ist. Was ist nun aber, wenn das Backend-System wiederum die Annahme einer weitergeleiteten Nachricht verweigert? Richtig, unser Mailserver würde diese als Bounce zurück zum Absender schicken. Dies wollen wir eben sowenig, wie den zusätzlichen Pflegeaufwand für die richtige und aktuelle relay_recipients-Tabelle!
Wir werden daher einfach die Entscheidung, ob nun eine Nachricht angenommen werden soll, oder nicht, an das Backendsystem delegieren.
Den notwendigen Konfogurationseintrag finden wir bereits in der Hauptkonfigurationsdatei von unserem Postfix 2.6.6 unter CentOS 6.x.
# grep verify /etc/postfix/master.cf
verify unix - - n - 1 verify
Postfix wird mit Hilfe des Moduls verify versuchen, noch während der Annahme der Bachricht von einem fremden Mailserver, beim Backend-System in Erfahrung zu bringen, ob dieses die Nachricht auch abnehmen würde. Ist dies der Fall, reicht Postfix die Nachricht an das Backend weiter. Anderenfalls wird die Annahme der Nachricht verweigert. Damit nun der Mailserver nicht jedesmal nachfragen muss, werden wir ihm hierzu eine kleine Datenbanktabelle spendieren, die auch nach einen Neustart des Servers zur Verfügung stehen kann.
Konfiguration
Als erstes legen wir nun das entsprechende Verzeichnis an und schenke es dem Nutzer Postfix.
# mkdir /var/spool/postfix/data
# chown postfix.root /var/spool/postfix/data
# chmod 700 /var/spool/postfix/data
Als nächstes definieren wir noch die entsprechende Datenbank, bzw. den Ort wo Postfix diese Datenbank abspeichern wird. Hierzu tragen wir in die Konfigurationsdatei main.cf folgenden Eintrag nach.
# vim /etc/postfix/main.cf
# Postfix-eigene verify-Datenbank für die dynamische (Kapitel 12.2.2 Dynamische Empfänger-Verifizierung) # Empfänger-Überprüfung nutzen address_verify_map = btree:/var/spool/postfix/data/verify
Ferner aktivieren wir noch den in der Grundkonfiguration unserers Restrictions-Regelwerk vorbereiteten Eintrag reject_unverified_recipient,.
# # Django : 2012-02-06 # Schutz durch Restrictions für unser SOHO # smtpd_recipient_restrictions = # Postmaster, abuse und andere aufgaben- oder funktionsgebundene E-Mail-Adressen (Role-Accounts) whitelisten check_recipient_access btree:/etc/postfix/access_recipient-rfc, # Black- und Whitelisting (Kapitel 8.2.3 White- und Blacklisting) check_client_access cidr:/etc/postfix/access_client, check_helo_access btree:/etc/postfix/access_helo, check_sender_access btree:/etc/postfix/access_sender, check_recipient_access btree:/etc/postfix/access_recipient, # Unsauberer eMails nicht annehmen (Kapitel 8.2.4 Anforderungen an Mailadressen) reject_non_fqdn_sender, reject_non_fqdn_recipient, reject_unknown_sender_domain, reject_unknown_recipient_domain, # Unsere eigenen Nutzer zulassen-/erlauben (Kapitel 8.2.2 Relaying erlauben und verbieten) permit_sasl_authenticated, permit_mynetworks, # RBL überprüfen (Kapitel 10.11 Realtime Blackhole Lists) reject_rbl_client zen.spamhaus.org, reject_rbl_client ix.dnsbl.manitu.net, reject_rbl_client bl.spamcop.net, reject_rbl_client dnsbl.njabl.org, reject_rhsbl_client multi.uribl.com, # Dynamische Prüfung auf existente Relay-Empfänger (Kapitel 12.2.2 Dynamische Empfänger-Verifizierung) reject_unverified_recipient, # Backupserver (MX) erlauben # permit_mx_backup, # alles andere an relaying verbieten (Kapitel 8.2.2 Relaying erlauben und verbieten) reject_unauth_destination, # Zu guter Letzt alles durchlassen, was bis jetzt noch nicht beanstandet wurde permit
Die Pflege der verify-Datenbank übernimmt dabei Postfix selbst, trägt neue Adressen ein und löscht auch regelmäßig alte Einträge - kurz und gut, der Postfix betreibt also eine Art Brutpflege. Da wir keine Änderungen an weiteren Parametern vorgenommen hatten, greifen hier die Default-Werte.
# postconf address_verify_positive_refresh_time
address_verify_positive_refresh_time = 7d
Nach Ablauf der sieben Tage wird das verify-Modul eine bereits bekannte und positiv gekennzeichnete eMailadresse erneuit beim Zielserver anfragen und die Aktualität des Datensatzes überprüfen.
# postconf address_verify_positive_expire_time
address_verify_positive_expire_time = 31d
Erst nach Ablauf von 31 Tagen wird eine bekannte und positive Adresse aus der Datenbank entfernt. Da aber bereits nach 7 Tagen eine Überprüfung der Adresse stattfindet, werden „gute Adressen“ quasi nie gelöscht sondern stehen sofort zur Verfügung!
# postconf address_verify_negative_refresh_time
address_verify_negative_refresh_time = 3h
Nach drei Stunden wird das verify-Modul eine noch nicht existente gecachte Empfänger-Adresse beim Zielserver erneut anfragen.
# postconf address_verify_negative_expire_time
address_verify_negative_expire_time = 3d
Nicht existierende Empfängeradressen werden maximal drei Tage vorgehalten und dann gelöscht.
# postconf address_verify_sender
address_verify_sender = $double_bounce_sender
# postconf double_bounce_sender
double_bounce_sender = double-bounce
Dieser Parameter legt fest, mit welchem Envelope-From die Anfragen an den Zielserver gerichtet werden sollen.
automatische Pflege
Erreicht nun eine Kontaktanfrage von einem fremden Mailserver, also einem Server, der nicht in $mynetworks definiert ist, kann man im Logfile des Mailservers sehr schön beobachten, wie Postfix die Adressen überprüft.
# tail -f /var/log/maillog
... Jun 4 22:11:20 vml000080 postfix/smtpd[13738]: connect from unknown[192.168.10.45] Jun 4 22:12:06 vml000080 postfix/cleanup[13743]: 55C673A: message-id=<20120604201206.55C673A@mx1.nausch.org> Jun 4 22:12:06 vml000080 postfix/qmgr[13643]: 55C673A: from=<double-bounce@nausch.org>, size=253, nrcpt=1 (queue active) Jun 4 22:12:06 vml000080 postfix/lmtp[13744]: 55C673A: to=<django@nausch.org>, relay=10.0.0.70[10.0.0.70]:24, delay=0.08, delays=0.04/0.01/0.02/0.01, dsn=2.1.5, status=deliverable (250 2.1.5 ok) Jun 4 22:12:06 vml000080 postfix/qmgr[13643]: 55C673A: removed Jun 4 22:12:09 vml000080 postfix/smtpd[13738]: 563E13A: client=unknown[192.168.10.45] Jun 4 22:12:17 vml000080 postfix/smtpd[13738]: disconnect from unknown[192.168.10.45] ...
Das Beispiel zeigt einen erfolgreichen Überprüfungsversuch status=deliverable (250 2.1.5 ok) ).
Wir im Gegensatz versucht an einen nicht existierenden Empfänger eine Nachricht zuzustellen, erfolgt hier der Vermerk status=undeliverable .
... Jun 4 22:26:07 vml000080 postfix/smtpd[13753]: connect from unknown[192.168.10.45] Jun 4 22:26:37 vml000080 postfix/cleanup[13760]: F0DAC3A: message-id=<20120604202637.F0DAC3A@mx1.nausch.org> Jun 4 22:26:38 vml000080 postfix/qmgr[13643]: F0DAC3A: from=<double-bounce@nausch.org>, size=253, nrcpt=1 (queue active) Jun 4 22:26:38 vml000080 postfix/lmtp[13761]: F0DAC3A: to=<peer.heinlein@nausch.org>, relay=10.0.0.70[10.0.0.70]:24, delay=0.08, delays=0.04/0.01/0.01/0.01, dsn=5.1.1, status=undeliverable (host 10.0.0.70[10.0.0.70] said: 550-Mailbox unknown. Either there is no mailbox associated with this 550-name or you do not have authorization to see it. 550 5.1.1 User unknown (in reply to RCPT TO command)) Jun 4 22:26:38 vml000080 postfix/qmgr[13643]: F0DAC3A: removed Jun 4 22:26:40 vml000080 postfix/smtpd[13753]: NOQUEUE: reject: RCPT from unknown[192.168.10.45]: 450 4.1.1 <peer.heinlein@nausch.org>: Recipient address rejected: unverified address: host 10.0.0.70[10.0.0.70] said: 550-Mailbox unknown. Either there is no mailbox associated with this 550-name or you do not have authorization to see it. 550 5.1.1 User unknown (in reply to RCPT TO command); from=<swat@nausch.org> to=<peer.heinlein@nausch.org> proto=SMTP helo=<ich> Jun 4 22:26:49 vml000080 postfix/smtpd[13753]: disconnect from unknown[192.168.10.45] ...
Einträge suchen/anzeigen
Werfen wir nun einen Blick in die verify-Datenbank von Postfix können wir für beide Beispiele die entsprechenden Einträge finden.
# postmap -s btree:/var/spool/postfix/data/verify
django@nausch.org 0:0:1338840726:250 2.1.5 ok peer.heinlein@nausch.org 2:0:1338841598:host 10.0.0.70[10.0.0.70] said: 550-Mailbox unknown. Either there is no mailbox associated with this 550-name or you do not have authorization to see it. 550 5.1.1 User unknown (in reply to RCPT TO command)
manuell Einträge löschen
Wollen wir, warum auch immer, einen Eintrag der verify-Datenbank manuell entfernen, greifen wir auch auf den Befehl postmap zurück.
# postmap -d peer.heinlein@nausch.org /var/spool/postfix/data/verify
LMTP-Einlieferungstests
Da nun alle Konfigurationen erfolgreich abgeschlossen sind, können wir uns nunmehr an den finalen Test unserer LMTP-Konfiguration wagen. Auch hier verwenden wir den gewohnten Test via telnet von berechtigten SMTP-Host aus.
$ telnet 10.0.0.70 24
Trying 10.0.0.70...
Connected to 10.0.0.70.
Escape character is '^]'.
220 imap.nausch.org Dovecot ready.
# telnet 10.0.0.70 24
$ telnet 10.0.0.70 24 Trying 10.0.0.70... Connected to 10.0.0.70. Escape character is '^]'. 220 imap.nausch.org Dovecot ready. LHLO vml000080.dmz.nausch.org 250-imap.nausch.org 250-8BITMIME 250-ENHANCEDSTATUSCODES 250 PIPELINING mail from:<django@nausch.org> 250 2.1.0 OK rcpt to:<michael@nausch.org> 250 2.1.5 OK DATA 354 OK From: django@nausch.org To: michael@nausch.org Subj: finaler LMTP-Einlieferungstest Date: 2014-07-23 23:42 Ahoi, das ist eine Testmail, eingeliefert via telnet imap-server auf Port 24 . 250 2.0.0 <michael@nausch.org> GoSmFy6y0FNUYQAAOs1BfA Saved quit 221 2.0.0 OK Connection closed by foreign host.
Links
~~DISCUSSION~~