Postfix TLS perfect forward secrecy

Dank #prism ist Forward Secrecy für E-Mail gerade in aller Munde. Ich habe mal die relevanten Informationen für Postfix zusammengetragen, damit man nicht lange suchen muss. Aber erst mal ein wenig Schlau machen…

Was ist Forward Secrecy?

Wikipedia beschreibt Forward Secrecy wie folgt:

Folgenlosigkeit (englisch perfect forward secrecy, PFS; auf deutsch etwa perfekt fortgesetzte Geheimhaltung) bedeutet in der Kryptographie die Eigenschaft von Verschlüsselungsverfahren, dass aus einem aufgedeckten Schlüssel nicht auf vorhergehende oder nachfolgende Schlüssel eines Kommunikationskanals geschlossen werden kann.

Wikipedia

In anderen Worten: Sollte jemand den verschlüsselten Datenverkehr mitgeschnitten haben, kann dieser - selbst wenn der Key kompromittiert wurde (!) - nachträglich nicht mehr entschlüsselt werden.

Wie muss man Postfix dazu konfigurieren?

Technische Voraussetzung für Forward Secrecy sind zusätzliche, temporäre Einmalschlüssel, die für ephemeral Diffie-Hellman (EDH) Verschlüsselung geeignet sind. Wer OpenSSL >= 1.0.0 und Postfix >= 2.6.0 einsetzt kann sie einfach generieren. Auf der Kommandozeile wird dazu einen Satz DH-Parameterdateien generiert - 1024-Bit für non-export und 512-Bit für export ciphers:

% openssl gendh -out /etc/postfix/dh_512.pem -2 512
% openssl gendh -out /etc/postfix/dh_2048.pem -2 2048

Diese Schlüssel werden dann, ergänzend zu einer bereits bestehenden TLS-Konfiguration für den Postfix smtpd SMTP-Server, so eingebunden:

smtpd_tls_dh1024_param_file = ${config_directory}/dh_2048.pem
smtpd_tls_dh512_param_file = ${config_directory}/dh_512.pem

# Postfix ≥ 2.6 für elliptic curve cryptography:
smtpd_tls_eecdh_grade = strong

Wichtig

Debian hat in der Vergangenheit GnuTLS gepatched und die minimal akzeptable Anzahl an bits von 1024 auf 2048 hochgesetzt. Das führt zu Problemen in der Kommunikation mit anderen Servern. Der Workaround besteht darin, Postfix von vornherein ein Diffie-Hellman Cert mit 2048 Bit an die Hand zu geben.

Bemerkung

Viktor Dukhovni schreibt zusätzlich in Exim, DH, GnuTLS & interop: If your openssl(1) version is 1.0.0 or higher, your server may perform faster if you generate DSA-style parameters:

% openssl dhparam -dsaparam -out dh_2048.pem 2048

Alte Software wie z.B. Netscape 7 kommt nicht 2048-Bit EDH nicht klar. In so einem Fall muss man auf den Portsl 465 und 587 (mit denen solche Clients reden) mit 1024-Bit EDH betreiben:

% openssl dhparam -out dh1024.pem 1024
% postconf -e 'submission_tls_dh1024_param_file = ${config_directory}/dh1024.pem'

Und in der master.cf:

465 inet n ... smtpd
  -o smtpd_tls_wrappermode=yes
  -o smtpd_tls_dh1024_param_file=$submission_tls_dh1024_param_file
  ...
587 inet n ... smtpd
  -o smtpd_tls_dh1024_param_file=$submission_tls_dh1024_param_file
  ...

Damit der Server die neue EDH-Verschlüsselungsmethode wählt und der Client nicht selbst und frei (das Falsche) wählen darf, kommt noch der tls_preempt_cipherlist-Parameter (ab Postfix >= 2.8.0) mit hinzu:

tls_preempt_cipherlist = yes

Wichtig

Das kann bei br0ken clients zu Verbindungsproblemen führen. Wenn diese eine statische IP besitzen kann man diese mit smtpd_discard_ehlo_keyword_address_maps davon abhalten wieder und wieder gegen eine Wand zu rennen…

Damit wird der Liste des Servers Vorrang gegeben werden. Voraussetzung dafür ist (mindestens) eine SSLv3-Verbindung. Ältere Standards wie z.B. SSLv2 lassen dem Client die Wahl der Verschlüsselungsmethode. SSLv2 will ohnehin niemand haben, weil es nicht brauchbar sicher ist. In der main.cf weist man den Server deshalb an sie gar nicht in die Liste würdiger Standards aufzunehmen:

smtpd_tls_protocols = !SSLv2

SMTP Forward Secrecy testen

Mit dem openssl-Kommando und dessen s_client lässt sich dann abschliessend einfach testen, ob jetzt ECDHE-Chiffren zum Einsatz kommen:

$ openssl s_client -CAfile /etc/ssl/certs/ca-certificates.crt -starttls \
        smtp -connect mail.sys4.de:25
...
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : ECDHE-RSA-AES256-SHA
    Session-ID: 37751B6CA3687E6477827A3D29AEC162B470990429FFF0245F0B57FC3B66DCB2
    Session-ID-ctx:
    Master-Key: 8C1882D9F7C4916AEA6EFCE45CA950EC260D34FAC40C4717CCFAF5150A87A693
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 3600 (seconds)
    TLS session ticket:
    0000 - 69 0e 9c e5 42 97 33 71-e2 31 26 35 95 b5 42 fd   i...B.3q.1&5..B.
    0010 - 05 b5 d7 d0 53 f6 23 13-2e d6 e9 be 46 62 45 c7   ....S.#.....FbE.
    0020 - 90 a2 d5 b4 c0 e3 cc 3c-4b 94 6a af 07 25 be 1b   .......<K.j..%..
    0030 - 44 ce a0 0a d8 df e4 73-34 bc 8e 88 c2 e8 28 84   D......s4.....(.
    0040 - 89 8a 99 cc a4 15 f6 4e-58 92 53 7f 92 77 20 b3   .......NX.S..w .
    0050 - 78 ec 9b 03 74 be d7 8f-ae 46 6d 5f e6 8a 6d cb   x...t....Fm_..m.
    0060 - 60 03 b9 a4 95 78 7e fd-e4 94 40 ea 77 10 95 21   `....x~...@.w..!
    0070 - 32 6c b1 7d 1e 5a 29 ec-ae d7 a3 a3 05 84 de dc   2l.}.Z).........
    0080 - e0 6b e4 c1 84 43 4e 62-9f b5 bc ff a8 f9 99 6d   .k...CNb.......m
    0090 - a8 b2 40 8c ef 2b 44 28-ea fb 37 b6 4b 48 0d 8d   ..@..+D(..7.KH..

    Start Time: 1376481129
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
250 DSN
QUIT

Nach einer Weile lassen sich dann auch entsprechende Verbindungen im LOG nachweisen:

$ zegrep "TLS connection established from.*with cipher.*ECDHE" /var/log/mail.log | \
        awk '{printf("%s %s %s %s\n", $12, $13, $14, $15)}' | sort | uniq -c | sort -n
      5 TLSv1 with cipher ECDHE-RSA-AES128-SHA
     17 TLSv1 with cipher ECDHE-RSA-AES256-SHA
    155 TLSv1 with cipher ECDHE-RSA-RC4-SHA

Kommentare

  1. Torsten Quack

    Torsten Quack (4 Jahre, 3 Monate) # Reply

    Toll, danke für diese Zusammenfassung der notwendigen Schritte. In 3 min. zu einer sichereren TLS-Konfiguration :) . Als nächstes ist Cyrus an der Reihe ...

    -tq

  2. Ihsan Dogan

    Ihsan Dogan (4 Jahre, 2 Monate) # Reply

    Mit welcher Einstellung schreibt Postfix den Ciphers in Logfile?

  3. Patrick Koetter

    Patrick Koetter (4 Jahre, 2 Monate) # Reply

    Aus dem TLS_README:

    Example:

    /etc/postfix/main.cf:
    smtpd_tls_loglevel = 0

    To include information about the protocol and cipher used as well as the client and issuer CommonName into the "Received:" message header, set the
    smtpd_tls_received_header variable to true. The default is no, as the information is not necessarily authentic. Only information recorded at the final destination is reliable, since the headers may be changed by intermediate servers.

  4. Christian

    Christian (3 Jahre) # Reply

    Hallo,

    vielen Dank für die tolle Anleitung.

    Funktioniert das alles, wenn man nur einen 2048-Bit-DH-Schlüssel einbindet?
    Sprich, wenn ich nur den “non export” EDH eingebe, und auf dem 512-Bit “export EDH” verzichte.

    Meine CA stellt nämlich keine Schlüssel unter 2048-Bit aus.

    Vielen Dank im Voraus.

  5. Frank

    Frank (3 Jahre) # Reply

    Ooops... sorry, ich habe meinen Reply an Dich aus Versehen als neuen Kommentar angelegt.

  6. Frank

    Frank (3 Jahre) # Reply

    Hmmm... kann es sein, dass Du etwas verwechselst?
    Die "DH params" sind Primzahlen und (noch) keine Schlüssel.
    Und Deine CA stellt Dir Zertifikate und keine Schlüssel aus (auch wenn man sich die Keys auch vom Zertifikatsprovider Deines Vertrauens erzeugen lassen kann).
    Außerdem vermute ich mal, dass Dein Zertifikat RSA-basiert ist. Beispiel:

    # openssl x509 -text -noout </etc/pki/tls/certs/localhost.crt|grep "Signature Algorithm"
    Signature Algorithm: sha1WithRSAEncryption
    Signature Algorithm: sha1WithRSAEncryption

  7. ted

    ted (3 Jahre) # Reply

    Hey,
    ich kann leider keine E-Mail von hotmail empfangen senden geht aber ...

    "Dec 2 16:26:17 server02 postfix/smtpd[28390]: connect from snt004-omc2s39.hotmail.com[65.54.61.90]
    Dec 2 16:26:17 server02 postfix/smtpd[28390]: SSL_accept error from snt004-omc2s39.hotmail.com[65.54.61.90]: lost connection
    Dec 2 16:26:17 server02 postfix/smtpd[28390]: lost connection after STARTTLS from snt004-omc2s39.hotmail.com[65.54.61.90]
    Dec 2 16:26:17 server02 postfix/smtpd[28390]: disconnect from snt004-omc2s39.hotmail.com[65.54.61.90]
    Dec 2 16:26:17 server02 postfix/smtpd[28390]: connect from snt004-omc2s39.hotmail.com[65.54.61.90]
    Dec 2 16:26:18 server02 postfix/smtpd[28390]: disconnect from snt004-omc2s39.hotmail.com[65.54.61.90]"

    Hier mal meine config:
    "#SMTPD (Eingang)
    smtpd_tls_loglevel = 1
    smtpd_tls_auth_only = yes
    smtpd_sasl_auth_enable = yes
    tls_preempt_cipherlist = yes
    smtpd_tls_ciphers = high
    smtpd_tls_mandatory_ciphers= high
    smtpd_tls_security_level = encrypt
    smtpd_tls_protocols = !SSLv2,!SSLv3
    smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3
    smtpd_tls_key_file = /etc/pki/tls/private/flieden.key
    smtpd_tls_cert_file = /etc/pki/tls/certs/flieden_bundle.crt
    smtpd_tls_CAfile = /etc/pki/tls/certs/cacert_bundle.crt
    smtpd_tls_dh512_param_file = ${config_directory}/dh512.pem
    smtpd_tls_dh1024_param_file = ${config_directory}/dh2048.pem
    #SMTP (Ausgang)
    smtp_tls_loglevel = 1
    smtp_tls_ciphers = high
    smtp_tls_mandatory_ciphers= high
    smtp_tls_security_level = encrypt
    smtp_tls_protocols = !SSLv2,!SSLv3
    smtp_tls_mandatory_protocols = !SSLv2,!SSLv3
    smtp_tls_key_file = /etc/pki/tls/private/flieden.key
    smtp_tls_cert_file = /etc/pki/tls/certs/flieden_bundle.crt
    smtp_tls_CAfile = /etc/pki/tls/certs/cacert_bundle.crt"

  8. Frank

    Frank (3 Jahre) # Reply

    Hi,

    also vorab eine Info aus meinen Logs:
    hotmail.com unterstützt zumindest TLS1 mit AES256-SHA.

    Nutzt Du noch OpenSSL 0.9x? Dann schau mal nach, welche Cipher-Suite hier tatsächlich verwendet wird. Bei mir ist es diese:

    [postfix-2.3.3]$ grep -r DEF.*CLIS src/global/*params.h |cut -d" " -f2-|grep HIGH
    DEF_TLS_HIGH_CLIST "!EXPORT:!LOW:!MEDIUM:ALL:+RC4:@STRENGTH"
    [postfix-2.3.3]$ openssl ciphers '!EXPORT:!LOW:!MEDIUM:ALL:+RC4:@STRENGTH'
    ADH-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:KRB5-DES-CBC3-MD5:KRB5-DES-CBC3-SHA:ADH-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:ADH-AES128-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA
    [frank@viclavic postfix-2.3.3]

    Die Angaben zu Deiner Konfiguration sind nur eingeschränkt nutzbar. Leider zeigt die Erfahrung, dass "out in the wild" unglaublich viele Postfix-Installationen zu finden sind, bei denen das ältere Postfix (z.B. 2.3 wie bei mir) mit Konfigurationen für 2.8 gefüttert wird (ungeprüfter C&P aus dem Netz). Gerade von 2.2 bis 2.8 hat es bez. Verschlüsselung sehr viele Änderungen in Postfix gegeben. Mehr Infos zu dem Problem gibt's beim Klick auf meinen Namen.

    Frank

  9. Frank

    Frank (3 Jahre) # Reply

    Ergänzend noch der relevante Auszug aus meiner Config:

    # only FS (fails on hotmail.com):
    #tls_export_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:ALL:!aNULL:!ADH:!3DES:!EXP:!RC4:!kRSA:!kKRB5:!aDSS:!DES:!aPSK:!kECDH
    # with AES256-SHA (for hotmail and other NSA friends)tls_export_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:ALL:!aNULL:!ADH:!3DES:!EXP:!RC4:!kKRB5:!aDSS:!DES:!aPSK:!kECDH:!RC2:!AES128-SHA
    #tls_export_cipherlist = ALL:!DHE
    smtp_tls_mandatory_ciphers = export
    smtpd_tls_mandatory_ciphers = export
    smtp_tls_ciphers = export
    smtpd_tls_ciphers = export
    # pf 2.6 / rhel 6; enable:
    smtpd_tls_eecdh_grade = strong

    Das sieht jetzt ein bisschen "komisch" aus wegen "export", funktioniert aber bereits ab Postfix 2.2 aufwärts und kann so direkt auf Centos 5 und 6 verwendet werden (Postfix 2.3 bzw. 2.6).

  10. Frank

    Frank (3 Jahre) # Reply

    Sorry, zwei geschachtelte und mehrfach "detachte" screen-Sessions haben die Umbrüche zerstückelt. Ich habe das zu spät gesehen. Das ist die Konfiguration der Cipherlist (Postfix ab 2.2, OpenSSL ab 0.97):

    tls_export_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:ALL:!aNULL:!ADH:!3DES:!EXP:!RC4:!kKRB5:!aDSS:!DES:!aPSK:!kECDH:!RC2:!IDEA:!SEED:!CAMELLIA:!AES128-SHA

    (Auf einem RHEL-6-Server macht Hotmail übrigens "TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384". Deshalb vermute ich bei Dir mal OpenSSL 0.9x.)

  11. ted

    ted (3 Jahre) # Reply

    Hi,

    ich benutze:

    Centos 7
    Openssl 1.0.1e
    Postfix 2.10.1

    An den cipher liegt es glaube ich nicht:
    openssl ciphers '!EXPORT:!LOW:!MEDIUM:ALL:+RC4:@STRENGTH'
    ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:AECDH-AES256-SHA:ADH-AES256-GCM-SHA384:ADH-AES256-SHA256:ADH-AES256-SHA:ADH-CAMELLIA256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA:PSK-AES256-CBC-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:AECDH-AES128-SHA:ADH-AES128-GCM-SHA256:ADH-AES128-SHA256:ADH-AES128-SHA:AECDH-DES-CBC3-SHA:ADH-CAMELLIA128-SHA:ADH-DES-CBC3-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:CAMELLIA128-SHA:DES-CBC3-SHA:DES-CBC3-MD5:PSK-AES128-CBC-SHA:PSK-3DES-EDE-CBC-SHA:KRB5-DES-CBC3-SHA:KRB5-DES-CBC3-MD5

    Wenn ich smtpd_tls_security_level von encrypt auf may setze kann ich auch mail von hotmail empfangen und nicht nur senden was ja sowie so schon ging.
    Und ja er verschlüsselt dann mit ECDHE-RSA-AES256-SHA384:

    Dec 2 21:10:33 server02 postfix/smtp[5480]: Untrusted TLS connection established to mx3.hotmail.com[65.54.188.94]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)

    Allerdings möchte ich nur verschlüsselt Mails empfangen und senden, deshalb würde ich gerne

    smtpd_tls_security_level = encrypt
    smtp_tls_security_level = encrypt

    gesetzt lassen und nicht,

    smtpd_tls_security_level = may

    wie kann ich das hinbekommen, jedenfalls habe ich das Porblem nur mit Hotmail...

  12. Frank

    Frank (3 Jahre) # Reply

    > Dec 2 21:10:33 ... ... mx3.hotmail.com[65.54.188.94]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)

    Erst einmal stellen wir hiermit fest, dass die verschlüsselte Übertragung von hotmail.com aus funktioniert. :-)

    > Allerdings möchte ich nur verschlüsselt Mails empfangen und senden, deshalb würde ich gerne
    > smtpd_tls_security_level = encrypt
> smtp_tls_security_level = encrypt

    Damit hättest Du aber kein "opportunistic TLS" mehr, sondern "mandatory TLS". Don't use mandatory TLS on public smtp servers!

    Siehe dazu:
    http://www.tuxad.de/blog/archives/2014/10/23/rhel_5_postfix_poodle_patch/index.html
    http://www.heise.de/security/artikel/Forward-Secrecy-testen-und-einrichten-1932806.html
    und vor allem http://www.postfix.org/TLS_README.html :

    "You can ENFORCE the use of TLS, so that the Postfix SMTP server announces STARTTLS and accepts no mail without TLS encryption, by setting "smtpd_tls_security_level = encrypt". According to RFC 2487 this MUST NOT be applied in case of a publicly-referenced Postfix SMTP server. This option is off by default and should only seldom be used."

    Frank

Kommentare deaktiviert.