Данная статья является логическим продолжением статьи "Интеграция почтового анти-спама rspamd с opensmtpd" из-за некоторого вызова, который мне бросили, сказав, что сложно реализовать greylisting в связке opensmtpd+rspamd.


"Историй успеха" интеграции greylisting в opensmtpd я не встречал (если они существуют, то просьба написать в комментариях).


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


Мне удалось реализовать простой способ greylisting'а.



Несколько уточнений:


  1. Способ простой только для того случая, если реализация связки opensmtpd+rspamd сделана через скрипт-прослойку mda.


  2. Реализация greylisting'а для opensmtpd существует через фильтр. Но, как знают, заинтересованные в opensmtpd лица, стабильной реализации фильтров в opensmtpd нет. Кроме того, не хотелось добавлять ещё один демон при наличии встроенного грейлистинга в rspamd.


  3. Реализация грейлистинга для opensmtpd существует для freebsd и spamd. Подробностями реализации не интересовался, т.к. демона spamd под linux нет.


  4. Реализация является костылём и использованием недокументированных возможностей, но куда мы без них в IT?

Теория


Greylisting — методика отброса спама, основанная на том, что спам-программы хотят разослать как можно больше спама здесь и в данную секунду.


Упрощённая логика грейлистинга: если к нам приходит письмо, то мы отвечаем отправителю временной ошибкой, сами запоминаем отправителя (например, на сутки) для того, чтобы принять от него письмо через некоторое время (например, через 5 минут).


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


После того, как мы отправителя запомнили, то в течение суток (как пример), проверка на грейлисты не делается повторно. Это позволяет сократить время доставки повторного письма (если это правильный отправитель).


В postfix+amavis+spamasassin greylisting делался, если не ошибаюсь, по доменным именам. В rspamd ключём для greylisting'а сделан IP адрес отправителя с маской /19 (конфигурируемо). Со стороны всеобщей кластеризации и гео-распределённых сервисов — это выглядит как более правильное решение, но и обсуждаемое, с другой стороны.


К сожалению, всё вышесказанное в теории выглядит хорошо, но на практике, когда на чайниках, микроволновках и компьютерах обычных пользователей существует множество ботнетов, которые рассылают спам через обычный Outlook (как он там, существует ещё до сих пор на Windows?) — всё не так замечательно. Но как-то методика работает и отказываться от неё не стоит.


Практика


redis в rpsamd


Включаем поддержку редиса в rpsamd. Модуль грейлистинга хранит в редисе свои данные.


# /etc/rspamd/local.d/redis.conf
servers = "redis.example.com";
password = "example_password";

Запускаем редис (в докере, например, это делается одной командой).


greylisting в rspamd


Включаем модуль грейлистинга (по умолчанию, он выключен). expire — время, на которое отправитель становится доверенным, после прохождения проверки. Я специально подкрутил побольше. По умолчанию — 86400 секунд.


# /etc/rspamd/modules.d/greylist.conf
greylist {
  expire = 864000;

  .include(try=true,priority=5) "${DBDIR}/dynamic/greylist.conf"
  .include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/greylist.conf"
  .include(try=true,priority=10) "$LOCAL_CONFDIR/override.d/greylist.conf"
}

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


greylisting в opensmtpd


Самая неоднозначная часть решения.


После того, как мы отправили письмо демону rspamd через клиент rspamc (см. предыдущую статью) — демон нам на STDOUT отвечает текстом письма с добавленными заголовками.


В случае, если требуется greylisting, то в заголовках будет присутствовать "X-Spam-Action: soft reject". По хорошему, mta или фильтры распознают этот заголовок и отвечают отправителю временной ошибкой.


Но у нас нет поддержки mta или фильтров. Поэтому, мы просто делаем exit 1!


# см. скрипт из предыдущий статьи
greylisted=$( cat $mail_file | fgrep 'X-Spam-Action: soft reject' )
if [ -n "$greylisted" ]; then
  exit 1
fi

opensmtpd, получив код возврата 1, понимает, что что-то пошло не так и за нас отвечает отправителю временной ошибкой.


Особенности запуска docker контейнера с opensmtpd: его нужно запускать в режиме сети "host", чтобы демон видел корректные IP адреса отправителей.


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


Итого


Ещё меньше спама.

Поделиться с друзьями
-->

Комментарии (7)


  1. acmnu
    01.02.2017 12:06
    +2

    Сложности с грейлистом довольно большие наблюдаю я сейчас.


    Во-первых, многие (те кто базируется на решениях MS) внедрили у себя защиту от спама на основе генерации липовых sender. Каждая посылка или перепосылка сообщения будет вестись от некого липового сендера с псевдорандомным local part. Таким образом грейлистить по sender стало трудновато.


    Во-вторых, есть проблемы с большими сетями: mail.ru, gmail.com, yandex.ru и особенно outlook.com имеют кучу выходных MTA. Outlook.com особенно неприятен, поскольку всегда перепосылает с другого сервера, в отличии от yandex.ru, например. Правило /19, о котором говорится в статье, мне кажется не самым удачным. С одной стороны сетка у тех же MS может быть и шире /19, а с другой могут начаться ложно положительные срабатывания, когда две машины спамера находятся в пределах одной /19 сети. Короче баланс тут поймать очень сложно.


    И в-третьих, проблема согласования времени повторов. К сожалению нет такого стандрата: грейлист. Это просто грязный хак. Для отправляющего сервера это выглядит как defer — временная проблема доставки. И тайминги повтора определяются каждым поставщиком индивидуально. Например все крупные игроки, стараются перепослать письмо очень быстро с этого же MTA (кроме outlook.com). Я так думаю, что с их бешенным поток им крайне не выгодно раздувать очередь, поэтому письма имеют короткий ретри на том же MTA, а потом падают на дополнительные MTA специализирующиеся на повторной доставке. А таймаут грейлиста обычно стоит на 5 минут. И в случае с yandex.ru, например, за эти пять минут он уже раза три к вам стукнется, плюнет и уйдет уже минут на десять. Это вносит раздражение для персонала. На деле, если не угадать с таймаутом, то письмо может прийти и через полчаса и через час.


    Я с этим боролся следущим образом.


    Для начала был составлен список условно доверенных доменов: это крупные игроки плюс все те домены, на которые хоть раз писал один из наших сотрудников (роботы не в счет).
    Если приходит письмо с сендером из этого домена, то я снача проверяю spf на строгое положительное совпадение (~all разумеется не учитывается). Если совпало, то грейлист отключается. Если spf нет, то я проверяю на строгое соответствие MX или A записи для ip. Если и это не помогло, то тогда все это падает в greylist и собирается для оценки в качестве еженедельного отчета.


    В качестве ключа я нынче использую домен, взятый из sender, ip MTA и rcpt. Т.е. из классики я выкинул только local part of sender.


    1. acmnu
      01.02.2017 12:11

      А сам грейлист, к слову, это два шелл скрипта на входном MTA: один создает файл в имени которого ключ, а другой чистит его через сутки, если он не стал белым.


  1. cebka
    01.02.2017 14:52

    Rspamd делает грейлистинг не только по sender/ipnet, но и по partial body hash. Так что никаких проблем с gmail или кривыми клиентами не будет.


    Ну и есть, конечно же, whitelist'ы по spf/dkim/dmarc: https://rspamd.com/doc/modules/whitelist.html


    С грейлистингом и рейтлимитами вполне себе можно передать удаленному MTA, через сколько ему посылать в следующий раз (например, сейчас модуль ratelimit так и делает). Другое дело, что такие сообщения не стандартизованы, хотя об этом идет дискуссия в m3aawg.


    1. acmnu
      01.02.2017 16:41

      Хм. А смысл в таких сообщениях? Как только их стандартизируют спамеры начнут их использовать.


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


      1. cebka
        01.02.2017 17:21

        Хм. А смысл в таких сообщениях? Как только их стандартизируют спамеры начнут их использовать.

        Ну и пусть используют. Чем им это поможет-то?


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

        Поэтому грейлистинг бесполезен, да?


        1. acmnu
          01.02.2017 17:42

          Поможет ещё как. Сейчас они фактически не знаю, проблема это или грейлист, а тут им прямым текстом будут говорить: зайди через пять минут. И ведь таки придут.


          1. cebka
            01.02.2017 18:42

            Поможет ещё как. Сейчас они фактически не знаю, проблема это или грейлист, а тут им прямым текстом будут говорить: зайди через пять минут. И ведь таки придут.

            А то, что сейчас им возвращают временную 400-ю ошибку и что-то вроде 'Try again later', вас никак не смущает?