Enabling SSL/TLS for Postfix (Submission) and Dovecot (IMAPS)

Published on February 04, 2025


This tutorial explains how to set up SSL/TLS on a Debian/Ubuntu server for secure email submission (SMTP on port 587) and secure IMAP (IMAPS on port 993). We’ll rely on self-signed certificates for a private network scenario, but we’ll also show how you’d integrate Let’s Encrypt if your domain is accessible online. These steps help ensure that passwords and mail content stay encrypted on the wire.

1. Overview: SSL/TLS Ports in This Setup

We won’t be listening on port 25 for inbound mail from external servers, nor on port 143 for plain IMAP. Instead, we’ll focus on:

  • Port 587 (Submission): Clients submit outgoing mail here using STARTTLS.
  • Port 993 (IMAPS): Fully encrypted IMAP connections for mail retrieval.
  • (Optional) Port 465 (SMTPS): If you want a traditional SSL-wrapped SMTP instead of STARTTLS on 587.

This approach is modern and recommended, especially in an internal lab or small environment where you don’t need full public SMTP.

2. Prerequisites

  1. Postfix and Dovecot are already installed and working (without relying on port 25 or port 143).
  2. You have a hostname or domain, such as mail.smc.lan (either local DNS or real FQDN).
  3. A static IP and a proper DNS record, even if just local or in /etc/hosts.

3. Generating Certificates

3.1 Option A: Self-Signed Certificates

  1. Create a dedicated directory for certificates:
    sudo mkdir -p /etc/ssl/mail
    sudo chmod 700 /etc/ssl/mail
  2. Generate a private key (2048 bits is fine):
    cd /etc/ssl/mail
    sudo openssl genrsa -out mailserver.key 2048
  3. Create a certificate signing request (CSR):
    sudo openssl req -new -key mailserver.key -out mailserver.csr
    Make sure the Common Name (CN) matches your domain (e.g. mail.smc.lan).
  4. Self-sign the certificate (valid ~10 years here):
    sudo openssl x509 -req -days 3650 -in mailserver.csr -signkey mailserver.key -out mailserver.crt
  5. Set permissions:
    sudo chmod 600 mailserver.key
    sudo chmod 644 mailserver.crt
    Only root can read the key.

Note: Self-signed certs will prompt warnings in most mail clients. You can manually trust them on each client if desired.

3.2 Option B: Let’s Encrypt Certificates

If your server is publicly accessible with a real domain, you can use Let’s Encrypt:

  1. Install certbot:
    sudo apt update
    sudo apt install certbot
  2. Obtain the certificate:
    sudo certbot certonly --standalone -d mail.example.com
  3. Certificates usually live in /etc/letsencrypt/live/mail.example.com/:
    • fullchain.pem (public cert)
    • privkey.pem (private key)

4. Configuring Postfix for Secure Submission

We’ll set up Postfix to handle encrypted SMTP submission on port 587, plus an optional port 465 if desired.

4.1 Postfix TLS Settings

In /etc/postfix/main.cf, specify certificate paths and TLS parameters:

# TLS cert/key (self-signed)
smtpd_tls_cert_file = /etc/ssl/mail/mailserver.crt
smtpd_tls_key_file  = /etc/ssl/mail/mailserver.key

# If using Let's Encrypt:
#smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
#smtpd_tls_key_file  = /etc/letsencrypt/live/mail.example.com/privkey.pem

smtpd_use_tls = yes
smtpd_tls_auth_only = yes
smtpd_tls_security_level = may
smtpd_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_ciphers = high
smtpd_tls_loglevel = 1

smtp_tls_security_level = may
smtp_tls_protocols = !SSLv2, !SSLv3
smtp_tls_ciphers = high

smtpd_tls_auth_only = yes ensures login is only allowed under encryption. Setting security_level = may means Postfix offers TLS but doesn’t force it. You could use encrypt if you want to require encryption from clients on your LAN, but be aware that this will break any mail client that doesn’t support TLS.

4.2 Enabling Submission on Port 587

In /etc/postfix/master.cf, find or add the submission service:

submission inet n - y - - smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

This opens port 587, requires TLS (encrypt), and enforces authentication for sending mail. Perfect for mail clients like Thunderbird or Outlook in a local environment.

4.3 (Optional) SMTPS on Port 465

If you prefer port 465 for immediate TLS:

smtps inet n - y - - smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject

Restart Postfix:

sudo systemctl restart postfix

5. Configuring Dovecot for IMAPS (Port 993)

We won’t use IMAP on 143. Instead, we’ll let Dovecot listen securely on 993.

5.1 SSL Settings in Dovecot

Open /etc/dovecot/conf.d/10-ssl.conf and set:

ssl = yes
ssl_cert = </etc/ssl/mail/mailserver.crt
ssl_key  = </etc/ssl/mail/mailserver.key

# Or Let's Encrypt paths:
#ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
#ssl_key  = </etc/letsencrypt/live/mail.example.com/privkey.pem

