跳转至内容

Postfix

来自 ArchWiki
(从PostFix重定向而来)

Postfix 是一种 邮件传输代理,根据 其网站

的说法,它力求做到快速、易于管理和安全,同时又能与 sendmail 兼容,不至于引起现有用户的反感。因此,其外部具有 sendmail 的风格,但内部完全不同。

本文以 邮件服务器 为基础。本文的目的是设置 Postfix 并解释基本配置文件。其中包含设置仅本地系统用户传递的说明,以及一个指向虚拟用户传递指南的链接。

安装

安装 postfix 软件包。

配置

有关更多信息,请参阅 Postfix Basic Configuration。默认情况下,配置文件位于 /etc/postfix。最重要的两个文件是:

  • master.cf,定义了启用的 Postfix 服务以及客户端如何连接它们,请参阅 master(5)
  • main.cf,主配置文件,请参阅 postconf(5)

配置更改需要 重载 postfix.service 服务,或者运行 postfix reload 命令才能生效。

别名 (Aliases)

请参阅 aliases(5)

您可以在 /etc/postfix/aliases 文件中指定别名(也称为转发器)。

您应该将所有发送给 root 的邮件映射到另一个账户,因为以 root 身份阅读邮件不是一个好主意。

取消注释以下行,并将 you 替换为真实的账户。

root: you

完成编辑 /etc/postfix/aliases 文件后,您必须运行 postalias 命令。

 # postalias /etc/postfix/aliases

对于后续的更改,您可以使用:

 # newaliases
提示 或者,您可以创建 ~/.forward 文件,例如,root 的 /root/.forward。指定应将 root 邮件转发到的用户,例如 user@localhost
/root/.forward
user@localhost

本地邮件

要仅将邮件传递给本地系统用户(存在于 /etc/passwd 中),请将 /etc/postfix/main.cf 更新为以下配置。取消注释、修改或添加以下行:

myhostname = localhost
mydomain = localdomain
mydestination = $myhostname, localhost.$mydomain, localhost
inet_interfaces = $myhostname, localhost
mynetworks_style = host
default_transport = error: outside mail is not deliverable

所有其他设置可以保持不变。设置完以上配置文件后,您可能希望设置一些 #别名,然后 #启动 Postfix

虚拟邮件

虚拟邮件是指不映射到用户账户(/etc/passwd)的邮件。

虚拟别名

虚拟别名用于重写所有本地、虚拟和远程目标的收件人地址。这可用于重写单个收件人或整个域的目标地址。

虚拟地址别名

为单个地址设置虚拟别名。

启用虚拟别名表

/etc/postfix/main.cf
virtual_alias_maps = lmdb:/etc/postfix/virtual

填充虚拟别名表

/etc/postfix/virtual
user@domain address

重建索引文件

# postmap /etc/postfix/virtual

重新启动 postfix.service 服务。

检查配置

运行 postfix check 命令。它应该会输出您在配置文件中可能犯的任何错误。

要查看所有配置,请键入 postconf。要查看与默认值有何不同,请尝试 postconf -n

启动 Postfix

注意 Postfix 至少需要运行一次 newaliases 才能启动,即使您没有设置任何 #别名

启动/启用 postfix.service 服务。

TLS

有关更多信息,请参阅 Postfix TLS Support

安全 SMTP(发送)

默认情况下,Postfix/sendmail 不会将电子邮件加密发送给其他 SMTP 服务器。要使用 TLS(如果可用),请将以下行添加到 main.cf

/etc/postfix/main.cf
smtp_tls_security_level = may

要*强制*使用 TLS(并在远程服务器不支持时失败),请将 may 更改为 encrypt。但请注意,如果 SMTP 服务器是公开引用的,这违反了 RFC:2487

安全 SMTP(接收)

警告 如果您部署了 TLS,请务必遵循 weakdh.org 的指南 以防止 FREAK/Logjam。自 2015 年中期以来,默认设置已能防范 POODLE。有关更多信息,请参阅 服务器端 TLS

默认情况下,Postfix 不接受安全邮件。

您需要 获取证书。通过将以下行添加到 main.cf,将 Postfix 指向您的 TLS 证书:

/etc/postfix/main.cf
smtpd_tls_security_level = may
smtpd_use_tls = yes
smtpd_tls_cert_file = /path/to/cert.pem
smtpd_tls_key_file = /path/to/key.pem

有两种方法可以接受安全邮件:STARTTLS over SMTP(端口 587,也称为“submission”端口)和 SMTPS(端口 465,也称为“submissions”端口)。后者之前已被弃用,但已被 RFC:8314 恢复。

