Heute las ich einen Artikel über das Aufsetzen eines eigenen Mailservers und ob dies eine gute Idee wäre? – Letztendlich riet der Autor vom Betrieb eines eigenen Mailservers mehr oder weniger ab.

Es ist dabei erst einmal gar nicht so schwierig einen eigenen Mailserver aufzusetzen und Emails zu versenden und zu empfangen.

Für welche Mailserver-Software man sich da entscheidet, bleibt eigentlich nur dem persönlichen Geschmack überlassen, denn vom Funktionsumfang her ist die gängige Serversoftware ähnlich ausgestattet.

Ich habe mich für sendmail in Kombination mit procmail entschieden, da ich bereits mehrere Jahre Erfahrung im Betrieb und der Konfiguration eines Email-Servers habe. Gerade sendmail scheint für den Anfänger nicht einfach zu konfigurieren zu sein und es geht immer noch folgender Mythos herum:

Man ist erst ein echter UNIX-Admin, wenn man eine sendmail.cf editiert hat!

Dabei ist die Notwendigkeit eine sendmail.cf-Konfigurationsdatei zu editieren sogar recht klein! Sendmail bringt leistungsfähige Makros mit, welche mit Hilfe des m4-Makropräprozessors eine angepasste sendmail.cf-Konfigurationsdatei erzeugen. Wie das genau funktioniert, kann man in der sendmail Dokumentation nachlesen oder sich Bücher wie zum Beispiel „sendmail“ vom O’Reilly-Verlag zulegen. Auch verraten einige klassische Linux-/UNIX-Administratorenhandbücher grundlegende Informationen zum Aufsetzen von sendmail.

Meine Konfiguration für sendmail sieht wie folgt aus:

