The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Каталог документации / Раздел "Настройка почты (sendmail, postfix, qmail)" (Архив | Для печати)

Создание почтовой системы на базе exim, dbmail, amavisd-new и postgresql.

Оригинал: ezh.msk.ru
Автор: Алексей Аксенов
При полном или частичном копировании статей просьба оставлять ссылку на источник.

Создание почтовой системы на базе exim, dbmail, amavisd-new и postgresql.

Оглавление

О статье.

Эта статья рассказывает об устройстве реально работающей почтовой системы. Я очень хотел сделать упор на том, как это работает и почему именно так, а не иначе. В интернете можно найти множество статей, которые не могут ответить на вопросы: "Как? Почему? Чем лучше?" и на вопрос "Зачем?" - дается стандартный ответ, что рецепт в статье автора, это то единственное, что мы искали. Эти статьи похожи на "тупое руководство": "Взять деталь А, присоединить к детали Б под углом в 30 градусов и т.д." Очень мне не понравилось такое положение дел, а поскольку хаять то, что сделали другие проще всего, то я решил пойти другим путем и написать свою статью, в которой Вы можете найти для себя ответы на вопросы "Как?" и "Чем лучше?" и, может быть, даже ответ на вопрос "Зачем?". На вопрос "Почему?" могу сказать только, что на вкус, на цвет - товарищей нет и, из пушки по воробьям стрелять вряд ли стоит, однако на медведя с перочинным ножиком ходить, тоже неправильно. Другой причиной создания статьи явились сообщения в почтовых листах, где одни люди просили рассказать о вкусностях amavisd-new и dbmail, а другие говорили, что эти системы успешно используют средние/крупные провайдеры, что меня сильно заинтриговало. Документации и описаний вкусностей на русском языке не нашел вообще (кроме пары "тупых руководств", в которых естественно не было ответов на мои вопросы), нашел немного на английском, потом заглянул в почтовые рассылки, заинтересовался, разобрался, понравилось как работает, решил описать в общих чертах. В общих чертах получалось как-то не очень, хотелось рассказать о том и о сем и ничего не забыть. Каков результат судить Вам. Систему создавал применительно к организации, то есть приведение к нужным скоростным кондициям для хостинга напильником не производил. Есть много способов заставить все это работать быстрее, однако мне оно было ненужно. Установка этой системы оправдает себя уже при 50 учетных записях и более, хотя эта системка imho неплохо и с 5000 справится. После небольшой доводки конечно, хотя. может и без доводки потянет... Железо и пользователи разные бывают. За время написания статьи успело смениться несколько версий софта, так что можно сказать, что были использованы exim v4.2x, postgresql v 7.3x, amavisd-new c какой-то версии по 20030616_p8 и SpamAssassin 2.6x. Версия антивируса не принципиальна, так как к amavisd-new можно легко подключить практически любой linux антивирус. Linux дистрибутив - Gentoo.
/ЗЫ. так как статья писалась на протяжении достаточно продолжительного времени, в ней могут встретиться неточности. Если заметите что-нибудь подозрительное, пишите, исправлю. Так же пишите, если у Вас возникнет какое-нибудь интересное дополнение. /

DBMail

Возможности DBMail.

Что такое DBMail? DBMail - это набор программ, позволяющих хранить почтовые сообщения в таких базах данных как mysql и postgresql. В этот пакет входят следующие программы:
  • dbmail-imapd - полнофункциональный imap (imap4r1) сервер, обеспечивающий доступ к почтовым ящикам пользователей.
  • dbmail-pop3 - полнофункциональный pop3 сервер, обеспечивающий доступ к почтовым ящикам пользователей.
  • dbmail-adduser - программа, позволяющая нам управлять пользователями Dbmail. Она позволяет добавлять, удалять, изменять и показывать информацию о пользователе или наборе пользователей. С помощью этой программы мы можем так же управлять алиасами пользователей.
  • dbmail-smtp - программа, с помощью которой осуществляется добавление почтовых сообщений в почтовый ящик, причем адрес ящика пользователя может быть установлен из MIME заголовка сообщения или задан в явном виде.
  • dbmail-maintenance - программа, которая проверяет целостность базы данных и производит очистку сообщений в базе помеченных для удаления. Разработчики рекомендуют запускать ее раз в сутки, используя крон.
Основные преимущества использования этого почтового комплекса, по мнению разработчиков, таковы:
  • масштабируемость - все зависит от БД, которую мы используем. (Кстати, в инструкции по инсталляции говорится, что при использовании mysql лучше использовать innodb - тип таблиц, предназначенный для получения максимальной производительности при обработке больших объемов данных, т.к. таблички в некоторых случаях получаются великоваты). Чего-то у них там написано про кластер. Не знаю. руками такие вещи не трогал - необходимости не было.
  • управляемость - база данных SQL. Ой-ой-ой! Ну все! Хватит! Хватит мечтать, что можно сделать с этой штукой.
  • скорость - эффективнее получить разобранное сообщение из БД, а не разбирать текстовые файлы. /ЗЫ Логично конечно, но чего-то там мелькала цифра - отдача 250 сообщений/секунду, однако, это на каком сервере и сообщений какого объема? imho 086 с одним метром памяти вообще все это хозяйство даже запустить не сможет. По поводу скорости - очень спорное заявление от создателей. К тому же в списке рассылки DBMail есть заявление от человека (а может это и не человек вовсе, а нелюдь), что DBMail без проблем обработал почтовое сообщение объемом более 500 метров. Люди/нелюди экстрималы, однако./
  • безопасность - DBMail не нужны специальные разрешения на запись специальных файлов в специальные каталоги - этот софт работает с БД.
  • гибкость - эффект от изменения данных в почтовой системе проявляется немедленно (добавление пользователей, изменение пароля и т.д.). Хотя на практике есть одно изменение, которое не вступает в силу немедленно. Вспомните описание dbmail-maintenance.

Установка и настройка DBMail.

Заходим на сайт http://www.dbmail.org/ и скачиваем dbmail-x.y.z.tgz. Распаковываем.
Создаем почтовую базу данных:

createuser -U postgres dbmail
createdb -E koi8-r -U postgres dbmail
psql -U postgres dbmail
        ALTER USER dbmail WITH PASSWORD 'secret';
psql -U dbmail dbmail < sql/postgresql/create_tables.pgsql
Компилируем и инсталлируем DBMail:

groupadd dbmail
useradd -g dbmail dbmail
затем откорректируем все необходимые пути и выполним

./build.sh
./install-dbmail.sh
Копируем dbmail.conf в /etc/dbmail.conf и правим в соответствии с нашими требованиями.
Основные опции, использующиеся в конфигурации DBMail:
  • TRACE_LEVEL - уровень детализации логов; всего уровней 6, по умолчанию стоит 2ой уровень. (TRACE_FATAL -1, TRACE_STOP 0, TRACE_MESSAGE 1, TRACE_ERROR 2, TRACE_WARNING 3, TRACE_INFO 4, TRACE_DEBUG 5).
  • TRACE_TO_SYSLOG - писать ли ошибки в SYSLOG (1/0)? По умолчанию включено.
  • TRACE_VERBOSE - вывод сообщений на консоль (1/0).
  • SENDMAIL - путь к sendmail.
  • DBMAIL_FROM_ADDRESS - почтовый адрес демона, осуществляющего возврат (например, при невозможности доставки сообщения).
  • POSTMASTER - адрес постмастера.
  • AUTO_NOTIFY - в таблице auto_notifications мы можем задать для пользователя адрес уведомления, тогда, при получении почты, будут отсылаться уведомления от autonotify@DBMail с темой "NEW MAIL NOTIFICATION" на адрес notify_address. (yes/no).
  • AUTO_REPLY - в таблице auto_replies мы можем задать для пользователя текстовое поле reply_body, содержащее автоответ, который будет автоматически отсылаться при приеме корреспонденции пользователя. (yes/no).
  • Подключение к БД - стандартные опции host/user/pass/db.
/ЗЫ. К сожалению, стандартной программы для добавлений/удаления автоответа и автоуведомления нет (не нашел/не искал), поэтому, если нужно, юзаем SQL/

Программы, входящие в DBMail.

dbmail-imapd и dbmail-pop3d - два демона - параметры -v (версия) и -f (расположение конфигурационного файла)
dbmail-adduser - программа, управляющая нашими пользователями. При добавлении рекомендуется добавлять алиас в обязательном порядке. Если мы поддерживаем несколько доменов (а ведь мы поддерживаем несколько доменов), то логично имя пользователя задать как user@domain и такой же обязательный алиас.
Пример добавления пользователя:

dbmail-adduser add test@test.com password 0 0 test@test.com
Пример добавления перенаправления почты (в своей системе я эту возможность отключил):

dbmail-adduser f postmaster@test.com postmaster
Пример добавления дополнительного адреса для почтового ящика:

dbmail-adduser c test@test.com +a test2@test.com
Так же алиасы поддерживают редирект сообщения во внешние программы:

dbmail-adduser f procmail@test.com "|/usr/bin/procmail" - алиас перенаправляет сообщения пользователя procmail@test.com программе procmail.
dbmail-adduser f spam@test.com "|/usr/bin/spamassassin | dbmail-smtp -d nospam@test.com" - один из вариантов фильтрации почты.
dbmail-smtp - программа, позволяющая добавлять почту в БД. Параметры запуска dbmail-smtp таковы:
  • -n [headerfield] - нормальная доставка сообщения, адрес извлекается из [headerfield] (по умолчанию "deliver-to")
  • -m "mailbox" -u [usernames] - доставка сообщения в определенную папку IMAP пользователей [usernames], причем mailbox может представлять собой путь
  • -d [addresses] доставка сообщения, где [addresses] адреса получателей.
  • -u [usernames] доставка сообщения, где [usernames] имя пользователей. Чем этот режим отличается от -d? Тем, что даже если у нас указаны алиасы, то DBMail ни на что смотреть не будет, а просто положит сообщение в ящики [usernames]
Все, что во множественном числе, может содержать несколько записей, разделенных пробелом.
/ЗЫ Господа! Не перепутайте местами -m и -u, иначе вы будете неприятно удивлены. Если вы хотите узнать, чем вы будете удивлены, то загляните в main.c (напоминаю, что я рассказываю про версию 1.2.3) Ну кто ж так парсеры командной строки пишет? Эх, ну да простим ребятам. Все-таки такую вещь создали./
Пример выдержки куска procmail, использующий IMAP папку:

# Spam goes to the spam box
:0 H: spamlock
* ^X-Spam-Status: Yes
| /usr/sbin/dbmail-smtp -m "spam" -u test@test.com

Особенности DBMail.

При использовании IMAP сервера для доступа к почте, мы можем сделать ящик только для чтения. Эту прекрасную возможность мы можем реализовать, установив SQLdb->mailboxes->permission=1 (IMAPPERM_READ). По умолчанию permission=2, что является разрешением типа IMAPPERM_READWRITE.
А теперь попробуем решить такую задачку: "Использовать ли нам реализацию алиасов DBMail или же реализовать это силами нашего MTA?" Странный вопрос, не так ли? Ответ - без особой необходимости, нет, не стоит, так как здесь есть момент первый и последний: нужно помнить, что DBMail, это система хранения и доступа к почте для конечных пользователей, а не полноценный smtp сервер. Факт, который очевиден для создателей этой системы. Обработку алиасов, фильтрацию почты, хранение почтовых архивов - все это мы предоставим exim'у, как программе специально разработанной для таких вещей, а не всяким блохоплавающим и почтоотдающим, пускай даже и очень быстро. Однако во всем нужна мера: мы можем использовать алиасы как DBMail, так и MTA - получается очень гибкая и удобная система.
/ЗЫ Можно даже сказать, что DBMail это система доступа для очень большого количества пользователей. В списке рассылки один человечек что-то писал про 400 тысяч юзверей, и где это он работает? хотя нет. лучше не знать. /
Не стоит удивляться, если dbmail-smtp вернет ошибку при попытке положить письмо в несуществующую папку IMAP. Функции проверки существования папки и ее создание лежит на системе, которая использует DBMail. Впрочем, в интернете можно найти примеры, показывающие как реализовать проверку и создание такой папки. В этом нет ничего сложного, так как папкой является запись в таблице mailboxes.
Вот вроде бы мы и рассмотрели основные возможности DBMail. Теперь можно добавить dbmail-maintenance в cron и пойти выпить чашечку чая или кофе. Для получения более полных данных о настройке и работе DBMail советую почитать англоязычные источники и не менее англоязычные исходники. (это не черный юмор, это правда жизни)

