Skip to main content

Использование fuzzy хешей

English version

Введение​

Нечеткие хеши (fuzzy hashes) используются для поиска похожих писем - то есть, при помощи такого метода можно найти сообщения, которые содержат такой же или незначительно измененный текст. Данная технология хорошо подходит для блокировки спам-рассылок, которые отправляются сразу многим пользователям. Так как хеш функция однонаправлена, то восстановить исходный текст, имея только хеш, невозможно, что позволяет направлять запросы сторонним хранилищам хешей без риска раскрытия информации.

Следует отметить, что rspamd использует нечеткие хеши не только для сравнения текстовых данных, но и изображений и других вложений в письмах. Однако в этом случае отсутствует элемент нечеткой логики, и rspamd ищет точные соответствия для одинаковых объектов.

Данная статья предназначена для администраторов почтовых систем, которые хотят создать собственное хранилище хешей и обучать его самостоятельно.

Шаг 1: выбор источников хешей​

В первую очередь необходимо выбрать источники образцов спама для обучения. Основной принцип - использование для обучения спам-рассылок, которые приходят многим пользователям. Существует два основных подхода к решению подобной задачи:

  • использование жалоб пользователей;
  • создание ловушек для спама (honeypot).

Использование жалоб пользователей​

Пользователи являются одним из ресурсов, позволяющих оценивать качество работы системы фильтрации спама, поэтому желательно предусмотреть механизм использования жалоб пользователей для обучения хранилища хешей. К сожалению, пользователи часто жалуются и на легитимные письма, на которые они сами же и подписались: рассылки магазинов, уведомления от систем бронирования билетов и даже на личные письма, которые им по каким-то причинам не нравятся. Многие пользователи просто не видят разницу между кнопками "удалить" и "пожаловаться на спам". Возможно, хорошей идеей будет запросить у пользователя дополнительную информацию о жалобе, например, почему он считает, что это письмо спам, а также обратить внимание пользователя на то, что он может отписаться от получения рассылок.

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

В rspamd также есть две возможности, позволяющие отсеивать некоторые "ложные" срабатывания:

  1. вес хеша;
  2. фильтры обучения.

Первый метод довольно прост: давайте назначим каждой жалобе некоторый вес и при каждом обучении будем прибавлять его к сохраненному значению соответствующего хеша. При совпадении с хешем rspamd назначает не полные очки символа сразу: их величина растет вместе с весом хеша и приближается к полному значению, когда вес достигает параметра hits_limit правила (множитель равен tanh(e * вес / hits_limit)). Например, если вес жалобы w=1, а hits_limit равен 20, то одна жалоба дает около 14% очков символа, 10 жалоб - около 88%, а 20 жалоб - около 99%. Таким образом, хеши с малым весом тоже добавляют небольшие очки. Чтобы полностью игнорировать слабые совпадения, задайте в правиле параметр weight_threshold: совпадения, множитель которых (доля очков символа, описанная выше) меньше этого значения, не учитываются.

Второй метод - фильтры обучения - позволяет написать некоторые условия на языке Lua, которые запрещают обучение, скажем, для писем с определенного домена (например, facebook.com). Возможности фильтров достаточно обширны, но требуют ручной работы по их настройке.

Настройка ловушек спама​

Для данного метода необходимо иметь такие почтовые адреса, на которые не приходит легитимная почта, зато приходит много спама. Основная идея заключается в том, чтобы "засветить" адрес в базах спамеров, не показывая его легитимным пользователям. Для этого можно, например, разместить на достаточно популярном веб-сайте элемент iframe, который не отображается пользователям (имеет свойство hidden или нулевой видимый размер), но содержит доступные ботам email-адреса ловушек. В последнее время этот метод стал не очень эффективен, так как спамеры научились обходить такие приемы.

