自建邮件服务器 Mailu 方案分析:在阿里云上安全地收发邮件
你以为建个博客就完了,但互联网上的扫描器可不这么想。上次分析完博客安全,这次我盯上了另一个”自建”大坑——邮件服务器。
一、为什么想自建邮箱
市面上企业邮箱不少,腾讯、阿里、Google Workspace,注册就能用。但自建邮箱有几个绕不开的吸引力:
- 数据主权:邮件内容存在自己服务器上,不经过第三方
- 完全控制:域名、存储、规则、反垃圾策略,全在自己手里
- 技术挑战:邮件系统涉及 DNS、TLS、SPF、DKIM、DMARC、反垃圾……搞明白了,对系统架构的理解会上一个台阶
但邮件服务器和 Web 服务不一样——它有一套自己的”潜规则”,一不小心就会进垃圾邮件箱,甚至被拉黑。
二、服务器环境
先看看我手头有什么:
| 项目 | 配置 |
|---|---|
| 系统 | Rocky Linux 9.7 |
| CPU / 内存 | x86_64 / 14Gi RAM |
| 磁盘 | 80GB SSD,剩余 41GB |
| 公网 IP | 阿里云 ECS(已隐藏) |
| 域名 | 自有域名(已隐藏) |
| 已有服务 | Nginx(HTTP,托管静态博客)+ Docker |
| Docker | v29.4.3,Compose v5.1.3 |
Docker 环境现成,磁盘空间够用,内存充裕。看起来条件不错——直到我测了一下 25 端口。
三、第一道坎:25 端口被封
测试过程
自建邮件服务器要能给别人发邮件,必须通过标准 SMTP 端口连接对方的 MX 服务器投递。我分别测了 Gmail、QQ 邮箱和 163 邮箱:
nc -v -w 5 <对方 MX 服务器地址> 25
# → TIMEOUT
三个主流邮箱,全部超时。原因很明确:
阿里云 ECS 默认封禁了 25 端口的出站流量。
这是国内云厂商的通用做法——防止云服务器被当作垃圾邮件跳板。你可以提工单申请解封,但通过率不高,而且就算解封了,云服务器 IP 段的信誉也普遍偏低,发出去的邮件进垃圾箱的概率很大。
这对自建邮箱意味着什么?
| 方向 | 端口 | 阿里云限制 | 结果 |
|---|---|---|---|
| 别人给我发邮件(入站) | 25 | 不限 | ✅ 只要安全组放行就行 |
| 我给别人发邮件(出站) | 25 | 封禁 | ❌ 无法直连对方 MX |
所以,如果你只收不发,25 出站被封不影响。但如果要发信,就必须绕道。
四、发信的出路:587 和 465
SMTP 有三个常用端口,各有各的定位:
| 端口 | 名称 | 设计用途 | 认证 | 加密 | 阿里云出站 |
|---|---|---|---|---|---|
| 25 | SMTP | 服务器→服务器投递 | 无 | 可选 STARTTLS | ❌ 封禁 |
| 587 | Submission | 客户端→服务器提交 | 必须 | 强制 STARTTLS | ✅ 开放 |
| 465 | SMTPS | 客户端→服务器提交(隐式TLS) | 必须 | 连接即 TLS | ✅ 开放 |
标准 SMTP 端口是服务器之间的”快递通道”,不需要认证,靠 IP 信誉和 SPF/DKIM 建立信任。但因为它没有认证机制,也成了垃圾邮件的重灾区——所以云厂商直接封了。
Submission 和 SMTPS 是用户提交邮件的”柜台窗口”,必须登录认证,全程加密。这两个端口阿里云完全放行。
所以自建邮箱的发信方案就一条路:本地邮件服务器通过 587/465 端口连接到 SMTP 中继服务,由中继代投。
五、SMTP 中继服务对比
| 服务 | 587 | 465 | 免费额度 | 注册门槛 | 适合场景 |
|---|---|---|---|---|---|
| SMTP2GO | ✅ | ✅ | 1,000 封/月 | 邮箱注册即用 | 个人首选,开箱即用 |
| SendGrid | ✅ | ✅ | 100 封/天 | 需信用卡验证 | 开发者友好 |
| Amazon SES | ✅ | ✅ | 62,000 封/月 | AWS 账号 + 审核 | 量大最便宜 |
| Brevo | ✅ | ✅ | 300 封/天 | 邮箱注册 | 欧洲隐私合规 |
| Mailgun | ✅ | ❌ | 前 3 月 5,000 封 | 信用卡 | 开发者 API 强 |
| 阿里云邮件推送 | ✅ | ❌ | 200 封/天 | 阿里云账号 | 国内生态 |
个人用量一个月几十封到几百封,SMTP2GO 的 1,000 封免费额度绰绰有余。配置上就是在 Mailu 的 .env 里加三行:
RELAYHOST=smtp.<中继服务域名>:587
RELAY_LOGIN=your_user
RELAY_PASSWORD=***
六、Mailu 方案分析
为什么选 Mailu
自建邮件服务器有几个主流选择:
| 方案 | 复杂度 | 资源占用 | Web 面板 | 适合 |
|---|---|---|---|---|
| Mailcow | 中 | ~3.5GB | ✅ SOGo | 多人多域名 |
| Mailu | 低 | ~500MB-1.5GB | ✅ SnappyMail | 个人/小团队 |
| Postfix + Dovecot 手工 | 高 | <200MB | ❌ | 技术极客 |
| Modoboa | 中 | ~1GB | ✅ | 中等规模 |
我选 Mailu 的理由:
- 轻量:去掉 ClamAV 只要 ~500MB 内存,对主流配置的云服务器毫无压力
- Docker 原生:一套
docker-compose.yml搞定,和我现有环境完全匹配 - 功能完整:Postfix + Dovecot + Rspamd + Webmail + 管理面板,该有的都有
- 文档清晰:官方文档覆盖从 DNS 配置到中继设置的完整流程
Mailu 架构
Mailu 用 Docker Compose 部署,核心容器如下:
┌─────────────────────────────────────────┐
│ docker compose │
│ │
│ frontend (Nginx) ← HTTP/S, SMTP, IMAP│
│ │ │
│ ├── admin ← Web 管理面板 │
│ ├── webmail ← Roundcube/Snappy │
│ ├── postfix ← SMTP 收信 │
│ ├── dovecot ← IMAP 邮件存储 │
│ ├── rspamd ← 反垃圾/SPF/DKIM │
│ └── redis ← 缓存 │
│ │
│ (可选) clamav ← 病毒扫描 (~1GB) │
└─────────────────────────────────────────┘
DNS 配置
自建邮件服务器的 DNS 记录是重中之重,少一个都可能收不到信或者进垃圾箱:
# 邮件服务器地址
A mail → <服务器公网 IP>
# MX 记录(告诉世界你的邮件服务器在哪)
MX @ → mail.<你的域名>. 优先级 10
# SPF(声明哪些 IP 可以代表你的域名发信)
TXT @ → v=spf1 mx ~all
# DKIM(邮件签名,证明邮件确实来自你)
TXT dkim._domainkey → v=DKIM1; k=rsa; p=<Mailu 自动生成的公钥>
# DMARC(告诉收件方如何处理伪造你的邮件)
TXT _dmarc → v=DMARC1; p=none; rua=mailto:dmarc@<你的域名>
其中 DKIM 密钥由 Mailu 自动生成,DMARC 策略初期用 p=none(只报告不拒收),确认正常后改为 p=quarantine 或 p=reject。
七、端口冲突与解决方案
问题
我现有的 Nginx 占了 HTTP 标准端口(托管静态博客),而 Mailu 自带的前端 Nginx 也需要标准 HTTP/HTTPS 端口。
方案对比
| 方案 | 做法 | 可行性 |
|---|---|---|
| A. 博客改端口 | 博客从 HTTP 标准端口改到非标准端口,Mailu 独占标准端口 | ✅ 推荐 |
| B. Nginx 反代 | 现有 Nginx 反代到 Mailu 后端 | ❌ Mailu 内部路由复杂,官方不推荐 |
| C. Mailu 非标准端口 | Mailu 用非标准 SMTP 端口 | ❌ MX 记录只支持标准 SMTP 端口,改端口无法收信 |
方案 A 是最干净的解法。个人博客只有我自己看,用非标准端口完全不影响。而且 Mailu 自带 Let’s Encrypt 证书自动续期,用标准端口才能正常工作。
八、安全风险评估
自建邮件服务器 = 在互联网上开几个固定端口,等着别人连。安全分析是必须的。
攻击面
互联网
│
┌────────────┼────────────┐
▼ ▼ ▼
25端口 443端口 993端口
(SMTP) (Web/HTTPS) (IMAPS)
│ │ │
┌────┴────┐ ┌───┴───┐ ┌───┴───┐
│ Postfix │ │ Nginx │ │Dovecot│
│ 收信队列 │ │ Webmail│ │ 邮箱存储│
└─────────┘ └───────┘ └───────┘
各端口风险
| 端口 | 风险等级 | 主要威胁 | 缓解措施 |
|---|---|---|---|
| SMTP(入站) | 🟡 中 | 垃圾邮件投递、缓冲区溢出 | Rspamd 反垃圾、Postfix 连接数限制 |
| HTTPS | 🔴 高 | Web 面板暴力破解、注入攻击 | HTTPS + fail2ban + 强密码 |
| IMAPS | 🟡 中 | IMAP 暴力破解 | Dovecot 认证限制、fail2ban |
| Submission | — | 不发信就不开 | 完全关闭 |
最大威胁:Web 管理面板
Mailu 的管理面板可以通过 https://mail.<你的域名>/admin 访问,这是最容易被自动化工具攻击的入口。
缓解措施:
- 强密码:admin 账户必须用强密码
- fail2ban:已有 fail2ban 运行中,加入 Mailu 登录失败规则
- IP 白名单(可选):只允许自己的 IP 访问
/admin - 双因素认证:如果后续 Mailu 版本支持
只收不发的安全优势
如果只做”收邮件”,不发邮件,安全风险会显著降低:
- 不会被当作垃圾邮件源:不发信 = 不会有人举报你发垃圾
- 不需要 SPF/DKIM 发信策略:减少了 DNS 配置复杂度
- 不需要 SMTP 中继账号:减少了一个攻击面
- 587/465 端口完全关闭:攻击面又少一块
安全加固清单
| 级别 | 措施 |
|---|---|
| 必做 | 强密码、HTTPS、fail2ban、关闭 587 端口、邮箱配额 |
| 推荐 | 管理面板 IP 白名单、只开 993 关 143(强制 SSL)、定期备份 |
| 可选 | 反垃圾规则调优、审计日志、容器资源限制 |
九、数据目录规划
<邮件服务目录>/
├── docker-compose.yml
├── .env # 核心配置
├── certs/ # Let's Encrypt 证书(自动生成)
├── data/
│ ├── postfix/ # 邮件队列
│ ├── dovecot/ # 邮箱存储(Maildir 格式)
│ ├── rspamd/ # 反垃圾学习数据
│ └── redis/ # 缓存
└── overrides/ # 自定义配置
邮件数据存在 <邮件服务目录>/data/dovecot/,按用户目录结构组织,格式是标准的 Maildir,随时可以迁移到其他系统。
备份策略
# 简单但有效的备份方案
tar czf <备份目录>/mailu-$(date +%Y%m%d).tar.gz <邮件服务目录>/data/
# 加上 cron 定时执行 + 远程存储
十、资源占用预估
| 组件 | 内存 | 磁盘 |
|---|---|---|
| Frontend (Nginx) | ~30MB | — |
| Postfix | ~20MB | 队列 < 50MB |
| Dovecot | ~50MB | 邮件存储(按实际量) |
| Admin | ~100MB | — |
| Webmail | ~100MB | — |
| Rspamd | ~200MB | ~100MB |
| Redis | ~20MB | — |
| ClamAV(可选) | ~1GB | — |
| 合计 | ~520MB(无 ClamAV) | 按需 |
对于一台主流配置的云服务器,Mailu 的开销几乎可以忽略。即使加上 ClamAV,也才 ~1.5GB。
十一、最终方案
经过分析,我的最终落地方案是:
┌──────────────────────────────────────────────────┐
│ 阿里云 ECS │
│ │
│ 个人博客 :<非标准端口> ← 静态 Astro 站点 │
│ │
│ Mailu ← Docker Compose │
│ ├── 收信: SMTP 入站(不受出站封禁影响) │
│ ├── Webmail: HTTPS 访问 │
│ ├── IMAP: IMAPS(强制 SSL) │
│ └── 发信: 通过 Submission → SMTP2GO 中继代发 │
│ │
│ DNS: mail.<你的域名> → <服务器公网 IP> │
│ MX: <你的域名> → mail.<你的域名> │
│ SPF/DKIM/DMARC: 全部配置 │
│ fail2ban: 保护各暴露端口 │
└──────────────────────────────────────────────────┘
一句话总结:Mailu Docker 部署 + SMTP2GO 中继发信 + fail2ban 防护 + 个人博客改到非标准端口让出标准端口。
十二、还没开始
分析做完了,方案也确定了。但截至目前——还没有部署。
原因很简单:邮件服务器一旦上线,就需要持续的运维——DNS 不能错、证书不能过期、磁盘不能满、日志要看、备份要做。在决定投入这份运维成本之前,先把方案想清楚,比冲动 docker compose up -d 更重要。
等哪天真的需要了,按这个方案走就行。
—— 分析于 2026-05-18,待实施。