Postfix: Enforce sending encrypted e-mails with TLS (smtp over TLS)

Written by - 1 comments

Published on - Listed in Linux Internet Mail


By default, Postfix does not encrypt outgoing e-mails. In case of a man-in-the-middle-attacks, this can be a security issue.

By setting the following parameter in /etc/postfix/main.cf, all outgoing e-mails (to any destination) will be encrypted with TLS:

smtp_tls_security_level = encrypt

But this brings another problem: Many mail servers do not accept TLS connections. E-mails to such mail servers will therefore not be sent.
As an alternative, one can set smtp_tls_security_level = may - with this setting, TLS encryption is only used, if the recipient server accepts TLS connections.

In some circumstances, it is necessary to enforce certain TLS connections to specific domains. That's what I had to do today.
While looking through the Postfix documentation, I got aware of the TLS Policy Table. This setting allows to define TLS connections on a per-domain basis.

Example: One wants to enforce TLS on all e-mails sent to *@example.com. The MX of example.com is receive.example.com.

First, create the tls_policy file and enter the specific domain followed by the TLS option. Then create the hash database of that file:

# touch /etc/postfix/tls_policy

# echo "example.com                 encrypt" > /etc/postfix/tls_policy

# postmap /etc/postfix/tls_policy

Now you need to tell Postfix to use a TLS Policy Table. You define that in /etc/postfix/main.cf:

# cat /etc/postfix/main.cf | grep tls_policy
smtp_tls_policy_maps = hash:/etc/postfix/tls_policy

Reload Postfix (restart is not necessary), to use TLS Policy Table:

# /etc/init.d/postfix reload

Let's see how it looks in the logs, when Postfix sends an e-mail (debug_peer activated).

LOG OUTPUT WITHOUT TLS:

postfix/pickup[28256]: 4CAEB11560005: uid=0 from=
postfix/cleanup[28257]: 4CAEB11560005: message-id=<20120803074914.4CAEB11560005@send.example.com>
postfix/qmgr[28259]: 4CAEB11560005: from=, size=330, nrcpt=1 (queue active)
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 220 area-1.ch ESMTP Postfix (Debian/GNU)
postfix/smtp[28260]: > send.example.com[192.168.10.20]:25: EHLO send.example.com
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250-area-1.ch
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250-PIPELINING
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250-SIZE 36700160
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250-VRFY
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250-ETRN
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250-STARTTLS
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250-AUTH PLAIN LOGIN
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250-ENHANCEDSTATUSCODES
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250-8BITMIME
postfix/smtp[28260]: < receive.example.com[192.168.10.10]:25: 250 DSN
postfix/smtp[28260]: server features: 0x901f size 36700160       
postfix/smtp[28260]: Using ESMTP PIPELINING, TCP send buffer size is 4096
postfix/smtp[28260]: > send.example.com[192.168.10.20]:25: MAIL FROM: SIZE=330
...

LOG OUTPUT WITH TLS:

postfix/pickup[28066]: 4057311560005: uid=0 from=
postfix/cleanup[28067]: 4057311560005: message-id=<20120803074748.4057311560005@send.example.com>
postfix/qmgr[28069]: 4057311560005: from=, size=330, nrcpt=1 (queue active)
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 220 area-1.ch ESMTP Postfix (Debian/GNU)
postfix/smtp[28070]: > send.example.com[192.168.10.20]:25: EHLO send.example.com
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250-area-1.ch
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250-PIPELINING
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250-SIZE 36700160
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250-VRFY
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250-ETRN
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250-STARTTLS
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250-AUTH PLAIN LOGIN
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250-ENHANCEDSTATUSCODES
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250-8BITMIME
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 250 DSN
postfix/smtp[28070]: server features: 0x901f size 36700160
postfix/smtp[28070]: Using ESMTP PIPELINING, TCP send buffer size is 4096
postfix/smtp[28070]: > send.example.com[192.168.10.20]:25: STARTTLS
postfix/smtp[28070]: < receive.example.com[192.168.10.10]:25: 220 2.0.0 Ready to start TLS
postfix/smtp[28070]: send attr request = lookup
postfix/smtp[28070]: send attr cache_type = smtp
postfix/smtp[28070]: send attr cache_id = smtp:192.168.10.10:25:area-1.ch&p=1&c=ALL:!EXPORT:!LOW:+RC4:@STRENGTH:!eNULL
postfix/smtp[28070]: private/tlsmgr: wanted attribute: status
...

Note that the sending server "tells" the recipient server (area-1.ch) to use TLS (STARTTLS) and area-1.ch confirms. This is then followed by the TLS encryption itself.

As I've defined "encrypt" as TLS option, this means, that TLS is enforced and all server certificates of the recipient server are accepted, including self-signed certificates.

If you're suspicious, you can set the TLS option to the highest value: secure. With secure, the server certificate on the recipient side MUST be verified by a known Certificate Issuer (e.g. VeriSign), otherwise the mail will not be sent and will stay in the mail queue:

...
postfix/smtp[28515]: input attribute value: z0FpDdCLPEJc225tMd0BI5CHP28PkTUD36/TT+YU5bI=
postfix/smtp[28515]: private/tlsmgr: wanted attribute: (list terminator)
postfix/smtp[28515]: input attribute name: (end)
postfix/smtp[28515]: certificate verification failed for receive.example.com[192.168.10.10]:25: untrusted issuer /C=CH/ST=Geneva /L=Geneva/O=Claudio Kuenzler/OU=Claudio Kuenzler/CN=receive.example.com
postfix/smtp[28515]: send attr request = update
postfix/smtp[28515]: send attr cache_type = smtp
postfix/smtp[28515]: send attr session = [data 1712 bytes]
...

# mailq
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
5626511560005      330 Fri Aug  3 09:50:15  root@send.example.com 
                                              (Server certificate not trusted)
                                         recipient@receive.example.com


Add a comment

Show form to leave a comment

Comments (newest first)

Sebastian from Germany wrote on Dec 1st, 2015:

Thanks, it works well but I needed to add the domain from "tls_policy" to "transport" file to get it to work. Otherwise postfix sends all mails to our standard relay host.


RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Office   OpenSearch   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder