As some initiatives (like Let's Encrypt as one example) try to force TLS usage everywhere. We thought about doing the same for the CentOS.org infra. Obviously we already had some x509 certificates, but not for every httpd server that was serving content for CentOS users. So we decided to enforce TLS usage on those servers. But TLS can be used obviously on other things than a web server.

That's why we considered implementing something for our Postfix nodes. The interesting part is that it's really easy (depending of course at the security level one may want to reach/use). There are two parts in the postfix main.cf that can be configured :

  • outgoing mails (aka your server sends mail to other SMTPD servers)
  • incoming mails (aka remote clients/servers send mail to your postfix/smtpd server)

Let's start with the client/outgoing part : just adding those lines in your main.cf will automatically configure it to use TLS when possible, but otherwise fall back on clear if remote server doesn't support TLS :

# TLS - client part
smtp_tls_CAfile=/etc/pki/tls/certs/ca-bundle.crt
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache 

The interesting part is the smtp_tls_security_level option : as you see, we decided to force it to may . That's what Postfix official TLS documentation calls "Opportunistic TLS" : in some words it will try TLS (even with untrusted remote certs !) and will only default to clear if no remote TLS support is available. That's the option we decided to use as it doesn't break anything, and even if the remote server has a self-signed cert, it's still better to use TLS with self-signed than clear text, right ?

Once you have reloaded your postfix configuration, you'll directly see in your maillog that it will start trying TLS and deliver mails to servers configured for it :

Sep  3 07:50:37 mailsrv postfix/smtp[1936]: setting up TLS connection to ASPMX.L.GOOGLE.com[173.194.207.27]:25
Sep  3 07:50:37 mailsrv postfix/smtp[1936]: Trusted TLS connection established to ASPMX.L.GOOGLE.com[173.194.207.27]:25: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)
Sep  3 07:50:37 mailsrv postfix/smtp[1936]: DF584A00774: to=<>, orig_to=<>, relay=ASPMX.L.GOOGLE.com[173.194.207.27]:25, delay=1, delays=0/0.12/0.22/0.71, dsn=2.0.0, status=sent (250 2.0.0 OK 1441266639 79si29025652qku.67 - gsmtp)

Now let's have a look at the other part : when you want your server to present the STARTTLS feature when remote servers/clients try to send you mails (still in postfix main.cf) :

# TLS - server part
smtpd_tls_CAfile=/etc/pki/tls/certs/ca-bundle.crt
smtpd_tls_cert_file = /etc/pki/tls/certs/<%= postfix_myhostname %>-postfix.crt 
smtpd_tls_key_file = /etc/pki/tls/private/<%= postfix_myhostname %>.key
smtpd_tls_security_level = may
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache

Still easy, but here we also add our key/cert to the config but if you decide to use a signed by a trusted CA cert (like we do for centos.org infra), be sure that the cert is the concatenated/bundled version of both your cert and the CAChain cert. That's also documented in the Postfix TLS guide, and if you're already using Nginx, you already know what I'm talking about as you already have to do it too.

If you've correctly configured your cert/keys and reloaded your postfix config, now remote SMTPD servers will also (if configured to do so) deliver mails to your server through TLS. Bonus point if you're using a cert signed by a trusted CA, as from a client side you'll see this :

Sep  2 16:17:22 hoth postfix/smtp[15329]: setting up TLS connection to mail.centos.org[72.26.200.203]:25
Sep  2 16:17:22 hoth postfix/smtp[15329]: Trusted TLS connection established to mail.centos.org[72.26.200.203]:25: TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Sep  2 16:17:23 hoth postfix/smtp[15329]: CC8351C00C9: to=<fake_one_for_blog_post@centos.org>, relay=mail.centos.org[72.26.200.203]:25, delay=1.6, delays=0.19/0.03/1.1/0.31, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as A7299A006E2)

The Trusted TLS connection established part shows that your smtpd server presents a correct cert (bundle) and that the remote server sending you mails trusts the CA used to sign that cert.

There are a lot of TLS options that you can also add for tuning/security reasons, and all can be seen through postconf |grep tls, but also on the Postfix postconf doc