Общие принципы работы greylisting фильтра

Основная идея, лежащая в основе, фильтрации спама через greylisting сводится к тому, что если сервер-получатель письма сообщает серверу-отправителю о временной невозможности принять письмо, сервер-отправитель «откладывает письмо в сторону» и повторяет попытку отправить письмо через какое-то время. Для правильно настроенных серверов такая задержка колеблется от 20-30 минут до 4-5 часов.

Поведение машин, рассылающих спам, принципиально отличается:

не доставленное письмо, как правило, выбрасывается, и повторной доставки не происходит

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

Основываясь на данных фактах можно организовать работу почтового сервера таким образом, что при первой попытке доставить письмо, сервер отказывается принять письмо с кодом ошибки 4ХХ (временные проблемы), и будет отказываться его принимать еще какое-то время (15-20 минут). Попытка доставить письмо каким-нибудь образом «запоминается» почтовым сервером, при повторной доставке письма сверяются «запомненные» параметры и параметры новой попытки. При выполнении всех необходимых условий, почтовый сервер соглашается принять письмо, в противном случае он в праве ответить как временным кодом ошибки (4ХХ), так и кодом фатальной ошибки (5ХХ).

Установленная реализация

Имеющаяся реализация расположена в директории /usr/local/greyListing/, кроме конфигурационного файла /etc/postfix/greyListing.conf.

Состав пакета

/usr/local/greyListing/greylist.pl — собственно скрипт greylist-фильтра.

/usr/local/greyListing/black-list-*.pl — скрипты внесения записей в чёрные списки.

/usr/local/greyListing/white-list-*.pl — скрипты внесения записей в белые списки.

/usr/local/greyListing/de{black,white}-list-*.pl — скрипты удаления записей из чёрных/белых списков.

/usr/local/greyListing/add-to-force-delivering.pl — скрипт внесения адресов в список обязательной доставки, адресатам из этого списка письма доставляются минуя все механизмы фильтрации.

/usr/local/greyListing/remove-from-force-delivering.pl — скрипт удаления адресов из списка обязательной доставки.

/usr/local/greyListing/greyEraiser.pl — скрипт для удаления слишком старых записей в таблицах токенов (Tokens и wellcome_back_tokens)

/etc/postfix/greyListing.conf — кофигурационный файл, содержащий параметры подключения к базе данных и значения различных временных характеристик работы системы.

Алгоритм работы

В отличии от оригинального, предложенный вариант обладает значительно более развесистым списком критериев, которые проверяются для принятия решения о приёме письма (или отказе от приёма).

Список проверок выполняемых фильтром в порядке их исполнения:

check_full_recipient_addr — проверяется, что е-мейл адрес содержит символ @ Если символа @ нет, письмо блокируется с кодом фатальной ошибки.

check_force_delivering_recipient_list — проверяется, что е-мейл адресата содержится в списке обязательной доставки. Если адресат указан в списке, письмо принимается минуя все последующие проверки.

check_smtp_authenticated_user — проверяется прошёл ли SMTP-клиент авторизацию на почтовом сервере. Если SMTP-клиент выполнил авторизацию, письмо принимается минуя все последующие проверки.

check_akstc — проверяется, что е-мейл отправителя совпадает с рядом регулярных выражений; например, /^akstc($domain2)mnsdgs/ =~ akstcanilkaracamnsdgs@anilkaraca.com Данные шаблоны характерны спам-рассылкам, письмо блокируется с кодом фатальной ошибки.

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

check_sender_black_list — проверяется, что данному отправителю запрещено посылать нам почту. Позволяет блокировать приём почты от конкретного пользователя удалённой системы. Письмо блокируется с кодом фатальной ошибки.

check_user_contact_list — проверяется, что данный отправитель с данного SMTP-клиента известен адресату. Данный список позволяет связать отправителя, получателя и IP-адрес удалённой системы. Заполнение этого списка возложено на самих пользователей, для чего им предоставляется специальный web-интерфейс. При прохождении письма с параметрами, указанными в списке, письмо принимается без задержки.

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

check_black_list — проверяется, что данному SMTP-клиенту запрещено посылать нам почту. Это классический чёрный список. Поддерживается список IP-адресов и список доменных имён.

check_white_list — проверяется, что данному SMTP-клиенту разрешено посылать нам почту. Это классический белый список. Поддерживается список IP-адресов и список доменных имён.

check_tokens — проверяется, были ли предыдущие попытки доставить письмо от данного отправителя данному адресату с данного SMTP-клиента. Это и есть проверка серого списка как таковая.

Необходимо отметить, что чёрные списки всегда имеют более высокий приоритет над аналогичными белыми списками.

Алгоритм проверки серого списка

Все переменные, упоминаемые в данном разделе, описаны в файле /etc/postfix/greyListing.conf

При своей работе алгоритм оперирует понятием временного окна — это диапазон времени начинающийся в некоторый момент t0 и имеющий продолжительность $greylist_deadline. Принято, что комбинация адреса отправителя, адреса получателя и IP-адреса удалённого компьютера однозначно определяет принимаемое сообщение.

Строго формально, это не верно, т.к. параллельно могут быть отправлены несколько писем. Но на этапе SMTP-дилога между почтовыми системами, никаких уникальных идентификаторов письма не существует.

Серый список содержит, кроме указанных трёх параметров, еще и значение t0, начиная с которого мы готовы принимать повторные попытки доставить письмо.

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

при необходимости в сером списке регистрируется новая запись

временное окно для данного письма сдвигается на $greylist_delay секунд в будущее.

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

письмо принимается для доставки

временное окно для данного письма сдвигается на текущий момент.

Структура таблиц

CREATE TABLE `Tokens` ( `client_address` VARCHAR(15) NOT NULL DEFAULT '', `sender` VARCHAR(241) NOT NULL DEFAULT '', `recipient` VARCHAR(241) NOT NULL DEFAULT '', `val` INT(11) DEFAULT NULL, `client_name` VARCHAR(250) DEFAULT NULL, PRIMARY KEY (`client_address`,`sender`,`recipient`) ); CREATE TABLE `domain_black_list` ( `domain` VARCHAR(241) NOT NULL DEFAULT '', `insert_time` INT(11) DEFAULT NULL, PRIMARY KEY (`domain`) ); CREATE TABLE `domain_white_list` ( `domain` VARCHAR(241) NOT NULL DEFAULT '', PRIMARY KEY (`domain`) ); CREATE TABLE `force_delivering_recipients` ( `recipient` VARCHAR(241) NOT NULL DEFAULT '', PRIMARY KEY (`recipient`) ); CREATE TABLE `ip_black_list` ( `IP` VARCHAR(15) NOT NULL DEFAULT '', `insert_time` INT(11) DEFAULT NULL, PRIMARY KEY (`IP`) ); CREATE TABLE `ip_white_list` ( `IP` VARCHAR(15) NOT NULL DEFAULT '', PRIMARY KEY (`IP`) ); CREATE TABLE `sender_black_list` ( `sender` VARCHAR(241) NOT NULL DEFAULT '', PRIMARY KEY (`sender`) ); CREATE TABLE `sender_white_list` ( `IP` VARCHAR(15) NOT NULL DEFAULT '', `sender` VARCHAR(241) NOT NULL DEFAULT '', PRIMARY KEY (`IP`,`sender`) ); CREATE TABLE `user_contact_list` ( `sender` VARCHAR(241) NOT NULL DEFAULT '', `recipient` VARCHAR(241) NOT NULL DEFAULT '', `IP` VARCHAR(15) NOT NULL DEFAULT '', PRIMARY KEY (`sender`,`recipient`,`IP`) ); CREATE TABLE `wellcome_back_tokens` ( `sender` VARCHAR(241) NOT NULL DEFAULT '', `recipient` VARCHAR(241) NOT NULL DEFAULT '', `val` INT(11) DEFAULT NULL, PRIMARY KEY (`sender`,`recipient`) );

Интерфейс

Командная строка

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

Скрипты для управления чёрным и белым списком доменов. В качестве параметра принимают имя домена. С практической точки зрения, вещь почти бессмысленная, т.к. SMTP позволяет подделывать адрес отправителя, но для полноты функционала существует.

/usr/local/greyListing/black-list-domain.pl remote.domain.com /usr/local/greyListing/deblack-list-domain.pl remote.domain.com /usr/local/greyListing/white-list-domain.pl remote.domain.com /usr/local/greyListing/dewhite-list-domain.pl remote.domain.com

Скрипты для управления чёрным и белым списком IP-адресов. В качестве параметра принимают IP-адрес удалённой машины. Текущая версия не позволяет указывать адреса сетей – только атомарные IP-адреса.

/usr/local/greyListing/black-list-ip.pl 1.2.3.4 /usr/local/greyListing/deblack-list-ip.pl 1.2.3.4 /usr/local/greyListing/white-list-ip.pl 1.2.3.4 /usr/local/greyListing/dewhite-list-ip.pl 1.2.3.4

Скрипты для управления чёрным списком email-адресов отправителей.

/usr/local/greyListing/black-list-sender.pl sender@remote.domain /usr/local/greyListing/deblack-list-sender.pl sender@remote.domain

Скрипты для управления белым списком отправителей. В качестве параметров принимают IP-адрес удалённой машины и email-адрес отправителя.

/usr/local/greyListing/white-list-email.pl 1.2.3.4 sender@addr /usr/local/greyListing/dewhite-list-email.pl 1.2.3.4 sender@addr

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

/usr/local/greyListing/add-to-force-delivering.pl recipient@local.domain /usr/local/greyListing/remove-from-force-delivering.pl recipient@local.domain

Скрипт для удаления старых записей из таблиц Tokens и wellcome_back_tokens.

/usr/local/greyListing/greyEraiser.pl

Web-интерфейс.

Tracedump:

newBaseSize: 16pt
newBaseSizeInPt: 16