Postfix Before-Queue Content Filter


WARNING

The before-queue content filtering feature described in this document limits the amount of mail that a site can handle. See the "Pros and Cons" section below for details.

The Postfix before-queue content filter feature

As of version 2.1, the Postfix SMTP server can forward all incoming mail to a content filtering proxy server that inspects all mail BEFORE it is stored in the Postfix mail queue. It is roughly equivalent in capabilities to the approach described in MILTER_README, except that the latter uses a dedicated protocol instead of SMTP.

The before-queue content filter is meant to be used as follows:

Internet -> Postfix SMTP server -> Before queue filter -> Postfix SMTP server -> Postfix cleanup server -> Postfix queue -< smtp
local
virtual

The before-queue content filter is not to be confused with the approach described in the FILTER_README document, where mail is filtered AFTER it is stored in the Postfix mail queue.

This document describes the following topics:

Principles of operation

As shown in the diagram above, the before-queue filter sits between two Postfix SMTP server processes.

The before-queue content filter described here works just like the after-queue content filter described in the FILTER_README document. In many cases you can use the same software, within the limitations as discussed in the "Pros and Cons" section below.

Pros and cons of before-queue content filtering

Configuring the Postfix SMTP pass-through proxy feature

In the following example, the before-filter Postfix SMTP server gives mail to a content filter that listens on localhost port 10025. The after-filter Postfix SMTP server receives mail from the content filter via localhost port 10026. From then on mail is processed as usual.

The content filter itself is not described here. You can use any filter that is SMTP enabled. For non-SMTP capable content filtering software, Bennett Todd's SMTP proxy implements a nice Perl-based framework. See: https://web.archive.org/web/20151022025756/http://bent.latency.net/smtpprox/ or https://github.com/jnorell/smtpprox/

Internet -> Postfix SMTP server on port 25 -> filter on localhost port 10025 -> Postfix SMTP server on localhost port 10026 -> Postfix cleanup server -> Postfix incoming queue

This is configured by editing the master.cf file:

/etc/postfix/master.cf:
    # =============================================================
    # service type  private unpriv  chroot  wakeup  maxproc command
    #               (yes)   (yes)   (yes)   (never) (100)
    # =============================================================
    #
    # Before-filter SMTP server. Receive mail from the network and
    # pass it to the content filter on localhost port 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 and later performance feature.
        # -o smtpd_proxy_options=speed_adjust
    #
    # After-filter SMTP server. Receive mail from the content filter
    # on localhost port 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 and later: specify empty 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

Note: do not specify spaces around the "=" or "," characters.

The before-filter SMTP server entry is a modified version of the default Postfix SMTP server entry that is normally configured at the top of the master.cf file:

The after-filter SMTP server is a new master.cf entry:

By default, the filter has 100 seconds to do its work. If it takes longer then Postfix gives up and reports an error to the remote SMTP client. You can increase this time limit (see the "Configuration parameters" section below) but doing so is pointless because you can't control when the remote SMTP client times out.

Configuration parameters

Parameters that control proxying:

How Postfix talks to the before-queue content filter

The before-filter Postfix SMTP server connects to the content filter, delivers one message, and disconnects. While sending mail into the content filter, Postfix speaks ESMTP but uses no command pipelining. Postfix generates its own EHLO, XFORWARD (for logging the remote client IP address instead of localhost[127.0.0.1]), DATA and QUIT commands, and forwards unmodified copies of all the MAIL FROM and RCPT TO commands that the before-filter Postfix SMTP server didn't reject itself. Postfix sends no other SMTP commands.

The content filter should accept the same MAIL FROM and RCPT TO command syntax as the before-filter Postfix SMTP server, and should forward the commands without modification to the after-filter SMTP server. If the content filter or after-filter SMTP server does not support all the ESMTP features that the before-filter Postfix SMTP server supports, then the missing features must be turned off in the before-filter Postfix SMTP server with the smtpd_discard_ehlo_keywords parameter.

When the filter rejects content, it should send a negative SMTP response back to the before-filter Postfix SMTP server, and it should abort the connection with the after-filter Postfix SMTP server without completing the SMTP conversation with the after-filter Postfix SMTP server.