Title: Обучаем антиспам с помощью Sieve в Dovecot Content: Вернуться к теме обучения антиспам-фильтров в Dovecot, которая ранее уже затрагивалась в одной из статей на этом сайте, меня заставило недавнее сообщение от всё помнящего "Charlie Root" прекращении поддержки широко используемого для этих нужд расширения Antispam plugin.
To: root@my.server
Subject: my.server weekly security run output
Message-Id: <E1dObLP-000MHX-25@my.server>
From: Charlie Root <root@my.server>
Date: Sat, 24 Jun 2017 05:02:43 +0200
Checking for packages with security vulnerabilities:
dovecot2-antispam-plugin-20130429_29: Tag: expiration_date Value: 2017-07-31
dovecot2-antispam-plugin-20130429_29: Tag: deprecated Value: Use pigeonhole instead. See https://wiki2.dovecot.org/HowTo/AntispamWithSieve
-- End of security output --
Действительно, благодаря наличию расширения протокола Sieve для IMAP согласно стандарту RFC6785 в Dovecot ничто не мешат использовать его для тех же задач. В качестве примера воспользуемся статьёй в wiki Dovecot и реализуем уже знакомый механизм отложенного пакетного обучения антиспам фильтра в комплексе Spamassassin.
Итак, имеем установленный Dovecot 2 последней на момент написания статьи версии в среде FreeBSD.
root@beta:~ # uname -v
FreeBSD 11.0-RELEASE-p9 #0: Tue Apr 11 08:48:40 UTC 2017 root@amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC
root@beta:~ # dovecot --version
2.2.30.2 (c0c463e)
Создадим необходимые для работы нового механизма настройки в конфигурационном файле Dovecot расположенном по стандартному пути /usr/local/etc/dovecot/dovecot.conf, не забыв удалить старые, относящиеся к Antispam plugin.
root@beta:/usr/local/etc/dovecot # cd /usr/local/etc/dovecot/
root@beta:/usr/local/etc/dovecot # diff -u dovecot.conf.bak dovecot.conf
--- dovecot.conf.bak 2017-06-24 13:52:23.656134000 +0200
+++ dovecot.conf 2017-06-24 15:28:18.465615000 +0200
@@ -134,13 +134,18 @@
# -- Spam autolearning
plugin {
- antispam_backend = mailtrain
- antispam_trash = Trash
- antispam_spam = Junk
- antispam_mail_sendmail = /usr/local/etc/dovecot/move-cmd.sh
- antispam_mail_spam = %u-report
- antispam_mail_notspam = %u-revoke
- antispam_mail_sendmail_args =
+ sieve_plugins = sieve_imapsieve sieve_extprograms
+ # From elsewhere to Spam folder
+ imapsieve_mailbox1_name = Junk
+ imapsieve_mailbox1_causes = COPY
+ imapsieve_mailbox1_before = file:/usr/local/etc/dovecot/report-spam.sieve
+ # From Spam folder to elsewhere
+ imapsieve_mailbox2_name = *
+ imapsieve_mailbox2_from = Junk
+ imapsieve_mailbox2_causes = COPY
+ imapsieve_mailbox2_before = file:/usr/local/etc/dovecot/report-ham.sieve
+ sieve_pipe_bin_dir = /usr/local/etc/dovecot
+ sieve_global_extensions = +vnd.dovecot.pipe
}
service auth {
@@ -209,7 +214,7 @@
}
protocol imap {
- mail_plugins = $mail_plugins antispam imap_acl imap_quota last_login
+ mail_plugins = $mail_plugins imap_sieve imap_acl imap_quota last_login
imap_client_workarounds = delay-newmail tb-extra-mailbox-sep
}
Здесь приведён вывод в формате программы diff с отличиями предыдущей конфигурации от новой, где минусом помечены удаляемые строки, а плюсом наоборот — добавляемые. Во-первых, из описания используемых расширений mail_plugins протокола IMAP плагин antispam заменён на imap_sieve. Далее, все упоминания расширения Antispam начинающиеся со строки antispam_ удалены и добавлены два блока обработки перемещений сообщений: в папку со спамом Junk (переменные imapsieve_mailbox1_) и, соответственно, из неё (imapsieve_mailbox1_), а также ряд необходимых для функционирования новой схемы переменных и расширений.
Каждый из обработчиков вызывает свой Sieve-скрипт.
root@beta:/usr/local/etc/dovecot # cat report-spam.sieve
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
if environment :matches "imap.user" "*" {
set "username" "${1}";
}
pipe :copy "move-cmd.sh" [ "${username}-report" ];
root@beta:/usr/local/etc/dovecot # cat report-ham.sieve
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
if environment :matches "imap.mailbox" "*" {
set "mailbox" "${1}";
}
if string "${mailbox}" "Trash" {
stop;
}
if environment :matches "imap.user" "*" {
set "username" "${1}";
}
pipe :copy "move-cmd.sh" [ "${username}-revoke" ];
Оба они передают обработку перемещаемого сообщения одному и тому же shell-скрипту move-cmd.sh, который ничем не отличается от ранее используемого совместно с раширением Antispam согласно описанного в статье "Отложенное пакетное обучение антиспам-фильтра используя Dovecot" механизма.
root@beta:/usr/local/etc/dovecot # ll move-cmd.sh
-rwxr-xr-x 1 mailnull mail 328 24 июня 14:46 move-cmd.sh*
root@beta:/usr/local/etc/dovecot # cat move-cmd.sh
#!/bin/sh
# Move message to temporary directory for learning
# (c)2016 by Max Kostikov http://kostikov.co e-mail: max@kostikov.co
dir="/var/spool/dovecot-learn" # directory for messages
log="/var/log/dovecot-learn.log"
now=$(date +"%F %T")
echo "$now MOVE $*-$$.msg" >> $log
cat<&0 >> $dir/$*-$$.msg
exit 0
Вкратце, он сохраняет перемещаемое сообщение в специальной папке, откуда впоследствии согласно расписанию в cron будет вызван пакетный обработчик learn-cmd.sh, который и передаст все накопленные сообщения на обучение Spamassassin.
root@beta:/usr/local/etc/dovecot # ll learn-cmd.sh
-rwxr-xr-x 1 mailnull mail 704 20 сент. 2016 learn-cmd.sh*
root@beta:/usr/local/etc/dovecot # cat learn-cmd.sh
#!/bin/sh
# Learn Spamassassin from temporary directory
# (c)2016 by Max Kostikov http://kostikov.co e-mail: max@kostikov.co
dir="/var/spool/dovecot-learn" # saved messages for learning
log="/var/log/dovecot-learn.log"
maxsize=2097152 # in bytes
for i in `ls ${dir}`;
do
tmp=`echo $i | sed 's|-[0-9]*\.msg$||'`
user=`echo $tmp | sed 's|-.*$||'` # get username
act=`echo $tmp | sed 's|^'$user'-||'` # get action (report for spam or revoke for ham)
now=$(date +"%F %T")
echo -n "$now LEARN $i: " >> $log
if [ $maxsize -gt `stat -f%z $dir/$i` ];
then
spamc -s $maxsize -u $user -C $act < $dir/$i >> $log
else
echo "skipped due exceed maximum size" >> $log
fi
rm -f $dir/$i
done
В данном случае используется универсальный клиент Spamassassin spamc, который во-первых, заметно быстрее традиционно применяемого для обучения клиента sa-learn, а, во-вторых, обладает дополнительным функционалом по отправке уведомлений о спаме во внешние системы фильтрации (детали см. в статье "Отправляем отчёты о спаме во внешние сервисы через Spamassassin"). Обратите внимание, что для реализации возможности обучения через него демон spamd должен быть запущен с ключом -l или --allow-tell.
Теперь осталось скомпилировать созданные sieve-скрипты в бинарную форму и перезапустить сервис Dovecot, попутно проверив наличие скрипта-обработчика в списке заданий cron.
root@beta:/usr/local/etc/dovecot # sievec report-spam.sieve
root@beta:/usr/local/etc/dovecot # sievec report-ham.sieve
root@beta:/usr/local/etc/dovecot # ll *.svbin
-rw-r--r-- 1 root mailnull 458 25 июня 13:17 report-ham.svbin
-rw-r--r-- 1 root mailnull 364 25 июня 13:17 report-spam.svbin
root@beta:/usr/local/etc/dovecot # cat /etc/crontab | grep learn-cmd
15 * * * * mailnull /usr/local/etc/dovecot/learn-cmd.sh >/dev/null 2>&1
root@beta:/usr/local/etc/dovecot # service dovecot restart
Stopping dovecot.
Waiting for PIDS: 10892.
Starting dovecot.
За результатами работы обработчиков можно, как и ранее, наблюдать в файле протокола /var/log/dovecot-learn.log.
root@beta:/usr/local/etc/dovecot # tail /var/log/dovecot-learn.log
2017-06-24 17:19:47 MOVE foo@my.server-report-1134.msg
2017-06-24 18:15:00 LEARN foo@my.server-report-1134.msg: Message successfully reported/revoked
Ну и, в качестве финальной точки, удаляем ставший уже ненужным Antispam plugin.
root@beta:/usr/local/etc/dovecot # pkg delete dovecot2-antispam-plugin
Checking integrity... done (0 conflicting)
Deinstallation has been requested for the following 1 packages (of 0 packages in the universe):
Installed packages to be REMOVED:
dovecot2-antispam-plugin-20130429_29
Number of packages to be removed: 1
Proceed with deinstalling packages? [y/N]: y
[1/1] Deinstalling dovecot2-antispam-plugin-20130429_29...
[1/1] Deleting files for dovecot2-antispam-plugin-20130429_29: 100%
Задача решена!