RFC 4954: SMTP 认证扩展
ELI5: 想象一个邮局,任何人都可以走进去投递邮件,声称来自任何人。很混乱,对吧?SMTP AUTH 就是柜台的身份检查。在你交出邮件之前,你需要证明你是谁——用户名、密码,什么都要。只有在职员确认你的身份后,你才能提交你的邮件。没有 AUTH,SMTP 就像一扇对滥用敞开的门。
为什么存在这个机制
原始SMTP(RFC 5321)没有发件人身份验证的概念。任何客户端都可以连接到任何服务器并以任何人的身份发送邮件。这种设计在互联网早期有效,当时所有参与者都是值得信任的,但它成为了垃圾邮件问题的基础。
RFC 4954定义了SMTP的AUTH扩展,为客户端提供了在提交邮件前向邮件服务器进行身份验证的标准化方式。它使用SASL(简单身份验证和安全层)框架,允许多个身份验证机制无需改变SMTP协议本身即可接入。
该RFC废弃了RFC 2554(1999),修复了安全问题并澄清了AUTH与其他SMTP扩展(如STARTTLS)的交互。
工作原理
AUTH协商
- 客户端连接并发出
EHLO。 - 服务器通告
250-AUTH,后跟支持的SASL机制列表。 - 客户端选择一个机制并发送
AUTH <mechanism>,可选地带有初始响应。 - 服务器和客户端交换一个或多个挑战/响应轮次(机制相关)。
- 服务器以
235(身份验证成功)或535(身份验证失败)响应。
SMTP传输:AUTH PLAIN
PLAIN机制在包含授权身份、身份验证身份和密码的单个Base64编码字符串中发送凭证:
# 连接并发现功能
S: 220 smtp.mailertogo.com ESMTP
C: EHLO app.example.com
S: 250-smtp.mailertogo.com
S: 250-STARTTLS
S: 250-AUTH PLAIN LOGIN XOAUTH2
S: 250-SIZE 26214400
S: 250 ENHANCEDSTATUSCODES
# 先升级到TLS(总是在AUTH之前)
C: STARTTLS
S: 220 2.0.0 Ready to start TLS
# ...TLS握手...需要重新EHLO
C: EHLO app.example.com
S: 250-smtp.mailertogo.com
S: 250-AUTH PLAIN LOGIN XOAUTH2
S: 250 ENHANCEDSTATUSCODES
# 使用AUTH PLAIN进行身份验证
# "\0alice@example.com\0secretpassword"的Base64编码
C: AUTH PLAIN AGFsaWNlQGV4YW1wbGUuY29tAHNlY3JldHBhc3N3b3Jk
S: 235 2.7.0 Authentication successful
# 现在已授权提交邮件
C: MAIL FROM:<alice@example.com>
S: 250 2.1.0 OK
SMTP传输:AUTH LOGIN
LOGIN机制对用户名和密码使用单独的挑战/响应:
C: AUTH LOGIN
S: 334 VXNlcm5hbWU6 ← "Username:"的Base64编码
C: YWxpY2VAZXhhbXBsZS5jb20= ← "alice@example.com"的Base64编码
S: 334 UGFzc3dvcmQ6 ← "Password:"的Base64编码
C: c2VjcmV0cGFzc3dvcmQ= ← "secretpassword"的Base64编码
S: 235 2.7.0 Authentication successful
SMTP传输:AUTH失败
C: AUTH PLAIN AGJhZEBleGFtcGxlLmNvbQB3cm9uZw==
S: 535 5.7.8 Authentication credentials invalid
# 收到535后客户端不能尝试发送邮件
关键技术细节
SASL机制
RFC 4954不直接定义身份验证机制。它提供了框架;机制来自SASL注册表。SMTP中最常用的机制:
| 机制 | 工作原理 | 安全说明 |
|---|---|---|
PLAIN |
单个Base64字符串:\0authzid\0password
|
简单,广泛支持。仅限于TLS上使用。 |
LOGIN |
用户名和密码的两步挑战/响应 | 非标准但无处不在。仅限于TLS上使用。 |
XOAUTH2 |
格式化字符串中的OAuth 2.0承载令牌 | 不传输密码。基于令牌,由Gmail和Microsoft 365使用。 |
SCRAM-SHA-256 |
带有通道绑定的加盐挑战/响应 | 密码不发送,即使是哈希形式。相互身份验证。安全性最佳但SMTP采用率有限。 |
CRAM-MD5 |
带有MD5 HMAC的挑战/响应 | 已弃用。MD5被认为较弱。避免发送密码但不防止重放攻击。 |
AUTH PLAIN凭证格式
PLAIN机制编码三个用空字节(\0)分隔的字段,然后进行Base64编码:
# 格式:[authzid] \0 authcid \0 password
# authzid = 授权身份(通常为空或与authcid相同)
# authcid = 身份验证身份(用户名)
# password = 明文密码
# 示例:authzid为空,authcid为"alice@example.com",密码为"s3cret"
\0alice@example.com\0s3cret
# Base64编码后:
AGFsaWNlQGV4YW1wbGUuY29tAHMzY3JldA==
初始响应优化
RFC 4954允许客户端在AUTH命令的同一行发送初始SASL响应(如上面PLAIN示例所示)。与较早的两步方法相比,这节省了一个往返,较早的方法中服务器首先发送空挑战。对于PLAIN之类客户端首先发言的机制,此优化是标准的。
与STARTTLS的交互
RFC 4954强烈建议服务器在建立TLS后再通告AUTH。这防止客户端意外以明文发送凭证。典型流程为:
- 连接 → EHLO → 服务器通告STARTTLS但不通告AUTH
- STARTTLS → TLS握手
- 再次EHLO → 服务器现在通告AUTH(STARTTLS不再列出)
- AUTH → 提交邮件
响应代码
| 代码 | 含义 |
|---|---|
235 |
身份验证成功 |
334 |
服务器挑战(SASL交换的继续) |
432 |
需要密码转换(服务器要求更改密码) |
454 |
临时身份验证失败(稍后重试) |
500 |
AUTH命令无法识别(服务器不支持AUTH) |
534 |
身份验证机制过于简单(服务器需要更强的机制) |
535 |
身份验证凭证无效 |
AUTH和MAIL FROM身份
成功身份验证后,服务器将连接与已验证身份相关联。MSA随后可以强制MAIL FROM和标头From:地址匹配(或授权给)已验证的用户。这防止已验证的用户欺骗任意发件人地址。
常见错误
- 在STARTTLS之前发送AUTH。如果服务器在明文连接上通告AUTH(某些配置错误的服务器这样做),您的凭证仍会以明文形式传输。始终在身份验证前建立TLS。使用端口465上的隐式TLS时,这是自动的。
-
将Base64编码与加密混淆。Base64是一种编码,不是加密。
AUTH PLAIN以平凡的可解码格式发送凭证。保护来自TLS层,而不是Base64。 - 不处理535错误。AUTH失败意味着服务器拒绝了您的凭证。在循环中重试相同凭证将导致您的IP被速率限制或阻止。检查凭证并优雅地失败。
- 当PLAIN可用时硬编码AUTH LOGIN。LOGIN是一个非标准机制,实现不一致。如果服务器支持PLAIN,优先选择它。如果它支持XOAUTH2或SCRAM,优先选择那些。
- 在STARTTLS后不重新发出EHLO。建立TLS后,功能列表会改变。AUTH可能仅在TLS后EHLO响应中出现。跳过第二个EHLO意味着您的客户端永远无法发现AUTH支持。
-
忽略初始响应优化。发送
AUTH PLAIN而不带内联凭证会强制不必要的额外往返。大多数现代服务器支持初始响应。 - 使用CRAM-MD5以获得"安全性"。CRAM-MD5避免发送明文密码,但它使用MD5(已破解),不防止重放攻击,并要求服务器以可恢复形式存储密码。PLAIN over TLS严格上更优。
可交付性影响
- 邮件提交所需。每个现代电子邮件服务都需要SMTP AUTH来进行提交(RFC 6409)。没有身份验证,服务器将以530(需要身份验证)响应拒绝您的邮件。
- 启用发件人身份绑定。身份验证将每条邮件与已知帐户绑定。这让电子邮件服务能够强制执行发送策略、应用DKIM签名并跟踪每个已验证发件人的声誉。
- 防止开放中继滥用。通过在接受邮件进行传递前要求身份验证,服务器避免被利用作为开放中继 —— 这会迅速导致IP列入黑名单并对服务器上的所有用户造成递送失败。
- 用于现代集成的OAuth2。Gmail和Microsoft 365等服务正在弃用基于密码的AUTH,转而支持XOAUTH2。迁移到基于令牌的身份验证可避免禁用基本身份验证时的服务中断。
- 速率限制和滥用防止。已验证的会话允许按用户速率限制。如果一个帐户被破坏,服务可以限制或禁用该帐户而不影响同一基础设施上的其他发件人。