要启用 STARTTLS over SMTP(端口 587),请在 master.cf 中取消注释以下行:

/etc/postfix/master.cf
submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_auth_only=yes
  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_relay_restrictions=
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

smtpd_*_restrictions 选项保持注释状态,因为 $mua_*_restrictions 默认未在 main.cf 中定义。如果您决定设置任何 $mua_*_restrictions,请也取消注释那些行。

要启用 SMTPS(端口 465),请在 master.cf 中取消注释以下行:

/etc/postfix/master.cf
submissions     inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
  -o smtpd_relay_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

上面关于 $smtpd_*_restrictions 行的理由与上面相同。

后量子 TLS

从 Postfix 3.10 和 OpenSSL 3.5.0 开始,可以为 TLS 提供后量子密钥交换。为此,需要向 OpenSSL 提供一个配置文件,因为 Postfix 本身不支持新的密钥交换语法。

注意 后量子密钥交换仅在发送方和接收方服务器都支持时才会使用。但是,启用它没有任何坏处——它只会作为机会使用,如果可能的话。一些大型服务,如 GMail,已经提供了 X25519MLKEM768 密钥交换。您可以使用 testssl.sh 或使用 Hardenize 网站服务 来测试服务器是否支持任何后量子算法。

要启用此功能,请在您的配置中添加以下内容(请参阅 [1]):

/etc/postfix/main.cf
tls_eecdh_auto_curves =
tls_ffdhe_auto_groups =
tls_config_file = ${config_directory}/openssl.cnf
tls_config_name = postfix

然后,您需要添加一个适当的 OpenSSL 配置:

/etc/postfix/openssl.cnf
postfix = postfix_settings
[postfix_settings]
ssl_conf = postfix_ssl_settings
[postfix_ssl_settings]
system_default = baseline_postfix_settings
[baseline_postfix_settings]
Groups = *X25519MLKEM768 / *X25519:X448 / P-256:P-384:P-521:ffdhe2048:ffdhe3072

这会启用新的后量子安全密钥交换 X25519MLKEM768,以及用于传统、非量子安全曲线的先前默认设置。

注意 OpenSSL 还支持进一步的后量子交换,例如混合方案 SecP256r1MLKEM768 和 SecP384r1MLKEM1024,或仅通过 MLKEM512、MLKEM768 和 MLKEM1024 使用 ML-KEM。目前,混合方案是首选,因为它们至少能提供与 X25519 和同类算法相同的经典安全性,以防 ML-KEM 或其实现出现任何问题。考虑到这些算法相当新,X25519MLKEM768 似乎是目前采用最多的。如果需要,也可以添加其他密钥交换方案,它们的出现不会引起任何问题。

技巧与提示

阻止传入邮件

使用 Postfix 可以轻松地通过发件人地址手动阻止传入邮件。

创建并打开 /etc/postfix/blacklist_incoming 文件,并附加发件人电子邮件地址。

user@example.com REJECT

然后使用 postmap 命令创建数据库。

# postmap lmdb:blacklist_incoming

main.cf 的第一个 permit 规则之前添加以下代码:

smtpd_recipient_restrictions = check_sender_access lmdb:/etc/postfix/blacklist_incoming

最后,重新启动 postfix.service 服务。

隐藏发件人的 IP 和用户代理在 Received 头部

这主要是出于隐私考虑,如果您使用 Thunderbird 发送电子邮件。Received 头部会包含您的局域网和广域网 IP 以及您使用的电子邮件客户端的信息。(原始来源:AskUbuntu)我们的目标是删除传出电子邮件中的 Received 头部。这可以通过以下步骤完成:

将以下行添加到 main.cf

smtp_header_checks = regexp:/etc/postfix/smtp_header_checks

用以下内容创建 /etc/postfix/smtp_header_checks

/^Received: .*/     IGNORE
/^User-Agent: .*/   IGNORE

最后,重新启动 postfix.service 服务。

Postfix 在 chroot 监狱中

本文或本章节的准确性存在争议。

原因:这已在 2016 年添加,且修改很少。这很可能使用 systemd/Sandboxing 功能,特别是 RootDirectory= 来实现会更好。(请在 Talk:Postfix 中讨论)

默认情况下,Postfix 不会放在 chroot 监狱中。Postfix 文档 [2] 提供了有关如何实现此类监狱的详细信息。以下概述了步骤,这些步骤基于 Postfix 源代码中提供的 chroot-setup 脚本。

