Product SiteDocumentation Site

第 11 章 网络服务:Postfix、Apache、NFS、Samba、Squid、LDAP、SIP、XMPP、TURN

11.1. 邮件服务器
11.1.1. 安装 Postfix
11.1.2. 配置虚拟域
11.1.3. 接收邮件和发送邮件的限制
11.1.4. 设置 灰名单
11.1.5. 根据收件人定制筛选程序
11.1.6. Integrating an Antivirus Filter
11.1.7. 用 SPF、DKIM 和 DMARC 应对垃圾邮件
11.1.8. 认证的 SMTP
11.2. Web 服务器(HTTP)
11.2.1. 安装 Apache
11.2.2. 为 SSL 添加支持
11.2.3. 配置虚拟主机
11.2.4. 常用指令
11.2.5. 日志分析程序
11.3. FTP文件服务器
11.4. NFS 文件服务器
11.4.1. 使 NFS 安全
11.4.2. NFS 服务器
11.4.3. NFS 客户端
11.5. 用 Samba 设置 Windows 共享
11.5.1. Samba 服务器
11.5.2. Samba 客户端
11.6. HTTP/FTP 代理
11.6.1. 安装
11.6.2. 配置缓存
11.6.3. 配置筛选程序
11.7. LDAP 目录
11.7.1. 安装
11.7.2. 填入目录
11.7.3. 使用 LDAP 管理账户
11.8. 实时通信服务
11.8.1. RTC 服务的 DNS 设置
11.8.2. TURN 服务器
11.8.3. SIP 代理服务器
11.8.4. XMPP 服务器
11.8.5. 在端口 443 运行服务
11.8.6. 添加 WebRTC
网络服务是用户在日常工作中直接与之互动的程序。它们是信息系统的冰山一角,这一章节将集中阐释;它们所依赖而对用户不可见的部分就是我们已经描述过的基础架构。它们通常需要涉及 第 10.2 节 “X.509 认证” 中所描述的加密技术。

11.1. 邮件服务器

Falcot 公司的管理员选择 Postfix 作为电子邮件服务器,理由是它可靠且易于配置。的确,它的设计强制每个任务以所需要最小的权限在进程中实施,这是针对安全问题的巨大的缓解措施。

11.1.1. 安装 Postfix

postfix 软件包包含主要的 SMTP 守护进程。其它软件包(如postfix-ldappostfix-pgsql)为 Postfix 添加了额外的功能,包括访问映射数据库。如果您知道自己需要它们,那么应该安装它们。
一些 Debconf 问题在包安装时会被问到,相关回答允许生成 /etc/postfix/main.cf 配置文件的首个版本。
第一个问题处理设置的类型。在服务器连接到因特网上的情况下,只有两个建议的回答是相关的,即“Internet site”和“Internet with smarthost”。前者适用于接收到来的电子邮件并直接向收件人发送外发邮件的服务器,因此很适合Falcot公司的情况。后者适用于正常接收到来的电子邮件的服务器,但通过中间的 SMTP 服务器——“smarthost”发送外发邮件,而不是直接发送到收件人的服务器。这对于使用动态 IP 地址的个人来说非常有用,因为许多电子邮件服务器拒绝直接从这样的 IP 地址发送的消息。在这种情况下,smarthost 通常是 ISP 的 SMTP 服务器,它总是被配置为接受来自 ISP 客户的电子邮件,并适当地转发。这种设置(使用 smarthost)对于那些不是永久地连接到因特网上的服务器也是相关的,因为它避免了要管理一个无法投递的邮件队列,而这些邮件需要在以后重新尝试。
第二个问题处理机器的全名,用于从本地用户名生成电子邮件地址;机器的全名最终作为 "@" 之后的部分。在 Falcot 公司的情况下,回答应该是 mail.falcot.com 。这是默认询问的唯一问题,但它所导致的配置还不够完整,无法满足 Falcot 公司的需求,这就是为什么管理员运行 dpkg-reconfigure postfix ,以便能够定制更多参数。
其中一个额外的问题是询问与这台机器相关的所有域名。默认列表包括其全名以及 localhost 的一些同义词,但主要的 falcot.com 域名需要手动添加。更一般的是,这个问题通常应该用这台机器作为 MX 服务器的所有域名来回答,换句话说,就是 DNS 所说的这台机器可以接受电子邮件的所有域名。这些信息最终会出现在 Postfix 主配置文件 /etc/postfix/main.cfmydestination 变量中。
发送邮件时 DNS MX 记录的角色

图 11.1. 发送邮件时 DNS MX 记录的角色

在某些情况下,安装过程中还可以询问应该允许哪些网络通过机器发送电子邮件。在其默认配置中,Postfix 只接受来自机器本身的电子邮件;通常会添加本地网络。Falcot 公司的管理员将 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

11.1.2. 配置虚拟域

The mail server can receive mails addressed to other domains besides the main domain; these are then known as “virtual“ domains. In most cases where this happens, the emails are not ultimately destined to local users. Postfix provides two interesting features for handling virtual domains.

11.1.2.1. 虚拟别名域

虚拟别名域只包含别名,也就是只将电子邮件转发给其它地址的地址。
通过将其名称添加到 virtual_alias_domains 变量中,并引用 virtual_alias_maps 变量中的地址映射文件,来启用这样的域。
virtual_alias_domains = falcotsbrand.com
virtual_alias_maps = hash:/etc/postfix/virtual
/etc/postfix/virtual 文件以相当直接的语法来描述映射:每行包含两个由空白字符分开的字段;第一字段是别名,第二个字段是重定向的电子邮件地址列表。特殊的 @domain.com 语法涵盖了域中所有其余的别名。
webmaster@falcotsbrand.com  jean@falcot.com
contact@falcotsbrand.com    laure@falcot.com, sophie@falcot.com
# 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 来更新。

11.1.2.2. 虚拟邮箱域

发给虚拟邮箱域的消息,存储在没有指定给本地系统用户的邮箱中。
启用虚拟邮箱域需要在 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
jean@falcot.org falcot.org/jean/
# Sophie's email is stored in a traditional "mbox" file,
# with all mails concatenated into one single file
sophie@falcot.org falcot.org/sophie

11.1.3. 接收邮件和发送邮件的限制

数量增长的主动巨量(垃圾) 电子邮件需要更加严格地确定服务器接受哪些电子邮件。这一节展现了 Postfix 中包含的一些策略。
如果拒绝法则太过严格,那么会发生即使是合法的电子邮件交流也会被封锁在外面的情况。这样,好的习惯是测试严格程度,并在这时直接使用 soft_bounce = yes 指令,来防止请求被永久拒绝。通过warn_if_reject 来预置拒绝类型的指令,只有日志消息被记录,不是去拒绝请求。

11.1.3.1. 基于 IP 的访问限制

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 配置变量所定义的)。
第二条指令通常拒绝来自没有完全合法 DNS 配置的机器的邮件。这样的合法配置意味着 IP 地址可以被解析为名称,而这个名称可以反过来解析为 IP 地址。这个限制通常太严格,因为很多电子邮件服务器不具有它们 IP 地址的反向 DNS。这解释了为什么 Falcot 公司的管理员为 reject_unknown_client 指令预置了 warn_if_reject 修饰符:这个修饰符 将拒绝行为转换为日志中记录的简单警告。然后如果规则被实际强制执行的话,管理员可以关注被拒绝的消息数量,并且如果他们想要启用这样的强制执行的话,就可以在后面做出决定。
The 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.
后四条规则拒绝来自其中一个黑名单中列出的服务器的任何消息。RBLRemote Black List(远程黑名单)的缩写,而 RHSBL 的意思是 Right-Hand Side Black List(右手侧黑名单)。差异是前面的黑名单列出了 IP 地址,而后面的黑名单列出了域名。有几个这样的服务,列出了名声不好的、配置很差的服务器的域和 IP 地址,垃圾邮件发件人使用这些服务器作为他们电子邮件的中继,同样那些不想要的邮件也依赖这样被蠕虫或病毒感染的机器。

11.1.3.2. 检查 EHLOHELO 命令的合法性

每个 SMTP 交换从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 协议,并且它们可以通过一些无意义的名称来引入自身。
The 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 文件中。

11.1.3.3. Accepting or Refusing Mails Based on the Announced Sender

每条消息都有一位发件人,由STMP 协议的 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 表格将一些特殊处理映射到一些发件人。这通常意味着将一些发件人列入白名单或黑名单。
The 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 joe.bloggs@falcot.com are only accepted if such an address really exists.
最后,reject_non_fqdn_sender 规则拒绝那些自称来自没有完全合格域名的地址的电子邮件。实际上,这意味着拒绝来自 user@machine 的电子邮件:地址必须宣布为 user@machine.example.comuser@example.com
reject_rhsbl_sender 规则根据(基于域的)RHSBL 服务来拒绝发件人。

11.1.3.4. Accepting or Refusing Mails Based on the Recipient

