Harden the SSL configuration of your mailserver

Harden_the_SSL_configurationI described in one of my earlier post how to Setup Postfix with SMTP-AUTH and TLS on CentOS. I’m going to follow that up in this article by describing how to harden the SSL  configuration of your mail server.

I have enabled SSL why is that not enough?

There are many cryptographic standards and methods used while securing an SSL connection. Some of them are considered secure while others are considered insecure as they have weaknesses or flaws that compromise security. When you use SSL to connect to a mailserver you expect your information to be secure. To ensure that, the SSL configuration of the related services needs to be setup to only use cryptographic ciphers that are considered secure.

A system admin does not need to know about every weakness, but needs to know where he can find the information he needs to finish his job. As far as SSL hardening goes, there is an excellent website at BetterCrypto which provides detailed information as well as configuration examples. Most of the settings have been tested on Debian based systems but can be applied to CentOS and other Linux distributions as well.

infoI suggest to check the latest information on the BetterCrypto website to keep up with latest news about protocols and ciphers that are considered insecure.

Dovecot SSL settings

In dovecot as setup from the CentOS repository you’ll find the config file responsible for ssl in the following path.

/etc/dovecot/conf.d/10-ssl.conf

At the end of the file you will see a line configuring the cipher list. In the default configuration this list is commented out. Add the following configuration option to configure the list.

# SSL ciphers to use
ssl_cipher_list = EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA

Testing the configuration

Testing the dovecot configuration can be done via the openssl command. The following command will force openssl to try to use only SSLv2 with the EXP and the LOW cipher which is disabled in the configuration.

$ openssl s_client -crlf -connect 127.0.0.1:993 -cipher aNULL:eNULL:LOW:3DES:MD5:EXP:PSK:DSS:RC4:SEED:ECDSA -ssl2
CONNECTED(00000003)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 48 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : SSLv2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1406061627
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

As the above output shows, the SSL handshake did not work due to the disabled cipher and protocol.

infoSSLv2 has been marked weak for quite a while. As a result of that, some distributions have removed SSLv2 already from there openssl versions. This sadly prevents you from testing the server for it.

You could continue this test as well with the SSLv3 protocol which is also not allowed with these ciphers.

Postfix SSL settings

Additionally to enabling the TLS support as described in my previous post about Setting up Postfix with SMTP-AUTH and TLS on CentOS these settings will increase the security of your SSL configuration.

In the /etc/postfix/main.cf configuration file add the following settings.

# Hardening SSL configuration
#

# enable opportunistic TLS support in the SMTP server and client
smtp_tls_security_level = may
smtp_tls_loglevel = 1

# only offer authentication after STARTTLS
smtpd_tls_auth_only = yes

# Disable SSL compression
tls_ssl_options = NO_COMPRESSION

# Disable SSLv2 and SSLv3 leaving TLSv1, TLSv1.1 and TLSv1.2 enabled.
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_protocols = !SSLv2 !SSLv3

# Configure the allowed cipher list
smtpd_tls_mandatory_ciphers=high
tls_high_cipherlist=EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA

# Enable EECDH key exchange for Forward Security
smtpd_tls_eecdh_grade=ultra

This SSL configuration will not affect the smptd running on port 25. Restricting weak SSL encryption on port 25 might be counterproductive. Other mail servers will deliver their emails to this mail server on port 25. Accepting weak SSL protocols and ciphers is better then getting the emails without SSL encryption. But we want to make sure that client connections are always made using secure ciphers. Therefore we need to activate the submission service on port 587 and deactivate authentication via the smtpd port 25.

To deactivate authentication via smtp on port 25, add the option “-o smtpd_sasl_auth_enable=no” to the configuration of the smtp service in the /etc/postfix/master.cf file. The resulting lines should look like this.

smtp      inet  n       -       n       -       -       smtpd
        -o content_filter=smtp-amavis:[127.0.0.1]:10024
        -o smtpd_sasl_auth_enable=no

Now the submission service needs to be enabled. This is done by uncommenting the submission lines in the /etc/postfix/master.cf configuration file and adding the options to force encryption as well as forcing the list of mandatory ciphers. The resulting line in the master.cf should read like this.

submission inet n       -       n       -       -       smtpd
         -o smtpd_tls_security_level=encrypt
         -o tls_preempt_cipherlist=yes

After the configuration has been changed, restart postfix to apply the changes. Keep in mind that you need to change all email clients to use port 587 to send email with this configuration activated.

/etc/init.d/postfix restart

Testing the configuration

For testing postfix, change the following parameter in the /etc/postfix/main.cf to enable logging of summary messages during the TLS handshake. This will allow you to verify in the server log which cipher was used for the TLS connection.

smtpd_tls_loglevel = 1

Lets start by testing the authentication without an ssl connection. To do this you can use my Mailserver-Test script and execute the following command. Alternatively, you can connect via telnet as shown in the output below and enter the commands manually.

