This document describes how to lock down the Postfix mail server configuration, to include spam filtering. There are many methods available, ours uses only two. First we tweak Postfix to block crud and secondly filter through SpamAssassin.

How does it work?

Firstly Postfix will be "hardened" to prevent poorly written software from sending with it. Postfix will also be configured to filter connections, who says HELO, even recipient and sender domains by using RBL and RHSBL restrictions.

SpamAssassin is used to process messages that pass this first test and then delivers them to the maildir. SpamAssassin is not designed to listen directly to the "untrusted network", as in the internet, Postfix however is. Postfix will still be the first line of defense, SpamAssassin will receive messages from Postfix for further processing.

Postfix Spam Filter Configuration

Below is cut from our main.cf file, each configuration option is commented. Changes are made for more restrictions on all aspects of Postfix. They are listed in increasing order of complication, so start with the changes at the top and work your way down with only a few changes at a time. Test your configuration after each set of changes, at least a fire-test if not more. The amount of connections, use of strict RFC compliance, blacklists and other restrictions will serve to harden Postfix. The links at the end provide more information about blacklists, an important feature.

The first part is to change basic operations for a more strict environment. Do these first then test your environment.

# Fundamental checking
allow_percent_hack = no
allow_untrusted_routing = no
disable_vrfy_command = yes
parent_domain_matches_subdomains =
strict_rfc821_envelopes = yes
smtpd_delay_reject = yes
smtpd_helo_required = yes

Connection Restrictions

Sometimes your machine is pretty open, like an inbound gateway or other utility mailhub. And, because it's open, there are some who will abuse that. You can use firewall rules to block IPs, that's quite easy but you can also block them in Postfix.

I like to use the smtpd_client_restrictions with a hash table of Bad IPs.

smtpd_client_restrictions = permit_mynetworks
	reject_unknown_client_hostname
	reject_unknown_reverse_client_hostname
	check_client_access hash:/etc/postfix/main.cf.d/check_client_access
	permit

Now the table file check_client_access can be used to specify IPs, or hosts, or patterns to reject. This annotated example shows some of each.

# By Hostname Patterns (depends on parent_domain_matches_subdomains
.bad.tld REJECT

# IP
8.8.8.8 REJECT

# IPv4 CDIR
192.168.0.0/16 REJECT

# IPv6 too
2600::2600 REJECT

Restricting at HELO

This blocks connects at the next stage, when they say HELO, which we require. Additional checks can be made here, everyone who's doing it right has proper hostname and reverse DNS configured for their hosts. We reject mis-configured or silly hostnames here.

smtpd_helo_restrictions = permit_mynetworks
	reject_invalid_helo_hostname
	reject_non_fqdn_helo_hostname
	reject_unknown_helo_hostname
	permit

Restricting at MAIL FROM

smtpd_sender_restrictions = permit_mynetworks
  permit_sasl_authenticated
  reject_non_fqdn_sender
  reject_unknown_sender_domain
  permit

Restricting at RCPT TO

smtpd_relay_restrictions = 

smtpd_recipient_restrictions =  permit_mynetworks
  permit_sasl_authenticated
  reject_unlisted_recipient
  reject_unauth_destination
  reject_unauth_pipelining
  reject_non_fqdn_recipient
  reject_unknown_recipient_domain
  check_policy_service unix:/var/spool/postfix/private/postgrey
  permit

These changes restrict what hostnames we accept in the required HELO, test changes after this stage. Put the permit authenticated users, reject silly hosts, then allow. Note that some people will not be able to send with rules like reject_non_fqdn_hostname because they are using bad clients or mis-configured servers.

smtpd_helo_restrictions = permit_mynetworks
  permit_sasl_authenticated
  reject_non_fqdn_hostname
  reject_invalid_hostname
  reject_unknown_hostname
  permit

This prevents unauthorized mail, like relay, from happening but allows our trusted connections to relay.

smtpd_recipient_restrictions = permit_mynetworks
  permit_sasl_authenticated
  reject_non_fqdn_recipient
  reject_unauth_destination
  permit

This filter is applied on the senders domain name, trust who we trust first, filter bad stuffs, allow.

# harden who can send inbound or relay mail
smtpd_sender_restrictions = permit_mynetworks
  permit_sasl_authenticated
  reject_non_fqdn_sender
  reject_unknown_sender_domain
  reject_unauth_pipelining
  reject_rhsbl_sender blackhole.securitysage.com
  reject_rhsbl_sender rhsbl.ahbl.org
  permit

If a log was kept of previous junk emails before the configuration then compare those with logs with this configuration in place. In our experience this catches a log of junk, both by restricting poorly written spam software and using the blacklists. Additional blacklists can be used, see the links at the bottom.

SpamAssassin Configuration

If the above configuration is not tight enough SpamAssassin can be used to further filter spam messages out. We however, currently have no more information, it will be here soon.

See Also

Change Log