每封电子邮件具有至少一名收件人,由 SMTP 协议中的 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 规则拒绝非完全合格的地址;从而不能将邮件发送给 jeanjean@machine,并且需要替代使用完整地址,如 jean@machine.falcot.comjean@falcot.com
在结尾的 permit 指令不是必要的。但它用于在限制列表的末端使默认策略显性化。

11.1.3.5. 与 DATA(数据) 命令相关的限制

SMTP的 DATA(数据) 命令在消息内容之前发出。它本质上不提供任何信息,除了宣布下面的是什么。它仍然可以受到检查。

例 11.6. DATA(数据) 检查

smtpd_data_restrictions = reject_unauth_pipelining
如果在对之前的命令回复被发送前,发送部分就发送了命令的话,那么 reject_unauth_pipelining 指令促使消息被拒绝。这针对垃圾邮件机器人使用的一般优化进行保护,因为它们通常毫不在乎回复,并且只聚焦在尽可能短的时间发送尽可能多的电子邮件。

11.1.3.6. 应用限制

尽管上面的命令在 SMTP 交换的各个阶段验证信息,Postfix 默认发送真正的拒绝作为对 RCPT TO 命令的回应。
这意味着即使消息由于非法的 EHLO 命令被拒绝,当宣布拒绝的时候 Postfix 也知道发件人和收件人。相比交流一开始就中断了,它可以将更显性的消息记入日志。此外,很多 SMTP 客户端在 SMTP 命令的早期都不希望失败,这些客户端通过这样较晚的拒绝而较少受到困扰。
这个选择的最后一个优点是在 STMP 交换的各个阶段规则都会聚集信息;这允许确定更精细粒度的许可,如拒绝那些宣布自己是本地发件人的非本地连接。
默认行为由 smtpd_delay_reject 规则来控制。

11.1.3.7. 根据消息内容来筛选

如果没有一种方式对信息内容进行检查的话,验证与限制系统将是不完整的。Postfix 将应用于电子邮件头的检查从那些应用于电子邮件主体的检查中区别出来。

例 11.7. 启用基于内容的筛选

header_checks = regexp:/etc/postfix/header_checks
body_checks = regexp:/etc/postfix/body_checks
这些文件都含有正则表达式(一般被称为 regexpsregexes)的列表,以及当电子邮件头(或主体)与表达式匹配时触发的相关动作。

例 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(一个批量电子邮件软件),则拒绝消息。第二个表达式控制消息的主题;如果提到病毒通知,那么我们可以决定不拒绝消息,而是立即丢弃它。
这些筛选的使用是把双刃剑,因为容易使规则太过一般化,并且结果容易丢失合法的电子邮件。在这些情况下,不仅丢失消息,它们的发件人也会得到不需要的(令人困扰的)错误消息。

11.1.4. 设置 灰名单

“Greylisting” is a filtering technique according to which a message is initially rejected with a temporary error code, and only accepted after a further delivery attempt with some delay. This filtering is particularly efficient against spam sent by the many machines infected by worms and viruses, since this software rarely acts as a full SMTP agent (by checking the error code and retrying failed messages later), especially since many of the harvested addresses are really invalid and retrying would only mean losing time.
Postfix 本身不提供灰名单,但它有个特性,接受还是拒绝给定消息的决定可以委托给外部程序。postgrey 软件包刚好包含这样的程序,它被设计与这个访问策略委托服务来对接。
一旦安装了 postgrey,它就作为守护进程运行,并且监听 10023 端口。Postfix 然后可以配置来使用它,通过添加 check_policy_service 参数作为外部限制:
smtpd_recipient_restrictions =
    permit_mynetworks,
    [...]
    check_policy_service inet:127.0.0.1:10023
Each time Postfix reaches this rule in the rule set, it will connect to the 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.
灰名单的主要缺点是合法消息会延迟,也不会总是被接受。它还增加了服务器发送很多合法电子邮件的负担。

11.1.5. 根据收件人定制筛选程序

第 11.1.3 节 “接收邮件和发送邮件的限制”第 11.1.4 节 “设置 灰名单 回顾了很多可能的限制。在限制接收到垃圾邮件的量方面它们都有自己的作用,但它们也有自己的缺点。这样,根据收件人来定制一组筛选程序会越来越常见。在 Falcot 公司,灰名单吸引了多数用户,但它阻碍了需要低延迟电子邮件的一些用户(如技术支持服务)的工作。相似地,从会被列入黑名单的一些亚洲提供商那里接收电子邮件的商务服务有时也会有问题;这项服务要求非筛选的地址,从而能够响应。
Postfix 通过“restriction class(限制类)”的概念来提供筛选服务的定制。类在 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
postmaster@falcot.com  permissive
support@falcot.com     permissive
sales-asia@falcot.com  permissive

