Методы борьбы со спамом: Greylisting

Не так давно решил всё-таки завести собственный почтовый сервер, просто ради того, чтобы освежить некоторые моменты связанные с около-email технологиями, которые как мне показалось, я начал немного забывать. К тому же, как-то несолидно админу быть без собственного почтового сервера.

Ещё не закончив конфигурирование сервера, уже после создания mx записи, я начал получать странноватые коннекты на smtp порт и примерно представляя природу данных коннектов, сразу же начал задумываться о методах борьбы со спамом.

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


Содержание:

  1. Методы борьбы со спамом
  2. Greylisting
  3. Окружение
  4. Настройка spamd
  5. Настройка pf
  6. Настройка bgp-spamd
  7. Тюнинг spamd
  8. Заключение
  9. Полезные ресурсы

Методы борьбы со спамом

Greylisting

До настоящего момента я не был знаком со всем изобилием методик борьбы со спамом. Мои знания ограничивались решениями скорее корпоративного уровня, типа подключения своего домена на Яндекс.Почту или то же самое, только от Google. Кроме того, был наслышан о решениях от Касперского и прочих производителей противовирусного ПО (тут же можно вспомнить Яндекс.Спамоборону, которая была популярна в своё время). Ну и конечно же хардварные (а теперь уже и облачные, и виртуальные) решения, от той же Cisco: нынешний Cisco Email Security, бывший Ironport.

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

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

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


Greylisting

В своё время, начитывая информацию по pf, наткнулся на великолепный труд Book of PF, 3rd Edition, написанный Peter N. M. Hansteen, где мельком ухватил информацию о методике борьбы со спамом, не предусматривавшей анализ самого текста письма. Заинтересовавшись ей, решил как-нибудь повнимательнее ознакомится с данной технологией. И вот, начиная получать немалое число коннектов на smtp порт, вспомнил про greylisting.

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


Окружение

Операционная система: моя любимая FreeBSD.
Брандмауэр: полюбившийся мне в последнее время своей простотой, лаконичностью и чистотой конфигурационного файла pf.
В качестве smtp сервера я решил попробовать новый для себя OpenSMTP сервер, который, как отмечают многие, проще в плане конфигурирования и сопровождения, нежели такие монструозные столпы индустрии как Postfix, Exim и уж тем более Sendmail. Разумеется, у OpenSMTP есть минусы. Например, он не умеет в milter и хотя у него есть т.н. filters, которые выполняют их роль и доступны в порте opensmtp-extras, всё же они помечены как beta и авторы не рекомендуют их использовать в продакшене (само собой они активно применяются). Впрочем, OpenSMTP уже довольно-таки продолжительное время является mta по-умолчанию в OpenBSD, что говорит о зрелости данного продукта. В общем, решил попробовать.

Что же касается конкретной софтверной реализации метода greylisting, то тут мой выбор пал на знаменитый демон Spamd. Среди основных его плюсов можно отметить следующие:

  • spamd является стендэлоун демоном, это не модуль, не плагин, не расширение к какому-либо другому mta;
  • spamd написан на C, фактически это сильно урезанная версия канонического Sendmail;
  • spamd активно применяется в xBSD сообществе и отзывы о нём исключительно положительные;
  • в нём реализованы очень популярные техники борьбы со спамом: Blacklisting, Tarpits, Spamtrapping.

Настройка spamd

Довольно проста и проходит без каких-либо проблем.
Постольку поскольку spamd плотно интегрирован с брандмауэром pf, предполагается, что pf уже установлен и работает. Устанавливаем spamd из портов (устанавливается вот эта версия). Проверяем установку, должны быть установлены следующие компоненты:

  • spamdсам демон, который будет слушать smtp, smtps, submission порты на предмет подключения к ним удалённого сеанса от сервера исходящей почты;
  • spamd.confконфигурационный файл демона, где содержится информация о чёрных списках, белых списках и очерёдности их применения;
  • spamdbпрограмма для работы с базой данных (sqlite3) демона;
  • spamd-setupпрограмма для применения обновлений конфигурационного файла, чёрных списков, белых списков;
  • spamlogdпрограмма для мониторинга виртуального интерфейса pf, в который будет отправлятся информация о прошедших spamd подключениях от или к почтовому серверу, т.е. заведомо белых.

В зависимости от указанного --prefix, по-умолчанию в: /usr/local/etc/spamd, /usr/local/sbin/, /var/db/, /usr/local/libexec/, /var/run/.

Прописываем параметры автозапуска демона в rc.conf:

obspamd_enable="YES"
obspamd_flags="-4 -G25:4:864 -h host.name -l127.0.0.1 -n \"Best smtp server ever 1.0.33.05b\" -S10 -s1 -v -w1"
obspamd_black="NO"
obspamlogd_enable="YES"
obspamlogd_flags="-W 960"
obspamlogd_pflog_if=pflog1

Про ключики можно прочитать в мане. Стоит только отметить лишь следующее:

  • настройки -G по-умолчанию вполне актуальны;
  • не стоит использовать ключ -5, потому как используя данный ключ spamd отправляет не ошибку "451 Temporary failure, please try again later.", а ошибку типа "500 5.5.1 Command unrecognized", которая может быть интерпретирована не как временная ошибка, а как перманентная, получив которую удалённый сервер прекратит попытки пересылки сообщения;
  • нужно обратить внимание на название виртуального интерфейса pf, мониторинг которого будет осуществляться демоном spamlogd, для пополнения белых списков IP адресов (обычно pflog1), он должен быть указан в pf.conf, как интерфейс для логгирования входящего\исходящего трафика на наш почтовый сервер;
  • опция -v – по желанию.

Создаём простейший конфигурационный файл spamd.conf:

all:\
         :::

Здесь ко всем входящим соединениям не применяется ни один чёрный или белый список IP адресов хостов. Причина проста: существует практика отказа от использования открытых чёрных списков хостов-спамеров типа dnsbl, okeah, nixspam. Один из основных негативных моментов использования подобных списков, ведущий к отказу их использования, связан с тем, что в них указано значительное число адресов, которые не всегда являются рассыльщиками спама. Лично мне она кажется достаточно разумной. К тому же, если мы не планируем получать письма из Кореи или, например, Китая, то проще заблокировать доступ к нашему хосту изо всех этих регионов. Впрочем, существует, однако, и несколько иной подход к использованию сторонних белых и чёрных списков хостов, об нём будет упомянуто ниже.

Небольшой список команд для работы со spamd:
1. spamdb – отобразить текущую базу сервиса. Вывод grepабелен.
2. spamdb -t -d $ipaddr – удалить запись TRAPPED запись.
3. spamdb -t -a $ipaddr – добавить запись TRAPPED запись.
4. spamd-setup – применить обновления списков или базы данных. Разумно поместить в crontab для запуска раз в 5-10 минут.
Подробнее о работе с базой данных spamd – в мане.


Настройка pf

Вносим необходимые изменения в pf.conf (настроен и работает, /etc/services уже дополнен):

# vars
mailIn = { smtp, smtps, submission }

# tables
table <bruteforce> persist
table <bgp_bypass> persist
table <spamd-white> persist
table <spamd> persist
table <localwhite> persist file "/path/to/localwhite.txt"

# translation
no rdr inet proto tcp from { <spamd-white>, <bgp_bypass>, <localwhite> } to any port $mailIn
rdr inet proto tcp from any to any port $mailIn -> 127.0.0.1 port spamd

# filtering
# mail-in
pass in log (to pflog1) on $ext_if inet proto tcp from any to 127.0.0.1 port spamd
pass in log (to pflog1) on $ext_if inet proto tcp from { <spamd-white>, <localwhite> } to any port $mailIn keep state (max-src-conn 50, max-src-conn-rate 25/5, overload <bruteforce> flush global)

# mail-out
pass out quick log (to pflog1) on $ext_if proto tcp from any to any port $mailIn

Не путаем секции (переменные, таблицы, трансляция, фильтрация).

Секция таблиц:

  • bruteforce – таблица для временного хранения IP брутфорсеров.
  • bgp_bypass – таблица сервиса bgp-spamd, о ней позже.
  • spamd-white – таблица, в которую spamd вносит IP адреса хостов, показавшихся не спамерами. Название захардкожено в spamd, изменять не стоит.
  • spamd – таблица, для spamd, работающего в режиме Blacklisting.
  • local_white – таблица заведомо известных IP адресов, которые не нужно проверять.

Секция трансляции:

  • В первой строке: пропускаем все проверенные адреса и адреса из белых списков мимо spamd на opensmtpd.
  • Во второй строке: заворачиваем весь входящий трафик на порты smtp, smtps, submission на spamd демон, который слушает 127.0.0.1:8025.

Секция фильтрации:

  • В первой строке: разрешаем и логгируем доступ извне на 127.0.0.1:8025, где висит spamd (можно использовать директиву rdr pass, по желанию, однако, нужно понимать, что в логах это будут логи именно rdr, а не pass).
  • Во второй строке: разрешаем и логгируем доступ для входящего трафика с заведомо белых и знакомых IP адресов прямиком на opensmtpd. На этом и седующем этапах логгирования происходит пополнение базы /var/db/spamd WHITE-записями, на основании которых будет пополняться и обновляться таблица spamd-white.
  • В третьей строке: разрешаем и логгируем исходящий траффик на порты smtp, smtps, submission от нашего хоста. Логгируем для того, чтобы пополнять таблицу spamd-white IP адресами для наших хостов-реципиентов, предполагая, что мы будет отправлять письма хостам, которым мы доверяем. Это будет работать, если в строке автозапуска spamlogd не указан ключ -I, с указанием которого spamlogd вносит в spamd-white только IP адреса входящих соединений.

Небольшой список полезных команд для работы с pf:
pfctl -nf /etc/pf.conf – проверяем конфигурационный файл pf на наличие ошибок.
pfctl -sa – смотрим правила и статистику работы pf.
pfctl -vvsr – смотрим активные правила pf с их порядковыми номерами.
pfctl -t tableName -T show – просмотреть таблицу.
pfctl -t tableName -T flush – дропнуть таблицу.

Собственно и всё, уже на этом этапе конфигурирования spamd будет работать корректно и отсекать бОльшее число неправильных подключений. Однако, эту конфигурацию можно улучшить, добавив несколько важных опций.


Настройка bgp-spamd

Как отмечалось выше, не всегда есть смысл пользоваться открытыми чёрными списками хостов-отправителей спам рассылок, впрочем, с чёрными списками IP адресов работать проще и применяя их можно ещё больше уменьшить вероятность получения спам-сообщения. Для удовлетворения этим требованиям был создан проект BGP-Spamd. Идея проекта заключается в реализации обновления практически в режиме реального времени списка хостов, которые активно спамили на известные GREYTRAPы и распространения этих адресов посредством популярного динамического протокола маршрутизации BGP конечным пользователям, т.е. нам.
Установка и настройка этого сервиса также проста.
Для этого нам понадобится установить из портов проверенный OpenBGPD и настроить его.
Изменяем /usr/local/etc/bgpd.conf до следующего состояния:

# macros
rsus="64.142.121.62"    # rs.bgp-spamd.net
rseu="217.31.80.170"    # eu.bgp-spamd.net
spamdAS="$asNumber"     # where asNumber is in range(64512:65535)

AS 65501
fib-update no            # Do not update local routing table

group "spam-bgp" {
    remote-as $spamdAS
    multihop 64
    announce none           # Do not send Route Server any information
    neighbor $rseu
    neighbor $rsus
}

# 'match' is required, to remove entries when routes are withdrawn
match from group "spam-bgp" community $spamAS:42 set pftable "bgp_bypass"

В целом тут всё понятно, единственное на что действительно стоит обратить внимание, так это на директивы fib-update no и announce none в секции group "spam-bgp".
Последняя строка для нас интересна тем, что сервис bgp-spamd распространяет не только чёрные списки адресов, но и списки проверенных хостов, не являющихся спамерами. Как понятно из синтаксиса, данная строка пополняет таблицу bgp_bypass нашего брандмауэра, хосты из которой не перенаправляются на spamd. Впрочем, можно обойтись и без него. Список же чёрных адресов мы не будем отправлять в отдельную таблицу для брандмауэра для их моментальной блокировки, но добавим в таблицу spamd-greytrap базы данных spamd, для того чтобы не сразу отбрасывать эти заведомо спамерские коннекты, а предоставить им возможность общаться с нашим spamd, работающим для этих адресов в режиме blacklisting.
Для этого напишем небольшой скрипт:

#!/bin/sh
AS=65066
/usr/local/sbin/bgpctl show rib community ${AS}:666 | sed -e '1,4d' -e 's/\/.*$//' -e 's/[ \*\>]*//' > /path/to/spamd_bgp_blacklist.txt
/usr/local/sbin/spamd-setup

и поместим его в crontab для запуска раз в 30 минут:

30		*	*	*	*	/path/to/spamd-bgp-update.sh

После чего отредактируем smapd.conf до такого вот состояния:

all:\
        :bgp-spamd:whitelist:
whitelist:\
        :white:\
        :method=file:\
        :file=/path/to/spamd-whitelist.txt:
bgp-spamd:\
        :black:\
        :msg="Your IP %A has sent email to a spamtrap":\
        :method=file:\
        :file=/path/to/spamd_bgp_blacklist.txt:

Где:
spamd-whitelist.txt – файл с указанием известных нам адресов.
spamd_bgp_blacklist.txt – файл, содержащий полученный список чёрных адресов от сервиса bgp-spamd.

На этом конфигурирование небольшой, но эффективной системы по мониторингу портов smtp, smtps, submission на предмет подключения к ним хостов-распространителей спама можно считать завершённой.
Впрочем, spamd позволяет нам сделает ещё кое-что, чтобы усложнить жизнь распространителям спама.


Тюнинг spamd

В spamd, как уже отмечалось выше, реализованы популярные методики борьбы со спамом: Blacklisting, Tarpits, Spamtrapping. И если Blacklisting был активирован для определённого набора хостов-спамеров выше, а с Tarpits можно поиграть устанавливая различные значения ключей -w -s -S в параметрах запуска самого демона spamd, то для реализации Spamtrapping мы можем использовать команду для добавления значения GREYTRAP в базу данных spamd:

  • spamdb -T -a itsatrap@moiseev.su, где itsatrap@moiseev.su – ловушка для спамеров, которые парсят веб-страницы на предмет наличия почтовых адресов, с последующей рассылкой по ним спам-сообщений;
  • spamdb -T -d itsatrap@moiseev.su – чтобы удалить ловушку.

Предполагается, что человек не станет отправлять письмо на подобный адрес, кроме того, его можно спрятать на странице так, чтобы робот-парсер смог бы его найти, а человек не обратил на него никакого внимания.

Помимо работы spamd в режиме Greylisting, spamd можно также настроить на работу в режиме Blacklisting only. Для этого в pf.conf нужно создать таблицу spamd, а сам spamd перевести в режим blacklisting путём внесения строки obspamd_black="YES" в rc.conf. Данный режим можно использовать, если есть желание побороться с ветряными мельницами, на хостах, где нет почтового сервера, но есть возможность прописать mx запись в dns записи для данного хоста. В режиме Blacklisting все входящие подключения на порты smtp, smtps, submission будут помечаться как спамерские, с соответствующим для них поведением spamd. Собственно в этом и заключается главное отличие Greylisting от Blacklisting: при подключении удалённого хоста, в зависимости от типа принадлежности хоста к одной из таблиц GREY или TRAPPED, для него будет применён следующий подход. В случае, если это GREY хост, при вводе команды DATA ему будет возвращена ошибка "451 Temporary failure, please try again later.", после чего подключение закроется. Если же хост находится в TRAPPED, то spamd продолжит его слушать до победного (либо спамер будет вынужден сдаться, либо он-таки доставит спам-сообщение). В сети встречал упоминания того, что некоторые спамеры проводили по 10000 секунд в попытках доставить сообщение spamd.

В дополнение ко всему, функционал работы spamd можно дополнить путём создания файла spamd.alloweddomains, в котором указать домены, IP адреса, письма с которых, отправленные на адрес-GREYTRAP, не будут автоматически добавляться в таблицу spamd-greytrap. Туда имеет смысл добавить суффиксы доменов публичных почтовых сервисов.

Кроме того, имея несколько работающих spamd демонов на разных хостах, между ними можно настроить синхронизацию чёрных и белых списков адресов. Подробнее в мане.

Среди многочисленных достоинств spamd, разумеется, у него есть и минусы. Во-первых, это, конечно же, проблема получения писем от round-robin серверов. Она решается двумя способами:

  • Включение такие важных почтовых сервисов в spamd-whitelist путём поиска spf записей для таких доменов с корректными IP адресами хостов. Например, для gmail этот процесс выглядит так:
~$ host -t TXT _spf.google.com
_spf.google.com descriptive text "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"

по желанию, процесс добычи IP адресов можно автоматизировать.

  • Расширением времени пребывания адреса в таблице GREY, установив парамеры запуска spamd примерно вот так: -G8:10:864. Увеличение времени пребывания IP адреса в таблице GREY позволит увеличить шанс получения повторного письма в отведённый для этого временной интервал.

По опыту моего использования spamd, могу сказать, что стандартных -G25:4:864 достаточно и для round-robin серверов. Так, мне преспокойно дошли письма от Сбербанка и Adobe, адреса серверов которых до этого я не добавлял в spamd-whitelist.


Заключение

Моё общее впечатление от использования данного набора программ исключительно положительное. За всё время использования spamd только одно спам-письмо смогло пройти Greylisting барьер, когда я для эксперимента запускал spamd с параметрами -G8:10:864 для того, чтобы улучшить работу spamd с почтовыми сервисами, работающими по принципу round-robin. Тогда один спам-сервис, совершенно внезапно, решил повторить рассылку через 9 часов, после ошибки "451 Temporary failure, please try again later.".

Немного о результатах работы spamd.
На данный момент, мой TOP10 самых целеустремлённых спамеров выглядит так:

~$cat spamd.log | grep disconnected | sort -n -k 9 -r | head -n 10
Mar 24 15:06:35 hostname spamd[]: 181.55.191.15: disconnected after 607 seconds. lists: spamd-greytrap
Apr 20 03:20:44 hostname spamd[]: 118.107.130.66: disconnected after 606 seconds. lists: bgp-spamd
Mar 31 01:32:36 hostname spamd[]: 149.126.18.164: disconnected after 591 seconds. lists: spamd-greytrap
Apr 20 18:51:41 hostname spamd[]: 202.67.40.226: disconnected after 495 seconds. lists: bgp-spamd
Apr 20 21:18:52 hostname spamd[]: 78.96.35.128: disconnected after 482 seconds. lists: bgp-spamd
Apr 19 12:43:41 hostname spamd[]: 180.210.206.52: disconnected after 476 seconds. lists: bgp-spamd
Apr 18 11:52:13 hostname spamd[]: 150.101.196.251: disconnected after 466 seconds.
Apr 18 13:11:17 hostname spamd[]: 150.101.196.251: disconnected after 464 seconds.
Apr 18 16:06:28 hostname spamd[]: 217.165.162.33: disconnected after 461 seconds.
Apr 17 10:48:42 hostname spamd[]: 27.3.91.176: disconnected after 459 seconds.

Самый настырный спамер совершил 5130 подключений:

~$cat spamd.log | grep 84.38.130.212 | grep disconnected | wc -l
    5130

Вот так выглядит TOP5 его подключений, отсортированных по времени его прибывания на spamd, пытаясь отправить ему письмо:

~$cat spamd.log | grep 84.38.130.212 | grep disconnected | sort -n -k 9 -r | head -n 5
Apr 23 01:00:51 hostname spamd[]: 84.38.130.212: disconnected after 431 seconds. lists: spamd-greytrap
Apr 23 15:23:17 hostname spamd[]: 84.38.130.212: disconnected after 409 seconds. lists: spamd-greytrap
Apr 23 06:53:14 hostname spamd[]: 84.38.130.212: disconnected after 385 seconds. lists: spamd-greytrap
Apr 23 02:15:04 hostname spamd[]: 84.38.130.212: disconnected after 382 seconds. lists: spamd-greytrap
Apr 23 01:13:51 hostname spamd[]: 84.38.130.212: disconnected after 373 seconds. lists: spamd-greytrap

В сумме он общался со spamd довольно продолжительное время:

~$cat spamd.log | grep 84.38.130.212 | grep disconnected | awk -F ' ' '{sum += $9} END {print sum}'
224673

224673 секунд, это соответствует примерно 62.4 часам чистого времени пересылки очень важных спам-сообщений со скоростью 1 бит в секунду замечательному демону spamd.

Вот так выглядит обычный процесс общения TRAPPED хоста со spamd:

Пожалуй это всё, что касается метода Greylisting в одной из лучших его реализаций – spamd.

Что происходит со входящим письмом далее? Далее письмо попадает на сам сервер opensmtpd, где ко всем входящим письмам применяется filter, который пересылает его Spamassassinу, который уже проверяет письмо:

  • принадлежность IP адреса домента-отправителя к адресам в списках dnsbl, psbl и прочих сервисов;
  • происходит проверка spf и dmarc записей домена;
  • проверяется PTR запись;
  • проверяется dkim подпись;
  • проверяется тема и текст самого письма на наличие шаблонных фраз;

И, что самое главное, письмо не отбрасывается. Входящему письму с подозрением на спам изменяется тема на “[SPAM] + $subj”. После чего, письмо минуя Inbox отправляется в Junk ящик, и уже сам пользователь решает: является ли это письмо спамом или нет. Т.е. принудительно оно не отбрасывается, что мягко принуждает пользователя создавать собственные правила для обнаружения спама и практически полностью исключает false-positive удаления писем.


Полезные ресурсы