Perfect Forward Secrecy in Sendmail einrichten

Perfect Forward Secrecy (PFS) in der Kryptographie meint, dass durch das Erlangen von geheimen Masterschlüsseln, die zur Erstellung der Sitzungsschlüssel verwendet wurden, nicht auf den Inhalt zukünftig oder bereits aufgezeichneter Kommunikation der Schlüsselverwender geschlossen werden kann. Ein gestohlener Masterschlüssel ist damit nicht mehr wert als ein gestohlender Sitzungsschlüssel, beide erlauben jeweils nur die Entschlüsselung "ihrer" Session.

TLS bietet dafür zwei Verfahren:

  • Ephemeral Diffie-Hellman (DHE)
  • Ephemeral Elliptic Curve Diffie-Hellman (ECDHE)

Das Diffie-Hellman-Verfahren bedient sich zur Ermittlung eines gemeinsamen Sitzungsschlüssels einer einfach zu berechnenden mathematischen Funktion, deren Umkehr bei ausreichender Länge der gewählten Parameter bislang als nicht lösbar gilt. Neben anderen erzeugen die Kommunikationspartner dabei jeweils zwei zufällige Parameter, von denen sie einen dem Partner während des TLS Handshakes unverschlüsselt zusenden. Mit den öffentlich übertragenen Parametern und dem eigenen geheimen berechnen beide den gemeinsamen Schlüssel für die eigentliche verschlüsselte Verbindung.

Perfect Forward Secrecy wird bei TLS mittels Ephemeral (flüchtig) Diffie-Hellman erreicht. Hierbei dürfen die Parameter nicht wiederverwendet, sondern müssen für jede Session absolut zufällig neu generiert werden. Wichtig ist, dass dies von beiden Teilnehmern gemacht wird, weil aus jedem der Geheimnisse plus den im Klartext übertragenen öffentlichen Parametern der Sitzungsschlüssel errechnet werden kann.

Der Schlüsselaustausch im RSA-Verfahren bietet keine Perfect Forward Secrecy, weil die damit generierten Sitzungsschlüssel vom Private Key des Servers abhängen. Bei Diffie-Hellman dient der Server-Schlüssel lediglich dazu, den öffentlich übertragenen Diffie-Hellman Public Key zu signieren, um Man-in-the-Middle-Attacken zu unterbinden.

OpenSSL Cipherlist

Sendmail verwendet die Cipherlist Syntax von OpenSSL, so dass sie sich mit Hilfe des Kommandos 'openssl ciphers -v [cipherlist]' gut testen lässt. Ab OpenSSL-Version 1.0.0 kann man alternativ den Parameter '-V' nutzen, wodurch zusätzlich die Cipher ID ausgegeben wird. Das kann sehr hilfreich sein, weil OpenSSL nicht immer die RFC-Namen verwendet und man die Cipher anhand ihrer ID identifizieren muss.

Wir beginnen mit den Ciphern, die wir ausschließen wollen:

!kECDH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED

Die Keywords für die Konfiguration der Cipherlist sind prinzipiell hier dokumentiert. Leider ist die Seite nie ganz aktuell; welche Keywords eine OpenSSL-Version genau unterstützt, kann man im jeweiligen Source nachlesen.

Wir wollen unsere 'ECDHE' (vorrangig, weil schneller) und 'DHE' Suites voranstellen:

EECDH:EDH:!kECDH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED

Nun verfeinern wir die Reihenfolge der Cipher. Für TLSv1.2 Clients bieten wir zunächst "ihre" Cipher, vorrangig mit 'AES-GCM'; außerdem ziehen wir für die Authentisierung aus Performance-Gründen 'ECDSA''RSA' vor:

EECDH+ECDSA:EECDH+AESCGM:EECDH:EDH:+TLSv1!kECDH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED

Zusätzlich möchten wir auch noch mit Partnern kommunizieren, die bislang kein PFS implementiert haben. Dafür fügen wir die 'HIGH' Cipher hinzu:

EECDH+ECDSA:EECDH+AESCGM:EECDH:EDH:HIGH:+TLSv1!kECDH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED

 Mittels 'openssl ciphers' geben wir uns die resultierende Liste aus:

[root@popc mail]# openssl ciphers -v 'EECDH+ECDSA:EECDH+AESCGM:EECDH:EDH:HIGH:+TLSv1:!kECDH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED'
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA384
ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA256
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA384
ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD
ECDHE-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA256
DHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(256) Mac=AEAD
DHE-RSA-AES256-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(256) Mac=SHA256
DHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AESGCM(128) Mac=AEAD
DHE-RSA-AES128-SHA256 TLSv1.2 Kx=DH Au=RSA Enc=AES(128) Mac=SHA256
AES256-GCM-SHA384 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(256) Mac=AEAD
AES256-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA256
AES128-GCM-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AESGCM(128) Mac=AEAD
AES128-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA256
ECDHE-ECDSA-AES256-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(256) Mac=SHA1
ECDHE-ECDSA-AES128-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=AES(128) Mac=SHA1
ECDHE-ECDSA-RC4-SHA SSLv3 Kx=ECDH Au=ECDSA Enc=RC4(128) Mac=SHA1
ECDHE-RSA-AES256-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(256) Mac=SHA1
ECDHE-RSA-AES128-SHA SSLv3 Kx=ECDH Au=RSA Enc=AES(128) Mac=SHA1
ECDHE-RSA-RC4-SHA SSLv3 Kx=ECDH Au=RSA Enc=RC4(128) Mac=SHA1
DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1
DHE-RSA-AES128-SHA SSLv3 Kx=DH Au=RSA Enc=AES(128) Mac=SHA1
AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1
AES128-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1

Konfiguration Sendmail

Zur Unterstützung auch der Elliptic Curve Varianten des Diffie-Hellman-Verfahrens muss Sendmail neben '_FFR_TLS_1' zusätzlich mit '_FFR_TLS_EC' (erfordert Sendmail 8.14.8 oder höher) kompiliert sein, prüfen:

[root@popc ~]# sendmail -d0.13 < /dev/null
Version 8.14.9
[...]
FFR Defines: _FFR_TLS_1 _FFR_TLS_EC
[...]

Ab Sendmail 8.14.8 werden Diffie-Hellman Keys der Länge 2048 Bit unterstützt ('confDH_PARAMETERS').

Damit OpenSSL für jede Schlüsselvereinbarung mittels Ephemeral Diffie-Hellman auch wirklich neue Parameter erzeugt, müssen die Optionen 'SSL_OP_SINGLE_DH_USE' bzw. 'SSL_OP_SINGLE_ECDH_USE' von der Applikation gesetzt werden. Dieses ist bei Sendmail standardmäßig der Fall, muss also nicht eigens konfiguriert werden.

Insgesamt ergibt sich für die sendmail.mc

define(`confDH_PARAMETERS', `2048')dnl

LOCAL_CONFIG
O ServerSSLOptions=+SSL_OP_NO_SSLv2 +SSL_OP_NO_SSLv3 +SSL_OP_CIPHER_SERVER_PREFERENCE
O ClientSSLOptions=+SSL_OP_NO_SSLv2 +SSL_OP_NO_SSLv3
O CipherList=EECDH+ECDSA:EECDH+AESCGM:EECDH:EDH:HIGH:+TLSv1:!kECDH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED

Update: Sendmail 8.15.1

In Sendmail 8.15.1 ist die Compile Option '_FFR_TLS_1' entfallen, 'ServerSSLOptions', 'ClientSSLOptions', und 'CipherList' stehen jetzt immer zur Verfügung, '_FFR_TLS_EC' muss weiterhin gesetzt werden.

Konfiguration in sendmail.mc (Sendmail 8.15.1):

define(`confDH_PARAMETERS', `2048')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', `EECDH+ECDSA:EECDH+AESCGM:EECDH:EDH:HIGH:+TLSv1:!kECDH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!SEED')dnl

Testen mittels OpenSSL:

pop:~ eh$ openssl s_client -connect popc:25 -starttls smtp
[...]
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
[...]

Logzeile Sendmail:

Nov  7 20:51:58 popc sendmail[24232]: STARTTLS=server, relay=pop [192.168.12.113], version=TLSv1/SSLv3, verify=NO, cipher=ECDHE-RSA-AES256-GCM-SHA384, bits=256/256

Referenzen:

1. http://en.wikipedia.org/wiki/Forward_secrecy

2. http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange

3. http://tools.ietf.org/html/rfc2631

4. https://wiki.mozilla.org/Security/Server_Side_TLS

5. https://www.openssl.org/docs/apps/ciphers.html

6. https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html