Postfix and TLS encryption

With hackers around every corner, governments wants to read your emails, now a days encryption is a necessity. Now most major sites are only available on https, and more and more IM are using encryption. But what about and old protocol email that is still very popular and we cant go without it any more. How can we increase security for this?

Of course you can use S/MIME or PGP and have end to end encryption, but the problem that in transit between mail servers the from, to, cc, and subject fields are not encrypted. For this we can use Transport Layer Security (TLS) encryption between the smtp servers. Now in June 2018 from Google's perspective 89% outbound mails and 88% inbound mails are using encryption.

In this post I will show how I setup a smtp server running Postfix with TLS encryption and with the correct cyphers. So that email between smtp servers where possible is using strong email encryption.

Postfix mail daemon

First you need to know that postfix has separate mail daemons for handling different flow of mail. And each daemon is configured separately. So it is possible to accept weak ciphers but you only use strong ciphers when delivering mail to the out side.

The two that are responsible for handling mail in and out from the world are:

smtpd - The SMTP daemon process for handling incoming mail and delivering to the appropriate internal location.

smtp - The SMTP daemon process for delivering mail out to the world.

Default config test

Lets see first how good this default config is for incoming mail to the smtpd daemon. Normally I would test it with SSLLABS sadly this only can check https can't check smtp/STARTTLS. A alternative is htbridge but we will use this later. There is also a shellscript self hosted tool on which can check your SSL/TLS settings and vulnerabilities of your mail server.

To test with testssl run the following after installing.

~>./ -t smtp localhost:25

Below is a summery of the issues with the default postfix config on Ubuntu 16.04.

Lets see how we can fix these issues.

Trusted certificate

While it is not mandatory for mailserver to have a trusted certificate, now a day's it is easy and free to get one from LetsEncrypt. So request one and use it for Postfix. Make sure you use the fullchain, so that intermediates in the chain are also sent.

smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

What about a client certificate for the smtp daemon? For this the readme from postfix is very clear

Do not configure Postfix SMTP client certificates unless you must present client TLS certificates to one or more servers. Client certificates are not usually needed, and can cause problems in configurations that work well without them. The recommended setting is to let the defaults stand:

Disable SSL,TLSv1

After that we disable all SSL and TLSv1, allow only high ciphers for both smtp and smtpd. This will mitigate BEAST. And allow only high ciphers. And we want to negotiate the strongest available cipher available with the remote server.

smtpd_tls_protocols = TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_protocols = TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_ciphers = high
smtpd_tls_ciphers = high
smtpd_tls_mandatory_protocols = TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_mandatory_protocols = TLSv1.2, TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_mandatory_ciphers = high
smtpd_tls_mandatory_ciphers = high
Disable deprecated ciphers

And exclude some deprecated not so secure ciphers.

smtpd_tls_mandatory_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
smtpd_tls_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
smtp_tls_mandatory_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
smtp_tls_exclude_ciphers = MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL
tls_preempt_cipherlist = yes
Use opportunistic encryption

With mailserver we want to use opportunistic encryption. We don't force encryption, If we do so this sounds secure but not all other mail servers supports encryption. So worse case scenario you will not receive from some other mail servers or be able to sent to some other mail server that dont support TLS.

This is also stated in RFC2487

A publicly-referenced SMTP server MUST NOT require use of the STARTTLS extension in order to deliver mail locally. This rule prevents the STARTTLS extension from damaging the interoperability of the Internet's SMTP infrastructure.

To set oppertunistic encryption enable the following settings.

smtpd_tls_security_level = may
smtp_tls_security_level = may

Quoted from

At the "may" TLS security level, TLS encryption is opportunistic. The SMTP transaction is encrypted if the STARTTLS ESMTP feature is supported by the server. Otherwise, messages are sent in the clear. Opportunistic TLS can be configured by setting "smtp_tls_security_level = may".

With this, the Postfix SMTP server announces STARTTLS support to remote SMTP clients, but does not require that clients use TLS encryption.

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.

We could also validate remote certificates for the smtp daemon with verify or secure like you would normal do with https in a browser, but with a mail server this is not common since the majority of them will fail validation due to poor setup. So you will lose emails if you use this.

With these settings we are still susceptible for a downgrade attack. This because is email has been invented in 1982 and SSL/TLS in 1999 so security needed to be adopted to an existing protocol to maintain backward compatibility. And we still want to be able to send and receive emails from legacy or poorly configured servers.

Update June 2018
There are some options coming to solve these issues. Like mta-sts or a startssl policy list. But these are still very new and not broadly supported yet. Maybe an other time I make a post about these.

Test new config

After these settings, and you restart postfix and check again with, all issue's reported earlier are gone. except for the following one.

Secure Client-Initiated Renegotiation VULNERABLE (NOT ok), potential DoS threat

The impact of TLS-based attacks on SMTP should not be over-stated. Presently, most SMTP clients don't verify the TLS certificates of SMTP servers. Such clients are already vulnerable to ordinary man-in-the-middle attacks, and TLS renegotiation introduces no new threats for them.

The Postfix SMTP server with OpenSSL is not affected by the TLS renegotiation attack that redirects and modifies SMTP mail, due to accidental details of the Postfix and OpenSSL implementations.


An other tool you can test online with is from these can also check mailservers, make sure you use :25 at the end of your hostname. With the above SSL/TLS settings for postfix you get an A. If you are using this site, make sure to hit refresh after you changed your postfix config or else you will get cached results.

htbridge will give the following warning. This is due to the fact that postfix doesn't support OCSP stapling. So we can not do anything about this, so we will ignore this.


Check the logs / headers if it is working

How do I know when mail is delivered over TLS, you can ook in the
mail logs. But before this is logged, you need to enable the tls log level.

smtpd_tls_loglevel = 2
smtp_tls_loglevel = 2

After that you will see something like this for an incoming mail daemon smtpd, in this case from google/gmail.

Aug  4 18:58:41 mail postfix/smtpd[18454]: setting up TLS connection from[]
Aug  4 18:58:41 mail postfix/smtpd[18454]:[]: TLS cipher list "aNULL:-aNULL:HIGH:@STRENGTH:!MD5:!DES:!ADH:!RC4:!PSD:!SRP:!3DES:!eNULL:!aNULL"
Aug  4 18:58:41 mail postfix/smtpd[18454]:[]: Issuing session ticket, key expiration: 1501874441
Aug  4 18:58:41 mail postfix/smtpd[18454]: Anonymous TLS connection established from[]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)

And for an outgoing mail using the smtp daemon.

Aug  4 19:19:02 mail postfix/smtp[18987]: setting up TLS connection to[]:25
Aug  4 19:19:02 mail postfix/smtp[18987]:[]:25: TLS cipher list "aNULL:-aNULL:HIGH:@STRENGTH:!MD5:!DES:!ADH:!RC4:!PSD:!SRP:!3DES:!eNULL:!aNULL"
Aug  4 19:19:02 mail postfix/smtp[18987]:[]:25: depth=2 verify=0 subject=/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
Aug  4 19:19:02 mail postfix/smtp[18987]:[]:25: depth=1 verify=1 subject=/C=US/O=Google Inc/CN=Google Internet Authority G2
Aug  4 19:19:02 mail postfix/smtp[18987]:[]:25: depth=0 verify=1 subject=/C=US/ST=California/L=Mountain View/O=Google Inc/
Aug  4 19:19:02 mail postfix/smtp[18987]:[]:25:, issuer_CN=Google Internet Authority G2, fingerprint=05:DF:99:DD:61:DA:84:5C:77:EF:5B:72:5D:05:B1:52, pkey_fingerprint=EC:A8:0A:1E:05:F2:51:48:B5:DC:1C:A2:78:5E:ED:DE
Aug  4 19:19:02 mail postfix/smtp[18987]: Untrusted TLS connection established to[]:25: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)

If you want the information in the email headers you can enable the following option.

smtpd_tls_received_header = yes

Then if you view the headers of the email message you will see wich ciphers was used for this connection.

Received: from ( [])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)

After implementing these settings, your mailserver will exchange emails with other email server using high 'secure' encryption if possible.