I 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.
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.
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", $12, $13, $14, $15)}' | 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/.