跳转到主要内容

于 2025年04月22日 摘录自 Postfix Before-Queue Content Filter

警告

本文档中描述的"队列前内容过滤"功能会限制站点能够处理的邮件数量。请参阅下文的"优缺点"部分以获取详细信息。

Postfix 队列前内容过滤功能

从版本 2.1 开始,Postfix SMTP 服务器可以将所有传入邮件转发到一个内容过滤代理服务器,该服务器会在邮件存储到 Postfix 邮件队列之前对其进行检查。其功能大致相当于在MILTER_README中描述的方法,但后者使用专用协议而非 SMTP。

队列前内容过滤器应按以下方式使用:

Internet-> Postfix SMTP 服务器-> 之前 队列 过滤器-> Postfix SMTP 服务器-> Postfix 清理服务器-> Postfix 队列-< smtp
本地
虚拟

队列前内容过滤器不应与FILTER_README文档中描述的方法混淆,后者是在邮件存储到Postfix邮件队列后进行过滤。

本文档描述以下主题:

工作原理

如上图所示,队列前过滤器位于两个 Postfix SMTP 服务器进程之间。

  • 队列前过滤器 Postfix SMTP 服务器接受来自互联网的连接,并执行常规中继访问控制、SASL 认证、TLS 协商、RBL 查询、拒绝不存在的发件人或收件人地址等操作。
  • 队列前过滤器从Postfix接收未过滤的邮件内容,并执行以下操作之一:
    1. 通过SMTP将邮件重新注入Postfix,可能在更改其内容和/或目的地后。
    2. 丢弃或隔离邮件。
    3. 通过向Postfix发送适当的SMTP状态代码拒绝邮件。Postfix 将状态传递回远程 SMTP 客户端。这样,Postfix 无需发送退信消息。
  • 后过滤器 Postfix SMTP 服务器从内容过滤器接收邮件。此后,Postfix 按照常规流程处理邮件。

本文中描述的队列前内容过滤器与FILTER_README文档中描述的队列后内容过滤器工作原理相同。在许多情况下,您可以使用相同的软件,但需遵循"优缺点"部分中讨论的限制。

队列前内容过滤的优缺点

  • 优点:Postfix可以在入站SMTP邮件传输完成前拒绝邮件,因此Postfix无需将被拒绝的邮件发回发件人(发件人地址通常已被伪造)。未被接受的邮件仍由远程SMTP客户端负责。
  • 缺点:smtpd(8) 服务在 smtpd_proxy_filter 之前,无法支持涉及头部或正文访问,或涉及队列文件操作(即任何涉及由 cleanup(8) 服务处理的内容)。

    相反,请使用 smtpd(8) 服务在 smtpd_proxy_filter 之后指定这些功能。在某些情况下,可以将一个在过滤器前执行的 PREPEND 操作(该操作会发出一个唯一模式,例如包含 MTA 域名)与一个在过滤器后执行的 header_checks 操作(实现所需功能),以及一个 smtp_header_checks IGNORE 操作,用于从转发邮件中删除预先添加的头部。

  • 缺点:远程 SMTP 客户端期望在截止时间内收到 SMTP 响应。随着系统负载增加,可用 CPU 周期越来越少,最终您必须停止接受邮件或停止过滤邮件。这就是为什么队列前内容过滤器限制了站点可处理的邮件数量。
  • 缺点:内容过滤软件可能消耗大量内存资源。您需要减少同时运行的内容过滤进程数量,以防止邮件突发导致系统崩溃。
    • 在 Postfix 2.7 及更高版本中,SMTP 客户端将经历从发送"消息结束"到 Postfix SMTP 服务器回复之间延迟的增加(在此,过滤前 SMTP 服务器进程的数量可能大于过滤进程的数量)。
    • 在 Postfix 2.7 之前的版本中,SMTP 客户端将经历服务响应延迟的增加(在此情况下,过滤前 SMTP 服务器进程的数量始终等于过滤进程的数量)。

配置 Postfix SMTP 转发代理功能

在以下示例中,过滤前 Postfix SMTP 服务器将邮件传递给监听本地主机端口 10025 的内容过滤器。过滤后 Postfix SMTP 服务器通过本地主机端口 10026 从内容过滤器接收邮件。此后邮件按常规流程处理。

内容过滤器本身在此不做描述。您可以使用任何支持 SMTP 的过滤器。对于不支持 SMTP 的内容过滤软件,Bennett Todd 的 SMTP 代理实现了一个基于 Perl 的框架。参见:https://web.archive.org/web/20151022025756/http://bent.latency.net/smtpprox/https://github.com/jnorell/smtpprox/

互联网-> Postfix SMTP 服务器在端口 25-> 在本地主机端口 10025 上过滤-> 本地主机端口 10026 上的 Postfix SMTP 服务器-> Postfix 清理服务器-> Postfix incoming queue

此配置通过编辑master.cf文件进行设置:

/etc/postfix/master.cf:
# =============================================================
# 服务类型 权限 是否启用 是否启用 chroot 唤醒 最大进程数 命令
# (是) (是) (是) (从不) (100)
# =============================================================
#
# 预过滤 SMTP 服务器。从网络接收邮件并
# 转发至本地主机端口 10025 的内容过滤器。
#
smtp inet n - n - 20 smtpd
-o smtpd_proxy_filter=127.0.0.1:10025
-o smtpd_client_connection_count_limit=10
# Postfix 2.7 及更高版本的性能优化功能。
# -o smtpd_proxy_options=speed_adjust
#
# 过滤后 SMTP 服务器。从内容过滤器接收邮件
# 通过本地主机端口 10026。
#
127.0.0.1:10026 inet n - n - - smtpd
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
# Postfix 2.10 及更高版本:指定空的 smtpd_relay_restrictions。
-o smtpd_relay_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o smtpd_data_restrictions=
-o mynetworks=127.0.0.0/8
-o receive_override_options=no_unknown_recipient_checks

注意:请勿在"="或","字符周围添加空格。

SMTP 服务器条目是默认 Postfix SMTP 服务器条目的修改版本,通常配置在 master.cf 文件的顶部:

  • SMTP 会话数量从默认的 100 减少到仅 20。这可防止大量邮件导致系统因过多内容过滤进程而崩溃。
  • "-o smtpd_client_connection_count_limit=10" 防止单个 SMTP 客户端占用所有 20 个 SMTP 服务器进程。如果所有邮件均来自可信的中继主机,则无需设置此限制。

    注意:此设置在 Postfix 2.2 及更高版本中可用。较早版本的 Postfix 将忽略此设置。

  • "-o smtpd_proxy_filter=127.0.0.1:10025" 告诉前置过滤 SMTP 服务器,应将传入邮件转发给监听本地主机 TCP 端口 10025 的内容过滤器。
  • "-o smtpd_proxy_options=speed_adjust" 告诉前置过滤 SMTP 服务器,在连接到内容过滤器之前应先接收整个电子邮件消息。这减少了同时运行的过滤进程数量。

    注释 1:当此选项启用时,内容过滤器不得对多收件人邮件的收件人进行"选择性"拒绝。拒绝所有收件人或接受所有收件人均可接受。

    注释 2:此功能会将最小可用队列空间增加 $message_size_limit。额外空间用于将邮件保存到临时文件。

  • Postfix ≥ 2.3 支持 TCP 和 UNIX 域过滤器。上述过滤器可指定为 "inet:127.0.0.1:10025"。要指定 UNIX 域过滤器,请指定 "unix:路径名"。相对路径名相对于 Postfix 队列目录进行解释。

后过滤器 SMTP 服务器是 master.cf 中的新条目:

  • "127.0.0.1:10026" 使后过滤器 SMTP 服务器仅监听本地主机地址,不会暴露给网络。切勿将后过滤器 SMTP 服务器暴露到互联网 :-)
  • "-o smtpd_authorized_xforward_hosts=127.0.0.0/8" 允许后过滤器 SMTP 服务器从前过滤器 SMTP 服务器接收远程 SMTP 客户端信息,从而使后过滤器 Postfix 守护进程记录远程 SMTP 客户端信息,而非记录本地主机 [127.0.0.1]。
  • 其他后过滤器 SMTP 服务器设置避免了在 "前过滤器" SMTP 服务器中已完成的工作重复。

默认情况下,过滤器有 100 秒时间完成其工作。如果超时,Postfix 将放弃并向远程 SMTP 客户端报告错误。您可以增加此时间限制(参见下文的 "配置参数" 部分),但这样做毫无意义,因为您无法控制远程 SMTP 客户端的超时时间。

配置参数

控制代理的参数:

  • smtpd_proxy_filter(语法:主机:端口):队列前内容过滤器的主机和 TCP 端口。如果未指定主机或主机:,则默认使用 localhost。
  • smtpd_proxy_timeout(默认:100 秒):连接到队列前内容过滤器以及发送和接收命令和数据的超时时间。所有代理错误都会记录到 maillog 文件中。出于隐私考虑,远程 SMTP 客户端仅看到 "451 错误:队列文件写入错误"。不应向陌生人披露内部细节。
  • smtpd_proxy_ehlo (默认值:$myhostname): 发送 EHLO 命令到队列前内容过滤器时使用的主机名。

Postfix 如何与队列前内容过滤器通信

Postfix SMTP 服务器连接到内容过滤器,发送一条消息,然后断开连接。在将邮件发送到内容过滤器时,Postfix 使用 ESMTP 协议但不使用命令管道。Postfix 自行生成 EHLO、XFORWARD(用于记录远程客户端 IP 地址而非 localhost[127.0.0.1])、DATA 和 QUIT 命令,并转发 before-filter Postfix SMTP 服务器未自行拒绝的所有 MAIL FROM 和 RCPT TO 命令的未修改副本。Postfix 不发送其他任何 SMTP 命令。

内容过滤器应接受与前置过滤器 Postfix SMTP 服务器相同的 MAIL FROM 和 RCPT TO 命令语法,并应将这些命令原样转发给后置过滤器 SMTP 服务器。如果内容过滤器或后过滤器 SMTP 服务器不支持前过滤器 Postfix SMTP 服务器支持的所有 ESMTP 功能,则必须在前过滤器 Postfix SMTP 服务器中通过 smtpd_discard_ehlo_keywords 参数。

当过滤器拒绝内容时,它应向前置过滤器 Postfix SMTP 服务器发送一个负面 SMTP 响应,并应在未完成与后置过滤器 Postfix SMTP 服务器的 SMTP 会话的情况下终止与后置过滤器 Postfix SMTP 服务器的连接。