Другой возможный способ создания ловушки - это поиск доменов, бывших ранее популярными, но не работающих в настоящее время (адреса из этих доменов находятся во многих спамерских базах). В этом случае нужны фильтры обучения, так как высока вероятность того, что в "черный" список попадут легитимные письма, например, от социальных сетей или служб рассылки.

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

Шаг 2: Настройка хранилища​

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

Важное замечание: хранилище работает не с письмами, а с готовыми хешами. То есть, чтобы преобразовать письмо в его хеш нужен отдельный процесс сканера или контроллера:

Функции хранилища:

  1. Хранение и проверка хешей
  2. Транспортное шифрование протокола
  3. Удаление устаревших хешей
  4. Контроль доступа (как на запись, так и на чтение)
  5. Репликация (средствами Redis)

Архитектура хранилища​

По умолчанию хеши хранятся в Redis (backend = "redis" в /etc/rspamd/worker-fuzzy.inc). Каждый хеш - это ключ Redis, состоящий из префикса prefix (по умолчанию fuzzy) и значения хеша, а шинглы текстовых хешей хранятся в отдельных ключах. Если в local.d/worker-fuzzy.inc не заданы servers (или read_servers и write_servers), хранилище использует серверы Redis из local.d/redis.conf (см. настройку Redis). Чтобы хранилище хешей работало с другими серверами Redis, чем остальной rspamd, задайте servers в local.d/worker-fuzzy.inc или добавьте секцию fuzzy в local.d/redis.conf:

# local.d/redis.conf
servers = "127.0.0.1:6379";

# Redis servers for the fuzzy storage only
fuzzy {
servers = "10.0.0.5:6379";
}

Хранилище хешей rspamd всегда выполняет запись строго из одного процесса - первого процесса хранилища. Он ведет очередь обновлений, а остальные процессы просто передают запросы на запись от клиентов в эту общую очередь. По умолчанию очередь записывается в хранилище один раз в минуту (параметр sync), а команда rspamadm control fuzzysync записывает ее немедленно. Таким образом, хранилище рассчитано на профиль нагрузки с преобладанием запросов на чтение.

Старый бэкенд SQLite по-прежнему поддерживается. Для его использования задайте бэкенд и путь к файлу базы, который должен принадлежать пользователю rspamd:

# local.d/worker-fuzzy.inc
backend = "sqlite";
hash_file = "${DBDIR}/fuzzy.db";

sqlite крайне плохо работает при конкурентных запросах на запись: в этом случае производительность СУБД падает на несколько порядков, поэтому запись из одного процесса особенно важна для этого бэкенда. Хеши из существующей базы SQLite можно перенести в Redis командой rspamadm fuzzyconvert.

Устаревание хешей​

Другой важной задачей хранилища является удаление устаревших хешей из базы (параметр expire). В Redis каждый хеш и его шинглы хранятся со временем жизни (TTL), равным expire, и Redis удаляет их сам; при использовании SQLite устаревшие хеши удаляет процесс хранилища. Так как обычно продолжительность рассылок спама ограничена, то нет смысла хранить хеши постоянно. Разумным будет сопоставить количество хешей, которые приходят на обучение в течение определенного времени, с достаточным для их хранения размером оперативной памяти. Redis хранит все данные в памяти: например, в тесте с rspamd 4.2.2 каждый текстовый хеш вместе с 32 шинглами занимал около 7,5 КБ памяти Redis, то есть 400 тысяч текстовых хешей требуют около 3 ГБ. Хеши изображений и вложений не имеют шинглов и занимают намного меньше.

Не рекомендуется допускать увеличение базы до объема, который превышает размер доступной оперативной памяти, из-за значительного ухудшения производительности. Кроме того, нет смысла хранить хеши дольше, чем приблизительно три месяца. Поэтому, если у вас небольшое количество хешей, пригодных для обучения, то лучше установить устаревание в 90 дней. В противном случае лучше установить более короткий период устаревания.

Пример настройки​

