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

Symfony2 SecurityBundle and FOSUserBundle integration: How does it work?

Overview A couple of days ago, I realized I needed to add some new functionality to the login process. Specifically, I needed to track all previous login attempts. Not knowing anything about the new Symfony2 SecurityBundle, I had to go through the underlying code to understand what was going on. In the process, I think got a basic idea about how the new SecurityBundle interacts with FOSUserBundle. Configuration I have a basic security configuration as illustrated below. app/config/security.yml security: encoders: Symfony\Component\Security\Core\User\User: plaintext role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: ROLE_ADMIN providers: fos_userbundle: id: fos_user.user_manager firewalls: main: pattern: .* form_login: provider: fos_userbundle check_path: /user/login_check login_path: /user/login lo...