ssl_protocols = !SSLv2 !SSLv3
ssl_cipher_list = HIGH:!aNULL:!MD5
ssl_prefer_server_ciphers = yes

5.2 Enabling IMAPS on 993

In /etc/dovecot/conf.d/10-master.conf or 20-imap.conf:

protocols = imap

service imap-login {
  inet_listener imaps {
    port = 993
    ssl = yes
  }
  # no inet_listener imap here since we're not using 143
}

Then restart Dovecot:

sudo systemctl restart dovecot

6. Enabling Client Auth via Dovecot

If you want your mail clients to authenticate when sending mail on 587, set up Dovecot’s SASL service. In /etc/dovecot/conf.d/10-auth.conf:

auth_mechanisms = plain login

passdb {
  driver = pam
}

userdb {
  driver = passwd
}

In /etc/dovecot/conf.d/10-master.conf, ensure Dovecot’s auth socket is accessible to Postfix:

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

7. Firewall Configuration

You’ll want to open only the ports needed for SSL/TLS submission and IMAPS. Below are two approaches: UFW (simpler) and iptables (detailed).

7.1 Using UFW

sudo ufw allow 587/tcp     # Submission
sudo ufw allow 465/tcp     # (Optional SMTPS)
sudo ufw allow 993/tcp     # IMAPS
sudo ufw enable

7.2 Using iptables

If you prefer full control, here’s an example set of iptables rules to allow SMTP submission (587), optional SMTPS (465), and IMAPS (993). We’ll also allow SSH (22), then drop everything else. Adjust to your needs.

# 1) Default policies: deny incoming, allow outgoing
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

# 2) Allow loopback traffic
sudo iptables -A INPUT -i lo -j ACCEPT

# 3) Allow established connections to keep working
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 4) Allow SSH (so we don't lock ourselves out)
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 5) Allow Submission (587)
sudo iptables -A INPUT -p tcp --dport 587 -j ACCEPT

# 6) (Optional) Allow SMTPS (465)
sudo iptables -A INPUT -p tcp --dport 465 -j ACCEPT

# 7) Allow IMAPS (993)
sudo iptables -A INPUT -p tcp --dport 993 -j ACCEPT

# 8) Log or drop everything else (optional logging rule shown)
# sudo iptables -A INPUT -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
# Then drop it:
# sudo iptables -A INPUT -j DROP

# 9) Check rules
sudo iptables -L -n -v

# 10) (Optional) Make rules persistent across reboots on Debian/Ubuntu
sudo apt-get install iptables-persistent
sudo netfilter-persistent save
sudo netfilter-persistent reload

This configuration ensures only the essential ports for secure mail and SSH management are open. Everything else is dropped by default.

8. Verifying SSL/TLS

  1. Check Postfix ports:
    sudo netstat -tlnp | grep master
    You should see 587, possibly 465.
  2. Check Dovecot ports:
    sudo netstat -tlnp | grep dovecot
    Look for 993.
  3. Test with OpenSSL:
    openssl s_client -connect mail.smc.lan:587 -starttls smtp
    openssl s_client -connect mail.smc.lan:993
    This shows you certificate details. Type QUIT or A1 LOGOUT to exit.

9. Configuring a Mail Client (e.g., Thunderbird)

  • Incoming (IMAPS):
    • Server: mail.smc.lan
    • Port: 993
    • Security: SSL/TLS
    • Username: your system (or virtual) user, e.g., alice
  • Outgoing (SMTP Submission):
    • Server: mail.smc.lan
    • Port: 587 (or 465 if using SMTPS)
    • Security: STARTTLS (on 587) or SSL/TLS (on 465)
    • Username: same as your email user, e.g., alice
  • If you’re using a self-signed cert, Thunderbird may warn about an untrusted authority. Accept or import it manually if desired.

10. Testing Everything

  1. Send yourself an email from Thunderbird to confirm encryption works.
  2. Check /var/log/mail.log for any errors.
  3. Verify Thunderbird shows a secure (SSL/TLS) connection in Account Settings or status icons.

11. Additional Security Considerations

  • Force Encrypted Auth: We used smtpd_tls_auth_only = yes, so no plaintext auth is allowed.
  • Strong Cipher Suites: Exclude old protocols like SSLv2/3 and limit ciphers to HIGH or similar.
  • Internal CA: If you have a private CA, you can sign your certificate so local clients trust it without warnings.
  • Certificate Renewal: Self-signed certs need manual renewal. Let’s Encrypt auto-renews if you’re public-facing.

Conclusion

By focusing on ports 587 (Submission) and 993 (IMAPS), you can run a secure mail solution without exposing standard SMTP (25) or plain IMAP (143). You’ve learned how to generate certificates, configure Postfix and Dovecot for encrypted connections, open the right firewall ports (with extra detail on iptables), and test everything from both the command line and a mail client. Enjoy your safer, fully encrypted mail system!