За хранение нечетких хешей отвечает процесс rspamd под названием fuzzy_storage. Для включения и настройки этого процесса используется файл /etc/rspamd/local.d/worker-fuzzy.inc:

# local.d/worker-fuzzy.inc
# Socket to listen on (UDP and TCP)
bind_socket = "*:11335";

# Number of processes to serve this storage (useful for read scaling)
count = 4;

# Storage backend: "redis" (default) or "sqlite"
backend = "redis";

# Redis servers for this storage only; if not set, the servers
# from local.d/redis.conf are used
#servers = "127.0.0.1:6379";

# Prefix for Redis keys (default: "fuzzy")
#prefix = "fuzzy";

# Hashes storage time (3 months)
expire = 90d;

# Write queued updates to the storage each minute
sync = 1min;

Этот файл включается внутрь секции worker "fuzzy" в rspamd.conf после настроек по умолчанию из /etc/rspamd/worker-fuzzy.inc, поэтому обертка worker "fuzzy" { ... } в нем не нужна. То же относится к остальным примерам настройки хранилища в этой статье. По умолчанию процесс отключен директивой count = -1 в rspamd.conf, поэтому для его включения нужно задать count, как в примере. По умолчанию хранилище слушает localhost:11335; значение *:11335 из примера позволяет принимать запросы и с других хостов.

Настройки доступа​

Запрашивать хеши может любой клиент (если доступ не ограничен параметрами blocked или encrypted_only), но добавлять и удалять хеши можно только с адресов, перечисленных в allow_update. В поставляемом файле /etc/rspamd/worker-fuzzy.inc задано allow_update = ["localhost"], то есть по умолчанию изменения принимаются только с локального хоста. Чтобы разрешить обучение с других адресов, необходимо задать список доверенных IP-адресов и/или сетей. Как правило, лучше всего разрешить запись только с локальных адресов (127.0.0.1 и ::1), так как fuzzy storage использует протокол UDP, который не имеет защиты от подделки IP-адреса источника (что можно исправить путем настройки верификации обратного маршрута на маршрутизаторе, но это зачастую игнорируется системными администраторами):

# local.d/worker-fuzzy.inc
allow_update = ["127.0.0.1", "::1"];

# or 10.0.0.0/8, for internal network

Адреса из local.d/worker-fuzzy.inc добавляются к списку по умолчанию; чтобы заменить список, задайте allow_update в override.d/worker-fuzzy.inc.

Важное замечание: Если в списке серверов в конфигурации плагина fuzzy_check (см. далее) присутствует имя localhost, необходимо разрешить доступ как с адреса 127.0.0.1, так и с адреса ::1, так как резолвер возвращает поочередно все известные для имени хоста адреса. Имя хоста в allow_update, например localhost в настройках по умолчанию, преобразуется во все его адреса.

Также для разграничения доступа может использоваться транспортное шифрование, которое мы рассмотрим далее.

Транспортное шифрование​

Протокол работы с хранилищем хешей позволяет включать необязательное (opportunistic) или обязательное шифрование, основанное на криптосистеме с открытым ключом. Архитектура шифрования основана на конструкции cryptobox: https://nacl.cr.yp.to/box.html и похожа на алгоритм end-to-end шифрования DNSCurve: https://dnscurve.org/.

Чтобы настроить транспортное шифрование, в первую очередь нужно создать пару ключей для сервера хранилища с помощью команды rspamadm keypair -u:

keypair {
pubkey = "og3snn8s37znxz53mr5yyyzktt3d5uczxecsp3kkrs495p4iaxzy";
privkey = "o6wnij9r4wegqjnd46dyifwgf5gwuqguqxzntseectroq7b3gwty";
id = "f5yior1ag3csbzjiuuynff9tczknoj9s9b454kuonqknthrdbwbqj63h3g9dht97fhp4a5jgof1eiifshcsnnrbj73ak8hkq6sbrhed";
algorithm = "curve25519";
type = "kex";
}

