How To Fight Spam Using Your Postfix Configuration

Want to support HowtoForge? Become a subscriber!
 
Submitted by todgerme (Contact Author) (Forums) on Sun, 2006-08-20 19:19. :: Anti-Spam/Virus | Postfix

How To Fight Spam Using Your Postfix Configuration 

In this guide you will learn how to tweak the default Falko mail guide for  Postfix (+Auth SMTP + Quota), http://www.howtoforge.com/virtual_postfix_mysql_quota_courier, setup to better combat SPAM and allow a little bit of backward compatibilty of the older Qmail systems.


So lets get started...

The HowtoForge guide is great for everything however if you have a very busy mail server running Spam Assasin on 1000s of message per minute is a CPU killer.  The best answer is to stop the mail before it hits Spam Assasin with a range of RBL (Realtime Blacklists) and RHBL (Same but different), Greylistings and Helo Checks.

 First of all we want to change the existing smtpd restrictions and add a whole host of new checks to help reduce the amount of mail the system accepts in /etc/postfix/main.cf

### Checks to remove badly formed email
smtpd_helo_required     = yes
strict_rfc821_envelopes = yes
disable_vrfy_command = yes

unknown_address_reject_code  = 554

unknown_hostname_reject_code = 554

unknown_client_reject_code   = 554



smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname, regexp:/etc/postfix/helo.regexp, permit





### When changing sender_checks, this file must be regenerated using postmap <file>, to generate a Berkeley DB



smtpd_recipient_restrictions =

   check_client_access hash:/etc/postfix/helo_client_exceptions

   check_sender_access    hash:/etc/postfix/sender_checks,

   reject_invalid_hostname,
### Can cause issues with Auth SMTP, so be weary!
   reject_non_fqdn_hostname,
##################################
   reject_non_fqdn_sender,

   reject_non_fqdn_recipient,

   reject_unknown_sender_domain,

   reject_unknown_recipient_domain,

   permit_mynetworks,

   reject_unauth_destination,



# Add RBL exceptions here, when changing rbl_client_exceptions, this
file must be regenerated using postmap <file>, to generate a
Berkeley DB

          check_client_access hash:/etc/postfix/rbl_client_exceptions,

          reject_rbl_client cbl.abuseat.org,

          reject_rbl_client sbl-xbl.spamhaus.org,

          reject_rbl_client bl.spamcop.net,

          reject_rhsbl_sender    dsn.rfc-ignorant.org,



         check_policy_service inet:127.0.0.1:60000

         permit 


Now to explain but first we need to create a few files:

The first file we want to create is /etc/postfix/helo.regexp and this will contain:

/^subdomain\.host\.com$/           550 Don't use my own hostname
/^xxx\.yyy\.zzz\.xxx$/             550 Don't use my own IP address
/^\[xxx\.yyy\.zzz\.xxx\]$/         550 Don't use my own IP address
/^[0-9.]+$/                        550 Your software is not RFC 2821 compliant
/^[0-9]+(\.[0-9]+){3}$/            550 Your software is not RFC 2821 compliant

 This alone will turn away spammers trying to send the helo command and impersonating either the server receiving the mail by IP or by hostname as well as turning away some of the mail that doesn't meet RFC 2821 compliance.

 

Next up, we need to create /etc/postfix/helo_client_exceptions:


#These client IP addresses are allowed to bypass fqdn checks
# Some Comment to identify IP address below
www.xxx.yyy.zzz OK

 

This file is needed incase a badly behaved mail server can't send the correct helo and you need to allow mail to be accepted from that source.  In my experience, things like standalone devices, CCTV camera are poor at complying to standards so you might need to make an exception for this.

 Before any changes in this file become usable you need to run

postmap /etc/postfix/helo_client_exceptions

This will create a file called  /etc/postfix/helo_client_exceptions.db


Moving down, we have /etc/postfix/sender_checks which allows you to bypass the various FQDN checks and allow a particular sender through.  This is particular useful if a company runs an internal mail network such as domain.com but email runs on int.domain.com and there is no DNS setup int.domain.com, this is great for security but not great becuase external DNS doesn't know about the internal structure and therefore postfix will reject the int.domain.com.

user@domain.com      REJECT 
user@int.domian.com   OK

Once again this file once modified must have a Berkely DB file created and thus we create it using:

postmap /etc/postfix/sender_checks

 Next we have our RBL checks.  There are many websites dedicated to RBLs but to cut down the article length, simply put these lists are updated constantly and provide IPs and hostnames which spammers are using to relay mail.  Each IP that tries to send mail to your mail server will be checked against these lists (4 used above) and if the IP isn't listed in the RBLs, the mail server will accept the mail.  Ofcourse servers find themselves on these lists all the time inadvertingly or the lists take 24 hours to remove the blacklisted IP after a spam outbreak so it is always best to once again have a way of bypassing these checks.


To do so we create a file called /etc/postfix/rbl_client_exceptions:

## Some Random comment
www.xxx.yyy.zzz OK

Once again you must run postmap to generate the Berkeley DB file

postmap /etc/postfix/rbl_client_exceptions

 

The final line of the smtpd restrictions is the greylisting filter.  I won't go into any detail on this as a guide already exists on howtoforge, http://www.howtoforge.com/greylisting_postfix_postgrey but if you do not wish to use Greylisting, simply omit the line

check_policy_service inet:127.0.0.1:60000

 

The smtpd restrictions is very easy to follow, until one of the checks gives the green flag for the message to pass into the Postfix queue, most answering not sure move on unless an explicit NO is given the message will move down the list of checks.

 

QMAIL LEGACY

DJB (Dan Bernstein) developed an alternative to SMTP called QMQP.  It is said to be faster with less overheads.  So if you are replacing your old Qmail MTAs with Postfix you may need to enable support for QMQP.

We do this adding the following into /etc/postfix/main.cf

qmqpd_authorized_clients = $mynetworks 
qmqpd_error_delay = 5s
qmqpd_timeout = 300s

Realistically you can authenicate against anything but I decided to authenticate against mynetworks.  After you have added the above into main.cf you need to further modify /etc/postfix/master.cf and make sure it contains the following:

628      inet  n       -       -       -       100       qmqpd  

Now all you need to go is restart Postfix

/etc/init.d/postfix restart

 You can check your new QMQP aware Postfix by typing:

telnet localhost 628

Authentication Via IP (Ideal for Smarthost relaying in MS Exchange Servers )

Next we are going to mod the guide a little to make the setting of mynetworks a little easier than through flatfiles namely /etc/postfix/main.cf

Create the following /etc/postfix/mysql-mynetworks.cf

user = mail_admin
password = password
dbname = mail
table = allowed_hosts
select_field = 'IP'
where_field = IP
hosts = 127.0.0.1
additional_conditions = and active='yes'

You will need the following SQL at this point

CREATE TABLE `allowed_hosts` (
  `active` enum('yes','no') NOT NULL default '1',
  `IP` varchar(15) NOT NULL default '',
  `Client` varchar(128) NOT NULL default '',
  `Comments` text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;


 

Finally lets activate this by changing our mynetworks line the main.cf of Postfix to:
mynetworks = 127.0.0.0/8, proxy:mysql:/etc/postfix/mysql-mynetworks.cf  

Finally restart Postfix for changes to take effect:

chmod o= /etc/postfix/mysql-mynetworks.cf
chgrp postfix /etc/postfix/mysql-mynetworks.cf

/etc/init.d/postfix restart

 


Please do not use the comment function to ask for help! If you need help, please use our forum.
Comments will be published after administrator approval.
Submitted by henny (registered user) on Thu, 2008-01-17 02:21.

If you want more aggressive filtering and can accept the increased risk of false positives, consider some of the other less-conservative blackhole lists such as the ones run by SPEWS or the various lists of blocks of dynamic IP addresses., Like SpamFilter ISP you may also consider using the reject_unknown_hostname option mentioned in the “HELO restrictions” section, but you can expect a small, measurable increase in false positives.

The ruleset described above should be sufficient on its own to eliminate the vast majority of junk email, so your time would probably be better spent implementing and adjusting it before testing other measures.

Submitted by pgeorge (registered user) on Sun, 2008-04-06 18:31.


The tutorial is very good, but unfortunately Postfix still have some problems with latests releases. Once I tried to configure my Postfix to fight spam and in the end I got another problem, the queue was always full and never managed to empty it. Probably it was just my badluck, with a bad version. If you want some email utitlities that can help you fight spam, you can try some free Email Tools

Good luck all.

Submitted by DigitalExorcist (registered user) on Sat, 2006-12-30 21:08.

When I ran this setup, I found that it was missing quite a few things - like backscatter prevention, and bayesian support.

 I did find a good writeup on http://www.piratefish.org - I've found it worthwhile and informative - and it covers backscatter, SPF checking, anti-virus, blacklists and more - and it's a complete from the ground up walkthrough using Debian Linux.  The last update added OCR of spam images to search them for spammy words too.

Submitted by admin (registered user) on Sun, 2006-12-31 13:29.
Well, I can't find any free instructions on piratefish.org. It seems you must buy an ebook with the instructions...
Submitted by Anonymous (not registered) on Mon, 2011-01-03 17:27.
This is because the piratefish post was a cunning attempt at Spam.
Submitted by Sapheriel (registered user) on Thu, 2006-09-07 21:46.

four things:

1) you assume that $mynetworks is listed in proxy_read_maps

2) check_policy_service inet:127.0.0.1:60000

i'm not aware of running anything on that port. you never explain that option either.

3) your lookup table works with '0' and '1' for the `active` column, your configuration file looks for 'yes'

4) your lookup table has no index.

since postfix 2.2, query templates (http://www.postfix.org/MYSQL_README.html) are supported which allows would allow, for example, to convert the ip address into an integer before lookup which makes indexing easier.

Submitted by todgerme (registered user) on Sun, 2006-09-10 11:08.

1) This is a hook on guide to this article on Howtoforge, http://www.howtoforge.com/virtual_postfix_mysql_quota_courier_p2 where $mynetworks is already in the proxy_read_maps

2) Added a little meat to the bones, my bad, but it was an article written in a rush.

 

3) Fixed, once again my bad.

 

4) You don't need one, works fine without it.

 

The original howtoforge guide which this is a hook for is based on Postfix 2.1 not 2.2 where the various query templates are much different so why bring this up it makes the whole situation more confusing when people just want a handy copy/paste guide.

Submitted by youmyfriendarea... (registered user) on Thu, 2006-09-07 20:26.
>550 Your software is not RFC 2821 compliant

Ironically by doing this, you yourself are breaking an RFC, RFC793 specifically The Robustness Principle (Postel's Law):

TCP implementations will follow a general principle of robustness: be conservative in what you do, be liberal in what you accept from others.

Submitted by daesoft (registered user) on Sat, 2006-11-04 02:10.

Actually Postel's Law was refined with RFC 3117

"A subsequent RFC, RFC 3117, suggests that Postel's principle be followed only loosely, lest errors or less-than-desirable implementations should be propagated generally"  -Wikipedia

Not to mention that I doubt Postel envisioned the directions that TCP would be taken 25 years after RFC793 was written.

Submitted by todgerme (registered user) on Sun, 2006-09-10 11:13.
A recent article published said that about 90% of mail bouncing around the mail servers is junk. With this setup I found I am rejecting 88% of the mail coming in to the system. There is a lot of bad email servers out there and I doubt anyone will ever achieve the perfect balance but when dealing with spam based on that rule we shouldn't use any Antispam techniques and simply look through 2000 messages per day of which 4 are legimate. Happy mediums are so hard to find!