首先,进入 /etc/postfix 目录下的 master.cf 文件,并将所有 chroot 条目更改为 'yes'(y),除了 qmgrproxymapproxywritelocalvirtual 服务。

其次,创建两个函数,以便稍后帮助我们将文件复制到 chroot 监狱中(参见最后一步)。

$ alias CP="cp -p"
cond_copy() {
  # find files as per pattern in $1
  # if any, copy to directory $2
  dir=$(dirname "$1")
  pat=$(basename "$1")
  lr=$(find "$dir" -maxdepth 1 -name "$pat")
  if test ! -d "$2" ; then exit 1 ; fi
  if test "x$lr" != "x" ; then $CP $1 "$2" ; fi
}

接下来,创建监狱的新目录。

$ set -e
$ umask 022
$ POSTFIX_DIR=${POSTFIX_DIR-/var/spool/postfix}
$ cd ${POSTFIX_DIR}
$ mkdir -p etc lib usr/lib/zoneinfo
$ test -d /lib64 && mkdir -p lib64

查找 localtime 文件。

$ lt=/etc/localtime
$ if test ! -f $lt ; then lt=/usr/lib/zoneinfo/localtime ; fi
$ if test ! -f $lt ; then lt=/usr/share/zoneinfo/localtime ; fi
$ if test ! -f $lt ; then echo "cannot find localtime" ; exit 1 ; fi
$ rm -f etc/localtime

将 localtime 和其他一些系统文件复制到 chroot 的 etc 目录中。

$ CP -f $lt /etc/services /etc/resolv.conf /etc/nsswitch.conf etc
$ CP -f /etc/host.conf /etc/hosts /etc/passwd etc
$ ln -s -f /etc/localtime usr/lib/zoneinfo

确保 resolv.conf 的所有者是 root。

$ chown root /var/spool/postfix/etc/resolv.conf

使用之前创建的 cond_copy 函数将所需库复制到 chroot 中。

$ cond_copy '/usr/lib/libnss_*.so*' lib
$ cond_copy '/usr/lib/libresolv.so*' lib
$ cond_copy '/usr/lib/libdb.so*' lib

别忘了 重载 Postfix。

DANE (DNSSEC)

资源记录

警告 这不是一个简单的部分。请注意,您必须确保您知道自己在做什么。最好先阅读 常见错误

DANE 支持多种记录类型,但并非所有类型都适用于 Postfix。

证书使用 0 不受支持,1 被映射到 3,2 是可选的,因此建议发布“3”记录。更多关于 DANE#资源记录 的信息。

配置

本文章或章节需要扩充。

原因:tempfail 是什么意思?(请在 Talk:Postfix 中讨论)

机会性 DANE 配置如下:

/etc/postfix/main.cf
smtpd_use_tls = yes
smtp_dns_support_level = dnssec
smtp_tls_security_level = dane
/etc/postfix/master.cf
dane       unix  -       -       n       -       -       smtp
  -o smtp_dns_support_level=dnssec
  -o smtp_tls_security_level=dane

要使用每个域的策略,例如,example.org 的机会性 DANE 和 example.com 的强制 DANE,可以使用类似以下内容:

/etc/postfix/main.cf
indexed = ${default_database_type}:${config_directory}/

# Per-destination TLS policy
#
smtp_tls_policy_maps = ${indexed}tls_policy

# default_transport = smtp, but some destinations are special:
#
transport_maps = ${indexed}transport
transport
example.com dane
example.org dane
tls_policy
example.com dane-only
注意 对于全局强制 DANE,将 smtp_tls_security_level 更改为 dane-only。请注意,这将导致 Postfix 对所有根本不使用 DANE 的传递返回 tempfail(响应 4.X.X 错误代码)!

完整的文档可以在 这里找到。

附加功能

https://postfixadmin.sourceforge.net/ || postfixadmin

Postgrey

本文或本节需要在语言、wiki 语法或风格方面进行改进。请参阅 Help:Style 获取参考。

原因:参见 Help:Style(请在 Talk:Postfix 中讨论)

Postgrey 可用于为 Postfix 邮件服务器启用 灰名单

安装

安装 postgrey 软件包。要快速运行它,请编辑 Postfix 配置文件并添加以下行:

/etc/postfix/main.cf
smtpd_recipient_restrictions =
  check_policy_service inet:127.0.0.1:10030

然后 启动/启用 postgrey 服务。之后,重载 postfix 服务。现在应该已经启用了灰名单。

配置

配置通过 扩展单元 postgrey.service 完成。

白名单