Данная команда создает уникальную пару ключей, в которой открытый ключ (public key) может быть скопирован вручную на хост клиента (например, через ssh) или же опубликован каким-либо способом, гарантирующим достоверность (например, заверен цифровой подписью или размещен на HTTPS-сайте). Закрытый ключ (private key) должен храниться в секрете.

Каждое хранилище может работать одновременно с произвольным числом ключей:

# local.d/worker-fuzzy.inc
keypair = [
{
pubkey = "...";
privkey = "...";
},
{
pubkey = "...";
privkey = "...";
},
{
pubkey = "...";
privkey = "...";
}
]

Эта возможность полезна для создания закрытых хранилищ, где доступ разрешен только тем клиентам, которым известен один из открытых ключей:

Для включения режима обязательного шифрования используется опция encrypted_only:

# local.d/worker-fuzzy.inc
encrypted_only = true;

keypair = [
{
pubkey = "...";
privkey = "...";
}
]

В этом режиме клиенты, у которых нет действительного открытого ключа, не смогут обращаться к хранилищу.

Проверка работы хранилища​

Для проверки работы хранилища можно использовать команду rspamadm control fuzzystat. Пример ее вывода для небольшого тестового хранилища с бэкендом Redis:

Statistics for storage u33g775t7jfns8x4ca118c4q1wbfdo3
blocked_requests: 0
decrypt_errors: 0
ratelimited_requests: 0
fuzzy_checked: (v0.6: 0), (v0.8: 0), (v0.9: 24)
fuzzy_shingles: (v0.6: 0), (v0.8: 0), (v0.9: 24)
fuzzy_found: (v0.6: 0), (v0.8: 0), (v0.9: 23)
fuzzy_stored: 53
fuzzy_expired: 0
invalid_requests: 0
delayed_hashes: 0

Storage statistics (1 in 10 digests sampled, 8 of 53, scanned 2026-10-08 10:43:59 on 127.0.0.1:6379 in 0 seconds):
Flag 11: 53 hashes, weight avg 10.0, max 10
Multi-flag hashes: 0
Shingled hashes: 53 (1.70k shingle slots)
Age: <1d 53, <7d 0, <30d 0, older 0

Keys statistics:
Key id: r5fc7ix5t86mq
Checked: 23 (0 per hour in average)
Matched: 22 (0 per hour in average)
Errors: 0
Added: 1
Deleted: 0

Flags stat:
[11]:
Matched: 22 (0 per hour in average)
Errors: 0
Added: 0
Deleted: 0
...

Сначала отображается общая статистика хранилища: количество сохраненных и устаревших хешей, а также число проверенных хешей, проверок шинглов и найденных хешей. Эти три счетчика разбиты по версиям протокола клиента. Хранилище принимает запросы от rspamd 1.0 и новее, и три значения относятся к запросам от rspamd 1.0 - 1.6, от rspamd 1.7 - 3.x и от rspamd 4.0 и новее (клиенты с поддержкой нескольких флагов для одного хеша). В rspamd 4.2.2 rspamadm по-прежнему подписывает эти столбцы старыми именами v0.6, v0.8 и v0.9.

При использовании Redis число сохраненных хешей и блок Storage statistics вычисляются периодическим сканированием ключей Redis (по умолчанию не чаще одного раза в 4 часа, см. count_scan в /etc/rspamd/worker-fuzzy.inc). Значения по флагам, шинглам и возрасту хешей вычисляются по выборке хешей.

Далее по каждому из ключей, сконфигурированных в хранилище, отображается подробная статистика, в том числе по флагам, и по последним IP-адресам клиентов, от которых были получены запросы. И в заключение можно увидеть общую статистику по IP-адресам.

