MTA-STS 是解决邮件传输层降级攻击的标准方案。很多企业部署了 SPF、DKIM、DMARC 之后便认为邮件安全已经完成,但这三项解决的是”发件人身份是否被伪造”,并不能阻止中间人把 STARTTLS 协商降级为明文,也无法防止攻击者用无效证书冒充对端 MX。MTA-STS 通过 DNS 声明加 HTTPS 托管策略的方式,强制发信方使用有效证书的 TLS 连接,是当前投入产出比最高的一项补充加固。
适用场景
- 企业使用自有域名收发邮件,MX 指向自建邮件网关或企业邮箱;
- 已配置 SPF、DKIM、DMARC,但传输层仍可能被降级为明文 SMTP;
- 金融、外贸、医疗等对邮件内容保密性有合规要求的行业;
- 需要持续获取传输失败报告,及时发现对端证书异常或配置漂移。
前置条件
- 拥有域名 DNS 记录管理权限,可以添加 TXT 记录;
- 能够为
mta-sts.你的域名这个子域签发并部署受公网信任的证书(不能使用自签或过期证书); - 已确认全部对外的 MX 主机名,漏配任意一个都会造成投递失败;
- 规划一个专用邮箱接收 TLS 报告,例如
tlsrpt@你的域名。
原理说明
MTA-STS(SMTP MTA Strict Transport Security,RFC 8461)由两部分协同工作。第一部分是 DNS 中的策略声明记录,位于 _mta-sts 子域,内容形如 v=STSv1; id=2026100701;,其中 id 是策略版本标识,每次修改策略文件都必须同步更新 id,否则对端会继续使用缓存副本。第二部分是 HTTPS 托管的策略文件,固定路径为 https://mta-sts.你的域名/.well-known/mta-sts.txt。
强制路径可拆成三步。发信方先查询 _mta-sts 的 TXT 记录,若存在则通过 HTTPS 拉取策略文件并缓存(缓存时长由 max_age 决定);之后在投递前校验对端 MX 是否在策略声明的 mx 列表中、TLS 证书是否有效且与 MX 主机名匹配。mode: enforce 下校验不通过则拒绝投递,而非降级到明文。
TLS-RPT(RFC 8460)是配套的报告机制,通过 _smtp._tls 子域的 TXT 记录声明报告接收地址,对端检测到 TLS 协商失败时会发送结构化报告。没有 TLS-RPT,启用 enforce 就像蒙眼开车:一旦有客户因为证书链不完整而被拒收,你无法察觉,只会表现为”对方收不到邮件”。
需要明确三者的分工:SPF/DKIM/DMARC 防伪造发件人,MTA-STS 防传输降级与中间人,TLS-RPT 提供失败可见性。它们互补而非替代。
策略文件中的 mx 支持精确主机名,也可使用通配符写法(如 *.example.com),但通配符只匹配同一父域,跨域委派出去的 MX 必须逐个列出。max_age 是发信方缓存策略文件的最长秒数,取值越大越安全、出问题回退越慢,建议从 86400 起步,稳定运行一个月后再提升到 604800。若策略文件无法访问或证书校验失败,发信方的行为由 mode 决定:enforce 下直接拒发,testing 下正常投递但发送 TLS-RPT 报告,none 等同于未启用。
操作步骤
1. 部署 HTTPS 策略文件
先为 mta-sts 子域申请证书并配置 Nginx 站点。策略文件内容示例:
version: STSv1
mode: testing
mx: mx1.example.com
mx: mx2.example.com
max_age: 86400
首次务必使用 testing 模式,观察两周确认无异常后再切 enforce。文件必须放在 /.well-known/mta-sts.txt,且不允许任何重定向,Content-Type 建议为 text/plain。
2. Nginx 托管配置
server {
listen 443 ssl http2;
server_name mta-sts.example.com;
ssl_certificate /etc/letsencrypt/live/mta-sts.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mta-sts.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location = /.well-known/mta-sts.txt {
root /var/www/mta-sts;
default_type text/plain;
add_header Cache-Control "public, max-age=3600";
break;
}
location / { return 404; }
}
3. 添加 DNS 记录
# 策略声明记录(id 随策略更新而递增)
_mta-sts.example.com. IN TXT "v=STSv1; id=2026100701;"
# TLS 报告接收记录
_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:tlsrpt@example.com;"
4. 切换 enforce 模式
version: STSv1
mode: enforce
mx: mx1.example.com
mx: mx2.example.com
max_age: 604800
切换时同步更新 TXT 中的 id,并把 max_age 从 86400 提升到 604800。若中途出现投递异常,把 mode 改回 testing 并再次更新 id 即可快速回退,无需等待缓存自然过期。
5. 上线检查清单
- 策略文件中列出的 MX 与 DNS 中的
MX记录完全一致,包含备份 MX 与负载均衡主机名; mta-sts子域证书由公网信任的 CA 签发、未过期、主机名匹配;/.well-known/mta-sts.txt无 301/302 跳转、无认证拦截、Content-Type 为text/plain;- TXT 记录中的
id与策略文件当前版本一一对应,每次改动文件都必须同步递增; _smtp._tls指向的报告邮箱容量充足,且未被反垃圾规则误拦;- WAF 与 CDN 已放行
/.well-known/路径,且未缓存旧版本策略文件。
条件允许时,建议在切换 enforce 前用第三方连通性测试工具,从公网对每个 MX 做一次 STARTTLS 握手与证书链校验,提前暴露中间证书缺失一类问题。
配置验证
# 1. DNS 记录是否生效
dig +short TXT _mta-sts.example.com
dig +short TXT _smtp._tls.example.com
# 2. 策略文件可访问且无重定向
curl -sS -o - -w "\nHTTP=%{http_code} redirect=%{num_redirects}\n" \
https://mta-sts.example.com/.well-known/mta-sts.txt
# 3. 证书链与主机名校验
openssl s_client -connect mta-sts.example.com:443 -servername mta-sts.example.com \
2>/dev/null | openssl x509 -noout -subject -dates -ext subjectAltName
# 4. 校验 MX 主机 TLS 证书可用性
for mx in mx1.example.com mx2.example.com; do
echo "== $mx"
openssl s_client -starttls smtp -connect ${mx}:25 -servername ${mx} \
2>/dev/null | openssl x509 -noout -subject -enddate
done
第 2 步的 redirect 必须为 0,第 3 步的 -dates 需确认未过期,第 4 步要对策略文件里列出的每一个 MX 都执行,避免漏配主机名导致 enforce 后投递失败。
常见问题
FAQ 1:配置了 DMARC 还需要 MTA-STS 吗?
需要,两者不在同一层。DMARC 校验的是发件域身份,识别伪造邮件;MTA-STS 约束的是传输通道,阻止 STARTTLS 降级为明文和伪造对端证书。攻击者可以在完全通过 DMARC 校验的情况下,中途窃听明文传输的邮件正文。只做 DMARC 的邮箱,正文仍可能裸奔。
FAQ 2:直接上 enforce 模式会不会导致邮件被拒收?
存在风险,主要来自三类情况:MX 列表漏配、对端证书链不完整(部分老网关缺少中间证书)、以及策略文件被 CDN 缓存导致版本错乱。因此标准做法是先 testing 观察,配合 TLS-RPT 报告确认无失败,再切 enforce;同时把 max_age 从 86400 逐步提升,保证出问题时能快速回退。
FAQ 3:mta-sts 子域能否放在 CDN 后面?
可以,但必须确保回源正确、不重定向、不缓存错误版本,且 CDN 不会把 HTTPS 强制跳转或插入验证页面。由于策略文件更新依赖 TXT 记录中的 id 变化,CDN 缓存时间应设置得比 max_age 短。若站点本身有 WAF,注意 /.well-known/ 路径必须加入放行白名单,否则报告接收方或对端拉取策略时会拿到 403。
FAQ 4:TLS-RPT 报告收不到怎么办?
先确认 _smtp._tls 记录的 TXT 值格式与逗号分隔正确,再检查报告邮箱是否存在容量或反垃圾拦截。报告以 gzip 压缩的 JSON 通过邮件发送,主题通常包含 Report Domain,容易被规则误判。建议为 tlsrpt@ 单独建收件箱并关闭激进过滤,也可解析报告后接入监控告警。
总结
邮件安全需要分层建设:SPF、DKIM、DMARC 管身份,MTA-STS 管传输,TLS-RPT 管可见性。落地顺序建议先部署 TLS-RPT 拿到基线报告,再上线 testing 模式策略,最后在报告清零后切换 enforce。整个过程务必核对 MX 列表完整性与证书链有效性,任何一步缺失都会直接表现为业务邮件被拒收。