这是什么
一个完整的单域名邮件服务器:Postfix 负责传输,Dovecot 负责 IMAP 和本地投递,rspamd 负责过滤和 DKIM 签名,以及三个 DNS 记录决定了大型接收方是将你的邮件放入收件箱还是放进一个没人打开的文件夹。它能发送、能接收、能认证,而且不是一个开放中继。
运营自己的邮件服务器是不合时宜的建议,而且通常是有充分理由的。可送达性是难点,而不是软件。DNS 设置错误,那么全世界配置最仔细的 Postfix 也会把消息直接发向虚空。
开始之前
- 一台 R-8 或更高配置。过滤是 CPU 密集型任务,在垃圾邮件浪潮期间,rspamd 会高兴地使用你给它的每一个核心。
- 一个你能控制 DNS 的域名,并且有耐心等待传播。
- 在实例地址上设置反向 DNS 到你的邮件主机名。这可以在面板中编辑,而且是强制性的:接收方会拒绝无法解析的发件人。
- 提交一个工单给支持,询问你的实例是否开放出站 25 端口。在构建之前询问,而不是之后。
- 全程使用
mail.example.com。替换为你自己的。
1. 主机名和 DNS
hostnamectl set-hostname mail.example.com
apt update && apt full-upgrade -y现在就发布这些记录,因为证书步骤需要 A 记录,签名步骤需要一个存放密钥的地方。表中的值是每个记录的作用,而不是要粘贴的内容。
| 记录 | 名称 | 内容 |
|---|---|---|
| A / AAAA | mail | 面板中的实例地址 |
| MX | @ | 10 mail.example.com. |
| TXT | @ | v=spf1 mx -all |
| TXT | _dmarc | v=DMARC1; p=none; rua=mailto:[email protected]; adkim=s; aspf=s |
| PTR | 实例地址 | mail.example.com — 在面板中设置 |
SPF 记录表示:我的 MX 主机发送我的邮件,其他一切都是伪造的。硬失败而不是软失败,因为 ~all 会邀请接收方自行决定,而他们的决定不会是宽大的。DMARC 从 p=none 开始,这样在有任何事情被拒绝之前,你可以收集一个星期的报告。
2. 证书
apt install -y certbot
certbot certonly --standalone -d mail.example.com现在还没有服务监听 80 端口,所以 standalone 模式是最简单的路径。更新挂钩会在最后添加,一旦守护进程存在以重新加载。
3. Postfix
DEBIAN_FRONTEND=noninteractive apt install -y postfix postfix-pcre dovecot-imapd dovecot-lmtpd rspamd redis-server现在设置传输配置。下面的每一行都是经过深思熟虑的;postconf 会直接写入它们,所以没有编辑器可以出错:
postconf -e "myhostname = mail.example.com"
postconf -e "mydestination = localhost"
postconf -e "smtpd_banner = \$myhostname ESMTP"
postconf -e "inet_interfaces = all"
postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem"
postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem"
postconf -e "smtpd_tls_security_level = may"
postconf -e "smtp_tls_security_level = dane"
postconf -e "smtpd_tls_mandatory_protocols = >=TLSv1.2"
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination"
postconf -e "smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unknown_recipient_domain reject_unauth_destination"
postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "virtual_mailbox_domains = example.com"
postconf -e "smtpd_milters = inet:127.0.0.1:11332"
postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
postconf -e "milter_default_action = accept"最重要的一行是 smtpd_relay_restrictions。它以 reject_unauth_destination 结尾,这正是阻止整个互联网使用你的机器发送邮件的原因。一个开放中继会在数小时内让你的 IP 被列入黑名单,而且这还违反了可接受使用政策。
启用 submission 端口,以便你自己的客户端可以发送邮件,要求认证,并且不允许匿名访问:
postconf -M submission/inet="submission inet n - y - - smtpd"
postconf -P "submission/inet/syslog_name=postfix/submission"
postconf -P "submission/inet/smtpd_tls_security_level=encrypt"
postconf -P "submission/inet/smtpd_sasl_auth_enable=yes"
postconf -P "submission/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"4. Dovecot
在单个系统用户下使用 Maildir 格式的邮箱可以让这个构建保持精简。创建用户和存储:
groupadd -g 5000 vmail
useradd -g vmail -u 5000 -d /var/vmail -m vmail
install -d -o vmail -g vmail -m 700 /var/vmail/example.com编写 /etc/dovecot/conf.d/99-local.conf:
mail_location = maildir:/var/vmail/%d/%n
mail_uid = vmail
mail_gid = vmail
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
ssl_min_protocol = TLSv1.2
auth_mechanisms = plain login
disable_plaintext_auth = yes
passdb {
driver = passwd-file
args = scheme=ARGON2ID username_format=%u /etc/dovecot/users
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/vmail/%d/%n
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}创建一个邮箱。该命令会提示两次并写入一个哈希,而绝不会是密码本身:
echo -n "[email protected]:" >> /etc/dovecot/users
doveadm pw -s ARGON2ID >> /etc/dovecot/users
chmod 640 /etc/dovecot/users
chgrp dovecot /etc/dovecot/users5. rspamd 和 DKIM
生成签名密钥,然后发布公钥部分:
install -d -o _rspamd -g _rspamd -m 750 /var/lib/rspamd/dkim
rspamadm dkim_keygen -s mail -b 2048 -d example.com -k /var/lib/rspamd/dkim/example.com.mail.key
chown _rspamd:_rspamd /var/lib/rspamd/dkim/example.com.mail.key
chmod 400 /var/lib/rspamd/dkim/example.com.mail.key该命令会在标准输出上打印一条 DNS 记录。将其作为 TXT 记录发布到 mail._domainkey.example.com,完全按照打印的内容,将引号中的段按你的 DNS 提供商期望的方式连接起来。然后告诉 rspamd 密钥的位置,在 /etc/rspamd/local.d/dkim_signing.conf 中:
path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector = "mail";
allow_username_mismatch = true;
use_domain = "header";
sign_authenticated = true;
sign_local = true;绑定 milter 并为 Web 界面设置密码:
echo "bind_socket = \"127.0.0.1:11332\";" > /etc/rspamd/local.d/worker-proxy.inc
rspamadm pw将生成的哈希粘贴到 /etc/rspamd/local.d/worker-controller.inc 中作为 password = "..."。通过 SSH 隧道访问界面,而不是将 11334 端口开放给全世界。
6. 启动所有服务
systemctl enable --now redis-server rspamd dovecot postfix
postfix check
systemctl --no-pager --failed添加一个更新挂钩,以便新证书到达两个守护进程:
echo "systemctl reload postfix dovecot" > /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh验证
三个测试。第一个是本地的,第二个是关键的,第三个是让你远离黑名单的。
echo | openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com 2>/dev/null | grep -E "subject=|Verify return"然后从你的新服务器向你在大型网络邮件提供商处持有的一个邮箱发送一条消息,打开收到的消息并阅读其原始邮件头。你在寻找一行:
Authentication-Results: mx.receiver.example;
dkim=pass [email protected];
spf=pass smtp.mailfrom=example.com;
dmarc=pass (p=NONE) header.from=example.com三个通过后你就完成了。dkim=none 表示 rspamd 没有签名,所以检查 rspamadm configdump dkim_signing。spf=fail 几乎总是意味着消息通过 IPv6 发出,而你的 SPF 记录只覆盖了 v4 MX 地址。
最后,证明你不是一个中继。从任何其他机器,连接并尝试在两个你不拥有的域名之间发送邮件:
apt install -y swaks
swaks --to [email protected] --from [email protected] --server mail.example.com正确的结果是在收件人阶段被拒绝:554 5.7.1 Relay access denied。否则意味着你配置了一台机器,会在一天之内被滥用,你应该停下来重新阅读第三步。
事后
将 DMARC 留在 p=none 一个星期,并阅读聚合报告。一旦它们显示只有你自己的服务器在签名你自己的邮件,然后移至 p=quarantine,再两周后移至 p=reject。顺便为 /var/vmail 添加节点外备份,因为邮件是用户永远没有第二副本的东西,而我们的备份附加服务会写入与实例不同的站点。