Для изменения вывода этой команды можно использовать следующие опции (например, rspamadm control fuzzystat -n):

  • -n: выводить "сырые" числа без сокращения
  • --short: не выводить подробную статистику по ключам и IP-адресам
  • --no-keys: не выводить статистику по ключам
  • --no-ips: не выводить статистику по IP-адресам
  • --sort: сортировать:
    • checked: по числу проверенных хешей (по умолчанию)
    • matched: по числу найденных хешей
    • errors: по числу ошибочных запросов
    • name: по идентификатору ключа или IP-адресу

Шаг 3: Настройка плагина fuzzy_check​

Плагин fuzzy_check используется процессами-сканерами для проверки писем и процессами-контроллерами для обучения хранилища.

Функции плагина:

  1. Обработка писем и создание хешей их отдельных частей
  2. Выполнение запросов к хранилищу
  3. Транспортное шифрование

Обучение производится командой rspamc fuzzy_add:

$ rspamc -f 11 -w 10 fuzzy_add <message|directory|stdin>

Где параметр -w задает вес хеша, который мы обсуждали ранее, а -f указывает номер флага. Флаг должен быть указан в fuzzy_map правила, которое не работает в режиме только для чтения, иначе контроллер вернет ошибку 404. В примере local.d/fuzzy_check.conf ниже флаг 11 соответствует символу LOCAL_FUZZY_DENIED.

Флаги позволяют хранить хеши различного происхождения в хранилище. Например, хеши спам-ловушек, хеши жалоб пользователей и хеши писем из "белого" списка. Каждый флаг может быть ассоциирован с собственным символом и, соответственно, иметь свой вес при проверке письма:

Флаг можно указывать как по номеру:

$ rspamc -f 11 -w 10 fuzzy_add <message|directory|stdin>

так и по символу:

$ rspamc -S LOCAL_FUZZY_DENIED -w 10 fuzzy_add <message|directory|stdin>

Соответствие символов флагам нужно настроить в секции fuzzy_map правила rule. Символ FUZZY_DENIED соответствует флагу 1 правила rspamd.com из modules.d/fuzzy_check.conf, которое работает только для чтения, поэтому для обучения локального хранилища из этого примера он не подходит.

Пример local.d/fuzzy_check.conf:

# local.d/fuzzy_check.conf
rule "local" {
# Fuzzy storage server list
servers = "localhost:11335";
# Default symbol for unknown flags
symbol = "LOCAL_FUZZY_UNKNOWN";
# Additional mime types to store/check
mime_types = ["*"];
# Default hits_limit for flags without their own value
hits_limit = 20.0;
# Whether we can learn this storage
read_only = no;
# Ignore unknown flags
skip_unknown = yes;
# Hash generation algorithm
algorithm = "mumhash";
# Use direct hash for short texts
short_text_direct_hash = true;

# Map flags to symbols
fuzzy_map = {
LOCAL_FUZZY_DENIED {
# Hash weight for nearly the full symbol score
hits_limit = 20.0;
# Flag to match
flag = 11;
}
LOCAL_FUZZY_PROB {
hits_limit = 10.0;
flag = 12;
}
LOCAL_FUZZY_WHITE {
hits_limit = 2.0;
flag = 13;
}
}
}

Пример local.d/fuzzy_group.conf:

# local.d/fuzzy_group.conf
max_score = 12.0;
symbols = {
"LOCAL_FUZZY_UNKNOWN" {
weight = 5.0;
description = "Generic fuzzy hash match";
}
"LOCAL_FUZZY_DENIED" {
weight = 12.0;
description = "Denied fuzzy hash";
}
"LOCAL_FUZZY_PROB" {
weight = 5.0;
description = "Probable fuzzy hash";
}
"LOCAL_FUZZY_WHITE" {
weight = -2.1;
description = "Whitelisted fuzzy hash";
}
}

Рассмотрим некоторые полезные опции, которые можно настраивать в модуле.

