Home / Alt manpages / postscreen(8postfix)

  • postscreen(8postfix)
  • Postfix admin command
  • linux

Put Postfix postscreen into Service Without Blocking Mail First

You will prepare Postfix postscreen for an MX listener, confirm that it is only observing traffic, and identify the small set of controls that turn observation into rejection. This guide uses Postfix 3.8.6, installed from the Ubuntu postfix package on the reference machine. Allow 20 to 30 minutes for inspection and a reload; allow longer if you need to test a real external sender.

You need root access for changes to /etc/postfix and for postfix reload. The inspection commands are ordinary, unprivileged commands. Do not put postscreen in front of submission traffic on port 587: the manual says it is for MX traffic and should not handle mail from authenticated end-user clients.

1. Confirm the installed version and service layout

Start by checking the binary, Postfix version, and current master service table:

$ dpkg-query -W -f='${Package} ${Version}\n' postfix
postfix 3.8.6-1ubuntu0.1
$ postconf mail_version
mail_version = 3.8.6
$ postconf -Mf | grep -E '^(smtp|postscreen|smtpd|dnsblog|tlsproxy) '
smtp      inet  n       -       y       -       -       smtpd
submission inet n       -       y       -       -       smtpd

The exact service rows vary by installation. On the reference machine there is no postscreen row, so postscreen is not currently handling the public SMTP listener. The daemon is installed at /usr/lib/postfix/sbin/postscreen; it is normally started by the Postfix master service, not by running that path directly.

Checkpoint

Save the output of postconf -Mf before editing master.cf. It is your rollback reference.

2. Record the non-destructive defaults

Postscreen's defaults are deliberately safe for an initial observation period. Ask Postfix for the values that matter:

$ postconf -d postscreen_access_list postscreen_dnsbl_action \
  postscreen_dnsbl_sites postscreen_greet_action postscreen_greet_wait \
  postscreen_pipelining_enable postscreen_non_smtp_command_enable \
  postscreen_bare_newline_enable postscreen_cache_retention_time
postscreen_access_list = permit_mynetworks
postscreen_dnsbl_action = ignore
postscreen_dnsbl_sites =
postscreen_greet_action = ignore
postscreen_greet_wait = ${stress?{2}:{6}}s
postscreen_pipelining_enable = no
postscreen_non_smtp_command_enable = no
postscreen_bare_newline_enable = no
postscreen_cache_retention_time = 7d

In this mode, postscreen logs what it finds and hands connections to a Postfix SMTP server. permit_mynetworks excludes trusted networks from tests. An empty postscreen_dnsbl_sites list means there is no DNS blocklist scoring to act on, even if you set a DNSBL action later.

The wait value is stress-dependent: the normal default is up to six seconds and the overload value is up to two seconds. That delay is a reason to test mail flow and monitor logs before making postscreen a permanent part of the MX path.

3. Add postscreen to the MX path

Before editing, inspect the active configuration and make a dated copy as root:

$ sudo postconf -h config_directory
/etc/postfix
$ sudo cp --preserve=all /etc/postfix/master.cf /etc/postfix/master.cf.before-postscreen

Warning

The next change affects inbound SMTP service. Work during a maintenance window and keep a second administrative session available. Do not replace the submission service. The usual arrangement is for the public smtp service to run postscreen, with a separate smtpd pass-through service for connections that postscreen has accepted. The dnsblog and tlsproxy services are also needed when the selected postscreen configuration uses DNS lookups or TLS.

Use the exact service stanza recommended by the installed Postfix documentation for your package, preserving the existing indentation and any local overrides. Do not copy a stanza from an unrelated host: chroot settings, process limits, TLS overrides and service names are deployment-specific. The important boundary is that port 25 is the postscreen entry point, while port 587 remains an authenticated smtpd service.

After the edit, ask Postfix to parse the service table before reloading:

$ sudo postfix check
$ postconf -Mf | grep -E '^(smtp|postscreen|smtpd|dnsblog|tlsproxy) '
smtp       inet  ... postscreen ...
postscreen ...     ... postscreen
smtpd      pass   ... smtpd
dnsblog    unix   ... dnsblog
tlsproxy   unix   ... tlsproxy

The spacing and whether a row is printed depend on the local file. Treat any error from postfix check as a stop signal. Restore the saved file with sudo cp --preserve=all /etc/postfix/master.cf.before-postscreen /etc/postfix/master.cf, then run sudo postfix check again.

4. Reload and verify observation mode

Only reload after the configuration check succeeds:

$ sudo postfix reload
postfix/postfix-script: refreshing the Postfix mail system

The wording can differ, and a successful reload does not prove that an outside host can deliver mail. Watch the mail log while making one controlled SMTP connection from a permitted test host:

$ sudo journalctl -u postfix --since '5 minutes ago' --no-pager
$ sudo postconf -h maillog_file 2>/dev/null
/var/log/mail.log
$ sudo tail -f /var/log/mail.log

Look for postscreen decisions, the client address, and the hand-off to smtpd. Do not assume that a DNSBL lookup or a pre-greeting test has blocked anything while its action remains ignore. If the service is not listening, check ss -ltnp | grep ':25 ', the host firewall and the MX address before changing postscreen policy.

5. Add one controlled blocking policy

Do not enable every test at once. Start with a DNS reputation policy only after choosing DNSBL providers, reading their usage rules, and deciding how false positives will be handled. The manpage defines postscreen_dnsbl_action as the action taken when the combined score reaches the threshold, and its default is ignore. A typical policy therefore has three deliberate parts:

postscreen_dnsbl_sites = YOUR_DNSBL_1*2, YOUR_DNSBL_2
postscreen_dnsbl_threshold = 2
postscreen_dnsbl_action = enforce

YOUR_DNSBL_1 and YOUR_DNSBL_2 are placeholders, not valid provider names. Replace them only with services you have selected and configured. Test the syntax with sudo postfix check, then reload with sudo postfix reload. Keep soft_bounce = yes as a temporary safety net only if you understand its effect: it turns rejections into temporary failures and can leave senders retrying for days. Remove it after testing.

For protocol tests, enable one feature at a time, such as postscreen_pipelining_enable = yes or postscreen_non_smtp_command_enable = yes, and choose its action explicitly. The after-greeting tests can make a client reconnect from the same IP before delivery. They can also interfere with clients that need AUTH, XCLIENT or XFORWARD; the manpage specifically warns against enabling those tests when port 25 must advertise those services.

6. Recover quickly if mail flow changes

If legitimate delivery is delayed or rejected, first return the action to ignore rather than deleting the cache or guessing at a DNSBL score:

$ sudo postconf -e 'postscreen_dnsbl_action = ignore'
$ sudo postfix check
$ sudo postfix reload

For a service-level rollback, restore the saved master.cf, validate it, and reload:

$ sudo cp --preserve=all /etc/postfix/master.cf.before-postscreen /etc/postfix/master.cf
$ sudo postfix check
$ sudo postfix reload

Keep the cache while investigating: it records temporary decisions and is normally stored at btree:$data_directory/postscreen_cache, with expired entries retained for seven days by default. Removing it is not a general repair and can force legitimate clients through the tests again.

Done means

  • Postfix 3.8.6 and the active service table were checked before editing.
  • Port 25 is the only listener placed behind postscreen; authenticated submission remains separate.
  • postfix check passes before every reload.
  • Observation mode was verified in the mail log before any rejection action was enabled.
  • DNSBL providers, scores and false-positive recovery are documented before enforcement.
  • A tested master.cf backup and an action-level rollback command are available.