MAATRIX / Блог / Спам-фильтр на своём сервере: настройка без потери писем

Спам-фильтр на своём сервере: настройка без потери писем

MAATRIX

Вы включили антиспам на своём почтовом сервере — и через неделю выясняется, что клиент писал три дня назад, а письмо тихо легло в карантин и никто его не видел. Пропущенное спам-письмо — это раздражение. Потерянное письмо от клиента — это упущенная сделка, испорченные отношения, а иногда и деньги. Разберём, как настроить спам-фильтр так, чтобы он реально отсеивал мусор, но не откусывал легитимную почту вместе с ним.

Компромисс, который никуда не денется

Любой спам-фильтр работает на одном и том же принципе: он присваивает письму оценку подозрительности и сравнивает её с порогом. Чем ниже порог (агрессивнее настройка) — тем больше реального спама отсеивается, но тем выше шанс, что письмо от нового клиента, с непривычной для вашей переписки темой или с вложением нетипичного формата тоже наберёт достаточно баллов и попадёт под раздачу. Чем выше порог (мягче настройка) — тем безопаснее для легитимной почты, но тем больше спама проходит насквозь.

Это не баг конкретного фильтра и не повод искать «тот самый идеальный движок». Это фундаментальное свойство любой системы бинарной классификации при неполной информации. У фильтра нет способа со стопроцентной уверенностью отличить письмо от нового поставщика с непривычным вложением от целенаправленного фишинга — оба формально выглядят похоже: незнакомый отправитель, нетипичный для вашей переписки контент, иногда ссылка на внешний ресурс. Различие часто видно только человеку, который знает контекст.

Отсюда практический вывод: не ищите «правильные» пороги в интернете и не копируйте чужой конфиг один в один. Правильное положение на этой шкале зависит от того, чем вы рискуете больше — пропущенным спамом или потерянным письмом. У службы поддержки, куда клиенты пишут с разных адресов впервые, риск ложного срабатывания дороже, чем у внутренней рассылки между сотрудниками одной компании. Осознанно выберите точку на этом спектре под свою почту, а не берите настройки по умолчанию как данность.

Три слоя, а не один фильтр

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

1. Репутация и аутентификация отправителя. Это первый и самый дешёвый по вычислениям фильтр: проверка SPF, DKIM, DMARC и репутации IP отправляющего сервера. Письмо, не прошедшее аутентификацию домена, с высокой вероятностью подделка — это разобрано подробно в статье про то, как письма вообще попадают в спам. Важный нюанс именно для темы ложных срабатываний: провал SPF/DKIM у легитимного письма чаще всего означает не подделку, а неправильно настроенную пересылку (форвардинг ломает SPF) или письмо, отправленное через стороннего провайдера рассылок без корректного выравнивания DKIM. Не выносите приговор по одному проваленному механизму — смотрите на DMARC-политику и совокупность признаков.

2. Анализ содержимого письма. Здесь работает движок вроде rspamd — он разбирает тело письма, заголовки, вложения и присваивает баллы за десятки эвристик: подозрительные HTML-конструкции, несоответствие Reply-To и From, характерные фразы, битые заголовки, вложения типа .exe или .js под видом документа. Подробная установка такого фильтра описана в статье про настройку rspamd на VPS. Сюда же относится байесовский классификатор — статистическая модель, которая учится на вашей собственной переписке, что для вас типично, а что нет, и со временем подстраивается под специфику именно вашего потока почты.

3. Внешние чёрные списки (RBL/DNSBL). Списки вроде Spamhaus ZEN, SORBS или Spamcop содержат IP-адреса, замеченные в рассылке спама или скомпрометированные под ботнет. Это быстрая и полезная проверка, но у неё есть слабое место для темы ложных срабатываний: в такие списки иногда попадают целые диапазоны IP shared-хостингов или VPS-провайдеров, и если легитимный отправитель арендует сервер в том же пуле адресов, что и спамер, письмо получит штраф незаслуженно. Поэтому чёрные списки лучше использовать не как жёсткий blocklist на отбраковку, а как один из сигналов внутри общей оценки.

