#!/bin/blog

March 10, 2007

Postfix 2.3: Abgehend Server-Zertifikate prüfen

Filed under: Internet — Tags: , , , , — martin @ 10:59 pm

Ausgangslage: Ein Internet-Mailgateway unter Postfix 2.3 soll ganz normal Mail an beliebige Gegenstellen im Internet ausliefern. Für bestimmte Zieldomains soll sichergestellt werden, daß Mails dorthin ausschließlich TLS-verschlüsselt übertragen werden.

Hier die Basiskonfiguration für TLS, ein Auszug aus der main.cf:
# TLS grundsätzlich deaktivieren, Aktivierung erfolgt dann fallweise.
smtp_tls_security_level = none
# Auch wenn wir selbst kein TLS machen, wollen wir loggen, wenn
# Gegenstellen TLS anbieten.
smtp_tls_note_starttls_offer = yes
# Apropos Log; standardmäßig loggt Postfix überhaupt keine Infos zu
# TLS-Transaktionen.
smtp_tls_loglevel = 1
# In dieser Map tragen wir die Gegenstellen ein, mit denen wir nur per
# TLS kommunizieren wollen.
smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
# Und in diesem Verzeichnis sind die Zertifikate enthalten, von denen
# die Zertifikate der Gegenstellen signiert sein müssen, um als akzeptabel
# zu gelten.
smtp_tls_CApath = /etc/postfix/tls/cacerts.d

Zu beachten ist, daß die im smtp_tls_CApath hinterlegten Zertifikate vor Verwendung gehasht werden müssen. Dafür wird das Perl-Script c_rehash aus der OpenSSL-Distribution verwendet.

c_rehash `postconf -h smtp_tls_CApath`

(Falls der smtp-Client im chroot läuft, müssen die Zertifikate und die Links mit den Hashwerten dort ebenfalls vorhanden sein. Man kann das z.B. erreichen, indem man die Zertifikate in /var/spool/postfix/etc/postfix/tls/cacerts.d/ ablegt und das Verzeichnis dann per Symlink aus /etc/postfix/tls/ erreichbar macht. Oder man legt einen entsprechenden Kopierjob an. Der Fantasie des Lesers sind keine Grenzen gesetzt.)

Wie intensiv die Zertifikate bei abgehenden Verbindungen geprüft werden sollen, wird mittels smtp_tls_security_level festgelegt. Darüberhinaus können in der über smtp_tls_policy_maps referenzierten Datei /etc/postfix/tls_policy pro Zieldomain abweichende Policies definiert werden. Es lassen sich eine ganze Menge “Sicherheitsstufen” einstellen:

  • none: Es wird generell nicht verschlüsselt. Wenn der gegnerische Mailserver seine Verschlüsselungsbereitschaft anzeigt (STARTTLS im ESMTP-Greeting), wird dies ignoriert.
  • may: Wenn der gegenerische Mailserver STARTTLS anbietet, wird verschlüsselt, wenn nicht, dann nicht.
  • encrypt: Die Mail wird nur übertragen, wenn der gegnerische Mailserver STARTTLS anbietet und eine Verschlüsselung aufgebaut werden kann. Eine Prüfung des Server-Zertifikats findet nicht statt. Selbstsignierte Zertifikate werden akzeptiert.
  • verify: Die Mail wird nur übertragen, wenn der gegnerische Server ein Zertifikat benutzt, das von einer CA ausgestellt wurde, deren Zertifikat im mit smtp_tls_CApath angegebenen Pfad enthalten ist.
  • secure: Die Mail wird nur übertragen, wenn der gegnerische Server ein Zertifikat benutzt, das von einer CA ausgestellt wurde, deren Zertifikat im mit smtp_tls_CApath angegebenen Pfad enthalten ist und bei dem der im Zertifikat eingetragene Common Name mit der Zieldomain übereinstimmt.

Als Default-Policy (smtp_tls_security_level) eignen sich ausschließlich “none” und “may”, denn mit “encrypt” und aufwärts wird man ein Gateway, das Mail ins Internet senden soll, nicht betreiben können. Ich habe mich im vorliegenden Fall für “none” entschieden, da ich in der von “may” gebotenen opportunistischen Verschlüsselung keinen Nutzen erkenne. Im Gegenteil: Opportunistische Verschlüsselung kostet mich nicht nur Rechenzeit, sondern es besteht potentiell die Gefahr, daß Probleme bei der Kommunikation mit MTAs auftreten, bei denen TLS fehlerhaft konfiguriert und/oder implementiert ist.

