Dspam on Debian with MySQL, Exim4 and Apache 1.x HOWTO

Pick your flavor: Debian Sarge / unstable will work.

Tested Versions:

If anything doesn't work - try these versions first.

DSPAM

1. Configure DSPAM

 ./configure --disable-bias \
             --enable-virtual-users \
             --with-storage-driver=mysql_drv \
             --with-mysql-includes=/usr/include/mysql \
             --enable-debug \
             --with-dspam-home-owner=exim \
             --with-dspam-group=mail \
             --with-delivery-agent=/usr/sbin/exim4 \
             --with-quarantine-agent=/usr/sbin/exim4 \
             --enable-experimental

2. as root (pick checkinstall to build your own Debian package):

        make
        make install      or      checkinstall -D

3. configure Exim4 according to Installation/Exim/Exim

(note: in some configurations you need to comment out the check_local_user below, for example when you allow virtual users with Cyrus. See 10 for one alternative solution to this)

/etc/exim4/conf.d/router/620_exim4-config_dspam:

        dspam_router:
                no_verify
                check_local_user
                # When to scan a message :
                # - it isn't already flagged as spam from Spamassassin
                # - it isn't already flagged as spam from DSPAM
                # - it isn't already scanned
                # - it isn't local
                # - it isn't from one internal domain user to another
                # - it is less than 512k in size
                condition   = "${if and { \
                        {!def:h_X-Spam-Flag:} \
                        {!def:h_X-FILTER-DSPAM:} \
        #               {!eq {$received_protocol}{local}} \
                        { <= {$message_size}{512k}} \
                        }\
                        {1}{0}}"
                headers_add  = "X-FILTER-DSPAM: by $primary_hostname on $tod_full"
                driver       = accept
                transport    = dspam_spamcheck
                # Which users to run dspam for.
                #local_parts = /usr/local/etc/exim/dspam-testers
        dspam_addspam_router:
                driver            = accept
                local_part_prefix = spam-
                transport         = dspam_addspam
        dspam_falsepositive_router:
                driver            = accept
                local_part_prefix = nospam-
                transport         = dspam_falsepositive

/etc/exim4/conf.d/transport/40_exim4-config_dspam:

        dspam_spamcheck:
                driver = pipe
                command = "/usr/local/bin/dspam --deliver=innocent --user \
                        ${lc:$local_part} -f '$sender_address' -bm %u"
                home_directory = "/tmp"
                current_directory = "/tmp"
                user = Debian-exim
                group = mail
                log_output = true
                return_fail_output = true
                return_path_add = false
                message_prefix =
                message_suffix =
        dspam_addspam:
                driver = pipe
                command = "/usr/local/bin/dspam --class=spam --source=error --user \
                        ${lc:$local_part} -f '$sender_address' -bm %u"
                home_directory = "/tmp"
                current_directory = "/tmp"
                user = Debian-exim
                group = mail
                log_output = true
                return_fail_output = true
                return_path_add = false
                message_prefix =
                message_suffix =
        dspam_falsepositive:
                driver = pipe
                command = "/usr/local/bin/dspam --class=innocent --source=error \
                        --deliver=innocent,spam --user ${lc:$local_part}\
                        -f '$sender_address' -bm %u"
                home_directory = "/tmp"
                current_directory = "/tmp"
                user = Debian-exim
                group = mail
                log_output = true
                return_fail_output = true
                return_path_add = false
                message_prefix =
                message_suffix =

4. configure mysql according to MySQL

(if you don't have mysql installed, see below and install it)

        mysqladmin -u root -p create dspam
        mysql -u root -p dspam < ./src/tools.mysql_drv/mysql_objects-4.1.sql
        mysql -u root -p dspam < ./src/tools.mysql_drv/virtual_users.sql
        mysql -u root -p
        mysql> grant all on dspam.* to dspam@localhost identified by 'root';

5. change conf in dspam (usually /usr/local/etc/dspam.conf) and uncomment sql and change the password:

MySQLServer     /var/run/mysqld/mysqld.sock
MySQLPort
MySQLUser           dspam
MySQLPass           changeme
MySQLDb             dspam
MySQLCompress       true

6. create a user account "bfuuser" and as root:

        dspam_stats bfuuser

you should get:

        bfuuser            TS:     0 TI:     0 SM:     0 IM:     0 SC:     0 IC:     0

If not, then you must play with permissions and with the connection to mysql database, until you get this result.

7. add the following to dspam.conf:

        Trust Debian-exim

8. send email to "bfuuser" and you should get:

        bfuuser            TS:     0 TI:     1 SM:     0 IM:     0 SC:     0 IC:     0

9. forward this email from bfuuser to spam-bfuuser@localhost, which should make "TI:0, SM:1". If yes, then dspam should work. More in README, section TESTING.

10. If you use virtual users (ie with cyrus), and don't check for local_users as descrbibed at 3), dspam might end up looking at a lot of bogus email before it hands it over to cyrus, which then bounces it as undeliverable. The best thing to do is to create a seperate acl for this.

A dirty hack is this one: comment out the:

#.ifndef CHECK_RCPT_LOCAL_LOCALPARTS
#CHECK_RCPT_LOCAL_LOCALPARTS = ^[.] : ^.*[@%!/|\'`#&?]
#.endif

and replace it with:

.ifndef CHECK_RCPT_LOCAL_LOCALPARTS
hide pgsql_servers = localhost/dspamdb/USERNAME/SECRET
CHECK_RCPT_LOCAL_LOCALPARTS = !pgsql;select username from dspam_virtual_uids where username = '${quote_pgsql:$local_part}' : ${lookup{$local_part}lsearch{/etc/aliases}}
.endif

Note the ! in front of pgsql. For this to work, however, your dspam_virtual_uids (and etc/aliases) needs to be up to date, and contain the ham-USER and spam-USER alternatives.

CGI script

1. install apache-ssl

2. in /etc/apache-ssl/httpd.conf add:

        <Directory "/var/www/dspam/html">
                Options FollowSymLinks ExecCGI
                AllowOverride None
                Order deny,allow
                Deny from all
                AddHandler cgi-script .cgi .pl
                SSLRequireSSL
                AuthType Basic
                AuthName "DSPAM Control Center"
                AuthUserFile /var/www/dspam/etc/htpasswd
                Require valid-user
                Satisfy Any
        </Directory>

then change

        User Debian-exim
        Group mail

and restart apache.

3. create /var/www/dspam and inside directories "etc" and "html"

4. copy /etc/shadow to etc/htpasswd, leave only the lines with users which we want, plus only first two columns.

5. to html/ copy everything from dspam-3.4.4/cgi/*

chown -R Debian-exim.Debian-exim dspam/*

6. graphs - install:

        apt-get install libgd-gd1-perl libgd-graph-perl libgd-graph3d-perl libgd-perl libgd-text-perl libgdbm3 libgdbmg1

7. with the browser go to https://localhost/dspam/html/dspam.cgi and fill in the username and password of the user.

Installing MySQL

1. install packages:

        apt-get install mysql-server-4.1 mysql-client-4.1

2. password for root - as a normal user:

        mysqladmin -u root password 'enter-your-good-new-password-here'

(see /usr/share/doc/mysql-server-4.1/README.Debian.gz, or MySQL)

Training

1. spam

        dspam_corpus --addspam ondra /home/ondra/Desktop/Downloads/631.r2

2. nonspam

        dspam_corpus ondra mbox

Regenerate an expired SSL certificate

Remove the existing cert and reconfigure the package

rm /etc/apache-ssl/apache.pem
dpkg-reconfigure apache-ssl

The CGI script patch

I prefer to archive every spam from the quarantine using archivemail, thus I applied the following patches.

dell:/var/www/dspam/html# diff templates/nav_quarantine.html /home/ondra/dspam/dspam-3.4.8/cgi/templates/nav_quarantine.html
45d44
< <!--
49,50d47
< -->
< <input type="submit" value="Archive" name="archive">

and

dell:/var/www/dspam/html# diff dspam.cgi /home/ondra/dspam/dspam-3.4.8/cgi/dspam.cgi
715c715
<   if ($FORM{'archive'} ne "") {
---
>   if ($FORM{'deleteAll'} ne "") {
728,730c728,729
<       #open(FILE, ">$MAILBOX");
<       #close(FILE);

<         system("/usr/bin/archivemail --days=1 --include-flagged --quiet \"$MAILBOX\"");
---
>       open(FILE, ">$MAILBOX");
>       close(FILE);

last edited 2006-06-21 06:31:08 by GijsHillenius