How to Use Postfix Postscreen to Test Email for Spam: Part 1


I recently read with interest that the powerful mail transfer agent (MTA) that is Postfix has introduced a relatively new addition to its load mitigation and anti-spam arsenal. As of version 2.8, Postfix now incorporates Postscreen.

In previous versions of the mail server, only one connection could be processed by each SMTP system process before moving to the next one in the queue. That’s far from ideal when you’re processing tens if not hundreds of thousands of emails every day. For superior efficiency, a single Postscreen process can handle multiple connections simultaneously and act as filter, deciding which email is valid and which might come from spambots, before passing the job onto an SMTP process.

The theory goes that, with less impact from spambots, there are more resources available to process valid email more efficiently. This in turn means you have more capacity available — or bang for your buck — when it comes to your hardware. What piqued my interest about Postscreen was the fact that Postfix already makes sterling efforts to mitigate server load conditions impeccably.

This well-designed MTA automagically deploys its own “stress-adaptive behavior“ when it’s feeling the pressure. This action takes the form of a quick daemon restart (without dropping existing network connections) and the lowering in its tolerance of who and how other machines are allowed to connect and deliver email to it. This super-clever and automatically configured change in settings acts simply as a temporary measure until Postfix feels that its cortisol has decreased to a healthier level.

Although I was amazed when I first read about this type of reaction to heavy load caused by a deluge of email — whether from an attack or from a busy mail server that had been suffering a network outage coming back online again — I was equally impressed by Postscreen’s functionality. In this article, I’ll take a look at how it can help you now.

Ham Not Spam

As demoralizing as it may be, on our beloved Internet today, most email is spam (unsolicited) not ham (solicited). And, apparently most of the spam generated today is sourced from malware being installed on desktop and laptops, which have been compromised unwittingly by some download or unsuspecting click in the past.

Sadly, those in the know estimate that this scenario will continue for the foreseeable future; thus, the onus to provide solutions ultimately falls on the Internet’s email infrastructure. According to the Postfix documentation, it became obvious that without some form of inbuilt mechanism to cope with the continual waterfall of spam, mail servers  would spend significantly more time refusing to process email than actually accepting it.

As you delve further into how Postscreen works, you realize how difficult it is to circumvent the pressures of inbound spam. Postfix’s programmers realized that the most efficient way of detecting whether an email should be classified as spam or ham was to make the decision based on a single criterion. In other words, if any of a number of tests fails, the email is binned.

To achieve such efficiency, the key premise of Postscreen is one of temporary whitelisting. Thankfully, zombie machines (i.e., compromised machines infected via numerous methods) are in a race against time to cause as much damage as possible before they are blacklisted by ISPs and spam lists. This means they tend to rush through email delivery and hurry MTAs along, making them suspicious with less-than-polite and badly ordered SMTP commands.

Postfix works on two main criteria to identify zombie machines: one, if the connecting IP address is found to be blacklisted and, second, if it hurries through the SMTP process with malformed commands. The Postfix docs make the point that inspecting the content of an email isn’t a good way of making a decision using one measurement; there are simply too many factors, so it requires relatively high levels of processing power.

Some of the single-measurement tests that Postfix employs inevitably delay the processing of emails by a few seconds; however, clearly the main objective is to minimize these. As I just mentioned, the inspection of hurried SMTP commands (e.g., details relating to the “helo”, the sender, and the recipient) are used in the well-considered tests. Before reaching that stage, however, whitelists (and blacklists) are queried, too. I’ll take a closer look at these in a moment.

Defense Overview

Here’s a quick summary of which parts of an email transaction Postscreen deals with in order to help manage unsolicited email. The Postfix docs refer to a “multi-layer defense,” all designed with efficiency in mind.

To keep around 90 percent of spam at arm’s length, at the outside layer, the clever Postscreen makes light work of repelling zombie machines and spambots. These “inexpensive” defenses make a massive difference in the effort that a mail server needs to undertake.

The second layer is one concerned with SMTP-level checks — thanks to configured policies or “milter” (a portmanteau of mail filter) applications, such as DKIM (Domain Keys Identified Mail) implementations that check the identity of a sender, among other things.

The third layer is more concerned about the content of emails and their headers. The docs say that through several options, Postfix “can block unacceptable attachments such as executable programs, and worms or viruses with easy-to-recognize signatures.”

Finally, you can pipe email through Postfix, and beyond, into well-known content filtering applications. One example might be the popular SpamAssassin, which employs clever techniques, such as Bayesian probability, to determine if an email is ham or spam.

I like the simplicity and considered approach of this particular statement from the docs: “The general strategy is to use the less expensive defenses first, and to use the more expensive defenses only for the spam that remains.”

In this loosely formed layered model, the vigilant Postscreen is deployed within the first two layers.

Your Machines

Clearly, you need the ability to configure settings so that your own valid machines can always connect without delays or without the risk of their being spurned by your trusty mail server. You can adjust the postscreen_access_list option to affect those machines which are immediately whitelisted. Usually, this particular option will simply default to the permit_mynetworks option, which might seem familiar because it essentially just points at the “mynetworks” option. Anybody who has ever looked inside the main config file, /etc/postfix/, will have probably spotted that option or indeed added their own IP addresses to it.

To see how whitelisting your own machines works, here’s a reminder of the greeting that SMTP uses; it usually looks something like this:

220 mail.chrisbinnie.tld ESMTP server ready Tue, 11 Nov 2121 11:11:11 +0100

By adding an IP address or address range to “mynetworks” or adding a “permit” entry to postscreen_access_list (which I’ll look at it a moment), the sending machine won’t be grilled by Postfix either before or after the 220 “greeting” tests. Safe passage is therefore assured.

If you wanted to add either blacklisted or whitelisted IP addresses and ranges to your Postfix build, then you would add them to the /etc/postfix/postscreen_access.cidr file and then point your file at that location. Obviously, you can adjust that filename if you need to. The .cidr file extension means a file format within which the flexible MTA will look for classless inter-domain routing (CIDR) formatted address ranges. The Postfix docs offer us the following example for our .cidr file:

# Rules are evaluated in the order as specified.
# Blacklist 192.168.* except           permit       reject

Listing 1: How the “postscreen_access.cidr” file looks using the CIDR notation for networks.

I hope you’ll agree that this example speaks volumes (and follows the clarity of much of the well-written Postfix docs). And, you can tailor it to suit your needs.

Next we’ll make a small change to our /etc/postfix/ file. Note the comma separation because we want to also include the contents of “mynetworks” by using the permit_mynetworks option.

postscreen_access_list = permit_mynetworks, cidr:/etc/postfix/postscreen_access.cidr

A quick refresh of our config, cleverly performed without resetting all of the current connections, is now needed to set any changes live. We can achieve just that by running this simple command:

# postfix reload

There’s more to this approach than meets the eye; we don’t just receive whitelist and blacklist content options. This MTA also offers configurable actions on how to react to a blacklisted machine. There are no whitelisted actions; however, because we always want such a host to move forward — one that has been cleared to proceed — onto an SMTP process of its own. In your log files, you will see an entry for each result, including a hostname and a port number, either referenced as WHITELIST or BLACKLIST.

The settings which you can affect for a blacklisted machine are as we can see in Table 1.




The is the default action, and here failures are of little consequence. As other tests will also be applied, you could use this setting for testing, generating lots of logs without actually blocking -mails and upsetting your users.


Postfix will continue with its additional testing if you use this option. Here we respond with the all-too-common SMTP error 550. One MTA’s example error 550 response might be “550 Requested action not taken: mailbox unavailable” which is often seen for spam.

You should be aware that there are many 550 error statements made by MTAs such as “relay not permitted”. Note that if senders generate enough error 550s they may end up on a blacklist (or two), which could affect their ability to send email globally. For future reference, Postfix will dutifully log the “helo”, the sender, and the intended recipient for reference.


Here we get much more medieval and simply kill the connection as soon as it arrives. Postfix will respond with a 521 SMTP error code. This draconian error code states something along the lines of “mail.chrisbinnie.tld does not accept mail (see RFC1846)”.

Table 1: Available actions for machines which are blacklisted; whitelisted machines go unhindered.

The options shown in Table 1 apply to both permanently blacklisted machines and also those picked up during the tests performed by Postfix before the greeting takes place. Each is tested for again and repeated whenever the sending machine returns at a later date. Additionally, if third-party real-time blackLists (RBLs), such as the powerful SpamHaus, are used and give a negative warning then they also apply. As you can see, it’s possible both to log and test any changes you make to your configuration and at the same time limit the resources used.

Stay Tuned

In this article, I looked at the tests that Postfix uses to identify zombie machines and described how Postscreen helps manage unsolicited email using a “multi-layer defense. Next time, I’ll look at some of the “deep protocol” tests that Postfix performs after the initial greeting.

Read Part 2 here.
Chris Binnie is a Technical Consultant with 20 years of Linux experience and a writer for Linux Magazine and Admin Magazine. His new book Linux Server Security: Hack and Defend teaches you how to launch sophisticated attacks, make your servers invisible and crack complex passwords.