#LyX 1.6.4 created this file. For more info see http://www.lyx.org/ \lyxformat 345 \begin_document \begin_header \textclass book \begin_preamble \usepackage{indentfirst} \frenchspacing \end_preamble \use_default_options false \language russian \inputencoding utf8 \font_roman cmr \font_sans cmss \font_typewriter cmtt \font_default_family sfdefault \font_sc false \font_osf false \font_sf_scale 100 \font_tt_scale 100 \graphics default \paperfontsize default \spacing single \use_hyperref true \pdf_title "Rspamd" \pdf_author "Vsevolod Stakhov" \pdf_bookmarks true \pdf_bookmarksnumbered true \pdf_bookmarksopen false \pdf_bookmarksopenlevel 1 \pdf_breaklinks false \pdf_pdfborder true \pdf_colorlinks true \pdf_backref false \pdf_pdfusetitle true \papersize a4paper \use_geometry false \use_amsmath 0 \use_esint 0 \cite_engine basic \use_bibtopic false \paperorientation portrait \secnumdepth 3 \tocdepth 3 \paragraph_separation indent \defskip medskip \quotes_language french \papercolumns 1 \papersides 1 \paperpagestyle fancy \tracking_changes false \output_changes false \author "" \author "" \end_header \begin_body \begin_layout Title Руководство по системе фильтрации спама rspamd. \end_layout \begin_layout Date 22.03.2010 \end_layout \begin_layout Author Стахов Всеволод. \end_layout \begin_layout Standard \begin_inset CommandInset toc LatexCommand tableofcontents \end_inset \end_layout \begin_layout Standard \end_layout \begin_layout Chapter Общая информация и возможности rspamd \end_layout \begin_layout Standard Rspamd - это система, предназначенная для фильтрации спама. Изначально rspamd разрабатывался как фильтр для электронной почты, но он может применяться и для другого типа сообщений (например, для jabber или icq сообщений). В основе rspamd лежит концепция асинхронной обработки входящих сообщений. Для этого применяется библиотека libevent. Это накладывает определенные ограничения на возможности rspamd, так как для любой блокирующей операции (например, чтение из сетевого сокета) необходимо регистрировать отдельное событие и его обработчика, но дает преимущества в скорости работы системы и уменьшает различные служебные затраты (например, на создание процессов или потоков). Rspamd поддерживает встроенные фильтры на языке lua, что позволяет писать собственные фильтры без необходимости пересборки системы. Rspamd настраивается путем редактирования конфигурационного файла. Также имеется управляющий интерфейс, посредством которого можно различным образом управлять работой системы и получать ее текущее состояние. Rspamd поддерживает различные типы фильтров: фильтры на основе регулярных выражений, фильтры на основе DNS запросов, фильтры на основе статистики, фильтры по различным спискам и другие типы фильтров (например, фильтры, написанные на языке lua и выполняющие различные действия по анализу сообщений). Rspamd имеет протокол, совместимый с системой spamassassin (в дальнейшем протокол spamc), а также его расширение - rspamc, позволяющее передавать больше информации фильтру, что ускоряет обработку сообщений. Система rspamd состоит из двух основных частей: монитор процессов и процессы, осуществляющие обработку (workers). Монитор процессов отвечает за старт системы, открытие/закрытие журналов работы, а также обеспечивает непрерывную работу рабочих процессов и их перезапуск при необходимости. \end_layout \begin_layout Chapter Установка rspamd \end_layout \begin_layout Section Требования \end_layout \begin_layout Itemize GNU C компилятор (работоспособность проверялась на gcc 4.2.1) \end_layout \begin_layout Itemize cmake - \begin_inset CommandInset href LatexCommand href name "http://cmake.org/" target "http://cmake.org/" \end_inset используется для конфигурации сборки и генерации Makefile. Необходимая версия - не менее 2.6. \end_layout \begin_layout Itemize glib - \begin_inset CommandInset href LatexCommand href name "http://ftp.gnome.org/" target "http://ftp.gnome.org/pub/GNOME/sources/glib/2.20/" \end_inset используется для различного рода утилит и структур хранения данных (хеши, деревья, списки). Необходимая версия - не менее 2.16. \end_layout \begin_layout Itemize gmime - \begin_inset CommandInset href LatexCommand href name "http://ftp.acc.umu.se" target "http://ftp.acc.umu.se/pub/GNOME/sources/gmime/2.2/" \end_inset используется для разбора mime структуры сообщений. Необходимая версия 2.2. Работа с gmime 2.4 и старше не проверялась. \end_layout \begin_layout Itemize lua - \begin_inset CommandInset href LatexCommand href name "http://www.lua.org/" target "http://www.lua.org/download.html" \end_inset используется для работы lua плагинов (без liblua работа rspamd возможна, но без поддержки lua плагинов). Версия необходима не меньше, чем 5.1. \end_layout \begin_layout Itemize libevent - \begin_inset CommandInset href LatexCommand href name "http://www.monkey.org/~provos/libevent/" target "http://www.monkey.org/~provos/libevent/" \end_inset используется для кросс-платформенной обработки асинхронных событий, а также для определения DNS имен (также асинхронного). \end_layout \begin_layout Section Установка \end_layout \begin_layout Standard Для сборки rspamd необходимо скачать архив (самая свежая версия может быть найдена на \begin_inset CommandInset href LatexCommand href name "http://cebka.pp.ru/distfiles/" target "http://cebka.pp.ru/distfiles/" \end_inset ). После этого необходимо распаковать архив и скомпилировать код: \end_layout \begin_layout LyX-Code $ tar xzf rspamd-x.x.x.tar.gz \end_layout \begin_layout LyX-Code $ cd rspamd-x.x.x \end_layout \begin_layout LyX-Code $ cmake . \end_layout \begin_layout LyX-Code $ make \end_layout \begin_layout Standard Установка осуществляется стандартным \end_layout \begin_layout LyX-Code # make install \end_layout \begin_layout Standard В процессе установки копируются исполняемые файлы rspamd: bin/rspamd и bin/rspam c, а также примеры конфигурации и плагины, устанавливающиеся в каталог etc/rspam d/. Также для ОС FreeBSD устанавливается стартовый скрипт rspamd.sh в каталог etc/rc.d. \end_layout \begin_layout Section Запуск \end_layout \begin_layout Standard Rspamd запускается либо из стартового скрипта, либо непосредственно вызовом rspamd. Доступные опции командной строки: \end_layout \begin_layout Code -h: Показать справочную информацию и выйти \end_layout \begin_layout Code -t: Проверить конфигурационный файл и выйти \end_layout \begin_layout Code -C: Показать содержимое кеша символов и выйти \end_layout \begin_layout Code -V Показать все переменные rspamd и выйти \end_layout \begin_layout Code -f: Не выполнять демонизацию \end_layout \begin_layout Code -c: Указать путь до конфигурационного файла (по умолчанию используется /usr/local/etc/rspamd.conf) \end_layout \begin_layout Code -u: Пользователь, под которым осуществлять работу rspamd \end_layout \begin_layout Code -g: Группа, под которой осуществять работу rspamd \end_layout \begin_layout Standard Если rspamd запускается от суперпользователя, то после создания лог-файла, PID-файла, а также сокетов, принимающих соединения, осуществляется сброс привиллегий до пользователя и группы, указанных в опциях командной строки (таким образом, все рабочие процессы работают от указанного пользователя и группы). \end_layout \begin_layout Chapter Общие принципы работы \end_layout \begin_layout Standard Прежде чем приступать к настройке rspamd необходимо понять основные принципы функционирования системы. \end_layout \begin_layout Section Планирование и запуск рабочих процессов \end_layout \begin_layout Standard При запуске rspamd происходят следующие действия: \end_layout \begin_layout Enumerate Запускается главный процесс (rspamd main) \end_layout \begin_layout Enumerate Инициализируются конфигурационные параметры по умолчанию \end_layout \begin_layout Enumerate Читаются параметры командной строки \end_layout \begin_layout Enumerate Настраивается журналирование ошибок в терминал \end_layout \begin_layout Enumerate Читается и парсится конфигурационный файл \end_layout \begin_layout Enumerate Инициализируются модули \end_layout \begin_layout Enumerate Модули читают свои конфигурационные параметры \end_layout \begin_layout Enumerate Устанавливаются лимиты \end_layout \begin_layout Enumerate Настраивается журналирование, указанное в конфигурационном файле \end_layout \begin_layout Enumerate Происходит демонизация (если не указан флаг -f) \end_layout \begin_layout Enumerate Настраивается обработка сигналов головным процессом \end_layout \begin_layout Enumerate Записывается PID-файл \end_layout \begin_layout Enumerate Инициализируются lua плагины \end_layout \begin_layout Enumerate Инициализируется подсистема событий и mime парсер \end_layout \begin_layout Enumerate Загружается кеш символов \end_layout \begin_layout Enumerate Порождаются рабочие процессы (сброс привиллегий осуществляется сразу же после вызова fork) \end_layout \begin_layout Enumerate Начинается цикл обработки сигналов \end_layout \begin_layout Standard Головной процесс rspamd реагирует на следующие сигналы: \end_layout \begin_layout Itemize SIGTERM - послать всем рабочим процессам SIGTERM, дождаться их завершения и выйти \end_layout \begin_layout Itemize SIGINT - то же, что и SIGTERM \end_layout \begin_layout Itemize SIGHUP - переинициализировать журналирование и породить новые рабочие процессы, завершив старые (при этом, существующие рабочие процессы завершают работу, обработав уже полученные соединения) \end_layout \begin_layout Itemize SIGCHLD - головной процесс получает этот сигнал при завершении работы рабочего процесса. Если рабочий процесс завершился некорректно, то планируется его перезапуск через 2 секунды. \end_layout \begin_layout Itemize SIGUSR2 - приходит от рабочего процесса, когда тот успешно инициализируется \end_layout \begin_layout Itemize SIGALARM - сигнализирует о необходимости запуска рабочего процесса, который был запланирован после получения SIGCHLD \end_layout \begin_layout Standard Таким образом, головной процесс отвечает за инициализацию, конфигурацию, работу с PID-файлом, работу с журналированием, а также за порождение рабочих процессов. В ходе работы головной процесс постоянно следит за работой рабочих процессов и обеспечивает перезапуск некорректно завершившихся рабочих процессов. Для ротации файлов журналирования рабочему процессу необходимо послать сигнал SIGHUP. \end_layout \begin_layout Section Логика обработки сообщений \end_layout \begin_layout Standard Инициализация рабочего процесса предельно проста: происходит переинициализация libevent, а также инициализация DNS resolver'а. После этого рабочий процесс устанавливает обработчик готовности к чтению слушающего сокета (этот сокет создается в головном процессе и передается рабочему процессу как параметр). При готовности к чтению на слущающем сокете рабочий процесс создает новый объект типа worker_task и делается accept на слушающем сокете. После этого rspamd обрабатывает протокол rspamc (или же spamc) и читает сообщение. После окончания получения сообщения rspamd декодирует его содержимое и начинает обработку. Для более простого изложения принципов работы rspamd необходимо описать некоторые понятия: \end_layout \begin_layout Itemize Символ - это правило фильтрации rspamd, например, некоторое регулярное выражение или же запрос к DNS или же любое другое действие. Символ имеет собственный вес и имя. Таким образом, символ можно считать результатом работы одного правила фильтраци и. Если это правило сработало, то оно добавляет символ с определенным весом и атрибутами, если нет, то символ не добавляется. \end_layout \begin_layout Itemize Метрика - это набор логически связанных правил и связанных с ними символов. Такая группа имеет свой предел очков, после набора которых сообщение считается по этой метрике спамом. Очки формируются после подсчета весов символов, добавленных в метрику (при этом, разумеется, несработавшие правила символов не добавляют и их вес равен нулю) и обработки этих весов функцией консолидации. По умолчанию такой функцией является функция-факторизатор, которая просто считает вес каждого символа равным константе, заданной в конфигурационном файле для этого символа, например, следующие параметры в конфигурационном файле задают вес символа MIME_HTML_ONLY равный одному, а вес символа FAKE_HTML - восьми: \end_layout \begin_layout LyX-Code "MIME_HTML_ONLY" = 1; \end_layout \begin_layout LyX-Code "FAKE_HTML" = 8; \end_layout \begin_layout Itemize Модуль - это набор правил rspamd, который обеспечивает общие проверки. Например, модуль проверки регулярных выражений или модуль проверки URL'ей по \begin_inset Quotes eld \end_inset черным \begin_inset Quotes erd \end_inset спискам. Модули также могут быть написаны на языке LUA. Каждый модуль регистрирует символы, соответствующие сконфигурированным в нем правилам, в таблице символов заданной метрики (или метрики по умолчанию \begin_inset Quotes eld \end_inset default \begin_inset Quotes erd \end_inset ). \end_layout \begin_layout Itemize Таблица символов метрики - это таблица, хранящая данные о зарегистрированных символах, таблица отсортирована, чтобы обеспечить проверку самых \begin_inset Quotes eld \end_inset удобных \begin_inset Quotes erd \end_inset правил в первую очередь. Критерий \begin_inset Quotes eld \end_inset удобности \begin_inset Quotes erd \end_inset составляется из трех составляющих: веса правила, частоты его срабатывания и времени его выполнения. Чем больше вес, частота срабатывания и меньше время выполнения, тем раньше будет проверено это правило. \end_layout \begin_layout Itemize Классификатор - это алгоритм, обеспечивающий определение принадлежности сообщения к какому-либо классу. Класс определяется символом (например символ SPAM, имеющий вес 5 и символ HAM, имеющий вес -5). Принадлежность к классу обеспечивается либо статистически, путем разбора текста сообщения на токены и сравнения с известными токенами, хранящимися на диске в виде файла токенов (statfile), либо же иным алгоритмом (например, нейросетью). В результате работы классификатора определяется соответствие сообщения какому-либо классу и добавления соответствующего этому классу символа. Классификатор отличается от обычного модуля тем, что он не просто проверяет какие-либо характеристики сообщения, а сравнивает содержание сообщения с известными ему наборами. То есть, классификатор для его работы необходимо обучать на различных наборах. В настоящее время в rspamd реализован алгоритм классификации winnow и разбора на токены OSB. О них будет написано в дальнейшем. \end_layout \begin_layout Standard Обработка осуществляется по следующей логике: \end_layout \begin_layout Itemize для каждой метрики выбирается таблица символов и выбираются по очереди символы (по степени \begin_inset Quotes eld \end_inset удобности \begin_inset Quotes erd \end_inset ) \end_layout \begin_layout Itemize для каждого символа вызывается соответствующее правило \end_layout \begin_layout Itemize после вызова очередного правила проверяется, не превысил ли результат метрики порогового результата \end_layout \begin_layout Itemize при превышении порога сообщение считается по этой метрике спамом и больше символов из этой метрики не проверяется \end_layout \begin_layout Itemize для сообщения проверяется принадлежность к какому-либо классу для корректировки результата \end_layout \begin_layout Itemize после определения принадлежности к классу происходит окончательный пересчет очков по метрике и при совпадении критериев автообучения происходит автообучени е классификатора \end_layout \begin_layout Standard После обработки сообщений для каждой из метрик выводится результат. Если используется протокол spamc, то считается только метрика \begin_inset Quotes eld \end_inset default \begin_inset Quotes erd \end_inset , а дополнительные метрики добавляются как заголовки вида X-Spam-Status: metric; result. Для протокола rspamc выводятся результаты всех метрик, что позволяет настраиват ь различные группы правил и осуществлять фильтрацию сообщений не только как spam/ham, а задавать различные критерии оценки. \end_layout \begin_layout Chapter Настройка rspamd \end_layout \begin_layout Section Общие правила настройки \end_layout \begin_layout Standard Файл конфигурации rspamd имеет следующий синтаксис: \end_layout \begin_layout LyX-Code param = value; \end_layout \begin_layout Standard Точка с запятой является обязательной в конце каждой директивы. Некоторые директивы являются составными и обрамляются фигурными скобками, например: \end_layout \begin_layout LyX-Code section { \end_layout \begin_deeper \begin_layout LyX-Code param = value; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard Также позволяется включать другие файлы (точка с запятой в конце директивы не нужна): \end_layout \begin_layout LyX-Code .include /path/to/file \end_layout \begin_layout Standard В конфигурационном файле допускается определять и использовать переменные: \end_layout \begin_layout LyX-Code $var = "some text"; \end_layout \begin_layout LyX-Code param = "${var}"; \end_layout \begin_layout Standard Приведенный фрагмент определяет переменную $var и присваивает параметру \begin_inset Quotes eld \end_inset param \begin_inset Quotes erd \end_inset значение \begin_inset Quotes eld \end_inset some text \begin_inset Quotes erd \end_inset . Переменные имеют глобальную область действия, обрамление переменных фигурными скобками при использовании (вида ${some_variable}) обязательно. Большинство строк конфигурационного файла обрамляется двойными кавычками. Одинарные кавычки применяются только при конфигурации модуля (это поведение подлежит пересмотру в следующих версиях): \end_layout \begin_layout LyX-Code .module 'name' { \end_layout \begin_deeper \begin_layout LyX-Code param = "value"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Subsection Определения списков \end_layout \begin_layout Standard В rspamd многие параметры задаются в виде списков. Списки задаются ссылкой на файл или же http ресурс. Основное отличие таких файлов в том, что rspamd проверяет изменения в таких файлах (примерно раз в минуту, используя случайный разброс) и перегружает списки при их модификации. Таким же образом организована загрузка списков через http, только вместо modification time используется HTTP 1.1 заголовок If-Modified-Since, в ответ на который http сервер может выдать ответ 304: Not modified, в таком случае rspamd не перечитывает список. Списками задаются те параметры, которые могут содержать много значений и которые могут часто меняться. Для того, чтобы не приходилось выполнять перезапуск rspamd списки перечитываютс я по мере их обновления. Определения списков выглядят следующим образом: \end_layout \begin_layout Itemize http список: \end_layout \begin_layout LyX-Code param = "http://test.ru:81/some/path.php"; \end_layout \begin_layout LyX-Code param = "http://test.ru/some/other.txt"; \end_layout \begin_layout Itemize file список: \end_layout \begin_layout LyX-Code param = "file:///var/run/rspamd/some.file"; \end_layout \begin_layout Section Общие параметры конфигурации \end_layout \begin_layout Standard Общие параметры не принадлежат никакой секции и позволяют задавать общие настройки системы. \end_layout \begin_layout Itemize pidfile - путь до PID-файла: \end_layout \begin_layout LyX-Code pidfile = "/var/run/rspamd.pid"; \end_layout \begin_layout Itemize statfile_pool_size - размер пула файлов статистики в памяти. Может быть с суффиксом, определяющим единицы измерение (по умолчанию байты): K - килобайты, M - мегабайты, G - гигабайты. \end_layout \begin_layout LyX-Code statfile_pool_size = 40M; \end_layout \begin_layout Itemize raw_mode - если этот параметр равен \begin_inset Quotes eld \end_inset yes \begin_inset Quotes erd \end_inset , то rspamd не осуществляет перекодировку сообщений в utf8, в этом режиме проверка сообщений осуществляется быстрее, но при этом одинаковые сообщения в разных кодировках будут обрабатываться как разные. \end_layout \begin_layout LyX-Code raw_mode = yes; \end_layout \begin_layout Itemize filters - строка, содержащая список включенных модулей, имена модулей разделяютс я запятыми и/или пробелами. \end_layout \begin_layout LyX-Code filters = "surbl,regexp,chartable,emails"; \end_layout \begin_layout Section Настройка процессов \end_layout \begin_layout Standard Данные секции служат для определения параметров рабочих процессов. Общие параметры рабочего процесса: \end_layout \begin_layout Itemize type - тип рабочего процесса: \end_layout \begin_deeper \begin_layout Itemize normal - обычный процесс обработки сообщений \end_layout \begin_layout Itemize controller - управляющий процесс \end_layout \begin_layout Itemize lmtp - процесс обработки сообщений по протоколу lmtp \end_layout \begin_layout Itemize fuzzy - хранилище хешей \end_layout \end_deeper \begin_layout LyX-Code type = "normal"; \end_layout \begin_layout Itemize bind_socket - параметры слушающего сокета процесса, может определять либо tcp сокет, либо unix сокет: \end_layout \begin_deeper \begin_layout Itemize host:port - осуществляет bind на указанные host и port \end_layout \begin_layout Itemize *:port - осуществляет bind на указанные port на всех локальных адресах \end_layout \begin_layout Itemize /path/to/socket - осуществляет bind на указанный unix socket \end_layout \end_deeper \begin_layout LyX-Code bind_socket = localhost:11334; \end_layout \begin_layout Itemize count - количество процессов данного типа. По умолчанию это число равно числу логических процессоров в системе. \end_layout \begin_layout LyX-Code count = 1; \end_layout \begin_layout Standard Для процессов типа \begin_inset Quotes eld \end_inset controller \begin_inset Quotes erd \end_inset можно также указать пароль для привиллегированных команд параметром password, а для процессов типа \begin_inset Quotes eld \end_inset fuzzy \begin_inset Quotes erd \end_inset необходимо указать путь к файлу, который будет использован как хранилище хешей параметром hashfile. Пример настройки рабочих процессов: \end_layout \begin_layout LyX-Code worker { \end_layout \begin_deeper \begin_layout LyX-Code type = "normal"; \end_layout \begin_layout LyX-Code count = 1; \end_layout \begin_layout LyX-Code bind_socket = *:11333; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code worker { \end_layout \begin_deeper \begin_layout LyX-Code type = "controller"; \end_layout \begin_layout LyX-Code bind_socket = localhost:11334; \end_layout \begin_layout LyX-Code count = 1; \end_layout \begin_layout LyX-Code password = "q1"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout LyX-Code worker { \end_layout \begin_deeper \begin_layout LyX-Code type = "fuzzy"; \end_layout \begin_layout LyX-Code bind_socket = localhost:11335; \end_layout \begin_layout LyX-Code count = 1; \end_layout \begin_layout LyX-Code hashfile = "/tmp/fuzzy.db"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Section Настройки журналирования \end_layout \begin_layout Standard Данные настройки определяют тип журналирования и его параметры. \end_layout \begin_layout Itemize log_type - тип журналирования: \end_layout \begin_deeper \begin_layout Itemize console - журналирование в stderr \end_layout \begin_layout Itemize syslog - журналирование через syslog \end_layout \begin_layout Itemize file - журналирование в файл \end_layout \end_deeper \begin_layout LyX-Code log_type = console; \end_layout \begin_layout Itemize log_level - уровень ведения журнала \end_layout \begin_deeper \begin_layout Itemize DEBUG - журналирование отладочной информации \end_layout \begin_layout Itemize INFO - журналирование информационных событий \end_layout \begin_layout Itemize WARN - журналирование только предупреждений \end_layout \begin_layout Itemize ERROR - журналирование только ошибок \end_layout \end_deeper \begin_layout LyX-Code log_level = INFO; \end_layout \begin_layout Itemize log_facility - используется для журналирования в syslog и определяет назначение сообщений. Более подробно об этом можно узнать из man syslog. \end_layout \begin_layout LyX-Code log_facility = "LOG_MAIL"; \end_layout \begin_layout Itemize log_file - используется для журналирования в файл и путь к файлу журнала. \end_layout \begin_layout LyX-Code log_file = "/var/log/rspamd.log"; \end_layout \begin_layout Standard Пример настройки журналирования: \end_layout \begin_layout LyX-Code logging { \end_layout \begin_deeper \begin_layout LyX-Code log_type = file; \end_layout \begin_layout LyX-Code log_level = INFO; \end_layout \begin_layout LyX-Code log_file = "/var/log/rspamd.log" \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Section Настройки метрики \end_layout \begin_layout Standard Для настроек метрик используются секции \begin_inset Quotes eld \end_inset metric \begin_inset Quotes erd \end_inset . Основные параметры метрик: \end_layout \begin_layout Itemize name - имя метрики. \end_layout \begin_layout LyX-Code name = "default"; \end_layout \begin_layout Itemize required_score - минимальное число очков, необходимое, чтобы сообщение считалось спамом по данной метрике. \end_layout \begin_layout LyX-Code required_score = 10; \end_layout \begin_layout Itemize cache_file - путь до файла, содержащего кеш символов метрики (используется, чтобы сохранить статистику \begin_inset Quotes eld \end_inset удобности \begin_inset Quotes erd \end_inset символов метрики, чтобы при перезапуске rspamd не терять накопленных данных). \end_layout \begin_layout LyX-Code cache_file = "/var/run/rspamd/metric.cache"; \end_layout \begin_layout Standard Пример настройки метрики: \end_layout \begin_layout LyX-Code metric { \end_layout \begin_deeper \begin_layout LyX-Code name = "default"; \end_layout \begin_layout LyX-Code required_score = 10.1; \end_layout \begin_layout LyX-Code cache_file = "/tmp/symbols.cache"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Section Настройка классификаторов \end_layout \begin_layout Standard Для настройки классификаторов используются секции \begin_inset Quotes eld \end_inset classifier \begin_inset Quotes erd \end_inset . Общие настройки классфикатора: \end_layout \begin_layout Itemize type - алгоритм классификатора (в настоящее время определен только \begin_inset Quotes eld \end_inset winnow \begin_inset Quotes erd \end_inset ). \end_layout \begin_layout LyX-Code type = "winnow"; \end_layout \begin_layout Itemize tokenizer - алгоритм разбиения сообщения на токены (в настоящее время определен только \begin_inset Quotes eld \end_inset osb-text \begin_inset Quotes erd \end_inset ). \end_layout \begin_layout LyX-Code tokenizer = "osb-text"; \end_layout \begin_layout Standard Также каждый классификатор может содержать определения классов и соответствующих им файлов токенов. Для этого используется подсекция statfile, содержащая следующие параметры: \end_layout \begin_layout Itemize symbol - имя класса и имя символа, используемого для данного класса. \end_layout \begin_layout LyX-Code symbol = "WINNOW_SPAM"; \end_layout \begin_layout Itemize path - путь до файла. \end_layout \begin_layout LyX-Code path = "/var/run/rspamd/winnow.spam"; \end_layout \begin_layout Itemize size - размер данного файла. Также может иметь суффикс размерности. \end_layout \begin_layout LyX-Code size = 100M; \end_layout \begin_layout Standard Внутри каждого определения класса можно использовать подсекцию autolearn, определяющую условия, при которых происходит автоматическое обучение данного класса. Секция имеет следующие параметры: \end_layout \begin_layout Itemize min_mark - минимальное число очков, при котором осуществляется обучение. \end_layout \begin_layout LyX-Code min_mark = 10.1; \end_layout \begin_layout Itemize max_mark - максимальное число очков, при котором осуществляется обучение. \end_layout \begin_layout LyX-Code max_mark = 0.1; \end_layout \begin_layout Standard Автообучение происходит, если данное сообщение отвечает данным критериям. То есть, логично обучать класификатор HAM сообщениями, указав максимальное количество очков, близкое к нулю и SPAM сообщениями, указав минимальное число очков, близкое к срабатыванию триггера SPAM для данной метрики. Таким образом, классифицируемые как спам сообщения обучают класс SPAM, а классифицируемые как HAM (то есть, на них не сработали правила метрики) - обучают класс HAM. \end_layout \begin_layout Standard Пример определения классификатора: \end_layout \begin_layout LyX-Code classifier { \end_layout \begin_deeper \begin_layout LyX-Code type = "winnow"; \end_layout \begin_layout LyX-Code tokenizer = "osb-text"; \end_layout \end_deeper \begin_layout LyX-Code \end_layout \begin_deeper \begin_layout LyX-Code statfile { \end_layout \begin_deeper \begin_layout LyX-Code symbol = "WINNOW_SPAM"; \end_layout \begin_layout LyX-Code path = "/tmp/test.spam"; \end_layout \begin_layout LyX-Code size = 10M; \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code autolearn { \end_layout \begin_deeper \begin_layout LyX-Code min_mark = 10.0; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code statfile { \end_layout \begin_deeper \begin_layout LyX-Code symbol = "WINNOW_HAM"; \end_layout \begin_layout LyX-Code path = "/tmp/test.ham"; \end_layout \begin_layout LyX-Code size = 10M; \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code autolearn { \end_layout \begin_deeper \begin_layout LyX-Code max_mark = 0.1; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Subsection Настройка синхронизации статистики \end_layout \begin_layout Standard Статистические данные можно синхронизировать между несколькими rspamd. Для этого используется master/slave синхронизация и бинарный лог изменений в статистическом файле. Для настройки синхронизации используются следующие параметры при определении статистического файла: \end_layout \begin_layout LyX-Code statfile { \end_layout \begin_deeper \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code binlog = "slave"; \end_layout \begin_layout LyX-Code binlog_master = "somehost:11334"; \end_layout \begin_layout LyX-Code ... \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code statfile { \end_layout \begin_deeper \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code binlog = "master"; \end_layout \begin_layout LyX-Code ... \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard При настройке slave для синхронизации указывается адрес master для данного файла. Этот адрес фактически является адресом контроллера, который сконфигурирован работать с данным файлом как master. Если rspamd настроен работать с данным файлом статистики как master, то создается специальный файл с таким же именем, как файл статистики, но имеющим суффикс .binlog. В данный файл записываются ревизии и изменения, внесенные в файл статистики. Данный файл хранит фиксированное число изменений и ротируется при переполнении. Синхронизация производится всеми slave хостами с промежутком от 1-й до 2-х минут. При этом, нет разницы, в каком состоянии был файл статистики на slave хосте - после синхронизации файл статистики на slave будет в точности совпадать с файлом статистики на master'е. Обновления файлов статистики являются инкрементальными, то есть передаются только изменения, а не файлы целиком. Синхронизация файлов статистики позволяет легко построить кластер rspamd, которые работают и обучаются идентично (хотя обучение должно производиться через контроллер мастера). \end_layout \begin_layout Section Настройка коэффициентов символов \end_layout \begin_layout Standard Для настройки коэффициентов применяется секция \begin_inset Quotes eld \end_inset factors \begin_inset Quotes erd \end_inset . Данная секция состоит из набора определений вида \end_layout \begin_layout LyX-Code "СИМВОЛ" = вес; \end_layout \begin_layout Standard например: \end_layout \begin_layout LyX-Code "R_UNDISC_RCPT" = 5; \end_layout \begin_layout LyX-Code "MISSING_MID" = 3; \end_layout \begin_layout LyX-Code "R_RCVD_SPAMBOTS" = 3; \end_layout \begin_layout LyX-Code "R_TO_SEEMS_AUTO" = 3; \end_layout \begin_layout LyX-Code "R_MISSING_CHARSET" = 5; \end_layout \begin_layout Standard В секции \begin_inset Quotes fld \end_inset factors \begin_inset Quotes frd \end_inset также можно задать параметр grow_factor, который задает коэффициент приращения при добавлении символов в метрику. Работает это так: допустим, добавляется первый символ - его реальный вес будет равен 1 * factor (то есть, если factor равен 1, то и реальный вес будет равен 1), после чего следующий символ будет иметь реальный вес grow_facto r * factor (например, если grow_factor = 1.1, то реальный вес будет 1.1 * factor), далее следующий будет иметь вес (1 + ((grow_factor) - 1)*2)*factor (то есть, при предыдущем grow_factor, реальный вес будет 1.2 * factor, следующий символ 1.3, затем 1.4 и.т.д.). Данная возможность позволяет увеличивать вес письмам, проходящим по нескольким правилам. Правила с отрицательным весом не увеличивают grow_factor и не модифицируются им (то есть, реальный вес таких правил равен 1 * factor). Пример задания параметра grow_factor: \end_layout \begin_layout LyX-Code grow_factor = 1.1; \end_layout \begin_layout Standard Также существует возможность создавать \begin_inset Quotes fld \end_inset составные \begin_inset Quotes frd \end_inset символы - символы, которые являются комбинацией других символов. Это нужно для возможности указывать, что комбинация определенных символов имеет больший (или, наоборот, меньший) вес, чем сумма весов нескольких символов. Составные символы представляют собой логические выражения из других символов, например: \end_layout \begin_layout LyX-Code composites { \end_layout \begin_deeper \begin_layout LyX-Code COMPOSITE_SYMBOL1 = \begin_inset Quotes fld \end_inset SYMBOL1 & (SYMBOL2 | SYMBOL3) \begin_inset Quotes frd \end_inset ; \end_layout \begin_layout LyX-Code COMPOSITE_SYMBOL2 = \begin_inset Quotes fld \end_inset SYMBOL3 & !SYMBOL4 \begin_inset Quotes frd \end_inset ; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard При добавлении составного символа все символы, входящие в него, удаляются из результата. То есть, при срабатывании COMPOSITE_SYMBOL1 из предыдущего примера символы SYMBOL1, SYMBOL2 и SYMBOL3 в ответе не появятся. \end_layout \begin_layout Section Представления и настройки \end_layout \begin_layout Subsection Представления \end_layout \begin_layout Standard В rspamd существует возможность настройки правил, которые будут проверяться, исходя из определенных критериев. Представления настраиваются в конфигурационном файле rspamd и позволяют разделить правила, исходя из входящих данных, например, заголовок From письма или же по ip, откуда нам пришло данное письмо. Представления проверяются при проверке любого правила и при совпадении данных письма проверяются не все символы, а те, которые заданы данным представл ением. При настройки представлений задаются входные данные письма (from и ip) и символы, которые должны проверяться. Входные данные могут дублироваться, то есть, можно задать несколько from и несколько ip, задаются эти параметры либо в виде регулярных выражений: \end_layout \begin_layout LyX-Code from = \begin_inset Quotes fld \end_inset /^.*@somedomain.com$ \begin_inset Quotes frd \end_inset ; \end_layout \begin_layout LyX-Code from = \begin_inset Quotes fld \end_inset /^.*@otherdoma[a-z]+.com$ \begin_inset Quotes frd \end_inset ; \end_layout \begin_layout Standard либо в виде map: \end_layout \begin_layout LyX-Code from = \begin_inset Quotes fld \end_inset file:///usr/local/etc/rspamd/from.map \begin_inset Quotes frd \end_inset ; \end_layout \begin_layout LyX-Code ip = \begin_inset Quotes fld \end_inset http://somehost:81/ip.map \begin_inset Quotes frd \end_inset ; \end_layout \begin_layout Standard Символы также могут быть заданы несколькими директивами symbols (которые будут объединены в список): \end_layout \begin_layout LyX-Code symbols = \begin_inset Quotes fld \end_inset /^.*URIBL.*$/ \begin_inset Quotes frd \end_inset ; \end_layout \begin_layout Standard Пример задания представления в конфигурационном файле: \end_layout \begin_layout LyX-Code view { \end_layout \begin_deeper \begin_layout LyX-Code ip = "file:///usr/local/etc/rspamd/ip_internal.inc"; \end_layout \begin_layout LyX-Code skip_check = yes; \end_layout \begin_layout LyX-Code from = "file:///usr/local/etc/rspamd/from_internal.inc"; \end_layout \begin_layout LyX-Code symbols = "/^.*URIBL.*$/"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard Директива \begin_inset Quotes fld \end_inset skip_check \begin_inset Quotes frd \end_inset используется для пропуска всех проверок rspamd для данного представлений. В результате при использовании протокола rspamc 1.1 вместо маркера спама (True или False) будет маркер пропуска (Skip). При использовании spamc или же rspamc 1.0 будет стандартный маркер False (так как реально у письма будет 0 баллов). \end_layout \begin_layout Subsection Пользовательские настройки \end_layout \begin_layout Standard Пользовательские настройки, в отличие от представлений, дают возможность выбора правил, а также настройки граничных значений баллов письма, исходя из получателя письма. При этом, настройки можно задавать индивидуально пользователю или же всему домену пользователя. Индивидуальные настройки пользователя перекрывают настройки домена. При выборе настроек используются следующие данные (учитывая последовательность) : \end_layout \begin_layout Enumerate проверяется заголовок Deliver-To, передаваемый при использовании протокола rspamc; \end_layout \begin_layout Enumerate проверяется заголовок User, передаваемый MTA exim при использовании любого протокола; \end_layout \begin_layout Enumerate проверяется первый получатель письма из заголовка rspamc Rcpt; \end_layout \begin_layout Enumerate проверяется первый получатель письма из заголовка mime To. \end_layout \begin_layout Standard Необходимо обратить внимание , что при наличии нескольких получателей, будет проверяться только первый из них, чтобы избегать двусмысленного поведения. Сами настройки задаются в json файлах, так как данные файлы могут содержать очень много информации о пользователях, и хранить это все в конфигурационном файле нецелесообразно. Для задания пользовательских настроек используется секция \begin_inset Quotes fld \end_inset settings \begin_inset Quotes frd \end_inset , которая содержит всего два параметра: user_settings и domain_settings. Например: \end_layout \begin_layout LyX-Code settings { \end_layout \begin_deeper \begin_layout LyX-Code user_settings = "http://somehost/users.php"; \end_layout \begin_layout LyX-Code domain_settings = "http://somehost/domains.php"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard Формат соответствующих json файлов достаточно прост - это массив объектов, задающих настройки. Объект настройки содержит следующие параметры: \end_layout \begin_layout Itemize name - имя пользователя или домена; \end_layout \begin_layout Itemize metrics - объект, задающий предельные очки по метрикам, вида \begin_inset Quotes fld \end_inset metric_name \begin_inset Quotes frd \end_inset -> score; \end_layout \begin_layout Itemize factors - объект, задающий индивидуальные настройки множителей вида \begin_inset Quotes fld \end_inset symbol \begin_inset Quotes frd \end_inset -> score; \end_layout \begin_layout Itemize want_spam - булево значение, при задании его как true, rspamd отключает проверки для данного пользователя. \end_layout \begin_layout Standard Пример json настроек: \end_layout \begin_layout LyX-Code [ \end_layout \begin_deeper \begin_layout LyX-Code { \end_layout \begin_deeper \begin_layout LyX-Code "name":"somedomain.ru", \end_layout \begin_layout LyX-Code "metrics":{"default":11}, \end_layout \begin_layout LyX-Code "factors":{"R_FUZZY":10.1}, \end_layout \begin_layout LyX-Code "want_spam":false \end_layout \end_deeper \begin_layout LyX-Code }, \end_layout \begin_layout LyX-Code { \end_layout \begin_deeper \begin_layout LyX-Code "name":"some.other.domain.com", \end_layout \begin_layout LyX-Code "metrics":{"default":5.5}, \end_layout \begin_layout LyX-Code "factors":{"URIBL":20.3}, \end_layout \begin_layout LyX-Code "want_spam":false \end_layout \end_deeper \begin_layout LyX-Code } \end_layout \end_deeper \begin_layout LyX-Code ] \end_layout \begin_layout Standard Файлы настроек перезагружаются по мере обновления, как и любые другие файлы списков. \end_layout \begin_layout Chapter Настройка модулей \end_layout \begin_layout Section Настройка модуля surbl \end_layout \begin_layout Standard Модуль surbl служит для проверки URL'ей в письме на различных \begin_inset Quotes eld \end_inset черных \begin_inset Quotes erd \end_inset списках. Модуль делает следующее: для каждого из url, найденных в сообщении, извлекает доменный компонент (2-го или 3-го уровня), добавляет суффикс имени surbl и делает dns запрос. При успешном определении такого имени добавляется символ. Пример работы: \end_layout \begin_layout LyX-Code URL (http://some.test.ru/index.html) -> test.ru + (insecure-bl.rambler.ru) -> \end_layout \begin_layout LyX-Code resolve test.ru.insecure-bl.rambler.ru -> 127.0.0.1 -> add symbol \end_layout \begin_layout Standard Параметры настройки: \end_layout \begin_layout LyX-Code .module 'surbl' { \end_layout \begin_deeper \begin_layout LyX-Code # Определение суффикса SURBL \end_layout \begin_layout LyX-Code # Символы '%b' заменяются на значение определенного бита \end_layout \begin_layout LyX-Code suffix_%b_SURBL_MULTI = "multi.surbl.org"; \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code # Суффикс для каждого из бит \end_layout \begin_layout LyX-Code bit_2 = "SC"; # sc.surbl.org \end_layout \begin_layout LyX-Code bit_4 = "WS"; # ws.surbl.org \end_layout \begin_layout LyX-Code bit_8 = "PH"; # ph.surbl.org \end_layout \begin_layout LyX-Code bit_16 = "OB"; # ob.surbl.org \end_layout \begin_layout LyX-Code bit_32 = "AB"; # ab.surbl.org \end_layout \begin_layout LyX-Code bit_64 = "JP"; # jp.surbl.org \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code # Имя метрики \end_layout \begin_layout LyX-Code metric = "default"; \end_layout \begin_layout LyX-Code # Список доменов, для которых необходимо использовать 3 доменных \end_layout \begin_layout LyX-Code # компонента, вместо двух \end_layout \begin_layout LyX-Code 2tld = "file:///etc/rspamd/2tld.inc"; \end_layout \begin_layout LyX-Code # Список URL'ей, которые не будут проверяться этим модулем \end_layout \begin_layout LyX-Code whitelist = "file:///etc/rspamd/surbl-whitelist.inc"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard Некоторые пояснения по данной конфигурации. Модуль SURBL может осуществлять проверку битов в полученном от DNS сервера ответе, и вставлять соответствующий символ. Это используется для проверки сразу нескольких списков одним DNS запросе. Тогда ответ сервера содержит списки, в которых встретился данный URL в виде битов адреса. Более подробно с этим можно ознакомиться тут: \begin_inset CommandInset href LatexCommand href name "http://www.surbl.org/lists.html#multi" target "http://www.surbl.org/lists.html#multi" \end_inset . Список 2tld используется для задания списка доменов, для которых необходимо проверять не два уровня доменного имени, а три. Например, это актуально для виртуальных хостингов или же специальных зон для доменов третьего уровня, например org.ru или pp.ru. \end_layout \begin_layout Section Настройка модуля regexp \end_layout \begin_layout Standard Модуль regexp является очень важным в работе rspamd, так как определяет все правила фильтрации сообщений по регулярным выражениям. Модуль работает с логическими выражениями из регулярных выражений, поэтому его настройка выглядит достаточно запутанной. Однако, если пользоваться переменными, то логика работы становится более понятной. При настройке самого модуля используются простые директивы вида: \end_layout \begin_layout Code ИМЯ_СИМВОЛА = "логическое выражение" \end_layout \begin_layout Standard Само логическое выражение содержит различные регулярные выражения и функции, объединенные символами логики: \end_layout \begin_layout Itemize & - логическое \begin_inset Quotes eld \end_inset И \begin_inset Quotes erd \end_inset \end_layout \begin_layout Itemize | - логическое \begin_inset Quotes eld \end_inset ИЛИ \begin_inset Quotes erd \end_inset \end_layout \begin_layout Itemize ! - логическое отрицание \end_layout \begin_layout Standard Приоритет операций может изменяться скобками, например: \end_layout \begin_layout LyX-Code A & B | C - выполняется слева направо A & B затем | C \end_layout \begin_layout LyX-Code A & (B | C) - выполняется как (B | C) затем & A \end_layout \begin_layout Standard Сами регулярные выражения совместимы с perl regular expressions. Их синтаксис можно изучить в соответствующей литературе: \begin_inset CommandInset href LatexCommand href name "http://perldoc.perl.org/perlre.html" target "http://perldoc.perl.org/perlre.html" \end_inset . У rspamd есть дополнительные флаги, определяющие, в какой части сообщения искать заданное регулярное выражение: \end_layout \begin_layout Itemize r - "сырой" незакодированный в utf8 regexp \end_layout \begin_layout Itemize H - ищет по заголовкам сообщения \end_layout \begin_layout Itemize M - ищет по всему сообщению (в "сыром" виде, то есть без mime декодинга) \end_layout \begin_layout Itemize P - ищет по всем текстовым mime частям \end_layout \begin_layout Itemize U - ищет по url \end_layout \begin_layout Itemize X - ищет по "сырым" хедерам (опять же без декодирования) \end_layout \begin_layout Standard Если в регулярном выражении встречаются символы двойной кавычки ( \begin_inset Quotes eld \end_inset ) или же слэша (/), то их необходимо экранировать обратным слэшем (при этом сам обратный слэш экранировать необязательно): \end_layout \begin_layout LyX-Code \backslash " \backslash / \end_layout \begin_layout Standard Для поиска по заголовкам формат регулярного выражения несколько меняется: \end_layout \begin_layout LyX-Code Имя_заголовка=/регулярное_выражение/H \end_layout \begin_layout Standard При поиске по заголовкам происходит поиск заголовков с таким именем и сравнение их значений с регулярным выражением, пока это выражение не будет найдено, либо пока не будут проверены все заголовки с таким именем. Для multipart сообщений происходит поиск заголовков по всем частям сообщения. Это справедливо для всех функций, работающих с заголовками. Поиск по \begin_inset Quotes eld \end_inset сырым \begin_inset Quotes erd \end_inset заголовкам происходит без учета mime частей - только по заголовкам самого сообщения. При этом, хотя и не происходит декодирования заголовков, но происходит их де-фолдинг (фолдинг - перенос заголовков по строчкам). Модуль regexp также может использовать внутри логических выражений встроенные функции rspamd. Встроенные функции всегда возвращат логическое значение (истина или ложь) и могут принимать аргументы (в том числе аргументы, являющиеся логическими выражениями). Список встроенных функций: \end_layout \begin_layout Itemize header_exists - принимает в качестве аргумента имя хедера, возвращает true, если такой заголовок существует \end_layout \begin_layout Itemize compare_parts_distance - принимает в качестве аргумента число от 0 до 100, которое отражает разницу в процентах между частями письма. Функция работает с сообщениями, содержащими 2 текстовые части (text/plain и text/html) и возвращает true тогда, когда эти части различаются более чем на n процентов. Если аргумент не указан, то по умолчанию ищется различие в 100% (полностью разные части). \end_layout \begin_layout Itemize compare_transfer_encoding - сравнивает Content-Transfer-Encoding с заданной строкой \end_layout \begin_layout Itemize content_type_compare_param - сравнивает параметр content-type заголовка с регулярным выражением или строкой: \end_layout \begin_layout LyX-Code content_type_compare_param(Charset, /windows- \backslash d+/) \end_layout \begin_layout LyX-Code content_type_compare_param(Charset, ascii) \end_layout \begin_layout Itemize content_type_has_param - проверяет, есть ли в заголовке content-type определенны й параметр \end_layout \begin_layout Itemize content_type_is_subtype - сравнивает подтип content-type с регулярным выражением или строкой \end_layout \begin_layout Itemize content_type_is_type - сравнивает тип content-type с регулярным выражением или строкой \end_layout \begin_layout LyX-Code content_type_is_type(text) \end_layout \begin_layout LyX-Code content_type_is_subtype(/?.html/) \end_layout \begin_layout Itemize regexp_match_number - принимает в качестве первого параметра число, которое означает порог сработавших регэкспов и список регэкспов или функций, которые должны проверяться. Если число сработавших регэкспов или функций больше порога, функция возвращает TRUE, иначе - FALSE, например: \end_layout \begin_layout LyX-Code regexp_match_number(2, ${__RE1}, ${__RE2}, header_exists(Subject)) \end_layout \begin_layout Itemize has_only_html_part - функция возвращает TRUE, если в сообщении есть только одна HTML часть \end_layout \begin_layout Itemize compare_recipients_distance - вычисляет процент схожих получателей письма. Принимает аргумент - порог в процентах похожести. \end_layout \begin_layout Itemize is_recipients_sorted - возвращает TRUE, если список получателей сортирован (работает только если число получателей >= 5). \end_layout \begin_layout Itemize is_html_balanced - возвращает TRUE, если теги всех html частей сбалансированы \end_layout \begin_layout Itemize has_html_tag - возвращает TRUE, если заданный html тег найден \end_layout \begin_layout Standard Данные функции были созданы для решения задач, которые сложно или же невозможно решить при помощи обычных регулярных выражений. При конфигурации модуля regexp целесообразно определить все логические выражения в отдельных переменных, подключить их при помощи директивы .include и задавать символы как: \end_layout \begin_layout LyX-Code СИМВОЛ="${переменная}"; \end_layout \begin_layout Standard иначе конфигурация модуля будет практически нечитаемой из-за обилия регулярных выражений. \end_layout \begin_layout Section Настройка модуля spf \end_layout \begin_layout Standard Модуль spf предназначен для проверки spf записей для отправителя письма. Технология SPF позволяет определить в DNS TXT запись для данного домена с определениями, с каких ip адресов или сетей допустима отправка почты для данного домена. Также spf позволяет создавать \begin_inset Quotes fld \end_inset черные списки \begin_inset Quotes frd \end_inset для данного домена - адреса, с которых запрещена отправка почты для домена. Rspamd может получать spf записи, и проверять, возможна ли отправка почты данного домена с данного ip. При этом возможно добавление 3-х символов: \end_layout \begin_layout Itemize FAIL - отправка запрещена \end_layout \begin_layout Itemize SOFTFAIL - отправка явно не разрешена, но и явно не запрещена \end_layout \begin_layout Itemize ALLOW - отправка явно разрешена \end_layout \begin_layout Standard Для задания этих символов можно использовать настройки модуля spf: \end_layout \begin_layout LyX-Code .module 'spf' { \end_layout \begin_deeper \begin_layout LyX-Code symbol_fail = "SPF_FAIL"; \end_layout \begin_layout LyX-Code symbol_softfail = "SPF_SOFTFAIL"; \end_layout \begin_layout LyX-Code symbol_allow = "SPF_ALLOW"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard Коэффициенты для данных символов лучше определить следующим образом: высокий вес для символа FAIL, достаточно низкий вес для символа SOFTFAIL и отрицательны й вес для символа ALLOW. \end_layout \begin_layout Chapter Cтатистические алгоритмы \end_layout \begin_layout Section Winnow и OSB \end_layout \begin_layout Standard В rspamd используется алгоритм ортогональных разреженных биграмм (OSB), который основан на следующем принципе: \end_layout \begin_layout Code \begin_inset listings inline false status open \begin_layout Quotation \end_layout \begin_layout Quotation \end_layout \begin_layout Quotation н ----------------------------------- \end_layout \begin_layout Quotation а ----------------------------------- \end_layout \begin_layout Quotation б ----------------------------------- \end_layout \begin_layout Quotation о | w1 | w2 | w3 | w4 | w5 | \end_layout \begin_layout Quotation р | | | | | | --> выходные токены \end_layout \begin_layout Quotation ы ----------------------------------- \end_layout \begin_layout Quotation / Текущий набор хешей и весов \end_layout \begin_layout Quotation / \end_layout \begin_layout Quotation Входные токены \end_layout \end_inset \end_layout \begin_layout Standard То есть, процесс преобразования можно представить следующим образом: для каждого набора весов (w1..w5) составляется набор хешей. Токены образуются из текста. Например, возьмем некое письмо и наложим на него окно: \end_layout \begin_layout LyX-Code "Мама мыла раму." \end_layout \begin_layout LyX-Code |________| \end_layout \begin_layout Standard В данном окне создаются 2 токена: \end_layout \begin_layout Standard h("Мама"), h("мыла"), где h - хеш функция. \end_layout \begin_layout Standard Дальше окно двигается вправо на один токен и опять создаются 2 токена: h("мыла") , h("раму") \end_layout \begin_layout Standard В rspamd используется окно в 5 токенов и используются пары: \end_layout \begin_layout LyX-Code 1 - 5 -- h1 \end_layout \begin_layout LyX-Code 2 - 5 -- h2 \end_layout \begin_layout LyX-Code 3 - 5 -- h3 \end_layout \begin_layout LyX-Code 4 - 5 -- h4 \end_layout \begin_layout Standard Каждый такой токен состоит из двух хешей (h1 и h2). То есть каждое слово текста может давать до 5-ти токенов. Это делается для того, чтобы в статистических алгоритмах учитывать не индивидуа льные слова, и их сочетания, чтобы уменьшить ошибку. \end_layout \begin_layout Standard После этого мы должны вычислить принадлежность потока выходных токенов к некоторому классу. Для этого используется алгоритм Winnow. Идея алгоритма очень проста: \end_layout \begin_layout Enumerate Каждый возможный входной токен имеет вес 1.0 (то есть, нас интересуют только те токены, которые не равны 1.0) \end_layout \begin_layout Enumerate Для обучения проделываем следующие шаги: \end_layout \begin_deeper \begin_layout Enumerate генерируем набор токенов путем OSB алгоритма \end_layout \begin_layout Enumerate удаляем все дупликаты \end_layout \begin_layout Enumerate если данный входной набор принадлежит классу (например, спам или неспам), то умножаем вес каждого встреченного токена на т.н. Promotion Constant, которая равна 1,23 \end_layout \begin_layout Enumerate если данный входной набор не принадлежит классу, то умножаем каждый найденный токен на Demotion Constant в данном классе, которая равна 0,83 \end_layout \begin_layout Enumerate абсолютно неважно, сколько раз встречался данный токен во входном потоке, мы его умножаем на promotion или demotion только один раз \end_layout \end_deeper \begin_layout Enumerate Для классификации потока мы поступаем следующим образом: \end_layout \begin_deeper \begin_layout Enumerate генерируем набор токенов путем OSB алгоритма \end_layout \begin_layout Enumerate удаляем все дупликаты \end_layout \begin_layout Enumerate суммируем веса всех токенов, найденных в каждом из файлов данных статистики (при этом те токены, которые мы не нашли, имеют вес 1) \end_layout \begin_layout Enumerate затем мы делим полученную сумму на число токенов и смотрим, какой из классов (файлов данных) набрал больше очков и делаем заключение о принадлежности входного текста к классу \end_layout \end_deeper \begin_layout Standard Файлы данных статистики представляют собой следующие структуры: \end_layout \begin_layout LyX-Code { \end_layout \begin_deeper \begin_layout LyX-Code Header, \end_layout \begin_layout LyX-Code { feature_block1..feature_blockN } \end_layout \end_deeper \begin_layout LyX-Code } \end_layout \begin_layout Standard Заголовок файла очень прост: \end_layout \begin_layout LyX-Code struct { \end_layout \begin_deeper \begin_layout LyX-Code char magic[3] = { 'r', 's', 'd' }; \end_layout \begin_layout LyX-Code u_char version[2] = { '1', '0' }; \end_layout \begin_layout LyX-Code uint64_t create_time; \end_layout \end_deeper \begin_layout LyX-Code } \end_layout \begin_layout Standard Каждый feature_block состоит из 4-х полей: \end_layout \begin_layout LyX-Code struct { \end_layout \begin_deeper \begin_layout LyX-Code uint32_t hash1; \end_layout \begin_layout LyX-Code uint32_t hash2; \end_layout \begin_layout LyX-Code double value; \end_layout \begin_layout LyX-Code uint32_t last_access; \end_layout \end_deeper \begin_layout LyX-Code } \end_layout \begin_layout Standard Итого 16 байт на каждый feature. 0-е значения показывают свободную ячейку. Значение hash1 используется в качестве индекса: \end_layout \begin_layout LyX-Code idx = hash1 % filesize; \end_layout \begin_layout Standard Где filesize - размер в количестве feature_block'ов. При этом данный токен должен помещаться в заданную ячейку или ячейку за ним. При этом образуется цепочка токенов: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout idx \end_layout \begin_layout Plain Layout \backslash \end_layout \begin_layout Plain Layout | занят | занят | занят | свободен | \end_layout \begin_layout Plain Layout \backslash -----^ \backslash -----^ \backslash -----^ \end_layout \end_inset При этом, длина такой цепочки должна быть лимитирована некоторым разумным числом, например 128. Тогда максимальное время доступа будет не более 128-и итераций. Если мы не нашли за 128 итераций свободную ячейку, то мы можем поместить новый токен на место того, который меньше всего использовался (min (last_access )). При этом при доступе к ячейке необходимо обновлять last_access: \end_layout \begin_layout Code last_access = now - creation_time. \end_layout \begin_layout Standard Такая организация позволяет замещать только наименее используемые токены. \end_layout \begin_layout Chapter Протокол rspamc \end_layout \begin_layout Standard Формат запроса схож с http: \end_layout \begin_layout LyX-Code COMMAND RSPAMC/1.0 \end_layout \begin_layout Standard При этом допустимы следующие команды: \end_layout \begin_layout Itemize CHECK - проверить сообщение и выдать результат по каждой из метрик (не выводя символов) \end_layout \begin_layout Itemize SYMBOLS - проверить сообщение, выдать результат по каждой из метрик и символы по каждой из метрик \end_layout \begin_layout Itemize PROCESS - проверить сообщение, выдать результат по каждой из метрик, а затем вывести исходное сообщение \end_layout \begin_layout Itemize PING - не принимая сообщение выдать готовность к работе \end_layout \begin_layout Standard Также в зависимости от подключенных плагинов могут быть доступны другие команды протокола, например URLS (вывести все найденные в сообщении url'и) или EMAILS. \end_layout \begin_layout Standard Формат ответа: \end_layout \begin_layout LyX-Code SPAMD/1.1 0 EX_OK \end_layout \begin_layout LyX-Code \backslash / \backslash / \end_layout \begin_layout LyX-Code Версия Код ошибки \end_layout \begin_layout LyX-Code Spam: False ; 2 / 5 \end_layout \begin_layout Standard Это формат совместимости с sa-spamd (без метрик). Новый формат ответа: \end_layout \begin_layout LyX-Code RSPAMD/1.0 0 EX_OK \end_layout \begin_layout LyX-Code Metric: Name; Spam_Result; Spam_Mark / Spam_Mark_Required \end_layout \begin_layout LyX-Code Metric: Name2 ; Spam_Result2 ; Spam_Mark2 / Spam_Mark_Required2 \end_layout \begin_layout Standard Заголовков типа metric может быть несколько. Формат вывода символов: \end_layout \begin_layout LyX-Code SYMBOL1, SYMBOL2, SYMBOL3 -- формат совместимости с sa-spamd \end_layout \begin_layout LyX-Code Symbol: Name; Param1,Param2,Param3 -- формат rspamd \end_layout \begin_layout Standard Формат ответа зависит от формата запроса: \end_layout \begin_layout LyX-Code PROCESS SPAMC/1.2 \end_layout \begin_layout LyX-Code \backslash / \backslash / \end_layout \begin_layout LyX-Code Команда Версия \end_layout \begin_layout Standard В любом из режимов работы поддерживаются следующие заголовки: \end_layout \begin_layout Itemize Content-Length - длина сообщения \end_layout \begin_layout Itemize Helo - HELO, полученный от клиента \end_layout \begin_layout Itemize From - MAIL FROM \end_layout \begin_layout Itemize IP - IP клиента \end_layout \begin_layout Itemize Recipient-Number - число реципиентов \end_layout \begin_layout Itemize Rcpt - реципиент \end_layout \begin_layout Itemize Queue-ID - идентификатор очереди \end_layout \begin_layout Standard Эти значения могут использоваться в фильтрах rspamd. \end_layout \begin_layout Chapter Клиент rspamc \end_layout \begin_layout Standard Клиент rspamc представляет собой программу, написанную на perl и предназначенную для работы с системой rspamd. Rspamc принимает следующие аргументы: \end_layout \begin_layout Itemize -с: определяет путь к конфигурационному файлу rspamd, используется для работы с локальным rspamd \end_layout \begin_layout Itemize -h: определяет адрес удаленного rspamd сервера \end_layout \begin_layout Itemize -p: определяет порт для удаленного rspamd сервера \end_layout \begin_layout Itemize -P: определяет пароль для работы с привиллегированными командами rspamd \end_layout \begin_layout Itemize -s: определяет имя символа для обучения классификатора \end_layout \begin_layout Standard Последним аргументом rspamc принимает команду. Если команда не задана, то используется команда SYMBOLS. Команды, принимаемые rspamc: \end_layout \begin_layout Itemize команды по обработке сообщений: \end_layout \begin_deeper \begin_layout Itemize symbols - по данной команде проверяется сообщение, переданное через stdin rspamc \end_layout \begin_layout Itemize check - по данной команде выводится только результат по метрикам без символов \end_layout \begin_layout Itemize process - возвращает не только символы, но и исходное сообщение \end_layout \begin_layout Itemize urls - выводит все найденные url'и \end_layout \begin_layout Itemize emails - выводит все найденные адреса e-mail в сообщении \end_layout \end_deeper \begin_layout Itemize команды по работе с управляющим интерфейсом \end_layout \begin_deeper \begin_layout Itemize stat - выводит статистику работы \end_layout \begin_layout Itemize learn - обучает классификатор по определенному классу (указанному опцией -s) \end_layout \begin_layout Itemize shutdown - останавливает систему rspamd \end_layout \begin_layout Itemize uptime - выводит время работы rspamd \end_layout \begin_layout Itemize counters - выводит значения счетчиков символов \end_layout \begin_layout Itemize fuzzy_add - добавляет fuzzy hash в хранилище \end_layout \begin_layout Itemize fuzzy_del - удаляет fuzzy hash из хранилища \end_layout \end_deeper \begin_layout Chapter LUA API плагинов \end_layout \begin_layout Standard Rspamd позволяет реализовывать различную логику в виде lua плагинов, для чего используется директива modules. Данная директива позволяет задавать пути к каталогам, содержащим скрипты на lua: \end_layout \begin_layout LyX-Code modules { \end_layout \begin_deeper \begin_layout LyX-Code module_path = \begin_inset Quotes fld \end_inset /some/path/ \begin_inset Quotes frd \end_inset ; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard При инициализации rspamd загружает все файлы вида *.lua и выполняет их (при ошибке в коде плагинов rspamd запускаться не будет, выдавая ошибку конфигурации , при указанной опции -t будет проверяться не только синтаксис конфигурационного файла, но и синтаксис плагинов). При этом, определяется глобальная переменная rspamd_config, позволяющая извлекать опции конфигурации и регистрировать правила и соответствующие им символы. Таким образом, каждый lua плагин условно можно разделить на две части: исполняемый код, выполняющий настройку опций модуля, регистрирующий функции правил (callbacks), и собственно обработчики правил. \end_layout \begin_layout Section Настройка lua модуля \end_layout \begin_layout Standard Для извлечения параметров конфигурации и регистрации обработчиков правил применяется глобальная переменная rspamd_config, которая обладает рядом полезных методов: \end_layout \begin_layout Itemize get_module_opt (module_name, option_name) - возвращает значение опции option_nam e для модуля с именем module_name. То есть, если в конфигурационном файле есть следующая запись: \end_layout \begin_layout LyX-Code module 'test' { \end_layout \begin_deeper \begin_layout LyX-Code param = \begin_inset Quotes fld \end_inset value \begin_inset Quotes frd \end_inset ; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_deeper \begin_layout Standard То вызов rspamd_config:get_module_opt('test', 'param') вернет строку 'value'; \end_layout \end_deeper \begin_layout Itemize get_all_opts (module_name) - возвращает таблицу из всех опций для данного модуля, ключом служит имя опции: \end_layout \begin_layout LyX-Code local opts = rspamd_config:get_all_opts('test') \end_layout \begin_layout LyX-Code if opts then \end_layout \begin_deeper \begin_layout LyX-Code var = opts['param'] \end_layout \begin_layout LyX-Code for k,v in pairs opts do \end_layout \begin_deeper \begin_layout LyX-Code print ( \begin_inset Quotes fld \end_inset Param: \begin_inset Quotes frd \end_inset .. k .. \begin_inset Quotes fld \end_inset Value: \begin_inset Quotes frd \end_inset .. v) \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \begin_layout Itemize get_metric (name) - возвращает объект метрики с данным именем \end_layout \begin_layout Itemize register_function(name, callback) - регистрирует функцию lua для использования в логических выражениях rspamd, callback в данном случае - строка с именем функции, пример применения: \end_layout \begin_layout LyX-Code function some_func(task, arg1, arg2) \end_layout \begin_deeper \begin_layout LyX-Code return false \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code rspamd_config:register_function('lua_func', 'some_func') \end_layout \begin_layout Standard Объект метрики используется для регистрации символов: \end_layout \begin_layout Itemize register_symbol (symbol, initial_weight, callback) - symbol определяет имя символа, initial_weight - изначальный вес, callback - строка с именем функции: \end_layout \begin_layout LyX-Code local m = rspamd_config:get_metric('default') \end_layout \begin_layout LyX-Code if m then \end_layout \begin_deeper \begin_layout LyX-Code m:register_symbol('TEST', 1.0, 'some_callback') \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \begin_layout Standard После регистрации обработчика символа этот обработчик будет вызываться rspamd обычным образом, используя планировщик символов (это подробно описано в 3.2). \end_layout \begin_layout Section Обработчик правила \end_layout \begin_layout Standard Обработчик правила - это функция, реализующая логику правила. В качестве параметра она принимает объект task, из которого можно извлечь различную информацию о сообщении. После выполнения логики работы обработчик может вставить символ, используя тот же объект task. Таким образом типичная функция-обработчик выглядит следующим образом: \end_layout \begin_layout LyX-Code function some_callback(task) \end_layout \begin_deeper \begin_layout LyX-Code if some_condition(task) then \end_layout \begin_deeper \begin_layout LyX-Code task:insert_result(metric, symbol, 1) \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \begin_layout Standard Функция insert_result принимает в качестве параметров имя метрики, имя символа, вес и необязательный список строковых параметров, которые будут ассоциированы с этим символом. Объект task предоставляет ряд функций, позволяющих создать логику правила фильтрации: \end_layout \begin_layout Itemize get_received_headers() - возвращает массив из обработанных заголовков Received в виде таблицы: \end_layout \begin_deeper \begin_layout Itemize h['from_hostname'] - hostname, откуда получено сообщение \end_layout \begin_layout Itemize h['from_ip'] - ip, откуда получено сообщение \end_layout \begin_layout Itemize h['real_hostname'] - hostname, распознанное самим релеем \end_layout \begin_layout Itemize h['real_ip'] - ip, который соответствует real_hostname \end_layout \begin_layout Itemize h['by_hostname'] - hostname самого релея \end_layout \begin_layout Standard received заголовки в массиве идут в обратном порядке, то есть, первые релеи письма будут первыми элементами массива \end_layout \end_deeper \begin_layout Itemize get_raw_headers() - возвращает строку, содержащую все заголовки сообщения в неразобранном виде \end_layout \begin_layout Itemize get_text_parts() - возвращает массив объектов типа text_part \end_layout \begin_layout Itemize get_urls() - возвращает массив строк, содержащих извлеченные из сообщения URL'и \end_layout \begin_layout Itemize get_message() - возвращает объект типа сообщение \end_layout \begin_layout Itemize get_recipients() - возвращает массив получателей письма, переданных в ходе smtp диалога (командами RCPT TO:) \end_layout \begin_layout Itemize get_from() - возвращает адрес отправителя письма, переданных в ходе smtp диалога (команда MAIL FROM:) \end_layout \begin_layout Itemize get_helo() - возвращает значение HELO \end_layout \begin_layout Itemize get_from_ip() - возвращает ip адрес, откуда нам пришло данное письмо \end_layout \begin_layout Standard Объект \begin_inset Quotes fld \end_inset message \begin_inset Quotes frd \end_inset применяется для манипуляций с заголовками: \end_layout \begin_layout Itemize get_header(headername) - возвращает массив всех значений заголовков с таким именем (может быть массив из одного элемента, если такой заголовок в сообщении представлен единожды) \end_layout \begin_layout Itemize set_header(headername, headervalue) - устанавливает заданный заголовок \end_layout \begin_layout Standard Объект text_part предназначен для манипуляций с текстовым содержимым сообщения: \end_layout \begin_layout Itemize get_content() - возвращает текстовое содержимое части \end_layout \begin_layout Itemize is_html() - возвращает true, если данная часть представляет собой HTML \end_layout \begin_layout Itemize is_empty() - возвращает true, если данная часть не содержит текста \end_layout \begin_layout Itemize get_fuzzy() - возвращает строку с нечетким хешем для данного сообщения \end_layout \begin_layout Standard Пример функции-обработчика: \end_layout \begin_layout LyX-Code function received_cb (task) \end_layout \begin_deeper \begin_layout LyX-Code local recvh = task:get_received_headers() \end_layout \begin_layout LyX-Code for _,rh in ipairs(recvh) do \end_layout \begin_deeper \begin_layout LyX-Code if rh['real_ip'] then \end_layout \begin_deeper \begin_layout LyX-Code local parts = task:get_text_parts() \end_layout \begin_layout LyX-Code for _,part in ipairs(parts) do \end_layout \begin_deeper \begin_layout LyX-Code if not part:is_empty() then \end_layout \begin_deeper \begin_layout LyX-Code local text = part:get_content() \end_layout \begin_layout LyX-Code if some_filter(text) then \end_layout \begin_layout LyX-Code task:insert_result(metric, symbol, 1) \end_layout \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \begin_layout Section Использование DNS \end_layout \begin_layout Standard Для многих задач фильтрации сообщений используются различные DNS запросы, поэтому lua интерфейс предоставляет возможность планирования DNS запросов, используя объект task: \end_layout \begin_layout Itemize resolve_dns_a(host, callback) - выполняет прямое преобразование имени host, после чего вызывает обработчик callback \end_layout \begin_layout Itemize resolve_dns_ptr(ip, callback) - то же, что и предыдущее, но выполняет обратное преобразование ip \end_layout \begin_layout Standard Так как DNS преобразования осуществляются асинхронно, то необходимо задавать обработчик, который будет вызываться по завершению DNS запроса. Обработчик имеет следующий вид: \end_layout \begin_layout LyX-Code function dns_cb(task, to_resolve, results, err) \end_layout \begin_layout Itemize task - объект task \end_layout \begin_layout Itemize to_resolve - строка, содержащая имя хоста или ip, для которого выполнялось преобразование \end_layout \begin_layout Itemize results - массив, содержащий ip адреса (для прямого преобразования) или же имя хоста (для обратного). В случае ошибки этот параметр имеет значение nil \end_layout \begin_layout Itemize err - строка, описывающая ошибку (или nil, если преобразование успешно завершило сь) \end_layout \begin_layout Standard Пример функции-обработчика результатов DNS запроса: \end_layout \begin_layout LyX-Code function dns_cb(task, to_resolve, results, err) \end_layout \begin_deeper \begin_layout LyX-Code if results then \end_layout \begin_deeper \begin_layout LyX-Code local _,_,rbl = string.find(to_resolve, '%d+ \backslash .%d+ \backslash .%d+ \backslash .%d+ \backslash .(.+)') \end_layout \begin_layout LyX-Code task:insert_result(metric, symbol, 1, rbl) \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \begin_layout Section Использование файлов-списков \end_layout \begin_layout Standard В lua плагинах можно задавать и использовать файлы списков, как это описано в п. 4.1. Это полезно, когда в lua необходимо использовать некоторые данные, которые бы асинхронно обновлялись в процессе работы rspamd. API по работе со списками сожержит следующие функции: \end_layout \begin_layout Itemize rspamd_config:add_radix_map (string) - добавляет определение списка, содержащего ip адреса и сети. При удачном добавлении возвращается объект типа rspamd_radix, который может использоваться в обработчиках символов для определения наличия в каком-либо списке заданного ip; \end_layout \begin_layout Itemize rspamd_config:add_hash_map (string) - добавляет определение списка строк (доменов), при успешном добавлении возвращает объект типа rspamd_hash. \end_layout \begin_layout Standard Использовать списки целесообразно в функциях-обработчкиках, так как сразу же после добавления эти списки могут оказаться пустыми. Объекты, возвращаемые функциями, регистрирующими файлы списков, имеют метод get_key, позволяющий определить наличие какого-либо элемента в списке. Для списков ip адресов этот объект принимает целое число, для списка строк - строку. Простой пример использования списков. \end_layout \begin_layout Standard Регистрация: \end_layout \begin_layout LyX-Code local radix_list = nil \end_layout \begin_layout LyX-Code local host_list = nil \end_layout \begin_layout LyX-Code radix_list = rspamd_config:add_radix_map ('http://somehost/ip.list') \end_layout \begin_layout LyX-Code host_list = rspamd_config:add_hash_map ('http://otherhost/host.list') \end_layout \begin_layout Standard Использование в обработчике символа: \end_layout \begin_layout LyX-Code function check_whitelist (task) \end_layout \begin_deeper \begin_layout LyX-Code -- check client's ip \end_layout \begin_layout LyX-Code local ipn = task:get_from_ip_num() \end_layout \begin_layout LyX-Code if ipn and radix_list then \end_layout \begin_deeper \begin_layout LyX-Code local key = radix_list:get_key(ipn) \end_layout \begin_layout LyX-Code if key then \end_layout \begin_deeper \begin_layout LyX-Code task:insert_result(metric, symbol_ip, 1) \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code -- check client's from domain \end_layout \begin_layout LyX-Code local from = task:get_from() \end_layout \begin_layout LyX-Code if from and host_list then \end_layout \begin_deeper \begin_layout LyX-Code -- extract domain part \end_layout \begin_layout LyX-Code local _,_,domain = string.find(from, '@(.+)>?$') \end_layout \begin_layout LyX-Code local key = host_list:get_key(domain) \end_layout \begin_layout LyX-Code if key then \end_layout \begin_deeper \begin_layout LyX-Code task:insert_result(metric, symbol_from, 1) \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \end_deeper \begin_layout LyX-Code end \end_layout \begin_layout Chapter Perl API rspamd \end_layout \begin_layout Standard Для обработки сообщений системой rspamd было создано простое perl api для проверки сообщений системой rspamd и обучения системы rspamd. Данное API содержится в модуле Mail::Rspamd::Client. Использование API достаточно тривиально: \end_layout \begin_layout LyX-Code #!/usr/bin/perl -w \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code use Mail::Rspamd::Client; \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code my $testmsg; \end_layout \begin_layout LyX-Code while (<>) { \end_layout \begin_deeper \begin_layout LyX-Code $testmsg .= $_; \end_layout \end_deeper \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code my $client = new Mail::Rspamd::Client( \end_layout \begin_deeper \begin_layout LyX-Code { \end_layout \begin_deeper \begin_layout LyX-Code port => 11333, \end_layout \begin_layout LyX-Code hosts => ['localhost:11333',], \end_layout \begin_layout LyX-Code ip => '127.0.0.1' \end_layout \end_deeper \begin_layout LyX-Code } \end_layout \end_deeper \begin_layout LyX-Code ); \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code if ($client->ping()) { \end_layout \begin_deeper \begin_layout LyX-Code print "Ping is ok \backslash n"; \end_layout \end_deeper \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code my $result = $client->check($testmsg); \end_layout \begin_layout LyX-Code \end_layout \begin_layout LyX-Code if ($result && $result->{'default'}->{'isspam'} eq 'True') { \end_layout \begin_deeper \begin_layout LyX-Code print "spam \backslash n"; \end_layout \end_deeper \begin_layout LyX-Code } else { \end_layout \begin_deeper \begin_layout LyX-Code print "ham \backslash n"; \end_layout \end_deeper \begin_layout LyX-Code } \end_layout \begin_layout Standard Результаты обработки сообщения возвращаются в виде ссылки на хеш, который индексирован по метрикам. Каждая из метрик, в свою очередь, также является ссылкой на хеш, содержащий поля: \end_layout \begin_layout Itemize isspam - строка 'True' или 'False' \end_layout \begin_layout Itemize score - вес сообщения \end_layout \begin_layout Itemize threshold - предельный вес данной метрики \end_layout \begin_layout Itemize symbols - массив символов для данного сообщения \end_layout \begin_layout Standard Модуль имеет внутреннюю логику работы с несколькими серверами rspamd, выбирая каждый раз случайный сервер, а также помечая долго не работающие сервера, исключая их из списка активных на некоторое время. При создании Mail::Rspamd::Client также можно указать параметр from (значение SMTP команды mail from), параметр rcpt (массив SMTP команд rcpt to) и user (авторизированный пользователь SMTP). Полный список параметров: \end_layout \begin_layout Itemize username - имя пользователя (строка) \end_layout \begin_layout Itemize ip - ip адрес, с которого пришло сообщение (строка) \end_layout \begin_layout Itemize subject - тема письма (для не mime сообщений) \end_layout \begin_layout Itemize timeout - время ожидания в секундах (число) \end_layout \begin_layout Itemize password - пароль для команд котроллера (строка) \end_layout \begin_layout Itemize statfile - имя символа файла статистики для обучения (строка) \end_layout \begin_layout Itemize weight - вес сообщения для команд fuzzy_add и learn (число) \end_layout \begin_layout Itemize imap_search - строка поиска по IMAP (строка) \end_layout \begin_layout Standard Для выполнения команды на всех серверах используется команда do_all_cmd, возвращающая хеш вида host => %results. \end_layout \begin_layout Chapter Использование HTTP Redirector \end_layout \begin_layout Standard HTTP редиректор представляет собой утилиту, которая умеет проверять различные способы HTTP редиректов и выдавать реальный URL для любого заданного. Данная утилита предназначена для проверки URL'ей вида tinyurl.com, youfrog.com и прочих сервисов \begin_inset Quotes fld \end_inset коротких \begin_inset Quotes frd \end_inset URL'ей. HTTP редиректор работает как обычный HTTP сервер и принимает стандартные запросы вида: \end_layout \begin_layout LyX-Code GET /url_to_resolve HTTP/1.0 \end_layout \begin_layout LyX-Code \end_layout \begin_layout Standard Для работы URL редиректор требует ряд perl модулей: \end_layout \begin_layout Itemize HTTP::Request - обработка HTTP запросов; \end_layout \begin_layout Itemize POE (Component::Server::TCP Filter::HTTPD Component::Client::HTTP) - для асинхронной обработки соединений; \end_layout \begin_layout Itemize HTML::HeadParser - для парсинга HTTP заголовков; \end_layout \begin_layout Itemize SWF::Element - для обработки SWF (adobe flash) редиректов; \end_layout \begin_layout Itemize Cache::Memcached::Fast - для хранения кеша URL'ей; \end_layout \begin_layout Itemize Digest::SHA256 - для индексации хеша; \end_layout \begin_layout Itemize Proc::Daemon, Proc::PidUtil - для демонизации и управления процессом; \end_layout \begin_layout Itemize URI::Escape - для нормализации URL'ей. \end_layout \begin_layout Standard Настройка утилиты осуществляется правкой скрипта rspamd-redirector, конфигурацио нные параметры находятся в хеше %cfg: \end_layout \begin_layout LyX-Code our %cfg = ( \end_layout \begin_deeper \begin_layout LyX-Code port => 8080, # Порт для приема соединений \end_layout \begin_layout LyX-Code max_size => 102400, # Максимальный размер принимаемых данных \end_layout \begin_layout LyX-Code http_timeout => 5, # Таймаут соединений (секунды) \end_layout \begin_layout LyX-Code max_rec => 5, # Максимум подзапросов \end_layout \begin_layout LyX-Code pidfile => '/var/run/rspamd/redirector.pid',# Путь до файла pid'а \end_layout \begin_layout LyX-Code logfile => '/var/log/rspamd-redirector.log',# Путь до log файла \end_layout \begin_layout LyX-Code do_log => 0, # Включить логирование запросов \end_layout \begin_layout LyX-Code debug => 0, # Включить отладочную информацию \end_layout \begin_layout LyX-Code memcached_servers => # Сервера кеша URL'ей \end_layout \begin_deeper \begin_layout LyX-Code [ \end_layout \begin_deeper \begin_layout LyX-Code { address => 'localhost:11211', weight => 2.5 }, \end_layout \end_deeper \begin_layout LyX-Code ], \end_layout \end_deeper \begin_layout LyX-Code digest_bits => 256, # Число бит в ключе кеша \end_layout \begin_layout LyX-Code cache_expire => 3600, # Время в секундах хранения записи кеша \end_layout \begin_layout LyX-Code user => '@RSPAMD_USER@', # Пользователь \end_layout \begin_layout LyX-Code group => '@RSPAMD_GROUP@', # Группа \end_layout \end_deeper \begin_layout LyX-Code ); \end_layout \begin_layout Standard Для работы с redirector'ом необходимо учитывать следующее: при определенни редиректа rspamd-redirector делает полноценный http запрос, то есть, если мы будем пытаться разрешить запросы с различными GET параметрами в URL (например http://some_evil_host/unsubscribe?email=good@email.com), то тем самым можем занести \begin_inset Quotes fld \end_inset хорошие \begin_inset Quotes frd \end_inset адреса в списки спамеров. Кроме этого, появляется возможность организовать атаку на некоторый http сервер, послав много писем, содержащих его адрес. Поэтому проверять редиректы можно только у проверенных доменов. Для этого используются настройки модуля surbl в самом rspamd (так как именно модуль surbl отвечает за работу с редиректором): \end_layout \begin_layout LyX-Code .module 'surbl' { \end_layout \begin_deeper \begin_layout LyX-Code ... \end_layout \begin_layout LyX-Code redirector = "localhost:8080"; \end_layout \begin_layout LyX-Code # Connect timeout for redirector \end_layout \begin_layout LyX-Code redirector_connect_timeout = "1s"; \end_layout \begin_layout LyX-Code # IO timeout for redirector \end_layout \begin_layout LyX-Code redirector_read_timeout = "10s"; \end_layout \begin_layout LyX-Code # Maps for hosts that should be checked with redirector \end_layout \begin_layout LyX-Code redirector_hosts_map = "http://some_host/redirector.hosts"; \end_layout \begin_layout LyX-Code ... \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard При этом список redirector_hosts_map содержит домены, которые будут перед проверкой по surbl листам проверяться на наличие редиректов (то есть, именно в том виде, что будет при surbl запросе - 2 или 3 компонента имени хоста). Кеш URL'ей обязателен для работы редиректора, так как в противном случае массовая рассылка с одинаковым URL'ем приведет к большому числу http запросов. Кроме этого, кеш URL'ей существенно ускоряет работу редиректора. Лог файл редиректора позволяет увидеть, какие редиректы были распознаны и их тип: HTTP редирект, HTML редирект (тег meta refresh), JavaScript редирект (location = ...), SWF редирект или же кешированный редирект (найденный в memcached ). Взаимодействие с редиректором возможно не только из rspamd, но и из любого другого приложения, работающего по HTTP протоколу. \end_layout \begin_layout Chapter Хранилище нечетких хешей \end_layout \begin_layout Standard Нечеткий хеш (fuzzy hash) отличается от обычного тем, что при небольшом изменении в исходном тексте, он также меняется незначительно. Традиционный (криптографический) хеш в таком случае меняется сильно. Эта особенность позволяет использовать нечеткие хеши для определения степени похожести текстов (у похожих текстов будут похожие нечеткие хеши). Эта операция является более быстрой, чем сравнение текстов, кроме этого, нечеткие хеши можно хранить, сравнивая с ними впоследствие полученные сообщения. В rspamd есть возможность использования хранилища нечетких хешей для проверки сообщений. При этом считаются хеши всех текстовых частей сообщения, а затем эти хеши проверяются на наличие в хранилище (с определенным процентом ошибки). Для хранилища хешей создается специальный процесс fuzzy, который работает с рабочим процессом rspamd по UDP протоколу. Несколько хранилищ создают общее хранилище хешей, каждый из элементов которого содержит часть хешей. При добавлении или удалении нового хранилища в общее хранилище, все данные хешей теряются (возможно, это будет устранено в будущем). При проверке хеша выбирается одно из хранилищ (соответственно хешу) и на него шлется запрос. При записи хеша выбирается то же самое хранилище, что и при проверке. Запись и удаление хеша из общего хранилища обеспечивается командами fuzzy_add и fuzzy_del на любом из контроллеров, использующих данное хранилище. Это можно делать, например, используя клиент rspamc: \end_layout \begin_layout LyX-Code rspamc fuzzy_add < message_to_add.eml \end_layout \begin_layout LyX-Code rspamd fuzzy_del < message_to_del.eml \end_layout \begin_layout Standard Настройка хранилища обеспечивается созданием записи для процесса fuzzy storage: \end_layout \begin_layout LyX-Code worker { \end_layout \begin_deeper \begin_layout LyX-Code type = "fuzzy"; \end_layout \begin_layout LyX-Code # Bind socket for fuzzy interface \end_layout \begin_layout LyX-Code bind_socket = *:11335; \end_layout \begin_layout LyX-Code count = 1; \end_layout \begin_layout LyX-Code # Path to filesystem storage \end_layout \begin_layout LyX-Code hashfile = "/tmp/fuzzy.db"; \end_layout \begin_layout LyX-Code # Expire time for hashes in storage (h - for hours, d - for days) \end_layout \begin_layout LyX-Code expire = "10d"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard Для увеличения производительности хранилища можно заменить нечеткий поиск на поиск точного соответствия, а также установкой libJudy ( \begin_inset CommandInset href LatexCommand href name "judy arrays" target "http://judy.sourceforge.net" \end_inset ). После этого необходимо пересобрать rspamd (libJudy обнаруживается автоматически ) и указать в настройках fuzzy worker'а параметр: \end_layout \begin_layout LyX-Code use_judy = "yes"; \end_layout \begin_layout Standard Настройка hashfile используется для указания файла, в который периодически будут записываться полученные в хранилище хеши (частота синхронизации с файлом зависит от интенсивности модификаций в хранилище, также синхронизация происходит при завершении процесса fuzzy storage). Для настройки клиентской части хранилища используется модуль fuzzy_check: \end_layout \begin_layout LyX-Code .module 'fuzzy_check' { \end_layout \begin_deeper \begin_layout LyX-Code metric = "default"; \end_layout \begin_layout LyX-Code symbol = "R_FUZZY"; \end_layout \begin_layout LyX-Code # List of fuzzy storage servers, separated by ',' or ';' or simple by spaces \end_layout \begin_layout LyX-Code servers = "localhost:11335;some_host:11335"; \end_layout \end_deeper \begin_layout LyX-Code }; \end_layout \begin_layout Standard После настройки клиентской части с указанными серверами начинает работать как рабочий процесс (для проверки сообщений), так и контроллер (для записи/удал ения хешей из хранилища). \end_layout \begin_layout Chapter CGI интерфейс rspamd \end_layout \begin_layout Standard Rspamd имеет простой интерфейс для управления кластером серверов при помощи веб браузера. Интерфейс позволяет выполнять основные команды (проверка сообщений, обучение rspamd, операции с fuzzy хешами, статистика) на выбранных серверах. Для передачи сообщения rspamd используется либо поле текстового ввода, либо непосредственная загрузка файла. Если используется поле текстового ввода и сообщение вводится в него без mime заголовков (например, для обучения), то интерфейс автоматически вставляет заголовки по умолчанию и передает составленное таким образом сообщение для обработки rspamd. Запуск CGI интерфейса возможен двумя способами: как standalone сервера и как cgi скрипта. Первый способ подходит для тестовой работы или же для использования в один поток. Второй способ лишен этиго недостатка, но требует наличия настроенного веб сервера. Для работы с rspamd используется модуль Mail::Rspamd::Client, описанный ранее. Аргументы запуска CGI интерфейса: \end_layout \begin_layout Itemize -standalone - запуск в виде standalone http сервера \end_layout \begin_layout Itemize -port - порт для запуска \end_layout \begin_layout Itemize -host - имя хоста для запуска standalone сервера \end_layout \begin_layout Itemize -cfg - имя файла, содержащего список серверов, с которыми будет работать CGI интерфейс \end_layout \end_body \end_document