要添加自动白名单(成功的邮件会被列入白名单,无需再等待),请添加 --auto-whitelist-clients=N 选项,并将 N 替换为一个合适的较小的数字(或保留其默认值 5)。

/etc/systemd/system/postgrey.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/postgrey --inet=127.0.0.1:10030 \
       --pidfile=/run/postgrey/postgrey.pid \
       --group=postgrey --user=postgrey \
       --daemonize \
       --greylist-text="Greylisted for %%s seconds" \
       --auto-whitelist-clients

要添加您自己的白名单客户端列表(除了默认列表),请创建 /etc/postfix/postgrey_whitelist_clients.local 文件,每行输入一个主机或域名,然后重新启动 postgrey.service 服务使更改生效。

故障排除

如果您指定了 --unix=/path/to/socket 并且套接字文件未创建,请确保您已从服务文件中删除了默认的 --inet=127.0.0.1:10030

有关可能选项的完整文档,请参阅 perldoc postgrey

SpamAssassin

本节介绍如何集成 SpamAssassin

SpamAssassin 独立通用设置

注意 如果您想结合 SpamAssassin 和 Dovecot 邮件过滤,请忽略接下来的两行,而是继续向下阅读。

编辑 /etc/postfix/master.cf,在 smtp 下添加内容过滤器。

smtp      inet  n       -       n       -       -       smtpd
  -o content_filter=spamassassin

另外,为 SpamAssassin 添加以下服务条目:

spamassassin unix -     n       n       -       -       pipe
  flags=R user=spamd argv=/usr/bin/vendor_perl/spamc -e /usr/bin/sendmail -oi -f ${sender} ${recipient}

现在您可以 启动启用 spamassassin.service 服务。

SpamAssassin 结合 Dovecot LDA / Sieve(邮件过滤)

按照 Dovecot#Sieve 中的说明设置 LDA 和 Sieve 插件。但是,请忽略最后一行 mailbox_command...

取而代之的是,在 /etc/postfix/master.cf 中添加一个管道:

 dovecot   unix  -       n       n       -       -       pipe
       flags=DRhu user=vmail:vmail argv=/usr/bin/vendor_perl/spamc -u spamd -e /usr/lib/dovecot/dovecot-lda -f ${sender} -d ${recipient}

并在 /etc/postfix/main.cf 中激活它:

 virtual_transport = dovecot

或者,如果您不想使用虚拟传输,您可以使用 mailbox_command。后者以本地用户和组身份运行,而管道则使用 user 设置以指定的特权用户身份运行。

 mailbox_command = /usr/bin/vendor_perl/spamc -u spamd -e /usr/lib/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT"

SpamAssassin 结合 Dovecot LMTP / Sieve

按照 Dovecot#Sieve 中的说明设置 LMTP 和 Sieve。

编辑 /etc/dovecot/conf.d/90-plugin.conf 并添加:

 sieve_before = /etc/dovecot/sieve.before.d/
 sieve_extensions = +vnd.dovecot.filter
 sieve_plugins = sieve_extprograms
 sieve_filter_bin_dir = /etc/dovecot/sieve-filter
 sieve_filter_exec_timeout = 120s #this is often needed for the long running spamassassin scans, default is otherwise 10s

创建目录并将 spamassassin 作为 dovecot 可以运行的二进制文件放入其中。

 # mkdir /etc/dovecot/sieve-filter
 # ln -s /usr/bin/vendor_perl/spamc /etc/dovecot/sieve-filter/spamc

创建一个新文件 /etc/dovecot/sieve.before.d/spamassassin.sieve,其中包含:

 require [ "vnd.dovecot.filter" ];
 filter "spamc" [ "-d", "127.0.0.1", "--no-safe-fallback" ];

编译 sieve 规则 spamassassin.svbin

 # cd /etc/dovecot/sieve.before.d
 # sievec spamassassin.sieve

最后,重新启动 dovecot.service 服务。

基于规则的邮件处理

使用策略服务,您可以轻松地精细调整 Postfix 的邮件传递行为。 postfwd 提供了执行此操作的服务。这允许您例如实现时间感知的发件人和收件人灰名单/黑名单,以及 SPF 策略检查。

策略服务是独立的服务,并像这样连接到 Postfix:

/etc/postfix/main.cf
smtpd_recipient_restrictions =
  ...
  check_policy_service unix:/run/policyd.sock
  check_policy_service inet:127.0.0.1:10040

将策略服务放在队列的末尾可以减少负载,因为只处理合法的邮件。请确保将其放在第一个 permit 语句之前,以捕获所有传入的消息。