# Aggressive filtering for some privileged users
joe@falcot.com         aggressive

# Special rule for the mailing-list manager
sympa@falcot.com       reject_unverified_sender

# Greylisting by default
falcot.com             greylisting

11.1.6. Integrating an Antivirus Filter

The many viruses circulating as attachments to emails make it important to set up an antivirus solution at the entry point of the company network, since despite an awareness campaign, some users will still open attachments from obviously shady messages.
The Falcot administrators selected clamav from the homonymous package.
防病毒软件与电子邮件服务器之间的接口任务由 clamav-milter 执行。miltermail filter,邮件筛选程序的缩写)是特别设计与电子邮件服务器来接口的筛选程序。milter 使用标准的应用程序接口(API),来提供比电子邮件服务器之外的筛选程序更好的性能。Milters 最初由 Sendmail 引入,但 Postfix 很快就效仿了。
一旦安装了 clamav-milter 软件包,就应该重新配置 milter 来运行在 TCP 端口上,而不是在默认命名套接字上。这可以通过 dpkg-reconfigure clamav-milter 来实现。当提示“Communication interface with Sendmail”( Sendmail 的通讯接口)时,回答 “inet:10002@127.0.0.1”。
标准的 ClamAV 配置适应多数情况,但一些重要的参数仍然需要用 dpkg-reconfigure clamav-base 来定制。
最后一步包括告诉 Postfix 使用最近配置的筛选程序。这是件简单的事,将后面的指令添加到 /etc/postfix/main.cf中:
# Virus check with clamav-milter
smtpd_milters = inet:[127.0.0.1]:10002
如果防病毒软件发生问题,这一行可以被注释掉,并且应该运行 systemctl reload postfix,使这项更改被接受。
由 Postfix 处理的所有消息现在经过防病毒软件删选程序。

11.1.7. 用 SPF、DKIM 和 DMARC 应对垃圾邮件

每天大量发送的自发电子邮件导致建立了几条标准,目的在于验证授权的电子邮件的发送主机被授权,以及没有关联的电子邮件是否合法。后面的系统都是基于 DNS 的,并且需要管理员不仅控制邮件服务器,而且还要控制有问题的域的 DNS。

11.1.7.1. 集成发件人策略框架(Sender Policy Framework,即SPF)

发件人策略框架(Sender Policy Framework,即SPF)用于验证对于给定的域,某个邮件服务器是否允许合法地发送电子邮件。它主要通过 DNS 来配置。配置入口的语法在: 中具体解释
The following is a sample DNS entry which states that all the domain's Mail Exchange Resource Records (MX-RRs) are allowed to send email for the current domain, and all others are prohibited. The DNS entry does not need to be given a name. But to use the 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"
它声明发件人的 IP 必须与发送域的记录匹配,或者必须作为当前域的一个电子邮件交换资源记录(Mail Exchange Resource Records)列出,或者必须是三个提到的 IP4 地址之一。所有其它主机应该被标记为不允许对那些发件人域发送电子邮件。后者被称为“软失败”,并且要由此标记电子邮件,但仍可以接受它。
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_rejectMail_From_reject,如果检查失败的话,它们将通过将追加标头(False),来配置电子邮件应该被拒绝(Fail)还是应该被接受。当消息被垃圾邮件筛选程序进一步处理时,后者通常很有用。
如果结果要由 opendmarc第 11.1.7.3 节 “集成基于域的消息认证、报告与一致性(DMARC)”)使用,那么 Header_Type 必须设置为 AR
注意 spamassassin 包含插件来检查 SPF 记录。

11.1.7.2. 和集成 DomainKeys (DKIM) 签名与检查

域密钥识别邮件(Domain Keys Identified Mail,缩写为DKIM)标准是发件人认证系统。邮件传输代理,这里是 postfix,将与域名相联系的数字签名添加到外发电子邮件的标头中。接收部分可以通过相对于发件人 DNS 记录中下载的公钥来检查签名,从而验证消息本体和标头字段。
必要的工具与软件包opendkimopendkim-tools 一起上市。
第一个私钥必须使用命令 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=[...]"
Debian 中的 opendkim 软件包默认为 2048 字节。不幸的是一些 DNS 服务器只能处理最大 255 个字符的文本入口,这超过了所选择的默认尺寸。在这种情况下,使用 -b 1024 选项来选择较小的密钥尺寸。如果 opendkim-testkey 成功的话,入口就会被成功设置。入口的语法在这里解释:
为了配置 opendkim,必须在 /etc/default/opendkim 中选择 SOCKETRUNDIR。请注意,必须在 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)并指定内部或可信任的主机(InternalHostsExternalIgnoreList),它们可以通过服务器作为签名的主机之一发送邮件,而无需证书。
后面在 /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) 中获得。
注意 spamassassin 包含插件来检查 DKIM 记录。

