Tuesday, February 9, 2010

Amavisd-new ClamAv and Spamassassin on CentOS 5 Postfix

SkyHi @ Tuesday, February 09, 2010

Install Amavisd-New on CentOS 5

Amavisd-new isn’t in the CentOS repositories, so the first thing you’ll need to do is to install the Dag Wieers/RPMForge repository into your YUM configuration. First, go to the Dag Wieers/RPMForge website.


Copy and paste the appropriate command for your Red Hat-style distro to the command-line of your local computer.

To keep the RPMForge packages from overriding official CentOS packages, install the YUM Priorities plug-in.

yum install yum-priorities

Then, open the /etc/yum/pluginconf.d/priorities.conf file, and verify that the following lines are present:

enabled = 1

Open the /etc/yum.repos.d/CentOS-Base.repo file, or whatever its equivalent it for your distro, and add the line:

to the “base”, “addons”, “updates”, and “extras” sections of the file. Add the line:


to the “centosplus” and “contrib” sections of the file. (Again, the section names may vary, depending on which particular distro that you’re running.)

Open the /etc/yum.repos.d/rpmforge.repo file, and add the line:


To test your configuration, run the command,

yum check-update

When it finishes, you should see a line similar to:

818 packages excluded due to repository priority protections

ClamAV and Spamassassin Install
Before you install amavisd-new you will want to install both clamav and spamassassin as it will make it easier when you install amavisd-new.

yum install clamav clamav-milter spamassassin

You will need to edity /etc/default/spamassassin to get it to start. Change enabled to 1.

Enabled = 1

service spamassassin start

Amavisd-new Installation
This program is used to tie the scanning programs ClamAv and SpamAssassin to Postfix.
yum install amavisd-new

To start the program it is best to start it with the debug mode.

/usr/sbin/amavisd debug

Use CTRL+C to stop it.

Setup Requirements for amavisd-new
You need to add a user and group that can run the amavisd daemon.
useradd vscan
groupadd vscan

Create a directory for the program:
mkdir /var/vscan

Create these sub-directories:
mkdir /var/vscan/tmp
mkdir /var/vscan/var
mkdir /var/vscan/db
mkdir /var/vscan/home

Change ownership and permissions for the vscan.
chown -R vscan:vscan /var/vscan
chmod -R 750 /var/vscan

Edit the /etc/amavisd.conf
The key to this file is to edit the MYHOME to reflect the change to /var/vscan. Other settings are evaluated later in this document.

Each major section of the /etc/amavisd.conf file will be examined with explanations.


# @bypass_virus_checks_maps = (1); # controls running of anti-virus code
# @bypass_spam_checks_maps = (1); # controls running of anti-spam code
# $bypass_decode_parts = 1; # controls running of decoders&dearchivers

You have the option to bypass virus and spam checks. The primary reason for this choice would be to reduce the load on your server. If you want to bypass a check uncomment the line. When mail is processed by amavisd it follows this order:
1. virus scan
2. banned email
3. spam scan
4. invalid header scan

This process has a purpose in that the most dangerous option is evaluated first to the least dangerous. This process order may even cause greater load on the server but has been considered to be more important in the long run for the server.

Be sure that you set up a user and group for use with amavisd. Here the user and group that were created is vscan. Enter that information into this section of the conf file.

$daemon_user = ‘vscan’; # (no default; customary: vscan or amavis), -u
$daemon_group = ‘vscan’; # (no default; customary: vscan or amavis), -g

Enter the correct domain for your server.

$mydomain = ‘example.com’; # a convenient default for other settings

The $MYHOIME setting is critical to getting amavid to work correctly. The /var/vscan directory will need to be created and permissions set. Here is a list of the important files and directories that should be created in /var/vscan.

total 32
drwxr-xr-x 7 vscan vscan 4096 Sep 18 06:22 .
drwxr-xr-x 22 root root 4096 Jul 12 06:06 ..
-rw-r—– 1 vscan vscan 0 Sep 18 17:21 amavisd.lock
-rw-r—– 1 vscan vscan 6 Sep 18 06:22 amavisd.pid
srwxr-x— 1 vscan vscan 0 Sep 18 06:22 amavisd.sock
drwxr-xr-x 2 vscan vscan 4096 Sep 18 06:22 db
drwxr-xr-x 2 vscan vscan 4096 Sep 29 2007 home
drwx—— 2 vscan vscan 4096 Sep 19 05:51 .spamassassin
drwxr-xr-x 7 vscan vscan 4096 Sep 19 05:51 tmp
drwxr-xr-x 2 vscan vscan 4096 Sep 29 2007 var

The quarantine directory /var/virusmails must also be created and permissions set. This directory is used to house spam or infected email for further review. The mail is compressed with .gz to save space which can be an issue over time. The number of email placed in the quarantine depends on your settings if you are saving infected email and at what level is spam being placed in a quarantine, these settings are reviewed below.

# $MYHOME = ‘/var/vscan’; # a convenient default for other settings, -H
$TEMPBASE = “$MYHOME/tmp”; # working directory, needs to exist, -T
$ENV{TMPDIR} = $TEMPBASE; # environment variable TMPDIR, used by SA, etc.
$QUARANTINEDIR = ‘/var/virusmails’; # -Q

This section simply shows you the directories that are in the /var/vscan folder and what they are used for.

# $db_home = “$MYHOME/db”; # dir for bdb nanny/cache/snmp databases, -D
# $helpers_home = “$MYHOME/var”; # working directory for SpamAssassin, -S
# $lock_file = “$MYHOME/var/amavisd.lock”; # -L
# $pid_file = “$MYHOME/var/amavisd.pid”; # -P
#NOTE: create directories $MYHOME/tmp, $MYHOME/var, $MYHOME/db manually

The log level of amavisd will help you find the information that you will need. The default log level is 0. Typically on a mail server if you have just set up the system or if you need lots of information for evaluation of the mail system increase the level, level 5 is not overwhelming data. You can see that the system uses syslog. If your Linux version is not using syslog you will need to modify the setup to reflect the logging system that you are using.

$log_level = 0; # verbosity 0..5, -d
$log_recip_templ = undef; # disable by-recipient level-0 log entries
$DO_SYSLOG = 1; # log via syslogd (preferred)
$syslog_facility = ‘mail’; # Syslog facility as a string
# e.g.: mail, daemon, user, local0, … local7
$syslog_priority = ‘debug’; # Syslog base (minimal) priority as a string,
# choose from: emerg, alert, crit, err, warning, notice, info, debug

This line lists the socket port that should be listening. Note this is only on the localhost and will not allow connections from the Internet. This is the port you should have set up with Postfix.

$inet_socket_port = 10024; # listen on this local TCP port(s)

Spam levels are set within amavisd not within Spamassassin. When mail is analyzed for Spam it is evaluated by Spamassassin and given a numerical score. These scores are derived from an analysis of the entire message. Messages with a Spam score of 1.9 or less are considered safe from Spam mail and will be delivered with no restrictions. If the returned score is 2 or greater amavisd will then perform additional alterations of the email if so configured. Listed below are the default levels in which amavisd performs. The first tag will by default alert the system but pass the mail onto the user’s MUA.

The tag2 level is set at 6.2 which modifies the header with a Spam header which is determined by this setting further down in the amavisd.conf. One thought is to alter this header so that it will not be confused by any other headers set by additional programs that a user can configure. The mail is passed on to the user’s MUA which may take additional action based on this Spam header. So if mail does not arrive at the user it could be that the MUA is dumping the mail based on this header.

$sa_spam_subject_tag = ‘***SPAM*** ‘;

The kill level takes an entirely different action. Once the kill level is reached the mail is either bounced or deleted, depending on the options that you select. The DSN (delivery status notification) is set at 10, anything above that will not receive any notification. Note that there is also an option to turn off the quarantine once a message reaches a certain level, the default is 25.

$sa_tag_level_deflt = 2.0; # add spam info headers if at, or above that level
$sa_tag2_level_deflt = 6.2; # add ’spam detected’ headers at that level
$sa_kill_level_deflt = 6.9; # triggers spam evasive actions (e.g. blocks mail)
$sa_dsn_cutoff_level = 10; # spam level beyond which a DSN is not sent
$sa_crediblefrom_dsn_cutoff_level = 18; # likewise, but for a likely valid From
# $sa_quarantine_cutoff_level = 25; # spam level beyond which quarantine is off

This is the reinjection port once the mail has gone through the content filter.

# $notify_method = ’smtp:[]:10025′;
# $forward_method = ’smtp:[]:10025′; # set to undef with milter!

These are the default settings for how to handle detected virus, banned mail and Spam. You can uncomment the line and modify the outcome to D_DISCARD, D_BOUNCE or D_PASS.

# $final_virus_destiny = D_DISCARD;
# $final_banned_destiny = D_BOUNCE;
# $final_spam_destiny = D_BOUNCE;
# $final_bad_header_destiny = D_PASS;

Connecting amavisd-new to Postfix
In creating a connection with Postfix it is important to not send the main back into Postfix on port 25 creating a mail loop. So it is important to create a connection to a separate port to bring back mail that has been scanned. amavisd-new uses port 10024 by default.

You must add a content filter connection to the main.cf.

content_filter = amavisd-new:[]:10024

Testing the Connection for ESMTP Commands
$ telnet localhost 10024
Connected to localhost.localdomain (
Escape character is ‘^]’.
220 [] ESMTP amavisd-new service ready
EHLO mail.example.com
221 2.0.0 [] amavisd-new closing transmission channel
Connection closed by foreign host.

Now create a transport in the master.cf file.

# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: “man 5 master”).
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd -v
#submission inet n - n - - smtpd
# -o smtpd_enforce_tls=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
amavisd-new unix - - n - 2 smtp
-o smtp_data_done_timeout=1200s
-o disable_dns_lookups=yes

This setup uses a copy of the typical smtp transport. The name that you list must be exactly the same as the name in the content_filter setting for main.cf. The max number of concurrent processes is set to 2 to help manage resources. This should be reviewed after the server is running for awhile. The increased timeout setting will help if amavisd-new takes an extended time so that Postfix does not give up.

Configure a Reinjection Path
This is a way for amavisd-new to send mail back into the Postfix queue without creating a loop.

# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: “man 5 master”).
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd -v
#submission inet n - n - - smtpd
# -o smtpd_enforce_tls=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_client_restrictions=permit_sasl_authenticated,reject
amavisd-new unix - - n - 2 smtp
-o smtp_data_done_timeout=1200s
-o disable_dns_lookups=yes inet n - n - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
-o smtpd_restriction_classes=
-o smtpd_client_restrictions=
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=
-o strict_rfc821_envelopes=yes

The reason many of these smptd restrictions are set to = with nothing behind it is that Postfix has already run these checks and you want to make sure that they are not run again. Remember you are sending the output back to your queue so you do not want to repeat what you have already done and you do not want to create a loop.