Postfix TLS 支持为您带来的好处
传输层安全协议(TLS,原名 SSL)提供基于证书的身份验证和加密会话。加密会话可保护通过 SMTP 邮件或 SASL 身份验证传输的信息。
注意:启用 Postfix 中的 TLS 支持不仅能加密邮件并验证远程 SMTP 客户端或服务器,还会启用数以十万计的 OpenSSL 库代码行。假设 OpenSSL 的代码与 Wietse 的代码同样精心编写,每 1000 行代码会为 Postfix 引入一个额外漏洞。
本文档涵盖的主题:
最后但同样重要的是,对于急于尝试的用户:
Postfix TLS 支持的工作原理
下图显示了 Postfix TLS 架构的主要元素及其关系。带编号的彩色框代表 Postfix 守护进程程序。其他彩色框代表存储元素。
- smtpd(8) 服务器实现 SMTP 通过 TLS 的服务器端。
- smtp(8) 客户端实现 SMTP(及 LMTP)的 TLS 客户端侧。
- tlsmgr(8) 服务器维护用于初始化 TLS 引擎的伪随机数生成器 (PRNG),该 PRNG 用于 smtpd(8) 服务器和 smtp(8) 客户端进程中,并维护 TLS 会话密钥缓存文件。
未在图中显示的是 tlsproxy(8) 服务器和 postscreen(8) 服务器。这些服务器与smtpd(8)以相同方式使用 TLS。
| 网络->; ; | smtpd(8) ; ; | <;---seed---- <;-key/cert->; ; | tlsmgr(8) ; ; | ----种子--->; <;-密钥/证书->; ; | smtp(8) ; ; | ->;网络 | |||||||||||
| ; |
| | | |
| ; | ; | ||||||||||||
| ; | smtpd session 密钥缓存 | ; | 伪随机数生成器 状态 ; 文件 | ; | smtp session 密钥缓存 | ; | ; | ||||||||||
SMTP 服务器特定设置
本节涵盖的内容:
- 服务器端证书和私钥配置
- 服务器端前向保密配置
- 服务器端 TLS 活动日志记录
- 在 Postfix SMTP 服务器上启用 TLS
- 客户端证书验证
- 仅支持通过 TLS 进行身份验证
- 服务器端 TLS 会话缓存
- 服务器访问控制
- 服务器端加密套件控制
- 其他服务器控制
服务器端证书和私钥配置 ;
要使用 TLS,Postfix SMTP 服务器通常需要一个证书和一个私钥。两者都必须以 "PEM" 格式存储。私钥不得加密,即:密钥必须在无需密码的情况下可访问。证书和私钥可以存储在同一个文件中,此时证书文件应由"root"用户所有,且不可被其他用户读取。如果密钥单独存储,此访问限制仅适用于密钥文件,而证书文件可设置为"世界可读"。
未由知名公共 CA 签名的公共互联网 MX 主机仍需生成并准备好向大多数客户端展示自签名或私有 CA 签名的证书。远程 SMTP 客户端通常无法验证自签名证书,但除非客户端运行 Postfix 或类似软件,否则它只会协商需要服务器证书的 TLS 密码套件。
对于不是公共互联网 MX 主机的服务器,Postfix 支持无证书配置。这意味着仅使用匿名 TLS 密码套件,而此类套件不被典型 SMTP 客户端支持。由于部分客户端在 TLS 握手失败后可能不会回退到明文传输,因此无证书的 Postfix SMTP 服务器将无法接收来自部分启用 TLS 的客户端的邮件。为避免意外配置为无证书模式,Postfix仅在管理员明确设置 "smtpd_tls_cert_file = none" 时启用无证书操作。这确保新配置的 Postfix SMTP 服务器不会意外启用无证书的 TLS。
注意:在 TLS 1.3 中,服务器证书是 必不可少 的。若要无证书运行,需通过在 "smtpd_tls_protocols" 中添加 "<=TLSv1.2"(或对于 Postfix < 3.6,添加 "!TLSv1.3"),并可能还需要在 "smtpd_tls_mandatory_protocols" 中添加 "<=TLSv1.3"。建议直接配置证书链。不推荐使用无证书模式。
;
支持 RSA、DSA 和 ECDSA(Postfix ≥ 2.6)证书。大多数站点仅使用 RSA 证书。您可以同时配置三种证书,此时与远程 SMTP 客户端协商的密码套件将决定使用哪个证书。如果您的 DNS 区域已签名,且您希望发布 DANE TLSA(RFC 6698, RFC 7671, RFC 7672)记录,这些记录必须与所有配置的证书链匹配。由于最佳实践是发布"3 1 1"证书关联,请为每个公钥证书摘要创建一个单独的 TLSA 记录。
创建服务器证书文件
要验证 Postfix SMTP 服务器证书,远程 SMTP 客户端必须通过 TLS 握手或公钥基础设施接收签发 CA 证书。这意味着 Postfix 服务器公钥证书文件必须首先包含服务器证书,然后是签发 CA(自下而上顺序)。Postfix SMTP 服务器证书必须可作为 SSL 服务器证书使用,并通过 "openssl verify -purpose sslserver ..." 测试。
以下示例演示了如何创建服务器证书文件。假设 "server.example.com" 的证书由 "intermediate CA" 签发,而 "intermediate CA" 自身由 "root CA" 签发。
使用传统公共 CA 信任验证时,可以省略 "server.pem" 证书文件中的根证书。如果客户端信任根 CA,它已经拥有根 CA 证书的本地副本。省略根 CA 证书可减少服务器 TLS 握手大小。
% cat server_cert.pem intermediate_CA.pem >; server.pem
如果您发布了DANE TLSA(RFC 6698, RFC 7671, RFC 7672) "2 0 1" 或 "2 1 1" 记录来指定根 CA 证书摘要,您必须在 "server.pem" 证书文件中包含相应的根 CA 证书。
% cat server_cert.pem intermediate_CA.pem root.pem >; server.pem
远程 SMTP 客户端仅在能够访问对应证书的情况下,才能使用您发布的 TLSA 记录(该记录仅包含证书摘要)。如果未根据服务器发布的 TLSA 记录验证证书,SMTP 客户端通常会推迟邮件投递。上述内容也适用于 "2 0 2" 和 "2 1 2" TLSA 记录或任何其他 CA 证书的摘要,但预计 SHA256 将是 TLSA 中最常见的摘要。
作为最佳实践,应发布指定服务器公钥 SHA256 摘要的 "3 1 1" TLSA 关联。当证书使用相同的公钥/私钥对续签时,这些关联无需修改即可继续使用。
有关如何计算证书或其公钥的摘要以用于 TLSA 记录的说明,请参阅 smtpd_tls_fingerprint_digest main.cf 参数。
当生成新密钥或证书时,必须在实际部署新密钥或证书到服务器之前,提前发布包含新摘要的额外 TLSA 记录。必须留出足够时间让 DNS 缓存中仅包含旧摘要的 TLSA RR 集合过期。最安全的做法是等待之前 TLSA RRset 上的 DNSSEC 签名过期,然后再将服务器切换为使用更新的 TLSA RRset 中发布的密钥。一旦新的证书信任链和私有密钥生效,应再次更新 DNS 以从 TLSA RRset 中移除旧的摘要。
如果您希望 Postfix SMTP 服务器接受由一个或多个根 CA 签发的远程 SMTP 客户端证书,请将根证书附加到 $smtpd_tls_CAfile,或将其安装在 $smtpd_tls_CApath 目录中。
配置服务器证书和密钥文件
示例:Postfix ≥ 3.4 的全链文件。一个或多个链文件,每个文件以密钥开头,紧跟对应的证书及任何额外签发者证书。单个文件可包含多个 (密钥, 证书, [链]) 序列,每个算法对应一个序列。通常建议将每个算法的链保存在独立文件中。大多数用户可能仅部署单个 RSA 链,但使用 OpenSSL 1.1.1 时,可部署多达五个链,分别对应 RSA、ECDSA、ED25519、ED448 以及已废弃的 DSA。
# Postfix ≥ 3.4。首选配置接口。每个文件 # 以私钥开头,随后是对应的 # 证书,以及任何中间颁发者证书。根CA # 证书在作为DANE信任锚发布时也可能需要。 # smtpd_tls_chain_files = /etc/postfix/rsa.pem, /etc/postfix/ecdsa.pem, /etc/postfix/ed25519.pem, /etc/postfix/ed448.pem
您还可以将密钥与证书分开存储,前提是每个密钥都列在对应的证书链之前。将密钥及其关联的证书链存储在单独的文件中不推荐,因为这在密钥轮换过程中容易引发竞争条件,因为无法原子地更新多个文件。
# Postfix ≥ 3.4. # 将密钥与关联的证书分开存储不 # 推荐。 smtpd_tls_chain_files = /etc/postfix/rsakey.pem, /etc/postfix/rsacerts.pem, /etc/postfix/ecdsakey.pem, /etc/postfix/ecdsacerts.pem
以下示例展示了 Postfix 3.3 及更早版本中针对旧算法的配置。在 Postfix ≤ 3.3 中,即使密钥与证书存储在同一文件中,系统仍会读取该文件两次,且在密钥轮换时仍存在(短暂的)竞争条件。而 Postfix ≥ 3.4 在密钥和证书位于同一文件时避免了该竞争条件,但建议使用上文提到的新的 "smtpd_tls_chain_files" 接口。
;
RSA 密钥和证书示例:
/etc/postfix/main.cf: smtpd_tls_cert_file = /etc/postfix/server.pem smtpd_tls_key_file = $smtpd_tls_cert_file
其 DSA 对应项:
/etc/postfix/main.cf: smtpd_tls_dcert_file = /etc/postfix/server-dsa.pem smtpd_tls_dkey_file = $smtpd_tls_dcert_file
其ECDSA对应配置(Postfix ≥ 2.6 + OpenSSL ≥ 1.0.0):
/etc/postfix/main.cf: # 部分客户端不支持 ECDSA,因此您可能仍需 # RSA 证书及私钥。 # smtpd_tls_eccert_file = /etc/postfix/server-ecdsa.pem smtpd_tls_eckey_file = $smtpd_tls_eccert_file
TLS 证书用于仅服务支持匿名加密套件的客户端的服务器:
/etc/postfix/main.cf: # 不推荐:会破坏 TLS 1.3 以及不支持 # 匿名密码套件的客户端。 smtpd_tls_cert_file = none
要验证远程 SMTP 客户端证书,Postfix SMTP 服务器需要信任签发证书的证书颁发机构 (CA) 的证书。这些以 "PEM" 格式存储的证书可以保存在单个 $smtpd_tls_CAfile,或在多个文件中存储,每个文件包含一个CA证书,文件路径为$smtpd_tls_CApath目录。如果使用目录,请务必创建必要的"哈希"链接:
# $OPENSSL_HOME/bin/c_rehash /path/to/directory
$smtpd_tls_CAfile 包含一个或多个受信任的 CA 的证书。该文件在 Postfix 进入可选的 chroot 监狱之前以 root 权限打开,因此无需在 chroot 监狱内部访问。
可以通过 $smtpd_tls_CApath 目录指定额外的受信任 CA,此时证书将从该目录中读取(使用 $mail_owner 权限)从目录中的文件中读取证书。因此,$smtpd_tls_CApath 目录必须在可选的 chroot 监狱内可访问。
当您配置 Postfix SMTP 服务器以请求 客户端证书 时,$smtpd_tls_CAfile 中,以便客户端选择由您信任的 CA 签名的身份。如果未指定 $smtpd_tls_CAfile,则不会发送首选 CA 列表,客户端可以自由选择由任何 CA 签名的身份。许多客户端会使用固定的身份,无论首选CA列表如何,您可能通过将客户端CA证书主要或仅安装在$smtpd_tls_CApath中来减少TLS协商开销。在后一种情况下,无需指定 $smtpd_tls_CAfile。
注意,除非使用客户端证书来允许对 TLS 认证客户端的更大访问权限,否则最好不要要求客户端证书,因为除了增加开销外,某些客户端(尤其是某些情况下 qmail)在请求客户端证书时无法完成 TLS 握手。
示例:
/etc/postfix/main.cf: smtpd_tls_CAfile = /etc/postfix/CAcert.pem smtpd_tls_CApath = /etc/postfix/certs
服务器端前向保密配置 ;
如果您希望充分利用支持前向保密的加密算法,请参阅快速入门部分。完整文档方便地将 Postfix 前向保密支持的所有信息集中在一个地方:什么是前向保密、如何调整设置,以及当 Postfix 使用支持前向保密的密码套件时可以预期看到的内容。
服务器端 TLS 活动日志记录 ;
要获取有关 Postfix SMTP 服务器 TLS 活动的更多信息,您可以将日志级别从 0 到 4 增加。每个日志级别都包含在较低日志级别中记录的信息。
级别 Postfix 2.9 及更高版本 较早版本。 0 禁用 TLS 活动日志记录。 1 仅在 TLS 握手完成时记录摘要消息 — 如果客户端证书验证未被要求,则不记录客户端证书信任链验证错误。 记录摘要消息、对等证书摘要信息,并无条件记录信任链验证错误。 2 在 TLS 协商过程中也记录日志级别。 3 同时记录 TLS 协商过程的十六进制和 ASCII 转储。 4 同时记录 STARTTLS 后的完整传输的十六进制和 ASCII 转储。
仅在出现问题时使用日志级别 3。强烈不建议使用日志级别 4。
示例:
/etc/postfix/main.cf: smtpd_tls_loglevel = 0
要将协议和加密方式以及客户端和签发者的通用名称(CommonName)包含在"Received:"消息头中,请将smtpd_tls_received_header变量设置为true。默认值为 no,因为这些信息不一定可靠。只有最终目的地记录的信息才是可靠的,因为中间服务器可能会修改头部信息。
示例:
/etc/postfix/main.cf: smtpd_tls_received_header = yes
在 Postfix SMTP 服务器中启用 TLS ;
默认情况下,Postfix SMTP 服务器中 TLS 处于禁用状态,因此与普通 Postfix 没有区别。通过设置 "smtpd_tls_security_level = may" 显式启用。
示例:
/etc/postfix/main.cf: smtpd_tls_security_level = may
这样,Postfix SMTP 服务器会向远程 SMTP 客户端宣布支持 STARTTLS,但不要求客户端使用 TLS 加密。
注意:当无特权用户调用 "sendmail -bs" 时,由于无法访问 Postfix SMTP 服务器的私钥,STARTTLS 不会被提供。这是预期行为。
您可以强制使用 TLS,使 Postfix SMTP 服务器宣布支持 STARTTLS 并拒绝接受未加密的邮件,通过设置 "smtpd_tls_security_level = encrypt"。根据RFC 2487,如果 Postfix SMTP 服务器是公开可访问的,则不应应用此设置。此选项默认关闭,仅在特殊情况下使用。
示例:
/etc/postfix/main.cf: smtpd_tls_security_level = encrypt
TLS 还用于"包装器"模式,在此模式下服务器始终使用 TLS,而非声明支持 STARTTLS 并等待远程 SMTP 客户端请求 TLS 服务。部分客户端(如 Outlook [Express])更倾向于使用"包装器"模式。这适用于 OE(Win32 <; 5.0 以及 Win32 >;=5.0 且运行在端口 <;>;25 的情况)以及 OE(5.01 Mac 在所有端口)。
严格不建议在main.cf中使用此模式。若需支持此服务,请在master.cf中启用专用端口,并设置 "-o smtpd_tls_wrappermode=yes"(注意:"="两侧无空格)作为 smtpd(8) 命令行选项。端口 465(提交,以前称为 smtps)是最常见的示例。
示例:
/etc/postfix/master.cf: submissions inet n - n - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes
客户端证书验证
要接收远程 SMTP 客户端证书,Postfix SMTP 服务器必须明确请求一个($smtpd_tls_CAfile 的任何内容也会作为提示发送给客户端,以便从合适的 CA 中选择证书)。遗憾的是,Netscape 客户端在没有匹配的客户端证书时会报错,或向用户提供证书列表供选择。此外,部分 MTA(尤其是某些版本的 qmail)在请求客户端证书时无法完成 TLS 协商,并终止 SMTP 会话。因此,此选项默认关闭。如果您希望使用基于证书的中继功能(例如与permit_tls_clientcerts功能配合),则需要该证书。要求客户端证书的服务器必须首先提供自己的证书。虽然 Postfix 默认向远程 SMTP 客户端提供匿名加密套件,但当 Postfix SMTP 服务器配置为请求客户端证书时,这些加密套件会被自动抑制。
示例:
/etc/postfix/main.cf: smtpd_tls_ask_ccert = yes smtpd_tls_security_level = may
当 TLS 被强制启用时,您还可以通过设置 "smtpd_tls_req_ccert = yes" 来要求所有 TLS 连接必须提供远程 SMTP 客户端证书。此功能意味着 "smtpd_tls_ask_ccert = yes"。当 TLS 未强制执行时,"smtpd_tls_req_ccert = yes" 将被忽略,并记录一个警告。
示例:
/etc/postfix/main.cf: smtpd_tls_req_ccert = yes smtpd_tls_security_level = encrypt
客户端证书验证深度通过 main. cf smtpd_tls_ccert_verifydepth 参数指定。默认验证深度为 9(OpenSSL 的默认值),以兼容 Postfix 2.5 之前的版本,在这些版本中 smtpd_tls_ccert_verifydepth 被忽略。当配置对根 CA 的信任时,无需显式信任由根 CA 签名的中间 CA,除非 $smtpd_tls_ccert_verifydepth 小于感兴趣客户端证书链中的 CA 数量。验证深度为 1 时,仅可验证直接由受信任 CA 签名的证书,所有受信任的中间 CA 需显式配置。验证深度为 2 时,您可以验证由根 CA 或直接中间 CA 签名的客户端(只要客户端正确配置了其中间 CA 证书)。
示例:
/etc/postfix/main.cf: smtpd_tls_ccert_verifydepth = 2
仅支持通过 TLS 进行身份验证
通过未加密通道发送AUTH数据存在安全风险。当要求启用 TLS 层加密("smtpd_tls_security_level = encrypt")时,Postfix SMTP 服务器将在通过 STARTTLS 激活 TLS 层后,才宣布并接受 AUTH。当 TLS 层加密为可选时("smtpd_tls_security_level = may"),仍可能有必要仅在 TLS 激活时提供 AUTH。为了与非 TLS 客户端保持兼容性,默认情况下接受未加密的 AUTH。若要更改此行为,请设置 "smtpd_tls_auth_only = yes"。
示例:
/etc/postfix/main.cf: smtpd_tls_auth_only = no
服务器端 TLS 会话缓存
Postfix SMTP 服务器与远程 SMTP 客户端协商会话,这会消耗部分计算机时间和网络带宽。除 SSLv2 之外的 SSL 协议版本支持恢复缓存会话。这不仅更节省 CPU 和带宽,还能降低延迟,因为恢复会话仅需一次网络往返,而从头创建会话则需要两次往返。
由于 Postfix 使用多个 smtpd(8) 服务进程,内存缓存不足以支持会话复用。客户端每个服务器最多存储一个缓存会话,且极少会重复连接到同一服务器进程。因此,Postfix SMTP 服务器中的会话缓存通常需要共享缓存(Postfix ≥ 2.11 版本中提供了一种替代方案,如下所述)。
为了在多个 smtpd(8) 进程之间共享会话信息,使用会话缓存数据库。您可以指定任何能够存储几个千字节对象且支持顺序操作符的数据库类型。DBM 数据库不适合,因为它们只能存储小型对象。缓存由 tlsmgr(8) 进程维护,因此不存在并发访问问题。会话缓存强烈推荐,因为反复协商 TLS 会话密钥的成本很高。
从 Postfix 2.11 开始,与兼容的 OpenSSL 库(至少 0.9.8h,建议 1.0.0 或更高版本)链接后,Postfix SMTP 服务器支持 RFC 5077 TLS 会话恢复功能,当远程 SMTP 客户端也支持 RFC 5077 时,无需服务器端状态。会话由服务器加密并以会话票据的形式返回给客户端进行存储。当客户端发送有效的会话票据时,服务器对其进行解密并恢复会话,前提是票据和会话均未过期。这使得无需在服务器上分配共享数据库空间即可恢复缓存会话。因此,对于 Postfix ≥ 2.11,smtpd_tls_session_cache_database 参数通常应保持为空。会话缓存可通过将会话缓存超时设置为零来禁用,否则超时时间必须至少为 2 分钟,最多为 100 天。
注意,会话票据仅在客户端禁用 SSLv2 且不使用与 SSLv2 兼容的旧版 HELLO 消息时才能协商。此行为在 Postfix ≥ 2.6 的 SMTP 客户端中默认启用。
示例:
/etc/postfix/main.cf: smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
注意:从版本 2.5 开始,Postfix 在打开此文件时不再使用 root 权限。该文件现在应存储在 Postfix 拥有的 data_directory 目录下。作为迁移辅助措施,若尝试在非 Postfix 目录下打开该文件,系统将重定向至 Postfix 所属的 data_directory 目录,并记录警告信息。
缓存的 Postfix SMTP 服务器会话信息在一定时间后过期。Postfix/TLS 不使用 OpenSSL 的默认值 300 秒,而是使用更长的 3600 秒(即 1 小时)。RFC 2246 建议最大值为 24 小时。
示例:
/etc/postfix/main.cf: smtpd_tls_session_cache_timeout = 3600s
从 Postfix 2.11 开始,此设置不能超过 100 天。如果设置为 ≤ 0,会话缓存将被禁用。如果设置为小于 2 分钟的正值,则使用 2 分钟的最小值。
当 Postfix SMTP 服务器未将 TLS 会话保存到外部缓存数据库时,客户端会话缓存可能无效。为减少客户端资源浪费,可配置 Postfix SMTP 服务器不生成 TLS 会话 ID。默认情况下,Postfix SMTP 服务器始终生成 TLS 会话 ID。此设置可解决与部分 MUA 的已知互操作性问题,并避免与其他 MTA 的潜在互操作性问题。
示例:
smtpd_tls_always_issue_session_ids = no
服务器访问控制
Postfix TLS 支持为 Postfix SMTP 服务器访问控制引入了三项额外功能:
允许远程 SMTP 客户端请求,如果客户端证书指纹或证书公钥指纹(Postfix 2.9 及更高版本)在客户端证书表中列出(参见下方 relay_clientcerts 讨论)。
允许远程 SMTP 客户端请求,如果客户端证书通过信任链验证。适用于仅向受信任客户端颁发证书的私有证书颁发机构(CA)。
使用远程 SMTP 客户端证书指纹或公钥指纹(Postfix 2.9 及更高版本)作为指定的 access(5) 表的查找键。
用于计算客户端证书指纹的摘要算法通过 main. cf smtpd_tls_fingerprint_digest 参数指定。默认算法为sha256,当 Postfix 版本 ≥ 3.6 且compatibility_level 设置为 3.6 或更高时。对于 Postfix ≤ 3.5,默认算法为md5。最佳实践算法现为sha256。哈希函数密码分析的最新进展已导致md5和sha1被弃用,转而采用sha256。然而,只要没有已知的"第二预映像"攻击针对旧算法,在这种情况下使用它们虽然不推荐,但仍可能安全。
permit_tls_all_clientcerts 功能需谨慎使用,因为它可能导致过多的访问权限。仅在特殊 CA 签发客户端证书且该 CA 被列为受信任 CA 时使用此功能。如果其他 CA 被信任,则任何拥有有效客户端证书的用户都将被授权。permit_tls_all_clientcerts 功能可用于专门创建的邮件中继服务器。
然而,建议继续使用permit_tls_clientcerts功能,并通过$relay_clientcerts,因为permit_tls_all_clientcerts不允许控制何时不再使用证书(例如员工离职)。
示例:
# 在 Postfix 2.10 及更高版本中,邮件中继策略 # 建议在 smtpd_relay_restrictions 中指定。 /etc/postfix/main.cf: smtpd_relay_restrictions = permit_mynetworks permit_tls_clientcerts reject_unauth_destination# 较旧的配置将中继控制和垃圾邮件控制合并到 # smtpd_recipient_restrictions。若要使用此示例与 Postfix ≥ # 2.10 指定 "smtpd_relay_restrictions=". /etc/postfix/main.cf: smtpd_recipient_restrictions = permit_mynetworks permit_tls_clientcerts reject_unauth_destination ...其他规则...
示例:Postfix 查找表以 (键, 值) 对的形式存储。由于我们仅需键,值可自由选择,例如用户名或主机名:
/etc/postfix/main.cf: relay_clientcerts = hash:/etc/postfix/relay_clientcerts /etc/postfix/relay_clientcerts: D7:04:2F:A7:0B:8C:A5:21:FA:31:77:E1:41:8A:EE:80 lutzpc.at.home
要从 X.509 证书中提取公钥指纹,您需要从证书中提取公钥,并计算其 DER(ASN.1)编码的适当摘要。使用 OpenSSL,"x509" 命令的 "-pubkey" 选项会始终以 "PEM" 格式提取公钥。我们将结果管道传输到另一个 OpenSSL 命令,该命令将密钥转换为 DER,然后使用 "dgst" 命令计算指纹。
示例:
$ openssl x509 -in cert.pem -noout -pubkey | openssl pkey -pubin -outform DER | openssl dgst -sha256 -c (stdin)= 64:3f:1f:f6:e5:1e:d4:2a:...:8b:fc:09:1a:61:98:b5:bc:7c:60:58
服务器端加密套件控制
Postfix SMTP 服务器支持 5 种不同的加密级别,这些级别由 smtpd_tls_mandatory_ciphers 配置参数指定,该参数确定强制 TLS 加密时所需的最低加密级别。强制 TLS 的默认最低加密级别为"medium",即 128 位加密或更高。smtpd_tls_ciphers 参数(Postfix ≥ 2.6)控制使用机会主义 TLS 时的最低加密级别。在此,Postfix 2015 年中之后的版本默认最低加密级别为"medium",较旧版本为"export"。对于 Postfix 2.6 之前的版本,机会性 TLS 的最低加密级别始终为"export"。
默认情况下,匿名加密套件已启用。当远程 SMTP 客户端请求证书时,它们会自动禁用。如果预期客户端始终验证 Postfix SMTP 服务器证书,您可以通过设置 "smtpd_tls_mandatory_exclude_ciphers = aNULL" 或 "smtpd_tls_exclude_ciphers = aNULL",具体取决于实际需求。无法强制远程 SMTP 客户端验证服务器证书,因此通常无需排除匿名加密套件。
启用强制和机会性 TLS 加密后,Postfix SMTP 服务器在 2015 年中之后的版本中默认禁用 SSLv2 和 SSLv3;较旧版本仅在启用强制 TLS 时禁用 SSLv2。强制性 TLS 协议列表通过 smtpd_tls_mandatory_protocols 配置参数指定。smtpd_tls_protocols 参数(Postfix ≥ 2.6)控制使用机会性 TLS 时的 TLS 协议。
请注意,OpenSSL 库仅支持协议排除(不支持包含)。因此,Postfix 只能排除在 Postfix 软件编写时已知的协议。如果 OpenSSL 库中添加了新协议,则必须修改 Postfix 源代码才能排除这些协议。
对于不是公共互联网 MX 主机的服务器,Postfix 支持不使用 服务器证书 且仅使用 匿名加密套件 的配置。此功能通过显式设置 "smtpd_tls_cert_file = none" 并不过指定 smtpd_tls_dcert_file 或 smtpd_tls_eccert_file。此类配置可能无法与某些客户端兼容,并且需要显式禁用 TLSv1.3。因此,不建议使用此类配置,建议直接配置一个合适的证书。
示例:MSA 要求使用 TLSv1.2 或更高版本,并使用高级加密套件:
/etc/postfix/main.cf: smtpd_tls_cert_file = /etc/postfix/cert.pem smtpd_tls_key_file = /etc/postfix/key.pem smtpd_tls_mandatory_ciphers = high smtpd_tls_mandatory_exclude_ciphers = aNULL, MD5 smtpd_tls_security_level = encrypt # Postfix 3.6 及更高版本推荐的语法: smtpd_tls_mandatory_protocols = >;=TLSv1.2 # 旧语法: smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
对于 Postfix ≥ 3.4,请改为指定一个包含密钥、对应证书以及任何关联签发证书的单一文件,并将 "smtpd_tls_cert_file" 和 "smtpd_tls_key_file" 以及相关的 DSA 和 ECDSA 参数为空。
/etc/postfix/main.cf: smtpd_tls_chain_files = /etc/postfix/rsachain.pem smtpd_tls_cert_file = smtpd_tls_key_file = ...
如果您希望充分利用提供前向保密的加密算法,请参阅快速入门部分。完整文档方便地将 Postfix 前向保密支持的所有信息集中在一个地方:什么是前向保密、如何调整设置,以及当 Postfix 使用支持前向保密的密码套件时可以预期看到的内容。
Postfix 2.8 及更高版本,结合 OpenSSL 0.9.7 及更高版本,允许 TLS 服务器在 TLS 客户端之前选择密码套件偏好列表。此功能仅在 SSLv3 及更高版本中可用,因为在 SSLv2 中,客户端会从服务器提供的列表中选择密码套件。
默认情况下,OpenSSL 服务器会选择客户端最偏好的密码套件(且服务器支持该套件)。在 SSLv3 及更高版本中,服务器可以选择其支持(提供)的客户端最偏好的密码套件。设置 "tls_preempt_cipherlist = yes" 可启用服务器密码套件偏好设置。默认的 OpenSSL 行为在 "tls_preempt_cipherlist = no" 时适用。
虽然服务器密钥套件选择在某些情况下可能导致更安全或性能更高的密钥套件选择,但存在兼容性问题的风险。过去,部分 SSL 客户端曾列出其未正确实现的低优先级密钥。若服务器选择客户端优先级较低的密钥,可能导致客户端实现存在缺陷的密钥被选中。最值得注意的是,Windows 2003 Microsoft Exchange 服务器对 DES-CBC3-SHA 的实现存在缺陷,而 OpenSSL 认为该加密套件比 RC4-SHA 更安全。启用服务器加密套件选择可能导致与 Windows 2003 Microsoft Exchange 客户端的兼容性问题。
其他服务器控制选项
smtpd_starttls_timeout 参数限制了 Postfix SMTP 服务器在 TLS 启动和关闭握手过程中写入和读取操作的时间。
示例:
/etc/postfix/main.cf: smtpd_starttls_timeout = 300s
在 Postfix 2.8 及更高版本中,tls_disable_workarounds 参数指定了一个列表或位掩码,用于禁用默认启用的 OpenSSL 漏洞修复方案。如果 OpenSSL 中默认启用的某个工作绕过方案被发现存在安全风险,或引入了意外的互操作性问题,可能需要禁用这些方案。启用的漏洞修复列表与 OpenSSL 版本相关。请参阅 tls_disable_workarounds 参数的文档以获取支持的值列表。
示例:
/etc/postfix/main.cf: tls_disable_workarounds = 0xFFFFFFFF tls_disable_workarounds = CVE-2010-4180
在 Postfix ≥ 2.11 中,tls_ssl_options 参数指定要启用的 OpenSSL 选项的列表或位掩码。指定以下命名选项中的一个或多个,或在 ssl.h 文件中与运行时 OpenSSL 库对应的十六进制位掩码。虽然关闭所有漏洞修复(见上文)可能是合理的,但尝试启用所有功能并非明智之举。请参阅 tls_ssl_options 参数文档以获取支持值的列表。
示例:
/etc/postfix/main.cf: tls_ssl_options = no_ticket, no_compression
仅在需要严格控制该功能(例如应对新漏洞或严重兼容性问题)时,才应通过十六进制掩码启用功能。Postfix 不保证掩码位与旧版本的向后兼容性。在某个版本中通过掩码启用的功能,可能在后续版本中通过其他方式启用,此时掩码位将被忽略。因此,使用十六进制掩码仅作为临时措施,直至 Postfix 或 OpenSSL 发布新版本提供更优解决方案。
SMTP 客户端特定设置
本节涵盖的内容:
- 在 SMTP/LMTP 客户端中配置 TLS
- 客户端 TLS 活动日志记录
- 客户端证书和私钥配置
- 客户端 TLS 连接复用
- 客户端 TLS 会话缓存
- 客户端 TLS 限制
- 按目标的 TLS 策略
- 发现支持 TLS 的服务器
- 服务器证书验证深度
- 客户端加密套件控制
- 客户端提交(原名为 smtps)支持
- 其他客户端控制 ;
在 SMTP/LMTP 客户端中配置 TLS ;
与 Postfix SMTP 服务器类似,Postfix SMTP/LMTP 客户端实现了多个 TLS 安全级别。这些级别在以下各节中进行了详细描述。
none
may
加密
dane
仅dane
指纹
验证
安全
LMTP 交付代理中的 TLS 支持 ;
smtp(8) 和 lmtp(8) 传递代理由一个双用途程序实现。具体来说,下面描述的所有 TLS 功能均适用于 SMTP 和 LMTP,只需将每个参数名称前的 "smtp_" 前缀替换为 "lmtp_"。
Postfix LMTP 交付代理可与监听 UNIX 域套接字的 LMTP 服务器进行通信。当服务器证书验证启用且服务器监听 UNIX 域套接字时,$myhostname 参数用于设置 TLS 验证的 nexthop 和 hostname。
注意:在 UNIX 域套接字或回环 TCP 连接上对 LMTP 流量进行机会加密是没有意义的。TLS 在此上下文中仅在强制要求时有用,通常是为了允许服务器或客户端中至少一方验证另一方。当客户端和服务器均支持时,"null" 密码级别在此上下文中可能合适。"null" 密码提供认证但不提供加密。
不使用 TLS 加密 ;
在"none" TLS 安全级别下,TLS 加密被禁用。这是默认安全级别,可通过设置"smtp_tls_security_level = none"显式配置。对于 LMTP,请使用对应的"lmtp_"参数。
针对每个目的地的设置可能覆盖此默认设置,此时 TLS 将被选择性使用,仅对明确配置为使用 TLS 的目的地启用。
您可以对部分目的地禁用 TLS,同时保持对其他目的地的启用。通过 Postfix TLS 策略表,将安全级别设置为"none"。
机会主义 TLS ;
在 "may" TLS 安全级别下,TLS 加密是 机会主义的。如果服务器支持 STARTTLS ESMTP 功能,则 SMTP 交易将被加密。否则,消息以明文形式发送。机会主义 TLS 可通过设置 "smtp_tls_security_level = may" 进行配置。对于 LMTP,请使用对应的 "lmtp_" 参数。
"smtp_tls_ciphers"和"smtp_tls_protocols" 配置参数(Postfix ≥ 2.6)用于控制机会主义 TLS 中使用的加密级别和协议。在较早的 Postfix 版本中,机会主义 TLS 始终使用加密级别 "export" 并启用所有协议。
使用机会性 TLS 时,即使服务器证书不受信任或名称不匹配,邮件投递仍会继续。当机会性 TLS 会话的 TLS 握手失败时,Postfix SMTP 客户端不会放弃邮件投递,而是尝试禁用 TLS 重新进行交易。尝试未加密连接可使邮件投递到具有不兼容服务器 TLS 实现的站点。
机会主义加密从未用于 UNIX 域套接字上的 LMTP。通信通道在没有 TLS 时已加密,因此 TLS 的唯一潜在好处是身份验证。不要为 UNIX 域套接字上的 LMTP 交付配置机会主义 TLS。仅在 encrypt 安全级别或更高时为 UNIX 域套接字上的 LMTP 配置 TLS。尝试配置 LMTP 会话的opportunistic加密将被忽略,并在邮件日志中记录警告。
您可以仅对选定的目的地启用opportunistic TLS。通过 Postfix TLS 策略表,指定"may"安全级别。
这是 TLS 保护的 SMTP 会话中最常见的安全级别,更高的安全级别通常不可用,如果需要,通常仅在每个目的地基础上进行配置。请参阅上文关于 TLS 限制 的部分。
示例:
/etc/postfix/main.cf: smtp_tls_security_level = may
强制 TLS 加密 ;
在 "encrypt" TLS 安全级别下,消息仅通过 TLS 加密会话发送。除非远程 SMTP 服务器支持 STARTTLS ESMTP 功能,否则 SMTP 交易将被中止。如果未找到合适的服务器,消息将被延迟。强制 TLS 加密可通过设置 "smtp_tls_security_level = encrypt" 进行配置。即使启用了 TLS 加密,即使服务器证书不受信任或名称不正确,邮件投递仍会继续。对于 LMTP,请使用相应的 "lmtp_" 参数。
在此安全级别及更高级别下,smtp_tls_mandatory_protocols 和 smtp_tls_mandatory_ciphers 配置参数决定了足够安全的 SSL 协议版本列表及最低加密强度。若协议或加密要求未满足,邮件传输将被中止。这些参数的文档包含有用的互操作性和安全指南。
尽管强制 TLS 加密可消除被动监听攻击,但其不适合作为向公共互联网发送邮件的默认安全级别。部分 MX 主机完全不支持 TLS,而部分支持 TLS 的主机存在实现缺陷。在向互联网发送邮件的主机上,不应将强制 TLS 加密设置为默认安全级别。
您可以仅对特定目标启用强制 TLS 加密。通过 Postfix TLS 策略表,指定 "encrypt" 安全级别。
示例:
在下例中,通过对应 MX 主机发送至 example.com 及其子域的流量始终使用 TLS。SSLv2 协议将被禁用(默认设置为 smtp_tls_mandatory_protocols,该设置排除 SSLv2+3)。默认情况下,所有"加密"安全级别的会话仅使用高强度或中强度(即 128 位或更高)的加密算法。
/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/postfix/tls_policy: example.com encrypt .example.com encrypt
在以下示例中,通过 MSA "[example.net]:587" 配置了安全消息提交。TLS 会话在不进行身份验证的情况下加密,因为此 MSA 没有可接受的证书。此 MSA 已知支持 "TLSv1" 和 "高" 级别的密码套件,因此通过 策略表 选择这些选项。
注意:策略表查找键是收件域中下一跳的精确指定,transport(5) 表或 relayhost 参数,包括任何包围的方括号和可选端口。请确保一致性:后缀 ":smtp" 或 ":25" 或不带端口后缀会导致不同的策略表查找键,尽管它们在功能上等同于下一跳规范。对于所有目的地,最多使用其中一种形式。下文中的策略表包含多个键,以防传输表条目未一致指定。
/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/services: submission 587/tcp msa # 邮件提交 /etc/postfix/tls_policy: # Postfix ≥ 3.6 "protocols" 语法 [example.net]:587 encrypt protocols=>;=TLSv1.2 ciphers=high # 旧版 "protocols" 语法 [example.net]:msa encrypt protocols=!SSLv2:!SSLv3 ciphers=high
DANE TLS 认证。
Postfix SMTP 客户端支持基于 DANE TLSA (RFC 6698, RFC 7671,RFC 7672)记录。包括可选的"dane"级别和强制性的"dane-only"级别。
"dane"级别是opportunistic TLS 的更强形式,当目标域使用 DNSSEC 发布其 MX 主机的 DANE TLSA 记录时,可抵御中间人攻击和降级攻击。如果远程 SMTP 服务器具有"可用的"(参见 RFC 7672 第 3 节)DANE TLSA 记录,则服务器连接将被认证。当 DANE 认证失败时,不会回退到未认证或明文传输。
如果为某个远程 SMTP 服务器发布了 TLSA 记录(暗示支持 TLS),但所有记录均因不支持的参数或数据格式错误而"不可用",Postfix SMTP 客户端将使用 强制 未认证的 TLS。否则,当未发布任何 TLSA 记录时,Postfix SMTP 客户端的行为与 may 相同。
TLSA 记录必须发布在 DNSSEC 验证的 DNS 区域中。任何未通过 DNSSEC 保护的 DNS 区域中的 TLSA 记录将被忽略。Postfix SMTP 客户端不会查找与 MX 主机关联的 TLSA 记录,如果该 MX 主机的 "A" 或 "AAAA" 记录位于 "不安全" 的 DNS 区域中。此类查找已被观察到会导致与实现不佳的 DNS 服务器之间的互操作性问题,并且无论如何都不应期望此类查找能产生"安全"结果,因为这需要在主机记录与关联的"_25._tcp"子 TLSA 记录之间配置一个非常不可能存在的 DLV DNS 信任锚点。
"dane-only"级别是一种基于DANE公钥基础设施(PKI)的安全通道 TLS。如果存在可用的TLSA记录,则用于验证远程SMTP服务器。否则,或当服务器证书验证失败时,通过该服务器进行的传输将临时失败。
在两个安全级别下,目标的 TLS 策略均通过 DNSSEC 验证的 TLSA 记录获取。要使 TLSA 策略生效,目标域所在的 DNS 区域必须已签名,且 Postfix SMTP 客户端的操作系统必须配置为将 DNS 查询发送到能够验证签名记录的递归 DNS 服务器。每个 MX 主机的 DNS 区域也需要签名,并需要发布 DANE TLSA 记录(参见 RFC 7672 第 3 节),以指定如何验证该 MX 主机的 TLS 证书。
TLSA 记录不会覆盖正常的 SMTP MX 主机选择算法。如果部分 MX 主机支持 TLSA 而其他主机不支持,则 TLS 安全性会因交付而异。域所有者需合理配置其 MX 主机和 DNS。要配置 Postfix SMTP 客户端以支持 DNSSEC 查询,请参阅 smtp_dns_support_level main.cf 参数。tls_dane_digests 参数控制支持的摘要列表。
如RFC 7672第3节所述,证书用途"0"和"1"(旨在"限制"现有Web-PKI信任)不支持MTA到MTA的SMTP。相反,使用"0"和"1"的TLSA记录将被视为"不可用"。
Postfix SMTP客户端仅支持证书用途"2"和"3"。从Postfix 3.2开始,对证书用途"1"静默映射为"3"的实验性支持已被移除。
当为远程 SMTP 服务器获取可用的 TLSA 记录时,Postfix SMTP 客户端会在 SSL 客户端初始化消息中发送 SNI TLS 扩展。这可能有助于远程 SMTP 服务器履行其承诺,提供与 TLSA 记录匹配的证书。
在协议和密码套件选择过程中,"dane"安全级别被视为"强制"TLS安全级别,弱密码套件和协议将被禁用。由于DANE用于验证服务器证书,"aNULL"密码套件在此级别会被透明排除,无需手动配置。RFC 7672 (DANE) TLS 认证在 Postfix 2.11 及更高版本中可用。
当 DANE TLSA 记录指定了信任锚 (TA) 证书(即签发 CA)时,用于验证服务器证书的 peername 的策略无条件为 "nexthop, hostname"。从 DNSSEC 验证的 MX 查询中获取的 nexthop 域和主机名均可防止伪造,且服务器证书必须包含其中至少一个名称。
当DANE TLSA记录指定一个终端实体(EE)证书(即实际服务器证书)时,与下文所述的指纹安全级别相同,不进行名称验证或证书过期检查。服务器证书(或其公钥)要么与DANE记录匹配,要么不匹配。服务器管理员应优先发布此类EE记录,而非其他类型。
Postfix SMTP 客户端支持 DANE 的先决条件是:
- 一个在编译时支持 TLS SNI 扩展和 "SHA-2" 消息摘要的 OpenSSL 库。
- 一个在编译时支持 DNSSEC 的 DNS 解析库。在较旧系统上编译的 Postfix 二进制文件即使部署在具有更新解析库的系统上,也不会支持 DNSSEC。
- "smtp_dns_support_level" 必须设置为 "dnssec"。
- "smtp_host_lookup"参数必须包含"dns"。
- 一个支持 DNSSEC 验证的递归解析器(见下文注释)。
上述客户端先决条件不适用于 Postfix SMTP 服务器。只要它支持 TLSv1 且其 TLSA 记录发布在 DNSSEC 签名的区域中,它将支持 DANE。要接收多个域的 DANE 保护邮件,请使用相同的主机名将服务器添加到每个域的 MX 记录中。Postfix SMTP 服务器支持 SNI(Postfix 3.4 及更高版本),通过 tls_server_sni_maps 配置。
注意:Postfix SMTP 客户端的内部 stub DNS 解析器支持 DNSSEC,但其自身不验证 DNSSEC 记录,而是将 DNSSEC 验证委托给操作系统配置的递归 DNS 解析器。Postfix DNS 客户端依赖于与解析器缓存之间的安全通道来确保 DNSSEC 完整性,但不支持 TSIG 来保护自身与名称服务器之间的传输通道。因此,强烈建议(否则DANE安全保证无效)每个MTA运行一个本地DNSSEC验证递归解析器(nlnetlabs.nl提供的"unbound"是一个合理选择),并监听回环接口,同时系统应配置为仅使用此本地名称服务器。若需转发查询,本地名称服务器可将请求转发至另一主机上的上游递归解析器。
注意:当操作系统中的递归名称服务器非本地时,启用 EDNS0 扩展 DNS 数据包大小并在 DNS 请求中设置 DNSSEC "DO" 位,或在名称服务器响应中返回新的 DNSSEC 专用记录,可能导致旧版或存在缺陷的防火墙和 DNS 服务器实现出现问题。因此,Postfix 默认不启用 DNSSEC。由于 MX 查询在安全级别确定之前发生,因此除非设置 "smtp_dns_support_level = dnssec",否则所有目标的 DANE 支持均被禁用。要选择性启用 DNSSEC 查询,请定义一个新的专用传输,并在 master.cf 中,并将选定的域名路由到该传输。如果 DNSSEC 对于这些域名足够可靠,您可以通过修改全局 smtp_dns_support_level。
示例:为选定目的地启用"dane"安全级别,默认使用机会性 TLS。这是早期采用者的推荐配置。
;
- "example.com"目的地使用 DANE,但如果未找到 TLSA 记录或记录不可用,邮件将被延迟。
"example.org" 目的地在可能的情况下使用 DANE,但如果未找到 TLSA 记录,则使用机会性 TLS。 indexed = ${default_database_type}:${config_directory}/ # # 默认:使用无 DNSSEC 查询的opportunistic TLS。 # smtp_tls_security_level = may smtp_dns_support_level = enabled # # 针对每个目的地的 TLS 策略 # smtp_tls_policy_maps = ${indexed}tls_policy # # default_transport = smtp,但某些目的地特殊: # transport_maps = ${indexed}transport
transport: example.com dane example.org dane
tls_policy: example.com dane-only
master.cf: dane unix - - n - - smtp -o smtp_dns_support_level=dnssec -o smtp_tls_security_level=dane
证书指纹验证 ;
在 指纹 安全级别下,不使用或要求任何受信任的证书颁发机构。证书信任链、过期日期等信息均不进行验证。相反,smtp_tls_fingerprint_cert_match 参数或 policy 表中的 "match" 属性列出了远程 SMTP 服务器证书指纹或公钥指纹。证书指纹验证功能在 Postfix 2.5 及更高版本中可用,公钥指纹支持在 Postfix 2.9 及更高版本中可用。
如果证书指纹以安全方式交换,这是最强的,但也是最不具可扩展性的安全级别。管理员需要安全地收集每个对等服务器 X.509 证书的指纹,将其存储到本地文件中,并在对等服务器的公钥证书发生变化时更新此本地文件。如果使用公钥指纹代替整个证书的指纹,即使证书续签后,指纹仍保持有效,前提是用于获取新证书的公钥/私钥对保持不变。
指纹验证可能适用于通过互联网连接少量分支机构的 SMTP "VPN",或与中央邮件枢纽的加密连接。若远程 SMTP 服务器由第三方管理且其公钥证书会定期更新而未与验证站点提前协调,该方案效果不佳。
用于计算指纹的摘要算法由smtp_tls_fingerprint_digest参数选择。在policy表中,多个指纹可通过"|"分隔符在单个匹配属性中组合,或使用多个匹配属性。由于":"字符出现在每个指纹(十六进制)数字之间,因此不作为分隔符使用。
默认算法为 sha256,当 Postfix ≥ 3.6 且 compatibility_level 设置为 3.6 或更高时;当 Postfix ≤ 3.5 时,默认算法为 md5。最佳实践算法现为sha256。哈希函数密码分析的最新进展已导致md5和sha1被弃用,转而采用sha256。然而,只要没有已知的"第二预映像"攻击针对旧算法,在这种情况下使用它们虽然不推荐,但仍可能安全。
示例:使用内部邮件中继的指纹 TLS 安全设置。列出了两个匹配的指纹。relayhost 可能是由负载均衡器后端的多台物理主机组成,每台主机都有自己的私钥/公钥和自签名证书。或者,单个relayhost可能正在从一组私钥/公钥切换到另一组,且在切换前两组密钥均被信任。
relayhost = [mailhub.example.com] smtp_tls_security_level = fingerprint smtp_tls_fingerprint_digest = sha256 smtp_tls_fingerprint_cert_match = 51:e9:af:2e:1e:40:1f:de:64:...:30:35:2d:09:16:31:5a:eb:82:76 b6:b4:72:34:e2:59:cd:fb:c2:...:63:0d:4d:cc:2c:7d:84:de:e6:2f
示例:证书指纹验证与选定目标。如上例所示,我们展示了两个匹配的指纹:
/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy smtp_tls_fingerprint_digest = sha256
/etc/postfix/tls_policy: example.com 指纹 match=51:e9:af:2e:1e:40:1f:de:...:35:2d:09:16:31:5a:eb:82:76 匹配=b6:b4:72:34:e2:59:cd:fb:...:0d:4d:cc:2c:7d:84:de:e6:2f
要从X.509证书中提取公钥指纹,您需要从证书中提取公钥,并计算其DER(ASN.1)编码的适当摘要。使用OpenSSL时,"x509"命令的"-pubkey"选项会始终以"PEM"格式提取公钥。我们将结果管道传输到另一个 OpenSSL 命令,该命令将密钥转换为 DER,然后使用 "dgst" 命令计算指纹。
示例:
$ openssl x509 -in cert.pem -noout -pubkey | openssl pkey -pubin -outform DER | openssl dgst -sha256 -c (stdin)= 64:3f:1f:f6:e5:1e:d4:2a:56:...:09:1a:61:98:b5:bc:7c:60:58
强制服务器证书验证 ;
在verify TLS安全级别下,仅在远程SMTP服务器证书有效(未过期或被撤销,且由受信任的证书颁发机构签名)且服务器证书名称与已知模式匹配时,才通过TLS加密会话发送消息。强制服务器证书验证可通过设置 "smtp_tls_security_level = verify" 进行配置。smtp_tls_verify_cert_match 参数可覆盖默认的 "主机名" 证书名称匹配策略。通常仅在针对 安全通道 目的地时才需调整匹配策略。对于 LMTP,请使用对应的 "lmtp_" 参数。
如果服务器证书链受信任(参见 smtp_tls_CAfile 和 smtp_tls_CApath),则使用证书 SubjectAlternativeName 扩展中的任何 DNS 名称来验证远程 SMTP 服务器名称。如果未指定 DNS 名称,则检查证书的 CommonName。如果希望强制加密但不验证服务器证书,请参阅 上方。
在 Postfix ≥ 2.11 中,"smtp_tls_trust_anchor_file" 参数或更常见的对应的按目的地设置的 "tafile" 属性可选地修改信任链验证。如果该参数不为空,CAfile 和 CApath 中指定的根 CA 将不再被信任。相反,Postfix SMTP 客户端仅信任由所选文件中包含的信任锚之一签名的证书链。指定的信任锚证书和公钥不受过期限制,且无需是(自签名)根 CA。它们可以是中间证书。因此,这些证书也可能出现在远程 SMTP 服务器呈现的信任链的中间位置,任何未受信任的签发父证书将被忽略。
尽管强制证书信任链和主体名称验证可消除"中间人"等攻击,但将其作为默认互联网邮件传输策略并不现实。部分 MX 主机不支持 TLS,且大量启用 TLS 的 MTA 使用自签名证书或由私有证书颁发机构签名的证书。在向互联网传输邮件的机器上,不应将强制服务器证书验证设置为默认策略。
若您确定仅连接至支持RFC 2487且能提供可验证服务器证书的服务器,则将强制服务器证书验证设为默认安全级别可能是合适的。例如,客户端将所有邮件发送至提供必要 STARTTLS 支持的中央邮件中继服务器。在此类场景中,通常可改用 secure-channel 配置。
您可以仅对特定目的地启用强制服务器证书验证。通过 Postfix TLS 策略表,指定 "verify" 安全级别。
示例:
在此示例中,Postfix SMTP 客户端对发往 example.com 域的所有流量进行加密。对等主机名经过验证,但验证易受 DNS 响应伪造攻击。发往 example.com 收件人的邮件使用 "high" 级加密算法。
/etc/postfix/main.cf: 索引 = ${default_database_type}:${config_directory}/ smtp_tls_CAfile = ${config_directory}/CAfile.pem smtp_tls_policy_maps = ${indexed}tls_policy /etc/postfix/tls_policy: example.com verify ciphers=high
安全服务器证书验证 ;
在安全 TLS安全级别下,消息仅通过安全通道 TLS会话发送,且DNS防伪造服务器证书验证成功。若未找到合适服务器,消息将被延迟。Postfix 的安全通道可通过设置 "smtp_tls_security_level = secure" 进行配置。smtp_tls_secure_cert_match 参数可覆盖默认的 "nexthop, dot-nexthop" 证书匹配策略。对于 LMTP,请使用对应的 "lmtp_" 参数。
如果服务器证书链受信任(参见 smtp_tls_CAfile 和 smtp_tls_CApath),则使用证书扩展中的 SubjectAlternativeName 中的任何 DNS 名称来验证远程 SMTP 服务器名称。如果未指定 DNS 名称,则检查 CommonName。如果您希望强制加密但不验证服务器证书,请参阅 上方。
在 Postfix ≥ 2.11 中,"smtp_tls_trust_anchor_file" 参数或更常见的对应的按目的地设置的 "tafile" 属性可选地修改信任链验证。如果该参数不为空,CAfile 和 CApath 中指定的根 CA 将不再被信任。相反,Postfix SMTP 客户端仅信任由所选文件中包含的信任锚之一签名的证书链。指定的信任锚证书和公钥不受过期限制,且无需是(自签名)根 CA。它们可以是中间证书。因此,这些证书也可能出现在远程 SMTP 服务器呈现的信任链的中间位置,任何未受信任的签发父证书将被忽略。
尽管强制安全服务器证书验证可消除"中间人"攻击等威胁,但其不适合作为默认互联网邮件传输策略。部分 MX 主机不支持 TLS,且相当比例的 TLS 启用型 MTA 使用自签名证书或由私有证书颁发机构签名的证书。在向互联网传输邮件的机器上,不应将安全 TLS 验证设置为默认策略。
若您确定仅连接至支持RFC 2487且能提供可验证服务器证书的服务器,则将强制安全服务器证书验证设为默认安全级别可能是合适的。例如,一个将所有邮件发送至提供必要 STARTTLS 支持的中央邮件中继站的客户端。
您可以仅对特定目标启用安全 TLS 验证。通过 Postfix TLS 策略表,指定 "secure" 安全级别。
示例:
不覆盖transport(5)表的TLS安全通道:
Postfix SMTP 客户端将加密所有流量,并验证目标名称不受伪造 DNS 响应的影响。仍使用 MX 查找来查找 example.com 的 SMTP 服务器主机名,但这些主机名在检查服务器证书中的名称时不会被使用。相反,要求是 example. com 的 MX 主机必须拥有主题名称为 example.com 或其子域的受信任证书,请参阅 smtp_tls_secure_cert_match 参数的文档。
相关域名 example.co.uk 和 example.co.jp 与主域名 example.com 托管在相同的 MX 主机上,且流量通过验证服务器证书中的主域名 example.com 进行加密。这使服务器管理员无需让 CA 签发包含所有二级域名的证书。缺点是,希望与二级域名建立安全连接的客户端需要显式配置 TLS 策略表 条目。
注意,处理相关域名有两种方式。第一种是使用每个域名的默认路由,但通过策略表条目覆盖预期证书主体名称。第二种方法是覆盖传输表中的下一跳,并使用单个策略表条目来处理共同的下一跳。我们选择第一种方法,因为它在域所有权发生变化时效果更好。使用第二种方法,邮件会安全地发送到错误的目的地,而使用第一种方法,身份验证失败,邮件留在本地队列中。在大多数情况下,第一种方法更合适。
;
/etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAfile.pem smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/postfix/transport: /etc/postfix/tls_policy: example.com 安全 example.co.uk 安全 匹配=example.com:.example.com example.co.jp 安全 匹配=example.com:.example.com
通过 transport(5) 表覆盖的 TLS 安全通道:
;
在此情况下,发往example.com及其相关域名的流量将被发送到单一逻辑网关(为避免单点故障,其名称可能解析为一个或多个负载均衡器地址,或多个物理主机的联合地址)。通过网关 IP 地址可达的所有物理主机在其证书中都列出了逻辑网关名称。
/etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAfile.pem transport_maps = hash:/etc/postfix/transport smtp_tls_policy_maps = hash:/etc/postfix/tls_policy /etc/postfix/transport: example.com smtp:[tls.example.com] example.co.uk smtp:[tls.example.com] example.co.jp smtp:[tls.example.com] /etc/postfix/tls_policy: [tls.example.com] secure match=tls.example.com
客户端 TLS 活动日志记录 ;
要获取有关 Postfix SMTP 客户端 TLS 活动的更多信息,您可以将日志级别从 0 增加到 4。每个日志级别都包含在较低日志级别中记录的信息。
级别 Postfix 2.9 及更高版本 较早版本。 0 禁用 TLS 活动日志记录。 1 仅在 TLS 握手完成时记录摘要消息 — 如果不需要验证服务器证书,则不记录远程 SMTP 服务器证书信任链验证错误。 记录摘要消息并无条件记录信任链验证错误。 2 同时记录 TLS 协商过程中的日志级别。 3 同时记录 TLS 协商过程的十六进制和 ASCII 转储。 4 同时记录 STARTTLS 后的完整传输的十六进制和 ASCII 转储。 示例:
/etc/postfix/main.cf: smtp_tls_loglevel = 0
客户端证书和私钥配置 ;
除非您必须向一个或多个服务器提供客户端 TLS 证书,否则请勿配置 Postfix SMTP 客户端证书。客户端证书通常不需要,且可能在无需它们即可正常工作的配置中引发问题。推荐设置为保留默认值:
smtp_tls_cert_file = smtp_tls_dcert_file = smtp_tls_key_file = smtp_tls_dkey_file = # Postfix ≥ 2.6 smtp_tls_eccert_file = smtp_tls_eckey_file = # Postfix ≥ 3.4 smtp_tls_chain_files =
使用默认设置的最佳方式是,如果存在上述参数,请在 main.cf 中注释掉这些参数。
在 TLS 启动协商过程中,Postfix SMTP 客户端可能会向远程 SMTP 服务器提供证书。浏览器通常允许用户从与远程 SMTP 服务器指定的 CA 名称匹配的证书中进行选择。Postfix SMTP 客户端目前尚未提供在运行时从多个候选证书中选择的机制,且仅支持单组证书(每个公钥算法最多一个)。
支持 RSA、DSA 和 ECDSA(Postfix ≥ 2.6)证书。您可以同时配置这三种证书,此时使用的密码套件决定呈现哪个证书。
Postfix SMTP 客户端可以使用与 Postfix SMTP 服务器相同的密钥/证书对。如果需要呈现证书,它必须以"PEM"格式存储。私钥不得加密,即:必须无需密码即可访问。证书和私钥两部分可以存储在同一个文件中。
使用 OpenSSL 1.1.1 和 Postfix ≥ 3.4 时,还可配置 Ed25519 和 Ed448 证书。无需添加两组额外的密钥和证书参数,Postfix 3.4 引入了新参数 "smtp_tls_chain_files",该参数可一次性指定所有配置的证书,并一次性处理包含密钥和关联证书的文件,从而避免密钥轮换时的潜在竞争条件。
要使远程 SMTP 服务器能够验证 Postfix SMTP 客户端证书,必须将签发证书的 CA 证书提供给服务器。您应将所需证书包含在客户端证书文件中,先添加客户端证书,再添加签发 CA(自下而上顺序)。
示例:证书 "client.example.com" 由 "intermediate CA" 签发,而 "intermediate CA" 自身由 "root CA" 签发。以"root"超级用户身份创建 client.pem 文件:
# umask 077 # cat client_key.pem client_cert.pem intermediate_CA.pem >; chain.pem
在此提供的 Postfix SMTP 客户端证书必须可作为 SSL 客户端证书使用,并通过 "openssl verify -purpose sslclient ..." 测试。
信任根 CA 的服务器已本地存储根 CA 证书,因此无需在此包含根 CA 证书。将其从 "chain.pem" 文件中省略可减少 TLS 交换的开销。
若要让 Postfix SMTP 客户端接受由这些 CA 签发的远程 SMTP 服务器证书,请将根证书附加到 $smtp_tls_CAfile 或将其安装在 $smtp_tls_CApath 目录中。
示例:Postfix ≥ 3.4 一体化链文件。一个或多个链文件,每个文件以密钥开头,紧跟对应的证书及任何额外签发者证书。单个文件可包含多个 (密钥, 证书, [链]) 序列,每种算法对应一个序列。通常建议将每种算法的链保存在独立文件中。大多数用户可能只会部署一个 RSA 链,但使用 OpenSSL 1.1.1 时,可以部署多达五个链,分别用于 RSA、ECDSA、ED25519、ED448 以及已废弃的 DSA。
# Postfix ≥ 3.4。首选配置接口。每个文件 # 以私钥开头,随后是对应的 # 证书,以及任何中间颁发者证书。 # smtp_tls_chain_files = /etc/postfix/rsa.pem, /etc/postfix/ecdsa.pem, /etc/postfix/ed25519.pem, /etc/postfix/ed448.pem
您还可以将密钥与证书分开存储,前提是每个密钥都列在对应的证书链之前。将密钥及其关联的证书链存储在单独的文件中不推荐,因为这在密钥轮换过程中容易引发竞争条件,因为无法原子地更新多个文件。
# Postfix ≥ 3.4. # 将密钥与关联的证书分开存储不 # 推荐。 smtp_tls_chain_files = /etc/postfix/rsakey.pem, /etc/postfix/rsacerts.pem, /etc/postfix/ecdsakey.pem, /etc/postfix/ecdsacerts.pem
以下示例展示了 Postfix 3.3 及更早版本中针对特定算法的配置。在 Postfix ≤ 3.3 中,即使密钥与证书存储在同一文件中,系统仍会读取该文件两次,且在密钥轮换时仍存在(短暂的)竞争条件。而 Postfix ≥ 3.4 在密钥和证书位于同一文件时避免了该竞争条件,但建议使用上文提到的新的 "smtp_tls_chain_files" 接口。
;
RSA 密钥和证书示例:
/etc/postfix/main.cf: smtp_tls_cert_file = /etc/postfix/client.pem smtp_tls_key_file = $smtp_tls_cert_file
其 DSA 对应参数:
/etc/postfix/main.cf: smtp_tls_dcert_file = /etc/postfix/client-dsa.pem smtp_tls_dkey_file = $smtp_tls_dcert_file
其 ECDSA 对应参数(Postfix ≥ 2.6 + OpenSSL ≥ 1.0.0):
/etc/postfix/main.cf: smtp_tls_eccert_file = /etc/postfix/client-ecdsa.pem smtp_tls_eckey_file = $smtp_tls_eccert_file
为了验证远程 SMTP 服务器证书,Postfix SMTP 客户端需要信任签发证书的证书颁发机构 (CA) 的证书。这些以 "pem" 格式存储的证书可以保存在单个 $smtp_tls_CAfile,或存储在多个文件中,每个文件包含一个CA证书,文件路径为$smtp_tls_CApath目录下。如果使用目录,请务必创建必要的"哈希"链接:
# $OPENSSL_HOME/bin/c_rehash /path/to/directory
$smtp_tls_CAfile 包含一个或多个受信任的 CA 的证书。该文件在 Postfix 进入可选的 chroot 监狱之前以 root 权限打开,因此无需在 chroot 监狱内部访问。
可以通过 $smtp_tls_CApath 目录指定额外的受信任 CA,此时证书将从该目录中读取(使用 $mail_owner 权限)从目录中的文件中读取证书。因此,$smtp_tls_CApath 目录需要在可选的 chroot 监狱内可访问。
在 $smtp_tls_CAfile 和 $smtp_tls_CApath 是一个空间与时间的权衡。如果存在大量受信任的 CA,将所有 CA 预加载到内存中的成本可能无法通过在需要证书时减少访问时间来抵消。
示例:
/etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/CAcert.pem smtp_tls_CApath = /etc/postfix/certs
客户端 TLS 连接复用
历史上,Postfix SMTP 客户端支持每个明文连接发送多个邮件。Postfix 3.4 引入了对每个 TLS 加密连接发送多个邮件的支持。每个连接发送多个邮件可提升邮件投递性能,尤其对于那些对不合并投递的客户端进行流量限制的目的地。
要启用每个 TLS 连接发送多个邮件,请指定:
/etc/postfix/main.cf: smtp_tls_connection_reuse = yes
或者,在 smtp_tls_policy_maps 条目中指定属性 "connection_reuse=yes"。
TLS 连接复用的实现依赖于与传输明文 SMTP 邮件相同的 scache(8) 服务,以及与 tlsproxy(8) 守护进程,并依赖于 qmgr(8) 守护进程提供的相同提示。请参阅"Postfix 连接缓存"以了解底层连接复用基础设施的详细描述。
初始 SMTP 握手:
smtp(8) ->; 远程 SMTP 服务器
复用 SMTP/TLS 连接,或建立新的 SMTP/TLS 连接:
smtp(8) ->; tlsproxy(8) ->; 远程 SMTP 服务器
缓存的 SMTP/TLS 连接:
scache(8) ->; tlsproxy(8) ->; 远程 SMTP 服务器
从 Postfix 3.4 开始,TLS 连接复用默认处于禁用状态。一旦对整体性能的影响得到明确,此设置可能会发生变化。
客户端 TLS 会话缓存
远程 SMTP 服务器与 Postfix SMTP 客户端会协商一个会话,这会消耗一些计算机时间和网络带宽。默认情况下,此会话信息仅缓存在实际使用该会话的 smtp(8) 进程中,并在进程终止时丢失。为了在多个smtp(8)进程之间共享会话信息,可以使用持久化会话缓存。您可以指定任何能够存储几千字节对象且支持序列操作符的数据库类型。DBM 数据库不适合,因为它们只能存储小型对象。缓存由tlsmgr(8)进程维护,因此不存在并发访问问题。会话缓存强烈推荐,因为反复协商 TLS 会话密钥的成本很高。未来 Postfix SMTP 服务器可能限制客户端在单位时间内可协商的会话数量。
示例:
/etc/postfix/main.cf: smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache
注意:从版本 2.5 开始,Postfix 在打开此文件时不再使用 root 权限。该文件现在应存储在 Postfix 拥有的 data_directory 目录下。作为迁移辅助措施,若尝试在非 Postfix 目录下打开该文件,系统将重定向至 Postfix 所属的 data_directory 目录,并记录警告信息。
缓存的 Postfix SMTP 客户端会话信息在一定时间后过期。Postfix/TLS 不使用 OpenSSL 的默认值 300 秒,而是使用更长的 3600 秒(即 1 小时)。RFC 2246 建议最大值为 24 小时。
示例:
/etc/postfix/main.cf: smtp_tls_session_cache_timeout = 3600s
从 Postfix 2.11 开始,此设置不能超过 100 天。如果设置为 ≤ 0,则禁用会话缓存。如果设置为小于 2 分钟的正值,则使用 2 分钟的最小值。
客户端 TLS 限制 ;
TLS通信通道的安全属性取决于应用程序。虽然TLS协议可在客户端与服务器之间提供保密、防篡改、相互认证的通信通道,但并非所有安全特性都适用于每种通信场景。
例如,虽然浏览器与Web服务器之间可实现相互TLS认证,但对于面向公众的Web服务器而言,验证每个潜在用户的身份既不实际也不必要。实际上,大多数 HTTPS 交易是异构的:浏览器验证 HTTPS 服务器的身份,但用户保持匿名。大部分安全策略由客户端决定。如果客户端选择不验证服务器的名称,服务器并不知情。浏览器安全中有许多有趣的主题,但我们在此不作深入探讨。我们的目标是理解 TLS 与 SMTP 结合时的安全特性。
一个重要的 SMTP 特定观察是,公共 MX 主机比 HTTPS 服务器更依赖于 SMTP 客户端。它不仅无法强制客户端正确使用 TLS,甚至无法强制使用 TLS,因为 SMTP 客户端对 TLS 的支持仍属例外而非常态。在实际中,无法将对 MX 主机的访问限制为仅 TLS 启用的客户端。此类策略将导致与全球通过电子邮件通信的能力大幅下降。
有人可能会尝试强制要求来自特定发送组织的邮件使用 TLS,但此方法同样面临障碍。其中一个障碍是,我们无法在看到"MAIL FROM:" SMTP命令之前确定发件人(或声称的发件人)的身份。此时,如果 TLS 尚未启用,一个潜在敏感的发件人地址(以及在 SMTP 管道中一个或多个收件人)已经以明文形式泄露。另一个障碍是,发件人发送给收件人的邮件可能被转发,而转发组织可能与最终目的地没有安全协议。退信也需要保护。这些只能通过连接客户端的IP地址和HELO名称来识别,而很难跟踪发送组织所有外发邮件服务器的潜在IP地址或HELO名称。
因此,向公共 MX 主机发送邮件时的 TLS 安全几乎完全由客户端负责。服务器主要作为 TLS 安全的被动支持者,其余部分由客户端决定。虽然当服务器是仅处理来自可信客户端的出站邮件的专用 MSA 时,服务器有更大机会强制执行客户端安全策略,但本文重点讨论客户端安全策略。
在 SMTP 客户端,情况更为复杂。与 HTTPS 不同,在向指定域发送邮件时,很少直接使用域名为 SMTP 会话的目标主机。更常见的做法是通过 MX 查询(这些查询通常未经身份验证)获取域的 SMTP 服务器主机名。当前实践中,当客户端验证通过不安全方式获取的 MX 主机名时,该主机名易受 DNS 中间人攻击。
采用 DNSSEC 和 RFC6698(DANE)可逐步(随着域名实施 DNSSEC 并为 MX 主机发布 TLSA 记录)解决 DNS 中间人风险,并为 TLS 下的 SMTP 提供可扩展的密钥管理。Postfix ≥ 2.11 支持新的 dane 和 dane-only 安全级别,这些级别利用了这些标准。
如果客户端尝试验证收件人域名,多域 SMTP 服务器需要在其证书中列出所有电子邮件域名,并在添加新域名时生成新证书。至少部分 CA 对服务器证书中可包含的域名数量设定了较低限制(某知名 CA 为 20)。此方法与当前实践不一致且无法扩展。
遗憾的是,TLS 安全通道(完全认证且免疫中间人攻击)对发送和接收站点施加了限制,这阻碍了其普遍部署。用户需要为每个目标域名手动配置此类安全设置,并且在许多情况下,还需为托管在同一安全目标上的其他域名实施非默认的TLS 策略表条目。出于这些原因,安全通道配置将永远不会成为标准。对于未进行特定安全安排的通用域名,此安全级别并不合适。
由于强认证通常不可行,且可验证证书需要时间和成本,许多实施 TLS 的服务器使用自签名证书或私有 CA。这进一步限制了验证 TLS 在公共互联网上的适用性。
历史注释:尽管这些问题及相关功能的文档在 Postfix 2.3 中是新的,但该问题在 Postfix 1.0 设计阶段(Lutz Jänicke 设计首个非官方 Postfix TLS 补丁时)已得到充分理解。参见他的原始帖子 https://web.archive.org/web/20070816181658/http://www.imc. org/ietf-apps-tls/mail-archive/msg00304.html 以及第一个回复 https://web.archive. org/web/20070807073846/http://www.imc.org/ietf-apps-tls/mail-archive/msg00305.html。该问题甚至并非 SMTP 或 TLS 专有,HTTPS 和 Kerberos 通过别名建立安全连接时也存在类似问题。SMTP 只是更频繁地使用间接命名(通过 MX 记录)。
TLS 策略表 ;
一小部分服务器支持 STARTTLS,但协商始终失败。只要加密不是强制要求的,Postfix SMTP 客户端会立即尝试使用禁用 TLS 的方式重新发送邮件,无需显式禁用 TLS 针对问题目的地。
策略表通过smtp_tls_policy_maps参数指定。该参数列出了根据下一跳目的地映射Postfix SMTP客户端TLS安全策略的可选查找表。
TLS 策略表通过完整的下一跳目的地进行索引,该目的地可以是收件人域名,也可以是传输表中指定的下一跳的字面值,$local_transport、$virtual_transport 或 $relay_transport 或 $default_transport。这包括任何包围的方括号以及任何非默认目标服务器端口后缀。LMTP 套接字类型前缀(inet: 或 unix:)不包含在查找键中。
仅使用下一跳域名,或在 LMTP 通过 UNIX 域套接字时使用 $myhostname,作为证书验证的下一跳名称。端口和任何包围的方括号用于表查找键,但不用于服务器名称验证。
当查找键是一个不包含方括号或任何:port后缀的域名(通常为收件人域名),且完整域名未在表中找到时,与transport(5)表中的行为一致,将递归匹配以"."开头的父域名。这允许为收件域及其所有子域指定安全策略。
查找结果是一个安全级别,后跟可选的空格和/或逗号分隔的名称=值属性,这些属性将覆盖相关的main.cf设置。TLS 安全级别 级别 在上面已描述。下面,我们描述对应的表格语法:
none
不使用 TLS。此级别不支持任何额外属性。
可选
机会主义 TLS。可选的 "ciphers"、"exclude" 和 "protocols" 属性(适用于 Postfix ≥ 2.6 中的机会性 TLS)以及 "connection_reuse" 属性(Postfix ≥ 3.4)将覆盖 "smtp_tls_ciphers","smtp_tls_exclude_ciphers", "smtp_tls_protocols", 和 "smtp_tls_connection_reuse" 配置参数。在此级别及更高级别,可选的 "servername" 属性(Postfix ≥ 3.4 版本可用)将覆盖全局 "smtp_tls_servername"参数,允许为每个目的地配置发送给远程SMTP服务器的SNI扩展。可选的"enable_rpk"属性(Postfix ≥ 3.9)覆盖main. cf smtp_tls_enable_rpk 参数。当机会主义 TLS 握手失败时,Postfix 将尝试禁用 TLS 重新建立连接。这允许向具有不兼容 TLS 实现的站点发送邮件。
加密
强制加密。邮件仅在远程 SMTP 服务器支持 STARTTLS 且 TLS 握手成功时才被投递。在此级别及更高级别,可选的 "protocols" 属性将覆盖 main. cf smtp_tls_mandatory_protocols 参数,可选的 "ciphers" 属性将覆盖 main.cf main. cf smtp_tls_mandatory_exclude_ciphers 参数,而可选的 "connection_reuse" 属性(Postfix ≥ 3.4)将覆盖 main. cf smtp_tls_connection_reuse 参数。可选的 "enable_rpk" 属性(Postfix ≥ 3.9)覆盖 main. cf smtp_tls_enable_rpk 参数。
dane
机会主义DANE TLS。目标的TLS策略通过DNSSEC中的TLSA记录获取。如果未找到TLSA记录,则使用may的有效安全级别。如果找到 TLSA 记录但均不可用,则有效安全级别为 encrypt。当为远程 SMTP 服务器获取可用的 TLSA 记录时,服务器证书必须与 TLSA 记录匹配(且 SNI 名称无条件设置为 TLSA 基础域名)。RFC 7672 (DANE) TLS 认证和 DNSSEC 支持在 Postfix 2.11 及更高版本中可用。可选的 "connection_reuse" 属性(Postfix ≥ 3.4)覆盖 main. cf smtp_tls_connection_reuse 参数。当有效安全级别为 may 时,可选的 "ciphers"、"exclude" 和 "protocols" 属性(Postfix ≥ 2.6)将覆盖 "smtp_tls_ciphers","smtp_tls_exclude_ciphers",以及 "smtp_tls_protocols" 配置参数。当使用的有效安全级别为 加密 时,可选的 "ciphers"、"exclude" 和 "protocols" 属性(Postfix ≥ 2.6)将覆盖 "smtp_tls_mandatory_ciphers", "smtp_tls_mandatory_exclude_ciphers",以及 "smtp_tls_mandatory_protocols" 配置参数。
dane-only
强制使用DANE TLS。目标的TLS策略通过DNSSEC中的TLSA记录获取。如果未找到TLSA记录,或所有记录不可用,则不会与服务器建立连接。当为远程SMTP服务器获取到可用的TLSA记录时,服务器证书必须与TLSA记录匹配。RFC 7672 (DANE) TLS 认证和 DNSSEC 支持在 Postfix 2.11 及更高版本中可用。可选的 "ciphers"、"exclude" 和 "protocols" 属性(Postfix ≥ 2.6)将覆盖 "smtp_tls_mandatory_ciphers","smtp_tls_mandatory_exclude_ciphers",以及 "smtp_tls_mandatory_protocols" 配置参数。可选的 "connection_reuse" 属性(Postfix ≥ 3.4)覆盖 main. cf smtp_tls_connection_reuse 参数。
fingerprint
证书指纹验证。 适用于 Postfix 2.5 及更高版本。在此安全级别下,不存在受信任的证书颁发机构。证书信任链、过期日期等信息均不进行验证。取而代之的是,可选的 "match" 属性,或默认的 main.cf smtp_tls_fingerprint_cert_match 参数,列出可接受的服务器证书的证书指纹或公钥指纹(Postfix 2.9 及更高版本)。用于计算指纹的摘要算法由smtp_tls_fingerprint_digest参数选择。多个指纹可通过"|"分隔符在单个匹配属性中组合,或使用多个匹配属性。":"字符不作为分隔符,因为它出现在每个指纹(十六进制)数字之间。可选的"ciphers"、"exclude"和"protocols"属性(Postfix ≥ 2.6)会覆盖"smtp_tls_mandatory_ciphers","smtp_tls_mandatory_exclude_ciphers",以及 "smtp_tls_mandatory_protocols" 配置参数。可选的 "connection_reuse" 属性(Postfix ≥ 3.4)覆盖 main. cf smtp_tls_connection_reuse 参数。可选的 "enable_rpk" 属性(Postfix ≥ 3.9)覆盖 main. cf smtp_tls_enable_rpk 参数。
verify
强制服务器证书验证。邮件仅在 TLS 握手成功、远程 SMTP 服务器证书链可验证且证书中的 DNS 名称与指定的匹配条件一致时才被投递。在此安全级别下,假设 DNS MX 查询足够安全,且服务器证书中验证的名称可能通过未经验证的 DNS MX 查询获取。服务器证书名称必须与可选的 "match" 属性匹配,否则必须与 main. cf smtp_tls_verify_cert_match 参数值。在 Postfix ≥ 2.11 中,"tafile" 属性可选地以与 "smtp_tls_trust_anchor_file" 参数相同的方式修改信任链验证。"tafile"属性可多次指定以加载多个信任锚文件。可选的"connection_reuse"属性(Postfix ≥ 3.4)覆盖main. cf smtp_tls_connection_reuse 参数。
secure
安全证书验证。 只有在 TLS 握手成功、远程 SMTP 服务器证书链可验证且证书中的 DNS 名称与指定的匹配条件一致时,邮件才会被发送。在此安全级别下,尽管 DNS MX 查询可能用于确定候选下一跳网关 IP 地址,但它们被认为不足以用于 TLS 证书名称验证。相反,服务器证书中验证的默认名称直接从下一跳获取,或通过可选的 "match" 属性显式指定,该属性覆盖 main.cf smtp_tls_secure_cert_match参数。可选的"ciphers"、"exclude"和"protocols"属性(Postfix ≥ 2.6)会覆盖"smtp_tls_mandatory_ciphers","smtp_tls_mandatory_exclude_ciphers",以及 "smtp_tls_mandatory_protocols" 配置参数。在 Postfix ≥ 2.11 中,"tafile" 属性可选地修改信任链验证,与 "smtp_tls_trust_anchor_file" 参数以相同方式工作。"tafile"属性可多次指定以加载多个信任锚文件。可选的"connection_reuse"属性(Postfix ≥ 3.4)覆盖main. cf smtp_tls_connection_reuse 参数。
注意事项:
- "match"属性特别适用于验证托管在共享服务器上的域名的 TLS 证书。在这种情况下,请为共享服务器的名称指定"match"规则。虽然可以通过 Postfix 的 transport(5) 表中的手动路由覆盖实现安全验证,但当域被分配给新的网关主机时,此方法可能导致邮件发送到错误的主机。而 "match" 属性方法避免了手动路由覆盖的问题;如果对新 MX 主机的验证失败,邮件将被延迟。
- 当策略表条目指定多个匹配模式、多个匹配策略或多个协议时,这些必须用冒号分隔。
- "exclude"属性(Postfix ≥ 2.6)用于禁用与特定强制性 TLS 目的地握手失败的加密套件,而不会禁用所有强制性目的地的加密套件。或者,您可以在main.cf中排除与多个远程服务器存在问题的加密套件,并在策略表中通过设置较短或空的排除列表,按目的地选择性启用这些加密套件。针对每个目的地的"排除"列表会优先于机会性及强制性安全级别排除规则,因此所有被排除的加密套件均可启用在已知安全的目的地。对于存在加密套件特定问题的非强制性 TLS 目的地,Postfix 将回退至明文传输。若明文传输不可接受,请将 TLS 设为强制并排除问题加密套件。
示例:
/etc/postfix/main.cf: smtp_tls_policy_maps = hash:/etc/postfix/tls_policy # Postfix 2.5 及更高版本 smtp_tls_fingerprint_digest = sha256 /etc/postfix/tls_policy: example.edu none example.mil may example.gov encrypt ciphers=high example.com verify match=hostname:dot-nexthop ciphers=high example.net secure .example.net secure match=.example.net:example.net [mail.example.org]:587 secure match=nexthop # Postfix 2.5 及更高版本 [thumb.example.org] 指纹 匹配=b6:b4:72:34:e2:59:cd:fb:...:0d:4d:cc:2c:7d:84:de:e6:2f 匹配=51:e9:af:2e:1e:40:1f:de:...:35:2d:09:16:31:5a:eb:82:76 # Postfix ≥ 3.6 "协议"语法 example.info 可用协议=>=TLSv1 密码套件=中 排除=3DES # 旧版协议语法 example.info 可用协议=!SSLv2:!SSLv3 密码套件=medium 排除=3DES
注意: 如果在非默认设置的 smtp_tls_secure_cert_match 或在策略表的 "match" 属性中,可能会使 "secure" 级别易受 DNS 伪造攻击。在 DNS 安全无法保证的环境中,请勿在 secure-channel 配置中使用 "hostname" 策略。
发现支持 TLS 的服务器 ;
由于我们是按站点决定是否使用 TLS,因此最好有一份提供 "STARTTLS" 的站点列表。我们可以使用此选项自行收集。
如果启用了smtp_tls_note_starttls_offer功能,且服务器在未启用TLS的情况下提供了STARTTLS,Postfix SMTP客户端会记录如下日志:
postfix/smtp[pid]: 主机提供了 STARTTLS:[主机名.示例.com]
示例:
/etc/postfix/main.cf: smtp_tls_note_starttls_offer = yes
服务器证书验证深度
服务器证书验证深度通过 main. cf smtp_tls_scert_verifydepth 参数指定。默认验证深度为 9(OpenSSL 默认值),以兼容 Postfix 2.5 之前的版本,在这些版本中 smtp_tls_scert_verifydepth 被忽略。当配置对根 CA 的信任时,无需显式信任由根 CA 签名的中间 CA,除非 $smtp_tls_scert_verifydepth 小于目标服务器证书链中的 CA 数量。当验证深度为 1 时,仅能验证直接由受信任 CA 签名的证书,所有受信任的中间 CA 均需显式配置。验证深度为 2 时,您可以验证由根 CA 或直接中间 CA 签名的服务器(只要服务器正确配置了中间 CA 证书)。
示例:
/etc/postfix/main.cf: smtp_tls_scert_verifydepth = 2
客户端加密套件控制 ;
Postfix SMTP 客户端支持由 smtp_tls_mandatory_ciphers 配置参数指定的 5 种不同的加密级别。此设置控制强制使用 TLS 加密时 SMTP 客户端可接受的最低 TLS 加密级别。默认值 "medium" 适用于大多数需要强制启用 TLS 的目标,且已超出当前密码分析方法的破解范围。有关如何按目的地配置密码套件的详细信息,请参阅 smtp_tls_policy_maps。
默认情况下允许匿名加密套件,并在验证远程 SMTP 服务器证书时自动禁用。若要在"加密"安全级别下禁用匿名加密套件,请将"smtp_tls_mandatory_exclude_ciphers = aNULL"; 若要即使在机会主义 TLS 情况下也禁用匿名加密套件,请设置 "smtp_tls_exclude_ciphers = aNULL"。通常无需采取这些措施。匿名加密套件可节省带宽和 TLS 会话缓存空间,如果证书被忽略,请求它们几乎没有意义。
"smtp_tls_ciphers" 配置参数(Postfix ≥ 2.6)用于控制机会主义 TLS 的最低密码套件等级。对于 2015 年中之后发布的 Postfix 版本,机会主义 TLS 的默认最低加密级别为 "medium",而较旧版本为 "export"。对于 Postfix <; 2.6,机会主义 TLS 的最低加密级别始终为 "export"。
启用强制和机会性 TLS 加密时,Postfix SMTP 客户端默认禁用 SSLv2 和 SSLv3。强制 TLS 协议列表通过 smtp_tls_mandatory_protocols 配置参数指定。对应的 smtp_tls_protocols 参数(Postfix ≥ 2.6)控制机会性 TLS 中使用的 TLS 协议。
示例:
/etc/postfix/main.cf: smtp_tls_mandatory_ciphers = medium smtp_tls_mandatory_exclude_ciphers = RC4, MD5 smtp_tls_exclude_ciphers = aNULL smtp_tls_ciphers = medium # Postfix ≥ 3.6 推荐格式: smtp_tls_mandatory_protocols = >;=TLSv1.2 smtp_tls_protocols = >;=TLSv1 # Postfix <; 3.6 的旧格式: smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtp_tls_protocols = !SSLv2,!SSLv3
客户端提交(以前称为 smtps)支持 ;
这些部分说明了如何向不支持 STARTTLS 但在 TCP 端口 465 上提供提交(smtps)服务的服务器发送邮件。根据 Postfix 版本,可能需要一些额外的工具。
Postfix ≥ 3.0
Postfix SMTP 客户端自版本 3.0 起内置了提交服务支持。使用以下示例之一,可将所有远程邮件或部分远程邮件发送至提交(smtps)服务器。
Postfix ≥ 3.0:将所有远程邮件发送至提交(原名为 smtps)服务器
第一个示例将通过名为 "mail.example.com" 的提供商提交服务器发送所有远程邮件:
/etc/postfix/main.cf: # 客户端提交需要"encrypt"或更高级别的加密。 smtp_tls_security_level = encrypt smtp_tls_wrappermode = yes # [] 抑制 MX 查询。 relayhost = [mail.example.com]:submissions
使用 "postfix reload" 使更改生效。
参见 SOHO_README 以获取有关 SASL 认证的更多信息。
Postfix ≥ 3.0:仅将指定目的地的邮件发送至提交服务(原名为 smtps)
第二个示例将仅使用提交服务(smtps)发送 "example.com" 的邮件。此次,Postfix 使用传输映射仅通过提交服务(smtps)发送 "example.com" 的邮件:
/etc/postfix/main.cf: transport_maps = hash:/etc/postfix/transport /etc/postfix/transport: example.com 转发提交邮件:example.com:submissions /etc/postfix/master.cf: 转发提交邮件 unix - - n - - smtp # 客户端提交服务需要使用 "encrypt" 或更高级别的加密。 -o smtp_tls_security_level=encrypt -o smtp_tls_wrappermode=yes
使用 "postmap hash:/etc/postfix/transport" 和 "postfix reload" 使更改生效。
有关 SASL 身份验证的更多信息,请参阅 SOHO_README。
Postfix <; 3.0
请参阅 TLS_LEGACY_README。
其他客户端控制 ;
smtp_starttls_timeout 参数限制了 Postfix SMTP 客户端在 TLS 启动和关闭握手过程中写入和读取操作的时间。如果出现问题,Postfix SMTP 客户端将尝试邮件交换列表中的下一个网络地址,并在没有可用替代服务器时推迟投递。
示例:
/etc/postfix/main.cf: smtp_starttls_timeout = 300s
在 Postfix 2.8 及更高版本中,tls_disable_workarounds 参数指定要禁用的 OpenSSL 漏洞修复方案的列表或位掩码。如果 OpenSSL 中默认启用的某个工作绕过方案被发现存在安全风险,或引入了意外的兼容性问题,可能需要禁用这些方案。当与可能存在漏洞的 OpenSSL 库链接时,该参数的默认值已禁用了一些已知存在问题的漏洞工作绕过方案。
示例:
/etc/postfix/main.cf: tls_disable_workarounds = 0xFFFFFFFF tls_disable_workarounds = CVE-2010-4180, LEGACY_SERVER_CONNECT
注意:目前禁用 LEGACY_SERVER_CONNECT 并不明智,因为许多服务器尚未打补丁,而 Postfix 对于 TLS 协议中的重新协商问题并不存在显著漏洞。
对于 Postfix ≥ 2.11,tls_ssl_options 参数指定要启用的 OpenSSL 选项列表或位掩码。指定以下命名选项中的一个或多个,或在 ssl.h 文件中与运行时 OpenSSL 库对应的十六进制位掩码。虽然关闭所有漏洞修复(见上文)可能是合理的,但尝试启用所有功能并非明智之举。
未来版本的 OpenSSL 可能默认不再允许连接不支持安全重新协商的服务器。由于 SMTP 的暴露风险较低,且部分 SMTP 服务器可能未打补丁,您可以将 LEGACY_SERVER_CONNECT 添加到选项中,以恢复当前 OpenSSL 版本的更宽松默认设置。
示例:
/etc/postfix/main.cf: tls_ssl_options = NO_TICKET, NO_COMPRESSION, LEGACY_SERVER_CONNECT
仅在需要严格控制该功能(例如应对新漏洞或严重兼容性问题)时,才应通过十六进制掩码启用功能。Postfix 不保证掩码位与旧版本的向后兼容性。在某个版本中通过掩码启用的功能,可能在后续版本中通过其他方式启用,此时掩码位将被忽略。因此,使用十六进制掩码仅作为临时措施,直至 Postfix 或 OpenSSL 发布新版本提供更优解决方案。
TLS 管理器特定设置 ;
加密软件(如 TLS)的安全性在很大程度上依赖于生成不可预测的密钥和其他信息的能力。为此,tlsmgr(8) 进程维护一个伪随机数生成器(PRNG)池。此池在smtp(8)和smtpd(8)进程初始化时被查询。默认情况下,这些守护进程请求 32 字节,相当于 256 位。这足以生成一个 128 位(或 168 位)的会话密钥。
示例:
/etc/postfix/main.cf: tls_daemon_random_bytes = 32
为了向内存中的伪随机数生成器(PRNG)池提供数据,tlsmgr(8) 会从外部源读取熵,既在启动时读取,也在运行时读取。指定一个良好的熵源,如 EGD 或 /dev/urandom;确保仅使用非阻塞源(在 OpenBSD 上,当 tlsmgr(8) 报告 /dev/urandom 超时错误时,请使用 /dev/arandom)。如果熵源不是常规文件,必须在源名称前添加源类型前缀:设备特殊文件使用 "dev:", EGD 兼容套接字接口的源使用 "egd:".
示例(仅在 main.cf 中指定一个):
/etc/postfix/main.cf: tls_random_source = dev:/dev/urandom tls_random_source = egd:/var/run/egd-pool
默认情况下,tlsmgr(8) 在每次初始化时从外部熵源读取 32 字节。此数量(256 位)足以生成一个 128 位对称密钥。使用 EGD 和设备熵源时,tlsmgr(8) 将每次读取的数据量限制为 255 字节。如果指定普通文件作为熵源,可以读取更大的数据量。
示例:
/etc/postfix/main.cf: tls_random_bytes = 32
为了更新其内存中的伪随机数生成器(PRNG)池,tlsmgr(8)会在经过一段伪随机时间后再次查询外部熵源。该时间由 PRNG 计算得出,范围在 0 到通过 tls_random_reseed_period 指定的最大时间之间。默认最大时间间隔为 1 小时。
示例:
/etc/postfix/main.cf: tls_random_reseed_period = 3600s
tlsmgr(8) 进程会在固定时间间隔和进程终止时将 PRNG 状态保存到一个持久交换文件中,以便下次启动时恢复 PRNG 状态。如果该文件不存在,则会自动创建。
示例:
/etc/postfix/main.cf: tls_random_exchange_name = /var/lib/postfix/prng_exch tls_random_prng_update_period = 3600s
从版本 2.5 开始,Postfix 在打开此文件时不再使用 root 权限。该文件现在应存储在 Postfix 拥有的 data_directory 目录下。作为迁移辅助措施,若尝试在非 Postfix 目录下打开该文件,系统将重定向至 Postfix 拥有的 data_directory 目录,并记录警告信息。如果您希望继续使用现有的 PRNG 状态文件,请将其移动到 data_directory 并将其所有权更改为通过 mail_owner 参数指定的账户。
在较早版本的 Postfix 中,默认文件位置位于 Postfix 配置目录下,而该位置不适合存放由 Postfix 修改的信息。
快速入门,简单实现
以下步骤可快速入门。由于您签名了自己的 Postfix 公钥证书,因此可获得 TLS 加密但不支持 TLS 身份验证。这足以用于测试,以及与无信任关系的站点交换邮件。若需真实身份验证,您还需为域名启用 DNSSEC 记录签名,并发布 TLSA 记录,或确保 Postfix 公钥证书由受信任的证书颁发机构签名。要验证远程主机的证书,您需要一个支持 DNSSEC 验证的本地解析器,并启用 DANE 认证,或配置 Postfix SMTP 客户端使用认证机构的公钥证书列表,但请务必阅读关于后者方法的 限制。
在下面的示例中,用户输入以bold字体显示,而"#"提示符表示超级用户 shell。
使用 Postfix ≥ 3.1 快速启动 TLS
Postfix 3.1 提供了内置支持,可在 SMTP 客户端和服务器中启用 TLS,并进行证书和 DANE TLSA 记录的持续管理。
在 Postfix ≥ 3.1 SMTP 客户端中快速启动 TLS。
如果您使用的是 Postfix 3.1 或更高版本,且 SMTP 客户端的 TLS 设置处于默认状态,您可以按照以下步骤在 SMTP 客户端中启用 opportunistic TLS:
# postfix tls enable-client # postfix reload
如果 Postfix SMTP 客户端的 TLS 设置未处于默认状态,此操作不会进行任何更改,而是建议 SMTP 客户端 TLS 的最小必要设置。"postfix reload"命令是可选的,仅在您希望设置立即生效时需要执行。注意,这不会启用对任何公共证书颁发机构的信任,也不会配置客户端 TLS 证书,因为在使用 opportunistic TLS 的情况下,这些证书大多没有意义。
目前尚无一键启用 DANE 认证的命令。这是因为 DANE 需要修改您的 resolv.conf 文件,并配置一个本地 DNSSEC 验证解析器,这些更改难以在可移植环境中自动化实现。
如果您愿意将设置恢复为默认值并切换到"默认"机会主义 TLS 配置,则可以:清除所有 SMTP 客户端 TLS 设置,然后启用客户端 TLS:
# postconf -X `postconf -nH | grep -E '^smtp(_|_enforce_|_use_)tls'` # postfix tls enable-client # postfix reload
Postfix ≥ 3.1 SMTP 服务器中的快速启动 TLS.
如果您使用的是 Postfix 3.1 或更高版本,且 SMTP 服务器 TLS 设置处于默认状态,可按以下步骤在 SMTP 服务器中启用机会性 TLS:
# postfix tls enable-server # postfix reload
如果 Postfix SMTP 客户端的 TLS 设置未处于默认状态,此操作不会进行任何更改,而是会建议 SMTP 客户端 TLS 的最小必要设置。 "postfix reload" 命令是可选的,仅在您希望设置立即生效时需要执行。这将生成一个自签名私钥和证书,并在 Postfix SMTP 服务器上启用 TLS。
如果您愿意将设置恢复为默认值并切换到"默认"服务器 TLS 配置,则可以:清除所有 SMTP 服务器 TLS 设置,然后启用服务器 TLS:
# postconf -X `postconf -nH | grep -E '^smtpd(_|_enforce_|_use_)tls'` # postfix tls enable-server # postfix reload
Postfix ≥ 3.1 提供了对 SMTP 服务器 TLS 的持续管理额外内置支持,通过额外的 "postfix tls" 子命令实现。这些命令使生成证书签名请求、创建和部署新密钥及证书、生成 DANE TLSA 记录变得简单。详情请参阅 postfix-tls(1) 文档。
自签名服务器证书
以下命令(贡献者:Viktor Dukhovni)用于生成并安装本地 Postfix 系统使用的 2048 位 RSA 私钥及 10 年有效期的自签名证书。这需要超级用户权限。(通过使用证书和密钥文件的日期特定文件名,并更新 main.cf 中的新文件名,可以避免密钥和证书不匹配的潜在竞争条件。)
# dir="$(postconf -h config_directory)" # fqdn=$(postconf -h myhostname) # case $fqdn in /*) fqdn=$(cat "$fqdn");; esac # ymd=$(date +%Y-%m-%d) # 密钥="${dir}/key-${ymd}.pem"; rm -f "${key}" # 证书="${dir}/cert-${ymd}.pem"; rm -f "${cert}" # (umask 077; openssl genrsa -out "${key}" 2048) && openssl req -new -key "${key}" \ -x509 -subj "/CN=${fqdn}" -days 3650 -out "${cert}" && postconf -e \ "smtpd_tls_cert_file = ${cert}" \ "smtpd_tls_key_file = ${key}" \ 'smtpd_tls_security_level = may' \ 'smtpd_tls_received_header = yes' \ 'smtpd_tls_loglevel = 1' \ 'smtp_tls_security_level = may' \ 'smtp_tls_loglevel = 1' \ 'smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache' \ 'tls_random_source = dev:/dev/urandom'
注意:最后一条命令需要同时使用单引号 (') 和双引号 (")。
postconf(1) 命令启用了接收和发送邮件时的机会性 TLS。它还启用了 TLS 连接日志记录,并在 "Received" 头中记录 TLS 使用情况。Postfix SMTP 客户端中也启用了 TLS 会话缓存。对于 Postfix ≥ 2.10,SMTP 服务器无需显式会话缓存,因为会话复用可通过 RFC 5077 TLS 会话票据更好地处理。
私有证书颁发机构
成为自己的证书颁发机构(CA),以便您可以签发自己的证书,并且您的系统可以验证来自您自己的 CA 的证书。此示例使用随 OpenSSL 附带的 CA.pl 脚本。在某些系统上,OpenSSL 将此脚本安装为 /usr/local/openssl/misc/CA.pl。部分系统将其作为openssl-perl或类似包的一部分安装。该脚本会在./demoCA/private/cakey.pem创建私钥,并在./demoCA/cacert.pem创建公钥。
% /usr/local/ssl/misc/CA.pl -newca CA 证书文件名(或按回车创建) 正在生成 CA 证书 ... 使用 /etc/ssl/openssl.cnf 中的配置 生成 1024 位 RSA 私钥 ....................++++++ .....++++++ 将新私钥写入 './demoCA/private/cakey.pem' 输入 PEM 密码短语:whatever
为主机 foo.porcupine.org 创建一个未加密的私钥,并生成一个未签名的公钥证书。
% (umask 077; openssl req -new -newkey rsa:2048 -nodes -keyout foo-key.pem -out foo-req.pem) 使用配置文件 /etc/ssl/openssl.cnf 生成一个 2048 位 RSA 私钥 ........................................++++++ .... 写入新的私钥到 'foo-key.pem' ----- 您即将被要求输入将被纳入 证书请求的信息。 您即将输入的内容称为区分名称(DN)。 有许多字段,但您可以留空一些 对于某些字段,将有默认值, 如果您输入 '.', 该字段将被留空。 ----- 国家名称(2 位代码)[AU]:US 州或省名称(全名)[Some-State]:New York 地点名称(例如,城市)[]:Westchester 组织名称(例如,公司)[Internet Widgits Pty Ltd]:Porcupine 组织单位名称(例如,部门)[]: 通用名称(例如,您的名称)[]:foo.porcupine.org 电子邮件地址[]:[email protected] 请输入以下"额外"属性 与证书请求一起发送 挑战密码[]:whatever 可选公司名称[]:
使用我们在几步之前创建的证书颁发机构私钥,为主机 foo.porcupine.org 的公钥证书签名。
% openssl ca -out foo-cert.pem -days 365 -infiles foo-req.pem 使用 /etc/ssl/openssl.cnf 中的配置 输入 PEM 密码:whatever 检查请求是否与签名匹配 签名正确 主体的区分名称如下 countryName :PRINTABLE:'US' stateOrProvinceName :PRINTABLE:'New York' localityName :PRINTABLE:'Westchester' organizationName :PRINTABLE:'Porcupine' 通用名称:可打印名称:'foo.porcupine.org' 电子邮件地址:IA5字符串:'[email protected]' 证书有效期至2005年11月21日19:40:56 GMT(365天) 是否签名证书?[y/n]:y 1 个证书请求已签名,是否提交?[y/n]y 将数据库写入文件,包含 1 条新记录 数据库已更新
安装主机私钥、主机公钥证书和证书颁发机构证书文件。此操作需要超级用户权限。
以下命令假设密钥和证书将安装在本地 Postfix MTA 上。如果 Postfix MTA 位于其他主机,请相应调整命令。
# cp demoCA/cacert.pem foo-key.pem foo-cert.pem /etc/postfix # chmod 644 /etc/postfix/foo-cert.pem /etc/postfix/cacert.pem # chmod 400 /etc/postfix/foo-key.pem
配置 Postfix,通过在 /etc/postfix/main.cf 中添加以下内容。通常不建议配置客户端证书,除非有服务器通过客户端证书验证邮件提交。通常,执行 TLS 客户端身份验证的服务器会签发由其自身 CA 签名的所需证书。如果客户端证书和密钥配置错误,将无法向要求客户端证书但不强制所有客户端提供证书的网站发送邮件。
/etc/postfix/main.cf: smtp_tls_CAfile = /etc/postfix/cacert.pem smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_tls_session_cache smtp_tls_security_level = may smtp_tls_loglevel = 1 smtpd_tls_CAfile = /etc/postfix/cacert.pem smtpd_tls_cert_file = /etc/postfix/foo-cert.pem smtpd_tls_key_file = /etc/postfix/foo-key.pem smtpd_tls_received_header = yes smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_session_cache tls_random_source = dev:/dev/urandom smtpd_tls_security_level = may smtpd_tls_loglevel = 1
构建支持 TLS 的 Postfix
这些说明假设您已按照INSTALL文档从源代码构建了Postfix。如果您从供应商特定的源代码包构建Postfix,可能需要进行一些修改。
要构建支持 TLS 的 Postfix,首先需要生成包含必要定义的 make(1) 文件。这通过在 Postfix 顶级目录中执行命令 "make makefiles" 并使用如下所示的参数来实现。
注意:请勿使用 Gnu TLS。它会导致 Postfix 守护进程以退出状态码 2 异常终止,而非允许 Postfix 1) 将错误报告到 maillog 文件,以及 2) 在适当情况下提供明文服务。 ;
如果 OpenSSL 头文件(如 ssl.h)位于目录 /usr/include/openssl,且 OpenSSL 库文件(如 libssl.so 和 libcrypto.so)位于目录 /usr/lib:
% make tidy # 如果之前构建时留有残留文件 % make makefiles CCARGS="-DUSE_TLS" AUXLIBS="-lssl -lcrypto"
如果 OpenSSL 头文件(如 ssl.h)位于目录 /usr/local/include/openssl,且 OpenSSL 库文件(如 libssl.so 和 libcrypto.so)位于目录 /usr/local/lib:
% make tidy # 如果之前构建时留有残留文件 % make makefiles CCARGS="-DUSE_TLS -I/usr/local/include" \ AUXLIBS="-L/usr/local/lib -lssl -lcrypto"
如果 OpenSSL 共享库位于运行时链接器未知目录中,请在 "-lcrypto" 后添加 "-Wl,-R,/path/to/directory" 选项。
在 Solaris 系统中,请按以下方式指定 -R 选项:
% make tidy # 如果之前构建时留有残留文件 % make makefiles CCARGS="-DUSE_TLS -I/usr/local/include" \ AUXLIBS="-R/usr/local/lib -L/usr/local/lib -lssl -lcrypto"
如果你需要应用其他自定义设置(如 Berkeley DB 数据库、MySQL、PostgreSQL、LDAP 或 SASL),请参阅相应的 Postfix README 文档,并将其中的 "make makefiles" 指令与上述指令结合使用:
% make tidy # 如果之前构建时留有残留文件 % make makefiles CCARGS="-DUSE_TLS \ (其他 -D 或 -I 选项)" \ AUXLIBS="-lssl -lcrypto \ (其他 -l 选项用于 /usr/lib 中的库) \ ((-L/path/name + -l 选项用于其他库)"
要完成构建过程,请参阅 Postfix INSTALL 说明。Postfix 默认关闭 TLS 支持,因此安装完成后即可开始使用 Postfix。
报告问题 ;
问题最好通过 <;[email protected]>; 报告。有关订阅信息,请参阅 https://www.postfix.org/lists.html。在报告问题时,请尽可能详细。如有可能,提供补丁将非常感谢。
致谢 ;
- Postfix 的 TLS 支持最初由 Lutz Jänicke 在 Cottbus 技术大学开发。
- Wietse Venema 采用了该代码,进行了部分重构,并从 Lutz 的文档中整理了这部分文档。
- Victor Duchovni 在重新实现 smtp_tls_per_site 代码时,在强制执行级别方面发挥了关键作用,这大大简化了实现过程。
- Victor Duchovni 实现了指纹安全级别,添加了更多合理性检查,并将 TLS 连接管理与安全策略执行分离。后者更改简化了验证证书签名、证书名称和证书指纹的代码。