11.1.7.3. 集成基于域的消息认证、报告与一致性(DMARC)

基于域的消息认证、报告与一致性(DMARC)标准,可以通过_dmarc名称来确定 DNS TXT 入口,以及当包含您的域作为发送主机的电子邮件使用 DKIM 和 SPF 验证失败时应该执行的动作。
让我们看看两个大提供商的条目:
# host -t TXT _dmarc.gmail.com
_dmarc.gmail.com descriptive text "v=DMARC1; p=none; sp=quarantine; rua=mailto:mailauth-reports@google.com"
# host -t TXT _dmarc.yahoo.com
_dmarc.yahoo.com descriptive text "v=DMARC1; p=reject; pct=100; rua=mailto:d@rua.agari.com; ruf=mailto:d@ruf.agari.com;"
Yahoo 具有严格的策略来rejec(拒绝)t所有的电子邮件,防止它们从 Yahoo 账户发送,但没有 DKIM 和 SPF 检查或检查失败。Google Mail (Gmail)传播非常放松的策略,其中来自主域的消息仍然应该被接受(p=none)。对于子域,它们应该被标记为垃圾邮件(sp=quarantine)。在 rua 密钥中给出的地址可以用于将汇总的 DMARC 报告发送给它。完整语法在这里解释:
postfix 邮件服务器也可以使用这个信息。opendmarc 软件包包含必要的 milter 。与 opendkim 相似,SOCKETRUNDIR 必须在 /etc/default/opendmarc 中选择(对于 Unix 套接字,必须确认它们能够在 postfix chroot 内找到)。配置文件/etc/opendmarc.conf 包含具体的注释,并且还在 opendmarc.conf(5) 中解释。DMARC 验证失败的电子邮件默认被拒绝,但通过添加适当的标头字段而被标记。要更改的话,需使用 RejectFailures true
然后 milter 添加到 smtpd_miltersnon_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
milter 还可以可选择地替代应用于 /etc/postfix/master.cf 中。

11.1.8. 认证的 SMTP

能够发送电子邮件需要能够访问到 SMTP 服务器;还需要所谓的 SMTP 服务器,通过它来发送电子邮件。对于漫游用户,这会需要定期更改 SMTP 客户端的配置,因为 falcot 公司的 SMTP 服务器拒绝来自明显不属于公司 IP 地址的邮件。有两个解决方案:漫游用户在他们的计算机上安装 SMTP 服务器,或者他们通过一些方式被认证为雇员,从而仍然使用公司的服务器。不推荐前面的解决方案,因为计算机不会永远地连接,并且在出现问题时不能重复尝试发送消息;我们将聚焦于后一个解决方案。
Postfix 中的 SMTP 认证依赖于 SASL(Simple Authentication and Security Layer,简单认证与安全层)。它需要安装 libsasl2-modulessasl2-bin 软件包,然后在 SASL 数据库中为 SMTP 服务器上需要认证的每位用户注册密码。这通过 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 ...]
注意 SASL 数据库创建在 Postfix 的目录下。为了确保一致性,还使用 ln -sf /var/spool/postfix/etc/sasldb2 /etc/sasldb2 命令,将 /etc/sasldb2 转变成指向由 Postfix 使用的数据库的符号链接。
现在需要配置 Postfix 来使用 SASL。首先 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,
[...]
不通过未加密的连接发送密码通常是好的主意。Postfix 允许为它运行其上的每个端口(服务)使用不同的配置。所有这些可以在 /etc/postfix/master.cf 文件中以不同的规则和指令来配置。为了完全关闭对端口 25(smtpd 服务)的认证,要添加后面的指令:
smtp      inet  n       -       y       -       -       smtpd
    [..]
    -o smtpd_sasl_auth_enable=no
    [..]
如果由于一些原因,客户端使用了过期的 AUTH 命令(一些非常老的客户端会这样),那么可以使用 broken_sasl_auth_clients 指令来启用与它们的互操作性。