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?

A popular internet mail server that I am using regularly is Postfix. How can we setup Postfix to use TLS encryption with correct ciphers, so that email between mail 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 sadly this only can check https can't check smtp/STARTTLS. A alternative is but we will use this later. There is also a cli self hosted tool on which can check your SSL/TLS settings and vulnerabilities.

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. 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.

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.