The Perfect SpamSnake - Ubuntu 8.04 LTS - Page 4

6.3 Postfix Anti-Spam Settings

6.3.1 smtpd_helo_required

Make any connecting mail server do a proper smtp "handshake" and announce its name. Internet RFCs require this, so we do too.

postconf -e "smtpd_helo_required = yes"

I also changed the smtpd_banner to "$myhostname ESMTP $mail_name SpamSnake".

Preface: Postfix' restriction stages are as follows, and are processed in the following order:


We are only going to place entries in the last three restriction stages. Restriction stages are processed in this order regardless of the order listed in


6.3.2 smtpd_sender_restrictions

This restriction stage restricts what sender addresses this system accepts in MAIL FROM: commands (the envelope sender). We will place three tests (restrictions) in this restriction stage.


6.3.4 check_sender_access (Optional)

Here we ask Postfix to compare the envelope sender to entries in an /etc/postfix/sender_access database and act upon those entries if a match is found. We also define what action is taken there (OK, DUNNO, REJECT etc.) on a sender by sender basis. If the sender is not listed in the file, the test evaluates to DUNNO, and the next test is performed.


6.3.5 reject_non_fqdn_sender

Reject when the envelope sender mail address is not in the proper format.


6.3.6 reject_unknown_sender_domain

Reject when the envelope sender's domain part of the mail address has no DNS "A" or "MX" record at all. On occasion, you will see in a report that someone you wish to receive mail from has been rejected by this setting. One possible cause of this is when legitimate senders deliberately use bogus domain names so you will not reply to them. This is where the sender access list comes in handy. You can give them an OK there, and this test will be bypassed.

Now to implement these three restrictions:

postconf -e "smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/sender_access, reject_non_fqdn_sender, reject_unknown_sender_domain"


6.3.7 smtpd_recipient_restrictions

The access restrictions that the Postfix SMTP server applies in the context of the RCPT TO: command. This refers to the "envelope recipient" which is what the client gave in the "RCPT TO:" line during the SMTP session, not the header "To:" line. Let's look at those specific restrictions (tests) we place in smtpd_recipient_restrictions:


6.3.8 permit_mynetworks

Allows machines listed in "mynetworks" to skip the rest of the tests in this restriction stage (permit = OK). In other words, it exits this stage and is tested in the next stage (smtpd_data_restrictions). Because permit_mynetworks is placed in front of reject_unauth_destination, this means machines in $mynetworks are allowed to relay mail to any domain. Without this, we would only be able to send mail to our own domain(s). If the IP address of the sender is not listed in $mynetworks, the test evaluates to "DUNNO" and continues on to the next test (reject_unauth_destination).


6.3.9 reject_unauth_destination & reject_unknown_recipient_domain

This, along with permit_mynetworks is used for relay control. This setting, in essence, means that mail bound for any domain that we have not configured our machine to accept mail for will be rejected. In our case Postfix will use the relay_domains setting (or table) that we configured earlier to determine what domains those are. If the domain is listed in relay_domains, this test evaluates to "DUNNO" and the session is allowed to go on to the next test (if any).


6.3.10 reject_unauth_pipelining

Rejects bulk mailers that attempt to use pipelining to speed delivery, without checking if it is supported first (non-RFC, common among spammers).

Now to implement these three restrictions:

postconf -e "smtpd_recipient_restrictions = reject_non_fqdn_sender, reject_unknown_sender_domain, reject_non_fqdn_recipient, reject_unknown_recipient_domain, permit_mynetworks, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_rbl_client"


6.3.11 smtpd_data_restrictions

Optional access restrictions that the Postfix SMTP server applies in the context of the SMTP DATA: command. Like smtpd_recipient_restrictions, this is a restriction stage.


6.3.12 reject_unauth_pipelining

I repeat this setting in smtpd_data_restrictions as it is not always effective when placed in smtpd_recipient_restrictions. I include it in smtpd_recipient_restrictions as I like to place it prior to any policy servers. Note that there are only a couple of restrictions that make good use of smtpd_data_restrictions.

postconf -e "smtpd_data_restrictions = reject_unauth_pipelining"


6.3.13 /etc/postfix/sender_access

We referenced this file in smtpd_sender_restrictions. We use this file to check the sender right at the front door. In this file, we'll list certain senders/domains/IPaddress ranges for special handling. Below are bogus examples, create your own as you see fit. Please read /etc/postfix/sender_access for more information. Although you could use this file for various purposes, considering the way we have set this up in smtpd_sender_restrictions, I suggest using it to either blacklist senders, or allow certain senders to bypass the remaining tests in smtpd_sender_restrictions.

vi /etc/postfix/sender_access

#Example sender access map file
makeabuck@mlm.tld 550 No MLM thanks
allspam.tld 550 Spam is not accepted here REJECT REJECT OK OK

Since this is a hash table, you need to postmap it as usual:

postmap /etc/postfix/sender_access


6.3.14 Final Look at the Postfix Install

Review changes:

less /etc/postfix/

Check the contents of the file for errors and repair if needed. Fire up Postfix:

postfix start

Check that Postfix responds:

telnet 25

You should see:

220 [yourFQDNhere] ESMTP Postfix (Ubuntu)

Hit [enter] a few times; then type quit to exit.

If it does not reply in this manner, open another terminal window and stop Postfix:

postfix stop

Make sure you ran newaliases and all the postmap commands above. Check all the settings in and Any time you make changes to or or to data tables, most (not all) of the time, it is required that you to reload Postfix with:

postfix reload


7 Pyzor, Razor, DCC, SpamAssassin and MailScanner Configuration

7.1 Install MailScanner

Install MailScanner Dependencies by doing the following:

apt-get install libconvert-tnef-perl libdbd-sqlite3-perl libfilesys-df-perl libmailtools-perl libmime-tools-perl libmime-perl libnet-cidr-perl libsys-syslog-perl libio-stringy-perl libfile-temp-perl

Install MailScanner from the Debian .deb Source:

dpkg -i mailscanner_4.68.8-1_all.deb


7.2 Pyzor Configuration

We need to change some permissions on pyzor first:

chmod -R a+rX /usr/share/doc/pyzor /usr/bin/pyzor /usr/bin/pyzord
chmod -R a+rxX /usr/share/python-support/pyzor

Here we supply the IP address of the Pyzor server to Pyzor. This will create the server's IP address in a servers file therein. Then it will test the connection. If you are behind a firewall, open port 24441/udp in and out to your server. While you're at it also open up 6277/udp for DCC, 2703/tcp for Razor and 783/tcp for SpamAssassin:

pyzor --homedir /var/lib/MailScanner discover
pyzor ping


7.3 Razor Configuration

Create the .razor configuration:

rm /etc/razor/razor-agent.conf
mkdir /var/lib/MailScanner/.razor
razor-admin -home=/var/lib/MailScanner/.razor -create
razor-admin -home=/var/lib/MailScanner/.razor -discover
razor-admin -home=/var/lib/MailScanner/.razor -register
chown -R postfix:www-data /var/lib/MailScanner
chmod -R ug+rwx /var/lib/MailScanner

Make the following changes to /var/lib/MailScanner/.razor/razor-agent.conf:

vi /var/lib/MailScanner/.razor/razor-agent.conf

Change debuglevel = 3 to debuglevel = 0 (yes zero not "o"). This will prevent Razor from filling up your drive with debug information. Those two lines should look like this when done:

debuglevel = 0
razorhome = /var/lib/MailScanner/.razor/


7.4 DCC Setup and Configuration

Install DCC from .deb source:

dpkg -i dcc-common_1.3.42-5_i386.deb
dpkg -i dcc-server_1.3.42-5_i386.deb

We are not running a DCC server, so we don't need to waste time checking ourselves.
Once the installation is done run:

cdcc "delete"
cdcc "delete Greylist"

Test our installation with:

cdcc info

You should get 'requests ok' from the servers.

7.4.1 64-bit DCC Installation

dpkg -i dcc-common_1.3.42-5_amd64.deb
dpkg -i dcc-server_1.3.42-5_amd64.deb

cdcc "delete"
cdcc "delete Greylist"

Test our installation with:

cdcc info

You should get 'requests ok' from the servers.


8 Configuring MailScanner and ClamAV

8.1 Stop Postfix:

postfix stop

Install the packages:

apt-get install clamav clamav-daemon

Update ClamAV virus defenitions:


Once that is done, we need to make a directory for SpamAssassin in the spool and give postfix permissions to it, if you run sa-learn --force as root, bayes databese that is stored in these directories will change to root:root and spamassassin will error looking at the db. Just keep an eye on the mail.log and you'll remember to change the permissions back. Also disable the MailScanner default configs:

mkdir /var/spool/MailScanner/spamassassin

Backup your MailScanner.conf file:

cp /etc/MailScanner/MailScanner.conf /etc/MailScanner/MailScanner.conf.back

Edit MailScanner.conf:

vi /etc/MailScanner/MailScanner.conf

Change the following parameters in MailScanner.conf:

%org-name% = ORGNAME
%org-long-name% = ORGFULLNAME
%web-site% = ORGWEBSITE
Run As User = postfix
Run As Group = www-data
Incoming Queue Dir = /var/spool/postfix/hold
Outgoing Queue Dir = /var/spool/postfix/incoming
MTA = postfix
Virus Scanners = clamav
Spam Subject Text = ***SPAM***
Send Notices = no
Spam List = SBL+XBL
Required SpamAssassin Score = 6
High SpamAssassin Score = 10
Spam Actions = deliver
High Scoring Spam Actions = delete
Rebuild Bayes Every = 0
Wait During Bayes Rebuild = no
SpamAssassin User State Dir = /var/spool/MailScanner/spamassassin

The first 9 lines are basically required in order for everything to work, the rest are recommended.


8.2 header_checks & body_checks

Let's go ahead and put this in header_checks is required because it allows us to hold all incoming email in order for MailScanner to do its thing:

postconf -e "header_checks = regexp:/etc/postfix/header_checks"

Edit header_checks:

vi /etc/postfix/header_checks

Add this line to the header_checks file, without it MailScanner will not work:

/^Received:/ HOLD


8.3 Fix to Disable Permission Checks on MailScanner Directories

Edit /etc/rc2.d/S20mailscanner to look like:

check_dir /var/spool/MailScanner       ${user:-postfix} ${group:-www-data}
#check_dir /var/lib/MailScanner         ${user:-mail} ${group:-mail}
#check_dir /var/run/MailScanner         ${user:-mail} ${group:-mail}
check_dir /var/lock/subsys/MailScanner       ${user:-postfix} ${group:-www-data}

In the file /etc/default/mailscanner, make sure this parameter is at 1:

vi /etc/default/mailscanner



8.4 MailScanner Webmin Plugin (Optional)

Login to Webmin, https://localhost:10000, and install the MailScanner module for webmin found at After this is done, you'll have to enter the following into your mailscanner module to get it to work:

Full path to MailScanner program /etc/init.d/mailscanner
Full path and filename of MailScanner config file /etc/MailScanner/MailScanner.conf
Full path to the MailScanner bin directory /usr/sbin
Full path and filename for the MailScanner pid file /var/run/MailScanner/
Command to start MailScanner /etc/init.d/mailscanner start
Command to stop MailScanner /etc/init.d/mailscanner stop


8.5 You can now start the system

/etc/init.d/mailscanner start
/etc/init.d/postfix start

Check your logs for errors:

tail -f /var/log/mail.log



Share this page:

42 Comment(s)

Add comment


From: at: 2008-09-17 15:07:59

Can I implement this solution on a machine running as a firewall with 2 network interfaces? One for the Internet and one for the internal network?


From: Anonymous at: 2008-10-06 18:12:18

In theory I don't see why not, but it probably isn't a good idea.  Doing that way makes the spamsnake a bridge between the two networks that isn't protected by the firewall.  The only way to make it secure is to have the firewall accept mail on the external interface, with the appropriate firewall blocking, pass it to the spamsnake on the internal interface for processing and then forward it to a mail server for distribution.  If the spamsnake accepts mail on the external interface directly, it will bypass the firewall.

The more secure option is to have the spamsnake be a separate external machine, accept and process all mail there and only pass the legitimate mail to the internal network via the external interface of the firewall.  The other benefit of this method is it reduces the load on the firewall since all the spam, and the associated connections, has been dumped before it reaches the firewall.

From: at: 2008-05-10 13:27:38

I've been using file based Greylisting for more than an year and I would say it is faster than the DB based ones. I am using tumgreyspf.

From: at: 2008-05-13 12:35:22

When it comes to the addons, it's really your choice which one you want to use.  I've been quite lucky with the db setup so that's why I use it. 

Thanks for your recommendation though.  If I have any problems with my current setup, I would be more than happy to give your recommendation a shot.

From: at: 2008-08-05 11:00:51

Hello ! Any specific reason for using MailScanner and not AMaViS ? Just out of curiosity. Regards, Sebastian M Juergse

From: at: 2008-10-14 16:04:23

I tried this setup with Amavis but thought MailScanner was a bit faster.

From: ctrl at: 2010-01-09 09:30:03

Large a thank you for your tutorial! I have used SpamSnake for 6 months and I am magic.

This morning, SpamSnake informs me of a very high number of message containing the Virus (Exploit.PDF-9669). Information taken, it acts of a bug in Clamav which I decide to update by a “apt-get install clamav clamav-demon clamav-fresclam” then I launch “freshclam” to recover the update of the database.

However, and in a more total way, I wishes knowledge if I could, without risk for the configuration of SpamSnake, throw a “apt-get upgrade”.

Better greetings,

From: Rob at: 2010-01-21 11:42:03

I installed this. Tested it and now it is running for all our domains and it works perfect! thanks :)

From: Haas at: 2008-11-16 16:01:24

Unarj: it seems, that unarj was removed from the Debian/Ubuntu archives

From: Anonymous at: 2008-11-25 18:57:52

Any news on how to install unarj now that it is no longer in the debian or ubuntu repos? I am trying to configure a spam snake following the tutorial but unarj is no longer available. Plese help.


From: Anonymous at: 2008-11-27 19:00:40

I've googled for 'linux arj options' and found that the options are the same as for 'arj'.

So I think that 'arj' already does the job of 'unarj'. If not, you can test if (as root or sudo) 'ln -s /usr/bin/arj /usr/bin/unarj' works...


From: Anonymous at: 2009-01-05 12:16:05

I downloaded the file from another mirror, saved it in my web folder and ointed linux to it ]

worked great

but can not get web admin working


From: Philip Jones at: 2009-02-23 15:09:11


 I found that if you change unarg... for arg_3.10.22-2_i386.deb at the end of the wget command it works fine, to check which files are available open the link (without the wget or filename) in your browser.

Great How-To


From: Gagandeep at: 2009-03-21 20:20:56

I downloaded it from here

From: Hurup at: 2008-11-11 18:04:26


After changed the Bind folder directories i get following error:

Nov 11 18:56:32 localservername named[20763]: starting BIND 9.4.2-P2 -u bind -t /var/lib/named
Nov 11 18:56:32 localservername named[20763]: found 1 CPU, using 1 worker thread
Nov 11 18:56:32 localservername named[20763]: loading configuration from '/etc/bind/named.conf'
Nov 11 18:56:32 localservername named[20763]: none:0: open: /etc/bind/named.conf: permission denied
Nov 11 18:56:32 localservername named[20763]: loading configuration: permission denied
Nov 11 18:56:32 localservername named[20763]: exiting (due to fatal error)
Nov 11 18:56:32 localservername kernel: [178236.619792] audit(1226426192.264:7): type=1503 operation="inode_permission" requested_mask="r::" denied_mask="r::" name="/var/lib/named/etc/bind/named.conf" pid=20764 profile="/usr/sbin/named" namespace="default"

The permissions are :

 # ls -la /etc/bind/
total 52
drwxr-sr-x 2 bind bind 4096 2008-11-11 18:38 .
drwxr-xr-x 3 root root 4096 2008-11-11 18:41 ..
-rw-r--r-- 1 bind bind  237 2008-10-10 18:53 db.0
-rw-r--r-- 1 bind bind  271 2008-10-10 18:53 db.127
-rw-r--r-- 1 bind bind  237 2008-10-10 18:53 db.255
-rw-r--r-- 1 bind bind  353 2008-10-10 18:53 db.empty
-rw-r--r-- 1 bind bind  270 2008-10-10 18:53 db.local
-rw-r--r-- 1 bind bind 2878 2008-10-10 18:53 db.root
-rw-r--r-- 1 bind bind  907 2008-10-10 18:53 named.conf
-rw-r--r-- 1 bind bind  165 2008-10-10 18:53 named.conf.local
-rw-r--r-- 1 bind bind  695 2008-10-10 18:53 named.conf.options
-rw-r----- 1 bind bind   77 2008-11-11 18:38 rndc.key
-rw-r--r-- 1 bind bind 1317 2008-10-10 18:53 zones.rfc1918


From: at: 2008-12-02 13:25:01


Please make sure apparmor is disabled.


From: Steve at: 2008-12-30 22:57:21

As an FYI, it would appear that installing bind9 re-enables apparmour

From: at: 2009-06-03 14:44:16



You have to redo the Remove Apparmour steps from Page 2 again following the bind9 install

From: José Manuel Avalos García at: 2009-12-02 07:17:31

 one to keep active Apparmour, add to /etc/apparmor.d/usr.sbin.named the next lines

  #CHROOT /var/lib/named/
  /var/lib/named/dev/random r,
  /var/lib/named/etc/bind/** r,
  /var/lib/named/var/cache/bind/** rw,
  /var/lib/named/var/cache/bind/ rw,
  /var/lib/named/var/run/bind/run/ w,
  /var/lib/named/var/run/bind/named.options r,
( before the last "}" ) 
and run
 /etc/init.d/apparmor restart
 /etc/init.d/bind9 start

From: Jamie Strandboge at: 2009-12-28 16:09:04

There is no reason to chroot bind9 if using AppArmor. Chrooting bind is the traditional way to limit file access for bind9, and it works fine, but does not confine bind9 as much as an AppArmor profile can. AppArmor also limits file access, networking and capabilities for bind9, and the Ubuntu developers have created a default bind9 installation that does not require any additional configuration for securing bind9. This way all users of bind9 can benefit from it.

Additionally, this tutorial recommends to disable all of AppArmor. Unless you have a very specific need to do so, this is not recommended. If you opt to chroot bind9 instead of use AppArmor, then please disable the profile, and leave the other profiles that are not causing problems to do their jobs. See my blog entry at for details.

From: Jake at: 2009-10-22 09:50:19

I would like to know the issues if any to leave bind9 alone and let apparmor deal with the security? I see that the author would like you to chroot bind9 but I wonder if it is out of habit or necessity.

From: Mastech Miami at: 2011-09-02 14:09:49

It is a problem installing "pecl install imagick". it returns

Cannot find config.m4.
Make sure that you run '/Applications/MAMP/bin/php5/bin/phpize' in the top level source directory of the module

to work around:

cd /usr


 php go-pear.phar

 pecl install imagick



From: at: 2008-05-17 02:23:27

For those in the 64-bit world:

dpkg -i dcc-common_1.3.42-5_amd64.deb
dpkg -i dcc-server_1.3.42-5_amd64.deb

From: Patrick at: 2009-03-26 10:30:37

Use mailscanner_4.74.16-1_all.deb in stead.

From: Klaus Hochlehnert at: 2008-12-28 22:23:36

Hi, couldn't get mailscanner from the mentioned location.
But I found it in the Intrepid archive:


Regards, Klaus

From: PieterJ at: 2008-09-25 14:04:57

You have to change this line in db_clean also:





From: Eric at: 2008-12-18 02:06:23

9.24.2 Filename and Filetype Release:
allow   .*      -       -

allow   .*      -       -

Remember to separate fields with tab characters

From: Mircsicz at: 2008-10-27 14:02:12

9.11 Fix to allow MailWatch to work with Postfix Inbound/Outbound Queue

the URL changed to:

From: Eric at: 2008-12-18 02:08:14

9.24.2 Filename and Filetype Release: /etc/MailScanner


allow .* - -


allow .* - -

Remember to separate fields with tab characters

From: Anonymous at: 2009-06-11 12:59:08 is to be found within


hope that I'm not the only one that dident find this file :P

From: Steve Baker at: 2009-10-14 07:24:59


Newer versions of Ubuntu enable an apparmor profile on /usr/sbin/clamd, this prohibits clam from seeing the Mailscanner spool folders and thus it cannot scan for viruses.  This issue is shown in the clamav logs as a 'permission denied' or 'access denied' error or similar, even if the permissions/groups on those folders is set correctly.

You need to edit the file /etc/apparmor.d/usr.sbin.clamd and add the following line:

 /var/spool/MailScanner/incoming/** r,


From: Walmiro Muzzi at: 2009-08-27 12:04:51

I'm having this warning when run spamassassin -D -p /etc/MailScanner/spam.assassin.prefs.conf --lint:

[6154] warn: lint: 2 issues detected, please rerun with debug enabled for more information

Please, how I fix it?


Thanks in advance.

From: Patrick at: 2009-03-29 00:20:31

Could you be a bit more specific on which howto this would be?

From: linch_y at: 2009-02-13 21:13:42

If someone finds it useful:

Instead of importing the users you may use live lookups against the AD. There is a howto in the howtoforge forums.

Good luck. 

From: hattmardy at: 2009-01-31 20:15:30

nevermind, i just realized i had simply forgot to uncomment out

open VALID, ">$VALID" or die "CANNOT OPEN $VALID $!";

and this was printing to this file ... doh!

From: hattmardy at: 2009-01-31 20:10:21

I had to modify the print VALID $mail line from:

print VALID $mail." OK\n";

 print "VALID = ", $mail ," OK!\n";

for some reason, the perl print string wasn't formed properly by default.

I was getting lots of  error messages:

print() on unopened filehandle VALID at /usr/bin/ line 86, <DATA> line 656

From: Anonymous at: 2009-08-21 16:44:13

I get this error email from cronjob : need help to resolve this issue.

 /opt/MailScanner/bin/MailScanner .... 

Starting MailScanner...Can't locate Filesys/ in @INC (@INC contains: /opt/MailScanner/lib /etc/perl /usr/local/share/perl/5.8.8 /usr/lib/perl5 /usr/share/perl5 /usr/share/perl/5.8 /usr/local/lib/site_perl /opt/MailScanner/lib /usr/local/lib/perl/5.8.8 /usr/lib/perl/5.8) at /opt/MailScanner/bin/MailScanner line 91.
BEGIN failed--compilation aborted at /opt/MailScanner/bin/MailScanner line 91.

 Please help ...

From: Patrick at: 2009-03-30 08:36:35

So, 13.1 should be apt-get install curl rsync

From: Patrick at: 2009-03-30 08:18:31
From: Richard at: 2009-05-26 20:17:34

Fix not necessary with Jaunty.

From: Tom at: 2009-07-01 18:24:16

The cron job set up to clean up the greylist table every night is too squeaky clean for me. It has the effect of wiping out the entire table every night. the greylist table uses column 'n' as a counter of how many times the entry has been hit. On the initial attempt this value is set to 1, when the remote MTA resends a valid email this value is set to 2 and incremented from there. This means that the minimum 'n' value for a valid entry is 2.

 I prefer to have my valid entries kept indefinitely, that way there isn't an ongoing delay for communication between valid business contacts. I set my crontab entry like so:

 55 23 * * * /usr/bin/mysql -ugld_user -pgld_pass -e 'USE gld_db; DELETE FROM greylist WHERE n < 2;' &> /dev/null

From: at: 2009-11-13 16:41:44

I will be sure to update the guide reflecting your correction. T