Postfix SMTP Connection Lost After STARTTLS: Debugging and Fixing the TLS Handshake Issue


23 views

When examining Postfix logs showing successful TLS initiation but immediate disconnection (with messages like lost connection after STARTTLS), we need to verify several configuration points:

# Check Postfix SMTPD TLS settings in main.cf:
smtpd_tls_security_level = may
smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes

For Rails applications using ActionMailer, ensure proper TLS settings:

# config/environments/production.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address: "localhost",
  port: 25,
  domain: "yourdomain.com",
  enable_starttls: :auto,  # Important for TLS negotiation
  openssl_verify_mode: 'none' # Temporary for debugging
}
  • Mismatched TLS protocols between client and server
  • Certificate verification failures
  • Network-level interruptions (firewalls, IDS systems)
  • Incomplete SSL/TLS library installations

Use openssl s_client to test the TLS handshake manually:

openssl s_client -starttls smtp -connect localhost:25 -debug

This helps identify exactly where the handshake fails. Match the output with your Postfix logs for correlation.

Verify these critical parameters in /etc/postfix/master.cf:

smtp      inet  n       -       y       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject

The log sequence shows a classic case where TLS handshake succeeds but the connection terminates immediately after STARTTLS negotiation. The key indicators:

Anonymous TLS connection established [...] lost connection after STARTTLS

When this occurs on localhost connections (127.0.0.1), these are the most likely suspects:

  1. SSL/TLS version mismatch between Postfix and Rails ActionMailer
  2. Certificate verification failures despite anonymous connection
  3. Courier-imap compatibility issues with modern TLS

First, verify your Postfix TLS settings in main.cf:

smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_tls_loglevel = 1

The critical setting in your Rails config/environments/production.rb:

config.action_mailer.smtp_settings = {
  address: "localhost",
  port: 25,
  enable_starttls_auto: true,
  openssl_verify_mode: 'none', # Temporary for debugging
  tls: true
}

Test the SMTP connection manually using OpenSSL:

openssl s_client -connect localhost:25 -starttls smtp -debug

Check Courier's SSL support with:

courier-pop3d -help | grep SSL

For development environments, you might need to either:

  • Generate proper self-signed certificates with SAN for localhost
  • Disable certificate verification temporarily with:
Postfix: smtpd_tls_received_header = yes
Rails: openssl_verify_mode: 'none'

If using older systems, explicitly set TLS v1.2 in Postfix:

smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
smtpd_tls_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1