Index
- Introduction.
- Installation.
- Configure MySQL.
- Configure dspam.
- Configure Apache web interface.
- Configure Nginx web interface.
- Maintenance.
- Download.
26-Jun-2011: first release. 28-Aug-2011: updated directory permissions, logrotate. 18-Jan-2012: add nginx configuration.
Introduction.
DSPAM is a scalable and open-source content-based spam filter designed for multi-user enterprise systems. The filter does this by “learning” from it’s mistakes. In our setup dspam is installed between postfix and dovecot-lda. Dspam is not run as a daemon, but spawned by postfix every time a email is processed. This is fine for our small home server. The overview of the total setup is like:
[Postfix] ---> [DSPAM] ----> [dovecot-lda] ---> (Users mailbox)
\
\--> [Quarantine]
[End user] ----------------> [Web interface]
Users can choose to use the Quarantine for spam mail, or let it pass and let the dovecot sieve filter put the mail in the users local Spam mailbox. These settings can be configured in the web interface.
Installation.
Install dspam using pacman:
[root@homsrv ~]# pacman -S dspam
resolving dependencies...
looking for inter-conflicts...
Targets (1): dspam-3.9.0-4
Total Download Size: 0.27 MB
Total Installed Size: 1.81 MB
Proceed with installation? [Y/n]
:: Retrieving packages from community...
dspam-3.9.0-4-i686 281.2K 710.0K/s 00:00:00 [######################] 100%
(1/1) checking package integrity [######################] 100%
(1/1) checking for file conflicts [######################] 100%
(1/1) installing dspam [######################] 100%
adding dspam system group... done.
adding dspam system user... done.
>>> To populate the DSPAM database, you need to follow several steps.
>>> First create a database. Login to the mysql command prompt.
$ mysql -u root -p
mysql> CREATE database dspam;
>>> Next, you need to create a dspam user. At the same MySQL prompt:
mysql> GRANT ALL PRIVILEGES ON dspam.* TO dspam@'localhost' IDENTIFIED BY 'passwd';
>>> Replacing passwd with your chosen password.
>>> If you want a space optimized db do:
$ mysql -u dspam dspam -p < /var/lib/dspam/mysql/mysql_objects-space.sql
>>> If you want a speed optimized db do:
$ mysql -u dspam dspam -p < /var/lib/dspam/mysql/mysql_objects-speed.sql
>>> Enter the password you set in the previous step, and the database should be
populated.
>>> Remember to edit /etc/dspam/dspam.conf accordenly
>>> If you want to use the postgresql, sqlite3 or Berekely DB4 backends,
>>> read the documentation
>>>
Optional dependencies for dspam
libmysqlclient: MySQL support
postgresql-libs: PostgreSQL support
db: BerkeleyDB support
sqlite3: SQLite support
[root@homsrv ~]#
Configure MySQL.
Create a database user for dspam:
[root@homsrv ~]# mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.5.13 Source distribution Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> CREATE database dspam; Query OK, 1 row affected (0.08 sec) mysql> GRANT ALL PRIVILEGES ON dspam.* TO dspam@'localhost' IDENTIFIED BY 'dspam'; Query OK, 0 rows affected (0.04 sec) mysql> quit; Bye [root@homsrv ~]#
The script /var/lib/dspam/mysql/mysql_objects-speed.sql can create most tables for dspam, but the syntax in that script is not correct for the current MySQL version. So edit that script with vi (or other editor of your choice) and global replace type= with ENGINE=. After the script is fixed, create the tables and add one other table from the command line:
[root@homsrv ~]# mysql -u dspam dspam -p \ < /var/lib/dspam/mysql/mysql_objects-speed.sql Enter password: [root@homsrv ~]# echo "create table dspam_virtual_uids ( \ uid smallint(5) unsigned NOT NULL AUTO_INCREMENT, \ username varchar(128) DEFAULT NULL, PRIMARY KEY (uid), \ UNIQUE KEY id_virtual_uids_01 (username) ) \ ENGINE=MyISAM;" | mysql -u dspam -p dspam
There should now be five tables in the database dspam.
Configure dspam.
First add the user dspam to the group users.
[root@homsrv ~]# usermod -a -G users dspam [root@homsrv ~]#
Then, edit /etc/dspam/dspam.conf (diff -u is shown):
--- dspam.conf.orig 2011-06-26 13:10:09.000000000 +0200
+++ dspam.conf 2011-06-26 13:17:27.000000000 +0200
@@ -45,7 +45,7 @@
#TrustedDeliveryAgent "/bin/maildrop" # Maildrop
#TrustedDeliveryAgent "/usr/local/sbin/exim -oMr spam-scanned" # Exim
#
-TrustedDeliveryAgent "/usr/bin/procmail"
+TrustedDeliveryAgent "/usr/lib/dovecot/dovecot-lda"
#
# Untrusted Delivery Agent: Specifies the local delivery agent and arguments
@@ -55,7 +55,7 @@
# the user DSPAM is processing mail for. This configuration parameter is only
# necessary if you plan on allowing untrusted processing.
#
-#UntrustedDeliveryAgent "/usr/bin/procmail -d %u"
+UntrustedDeliveryAgent "/usr/lib/dovecot/dovecot-lda -d %u"
#
# SMTP or LMTP Delivery: Alternatively, you may wish to use SMTP or LMTP
@@ -129,11 +129,11 @@
#
Trust root
Trust dspam
-Trust apache
-Trust mail
-Trust mailnull
-Trust smmsp
-Trust daemon
+Trust http
+#Trust mail
+#Trust mailnull
+#Trust smmsp
+#Trust daemon
#Trust nobody
#Trust majordomo
@@ -293,6 +293,7 @@
Preference "optOutClamAV=off" # { on | off } -> default:off
Preference "ignoreRBLLookups=off" # { on | off } -> default:off
Preference "RBLInoculate=off" # { on | off } -> default:off
+Preference "notifications=off" # { on | off } -> default:off
#
# Overrides: Specifies the user preferences which may override configuration
@@ -323,6 +324,7 @@
AllowOverride trainingMode
AllowOverride whitelistThreshold
AllowOverride dailyQuarantineSummary
+AllowOverride notifications
# --- MySQL ---
@@ -330,12 +332,12 @@
# Storage driver settings: Specific to a particular storage driver. Uncomment
# the configuration specific to your installation, if applicable.
#
-#MySQLServer /tmp/mysql.sock
+MySQLServer /var/run/mysqld/mysqld.sock
#MySQLPort
-#MySQLUser dspam
-#MySQLPass changeme
-#MySQLDb dspam
-#MySQLCompress true
+MySQLUser dspam
+MySQLPass dspam
+MySQLDb dspam
+MySQLCompress true
#MySQLReconnect true
# If you are using replication for clustering, you can also specify a separate
@@ -381,7 +383,7 @@
# (pointing to some arbitrary user), and the uid in the signature will
# switch to the correct user. Result: you need only one spam alias
-#MySQLUIDInSignature on
+MySQLUIDInSignature on
# --- PostgreSQL ---
@@ -623,7 +625,7 @@
# Notifications: Enable the sending of notification emails to users (first
# message, quarantine full, etc.)
#
-Notifications off
+Notifications on
#
# Purge configuration: Set dspam_clean purge default options, if not otherwise
@@ -814,7 +816,7 @@
# you are running the client and server on the same machine, as it eliminates
# much of the bandwidth overhead.
#
-ServerDomainSocketPath "/var/run/dspam/dspam.sock"
+#ServerDomainSocketPath "/var/run/dspam/dspam.sock"
#
# Client Mode: If you are running DSPAM in client/server mode, uncomment and
Then edit /etc/postfix-in/main.cf and disable dovecot-lda and enable dspam, so that the delivery part now looks like:
mailbox_command = /usr/bin/dspam --deliver=innocent --user $USER -- -d %u #mailbox_command = /usr/lib/dovecot/dovecot-lda -d "$USER"
To use dspam between postfix and dovecot-lda some file permissions need to be changed:
[root@homsrv ~]# cd /etc/dspam/ [root@homsrv dspam]# chmod 644 * [root@homsrv dspam]# cd /var/lib/dspam/ [root@homsrv dspam]# mkdir data [root@homsrv dspam]# chown dspam:users data [root@homsrv dspam]# chmod 770 data [root@homsrv dspam]# chown dspam:users . [root@homsrv dspam]# chmod 775 . [root@homsrv dspam]# ln -s /etc/dspam/txt/ [root@homsrv dspam]# ls -la total 24 drwxrwxr-x 5 dspam users 4096 Jun 26 14:17 . drwxr-xr-x 20 root root 4096 Jun 26 12:37 .. drwxrwx--- 2 dspam users 4096 Jun 26 14:17 data drwxr-xr-x 2 root root 4096 Jun 26 12:48 mysql drwxr-xr-x 2 root root 4096 Apr 4 14:35 pgsql lrwxrwxrwx 1 root root 15 Jun 26 14:34 txt -> /etc/dspam/txt/ [root@homsrv dspam]#
In the support archive (see download) in the directory examples/homsrv/etc/dspam/txt you will find three text files, put these in a /etc/dspam/txt and edit these files. You may translate them too if you like. It are templates for emails that are sent to a user when he/she gets the first mail or spam seen by dspam. For some reason these files are not shipped with Arch Linux.
Dspam writes the logfile to /var/lib.dspam so edit /etc/logrotate.d/dspam.logrotated:
/var/lib/dspam/system.log {
weekly
compress
su dspam users
create 0664 dspam users
}
Finally, restart postfix:
[root@homsrv ~]# /etc/rc.d/postfix restart :: Stopping postfix daemon [DONE] :: Starting postfix daemon [DONE] [root@homsrv ~]#
Configure Apache web interface.
Skip to the next paragraph if you use nginx as web server. The dspam web interface needs the apache suexec module to run. This means that the directory permissions of the installed web interface must be changed, the files in the cgi-bin directory of dspam must be owned by dspam, else suexec will not work. Then all users that want to make use of the web interface, need a user name and password. So if you’re server has Samba too, you will have three places where passwords are stored. In the next session, the permissions are set, a password is created for just one user, and extra perl modules are installed so that the web interface knows how to draw graphics.
[root@homsrv ~]# pacman -S perl-gdgraph
resolving dependencies...
looking for inter-conflicts...
Targets (4): gd-2.0.36RC1-3 perl-gd-2.44-3 perl-gdtextutil-0.86-2
perl-gdgraph-1.44-2
Total Download Size: 0.40 MB
Total Installed Size: 1.57 MB
Proceed with installation? [Y/n]
:: Retrieving packages from extra...
gd-2.0.36RC1-3-i686 177.1K 555.9K/s 00:00:00 [######################] 100%
:: Retrieving packages from community...
perl-gd-2.44-3-i686 129.4K 468.7K/s 00:00:00 [######################] 100%
perl-gdtextutil-0.... 24.4K 219.3K/s 00:00:00 [######################] 100%
perl-gdgraph-1.44-... 76.0K 348.9K/s 00:00:00 [######################] 100%
(4/4) checking package integrity [######################] 100%
(4/4) checking for file conflicts [######################] 100%
(1/4) installing gd [######################] 100%
(2/4) installing perl-gd [######################] 100%
(3/4) installing perl-gdtextutil [######################] 100%
(4/4) installing perl-gdgraph [######################] 100%
[root@homsrv ~]# cd /srv/http/dspam/
[root@homsrv dspam]# mkdir etc
[root@homsrv dspam]# cd etc
[root@homsrv etc]# htpasswd -c passwd mbroek (note: -c only the first time)
New password:
Re-type new password:
Adding password for user mbroek
[root@homsrv etc]# cd ..
[root@homsrv dspam]# chown -R dspam:dspam cgi-bin
[root@homsrv dspam]#
In /srv/http/dspam/cgi-bin you find the file admins. This file has the names of all users that are allowed to use the admin functions of the web interface. Currently only root is in that file. You may add normal users (like yourself) in that file, each user on a new line.
We use the dspam web interface as a virtual host, that means that when we connect to http://spam.wpl.ym and we log in we are in fact in the directory /srv/http/dspam/htdocs and there is no index.html. Put the following file as index.php in that directory so that users will be moved to the dspam.cgi as soon as they are logged in.
<?php header( "Location: http://spam.wpl.ym/cgi-bin/dspam.cgi" ); exit( 0 ); ?>
Add the following virtual host to /etc/httpd/conf/extra/httpd-vhosts.conf:
# # spam.wpl.ym <VirtualHost *:80> ServerAdmin admin@wpl.uk DocumentRoot /srv/http/dspam/htdocs ServerName spam.wpl.ym SuexecUserGroup dspam dspam ScriptAlias /cgi-bin/ /srv/http/dspam/cgi-bin/ <Directory /srv/http/dspam> Options FollowSymLinks ExecCGI Order deny,allow Deny from all Require valid-user AuthType Basic AuthName "DSPAM Control Center" Satisfy Any AuthUserFile /srv/http/dspam/etc/passwd Options +SymlinksIfOwnerMatch +Includes </Directory> </VirtualHost>
And add a “spam CNAME homsrv” line to /var/named/int/db.wpl.ym so that the nameserver resolves the hostname spam to the IP address of our home server.
Configure Nginx web interface.
The dspam web interface needs to run the CGI scripts as user dspam. In the nginx setup article you can see how we setup the standard fcgiwrap daemon. For this web interface we need to start a second fcgiwrap as user dspam. The next session will do this:
[root@homsrv ~]# cd /etc/conf.d/ [root@homsrv conf.d]# cp fcgiwrap fcgiwrap-dspam [root@homsrv conf.d]# vi fcgiwrap-dspam
In the new /etc/conf.d/fcgiwrap-dspam change the port to 9002 and the user and group into dspam. The next step:
[root@homsrv conf.d]# cd ../rc.d [root@homsrv rc.d]# cp fcgiwrap fcgiwrap-dspam [root@homsrv rc.d]# vi fcgiwrap-dspam
Edit the DAEMON variable and save the file:
DAEMON=fcgiwrap-dspam
Start the new fcgiwrap:
[root@homsrv rc.d]# rc.d start fcgiwrap-dspam :: Starting fcgiwrap-dspam daemon [DONE] [root@homsrv rc.d]# less fcgiwrap-dspam [root@homsrv rc.d]#
Now we have a CGI wrapper that runs as the dspam user. Add fcgiwrap-dspam to the DAEMONS() array /etc/rc.conf just before nginx so that the new wrapper starts during system boot.
All users that want to make use of the web interface, need a user name and password. So if you’re server has Samba too, you will have three places where user passwords are stored. In the next session a password is created for just one user, and extra perl modules are installed so that the web interface knows how to draw graphics.
[root@homsrv ~]# pacman -S perl-gdgraph
resolving dependencies...
looking for inter-conflicts...
Targets (4): gd-2.0.36RC1-3 perl-gd-2.44-3 perl-gdtextutil-0.86-2
perl-gdgraph-1.44-2
Total Download Size: 0.40 MB
Total Installed Size: 1.57 MB
Proceed with installation? [Y/n]
:: Retrieving packages from extra...
gd-2.0.36RC1-3-i686 177.1K 555.9K/s 00:00:00 [######################] 100%
:: Retrieving packages from community...
perl-gd-2.44-3-i686 129.4K 468.7K/s 00:00:00 [######################] 100%
perl-gdtextutil-0.... 24.4K 219.3K/s 00:00:00 [######################] 100%
perl-gdgraph-1.44-... 76.0K 348.9K/s 00:00:00 [######################] 100%
(4/4) checking package integrity [######################] 100%
(4/4) checking for file conflicts [######################] 100%
(1/4) installing gd [######################] 100%
(2/4) installing perl-gd [######################] 100%
(3/4) installing perl-gdtextutil [######################] 100%
(4/4) installing perl-gdgraph [######################] 100%
[root@homsrv ~]# cd /srv/http/dspam/
[root@homsrv dspam]# mkdir etc
[root@homsrv dspam]# cd etc
[root@homsrv etc]# htpasswd -c passwd mbroek (note: -c only the first time)
New password:
Re-type new password:
Adding password for user mbroek
[root@homsrv etc]#
In /srv/http/dspam/cgi-bin you find the file admins. This file has the names of all users that are allowed to use the admin functions of the web interface. Currently only root is in that file. You may add normal users (like yourself) in that file, each user on a new line.
We use the dspam web interface as a virtual host, that means that when we connect to http://spam.wpl.ym and we log in we are in fact in the directory /srv/http/dspam/htdocs and there is no index.html. Put the following file as index.php in that directory so that users will be moved to the dspam.cgi as soon as they are logged in.
<?php header( "Location: http://spam.wpl.ym/cgi-bin/dspam.cgi" ); exit( 0 ); ?>
Add the following virtual host to /etc/nginx/conf/nginx.conf and restart nginx:
# spam.wpl.ym
server {
listen 10.126.160.253:80;
listen [2001:1af8:fecf:7ea0::201]:80;
server_name spam.wpl.ym;
root /srv/http/dspam/htdocs;
access_log logs/spam_access_log;
error_log logs/spam_error_log;
auth_basic "DSPAM Access";
auth_basic_user_file /srv/http/dspam/etc/passwd;
index index.php;
location ~ \.php$ {
fastcgi_pass php;
include fastcgi.conf;
}
location ~ ^/cgi-bin/(.*\.cgi)$ {
root /srv/http/dspam/cgi-bin/;
rewrite ^/cgi-bin/(.*)\.cgi /$1.cgi break;
fastcgi_param AUTH_USER $remote_user;
fastcgi_param REMOTE_USER $remote_user;
include fastcgi.conf;
fastcgi_pass 127.0.0.1:9002;
}
}
And add a “spam CNAME homsrv” line to /var/named/int/db.wpl.ym so that the nameserver resolves the hostname spam to the IP address of our home server.
Maintenance.
Because after each processed email, new data is added to the MySQL database. A maintenance script /etc/cron.daily/dspam must be used to purge old data from the database. This script will also take care of log rotation, the file /etc/logrotate.d/dspam is not good for our purpose and must be removed.
After an update of the dspam package, /etc/logrorate.d/dspam is there again but you should get mail that it doesn’t work so you can remove it again.
#!/bin/sh
#
# /etc/cron.daily/dspam
#
# Michiel Broek, Arch Linux version (based on a Gentoo script).
LOGROTATE_AGE=30
SIGNATURE_AGE=90
PURGE_SCRIPT=/var/lib/dspam/mysql/purge-4.1.sql
# Idea from Gentoo script.
clean_mysql_drv()
{
if [ ! -e "/usr/bin/mysql" ]
then
echo "Can not run MySQL purge script: /usr/bin/mysql does not exist"
return 1
fi
if [ ! -f "$PURGE_SCRIPT" ]
then
echo "Can not run MySQL purge script: $PURGE_SCRIPT does not exist"
return 1
fi
# Get parameters from the config file
SQLSERVER=$(grep ^MySQLServer /etc/dspam/dspam.conf | cut -f 3)
SQLPORT=$(grep ^MySQLPort /etc/dspam/dspam.conf | cut -f 3)
SQLUSER=$(grep ^MySQLUser /etc/dspam/dspam.conf | cut -f 3)
SQLPASS=$(grep ^MySQLPass /etc/dspam/dspam.conf | cut -f 3)
SQLDB=$(grep ^MySQLDb /etc/dspam/dspam.conf | cut -f 3)
if [ ! -z "$(echo $SQLSERVER | grep ^/var)" ]
then
SQLCMD="/usr/bin/mysql --socket=${SQLSERVER} --user=${SQLUSER} \
--password=${SQLPASS}"
else
if [ -z "$SQLPORT" ]
then
SQLCMD="/usr/bin/mysql --host=${SQLSERVER} --user=${SQLUSER} \
--password=${SQLPASS}"
else
SQLCMD="/usr/bin/mysql --host=${SQLSERVER} --port=${SQLPORT} \
--user=${SQLUSER} --password=${SQLPASS}"
fi
fi
$SQLCMD ${SQLDB} < $PURGE_SCRIPT >/dev/null
}
run_dspam_clean()
{
if [ ! -e "/usr/bin/dspam_clean" ]
then
echo "Can not run DSPAM clean application:"
echo " /usr/bin/dspam_clean does not exist"
return 1
else
/usr/bin/dspam_clean -s${SIGNATURE_AGE} -p${SIGNATURE_AGE} \
-u${SIGNATURE_AGE},${SIGNATURE_AGE},${SIGNATURE_AGE},${SIGNATURE_AGE} \
>/dev/null 2>&1
return $?
fi
}
clean_mysql_drv
run_dspam_clean
# Rotate logs
su - dspam -c "umask 002 ; /usr/bin/dspam_logrotate \
-a ${LOGROTATE_AGE} -d /var/lib/dspam"
Download.
The complete set of configuration files is available in the next archive:
