Mail Security: MTA-STS + Mailcow
Self-hosting e-mail is kind of a challenging task as you have to keep up with all the mechanisms modern mail transport has to offer (e.g. SPF, DKIM, DMARC, DANE etc.). If you don't, the big guys (MS Exchange, Gmail & co.) will start rejecting your mails or marking them as spam and your inboxes will start becoming an easy target for spammers. Mailcow is a cool project that tries to lift most of the weight of hosting your own mail server from your shoulders. Unfortunately, there are still some uncovered subjects. One of them is MTA-STS.
I don't know what SPF, DKIM and DMARC mean.
Skip this part, if you do. Otherwise, bookmark this page, google the terms, implement them as quickly as you can and come back.
MTA-STS explained
MTA-STS stands for Mail Transfer Agent Strict Transport Security and is specified in RFC8461. MTA-STS is the counterpart for DNSSEC/DANE and it aims to force mail servers to communicate via TLS secured connections. This offers multiple benefits:
- Enhanced security against routing-based attacks (Spoofing, Cache Poisoning, MITM) even without DNSSEC/DANE as most DNS providers and mail hosters don't fully support DNSSEC/DANE (yet).
- Encrypted mail transfer between mail servers to guarantee confidentiality and integrity during mail transport.
Choose: MTA-STS or DNSSEC/DANE
MTA-STS and DNSSEC/DANE can be implemented and used on their own without the other or you can implement both. Both offer the same kind of security for similar problems. Therefore, you have to implement at least one of them. If you don't, attackers can easily reroute your mails to read and modify them.
How to implement MTA-STS policy (for mailcow)
MTA-STS requires two things:
- 3 DNS entries for every domain you want to receive mails to or send from
- A web server with trusted certificates for every domain you want to receive/send mails to/from that serves a text file
The following guide will show you how you can easily implement both requirements with mailcow. I assume that you have a correctly configured mailcow instance and your mail server has the hostname "mail.example.com".
!!! Make sure to replace every occurrence of mail.example.com with your mail domain !!!
DNS Entries
We start by adding the following 3 DNS entries to the DNS zone of your mail server. The assumption is, that your mail server "mail.example.com" has an A/AAAA record.
Make sure to also replace "report@example.com" with your preferred email for reports.
Afterward, you need to add the following 3 CNAME DNS entries to every one of your domains that use your mailcow server for e-mail.
mta-sts.txt
Go into your mailcow folder (should be /opt/mailcow-dockerized/
). Then go to data/web/.well-known/
. Afterward, create a file called mta-sts.txt
(touch mta-sts.txt
). Open up the file in your favorite editor (e.g. vim or nano) and enter the following content:
version: STSv1
mode: enforce
max_age: 172800
mx: mail.example.com
mx: *.example.com
Example from Google: https://mta-sts.google.com/.well-known/mta-sts.txt
Certificates for every mta-sts.* Domain
Mailcow provides a simple way to automatically issue the right certificates for each of your configured mail domains (inside the mailcow UI).
Go into your mailcow folder (should be /opt/mailcow-dockerized/
) and open the mailcow.conf
in your favorite editor. Now, scroll till you see ADDITIONAL_SAN
and ADDITIONAL_SERVER_NAMES
and add mta-sts.*
to both variables, like:
# ...
ADDITIONAL_SAN=mta-sts.*
# ...
ADDITIONAL_SERVER_NAMES=mta-sts.*
Save the file and reload the configuration by running docker-compose up -d
inside your mailcow folder.
Check if everything works
If everything works, you should now be able to open a link like
https://mta-sts.example.com/.well-known/mta-sts.txt
for every domain you configured in mailcow. If not, the reason for this could be that the DNS entries did not propagate yet. Then, just wait a few hours, run docker-compose restart acme-mailcow
in your mailcow folder and try again.
You should also go to checkTLS.com, enter your mail domain, click on "more options", set "check MTA-STS" and hit "Run Test". If everything is ok, it should look like this:
This is just the policy
The good news is that you implemented the MTA-STS policy. However, this is just the policy part. Other mail servers will use the policy to force secured transports. Mailcow, though, will not check the MTA-STS policies of other mail servers it tries to contact. There is an open github issue on the mailcow repo about fully implementing MTA-STS checks (see #1809).
References
- Header Image mailcow logo: Project licensed under GNU General Public License v3.0