📌 第三部分:客户端发邮件与加密邮件
本章我们将讨论并学习部署SMTP Submission、STARTTLS,实现客户端发邮件与邮件加密投递的功能。这一章比较重要,涉及邮件从客户端到邮件服务器、再从发信方服务器到收信方服务器的传输过程。下面将为各位一一拆解。
📤 客户端如何发送邮件?
用户在邮件客户端中撰写邮件并点击“发送”时,实际上是通过 SMTP 协议 将邮件提交给自己的邮件服务器,再由服务器转发到收件人服务器,完成整个传递过程。
发送邮件的基本流程如下:
- 用户配置好邮箱账户,填写发件服务器地址和端口(通常为 587)
- 客户端使用 SMTP + STARTTLS(或 SMTPS)连接发件服务器
- 输入账号密码进行身份认证(SASL)
- 邮件发送成功后,服务器将邮件投递给收件人所在的服务器
🔧 大致配置流程
要实现客户端正常、安全地发邮件,邮件服务器需完成以下准备:
- ✅ Postfix 启用 Submission(端口 587) 服务
- ✅ 配置 STARTTLS 加密,确保传输安全
- ✅ 启用 SASL 用户认证,防止匿名发信和被滥用
- ✅ 创建用户邮箱账户,并设置密码存储(如 sasldb2 或虚拟用户系统)
- ✅ 放行防火墙端口,允许客户端访问 587 端口
配置完成后,用户便可通过常见的邮件客户端(如 Outlook、Apple Mail、手机邮箱等)安全地发送邮件到任意合法邮箱地址。
在开始之前,我们先来了解一些基础概念。
什么是SMTP Submission
SMTP Submission是指通过端口587使用SMTP协议提交邮件,用于客户端将邮件提交到邮件服务器。它是区别于传统SMTP(端口25)的更安全、现代的邮件发送方式。
在SMTP Submission出现之前,客户端和服务器之间就是直接用SMTP的标准端口25提交邮件的。我们来回顾一下SMTP的历史:
背景历史:
- SMTP最早定义于1982年(RFC 821),当时:
- 只定义了端口25
- 没有用户认证
- 没有加密机制(全部明文)
主要问题:
- 安全问题:
- 任何人都能通过端口25“冒充”别人发信
- 导致伪造邮件泛滥
- 垃圾邮件激增:
- SMTP没有认证机制
- 不区分“客户端提交”与“服务器投递”
- 数据明文传输:
- 邮件内容、密码等在网络中裸奔
- 可被窃听、篡改
为了解决这些问题,SMTP Submission机制被提出:
- RFC 2476(1998年)定义了587端口作为邮件提交专用端口。
- 后续标准要求客户端:
- 用587提交邮件(必须认证身份)
- 用STARTTLS加密通信
- 邮件服务器才可以更好地区分:
- 谁是“用户”
- 谁是“其他邮件服务器”
现在几乎所有的邮件服务商都用587端口接收来自客户端的邮件。
以上内容总结为一句话:SMTP Submission是“发邮件”的安全管道(587端口)
好,现在我们知道邮件客户端收发邮件是有安全通道的,但邮件服务器(MTA)向另一台邮件服务器(MTA)投递邮件时,这个过程的安全性如何保证呢?答案是:STARTTLS和邮件签名机制(SPF、DKIM和DMARC)。
什么是STARTTLS?
STARTTLS = “我们先用明文打个招呼,然后立刻切换成加密通话。”
STARTTLS
是电子邮件和其他应用协议中一种将不安全连接升级为加密连接的机制。它不是一个新的协议,而是现有协议(如 SMTP、IMAP、POP3)中的一个扩展指令,允许客户端和服务器在原始明文连接上协商建立 TLS 加密通道。
工作流程(以SMTP为例):
客户端连接发信服务器:
- 先连接服务器的端口587(或 25)
- 收到服务器响应(明文)
- 客户端发送指令:
EHLO
- 服务器回应支持
STARTTLS
- 客户端发送:
STARTTLS
- 双方协商加密(开始TLS握手)
- 成功后,通信切换为加密通道
- 接着才会发送
AUTH LOGIN
(SASL)、MAIL FROM
等敏感信息
注意:
- STARTTLS必须由客户端“主动发起”,服务器不会强制。
- 如果不配置服务器强制加密,邮件可能仍以明文发送(不安全)。
- 所以很多现代邮件服务器会配置为:
- 接收邮件可选加密
- 发送邮件强制加密
接下来,我们先来配置SMTP Submission。配置过程中涉及两部分,其一是客户端连接邮件服务器的身份验证机制(SASL),其二是邮件传输过程中的加密机制(STARTTLS)。
在上面的流程中我们谈到了STARTTLS,那SASL又是什么呢?
什么是SASL?
SASL,全称Simple Authentication and Security Layer(简单认证和安全层),是一个通用的认证框架,用于在应用层协议(如SMTP、IMAP、POP3、LDAP等)中添加“认证”与“安全”功能。
SASL不是某种具体的认证方式,而是一个“框架”,它支持多种认证机制,比如:
PLAIN
(明文用户名+密码)LOGIN
(Base64 编码用户名+密码,分步提交)CRAM-MD5
(基于密钥的摘要认证)SCRAM-SHA-1
、XOAUTH2
等更高级机制
总而言之,SASL是一个可插拔的认证框架,用于让各种协议(如 SMTP、IMAP)支持多种登录方式(用户名密码、令牌、OAuth等),从而实现安全认证。
基于上述流程,我们只需要配置SASL和STARTTLS就可以实现SMTP Submission的功能了。
SMTP Submission配置
首先安装相关的软件包:
$ sudo dnf install cyrus-sasl cyrus-sasl-plain cyrus-sasl-md5
修改/etc/postfix/main.cf
,添加下面的内容,该配置默认使用cyrus作为SASL验证类型。Postfix也支持与Dovecot通信,使用Dovecot中已有的用户认证方式(PAM、系统账号、虚拟邮箱、数据库等)进行身份验证。对于个人网站来说,默认的配置就够用了。
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_sasl_auth_enable = yes #默认是PLAIN(明文)发送用户名和密码。
smtpd_sasl_security_options = noanonymous
smtpd_tls_security_level = encrypt #这个参数控制Postfix作为SMTP服务器(即接收邮件时),是否启用TLS以及如何使用TLS。
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
smtp_tls_security_level = encrypt #这个参数控制Postfix作为SMTP客户端(即向其他邮件服务器发送邮件时)是否启用TLS。
smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache
smtp_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtp_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem
smtpd_tls_protocols = TLSv1.2 TLSv1.3
smtpd_tls_loglevel = 1
smtp_tls_protocols = TLSv1.2 TLSv1.3
这里重点解释一下smtpd_relay_restrictions
和smtpd_recipient_restrictions
,基本概念如下:
smtpd_recipient_restrictions
控制的是对每个收件人地址是否允许接受邮件,而smtpd_relay_restrictions
则专门用于控制是否允许将邮件中继(转发)到非本地域的收件人。
举个通俗的例子,把自己想象成邮局,smtpd_recipient_restrictions
的作用就是验证这封信我该不该收下来?收件人合法吗?收件人存在吗?是不是在黑名单中?而smtpd_relay_restrictions
的作用是,我收到这封信后能不能转发这封信?发件人是谁?认证了吗?
在这个过程中,Postfix控制的是:别人是否可以将一封指定收件人的邮件交给我。哪怕这“别人”是你自己的邮箱客户端。
有了这些概念后,我们再来看其值的作用:
permit_mynetworks #允许本地收发邮件
permit_sasl_authenticated #允许sasl认证用户中继/允许接收sasl认证的用户发往外部域的邮件。
reject_unauth_destination #拒绝未授权的目的地
那么什么是“未授权的目的地”?让我们来看一下man 5 postconf
手册:
如果Postfix充当邮件转发服务器(Relay Server),它会允许目的地址属于
relay_domains
或relay_domains
的子域的邮件。
但如果邮件地址中包含额外的手动路由(如user@elsewhere@domain
),它仍然会被拒绝。也就是说只有目的地是这些域的邮件会被中继。如果邮件的目的地址匹配以下参数之一,Postfix认为它是本地投递,不会拒绝:
mydestination
:本机接受的域(本地投递)。inet_interfaces
:Postfix监听的网络接口地址。proxy_interfaces
:代理的接口地址。virtual_alias_domains
:虚拟邮箱的别名域。virtual_mailbox_domains
:Postfix负责接收的虚拟邮箱域。
这样的配置就避免自己的邮件服务器成为开放的中继。
接下来配置/etc/postfix/master.cf
,强制客户端通过587端口提交邮件,并且需要提供SASL身份验证,以及STARTTLS加密。
submission inet n - n - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
重新加载Postfix的配置:
$ sudo postfix reload
编辑/etc/sasl2/stmpd.conf
pwcheck_method: auxprop
mech_list: plain login
启动saslauthd服务:
$ sudo systemctl enable --now saslauthd.service
防火墙放行587端口:
$ sudo firewall-cmd --permanent --add-port=587/tcp
$ sudo firewall-cmd --reload
创建一个用于SASL验证的用户,注意这个不是Linux用户。
$ sudo saslpasswd2 -c testuser
$ sudo sasldblistusers2
重启Postfix:
$ sudo systemctl restart postfix
执行sasl数据库格式转换,否则提交邮件时maillog
中会提示“SASL error opening password file. Have you performed the migration from db2 using cyrusbdb2current??“
$ sudo cyrusbdb2current
修改/etc/sasl2/sasldb2
的owner,确保该文件能被Postfix进程访问。
$ sudo chown postfix:postfix /etc/sasl2/sasldb2
至此,SMTP Submission的配置完成,并且可以发送加密邮件。