Skip to main content

Securing Postfix and Dovecot with TLS

SSL/TLS vs STARTTLS

This seemed to be confusing at first but here is what it boils down to:

With STARTTLS, an existing TCP connection is upgraded to an encrypted one after the SMTP handshake. On the other hand, with SSL/TLS, an ecnrypted connection is negiotiated right away before an SMTP handshake takes place. In other words, STARTTLS is "TLS inside SMTP", while SSL/TLS is "SMTP inside TLS".

See this page for more information.

Another important difference between these two schemes is that STARTTLS does not require a separate port. You can continue to use the same smtp (25) or imap (143) port. SSL/TLS on the other hand requires separate smtp (465) and imap (993) ports.

Setup

I wanted to implement a STARTTLS scheme; however, I decided to revert back to SSL/TLS due to:

1. I am running Dovecot dovecot-1.0.7 on CentOS release 5.5. Unfortunately for me, I was not able to require SSL connections since the "ssl = required" configuration option is not available until v1.2+. WIthout this I could not force TLS for non-plaintext authentication.
[http://wiki.dovecot.org/SSL/DovecotConfiguration]

2. Outlook related issues described here.

SSL/TLS

Securing Postfix
The "smtpd_tls_wrappermode=yes" argument disables STARTTLS and enables SSL/TLS. It basically overrides the "smtpd_tls_security_level" flag inside /etc/postfix/main.cf. One thing to remember is that, you are not supposed to put this flag inside main.cf; it needs to be inside master.conf.
/etc/postfix/master.cf
smtp      inet  n       -       n       -       -       smtpd
smtps     inet  n       -       n       -       -       smtpd -o smtpd_tls_wrappermode=yes 
Since we are using the smtps service, we need to punch a hole in our firewall for port 465.
/etc/postfix/main.cf
smtpd_tls_cert_file = /etc/pki/tls/certs/mail.crt
smtpd_tls_key_file = /etc/pki/tls/private/mail.key
smtpd_tls_CAfile = /etc/pki/tls/certs/ca.crt
smtpd_tls_loglevel = 1
smtpd_tls_received_header = no
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_session_cache_timeout = 3600s
Testing
openssl s_client -tls1 -crlf -connect mail.domain.com:465
Securing Dovecot
/etc/dovecot.conf
protocols = imaps # we need to open port 993 for this

disable_plaintext_auth = yes # Allows plaintext authentication only when SSL/TLS is used first.
ssl = required # v1.2+ only. Requires SSL/TLS also for non-plaintext authentication. 

ssl_cert_file = /etc/pki/tls/certs/mail.crt
ssl_key_file = /etc/pki/tls/private/mail.key
Testing Dovecot setup:
openssl s_client -tls1 -crlf -connect mail.domain.com:993

STARTTLS

Securing Postfix
/etc/postfix/master.cf
smtp      inet  n       -       n       -       -       smtpd
#submission inet n       -       n       -       -       smtpd
As described previously, we can use an existing port with STARTTLS. Since we are using the usual smtp service, we need to punch a hole in our firewall for port 25. One other option is to use the submission service on port 587 to bypass ISP blocks.
/etc/postfix/main.cf
smtpd_tls_cert_file = /etc/pki/tls/certs/mail.crt
smtpd_tls_key_file = /etc/pki/tls/private/mail.key
smtpd_tls_CAfile = /etc/pki/tls/certs/ca.crt
smtpd_tls_loglevel = 1
smtpd_tls_received_header = no
smtpd_tls_security_level = encrypt # This setting requires STARTTLS
smtpd_tls_auth_only = yes
smtpd_tls_session_cache_timeout = 3600s
If you are using a Postfix version older than v2.3, see smtpd_enforce_tls flag.

Testing
openssl s_client -starttls smtp -crlf -connect mail.domain.com:25
Securing Dovecot
/etc/dovecot.conf
protocols = imap # No need for a separate port. We will stick with port 143.

disable_plaintext_auth = yes # Allows plaintext authentication only when SSL/TLS is used first.
ssl = required # v1.2+ only. Requires SSL/TLS also for non-plaintext authentication. 

ssl_cert_file = /etc/pki/tls/certs/mail.crt
ssl_key_file = /etc/pki/tls/private/mail.key
Testing Dovecot setup:
openssl s_client -starttls imap -crlf -connect mail.domain.com:143

Comments

Popular posts from this blog

Securing Symfony2 REST services with FOSOAuthServerBundle

Overview In my previous article, I wrote about setting up a Symfony2 REST service using FOSRestBundle. However, this REST service was behind a firewall protected by a generic form_login provider. Not really ideal if you wish to open your REST API to other applications. So in this article, I will try to explain how to set up FOSOAuthServerBundle to protect your REST API methods using OAuth2. Before we start getting into the gritty details, it is a good idea to have a look at the official OAuth2 documentation . Let's begin... FOSOAuthServerBundle Installation You have to install v1.1.0 of FOSOAuthServerBundle if you are using Symfony 2.0.x. If not, see the docs . First, add the following entries to your deps file: [FOSOAuthServerBundle] git=git://github.com/FriendsOfSymfony/FOSOAuthServerBundle.git target=bundles/FOS/OAuthServerBundle version=origin/1.1.x [oauth2-php] git=git://github.com/FriendsOfSymfony/oauth2-php.git Run the vendors script to install these...

Unexpected token "name" of value "if" ("end of statement block" expected) in "WebProfilerBundle:Collector:logger.html.twig"

Encountered this WebProfilerBundle error message when I ran the bin/vendors script to update my Symfony2 bundles. Make sure your deps file is up to date; you need to pay special attention to your version values. In this case, update your twig version to v1.2.0 as illustrated below: [twig] git=http://github.com/fabpot/Twig.git version=v1.2.0 Run the vendors script to update your bundle and the error message should disappear. You can get the most up to date deps file from the symfony-standard repository located at: https://github.com/symfony/symfony-standard/blob/master/deps

A Parcelable Tutorial for Android

Parcelable Interface Overview In one of my earlier posts, I mentioned writing an article about FOSOAuthBundle integration with an Android client. To keep that article to the point, I need to explain some concepts beforehand. One of the important concepts is the Android Parcelable interface that allows data to be transferred between different processes/threads. Certain network operations with Android such as authentication with OAuth2 and then fetching data from a REST endpoint should be performed in the background in order not to block the UI thread. This requires data to be fetched by a service (I have opted for Intent Services in my implementation) in the background and then passed back to the calling activity/fragment with a result callback. This is where the Parcelable interface comes into play. Basically, the Parcelable interface allows your classes to be flattened inside a message container called a Parcel to facilitate high performance inter process communication. The rece...