Фильтрация спама при помощи системы rspamd.
  1. История и предпосылки создания.
    Мы долгое время использовали для фильтрации спама spamassassin, однако, при
    наших объемах почтового трафика (9-10 миллионов писем в сутки) spamassassin
    не обеспечивал достаточной производительности. После анализа исходного кода
    и принципов работы было выявлены следующие "врожденные" проблемы SA:

    *   обработка письма осуществляется набором регулярных выражений, однако,
        количество этих выражений слишком велико и является ключевым моментом
        задумчивости SA (например, для извлечения received заголовков письма, SA
        проверяет оные на соответствие всем ему известным MTA, очевидно, что
        такое действие не является оптимальным);

    *   нет возможности явно получить ip адрес, с которого нам отправили письмо
        (в SA это делается парсом received заголовков, что я лично не считаю
        правильным, а тем более оптимальным способом, так как MTA всегда знает,
        откуда ему пришло данное письмо)

    *   нет возможности передачи спам фильтру данных SMTP диалога

    *   MIME парсинг писем очень медленный, так как опять же сделан на базе
        регулярных выражений

    В итоге можно сказать, что основная проблема SA - это излишняя увлеченность
    авторов регулярными выражениями и отсутствие оптимизации. В итоге, в
    качестве базовых принципов создания rspamd были принципы оптимизации времени
    обработки писем, в числе которых:

    *   полностью асинхронная работа с сетью (на базе libevent), в том числе DNS
        запросы и работа с http

    *   быстрые механизмы выделения памяти

    *   компиляция всех регулярных выражений и вызов только тех из них, которые
        наиболее возможны (то есть, имеется механизм ведения статистики
        срабатывания различных правил, и при обработке следующего письма
        учитывается обработка предыдущих, что позволяет максимально быстро
        провести основные тесты)

    *   расширяемая архитектура: возможность написания плагинов на си, lua,
        возможность добавления новых типов фильтров, расширений протокола
        rspamc, возможность добавления новых типов статистических алгоритмов,
        алгоритмов нормализации и парсинга текстов

    *   возможность динамической загрузки различных настроек, списков ip адресов
        и прочей информации через HTTP протокол с поддержкой даты модификации
        таких списков

    *   использование везде, где возможно, специализированных конечных автоматов
        для разбора и анализа текстов

    *   использование быстрого mime парсера gmime

    В результате перехода с SA на rspamd последний показал в среднем в 10 раз
    более быструю обработку сообщений. В данный момент rspamd имеет статус бета
    версии, но вполне пригоден для работы.

  2. Установка и настройка rspamd
    Для сборки rspamd вам потребуются:

    libevent <http://www.monkey.org/~provos/libevent/> - библиотека для
    асинхронной обработки событий
    glib <http://library.gnome.org/devel/glib/> - библиотека общего назначения,
    содержащая многие вещи, о которых разработчики libc, увы, забыли (glib не
    является графической библиотекой, хотя и используется, например, gtk)
    gmime <http://spruce.sourceforge.net/gmime/> - MIME парсер на базе
    библиотеки glib
    lua <http://www.lua.org/> - встраиваемый скриптовый язык (в принципе,
    наличие lua необязательно, но без lua многий функционал rspamd останется
    нереализованным)
    perl <http://www.perl.org/> - на перле написан, например, консольный клиент
    rspamc, распознаватель редиректов в URL'ях, поэтому наличие перла в системе
    крайне желательно
    cmake <http://www.cmake.org/> - система сборки, которая позволяет rspamd
    собираться (по крайней мере, в теории) на всех Posix совместимых системах.
    Использовать стандартные в данной ситуации autotools я не стал, так как
    считаю их самой неудобной в использовании системой сборки исходников,
    которую можно только придумать.
    mercurial <http://mercurial.selenic.com/> - система управления версиями
    (SCM), используемая для разработки rspamd. Так как в настоящее время rspamd
    находится в состоянии бета-версии, то релизы выходят нечасто и зачастую
    являются менее стабильными, чем текущая версия в репозитории, поэтому для
    установки rspamd лучше использовать версию непосредственно из репозитория.

    После установки всех требуемых программ и библиотек можно приступить
    непосредственно к установке rspamd.

    1) скачиваем текущее состояние репозитория: $ hg clone
    http://rspamd.hg.sourceforge.net:8000/hgroot/rspamd/rspamd
    2) конфигурируем rspamd: $ cd rspamd && cmake . (при необходимости изменить
    параметры можно вначале воспользоваться командой ccmake .)
    3) собираем: $ make
    4) устанавливаем: # make install

   Конфигурирование
    В процессе установки ставятся конфигурационные файлы по умолчанию в каталог
    {PREFIX}/etc. При этом, в каталог etc/rspamd устанавливаются правила по
    умолчанию (headers, html, drugs, loto и.т.п.), а в каталог
    etc/rspamd.conf.sample устанавливается конфигурационный файл по умолчанию.
    Его можно скопировать в файл etc/rspamd.conf и отредактировать в
    соответствии с собственными предпочтениями. Конфигурационный файл по
    умолчанию снабжен комментариями к каждой директиве, а также подробно описан
    в документации к rspamd, находящейся в каталоге исходников doc/rspamd.pdf. В
    данном же руководстве подробно изложен принцип работы rspamd и настройки
    всех модулей системы. Для базовой работы достаточно исправить пути к файлам
    логов, пидфайлу, а также обратить внимание на разделы factors и classifiers.
    Остановлюсь на этом несколько подробнее.

    Все директивы rspamd имеют формат param = value; где символ ';' является
    признаком окончания директивы. Также файл разбит на секции, каждая секция
    имеет имя (например worker {}) и внутренние директвы внутри фигурных скобок.
    После каждой секции также обязателен символ ';'. Также каждый модуль имеет
    особый формат секции:

