Greg's Obsolete Exim Virus Filter

One of Exim's more interesting features is its built-in filtering
language. It's certainly not a general-purpose programming language,
but for simple mail-filtering tasks it's a hell of a lot easier to use
than (shudder) procmail. It's also easier on your server than spawning
a Python or Perl script, since you don't have to fork() and
you don't have to startup a big hairy interpreter. (And you don't have
to write the script and worry about all the niggling little details of
how to handle email.)

One obvious application of Exim's "system filter" feature is to inspect
every email message for viruses. The original idea is due to Nigel
Metheringham; he created a
generic Windows
executable content filter and put it on the Exim web site.
This is not an all-singing, all-dancing, industrial-strength,
super-powered email virus filter. However, it's Good Enough for
a lot of people.

I started using Nigel's filter in July 2001, and expanded/improved
it over the following months. In particular, I added the following
features:

log every virus caught to Exim's reject log

save a copy of every virus caught

detect the SirCam and MyParty worms

I also made the rejection messages a tad nicer-looking (IMHO).

I stopped using this virus filter in June/July of 2002, because
Exim 4 provides a much better solution in the form of its
local_scan() API. I wrote
elspy to let me write
local_scan() functions in Python, and that's how I
do virus detection now. So this page is largely of historical interest.

Without further ado, here is my email virus
filter for Exim. You will almost certainly need to edit it
as follows before using it on your system:

make sure the logfile directive points to
Exim's reject log on your system. The default
(/var/log/exim/reject.log) is for a Red Hat Linux system;
Debian uses /var/log/exim/rejectlog; if you have built your
own Exim, only you know where its reject log is.

make sure that every save command (there's one
for each flavour of virus detected) saves messages in a
location agreeable to you; the default
(/usr/local/var/archives/exim-reject) is a peculiarity of the
system where this filter came from, which has lots and lots of
disk space in /usr/local, but not much in /var. I prefer to
put viruses in, eg., /var/mail/virus-reject .

make sure that in every mail command (again,
there's one for each flavour of virus), the once
option refers to a file that Exim can create. This file
is used to keep track of who has received virus rejection messages
from this filter, so we don't hammer the same person with 20
rejections for 20 copies of the same virus.

Of course, you'll also have to edit Exim's configuation file to
enable the filter. For Exim 3.x, you'll need to add the following:

# Virus filtering, using a filter descended from Nigel Metheringham's
# filter for rejecting mail that looks like a Windows e-mail virus.
message_filter = /etc/exim/system_filter
message_body_visible = 5000
# These are needed so we can save, pipe, or send mail from the
# system filter.
message_filter_file_transport = address_file
message_filter_reply_transport = address_reply
# Viruses can be big, and it's not really necessary to return
# every last byte.
return_size_limit = 30k

Of course, make sure that message_filter refers to
where you put the filter. Also, make sure that the two transports
-- address_file and address_reply -- exist;
they should look something like this:

address_file:
driver = appendfile
# these three options are not necessary, but I like them
delivery_date_add
envelope_to_add
return_path_add
address_reply:
driver = autoreply

Once you've got virus-filtering working, there are a few things to
consider:

Viruses are big; on a moderately busy system, saving every one
can add up quickly. Plan on several tens of megabytes per week
being consumed by viral email as long as you save them all.

Once you're satisfied that the filter works as advertised
(catches viruses, sends rejection messages), you might consider
not saving them all any more. Keep in mind that you will
discard email if you do that: if user@example.com sends
you 10 instances of, say, the SirCam worm in any one 24 hour
period, only the first will result in a rejection notice (with
an excerpt of the virus included). The other nine will be
silently discarded.