+++ /dev/null
-Особенности классификации и статистического анализа
-===================================================
-
-В rspamd используется алгоритм ортогональных разреженных биграмм (OSB),
-который основан на следующем принципе:
-
-
- н -----------------------------------
- а -----------------------------------
- б -----------------------------------
- о | w1 | w2 | w3 | w4 | w5 |
- р | | | | | | --> выходные токены
- ы -----------------------------------
- / Текущий набор хешей и весов
- /
-Входные токены
-
-То есть, процесс преобразования можно представить следующим образом:
-для каждого набора весов (w1..w5) составляется набор хешей. Первоначальный
-шаг выглядит так: берем 5 токенов, помещаем их в текущий набор, умножаем на
-веса, складываем, получаем выходной токен. Далее применяем последовательно для каждого
-набора весов. То есть, из одного набора хешей мы получаем число выходных токенов,
-равное числу наборов весов. Далее мы в w1 помещаем новый хеш и сдвигаем w1..w4 на
-1 вправо. С набором хешей w1',w1..w4 проделываем аналогичные операции. И так до
-тех пор, пока входные токены не закончатся. Выходных токенов больше, чем входных,
-в число раз, равное числу наборов весов.
-Сейчас в rspamd для формирования наборов весов используется алгоритм ортогональных
-разреженных биграмм. Число наборов в данном алгоритме равно N=W-1, где W - длина
-набора хешей (окно). Наборы весов формируются следующим образом (для W=5):
-{ 1, 7, 0, 0, 0 },
-{ 3, 0, 13, 0, 0 },
-{ 5, 0, 0, 29, 0 },
-{ 11, 0, 0, 0, 51 },
-
-После этого мы должны вычислить принадлежность потока выходных токенов к некоторому
-классу. Для этого используется алгоритм Winnow.
-
-Here's a quick synopsys of the algorithm:
-Идея алгоритма очень проста:
-1) Каждый возможный входной токен имеет вес 1.0 (то есть, нас интересуют только те
-токены, которые не равны 1.0)
-2) Для обучения проделываем следующие шаги:
- - генерируем набор токенов путем OSB алгоритма
- - удаляем все дупликаты
- - если данный входной набор принадлежит классу (например, спам или неспам), то умножаем вес
- каждого встреченного токена на т.н. Promotion Constant, которая равна 1,23
- - если данный входной набор не принадлежит классу, то умножаем каждый найденный токен на
- Demotion Constant в данном классе, которая равна 0,83
- - абсолютно неважно, сколько раз встречался данный токен во входном потоке, мы его умножаем
- на promotion или demotion только один раз
-3) Для классификации потока мы поступаем следующим образом:
- - генерируем набор токенов путем OSB алгоритма
- - удаляем все дупликаты
- - суммируем веса всех токенов, найденных в каждом из файлов данных статистики (при этом те токены,
- которые мы не нашли, имеют вес 1)
- - затем мы делим полученную сумму на число токенов и смотрим, какой из классов (файлов данных) набрал
- больше очков и делаем заключение о принадлежности входного текста к классу
-
-Файлы данных статистики представляют собой следующие структуры:
-{
-Header,
-{ feature_block1..feature_blockN }
-}
-Заголовок файла очень прост:
-struct {
- char magic[3] = { 'r', 's', 'd' };
- u_char version[2] = { '1', '0' };
- uint64_t create_time;
-}
-Каждый feature_block состоит из 4-х полей:
-struct {
- uint32_t hash1;
- uint32_t hash2;
- uint32_t value; /* На самом деле это float */
- uint32_t last_access;
-}
-Итого 16 байт на каждый feature. 0-е значения показывают свободную ячейку.
-Значение hash1 используется в качестве индекса:
-idx = hash1 % filesize;
-Где filesize - размер в количестве feature_block'ов. При этом данный токен
-должен помещаться в заданную ячейку или ячейку за ним. При этом образуется
-цепочка токенов:
-
-idx
- \
-| занят | занят | занят | свободен |
- \-----^ \-----^ \-----^
-При этом, длина такой цепочки должна быть лимитирована некоторым разумным числом,
-например 128. Тогда максимальное время доступа будет не более 128-и итераций.
-Если мы не нашли за 128 итераций свободную ячейку, то мы можем поместить новый токен
-на место того, который меньше всего использовался (min (last_access)). При этом
-при доступе к ячейке необходимо обновлять last_access: last_access = now - creation_time.
-Такая организация позволяет замещать только наименее используемые токены.
--- /dev/null
+Особенности классификации и статистического анализа
+===================================================
+
+В rspamd используется алгоритм ортогональных разреженных биграмм (OSB),
+который основан на следующем принципе:
+
+
+ н -----------------------------------
+ а -----------------------------------
+ б -----------------------------------
+ о | w1 | w2 | w3 | w4 | w5 |
+ р | | | | | | --> выходные токены
+ ы -----------------------------------
+ / Текущий набор хешей и весов
+ /
+Входные токены
+
+То есть, процесс преобразования можно представить следующим образом:
+для каждого набора весов (w1..w5) составляется набор хешей. Первоначальный
+шаг выглядит так: берем 5 токенов, помещаем их в текущий набор, умножаем на
+веса, складываем, получаем выходной токен. Далее применяем последовательно для каждого
+набора весов. То есть, из одного набора хешей мы получаем число выходных токенов,
+равное числу наборов весов. Далее мы в w1 помещаем новый хеш и сдвигаем w1..w4 на
+1 вправо. С набором хешей w1',w1..w4 проделываем аналогичные операции. И так до
+тех пор, пока входные токены не закончатся. Выходных токенов больше, чем входных,
+в число раз, равное числу наборов весов.
+Сейчас в rspamd для формирования наборов весов используется алгоритм ортогональных
+разреженных биграмм. Число наборов в данном алгоритме равно N=W-1, где W - длина
+набора хешей (окно). Наборы весов формируются следующим образом (для W=5):
+{ 1, 7, 0, 0, 0 },
+{ 3, 0, 13, 0, 0 },
+{ 5, 0, 0, 29, 0 },
+{ 11, 0, 0, 0, 51 },
+
+После этого мы должны вычислить принадлежность потока выходных токенов к некоторому
+классу. Для этого используется алгоритм Winnow.
+
+Here's a quick synopsys of the algorithm:
+Идея алгоритма очень проста:
+1) Каждый возможный входной токен имеет вес 1.0 (то есть, нас интересуют только те
+токены, которые не равны 1.0)
+2) Для обучения проделываем следующие шаги:
+ - генерируем набор токенов путем OSB алгоритма
+ - удаляем все дупликаты
+ - если данный входной набор принадлежит классу (например, спам или неспам), то умножаем вес
+ каждого встреченного токена на т.н. Promotion Constant, которая равна 1,23
+ - если данный входной набор не принадлежит классу, то умножаем каждый найденный токен на
+ Demotion Constant в данном классе, которая равна 0,83
+ - абсолютно неважно, сколько раз встречался данный токен во входном потоке, мы его умножаем
+ на promotion или demotion только один раз
+3) Для классификации потока мы поступаем следующим образом:
+ - генерируем набор токенов путем OSB алгоритма
+ - удаляем все дупликаты
+ - суммируем веса всех токенов, найденных в каждом из файлов данных статистики (при этом те токены,
+ которые мы не нашли, имеют вес 1)
+ - затем мы делим полученную сумму на число токенов и смотрим, какой из классов (файлов данных) набрал
+ больше очков и делаем заключение о принадлежности входного текста к классу
+
+Файлы данных статистики представляют собой следующие структуры:
+{
+Header,
+{ feature_block1..feature_blockN }
+}
+Заголовок файла очень прост:
+struct {
+ char magic[3] = { 'r', 's', 'd' };
+ u_char version[2] = { '1', '0' };
+ uint64_t create_time;
+}
+Каждый feature_block состоит из 4-х полей:
+struct {
+ uint32_t hash1;
+ uint32_t hash2;
+ uint32_t value; /* На самом деле это float */
+ uint32_t last_access;
+}
+Итого 16 байт на каждый feature. 0-е значения показывают свободную ячейку.
+Значение hash1 используется в качестве индекса:
+idx = hash1 % filesize;
+Где filesize - размер в количестве feature_block'ов. При этом данный токен
+должен помещаться в заданную ячейку или ячейку за ним. При этом образуется
+цепочка токенов:
+
+idx
+ \
+| занят | занят | занят | свободен |
+ \-----^ \-----^ \-----^
+При этом, длина такой цепочки должна быть лимитирована некоторым разумным числом,
+например 128. Тогда максимальное время доступа будет не более 128-и итераций.
+Если мы не нашли за 128 итераций свободную ячейку, то мы можем поместить новый токен
+на место того, который меньше всего использовался (min (last_access)). При этом
+при доступе к ячейке необходимо обновлять last_access: last_access = now - creation_time.
+Такая организация позволяет замещать только наименее используемые токены.
+++ /dev/null
-API Rspamd.
-===========
-
-TODO.
-
-ìÏÇÉËÁ ÒÁÂÏÔÙ ÆÉÌØÔÒÏ× rspamd.
-==============================
-
-1) ÷ÓÅ ÆÉÌØÔÒÙ ÒÅÇÉÓÔÒÉÒÕÀÔÓÑ × ËÏÎÆÉÇ ÆÁÊÌÅ × ÏÐÉÓÁÎÉÉ ÃÅÐÏÞÅË ÆÉÌØÔÒÏ×:
-header_filters=regexp,my_func
-ÇÄÅ ÉÍÑ ÆÉÌØÔÒÁ - ÜÔÏ ÌÉÂÏ ÎÁÚ×ÁÎÉÅ c ÍÏÄÕÌÑ, ÌÉÂÏ ÎÁÚ×ÁÎÉÅ ÐÅÒÌ ÆÕÎËÃÉÉ
-ôÉÐÙ ÆÉÌØÔÒÏ×:
-* header_filters - ÆÉÌØÔÒ ÚÁÇÏÌÏ×ËÏ×
-* mime_filters - ÆÉÌØÔÒ ÄÌÑ ËÁÖÄÏÊ mime ÞÁÓÔÉ
-* message_filters - ÆÉÌØÔÒ ×ÓÅÇÏ ÓÏÏÂÝÅÎÉÑ ÃÅÌÉËÏÍ
-* url_filters - ÆÉÌØÔÒÙ URL ÓÓÙÌÏË
-ó×ÏÉ ÒÅÚÕÌØÔÁÔÙ ÆÉÌØÔÒÙ ÒÅÇÉÓÔÒÉÒÕÀÔ ÐÒÉ ÐÏÍÏÝÉ ÄÏÂÁ×ÌÅÎÉÑ ÒÅÚÕÌØÔÁÔÁ × ÍÅÔÒÉËÕ.
-
-2) íÅÔÒÉËÁ - ÜÔÏ ÓÉÍ×ÏÌØÎÏÅ ÚÎÁÞÅÎÉÅ, × ËÏÔÏÒÏÍ ÒÅÇÉÓÔÒÉÒÕÀÔ Ó×ÏÉ ÒÅÚÕÌØÔÁÔÙ ÆÉÌØÔÒÙ
-óÕÝÅÓÔ×ÕÅÔ ÍÅÔÒÉËÁ ÐÏ ÕÍÏÌÞÁÎÉÀ - "default", × ËÏÔÏÒÏÊ ÒÅÇÉÓÔÒÉÒÕÀÔ ÒÅÚÕÌØÔÁÔÙ ÆÉÌØÔÒÙ,
-ÄÌÑ ËÏÔÏÒÙÈ Ñ×ÎÏ ÎÅ ÏÐÒÅÄÅÌÅÎÁ ÍÅÔÒÉËÁ
-äÌÑ ËÁÖÄÏÊ ÍÅÔÒÉËÉ ÓÕÝÅÓÔ×ÕÅÔ ÓÐÅÃÉÁÌØÎÁÑ ÆÕÎËÃÉÑ ËÏÎÓÏÌÉÄÁÃÉÉ, ËÏÔÏÒÁÑ ÒÁÓÓÞÉÔÙ×ÁÅÔ ËÏÜÆÆÉÃÉÅÎÔÙ
-ÒÅÚÕÌØÔÁÔÏ× ÓÏÇÌÁÓÎÏ ×ÎÕÔÒÅÎÎÅÊ ÌÏÇÉËÅ ÓÏÏÔ×ÅÔÓÔ×ÉÑ ÓÉÍ×ÏÌÏ× É ËÏÜÆÆÉÃÉÅÎÔÏ×. ðÏ ÕÍÏÌÞÁÎÉÀ ÔÁËÏÊ
-ÆÕÎËÃÉÅÊ Ñ×ÌÑÅÔÓÑ ÐÒÏÓÔÁÑ ÓÕÍÍÁ, ËÏÔÏÒÁÑ ÎÁÓÔÒÁÉ×ÁÅÔÓÑ ÏÓÏÂÙÍ ÏÂÒÁÚÏÍ × ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÍ ÆÁÊÌÅ:
-
-# âÌÏË factors
-factors {
- # îÁÐÒÉÍÅÒ, "SURBL_DNS"=5.0
- "SYMBOL_NAME" = coefficient;
-};
-ôÁËÖÅ ÄÌÑ ÍÅÔÒÉËÉ ÍÏÖÎÏ ÚÁÒÅÇÉÓÔÒÉÒÏ×ÁÔØ ÏÓÏÂÕÀ ÆÕÎËÃÉÀ, ÐÒÏÐÉÓÁ× × ÏÐÉÓÁÎÉÉ ÍÅÔÒÉËÉ
-metric {
- name = "test_metric";
- function = "some_function";
- required_score = 20.0;
-};
-ðÏËÁ ÐÏÄÄÅÒÖÉ×ÁÀÔÓÑ ÔÏÌØËÏ ÐÅÒÌÏ×ÙÅ ÆÕÎËÃÉÉ.
-
-3) òÅÚÕÌØÔÁÔ - ÜÔÏ ÐÁÒÁ ÚÎÁÞÅÎÉÊ: SYMBOL:FLAG, ÐÒÉ ÜÔÏÍ, SYMBOL - ÜÔÏ
-ÓÔÒÏÞËÁ, ÈÁÒÁËÔÅÒÉÚÕÀÝÁÑ ÒÅÚÕÌØÔÁÔ, Á FLAG - ÓÒÁÂÏÔÁÌ ÄÁÎÎÙÊ ÆÉÌØÔÒ ÉÌÉ ÎÅÔ
-(1 ÉÌÉ 0). òÅÚÕÌØÔÁÔ ÄÏÂÁ×ÌÑÅÔÓÑ × ÍÅÔÒÉËÕ, ÐÏÓÌÅ ÞÅÇÏ ÐÅÒÅÄÁÅÔÓÑ ÆÕÎËÃÉÉ ËÏÎÓÏÌÉÄÁÃÉÉ.
-
-4) éÔÏÇ - ÎÁ ×ÙÈÏÄÅ ÍÙ ÉÍÅÅÍ ÏÂÒÁÂÏÔÁÎÎÏÅ ÓÏÏÂÝÅÎÉÅ, ÓÐÉÓÏË ÍÅÔÒÉË É ÉÈ ÓÉÍ×ÏÌÏ× É ÒÅÚÕÌØÔÁÔÙ
-ÐÒÏ×ÅÒËÉ.
-
-ðÒÏÔÏËÏÌ.
-=========
-
-æÏÒÍÁÔ ÏÔ×ÅÔÁ:
-SPAMD/1.1 0 EX_OK
-\ / \/
- ÷ÅÒÓÉÑ ëÏÄ
- ÏÛÉÂËÉ
-Spam: False ; 2 / 5
-üÔÏ ÆÏÒÍÁÔ ÓÏ×ÍÅÓÔÉÍÏÓÔÉ Ó sa-spamd (ÂÅÚ ÍÅÔÒÉË)
-
-îÏ×ÙÊ ÆÏÒÍÁÔ ÏÔ×ÅÔÁ:
-RSPAMD/1.0 0 EX_OK
-Metric: Name ; Spam_Result ; Spam_Mark / Spam_Mark_Required
-Metric: Name2 ; Spam_Result2 ; Spam_Mark2 / Spam_Mark_Required2
-
-úÁÇÏÌÏ×ËÏ× ÔÉÐÁ metric ÍÏÖÅÔ ÂÙÔØ ÎÅÓËÏÌØËÏ.
-æÏÒÍÁÔ ×Ù×ÏÄÁ ÓÉÍ×ÏÌÏ×:
-SYMBOL1, SYMBOL2, SYMBOL3 -- ÆÏÒÍÁÔ ÓÏ×ÍÅÓÔÉÍÏÓÔÉ Ó sa-spamd
-Metric: SYMBOL1, SYMBOL2, SYMBOL3 -- ÆÏÒÍÁÔ rspamd
-
-æÏÒÍÁÔ ÏÔ×ÅÔÁ ÚÁ×ÉÓÉÔ ÏÔ ÆÏÒÍÁÔÁ ÚÁÐÒÏÓÁ:
-PROCESS SPAMC/1.2
-\ / \ /
-ëÏÍÁÎÄÁ ÷ÅÒÓÉÑ
-
-SPAMC - ÐÒÏÔÏËÏÌ ÓÏ×ÍÅÓÔÉÍÏÓÔÉ Ó sa-spamd
-RSPAMC - ÎÏ×ÙÊ ÐÒÏÔÏËÏÌ rspamd
-÷ ÌÀÂÏÍ ÉÚ ÒÅÖÉÍÏ× ÒÁÂÏÔÙ ÐÏÄÄÅÒÖÉ×ÁÀÔÓÑ ÓÌÅÄÕÀÝÉÅ ÚÁÇÏÌÏ×ËÉ:
-Content-Length - ÄÌÉÎÁ ÓÏÏÂÝÅÎÉÑ
-Helo - HELO, ÐÏÌÕÞÅÎÎÙÊ ÏÔ ËÌÉÅÎÔÁ
-From - MAIL FROM
-IP - IP ËÌÉÅÎÔÁ
-Recipient-Number - ÞÉÓÌÏ ÒÅÃÉÐÉÅÎÔÏ×
-Rcpt - ÒÅÃÉÐÉÅÎÔ
-
-üÔÉ ÚÎÁÞÅÎÉÑ ÍÏÇÕÔ ÉÓÐÏÌØÚÏ×ÁÔØÓÑ × ÆÉÌØÔÒÁÈ rspamd.
--- /dev/null
+API Rspamd.
+===========
+
+TODO.
+
+Логика работы фильтров rspamd.
+==============================
+
+1) Все фильтры регистрируются в конфиг файле в описании цепочек фильтров:
+header_filters=regexp,my_func
+где имя фильтра - это либо название c модуля, либо название перл функции
+Типы фильтров:
+* header_filters - фильтр заголовков
+* mime_filters - фильтр для каждой mime части
+* message_filters - фильтр всего сообщения целиком
+* url_filters - фильтры URL ссылок
+Свои результаты фильтры регистрируют при помощи добавления результата в метрику.
+
+2) Метрика - это символьное значение, в котором регистрируют свои результаты фильтры
+Существует метрика по умолчанию - "default", в которой регистрируют результаты фильтры,
+для которых явно не определена метрика
+Для каждой метрики существует специальная функция консолидации, которая рассчитывает коэффициенты
+результатов согласно внутренней логике соответствия символов и коэффициентов. По умолчанию такой
+функцией является простая сумма, которая настраивается особым образом в конфигурационном файле:
+
+# Блок factors
+factors {
+ # Например, "SURBL_DNS"=5.0
+ "SYMBOL_NAME" = coefficient;
+};
+Также для метрики можно зарегистрировать особую функцию, прописав в описании метрики
+metric {
+ name = "test_metric";
+ function = "some_function";
+ required_score = 20.0;
+};
+Пока поддерживаются только перловые функции.
+
+3) Результат - это пара значений: SYMBOL:FLAG, при этом, SYMBOL - это
+строчка, характеризующая результат, а FLAG - сработал данный фильтр или нет
+(1 или 0). Результат добавляется в метрику, после чего передается функции консолидации.
+
+4) Итог - на выходе мы имеем обработанное сообщение, список метрик и их символов и результаты
+проверки.
+
+Протокол.
+=========
+
+Формат ответа:
+SPAMD/1.1 0 EX_OK
+\ / \/
+ Версия Код
+ ошибки
+Spam: False ; 2 / 5
+Это формат совместимости с sa-spamd (без метрик)
+
+Новый формат ответа:
+RSPAMD/1.0 0 EX_OK
+Metric: Name ; Spam_Result ; Spam_Mark / Spam_Mark_Required
+Metric: Name2 ; Spam_Result2 ; Spam_Mark2 / Spam_Mark_Required2
+
+Заголовков типа metric может быть несколько.
+Формат вывода символов:
+SYMBOL1, SYMBOL2, SYMBOL3 -- формат совместимости с sa-spamd
+Metric: SYMBOL1, SYMBOL2, SYMBOL3 -- формат rspamd
+
+Формат ответа зависит от формата запроса:
+PROCESS SPAMC/1.2
+\ / \ /
+Команда Версия
+
+SPAMC - протокол совместимости с sa-spamd
+RSPAMC - новый протокол rspamd
+В любом из режимов работы поддерживаются следующие заголовки:
+Content-Length - длина сообщения
+Helo - HELO, полученный от клиента
+From - MAIL FROM
+IP - IP клиента
+Recipient-Number - число реципиентов
+Rcpt - реципиент
+
+Эти значения могут использоваться в фильтрах rspamd.