.module 'name' {
	param = value;
};
    Все это может показаться сложным на первый взгляд, но это позволяет лучше
    структурировать файл и облегчает расширяемость rspamd. Для первоначальной
    настройки достаточно обратить внимание на раздел factors, который описывает
    веса различных правил, раздел metric, который описывает максимальный вес,
    чтобы письмо считалось спамом, а также на раздел classifiers. Раздел
    classifiers обеспечивает работу статистических алгоритмов. В rspamd в
    настоящее время реализован алгоритм winnow, который работает следующим
    образом:

    1) текст разбивается на слова, также выделяется окно в пять слов
    2) окно перемещается по словам, при этом выделяются словосочетания по
    определенному алгоритму и вычисляется их хеш
    3) каждый полученный таким образом хеш проверяется в файле статистики, в
    котором хранятся хеши и их веса, если хеш найден, то его вес добавляется к
    суммарному весу данного файла
    4) файл, набравший в сумме больше веса считается классом письма

    Основная идея такого подхода в определении по словосочетаниям, к какому
    классу принадлежит данное письмо. В SA для этой цели используется
    вероятностный алгоритм bayes, который достаточно похож на вышеописанный, но
    считает не веса, а вероятности. Эффективность каждого из алгоритмов примерно
    одинакова и зависит в основном от эффективности обучения. Однако, в отличие
    от SA, rspamd использует не отдельные слова, а словосочетания, что повышает
    его эффективность. В секции classifiers можно установить различные классы
    писем, а далее в секции factors указать их вес (задав, например, для
    заведомо безвредных писем - ham - отрицательный вес). Размер файлов
    статистики должен быть разумно большим для хранения как можно большего числа
    хешей. Однако, необходимо учитывать, что эти файлы целиком загружаются в
    память (хотя, реализация отображения файла в памяти в различных ОС допускает
    загрузку и выгрузку страниц этого файла в своп системы, но эффективность
    этого довольно низка), поэтому необходимо соизмерять размер оперативной
    памяти и файлов статистики.

  4. Подключение и проверка работоспособности rspamd
    Для проверки работы системы rspamd проще всего воспользоваться командой
    rspamc:

hostname:~> rspamc stat
Do rspamc command stat
Messages scanned: 1234040
Messages learned: 59151
Connections count: 1176623
Control connections count: 59152
Pools allocated: 2530714
Pools freed: 2530699
Bytes allocated: 66991793394
Memory chunks allocated: 6453232
Shared chunks allocated: 3
Chunks freed: 6453090
Oversized chunks: 468849
Statfile: WINNOW_HAM (version 69); length: 100.0 MB; free blocks: 4563488; total blocks: 6553581; free: 69.63%
Statfile: WINNOW_SPAM (version 36383); length: 100.0 MB; free blocks: 760504; total blocks: 6553581; free: 11.60%
    В данном случае выводится общая статистика. Такого же эффекта можно
    достигнуть командой telnet на порт процесса controller (он описан в
    конфигурационном файле в секции worker, type у которого controller). По
    умолчанию это порт 11334 на адресе 127.0.0.1. Работу правил и статистики
    можно также проверить по команде rspamc:

~> rspamc symbols /tmp/mailman.eml 
Processing /tmp/mailman.eml
Process file: /tmp/mailman.eml
Sending 4950 bytes...
RSPAMD/1.1 0 OK
Metric: default; False; -3.35 / 10.00 / 0.00
Symbol: WINNOW_HAM; 5.00
Symbol: RECEIVED_RBL; pbl.spamhaus.org,insecure-bl.rambler.ru
Urls: 
    В данном случае показываются баллы, набранные письмом, а также
    дополнительная информация. Подробнее о протоколе rspamc в документации
    (doc/rspamd.pdf). Для подключения rspamd к MTA лучше всего использовать
    milter, если ваш MTA postfix или sendmail. В качестве milter'а можно
    использовать, например, rmilter: <https://www.milter.org/milter/71/>. О
    настройке postfix + rmilter мной была написана следующая заметка:
    <http://cebka.pp.ru/blog/2009/02/-nginxpostfixrmilter.html> Для MTA exim
    можно воспользоваться файлом local_scan.c в каталоге contrib/exim.
    Инструкции по его установке описаны в самом файле, однако, это требует
    пересборки MTA. Также rspamd "понимает" протокол SA, поэтому для подключения
    rspamd можно использовать те же средства, что и для подключения к MTA SA.

    Подробнее о командах rspamc и протоколе rspamc написано опять же в
    документации.

  5. Обучение rspamd
    Процесс обучения важен для корректной работы статистики. Для обучения
    используется команда rspamc learn. Для указания файла (класса) письма
    используется ключ -s. Пример использования:

~> rspamc -s WINNOW_HAM learn /tmp/mailman.eml
Processing /tmp/mailman.eml
Process file: /tmp/mailman.eml
Do rspamc command learn
Sending 4950 bytes...
Learn succeed. Sum weight: 128.48
    В качестве параметров можно указывать несколько файлов, целые каталоги, а
    также imap папки:

~> rspamc -s WINNOW_SPAM learn imaps:user:cebka:password::host:somehost.rambler.ru:mbox:abuse.spam
Processing imaps:user:cebka:password::host:mailsupport.rambler.ru:mbox:abuse.spam
Enter IMAP password: 
Process imap: host: somehost.rambler.ru, mbox: abuse.spam
Do rspamc command learn
Sending 382650 bytes...
Learn succeed. Sum weight: 1850.24
<skipped>
    При обучении необходимо учитывать, чтобы количество spam и ham писем было
    примерно равным. Вес показывает суммарный вес словосочетаний текста, который
    был до обучения данным письмом (то есть, то, насколько велика вероятность
    принадлежности данного письма к этому классу). При обнаружении неверных
    срабатываний статистики можно несколько раз применить learn к заданному
    письму, проверяя его суммарный вес.

  6. Поддержка и дальнейшие действия
    Если вы решили использовать rspamd для обработки вашей почты, то лучшим
    источником информации будет являться документация к rspamd, а также примеры
    lua плагинов: etc/plugins/lua. Целью же данной статьи является ознакомление
    с основными приемами по установке, конфигурированию и обучению rspamd, а
    также описание преимуществ rspamd по сравнению с SA. Если на любом этапе
    работы с rspamd у вас возникает проблема, то можно о ней сообщить мне:
    <mailto:vsevolod@highsecure.ru> или же в список рассылки rspamd на
    sourceforge (англоговорящий): <mailto:rspamd-devel@lists.sourceforge.net>.
    Сама система rspamd находится в состоянии бета-версии, поэтому ваша помощь в
    тестировании и запросы функциональности будут неоценимы в развитии rspamd.