Три слоя вместе дают возможность компенсировать слабости друг друга: письмо с чистой репутацией IP, но подозрительным содержимым получит умеренный штраф, а не мгновенный бан; письмо с новым IP, но безупречным содержимым и прошедшей аутентификацией — тоже пройдёт. Полагаться на один слой — например, только на RBL или только на content-фильтр — типичная причина, по которой фильтр либо ничего не ловит, либо ловит всё подряд.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Пороги вместо переключателя «вкл/выкл»

Практическая ошибка — воспринимать спам-фильтр как бинарный переключатель «пропустить / заблокировать». В rspamd, который сейчас чаще всего стоит на своих почтовых серверах, фактическая настройка — это несколько числовых порогов в /etc/rspamd/local.d/actions.conf:

# actions.conf — три уровня реакции вместо одного
greylist = 4;       # мягкое подозрение — временная задержка (greylisting)
add_header = 6;     # добавить заголовок X-Spam, письмо доставляется как обычно
reject = 15;         # жёсткий отказ на этапе SMTP-диалога

Смысл трёх порогов — не просто «спам / не спам», а три степени доверия:

  • Ниже greylist-порога — письмо доставляется как обычное, без пометок.
  • Между greylist и add_header — письмо получает временный отказ (soft bounce), и легитимный сервер отправителя повторит попытку через несколько минут, а большинство спам-ботов — нет, потому что они не соблюдают SMTP-стандарт повторной отправки. Это снижает поток спама почти без риска для легитимной почты — единственная цена: небольшая задержка доставки первого письма от нового отправителя.
  • Между add_header и reject — это и есть та самая «серая зона», подробнее ниже.
  • Выше reject — жёсткий отказ прямо на этапе приёма, обычно оправдан только для очень явного спама (совпадение с несколькими чёрными списками плюс явные признаки в содержимом одновременно).

Ключевая практическая рекомендация: держите порог reject заметно выше, чем add_header, и не отклоняйте письма на уровне SMTP только по одному сработавшему правилу. Резкий reject по единственному совпавшему признаку — самый частый источник потерянных легитимных писем, потому что письмо в этом случае не долетает вообще, и его невозможно найти и спасти постфактум.

Серая зона вместо мусорной корзины

Для писем, попавших в диапазон «подозрительно, но не однозначно спам», не удаляйте и не блокируйте их насовсем — направляйте в отдельную, видимую пользователю зону для ручной проверки. На практике это реализуется через связку rspamd + Sieve-фильтр в Dovecot:

# ~/.dovecot.sieve или глобальный default.sieve
require ["fileinto", "imap4flags"];

if header :contains "X-Spam-Flag" "YES" {
    if header :contains "X-Spam-Score" "6" {
        fileinto "Вероятный спам";
        stop;
    }
    fileinto "Junk";
    stop;
}

Важно, что «Вероятный спам» — это отдельная, регулярно проверяемая папка, а не автоудаление через N дней при первом же внедрении фильтра. Автоочистку старых писем из такой папки стоит включать только после того, как вы несколько недель понаблюдали, что туда реально попадает, и убедились, что легитимные письма туда не залетают систематически. Здесь же полезно завести отдельное правило пересылки копии таких писем администратору или в общий почтовый ящик поддержки — так у кого-то есть шанс заметить пропажу, даже если конечный пользователь не заглядывает в эту папку неделями.

Тот же принцип работает и на уровне вебмейла: если вы используете Roundcube (см. статью про настройку Roundcube на VPS), убедитесь, что папка с подозрительной почтой видна в списке папок по умолчанию, а не спрятана — пользователь должен иметь возможность туда заглянуть в один клик, а не искать в настройках, как её включить.

Регулярный аудит и обратная связь от пользователей

Настройка фильтра «один раз и забыли» — гарантированный способ через полгода обнаружить, что часть клиентов давно пишет вам в пустоту. Два процесса должны работать постоянно, а не разово при внедрении:

Регулярный просмотр того, что реально попадает в спам. В первые одну-две недели после включения или существенного изменения фильтра администратору стоит буквально раз в день просматривать содержимое папки карантина/«Вероятный спам» по всем ящикам и искать в ней легитимные письма. После стабилизации — раз в неделю выборочно. rspamd даёт для этого готовый инструмент — веб-интерфейс истории:

# rspamd web UI обычно слушает на 11334 порту
# смотрите историю сработавших правил и оценки за последние часы
curl -s http://127.0.0.1:11334/history | jq '.rows[] | select(.action=="reject")'

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

Явный канал для жалоб на ложные срабатывания. Пользователям нужен простой и не требующий технических знаний способ сообщить «вот это письмо ошибочно попало в спам» или «а вот это спам-письмо прошло мимо фильтра». Проще всего — специальный алиас или кнопка пересылки с меткой:

# пример: пользователь пересылает письмо на служебный адрес,
# скрипт на сервере извлекает исходный смысл через rspamc
cat forwarded_message.eml | rspamc learn_ham   # для ложного срабатывания
cat forwarded_message.eml | rspamc learn_spam  # для пропущенного спама

Обучение байесовского классификатора на реальных ошибках — самый надёжный способ со временем снизить долю ложных срабатываний именно для вашего потока почты, потому что модель подстраивается под специфику переписки конкретной компании, а не под усреднённые эвристики «спам вообще». Без обратной связи от пользователей администратор в принципе не узнает о доброй половине проблем — он видит только то, что явно легло в карантин, но не видит, что было отфильтровано молча по жёсткому reject или что пользователь сам удалил, не разобравшись.

Внедряйте изменения постепенно

Соблазн переключить фильтр из режима «почти ничего не блокирует» в режим «строгий» одним махом для всего сервера сразу — плохая идея, даже если новая конфигурация в теории лучше. Изменение порогов, добавление нового чёрного списка или включение нового модуля rspamd стоит вносить по одному изменению за раз, с паузой на наблюдение между ними — обычно от нескольких дней до недели, в зависимости от объёма почты на сервере.

Практическая последовательность внедрения:

  1. Внесите одно изменение (например, снизьте порог add_header на 1-2 балла или включите новый DNSBL-модуль).
  2. Оставьте новую настройку работать несколько дней, ежедневно проверяя историю reject- и add_header-событий на предмет знакомых, ожидаемых отправителей.
  3. Если легитимные письма начали получать повышенные баллы — откатите именно это изменение, а не всю конфигурацию целиком, и разберитесь, какой конкретно модуль или правило дало ложный сигнал.
  4. Только после стабилизации переходите к следующему изменению.

Такой пошаговый подход медленнее, чем один раз сразу настроить «по учебнику», зато откат единичного неудачного шага занимает минуты и затрагивает предсказуемый набор писем, а откат резкого изменения всей конфигурации сразу означает, что вы уже не знаете, сколько писем потеряно за прошедшие дни и от кого. Для новых доменов и IP это особенно важно — сервер только нарабатывает репутацию, и слишком резкий переход к строгим правилам одновременно с этим процессом может дать вам ложную картину «фильтр работает плохо», хотя причина в незрелой репутации самого сервера, разобранной в статье про настройку SPF, DKIM и DMARC.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Что важнее — не пропустить спам или не потерять письмо?

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

Можно ли просто взять чужой готовый конфиг rspamd с жёсткими порогами и поставить у себя?

Можно как стартовую точку, но не как окончательное решение. Чужие пороги откалиброваны под чужой поток почты и чужой профиль риска. Обязательно пройдите период наблюдения и скорректируйте под себя.

Сколько времени нужно, чтобы фильтр «настроился» после установки?

Однозначного срока нет — зависит от объёма почты и от того, как быстро вы кормите байесовский классификатор реальными примерами через learn_spam/learn_ham. Ориентировочно первые недели две-три — период повышенного внимания администратора, дальше режим можно перевести на еженедельные выборочные проверки.

Что делать, если письмо от постоянного клиента вдруг попало в карантин?

Проверьте историю rspamd для этого письма — обычно видно, какое именно правило дало основной вклад в оценку. Часто причина в том, что клиент сменил провайдера почты, IP или систему рассылки, и его новая инфраструктура ещё не наработала репутацию. Добавьте отправителя в белый список (whitelist_domains.map в rspamd) сразу, чтобы не повторилось.

Нужны ли внешние чёрные списки, если уже настроен content-анализ?

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

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →