这是我们设置和配置邮件服务器系列的第三部分。在本教程中,我们将安装并配置 Rspamd,将其连接到 Postfix,并创建 DKIM 和 DMARC DNS 记录。

您可能会问,为什么我们选择使用 Rspamd 而不是 Spamassassin。Rspamd 用 C 编写,维护更积极,因此比用 Perl 编写的 Spamassassin 快得多。另一个原因是 Rspamd 自带 DKIM 签名模块,因此我们无需使用另一个软件来签名外发邮件。

如果您不熟悉 Rspamd,可以在此处查看官方文档。

先决条件

在继续本教程之前,请确保您以具有 sudo 权限的用户身份登录,并且已经完成了本系列的第一部分和第二部分,我们在其中设置了 PostfixAdmin、Postfix 和 Dovecot。

安装 Redis

Redis 用作 Rspamd 的存储和缓存后端。使用以下命令安装:

终端
sudo apt update
sudo apt install -y redis-server
sudo systemctl enable --now redis-server
信息对于生产邮件服务器,请运行本地递归解析器,例如 Unbound。主要的 RBL 会对来自公共解析器(如 Google 或 Cloudflare)的查询进行速率限制或拒绝,因此随着流量增长,查询的可靠性会降低。 systemd-resolved 仅绑定 127.0.0.53 和 127.0.0.54,因此 Unbound 可以在其旁边监听 127.0.0.1:53。设置 Unbound 超出了本教程的范围,但一旦它运行起来,可以通过在 /etc/rspamd/local.d/options.inc 中添加 dns { nameserver = ["127.0.0.1"]; } 来让 Rspamd 指向它。

安装 Rspamd

Ubuntu 26.04 的 universe 软件源提供了较新的稳定版 Rspamd,因此我们可以直接从默认仓库安装:

终端
sudo apt install -y rspamd

确认安装的版本以及服务是否已启动:

终端
rspamd --version
systemctl status rspamd --no-pager
信息如果您想要比 Ubuntu universe 中更新的版本,可以在官方 Rspamd APT 仓库添加对 Ubuntu 26.04 resolute 套件的支持后使用它。请使用 /etc/apt/keyrings/ 下的现代 keyring 布局,而不是已弃用的 apt-key。

配置 Rspamd

我们不会修改默认配置文件,而是在 /etc/rspamd/local.d/ 下创建新文件来覆盖默认设置。

Ubuntu 26.04 已将 Rspamd 的常规 worker 绑定到 localhost 的 11333 端口。添加以下本地覆盖以使 IPv4 回环绑定明确:

/etc/rspamd/local.d/worker-normal.inccfg
bind_socket = "127.0.0.1:11333";

代理 worker 监听 11332 端口并支持 milter 协议。Postfix 通过此 worker 与 Rspamd 通信,因此我们启用 milter 模式并配置其在本地扫描邮件:

/etc/rspamd/local.d/worker-proxy.inccfg
bind_socket = "127.0.0.1:11332";
milter = yes;
timeout = 120s;
upstream "local" {
  default = yes;
  self_scan = yes;
}

为控制器 worker 生成加密密码,该 worker 提供对 Rspamd Web 界面的访问权限:

终端
rspamadm pw --encrypt -p rspamd_controller_password

输出应类似于以下内容:

输出
$2$khz7u8nxgggsfay3qta7ousbnmi1skew$zdat4nsm7nd3ctmiigx9kjyo837hcjodn1bob5jaxt7xpkieoctb
信息在运行命令之前,请将 rspamd_controller_password 替换为长的随机密码。

从终端复制密码并将其粘贴到控制器配置文件中:

/etc/rspamd/local.d/worker-controller.inccfg
password = "$2$khz7u8nxgggsfay3qta7ousbnmi1skew$zdat4nsm7nd3ctmiigx9kjyo837hcjodn1bob5jaxt7xpkieoctb";
bind_socket = "127.0.0.1:11334";

将 Rspamd 指向本地 Redis 实例:

/etc/rspamd/local.d/redis.confcfg
servers = "127.0.0.1";

将 Redis 设置为贝叶斯分类器的后端:

/etc/rspamd/local.d/classifier-bayes.confcfg
servers = "127.0.0.1";
backend = "redis";

打开 milter_headers.conf 文件并设置 Rspamd 写入已扫描邮件的标头:

/etc/rspamd/local.d/milter_headers.confcfg
use = ["x-spamd-bar", "x-spam-level", "authentication-results"];

您可以在 Rspamd 文档中找到有关 milter 标头的更多信息。

运行配置检查并重启 Rspamd 服务以使更改生效:

终端
sudo rspamadm configtest
sudo systemctl restart rspamd

配置 Postfix

配置 Postfix 以在代理 worker 套接字上使用 Rspamd milter:

终端
sudo postconf -e "smtpd_milters = inet:127.0.0.1:11332"
sudo postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
sudo postconf -e "milter_protocol = 6"
sudo postconf -e "milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}"
sudo postconf -e "milter_default_action = accept"

重启 Postfix 服务以使更改生效:

终端
sudo systemctl restart postfix

发送一封测试邮件并确认 Rspamd 已扫描它:

终端
swaks --to user@ggdoc.cn --from admin@ggdoc.cn --server 127.0.0.1
sudo grep -i rspamd /var/log/mail.log | tail -n 10

配置 Nginx

在本系列的第一部分中,我们为 PostfixAdmin 实例创建了一个 Nginx 服务器块。在该服务器中添加一个新的 location 块,以便我们可以通过 HTTPS 反向代理 Rspamd 控制器:

/etc/nginx/sites-enabled/mail.ggdoc.cnnginx
...
location /rspamd/ {
    proxy_pass http://127.0.0.1:11334/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
...

重新加载 Nginx 服务以使更改生效:

终端
sudo systemctl reload nginx

在浏览器中打开 https://mail.ggdoc.cn/rspamd/,输入您使用 rspamadm pw 生成的密码,即可看到 Rspamd Web 界面。

Ubuntu 26.04 上的 Rspamd Web 界面

创建 DKIM 密钥

域名密钥识别邮件(DKIM)是一种电子邮件身份验证方法,它向外发消息头添加加密签名。它允许接收方验证声称来自特定域名的电子邮件确实得到该域名所有者的授权。其主要目的是防止伪造电子邮件。

我们可以为托管的每个域名使用不同的 DKIM 密钥。Rspamd DKIM 签名模块支持开箱即用的按域布局,因此我们将使用包含域名和选择器的密钥路径。这样,您以后可以通过使用相同的选择器生成新密钥来添加更多域名。

创建一个目录来存储 DKIM 密钥,并使用 rspamadm 生成新的密钥对:

终端
sudo mkdir -p /var/lib/rspamd/dkim
sudo rspamadm dkim_keygen -b 2048 -s mail -d ggdoc.cn -k /var/lib/rspamd/dkim/ggdoc.cn.mail.key > /tmp/ggdoc.cn.mail.txt

在上面的例子中,我们使用 mail 作为 DKIM 选择器。私钥被写入 /var/lib/rspamd/dkim/ggdoc.cn.mail.key,我们将在 DNS 中发布的公钥 TXT 记录被捕获在 /tmp/ggdoc.cn.mail.txt 中。

设置正确的所有权和权限,以便只有 Rspamd 用户能读取私钥:

终端
sudo chown -R _rspamd:_rspamd /var/lib/rspamd/dkim
sudo chmod 750 /var/lib/rspamd/dkim
sudo chmod 440 /var/lib/rspamd/dkim/ggdoc.cn.mail.key

现在告诉 Rspamd 在哪里查找 DKIM 密钥。该路径使用 $domain 和 $selector 变量,因此相同的配置文件适用于您以后添加的每个域名:

/etc/rspamd/local.d/dkim_signing.confcfg
path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector = "mail";
allow_username_mismatch = true;

运行配置检查并重启 Rspamd:

终端
sudo rspamadm configtest
sudo systemctl restart rspamd

DNS 设置

DKIM 公钥 TXT 记录在我们生成密钥时被写入 /tmp/ggdoc.cn.mail.txt。内容应类似于以下内容:

输出
mail._domainkey IN TXT ( "v=DKIM1; k=rsa;"
    "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqdBRCqYzshc4LmmkxUkCH/rcIpSe..."
    "...ZTRe1FlONOzO7ZkQFb7O6ogFepWLsM9tYJ38TFPteqyO3XBjxHzp1AT0UvsPcauDoeHUXgqbxU7udG1t05f6ab5h/Kih+jisgHHF4ZFK3qRtawhWlA9DtS35DlwIDAQAB" ) ;

如果您运行自己的 Bind DNS 服务器,请将记录直接复制并粘贴到您的域名区域文件中。如果您使用 DNS Web 界面,请创建一个新的 TXT 记录,名称为 mail._domainkey。对于该值,请移除引号并将各行连接在一起,使记录包含一个以 v=DKIM1; 开头并以公钥结尾的单一字符串。

我们还将发布一条基于域的消息认证、报告与一致性(DMARC)记录。DMARC 会告知接收服务器如何处理未通过 SPF 或 DKIM 检查的邮件,同时保护您的域免受直接伪造,并提升其信誉。如需深入了解 SPF、DKIM 和 DMARC 如何协同工作,请参阅我们的电子邮件认证指南。

如果您从系列开始就一路跟随,那么您的域应该已经拥有 SPF 记录。DMARC 在 SPF 或 DKIM 任一通过且与“发件人”标头中的域对齐时即视为通过。建议同时发布两者,因为这为合法邮件提供了多种通过途径。DMARC 策略本身以 TXT 记录形式发布:

cfg
_dmarc  IN  TXT  "v=DMARC1; p=none; adkim=r; aspf=r;"

让我们分解这条记录:

  • v=DMARC1 是 DMARC 版本标识符。
  • p=none 告知接收方对未通过 DMARC 的邮件不采取任何操作。一旦您确信配置正确,可以将其更改为 quarantine 或 reject。
  • adkim=r 和 aspf=r 将 DKIM 和 SPF 对齐模式设置为宽松模式。使用 s 表示严格对齐。

与 DKIM 记录一样,将这一行粘贴到您的区域文件中,或创建一条 TXT 记录,名称为 _dmarc,值为 v=DMARC1; p=none; adkim=r; aspf=r;。

DNS 更改可能需要一段时间才能传播。您可以使用 dig 命令检查记录是否已传播:

终端
dig mail._domainkey.ggdoc.cn TXT +short
dig _dmarc.ggdoc.cn TXT +short
输出
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqdBRCqYzshc4LmmkxUkCH/rcIpSe..."
"v=DMARC1; p=none; adkim=r; aspf=r;"

您还可以使用 DMARC 检查器查看域名 DMARC 策略。

验证 DKIM 签名

在信任外发邮件被签名之前,请通过端口 587 发送一条经过认证的消息,并确认已投递的邮件副本中出现 DKIM-Signature 标头:

终端
swaks --to user@ggdoc.cn --from user@ggdoc.cn --server mail.ggdoc.cn --port 587 --auth LOGIN --auth-user user@ggdoc.cn --auth-password 'MAILBOX_PASSWORD' --tls

在用户的 Maildir 中找到最新的邮件并检查其标头:

终端
LATEST=$(sudo find /var/mail/vmail -type f \( -path '*/new/*' -o -path '*/cur/*' \) -printf '%T@ %p\n' | sort -nr | head -1 | awk '{print $2}')
sudo grep -E '^(DKIM-Signature|Authentication-Results|ARC-)' "$LATEST"

您应该看到一行 DKIM-Signature: v=1; a=rsa-sha256; ... d=ggdoc.cn; s=mail; ...。如果缺少该标头,请对照磁盘上的文件名检查 dkim_signing.conf 中的路径,并确认 _rspamd 用户可以读取该密钥。

故障排除

Rspamd 网页登录失败
确认 /etc/rspamd/local.d/worker-controller.inc 中的哈希值来自您在浏览器中输入的统一纯文本密码。然后重启 Rspamd 并重新加载 Nginx:

终端
sudo rspamadm configtest
sudo systemctl restart rspamd
sudo systemctl reload nginx

Postfix 邮件未被扫描
检查 Postfix 是否指向端口 11332 上的代理工作进程,然后发送一条本地测试消息并检查邮件日志:

终端
postconf smtpd_milters non_smtpd_milters
swaks --to user@ggdoc.cn --from admin@ggdoc.cn --server 127.0.0.1
sudo grep -i rspamd /var/log/mail.log | tail -n 20

DKIM-Signature 缺失
验证私钥名称是否与 dkim_signing.conf 中的 $domain.$selector.key 模式匹配,并且 _rspamd 用户可以读取它:

终端
sudo ls -l /var/lib/rspamd/dkim/
sudo -u _rspamd test -r /var/lib/rspamd/dkim/ggdoc.cn.mail.key