jamm virus/spam filtering and quotas

Chris Holleman <[email protected]> Thu, 17 Jun 2004 12:52:31 +0200
Newsgroups gmane.mail.jamm.user
Message-ID <[email protected]>
hello list, 

as promised. This howto is far from ready. I hope to clean things up this weekend and make a version that's suitable for a website.

feedback is more then welcome




Introduction
------------

This howto tries to describe various ways to add (per user) spamcontrol and
virusscanning  to the jamm mail system using maildrop. some sort of spamfilter
like spamassassin, spamprobe, and clamav. If you want to set things "per
user" you need to create an interface that wil give virtual users the ability to 
edit a mailfilter file. As a bonus it will give you also the ability to add 
quota's for your users. (you could do this with the VDA patch
to postfix, but i rather not patch if i don't have to). As this is not in the
jamm interface and i'm no java programmer i created a little shell script
that will set the quota for a user.


extra software needed
---------------------

maildrop
http://prdownloads.sourceforge.net/courier/maildrop-1.6.3.tar.bz2

spamassassin
http://www.spamassassin.org

clamav
http://prdownloads.sourceforge.net/clamav

a few scripts

Implementation
--------------

Spamassassin
------------
Install Spamassassin (or some other spamfiltering tool)

this is a quote from the SA install docs

The easiest way to do this is using CPAN.pm, like so:

perl -MCPAN -e shell                    [as root]
o conf prerequisites_policy ask
install Mail::SpamAssassin
quit


Clamav
------
I use clamav, but you can prolly use any other viruschecker too, you just have
to edit the interface script.

useradd clamav
groupadd clamav

./configure
make
make install
freshclam (to get the latest virus db)

You need a little script in between the xfilter command and clamav. I found a
perl script in some mailinglist that does that, but there are more ways to do
this. this url wil give some other solutions

http://www.clamav.net/3rdparty.html#pagestart

this is the script i use in /usr/local/bin/scanmail.pl

---snip------

#!/usr/bin/perl -w

use strict;

mkdir "/tmp/mailscan", 0777;

umask 077;
my $tmpnam = "/tmp/mailscan/$$";

my $fh;
open $fh, ">$tmpnam" or do {
        `logger -t scanmail "cannot open $tmpnam"`;
	                exit 1; # not much we can do, defer all mail
};

my @lines = <>;
print $fh @lines;
close $fh;

my @result = `/usr/bin/clamdscan --disable-summary --stdout --mbox $tmpnam`;
my $rc=($?>>8);
unlink $tmpnam or `logger -t scanmail "cannot unlink $tmpnam"`;

my @extra_headers=("X-Scanned: By Clamav\n");
#print "rc=$rc\n", @result;

