Table of Contents
- Introduction
- Content filtering, the basic idea
- Configuring Amavisd-new
- Configuring Postfix
- Configuring ClamAV
- Testing Amavisd-new
- Monitoring and maintainance of Amavisd-new
- Downloads
- References
- Document history
Introduction ⇑
This document explains how to filter your incoming email for both spam and virusses using Postfix, Amavisd-new and SpamAssassin. As the Internet gets more common and common to everyone each day, so is the amount of UBE. Massive amounts of spam and virusses are sent to many people (including yours truly) each day. On a “good” day, I receive approximately 50 to 100 spam-messages and between 7 to 30 virusses in my mailbox. Since I do not care about enlarging my willy, or massive amounts of tranquilizers, or a college degree, or willing to open any attachment containing “important documents”, I want to get rid of this junk, now!
Goals of this document ⇑
The purpose of this document is to explain how to implement virus- and UBE-filtering, using Postfix as MTA.
The goals of the used approach are:
- Simplicity: we want to keep the impact for the current mail transfer agent(s) as low as possible;
- Versatility: since there are many spam and virus scanners, we would like to switch when necessary. In addition, we would like to adapt the behaviour of our content-filter.
Prerequisites ⇑
This document assumes you have got a working Postfix configuration, for example as described by the “Dovecot, Postfix with PAM authentication” how to. The machine used for the described setup is running Debian Linux unstable/testing with the following software installed (Debian packages are enclosed in parenthesises):
- Amavisd-new v20030616p10
- (
amavisd-new)
- (
- ClamAV v0.80
- (
clamav,clamav-base,clamav-daemon)
- (
- Postfix v2.1.1
- (
postfix)
- (
- SpamAssassin v3.0.1
- (
spamassassin,spamc)
- (
- Razor v2.610
- (
razor)
- (
In addition, I've written some report scripts in Perl for Amavis. These scripts are mandatory and can be found in the download section.
Content filtering, the basic idea ⇑
Before going into the specific details of implementing content filtering in Postfix, we need to get the basic idea behind the concept of content filtering clear. This will help us to actually understand what we're doing and enables us to debug our setup more easily (see also figure 1):

- We set up the UBE-filter to act as a daemon listening on a free port;
- We tell our MTA that it should push every incoming mail through the UBE-filter. This MTA will be our public/default interface to the outside. Any incoming e-mails will therefore automatically be scanned by our UBE-filter;
- The UBE-filter examines the content of the incoming e-mails and determines whether it is dealing with spam or legitimate e-mails. The result is reported back to the first MTA instance, which, in its turn, reports this status back to the sender;
- Legitimate e-mails are forwarded by the UBE-filter to a second instance of our MTA that listens on its own private port. This second instance will take care of the “actual” delivery of the e-mails.
If you replace in the above scenario both MTA-instances with Postfix, and the UBE-filter with a combination of Amavis and ClamAV, you've got the configuration as we tend to implement in this how to.
The central part in our UBE-filter is Amavisd-new. This small daemon, written in Perl, acts as a bridge between the two Postfix instances and scans every incoming message for spam and/or virusses. Reasons for choosing Amavisd-new, is that it integrates nicely with SpamAssassing and has support for various virus-scanners.
Configuring Amavisd-new ⇑
Amavisd-new is configured by a single Perl-module, /etc/amavis/amavisd.conf,
which provides a plethora of options. The configuration file provided by Debian
has set most of the options to feasible defaults, but some need our attention.
The most important ones are:
$mydomain, which provides a default domain setting used by many other options as default. Note that this does not imply that you cannot set up a UBE-filter for many different domains. This is done by another setting,@local_domains_acl;$forward_methodand$notify_method, to set up the specific MTA-instances;@bypass_virus_checks_acland@bypass_spam_checks_acl, which should be commented to enable the checks for both spam and virusses;$inet_socket_port,$inet_socket_bindand@inet_aclto set the address, and port Amavisd-new listens on as well as the hosts that are allowed to connect to Amavisd-new;$final_virus_destiny,$final_banned_destiny,$final_spam_destinyand$final_bad_header_destiny, to determine the final destination of any found UBE.$sa_local_tests_onlyand$sa_auto_whitelistto set some of the options of- The local tests of SpamAssassin do not require Internet
- SpamAssassin can also automatically place any non-UBE sender on so-called `whitelists'.
A snippet with some of the described settings we're using for L'Xtreme.nl:
$mydomain = 'lxtreme.nl'; $forward_method = 'smtp:127.0.0.1:10025'; $notify_method = $forward_method; # @bypass_spam_checks_acl = qw( . ); $final_virus_destiny = D_PASS; $final_banned_destiny = D_PASS; $final_spam_destiny = D_PASS; $sa_local_tests_only = 0; $sa_auto_whitelist = 1;
Note that we pass all found UBE. This is because we're interested in what sort of UBE we're receiving, and allows us to learn the Bayesian filter of SpamAssassin with the results (perhaps after we've checked them).
After you've made all necessary changes to the configuration of Amavisd-new, you need to restart it:
/etc/init.d/amavis restart
Unless you've changed it, you should see a bunch of messages coming from
Amavisd-new in /var/log/mail.log. You should check that it is able to use the
Mail::SpamAssassin module and has at least one virus scanner found.
Configuring Postfix ⇑
As mentioned, we need to set up a second instance of Postfix. Furthermore, the first instance has to be set up to push everything to our Amavisd-new daemon.
Setting up the connection from Postfix (the first instance) to Amavisd-new and
from Amavisd-new to the second instance of Postfix is done in
/etc/postfix/master.cf. Append the following snippet:
# Amavisd-new integration # Make sure e-mails are *not* modified before entering Amavisd... pre-cleanup unix n - - - 0 cleanup -o virtual_alias_maps= -o canonical_maps= -o sender_canonical_maps= -o recipient_canonical_maps= -o masquerade_domains= # 1st instance of MTA => Amavisd-new smtp-amavis unix - - - - 2 lmtp -o smtp_data_done_timeout=1200 -o lmtp_send_xforward_command=yes -o disable_dns_lookups=yes
# 2nd instance of MTA 127.0.0.1:10025 inet 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=127.0.0.0/8 -o strict_rfc821_envelopes=yes -o smtpd_error_sleep_time=0 -o smtpd_soft_error_limit=1001 -o smtpd_hard_error_limit=1000 -o receive_override_options=no_header_body_checks
Furthermore, we need to modify both the smtp and pickup services to use
our “pre-cleanup” service. We need this service to assure that nothing of the
e-mail is modified (like address rewriting, filter, etc.) by any other Postfix
service. Modify the existing smtp and pickup services as follows:
smtp inet n - n - - smtpd -o cleanup_service_name=pre-cleanup pickup fifo n - n 60 1 pickup -o cleanup_service_name=pre-cleanup
The first instance of Postfix needs to push every incoming e-mail to our
smtp-amavis service. To do so, we need to add the following snippet to
/etc/postfix/main.cf:
# The connection to our UBE filter content_filter = smtp-amavis:[127.0.0.1]:10024
Postfix is now completely configured. Restart it to make the settings final:
/etc/init.d/postfix restart
Again, check your log-files (e.g. /var/log/mail.log) to make sure you've
made no mistakes and everything is up and running.
Configuring ClamAV ⇑
If you installed ClamAV from one of Debians package repositories, you do not need to configure ClamAV, as it is done automatically for you during the installation.
For security reasons, Debian installs both ClamAV as well as Amavisd-new under
their own users and groups (clamav and amavis). In order to make ClamAV to
cooperate with Amavisd-new, we need to add the clamav user as a member of the
amavis group:
[localhost:~]$ adduser clamav amavis
This allows ClamAV to access the files placed under (potential) quarantine by
Amavisd. You can try to do without it, but you will see various messsages in
/var/log/mail.log like:
Clam Antivirus-clamd FAILED - unknown status: \ /var/lib/amavis/amavis-20041206T23024 1-08038/parts: Access denied. ERROR
Testing Amavisd-new ⇑
TODO... Eicar pattern, checking log-files & quarantine...
Monitoring and maintainance of Amavisd-new ⇑
TODO... Bayesian learning script, Amavisd-new reporting script...
Downloads ⇑
TODO...
References ⇑
Document history ⇑
- v0.9 - (06-12-2004), Checked software versions, wrote most of the configuration sections;
- v0.8.1 - (02-09-2004), Minor textual updates;
- v0.8 - (20-06-2004), Added the picture showing the filtering paths;
- v0.7 - (11-06-2004), Initial version.