Postfix and ClamAV

On my FreeBSD box I have installed and configured Postfix, Procmail and SpamAssassin which is working really nicely for filtering SPAM.

I now want to install and setup anti virus. I have recently read about ClamAV. I see there is a ClamAV port but when I run make install it asks if I want to compile the milter interface...what is this?. Does anyone have any experience with ClamAV and Postfix?

One thing I was wondering is, does ClamAV integrate into SpamAssassin or Postfix? Where exactly does ClamAV fit into a setup like this?

Are there any good guides available for configuring this? ;)

Sorry for all the questions, just so unsure of how to implement this in my setup!
 
You need to update main.cf:
Code:
content_filter=smtp-amavis:[127.0.0.1]:10024

And master.cf:
Code:
smtp-amavis unix - - n - 2 smtp
  -o smtp_data_done_timeout=2400
  -o smtp_send_xforward_command=yes
  -o disable_dns_lookups=yes
  -o max_use=20
127.0.0.1:10025 inet n - n - - smtpd
  -o content_filter=
  -o local_recipient_maps=
  -o relay_recipient_maps=
  -o smtpd_restriction_classes=
  -o smtpd_delay_reject=no
  -o smtpd_client_restrictions=permit_mynetworks,reject
  -o smtpd_helo_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks_style=host
  -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 smtpd_client_connection_count_limit=0
  -o smtpd_client_connection_rate_limit=0
  -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings

See man pages for more info.

Are there any good guides available for configuring this?
http://www.purplehat.org/?page_id=4
 
vivek said:
You need to update main.cf:
Code:
content_filter=smtp-amavis:[127.0.0.1]:10024

And master.cf:
Code:
smtp-amavis unix - - n - 2 smtp
  -o smtp_data_done_timeout=2400
  -o smtp_send_xforward_command=yes
  -o disable_dns_lookups=yes
  -o max_use=20
127.0.0.1:10025 inet n - n - - smtpd
  -o content_filter=
  -o local_recipient_maps=
  -o relay_recipient_maps=
  -o smtpd_restriction_classes=
  -o smtpd_delay_reject=no
  -o smtpd_client_restrictions=permit_mynetworks,reject
  -o smtpd_helo_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o mynetworks_style=host
  -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 smtpd_client_connection_count_limit=0
  -o smtpd_client_connection_rate_limit=0
  -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_address_mappings

See man pages for more info.


http://www.purplehat.org/?page_id=4

I checked my main.cf file but I couldn't find any line of code like you mentioned:
Code:
content_filter=smtp-amavis:[127.0.0.1]:10024
Must I just add this at the bottom of the config file? I'm not using Amavis but ClamAV rather. I have installed ClamAV successfully and put it in the rc.conf so that clamd and freshclam run as a service on bootup. What do I put next to content_filter for ClamAV?

I also had a look through my master.cf file. Mine currently says this:
Code:
smtp      inet  n       -       n       -       -       smtpd
  -o content_filter=spamd:

Now currently I use SpamAssassin to stop SPAM. How do I add in ClamAV here too so that emails get scanned for virii?

I noticed theres something called ClamSMTP too. Do I use one or the other...or both?

Thanks for your help!! :e
 
I'm not sure if this is the best way to implement ClamAV with Postfix but heres what I have done so far:

1)Installed the ClamAV port and added the following to /etc/rc.conf:
Code:
clamav_freshclam_enable="YES"
clamav_clamd_enable="YES"

2) I then found this link which I followed exactly:

http://wiki.apache.org/spamassassin/FilteringViruses

3) I haven't been able to successfully send myself a test virus infected email (haha) as my AV picks up the test file from:

http://www.eicar.org/anti_virus_test_file.htm

Everytime. All webmail services pick it up too.

So what I did was send myself a test email from Gmail to myself and checked the email headers. It now says:

Code:
X-Clamav-Status: No

I *assume* that ClamAV is now scanning my incoming/outgoing emails as its putting it in the email header now? I also checked the ClamAV logfile but it doesn't show any activity with regards to scanning email, should it?

The logfile contents are as follows:
Code:
+++ Started at Mon Sep 28 11:17:30 2009
clamd daemon 0.95.2 (OS: freebsd7.2, ARCH: i386, CPU: i386)
Running as user clamav (UID 106, GID 106)
Log file size limited to 1048576 bytes.
Reading databases from /var/db/clamav
Not loading PUA signatures.
Loaded 624177 signatures.
LOCAL: Unix socket file /var/run/clamav/clamd.sock
LOCAL: Setting connection queue length to 15
Limits: Global size limit set to 104857600 bytes.
Limits: File size limit set to 26214400 bytes.
Limits: Recursion level limit set to 16.
Limits: Files limit set to 10000.
Archive support enabled.
Algorithmic detection enabled.
Portable Executable support enabled.
ELF support enabled.
Mail files support enabled.
OLE2 support enabled.
PDF support enabled.
HTML support enabled.
Self checking every 600 seconds.
Set stacksize to 1114112

Have I setup ClamAV to scan all incoming/outgoing emails correctly with Postfix and SpamAssassin?

Many thanks!
 
hydra said:
Use postfix with amavisd-new. Let amavisd-new use SpamAssassin and Clamav. That should work nicely.

Can you be a bit more specific please, I'm still quite new to FreeBSD...:e
 
If you're using security/amavisd-new (amavisd-new will use both SpamAssassin and ClamAV), try the following configuration:

In /usr/local/etc/postfix/master.cf:
Code:
amavisd-new
          unix  -       -       n       -       2       smtp
  -o smtp_data_done_timeout=1200s
  -o disable_dns_lookups=yes
  -o smtp_send_xforward_command=yes
  -o max_use=20

127.0.0.1:10025
          inet  n       -       n       -       -       smtpd
  -o content_filter=
  -o mynetworks=127.0.0.1/32
  -o smtpd_client_restrictions=
  -o smtpd_helo_restrictions=
  -o smtpd_sender_restrictions=
  -o smtpd_recipient_restrictions=permit_mynetworks,reject
  -o smtpd_data_restrictions=reject_unauth_pipelining
  -o smtpd_end_of_data_restrictions=
  -o smtpd_restriction_classes=
  -o smtpd_error_sleep_time=0
  -o smtpd_soft_error_limit=100
  -o smtpd_hard_error_limit=150
  -o local_recipient_maps=
  -o relay_recipient_maps=

In /usr/local/etc/postfix/main.cf:
Code:
content_filter = amavisd-new:[127.0.0.1]:10024

Don't forget to modify /usr/local/etc/amavisd.conf and /etc/rc.conf.

If you don't want to use security/amavisd-new, it's also possible to use scan for viruses using a SpamAssassin plugin. I prefer this method since it's a bit more lightweight.

Install security/p5-File-Scan-ClamAV.

Create /usr/local/etc/mail/spamassassin/clamav.cf:
Code:
loadplugin ClamAV clamav.pm
full CLAMAV eval:check_clamav()
describe CLAMAV ClamAV detected a virus
score CLAMAV 5

Create /usr/local/etc/mail/spamassassin/clamav.pm:
Code:
package ClamAV;
use strict;

# our $CLAMD_SOCK = 3310;               # for TCP-based usage
our $CLAMD_SOCK = "/var/run/clamav/clamd.sock";   # change me

use Mail::SpamAssassin;
use Mail::SpamAssassin::Plugin;
use File::Scan::ClamAV;
our @ISA = qw(Mail::SpamAssassin::Plugin);

sub new {
  my ($class, $mailsa) = @_;
  $class = ref($class) || $class;
  my $self = $class->SUPER::new($mailsa);
  bless ($self, $class);
  $self->register_eval_rule ("check_clamav");
  return $self;
}

sub check_clamav {
  my ($self, $permsgstatus, $fulltext) = @_;
  my $clamav = new File::Scan::ClamAV(port => $CLAMD_SOCK);
  my ($code, $virus) = $clamav->streamscan(${$fulltext});
  my $isspam = 0;
  my $header = "";
  if(!$code) {
    my $errstr = $clamav->errstr();
    Mail::SpamAssassin::Plugin::dbg("ClamAV: Error scanning: $errstr");
    $header = "Error ($errstr)";
  } elsif($code eq 'OK') {
    Mail::SpamAssassin::Plugin::dbg("ClamAV: No virus detected");
    $header = "No";
  } elsif($code eq 'FOUND') {
    Mail::SpamAssassin::Plugin::dbg("ClamAV: Detected virus: $virus");
    $header = "Yes ($virus)";
    $isspam = 1;
    # include the virus name in SpamAssassin's report
    $permsgstatus->test_log($virus);
  } else {
    Mail::SpamAssassin::Plugin::dbg("ClamAV: Error, unknown return code: $code");
    $header = "Error (Unknown return code from ClamAV: $code)";
  }
  $permsgstatus->{main}->{conf}->{headers_spam}->{"Virus"} = $header;
  $permsgstatus->{main}->{conf}->{headers_ham}->{"Virus"} = $header;
  # add a metadatum so that rules can match against the result too
  $permsgstatus->{msg}->put_metadata('X-Spam-Virus',$header);
  return $isspam;
}

