Фильтрация содержимого входящих сообщений в Postfix средствами Spamassassin с отправкой администратору копии письма
Тематические термины: Postfix, Spamassassin.
В данной статье мы разберем, как в Postfix можно проверять содержимое письма на наличие определенных ключевых фраз. Если письмо не проходит проверку, то мы его будем отклонять с отправкой сообщения администратору. Предполагается, что на сервере используется Spamassassin. Он будет проверять вхождения ключевых слов и присваивать им метки. Затем Postfix будем проверять заголовки — если в заголовках будут метки от Spamassassin, то такие письма будем перенаправлять на адрес администратора.
Настройка Spamassassin
В конфигурационном файле добавляем следующие строки:
vi /etc/mail/spamassassin/local.cf
include /usr/share/spamassassin/99_filter.cf
* в данном примере мы подгружаем файл 99_filter.cf, в котором будут наши ключевые фразы.
Создаем файл 99_filter.cf с ключевыми фразами:
vi /usr/share/spamassassin/99_filter.cf
body FILTER_CONTROL /Bad Phrase|Sale|Бомба/i
describe FILTER_CONTROL Bad Phrase description
score FILTER_CONTROL 0.001
* в данном примере мы задали настройку для трех фраз — Bad Phrase, Sale и бомба. Если в контенте письма попадутся данные фразы, им будет добавлен заголовок X-Spam-Status, в который попадет метка FILTER_CONTROL. Также мы задаем небольшой бал СПАМа, без него метка добавляться не будет (если необходимо, чтобы письмо попадало в СПАМ, задаем большой бал).
Перезапускаем spamassassin:
systemctl restart spamassassin
Отправляем письмо на ящик, который обслуживается нашим почтовым сервером. В теле письма пишем одно из ключевых фраз. Открываем заголовки письма — среди них мы должны увидеть что-то на подобие:
X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,FILTER_CONTROL
autolearn=no autolearn_force=no version=3.4.0
* как видим, в тексте есть наша метка FILTER_CONTROL.
Настройка Postfix
Открываем конфигурационный файл Postfix:
vi /etc/postfix/main.cf
Правим строку или добавляем ее:
header_checks = regexp:/etc/postfix/header_checks
Открываем файл header_checks:
vi /etc/postfix/header_checks
Добавляем:
/^X-Spam-Status:.*FILTER_CONTROL.*/ BCC security@dmosk.ru
* в данном примере мы ищем вхождения метки FILTER_CONTROL в заголовках письма, и если она есть, отправляем копию письма на адрес security@dmosk.ru.
Для работы действия BCC в header_checks, необходим Postfix версии 3 и выше. Проверить версию установленного MTA можно командой postconf -d | grep mail_version.
Проверяем настройку header_checks:
postmap -q "X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,FILTER_CONTROL" regexp:/etc/postfix/header_checks
Мы должны увидеть:
BCC security@dmosk.ru
Перезапускаем postfix:
systemctl restart postfix
Для проверки отправляем письмо с содержанием ключевой фразы — мы должны получить копию письма на другой ящик.
Варианты написания текста
Самое трудное при фильтрации контента — учесть разные варианты написания букв. Необходимо, чтобы фильтр смог распознать буквы, которые можно написать как разными способами, так и в разных кодировках.
Буквы
Для примера, берем букву «о» — ее можно заменить цифрой «0» или английской буквой «о», которая имеет другой код и будет по другому восприниматься системой, а читаться будет одинаково.
Таким образом, при составлении привил в файле 99_filter.cf, мы должны вести учет данных вариантов. Вот пример слова «Сова»:
((c|C|с|С)(o|O|о|О|0)(B|в|В)(a|A|а|А))
* в данном примере каждый вариант написания буквы идет в своих скобках. Сами варианты разделены вертикальной линией.
Кодировки
Различные почтовые клиенты будут отправлять русский текст в различных кодировках. Таким образом, наши правила не будут работать — нужно учитывать варианты использования разных кодов для символов. Например, тоже слово «Сова» в кодировке KOI8-R будет написано:
((\xd3|\xf3)(\xcf|\xef)(\xd7|\xf7)(\xc1|\xe1))
* в каждой скобке свой вариант написания буквы — строчной и заглавной.
Все вместе
Теперь нужно объединить два вышеописанных подхода. Получаем, что фильтр по слову «Сова» для KOI8-R должен выглядеть так:
body FILTER_CONTROL /((\xd3|\xf3|c|C|с|С)(\xcf|\xef|o|O|о|О|0)(\xd7|\xf7|B|в|В)(\xc1|\xe1|a|A|а|А))/