RFC 8314:明文已过时
ELI5: 多年来,电子邮件客户端通过明文端口连接到服务器,然后被要求"升级"到加密(STARTTLS)。这就像在拥挤的房间里用扬声器开始通话,然后低声说"让我们切换到私密线路"。RFC 8314 说:直接从私密线路开始。从第一个字节就用 TLS 连接——没有升级步骤,没有被窃听的窗口。
存在的原因
电子邮件历来使用三个明文端口进行客户端到服务器的通信:
| 端口 | 协议 | 用途 |
|---|---|---|
| 25 | SMTP | 服务器间中继 |
| 143 | IMAP | 邮箱访问 |
| 110 | POP3 | 邮箱访问 |
| 587 | 投递 | 客户端消息投递 |
这四个端口都以明文连接开始。STARTTLS被后来添加以在中间流升级这些连接为TLS。但STARTTLS存在系统性弱点:
- 降级攻击。攻击者可以从服务器响应中删除STARTTLS功能,许多客户端会无声地回退到明文。
- TLS前命令注入。STARTTLS完成前的明文阶段允许攻击者注入服务器在TLS握手后处理的SMTP命令。
- 凭据泄露。如果STARTTLS失败或被删除,客户端可能以明文发送AUTH凭据(用户名和密码)。
RFC 8314宣布这些明文连接对于电子邮件投递和邮箱访问已过时,并规定隐式TLS作为替代。
工作原理
隐式TLS对比STARTTLS
STARTTLS(旧方式):在明文端口连接,以明文交换问候,发送STARTTLS命令,协商TLS,然后继续加密会话。
-- 投递端口587上的STARTTLS -- 220 mail.example.com ESMTP ← 明文问候 EHLO client.example.com ← 明文 250-mail.example.com ← 明文 250-STARTTLS ← 攻击者可以删除此行 250 OK STARTTLS ← 明文 220 Go ahead ← 明文 -- TLS握手在此处发生 -- EHLO client.example.com ← 现已加密 AUTH PLAIN dXNlcjpwYXNz ← 加密(安全)
隐式TLS(RFC 8314方式):连接到专用TLS端口。TLS握手是连接时发生的第一件事。完全没有明文阶段。
-- 投递端口465上的隐式TLS -- -- TLS握手在连接时立即发生 -- 220 mail.example.com ESMTP ← 从第一个字节加密 EHLO client.example.com ← 加密 AUTH PLAIN dXNlcjpwYXNz ← 加密
新端口分配
| 服务 | 旧版(STARTTLS) | 新版(隐式TLS) | IANA名称 |
|---|---|---|---|
| 消息投递 | 587 | 465 | submissions |
| IMAP | 143 | 993 | imaps |
| POP3 | 110 | 995 | pop3s |
端口465有复杂的历史。它最初在1990年代后期被分配给"SMTPS",后来被撤销以支持端口587上的STARTTLS。RFC 8314将其重新分配为submissions(注意有's')用于隐式TLS投递。这一次是官方且永久的。
端口25呢?
端口25用于服务器间中继,不是客户端投递。RFC 8314不改变端口25行为。服务器间SMTP仍使用机会性STARTTLS,由MTA-STS或DANE提供强制。区分很重要:客户端使用凭据认证(必须受保护),而服务器通过DNS、DKIM和SPF认证。
关键技术细节
TLS版本要求
RFC 8314要求TLS 1.2或更高版本。TLS 1.0和1.1已由RFC 8996弃用。实际上,你应该要求最低TLS 1.2并倾向于TLS 1.3。
证书验证
使用隐式TLS,客户端必须使用标准Web PKI规则针对预期的主机名验证服务器证书。这与STARTTLS时代许多客户端接受任何证书的情况有重大改变。证书必须:
- 由受信任的证书颁发机构颁发。
- 与服务器主机名匹配(客户端连接到的名称,不一定是MX主机名)。
- 未过期或被撤销。
用于服务发现的SRV记录
RFC 8314与RFC 6186配合通过SRV记录进行自动客户端配置:
; 隐式TLS投递(RFC 8314 + RFC 6186)
_submissions._tcp.example.com. IN SRV 0 1 465 mail.example.com.
; 隐式TLS IMAP
_imaps._tcp.example.com. IN SRV 0 1 993 mail.example.com.
; 隐式TLS POP3
_pop3s._tcp.example.com. IN SRV 0 1 995 mail.example.com.
客户端配置
对于集成SMTP投递的应用开发者:
# Python示例:端口465上的隐式TLS import smtplib # 正确:SMTP_SSL立即以TLS连接 with smtplib.SMTP_SSL('mail.example.com', 465) as smtp: smtp.login('user', 'password') smtp.send_message(msg) # 避免:端口587上的STARTTLS(遗留) # with smtplib.SMTP('mail.example.com', 587) as smtp: # smtp.starttls() # smtp.login('user', 'password')
常见错误
- 混淆端口465和端口25。端口465用于带隐式TLS的客户端投递。端口25用于服务器间中继。永远不要将端口465用于MX投递。
- 仍然在端口587上提供明文而无STARTTLS强制。如果必须支持端口587,在AUTH前要求STARTTLS。永远不要允许凭据在明文连接上传送。
-
禁用证书验证。隐式TLS需要适当的证书验证。设置
verify=False或等效操作会完全破坏目的。改为修复证书。 - 使用TLS 1.0或1.1。这些已正式弃用。配置你的服务器仅接受TLS 1.2+。
-
将端口465视为"SMTPS"(1990年代版本)。旧SMTPS已被撤销。端口465现根据RFC 8314为
submissions——相同的基础行为(隐式TLS),但官方标准化并具有适当的IANA注册。 -
不发布SRV记录。没有
_submissions._tcpSRV记录,客户端无法自动发现你的隐式TLS端点。许多客户端仍默认为端口587上的STARTTLS。
可递送性影响
- 保护发件人凭据。对于使用SMTP投递的应用程序(例如你的应用连接到Go的邮寄程序),端口465上的隐式TLS确保你的API凭据永远不会在网络上以明文传输——甚至在STARTTLS升级期间也不会。
- 更快的连接建立。隐式TLS相比STARTTLS节省一个往返时间(无明文EHLO + STARTTLS交换)。对于大量发件人来说,这是有帮助的。
- 主要提供商要求的。Google Workspace和Microsoft 365都支持端口465上的隐式TLS。这是新集成的推荐投递方式。
- 消除一类攻击。STARTTLS剥离、命令注入和凭据嗅探都不可能使用隐式TLS。对于符合性敏感的环境,这很重要。