пятница, 29 октября 2010 г.

Случай с фильтрацией хэдеров в postfix.

Некоторое время назад я, ко всему прочему, добавил фильтрацию заголовков сообщений(хэдеров) в postfix. Делал это, чтоб всякие спамеры, рекламирующие виагру и т.п., сразу "отпинывались", не попадая в папку spam: хотя фильтрация спама у меня работает как надо, тем не менее зачем вообще принимать гарантированно спамерские письма?!

В main.cf добавляется запись:

header_checks = pcre:/etc/postfix/header_checks.pcre

Сам файл /etc/postfix/header_checks.pcre содержит:

/([ |^]viagra| sex |erection| meds | pills| drugs |cialis|tablet|sexmeds|valium|vicodin)/   REJECT We don't need any drugs

По наивности, я думал, что фильтруется именно поле"Subject:". Однако в один момент мне пожаловались, что почта от одного клиента возвращается с причиной возврата, указанной в Reject выше. Подумав и почитав ещё раз документацию, я решил, что строка "Received: from Tablet05...." заголовка письма совпадает с 'tablet' из шаблона pcre. Значит, фильтруется весь заголовок(почему я сразу это не уяснил из названия?), а нужно проверять именно тему заголовка писем(Subject).

Почитав документацию, я узнал, что есть здесь своя конструкция "If - endif", но работает она с рядом ограничений. Ладно, пробую заставить её поработать на меня:

if /^Subject:/
/([ |^]viagra| sex |erection| meds | pills| drugs |cialis|tablet|sexmeds|valium|vicodin)/   REJECT We don't need any drugs
endif

Далее по привычке даю команду:

postmap /etc/postfix/header_checks.pcre

Получаю в ответ:

postmap: warning: /etc/postfix/header_checks.pcre, line 5: expected format: key whitespace value

Как бы я ни старался, postmap не хочет воспринимать 'endif'. Долго копался в документации и интернете, пытаясь найти решение. Можно, конечно, прописать в каждую строчку часть шаблона, но мне казалось, это будет сказываться на быстродействии. И всё-таки мне хотелось заставить мою конструкцию заработать. В документации говорится:


if /pattern/flags

endif Match the input string against the patterns between
if and endif, if and only if the same input string
also matches /pattern/. The if..endif can nest.

Note: do not prepend whitespace to patterns inside
if..endif.    

Вот этот "Note" меня сбил с толку. Я думал, что нельзя использовать пробелы внутри шаблона. Ерунда, оказывается, всё просто: пробел лишь указывает, что данная строка - продолжение строчки выше. Меня в моём примере это вообще не касается. Ошибка, как оказалось, в том, что postmap не умеет работать с pcre-данными. Список поддерживаемых в postfix типов баз данных(postconf -m) содержит pcre, тем не менее postmap умеет только читать pcre-файлы, но не умеет создавать на их основе '.db' - файлы. По умолчанию postmap использует тип базы данных, указанный в параметре 'default_database_type' в main.cf, это можно также узнать командой:

postconf|grep default_database_type

У меня эта команда выдаёт:

default_database_type = hash

То есть ошибка у меня выдавалась при попытке создать hash-файл из pcre-данных. Логично. Так что можно просто удалить старый файл /etc/postfix/header_checks.pcre.db, и всё будет работать.

Другая ошибка, которую многие допускают, состоит в том, что пытаются создавать условия для работы с разными полями заголовка, т.е. , например, если найдено совпадение поля 'From', то попытаться найти совпадение поля 'Subject' и, в этом случае совершить какое-то действие и т.п. Так делать нельзя, т.к. в данный момент времени проверяется на совпадение только одна строка заголовка, и сравнивается она с каждым правилом из файла pcre по-порядку. Это как раз то, что используется в моём случае.

Комментариев нет:

Отправить комментарий