divert(-1)dnl
#-----------------------------------------------------------------------------
# $Sendmail: debproto.mc,v 8.15.2 2016-12-08 18:43:49 cowboy Exp $
#
# Copyright (c) 1998-2010 Richard Nelson. All Rights Reserved.
#
# cf/debian/sendmail.mc. Generated from sendmail.mc.in by configure.
#
# sendmail.mc prototype config file for building Sendmail 8.15.2
#
# Note: the .in file supports 8.7.6 - 9.0.0, but the generated
# file is customized to the version noted above.
#
# This file is used to configure Sendmail for use with Debian systems.
#
# If you modify this file, you will have to regenerate /etc/mail/sendmail.cf
# by running this file through the m4 preprocessor via one of the following:
# * make (or make -C /etc/mail)
# * sendmailconfig
# * m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
# The first two options are preferred as they will also update other files
# that depend upon the contents of this file.
#
# The best documentation for this .mc file is:
# /usr/share/doc/sendmail-doc/cf.README.gz
#
#-----------------------------------------------------------------------------
divert(0)dnl
#
# Copyright (c) 1998-2005 Richard Nelson. All Rights Reserved.
#
# This file is used to configure Sendmail for use with Debian systems.
#
define(`_USE_ETC_MAIL_')dnl
include(`/usr/share/sendmail/cf/m4/cf.m4')dnl
VERSIONID(`$Id: sendmail.mc, v 8.15.2-8 2016-12-08 18:43:49 cowboy Exp $')
OSTYPE(`debian')dnl
DOMAIN(`debian-mta')dnl
dnl DOMAIN(`generic')dnl
define(`confDOMAIN_NAME', `mail.ladegast.net')dnl
dnl # Items controlled by /etc/mail/sendmail.conf - DO NOT TOUCH HERE
undefine(`confHOST_STATUS_DIRECTORY')dnl #DAEMON_HOSTSTATS=
dnl # Items controlled by /etc/mail/sendmail.conf - DO NOT TOUCH HERE
dnl #
dnl # General defines
dnl #
dnl # SAFE_FILE_ENV: [undefined] If set, sendmail will do a chroot()
dnl # into this directory before writing files.
dnl # If *all* your user accounts are under /home then use that
dnl # instead - it will prevent any writes outside of /home !
dnl # define(`confSAFE_FILE_ENV', `')dnl
dnl #
dnl # Daemon options - restrict to servicing LOCALHOST ONLY !!!
dnl # Remove `, Addr=' clauses to receive from any interface
dnl # If you want to support IPv6, switch the commented/uncommentd lines
dnl #
FEATURE(`no_default_msa')dnl
DAEMON_OPTIONS(`Family=inet, Name=MTA-v4, Port=smtp')dnl
DAEMON_OPTIONS(`Family=inet, Name=MTA-v4-SSL, Port=465, M=s')dnl
DAEMON_OPTIONS(`Family=inet, Name=MSP-v4, Port=submission, M=Ea, Addr=127.0.0.1')dnl
DAEMON_OPTIONS(`Family=inet6, Name=MTA-v6, Port=smtp, A=2a01:4f8:c0c:2dfa::2')dnl
DAEMON_OPTIONS(`Fimily=inet6, Name=MTA-v6-SSL, Port=465, M=s, A=2a01:4f8:c0c:2dfa::2')dnl
DAEMON_OPTIONS(`Family=inet6, Name=MSP-v6, Port=submission, M=Ea, Addr=::1')dnl
dnl #
define(`confCW_FILE', `/etc/mail/sendmail.cw')dnl
define(`confCR_FILE', `/etc/mail/relay')dnl

dnl # Be somewhat anal in what we allow
define(`confPRIVACY_FLAGS',dnl
`needmailhelo,needexpnhelo,needvrfyhelo,restrictqrun,restrictexpand,nobodyreturn,authwarnings')dnl
dnl #
dnl # Define connection throttling and window length
define(`confCONNECTION_RATE_THROTTLE', `15')dnl
define(`confCONNECTION_RATE_WINDOW_SIZE',`10m')dnl
dnl #
dnl # Features
dnl #
dnl # use /etc/mail/local-host-names
FEATURE(`use_cw_file')dnl
dnl #
dnl # The access db is the basis for most of sendmail's checking
FEATURE(`access_db', , `skip')dnl
dnl #
dnl # The greet_pause feature stops some automail bots - but check the
dnl # provided access db for details on excluding localhosts...
FEATURE(`greet_pause', `1000')dnl 1 seconds
dnl #
dnl # Delay_checks allows sender<->recipient checking
FEATURE(`delay_checks', `friend', `n')dnl
dnl #
dnl # If we get too many bad recipients, slow things down...
define(`confBAD_RCPT_THROTTLE',`3')dnl
dnl #
dnl # Stop connections that overflow our concurrent and time connection rates
FEATURE(`conncontrol', `nodelay', `terminate')dnl
FEATURE(`ratecontrol', `nodelay', `terminate')dnl
dnl #
dnl # If you're on a dialup link, you should enable this - so sendmail
dnl # will not bring up the link (it will queue mail for later)
dnl define(`confCON_EXPENSIVE',`True')dnl
dnl #
dnl # Dialup/LAN connection overrides
dnl #
dnl include(`/etc/mail/m4/dialup.m4')dnl
dnl include(`/etc/mail/m4/provider.m4')dnl
dnl #
define(`confAUTH_MECHANISMS', `LOGIN PLAIN DIGEST-MD5 CRAM-MD5')dnl
TRUST_AUTH_MECH(`LOGIN PLAIN DIGEST-MD5 CRAM-MD5')dnl
define(`confAUTH_OPTIONS', `p')dnl

FEATURE(`always_add_domain')dnl
FEATURE(`nocanonify')dnl
FEATURE(`mailertable')dnl
FEATURE(`domaintable')dnl
FEATURE(`genericstable')dnl
FEATURE(`virtusertable')dnl
FEATURE(`block_bad_helo')dnl
FEATURE(`redirect')dnl
FEATURE(`badmx')dnl
FEATURE(`blacklist_recipients')dnl
define(`PROCMAIL_MAILER_PATH', `/usr/bin/procmail')dnl
FEATURE(`local_procmail', `/usr/bin/procmail')dnl
dnl # Default Mailer setup
MAILER_DEFINITIONS
MAILER(`procmail')dnl
MAILER(`smtp')dnl

Damit haben wir erst einmal eine grundsätzliche Konfiguration, welcher in einer perfekten Welt auch perfekt funktionieren würde. – Es ist aber nun leider so, dass die Welt eben nicht perfekt ist und wir uns mit ihren kleinen Unschönheiten herumschlagen müssen:

  • Spam
  • Domain Abuse
  • Mailserver, die als Open Relays konfiguriert sind

Spam

Gegen Spam gibt es bereits seit einigen Jahren etablierte Lösungen:

  • DNS-Blacklists
  • Spamfilter, welche die Mail nach Entgegennahme durch den Mailserver filtern

DNS-Blacklists

DNS-Blacklists funktionieren auf folgende Art und Weise: Versucht irgendein System bei unserem Mailserver Email oder auch Spam zuzustellen, wird die tatsächliche IP-Adresse der Gegenstelle bei einem oder mehreren speziellen DNS-Servern angefragt. Kommt als Antwort ein Fehler NXDOMAIN, also die IP-Adresse ist nicht vorhanden, darf die Email zugestellt werden, andernfalls wird diese mit einer Fehlermeldung abgewiesen.

Ich verwendete zwei DNS-Blacklists, die sehr gut gepflegt sind:

Die Blacklists werden über das Feature „enhdsnbl“ (enhanced DNS Blacklist) eingebunden, wobei auch ein spezifischer Fehlertext hinterlegt werden kann. In der Konfigurationsdatei sendmail.mc sieht das wie folgt aus:

FEATURE(`enhdnsbl', `zen.spamhaus.org', `"571 Rejected - " $&{client_name} " listed at zen.spamhaus.org!"', `t')dnl
FEATURE(`enhdnsbl', `ix.dnsbl.manitu.net', `"571 Rejected - " $&{client_name} " listed at ix.dnsbl.manitu.net!"', `t')dnl

Spamfilter

Ein Projekt läuft bereits seit Jahren unauffällig und glänzt durch erneuerbare Filterregeln: Spamassassin ist das Mittel der Wahl, wenn es darum geht eingehenden Spam zu bekämpfen, der nicht bereits schon von den DNS-Blacklist-Filtern unseres MTA ausgefiltert worden ist. Ich bevorzuge dabei die Per-User-Konfiguration, weil dann für jeden User individuell die Bayes-Filter trainiert werden können und sich vor allen Dingen alle User ihre eigenen Procmail-Rezepte erstellen können, um den Spam passend zu selektieren und zu filtern.

Procmail-Rezepte

Procmail ist ein sehr leistungsfäher LDA (local delivery agent), mit dessen Hilfe man sich innerhalb kürzester Zeit über reguläre Ausdrücke Filterregeln erstellen und sich so seine Email in verschiedene Programme, Ordner, Dateien etc. umleiten kann. Diese funktionalität machen wir uns zu nutze und leiten alle eingehende Email generell an Spamassassin weiter.

Ich setze ein globales Procmail-Rezept ein, welches jegliche zugestellte Email Emails mit einer Wertung von über 15.0 Punkten gleich direkt nach /dev/null entsorgt und alle anderen Emails mit einer Bewertung zwischen 5.0 und 15.0 in den Ordner „Junk“ des entsprechenden Users zustellt.

Die globale Procmail-Konfigurationsdatei (/etc/procmailrc) sieht wie folgt aus:

# global procmailrc
SHELL=/bin/bash
# set default deliver path to /var/mail/<username>
DEFAULT=$ORGMAIL
DROPPRIVS=yes

# filter incoming mails through Spamassassin
:0 fw
| /usr/bin/spamc -f

# move mails with a score of 15 or higher to /dev/null
:0 H
* ^X-Spam-Level: \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
/dev/null

# move all mails with a score lower than 15 but higher as the threshold to folder Junk
:0:
* ^X-Spam-Status: Yes
$HOME/mail/Junk

Dieses Beispiel macht auch deutlich, warum es sinnvoll ist den MTA (mail transfer agent), in unserem Falle sendmail, und den MDA/LDA (mail delivery agent) zu trennen. Zum einen beeinflussen Konfigurationsänderungen am MDA/LDA nicht den MTA und zum anderen sind wesentlich flexiblere Konfigurationsszenarien möglich.

Weitere Sicherungsmaßnahmen

Damit wir den Missbrauch unserer Domain in den Griff bekommen, müssen wir neben der grundsätzlichen Konfiguration noch viele kleine Dinge einrichten und zusätzliche Softwarepakete einsetzen, damit wir uns vor diesen Unannehmlichkeiten schützen und wir auch den Rest der Welt vor dem Missbrauch unserer Systeme und/oder Domains schützen:

  • STARTTLS und entsprechende Zertifikate
  • SPF (Sender policy framework)
  • DKIM (Domain keys identified mail)
  • DMARC (Domain-based Message Authentication, Reporting and Conformance)

STARTTLS und Zertifikate

Wir sollten unseren Mailserver auf jeden Fall STARTTLS-fähig machen. Das heißt, dass jeder andere Mailserver (oder User) eine verschlüsselte Sitzung innerhalb des SMTP-Dialogs aufbauen kann. Damit das vernünftig funktioniert, brauchen wir ein paar Zertifikate, die unseren Server mit seinem FQDN (full qualified domain name) ausweisen.

Let’s encrypt ist eine Zertifizierungsstelle, die uns die benötigten Zertifikate kostenfrei ausstellt. Ist alles korrekt konfiguriert, wird unser Mailserver ab sofort mit allen anderen Mailservern versuchen verschlüsselt zu kommunizieren. Man kann natürlich aber auch Millionen in Fernsehwerbung stecken und es Email made in Germany nennen! 😉

Unsere Zertifikate binden wir wie folgt in unsere Konfigurationsdatei ein:

define(`confDONT_BLAME_SENDMAIL', `GroupReadableKeyFile')dnl
define(`CERT_DIR', `/etc/letsencrypt/live/mail.ladegast.net')dnl
define(`confCACERT_PATH', `/etc/ssl/certs')dnl
define(`confCACERT', `CERT_DIR/chain.pem')dnl
define(`confSERVER_CERT', `CERT_DIR/cert.pem')dnl
define(`confSERVER_KEY', `CERT_DIR/privkey.pem')dnl
define(`confCLIENT_CERT', `CERT_DIR/cert.pem')dnl
define(`confCLIENT_KEY', `CERT_DIR/privkey.pem')dnl
define(`confSERVER_SSL_OPTIONS', `+SSL_OP_NO_SSLv2 +SSL_OP_NO_SSLv3 +SSL_OP_CIPHER_SERVER_PREFERENCE')dnl
define(`confCLIENT_SSL_OPTIONS', `+SSL_OP_NO_SSLv2 +SSL_OP_NO_SSLv3')dnl
define(`confCIPHER_LIST', `HIGH:!aNULL:!eNULL@STRENGTH')dnlSPF (Sender policy framework)

Die letzten 3 Zeilen schränken die verwendeten Chiffre zur Verschlüsselung ein. SSLv2 und SSLv3 sollten nicht mehr benutzt werden, da diese als unsicher gelten und nicht mehr verwendet werden sollen.

SPF (Sender policy framework)

SPF legt über einen DNS-Eintrag in der Zonendatei unserer Domain fest, welcher Host unserer Domain überhaupt Emails versenden darf. Dort sind im Falle von ladegast.net folgende Werte hinterlegt:

@       IN A 94.130.75.205
halley  IN A 94.130.75.205
mail    IN A 94.130.75.205
@       IN AAAA 2a01:4f8:c0c:2dfa::2
halley  IN AAAA 2a01:4f8:c0c:2dfa::2
mail    IN AAAA 2a01:4f8:c0c:2dfa::2
@       IN MX 10 mail
@       IN TXT "v=spf1 a mx -all"

Dabei ist es grundsätzlich wichtig, dass für den MX-Eintrag keine direkte IP festgelegt wird, sondern ein Name. Dieser Name darf aber kein CNAME auf einen anderen Namen sein, sondern muss zwingend als A-Eintrag hinterlegt sein. Der TXT-Eintrag macht unsere Domain SPF-fähig, nämlich dass wir SPF in der Version 1 verwenden (v=spf1), dass ein Absender mit unserem Domainnamen einen validen A-Eintrag oder MX-Eintrag unserer Domain haben muss (a mx) und dass alle anderen Absender-Hosts nicht erlaubt sind (-all). Damit legen wir den Grundstein, dass ein anderer Mailserver überprüfen kann, ob ein Host, welcher Emails in unseren Domainnamen einsenden will, auch wirklich von dem Domaininhaber autorisiert ist.

Das war es auch schon für SPF! Außer dem Ändern der Zonendatei des DNS-Servers ist keine weitere Konfiguration notwendig. Der Einsatz von SPF hat allerdings eine große Auswirkung darauf, dass mit unserer Email-Domain kein Schindluder mehr in Form von gespooften/gefälschten Emails mehr getrieben wird, solange der empfangende Mailserver eine Art von Spamfilter einsetzt, die den SPF-Record der Absenderdomain überprüft.

Alle anderen, die Email nach wie vor ungesehen akzeptieren, müssen auch damit rechnen, dass sie gefälschte Emails untergejubelt bekommen.

DKIM (Domain keys identified mail)

DKIM funktioniert im wesentlichen mit einer serverseitigen Signatur aller ausgehenden Emails. Der öffentliche Schlüssel zum Überprüfen dieser Signatur, ist ebenfalls in der Zonendatei unseres DNS-Servers hinterlegt:

default._domainkey       IN TXT     "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0V67I2HwYTlEsHktxFcS8Up4BO441qeXO6s3J5SzOXaRHRHVp5c41t28aVqfyrbJremHLVlz2BdhMs9jlVzkiS/pSZVJ8o91MAP8U1t50HExML8CRxcMCqnPZvn6VF3+1BRHbEMPFpoNJ/pcvquSbbmT/pqPVYAc2Ef6mcF5w60iEwxugXkMNv/BGsEdfqL/T3orzWi+v9ib4bsKGriMG2PmxDgiFWjPBTlwZ8oV2TpwgDpqcuIxOoFVkrcOakhgmJDeEferUXArDypO62rQayvs5phLOl8cZA2PMd41bCNDbB34kJR1iko/LsMBKj9FWCMrKMQ6LGwBcKqMdQsMjwIDAQAB"

Mit Hilfe dieses öffentlichen Schlüssels kann jeder Mailserver, der Emails von uns empfängt, die Authentizität dieser Emails feststellen, indem er die kryptografische Signatur der Email mit Hilfe dieses Public-Keys überprüft. Verschlüsselung und Authentizität sind nämlich zwei paar Schuhe:

  • Verschlüsselung schützt Daten vor unbefugtem Zugriff, aber nicht vor Veränderung durch Dritte
  • Überprüfung der Authentizität mittels eines MAC (Message authentication code) schützt Daten vor Veränderung, aber nicht vor unbefugtem Zugriff

Moderne Chiffre wie zum Beispiel AES-GCM (Galois Counter mode) beherrschen die gleichzeitige Verschlüsselung und die Generierung eines MAC im fortlaufenden Datenstrom. Der Einsatz von STARTTLS (Verschlüsselung) in Kombination mit SPF und DKIM (Feststellung der Authentizität) bildet diesen Mechanismus der gleichzeitigen Verschlüsselung und Feststellung der Authentizität auf Email ab. Der Empfänger kann nun feststellen, dass die Email einerseits verschlüsselt übertragen wurde und andererseits auch durch niemand anderen verändert wurde.

Ein Softwarepaket, welches DKIM für verschiedene Mailserver umsetzt und alle ausgehenden Mails mit einem MAC signiert, ist OpenDKIM. Damit OpenDKIM funktioniert, muss bei der Konfiguratuion ein entsprechender Domain-Key erzeugt und dieser im DNS-Server hinterlegt werden. Dann fügen wir OpenDKIM als Milter (Mail-Filter) zu unserer sendmail.mc hinzu. Die beiden nachfolgenden Zeilen erledigen dies:

dnl # OpenDKIM milter
INPUT_MAIL_FILTER(`opendkim', `S=local:/var/run/opendkim/opendkim.sock')dnl

DMARC (Domain-based Message Authentication, Reporting and Conformance)

Bleibt nun noch DMARC. – DMARC ist die Festlegung einer Policy (Richtlinie), wie mit Emails von unserer Domain umgegangen wird, wenn diese nicht gewissen Kriterien entsprechen. Man kann einen einfachen „Beobachtungsmodus“ aktivieren, bei welchem andere Mailserver regelmäßig Reports zu den empfangen Emails zusenden oder auch eine entsprechende Policy festlegen, dass andere Mailserver Emails auch verwerfen können (reject).

Damit DMARC überhaupt funktioniert, müssen bereits SPF und DKIM für die Domain erfolgreich eingerichtet werden sein und OpenDMARC als Milter in unserer sendmail Konfigurationsdatei eingetragen sein:

dnl # OpenDMARC milter
INPUT_MAIL_FILTER(`opendmarc', `S=local:/var/run/opendmarc/opendmarc.sock')dnl

Ansonsten finden sich im Internet eine ganze Reihe guter Artikel zum Thema DMARC-Einrichtung.

Fazit

Ist es nun eine gute Idee einen Mailserver zu betrieben? – Ich finde: Ja!

Es zwingt auf jeden Fall dazu sich mit den Techniken für einen sicheren Emailversand und -empfang auseinander zu setzen und das eigene Wissen zu erweitern. Beim Aufsetzen eines eigenen Mailservers werden einem selbst die Probleme beim Emailversand und -Empfang bewusst und man muss die Risiken abschätzen und ggf. Maßnahmen ergreifen.

Die oben genannten Maßnahmen sehe ich derzeit als absoluten Mindeststandard an, wenn es darum geht das Problem von Spam und Reverse-Spam (über Domain Abuse) einzudämmen. STARTTLS bietet zumindest grundsätzliche Sicherheit für die Übertragungswege einer Email, ersetzt aber nach wie vor nicht eine sichere Ende-zu-Ende-Verschlüsselung.