发件人策略框架

要将 发件人策略框架 与 Postfix 一起使用,您可以 安装 python-spf-engineAURpython-postfix-policyd-spfAURpostfix-policyd-spf-perlAUR

使用 spf-engine 或 python-postfix-policyd-spf

根据您的需要编辑 /etc/python-policyd-spf/policyd-spf.conf。一个详细注释的版本可以在 /etc/python-policyd-spf/policyd-spf.conf.commented 中找到。请额外注意 HELO 检查策略,因为标准设置会严格拒绝 HELO 失败。

main.cf 文件中,为 policyd 添加超时设置:

/etc/postfix/main.cf
policy-spf_time_limit = 3600s

然后添加一个传输:

/etc/postfix/master.cf
policy-spf  unix  -       n       n       -       0       spawn user=nobody argv=/usr/bin/policyd-spf

最后,您需要将 policyd 添加到 smtpd_recipient_restrictions。为了最小化负载,请将其放在限制列表的末尾,但在任何 reject_rbl_client DNSBL 行之前。

/etc/postfix/main.cf
smtpd_recipient_restrictions=
     ...
     permit_sasl_authenticated
     permit_mynetworks
     reject_unauth_destination
     check_policy_service unix:private/policy-spf

现在重载 postfix 服务。

您可以使用以下方法测试您的设置:

/etc/python-policyd-spf/policyd-spf.conf
defaultSeedOnly = 0

使用 postfix-policyd-spf-perl

使用 postfix 执行与 使用 python-postfix-policyd-spf 相同お的流程,但有以下区别:

main.cf 文件中 policyd 的超时设置:

/etc/postfix/main.cf
policy_time_limit = 3600

传输:

/etc/postfix/master.cf
policy  unix  -       n       n       -       0       spawn
     user=nobody argv=/usr/lib/postfix/postfix-policyd-spf-perl

将 policyd 添加到 smtpd_recipient_restrictions

警告check_policy_service 指定在 reject_unauth_destination 之后,否则您的系统可能成为开放中继。
/etc/postfix/main.cf
smtpd_recipient_restrictions=
     ...
     reject_unauth_destination
     check_policy_service unix:private/policy
     ...

发件人重写方案

要将 发件人重写方案 与 Postfix 一起使用,请 安装 postsrsdAUR 并调整设置:

/etc/postsrsd/postsrsd.conf
domains = { "yourdomain.tld", "yournextdomain.tld", "yournextdomain.tld" }
unprivileged-user = "postsrsd"

启用并启动守护进程,确保它在重启后也能运行。然后通过调整以下行来相应地配置 Postfix:

/etc/postfix/main.cf
sender_canonical_maps = socketmap:unix:srs:forward
sender_canonical_classes = envelope_sender
recipient_canonical_maps = socketmap:unix:srs:reverse
recipient_canonical_classes = envelope_recipient, header_recipient

重新启动 Postfix 并开始转发邮件。

故障排除

警告:“database /etc/postfix/*.db is older than source file ..”

如果您在 journalctl 中看到一个或两个警告:

warning: database /etc/postfix/virtual.db is older than source file /etc/postfix/virtual
warning: database /etc/postfix/transport.db is older than source file /etc/postfix/transport

然后,您可以根据收到的消息,使用以下命令修复它:

postmap /etc/postfix/transport
postmap /etc/postfix/virtual

然后 重新启动 postfix.service 服务。

Host or domain name not found. Name service error for name=...

如果您在 journalctl 中收到以下警告:

Host or domain name not found. Name service error for name=...

这可能是因为您在 chroot 中运行 Postfix,并且缺少 /etc/resolv.conf。如果是这样,您可以按照以下方法修复:

mkdir -p /var/spool/postfix/etc
cp /etc/resolv.conf /var/spool/postfix/etc/resolv.conf

然后 重新启动 postfix.service 服务。

error: require command: unknown Sieve capability `vnd.dovecot.filter'

spamassassin: line 1: error: require command: unknown Sieve capability `vnd.dovecot.filter'.
spamassassin: line 2: error: unknown command 'filter' (only reported once at first occurrence).
spamassassin: error: validation failed.
sievec(root): Fatal: failed to compile sieve script 'spamassassin.sieve'

如果您在按照 #SpamAssassin 结合 Dovecot LMTP / Sieve 操作后运行 sievec 时收到此错误,请将 /etc/dovecot/sieve.before.d/spamassassin.sieve 中的 sieve_extensions 替换为 sieve_global_extensions

重新启动 dovecot.service 服务。

参见