6. Content filtering

Now we have a fully-functional mail server, able to send and receive email and providing remote access to users' mailboxes. However, if we don't want our server to become an immune carrier of computer viruses or to be drowned under a sea of spam, we need to install all the necessary content-filtering tools.

Though Postfix natively supports multiple content inspection mechanisms, the documentation itself encourages the use of external filters and standard protocols because this allows you to choose the best MTA and the best content inspection software for your purpose.

The most efficient way to chain multiple content filters in Postfix is to use the Milter (mail filter) protocol, originally developed by sendmail and later implemented in Postfix too; the Milter protocol is used by applications that run outside the MTA to inspect SMTP events (CONNECT, DISCONNECT), SMTP commands (HELO, MAIL FROM, etc.) as well as mail content (headers and body) [...] before mail is queued [MILTER].

The mail filters we will be using are: milter-spamd, a Milter interface to SpamAssassin's spamd(1) daemon and clamav-milter, which checks emails for viruses using the ClamAV engine.

6.1 SpamAssassin

SpamAssassin is a mature, widely-deployed open source project that serves as a mail filter to identify Spam. SpamAssassin uses a variety of mechanisms including header and text analysis, Bayesian filtering, DNS blocklists, and collaborative filtering databases.

There are quite a few packages we need to install:

After the packages installation, you will find the main SpamAssassin configuration file (local.cf) in the fresh new /etc/mail/spamassassin directory. The configuration phase can be very complex and goes beyond the scope of this document; anyway, you can find all the details in the man page (Mail::SpamAssassin::Conf).

Just like Postfix, SpamAssassin has lots of configuration options, although, in most cases, default values can be preserved and only a few parameters need to be overridden:

/etc/mail/spamassassin/local.cf
rewrite_header	Subject	***** SPAM *****
report_safe	1
lock_method	flock
required_score	8.0

Now we can start the spamd(1) daemon and Milter:

# /usr/local/bin/spamd -d -u _spamdaemon -P
# install -o _postfix -g _postfix -d /var/spool/postfix/var/run/milter-spamd
# /usr/local/libexec/milter-spamd -p /var/spool/postfix/var/run/milter-spamd/spamd.sock -u _postfix

add the spamd(1) socket to the list of Postfix Milter applications:

/etc/postfix/main.cf
smtpd_milters = unix:/var/run/milter-spamd/spamd.sock

and reload Postfix configuration:

# postfix reload
postfix/postfix-script: refreshing the Postfix mail system

And don't forget to enable the spamd(1) daemon and Milter on boot:

/etc/rc.conf.local
[ ... ]
spamassassin_flags=""
milter_spamd_flags="-p /var/spool/postfix/var/run/milter-spamd/spamd.sock -u _postfix"
pkg_scripts="mysqld
             spamassassin milter_spamd
             postfix
             courier_authdaemond
             courier_imap courier_imap_ssl
             courier_pop3 courier_pop3_ssl"

You can test that the spam filter is working correctly by sending Postfix an email containing the GTUBE (Generic Test for Unsolicited Bulk Email).

6.2 ClamAV

ClamAV is an an open source (GPL) antivirus engine designed for detecting Trojans, viruses, malware and other malicious threats and is the de facto standard for mail gateway scanning. All the antivirus tasks are handled by three processes:

freshclam
which automatically updates the virus definitions, by connecting to one of the ClamAV mirrors; its configuration file is /etc/freshclam.conf;
clamd
a flexible and scalable multi-threaded antivirus daemon; its configuration file is /etc/clamd.conf;
clamscan
a command line antivirus scanner.

Required packages are:

The freshclam.conf configuration file requires only a few parameters:

/etc/freshclam.conf
# Comment or remove the line below.
#Example
DatabaseDirectory	/var/db/clamav
DatabaseOwner		_clamav
DNSDatabaseInfo		current.cvd.clamav.net
DatabaseMirror		db.it.clamav.net
DatabaseMirror		database.clamav.net
MaxAttempts		3
checks			24

Now we can update the virus definition database by running the freshclam command. Please make sure you have installed the latest release of ClamAV, or you'll get warning messages about reduced functionality, like the following:

# freshclam
ClamAV update process started at Tue Dec 18 00:35:25 2007
WARNING: Your ClamAV installation is OUTDATED!
WARNING: Local version: 0.90.3 Recommended version: 0.92
DON'T PANIC! Read http://www.clamav.net/support/faq
Downloading main.cvd [100%]
main.cvd updated (version: 45, sigs: 169676, f-level: 21, builder: sven)
WARNING: Your ClamAV installation is OUTDATED!
WARNING: Current functionality level = 16, recommended = 21
DON'T PANIC! Read http://www.clamav.net/support/faq
Downloading daily.cvd [100%]
daily.cvd updated (version: 5160, sigs: 8698, f-level: 21, builder: sven)
WARNING: Your ClamAV installation is OUTDATED!
WARNING: Current functionality level = 16, recommended = 21
DON'T PANIC! Read http://www.clamav.net/support/faq
Database updated (178374 signatures) from db.it.clamav.net (IP: 193.206.139.37)
#

The reduced "functionality level" means that you may not be able to use all the available virus signatures and, consequently, fail to detect the latest viruses. To automatically update the database, we simply have to schedule freshclam in crontab every hour (preferably not on the hour, just to avoid traffic peaks):

16 * * * * /usr/local/bin/freshclam >/dev/null 2>&1

Also the /etc/clamd.conf configuration file needs editing only very few parameters:

/etc/clamd.conf
# Comment or remove the line below.
#Example
DatabaseDirectory   /var/db/clamav
TCPAddr             127.0.0.1
TCPSocket           3310
User                _clamav
LogSyslog           yes
LogFacility         LOG_MAIL
[...]

and so does the Milter configuration file:

/etc/clamav-milter.conf
# Comment or remove the line below.
#Example
MilterSocket    /var/spool/postfix/var/run/milter-clamav/clamav.sock
User            _postfix
ClamdSocket     tcp:127.0.0.1:3310
LogSyslog       yes
LogFacility     LOG_MAIL
[...]

Now we can run clamd and clamav-milter:

# clamd
# install -o _postfix -g _postfix -d /var/spool/postfix/var/run/milter-clamav
# clamav-milter

add the milter-clamav socket to the list of Postfix Milter applications:

/etc/postfix/main.cf
smtpd_milters = unix:/var/run/milter-spamd/spamd.sock unix:/var/run/milter-clamav/clamav.sock

and reload Postfix configuration:

# postfix reload
postfix/postfix-script: refreshing the Postfix mail system

And of course enable the clamd and clamav-milter boot scripts:

/etc/rc.conf.local
[ ... ]
spamassassin_flags=""
milter_spamd_flags="-p /var/spool/postfix/var/run/milter-spamd/spamd.sock -u _postfix"
pkg_scripts="mysqld
             spamassassin milter_spamd
             clamd clamav_milter
             postfix
             courier_authdaemond
             courier_imap courier_imap_ssl
             courier_pop3 courier_pop3_ssl"

You can test that the antivirus filter is working correctly by sending Postfix an email containing the EICAR anti-malware test file.

Other mail filters that may be worth a look are: milter-greylist, which implements the greylist filtering method, milter-checkrcpt, which checks the validity of recipients (by asking another mail server) and milter-regex, which filters messages based on regular expressions.