Amavisd-new - A MAil VIrus Scaner.

Возможности Amavisd-new

В этой главе я попробую описать настройки amavisd-new, разбавляя их по ходу текста своими комментариями и замечаниями. При изучении существующих систем фильтрации мы столкнемся с достаточно широким спектром продуктов, одни из которых представляют собой небольшие скрипты, отсеивающие почту по ряду жестко заданных параметров, другие - дорогие навороченные системы, осуществляющие при фильтрации эвристический анализ, выявляющие неблагонадежных сотрудников, рассылающих свои резюме и т.д. /ЗЫ прошу прощения за философию, но, честно говоря, глядя на описание таких систем, вспоминается мне старикашка Эдельвейс со своей эвристической машиной, пытающийся выиграть тендер у большой тройки (был такой персонаж у Стругацких). IMHO, используя определенные административные меры и обладая определенными техническими возможностями, мы можем "выявлять неблагонадежных сотрудников, рассылающих свои резюме" более эффективно, нежели предлагаемая нам за немаленькие деньги эвристическая машинка. Естественно, не нарушая при этом законодательства РФ. / Если обратить внимание на "бесплатные решения" фильтрации почты, работающие совместно с exim'ом, то наиболее распространены такие варианты как:
  • транспорт pipe совместно с сортировщиком procmail, что является одним из наиболее простых и вместе с тем ресурсоемких методов (imho)
  • встроенный механизм фильтрации exim'a
  • патч exiscan-acl
  • специальные интерфейсы-посредники
/ЗЫ думаю, отцы почтостроения без проблем вспомнят и о паре собственных рецептов/
Amavisd-new является представителем последней категории (к этой же категории мы можем отнести и MIMEDefang, но на вкус, на цвет - товарищей нет, как говорится). Это демон - посредник между MTA и программными продуктами, фильтрующими почту. Он обеспечивает возможность легкой (хотя для кого как конечно) интеграции exim'а, spamassassin и более 30 антивирусных пакетов. Список интересных, на мой взгляд, возможностей amavisd-new:
  • отсутствует необходимость запускать новый процесс для фильтрации нового сообщения, как это происходит с procmail.
  • есть pre-forked reusable children.
  • есть возможность сделать chroot, включив в окружение внешние программы (тот же самый SpamAssassin).
  • можно использовать несколько антивирусных программ для проверки почты (на данный момент поддерживаются более 30 антивирусных пакетов).
  • возможна поддержка постоянных соединений с AV демонами.
  • поддерживается проверка MIME типа, заголовков.
  • возможно кэширование нескольких последних сообщений с созданием MD5 хеша содержимого, позволяющие повысить скорость фильтрации при массовой рассылке почты.
  • возможна индивидуальная настройка правил фильтрации для отдельных пользователей.
  • поддержка LDAP и SQL.
Это далеко не все возможности amavisd-new, и если вы захотите узнать об этой программе больше, советую зайти на сайт и почитать документацию.

Установка и настройка amavisd-new.

