RE:137

时间是唯一致死的毒药。

自建邮件服务器

最近 LQCD 的代码写得不太顺利,结果就是搭电子乐高的瘾又犯了,花了一下午和一晚上搭建了自己的 mail server。搭建过程不难,但还是会踩一些小坑,就在博客里做一个小小的记录。我使用的是由 Hetzner 提供的预装有 Debian GNU/Linux 11 (bullseye) 的服务器,用 Cloudflare 管理 DNS。小心 Hetzner。

主要参考文档:Docker Mailserver。以下内容也是按照文档中的顺序来组织的。

主机上的配置(PART A)#

rDNS(PTR 记录)#

在 Cloudflare 上创建 PTR 记录似乎没用,需要在 Hetzner 的管理面板直接编辑反向 DNS 记录: 设置 rDNS IPv4 和 IPv6 的 rDNS 都需要设置为 mail.example.comexample.com 替换为自己的),这是 实际提供邮件服务 的域名。子域名设置成别的也可以,一般默认是 mail

开放合适的端口#

确保出站的 25 和 465 端口是开放的。入站的端口除了 25 一定要打开以外,其余端口根据个人喜好来开放。我希望所有连接都用 implicit TLS,所以只开放了 465 和 993 端口。

根据 Hetzner 的文档,为了防止他们的服务器被滥用,Hetzner 上服务器的出站 25 和 465 端口默认是被关闭的,并且它们在防火墙设置处无法被开启,需要在 limit request 页面手动申请解封。如果用的是其他 ISP,也一定要认真确认端口的开放状态。

最后折腾了我大半晚上的就是这一步,小心 Hetzner。

DNS 服务商处的配置 (PART A)#

这一步先添加 A(AAAA) 记录以及 MX 记录。

  • 添加 A(AAAA) 记录
    域名部分是 实际提供邮件服务的域名,在这里就是 mail.example.com,该记录指向服务器的 IPv4(6) 地址。如果是在 Cloudflare 上配置,要关掉 proxy。
  • MX 记录
    域名部分是 邮箱账户 @ 后面的域名,在这里设置为 example.com,该记录指向 实际提供邮件服务的域名,即 mail.example.comPriority 部分写 0 就好。

添加完毕后运行如下测试,结果应该是一致的:

$ dig @1.1.1.1 +short MX example.com
mail.example.com
$ dig @1.1.1.1 +short A mail.example.com
11.22.33.44
$ dig @1.1.1.1 +short -x 11.22.33.44
mail.example.com

主机上的配置(PART B)#

安装 SSL 证书#

这里用 certbot 来安装 SSL 证书。安装时会用到 80 端口,所以如果有类似 Nginx 的占用 80 端口的服务需要暂时关闭。

# 为域名 mail.example.com 申请证书
$ sudo certbot certonly --standalone -d mail.example.com
# 查看所有证书的状态
$ sudo certbot certificates

配置 Docker Mailserver#

我新建了一个 mailserver 文件夹,在里面运行 Docker Mailserver 文档里的命令:

DMS_GITHUB_URL="https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master"
wget "${DMS_GITHUB_URL}/compose.yaml"
wget "${DMS_GITHUB_URL}/mailserver.env"

接下来编辑 compose.yaml

  • hostname 改为自己的
  • ports 下不需要的端口注释掉
  • 为了使用 SSL 证书,在 volumes 末尾添加:
    - /etc/letsencrypt:/etc/letsencrypt
    

然后编辑 mailserver.env

  • 重要
    • SSL_TYPE=letsencrypt:也是为了用 SSL 证书
  • 可选
    • TZ:服务器使用的时区。我设置了 TZ=Asia/Tokyo
    • ENABLE_CLAMAV:杀毒软件,打开打开
    • ENABLE_FAIL2BAN:防止密码被暴力破解,打开打开

      小提示(又是一个坑)
      如果设置了 ENABLE_FAIL2BAN = 1,一定要在 compose.yaml 中将

      # cap_add:
      #  - NET_ADMIN
      

      这两行的注释取消掉。

Mailserver 初次启动#

mailserver 文件夹中运行:

$ docker compose up -d  # 后台运行 docker compose 服务

这时在两分钟内添加第一个账户,那么就添加一个管理员账户:

$ docker exec -ti mailserver setup email add [email protected]

然后为管理员账户创建 postmaster 别名

$ docker exec -ti mailserver setup alias add [email protected] [email protected]

现在就可以在邮件客户端(Thunderbird 等)登录邮箱啦!向 Mail Tester 发一封测试邮件看看评分…2.1 分…嗯,看来还有一些配置要完成…

生成 DKIM key#

$ docker exec -it mailserver setup config dkim

生成的文件被放在了 ./docker-data/dms/config/opendkim/keys/example.com 中,我们需要的是 mail.txt 中的内容。

DNS 服务商处的配置 (PART B)#

最后,在域名 DNS 记录下添加三个神秘的 TXT:SPF、DKIM 和 DMARC

SPF#

最简单的一个,只需要添加:

  • Type: TXT
  • Name: example.com
  • Content: v=spf1 mx -all

DKIM#

通过之前的步骤,应该得到了 mail.txt 中的三行内容。把所有的双引号和空格删除以后,添加到下文中的 Content:

  • Type: TXT
  • Name: mail._domainkey.example.com
  • Content: v=DKIM1; h=sha256; k=rsa; p=一大串乱码

DMARC#

  • Type: TXT
  • Name: _dmarc
  • Content: v=DMARC1; p=reject; adkim=s; aspf=s; rua=mailto:某备用邮箱; ruf=mailto:某备用邮箱

最后,在 Mail Tester进行测试…10 分!在 Learn and Test DMARC也测试一下…全部 PASS!新的电子乐高搭好了!Hurray!

附录#

Docker Compose 常用命令#

$ docker compose up -d   # 后台运行 docker compose 服务
$ docker compose down    # 停止 docker compose 服务
$ docker compose logs -f # 查看服务日志

如果要完全重启 Docker Mailserver,最好的方法是

$ docker compose down
$ sudo systemctl restart docker.service
$ docker compose up -d

Docker Mailserver 常用命令#

# 创建新用户
$ docker exec -ti <CONTAINER NAME> setup email add [email protected]
# 查看用户列表
$ docker exec -ti <CONTAINER NAME> setup email list
# 生成 DKIM key
$ docker exec -it <CONTAINER NAME> setup config dkim

测试用网站#