1;

I use sa-compile after this, but I'm not sure if it's necessary. Restart SpamAssassin and it should work.
 
MANY thanks for this!! I think I will follow your ClamAV instructions as this is what I have installed on the weekend from security/clamAV. Just a few questions:

1) You said "Create /usr/local/etc/mail/spamassassin/:" ... is there meant to be a filename here? Or can I call it anything I like?

2) Is this the only section I need to edit:

# our $CLAMD_SOCK = 3310; # for TCP-based usage
our $CLAMD_SOCK = "/var/run/clamav/clamd.sock"; # change me

3) What actually happens with this configuration when a virus is detected? Is it deleted? Quarentined?

4) Does this solution make use of the ClamAV install I have on my server or should I uninstall it?
 
1) You said "Create /usr/local/etc/mail/spamassassin/:" ... is there meant to be a filename here? Or can I call it anything I like?

Sorry, I mistyped the path. It should be /usr/local/etc/mail/spamassassin/clamav.pm.

2) Is this the only section I need to edit:

# our $CLAMD_SOCK = 3310; # for TCP-based usage
our $CLAMD_SOCK = "/var/run/clamav/clamd.sock"; # change me

If you haven't changed the default socket location of ClamAV, this should be fine.


3) What actually happens with this configuration when a virus is detected? Is it deleted? Quarentined?

Nothing actually. It just adds a X-Spam-Virus: Yes header to the mail. Use mail/procmail, mail/maildrop, or mail/dovecot to send it to a special location or mailbox.

Some examples:
My ~/.procmailrc:
Code:
:0:
* ^X-Spam-Virus: Yes
Junk

For Dovecot LDA (with Sieve):
Code:
require "fileinto";

if header :contains "X-Spam-Virus" "YES" {
  fileinto "Infected";
}

4) Does this solution make use of the ClamAV install I have on my server or should I uninstall it?

This method makes use of your original installation of p5-Mail-SpamAssassin (remember to select SPAMC) and security/clamav.
 
dennylin93, thank you so much for your excellent reply. I still have a lot I am unsure of so I am going to build a test system rather and test what you mentioned. I don't want to break my "live" server at home....:e

In the meantime what I have tried is my modifying my /usr/local/etc/procmailrc as follows:
Code:
# Scan for viruses
:0
VIRUS=|clamdscan --no-summary --stdout -

:0fw
* VIRUS ?? ^.*: \/.* FOUND
| formail -b -f -t -I "X-Clamav-Status: Yes, $MATCH"

:0Efw
| formail -b -f -t -I "X-Clamav-Status: No"

:0:
* ^X-Clamav-Status: Yes
.Junk/

This seems to work. If I send a test email using the "fake" virus from EICAR it detects the infected email and puts it in the users Junk folder. What I would prefer to do is direct all infected emails to a quarintined type area (mailbox or folder I guess?) where only the admin of the server can inspect them and ultimately delete/clean them. How would I do this in the procmailrc file?

Many thanks for your valuable input! :stud
 
dennylin93, thank you so much for your excellent reply.

No problem.

I still have a lot I am unsure of so I am going to build a test system rather and test what you mentioned. I don't want to break my "live" server at home....:e

For testing purposes, there's the soft_bounce parameter in /usr/loca/etc/postfix/main.cf. This option turns all permanent failures into temporary ones (remember to turn it off once you're done testing). It's also possible to create backups of mail you receive using procmail:
Code:
:0 c:
Backup

What I would prefer to do is direct all infected emails to a quarintined type area (mailbox or folder I guess?) where only the admin of the server can inspect them and ultimately delete/clean them. How would I do this in the procmailrc file?

I seem to remember that Postfix doesn't call external programs using root due to security concerns. It might be possible to make procmail send mail to a special directory if the email is infected; however, I can't confirm this since I don't use procmail anymore.
 
Back
Top