Установка amavisd-new в gentoo linux не отнимет много времени. Достаточно дать команду emerge amavisd-new, и пакет установлен. После установки в каталоге etc появится файл amavisd.conf, в котором нам необходимо будет отредактировать 8 секций:
  • Essential daemon and MTA settings - настройки, отвечающие за взаимодействие демона amavisd-new и MTA (в данном случае exim'a).
  • MTA specific - настройка параметров, определяющих особенности взаимодействия amavisd-new и почтового сервера.
  • Logging - настройка параметров сохранения логов.
  • Notifications/DSN, BOUNCE/REJECT/DROP/PASS destiny, quarantine - настройка уведомлений, DSN(Delivery Status Notifications), результатов фильтрации (BOUNCE/REJECT/DROP/PASS), карантина.
  • Per-recipient and per-sender handling, whitelisting, etc. - настройка индивидуальных параметров для отдельных пользователей, настройка белых/черных списков и т.п.
  • Resource limits - настройка ограничений на использование ресурсов.
  • External programs, virus scanners, SpamAssassin - настройка взаимодействия amavisd-new и внешних программ.
  • Debugging - отладка.
/ЗЫ самая доступная документация в amavisd-new, это исходники, списки рассылки и конфигурационный файл, так как там указаны все необходимые параметры и их описание. Я долго прикидывал, как бы поподробнее описать настройку amavisd-new, и в итоге решил не мучаться, а просто дать описание переменных amavisd-new в том порядке, в котором они идут в конфигурации.

                   И еще.

         Если нам необходимо посмотреть содержимое переменной f, содержащей n уровней массивов/хешей (например, содержимое $per_recip_blacklist_sender_lookup_tables), то, на мой взгляд, проще всего это сделать, используя модуль Data::Dumper:
use Data::Dumper;
$Data::Dumper::Maxdepth = n;
print Data::Dumper->Dump([$f] , [qw(f)]); /
Настройка параметров, отвечающих за взаимодействие демона amavisd-new и MTA.
$MYHOME - задает рабочий каталог демона.
$mydomain - содержит название вашего домена и используется, как способ быстрой подстановки в других переменных конфигурационного файла.
$daemon_user и $daemon_group - задают учетную запись, с правами которой работает amavisd-new (рекомендуется использовать пользователя и группу, специально созданную для amavisd-new).
$TEMPBASE - содержит путь к рабочей директории, в которой создаются временные папки для распаковки проверяемой почты.
$helpers_home - указывает на каталог, находящийся на "нормальном" жестком диске, используется для установки переменной окружения HOME, так же передается Mail::SpamAssassin::new в виде опции home_dir_for_helpers.
$daemon_chroot_dir - используется, только если чрутим amavisd-new, в ином случае оставляем ее неопределенной.
$pid_file и $lock_file - определяют, соответственно, пути к pid и lock файлу.
Это были переменные, имеющие отношения непосредственно к работе демона. А теперь мы выберем тип MTA, с которым будет работать amavisd-new. Нам необходимо будет раскомментировать секцию, отвечающую за взаимодействие amavisd-new и exim v4. Ищем комментарий "POSTFIX, or SENDMAIL in dual-MTA setup, or EXIM V4" и раскомментируем следующие за ним переменные $forward_method и $notify_method. Определим Net::Server pre-forking настройки.
$max_servers - задает количество предварительно запущенных процессов.
$max_requests - определяет максимально допустимое количество параллельно обрабатываемых запросов. /ЗЫ в Интернете приводятся примеры, где этой переменной присваиваются значения более 50, однако определить для себя оптимальное значение можно IMHO только эмпирическим путем./
$child_timeout - задает максимальное время обработки запроса.
Нам предлагается раскомментировать @bypass_virus_checks_acl, @bypass_spam_checks_acl, если мы вообще не хотим использовать антивирусную проверку или фильтрацию спама соответственно.
Теперь установим переменные локальных доменов, отвечающие за определение типа почты: входящая/исходящая. В документации говорится, что к локальным доменам мы относим специальные хосты (типа localhost), домены, виртуальные домены, алиасы доменов и relay домены. Почему я написал переменные, а не переменную?
/ЗЫ Информация, изложенная ниже, является результатом данных, которые я получил из документации avamaisd-new, всевозможных почтовых рассылок, примеров конфигураций и анализа исходных текстов amavisd-new. Эта информация является моим собственным заключением. В официальной документации объяснение принципов определения локальных доменов отсутствует. /
Дело в том, что amavisd-new осуществляет поиск совпадений во всех доступных ему источниках. То есть, если вы укажете ему параметры подключения к SQL и LDAP базам, а так же укажете acl и хеш, то поиск совпадений будет производиться последовательно, во всех источниках. Источники поиска локальных доменов следующие (мы можем посмотреть их в README.lookups):скалярные величины/хеш, листок доступа(acl), регулярное выражение, SQL, LDAP. Если мы заглянем в исходники и посмотрим на код функции lookup, то увидим, что порядок просмотра совпадений зависит от порядка передачи типа источников. Проанализировав функцию check_mail, видим, что функции lookup источники передаются в следующем порядке: SQL, LDAP, хеш, листок доступа, регулярное выражение. В других функциях amavisd-new порядки просмотра источников аналогичны. В любом случае, назначение функции lookup, это ответить на вопрос: совпадение есть или нет, и порядок просмотра источников не играет для нас роли. (IMHO немного дополнительных знаний не повредят, да и рулить процессом спокойнее, обладая знанием, что там внутри) Итого мы можем сразу задать хеш (read_hash), листок доступа ($local_domains_acl) и регулярное выражение ($local_domains_re), соответствующие локальным доменам. Поиск локальных доменов в SQL и LDAP задается неявно в тот момент, когда мы указываем параметры подключения к базам данных.
Настройка параметров, определяющих особенности взаимодействия amavisd-new и почтового сервера.
$relayhost_is_client - позволяет использовать несколько почтовых серверов с одним демоном amavisd-new. /ЗЫ интересное предложение, не так ли? Реализовывать не доводилось./ При $relayhost_is_client =1 IP адрес в переменных $notify_method и $forward_method меняется на IP SMTP сервера, обращающегося с запросом, а порт вычисляется, как порт, который использовался для установки соединения + 1.
$insert_received_line - определяет необходимость добавления заголовка "Received:" при обработке письма.
$unix_socketname - определяет путь к юникс сокету amavisd-new, однако для взаимодействия с exim не используется.
$gets_addr_in_quoted_form - определяет, передается ли демону почтовый адрес, заключенный в кавычки или нет.
$inet_socket_port - указывает порт, на котором принимаются входящие соединения MTA (есть возможность указать несколько портов).
$inet_socket_bind - содержит список адресов интерфейсов, на которых мы хотим принимать запросы к демону (например, если у нас MTA находится на одной машине с amavisd-new, то мы можем присвоить $inet_socket_bind значение 127.0.0.1).
$inet_acl - список адресов хостов и сетей, которым разрешен доступ к amavisd-new демону.
Настройка параметров сохранения логов.
$DO_SYSLOG - определяет, будем ли мы использовать для хранения логов syslog.
$SYSLOG_LEVEL - определяет уровень сообщений, передаваемых syslog'у.
$LOGFILE - содержит путь к лог файлу.
$log_level - определяет, насколько детально должны вестись лог файлы. Всего 6 уровней детализации с 0-ого по 5-ый: 5-ый уровень - максимальный (выводится все, включая отладочную информацию). На 0-ом уровне записываются только события, касающиеся запуска, остановки демона, критических ошибок и обнаруженных вирусов.
$log_templ - содержит шаблон, который позволяет заносить в логи информацию, связанную с обработанными сообщениями (являются ли письма спамом, содержат ли вирус и т.д.). Подробное описание синтаксиса и переменных шаблона находятся в файле README.customize.
Настройка уведомлений, DSN(Delivery Status Notifications), результатов фильтрации (BOUNCE/REJECT/DROP/PASS), карантина.
$hdr_encoding и $bdy_encoding - содержат MIME кодировку заголовков и содержимого для отсылаемых уведомлений.
Если мы хотим переопределить стандартные уведомления, то можем использовать такие переменные как $notify_sender_templ, $notify_virus_sender_templ, $notify_virus_admin_templ, $notify_virus_recips_templ, $notify_spam_sender_templ, $notify_spam_admin_templ, присваивая им непосредственно текст или считывая шаблон из файла с помощью функции read_text, первый аргумент которой путь к файлу с шаблоном, а второй аргумент - кодировка шаблона. Есть возможность загрузить альтернативные шаблоны с помощью функции read_l10n_templates - эта функция загружает все найденные шаблоны, проверяя на наличие в указанной директории (вида ru_RU, en_US и т.п.) файлы из следующего списка: template-dsn.txt, template-virus-sender.txt, template-virus-admin.txt, template-virus-recipient.txt, template-spam-sender.txt, template-spam-admin.txt.
Установим переменные, отвечающие за фильтрацию сообщений. Фильтрация сообщений, на примере антивирусной проверки выглядит так:
  • Установлена переменная bypass_virus_checks? ==> PASS
  • Вирусы не обнаружены? ==> PASS
  • Заносится в лог файл факт обнаружения вируса, если определенна переменная $log_templ
  • Используется карантин, если определена переменная $virus_quarantine_to
  • Отсылается уведомление администратору, если определена переменная $virus_admin
  • Отсылается уведомление получателю, если определена переменная $warnvirusrecip или отправитель является нашим локальным пользователем, или установлена $warn_offsite
  • Добавляется расширение к адресу получателя для локальных получателей, если разрешено. Например, письмо с вирусом было отправлено на адрес test@test.com, а добавляемый суффикс "---virus". В результате письмо после проверки будет содержать адрес получателя test---virus@test.com.
  • Отсылается уведомление о (не) доставке сообщения отправителю, если требуется DSN (BOUNCE или ($warnvirussender и D_PASS))
  • Если адрес получателя в списке virus_lovers или установлена final_destiny==D_PASS ==> PASS
  • Иначе выполняется DISCARD (2xx) или REJECT (5xx) (в зависимости от final_*_destiny)
Аналогично происходит фильтрация спама. Если антивирусная проверка указывает на наличие вируса, спам проверка не производится. Следующие константы могут использоваться при установке переменных типа *destiny:
  • D_PASS - почта проходит к получателям, даже если был обнаружен вирус/спам/.
  • D_DISCARD - почта не проходит к получателям, отправитель не получает уведомление. Почтовое сообщение, попросту говоря, отбрасывается (однако кладется в карантин, если требуется). Конечно такая вещь, как блокировка почтового сообщения без отправки уведомлений, не всегда правильная реакция со стороны почтового сервера (" Человек послал письмо - ждет, надеется, а вы."), но порой необходимая.
  • D_BOUNCE - почта не проходит к получателям, уведомление о блокировке сообщения отсылается отправителю. Уведомление может не отсылаться, если название вируса соответствует $viruses_that_fake_sender_re или источником сообщения является почтовый лист(mailing list). Отправка уведомления осуществляется непосредственно amavisd-new.
/ЗЫ. Например, при обработке правила $final_spam_destiny = D_BOUNCE и обнаружении спама, amavisd-new сформирует от адреса, полученного из $hdrfrom_notify_sender, ответ следуещего вида:

 
Your message to:
-> адрес получателя


was considered unsolicited bulk e-mail (UBE).
Subject: xxxxxxxxxxx
Return-Path: 

Delivery of the email was stopped!

+ информация о заблокированном сообщении
 
/
  • D_REJECT - почта не проходит к получателям, отправитель должен получить reject (SMTP permanent reject response), если используется такой механизм как milter, или отправитель получает уведомление о невозможности доставки от MTA (если наш MTA:exim, postfix,.) Если вышеописанные два варианта ответа невозможны (например, мы не используем LMTP, это которое rfc2033, и различные получатели сообщения имеют различные параметры фильтрации), amavisd-new сам отсылает уведомление о невозможности доставки (так же, как это бы происходило при D_BOUNCE). Наиболее эффективен данный тип отказа в связке с sendmail milter при блокировке спама.
/ЗЫ при установке $final_spam_destiny = D_REJECT и обнаружении спама, amavis ответит exim'у сообщением: 550 5.7.1 Message content rejected, UBE, id=xxxxx-xx, что будет отражено в логах exim'a. Exim, в свою очередь, сформирует ответ от Mailer-Daemon на адрес, записанный в return-path, который будет выглядеть примерно так:
 
 This message was created automatically by mail delivery software.

 A message that you sent could not be delivered to one or more of its
 recipients. This is a permanent error. The following address(es) failed:

   адрес получателя
     SMTP error from remote mailer after end of data:
     host xxxxxxxxxx  [xxx.xxx.xxx.xxx]: 550 5.7.1 Message content rejected, UBE, id=xxxxx-xx

------ This is a copy of the message, including all the headers. ------

Содержимое письма. 
 
/
По своей сути D_BOUNCE и D_REJECT похожи, вся разница между ними в отправителе и содержании уведомления (amavis-new знает о причине посылки уведомления больше, чем MTA и, как следствие, может сгенерировать более подробный ответ).
$final_virus_destiny - устанавливает действие при фильтрации писем, зараженных вирусом, по умолчанию D_BOUNCE.
$final_banned_destiny - устанавливает действие при фильтрации писем, содержащих запрещенные MIME типы или присоединенные файлы, по умолчанию D_BOUNCE.
$final_spam_destiny - устанавливает действие при фильтрации писем, идентифицированных как спам, по умолчанию D_REJECT.
$final_bad_header_destiny - устанавливает действие при фильтрации писем, содержащих неправильные заголовки, по умолчанию D_PASS.
При фильтрации спама мы можем установить опцию $final_spam_destiny в D_PASS, если наши пользователи будут осуществлять фильтрацию почтовых сообщений по заголовкам или D_DISCARD, если мы выставили достаточно высокий kill_level и уверены, что такие сообщения действительно являются спамом. Нам так же выгоднее присвоить D_BOUNCE вместо D_REJECT, если мы не используем milter. При фильтрации вирусов как правило используется D_BOUNCE, однако мы можем установить $final_virus_destiny в D_PASS или использовать списки доступа virus_lovers для доставки сообщений с вирусами получателям и опцию $warnvirussender, для уведомления отправителя о факте отправки вируса. Использование D_REJECT оправдывает себя при использовании milter или при сильной вирусной атаке (печально, но такие вещи происходят все чаще и с каждым разом сильнее).
/ЗЫ amavisd-new воспринимает сигнал HUP и может перечитать конфигурацию без перезапуска. Мы можем в зависимости от ситуации менять опции и просить amavisd-new перечитать конфигурационный файл. Эту схему несложно реализовать с помощью monit. Редко когда может потребоваться, однако. /
Следует помнить, что если мы установим переменные final_*_destiny в D_DISCARD (это когда мы отбрасываем письмо, не отсылая уведомлений), а переменные $warn*sender=1, то D_DISCARD превращается в D_BOUNCE. Установка же переменных $warnvirussender и $warnspamsender имеет смысл только при final_*_destiny = D_PASS (для вирусов или спама).
Использование переменных $warn*sender имеет смысл только при разрешении прохождения спама и вирусов ($final_*_destiny=D_PASS, или *_lovers*), т.к. при D_BOUNCE и D_REJECT уведомление о невозможности доставить почту будет сгенерированно автоматически.
$warnvirussender - указывает, необходимо ли отсылать уведомление отправителю письма, зараженного вирусом.
$warnspamsender - указывает, необходимо ли отсылать уведомление отправителю письма, являющегося спамом.
$warnbadhsender - указывает, необходимо ли отсылать уведомление отправителю письма, содержащего некорректные заголовки.
$warnvirusrecip - указывает, необходимо ли отсылать уведомление получателю письма, зараженного вирусом.
$warnbannedrecip - указывает, необходимо ли отсылать уведомление получателю письма, содержащего некорректные MIME типы или файлы.
$warn_offsite - указывает, можно ли отсылать уведомления для $warn*recip, если получатель не является локальным пользователем.
$viruses_that_fake_sender_re - содержит список регулярных выражений, соответствующих названиям вирусов, которые могут подменять почтовый адрес отправителя. Если письмо заражено вирусом, находящимся в этом списке, amavisd-new не создает уведомление, отсылаемое отправителю, о невозможности доставки, т.к. велика вероятность того, что адрес отправителя не соответствует действительности.
$virus_admin и $spam_admin - содержат адреса администраторов или хеш адресов, на которые необходимо отсылать уведомления при обнаружении спама или вируса. Например, если мы присвоим $virus_admin приведенный ниже хеш, то уведомления о фильтрации писем адреса baduser@sub1.example.com будут отсылаться на HisBoss@sub1.example.com, для остальных писем, предназначенных домену .sub1.example.com, уведомления будут отсылаться на адрес virusalert@sub1.example.com; уведомления для писем домена .sub2.example.com отсылаться не будут; для писем, имеющих отношения к домену a.sub3.example.com уведомления будут отсылаться на адрес abuse@sub3.example.com, для остальных писем домена sub3.example.com, уведомления будут приходить на адрес virusalert@sub3.example.com; для оставшейся части писем, имеющих отношение к .example.com, уведомления отсылаются на noc@example.com; и, наконец, уведомления о фильтрации писем, не вошедших в вышеперечисленные категории, будут отправлены на адрес virusalert@hq.example.com. Просьба помнить, что речь идет не об уведомлениях вообще, а об уведомлениях администраторам:

$virus_admin = {
'baduser@sub1.example.com' => 'HisBoss@sub1.example.com',
'.sub1.example.com' => 'virusalert@sub1.example.com',
'.sub2.example.com' => '', # don't send admin notifications
'a.sub3.example.com' => 'abuse@sub3.example.com',
'.sub3.example.com' => 'virusalert@sub3.example.com',
'.example.com' => 'noc@example.com',
'.' => 'virusalert@hq.example.com',
};
$mailfrom_notify_admin, $mailfrom_notify_recip, $mailfrom_notify_spamadmin, $hdrfrom_notify_sender, $hdrfrom_notify_admin, $hdrfrom_notify_spamadmin - адреса отправителей соответствующих уведомлений.
$mailfrom_to_quarantine - адрес отправителя, который будет использован при пересылке сообщения в карантин.
$QUARANTINEDIR - указывает на каталог, содержащий письма, помещенные в карантин. /ЗЫ следует заметить, что если значением $QUARANTINEDIR является каталог, то amavisd-new будет использовать его как почтовый ящик maildir. Если же $QUARANTINEDIR ссылается на файл, то amavisd-new будет рассматривать этот файл как Unix-style mailbox. Не следует забывать так же, что одновременное использование файла несколькими процессами amavisd-new невозможно, что может отрицательно сказаться на скорости фильтрации почты./
$virus_quarantine_method, $spam_quarantine_method - задают шаблон для имени файла и тип карантина: local или bsmtp (batch smtp). При указании шаблона мы можем использовать макросы, список которых можно посмотреть в файле README.customize. Если мы используем такой тип карантина как 'local', то amavisd-new будет перенаправлять почту, используя данные, полученные из переменных $virus_quarantine_to и $spam_quarantine_to.
$virus_quarantine_to, $spam_quarantine_to - могут содержать скалярную величину, указатель на хеш или регулярное выражение. Используя хеш или регулярное выражение, мы можем назначать правила карантина для определенных групп доменов получателей. Скалярные значения и значения, полученные из хеша, amavisd-new интерпретирует следующим образом:
  • пустое или неопределенное(undef) значение запрещает перенаправление письма в карантин.
  • строка, не содержащая "@", указывает на необходимость amavisd-new стать LDA (local delivery agent) и поместить отфильтрованное письмо в локальный файл в соответствии с хешем псевдонимов - local_delivery_aliases, который мы можем переопределить в соответствии со своими нуждами. Если мы посмотрим исходный код amavisd-new, то обнаружим, что хеш по умолчанию уже содержит несколько определенных псевдонимов:
    • virus-quarantine - помещает письмо в текстовый файл в соответствии с шаблоном имени в каталог $QUARANTINEDIR
    • spam-quarantine - помещает письмо в gz архив в соответствии с шаблоном имени в каталог $QUARANTINEDIR
    • user-quarantine - помещает письмо в каталог $QUARANTINEDIR, в файл, имя которого содержит дату обработки и адрес отправителя письма
    • ham-quarantine - помещает письмо в $QUARANTINEDIR/ham.mbox
    • outgoing-quarantine - помещает письмо в $QUARANTINEDIR/outgoing.mbox
    • incoming-quarantine - помещает письмо в $QUARANTINEDIR/incoming.mbox
  • строка, содержащая "@", указывает на необходимость переслать отфильтрованную почту по указанному адресу. Если мы хотим переслать почту на локальный почтовый ящик, то можем использовать адрес вида "что-то@". Следует учесть, что при возникновении проблем с адресом, мы может получиться небольшое зацикливание, поэтому imho лучше всего фильтровать bounce сообщения, имеющие отношение к этому адресу. Этот вариант карантина неплохо работает с exim v4, postfix и dual-sendmail, однако необходимо быть осторожными при использовании sendmail milter.
$spam_quarantine_bysender_to - переменная аналогичная по функциям $spam_quarantine_to, но сортировка производится не по адресу получателя, а по адресу отправителя.
$X_HEADER_TAG и $X_HEADER_LINE - задают название заголовка и его содержание. Этот заголовок добавляется в письмо при антивирусной проверке.
$remove_existing_x_scanned_headers, $remove_existing_spam_headers - указывают не необходимость удаления заголовка $X_HEADER_TAG и X-Spam* после процесса фильтрации.
$bypass_decode_parts - запрещает amavisd-new распаковывать архивы, если мы хотим фильтровать только спам или у нас установлен антивирус, который сам справляется с распаковкой. При установке этой опции amavisd-new так же не сможет блокировать запрещенные типы файлов, если они помещены в архив. На проверку непосредственно MIME типов эта опция не влияет.
/ЗЫ В списках рассылки есть информация, где утверждается, что если антивирусная программа(F-Secure, Sophie,.) нормально поддерживает работу с архивами, то желательно включить эту опцию./
$keep_decoded_original_re - является регулярным выражением, содержащим типы файлов, которые необходимо проверять как в распакованном, так и в не распакованном виде. Может также содержать макросы, указывающие на необходимость проверки всего "не разобранного" письма.
$banned_filename_re - является регулярным выражением, содержащим шаблон запрещенных MIME типов и имен. Если какая либо часть письма соответствует значению регулярного выражения, то все письмо блокируется, так же как это происходит при выявлении вируса. С регулярным выражением сравнивается содержимое в следующих частях письма:
  • в Content-Type (объявленные(declared) и реальные MIME типы) включая message/partial и message/external-body (по rfc2046, это которое "Многоцелевые Расширения Почты Интернет").
  • в объявленных именах файлов, определенных MIME подполями Content-Disposition.filename и Content-Type.name, как в их raw (encoded) состоянии, так и в rfc2047-decoded виде, если есть такая возможность.
  • в типах файлов полученных в результате работы утилиты 'file', как в необработанном виде, так и в виде стандартных расширений .asc, .txt, .html, .doc, .jpg, .pdf, .zip, .exe, ... и т. п. Этот тип проверки осуществляется, только если переменная $bypass_decode_parts имеет значение 'истина'.
Если переменная $banned_filename_re не определена, то вышеперечисленные проверки не производятся.
Настройка индивидуальных параметров для отдельных пользователей, настройка белых/черных списков и т. п.
%virus_lovers, @virus_lovers_acl и $virus_lovers_re - соответственно хеш, массив и регулярное выражение. Эти переменные позволяют определить группы адресов/доменов, для которых нет необходимости блокировать зараженные вирусом письма. При обнаружении зараженных писем amavisd-new будет добавлять заголовок "X-AMaViS-Alert: INFECTED, message contains virus: ..." за исключением случая, когда мы используем milter interface. В случае использования milter interface'a (тьфу, тьфу, тьфу. как я рад, что мы юзаем exim) при обработке письма, имеющего сразу несколько получателей, избирательная блокировка невозможна: если хотя бы один из получателей не принадлежит virus_lovers, письмо блокируется.
%bypass_virus_checks, @bypass_virus_checks_acl и $bypass_virus_checks_re - соответственно хеш, массив и регулярное выражение. Эти переменные позволяют определить группы адресов/доменов, для которых нет необходимости производить антивирусную проверку. Антивирусная проверка не производится только в том случае, когда все получатели сообщения определены в bypass_virus_checks.
%spam_lovers, @spam_lovers_acl и $spam_lovers_re - переменные, позволяющие определить группы адресов/доменов, для которых нет необходимости блокировать спам. Алгоритм работы переменных аналогичен virus_lovers.
banned_files_lovers, @banned_files_lovers_acl и $banned_files_lovers_re - переменные, позволяющие определить группы адресов/доменов, для которых нет необходимости блокировать почту, содержащую файлы из черного списка. Алгоритм работы переменных аналогичен virus_lovers.
%bad_header_lovers, @bad_header_lovers_acl и $bad_header_lovers_re - переменные, позволяющие определить группы адресов/доменов, для которых нет необходимости блокировать почту, содержащую испорченные заголовки. Алгоритм работы переменных аналогичен virus_lovers.
%bypass_spam_checks,@bypass_spam_checks_acl и $bypass_spam_checks_re - переменные, позволяющие определить группы адресов/доменов, для которых нет необходимости проверять почтовые сообщения на спам. Алгоритм работы переменных аналогичен bypass_virus_checks.
%bypass_banned_checks, @bypass_banned_checks_acl и $bypass_banned_checks_re - переменные, позволяющие определить группы адресов/доменов, для которых нет необходимости производить проверку сообщений на файлы, содержащиеся в черном списке. Алгоритм работы переменных аналогичен bypass_virus_checks.
%bypass_header_checks, @bypass_header_checks_acl и $bypass_header_checks_re - переменные, позволяющие определить группы адресов/доменов, для которых нет необходимости производить проверку испорченных заголовков. Алгоритм работы переменных аналогичен bypass_virus_checks.
Более подробную информацию об использовании переменных *_lovers и bypass_* можно найти в файле README.lookups.
Несколько примеров использования *_lovers и bypass_* переменных:

$virus_lovers{lc("postmaster\@$mydomain")} = 1;
$virus_lovers{lc('postmaster@example.com')} = 1;
$virus_lovers{lc('abuse@example.com')} = 1;
$virus_lovers{lc('some.user@')} = 1; # для адреса, содержащего локальную часть some.user
$virus_lovers{lc('boss@example.com')} = 0; # никогда, даже если домен совпал
$virus_lovers{lc('example.com')} = 1; # для домена, но не поддоменов
$virus_lovers{lc('.example.com')}= 1; # для домена, включая поддомены

или

@virus_lovers_acl = qw( me@lab.xxx.com !lab.xxx.com .xxx.com yyy.org );
$bypass_virus_checks{lc('some.user2@butnot.example.com')} = 1;
@bypass_virus_checks_acl = qw( some.ddd !butnot.example.com .example.com );
@virus_lovers_acl = qw( postmaster@example.com );
$virus_lovers_re = new_RE( qr'^(helpdesk|postmaster)@example\.com$'i );
$spam_lovers{lc("postmaster\@$mydomain")} = 1;
$spam_lovers{lc('postmaster@example.com')} = 1;
$spam_lovers{lc('abuse@example.com')} = 1;
@spam_lovers_acl = qw( !.example.com );
$spam_lovers_re = new_RE( qr'^user@example\.com$'i );

не выполнять проверку на спам для получателей следующих доменов:

@bypass_spam_checks_acl = qw( d1.com .d2.com a.d3.com );

или другой пример (не выполнять проверку для всех, кроме...):

@bypass_spam_checks_acl = qw( !d1.com !.d2.com !a.d3.com . );

не проверять исходящую почту(если мы обслуживаем только $mydomain):

@bypass_spam_checks_acl = ( "!.$mydomain", "." );

недостатком последнего примера может являться то, что spamassassin не сможет анализировать исходящую ham (no-spam) почту и заносить результаты в bayes БД.
@lookup_sql_dsn - массив строк вида "DBI:тип базы данных:опции', 'логин', 'пароль'". Официально поддерживаются postgresql и mysql, но, учитывая, что amavisd-new работает с БД посредством DBI, по идее, он должен поддерживать и альтернативные источники данных. В массиве мы перечисляем параметры подключения ко всем необходимым нам СУБД(primary и backup). /ЗЫ на момент написания статьи, судя по исходникам, если задать несколько источников данных, то amavisd-new будет тупо перебирать их по порядку, пока не сможет подключиться к какому либо. скучные ребята. могли бы псевдобалансировку сделать что ли. хотя оно кому надо? не просили их просто. да и если нужно, проще самому поправить. /
$sql_select_policy - содержит строку запроса к БД, определяющую политику фильтрации почты для определенного адреса/домена. Макрос '%k' содержит список, созданный из адреса получателя. Записи в списке разделяются запятыми и содержат следующие значения: полный почтовый адрес, домен, точку. Мы должны использовать ORDER, если запрос к БД может возвратить несколько строк. Обрабатывается только первая строка. Если запрос возвращает несколько полей с одинаковым названием, то обрабатывается значение последнего поля (обработка поля id, при использовании настроек по умолчанию; '*,users.id').
$sql_select_white_black_list - содержит строку запроса к БД, определяющую черные/белые списки принадлежащие получателю. Макрос '%k' содержит список, созданный из адреса отправителя. Записи в списке разделяются запятыми и содержат следующие значения: полный почтовый адрес, домен, точку. Макрос '?' содержит идентификатор пользователя, для которого производится поиск.
$addr_extension_virus, $addr_extension_spam и $addr_extension_banned - содержат суффиксы, добавляемые к почтовому адресу при политике фильтрации D_PASS. Как правило, эти суффикса нужны для LDA, который может сортировать почту, раскладывая ее в разные папки. Суффиксы не добавляются к адресам почтовых сообщений, не содержащих спам, вирусы или подлежащих блокировке. Суффиксы так же не добавляются, если адрес является внешним (не принадлежит local_domains*).
$recipient_delimiter - символ разделителя, добавляемого amavisd-new перед суффиксом.
$replace_existing_extension - если значение переменной 'истина', происходит замена существующего суффикса на текущий, в противном случае суффикс добавляется к существующему суффиксу.
$localpart_is_case_sensitive - указывает на необходимость учитывать регистр символов в локальной части адреса при поиске совпадений.
%whitelist_sender, @whitelist_sender_acl, $whitelist_sender_re, %blacklist_sender, @blacklist_sender_acl, $blacklist_sender_re - соответственно хеши, массивы и регулярные выражения, содержащие значения глобальных (не зависимых от адреса получателя) белых и черных списков, использующихся только во время фильтрации спама. При проверке используется ENVELOPE SENDER адрес, то есть тот, что на конверте. Белый список позволяет гарантировать доставку сообщения от определенного источника даже в том случае, если почтовое сообщение распознается как спам. Все получатели письма из белого списка, помеченного как спам, становятся временно 'spam_lovers' со всеми вытекающими. Письму с адресом из черного списка присваивается высокий уровень спама, после чего происходит фильтрация. Если письмо из черного списка не блокируется (например, для получателей 'spam_lovers') amavisd-new присваивает заголовку 'X-Spam-Status' значение 'BLACKLISTED'. Адрес отправителя может принадлежать черному и белому спискам одновременно. В таком случае сообщение не блокируется и попадает к получателю помеченное как спам. Если все получатели письма принадлежат черному/белому списку, то сканирование письма на спам (вызов spamassassin) не производится. При добавлении записи в белый список следует учитывать, что на сегодня день злоумышленнику подменить адрес отправителя не составляет особого труда. Создатели системы рекомендуют по возможности использовать списки bypass_spam_checks_acl. Примеры списков:

@whitelist_sender_acl = qw( .example.com ); - домен example.com и его поддомены
@whitelist_sender_acl = ( ".$mydomain" ); - домен $mydomain и его поддомены
$whitelist_sender_re = new_RE(
qr'^postmaster@.*\bexample\.com$'i,
qr'^owner-[^@]*@'i,
qr'-request@'i,
qr'\.example\.com$'i ); - адрес postmaster для домена и поддоменов example.com, адрес с префиксом 'owner-', адрес с суффиксом '-request', все адреса домена и поддоменов example.com.
read_hash(\%whitelist_sender, '/var/amavis/whitelist_sender'); - загрузить список из файла
$whitelist_sender{''} = 1; - не блокировать bounce сообщения
При работе со списками-хешами удобно использовать функцию map, которая выдает результаты вычисления выражения (вычисляемого в списочном контексте):

map { $whitelist_sender{lc($_)}=1 } (qw(список адресов, разделенных пробелом или переводом строки));
$per_recip_blacklist_sender_lookup_tables, $per_recip_whitelist_sender_lookup_tables - хеши, содержащие значения черных/белых списков для отдельных групп доменов/получателей, аналогичные по функциям глобальным спискам. Значения в этих хешах переопределяют значения глобальных черных/белых списков. Ключами этих хешей являются адреса получателей, а значениями - массивы, состоящие из массивов, хешей или регулярных выражений, определяющих группы адресов отправителей. Пример списков:

$per_recip_blacklist_sender_lookup_tables = {
'user1@my.example.com'=>new_RE(qr'^(inkjetplanet|marketopt|MakeMoney)\d*@'i),
'user2@my.example.com'=>[qw( spammer@d1.example.org .d2.example.org )],
};
- помещаем в черный список получателя 'user1@my.example.com' письма с адресами, начинающимися со следующих слов: inkjetplanet, marketopt, MakeMoney; для пользователя 'user2@my.example.com' письма с адресом отправителя 'spammer@d1.example.org' и все из домена и поддоменов 'd2.example.org'

$per_recip_whitelist_sender_lookup_tables = {
'user@my.example.com' => [qw( friend@example.org .other.example.org )],
'.my1.example.com' => [qw( !foe.other.example.org .other.example.org )],
'.my2.example.com' => read_hash('/var/amavis/my2-wl.dat'),
'abuse@' => { 'postmaster@'=>1,'cert-advisory-owner@cert.org'=>1, 'owner-alert@iss.net'=>1},
};
- помещаем в белый список для пользователя 'user@my.example.com' адрес отправителя 'friend@example.org' и все адреса доменов и поддоменов 'other.example.org'; для всех пользователей домена и поддоменов '.my1.example.com' все адреса домена и поддоменов 'other.example.org', кроме адресов поддомена 'foe.other.example.org'; для всех пользователей домена и поддоменов '.my2.example.com' все адреса из файла 'my2-wl.dat' и, наконец, для пользователя 'abuse' любого домена адрес отправителя 'postmaster' для любого домена и адреса 'cert-advisory-owner@cert.org' и 'owner-alert@iss.net'.
Настройка ограничений на использование ресурсов.
$smtpd_recipient_limit - определяет максимально допустимое количество получателей для одного сообщения.
$MAXLEVELS - определяет максимальное число обрабатываемых уровней для вложенных архивов. Помогает защитить распаковщики, декодеры и антивирусы от некоторых видов почтовых бомб (например, 42.zip).
$MAXFILES - определяет максимальное количество файлов, извлекаемых из архива.
Следующие переменные позволяют установить ограничение на суммарные размеры распакованных частей почтового сообщения. Учитываются только исходные размеры почтового сообщения - то есть если в процессе распаковки вдруг какая-то из частей была удалена/стала меньше, то на исходный размер почтового сообщения это не влияет. Алгоритм расчета ограничения для занимаемого пространства:

quota = max($MIN_EXPANSION_QUOTA, $mail_size*$MIN_EXPANSION_FACTOR,
                        min($MAX_EXPANSION_QUOTA, $mail_size*$MAX_EXPANSION_FACTOR))
$MIN_EXPANSION_QUOTA и $MAX_EXPANSION_QUOTA - минимально и максимально допустимые размеры распакованных частей.
$MIN_EXPANSION_FACTOR и $MAX_EXPANSION_FACTOR - минимально и максимально допустимое количество раз, в которое распакованная почта должна быть больше оригинального запакованного сообщения.
Настройка взаимодействия amavisd-new и внешних программ.
$path - аналог переменной окружения PATH. Содержит пути, в которых будет производиться поиск внешних программ. Так же содержимое этой переменной будет присвоено переменной окружения PATH при запуске внешних программ. При chroot'е указывать каталоги необходимо относительно $daemon_chroot_dir.
$file - имя утилиты file
$gzip, $bzip2, $lzop, $uncompress, $unfreeze, $arc, $unarj, $unrar, $zoo, $lha, $cpio - имена и параметры внешних распаковщиков.
$sa_local_tests_only - позволяет отключить в SpamAssassin проверки, для которых необходимы интернет запросы, такие как DNSBL и тестирование Razor/Pyzor/DCC, при фильтрации спама и оставляет возможность использовать только правила, распознающие спам и движок Bayes. /ЗЫ после работы с SA и изучения мнений пользователей n-ого количества почтовых рассылок, форумов и т.д. могу посоветовать включать $sa_local_tests_only только, если наблюдаются проблемы с производительностью./
$sa_auto_whitelist - позволяет использовать белый список SA. По умолчанию отключен.
$sa_mail_body_size_limit - устанавливает максимальный размер почты, которую необходимо проверять на спам. /ЗЫ В конфигурационном файле amavisd-new утверждается, что только менее 1% спама имеет размер более 64k, причем лимит по умолчанию выставлен 150кб. IMHO универсального предела нет, и размер нужно выставлять в зависимости от конкретной нагрузки. К тому же наши спамеры совсем обнаглели и частенько рассылают сообщения более 150кб./
$sa_tag_level_deflt - содержит уровень, после которого необходимо добавить в сообщение заголовки 'X-Spam-Status' и 'X-Spam-Level'.
$sa_tag2_level_deflt - содержит уровень, после которого необходимо добавить в сообщение заголовок 'spam detected' - 'X-Spam-Flag: YES'.
$sa_kill_level_deflt - содержит уровень, после которого необходимо блокировать сообщение, поместить, при необходимости, в карантин и отправить, если нужно, уведомление о невозможности доставить почту.
Переменные $sa_*_level_deflt используются только в том случае, если amavisd-new не получил значения из других источников (SQL, LDAP). Эти переменные помимо скалярных величин могут содержать хеши (я так понимаю, что ключом, в таком случае, будет являться адрес получателя, а значением - уровень спама).
$sa_spam_subject_tag - содержит строку, добавляемую в тему письма при значении более tag2 баллов.
$sa_spam_modifies_subj - определяет, необходимо ли модифицировать тему письма при обнаружении спама. Значение $sa_spam_modifies_subj может содержать так же хеш из адресов получателей. Пример использования:

$sa_spam_modifies_subj = [qw( !user@example.com . )]; - для всех адресов кроме 'user@example.com'
@av_scanners - массив, элементы которого описывают интерфейс антивирусных программ. Каждый элемент состоит из нескольких полей:
  • Название антивирусного пакета, которое будет использоваться в логах и отчетах.
  • Название исполняемого файла, которое затем передается функции find_external_programs(), пытающейся найти полный путь к программе; если программа не найдена - антивирус блокируется. Это поле также может содержать список указателей на имена исполняемых файлов или полных путей, включающих имена исполняемых файлов - amavisd-new будет использовать первое совпадение. Для некоторых особых антивирусных пакетов есть возможность использовать в этом поле указатель на подпрограмму с массивом значений, которые будут переданы ей в виде аргументов.
  • Аргументы командной строки (или хитрой подпрограммы особого антивирусного пакета), передаваемые сканеру. Макрос '{}' заменяется на полный путь к проверяемому файлу, т.е. "$tempdir/parts", а '*' заменяется на имя проверяемого файла.
  • Массив кодов возврата или регулярных выражений применяемых к результату, возвращаемых антивирусной программой, говорящих, что вирусов не найдено.
  • Массив кодов возврата или регулярных выражений применяемых к результату, возвращаемых антивирусной программой, говорящих, что найден вирус.
  • Регулярное выражение, извлекающее названия вирусов из результатов проверки зараженного почтового сообщения.
  • Подпрограмма, которая должна быть выполнена до запуска антивирусной программы. (optional)
  • Подпрограмма, которая должна быть выполнена после запуска антивирусной программы. (optional)
Особенности использования @av_scanners:
  • В случае если значение массива @av_scanners не определено - amavisd-new не загружает антивирусный код вообще.
  • При проверке почты все найденные антивирусные сканеры запускаются в том порядке, в каком они указаны в списке до тех пор, пока не будет найден вирус или же, пока почтовое сообщение не будет проверено всеми найденными антивирусными пакетами.
  • Нерабочие элементы @av_scanners не влияют на производительность amavisd-new, т.к. поиск рабочих антивирусных пакетов производится только при запуске почтового демона.
  • Для того, что бы заблокировать поиск сканера, не установленного на вашем сервере, достаточно закомментировать элемент массива или же присвоить второму аргументу (имени исполняемого файла) пустое значение ''.
  • При использовании демонов следует блокировать поиск обычных исполняемых файлов - это справедливо для таких антивирусных пакетов, как Sophos, Trophie, Сlamd и подобных.
  • Настоятельно рекомендуется закомментировать все не использующиеся записи, особенно содержащие ссылки на подпрограммы, т.к. если оставить такую запись не закомментированной, то amavisd-new каждый раз будет пытаться установить соединение с антивирусом, что отрицательно скажется на производительности.
@av_scanners_backup - массив, аналогичный @av_scanners. Используется только в том случае, если ни один из сканеров из массива @av_scanners не вернул ни положительного, ни отрицательного ответа. В этом массиве рекомендуется использовать записи, описывающие вызов антивирусной программы из командной строки (это касается тех антивирусов, которые имеют возможность запуска, как в режиме демона, так и в виде консольной утилиты).
Отладка amavisd-new.
@debug_sender_acl - массив адресов отправителей. При получении письма, содержащего адрес отправителя из @debug_sender_acl, amavisd-new включает режим отладки.
$keep_decoded_original_re - позволяет сохранять оригинальные закодированные части письма. Имеет смысл только при использовании @debug_sender_acl.
$sa_debug - включает отладку SpamAssassin. Отладочная информация передается на STDERR. Используется совместно с 'amavisd debug'.

Особенности настройки SpamAssassin.

Spamassassin - почтовый фильтр, разработанный для идентификации спама. В gentoo linux для установки последней версии этого пакета необходимо дать команду 'emerge Mail-SpamAssassin' Впрочем, у пакета amavisd-new spamassassin прописан в зависимостях, так что если мы установили amavisd-new, то и spamassassin у нас уже должен быть установлен. Далее по тексту я вместо полного названия 'spamassassin' буду использовать стандартное сокращение SA
Опции, находящиеся в конфигурационном файле amavisd-new и отвечающие за настройки SA носят общий характер, поэтому нам все равно придется настраивать SA, несмотря на то, что он заработал из коробки.
SA у нас вызывается из amavisd-new в виде perl модуля. Прежде чем создавать конфигурационный файл необходимо разобраться, откуда, в каком порядке и как загружаются файлы. В этом нам поможет секция 'Customising SpamAssassin' в файле README, который идет в стандартной поставке.
После того, как мы выяснили, как SA обрабатывает конфигурационные файлы, и создали свой собственный конфиг, для отладки SA в конфигурации amavisd-new присвоим опции sa_debug значение 1. Запуская amavisd-new с опцией 'debug-sa' мы можем получить на STDERR достаточно подробную отладочную информацию. /ЗЫ imho во время отладки удобно вынимать письмо со спамом из почтового ящика программой fetchmail с опцией keep./
Создавая конфиг для SA, мы должны помнить, что опция 'add_header' при работе SA из amavisd-new бесполезна, т.к. " amavisd-new never modifies mail body or let SA do it. All mail (header) editing is done by amavisd-new and not by SA. Even though SA does observe options in its configuration file to rewrite mail body and modify mail header, the result is purposely not used by amavisd-new. There are two reasons for that: be able to offer a guarantee the mail body will not be altered, and secondly, SA is only called once regardless of the number of recipients. This means the per-recipient handling of mail relaying and header editing needs to be done entirely in amavisd-new, as there are no provisions in SA to analyze mail once and then prepare different modifications for different recipients, based on the same spam analysis" Что в переводе на русский язык звучит как: "не работает и работать не будет, т.к. amavisd-new не позволяет внешним программам править почтовые сообщения".
Так же при использовании SA с amavisd-new не имеет смысла использовать опцию 'required_hits', т.к. опции sa_*_level_deflt имеют более высокий приоритет. При использовании amavisd-new совместно в SA мы можем встретить еще одну интересную фичу: tag и tag2 проверки производятся только для локальных, а kill для всех доменов. Поэтому, если мы хотим, что бы amavisd-new добавлял всем почтовым сообщениям заголовки X-Spam-Status и X-Spam-Level, то мы должны присвоить sa_tag_level_deflt, например, -1 и сделать всю проверяемую почту внутренней - присвоить @local_domains_acl = ( "." ) в конфигурационном файле amavisd-new. IMHO делением почты на локальную и внешнюю должен заниматься наш MTA.
Во всем остальном следуем небольшому и очень просто написанному man'у (по сравнению с документацией на amavisd-new например) 'Mail::SpamAssassin::Conf'. Этот мануал состоит из следующих секций:
  • 'TAGS' - описывает макросы, которые мы можем использовать при генерации отчетов (не забываем, что опция add_header недоступна).
  • 'USER PREFERENCES' - содержит настройки, которые могут быть помещены как в site-wide ("local.cf") и пользовательские конфигурационные файлы.
  • 'PRIVILEGED SETTINGS' - содержит настройки, которые доступны только пользователям, запускающим SA из procmailrc или forward файлов, или в конфигурациях в "/etc/mail/spamassassin".
  • 'ADMINISTRATOR SETTINGS' - содержит опции, которые могут находиться только в конфигурационных файлах в каталоге "/etc/mail/spamassassin". Эти установки не могут быть использованы в "user_prefs" файлах, даже если установлена опция 'allow_user_rules'.
При фильтрации спама удобно использовать такие возможности SA, как проверку хостов отправителей в RBL или DNSBL, что одно и тоже, системах Pyzor, Razor, DCC. О DNSBL достаточно просто написано в статье Алексея Тутубалина "RBL: вред или польза?". Описание Pyzor, Razor, DCC можно найти в другой его статье c названием "Распределенные методы обнаружения спама - часть 2". Эти публикации можно найти, используя поисковые сервера или заглянуть на www.spamtest.ru в раздел 'статьи'.

Интеграция с Pyzor.

Наиболее проста установка Pyzor - 'emerge pyzor'. В конфигурационном файле SA присваиваем опции use_pyzor значение '1'. Можно присвоить pyzor_options значение '-d' для получения отладочной информации на STDERR. При первом запуске pyzor создаст папку '.pyzor' в домашнем каталоге учетной записи, от которой мы производили запуск (если вы запускаете SA из amavisd-new, то используется значение переменной $helpers_home) Затем программа получает адрес сервера, который записывается в '.pyzor/servers'. Все эти действия выполняются автоматически. Отправка отчетов о полученном спаме производится с помощью 'pyzor report'. /ЗЫ к сожалению, работа pyzor не впечатляет./

Интеграция с Razor.

Для установки Razor мы должны дать команду 'emerge razor' и добавить в конфигурационный файл SA опцию 'use_razor2 1'. Не нужно беспокоиться о патчах, gentoo о них позаботился. Теперь мы можем использовать razor2. После первого запуска наша система сама создаст каталог '.razor' и поместит туда необходимые файлы, так же, как это делал pyzor (естественно список файлов у razor свой). Если мы хотим, чтобы SA мог не только проверять почту в razor, но и отсылать отчеты о выявленном спаме, мы должны зарегистрировать razor-agent. В таком случае порядок действий таков:
  • выполняем razor-client - создаем необходимые символические ссылки для корректной работы
  • выполняем razor-admin -create - создаем конфигурационные файлы в папке .razor, находящейся в домашнем каталоге учетной записи, от имени которой производился запуск.
  • выполняем razor-admin -register или razor-admin -register -user=foo@bar.com или razor-admin -register -user=foo -pass=s1kr3t - создаем учетную запись пользователя, от имени которого будем отсылать отчеты.
  • выполняем razor-admin -discover - обновляем список razor серверов
  • копируем вновь созданную папку '.razor' в домашний каталог amavisd-new
  • выполняем на chown, переопределяя владельца каталога на учетную запись, под которой работает amavisd-new
  • редактируем, при необходимости, .razor/razor-agent.conf
Для того чтобы отправить отчет о полученном спаме в Razor мы должны запустить SA с ключом -r от учетной записи amavisd-new: 'spamassassin -r < spam-message'. Для того, чтобы сообщить о ложном срабатывании Razor мы должны запустить SA с ключом -k от учетной записи amavisd-new: 'spamassassin -k < spam-message'.

Интеграция с Distributed Checksum Clearinghouses.

Установка DCC от установки Razor и Pyzor принципиально ничем не отличается. После того как gentoo откомпилировал и проинсталлировал пакет, мы получаем рабочую dcc систему. То есть мы уже можем указать в конфигурационном файле SA 'use_dcc 1' приступить к фильтрации почты. Если необходимо, то после установки мы можем произвести дополнительную настройку DCC. Сама система состоит из следующих модулей:
  • dccproc (DCC Procmail Interface) - интерфейс, вызываемый из командной строки. Этот интерфейс используется SA, если не найден сокет dccifd.
  • dccm (DCC Milter Interface) - интерфейс, являющийся демоном, обеспечивающим взаимодействие DCC с sendmail. Запуск демона рекомендуется производить, используя скрипт 'start-dccm'.
  • dccifd (DCC Program Interface) - интерфейс, используемый по умолчанию SA и MTA отличными от sendmail. Представляет собой демон, прослушивающий unix сокет. Запуск демона рекомендуется производить, используя скрипт 'start-dccifd'.
  • cdcc (Control DCC) - утилита, необходимая для управления специальным файлом, отображаемом в память (memory mapped), доступным локальным клиентам DCC. В этом файле хранится такая информация как список хостов, номера портов, идентификационные номера, пароли локальных клиентов, допустимое время ожидания и т.д. cdcc так же используется для управления серверами, позволяя остановить работу, перезагрузить список DCC ID, управлять трассировкой и т.п.
  • dccd (DCC Daemon) - демон DCC. В требованиях к ресурсам говорится, что на середину 2003 года объем трафика между парой серверов составлял в среднем 40Mb/день. Для сервера рекомендуется выделить машину с ОЗУ не менее 512 Mb и жестким диском из расчета 100Mb на 100.000 почтовых сообщений/день с записями, хранящимися в БД 7 дней.
  • dbclean - утилита, позволяющая добавлять, пересоздавать, удалять и очищать устаревшие записи в БД DCC.
  • dblist - утилита, позволяющая как просматривать, так и осуществлять проверки содержимого БД DCC.
Принцип работы интерфейсов DCC состоит в отправке отчетов с контрольными суммами почтовых сообщений и получении ответа, содержащего количество аналогичных отчетов, отправленных другими системами. Если контрольные суммы находятся в белом списке (файл whiteclnt), то отчет DCC серверу не отправляется. В этом случае интерфейс не получает информацию о количестве получателей аналогичного сообщения и X-DCC заголовки не добавляются. Список серверов, с которыми работает интерфейс, находится в файле, отображаемом в память (memory mapped), доступным всем локальным клиентам DCC. Управление содержимым этого файла производится с помощью cdcc. Основные параметры работы демонов находятся в файле dcc_conf.
DCC поддерживает серые списки Эвана Гарриса (Evan Harris). Серые списки основаны на трех параметрах: IP-адрес узла, пересылающего сообщение, адрес отправителя и адрес получателя. Если хотя бы один из этих параметров ранее не встречался, мы должны заблокировать сообщение и попросить передающую сторону отправить письмо повторно. Вероятность того, что спамер будет производить повторную рассылку спама с одного и того же источника, близка к нулю, а если и будет, то этот источник к тому времени, скорее всего, попадет в черный список. Работа серых списков реализована на интерфейсе Sendmail Milter, так как мы в процессе получения письма должны проанализировать соответствующие параметры и выдать свой ответ MTA, инициировавшему соединение. Ведь bounce сообщение нас не устроит, не так ли? При необходимости нетрудно добавить аналогичную проверку в exim acl_smtp_data.
/ЗЫ если спамер воспользуется открытым релеем, который будет пытаться доставить нам спам, серый список нас не спасет. IMHO использование серых списков ничуть не опаснее использования других технологий, фильтрующих почтовые сообщения. Все системы фильтрации нужно использовать аккуратно, исходя из политик безопасности (или из их отсутствия) той организации, в которой устанавливается сервер. И тогда все будет ok... /

Создание почтовой системы на базе exim, spamassassin, amavisd-new и postgresql.

Основные положения.

Типы почтовых сообщений, которые будет обрабатывать наша система:
Исходящая почта.
Почта от источника, находящегося в relay_from_hosts принимается без аутентификации. IP адрес отправителя обязан принадлежать частному диапазону адресов. Адрес получателя обязан принадлежать виртуальному домену. При невыполнении условия с адресом получателя необходимо сделать запись в лог и переслать письмо тому, кто может решить - это ошибка или хак.
Почта с адресом источника, находящимся в виртуальном домене принимается только после аутентификации и проверки, определяющей, имеет ли право обладатель учетной записи использовать предоставленный адрес отправителя (то есть предотвращение ситуации, когда пользователь vasja@test.com может отправить после аутентификации письмо от petja@test.com).
Почта с адресом источника, принадлежащим специальному почтовому ящику, принимается после аутентификации и соответствующей проверки учетной записи и передается через соответствующий релей.
Входящая почта.
Почта с адресом получателя, находящимся в виртуальном домене принимается без аутентификации от отправителей, не входящих в домены нашей почтовой системы.
Почта с адресом получателя, принадлежащим специальному почтовому ящику, принимается только от серверов из списка relay_to_hosts.
Почта с адресом получателя, находящимся в виртуальном или специальном домене фильтруется на наличие спама и вирусов.
Транзитная почта.
Почта с адресом источника, находящимся в домене, для которого мы являемся релеем, принимается только после аутентификации релея, и проверки, что учетной записи релея принадлежит домен, из которого отправляется письмо.
Почта с адресом получателя, находящимся в домене, для которого мы являемся релеем, принимается без аутентификации от отправителей, не входящих в домены нашей почтовой системы.
Почта с адресом отправителя/получателя из домена, находящегося в белом списке.
Для почты, принадлежащей доменам белого списка, проверки на спам/rbl/вирусы не производятся.
Почта с адресом отправителя/получателя из домена, находящегося в черном списке.
Почта с адресом источника или получателя, находящимся в заблокированном домене, не обрабатывается.
Bounce сообщения.
Почта с пустым адресом источника принимается, только если адрес получателя принадлежит нашим доменам или системе, аутентифицированной как релей.
Итого мы получили 5 видов доменов:
  • Виртуальные домены (virtual_domains) - это домены наших пользователей.
  • Домены релеев (relay_to_domains) - домены, для которых наша система является прокси.
  • Домены белого списка (white_domains) - домены, которые не проверяются.
  • Домены черного списка (blocked_domains) - домены, с которыми мы взаимодействовать не хотим.
  • Домены специальных почтовых записей - домены, которые используются при работе со специальными почтовыми записями.
/ЗЫ в моем контексте специальная почтовая запись, это почтовый ящик, созданный на совершенно другом сервере, не имеющем к нам никакого отношения, например на mail.ru. Мы можем создать идентичную почтовую запись с помощью DBMail у себя и принимать и отсылать почту, указав наш почтовый сервер, который в данном случае будет являться релеем. Что это нам дает? Возможность использовать собственную систему фильтрации, вести архив почтовой переписки (входящие и исходящие сообщения), использовать алиасы для внешнего почтового ящика, возможность закрыть на фаерволе почтовые порты, повысить контроль над ситуацией./

База данных.

Основой для базы данных был выбран postgresql. Наличие представлений, триггеров, наследования imho упрощают создание единой базы данных для таких продуктов как DBMail+exim+amavisd-new и позволяют заложить часть логики и проверок в БД, что на момент написания статьи является недоступным для Mysql. /ЗЫ в 5ой версии mysql обещают триггера сделать. записная книжка. Только не надо пытаться доказывать, что mysql лучше postgresql и что есть и репликация и производительность выше. Это все равно, что сравнивать фуру и мотоцикл. Продукт выбирается в зависимости от цели./
За основу БД взята структура DBMail. Ниже приведено описание добавленных и измененных таблиц.
Изменена таблица 'aliases'. Добавлена проверка поля 'aliases' на присутствие допустимых символов, входящих в почтовый адрес. Добавлена проверка поля 'deliver_to' на возможность содержать только целое значение, то есть ссылку на почтовый ящик DBMail. Эта проверка блокирует возможность указывать вместо почтового ящика DBMail любой почтовый адрес (то есть создавать с помощью dbmail-adduser forwarding aliases). Такая блокировка позволяет устранить неоднозначность и упростить процесс нахождения соответствия между конечным адресом получателя и политикой фильтрации amavisd-new. При доставке сообщения получается следующая схема - получаем почту и копируем/перенаправляем при необходимости, для определенных получателей, используя таблицу 'aliases_exim', затем, для каждого реально существующего получателя виртуального домена с адресом в таблице 'aliases', фильтруем почтовое сообщение, используя индивидуальные правила, и, наконец, письмо попадает к получателю.
Добавлена таблица 'aliases_exim'. Cодержит список адресов, для которых необходимо скопировать/перенаправить почту. Используется exim'ом. Содержит проверку поля 'source' на присутствие допустимых символов, входящих в почтовый адрес и символ '%', обеспечивающий работу шаблонов. Также поле 'destination' является внешним ключом для поля 'alias' таблицы 'aliases'. В поле source мы можем вписать адрес со стандартными sql символами подстановки. Например, запись '%@test.com' говорит системе присылать всю почту домена 'test.com' на определенный адрес. Необходимо учитывать, что для возможности копировать почту с адреса 'a@test.com' на адрес 'b@test.com' мы должны добавить запись, где поле 'source' будет равно 'a@test.com', а 'destination' установлено в NULL. То есть, если мы создадим запись с полем 'source' равным '%@test.com' и полем 'destination' равным 'кто-то@где-то', то вся почта будет перенаправлена на 'кто-то@где-то' и никто из домена 'test.com' своей почты не получит. Для того чтобы почта не перенаправлялась, а копировалась, нам необходимо будет добавить еще одну запись, где полю 'source' мы также должны будем присвоить значение '%@test.com' ,а полю 'destination' - значение NULL. Реализация этого механизма явилась следствием работы драйвера redirect в exim.
Добавлена таблица 'domains'. Она содержит список виртуальных доменов, домены белых и черных списков. Поле 'name' содержит имя домена. Для задания типа достаточно присвоить полю 'types' значения 'V', 'W' или 'B'. Поле 'policy' является внешним ключом идентификатора политик фильтрации 'id' таблицы 'policy'. Поле 'priority' содержит положительное целое, которое указывает на приоритет политик (дело в том, что мы можем присваивать политики по умолчанию доменам, поддоменам с указанием приоритета и amavisd-new получит политику с наименьшим значением поля 'priority'). В этой таблице содержатся проверки поля 'type' на разрешенные типы доменов, поля 'name' на допустимые символы в имени домена, поля 'priority' на положительное целое значение. Полю 'id' присвоена последовательность 'alias_idnr_seq' таблицы 'aliases' - это позволяет получить уникальные непересекающиеся значения идентификаторов при объединении таблицы 'domains' и 'aliases'.
Добавлена таблица 'domains_relay'. Эта таблица является потомком таблицы 'domains' и содержит список доменов, для которых мы или кто-то для нас релей. Если поле 'relay' имеет значение NULL, то эта запись определяет домен, для которого мы являемся релеем, в противном случае запись определяет кого-то, кто является релеем для нашего домена. Если полю 'name' присвоено значение '.', то эта запись говорит о том, что всю почту необходимо отправлять через соответствующий релей. Соответственно поля username и password необходимы для smtp аутентификации (rfc2554). В этой таблице производятся проверки поля 'type' на корректный тип домена (возможен только тип 'R') и поля 'relay' на наличие допустимых символов в имени домена.
Добавлена таблица domains_special, необходимая для указания сервера, через который мы должны отсылать почту из специальных почтовых ящиков. Например, у пользователя есть учетная запись 'user@mail.ru' и мы должны отсылать почту через 'smtp.mail.ru', в таком случае в 'name' мы заносим имя домена 'mail.ru',а 'relay' присваиваем значение 'smtp.mail.ru'. Теперь для всех пользователей, имеющих почтовые ящики с доменом 'mail.ru', будет использоваться сервер 'smtp.mail.ru'. В таблице присутствуют проверки поля 'type' - значение должно быть 'S' и поля 'relay' на наличие допустимых символов в имени домена.
Изменена таблица 'users'. Добавлены поля 'policy' и 'priority' аналогичные полям таблицы 'domains'. Добавлено поле 'blocked', значению которого, при необходимости, можно присвоить 'истину' и владелец учетной записи не сможет отправить почтовые сообщения. В случае блокировки сервер сообщит, что учетная запись заблокирована. Получение почты не блокируется. Добавлено поле 'backup'. Если мы присвоим ему значение 'истина', то письмо, отправленное от любого адреса этой учетной записи, будет скопировано в IMAP папку с именем в макросе ARCHIVE_MAILBOX_NAME этой же учетной записи. /ЗЫ. Когда это может пригодиться? Тогда, когда желательно что бы архив всей почтовой переписки (включая отправленные письма) хранился в почтовом ящике. Пользователь с таким ящиком не зависим от локального почтового клиента, и может получить доступ к архиву почты из любого места, откуда можно получить доступ к самому почтовому серверу. К тому же удобно дать доступ к такому ящику нескольким людям (например, для почтовых ящиков support, webmasters, etc.). Они всегда будут в курсе переписки друг друга. Помните, что для каждого почтового ящика DBMail мы можем использовать права доступа и делать ящики доступными только для чтения./ В таблицу добавлены проверки полей 'policy' и 'priority' идентичные проверкам этих полей в таблице 'domains'.
Добавлена таблица 'wblist'. Эта таблица содержит белые и черные списки amavisd-new. Поле 'id' является внешним ключом на поле 'user_idnr' таблицы 'users'. Поле 'address' содержит адрес отправителя в формате, описанном в файле README.lookups (документация amavisd-new), и проверяется на соответствующие символы. Поле 'type' - булева переменная: истина - белый список, ложь - черный список.
Добавлена таблица 'policy'. Структура аналогична родной таблице 'policy' для amavisd-new. В эту таблицу сразу же добавляются стандартные правила фильтрации.
Таблицы aliases, auto_notifications, auto_replies, config, mailboxes, messageblks оставлены без изменений. Таблица messages также оставлена без изменений, хотя туда можно при необходимости добавить триггер, сохраняющий размер почтового сообщения и дату получения в отдельную таблицу. Этот триггер может обеспечить нас детальной информацией о суммарном объеме полученной почты для определенного пользователя за выбранный промежуток времени (и ненужно будет запускать для этого ресурсоемкие парсеры логов).
Созданы три представления. 'special_users' позволяет получить список всех специальных учетных записей, то есть, получаем все учетные записи для почтовых адресов, не принадлежащих нашим доменам. Представление 'users_policy' производит для каждого почтового адреса сопоставление политики фильтрации. Представление 'users_wblist' производит для каждого почтового адреса сопоставление белого и черного списков. Обратите внимание, что представление 'users_policy' возвращает политики для пользователей и доменов, а 'users_wblist' возвращает списки только для пользователей.
Так же добавил функции 'get_auth_data' и 'create_notexist_mailbox'. Функция 'get_auth_data' возвращает логин, пароль или пустое значение в зависимости от адреса и домена отправителя. Логин и пароль необходимы для SMTP аутентификации нашей почтовой системы. /ЗЫ. Exim поддерживает CRAM, LOGIN, PLAIN аутентификацию и умеет работать с TLS./ Функция 'create_notexist_mailbox' создает почтовый ящик, если он еще не создан, для определенной учетной записи. Если третий параметр, переданный функции, 'истина', то ящик создается только для учетной записи с установленным флагом 'backup'.

Настройка exim.

Исхожу из предположения, что вы знаете, что такое exim, умеем им пользоваться, а так же умеем пользоваться документацией, которая хоть, и написана на английском языке, зато содержит очень подробное объяснение особенностей этого замечательного почтового сервера. Если все рассматриваемые продукты выстроить здесь в порядке улучшения документированности, то imho получится такая цепочка: amavisd-new - DBMail - spamassassin - postgresql - exim. Большой респект людям, написавшим столь подробную документацию. /ЗЫ. Почему был выбран exim, а не qmail, не postfix и не sendmail? Qmail, в моем представлении, это не единых программный продукт, а огромное количество патчей, естественно, если я захочу все те вкусности, что мне необходимы. Postfix конечно хорош, прост в установке и настройке, патчить почти не надо. но, слишком уж он прост - нужно что-нибудь более функциональное, пускай и посложней и пообъемней. Ну а sendmail - это sendmail. Это не почтовый сервер, а целая идеология. Из него можно сделать что угодно и для чего угодно, но мне не надо. Мне был нужен почтовый сервер, а не идеология. И вообще, микроскопом гвозди забивать не люблю. только если заставят. И, скажу вам, плохо перевариваю людей, которые заявляют, что знают что-то от и до, а сами только проинсталлировать могут, да немного конфигурацию подправить. Ну вот. Опять на философию потянуло. Дети мифа о "zero administration" от корпорации Microsoft. Нужно только поправку сделать: не "zero administration", а "zero administration in default configuration". А как попросишь такого ребенка лет 30-ти с гаком что-нибудь нестандартное сделать, так он или в кусты с фразой "На провокационные вопросы не отвечаю!" или начинает рассказывать о необходимости закупки еще десятка продуктов, возможности которых будут использоваться максимум в пол силы. Позор. /
Описание списков доступа.
В acl_check_auth проверяем тип аутентификации. Разрешаем все типы аутентификации при использовании TLS и только CRAM аутентификации без TLS.
В acl_check_rcpt производим следующие проверки:
  • запрещаем почту с нестандартными local_parts
  • принимаем письма для postmaster виртуальных доменов и доменов, для которых мы релей.
  • проверяем адрес отправителя на доступность
  • запрещаем почту, имеющую отношение к заблокированным доменам и выдаем соответствующее предупреждение
  • проверяем отправителя в различных RBL и, в случае положительного результата, добавляем в письмо заголовок "X-BlackList-Warning"
  • принимаем всю почту извне для наших пользователей
  • принимаем почту для машин из списка 'relay_from_hosts'
  • блокируем отправку сообщения, если учетная запись заблокирована и выдаем соответствующее предупреждение
  • принимаем почту, если пользователь с текущей учетной записью может пользоваться адресом отправителя, указанном в отправляемом сообщении. Например, есть пользователь 'a@test.com' и для его почтового ящика создано два адреса 'a@test.com' и 'b@test.com'. Если адрес отправителя письма для пользователя 'a@test.com' будет 'a@test.com' или 'b@test.com', то сервер спокойно отправит сообщение, если же адрес отправителя будет, например 'c@test.com', то сервер выдаст ошибку.
  • запрещаем почту, если произошла ошибка аутентификации, и выдаем соответствующее предупреждение
  • запрещаем все другие почтовые сообщения, сообщая, что мы не открытый релей и для отправки требуется аутентификация.
В acl_check_vrfy_expn_etrn разрешаем использование VRFY, EXPN и ETRN только для хостов из списка 'relay_from_hosts'.
В acl_check_data производим проверки:
  • добавляем в сообщение IP системы, которая передала почту релею, у которого мы ее получили /ЗЫ звучит страшно, но на самом деле это не так. Если мы забираем почту с помощью какого либо релея, то проверять его IP в RBL не имеет смысла. Нас интересуют IP тех систем, которые к нему подключались, так как именно их IP следует проверять. Эта строчка добавляет заголовок с интересующим нас IP исключительно в целях отладки./
  • проверяем полученный IP для сообщений, доставленных через релей в RBL и, в случае положительного результата, добавляем в письмо заголовок "X-BlackList-Warning"
  • запрещаем сообщения, если их размер превышает MESSAGE_SIZE_LIMIT /ЗЫ не радует перспектива принимать огромные письма, хоть мы и можем. 500Mb письмо, по крайней мере, наше творение должно скушать и не подавиться. при наличии определенных ресурсов, конечно же./
  • проверяем все заголовки на корректность
  • запрещаем bounce сообщение с несколькими адресами получателей
  • разрешаем прием всех сообщений
Описание роутеров.
Роутера для доставки сообщений в localdomain или локальным пользователям не существует. Вся почта для локальных адресов сразу же переадресуется с помощью записей в файле '/etc/mail/aliases' и таблице 'aliases_exim'.
Роутер system_aliases обрабатывает файл '/etc/mail/aliases'. Почта обрабатывается только в том случае, если отправка производилась только с помощью протокола 'local' (этот протокол используется при отправке консольной программой sendmail) и из доменов 'local_domains', 'qualify_domain', либо вообще без домена.Роутер debug_route закомментирован, служит для всевозможных отладок и принимает всю почту.
Роутер virtual_aliases обрабатывает алиасы из таблицы 'aliases-exim'.
Роутер amavis обрабатывает всю входящую почту (на исходящую его смысла ставить нет imho, т.к. в случае проблем мы и так получим сообщение для postmaster или abuse). Не обрабатывает bounce сообщения и сообщения, отосланные с использованием протокола local.
Роутер dbmail_backup_route копирует всю почту в IMAP папку 'SENT' отправителя, являющегося пользователем виртуального домена, если для учетной записи установлен флаг 'backup'. /ЗЫ. Бедные люди, пишущие "продвинутые" фильтры и создающие умопомрачительные правила для простого копирования почты в exim... "Иногда в руки не очень умелого колдуна попадает магический инструмент огромной силы. И тогда начинается такое, что не привидится и самому изобретательному идиоту". (с) Николай Басов./
Роутер dbmail_route отвечает за доставку входящей почты пользователям виртуальных доменов.
Роутер spdbmail_route отвечает за доставку входящей почты пользователям специальных почтовых ящиков.
Роутер relay_route обеспечивает доставку почты серверам, для которых мы является релеем.
Роутер spmail_route отсылает сообщения с адресом отправителя, принадлежащим специальному почтовому ящику.
Роутер smart_route отсылает всю исходящую почту через релей, если в таблице domains_relay есть запись с полем name, содержащим значение '.'
Роутер dnslookup осуществляет стандартную доставку почты.
Роутер default_route всегда возвращает ошибку с сообщением 'Unknown user'.
Описание транспортов.
Транспорт fake_transport отправляет все сообщения в /dev/null.
Транспорт amavis служит для передачи сообщений amavisd-new для фильтрации спама и проверки на вирусы.
Транспорт remote_smtp служит для отправки исходящей и транзитной почты.
Транспорты address_pipe и address_file используются при работе роутера system_aliases.
Транспорт dbmail_transport используется для доставки почты в ящик dbmail.
Транспорт dbmail_transport_backup используется для доставки почты в IMAP папку 'SENT' почтового ящика dbmail. Если IMAP папка не создана, то проверка CHECK_FOR_SENTBOX в роутере dbmail_backup_route создаст ее. Необходимо учитывать, что сам dbmail не создает несуществующие папки автоматически, а завершается ошибкой при попытке записать сообщение в 0-ой ящик пользователя из-за нарушения целостности БД. Проверка на целостность производится при помощи внешнего ключа 'mailbox_idnr' в таблице 'messages'.
Описание конфигурации повторной отправки сообщений.
Правила повторной отправки сообщений оставил без изменений. В любом случае, использование чужой конфигурации из этого раздела, вряд ли кому-то пригодится, так как тонкую настройку этих параметров необходимо производить в индивидуальном порядке.
Описание конфигурации перезаписи адресов.
Вся конфигурация состоит из одной единственной записи, которая отвечает за домен в адресе автоматически создаваемых сообщений от 'Mailer-Daemon'. Позволяет избежать ситуации, когда, разместив у себя несколько почтовых доменов, в ответ на сообщение для одного из наших доменов 'кто-то@domain_1.com', сервер отправляет bounce сообщение с адресом основного нашего домена 'Mailer-Daemon@$qualify_domain'. Проверка производится по адресу только первого получателя почтового сообщения. То есть, если адрес первого получателя не принадлежит ни одному из наших доменов, то при отсылке bounce сообщений будет оставлен стандартный адрес 'Mailer-Daemon'.
Описание механизмов аутентификации.
Для аутентификации пользователей используется три типа проверок: cram md5, plain и login. При аутентификация cram макрос AUTH_CRAM_SERVER возвращает пароль для имени пользователя. Exim производит сравнение паролей полученных от пользователя и от AUTH_CRAM_SERVER, если они совпали то аутентификация успешна. При использование методов plain и login, макросы AUTH_PLAIN_SERVER и AUTH_LOGIN_SERVER сами сравнивают пароль пользователя и пароль в БД. Если макрос AUTH_PLAIN_SERVER/AUTH_LOGIN_SERVER возвращают положительный ответ, то аутентификация успешна. В процессе аутентификации имя пользователя присваивается переменной $authenticated_id с помощью 'server_set_id = $1'.
Если сервер сам должен аутентифицироваться при подключении к другой почтовой системе, то используются макросы AUTH_CLIENT_LOGIN и AUTH_CLIENT_PASSWORD возвращающие логин и пароль в зависимости от адреса и домена отправителя. Поиск учетной записи производится в такой последовательности:
  • поиск для доменов релеев
  • поиск для виртуальных доменов релея по умолчанию ('.')
  • поиск для специальных почтовых ящиков
  • Если ни одна проверок не завершилась удачно, то возвращается логин и пароль для домена '.' (запись с точкой в имени домена говорит, что сервер должен отсылать всю почту используя релей по умолчанию) или, если запись с доменом '.' не найдена, то возвращается пустое значение.
Макросы.
Создавая конфигурацию сервера, пришлось довольно часто создавать запросы к БД, использовать псевдоязык exim'a для проверок различных условий и получения значений, применять регулярные выражения. Чтобы не запутаться в зарослях кода были использованы макросы, некоторые из которых выглядят немного объемными и немного непонятными. Сейчас мы с ними разберемся, и вы увидите, что они на самом деле довольно простые и несложные.
Макросы RELAYDOMAINS, VIRTUALDOMAINS, BLOCKEDDOMAINS, WHITEDOMAINS делают запрос в БД и возвращают списки доменов соответствующих типов.
Макрос SPECIALMAIL возвращает список специальных почтовых ящиков, используя представление 'special_users'.
Макрос CHECK_AUTH_SNDR_BLOCKED проверяет, заблокирован ли пользователь виртуального домена, используя уникальный логин, находящийся в переменной $authenticated_id.
Макрос CHECK_AUTH_SNDR проверяет, имеет ли право учетная запись использовать адрес отправителя в передаваемом почтовом сообщении. Если учетная запись принадлежит релею, то разрешена почта с адресами отправителя только из домена релея или с пустым адресом (bounce сообщение). Если учетная запись пользователя ящика dbmail, то разрешено в качестве адреса отправителя использовать все адреса, указанные для этого ящика в таблице 'aliases'.
Макрос GET_ALIASES получает список алиасов для адреса получателя из таблицы 'aliases_exim'. Если в таблице существует запись вида 'адрес получателя',NULL , то в список алиасов добавляется адрес самого получателя и у нас получается не перенаправление, копирование почты.
Макрос CHECK_RCPT_SPADDR проверяет наличие адреса получателя в списке специальных почтовых ящиков.
Макрос CHECK_ SNDR_SPADDR проверяет наличие адреса отправителя в списке специальных почтовых ящиков.
Макрос GET_SPMAIL_ROUTE возвращает адрес сервера, через который необходимо отсылать почту с адресом отправителя, принадлежащим специальному почтовому ящику. Если значение не найдено, то в качестве адреса сервера используется домен адреса получателя.
Макрос GET_RELAY_ROUTE возвращает адрес сервера, через который необходимо отсылать почту с адресом получателя, принадлежащим домену, для которого мы являемся релеем. Если значение не найдено, то в качестве адреса сервера используется домен адреса получателя.
Макрос CHECK_SMART_ROUTE возвращает адрес сервера, через который необходимо отсылать всю почту (запись '.').
Макрос CHECK_FOR_SENTBOX проверяет наличие и при необходимости создает IMAP папку для адреса отправителя, который должен быть пользователем dbmail и у которого должен присутствовать backup флаг.
Макросы AUTH_PLAIN_SERVER и AUTH_LOGIN_SERVER проверяют пароль пользователя на совпадение с паролем в БД.
Макрос AUTH_CRAM_SERVER возвращает пароль пользователя dbmail.
Макросы AUTH_CLIENT_LOGIN и AUTH_CLIENT_PASSWORD возвращают логин и пароль, необходимые для аутентификации нашего сервера при отсылке исходящей/транзитной почты.
Макрос MTA_FINGERPRINT_001 является отпечатком нашей системы в заголовках 'Received', таким образом, за этим заголовком должен следовать заголовок почтовой системы с IP адресом сервера, от которого пришло сообщение. В этой конфигурации вы можете видеть отпечаток fetchmail - именно его я использую для сбора почты в специальные почтовые ящики. Сама конфигурация fetchmail генерируется из БД по шаблону и для нас никакого интереса не представляет (самая обычная конфигурация).
Макрос SOURCE_RELAY_IP получает IP адрес интересующей нас системы, используя MTA_FINGERPRINT_001.
Макрос SOURCE_RELAY_IP_REV получает IP адрес, в форме, подходящей для поиска в обратных зонах RBL, используя MTA_FINGERPRINT_001.
Мы можем создать и использовать несколько макросов MTA_FINGERPRINT, используя логическое 'или' в макросах SOURCE_RELAY_IP и SOURCE_RELAY_IP_REV.
Макрос SOURCE_RELAY_CHECK_IN_RBL определяет необходимость проверки системы в RBL. Проверка не производится, если адрес принадлежит диапазонам 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, если это bounce сообщение, если сообщение уже обработано amavisd-new.

Установка и настройка почтовой системы

Ниже описаны действия, которые необходимо выполнить для установки этой почтовой системы. Устанавливаем все необходимые пакеты командой emerge. В gentoo мы можем так установить exim, amavisd-new и postgresql. Установка spamassassin должна запуститься автоматически при установке amavisd-new. Скачиваем и распаковываем dbmail. Сразу же исправляем пути в начале файла build.sh. /ЗЫ как-то не красиво в ответах на вопросы набивать пути руками./ Так же ищем в файле build.sh строку 'install-dbmail.sh $bindir' и добавляем в начало './', иначе при инсталляции система полезет искать install-dbmail.sh в каталогах, прописанных в переменной окружения PATH, и файла не найдет. Запускаем build.sh и помним, что на все вопросы, где требуется ответить "да"/"нет" мы, в случае положительного ответа должны ввести 'y' в нижнем регистре, все остальные символы, включая 'Y', считаются отрицательным ответом. Копируем dbmail.conf в каталог etc. После того как мы проинсталлировали все пакеты, правим конфигурации и создаем БД. За основу берем родную базу dbmail:

createdb -E koi8-r -U postgres mail
psql -U postgres mail
        ALTER USER dbmail WITH PASSWORD 'secret';
psql -U dbmail mail < create_tables.pgsql
createlang -U postgres plpgsql mail
psql -U dbmail mail < dbmail_addon.pgsql
После создания БД мы должны добавить запись в таблицу domains с именем нашего домена и типом 'V' (virtual domain), теперь мы можем добавлять пользователей с помощью dbmail-adduser или любой другой программы, работающей с БД dbmail.
/ЗЫ если мы установим, настроим и запустим наш сервер, то увидим, что пользователи с почтовыми клиентами Оutlook версий ниже 2000, и версии Outlook 2003(11.5608.5703) и подобными продуктами (просьба не путать с Outlook Express) не могут отослать почту через наш сервер. Такая ситуация возникает вследствие того, что при незашифрованном почтовом сеансе наш сервер запрещает использовать передачу логина и пароля пользователя с механизмами аутентификации слабее CRAM-MD5, а при зашифрованном сеансе (использующем TLS) Outlook просто "висит". Outlook "зависает" потому, что у разработчиков этого популярного почтового клиента, по всей видимости, возникали трудности с прочтением и осознанием rfc3207 "SMTP Service Extension for Secure SMTP over Transport Layer Security". Такие клиенты умеют работать используя только устаревший протокол ssmtp (SMTP over SSL). Обойти эту проблему мы можем, запустив еще один демон exim'a, используя команду следующего вида: "exim -bd -oX '0.0.0.0.465' -tls-on-connect". В этом случае мы принудительно заставляем прослушивать exim порт 465 на всех интерфейсах и использовать TLS вне зависимости от возможностей почтового клиента.
.И напоследок хочется сказать, что не стоит забывать такой старый лозунг, как 'Твори! Выдумывай! Пробуй!'. Именно этому принципу, наверное, и следовал отличный ученый и замечательный человек Альберт Эйнштейн, создавая теорию атомной бомбы./
Замечания и исправления приветствуются. Пишите ezh@ezh.msk.ru.



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру