How to secure your Linux email services with SSL/TLS

Protect your Linux email services by understanding security certificates.
106 readers like this.

Traditionally, email services send data in an unprotected way—whether you are sending emails via SMTP or receiving them via IMAP or POP, the defaults are in cleartext. With more online applications enforcing encryption and the general consensus to protect your data, it's best to secure your email services with a Secure Sockets Layer/Transport Layer Security (SSL/TLS) security certificate.

First, a quick review of email services and protocols. Email is sent via a service called Simple Mail Transport Protocol (SMTP) using TCP port 25. This protocol sends emails from server to server based on DNS mail exchanger (MX) record lookups. Once an email is on the email server, it is retrieved using one of two services: Internet Message Access Protocol (IMAP) using port TCP 143, or Post Office Protocol (POP3) using port TCP 110. All of these services, by default, send your email and authentication to/from these services in plain text—thus, it's very unprotected!

To protect the email data and authentication, these services have added a security feature in which they can utilize an SSL/TLS certificate to wrap the data flow and communication with encryption. How SSL/TLS encryption secures information is beyond the scope of this article, but Bryant Son's internet security article covers it in great detail. At a high level, SSL/TLS encryption is a public/private encryption algorithm.

By adding these security features into the services, they can listen on new TCP ports:

Service Default TCP Port SSL/TLS Port
SMTP 25 587
IMAP 143 993
POP3 110 995

Generate SSL/TLS certificates

SSL/TLS certificates can be generated for free using tools like OpenSSL, or they can be purchased for a range of prices from public certificate authorities (CAs). In the past, generating your own certificate was easy and worked in most cases, but with the increasing demand for better security, most email clients don't trust self-generated SSL/TLS certificates without a manual exception.

If your use case is private or for testing, then saving money with a self-generated certificate makes sense. But if you're rolling this out to a large group or have paying customers, then you're better served by purchasing a certificate from a public, trusted company that sells them.

In either case, the process to start requesting a new certificate is to use the OpenSSL tooling on your Linux system to create a certificate signing request (CSR):

$ openssl req -new -newkey rsa:2048 -nodes -keyout mail.mydomain.key -out mail.mydomain.csr

This command will create a new CSR and private key at the same time for the service you are trying to secure. The process will ask you a number of questions associated with the certificate: location details, server fully qualified domain name (FQDN), email contact information, etc. Once you have filled out the information, the key and CSR will be generated.

If you generate your own certificate

If you want to generate your own certificate, you must create your own root CA before issuing the CSR command above. You can create your own root CA with:

$ openssl genrsa -des3 -out myCA.key 2048

It will prompt you to add a passphrase. Please give it a secure passphrase and don't lose it—this is your private root CA key, and as the name states, it's the root of all trust in your certificates.

Next, generate the root CA certificate:

$ openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem

After answering a few more questions, you will generate a root CA certificate with a five-year lifespan.

Using the CSR file from the steps above, you can request a new certificate to be generated and signed by the root CA you just created:

$ openssl x509 -req -in mail.mydomain.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out mail.mydomain.pem -days 1825 -sha256

Enter your private root CA key passphrase to create and sign the certificate.

Now you have the two files needed to configure your email services for enhanced security: the private key file, mail.mydomain.key, and the public certificate file, mail.mydomain.pem.

If you purchase a certificate

If you purchase a certificate from a vendor, it will ask you to upload that CSR to its system, as it is used as the input to generate the SSL/TLS certificate. The certificate will be accessible as a file (such as mail.mydomain.pem). Many SSL vendors also require you to download an intermediate certificate. If this is the case, you must combine the two certificate files into one, so the email service can process them both in combination. You can combine your certificate with a third-party intermediate certificate with:

$ cat mail.mydomain.pem gd_bundle-g2-g1.crt > mail.mydomain.pem

Notice that the output's file extension is .pem, which stands for Privacy-Enhanced Mail.

Now you have the two files you need to configure your email services for enhanced security: the private key file, mail.mydomain.key, and the public combined certificate file, mail.mydomain.pem.

Create a safe directory for your files

Whether you created your own key or bought one from a vendor, create a safe, root-owned directory for the two files you created above. An example workflow to create a safe play would be:

