Securing Email with MTA-STS and TLSRPT

What is MTA-STS (MTA Strict Transport Security)?

MTA-STS is a mechanism that enforces TLS encryption for your email communication. Think of it as HTTP Strict Transport Security (HSTS) for email. By instructing the sending mail server that a secure connection is mandatory, you can effectively mitigate or stop Man-in-the-Middle (MITM) attacks. The official abstract from the RFC puts it best:

SMTP MTA Strict Transport Security (MTA-STS) is a mechanism enabling mail service providers (SPs) to declare their ability to receive Transport Layer Security (TLS) secure SMTP connections and to specify whether sending SMTP servers should refuse to deliver to MX hosts that do not offer TLS with a trusted server certificate.

SMTP MTA Strict Transport Security (MTA-STS). RFC 8461. https://www.rfc-editor.org/rfc/rfc8461.html

In scenarios where DNSSEC isn’t an option, MTA-STS serves as a strong alternative to DANE. However, it’s crucial to understand that without DNSSEC, MTA-STS remains susceptible to downgrade attacks via DNS spoofing. It’s a trade-off worth considering.

What is TLSRPT (TLS Reporting)?

TLSRPT adds a crucial reporting layer to SMTP TLS connections. It’s a standardized way for sending mail servers to report on TLS connection failures, including details about which DANE or MTA-STS policy was in effect. The RFC clearly outlines its purpose:

A number of protocols exist for establishing encrypted channels between SMTP [..]. These protocols can fail due to misconfiguration or active attack, leading to undelivered messages or delivery over unencrypted or unauthenticated channels. This document describes a reporting mechanism and format by which sending systems can share statistics and specific information about potential failures with recipient domains. [..]

SMTP MTA TLS Reporting (TLSRPT). RFC 8460. https://www.rfc-editor.org/rfc/rfc8460.html

This reporting is invaluable for observability and troubleshooting, allowing you to catch misconfigurations before they cause major issues.

Requirements

Setting up MTA-STS and TLSRPT requires a few key components:

  • SSL Certificate: Unlike with DANE, your certificate must be issued by a trusted Certificate Authority. A self-signed certificate won’t work.
  • Webserver: You need a web server to publish the MTA-STS policy file.
  • DNS Control: The ability to add specific DNS records (TXT, A, AAAA) for your mail domains is mandatory.
  • Minimum TLS Version: Your Mail Transfer Agent (MTA) must support at least TLS 1.2.

Hands-on Setup: DNS Records

The first step is configuring the necessary DNS records. It’s important to note that you must add an MTA-STS record for every domain you send mail from, including subdomains. As RFC 8461 specifies, “the policy can be fetched only from ‘mail.example.com’, not ‘example.com’.”

_mta-sts TXT record

This record contains two fields: a version (v=STSv1) and a unique identifier (id=). The id acts like a serial number. Every time you update the policy file, you must change the id value to signal senders that a new policy is available.

Here’s how I manage this using nsupdate with Bind 9.16:

root@ns3:~# nsupdate -l
> zone jeanbruenn.info
> update add _mta-sts.jeanbruenn.info. 3600 IN TXT "v=STSv1; id=202107300200Z"
> send

To simplify administration across multiple domains, I prefer using CNAMEs to point all _mta-sts records to a central domain. This adheres to the “Once and Only Once” (OAOO) principle, which is a core concept of Infrastructure as Code (IaC). It ensures consistency and simplifies future administration. My main mailing domain is no-uce.de, so the process looks like this:

root@ns3:~# nsupdate -l
> zone no-uce.de
> update add _mta-sts.no-uce.de. 3600 IN TXT "v=STSv1; id=202107300200Z"
> send
> # for every domain point it to the mailservers domain
> zone jeanbruenn.info
> update add _mta-sts.jeanbruenn.info. 3600 IN CNAME _mta-sts.no-uce.de
> send

mta-sts A/AAAA record

Since the policy must be served over HTTPS, a DNS record is required to point the hostname to your web server. In my case, I want to centralize the policy on one system with the IP 1.2.3.4:

root@ns3:~# nsupdate -l
> zone no-uce.de
> update add mta-sts.no-uce.de 3600 IN A 1.2.3.4
> send

And again, I use CNAMEs to point other domains to this central policy server.

root@ns3:~# nsupdate -l
> zone jeanbruenn.info
> update add mta-sts.jeanbruenn.info. 3600 CNAME mta-sts.no-uce.de
> send

_smtp._tls TXT record

This record tells other systems where to send TLS reports. While the RFC doesn’t explicitly state whether CNAMEs should be followed, I use them for simplicity. This way, if I ever change the reporting address, I only have to update it in one place.

root@ns3:~# nsupdate -l
> zone no-uce.de
> update add _smtp._tls.no-uce.de 3600 IN TXT "v=TLSRPTv1; rua=mailto:himself@jeanbruenn.info"
> zone jeanbruenn.info
> update add _smtp._tls.jeanbruenn.info 3600 CNAME _smtp._tls.no-uce.de
> send

Configuring the Webserver & Policy

Next, we configure the web server to host the policy file. According to the RFC, your server must be able to respond to requests for mta-sts.yourdomain.com with a valid SSL certificate that covers all policy domains.

NGINX Configuration

It’s often practical to set up the server block without SSL first to obtain your Let’s Encrypt certificates. The key is to ensure the server_name directive includes all of your MTA-STS hostnames.

server {
	listen 80;
	listen [::]:80;
	listen 443 ssl;
	listen [::]:443 ssl;
        ssl_certificate /etc/letsencrypt/live/mta-sts.no-uce.de/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/mta-sts.no-uce.de/privkey.pem;
	root /var/www/mta-sts;
	index index.html index.htm index.nginx-debian.html;

	server_name mta-sts.no-uce.de
                    mta-sts.jeanbruenn.info;

	location / {
		try_files $uri $uri/ =404;
	}
}

The Policy File

The policy is a simple text file located at /.well-known/mta-sts.txt.

root@mail:/var/www/mta-sts/.well-known# cat mta-sts.txt 
version: STSv1
mode: enforce
max_age: 2419200
mx: mail.no-uce.de

The mode can be set to testing to get reports without enforcing the policy, or enforce to fully activate it. I use 28 days for max_age, which is specified in seconds.

The Second Half: Verifying Incoming Mail

Setting up the public-facing policy is only half the battle. The second, more complex part is configuring your MTA to verify the policies of incoming mail.

I chose the postfix-mta-sts-resolver for Postfix, which does exactly this. It’s a promising solution, but a key point to remember is that it may override DANE if you have both configured.

First, install the necessary dependencies:

apt-get install python3-pip
python3 -m pip install postfix-mta-sts-resolver

Next, configure your Postfix main.cf to use the resolver:

smtp_tls_policy_maps = socketmap:inet:127.0.0.1:8461:postfix

My mta-sts-daemon.yml configuration is straightforward:

root@mail:/etc/systemd/system# cat /etc/mta-sts-daemon.yml 
host: 127.0.0.1
port: 8461
reuse_port: true
shutdown_timeout: 20
cache:
  type: internal
  options:
    cache_size: 10000
proactive_policy_fetching:
  enabled: true
default_zone:
  strict_testing: false
  timeout: 4

Validation and Conclusion: The Infrastructure as Code Approach

To verify your setup, you can use a public validator; there are several available. I also monitor TLS reports to ensure everything is working as expected.

A report I received by google while I was testing and playing around with MTA-STS and TLSRPT:

{
   "organization-name":"Google Inc.",
   "date-range":
   {
      "start-datetime":"2021-07-29T00:00:00Z",
      "end-datetime":"2021-07-29T23:59:59Z"
   },
   "contact-info":"smtp-tls-reporting@google.com",
   "report-id":"2021-07-29T00:00:00Z_no-uce.de",
   "policies":[
   {
      "policy":
      {
         "policy-type":"no-policy-found",
         "policy-domain":"no-uce.de"
      },
      "summary":
      {
         "total-successful-session-count":7,
         "total-failure-session-count":0
      }
   }]
} 

Who uses MTA-STS?

I even wrote a simple script to check which mail providers sending mails to my system use MTA-STS:

while read -r domain; do
  echo $domain; 
  mtasts=$(dig TXT _mta-sts.$domain +short);
  if [ ! -z "$mtasts" ]; then
    echo $mtasts;
    curl -s "https://mta-sts.$domain/.well-known/mta-sts.txt";
  fi
  dig TXT _smtp._tls.$domain +short; 
  echo "";
done< <(grep -E "qmgr.*from=<" /var/log/mail.info | sed -r 's_.*from=<(.*)@(.*)>,? .*_\2_' | sort -u | grep -v queue)

My quick findings show that many major players, including Facebook, Gmail, and Hotmail, are using these technologies to secure their email traffic.

It’s clear that while setting up MTA-STS and TLSRPT requires multiple steps, the result is a significant boost to your mail security and a valuable tool for monitoring its health.

See also

2 thoughts on “Securing Email with MTA-STS and TLSRPT”

  1. Hi Jean,

    I’m interested in the third part 😉 – which is sadly missing:
    The implementation of TLS reporting with Postfix.
    It seems to be not easy possible, if at all…

    1. Hey Christoph,

      give me a few days I’ll check. I’m also curious about that one. If I find something for that I’ll let you know 🙂

      Jean

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.