The first test will make sure that the smtp service on port 25 does not offer the AUTH needed to authenticate and also does not accept an authentication.

$ ./smtp-test.sh auth username 127.0.0.1 sender@domain.com recipient@example.com
Enter SMTP-Password: password
SMTP-Server: 127.0.0.1
Sender-Email: sender@domain.com
Recipient-Email: recipient@example.com
Connection: non-ssl
    Auth: YES
    Auth-User: username
    Auth-Pass: *****

Starting the test ... FINISHED


telnet 127.0.0.1 25
S: Trying 127.0.0.1...
S: Connected to mail.example.com.
S: Escape character is '^]'.
S: 220 mail.example.com ESMTP Postfix
C: EHLO localhost
S: 250-mail.example.com
S: 250-PIPELINING
S: 250-SIZE 10240000
S: 250-VRFY
S: 250-ETRN
S: 250-STARTTLS
S: 250-ENHANCEDSTATUSCODES
S: 250-8BITMIME
S: 250 DSN
C: AUTH PLAIN AHVzZXJuYW1lAHBhc3N3b3Jk
S: 503 5.5.1 Error: authentication not enabled
C: MAIL FROM: <sender@domain.com>
S: 250 2.1.0 Ok
C: RCPT TO: <recipient@example.com>
S: 554 5.7.1 <recipient@example.com>: Relay access denied
C: DATA
S: 554 5.5.1 Error: no valid recipients
C: From: <sender@domain.com>
C: To: <recipient@example.com>
C: Date: Mon Jul 21 19:19:10 UTC 2014
C: Subject: smtp-test email
C:
C: This is a test mail sent from the smtp-test.
C: To find out more about this script visit https://www.tinned-software.net/en/scripts_mailserver-test/
C:
C: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ut
C: mauris ut metus posuere ullamcorper et sed tellus. Morbi eleifend vel enim
C: vitae volutpat. Mauris tincidunt adipiscing lobortis. Quisque sed
C: adipiscing tortor, nec feugiat augue. Sed mi orci, scelerisque at sem
C: vitae, eleifend vulputate dolor. Fusce hendrerit risus at quam aliquam, sit
C: amet rutrum justo placerat. Etiam a magna et augue ullamcorper aliquam
C: accumsan sit amet est. Fusce facilisis pulvinar orci, in congue quam
C: venenatis ut. Proin ullamcorper dolor convallis, pulvinar dui ac, venenatis
C: nisi. Sed vitae nisi vitae nulla luctus porttitor. Sed tincidunt porta mi,
C: eget rhoncus dui aliquam.
C: .
C:
S: 221 2.7.0 Error: I can break rules, too. Goodbye.
S: Connection closed by foreign host.
C: QUIT

The error message shows that the authentication is not offered as well as not allowed without an SSL connection and also not via port 25.

The second will test the weak ciphers on the submission port 587.

$ ./smtp-test.sh 127.0.0.1 sender@domain.com recipient@example.com ssl --port 587 --ssl-options "-cipher aNULL:eNULL:LOW:3DES:MD5:EXP:PSK:DSS:RC4:SEED:ECDSA -ssl2"
SMTP-Server: 127.0.0.1
Sender-Email: sender@domain.com
Recipient-Email: recipient@example.com
Connection: ssl
    Auth: NO

Starting the test ... FINISHED


openssl s_client -starttls smtp -crlf -connect 127.0.0.1:587 -cipher aNULL:eNULL:LOW:3DES:MD5:EXP:PSK:DSS:RC4:SEED:ECDSA -ssl2
S: write:errno=104
S: CONNECTED(00000003)
S: ---
S: no peer certificate available
S: ---
S: No client certificate CA names sent
S: ---
S: SSL handshake has read 221 bytes and written 83 bytes
S: ---
S: New, (NONE), Cipher is (NONE)
S: Secure Renegotiation IS NOT supported
S: Compression: NONE
S: Expansion: NONE
S: SSL-Session:
S:     Protocol  : SSLv2
S:     Cipher    : 0000
S:     Session-ID:
S:     Session-ID-ctx:
S:     Master-Key:
S:     Key-Arg   : None
S:     Krb5 Principal: None
S:     PSK identity: None
S:     PSK identity hint: None
S:     Start Time: 1406063896
S:     Timeout   : 300 (sec)
S:     Verify return code: 0 (ok)
S: ---
C: EHLO localhost

Because the weak ciphers that are not allowed, the SSL handshake failed as expected.

The third test will test the submission port again and will make sure that postfix will not accept emails without authentication.

$ ./smtp-test.sh mail.domain.com sender@domain.com recipient@example.com ssl --port 587
SMTP-Server: mail.domain.com
Sender-Email: sender@domain.com
Recipient-Email: recipient@example.com
Connection: ssl
    Auth: NO

Starting the test ... FINISHED