Во-первых, hits_limit (до rspamd 3.14.3 этот параметр назывался max_score, старое имя по-прежнему принимается) задает вес хеша, при котором совпадение получает почти полные очки символа, как описано в первом шаге. Его можно задать для всего правила и для каждого флага в fuzzy_map; флаг без собственного значения использует значение правила.

Вторым полезным параметром является mime_types, который определяет, какие типы вложений проверять (и обучать!) в данном хранилище. Этот параметр представляет собой список допустимых типов в формате ["type/subtype", "*/subtype", "type/*", "*"], где * заменяет любой допустимый тип. Как правило, достаточно сохранять хеши всех вложений типа application/*. Текстовые части и вложенные изображения автоматически проверяются плагином fuzzy_check (то есть, нет нужды добавлять image/* в список проверяемых вложений). Стоит иметь в виду, что вложения и изображения проверяются на точное соответствие, в отличие от текстов, которые могут немного отличаться.

Очень важной является опция read_only, если вы хотите обучать ваше хранилище. По умолчанию правило разрешает обучение (read_only = false):

read_only = true; # disallow learning
read_only = false; # allow learning (default)

Параметр encryption_key задает открытый ключ хранилища и включает шифрование запросов.

Параметр algorithm определяет алгоритм генерации хешей из текстовых частей писем (для вложений и изображений всегда используется blake2b). Исторически в rspamd использовался алгоритм siphash. Однако он имеет определенные проблемы с производительностью, особенно на устаревшем "железе" (CPU до Intel Haswell). Поэтому при создании собственного хранилища стоит рассмотреть другие, более быстрые алгоритмы:

  • xxhash
  • mumhash
  • fasthash

Для большинства задач я рекомендую использовать mumhash или fasthash, которые демонстрируют отличную производительность на множестве платформ. Поставляемое правило rspamd.com использует mumhash. Правило без параметра algorithm использует siphash, поэтому для нового хранилища алгоритм стоит задать явно. Для оценки производительности вы можете скомпилировать набор тестов из исходного кода rspamd:

$ make rspamd-test

и запустить тест различных вариантов алгоритмов вычисления хешей на вашей платформе:

test/rspamd-test -p /rspamd/shingles

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

Написание скриптов-условий для обучения​

Так как плагин fuzzy_check отвечает в том числе и за обучение, то именно в его конфигурации задается скрипт, определяющий, какие сообщения будут поступать на обучение, а какие нет. Этот скрипт представляет собой функцию Lua с одним аргументом типа rspamd_task и возвращает либо булево значение: true - обучать или false - не обучать, либо пару - булево значение и новый флаг, если в ходе выполнения скрипта выяснилось, что необходимо изменить исходный флаг обучения. Для задания условного скрипта служит параметр learn_condition, а для записи скрипта удобнее всего использовать многострочный синтаксис heredoc, который поддерживается UCL:

# Fuzzy check plugin configuration snippet
learn_condition = <<EOD
return function(task)
return true -- Always learn
end
EOD;

Приведем практические примеры полезных скриптов. Например, часто бывает нужно запретить использовать для обучения письма, отправленные с некоторых доменов. Для этого можно задать такой скрипт:

return function(task)
local skip_domains = {
'example.com',
'google.com',
}

local from = task:get_from()

if from and from[1] and from[1]['addr'] then
for i,d in ipairs(skip_domains) do
if string.find(from[1]['addr'], d) then
return false
end
end
end

return true
end

Функция должна возвращать булево значение во всех случаях: если она ничего не вернет, письмо не будет использовано для обучения.

В некоторых случаях полезно распределять обучение хешей по различным флагам в соответствии с их источником, который можно закодировать, например, в заголовке X-Source. Допустим, мы хотим иметь такое соответствие флагов и источников:

  • honeypot - "черный" список: 1
  • users_unfiltered - "серый" список: 2
  • users_filtered - "черный" список: 1
  • FP - "белый" список: 3

Тогда скрипт, осуществляющий такое распределение, может выглядеть следующим образом:

return function(task)
local skip_headers = {
['X-Source'] = function(hdr)
local sources = {
honeypot = 1,
users_unfiltered = 2,
users_filtered = 1,
FP = 3
}
local fl = sources[hdr]

if fl then return true,fl end -- Return true + new flag
return false
end
}

for h,f in pairs(skip_headers) do
local hdr = task:get_header(h) -- Check for interesting header
if hdr then
return f(hdr) -- Call its handler and return result
end
end

return false -- Do not learn if specified header is missing
end

Шаг 4: Настройка репликации хешей​

Зачастую бывает нужно собирать хеши из различных источников или иметь локальную копию удаленного хранилища. В rspamd 1.3 - 1.9 для этого была реализована репликация на уровне хранилища хешей (параметры sync_keypair, slave, masters, master_key и master_flags). В rspamd 2.0 она была удалена, и процесс хранилища теперь игнорирует эти параметры. При использовании Redis для этой задачи служит репликация Redis:

Мастером выступает основной сервер Redis, который получает все обновления хешей (добавление, модификацию или удаление). На каждой площадке слейва работают реплика Redis и процесс хранилища хешей, который обслуживает проверки из локальной реплики. Реплики Redis доступны только для чтения, поэтому процессы хранилища должны отправлять обновления на основной сервер, а реплики должны иметь возможность подключаться к нему, что нужно учитывать при настройке межсетевых экранов.

Резервное копирование и восстановление​

Данная процедура служит для резервного копирования хранилища, переноса его на другой хост или загрузки копии хешей на новый сервер Redis.

При использовании Redis хеши сохраняются средствами Redis, поэтому, если хеши должны сохраняться после перезапуска Redis, включите в его настройках снимки RDB или AOF. Чтобы сделать резервную копию, запишите в Redis накопленные обновления хранилища и запросите у Redis снимок:

rspamadm control fuzzysync
redis-cli BGSAVE

Redis записывает снимок в файл dump.rdb в своем каталоге данных (его показывает команда redis-cli CONFIG GET dir). Скопируйте файл, когда redis-cli LASTSAVE покажет новое время. Для восстановления остановите Redis, положите копию dump.rdb в его каталог данных и снова запустите Redis. Если включен AOF (appendonly yes), Redis загружает файлы AOF и игнорирует dump.rdb, поэтому на время восстановления отключите AOF и затем включите его снова. Снимок содержит все данные этого сервера Redis, в том числе данные других модулей rspamd; хеши хранилища - это ключи, начинающиеся с префикса prefix (по умолчанию fuzzy).

При использовании SQLite служит утилита sqlite3. Сначала выполните rspamadm control fuzzysync, чтобы в копию попали накопленные обновления, и сделайте копию базы:

sqlite3 /var/lib/rspamd/fuzzy.db ".backup fuzzy-backup.db"

Для восстановления остановите rspamd и выполните:

sqlite3 /var/lib/rspamd/fuzzy.db ".restore fuzzy-backup.db"

Конфигурирование репликации​

Каждая реплика настраивается директивой replicaof в конфигурации Redis, как описано в документации Redis по репликации. Процесс хранилища на площадке с репликой настраивается так, чтобы проверки выполнялись по локальной реплике, а обновления отправлялись на основной сервер:

# local.d/worker-fuzzy.inc on a site with a local Redis replica
count = 4;
# Checks are served by the local replica
read_servers = "127.0.0.1:6379";
# Updates go to the Redis primary
write_servers = "fuzzy-redis.example.com:6379";

Те же параметры read_servers и write_servers можно задать в секции fuzzy файла local.d/redis.conf. Разрешите подключения к основному серверу Redis только со своих хостов и защитите его паролем Redis (password).

Трансляция флагов с мастера на слейвы (master_flags) больше не поддерживается. Если в одно хранилище пишут несколько источников, используйте для них разные номера флагов.