基于 Docker 快速搭建 Maddy 邮箱服务
Docker 搭建
Maddy 是一个 GO 语言开发的 ALL-IN-ONE 邮件系统,主要功能是通过 SMTP 发送和接收邮件,通过 IMAP,客户端可以实现访问,也支持 DKIM、SPF、DMARC、DANE、MTA-STS 等邮件相关的安全和反垃圾协议。
通俗点讲就是部署特别方便, 资源占用少,非常适合个人使用的电子邮件服务器。
项目地址:maddy/maddy.conf at master · foxcpp/maddy (github.com)
前提:
- 拥有一台有公网 IP 的服务器,并且有域名
- 服务器开启以下端口:143,25,465,587,993
参考:常用邮件端口
以下用
example.com
这个域名作演示,实际中替换成真实域名。
1. 申请 SSL 证书
mx1.example.com
证书,下载得到
certificate.crt
和
private.key
将
certificate.crt
和
private.key
分别重命名为
fullchain.pem
、
privkey.pem
(配置文件中默认指定的名称)
2. 创建 docker 持久化目录,引入配置文件
从 maddy.conf 下载官方默认的配置文件,并修改其中内容:
(hostname)= mx1.example.com
(primary_domain)= example.com
创建一个目录 maddydata 用于存放容器内的数据映射,并且把上面的证书文件与 maddy.conf 放入
此时的 maddydata 目录结构如下:
maddydata
├── certs
│ └── mx1.example.com
│ ├── fullchain.pem
│ └── privkey.pem
└── maddy.conf
3. Docker 启动 Maddy
docker run \
--name maddy \
-e MADDY_HOSTNAME=mx1.example.com \
-e MADDY_DOMAIN=example.com \
-v /maddydata/certs:/etc/maddy/certs/ \
-v /maddydata:/data \
-p 25:25 \
-p 143:143 \
-p 587:587 \
-p 993:993 \
-d foxcpp/maddy:latest
如果 docker 服务启动失败,根据
docker logs maddy
查看日志寻找原因
4. 云服务器的 DNS 设置
更详细的解释可以参考官方文档 Installation & initial configuration - maddy
注意,
example.com
应该改成你自己的域名
# A 记录
example.com. A 10.2.3.4
# MX 记录
example.com. MX 10 mx1.example.com.
# MX 域解析
mx1.example.org. A 10.2.3.4
# SPF
example.com. TXT "v=spf1 mx ~all"
example.com. TXT "v=spf1 mx ~all"# _dmarc
_dmarc.example.com. TXT "v=DMARC1; p=quarantine; ruf=mailto:[email protected]"# _mta-sts. _smtp.tls
_mta-sts.example.com. TXT "v=STSv1; id=1"
_smtp._tls.example.com. TXT "v=TLSRPTv1;rua=mailto:[email protected]"# 设置的值项目运行后自动生成,cat maddydata/dkim_keys/example.com_default.dns
default._domainkey.example.com. TXT "v=DKIM1; k=ed25519; p=xxxxxxxxxxxx"
如果有 IPV6 地址,也可以配置上:
example.com. AAAA 2001:beef::1 # IPV6 有就配置
mx1.example.org. AAAA 2001:beef::1 # IPV6 有就配置
对于各个配置的详细解析可以参考后面部分。
Maddy 命令行操作
进入 maddy 容器中:
dockerexec -it maddy sh
Maddy 使用虚拟用户,所以不像 postfix 和 dovecot 一样需要创建系统用户。它需要创建的登录账户和 IMAP 本地存储账户。(登录账户是 SMTP 和 IMAP 登录时的验证信息)
# 创建一个 [email protected] 的登录账户
$ maddyctl creds create [email protected]
# 查看登录账户列表
$ maddyctl creds list
# 创建一个 [email protected] 邮件储存账户
$ maddyctl imap-acct create [email protected]
# 查看刚存储账户列表
$ maddyctl imap-acct list
# 可以看到账户下的邮件分类
$ maddyctl imap-mboxes list [email protected]
INBOX [\HasNoChildren]
Sent [\Sent \HasNoChildren]
Trash [\Trash \HasNoChildren]
Junk [\Junk \HasNoChildren]
Drafts [\Drafts \HasNoChildren]
Archive [\Archive \HasNoChildren]# 可以查看当前账户对应分类接收到的邮件,一般收件在 INBOX 中$maddyctl imap-msgs list [email protected] INBOX
测试是否搭建成功
登录上一个 Web 邮箱(例如 163),往你刚刚创建的
[email protected]
发送邮件
查看是否收到邮件:
$ maddyctl imap-msgs list [email protected] INBOX
UID1: <[email protected]> - =?utf-8?B?dGVzdEBoYWhhY29kZS5jbg==?=[\Recent], 2023-03-22 09:54:47 +0000 UTC
域名解析配置基础知识
无论邮箱系统用的什么软件,都绕不开邮件相关的域名解析,只要搞邮件就需配置以下域名解析:
- MX 记录 :域名系统基础记录,指向邮件服务器
- SPF 记录 :指定哪些服务器可以使用你的域名发送邮件
- DKIM 记录 :防止发送的电子邮件内容篡改
- DMARC 记录 :当 SPF 和 DKIM 验证失败时,指定接收方的处理策略并向指定邮箱报告
- PTR 记录 :即 IP 反解析,根据 IP 反查域名,需供应商来做
MX 记录
收发邮件时,MX 记录指定了自己的邮件服务器地址,可以设置优先级,一般建议 2 条以上 mx 记录()
域名 类型 值 优先级
example.com mx mx1.example.com 10
设置对应 MX 子域名的记录:
mx1.example.com A 10.2.3.4
设置好后使用 dig 命令验证一下:
dig mx example.com
PTR 记录
将域名映射到 IP 地址是正向解析,从 IP 地址到域名的映射就是反向解析,在公网上,反向解析无法由 DNS 提供,因为 IP 地址的管理权限属于运营商,所以需要向运营商申请添加反向解析,运营商通过 PTR(Pointer Record)记录将 IP 地址指向域名。邮件服务器 IP 不做 PTR 记录,发送邮件后会有很大概率被当成垃圾邮件。
联系供应商加好后,可以用 dig 命令验证:
dig -x mx1.example.com
SPF 记录
SPF 全名是 发件人策略框架,主要作用是将发信的邮件服务器和发信域名进行绑定,防止伪造发件人。在 SPF 记录中使用 TXT 记录指定允许发信的服务器,当对方收到邮件后,系统会验证发信域名并读取 SPF 记录中的 IP,验证是否一致后采取进一步动作。
以谷歌 SPF 记录为例:
# dig txt gmail.com
gmail.com. 300 IN TXT "v=spf1 redirect=_spf.google.com"# dig txt _spf.google.com
_spf.google.com. 300 IN TXT "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"# dig txt _netblocks.google.com
_netblocks.google.com. 300 IN TXT "v=spf1 ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:209.85.128.0/17 ip4:216.58.192.0/19 ip4:216.239.32.0/19 ~all"
SPF 记录以
v=spf1
开头,以
all
结尾,中间可以使用 ip4/ip6/a/mx/include/redirect 等关键字进行 ip 范围指定。SPF 记录的匹配机制会结合 限定词 来告诉服务器匹配记录时的动作。常见的限定词有:
+
放行,如果没有明确指定限定词,则为默认值。-
硬拒绝,直接拒绝来自未经授权主机的邮件。~
软拒绝,邮件可被接受,也可被标记为垃圾邮件。?
中性,不考虑邮件是否被接受。
个人邮件设置允许 mx 记录中的服务器发信即可,最终设置 SPF 记录为:
example.com txt "v=spf1 mx -all"
DKIM 记录
DKIM 记录主要作用也是防止邮件被恶意篡改,保证邮件内容的完整性,使用的方式是与 SSL 类似,服务器产生一个公私钥对,私钥为每一封外发的邮件签名并在邮件头中插入 DKIM 签名(DKIM-Signature 头),公钥则保存在域名的记录中,邮件接收方接收邮件时,通过 DNS 查询获得公钥,并使用公钥解密邮件签名, 从而验证邮件有效性和完整性。
Docker 运行 Maddy 启动后会自动生成 DKIM 私钥和需添加的 dns 记录,位置在:
dockerdata/dkim_keys/example.com_default.dns
default._domainkey.example.com txt "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0......"
DMARC 记录
DMARC 基于现有的 SPF 和 DKIM 协议,并声明对验证失败邮件的处理策略。邮件接收方接收邮件时,首先通过 DNS 获取 DMARC 记录,再对邮件来源进行 SPF 验证和 DKIM 验证,对验证失败的邮件根据 DMARC 记录进行处理,并将处理结果反馈给发送方。
_dmarc.nixops.me txt "v=DMARC1; p=quarantine; ruf=mailto:[email protected]"
p
:reject 拒绝该邮件;none 为不作处理;quarantine 标记为垃圾邮件。ruf
:检测到伪造邮件,接收方报告的邮箱地址
MTA-STS 和 TLS 报告
MTA-STS 是 MTA 严格传输安全协议,作用是确保发送给我们的电子邮件通过 TLS 安全地传输,防止中间人攻击。启用 MTA-STS 后,发送方邮件服务器只有在满足以下条件时,才会向我们发送邮件:
- 使用有效的证书通过身份验证
- 使用 TLS 1.2 或更高版本进行加密
当然如果发送方不支持 MTA-STS,仍然可以发送邮件(可能会有中间人攻击),主要是为了兼容。
启用 MTA-STS 所需条件:
- 创建策略文件,并提供 HTTPS 方式访问
- 通过 DNS 设置 txt 记录,告诉其它邮件服务商支持 MTA-STS
策略文件 mta-sts.txt 的内容为:
version: STSv1
mode: enforce
mx: mx1.nixops.me
mx: mx2.nixops.me
max_age: 86400
创建子域名并启用 https,最终的访问路径为:
https://mta-sts.nixops.me/.well-known/mta-sts.txt
配置 MTA-STS 的 TXT 记录:
_mta-sts.nixops.me TXT "v=STSv1; id=20211031T010101;"
一般 id 为时间戳。
DNSSEC, DNAME, CAA
启用了 MTA-STS 后,DANE 可以确保 TLS 证书是有效的,实际上是通过 DNS 的方式扮演了 CA 的角色。 DANE 通过 TLSA 记录,来声明某个证书的是可信的,由于 DANE 是基于 DNS 协议,可能会有被挟持的可能,因此需要启用 DNSSEC 来保障传输过程中不被修改。
- 启用 DNSSEC 需域名注册商及 dns 服务商都支持,在 DNS 服务商处选择开启 DNSSEC,然后将提供的 DS 记录填写到域名注册商即可
- 使用 TLSA 证书生成工具 及 PEM 格式的 TLS 证书生成 TLSA 记录
- 使用CAA Record Helper生成的 CAA 记录
为了保障 TLS 证书安全:
- DNSSEC 保障 DNS 记录传输过程中的安全
- DANE 在客户端侧阻止不当签发的证书
- CAA 指定域名允许哪个证书颁发机构为其颁发证书
此步为加强安全性,有能力推荐启用配置。
参考
参考文章:
- Maddy 打造个人邮箱服务 - 阅心笔记 (nixops.me)
- 开源邮件服务器 Maddy 部署教程 (lwebapp.com)
其他参考链接及有用的工具:
版权归原作者 萌宅鹿同学 所有, 如有侵权,请联系我们删除。