/etc/postfix/main.cf
配置文件的首个版本。
mail.falcot.com
。这是默认询问的唯一问题,但它所导致的配置还不够完整,无法满足 Falcot 公司的需求,这就是为什么管理员运行 dpkg-reconfigure postfix
,以便能够定制更多参数。
localhost
的一些同义词,但主要的 falcot.com
域名需要手动添加。更一般的是,这个问题通常应该用这台机器作为 MX 服务器的所有域名来回答,换句话说,就是 DNS 所说的这台机器可以接受电子邮件的所有域名。这些信息最终会出现在 Postfix 主配置文件 /etc/postfix/main.cf
的 mydestination
变量中。
192.168.0.0/16
添加到默认回答中。如果不询问问题,那么配置文件中的相关变量是 mynetworks
,如下面的示例所示。
procmail
来传递。这个工具允许用户根据存储在 ~/.procmailrc
文件中的规则,对到来的电子邮件进行排序。Postfix 和 Exim4 都建议默认使用 procmail ,但也有其它选择,如 maildrop 或 Sieve 筛选程序。
例 11.1. 初始 /etc/postfix/main.cf
文件
# See /usr/share/postfix/main.cf.dist for a commented, more complete version # Debian specific: Specifying a file name will cause the first # line of that file to be used as the name. The Debian default # is /etc/mailname. #myorigin = /etc/mailname smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) biff = no # appending .domain is the MUA's job. append_dot_mydomain = no # Uncomment the next line to generate "delayed mail" warnings #delay_warning_time = 4h readme_directory = no # See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on # fresh installs. compatibility_level = 2 # TLS parameters smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key smtpd_tls_security_level=may smtp_tls_CApath=/etc/ssl/certs smtp_tls_security_level=may smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination myhostname = mail.falcot.com alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases mydestination = mail.falcot.com, falcot.com, localhost.localdomain, localhost relayhost = mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 192.168.0.0/16 mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = all default_transport = smtp relay_transport = smtp inet_protocols = all myorigin = /etc/mailname
virtual_alias_domains
变量中,并引用 virtual_alias_maps
变量中的地址映射文件,来启用这样的域。
virtual_alias_domains = falcotsbrand.com virtual_alias_maps = hash:/etc/postfix/virtual
/etc/postfix/virtual
文件以相当直接的语法来描述映射:每行包含两个由空白字符分开的字段;第一字段是别名,第二个字段是重定向的电子邮件地址列表。特殊的 @domain.com
语法涵盖了域中所有其余的别名。
[email protected] [email protected] [email protected] [email protected], [email protected] # The alias below is generic and covers all addresses within # the falcotsbrand.com domain not otherwise covered by this file. # These addresses forward email to the same user name in the # falcot.com domain. @falcotsbrand.com @falcot.com
/etc/postfix/virtual
后,postfix 表格 /etc/postfix/virtual.db
需要使用 sudo postmap /etc/postfix/virtual
来更新。
virtual_mailbox_domains
变量中命名这个域,并且引用 virtual_mailbox_maps
中的邮箱映射文件。virtual_mailbox_base
参数包含目录,邮箱存储在其中。
virtual_mailbox_domains = falcot.org virtual_mailbox_maps = hash:/etc/postfix/vmailbox virtual_mailbox_base = /var/mail/vhosts
virtual_uid_maps
参数(各自的 virtual_gid_maps
)引用包含映射的文件,其中映射联系了邮件地址与“拥有”相应邮箱的系统用户(各自的用户组)。为了得到由相同的用户/用户组所拥有的所有邮箱,static:5000
语法指定了固定的 UID/GID (在这里,其值为 5000)。
/etc/postfix/vmailbox
文件的语法非常直接:两个字段由空白字符分开。第一个字段是虚拟域之一的电子邮件地址,而第二个字段是与之相联系的电子邮箱(相对于 virtual_mailbox_base 中指定的目录)。如果邮箱名称以斜杠(/
)结尾,那么电子邮件会存储为 maildir 格式;否则,会使用传统的 mbox 格式。maildir 格式使用整个目录来存储邮箱,每个单独的消息存储为单独的文件。另一方面,在 mbox 格式中,整个邮箱存储为一个文件,并且以“From
”(“来自”)开始的每一行(From
后面跟着一个空格)表示新消息的开始。
# Jean's email is stored as maildir, with # one file per email in a dedicated directory [email protected] falcot.org/jean/ # Sophie's email is stored in a traditional "mbox" file, # with all mails concatenated into one single file [email protected] falcot.org/sophie
soft_bounce = yes
指令,来防止请求被永久拒绝。通过warn_if_reject
来预置拒绝类型的指令,只有日志消息被记录,不是去拒绝请求。
smtpd_client_restrictions
指令控制哪些机器被允许与电子邮件服务器通信。
例 11.2. 基于客户端地址的限制
smtpd_client_restrictions = permit_mynetworks, warn_if_reject reject_unknown_client_hostname, check_client_access hash:/etc/postfix/access_clientip, reject_rhsbl_reverse_client dbl.spamhaus.org, reject_rhsbl_reverse_client rhsbl.sorbs.net, reject_rbl_client zen.spamhaus.org, reject_rbl_client dnsbl.sorbs.net
permit_mynetworks
指令用作第一条规则,接受来自本地网络中的机器的所有电子邮件(如由 mynetworks
配置变量所定义的)。
reject_unknown_client
指令预置了 warn_if_reject
修饰符:这个修饰符 将拒绝行为转换为日志中记录的简单警告。然后如果规则被实际强制执行的话,管理员可以关注被拒绝的消息数量,并且如果他们想要启用这样的强制执行的话,就可以在后面做出决定。
check_client_access
directive allows the administrator to set up a blacklist and a whitelist of email servers, stored in the /etc/postfix/access_clientip
file. Servers in the whitelist are considered as trusted, and the emails coming from there therefore do not go through the following filtering rules.
HELO
(或 EHLO
)命令开始,然后是发送电子邮件服务器的名称。检查这个名称的合法性会很有趣。为了完全强制执行 smtpd_helo_restrictions
中列出的限制,需要启用 smtpd_helo_required
选项。否则客户端会通过不发送任何 HELO
/EHLO
命令来跳过限制。
例 11.3. 对 EHLO
中宣称的名称的限制
smtpd_helo_required = yes smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, warn_if_reject reject_unknown_helo_hostname, check_helo_access hash:/etc/postfix/access_helo, reject_rhsbl_helo multi.surbl.org
permit_mynetworks
指令允许本地网络上的所有机器自由地引入它们自身。这是很重要的,因为一些电子邮件程序没有足够充分地尊重这部分 SMTP 协议,并且它们可以通过一些无意义的名称来引入自身。
reject_invalid_helo_hostname
rule rejects emails when the EHLO
announce lists a syntactically incorrect hostname. The reject_non_fqdn_helo_hostname
rule rejects messages when the announced hostname is not a fully-qualified domain name (including a domain name as well as a host name). The reject_unknown_helo_hostname
rule rejects messages if the announced name does not exist in the DNS. Since this last rule unfortunately leads to a lot of rejections, the administrators turned its effect to a simple warning with the warn_if_reject
modifier as a first step; they may decide to remove this modifier at a later stage, after auditing the results of this rule.
reject_rhsbl_helo
允许指定黑名单,针对 RHSBL 来检查主机名。
permit_mynetworks
作为第一条规则有个有趣的副作用:后面的规则只应用于本地网络以外的主机。这允许将那些宣称自己为 falcot.com
网络的一部分的主机列入黑名单,例如,通过将 falcot.com 拒绝,你不再我们的网络中!
这一行添加到 /etc/postfix/access_helo
文件中。
MAIL FROM(邮件来自)
命令宣布;再一次,这个信息能够以几种不同的方式验证。
例 11.4. 发件人检查
smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/access_sender, reject_unknown_sender_domain, reject_unlisted_sender, reject_non_fqdn_sender, reject_rhsbl_sender rhsbl.sorbs.net
/etc/postfix/access_sender
表格将一些特殊处理映射到一些发件人。这通常意味着将一些发件人列入白名单或黑名单。
reject_unknown_sender_domain
rule requires a valid sender domain, since it is needed for a valid address. The reject_unlisted_sender
rule rejects local senders if the address does not exist; this prevents emails being sent from an invalid address in the falcot.com
domain, and messages emanating from [email protected]
are only accepted if such an address really exists.
reject_non_fqdn_sender
规则拒绝那些自称来自没有完全合格域名的地址的电子邮件。实际上,这意味着拒绝来自 user@machine
的电子邮件:地址必须宣布为 [email protected]
或 [email protected]
。
reject_rhsbl_sender
规则根据(基于域的)RHSBL 服务来拒绝发件人。
RCPT TO
命令来宣布。即使与发件人地址进行的检查不那么相关,这些地址保证了合法性。
例 11.5. 收件人检查
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, reject_unlisted_recipient, reject_non_fqdn_recipient, permit
reject_unauth_destination
是基本的规则,需要外部消息写给我们;向这台服务器不服务的地址发送的消息被拒绝。没有这条规则的话,服务器会变成开放中继,允许所有的垃圾邮件发件人发送自主邮件;由此这条规则是强制的,它最好包含在接近列表的开始部分,从而没有其它规则能够在检查目的地之前对消息进行授权。
reject_unlisted_recipient
规则拒绝将消息发送给不存在的本地用户,这容易理解。最后,reject_non_fqdn_recipient
规则拒绝非完全合格的地址;从而不能将邮件发送给 jean
或 jean@machine
,并且需要替代使用完整地址,如 [email protected]
或 [email protected]
。
permit
指令不是必要的。但它用于在限制列表的末端使默认策略显性化。
DATA(数据)
命令在消息内容之前发出。它本质上不提供任何信息,除了宣布下面的是什么。它仍然可以受到检查。
reject_unauth_pipelining
指令促使消息被拒绝。这针对垃圾邮件机器人使用的一般优化进行保护,因为它们通常毫不在乎回复,并且只聚焦在尽可能短的时间发送尽可能多的电子邮件。
RCPT TO
命令的回应。
EHLO
命令被拒绝,当宣布拒绝的时候 Postfix 也知道发件人和收件人。相比交流一开始就中断了,它可以将更显性的消息记入日志。此外,很多 SMTP 客户端在 SMTP 命令的早期都不希望失败,这些客户端通过这样较晚的拒绝而较少受到困扰。
smtpd_delay_reject
规则来控制。
例 11.7. 启用基于内容的筛选
header_checks = regexp:/etc/postfix/header_checks body_checks = regexp:/etc/postfix/body_checks
例 11.8. 示例 /etc/postfix/header_checks
文件
/^X-Mailer: GOTO Sarbacane/ REJECT I fight spam (GOTO Sarbacane) /^Subject: *Your email contains VIRUSES/ DISCARD virus notification
GOTO Sarbacane
(一个批量电子邮件软件),则拒绝消息。第二个表达式控制消息的主题;如果提到病毒通知,那么我们可以决定不拒绝消息,而是立即丢弃它。
check_policy_service
参数作为外部限制:
smtpd_recipient_restrictions = permit_mynetworks, [...] check_policy_service inet:127.0.0.1:10023
postgrey
daemon and send it information concerning the relevant message. On its side, Postgrey considers the IP address/sender/recipient triplet and checks in its database whether that same triplet has been seen recently. If so, Postgrey replies that the message should be accepted; if not, the reply indicates that the message should be temporarily rejected, and the triplet gets recorded in the database.
smtpd_restriction_classes
参数中声明,并且以 smtpd_recipient_restrictions
的相同方式定义。check_recipient_access
指令然后定义表格,将给定的收件人映射到适当的限制组。
例 11.9. 在 main.cf
中定义限制类
smtpd_restriction_classes = greylisting, aggressive, permissive greylisting = check_policy_service inet:127.0.0.1:10023 aggressive = reject_rbl_client sbl-xbl.spamhaus.org, check_policy_service inet:127.0.0.1:10023 permissive = permit smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, check_recipient_access hash:/etc/postfix/recipient_access
例 11.10. /etc/postfix/recipient_access
文件
# Unfiltered addresses [email protected] permissive [email protected] permissive [email protected] permissive # Aggressive filtering for some privileged users [email protected] aggressive # Special rule for the mailing-list manager [email protected] reject_unverified_sender # Greylisting by default falcot.com greylisting
clamav
from the homonymous package.
clamav-milter
执行。milter (mail filter,邮件筛选程序的缩写)是特别设计与电子邮件服务器来接口的筛选程序。milter 使用标准的应用程序接口(API),来提供比电子邮件服务器之外的筛选程序更好的性能。Milters 最初由 Sendmail 引入,但 Postfix 很快就效仿了。
dpkg-reconfigure clamav-milter
来实现。当提示“Communication interface with Sendmail”( Sendmail 的通讯接口)时,回答 “inet:[email protected]
”。
dpkg-reconfigure clamav-base
来定制。
/etc/postfix/main.cf
中:
# Virus check with clamav-milter smtpd_milters = inet:[127.0.0.1]:10002
systemctl reload postfix
,使这项更改被接受。
include
directive it must have one.
Name: example.org Type: TXT TTL: 3600 Data: v=spf1 a mx -all
falcot.org
入口。
#
host -t TXT falcot.org
falcot.org descriptive text "v=spf1 ip4:199.127.61.96 +a +mx +ip4:206.221.184.234 +ip4:209.222.96.251 ~all"
postfix
邮件服务器可以使用 postfix-policyd-spf-python 软件包,对到来的电子邮件来检查 SPF 记录,这个软件包是用 Python 写的策略代理。文件 /usr/share/doc/postfix-policyd-spf-python/README.Debian
描述了将代理集成进 postfix 的必要步骤,因此不在这里重复。
/etc/postfix-policyd-spf-python/policyd-spf.conf
中完成,它完全存档在 policyd-spf.conf(5) 和 /usr/share/doc/postfix-policyd-spf-python/policyd-spf.conf.commented.gz
中。主要配置参数是 HELO_reject
和 Mail_From_reject
,如果检查失败的话,它们将通过将追加标头(False
),来配置电子邮件应该被拒绝(Fail
)还是应该被接受。当消息被垃圾邮件筛选程序进一步处理时,后者通常很有用。
postfix
,将与域名相联系的数字签名添加到外发电子邮件的标头中。接收部分可以通过相对于发件人 DNS 记录中下载的公钥来检查签名,从而验证消息本体和标头字段。
opendkim-genkey -s SELECTOR -d DOMAIN
来创建。 SELECTOR 必须是密钥的唯一名称。如果计划旋转密钥的话,它可以像 “mail”或创建日期那样简单。
例 11.11. 创建私钥用于为来自 falcot.com 的电子邮件签名
#
opendkim-genkey -s mail -d falcot.com -D /etc/dkimkeys
#
chown opendkim.opendkim /etc/dkimkeys/mail.*
/etc/dkimkeys/mail.private
和 /etc/dkimkeys/mail.txt
,并设置适当的所有权。第一个文件包含私钥,而后一个文件包含需要添加到 DNS 中的公钥:
Name: mail._domainkey Type: TXT TTL: 3600 Data: "v=DKIM1; h=sha256; k=rsa; s=email; p=[...]"
-b 1024
选项来选择较小的密钥尺寸。如果 opendkim-testkey
成功的话,入口就会被成功设置。入口的语法在这里解释:
/etc/default/opendkim
中选择 SOCKET
和 RUNDIR
。请注意,必须在 chrooted 环境下从 postfix
中访问 SOCKET
。进一步的配置在 /etc/opendkim.conf
中完成。后面是配置节选,它确定 Domain(域)
"falcot.com" 和所有子域 (SubDomain
)由 Selector(选择器)
"mail"和单独的私钥 (KeyFile
) /etc/dkimkeys/mail.private
来签名。对于标头和本体 “放松的”Canonicalization(规范)
能够容忍温和的修改(例如由邮件列表软件)。筛选程序在签名("s")和确认("v")Mode(模式)
中运行。如果签名验证失败(On-BadSignature
),那么邮件应该被隔离("q")。
[...] Domain falcot.com KeyFile /etc/dkimkeys/mail.private Selector mail [...] Canonicalization relaxed/relaxed Mode sv On-BadSignature q SubDomains yes [...] Socket inet:12345@localhost [...] UserID opendkim
KeyTable
)、域(SigningTable
)并指定内部或可信任的主机(InternalHosts
、ExternalIgnoreList
),它们可以通过服务器作为签名的主机之一发送邮件,而无需证书。
/etc/postfix/main.cf
中的指令使 postfix
使用筛选程序:
milter_default_action = accept non_smtpd_milters = inet:localhost:12345 smtpd_milters = inet:localhost:12345
/etc/postfix/master.cf
的服务中更有用。
/usr/share/doc/opendkim/
目录和手册页 opendkim(8) 与 opendkim.conf(5) 中获得。
_dmarc
名称来确定 DNS TXT 入口,以及当包含您的域作为发送主机的电子邮件使用 DKIM 和 SPF 验证失败时应该执行的动作。
#
host -t TXT _dmarc.gmail.com
_dmarc.gmail.com descriptive text "v=DMARC1; p=none; sp=quarantine; rua=mailto:[email protected]"
#
host -t TXT _dmarc.yahoo.com
_dmarc.yahoo.com descriptive text "v=DMARC1; p=reject; pct=100; rua=mailto:[email protected]; ruf=mailto:[email protected];"
rejec(拒绝)t
所有的电子邮件,防止它们从 Yahoo 账户发送,但没有 DKIM 和 SPF 检查或检查失败。Google Mail (Gmail)传播非常放松的策略,其中来自主域的消息仍然应该被接受(p=none
)。对于子域,它们应该被标记为垃圾邮件(sp=quarantine
)。在 rua
密钥中给出的地址可以用于将汇总的 DMARC 报告发送给它。完整语法在这里解释:
postfix
邮件服务器也可以使用这个信息。opendmarc 软件包包含必要的 milter 。与 opendkim 相似,SOCKET
和 RUNDIR
必须在 /etc/default/opendmarc
中选择(对于 Unix 套接字,必须确认它们能够在 postfix chroot 内找到)。配置文件/etc/opendmarc.conf
包含具体的注释,并且还在 opendmarc.conf(5) 中解释。DMARC 验证失败的电子邮件默认被拒绝,但通过添加适当的标头字段而被标记。要更改的话,需使用 RejectFailures true
。
smtpd_milters
和 non_smtpd_milters
中。如果我们配置 opendkim 和 opendmarc milters 在端口 12345 和 54321 上运行,那么 /etc/postfix/main.cf
中的入口看起来像这样:
non_smtpd_milters = inet:localhost:12345,inet:localhost:54321 smtpd_milters = inet:localhost:12345,inet:localhost:54321
/etc/postfix/master.cf
中。
saslpasswd2
命令完成,它使用几个参数。-u
选项确定认证域,必须与 Postfix 配置中的 smtpd_sasl_local_domain
参数匹配。-c
选项允许创建用户,而在 SASL 数据库需要存储在默认位置(/etc/sasldb2
)以外的不同位置的情况下,-f
允许指定要使用的文件。
#
saslpasswd2 -u `postconf -h myhostname` -f /var/spool/postfix/etc/sasldb2 -c jean
[... type jean's password twice ...]
ln -sf /var/spool/postfix/etc/sasldb2 /etc/sasldb2
命令,将 /etc/sasldb2
转变成指向由 Postfix 使用的数据库的符号链接。
postfix
用户需要被添加到 sasl
群组中,从而可以访问 SASL 账户数据库。还需要一些新的参数来启用 SASL,并且需要配置 smtpd_recipient_restrictions
参数来允许 SASL 认证的客户端自由发送电子邮件。
例 11.12. 在 /etc/postfix/main.cf
中启用 SASL
# Enable SASL authentication smtpd_sasl_auth_enable = yes # Define the SASL authentication domain to use smtpd_sasl_local_domain = $myhostname [...] # Adding permit_sasl_authenticated before reject_unauth_destination # allows relaying mail sent by SASL-authenticated users smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, [...]
/etc/postfix/master.cf
文件中以不同的规则和指令来配置。为了完全关闭对端口 25(smtpd
服务)的认证,要添加后面的指令:
smtp inet n - y - - smtpd [..] -o smtpd_sasl_auth_enable=no [..]
AUTH
命令(一些非常老的客户端会这样),那么可以使用 broken_sasl_auth_clients
指令来启用与它们的互操作性。