基于Docker-Mailserver构建三层加密私有邮件服务器实战指南

1. 项目概述:为什么我们需要一个真正私有的邮件堡垒?

如果你还在用Gmail、Outlook或者QQ邮箱处理那些包含敏感信息的邮件,比如合同草稿、身份凭证、内部沟通,那你可能正在把你的数字隐私暴露在聚光灯下。商业邮件服务商的数据挖掘、潜在的审查、服务器被黑的风险,这些都不是危言耸听。自己搭建邮件服务器听起来很硬核,但有了Docker-Mailserver,这件事的门槛被极大地降低了。它把Postfix、Dovecot、SpamAssassin、OpenDKIM、ClamAV等一堆复杂的邮件服务组件,打包成了一个用Docker Compose就能一键拉起的环境。

但这个项目的目的,远不止是“搭起来能发信”。它的核心是“终极加密”和“端到端安全”。这意味着,我们要构建的不仅仅是一个能工作的邮件服务器,而是一个从邮件离开你的客户端,到抵达收件人客户端,全程都尽可能处于加密状态的隐私堡垒。我们会覆盖传输层加密(TLS)、存储加密、以及最重要的——端到端加密(使用GPG或S/MIME),确保即使邮件服务器本身被攻破,邮件内容对攻击者而言也只是一堆乱码。这不仅仅是技术上的配置,更是一种对数字主权的实践。

2. 核心安全架构与组件选型解析

2.1 Docker-Mailserver的组件安全角色拆解

Docker-Mailserver不是一个单一软件,而是一个精心编排的安全生态。理解每个组件的安全职责,是正确配置的前提。

  • Postfix (MTA - 邮件传输代理):它是邮件的“邮局”和“路由器”。安全配置的核心在于强制使用TLS加密连接(防止传输中被窃听)、严格的身份验证(防止被用作垃圾邮件中转站)、以及细致的访问控制列表。我们会配置它只接受来自加密连接的邮件提交,并对发出的邮件强制尝试TLS连接。
  • Dovecot (MDA/IMAP/POP3 - 邮件投递与访问代理):它是邮件的“保险柜”和“存取窗口”。负责将邮件投递到用户邮箱,并通过IMAP/POP3协议提供给客户端。它的安全核心是用户认证、邮箱存储加密(使用mail_crypt插件),以及管理客户端连接加密。我们会启用mail_crypt,让存储在磁盘上的邮件也是加密的,即使有人复制了你的邮件数据文件也无法直接读取。
  • OpenDKIM & OpenDMARC:这是邮件的“身份印章”和“验证策略”。它们不是加密工具,但对于邮件能否安全送达至关重要。DKIM(域名密钥识别邮件)用私钥为发出的邮件签名,收件方服务器用DNS公钥验证,防止邮件在传输中被篡改。DMARC(基于域的消息认证、报告和一致性)则告诉收件方服务器,如果DKIM(或SPF)验证失败该怎么办(拒收、隔离或放行)。正确配置它们能极大提升邮件可信度,避免被标记为垃圾邮件或钓鱼邮件。
  • ClamAV & SpamAssassin:这是邮件的“安检门”和“垃圾过滤器”。ClamAV查杀病毒,SpamAssassin基于规则和贝叶斯过滤垃圾邮件。它们保护服务器和用户免受恶意软件和骚扰邮件的侵害。虽然不直接参与端到端加密,但一个安全的邮件环境离不开它们。

2.2 加密策略的三层防御体系

我们的安全目标是通过三层加密,构建纵深防御。

  1. 传输层加密 (TLS/SSL):保护邮件在“路上”的安全。确保邮件从你的客户端到服务器(SMTP提交,IMAP/POP3存取),以及从你的服务器到对方服务器(SMTP传输)的整个链路都是加密的。这通过Let‘s Encrypt等免费证书机构颁发的SSL/TLS证书实现。这是基础,必须做到100%强制。
  2. 存储层加密 (At-Rest Encryption):保护邮件在“家里”(服务器磁盘上)的安全。即使黑客入侵了服务器,拿到了数据库或邮件文件,也无法直接读取内容。Dovecot的mail_crypt插件可以实现这一点,它使用每个用户独立的密钥对邮箱进行加密。
  3. 端到端加密 (End-to-End Encryption, E2EE):保护的终极形态。确保邮件内容从发送者的客户端加密后,只有指定的接收者才能在其客户端解密。即使邮件经过的每一个服务器(包括你自己的)被完全控制,内容也无人能读。这主要通过GPG (GNU Privacy Guard)S/MIME (Secure/Multipurpose Internet Mail Extensions)协议实现,需要在邮件客户端(如Thunderbird + Enigmail, Outlook)进行配置,服务器不参与加解密过程,只传递密文。

注意:很多教程只做到第一层(TLS)就结束了,但这远远不够。TLS只能防止传输窃听,邮件在服务器上仍是明文。存储加密解决了服务器被入侵的风险,但管理员仍有权限。唯有端到端加密,才能真正实现“除了你和收件人,谁也无法阅读”的隐私承诺。本指南将完整实现这三层。

3. 基础环境部署与强制TLS配置

3.1 服务器准备与Docker环境部署

假设你有一台运行Ubuntu 22.04 LTS的VPS,域名是yourdomain.com。首先,完成基础准备:

# 更新系统并安装必要工具 sudo apt update && sudo apt upgrade -y sudo apt install -y docker.io docker-compose-v2 git curl # 将用户加入docker组,避免每次用sudo sudo usermod -aG docker $USER # 退出重新登录使组生效 # 获取Docker-Mailserver git clone https://github.com/docker-mailserver/docker-mailserver.git cd docker-mailserver

接下来是关键的域名解析。在你的域名DNS控制面板,必须添加以下记录(以yourdomain.com和IP1.2.3.4为例):

记录类型主机名说明
A@1.2.3.4主域名指向服务器IP
Amail1.2.3.4邮件服务器主机名
MX@10 mail.yourdomain.com.邮件交换记录,优先级10
TXT@v=spf1 mx ~allSPF记录,声明授权发信的服务器
CNAMEautodiscovermail.yourdomain.com.(可选) 客户端自动发现
CNAMEautoconfigmail.yourdomain.com.(可选) 客户端自动配置

3.2 生成配置与获取TLS证书

Docker-Mailserver提供了方便的配置生成脚本。在项目根目录执行:

# 生成主要的配置文件 `compose.yaml` 和 `mailserver.env` cp compose.yaml.dist compose.yaml cp mailserver.env.dist mailserver.env # 使用工具生成用户账户和DKIM密钥 ./setup.sh email add user1@yourdomain.com yourpassword ./setup.sh config dkim

现在,获取SSL/TLS证书。我们使用容器内的acme-companion(与Traefik搭配)或更直接的方式,使用Certbot。这里演示一个在宿主机操作,然后挂载证书的通用方法:

# 安装Certbot sudo apt install -y certbot # 申请证书(确保80/443端口可访问,且域名解析已生效) sudo certbot certonly --standalone -d mail.yourdomain.com --agree-tos --email admin@yourdomain.com # 证书通常存放在 /etc/letsencrypt/live/mail.yourdomain.com/ # 我们需要将其链接或复制到Docker-Mailserver能访问的目录 mkdir -p data/ssl sudo cp /etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem data/ssl/ sudo cp /etc/letsencrypt/live/mail.yourdomain.com/privkey.pem data/ssl/ sudo chown -R $USER:$USER data/ssl/

3.3 配置强制TLS与端口安全

编辑compose.yaml文件,确保服务定义中正确挂载了SSL证书目录。然后,关键在mailserver.env和环境变量中配置强制TLS。

编辑mailserver.env,找到并修改以下关键变量:

