Blocking SPAM (UCE) using Postfix


The e-mail administrator should try to protect users from unsolicited commercial email (UCE). The rise in UCE has become a nuisance to many email users today. The e-mail administrator should attempt to implement controls to minimize the amount of UCE that is delivered to local users. This article describes several methods that postfix provides for the e-mail administrator to filter known UCE sites and messages.

Blocking UCE

There are several levels where you can block UCE mails.

Postix SMTP Program

The Postfix smtpd program is responsible for accepting SMTP connections from remote hosts and receiving mail messages for local users. The optional access table directs the Postfix SMTP server
to selectively reject or accept mail. Access can be allowed or denied for specific host names, domain names, networks, host network addresses or mail addresses.

Problems with the SMTP Protocol

One technique used by UCE senders to hide their identity is to use phony addresses in the From: mail header lines. This is possible due to a security limitation in the standrad SMTP Protocol. During a normal SMTP session, both the HELO and the MAIL FROM: commands identify the sender. The remote host can enter any value for these commands.

Notes on HELO, Sender and Client

  • HELO/EHLO is what the sending machine *tells* your machine it is. It is easily spoofed and frequently mis-configured. Thus it may have no basis in reality.
  • Sender is the envelope-sender address (SMTP "MAIL FROM"), not the client machine's IP address or host name, or the "From:" field in the headers. (Though envelope-sender may well match "From:" in the headers.)
  • Client is the sending machine's IP address - and possibly host name (if there is one).

How to choose the optimal SMTPD Restriction Level ?

While it can be a good idea to restrict / reject specific types of messages as early as possible (a helo based restriction in the smtpd_helo_restrictions section), by placing all of the restrictions into the smtpd_recipient_restrictions, you will be able to accumulate as much information about the attempted spam as possible, as well as order all of the restrictions to better allow you to prevent spam - therefore we suggest to leave the client, helo and sender rstriction level empty.

If you were to reject at smtpd_client_restrictions, then you would not be able to determine the helo, sender, and recipient information, which could help improve the filters.

smtpd_client_restrictions =
smtpd_helo_restrictions =
smtpd_sender_restrictions =

SMTPD Client Restrictions

SMTPD client restrictions will put restrictions on what systems will be able to send mail through your server based on the client IP and host information (name). As restrictions are looked at in order, you will typically want to look at filters or restrictions that are based on local information first, in order to limit the external communications that will be initiated for each message.

Content of main.cf

smtpd_client_restrictions =
  check_client_access hash:/etc/postfix/maps/access_client,

Content of access_client  REJECT

Compile access_client into access_client.db

postmap hash:access

Test the Client Restriction

telnet rabbit 25
Trying rabbit...
Connected to rabbit.
Escape character is '^]'.
220 rabbit.akadia.com ESMTP Postfix
HELO rabbit
250 rabbit.akadia.com
MAIL FROM: <martin.zahn@akadia.ch>
250 Ok
RCPT TO: <martin.zahn@akadia.ch>
554 <dclient80-218-40-251.hispeed.ch[]>:
    Client host rejected: Access denied

SMTPD HELO Restrictions

First, you will want to enforce the requirement for a helo to be sent for each message. Without a helo, you will not be able to perform any helo checks. You can do this by adding the following line to main.cf:

smtpd_helo_required = yes

SMTPD helo restrictions will put restrictions on what systems will be able to send mail through your server based on the helo identification string.

SMTPD SENDER Restrictions

SMTPD sender restrictions will put restrictions on what addresses will be able to send mail through your server based on the sender email address (MAIL FROM:)


SMTPD recipient restrictions will put restrictions on what messages will be accepted into your server based on the recipient email address (RCPT TO:)

Note that all of the restrictions are in the recipient section because we like to have as much information as possible before rejecting an email. If you were to reject at smtpd_client_restrictions, then you would not be able to determine the helo, sender, and recipient information, which could help improve the filters.

smtpd_recipient_restrictions =
    check_client_access hash:/etc/postfix/maps/access_client,
    check_helo_access hash:/etc/postfix/maps/access_helo,
    check_sender_access hash:/etc/postfix/maps/access_sender,
    check_recipient_access hash:/etc/postfix/maps/access_recipient,
    reject_rhsbl_client blackhole.securitysage.com,
    reject_rhsbl_sender blackhole.securitysage.com,
    reject_rbl_client relays.ordb.org,
    reject_rbl_client blackholes.easynet.nl,
    reject_rbl_client cbl.abuseat.org,
    reject_rbl_client proxies.blackholes.wirehub.net,
    reject_rbl_client bl.spamcop.net,
    reject_rbl_client sbl.spamhaus.org,
    reject_rbl_client opm.blitzed.org,
    reject_rbl_client dnsbl.njabl.org,
    reject_rbl_client list.dsbl.org,
    reject_rbl_client multihop.dsbl.org,

By placing the RBL checks at the end, we are making sure that an external DNS check will only occur if nothing else will reject the spam message.

The trailing "permit" isn't necessary, strictly speaking, because there's an earlier "permit_mynetworks.". We just put it there because  it makes clear that whatever passes the earlier "check" and "reject" tests will be permitted.

All of the anti-UCE checks are under smtpd_recipient_restrictions, instead of having a separate smtpd_client_restrictions. This is because, unless you have set smtpd_delay_reject = no (default is "yes"), no rejecting takes place until after RCPT TO anyway. It's easier, cleaner and more predictable when all of the anti-UCE stuff is under recipient restrictions.

Getting Outside Help

RBLs (Real-time, IP Based Blacklist filtration) are most often available via DNS, and will contain a list of IP addresses that are commonly used by spammers, open relays, systems that are nonconformant to RFC, or whatever criteria the people running them choose to use.

The first thing to consider when the desire to implement an RBL hits you is who is running the filter. By using an RBL, you are intrinsically trusting the owner/operator/admin of the RBL not to list hosts that are valid mail servers with whom you would want to communicate, and to remove hosts from their lists who correct their problems in a timely manner.

Each mail administrator has to make his/her own choice which RBLs are most appropriate to their system. There are hundreds of different RBLs, and the choice of which ones to implement can be difficult.

An RHSBL (Real-time, Domain Based Blacklist filtration) like an RBL, is usually available via DNS, but contains a list of domain names (as opposed to IP addresses) that can be checked against the client domain of an email, as well as the domain portion (after the @) of the sender and recipient addresses. RHSBLs are so-called because they are primarily meant to check the "right-hand side" of sender addresses.

Header and Body Checks

Additional to the above checks you may want to scan the Header and/or Body of the Message for UCE Texts. Note that you cannot whitelist a sender or client in an access list to bypass header or body checks. Header and body checks take place whether you explicitly "OK" a client or sender, in access lists, or not.

Header Checks

The first thing that needs to be done is to enable header checks in the Postfix main.cf configuration file. This will tell postfix where to look for the header checks file.

To do this, add the following lines to main.cf:

header_checks = regexp:/etc/postfix/maps/header_checks
mime_header_checks = regexp:/etc/postfix/maps/mime_header_checks

The format for each line in the header_checks file is as follows:

/^HEADER: .*content_to_act_on/ ACTION

The HEADER listed can be any header available in an email. The Subject header is the most popular to reject on for key words or phrases in spam filtering, but others can be very useful as well.


/^Subject: .*Make Money Fast!/ REJECT

Mime Header Checks

In the mime_header_checks file, you will place a restriction for any file extentsons that you do not want to have passing through your system. For example:

/name=[^>]*\.(bat|com|exe|dll)/ REJECT

This will reject any messages that have attachments whose files end in .bat, .com, .exe or .dll.

Body Checks

The first thing that needs to be done is to enable body checks in the Postfix main.cf configuration file. This will tell postfix where to look for the body checks file.

To do this, add the following line to the file:

body_checks = regexp:/etc/postfix/maps/body_checks

The format for each line in the body_checks file is as follows:

/content_to_act_on/ ACTION

More Information about Fighting SPAM with Postfix