RSpamD¶
Setting up Redis¶
We'll first create separate Redis instances specifically for Rspamd. We'll create one for the bayes engine, one for fuzzy storage, and one for caching.
Further information: https://rspamd.com/doc/tutorials/redis_replication.html
Enter a sudo shell and install Redis and a secure password generator:
sudo -s
apt update && apt install redis-server pwgen
We'll first make a few tweaks to the system for an optimal Redis setup.
Add the following line to sysctl.conf:
nano /etc/sysctl.conf
net.core.somaxconn = 1024
vm.overcommit_memory=1
Now install hugepages and configure as follows:
apt update && apt install libhugetlbfs-bin
hugeadm --thp-never
Make sure /etc/rc.local exists and, if not, then create it as follows:
nano /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
exit 0
Add the hugepages command to the file using the following line:
/bin/sed -i '$i /usr/bin/hugeadm --thp-never' /etc/rc.local
Make the file executable:
chmod +x /etc/rc.local
And now restart rc-local:
systemctl restart rc-local
First we'll create a common configuration file for all instances:
mv /etc/redis/redis.conf /etc/redis/common.conf
Open this file and comment out any unixsocket, bind, or port lines. We also change protected mode to 'no':
nano /etc/redis/common.conf
#bind 127.0.0.1 ::1
#port 6379
# unixsocket /var/run/redis/redis-server.sock
# unixsocketperm 700
protected-mode no
Generate a secure password:
pwgen -Bvsc 64 1
This results in something like the following:
rtVh7zMTFHWm7HWVFXfcgNLXXtjC9scTt4mHVwjnrvqwsJ9qv9CjdwcCWtpqNVbL
Create the master Rspamd configuration file:
nano /etc/redis/redis-rspamd.conf
Enter the following, using the password you generated above:
#
# Redis Master configuration
# for Rspamd Modules
# Ratelimit, Greylisting, DMARC, Replies, IP score, Multimap, MX Check
#
include /etc/redis/common.conf
# Listen on localhost
bind 127.0.0.1 ::1
port 6380
unixsocket /var/run/redis-rspamd/redis-server.sock
unixsocketperm 700
daemonize yes
supervised systemd
pidfile /var/run/redis-rspamd/redis-server.pid
loglevel notice
logfile /var/log/redis/redis-rspamd.log
dbfilename dump-rspamd.rdb
requirepass rtVh7zMTFHWm7HWVFXfcgNLXXtjC9scTt4mHVwjnrvqwsJ9qv9CjdwcCWtpqNVbL
# maxmemory <bytes>
# maxmemory-policy noeviction
# maxmemory-samples 5
Create another password and use it with the Rspamd Bayesian configuration file:
nano /etc/redis/redis-rspamd-bayes.conf
Enter the following, using the new password:
#
# Redis Master configuration
# for Rspamd Bayesian statistic Module
#
include /etc/redis/common.conf
# Listen on localhost
bind 127.0.0.1 ::1
port 6381
unixsocket /var/run/redis-rspamd-bayes/redis-server.sock
unixsocketperm 700
daemonize yes
supervised systemd
pidfile /var/run/redis-rspamd-bayes/redis-server.pid
loglevel notice
logfile /var/log/redis/redis-rspamd-bayes.log
dbfilename dump-rspamd-bayes.rdb
requirepass rtVh7zMTFHWm7HWVFXfcgNLXXtjC9scTt4mHVwjnrvqwsJ9qv9CjdwcCWtpqNVbL
# maxmemory <bytes>
# maxmemory-policy noeviction
# maxmemory-samples 5
Create another password and use it with the Rspamd Bayesian configuration file:
nano /etc/redis/redis-rspamd-fuzzy.conf
Enter the following, using the new password:
#
# Redis Master configuration
# for Rspamd Fuzzy Module
#
include /etc/redis/common.conf
# Listen on localhost
bind 127.0.0.1 ::1
port 6382
unixsocket /var/run/redis-rspamd-fuzzy/redis-server.sock
unixsocketperm 700
daemonize yes
supervised systemd
pidfile /var/run/redis-rspamd-fuzzy/redis-server.pid
loglevel notice
logfile /var/log/redis/redis-rspamd-fuzzy.log
dbfilename dump-rspamd-fuzzy.rdb
requirepass rtVh7zMTFHWm7HWVFXfcgNLXXtjC9scTt4mHVwjnrvqwsJ9qv9CjdwcCWtpqNVbL
# maxmemory <bytes>
# maxmemory-policy noeviction
# maxmemory-samples 5
Make a copy of the pre-installed service file:
cp /lib/systemd/system/redis-server@.service /etc/systemd/system/
remove the existing unneeded service file:
mv /etc/systemd/system/redis.service ~/redis.service.bak
Edit the new service file:
nano /etc/systemd/system/redis-server@.service
Make sure it's set as follows:
# Templated service file for redis-server(1)
#
# Each instance of redis-server requires its own configuration file:
#
# $ cp /etc/redis/redis.conf /etc/redis/redis-myname.conf
# $ chown redis:redis /etc/redis/redis-myname.conf
#
# Ensure each instance is using their own database:
#
# $ sed -i -e 's@^dbfilename .*@dbfilename dump-myname.rdb@' /etc/redis/redis-myname.conf
#
# We then listen exlusively on UNIX sockets to avoid TCP port collisions:
#
# $ sed -i -e 's@^port .*@port 0@' /etc/redis/redis-myname.conf
# $ sed -i -e 's@^\(# \)\{0,1\}unixsocket .*@unixsocket /var/run/redis-myname/redis-server.sock@' /etc/redis/redis-myname.conf
#
# ... and ensure we are logging, etc. in a unique location:
#
# $ sed -i -e 's@^logfile .*@logfile /var/log/redis/redis-server-myname.log@' /etc/redis/redis-myname.conf
# $ sed -i -e 's@^pidfile .*@pidfile /var/run/redis-myname/redis-server.pid@' /etc/redis/redis-myname.conf
#
# We can then start the service as follows, validating we are using our own
# configuration:
#
# $ systemctl start redis-server@myname.service
# $ redis-cli -s /var/run/redis-myname/redis-server.sock info | grep config_file
#
# -- Chris Lamb <lamby@debian.org> Mon, 09 Oct 2017 22:17:24 +0100
[Unit]
Description=Advanced key-value store (%I)
After=network.target
Documentation=http://redis.io/documentation, man:redis-server(1)
[Service]
Type=forking
ExecStart=/usr/bin/redis-server /etc/redis/redis-%i.conf
ExecStop=/bin/kill -s TERM $MAINPID
PIDFile=/var/run/redis-%i/redis-server.pid
TimeoutStopSec=0
Restart=always
User=redis
Group=redis
RuntimeDirectory=redis-%i
RuntimeDirectoryMode=2755
UMask=007
PrivateTmp=yes
LimitNOFILE=65535
PrivateDevices=yes
ProtectHome=yes
ReadOnlyDirectories=/
ReadWriteDirectories=-/var/lib/redis
ReadWriteDirectories=-/var/log/redis
ReadWriteDirectories=-/var/run/redis-%i
NoNewPrivileges=true
CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE
MemoryDenyWriteExecute=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictRealtime=true
RestrictNamespaces=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
# redis-server can write to its own config file when in cluster mode so we
# permit writing there by default. If you are not using this feature, it is
# recommended that you replace the following lines with "ProtectSystem=full".
ProtectSystem=full
ReadWriteDirectories=-/etc/redis
[Install]
WantedBy=multi-user.target
Change permissions on the configuration files and reload systemd:
chown -Rc redis:redis /etc/redis
systemctl daemon-reload
Enable and start the services
systemctl enable redis-server@rspamd redis-server@rspamd-bayes redis-server@rspamd-fuzzy
systemctl start redis-server@rspam*.service --all
Check that the service are running with:
ps aux | grep redis
or
service redis-server@rspam* status
RSpamd Installation and Initial Configuration¶
Install dependencies (if you haven't already installed them):
apt install software-properties-common lsb-release wget
And add the Rspamd repository:
wget -O- https://rspamd.com/apt-stable/gpg.key | apt-key add -
echo "deb [arch=amd64] http://rspamd.com/apt-stable/ $(lsb_release -cs) main" | tee -a /etc/apt/sources.list.d/rspamd.list
Update the apt cache and install:
apt update && apt install rspamd
Instead of modifying the stock config files we will create new files in the /etc/rspamd/local.d/
directory which will overwrite the default setting.
/etc/rspamd/local.d/worker-normal.inc
contains information about the port on which Rspamd listens. Create the following file to configure the Rspamd normal worker to listen only to localhost interface:
nano /etc/rspamd/local.d/worker-normal.inc
and enter the following:
bind_socket = "127.0.0.1:11333";
bind_socket = "[::1]:11333";
Configure a proxy between Postfix and Rspamd, it listens on port 11332 and uses milter to communicate between the two tools. Edit the file /etc/rspamd/local.d/worker-proxy.inc
:
nano /etc/rspamd/local.d/worker-proxy.inc
and enter the following:
bind_socket = "127.0.0.1:11332";
bind_socket = "[::1]:11332";
milter = yes;
timeout = 120s;
upstream "local" {
default = yes;
self_scan = yes;
}
Set an encrypted password for the worker:
rspamadm pw --encrypt -p your_secret_password
obviously replacing 'your_secret_password' with your password of choice.
Copy the output into /etc/rspamd/local.d/worker-controller.inc
nano /etc/rspamd/local.d/worker-controller.inc
bind_socket = "127.0.0.1:11334";
bind_socket = "[::1]:11334";
bind_socket = "/tmp/rspamd-controller.sock mode=0666 owner=_rspamd";
password = "$2$khz7u8nxgggsfay3qta7ousbnmi1skew$zdat4nsm7nd3ctmiigx9kjyo837hcjodn1bob5jaxt7xpkieoctb";
Set the milter headers in the file /etc/rspamd/local.d/milter_headers.conf
:
nano /etc/rspamd/local.d/milter_headers.conf
use = ["x-spamd-bar", "x-spam-level", "authentication-results"];
Configuring Rspamd to use Redis¶
Configure redis to be used with rspamd by creating the following 3 files:
nano /etc/rspamd/local.d/redis.conf
Change the password to the one set in the corresponding redis config...
servers = "localhost:6380";
timeout = 1s;
db = "0";
password = "opHequ75iJgKnc7AyNJp995jhbzTKOSr";
nano /etc/rspamd/local.d/classifier-bayes.conf
Change the password to the one set in the corresponding redis config...
backend = "redis";
servers = "localhost:6381";
db = "0";
password = "opHequ75iJgKnc7AyNJp995jhbzTKOSr";
autolearn = true;
nano /etc/rspamd/override.d/worker-fuzzy.inc
Change the password to the one set in the corresponding redis config...
#
# Fuzzy Storage Master Worker on Charlotte
#
# Stores fuzzy hashes of messages.
# https://rspamd.com/doc/workers/fuzzy_storage.html
#
# number of worker instances to run
count = 1; # Disabled by default
# Listen on localhost
bind_socket = "127.0.0.1:11333";
bind_socket = "[::1]:11333";
# Store the hashes in Redis.
backend = 'redis';
servers = "localhost:6382";
timeout = 1s;
db = 0;
password = 'opHequ75iJgKnc7AyNJp995jhbzTKOSr';
# Expiration time of stored fuzzy hashes (default: 2 days)
expire = 90d;
# Allow localhost to perform changes to fuzzy storage.
allow_update = "127.0.0.1, ::1";
Finally, add the user '_rspamd' to the group 'redis':
usermod -a -G redis _rspamd
Adding Headers¶
Ww can add more information like the router the email travelled or extended headers added by the various mail server on the way to the destination. Such extended headers begin with an “X-“. rspamd can add such headers to help you filter out spam. We can do that by creating a new override file:
nano /etc/rspamd/override.d/milter_headers.conf
Add the following content to the file:
extended_spam_headers = true;
Restart RSpamd:
systemctl restart rspamd
Configuring Postfix¶
We need to configure Postfix to use the Rspamd milter.
Run the following commands to update the Postfix main configuration file:
postconf -e "milter_protocol = 6"
postconf -e "milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}"
postconf -e "milter_default_action = accept"
postconf -e "smtpd_milters = inet:127.0.0.1:11332"
postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
Restart the Postfix service for changes to take effect:
systemctl restart postfix
Configuring Dovecot¶
Next we configure Dovecot to use Rspamd.
Open the file /etc/dovecot/conf.d/20-lmtp.conf
and edit is as follows:
nano /etc/dovecot/conf.d/20-lmtp.conf
protocol lmtp {
postmaster_address = postmaster@example.com
mail_plugins = $mail_plugins sieve
}
Open the file /etc/dovecot/conf.d/20-imap.conf
and edit is as follows:
nano /etc/dovecot/conf.d/20-imap.conf
protocol imap {
mail_plugins = $mail_plugins imap_quota imap_sieve
}
Edit the file /etc/dovecot/conf.d/20-managesieve.conf
as follows:
nano /etc/dovecot/conf.d/20-managesieve.conf
service managesieve-login {
inet_listener sieve {
port = 4190
}
}
service managesieve {
process_limit = 1024
}
Open and edit the file /etc/dovecot/conf.d/90-sieve.conf
as follows:
nano /etc/dovecot/conf.d/90-sieve.conf
plugin {
# sieve = file:~/sieve;active=~/.dovecot.sieve
sieve_plugins = sieve_imapsieve sieve_extprograms
sieve_after = /etc/dovecot/sieve-after
sieve = file:/var/mail/vmail/sieve/%d/%n/scripts;active=/var/mail/vmail/sieve/%d/%n/active-script.sieve
# From elsewhere to Junk folder
imapsieve_mailbox1_name = Spam
imapsieve_mailbox1_causes = COPY
imapsieve_mailbox1_before = file:/etc/dovecot/sieve/learn-spam.sieve
# From Junk folder to elsewhere
imapsieve_mailbox2_name = *
imapsieve_mailbox2_from = Spam
imapsieve_mailbox2_causes = COPY
imapsieve_mailbox2_before = file:/etc/dovecot/sieve/learn-ham.sieve
sieve_pipe_bin_dir = /etc/dovecot/sieve
sieve_global_extensions = +vnd.dovecot.pipe
}
Create a directory for the sieve scripts:
mkdir -p /etc/dovecot/sieve-after
Create a global sieve filter in the file /etc/dovecot/sieve-after/spam-to-folder.sieve
. It will move emails marked as spam directly to the spam folder:
nano /etc/dovecot/sieve-after/spam-to-folder.sieve
require ["fileinto","mailbox"];
if anyof(
header :contains ["X-Spam-Flag"] "YES",
header :contains ["X-Spam"] "Yes",
header :contains ["Subject"] "*** SPAM ***"
)
{
fileinto :create "Spam";
stop;
}
Compile the script:
sievec /etc/dovecot/sieve-after/spam-to-folder.sieve
Create a new directory /etc/dovecot/sieve
to put the sieve files in:
mkdir /etc/dovecot/sieve
Create a script, named /etc/dovecot/sieve/learn-spam.sieve
, that will be triggered each time when you manually move an email into the spam folder:
nano /etc/dovecot/sieve/learn-spam.sieve
require ["vnd.dovecot.pipe", "copy", "imapsieve"];
pipe :copy "rspamd-learn-spam.sh";
Create a script, named /var/mail/vmail/sieve/global/report-ham.sieve
, that will be triggered each time when you move an email out of the spam folder:
nano /etc/dovecot/sieve/learn-ham.sieve
require ["vnd.dovecot.pipe", "copy", "imapsieve", "variables"];
if string "${mailbox}" "Trash" {
stop;
}
pipe :copy "rspamd-learn-ham.sh";
Restart Dovecot:
systemctl restart dovecot
Compile the sieve scripts and set permissions:
sievec /etc/dovecot/sieve/learn-spam.sieve
sievec /etc/dovecot/sieve/learn-ham.sieve
chmod u=rw,go= /etc/dovecot/sieve/learn-{spam,ham}.{sieve,svbin}
chown vmail.vmail /etc/dovecot/sieve/learn-{spam,ham}.{sieve,svbin}
And the last step is to create the simple shell scripts that do the actual spam/ham training.
nano /etc/dovecot/sieve/rspamd-learn-spam.sh
#!/bin/sh
exec /usr/bin/rspamc learn_spam
nano /etc/dovecot/sieve/rspamd-learn-ham.sh
#!/bin/sh
exec /usr/bin/rspamc learn_ham
and make them executable:
chmod u=rwx,go= /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh
chown vmail.vmail /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh
Restart Dovecot:
systemctl restart dovecot
Enable and restart Rspamd:
systemctl enable rspamd
systemctl restart rspamd
Creating DKIM Keys¶
This is not necessary if you've already configured DKIM using OpenDKIM. If this is the case then create the following:
nano /etc/rspamd/local.d/dkim_signing.conf
Enter the following line:
enabled = false;
If you wish to use RSpamd to deal with DKIM signing then follow the below steps:
First we create the folder to store our DKIM keys:
mkdir /var/lib/rspamd/dkim/
and then we create the keys for each of the domains that we handle, for example:
rspamadm dkim_keygen -b 2048 -s mail -d example.com -k /var/lib/rspamd/dkim/example.com.mail.key | tee -a /var/lib/rspamd/dkim/example.com.mail.pub
rspamadm dkim_keygen -b 2048 -s mail -d another-example.com -k /var/lib/rspamd/dkim/another-example.com.mail.key | tee -a var/lib/rspamd/dkim/another-example.com.mail.pub
The public and private keys should now be stored in /var/lib/rspamd/dkim/
We now change the permissions of the directory for security:
chown -R _rspamd: /var/lib/rspamd/dkim
find /var/lib/rspamd/dkim -name "*.key" -exec chmod 440 {} \;
find /var/lib/rspamd/dkim -name "*.pub" -exec chmod 440 {} \;
and finally we configure RSpamd so it knows where to find the keys:
nano /etc/rspamd/local.d/dkim_signing.conf
Enter the following text:
path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector_map = "/etc/rspamd/dkim_selectors.map";
allow_username_mismatch = true;
Create /etc/rspamd/dkim_selectors.map
:
nano /etc/rspamd/dkim_selectors.map
example.com mail
another-example.com mail
and restart RSpamd:
systemctl restart rspamd
DNS entries will also need to be entered using whichever DNS manager you use. For each of the domains you manage, run the following command:
cat /var/lib/rspamd/dkim/example.com.mail.pub
This will output something like the following:
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqdBRCqYzshc4LmmkxUkCH/rcIpSe/QdNIVmBrgqZmZ5zzWQi7ShdFOH7V32/VM1VRk2pkjDV7tmfbwslsymsfxgGhVHbU0R3803uRfxAiT2mYu1hCc9351YpZF4WnrdoA3BT5juS3YUo5LsDxvZCxISnep8VqVSAZOmt8wFsZKBXiIjWuoI6XnWrzsAfoaeGaVuUZBmi4ZTg0O4yl"
"nVlIz11McdZTRe1FlONOzO7ZkQFb7O6ogFepWLsM9tYJ38TFPteqyO3XBjxHzp1AT0UvsPcauDoeHUXgqbxU7udG1t05f6ab5h/Kih+jisgHHF4ZFK3qRtawhWlA9DtS35DlwIDAQAB"
) ;
The pieces inside the quotes need to be concatenated together and entered as a TXT DNS record with the name mail._domainkey
for example:
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqdBRCqYzshc4LmmkxUkCH/rcIpSe/QdNIVmBrgqZmZ5zzWQi7ShdFOH7V32/VM1VRk2pkjDV7tmfbwslsymsfxgGhVHbU0R3803uRfxAiT2mYu1hCc9351YpZF4WnrdoA3BT5juS3YUo5LsDxvZCxISnep8VqVSAZOmt8wFsZKBXiIjWuoI6XnWrzsAfoaeGaVuUZBmi4ZTg0O4ylnVlIz11McdZTRe1FlONOzO7ZkQFb7O6ogFepWLsM9tYJ38TFPteqyO3XBjxHzp1AT0UvsPcauDoeHUXgqbxU7udG1t05f6ab5h/Kih+jisgHHF4ZFK3qRtawhWlA9DtS35DlwIDAQAB
Configuring Nginx¶
To access the RSpamD web interface, we need to create a website in Nginx.
First we'll use acme.sh to create the certificates for the site. Change to root user with:
su -
Issue the RSA certificates with:
~/.acme.sh/acme.sh --issue --dns dns_cloudns -d rspamd.example.com --keylength 4096 --key-file /etc/letsencrypt/rsa-certs/rspamd.example.com/privkey.pem --ca-file /etc/letsencrypt/rsa-certs/rspamd.example.com/chain.pem --cert-file /etc/letsencrypt/rsa-certs/rspamd.example.com/cert.pem --fullchain-file /etc/letsencrypt/rsa-certs/rspamd.example.com/fullchain.pem --pre-hook "mkdir -p /etc/letsencrypt/rsa-certs/rspamd.example.com" --post-hook "find /etc/letsencrypt/rsa-certs/rspamd.example.com/ -name '*.pem' -type f -exec chmod 600 {} \;" --renew-hook "find /etc/letsencrypt/rsa-certs/rspamd.example.com/ -name '*.pem' -type f -exec chmod 600 {} \; -exec service nginx reload \;"
and ECC certificates with:
~/.acme.sh/acme.sh --issue --dns dns_cloudns -d rspamd.example.com --keylength ec-384 --key-file /etc/letsencrypt/ecc-certs/rspamd.example.com/privkey.pem --ca-file /etc/letsencrypt/ecc-certs/rspamd.example.com/chain.pem --cert-file /etc/letsencrypt/ecc-certs/rspamd.example.com/cert.pem --fullchain-file /etc/letsencrypt/ecc-certs/rspamd.example.com/fullchain.pem --pre-hook "mkdir -p /etc/letsencrypt/ecc-certs/rspamd.example.com" --post-hook "find /etc/letsencrypt/ecc-certs/rspamd.example.com/ -name '*.pem' -type f -exec chmod 600 {} \;" --renew-hook "find /etc/letsencrypt/ecc-certs/rspamd.example.com/ -name '*.pem' -type f -exec chmod 600 {} \; -exec service nginx reload \;"
Exit root by typing exit
.
Create the file as follows:
nano /etc/nginx/sites-available/rspamd.example.com
and enter the following (see the Nginx tutorial for more information on the includes):
server {
listen 99 ssl http2;
listen [::]:99 ssl http2;
server_name rspamd.example.com;
client_max_body_size 10M;
ssl_certificate /etc/letsencrypt/rsa-certs/rspamd.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/rsa-certs/rspamd.example.com/privkey.pem;
ssl_certificate /etc/letsencrypt/ecc-certs/rspamd.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/ecc-certs/rspamd.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/ecc-certs/rspamd.example.com/chain.pem;
include /etc/nginx/custom-config/ssl.conf;
include /etc/nginx/custom-config/header.conf;
location / {
include /etc/nginx/custom-config/proxy.conf;
proxy_pass http://127.0.0.1:11334;
client_max_body_size 10M;
}
}
I have used a different port. This way I have more control over security and I can restrict the port to my own static IP addresses. It's a good idea to do this with any server management web tools such as PHPMyAdmin and Webmin.
Enable the website:
ln -s /etc/nginx/sites-available/rspamd.example.com /etc/nginx/sites-enabled/
and reload nginx
service nginx reload
The website is accessed using the password you configured at the start of this guide.
Using ClamAV¶
This step only applies if you have installed and are running ClamAV.
Add x-virus to the milter headers in the file /etc/rspamd/local.d/milter_headers.conf
:
nano /etc/rspamd/local.d/milter_headers.conf
use = ["x-spamd-bar", "x-spam-level", "x-virus", "authentication-results"];
Create the file override.d/antivirus.conf
:
nano /etc/rspamd/override.d/antivirus.conf
Enter the following text:
clamav {
attachments_only = false;
symbol = "CLAM_VIRUS";
type = "clamav";
action = "reject";
servers = "/run/clamav/clamd.ctl";
}
Add the _rspamd user to the clamav group (required to access socket):
usermod -a -G clamav _rspamd
Reload Rspamd:
service rspamd reload
Explanation:
Attachment_only = false
defines whether just attachments are scanned or whether the entire email including images gets scanned.
symbol = "CLAM_VIRUS"
Adds a symbol named CLAM_VIRUS that can be used to assign scores or added as email headers.
type = "clamav"
sets a few defaults in the antivirus module that tell rspamd how to talk to ClamAV
action = "reject"
is an optional parameter that we use to instantly reject the email if a virus is found. We do not add a value to the spam score. Instead we refuse to accept the email during the incoming SMTP connection.
servers = "/var/run/clamav/clamd.ctl"
defines the way to communicate with ClamAV. In this case we tell it to use the Unix socket used by clamav-daemon
Testing
Now we can test the virus scanner configuration and make sure it's working. First we download a test signature to use:
wget https://secure.eicar.org/eicar.com
And then we can use the swaks utility to send a test email:
apt update && apt install swaks
swaks --to user@example.org --attach - --server localhost < eicar.com`
Swaks' primary design goal is to be a flexible, scriptable, transaction-oriented SMTP test tool. It handles SMTP features and extensions such as TLS, authentication, and pipelining; multiple version of the SMTP protocol including SMTP, ESMTP, and LMTP; and multiple transport methods including UNIX-domain sockets, internet-domain sockets, and pipes to spawned processes.
Further Reading: http://www.jetmore.org/john/code/swaks/latest/doc/ref.txt
Other Modules¶
Greylisting¶
Create the greylist.conf file:
nano /etc/rspamd/local.d/greylist.conf
Enter the following line:
servers = "localhost:6380";
To whitelist certain domains, create the file greylist-whitelist-domains.inc:
nano /etc/rspamd/local.d/greylist-whitelist-domains.inc
and simply add domainsn that you wish to whitelist, for example:
gmail.com
hotmail.com
github.com
outlook.com
Phishing¶
To enable the use of the openphish.com database, create the phishing.conf file:
nano /etc/rspamd/local.d/phishing.conf
Enter the following line:
openphish_enabled = true;
Firewall¶
RSpamd needs to be able to communicate to the RSpamd server on destination port 11335. Add the following rule to iptables to allow this:
iptables -A OUTPUT ! -o lo -p udp -d 88.99.142.95 -m conntrack --ctstate NEW -m udp --dport 11335 -j ACCEPT -m comment --comment "RSpamd"
Spam Training¶
Method 1: Untroubled.org¶
Spam archives can be found at http://untroubled.org/spam/
An example of using one of them to train RSpamd follows:
First install p7zip:
apt update && apt install p7zip p7zip-full
Create a spam directory and move into it:
mkdir ~/spam && cd ~/spam
Download an archive:
wget http://untroubled.org/spam/2020-01.7z
Extract the archive:
7z x 2020-01.7z
Learn the spam:
rspamc learn_spam ~/spam/2020/01/
repeat the steps with as many archives as you want.
You'll probably also want to exclude this spam directory from any virus scans you do in the future.
Method 2: GMail¶
If your gmail account collects quite a decent amount of spam, then its possible to export the spam folder using Google Takeout and getting RSpamd to learn from it.
First of all, you'll probably want to have a trawl through the gmail spam folder and delete any emails that shouldn't be classed as spam.
Once you're happy that your spam folder contains nothing but spam, go to Google Takeout here:
https://takeout.google.com/settings/takeout?pli=1
Under the 'Select data to include' section, click 'Deselect all'
Scroll down and tick the box to the right of 'Mail'
Click on the button beneath that currently says 'All Mail data included'
Make sure everything is unticked except 'Spam'
Click 'OK' and then 'Next Step'
Choose the option to send a download link to email and proceed
Once you've got the download link, download and then send the file to your server using whichever method you're comfortable with ie sftp, ssh, rsync, etc...
I personally uploaded the file to my Nextcloud and then copied it from there to my home directory.
Assuming that the takeout file is now in your home directory, unzip the archive to the spam directory (created in method 2):
Use the appropriate line depending on whether your archive is a zip or a tgz
unzip takeout-20200402T110047Z-001.zip -d ~/spam
tar -zvxf takeout-20200402T110047Z-001.zip -C ~/spam
Install mb2md. This utility converts mbox format mail archives to the maildir format that RSpamd understands.
apt update && apt install mb2md
Now use the utility to convert the mbox file to maildir:
mb2md -s ~/spam/Takeout/Mail/ -d ~/spam
And finally, have RSpamd learn the spam:
rspamc learn_spam ~/spam/.Spam_mbox/cur/