# 启用SSL/TLS SSL_TYPE=manual SSL_CERT_PATH=/etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem SSL_KEY_PATH=/etc/letsencrypt/live/mail.yourdomain.com/privkey.pem # 强制使用TLS ENABLE_POP3=no # 通常禁用不加密的POP3 ENABLE_FAIL2BAN=y # 启用防暴力破解 SPOOF_PROTECTION=y # 防欺骗保护 # Postfix强制TLS设置(通过postfix-main.cf覆盖) SMTPD_TLS_SECURITY_LEVEL=encrypt # 强制要求客户端连接使用TLS SMTPD_TLS_AUTH_ONLY=yes smtp_tls_security_level=may # 对外发送时尽量使用TLS,对方不支持则降级(可改为encrypt强制,但可能导致某些旧服务器无法收信)

你还需要创建自定义的Postfix和Dovecot配置文件来强化安全。在项目根目录创建config/目录(如果不存在),然后创建config/postfix-main.cfconfig/dovecot.cf

config/postfix-main.cf中添加:

# 强制提交端口(587)使用TLS并启用身份验证 smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unknown_client_hostname, reject_rbl_client sbl.spamhaus.org smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_mandatory_ciphers = high

config/dovecot.cf中确保:

# 强制IMAPS(993端口),禁用纯文本IMAP(143端口) ssl = required ssl_cert = </etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem ssl_key = </etc/letsencrypt/live/mail.yourdomain.com/privkey.pem ssl_min_protocol = TLSv1.2 ssl_cipher_list = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305

最后,在compose.yaml中,确保将这些配置目录和SSL证书目录挂载到容器内:

services: mailserver: image: docker.io/mailserver/docker-mailserver:latest volumes: - ./data/ssl/:/etc/letsencrypt/live/mail.yourdomain.com/:ro - ./config/:/tmp/docker-mailserver/:ro # ... 其他挂载

启动服务:docker compose up -d。使用./setup.sh email list检查用户,并用docker logs mailserver查看日志,确保无报错。

实操心得:强制TLS后,一定要用telnetopenssl s_client命令测试端口响应。例如,openssl s_client -connect mail.yourdomain.com:465 -starttls smtp应该能成功握手。如果遇到证书错误,通常是证书链不完整或域名不匹配。另一个常见坑是防火墙,务必放行25(SMTP)、465(SMTPS)、587(Submission)、993(IMAPS)、995(POP3S)端口。

4. 实现存储层加密:Dovecot mail_crypt 详解

传输安全了,接下来解决“静止数据”的安全。Dovecot的mail_crypt插件可以对每个用户的邮箱进行透明加密。这意味着邮件在写入磁盘前加密,读取时自动解密,对用户和客户端完全无感。

4.1 启用与配置 mail_crypt

首先,需要修改Dovecot的全局配置。我们通过环境变量和自定义配置文件来实现。编辑mailserver.env,添加或确认:

# 启用mail_crypt插件 ENABLE_DOVECOT_MAIL_CRYPT=y

这会让Docker-Mailserver在初始化时自动配置mail_crypt的基础框架。但我们需要更精细的控制。创建自定义配置文件config/dovecot-local.cf(或修改之前的dovecot.cf):

# 启用mail_crypt插件 mail_plugins = $mail_plugins mail_crypt # 配置mail_crypt plugin { # 使用共享的加密密码(存储在dovecot-encryption.password文件中) # 也可以使用用户特定的密码(更安全,但更复杂) mail_crypt_global_private_key = </etc/dovecot/global_private_key.pem mail_crypt_global_public_key = </etc/dovecot/global_public_key.pem # 加密算法和设置 mail_crypt_save_version = 2 mail_crypt_require_encrypted_user_key = yes } # 为每个邮箱定义加密设置 namespace inbox { # ... 其他设置 mail_crypt_save = 1 # 1=始终加密,0=不加密,2=根据用户偏好 }

4.2 生成加密密钥并管理

接下来,生成全局加密密钥对。在宿主机上操作:

# 进入docker-mailserver配置目录 cd /path/to/docker-mailserver # 生成RSA密钥对(4096位) openssl genrsa -out data/dovecot/global_private_key.pem 4096 openssl rsa -in data/dovecot/global_private_key.pem -pubout -out data/dovecot/global_public_key.pem # 设置正确的权限 chmod 600 data/dovecot/global_private_key.pem chmod 644 data/dovecot/global_public_key.pem

然后,需要修改compose.yaml,将密钥文件挂载到容器内正确的位置:

services: mailserver: volumes: - ./data/dovecot/global_private_key.pem:/etc/dovecot/global_private_key.pem:ro - ./data/dovecot/global_public_key.pem:/etc/dovecot/global_public_key.pem:ro # ... 其他挂载

4.3 为用户启用邮箱加密并验证

仅仅有全局密钥还不够,需要为每个用户“激活”加密。Docker-Mailserver的setup.sh脚本可以方便地管理用户加密密码。

# 为用户 user1@yourdomain.com 设置加密密码(可以与登录密码不同,更安全) ./setup.sh encrypt add user1@yourdomain.com # 按提示输入加密密码 # 列出已启用加密的用户 ./setup.sh encrypt list

重启Docker-Mailserver容器以使配置生效:docker compose restart

如何验证加密生效?

  1. 直接查看邮件文件:登录服务器,找到邮件存储目录(通常是./data/mail/yourdomain.com/user1/)。你会发现dovecot-encryption文件夹,里面存放着加密相关的密钥文件。而cur/,new/等目录下的邮件文件(通常是S=xxx,W=xxx格式的文件),用文本编辑器打开看,内容将是乱码(加密后的数据),而不是可读的邮件原文。
  2. 通过Dovecot日志:查看Dovecot的日志docker logs mailserver | grep -i crypt,应该能看到关于mail_crypt加载和加解密操作的信息。
  3. 客户端无感测试:用Thunderbird或Outlook配置好账户,收发邮件一切正常。这就是透明加密的魅力——安全升级对用户体验零影响。

注意事项mail_crypt的加密密码至关重要!如果丢失,加密的邮件将永久无法恢复。务必安全备份加密密码和全局密钥对。建议将加密密码与用户登录密码分开设置和管理。另外,启用加密后,邮件搜索(全文检索)功能可能会受影响或需要额外配置,因为Dovecot无法直接读取加密后的邮件内容来建立索引。

5. 端到端加密实战:GPG与S/MIME配置指南

这是隐私保护的皇冠。端到端加密(E2EE)意味着加密和解密只发生在通信双方的客户端设备上。服务器只是密文的搬运工。这里我们重点介绍最常用的两种标准:GPG(开源,社区驱动)和S/MIME(基于X.509证书,企业常用)。

5.1 使用GPG进行端到端加密

GPG(GNU Privacy Guard)是OpenPGP标准的开源实现。它使用非对称加密,每个人拥有一对密钥:公钥(公开,用于加密)和私钥(绝密,用于解密和签名)。

步骤1:在客户端生成GPG密钥对以Thunderbird邮件客户端为例,配合Enigmail插件(新版Thunderbird已内置OpenPGP支持)。

  1. 在Thunderbird中,打开账户设置->端到端加密->添加密钥
  2. 选择创建新OpenPGP密钥
  3. 输入你的姓名和邮箱(必须是你的Docker-Mailserver邮箱地址,如user1@yourdomain.com)。
  4. 设置一个强密码来保护你的私钥。这个密码是解密邮件的最后一道关卡,务必牢记。
  5. 密钥类型选择RSA,密钥长度至少4096位。过期时间可根据需要设置(例如5年)。
  6. 生成完成后,你的密钥对就存储在本地了。

步骤2:交换公钥要让别人给你发加密邮件,他们需要你的公钥。你可以:

  • 导出并发送:在Thunderbird的OpenPGP密钥管理器中,找到你的密钥,选择导出公钥,保存为一个.asc文件。通过非加密邮件(或其他安全渠道)发送给联系人。
  • 上传到公钥服务器:在密钥管理器中,选择上传公钥到密钥服务器(如keys.openpgp.org)。这样任何人只要知道你的邮箱,就能搜索到你的公钥。请注意隐私,上传到公钥服务器的信息是公开的。

步骤3:导入联系人的公钥并发送加密邮件当收到联系人的公钥文件(.asc)后,在Thunderbird中导入OpenPGP密钥。导入后,撰写给该联系人的新邮件。Thunderbird会检测到收件人有可用的公钥,工具栏会出现使用OpenPGP加密使用OpenPGP签名的选项。勾选加密,发送。这封邮件的正文和附件在离开你的电脑前就已加密,只有拥有对应私钥的联系人才能解密阅读。

步骤4:解密和验证签名收到加密邮件时,Thunderbird会自动用你的私钥解密(可能需要输入私钥保护密码)。如果邮件还带有数字签名,Thunderbird会验证签名,确认邮件确实来自声称的发件人且未被篡改。

5.2 使用S/MIME进行端到端加密

S/MIME同样使用非对称加密,但它基于广泛使用的X.509证书体系,与企业PKI集成更好,许多商业邮件客户端(如Outlook, Apple Mail)原生支持。

步骤1:获取S/MIME证书你需要从一个受信任的证书颁发机构(CA)获取一张个人邮件安全证书。有些CA提供免费试用证书,例如ActalisSectigo的部分产品。申请过程通常需要验证你对邮箱的控制权(会向你的邮箱发送验证邮件)。

  1. 向CA提交申请,选择“电子邮件保护证书”或“S/MIME证书”。
  2. 完成邮箱验证。
  3. 生成一个证书签名请求(CSR)。这通常在客户端(如Outlook)或OpenSSL命令行中完成。CA会要求你提交这个CSR。
  4. 验证通过后,CA会颁发证书(通常是一个.p12.pfx文件,包含了你的私钥和公钥证书)。

步骤2:在客户端安装S/MIME证书以Thunderbird为例:

  1. 打开首选项->隐私与安全->证书->查看证书
  2. 您的证书选项卡,点击导入,选择你从CA获得的.p12文件。
  3. 输入导入证书时设置的密码(如果有)。
  4. 导入成功后,你的证书会出现在列表中。在端到端加密设置中,为你的邮件账户选择这张S/MIME证书。

步骤3:发送加密和签名邮件与GPG类似,撰写邮件时,Thunderbird工具栏会出现使用S/MIME加密使用S/MIME签名的按钮。要加密,你需要首先拥有收件人的S/MIME公钥证书。通常,当收件人给你发送一封签名邮件时,其证书会自动附带并导入你的客户端。之后,你就可以向他发送加密邮件了。

5.3 GPG vs S/MIME 选择与混合策略

特性GPG (OpenPGP)S/MIME
标准开源标准 (RFC 4880)商业标准,基于X.509
证书体系去中心化的Web of Trust中心化的CA hierarchy
客户端支持需要插件或内置支持(Thunderbird好)广泛原生支持(Outlook, Apple Mail, 移动端)
企业集成较难容易,与AD/PKI集成
密钥管理用户自行管理,更灵活但也更复杂通常由CA或企业IT管理
常见场景技术社区、开源项目、个人隐私爱好者企业通信、政府机构、商业往来

个人建议:对于个人和小团队,从GPG开始学习成本低,自由度大。如果需要与更广泛的商业伙伴通信,尤其是对方可能只用Outlook,那么准备一张S/MIME证书会很有用。实际上,你可以两者都配置,根据不同的联系人选择使用哪种方式。Thunderbird等客户端可以同时管理GPG密钥和S/MIME证书。

核心避坑指南

  1. 私钥备份!私钥备份!私钥备份!无论是GPG私钥还是S/MIME的.p12文件,丢失就意味着永远无法解密之前收到的邮件。务必加密备份到多个安全位置(如离线U盘、密码管理器)。
  2. 信任链问题:GPG需要手动验证和签名对方的公钥以建立信任。S/MIME依赖于你对CA的信任。不要盲目信任任何证书。
  3. 元数据不加密:端到端加密只保护邮件正文和附件。收件人、发件人、主题、时间等元数据仍然是明文的。这是协议限制,需要知晓。
  4. 发送加密邮件前:务必确认你使用的确实是对方的公钥。GPG可以通过指纹验证,S/MIME可以查看证书详情。用错误公钥加密等于把秘密送给陌生人。

6. 高级安全加固与运维监控

基础和三层加密都完成后,我们需要让这个堡垒更坚固,并知道它是否安然无恙。

6.1 防火墙与网络层加固

除了Docker本身的网络隔离,应在宿主机防火墙(如ufw)上实施最小化开放原则。

sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp # SSH sudo ufw allow 25/tcp # SMTP (谨慎,可先限制来源IP) sudo ufw allow 465/tcp # SMTPS sudo ufw allow 587/tcp # Submission sudo ufw allow 993/tcp # IMAPS sudo ufw allow 995/tcp # POP3S sudo ufw allow 80/tcp # 用于证书续期 sudo ufw allow 443/tcp # 也可用于证书续期或Webmail sudo ufw enable

对于SMTP端口25,由于常被垃圾邮件发送者扫描,可以考虑使用云服务商的安全组或iptables规则,仅允许来自已知中继服务器或特定IP范围的连接。

6.2 日志监控与入侵检测

日志是安全运维的眼睛。Docker-Mailserver的日志统一输出到容器日志。

  • 集中查看docker logs --tail 100 -f mailserver实时跟踪。
  • 关键日志文件:在容器内,主要日志位于/var/log/mail/(mail.log, mail.warn等)和/var/log/dovecot/。可以通过挂载卷的方式持久化到宿主机。
  • 监控关键事件:使用fail2ban(已在环境中启用)监控认证失败日志,自动封禁IP。可以配置更严格的规则,例如短时间内多次连接尝试。
  • 使用外部工具:将日志导入到ELK Stack(Elasticsearch, Logstash, Kibana)或Grafana Loki + Promtail + Grafana中,可以建立仪表盘,监控诸如“每小时认证失败次数”、“外发邮件量突增”、“异常登录地理位置”等指标。

6.3 定期维护与备份策略

一个安全的系统必须是一个可维护的系统。

  1. 证书续期:Let‘s Encrypt证书90天过期。设置一个cronjob自动续期并重启容器。
    # 示例cronjob (每周日凌晨2点检查续期) 0 2 * * 0 certbot renew --quiet --deploy-hook "cd /path/to/docker-mailserver && docker compose restart mailserver"
  2. 软件更新:定期更新Docker镜像以获得安全补丁。
    cd /path/to/docker-mailserver docker compose pull docker compose up -d --force-recreate # 注意:先备份数据目录和配置
  3. 数据备份:备份以下关键数据,并加密存储。
    • ./data/mail/:所有用户的邮件(已加密)。
    • ./data/ssl//etc/letsencrypt/:TLS证书。
    • ./data/dovecot/global_*.pem:存储加密全局密钥。
    • ./config/mailserver.env:所有配置文件。
    • 用户加密密码:通过./setup.sh encrypt list显示的密码哈希,但最好有独立的记录。
    • GPG/SMIME私钥:由用户各自备份。
  4. 安全扫描:定期使用clamav进行病毒扫描(已集成),也可以考虑使用rkhunterlynis进行主机层面的安全审计。

7. 常见问题排查与故障恢复实录

即使准备再充分,实际运行中也会踩坑。这里记录几个我遇到过的典型问题。

7.1 邮件发送失败(被拒收)

这是最常见的问题,通常是由于反垃圾邮件策略。

  • 症状:日志中出现550 5.7.1 Message rejected due to SPF/DKIM/DMARC failure或类似信息。
  • 排查
    1. 检查DNS记录:使用在线工具(如mxtoolbox.com)检查你的域名的SPF、DKIM、DMARC记录是否已正确发布且生效。确保DKIM公钥与服务器生成的私钥匹配(./setup.sh config dkim会显示需要添加的TXT记录)。
    2. 检查PTR反向解析:很多邮件服务器会检查IP的反向DNS解析(PTR记录)是否与发信域名匹配。联系你的VPS提供商,为你的服务器IP设置PTR记录,指向mail.yourdomain.com
    3. 检查IP信誉:如果你的IP是新IP或有过发垃圾邮件的历史,可能会被列入黑名单(RBL)。在mxtoolbox.com检查你的IP是否在主要黑名单中。如果被列入了,需要按该黑名单网站的要求申请移除。
  • 解决:确保SPF、DKIM、DMARC、PTR四要素齐全。对于新服务器,初期可以尝试先向Gmail、Outlook等大型服务商发送测试邮件,它们的反馈通常比较详细。

7.2 客户端无法连接(SSL/TLS错误)

  • 症状:Thunderbird提示“安全连接失败”、“证书错误”或“协议错误”。
  • 排查
    1. 证书链不完整:使用openssl s_client -connect mail.yourdomain.com:993 -showcerts检查证书链。如果中间证书缺失,需要将fullchain.pem(包含服务器证书和中间证书)正确配置给Dovecot和Postfix。
    2. 证书域名不匹配:确保证书是针对mail.yourdomain.com申请的,而不是yourdomain.com。通配符证书*.yourdomain.com也可以。
    3. 协议或密码套件过时:我们在配置中已禁用不安全的SSLv3、TLSv1.0/1.1。确保客户端支持TLSv1.2或更高。检查配置中的ssl_min_protocolssl_cipher_list
    4. 端口错误或防火墙:确认客户端连接的是正确的加密端口(IMAPS: 993, SMTPS: 465, Submission: 587),并且宿主机防火墙和云服务商安全组已放行。
  • 解决:根据openssl s_client的输出和客户端错误信息逐一修正。Let‘s Encrypt的fullchain.pem通常是完整的。

7.3 启用mail_crypt后客户端搜索失效

  • 症状:在Thunderbird中搜索邮件内容,找不到已知存在的邮件。
  • 原因:Dovecot默认的全文搜索索引(fts)无法读取加密后的邮件内容。
  • 解决:需要配置mail_crypt与搜索插件协同工作。编辑Dovecot配置,启用mail_crypt的“索引化加密”或使用“插件化索引”。这是一个高级主题,通常需要在自定义配置中添加类似以下配置:
    plugin { mail_crypt_global_private_key = ... mail_crypt_require_encrypted_user_key = yes # 启用对加密邮件的索引支持 mail_crypt_save_version = 2 } # 使用一个支持加密邮件的索引后端,如fts-xapian(需要额外安装) # 或者,如果搜索不是刚需,可以接受此限制。
    更简单(但不完美)的临时方案是,在Thunderbird中设置为“在本地索引邮件”,但这只对本机已下载的邮件有效。

7.4 数据恢复演练(至关重要)

场景:服务器硬盘损坏,你需要从备份恢复。

  1. 恢复文件:将备份的./data/mail/,./data/ssl/,./data/dovecot/,./config/,mailserver.env等恢复到新服务器的相同路径。
  2. 恢复加密能力
    • 存储加密:确保global_private_key.pemglobal_public_key.pem已恢复,并且每个用户的加密密码记录已恢复(或用户记得自己的加密密码)。启动服务后,Dovecot应能自动解密邮件。
    • 端到端加密:用户的GPG/SMIME私钥需要由用户自己从备份中导入到新的客户端设备。服务器不存储这些,因此服务器恢复不影响E2EE。
  3. 验证:用一个测试账户登录Webmail或客户端,查看历史邮件是否完整、可读。发送一封测试邮件到外部邮箱(如Gmail),检查SPF/DKIM/DMARC是否通过。

最后的小技巧:定期进行“消防演习”。每季度或每半年,在一个隔离的测试环境中,用你的备份完整恢复一遍邮件系统。这能确保你的备份是有效的,并且你对恢复流程足够熟悉。在真正的灾难发生时,这份熟练度是无价的。隐私和安全是一场持续的战斗,而一个经过充分测试的恢复计划,是你最可靠的防线。