$ mkdir /etc/pki/tls
$ chown root:root /etc/pki/tls
$ chmod 700 /etc/pki/tls

Make sure to set the permissions on your files after you copy them into /etc/pki/tls with:

$ chmod 600 /etc/pki/tls/*

Configure your SMTP and IMAP services

Next, configure both the SMTP and the IMAP services to use the new security certificates. The programs used in this example for SMTP and IMAP are postfix and dovecot.

Edit /etc/postfix/ in your preferred text editor. Add the following lines:

smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/pki/tls/mail.mydomain.pem
smtpd_tls_key_file = /etc/pki/tls/mail.mydomain.key

Customize your config

The following options allow you to disable/enable different ciphers, protocols, etc.:

smtpd_tls_eecdh_grade = strong
smtpd_tls_protocols= !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_protocols= !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_ciphers = high
smtpd_tls_ciphers = high
tls_preempt_cipherlist = yes
smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5 , DES, ADH, RC4, PSD, SRP, 3DES, eNULL
smtpd_tls_exclude_ciphers = aNULL, MD5 , DES, ADH, RC4, PSD, SRP, 3DES, eNULL
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1

Edit /etc/dovecot/dovecot.conf by adding these three lines:

ssl = required
ssl_cert = </etc/pki/tls/mail.mydomain.pem
ssl_key = </etc/pki/tls/mail.mydomain.key

Add the following options to disable/enable different ciphers, protocols, and more (I'll leave understanding and considering these up to you):

ssl_prefer_server_ciphers = yes
ssl_protocols = !SSLv2 !SSLv3 !TLSv1 !TLSv1.1
ssl_min_protocol = TLSv1.2

Set context for SELinux

If your Linux distribution has SELinux enabled, set the correct SELinux context for your new certificate files.

For Postfix SELinux:

$ chcon -u system_u -t cert_t mail.mydomain.*

For Dovecot SELinux:

$ chcon -u system_u -t dovecot_cert_t mail.mydomain.*

Restart both services and connect with your updated email client configurations. Some email clients will auto-detect the new port numbers; others will require you to update them.

Test your setup

Quickly test from the command line with openssl and the s_client plugin:

$ openssl s_client -connect
$ openssl s_client -starttls imap -connect
$ openssl s_client -starttls smtp -connect

These test commands will show a plethora of data about the connection, certificate, cipher, session, and protocol you're using. This is not only a good way to validate that the new configuration is working but also to confirm you're using the appropriate certificate and security settings you defined in the postfix or dovecot configuration files.

Stay secure!

What to read next
User profile image.
Marc is a Principal Solutions Architect helping customers solve complex problems with Open Source software from Red Hat. With over 20 years of experience in the fields of Linux, Security and Networking, Marc can successfully and knowledgeably help his customers.


Nice article, but I am puzzled why there is. I mention of Let’s Encrypt and the ACME protocol, that would have made the article a much better read IMHO.

Great article Marc!

I just want to point out that "smtpd_tls_security_level=may" does not enforce TLS encryption.

Unfortunately there's still no guarantees that all the servers through which our messages will pass are safe (even if they use encryption), so at the moment the only way to stay confidential is end-to-end encryption (such as GPG, S/MIME, etc.).

Also, for private users I would suggest Let's Encrypt free certificates that nowadays are trusted by the majority of clients.

Note that the command given to create a combined .pem file will destroy mail.mydomain.pem.

$ cat mail.mydomain.pem gd_bundle-g2-g1.crt > mail.mydomain.pem

The shell will FIRST open and truncate mail.mydomain.pem, before it executes the cat command. So the end result will be the same as if you had simply copied gd_bundle-g2-g1.crt over the .pem file - the original contents of mail.mydomain.pem are lost.

The solution is to use a different name for the output file. :-)

Good catch! Yes, it should be your vendor.pem file catted/combined with the intermediate cert file.

$ cat vendor.pem gd_bundle-g2-g1.crt > mail.mydomain.pem

In reply to by Bjarni (not verified)

Hello Marc!
Definitely an informative article! Finally i got the right solution to secure Linux email services with the help of SSL.
Thanks a lot man.'Keep it up

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.