Nun zu den Zielen, mit denen wir verschlüsselt kommunizieren wollen. Wenn man davon ausgeht, daß keine Verschlüsselung besser ist als schlechte Verschlüsselung, kann man die Optionen “may” und “encrypt” in diesem Zusammenhang direkt vergessen:

  • Die opportunistische Verschlüsselung “may” bringt keinerlei Sicherheitsgewinn.
  • Kaum etwas anderes gilt für “encrypt”: Für eine Gegenstelle Verschlüsselung zu erzwingen und dann jedes Zertifikat, egal ob abgelaufen oder selbstsigniert, zu akzeptieren, ist nur die Illusion von Sicherheit, gerade so, als würde man das routinemäßige Abklicken von SSL-Warnungen im WWW-Browser zum Standard erheben.

Übrig bleiben also “verify” und “secure”, von denen die letztere natürlich ganz besonders verlockend klingt und es auch ist:

  • Mit “verify” wird erzwungen, daß Mail an eine Gegenstelle nur dann ausgeliefert wird, wenn deren Zertifikat von einer bekannten CA signiert wurde.
  • Mit “secure” wird nicht nur, wie bei “verify”, das Zertifikat überprüft, sondern es wird auch noch verlangt, daß der Common Name des gegnerischen Zertifikats der Zieldomain entspricht. Alternativ kann auch eine Liste von Host- und Domainnamen angegeben werden, die als Common Names für die Zieldomain akzeptabel sind.

Hier also ein paar Beispiele für Einträge in der tls_policy.

  • Für die Domain binblog.de soll uns eine einfache Überprüfung des Zertifikats reichen:
    binblog.de verify

  • Die Mailexchanger der Domain example.com liegen alle in example.com (mx1.example.com und mx2.example.com), und wir wollen nur Zertifikate akzeptieren, die auf einen Hostnamen (Common Name) unter example.com ausgestellt sind:
    example.com secure

  • Der Mailexchanger der Domain scsy.de hat den Namen vortex.f00.net. In diesem Fall müssen wir, wenn wir den Common Name überprüfen wollen, extra dazusagen, in welcher Domain er liegen bzw. welchen Namen er haben soll:
    scsy.de secure match=vortex.f00.net

Mit der in den letzten beiden Beispielen genannten “sicheren” Überprüfung von Zertifikaten stellen wir so weit wie möglich sicher, daß wir gegen DNS-Angriffe geschützt sind: Wird uns ein gefälschter MX-Record untergeschoben, weigert sich Postfix, Mail an diesen auszuliefern. Wechselt die Domain den Besitzer und bekommt neue Mailexchanger, weigert sich Postfix ebenfalls, Mail dorthin auszuliefern, solange nicht entsprechende Konfigurationsänderungen in der TLS Policy vorgenommen werden.

Wenn Postfix aufgrund einer Umstellung auf einer der Gegenseiten keine Mail ausliefern kann, werden die Mails übrigens nicht gebounced, sondern im Rahmen der normalen Timeouts in der Queue behalten. Es bleibt also genügend Gelegenheit, auf Überwachungen oder Useranrufe zu reagieren.

Diese gesamte Konfigurationsmethodik wurde von Postfix 2.2 zu Postfix 2.3 komplett ausgetauscht. Leider ist 2.3 bisher nur zu den wenigsten Distributionen durchgedrungen. Die Implementation in 2.3 ist aber so gelungen ausgefallen, daß ich jedem, der sich auf diese Ebene begeben will, nur zum Upgrade raten kann.

Wer das alles viel zu überkandidelt findet: Die übernächste Postfix-Version, 2.5, wird voraussichtlich sogar die Möglichkeit haben, gezielt die Fingerprints von Zertifikaten pro Zieldomain anzugeben. Damit dürfte dann wirklich das allerletzte DNS-Schlupfloch gestopft sein, und gleichzeitig können selbstsignierte Zertifikate verwendet werden.

Update am 21.3.: Hoffentlich werden hier jetzt keine Unwahrheiten mehr verbreitet. 😉

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: