Marc Haber wrote:
>
> We should have a system filter that calls an embedded perl function
> that does the scanning. It uses exim -Mvb and exim -Mvh (or the
> possibly future exim -Mva [1]) to obtain the message's header and body
> and do its scanning business. If the message is classified malicious,
> the embedded perl function could create new messages according to
> configuration (see (f) above) and subsequently fail delivery in the
> system filter, preventing the malicious message from being delivered
> in the first place. Probably, a bounce would be created to the sender,
> but I'd consider that a feature if the message is failed with "see
> notification report sent in a separate e-mail message". If the
> function determines a message to be clean, normal delivery can be
> continued. Thus, a clean message is only passed through the MTA a
> single time.
>
> What are your opinions about this concept?
Marc Haber wrote:
>
> Actually, I don't think that any modifications in the exim code base
> are necessary to implement this concept. It is nice to hear that you
> didn't see any obvious mistakes in here, so I'll probably go for a
> proof of concept next week.
I've setup Exim 3.16 to do a mailscan pretty close to what Marc
described, and can attest that the plan is definitely workable without
changes to Exim. Have been running this for a year now on a server
that handles about 6,000 msgs/day. Currently, I have a system filter
and perl script that look like:
-----
# Exim filter
if first_delivery
and ($received_protocol is not "virusscan")
and (${perl{mailscan}} is "fail")
then
seen finish
endif
-----
#!/usr/bin/perl
$real_scanner = '/usr/local/etc/exim/mailscan.py';
sub mailscan
{
$message_id = Exim::expand_string('$message_id');
$sender_address = Exim::expand_string('$sender_address');
$header_subject = Exim::expand_string('$header_subject');
$header_subject =~ s(\\)(\\\\)g;
$header_subject =~ s(\")(\\\")g;
$header_subject =~ s(\`)(\\\`)g;
$result = `$real_scanner $message_id "$sender_address"
"$header_subject"`;
chomp $result;
if (($result ne 'ok') && ($result ne 'fail'))
{
open(LOGFILE, ">>/var/log/mailscan.log");
print LOGFILE "$message_id <$sender_address>---------\nSubject:
[$header_subject]\n$result\n----------\n";
close(LOGFILE);
system("cp /var/spool/exim/input/$message_id-*
/var/mailscan/hold")
}
return $result;
}
------
I ended up writing the actual scanner in Python (like it better than
Perl), which makes a copy of the message (cheated and read directly from
the queue, instead of using -Mvb and -Mvh - will have to go back and
clean that up), parses all attachments, ponders the names of the files
(looking for .exe and such), and runs F-Secure Antivirus for Linux (this
in actually on a FreeBSD box).
If any problems are found, I send a reply to the sender (with "-oMr
virusscan" so the system doesn't bother scanning the reply), resend the
original to a quarantine address (again with "-oMr virusscan" so it
doesn't get scanned again), and print "fail" to stdout - which works its
way back to the exim system filter causing the original message to just
be dropped.
It's probably a bit inefficient to fire up a Perl interpreter inside
Exim just to invoke a Python interpreter :) I've started hacking at
3.16 a bit to see if Python can be integrated, the same way Perl is now.
Barry