Postfix
- 旨在快速、易于管理和安全,同时又与 sendmail 兼容,不会让现有用户感到不安。因此,外部具有 sendmail 风格,但内部完全不同。
本文建立在邮件服务器之上。本文的目标是设置 Postfix 并解释基本配置文件的作用。本文提供了设置仅限本地系统用户的交付的说明,以及指向虚拟用户交付指南的链接。
安装
配置
请参阅 Postfix 基本配置。配置文件默认位于 /etc/postfix
中。两个最重要的文件是
master.cf
,定义启用了哪些 Postfix 服务以及客户端如何连接到它们,请参阅 master(5)main.cf
,主配置文件,请参阅 postconf(5)
配置更改需要 postfix.service
重载 或运行 postfix reload
才能生效。
别名
请参阅 aliases(5)。
您可以在 /etc/postfix/aliases
中指定别名(也称为转发器)。
您应该将所有发送给 root 的邮件映射到另一个帐户,因为以 root 身份读取邮件不是一个好主意。
取消注释以下行,并将 you
更改为真实帐户。
root: you
完成编辑 /etc/postfix/aliases
后,您必须运行 postalias 命令
# postalias /etc/postfix/aliases
对于以后的更改,您可以使用
# newaliases
~/.forward
,例如 /root/.forward
用于 root 用户。指定应将 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
newaliases
才能使 Postfix 运行,即使您没有设置任何#别名。启动/启用 postfix.service
。
TLS
有关更多信息,请参阅 Postfix TLS 支持。
安全 SMTP (发送)
默认情况下,Postfix/sendmail 不会将电子邮件加密发送到其他 SMTP 服务器。要在可用时使用 TLS,请将以下行添加到 main.cf
/etc/postfix/main.cf
smtp_tls_security_level = may
要强制 TLS(并在远程服务器不支持时失败),请将 may
更改为 encrypt
。但是请注意,如果 SMTP 服务器是公开引用的,则这违反了 RFC:2487。
安全 SMTP (接收)
默认情况下,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
有两种方法可以接受安全邮件。SMTP 上的 STARTTLS(端口 587(也称为“submission”端口))和 SMTPS(端口 465(也称为“submissions”端口)。后者以前已弃用,但已由 RFC:8314 恢复。
要启用 SMTP 上的 STARTTLS(端口 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
行的原理与上面相同。
技巧与窍门
黑名单入站邮件
使用 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
。
在 Received 标头中隐藏发件人的 IP 和用户代理
这主要是一个隐私问题,如果您使用 Thunderbird 发送电子邮件。Received 标头将包含您的 LAN 和 WAN 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
。
chroot jail 中的 Postfix
默认情况下,Postfix 未放入 chroot jail 中。Postfix 文档 [1] 提供了有关如何完成此类 jail 的详细信息。步骤概述如下,并基于 Postfix 源代码中提供的 chroot-setup 脚本。
首先,进入目录 /etc/postfix
中的 master.cf
文件,并将除服务 qmgr
、proxymap
、proxywrite
、local
和 virtual
之外的所有 chroot 条目更改为“yes”(y)
其次,创建两个函数,这将帮助我们稍后将文件复制到 chroot jail 中(请参阅最后一步)
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 }
接下来,为 jail 创建新目录
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 配置如下
/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
smtp_tls_security_level
更改为 dane-only
。请注意,这会使 Postfix 在所有根本不使用 DANE 的交付中 tempfail(以 4.X.X
错误代码响应)!完整文档位于此处。
扩展功能
- PostfixAdmin — Postfix 的基于 Web 的管理界面。
Postgrey
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 独立通用设置
编辑 /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-engineAUR、python-postfix-policyd-spfAUR 或 postfix-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
reject_unauth_destination
之后指定 check_policy_service
,否则您的系统可能会变成开放中继。/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
。
找不到主机名或域名。名称服务错误,名称为=...
如果您使用 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
。
错误:require 命令:未知的 Sieve 功能 `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
。