openssl s_client -starttls smtp -crlf -connect mail.domain.com:587
S: depth=2 /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
S: verify error:num=19:self signed certificate in certificate chain
S: verify return:0
S: CONNECTED(00000003)
S: ---
S: Certificate chain
S:  0 s:/description=jlxxxxxxxxxxxx56/C=AT/ST=Wien/L=Vienna/O=John Doe/CN=mail.domain.com/emailAddress=webmaster@domain.com
S:    i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 2 Primary Intermediate Server CA
S:  1 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 2 Primary Intermediate Server CA
S:    i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
S:  2 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
S:    i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
S: ---
S: Server certificate
S: -----BEGIN CERTIFICATE-----
S: TISLYsdwcB31F81Eh8xqM5xp5ULgZY7A6krc+H4SOxbwAMNA3QrcfQmZLoUe1j3C
   ...
S: r1jufHiIajXt8hc+LfqWLhSsZEyWHnzIAVyjwDUPHb7y5btY0cNp
S: -----END CERTIFICATE-----
S: subject=/description=jlxxxxxxxxxxxx56/C=AT/ST=Wien/L=Vienna/O=John Doe/CN=mail.domain.com/emailAddress=webmaster@domain.com
S: issuer=/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 2 Primary Intermediate Server CA
S: ---
S: No client certificate CA names sent
S: ---
S: SSL handshake has read 6777 bytes and written 363 bytes
S: ---
S: New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
S: Server public key is 4096 bit
S: Secure Renegotiation IS supported
S: Compression: NONE
S: Expansion: NONE
S: SSL-Session:
S:     Protocol  : TLSv1
S:     Cipher    : DHE-RSA-AES256-SHA
S:     Session-ID: AE79XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX027
S:     Session-ID-ctx:
S:     Master-Key: C8A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX05AC
S:     Key-Arg   : None
S:     Start Time: 1406064691
S:     Timeout   : 300 (sec)
S:     Verify return code: 0 (ok)
S: ---
S: 250 DSN
C: EHLO localhost
S: 250-mail.domain.com
S: 250-PIPELINING
S: 250-SIZE 10240000
S: 250-VRFY
S: 250-ETRN
S: 250-AUTH PLAIN LOGIN
S: 250-AUTH=PLAIN LOGIN
S: 250-ENHANCEDSTATUSCODES
S: 250-8BITMIME
S: 250 DSN
C: MAIL FROM: <sender@domain.com>
S: 250 2.1.0 Ok
C: rcpt TO: <recipient@example.com>
S: 554 5.7.1 <recipient@example.com>: Relay access denied
C: DATA
S: 554 5.5.1 Error: no valid recipients
C: From: <sender@domain.com>
C: To: <recipient@example.com>
C: Date: Di 22 Jul 2014 23:31:27 CEST
C: Subject: smtp-test email
C:
C: This is a test mail sent from the smtp-test.
C: To find out more about this script visit https://www.tinned-software.net/en/scripts_mailserver-test/
C:
C: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ut
C: mauris ut metus posuere ullamcorper et sed tellus. Morbi eleifend vel enim
C: vitae volutpat. Mauris tincidunt adipiscing lobortis. Quisque sed
C: adipiscing tortor, nec feugiat augue. Sed mi orci, scelerisque at sem
C: vitae, eleifend vulputate dolor. Fusce hendrerit risus at quam aliquam, sit
C: amet rutrum justo placerat. Etiam a magna et augue ullamcorper aliquam
C: accumsan sit amet est. Fusce facilisis pulvinar orci, in congue quam
C: venenatis ut. Proin ullamcorper dolor convallis, pulvinar dui ac, venenatis
C: nisi. Sed vitae nisi vitae nulla luctus porttitor. Sed tincidunt porta mi,
C: eget rhoncus dui aliquam.
C: .
C:
S: 221 2.7.0 Error: I can break rules, too. Goodbye.
S: closed
C: QUIT

The postfix log file gives a record of which ciphers were used. The logging enabled earlier will write a couple of lines to the log about the used protocol and cipher. The following command will extract these lines from the /var/log/maillog and count them for a quick summary.

grep "TLS connection established from.*with cipher" /var/log/maillog | awk '{printf("%s %s %s %s\n", , , , )}' | sort | uniq -c | sort -n
      1 TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384
      1 TLSv1 with cipher ADH-DES-CBC-SHA
      3 SSLv2 with cipher DES-CBC3-MD5
      4 SSLv3 with cipher ECDHE-RSA-AES256-SHA
      4 TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256
      6 TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384
      8 TLSv1 with cipher ECDHE-RSA-AES128-SHA
     13 SSLv2 with cipher DES-CBC-MD5
     55 TLSv1 with cipher ECDHE-RSA-AES256-SHA
    323 TLSv1 with cipher DHE-RSA-AES256-SHA

Read more of my posts on my blog at http://blog.tinned-software.net/.

This entry was posted in Mailserver, Security and tagged , , . Bookmark the permalink.