docker-mailserver 端口与 TLS 深度指南:25 / 465 / 587 / 110 / 995 / 143 / 993 的职责划分与安全选型
【免费下载链接】docker-mailserverProduction-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) running inside a container.项目地址: https://gitcode.com/gh_mirrors/do/docker-mailserver
导读:邮件服务端口的数量与含义常常令人困惑,本文基于 docker-mailserver 官方文档《Security | Understanding the Ports》展开,系统梳理 SMTP、IMAP、POP3 各端口在"显式 TLS(STARTTLS)"与"隐式 TLS"两种模式下的职责与默认启用状态,结合本仓库中 compose.yaml、target/postfix/master.cf、target/dovecot/10-master.conf 等真实配置,讲清每个端口的入站/出站语义、465 端口的历史纠偏,以及邮件传输中 TLS 安全边界(为何邮件 TLS 不等同于 HTTPS)。读完你将能根据自己的场景(MUA 客户端、中继服务、直接投递)做出正确的端口选择与安全配置。
1. 端口速查表
docker-mailserver(下文简称 DMS)对外暴露的邮件端口可按下表快速定位。核心原则:能使用隐式 TLS(Implicit TLS)的端口就优先使用,它比显式 TLS(Explicit TLS /STARTTLS)更安全,且在接入反向代理时也更少麻烦。
| 协议 | 显式 TLS(Explicit TLS)¹ | 隐式 TLS(Implicit TLS) | 用途 | 默认启用 |
|---|---|---|---|---|
| ESMTP | 25 | 不适用 | 传输(接收邮件)² | 是 |
| ESMTP | 587 | 465 ³ | 提交(Submission) | 是 |
| POP3 | 110 | 995 | 收取邮件 | 否 |
| IMAP4 | 143 | 993 | 收取邮件 | 是 |
表注说明:
- 所谓"显式 TLS",指连接可以在双方都支持
STARTTLS时升级为 TLS 加密。在 110、143、587 端口上,DMS 会拒绝无法建立安全连接的请求;而端口 25 因协议强制要求,必须支持不加密连接。- 端口 25 用于接收邮件,DMS 还会在此基础上做垃圾邮件与病毒过滤。若要让邮件服务器替你把邮件发给第三方,应优先使用"提交"端口(465、587)——它们强制要求认证。除非配置了中继主机(例如 SendGrid),否则发出邮件仍会走 25 端口(因此你的云厂商或防火墙不能封锁出站 25 端口)。
- 465 自 2018 年(RFC 8314)起被重新定义为"提交"端口。
"默认启用"这一列与仓库中环境变量配置一一对应:ENABLE_IMAP默认为1(启用),而ENABLE_POP3默认为0(禁用),详见 docs/content/config/environment.md 与 docs/content/config/environment.md#enable_imap。这意味着如果你想用 POP3(110/995),需要在mailserver.env中显式开启ENABLE_POP3=1。
2. 关于端口 465 的历史纠偏:别被过时资料误导
社区和各类博客(甚至一些主流邮件中继服务商的文章)对 465 端口存在普遍误解,DMS 文档专门给出警示:
- 1997 年:465 端口曾短暂被指定为 SMTPS,作为 MTA 之间 25 端口的加密替代方案。
- 1998 年末:RFC 2487(
STARTTLS)还处于草案阶段时,IANA 就撤销了 SMTPS 的端口分配;相关草案历史也被修改,删除了所有关于 465 与 SMTPS 的提及。 - 2018 年:RFC 8314 发布,重新将 465 定义为 587 的隐式 TLS 提交端口,并明确指出 465 的普及需要时间。IANA 将 465 重新登记为
submissions服务。
因此,任何把 465 称为 "SMTPS" 的用法都是遗留用法,且已经过时二十多年。
为什么会造成这种混乱?因为 587 在历史上被更广泛地支持,大量软件在很长一段时间里都是围绕 587 构建或配置的;而STARTTLS即使在近几年也仍不断被发现新的 CVE。DMS 建议:不要被任何暗示"显式 TLS 优于隐式 TLS"的建议误导,应信任更官方的来源——例如 Postfix 上游master.cf配置中已经明确承认了submissions(465)端口。
在本仓库中,target/postfix/master.cf 即定义了submissions服务,并为其启用了smtpd_tls_wrappermode=yes——这正是隐式 TLS("包装模式")在 Postfix 侧的落地实现。
3. 我该用哪些端口?(SMTP 全景图)
下面的流程图展示了一个 DMS 实例在邮件收发链路中各个端口的角色。左侧是"入站"(别人给你发信 / 你的客户端提交发信),右侧是"出站"(你的服务器向外投递):
理解这张图的关键在于:端口的作用取决于数据流的方向——同一个端口 25,既可以是别人投递给你的入口,也可以是你向外直接投递的出口;而 465/587 则既是 MUA 客户端提交邮件的入口,也是你借助第三方中继向外转发时的出口。
4. 入站流量详解(图的左侧)
邮件到达你的服务器后,要么被处理并存入邮箱,要么被转发到另一台邮件服务器。
4.1 端口 25:相当于"物理信箱"
- 任何人都可以向这个地址投递邮件,绝大多数入站邮件都走这个端口。
- DMS 会主动对 25 端口收到的邮件做垃圾邮件与病毒过滤,并拒绝来自已知不良来源的邮件。
- 该端口允许通过
STARTTLS建立安全连接,但不强制——因为协议要求邮件必须允许以未加密连接到达(这是 RFC 5321 体系下 MTA 互操作性的硬性要求)。 - 理论上内部客户端也可以不经认证就通过 25 提交外发邮件,但这是不鼓励的做法,请优先使用"提交"端口。
4.2 端口 465 与 587:相当于"邮局信箱"
- 这是你委托服务器(DMS 扮演邮局 / MTA 角色)替你投递邮件的地方。
- 这两个端口统称"提交"(submission)端口,允许把邮件发给其他 MTA(如 Outlook、Gmail),但要求通过邮件账号认证。账号体系详见 docs/content/config/account-management/overview.md#accounts。
- 入站语境下,它主要服务两类场景:MUA 客户端(Thunderbird、Webmail、Mutt 等)发信;以及 DMS 被配置为邮件中继,或后端服务通过 DMS 发送事务性邮件(订单确认、密码重置、通知等)。
- 优先使用 465(隐式 TLS),而非 587(显式 TLS)。
注意:从"提交"到"投递"(入站再出站)涉及两条独立连接的协商与加密。中间可能还存在 DMS 完全不知情的其他连接,因此无法保证整条投递链路全程加密。
在仓库的 compose.yaml 中可以看到官方推荐的端口映射,注释明确标注了各端口语义:
ports: - "25:25" # SMTP (explicit TLS => STARTTLS, Authentication is DISABLED => use port 465/587 instead) - "143:143" # IMAP4 (explicit TLS => STARTTLS) - "465:465" # ESMTP (implicit TLS) - "587:587" # ESMTP (explicit TLS => STARTTLS) - "993:993" # IMAP4 (implicit TLS)注意 993(IMAP over TLS)在默认映射中已启用,而 POP3 的两个端口(110/995)未出现在默认映射中——这与上文ENABLE_POP3=0的默认值保持一致。
5. 出站流量详解(图的右侧)
从你的服务器发出的邮件,要么经由另一个 MTA(如 SendGrid)中继,要么直接投递给目标邮箱地址对应的 MTA(如 Gmail)。
5.1 端口 25(出站)
- 绝大多数 MTA 都用 25 端口接收入站邮件,因此当不涉及已认证中继时,25 就是出站端口。
- 服务提供商(VPS、ISP)通常会封锁出站 25 端口以防止垃圾邮件滥用。如果无法解封,你就必须通过中继服务代为发信。
5.2 端口 465 与 587(出站)
- 出站场景下,这两个"提交"端口用于向第三方中继服务建立信任:你需要向中继服务账号认证(配置方式见 docs/content/config/advanced/mail-forwarding/relay-hosts.md),随后中继再通过 25 端口替你完成投递。
- 这两个是最常用的端口,但 SendGrid 等智能主机(smart host)通常还支持一些额外的非标准端口作为备选。
- 通常出站只在"中继"场景使用这两个端口。理论上也可以直接投递到目标地址对应的 MTA,但那样需要对每个MTA 都持有凭据,实际很少这么做。
提示:DMS 本身也可以充当中继,但专业中继服务拥有被信任的信誉(能显著提高投递成功率)。信誉较低的 MTA 发出的邮件可能被当作垃圾邮件,甚至被直接拒收。
注意:你最多只能保证与你直连的那台 MTA 之间的连接是安全的。接收方 MTA 可能再把邮件转发给另一台 MTA(依此类推),每一跳连接都可能没有启用 TLS。
6. 显式 TLS(STARTTLS)与隐式 TLS 的本质区别
6.1 显式 TLS / 机会性 TLS(Explicit / Opportunistic TLS)——"可选"加密
- 这类端口上的通信以明文开始,升级到加密连接必须通过
STARTTLS协议显式请求并成功协商。 - 有时接入的反向代理配置错误或缺少对
STARTTLS协商的支持,会导致协商失败。
说明:
- 默认情况下,DMS 被配置为:当认证是必需的、而安全连接又建立失败时,直接拒绝连接,而不是放任不安全的连接继续。
- 端口 25 不需要认证:若
STARTTLS协商失败,邮件仍可通过未加密连接接收。如果你需要在可信双方之间进一步加固 25 端口,可以叠加 MTA-STS、STARTTLS Policy List、DNSSEC 与 DANE 等机制。
警告:
STARTTLS持续被发现新漏洞(2021 年 11 月仍有相关文章)。按照 RFC 8314 第 4.1 节的建议,应尽可能优先使用隐式 TLS。此外,STARTTLS的实现并不总是正确:客户端可能在 TLS 连接建立之前就过早发送凭据导致泄露;一些第三方(如部分 ISP)还会拦截STARTTLS握手,篡改网络流量以阻止建立安全连接。
6.2 隐式 TLS(Implicit TLS)——"强制"加密
- 这类端口上的通信始终加密(强制、隐含),规避了
STARTTLS的上述潜在风险。 - 虽然显式 TLS 在
STARTTLS成功协商时也能提供同样的收益,但隐式 TLS 能更可靠地避免连接被操纵与兼容性问题。
在仓库中,Postfix 侧两种模式的差异在 target/postfix/master.cf 中一目了然:
submission(587)使用smtpd_tls_security_level=encrypt(见 target/postfix/master.cf#L17-L29)——要求 TLS 但通过STARTTLS协商;submissions(465)使用smtpd_tls_wrappermode=yes(见 target/postfix/master.cf#L31-L43)——连接一建立即处于 TLS 包装模式。
Dovecot 侧同样在 target/dovecot/10-master.conf 定义了imap(143)/imaps(993)、pop3(110)/pop3s(995)两组监听器,其中imaps与pop3s监听器启用ssl = yes,即隐式 TLS 模式。
7. 安全性:邮件服务器的 TLS 与浏览器 HTTPS 的本质差异
与 HTTP/HTTPS 不同——HTTPS 中浏览器直接与提供网站的服务器通信,而邮件场景下即使建立了安全的 TLS 连接,也无法提供与 HTTPS 等效的安全保障:
- 邮件的收发往往要经过第三方(多个 MTA)中转,安全连接只存在于两台机器之间;MUA 与 MDA 之间的任何中间 MTA,能否成功建立安全连接完全取决于它们自己。
- 客户端与服务器之间还可能存在一些通常不被考虑在内的中间设备,例如流量途经 ISP 的链路——这些设备有能力通过拦截来破坏
cleartext(明文)连接。
因此,为邮件链路选配端口与 TLS 模式,只是"单跳安全"的第一步;要覆盖整条投递链路,还需要结合 MTA-STS、DANE/DNSSEC 等机制(详见 docs/content/config/security/ssl.md 中的 TLS 配置指南)。
8. 仓库中的落地实现:端口如何映射到服务
8.1 Postfix:master.cf中的 smtp / submission / submissions
target/postfix/master.cf 是 DMS 镜像内 Postfix 的 master 配置,三组与端口相关的服务定义如下:
| 服务 | 端口 | 关键参数 | 语义 |
|---|---|---|---|
smtp→postscreen→smtpd | 25 | postscreen前置守卫 | 接收外部入站,先经 postscreen 过滤(对应 DMS 的垃圾/病毒过滤链路) |
submission | 587 | smtpd_tls_security_level=encrypt、smtpd_sasl_auth_enable=yes | 显式 TLS + SASL 认证提交 |
submissions | 465 | smtpd_tls_wrappermode=yes、smtpd_sasl_auth_enable=yes | 隐式 TLS + SASL 认证提交 |
两个提交服务都启用了 Dovecot SASL(smtpd_sasl_type=dovecot),并通过smtpd_client_restrictions=permit_sasl_authenticated,reject与smtpd_relay_restrictions=permit_sasl_authenticated,reject强制只有已认证用户才能使用——这正是"提交端口必须认证"这一文档原则的源码级证据。
8.2 Dovecot:10-master.conf中的 IMAP / POP3 监听
target/dovecot/10-master.conf 定义了:
service imap-login:inet_listener imap(143,显式 TLS)+inet_listener imaps(993,隐式 TLS,ssl = yes);service pop3-login:inet_listener pop3(110,显式 TLS)+inet_listener pop3s(995,隐式 TLS,ssl = yes)。
而 TLS 的全局参数集中在 target/dovecot/10-ssl.conf:
ssl_min_protocol = TLSv1.2 ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:...:ECDHE-RSA-CHACHA20-POLY1305 ssl_server_prefer_ciphers = server8.3 安全监控:fail2ban 覆盖全部邮件端口
开启ENABLE_FAIL2BAN=1后,仓库中的 target/fail2ban/jail.local 会把以下端口全部纳入监控:
port = smtp,pop3,pop3s,imap,imaps,submission,submissions,sieve即 25、110、995、143、993、587、465 以及 Sieve(管理筛滤规则)端口都在 fail2ban 的封禁范围内。另需注意:启用 fail2ban 时必须在compose.yaml中添加cap_add: NET_ADMIN,否则 nftables 无法真正封禁 IP(见 docs/content/config/environment.md#enable_fail2ban)。
9. 配套安全设置:TLS_LEVEL与密码套件
端口选择之外,TLS_LEVEL环境变量控制认证端口(SMTP:587 + 465 / POP3:110 + 995 / IMAP:143 + 993)的密码套件列表(见 docs/content/config/environment.md#tls_level):
# TLS_LEVEL=modern ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305 # TLS_LEVEL=intermediate ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384- 套件构成三要素:密钥交换为 ECDHE(25 端口仍为机会性 TLS 提供 DHE)、认证为 RSA + ECDSA(取决于证书密钥类型)、加密为 AES-GCM + CHACHA20-POLY1305 + AES-CBC。
intermediate比modern多 4 个基于 AES-CBC 的套件(ECDHE-ECDSA/RSA-AES128/256-SHA256/384)。AES-CBC 在 TLS 1.2 下通常视为安全,但它不是 AEAD算法,故被modern排除。- 默认值为
modern(empty等价于 modern),两种级别的最低 TLS 版本均为 TLS 1.2;DMS 在协商时默认采用服务器优先(Postfixtls_preempt_cipherlist = yes,Dovecotssl_server_prefer_ciphers = server)。 - 端口 25 配置了比
intermediate更宽泛的密码套件列表(需兼容海量遗留 MTA),但同样经过安全过滤。
10. 实战验证:如何测试端口的 TLS 行为
在 DMS 容器内可以直接用openssl验证各端口是否按预期提供 TLS 服务(以下命令源自 docs/content/config/security/ssl.md):
# 显式 TLS:先明文连接,再通过 -starttls 协商升级 docker exec mailserver openssl s_client \ -connect 0.0.0.0:25 \ -starttls smtp \ -CApath /etc/ssl/certs/ # 隐式 TLS:465/993/995 无需 -starttls,连接即加密 docker exec mailserver openssl s_client \ -connect 0.0.0.0:465 \ -CApath /etc/ssl/certs/- 成功时响应中应出现证书链,并包含一行
Verify return code: 0 (ok)。 - 测试 143(IMAP)时需把
-starttls的参数从smtp改为imap;外部测试时把-connect的 IP 换成你的服务器地址,必要时用-servername mail.example.com显式指定 SNI。 - 25 端口不强制 TLS,因此即使去掉
-starttls也能建立明文连接——这正好印证了前文"25 端口必须支持不安全连接"的结论。
11. 选型总结与常见疑问
我应该开放哪些端口?
- 最小可用集(MUA 收发 + 收信):
25(收信)、465(发信,隐式 TLS)、993(IMAP,隐式 TLS)。这也是 compose.yaml 默认映射中的五个端口里除 143/587 之外最精简的组合。 - 需要兼容老客户端 / 服务:再加上
587(显式 TLS 提交)与143(显式 TLS IMAP)。 - 需要 POP3:显式开启
ENABLE_POP3=1并映射110、995。 - 出站 25 被封锁:使用中继服务(relay host),配置方法见 docs/content/config/advanced/mail-forwarding/relay-hosts.md。
465 vs 587,到底选哪个?
两者都是"提交"端口且都要求认证,唯一区别是加密模式:465 为隐式 TLS(连接即加密,更安全、对反向代理更友好),587 为显式 TLS(先明文再STARTTLS协商,兼容面更广但有已知风险)。除非有明确的兼容性约束,否则优先 465;把 587 留给那些尚不支持隐式 TLS 的老客户端。
邮件 TLS 安全到什么程度?
务必牢记:邮件链路是"逐跳"加密的。你只能保证自己这一跳(MUA ↔ DMS,或 DMS ↔ 下一跳 MTA)是加密的;后续跳数是否加密,取决于对方 MTA 的策略。因此除了端口与TLS_LEVEL之外,还应考虑 MTA-STS、DNSSEC/DANE、STARTTLS Policy List 等加固手段,并参阅 docs/content/config/security/ssl.md 了解证书的完整配置方式(Let's Encrypt、手动证书、自签名等)。
【免费下载链接】docker-mailserverProduction-ready fullstack but simple mail server (SMTP, IMAP, LDAP, Antispam, Antivirus, etc.) running inside a container.项目地址: https://gitcode.com/gh_mirrors/do/docker-mailserver
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考