map { s/^ *//; push @extra_headers, "X-Virus: $_\n"; } grep /FOUND/,
@result;
			
my $headers=1;
for my $line (@lines) {
	if ($headers and $line eq "\n") {
		for (@extra_headers) {
			print;
		}
		$headers=0;
	}
	print $line;
}
exit 0;
										
----snap----

note: i installed clamav via emerge (gentoo) so you might have to edit the
various paths of clamav binaries


										
Maildrop
-------
Install maildrop

configure maildrop
./configure --prefix=/usr/local/maildrop --without-db --disable-userdb
--enable-maildirquota --enable-maildropldap
--with-ldapconfig=/etc/maildrop/maildropldap.config
--with-etcdir=/etc/maildrop --enable-maildrop-uid=vmail
--enable-maildrop-gid=vmail

(of course all on one line)

make
make install


maildrop can work with virual users (procmail cannot), but you have to
configure the ldap lookups. this is my maildropldap.config without any
comments.
(you can edit the path with configure if you don't like my suggestion).

hostname        localhost
basedn          dc=myhosting,dc=example
filter          &(&(objectclass=JammmailAccount))
timeout         5
search_method           mail
default_uidnumber       1000
default_gidnumber       440
mail_attr               mail
maildir_attr            mailbox
homedirectory_attr      homedirectory
quota_attr              quota

Edit the default_uidnumber and default_gidnumber to match user and group vmail
You might also want to edit the ldap filter


Postfix
-------
edit main.cf

there is only one thing in here you need to change:
virtual_transport = maildrop

If you want the original jamm setup change it back to virtual and everything
should work like before

edit master.cf

create a maildrop line so it reads.

maildrop  unix  -       n       n       -       -       pipe
  flags=Ru user=vmail argv=/usr/local/maildrop/bin/maildrop -d ${recipient}

restart postfix

at this point mail should be delivered normal, but instead of using the
postfix virtual agent it uses maildrop.

TEST THIS before going any further !

------------------------------------
now for the fun part.

Configuring spamfiltering andvirusscanning
------------------------------------------

all of this in global, but can be configured per user. Problem is that a
virtual user cannot edit his/her own rules. everything i add in the global
mailfilter file can be added in a per user mailfilter. That is NO fun if you
have more then 3 users :-)

my /etc/maildrop/maildroprc

----snip-----

# get the domainname, Iwill need that later as maildrop doesn't create a
# maildir
# like the postfix virtual delivery agent. If there is a nicer way of doing
# this
# please let me know

DOMAINNAME=`echo $LOGNAME|sed 's/.*@//g'`

# this includes the per user mailfilter. if you use it place it in the maildir 
# it's a pitty that Jamm doesn't provide a separate per user homedirectory as
# it would
# make things a LOT easier, and imho there is no reason why every user should
# share
# /home/vmail/domains, but if i change that it would break jamm
#
# if you don't use exception maildrop will fail to deliver if the .mailfilter
# isn't there

exception   {
   include "$DEFAULT/.mailfilter"
   }

# the postfix virual delivery agent does this for you (creating a Maildir
# is it doesn't exist). Maildrop does not, so I created the same function
# here

#first test if the domainname is already there, and if not create it
`test -d $DOMAINNAME/`
if ( $RETURNCODE != 0 )
   `mkdir /home/vmail/domains/$DOMAINNAME`
#then check if the users mailbox is there, and if not create it
`test -d $DEFAULT/`
if ( $RETURNCODE != 0 )
	`/usr/local/maildrop/bin/maildirmake $DEFAULT`

# scan the email for viruses
xfilter "/usr/local/bin/scanmail.pl"

# scan message for spam if it's not to big
if ( $SIZE < 262144 )
        {
        xfilter "/usr/bin/spamc -f"
        }

#oke, I now have an email message that has a header saying it's scanned for
#viruses
# and if it's not to big scanned for spam. NOw let's do something usefull
# with it
# first test if ithe .Infected folder is already there
`test -d $DEFAULT/.Infected`
if ( $RETURNCODE != 0 )
	{
	# if you want to see this folder in squirrelmail automaticly
	# add something like this
	# `echo INBOX.Infected >> $DEFAULT/courierimapsubsrcibed`
        `/usr/local/maildrop/bin/maildirmake -f Infected $DEFAULT/`
        }

if (/^X-Virus/)
        {
        to $DEFAULT/.Infected
	# of course this is also possible
        #to /dev/null
	}

# first test if the folder is already there
`test -d $DEFAULT/.Spam`
if ($RETURNCODE != 0 )
        {
        # if you want to see this folder in squirrelmailautomaticly add something
        # like this
	# `echo INBOX.Spam >> $DEFAULT/courierimapsubsrcibed`
	`/usr/local/maildrop/bin/maildirmake -f Spam $DEFAULT/`
	}
# now lets put spam in the seperate box
if(/^X-Spam-Flag: YES/)
	{
	to $DEFAULT/.Spam
	# ofcourse this is also possible
	#to /dev/null
	}
																		 
---snap----


quota's
-------

as i said, i'm not a programmer, and i know very little of java coding so i
created my own way of adding quota (it already is in the jamm schema so that
should not be a problem. 

Only thing that is needed to use quota;s is to add them in ldap :-) kewl no ?

i use the ldapmodify tool for that in a little shell script (i know this is a
very ugly hack, but it works) itools like phpldapadmin can do this too

edit-quota.sh

----snip----

#!/bin/sh

EMAIL=$1
QUOTA=$2
JVD=`echo $EMAIL|sed 's/.*@//g'`

echo -e "dn:mail=$EMAIL,jvd=$JVD,o=hosting,dc=myhosting,dc=example\nchangetype: modify\nreplace: quota\nquota: $QUOTA"|ldapmodify -D'cn=Manager,dc=myhosting,dc=example' -w secret

----snap----
(the echo ... is all on one line)

syntax is 
./edit-quota.sh <email-adres> <quota>

quota is in the format NS,NC

where S is Size in bytes and C is number of files

you can use only Size or (i think) only Number of files though the last one i
haven't tested

a valid command line would be ./edit-quota.sh [email protected] 100000S

Starting and testing
-------------------

start the antivirus daemon
clamd

start the spamassassin daemon
spamd -d

send a message and see if the spam and virus headers are present. If they are
send a test spam and test virus message to see if that get's delivered in the
correct box.

Set the quota for example to 1S and try to send an email. if everything works as planned the mail will bounce.

-- 
Met vriendelijke groeten/kind regards,

Chris Holleman



-------------------------------------------------------
This SF.Net email is sponsored by The 2004 JavaOne(SM) Conference
Learn from the experts at JavaOne(SM), Sun's Worldwide Java Developer
Conference, June 28 - July 1 at the Moscone Center in San Francisco, CA
REGISTER AND SAVE! http://java.sun.com/javaone/sf Priority Code NWMGYKND