|
Bog BOS: exim - почтовый сервер (MTA) для борьбы со спамом
|
Последнее изменение файла: 2016.02.26
Скопировано с www.bog.pp.ru: 2024.12.03
Bog BOS: exim - почтовый сервер (MTA) для борьбы со спамом
Для чтения статьи рекомендуется предварительное знакомство с
exim является одним из немногих открытых (лицензия GNU) и активно
развиваемых MTA (версия 4.71 от 23 ноября 2009, был пропуск в 2008).
Основное внимание при разработке
уделялось борьбе со спамерами. Устанавливается и настраивается
значительно проще, чем sendmail.
Недостатки: отсутствие конвертации 7-bit/8-bit;
отсутствие DSN;
неадекватная обработка "double error";
адреса только в формате RFC2822 (адресов в формате UUCP нет, но UUCP транспорт
прикрутить возможно, поддержка batched SMTP есть);
внешний транспорт - только SMTP (локально в файл или pipe, LMTP);
компьютер д.б. постоянно подключён к Интернет;
очередь нельзя использовать для хранения и извлечения сообщений в стиле ETRN.
Лучше всего подходит в качестве "привратника",
фильтрующего входную почту и направляющего остатки более гибко
настраиваемому sendmail.
Разработка ведется под Solaris, так что настройка расположения файлов
отличается от той, что принята в Linux (/var/mail вместо /var/spool/mail
и т.д.).
Слова "отправитель" и "получатель" в тексте статьи означают адреса
отправителя и получателя соответственно, взятые из конверта письма,
и не имеют никакого отношения к полям заголовка письма. Слова
"письмо" и "сообщение" используются как синонимы.
Письмо может быть получено (при установлении соединения
может производиться аутентификация клиента):
- от удаленного хоста с помощью протокола SMTP; адреса отправителя и
получателя задаются с помощью команд MAIL и RCPT; после каждой команды
RCPT exim проверяет допустимость адреса с помощью ACL
(Access Control List) и, при необходимости,
выдает код ошибки SMTP; в конце сообщения exim проверяет допустимость
приема всего письма с помощью дополнительного ACL,
также выдавая код ошибки SMTP;
дополнительно до ответа об успешном приеме письма вызывается составляемая
администратором функция local_scan(),
которая позволяет производить дополнительные
проверки и модифицировать список получателей; кстати, адрес 127.0.0.1 также
считается удаленным хостом
- запуском команды exim -bm; адрес получателя задается в качестве
параметра (или берется из заголовка письма, если используется ключ -t);
письмо читается со стандартного ввода неинтерактивно
- запуском команды exim -bS; адрес получателя задается в начале
текста письма в виде команд RCPT, завершаемых командой DATA (batch SMTP);
письмо читается со стандартного ввода неинтерактивно
- запуском команды exim -bs; письмо читается со стандартного
ввода в интерактивном режиме с эмуляцией SMTP протокола; проверки ACL
производятся как для настоящего SMTP
Пользователь может установить свои дополнительный фильтры
(в файле ~/.forward, маршрутизатор redirect) в стандартном формате Sieve
(RFC 3028) или собственном формате exim.
Адрес отправителя в локальных режимах (не SMTP),
конструируется из имени пользователя и содержимого переменной
qualify_domain (команда MAIL в интерактивной эмуляции SMTP игнорируется).
Если переменная не установлена, то используется primary_hostname.
После успешного приема письма производится преобразование
адресов (address rewriting) для всех адресов в конверте и заголовках.
Если в процессе отправки порождаются новые адреса (например, с помощью механизма
aliasing), то их преобразование производится немедленно после порождения.
Затем в спуле (поддиректория input)
создаются 2 файла: первый содержит конверт, текущее состояние сообщения
и заголовки (имя состоит из идентификатора сообщения и суффикса "-H");
второй содержит тело письма (имя состоит из идентификатора сообщения и
суффикса "-D"). Для обработки аварийных ситуации (неожиданная перезагрузка)
используется файл, имя которого состоит из идентификатора сообщения и
суффикса "-J". В нормальных условиях он живет недолго.
Письмо будет храниться в спуле до тех пор, пока
оно не будет разослано всем получателям или отчет об ошибках не будет
отослан отправителю. Если письмо не может быть отправлено получателю, а
отчет об ошибке - отправителю, то оно помечается как "замороженное".
Администратор может его "оттаять" (или заморозить любое письмо вручную).
Имеются опции автоматического оттаивания через определённое время
и автоматического удаления.
При оттаивании делается последняя попытка отправить отчёт,
при неудаче он просто удаляется.
Администратор может спровоцировать ошибку доставки любого письма
в спуле вручную. Иногда, спул называют очередью, но exim не соблюдает
очередности обработки, так что это не очередь, а куча. При каждой попытке
отправки письма в спуле (в поддиректории msglog) добавляется запись
к журналу обработки сообщения (имя файла совпадает с идентификатором
сообщения). Файл удаляется при отправке письма всем получателям или
отправке всех отчетов об ошибках. Эту запись можно отключить
на перегруженном сервере.
Аналогичная запись делается в основном журнале.
При каждой попытке отправить письмо оно (один раз вне
зависимости от числа получателей) пропускается через системный фильтр
(см. filter.txt), который может добавить или заменить адреса получателей,
выбросить письмо, сгенерировать новое письмо, сгенерировать сообщение
об ошибке доставки. Первую попытку можно отличить по условию first_delivery.
При отправке письма каждый адрес получателя по очереди
предъявляется каждому сконфигурированному маршрутизатору,
если выполняются установленные
предварительные условия (preconditions),
пока один из них не признает адрес за "свой".
Получив адрес, маршрутизатор может:
принять его к обработке; после обработки адрес может быть помечен как
полностью обработанный или передан следующему маршрутизатору
- передать его для обработки определенному маршрутизатору (обязательно
ниже по списку)
- не признать адрес "своим"; имеется опция пропуска всех оставшихся
маршрутизаторов, что вызывает генерацию отчета об ошибке
- сгенерировать отчет об ошибке (помещается в спул как обычное письмо)
- отложить обработку адреса
- сообщить об ошибке в работе маршрутизатора (обработка адреса откладывается)
Маршрутизатор определяется типом и параметрами,
обрабатывает адрес, определяя какой транспорт
использовать при отправке или преобразуя адрес в один или несколько новых
адресов. Транспорт не вызывается немедленно, но адрес помещается в очередь.
Каждый порожденный адрес проверяется на дупликаты (прописные и строчные буквы
различаются) и
проходит всю процедуру с самого начала (включая немедленное преобразование
адресов в конверте и заголовке) или с указанного маршрутизатора.
Если ни один маршрутизатор не признал адрес, то посылается сообщение об ошибке.
Транспорт передает копию сообщения из спула в файл
или канал (локальный транспорт) или на удаленный хост по протоколу
SMTP (LMTP). Используемый транспорт и его параметры (например, имя хоста)
определяются маршрутизатором.
Транспорт может потребовать дополнительного преобразования
адресов и добавления или удаления полей заголовка в момент отправки.
Локальный транспорт выполняет доставку для каждого адреса по очереди,
порождая отдельный процесс с непривилегированными правами. Удаленный
транспорт доставляет сообщения по каждому адресу отдельно, порождая
процессы под uid exim, но выполняя их параллельно. При установлении
соединения exim может аутентифицировать себя как клиент.
Отправка письма по отдельному адресу может быть отложена
в маршрутизаторе (например, таймаут DNS) или транспорте, причем
как в удаленном (нет связи с удаленным хостом), так и в локальном
(переполнен почтовый ящик). Для повторной попытки отправить письмо
требуется запустить exim с ключом -q или запускать регулярную
обработку очереди с помощью cron, иначе письмо останется в очереди навечно.
Одновременно может быть запущено несколько обработчиков очереди.
Обработка очереди происходит последовательно
письмо за письмом. В конфигурационном файле должны быть заданы
правила,
определяющие для сочетания хост/адрес/тип-ошибки интервал повторения
попыток и максимальное время нахождения в очереди. Если письмо не
попадет ни под одно правило, то временная ошибка обрабатывается
как постоянная.
При истечении максимального времени нахождения в очереди, генерируется
сообщение об ошибке. После успешной повторной попытки удалённой
доставки сервер проверяет в своей БД не ждали ли другие письма отправки на
этот же хост и отправляет их в том же соединении.
Сгенерированное сообщение об ошибке обрабатывается как
обычное письмо. Одно исходное письмо может приводить к генерации нескольких
сообщений об ошибке, если оно имеет нескольких получателей и условия
ошибки для различных получателей появляются неодновременно. Текст сообщения
об ошибке можно настраивать. В любом случае, оно содержит поле заголовка
X-Failed-Recipients:, содержащее список неудачных адресов. Обычно
сообщение об ошибке посылается отправителю (задается командой
MAIL протокола SMTP), но для сгенерированных адресов может указываться
альтернативный адрес для сообщений об ошибках.
Все настройки хранятся в одном файле (по умолчанию -
/usr/exim/configure). Права доступа к файлу должны быть ограничены
(root:exim, 0640).
Пустые строки и строки, начинающиеся с символа #,
являются комментариями. Обратная косая черта в конце строки означает,
что следующая строка является строкой продолжения (пробелы после косой
и в начале строки продолжения игнорируются).
Разрешается включение
другого файла (глубина вложения неограничена) с помощью команды
".include имя-файла". Имя файла может быть заключено
в кавычки. Команда .include может использоваться в середине строки
и выполняется до макроподстановок.
Конфигурационный файл начинается с обязательной общей части
и может содержать в произвольном порядке секции (начало секции отмечается
строкой, начинающейся со слова begin и имени секции):
Общая часть содержит определения макро (см. ниже),
определения именованных списков доменов, адресов, хостов,
локальных частей и установку общих опций.
Если строка в общей секции начинается с прописной буквы,
то она воспринимается как определение макро в форме: имя = значение.
Имя может содержать буквы, цифры и подчеркивания. Начальные и конечные
пробелы удаляются из значения. Все последующие строки файла сканируются
на вхождение имени макро и заменяются его значением. Заметьте, что
никаких специальных символов, выделяющих вхождение имени макро не используется!
После подстановки получившийся текст сканируется на вхождение имени
следующего макро и т.д..
Общая секция и секции драйверов (аутентификаторы,
маршрутизаторы и транспорты) имеют одинаковый синтаксис.
Каждая опция записывается на отдельной строке. Имя опции содержит
строчные буквы и подчеркивания. Опция может иметь значение, которое
записывается после знака равенства (пробелы вокруг знака равенства удаляются).
Перед именем может стоять слово hide, что позволяет скрыть значение
от раскрытия с помощью exim -bP.
Значение логических опций (true, false, yes, no)
может быть задана без
использования формы имя=значение. Достаточно указать имя опции,
чтобы включить ее, или имя опции, перед которым стоит приставка "no_"
или "not_", чтобы выключить.
Целое число может трактоваться как шестнадцатеричное,
если начинается с "0x", как восьмеричное, если начинается с нуля, или
десятичное. Если за числом стоит буква K, то оно умножается на 1024,
если за числом стоит буква M, то - на 1024*1024. Некоторые опции
определяются как восьмеричные числа, их значения воспринимаются как
восьмеричные независимо от наличия нуля в начале числа.
Временной интервал записывается как последовательность
чисел, за каждым из которых записывается буква, обозначающая единицу
измерения (без пробелов): s, m, h, d, w. Например: 3h50m.
Строки могут заключаться в кавычки. Обратная косая черта
позволяет задавать специальные символы: \n, \r, \t, \\, \020, \xFF.
Некоторые опции задаются как список объектов.
Весь список рассматривается как строка, объекты в списке разделяются
двоеточиями. Если объект содержит двоеточие, то оно представляется двумя
двоеточиями. Пробелы вокруг разделителей удаляются. Разделитель можно
заменить на любой символ, если строку начать со знака меньше и этого
символа. Перед использованием списка он вычисляется,
как и любая другая строка.
Каждый объект в списке представляет собой шаблон,
с которым сравнивается имя домена, имя хоста, адрес или локальная часть
адреса. Если вычисление строки завершается аварийно, то exim считает,
что имя в список не входит. Специальные символы в шаблоне должны быть
защищены от их интерпретации при вычислении строки. Шаблоны могут быть
позитивными и негативными (начинаются с !). Совпадение имени с негативным
шаблоном означает, что имя отсутствует в списке. Если ни один шаблон не подошел,
но последним в списке был негативный шаблон, то считается, что имя в списке
(как будто в конец списка добавили шаблон *). В качестве шаблона можно
использовать абсолютное имя файла: каждая строка файла интерпретируется
как шаблон (строка не может содержать ссылку на другой файл; пустые
строки игнорируются; комментарии начинаются с #). Файл читается заново
при каждой обработке списка. Если перед именем файла стоит восклицательный
знак, то значения шаблонов в нем инвертируется. В дополнение к явному
заданию шаблона можно указывать запросы на
поиск в файле или БД (объекты в файле или БД
являются константами, не шаблонами!).
Синтаксис регулярных выражений, используемых в некоторых
опциях, соответствует регулярным выражениям языка perl. Точнее говоря,
используется библиотека PCRE (см. doc/pcre.txt).
Каждая секция драйверов и ACL делится на описание поименованных
драйверов. Описание каждого драйвера или ACL начинается со строки, в начале
которой записано его имя (должно быть уникально; можно использовать буквы,
цифры и подчеркивание), за которым идет двоеточие. Все опции до
имени следующего драйвера и двоеточия относятся к этому драйверу.
Порядок описания драйверов в секциях маршрутизаторов и аутентификаторов
важен.
exim ищет данные в файлах или БД в следующих случаях (синтаксис
определяется случаем):
- список доменов, хостов или адресов может вместо явного перечня
элементов содержать запрос на поиск в файле или БД
mysql;select newaddress from mail_redirect \
where localpart='${quote_mysql:$local_part}' \
and domain='${quote_mysql:$domain}'
- выражение подстановки строки содержит явный
запрос на поиск и подстановку результата поиска (результат поиска
может в свою очередь являться запросом на поиск первого типа)
transport = ${lookup mysql{select transport from mail_accept \
where localpart='${quote_mysql:$local_part}' \
and domain='${quote_mysql:$domain}'}{$value}fail}
Некоторые поисковые механизмы возвращают сообщение
о временной недоступности. Если это происходит в маршрутизаторе или транспорте,
то доставка сообщения задерживается.
Типы поисковых механизмов (делятся на 2 класса - по ключу и по запросу):
Механизмы поиска по ключу (cdb, dbm, dbmnz, dsearch, lsearch,
nis) позволяют задать задавать значение по умолчанию:
- если к имени механизма добавить звездочку, то при неудачном поиске
exim проводит повторный поиск по ключу "*"
- если к имени механизма добавить "*@", то при неудачном поиске
exim заменяет подстроку ключа до последнего знака @ на *
и производит повторный поиск (это позволяет обеспечить подоменное
значение по умолчанию для адресов); если повторный поиск заканчивается
неудачно, то exim производит третий поиск по ключу "*"
- если перед именем механизма добавить строку "partial-", то при
неудачном поиске exim добавляет "*." перед ключом и производит
повторный поиск; если повторный поиск заканчивается
неудачно, то exim заменяет левую часть ключа до первой точки
на * и проводит третий поиск; если и это не помогает, то процесс
повторяется пока в ключе не останется 2 не-* компонента (число
2 можно заменить на любое другое, поставив его между partial и тире);
вместо шаблона "*." можно использовать любую строку, указав её
в круглых скобках вместо тире в префиксе "partial-";
данный механизм работает в терминах поддоменов, а не подстрок
- использование префикса partial- можно комбинировать с суффиксами * и *@
(например, "partial0(.)lsearch*")
Результаты поиска кешируются. Последствия непредсказуемы.
При подстановке параметров в запросы (mysql и др.),
значение параметра может оказаться несовместимым с языком запросов.
Имеются операторы для преобразования параметров в безопасный вид:
${quote_mysql:строка}.
Поименованный список доменов определяется строкой:
domainlist имя-списка = список
Аналогично создаются hostlist, addresslist и localpartlist.
Для того, чтобы использовать поименованный список, надо
указать его имя и поставить перед ним знак +. Для отрицания списка надо перед
плюсом написать строку "! ". Поименованный список может быть использован
для создания другого поименованного списка (вложенность не ограничена).
В то время как макросы являются средством чисто текстовой подстановки,
поименованные списки вычисляются (например, можно сделать отрицание списка
поставив перед ним восклицательный знак, в то время как поставив
восклицательный знак перед макросом мы придадим отрицание только первому
элементу списка).
Результаты проверки вхождения элемента в поименованный
список кешируются, что ускоряет обработку (только если exim уверен, что
список постоянен).
Список доменов может содержать:
- @ (соответствует имени локального хоста)
- @[] (соответствует любому локальному IP адресу в квадратных скобках)
- @mx_any (соответствует любому домену, который имеет MX, указывающий
на локальный хост или хост, указанный в hosts_treat_as_local)
- @mx_primary (соответствует любому домену, чей primary MX указывает
на локальный хост или хост, указанный в hosts_treat_as_local)
- @mx_secondary (соответствует любому домену, чей не-primary MX указывает
на локальный хост или хост, указанный в hosts_treat_as_local)
- *строка (соответствует любому домену, чье имя заканчивается на строку)
- ^регулярное-выражение
- имя-поискового-механизма-по-ключу;абсолютное-имя-файла (действует также
поиск на частичное соответствие с помощью механизмов *, *@ и
partial-)
- имя-поискового-механизма-по-запросу;поисковый-запрос
- любая-текстовая-строка (сравнение независимо от регистра)
Список хостов может содержать (шаблоны с адресами лучше
ставить перед шаблонами с именами):
- пустой элемент (не пустой список! соответствует ситуации, когда не
используется TCP/IP)
- * (любое имя или адрес или не TCP/IP)
- доменное-имя (по имени вычисляется IP адрес, который сравнивается
с адресом тестируемого хоста; а если адресов несколько?)
- @ (по имени локального хоста - primary_host - вычисляется IP адрес,
который сравнивается с адресом тестируемого хоста)
- IP-адрес (сравнивается с адресом тестируемого хоста)
- @[] (адрес тестируемого хота сравнивается с адресами всех интерфейсов
локального хоста)
- адрес/длина-маски
- net-имя-поискового-механизма;параметры-запроса
(поиск в БД по ip-адресу;
при поиске по запросу используется переменная $sender_host_address;
можно использовать маскированный адрес в качестве ключа:
net24-dbm;/etc/networks.db, при этом адрес 192.168.34.6 преобразуется
в ключ 192.168.34.0/24)
- +include_unknown (если последующие шаблоны предназначены для
сравнения
имен хостов, а имя хоста по адресу определить не удалось)
- *строка (по IP-адресу определяется имя - или имена - и
проверяется соответствие строки окончанию имени)
- ^регулярное-выражение (по IP-адресу определяется имя
- или имена - и проверяется на соответствие регулярному выражению)
- имя-поискового-механизма;параметры-запроса
(по IP-адресу определяется имя и делается поиск в БД по имени)
Список адресов может содержать:
- пустой элемент (не пустой список! соответствует обратному адресу
сообщения об ошибке)
- ^регулярное-выражение
- @@имя-поискового-механизма;параметры-запроса
(доменная часть тестируемого адреса ищется в БД;
если не найдена, то нет соответствия; если найдена, то из БД
извлекается соответствующее данному ключу значение, которое
рассматривается как список через двоеточие локальных частей
(могут быть шаблонами, запросами на поиск в БД или негативными),
с которыми надо сравнить локальную часть адреса; можно использовать
частичный поиск через partial- или *; имеется механизм ссылок)
- имя-поискового-механизма;параметры-запроса
(можно использовать частичный поиск через *, но не partial-)
- если шаблон содержит @, но не является регулярным выражением
или запросом к БД, то локальная часть адреса сравнивается с
локальной частью шаблона (допускается начинать со *),
если совпадение достигнуто, то домен проверяется как в доменном
списке с использованием любых типов шаблонов
- все остальные шаблоны рассматриваются как доменные шаблоны, к которым
слева приписывается *@
- +caseful (восстанавливает регистр локальной части для дальнейших
сравнений; доменная часть всегда приводится к строчным буквам)
Список локальных частей может содержать (надо тщательнее
разбираться со сравнением в зависимости от регистра и без такового):
- *строка
- ^регулярное-выражение
- имя-поискового-механизма-по-ключу;абсолютное-имя-файла
(действует также поиск на частичное соответствие с помощью механизмов *,
*@ и partial-)
- имя-поискового-механизма-по-запросу;поисковый-запрос
- любая-текстовая-строка
Перед использованием каждая строка вычисляется.
Вычисление состоит в интерпретации команд, задаваемых с использованием
символа $, и маскировании специальных символов с помощью обратной
косой черты перед ними. Если строка заключена в кавычки, то обратную
косую черту необходимо удвоить, т.к. при обработке кавычек одна
обратная косая черта будет удалена. При необходимости заблокировать
вычисление длинной строки, ее можно заключить в скобки, состоящие из
"\N". Не надо забывать, что обратная косая черта имеет специальное
значение в уже вычисленных строках (\n, \t, \r, \020, \xFF) и как
признак строки продолжения.
Обрабатываемые команды:
- $имя-переменной (подстановка значения переменной)
- ${имя-переменной} (подстановка значения переменной)
- ${операция:строка} (сначала строка вычисляется,
затем к тем применяется указанная операция)
- ${extract{ключ}{строка1}[{строка2}[{строка3}|fail]]} (сначала вычисляются ключ и строка1; строка1 имеет вид списка
ключ=значение через пробел; если ключ имеется в этом списке, то вместо
всего выражения подставляется вычисленная строка2, иначе вычисленная
строка3; при вычислении строки2 можно использовать переменную
$value, которая имеет значение соответствующее ключу в списке
ключ=значение; если строка3 опущена, то вместо нее используется
пустая строка; если строка2 опущена, то вместо нее используется
строка $value; использование слова fail вместо строки3 приводит
к аварийному завершению вычисления строки (не только команды extract) -
forced expansion failure)
- ${extract{число}{разделители}{строка1}{строка2}[{строка3}]} (сначала вычисляются число,
строка разделителей и строка1; строка1 представляет собой список полей,
разделенных символами из строки разделителей; номер выбираемого поля
определяется числом; нумерация с 1; если число отрицательное, то
нумерация справа налево с -1; поле номер 0 - вся строка1;
если поле с указанным номером существует, то вместо
всего выражения подставляется вычисленная строка2, иначе вычисленная
строка3; при вычислении строки2 можно использовать переменную
$value, которая имеет значение соответствующее выбранному полю в строке1;
если строка3 опущена, то вместо нее используется пустая строка)
- $header_имя-заголовка: или $h_имя-заголовка:
(подставляется содержимое указанного поля заголовка письма;
несуществующее поле заголовка заменяется на пустую строку;
если заголовок имеет несколько полей с указанным именем, то
их содержимое сливается вместе; синтаксис имени и содержимого
поля определяется стандартом RFC2822)
- ${if условие {строка1}[{строка2}|fail]}
- ${lookup {ключ} имя-поискового-механизма-по-ключу {имя-файла} {строка1}[{строка2}|fail]} или
${lookup имя-поискового-механизма-по-запросу {запрос} {строка1}[{строка2}|fail]}
(сначала вычисляются ключ, имя-файла или запрос;
затем производится поиск в БД;
если поиск успешен, то вычисляется строка1 и заменяет все выражение;
можно использовать переменную $value, которая имеет значение,
найденное при поиске;
если поиск неуспешен, то вычисляется строка2 и заменяет все выражение;
если строка2 опущена, то вместо нее используется пустая строка;
строка1 и/или строка2 может в свою очередь также быть поиском в БД;
если строка1 опущена, то вместо нее используется строка $value;
разрешается частичный поиск по правилам partial-, * и *@;
при этом переменные $1 и $2 принимают значения левой и правой частей
шаблона)
- вызов подпрограммы perl, если exim собран с поддержкой perl
- ${readfile {имя-файла}[{строка1}]}
(вычисляются имя-файла и строка1; файл читается; NL заменяется
на строку1; результат подставляется вместо команды)
- ${run {программа аргументы}{строка1}[{строка2}|fail]}
(вычисляется программа и аргументы; программа запускается в отдельном
процессе (без shell!), но с теми же uid и gid;
если программа завершается успешно - возвращает 0, то
вычисляется строка1 и замещает выражение; при этом переменная
$value содержит вывод программы на stdout; если программа
завершается аварийно - возвращает не 0, то
вычисляется строка2 и замещает выражение;
если опущены строка1 и строка2, то в случае успешного завершения
стандартный вывод программы замещает выражение, иначе пустая строка;
код возврата помещается в переменую $runrc и доступен в дальнейшем)
- ${sg{строка}{регулярное-выражение}{замена}}
(строка, регулярное-выражение и замена вычисляются;
выполняется глобальная подстановка аналогично оператору s с опцией /g
в perl)
- ${tr{строка}{символы}{замены}}
(замена символов как в программе tr)
Операции:
- address: из строки извлекается адрес в формате RFC2822
- base62: строка из десятичных цифр преобразуется в основание 62 и
и выводится в виде строки из 6 символов (цифры и буквы)
- domain: строка интерпретируется как адрес RFC2822 и из нее
извлекается имя домена
- escape: непечатные символы строки преобразуются в маскированную
форму (с помощью обратной косой черты)
- expand: повторное вычисление строки
- hash_n_m или h_n_m: самодельная функция хеширования; выдает строку длины n
из набора символов длины m (m <= 62)
- lc: преобразование букв к строчным
- length_n или l_n: извлечь подстроку длины n
- local_part: строка интерпретируется как адрес RFC2822 и из нее
извлекается локальная часть адреса
- mask: строка типа 10.111.131.206/28 преобразуется в 10.111.131.192/28
- md5: возвращает 32 шестнадцатеричные цифры
- nhash_n: самодельная хеш-функция возвращает число от 0 до n-1
- nhash_n_m: самодельная хеш-функция возвращает два числа. разделенных
косой чертой (первое - от 0 до n-1, второе - от 0 до m-1)
- quote: если строка содержит символы, отличные от цифр, букв, точки,
подчеркивания и тире, то она заключается в кавычки; исходные кавычки
и обратные косые маскируются обратной косой чертой
- quote_имя-поискового-мезанизма: маскирование строки по правилам данного
поискового механизма
- rxquote: любой не буквоциферный символ маскируется обратной косой чертой
- substr_n_l или s_n_l: извлечь подстроку длины l, начиная со смещения n;
символы в строке нумеруются с 0; если смещение отрицательно, то отсчет
идет справа (самый правый символ имеет смещение -1)
- substr_n или s_n: извлечь подстроку, начиная со смещения n до конца
строки; символы в строке нумеруются с 0; если смещение отрицательно,
то извлечь подстроку, начиная с начала строки
- uc: преобразование букв к прописным
Условия в команде if:
- !условие
- or {{условие}...}
- and {{условие}...}
- ={строка1}{строка2} (сравнение чисел)
- =={строка1}{строка2}
- >{строка1}{строка2}
- >={строка1}{строка2}
- <{строка1}{строка2}
- <={строка1}{строка2}
- crypteq {строка1}{строка2}
строка1 шифруется и сравнивается с ранее зашифрованной строкой2;
строка2 должна начинаться с {md5} или {crypt} (фигурные скобки
надо маскировать, если строка2 задается непосредственно в тексте!);
{crypt} можно опускать (это формат /etc/shadow);
{md5} в формате LDAP, т.е. вычисляется MD5 и приводится
к печатному виду (24 символа в формате base64 или 32 символа в формате
шестнадцатеричных цифр); пароль в MD5 из /etc/shadow надо дополнить
двумя знаками равенства
- def:имя-переменной (переменная содержит непустую строку)
- def:header_имя-поля-заголовка:
(указанное поле заголовка существует в обрабатываемом письме)
- exist {имя-файла}
- eq {строка1}{строка2} (сравнение строк)
- first_delivary (истина, если это первая попытка отправить письмо)
- ldapauth
- match {строка}{регулярное-выражение}
- pam
- queue_running (истина, если обработка письма вызвана
обработкой очереди)
- radius
Переменные:
- $0, $1 и т.д. (результаты успешного выполнения последнего регулярного
выражения)
- $address_data (устанавливается опцией address_data маршрутизатора)
- $address_file (имя файла при маршрутизации сообщения в файл)
- $address_pipe (имя программы при маршрутизации сообщения в канал)
- $authenticated_id (в частности, если сообщение посылается локально,
то содержит имя пользователя)
- $authenticated_sender (в частности, если сообщение посылается локально,
то содержит адрес, сформированный из имени пользователя и
$qualify_domain
- $body_linecount
- $bounce_recipient
- $caller_gid, $caller_uid, $originator_gid, $originator_uid
- $compile_date, $compile_number, $version_number
(информация о программе exim)
- $dnslist_domain, $dnslist_text, $dnslist_value (информация о хосте,
находящемся в черном списке (DNS black list): домен, TXT, RR)
- $domain (устанавливается после преобразования адресов; доступен при
использовании пользовательских фильтров, но недоступен системному
фильтру; если несколько адресов обрабатываются за раз - например,
несколько RCPT в одной сессии -, то $domain устанавливается только,
если все адреса принадлежат одному домену; всегда становлен при
обработке ACL для RCPT; устанавливается при преобразовании
адресов; при сканировании списка доменов $domain содержит исходный
домен; при обработке опции smtp_etrn_command содержит аргумент
команды ETRN)
- $domain_data (если опция domains маршрутизатора производит поиск
в БД, то содержит результаты поиска в пределах этого
маршрутизатора и вызванного транспорта)
- $home (домашняя директория пользователя после проерки
check_local_user)
- $host
- $host_address
- $host_lookup_failed (сообщение пришло с хоста, чье имя определить не
удалось)
- $inode
- $interface_address (IP адрес интерфейса, через который пришло письмо)
- $interface_port (номер порта, через который пришло письмо)
- $local_part (содержит локальную часть адреса при маршрутизации и отправке
письма; не устанавливается, если письмо отправляется сразу нескольких
получателям; устанавливается после преобразования адресов; доступен при
использовании пользовательских фильтров, но недоступен системному
фильтру; распознанные префикс и суффикс локальной части не включаются;
если письмо направляется в файл, канал или автоответ, то содержит
локальную часть исходного адреса, а не имя файла и т.д.;
при обработке ACL для RCPT содержит локальную часть адреса
получателя; устанавливается также в процедуре преобразования адресов;
символы маскирования не включаются)
- $local_part_data (если опция local_parts маршрутизатора производит поиск
в БД, то содержит результаты поиска в пределах этого
маршрутизатора и вызванного транспорта)
- $local_part_prefix, $local_part_suffix
- $local_scan_data (содержит текст, который вернула функция local_scan())
- $localhost_number (значение опции localhost_number)
- $message_age (сколько секунд прошло от приема письма до начала
текущей попытки отправить его)
- $message_body (начало письма; NL преобразуется в пробел; размер ограничен
message_body_visible - 500)
- $message_body_end (конец письма; NL преобразуется в пробел;
размер ограничен message_body_visible - 500)
- $message_body_size (в байтах)
- $message_headers (строки, добавленные маршрутизаторами и транспортами
не включены)
- $message_id (сгенерированный exim идентификатор)
- $message_size (размер приблизительный; при обработки ACL для RCPT
хранит значение, полученное от команды MAIL или 0)
- $n0 - $n9 (счетчики для фильтров)
- $original_domain (содержит домен исходного адреса для порожденных
адресов)
- $original_local_part (содержит локальную часть исходного адреса
для порожденных адресов; префикс и суффикс не удалены)
- $parent_domain (доменная часть непосредственного предшественника
порожденного адреса - может быть несколько уровней перенаправления)
- $parent_local_part
- $pipe_address (только для транспорта типа pipe и транспортных фильтров)
- $primary_hostname (значение опции primary_hostname)
- $qualify_domain (значение опции qualify_domain)
- $qualify_recipient (значение опции qualify_recipient)
- $received_for (если письмо имеет одного получателя, то здесь
содержится его адрес при построении поля заголовка Received:)
- $received_protocol
- $recipients (список получателей из заголовка; недоступен в
пользовательских фильтрах - чтобы не выдать Bcc:)
- $recipients_count
- $reply_address (reply-to: или from:)
- $return_path (адрес отправителя из конверта без угловых скобок;
маршрутизатор может задать новый адрес возврата)
- $return_size_limit (значение опции return_size_limit, округленное
до 1000)
- $runrc (код возврата программы после ${run...})
- $self_hostname
- $sender_address (адрес отправителя из конверта без угловых скобок;
для сообщений об ошибках - пустая строка!
- $sender_address_domain, $sender_address_local_part
- $sender_fullhost (строка, содержащая ip адрес хоста-отправителя
в квадратных скобках; имя хоста, если оно было верифицировано
успешно; имя хоста в круглых скобках как оно было заявлено
в команде HELO или EHLO и не совпадает с верифицированным или адресом)
- $sender_helo_name (что заявил о себе отправитель в команде HELO
или EHLO)
- $sender_host_address
- $sender_host_authenticated (имя драйвера, аутентифицировавшего клиента)
- $sender_host_name (имя хоста-отправителя, если оно было верифицировано
через DNS)
- $sender_host_port
- $sender_ident (ответ удаленного ident или имя локального пользователя)
- $sender_rcvhost (информация о хосте отправителя для строки Received:
- адрес в квадратных скобках, верифицированное имя, текст в скобках)
- $smtp_command_argument (при обработке ACL для AUTH, EXPN, ETRN,
VRFY содержит аргументы этих команд)
- $sn0 - $sn9 (копии значений счетчиков $n0 - $n9 на момент завершения
работы системного фильтра; могут быть использованы в пользовательских
фильтрах)
- $spool_directory
- $thisaddress
- $tls_cipher
- $tls_peerdn
- $tod_bsdinbox (текущее время в формате Thu Oct 17 17:14:09 1995)
- $tod_epoch (текущее время в секундах от начала эпохи)
- $tod_full (текущее время в формате RFC2822)
- $tod_log (текущее время в формате журнала exim: 1995-10-12 15:32:29)
- $value (содержит значение после поиска в БД, выполнения программы и т.д.)
- $warnmsg_delay
- $warnmsg_recipients
Сокращенный список опций (тип, значение по умолчанию,
пояснения):
- accept_8bitmime (boolean; false; посылать 8BITMIME в ответ на EHLO
и принимать параметр BODY= команды MAIL; exim является "8-bit clean"
программой, но конвертировать протоколы не умеет, так что последствия
не понятны)
- acl_smtp_auth (вычисляемая строка; unset; определяет ACL для обработки
команды AUTH)
- acl_smtp_data (вычисляемая строка; unset; определяет ACL для обработки
всего сообщения перед подтверждением приема письма;
не все MTA и MUA воспринимают код ошибки 5xx в этот момент:
некоторые пытаются повторить передачу письма,
некоторые считают, что письмо доставлено)
- acl_smtp_etrn, acl_smtp_expn, acl_smtp_rcpt, acl_smtp_vrfy
- admin_groups (строка; unset; представляет собой список групп через
двоеточие; если пользователь является членом одной из групп, то он имеет
административные полномочия)
- allow_domain_literals (boolean, false, обрабатывать адреса типа
root@[127.0.0.1])
- allow_mx_to_ip (boolean; false; обход правила, запрещающего помещать
в MX запись имена, похожие на ip адрес)
- auth_advertise_hosts (вычисляемый список хостов; *; в ответ на EHLO
от этих хостов exim обещает обработать команду AUTH; некоторые MUA
увидев это требуют от пользователей указать имя и пароль, хотя они
могут и не потребоваться)
- auto_thaw (время; 0s; автоматически размораживать замороженные
сообщения через указанный интервал, если он больше нуля)
- bi_command (строка; unset; команда, выполняемая при вызове exim
с ключом -bi, эмулирующем работу newaliases)
- bounce_message_file (строка; unset; имя файла, содержащего шаблон
сообщения об ошибке)
- bounce_message_text (строка; unset; текст включается в конец сообщения
об ошибке)
- bounce_return_message (boolean; true; включать исходное сообщение
в сообщение об ошибке)
- bounce_sender_autentification (строка; unset; адрес отправителя сообщений
об ошибках, если они посылаются по аутентифицированному каналу)
- check_log_inodes, check_log_space, check_spool_inodes, check_spool_space
(integer; 0; проверяется наличие места перед приемом сообщения)
- daemon_smtp_port (строка; unset; на каком порту принимать почту)
- delay_warning (список интервалов; 24h; когда посылать отправителю
предупреждения о задержке доставки его письма)
- delay_warning_condition (вычисляемая строка; вычисляется в момент,
когда должно быть послано предупреждение о задержке доставки и
если в результате получается 0, no, false или пустая строка, то
не посылать предупреждения; при значении по умолчанию предупреждение не
посылается, если в поле заголовка Precendence: стоит bulk, list или junk)
- deliver_drop_privilege (boolean; false; сменить euid с root на exim
перед началом процесса доставки)
- deliver_queue_load_max (fixed-point, unset, перестать обрабатывать
очередь, если загрузка системы выше указанной)
- delivery_date_remove (boolean; true; удалять поле заголовка Delivery-date:
из входящих писем)
- dns_again_means_nonexist (вычисляемый список доменов; unset;
если DNS запрос для домена из списка вызывает ответ "try again",
то считать домен несуществующим)
- dns_check_names_pattern (строка; задает регулярное выражение,
которому должно удовлетворять имя домена перед посылкой DNS запроса;
если оно не удовлетворяет этому шаблону, то результат "not found"
генерируется без обращения к резольверу; по умолчанию - сюрприз! - шаблон,
описывающий стандарт доменного имени)
- drop_cr (boolean; false; удалять из локально полученных писем символы
CR, предшествующие NL)
- envelope_to_remove (boolean; true; удалять поле заголовка Envelope-to:
из входящих писем)
- errors_copy (вычисляемая строка; unset; вызывает посылку копий
генерируемых exim сообщений об ошибках (с помощью bcc:);
строка представляет собой список через двоеточие;
элемент списка состоит из шаблона и (после пробела) списка адресов
через запятую; адрес получателя сообщения об ошибке сравнивается
с шаблонами из списка, копия посылается по тем адресам, которые входят
в элемент списка первого подошедшего шаблона; строка вычисляется перед
использованием, так что можно использовать $local_part, $domain, $0, $1
и т.д.)
- errors_reply_to (строка; unset; текст поля заголовка Reply-To:
для генерируемых сообщений об ошибках)
- freeze_tell (строка; unset; представляет собой список адресов через запятую;
на эти адреса посылается сообщение о замораживаемых сообщениях, кроме
замораживания сгенерированных сообщений об ошибках)
- helo_accept_junk_hosts (вычисляемый список хостов; unset;
список хостов, от которых принимать почту даже если они нарушают
синтаксис команд HELO и EHLO)
- helo_lookup_domains (вычисляемый список доменов; @:@[];
если удаленный хост выдает в команде HELO или EHLO имя домена
из этого списка, то истинное имя домена определяется по DNS запросу
из ip адреса)
- helo_try_verify_hosts, helo_verify_hosts (вычисляемый список хостов; unset;
стандарт запрещает MTA отвергать почту, если ему не нравится параметр
команды HELO; для хостов, входящих в эти списки, exim требует
выдачи команды HELO или EHLO, и чтобы параметр HELO был либо
настоящий ip адрес удаленного хоста, либо соответствовал тому имени,
который exim получил из DNS по ip адресу, либо из него можно получить
настоящий ip адрес в результате DNS запроса; helo_verify_hosts не
принимает почту с таких хостов, а helo_try_verify_hosts продолжает
обработку (ситуацию можно отловить в ACL)
- hold_domains (вычисляемый список доменов; unset; почта для доменов из
списка не маршрутизируется и не отправляется; однако удаление старых
сообщений из очереди на них действует)
- host_lookup (вычисляемый список хостов; unset; exim определяет имя
удаленного хоста, если оно требуется для поиска в списке хостов
или он входит в helo_verify_hosts или в этот список)
- host_reject_connection (вычисляемый список хостов; unset)
- hosts_treat_as_local (вычисляемый список доменов; unset; не понял)
- ignore_bounce_errors_after (время; 10w; сгенерированные сообщения об
ошибках, которые не удалось доставить, замораживаются; через указанное
время exim размораживает их и пытается доставить в последний раз;
при неудаче они просто выкидываются)
- keep_malformed (время; 4d; сколько времени хранить запорченные файлы
в спуле)
- local_interfaces (список; unset; список ip адресов и портов через
двоеточие в виде 127.0.0.1 или 127.0.0.1.25 или [127.0.0.1]:25,
откуда exim будет принимать почту; только эти адреса считаются
локальными при маршрутизации и проверке зацикливания почты)
- log_selector (строка; unset; какие события записывать в журнал)
- lookup_open_max (integer; 25; максимальное количество одновременно
открытых файлов для поиска в БД)
- message_body_visible (integer; 500; сколько байт из тела письма
помещать в $message_body и $message_body_end)
- message_id_header_text (вычисляемая строка; unset;
если пришедшее сообщение не содержит поля заголовка Message-Id:,
то exim по умолчанию создает его из своего идентификатора
сообщения и имени хоста; установка данной опции позволяет добавить
текст в начало локальной части Message-Id)
- message_size_limit (вычисляемая строка; 50M; вычисляется для каждого
входящего сообщения, что позволяет настраивать в зависимости от адреса
и т.д.)
- move_frozen_messages (boolean; false; файлы в спуле и записи в журнале
для замороженных сообщений перемещаются из input и msgog в Finput и
Fmsglog; exim, eximon и утилиты не имеют поддержки этих файлов;
в 4.0.3 пропал!)
- mysql_servers (список; unset; список серверов MySQL и других данных,
необходимых для подсоединения)
- never_users (список; unset; список uid, под которыми ни в коем случае
не запускать процессы доставки; рекомендуется включить в него, как минимум,
root)
- percent_hack_domain (вычисляемый список доменов; unset; для доменов из
этого списка интерпретировать локальную часть адреса, содержащую %,
как в некоторм смысле source route, иначе рассматривать как обычную
строку)
- preserve_message_logs (boolean: false; индивидульные журналы обработки
сообщений не удаляются по завершению, а перемещаются в msglog.OLD)
- primary_hostname (строка; можно указать имя своего хоста, если не
уверен, что система определит его правильно; используется в EHLO)
- print_topbitchars (boolean; false; рассматривать ли коды символов выше 128
как печатные при записи в журнал и т.д.; иначе они будут преобразованы
в безопасные последовательности символов)
- prod_requires_admin (boolean; true; чтобы запускать обработу очереди
требуются права администратора)
- qualify_domain (строка; берется из primary_hostname;
добавляется к каждому адресу отправителя, не имеющему доменной части)
- qualify_recipient (строка; берется из qualify_domain;
добавляется к каждому адресу получателя, не имеющему доменной части)
- queue_domains (вычисляемый список доменов; unset; обработка почты
для данных доменов откладывается до обработки очереди)
- queue_list_requires_admin (boolean; true; для просмотра списка
сообщений в очереди требуются права администратора)
- queue_only (boolean; false; принятое сообщение не отправляется
немедленно, а откладывается до обработки очереди)
- queue_only_load (fixed-point; unset; если загрузка системы выше указанной,
то только принимать сообщения и складывать их в очередь)
- queue_run_in_order (boolean; false; обрабатывать сообщения в очереди
по порядку прихода)
- queue_run_max (integer; 5; максимальное количество одновременно
запускаемых автоматически (-q15m) обработчиков очереди; однако,
дополнительные обработчики могут быть запущены вручную или в результате
перезапуска exim)
- queue_smtp_domain (вычисляемый список доменов; unset; отправка почты
по smtp для данных доменов откладывается до обработки очереди)
- receive_timeout (время; 0s; интервал ожидания при получении
локальной почты)
- received_header_text (вычисляемая строка; вычисляется при каждом
обращении; содержит шаблон для генерации поля заголовка Received:;
шаблон по умолчанию слишком сложен, чтобы приводить его здесь :)
- received_headers_max (integer; 30; при превышении этого числа считается,
что произошло зацикливание и письмо не отправляется)
- recipient_unqualified_hosts (вычисляемый список хостов; unset;
определяет список хостов, с которых будут приниматься конверты с адресами
без доменной части)
- recipients_max (integer; 0; если число получателей (RCPT) превышает это
число, то на все последующие команды RCPT возвращается код возврата
452, но все ранние получатели обрабатываются нормально;
кстати, стандарт требует, чтобы MTA принимал минимум 100 RCPT)
- recipients_max_reject (boolean; false; полностью отвергать
SMTP соединение со слишком большим числом получателей - коды 552, 554)
- remote_max_parallel (integer; 2; если сообщение имеет множество получателей
на разных хостах, то exim запускает до remote_max_parallel процессов
доставки сообщения параллельно; если необходимо контролировать общее
число параллельно запускаемых процессов, то надо использовать еще и
queue_only или queue_smtp_domain, тогда число процессов будет ограничено
remote_max_parallel*queue_run_max)
- return_path_remove (boolean; true; удалять поля заголовка Return-Path:
из приходящих сообщений в соответствии с RFC2821)
- return_size_limit (integer; 100K; ограничение размера части исходного
сообщения, вставляемого в сообщение об ошибке доставки)
- rfc1413_hosts (вычисляемый список хостов; *; список хостов, у которых
запрашивать ident)
- rfc1413_query_timeout (время; 30s; если 0, то запросы выдаваться не будут)
- sender_unqualified_hosts (вычисляемый список хостов; unset;
определяет список хостов, с которых будут приниматься конверты с адресами
без доменной части)
- smtp_accept_max (integer; 20; максимальное число входящих SMTP соединений)
- smtp_accept_max_per_connection (integer; 1000; число сообщений, принимаемых
за одно соединение)
- smtp_accept_max_per_host (вычисляемая строка; unset; ограничивает число
одновременных входящих соединений с одного ip адреса;
при вычислении можно использовать $sender_host_address)
- smtp_accept_queue (integer; 0; если одновременное число входящих
соединений превышает это число, то полученные сообщения складываются
в очередь, а не отправляются немедленно)
- smtp_accept_queue_per_connection (integer; 10; если число писем, полученных
в одной сессии превышает это чмсло, то последующие письма складываются
в очередь, а не отправляются немедленно)
- smtp_accept_reserve (integer; 0; число зарезервированных соединений
от хостов из smtp_reserv_hosts при установленном ограничении
smtp_accept_max)
- smtp_banner (вычисляемая строка; вычисляется при каждом использовании;
определяет шаблон приветствия)
- smtp_check_spool_space (boolean; true; получив команду MAIL с параметром
SIZE, exim проверяет что после приема письма в разделе останется
check_spool_space байт)
- smtp_connect_backlog (integer; 20; борьба с SYN flood; для больших
систем рекомендуют увеличить до 50)
- smtp_enforce_sync (boolean; true; exim требует, чтобы клиент не посылал
очередную команду, не дождавшись ответа на предыдущую, иначе соединение
разрывается с кодом 554
- smtp_etrn_command (вычисляемая строка; unset; имя внешней программы и ее
параметры; запускается при получении ETRN под gid=exim)
- smtp_etrn_serialize (boolean; true; не позволяет одновременно запускать
идентичные программы в результате ETRN)
- smtp_load_reserve (fixed-point; unset; если загрузка системы превышает
указанный предел, то входящие соединения принимаются только от хостов
из smtp_reserv_hosts)
- smtp_ratelimit_hosts (вычисляемый список хостов; unset; если хост входит
в этот список, то smtp_ratelimit_mail и smtp_ratelimit_rcpt ограничивают
скорость прихода сообщений с него)
- smtp_ratelimit_mail (строка; unset; содержит список из четырех
значений через запятую, ограничивающий частоту поступления команды MAIL:
нижний порог, начальная задержка (здесь разрешаются доли секунды),
множитель для увеличения задержки; максимальное значение задержки
(не должно быть более 5 минут); автор рекомендует: 2,0.5s,1.05,4m)
- smtp_ratelimit_rcpt (строка; unset; содержит список из четырех
значений через запятую, ограничивающий частоту поступления команды RCPT;
автор рекомендует: 4,0.25s,1.015,4m)
- smtp_receive_timeout (время; 5m; это значение рекомендовано в RFC)
- smtp_reserve_hosts (вычисляемый список хостов; unset; определяет список
хостов для которых резервируются соединения в smtp_accept_reserv и
smtp_load_reserv)
- split_spool_directory (boolean; false; разбить директорию спула на 62
поддиректории; это ускоряет обработку большого количества файлов
в спуле)
- strip_excess_angle_brackets (boolean; false; удалять лишний уровень
угловых скобок из адресов, иначе они вызывают синтаксическую ошибку)
- strip_trailing_dot (boolean; false; удалять лишнюю точку в конце адреса,
иначе она вызывает синтаксическую ошибку)
- syslog_timestamp (boolean; true; ставить временную отметку на сообщениях,
посылаемых через syslog)
- system_filter (вычисляемая строка; unset; задает имя файла, в котором
хранится системный фильтр; он применяется ко всем сообщениям при
каждой попытке отправки перед маршрутизацией)
- system_filter_directory_transport (вычисляемая строка; unset;
задает имя транспорта, который будет использован при вызове команды
save в системном фильтре и задании имени файла, заканчивающегося на /
(сохранение каждого сообщения в отдельном файле))
- system_filter_file_transport (вычисляемая строка; unset;
задает имя транспорта, который будет использован при вызове команды
save в системном фильтре и задании имени файла, не заканчивающегося на /)
- system_filter_group (строка; unset; задает gid, под которым будет
запущен системный фильтр)
- system_filter_pipe_transport (вычисляемая строка; unset;
задает имя транспорта, который будет использован при вызове команды
pipe в системном фильтре)
- system_filter_reply_transport (вычисляемая строка; unset;
задает имя транспорта, который будет использован при вызове команды
mail в системном фильтре)
- system_filter_user (строка; unset; задает uid, под которым будет
запущен системный фильтр; если не установлено, то выполняется
как часть процесса отправки, то есть с правами root)
- timeout_frozen_after (время; 0s; замороженное сообщение, которое находится
в очереди дольше указанного времени, удаляется из нее при следующей
обработке; если это не было само по себе сообщение об ошибке доставки, то
генерируется такое сообщение и посылается отправителю)
- timezone (строка; unset; надеюсь, что все установилось правильно при
сборке)
- настройка TLS
- trusted_groups (задает список групп, члены которых считаются доверенными,
т.е. могут подделывать поле Sender: и т.п.)
- trusted_users (задает список доверенных пользователей)
- untrusted_set_sender (вычисляемый список адресов; unset;
разрешить недоверенным пользователям подделывать адрес отправителя
из этого списка; можно использовать $sender_ident для вычисления списка)
- warn_message_file (строка; unset; задает имя файла, содержащего шаблон
текста предупреждения о задержке сообщения в очереди более
delay_warning)
Очередность проверки условий перед выбором маршрутизатора:
- local_part_prefix (локальная часть адреса имеет указанный префикс,
который немедленно удаляется)
- local_part_suffix (локальная часть адреса имеет указанный суффикс,
который немедленно удаляется)
- verify (verify_sender, verify_recipient) и verify_only
(маршрутизатор может быть предназначен только для
верификации адреса или только для реальной отправки письма или для обоих
действий)
- address_test (пропустить маршрутизатор, если exim запущен в режиме
тестирования адресов: -bt)
- expn (маршрутизатор может быть запрещено использовать при обработке команды
EXPN)
- domains (доменная часть адреса входит в указанный список доменов)
- local_parts (локальная часть адреса входит в указанный список)
- check_local_user (локальная часть адреса должна соответствовать
учетной записи пользователя на хосте)
- router_home_directory (?)
- senders (адрес отправителя должен быть в указанном списке)
- require_files (проверяется наличие или отсутствие указанного файла)
- condition (вычисляется условное выражение)
Общие опции маршрутизаторов (тип; значение по умолчанию; описание):
- address_data (вычисляемая строка; unset; вычисляется после проверки
предварительных условий перед запуском маршрутизатора;
если вычисление заканчивается явной ошибкой (forced to fail),
то маршрутизатор отвергается; при других ошибках обработка
откладывается; результат доступен в $address_data даже после
отработки маршрутизатора (до следующей address_data);
используется для извлечения всех связанных с адресом данных из БД
в один прием)
- caseful_local_part (boolean; false; считать локальную часть
чувствительной к регистру)
- check_local_user (boolean; false; это предусловие;
локальная часть адреса должна
соответствовать учетной записи пользователя на хосте;
устанавливается $home)
- condition (вычисляемая строка; unset; это предусловие;
если результат есть пустая строка,
"0, "no", "false" или forced fail, то маршрутизатор пропускается;
при других ошибках обработка откладывается)
- debug_print (вычисляемая строка; unset; отладочная печать)
- domains (вычисляемый список доменов; это предусловие;
если доменная часть адреса не входит
в указанный список доменов, то маршрутизатор пропускается;
в $domain_data помещается результат поиска в БД)
- driver (строка; unset; тип маршрутизатора; обязательная опция)
- errors_to (вычисляемая строка; unset; если маршрутизатор принял адрес
к обработке, но возникли проблемы с доставкой, то сообщения об ошибке
будут направлены на errors_to; по умолчанию используется адрес
отправителя из конверта; при передаче письма дальше по SMTP отправителем
в конверте указывается errors_to)
- expn (boolean; true; это предусловие;
не пропускать маршрутизатор при обработке EXPN)
- fail_verify (boolean; false; fail_verify_sender &
fail_verify_recipient)
- fail_verify_recipient (boolean; false; если адрес принят маршрутизатором
при верификации получателя, то верификация неуспешна)
- fail_verify_sender (boolean; false; если адрес принят маршрутизатором
при верификации отправителя, то верификация неуспешна)
- fallback_hosts (список; unset; если маршрутизатор ставит адрес в
очередь для доставки по smtp, то список хостов и ip адресов используется
вместо fallback_hosts, указанного в транспорте)
- group (строка; unset; если маршрутизатор ставит адрес в очередь
и в описании транспорта не указана группа, то используется group;
если установлена check_local_user, то по умолчанию группа извлекается
из passwd)
- headers_add (вычисляемая строка; unset; список добавляемых
при маршрутизации адреса полей заголовка через \n)
- headers_remove (вычисляемая строка; unset; список имен удаляемых
полей заголовка)
- ignore_target_host (вычисляемый список хостов; unset; если ip адрес
удаленного хоста входит в этот список, то exim возвращает сообщение
"unrouteble domain"; очень полезно включить в этот список 127.0.0.1)
- local_part_prefix (список; unset; это предусловие;
проверяется, что локальная часть адреса
имеет указанный префикс, который немедленно удаляется, иначе
маршрутизатор пропускается; допускается ограниченный вид шаблона
в виде начальной звездочки)
- local_part_prefix_optional (boolean; false; не пропускать маршрутизатор,
если local_part_prefix не обнаружен)
- local_part_suffix (список; unset; это предусловие;
аналогично prefix, но звездочка может
быть только последним символом)
- local_part_suffix_optional (boolean; false; не пропускать маршрутизатор,
если local_part_suffix не обнаружен)
- local_parts (вычисляемый список локальных частей; unset;
это предусловие; маршрутизатор
выполняется только, если локальная часть адреса входит в список;
можно использовать $domain; возвращаемые при поиске данные доступны в
$loacal_part_data)
- log_as_local (boolean; true для accept и false для остальных;
адрес локальных получателей записывается в журнал без указания домена)
- more (boolean; true; если маршрутизатор запускается для адреса, но
отвергает его (decline), то пробовать следующий маршрутизатор;
перебивается опцией self=pass)
- pass_on_timeout (boolean; false; если истекло время ожидания при
DNS запросе, то передать следующему маршрутизатору вместо
откладывания в очередь)
- pass_router (строка; unset; если маршрутизатор передает письмо для
обработки следующему маршрутизатору, то здесь можно указать
его имя; по умолчанию - следующий по списку; нельзя переходить
вверх по списку)
- redirect_router (строка; unset; сгенерированные адреса начнут
обработку с указанного маршрутизатора вместо первого по списку)
- require_files (вычисляемый список строк; unset; это предусловие;
проверяется наличие или отсутствие (! перед именем) указанного файла;
используется абсолютное имя файла; перед именем файла может указываться
имя пользователя, запятая, имя группы и двоеточие для проверки прав
доступа; во время приема почты по SMTP exim работает с правами exim,
а при отправке из очереди с правами root, что может сказаться на
возможности проверки файлов)
- retry_use_local_part (boolean; true для маршрутизаторов, использующих
check_local_user; использовать ли локальную часть для управления
повторными попытками доставки)
- self (строка; "freeze"; используется маршрутизаторами, которые
определяют по адресу список удаленных хостов - dnslookup и manualroute,
в ситуации, когда первый хост в получившемся списке является
локальным (совпадение ip адреса) или указан в hosts_treat_as_local;
альтернативы:
- freeze (отметить в журнале и заморозить письмо)
- defer (отложить отправку до следующей попытки)
- reroute:домен (изменить домен и начать маршрутизацию заново)
- reroute:rewrite:домен (-//- и переписать заголовок)
- pass (передать обработку следующему маршрутизатору или
указанному в pass_router)
- fail (генерировть сообщение об ошибке доставки)
- send (поставить в очередь для отправки невзирая на)
- senders (вычисляемый список адресов; unset; это предусловие;
адрес отправителя должен быть в указанном списке)
- transport (вычисляемая строка; unset; вычисляется во время
маршрутизации и задает имя использумого транспорта)
- transport_current_directory (вычисляемая строка; unset;
используется для локальных транспортов)
- transport_home_directory (вычисляемая строка; если используется,
check_local_user, то по умолчанию устанавливается в его домашнюю
директорию, иначе unset;
используется для локальных транспортов)
- unseen (boolean; false; передать сообщение для обработки следующему
маршрутизатору даже если оно было принято текущим маршрутизатором;
позволяет клонировать письма)
- user (строка; unset; если маршрутизатор ставит адрес в очередь
и в описании транспорта не указан пользователь, то используется user;
если установлена check_local_user, то по умолчанию user извлекается
из passwd)
- verify (boolean; true; это предусловие; verify_sender &
verify_recipient)
- verify_only (boolean; false; это предусловие; маршрутизатор используется
только во время верификации адреса)
- verify_recipient (boolean; true; это предусловие; не пропускать во
время верификации адресов получателей)
- verify_sender (boolean; true; это предусловие; не пропускать во
время верификации адресов отправителей)
Маршрутизатор accept. При выполнении предусловий принимает
письмо к обработке и ставит в очередь к указанному транспорту. Дополнительных
опций не имеет.
Маршрутизатор dnslookup. Транспорт и хост определяются по DNS.
Сначала проверяются MX записи. Если MX запись не обнаружена и домен не указан
в опции mx_domain, то просматриваются адресные записи. MX записи с одинаковым
приоритетом сортируются случайным образом. Из получившегося списка удаляются
ссылки на локальный хост и хосты из списка hosts_treat_as_local (и все
хосты с равным и более низким приоритетом), если только они не имеют
максимальный приоритет (смотри опцию self). Дополнительные опции:
- check_secondary_mx (boolean; false; маршрутизатор отказывается
обрабатывать адреса, если локальный хост не найден в списке MX;
испольуется для специальной обработки доменов, для которых
наш сервер является запасным)
- mx_domains (вычисляемый список доменов; unset; список доменов,
для которых требуется наличие записи MX)
- same_domain_copy_routing (boolean; false; оптимизация маршрутизации
многих адресов из одного домена при условии, что маршрутизация не
зависит от локальной части)
- некоторое количество опций, управляющих работой резольвера;
по-моему, это лучше делать через resolv.conf
Маршрутизатор ipliteral. Не рекомендуется использовать.
Маршрутизатор iplookup. Используется только разработчиками
exim.
Маршрутизатор manualroute.
Транспорт и хост определяются шаблонами в обход системы DNS и MX.
Маршрутизатор queryprogram. Транспорт и хост вычисляются
внешней программой.
Маршрутизатор redirect.
Опции, применимые для всех транспортов:
- body_only (boolean; false; заголовок не передается)
- current_directory (вычисляемая строка; unset; текущая директория,
устанавливаемая при запуске транспорта)
- debug_print (вычисляемая строка; unset; отладочная печать)
- delivery_date_add (boolean; false; добавить поле заголовка Delivery-Date:)
- driver (строка; unset; тип транспорта)
- envelop_to_add (boolean; false; добавить поле заголовка Envelope-to:)
- group (строка; exim; gid для выполнения транспорта)
- headers_add (вычисляема строка; unset; список добавляемых
при транспортировке полей заголовка через \n)
- headers_only (boolean; false; тело письма не передается)
- headers_remove (вычисляемая строка; unset; список имен удаляемых
полей заголовка)
- headers_rewrite (строка; unset; адреса в заголовке преобразуются
при транспортировке; строка содержит список правил преобразования;
добавленные маршрутизатором и транспортом поля не преобразуются;
адреса в конверте не преобразуются)
- home_directory (вычисляемая строка; unset)
- message_size_limit (вычисляемая строка; 0; если размер письма больше,
то доставка завершается аварийно)
- retry_use_local_part (boolean; true для маршрутизаторов, использующих
check_local_user; использовать ли локальную часть для управления
повторными попытками доставки; для удаленных транспортов пока
не реализовано)
- return_path (вычисляемая строка; unset; замещает адрес отправителя
в конверте)
- return_path_add (boolean; false; добавлять поле заголовка
Return-Path:)
- transport_filter (вычисляемая строка; unset; задает команду,
запускаемую как отдельный процесс; письмо подается на stdin команды;
стандартный вывод команды посылается в качестве письма)
- user (строка; exim; uid для выполнения транспорта)
Транспорт smtp. В момент запуска $host и $host_address
есть имя и адрес первого хоста в списке, переданном маршрутизатором.
Перед соединением с конкретным хостом и во время соединения в них
помещается имя и адрес этого хоста. Опции:
- allow_localhost (boolean; false;
appendfile, autoreply, pipe, lmtp.
ACL вызываются общими опциями
acl_smtp_auth, acl_smtp_data, acl_smtp_etrn, acl_smtp_expn, acl_smtp_rcpt,
acl_smtp_vrfy. Если acl_smtp_auth не определена, то команда
AUTH всегда разрешается. Если acl_smtp_data не определена, то проверок
после получения сообщения не производится. Если не определена
acl_smtp_etrn, acl_smtp_expn, acl_smtp_rcpt или acl_smtp_vrfy, то
соответствующая команда не принимается. В опциях вместо имени ACL
может быть указано абсолютное имя файла, в котором должен лежать ACL.
Строка опции вычисляется перед использованием, что позволяет динамически
задавать имя ACL или имя файла. Если вычисленная строка не начинается
с косой черты и ACL с таким именем не найдена, то строка интерпретируется
как встроенный ACL.
Результатом проверки ACL может быть
accept (принято, код SMTP - 2xx), deny (не принято, 5xx),
defer (временный сбой, 4xx), error (ошибка синтаксиса, 4xx).
При обработке ACL для DATA доступна информация об
удаленном хосте и отправителе ($sender_host_address, $sender_address).
При обработке ACL для RCPT доступна информация об удаленном хосте и отправителе,
а также информация о получателе ($domain, $local_part).
При обработке ACL для других команд их аргументы доступны в
$smtp_command_argument.
Секция ACL начинается со строки "begin acl" и завершается
перед следующей секцией (слово "begin" в начале строки). Каждый
поименованный ACL начинается со строки, состоящей из его имени и двоеточия.
Завершается ACL началом следующего ACL или следующей секции.
В конце ACL подразумевается безусловная команда deny.
Каждая строка содержит команду, начинающуюся с действия, за которым
могут следовать условия и/или модификаторы (каждое на отдельной строке).
Если начало строки не содержит
действия (например, пробел), то она содержит условие или модификатор для
предыдущей команды. Отрицание условия обозначается восклицательным
знаком перед ним. Аргументы условий и модификаторов вычисляются
(forced fail при вычислении интерпретируется как удовлетворение условия).
Действие выполняется, если удовлетворены все условия или их нет (см.
исключения).
Действия:
- accept (если неудовлетворенное условие записано до условия endpass,
то управление передается следующей команде, если - после, то
обработка ACL завершается с результатом deny)
- deny
- require (если удовлетворены все условия, то управление передается
следующей команде, иначе обработка ACL завершается с результатом deny)
- warn (управление всегда передается следующей команде;
если удовлетворены все условия, то выполняется указанное
предупреждающее действие (message?))
Модификаторы:
- endpass (см. описание accept)
- log_message = текст (добавляется к сообщению, записываемому в журнал
при запрете доступа; текст вычисляется после проверки всех
условий, так что можно использовать установленные там переменные)
- message = текст (текст возвращается как сообщение об ошибке SMTP
при запрете доступа; текст вычисляется после проверки всех
условий, так что можно использовать установленные там переменные;
используется также для записи в журнал, если log_message не задан)
Условия:
- acl = имя ACL или непосредственная команда или абсолютное имя файла
(вызов подпрограммы; глубина вложения не более 20; возврат
accept означает выполнение условия; возврат deny означает невыполнение
условия; возврат defer приводит к завершению обработки текущего
ACL с результатом defer; кстати, строка-то вычисляется)
- authenticated = список аутентификаторов (если соединение не
аутентифицировано, то условие ложно, иначе имя аутентификатора
ищется в списке)
- condition = строка (если результат вычисления строки есть пустая строка,
"0", "no" или "false", то условие ложно)
- dnslists = список доменных имен и сопутствующей информации
(проверка вхождения в черные списки, известные как RBL;
устанавливает переменные $dnslist_domain, $dnslist_value,
$dnslist_text; например: dnslists=dialups.mail-abuse.org)
- domains = список доменов (только для RCPT; проверяет, что
домен получателя входит в список)
- encrypted = список методов шифрования (если соединение не
зашифровано, то условие ложно, иначе имя метода шифрования
ищется в списке)
- hosts = список хостов (проверяет, что удаленный хост входит в список;
ip адреса надо помещать в список до имен)
- local_parts = список локальных частей (только для RCPT; проверяет, что
локальная часть адреса получателя входит в список)
- recipients = список адресов (только для RCPT; проверяет, что
адрес получателя входит в список)
- sender_domains = список доменов (проверяет, что домен отправителя
входит в список)
- senders = список адресов (проверяет, что адрес отправителя
входит в список)
- verify = certificate (сессия зашифрована, клиент предоставил сертификат
и он верифицирован)
- verify = header_sender/опции
(только для DATA; проверяет наличие верифицированного адреса отправителя
в Sender:, Reply-To: или From:)
- verify = header_syntax (только для DATA; проверяет синтаксис полей
заголовка, содержащих адреса (Sender:, From:, Reply-To:, To:, CC:, Bcc:))
- verify = helo
- verify = recipient/опции (только для RCPT; верифицирует получателя)
- verify = reverse_host_lookup (по адресу получается список имен, для
каждого имени получается список адресов и проверяется, что исходный
адрес имеется в одном из этих списков - double check)
- verify = sender/опции (только для RCPT; верифицирует отправителя)
- verify = sender=address/опции
Верификация header_sender, recipient, sender.
Сначала адрес маршрутизируется в режиме верификации.
Опции:
- defer_ok (если маршрутизация в режиме верификации возвращает defer,
то считать, что верификация удалась)
- callout (для неместных адресов; exim делает SMTP соединение и пытается
определить, есть ли там такой почтовый ящик; не советую использовать -
съедят;)
- callout_defer_ok
Секция retry содержит набор правил,
определяющих для сочетания тройки хост, адрес
и тип ошибки интервал повторения попыток доставки для тех сообщений,
которые не удалось доставить немедленно, и максимальное время нахождения
в очереди. Если письмо не
подпадет ни под одно правило, то оно останется в очереди навечно.
При истечении максимального времени нахождения в очереди, генерируется
сообщение об ошибке. Каждое правило действует как на маршрутизатор, так и
на транспорт. После ошибок маршрутизации каждое правило сопоставляется
только с доменом в адресе. После ошибок транспортировки каждое
правило сопоставляется сначала с именем удаленного хоста, а затем
с доменом в адресе.
Правило занимает отдельную строку состоит из трех частей,
разделенных пробелом:
- вычисляемая перед использованием строка, которая представляет собой
один элемент списка адресов; если в качестве шаблона указано только имя
домена, то к нему перед применением приписывается строка "*@";
- имя ошибки или звездочка:
- auth_failed
- refused_MX (не удалось соединиться с хостом, имя которого получено
из MX записи)
- refused_A (не удалось соединиться с хостом, имя которого получено
не MX записи)
- refused
- timeout_connection
- timeout_DNS
- quota (квота ОС, квота appendfile или нет места на диске)
- список наборов параметров повтора, разделенных точкой с запятой;
отсутствие хотя бы одного набора означает немедленную генерацию сообщения
об ошибке; каждый набор содержит три элемента, разделенных запятыми:
- тип алгоритма
- F (повторение с фиксированным интервалом; параметр - размер
интервала)
- G (повторение с геометрически увеличивающимся размером
интервала; первый параметр - размер первого интервала;
второй параметр - мультипликатор)
- интервал (отсчитывается от времени первой неудачной доставки
для этого домена),
после которого применение набора заканчивается и
начинается применение следующего набора
- параметры
Время повторения - это намек, а не обещание ;).
Никто не гарантирует, что повторная доставка будет сделана именно в это время.
Время повторной доставки зависит от интервала обработки очереди или прихода
новых писем, направляемых в тот же домен.
Утилита exinext позволяет узнать для указанного
адреса или домена причину ошибки, когда были первая и последняя неудачные
попытки, когда ожидать следующую попытку доставки.
Аутентификаторы позволяют реализовать
расширения SMTP протокола (RFC 2554), касающиеся аутентификации клиента
с помощью метапротокола SASL (EHLO/AUTH).
Необходимые типы аутентификаторов должны быть заданы при сборке.
Порядок описания аутентификаторов важен.
Возможные типы аутентификаторов:
- plaintext (механизм PLAIN, псевдомеханизм LOGIN)
- cram_md5 (механизм CRAM-MD5)
- cyrus_sasl (только в роли сервера; механизмы определяются
библиотекой Cyrus SASL
- spa (механизм NTLM)
exim может выступать
с точки зрения аутентификации как в роли сервера, так и в роли клиента
(реализовано неполностью). Драйвер аутентификации может использоваться
в обоих случаях. Имена опций можно предварять префиксами "server_" или "client_",
чтобы определить роль сервера, при которой они используются.
После аутентификации клиента exim заполняет переменные $received_protocol ("esmtpa")
и $sender_host_authenticated (имя драйвера).
Необходимость аутентификации в роли клиента определяется опциями транспорта
(hosts_require_auth, hosts_try_auth) и анонсированными механизмами аутентификации
сервера. При этом можно использовать переменные $host и $host_address.
Общие опции (заголовок секции начинается с имени драйвера и двоеточия):
- driver (тип аутентификатора)
- public_name (имя SASL механизма)
- server_advertise_condition (показывать ли клиенту наличие механизма, см.
также общую опцию auth_advertise_hosts и acl_smtp_auth)
- server_debug_print
- server_set_id (вычисляется при успешной аутентификации клиента и сохраняется в
$authenticated_id)
- server_mail_auth_condition (реакция на MAIL AUTH= для аутентифицированных
данным драйвером соединений: если false, то очищать $authenticated_sender;
предварительно ACL acl_smtp_mailauth определяет - принимать ли
такую команду вообще и помещать ли значение AUTH= в $authenticated_sender
для аутентифицированных клиентов; $authenticated_sender используется
при передаче принятого сообщения следующему серверу, т.е. когда exim
выступает в ролт клиента)
Опции драйвера типа plaintext
- server_prompts (список приглашений через двоеточие; от клиента принимается
список строк, разделённых нулевыми байтами (Base64), которые размещаются
в $1, $2 и т.д.)
- server_condition (позволяет аутентифицировать клиента на основе значений
переменых $1, $2 и т.д.)
- client_send (последовательность вычисляемых строк через двоеточие;
первая строка посылается в команде AUTH, остальные по запросам сервера;
символ '^' заменяется на нулевой байт)
Механизм PLAIN определяет в качестве приглашения пустую строку,
имя пользователя во второй строке ответа, пароль - в третьей:
plain_server:
driver = plaintext
public_name = PLAIN
server_prompts = :
server_condition = \
${if and {{eq{$2}{username}}{eq{$3}{mysecret}}}{yes}{no}}
server_set_id = $2
plain_client:
driver = plaintext
public_name = PLAIN
client_send = ^username^mysecret
Механизм LOGIN определяет в качестве приглашения две строки
с запросом имени и пароля, имя пользователя в первой строке ответа, пароль - во второй,
например (использованы приглашения, "любимые" MS OE):
login_server:
driver = plaintext
public_name = LOGIN
server_prompts = Username:: : Password::
server_condition = \
${if and {{eq{$1}{username}}{eq{$2}{mysecret}}}{yes}{no}}
server_set_id = $1
login_client:
driver = plaintext
public_name = LOGIN
client_send = : username : mysecret
Опции драйвера типа cram_md5:
- server_secret (вычисляемая строка; определяет пароль пользователя;
перед вычислением в $1 кладётся имя пользователя)
- client_name (различные имена могут генерироваться, например, основываясь
на значении переменных $host и $host_address)
- client_secret
Опции драйвера типа cyrus_sasl (необходимо обеспечить права
доступа exim к файлам, требуемым Cyrus SASL; реализована только роль сервера!):
- server_hostname ($primary_hostname)
- server_mech (по умолчанию определяется по public_name)
- server_realm
- server_service
Опции драйвера типа spa (public_name = NTLM):
- server_password (вычисляемая строка; определяет пароль пользователя;
перед вычислением в $1 кладётся имя пользователя)
- client_domain
- client_username
- client_password
Поддержку TLS (SSL) необходимо включить явно при сборке.
Требуется наличие OpenSSL или GnuTLS (версия 1.0 или выше).
При этом необходимо заранее заготовить
незашифрованный ключ (exim:exim, 400)
и сертификат сервера,
подпись сертификата.
Системные переменные:
- $tls_certificate_verified
- $tls_cipher (например, для OpenSSL - DES-CBC3-SHA, для GnuTLS - RSA_ARCFOUR_SHA)
- $tls_peerdn (Distinguished Name клиента, OpenSSL разделяет простые имена символом
'/', GnuTLS - запятыми)
Опции конфигурации:
- tls_advertise_hosts (вычисляемый список хостов; unset; хостам из этого
списка в ответ на EHLO рекламируется наличие TLS)
- tls_certificate (вычисляемая строка; unset; имя файла, содержащего
сертификат сервера; этот сертификат используется только при приёме;
если сертификат подписан не корневым CA, то файл может содержать
сертификат этого промежуточного CA)
- tls_crl (вычисляемая строка; unset; имя файла, содержащего
CRL (список отозванных сертификатов) в формате PEM)
- tls_dhparam (вычисляемая строка; unset; имя файла, содержащего
значения параметра DH сервера; см. openssl dhparam; если не задан,
то используется только RSA механизм взаимодействия)
- tls_on_connect_ports (вычисляемый список номеров портов; unset;
подключающийся к указанным портам клиент должен использовать протокол SMTPS;
обычный номер порта - 465; прослушивание портов необходимо включить отдельно)
- tls_privatekey (вычисляемая строка; unset; имя файла, содержащего
приватный ключ сервера)
- tls_remember_esmtp (вычисляемая строка; unset; не сбрасывать параметры
сессии, полученные до STARTTLS; так не стоит делать)
- tls_require_ciphers (вычисляемая строка; unset; вычисляется при каждом соединении;
представляет собой список (через двоеточие) наборов шифрования,
например, DES-CBC3-SHA; тире и подчёркивания преобразуются к виду приемлимому
для OpenSSL или GnuTLS; список всех наборов для OpenSSL можно получить
командой: openssl list-cipher-commands; можно использовать сокращения (AES, !RC2)
или выражения (AES+SHA1))
- tls_verify_hosts (вычисляемый список хостов; unset;
клиент обязан предоставить сертификат; tls_verify_certificates
должен быть установлен)
- tls_try_verify_hosts (вычисляемый список хостов; unset;
попробовать получить сертификат клиента)
- tls_verify_certificates (вычисляемая строка; unset;
имя файла или каталога (только OpenSSL),
содержащего ожидаемые сертификаты клиентов;
имена файлов в директории должны иметь вид "хеш.0";
хеш можно получить с помощью команды "openssl x509 -hash -noout -in имя-файла")
Транспорт типа smtp имеет опции:
- hosts_avoid_tls (вычисляемый список хостов; unset; не пытаться использовать
STARTTLS при передаче на эти хосты)
- hosts_nopass_tls (вычисляемый список хостов; unset;
не использовать повторно созданный защищённый канал)
- hosts_require_tls (вычисляемый список хостов; unset)
- tls_certificate (вычисляемая строка; unset; имя файла, содержащего
сертификат; этот сертификат используется только при передаче)
- tls_crl (вычисляемая строка; unset; имя файла, содержащего
CRL (список отозванных сертификатов) в формате PEM)
- tls_privatekey (вычисляемая строка; unset; имя файла, содержащего
приватный ключ сервера)
- tls_require_ciphers (вычисляемая строка; unset)
- tls_tempfail_tryclear (boolean; true; если принимающий хост не входит
в hosts_require_tls и возникли временные (4xx) проблемы с защищённой сессией,
то посылать открытым текстом вместо задержки сообщения)
- tls_verify_certificates (вычисляемая строка; unset;
имя файла или каталога (только OpenSSL),
содержащего ожидаемые сертификаты серверов)
ACL для проверки команды STARTTLS задаётся опцией
acl_smtp_starttls.
Следующее условие ACL требует наличия верифицированного сертификата
клиента (tls_verify_hosts, tls_try_verify_hosts):
verify = certificate
Имеются следующие селекторы журнала:
- tls_cipher (использованный набор шифрования)
- tls_peerdn (Distinguished Name из сертификата клиента)
Ключи командной строки:
- -bd (запуск в режиме демона: отсоединиться от терминала и принимать входящие TCP-соединения на всех интерфейсах)
- -bdf (запуск в режиме демона без отсоединения от терминала)
- -C имя-конфигурационного-файла
- -Dимя-макро=значение-макро
- -odb (фоновая отправка полученного сообщения - процесс отправки
запускается, но принимающий процесс не дожидается его завершения;
перекрывает действие опции queue_only)
- -odq (полученное сообщение кладется в очередь;
аналогичен действию опции queue_only)
- -odqs (запускается фоновая отправка письма, адрес маршрутизируется,
локальная транспортировка обрабатывается, но транспортиjвка SMTP откладывается
в очередь; такое поведение позволяет пакетировать отправку нескольких
сообщений на один хост; аналогичен действию опции queue_smtp_domain)
- -os время (максимальное время ожидания SMTP команды
или блока данных; по умолчанию - 5 минут)
- -oX номер-порта (какой порт прослушивать; опция
daemon_smtp_port)
- -oX список-интерфейсов (какие интерфейсы и порты
прослушивать; в формате опции local_interfaces)
Обработка сигналов:
- SIGHUP - перезапуститься (используется при изменении конфигурационного
файла или самого exim, остальные файлы читаются заново при каждом
использовании)
Ключи командной строки:
- -bm (адрес получателя задается в качестве
параметра (или берется из заголовка письма, если используется ключ -t);
письмо читается со стандартного ввода неинтерактивно)
- -bS (адрес получателя задается в начале
текста письма в виде команд RCPT, завершаемых командой DATA (batch SMTP);
письмо читается со стандартного ввода неинтерактивно; HELO и EHLO действуют
как RSET; VRFY, EXPN, ETRN, и HELP игнорируются)
- -bs (письмо читается со стандартного
ввода в интерактивном режиме с эмуляцией SMTP протокола; проверки ACL
производятся как для настоящего SMTP; используется также, если exim
вызывается из inetd/xinetd)
- -dropcr (при приеме локальной почты предполагается, что
строки завершаются одним LF; данный ключ указывает, что строки
завершаются CRLF; CR при хранении в очереди отбрасывается)
- -F строка (имя отправителя; по умолчанию используется
поле GECOS из /etc/passwd)
- -f адрес-отправителя (может использоваться только
доверенными (trusted) пользователями; по умолчанию в качестве локальной
части используется учетное имя пользователя, запустившего программу, а в
качестве доменной части - значение qualify_domain; если не совпадает
с полем заголовка From:, то exim добавляет поле Sender:)
- -odf (приняв письмо, exim дожидается его доставки перед
завершением процесса)
- -oee (сообщение об ошибке отправляется почтой,
код возврата определяется успешностью посылки сообщения об ошибке)
- -oem (сообщение об ошибке отправляется почтой,
код возврата не нуль, если была ошибка)
- -oep (сообщение об ошибке выводится на stderr)
- -oi (отдельная точка на строке не завершает ввод сообщения)
- -oMa, -oMaa, -oMas, -oMai, -oMi,
-oMr, -oMs, -oMt позволяют доверенному пользователю задать
"вручную" адрес хоста и номер порта отправителя, аутентификацию, адрес
интерфейса, имя принимающего протокола, имя хоста отправителя
- -or время (максимальное время ожидания ввода)
- -t (адреса получателей извлекаются из полей заголовка
To:, Cc: и Bcc: до преобразования адресов; адреса, заданные в аргументах
командной строки, удаляются из списка получателей; сообщения с полями
заголовка Recent- не обрабатываются)
Запуск exim с ключом -bp выводит содержимое
очереди. В качестве параметра может быть указан идентификатор сообщения.
Выводится время нахождения в очереди, размер сообщения, локальный
идентификатор сообщения, адрес отправителя. Для замороженного сообщения
выдается пометка "*** frozen ***". В последующих строках
выводятся адреса получателей. Адреса, по которым сообщение уже отправлено,
помечаются буквой D.
Если exim выполняется под именем mailq,
то он работает, как если бы exim запускался с ключом -bp.
Ключ -bpa действует аналогично -bp,
но дополнительно показывает сгенерированные адреса.
Ключ -bpu действует аналогично -bp, но
показываются только те адреса получателей, которым письмо еще не
отправлено.
Ключ -bpc выводит общее число сообщений в очереди.
При запуске exim с ключом
-M идентификатор-сообщения ... он пытается отправить указанное
сообщение из очереди. Замороженное сообщение предварительно размораживается.
Игнорируются все ограничения на повтор отправки.
Ключ
-Mar идентификатор-сообщения адрес ...
добавляет список получателей к сообщению в очереди.
Ключ
-Mes идентификатор-сообщения адрес
изменяет адрес отправителя указанного сообщения в очереди.
Ключ -Mf идентификатор-сообщения ...
замораживает сообщение.
Ключ -Mg идентификатор-сообщения ...
прекращает дальнейшие попытки послать сообщение. В тексте посылаемого
в результате сообщения об ошибке доставки будет сказано:
"cancelled by administrator".
Ключ -Mmad идентификатор-сообщения ...
делает пометку о доставке для всех адресов получателей.
Ключ
-Mmd идентификатор-сообщения адрес ...
делает пометку о доставке для указанных адресов получателей.
Ключ -Mrm идентификатор-сообщения ...
молча удаляет сообщение из очереди.
Ключ -Mt идентификатор-сообщения ...
размораживает сообщение.
Ключ -q сканирует очередь и пытается
отправить все найденные сообщения по одному разу. Дожидается завершения
отправки предыдущего сообщения перед обработкой следующего.
Некоторые сообщения могут быть пропущены в соответствии с установленными
правилами повтора посылки. Порядок обработки сообщений неопределен.
Ключ -qq. Обработка очереди в два прохода:
при первом проходе производится маршрутизация адресов и отправка локальной
почты. На втором проходе отправляется удаленная почта. Это позволяет
пакетизировать сообщения и особенно полезно для сервера, подключенного
к Интернет не в постоянном режиме..
Ключ -q[q]i. Обрабатывать только те
сообщения в очереди, для которых еще не было попыток отправки.
Ключ -q[q][i]f. Обрабатывать
сообщения, не обращая внимания на правила повтора.
Ключ -q[q][i]ff. Обрабатывать
сообщения, не обращая внимания на правила повтора и "замороженность".
Ключ -qинтервал. Обрабатывать очередь
многократно с указанным интервалом. Перед интервалом могут быть
указаны флаги q,i,f. Обычно комбинируется с ключом -bd, например:
exim -bd -q30m для одновременного приема сообщений по SMTP и обработки
очереди с инервалом в 30 минут.
Ключ -R[флаги] строка.
Однократная обработка тех сообщений в очереди, необслуженные адреса
получателей которых содержат указанную строку (независимо от регистра).
Если сообщение выбрано, то обрабатываются все его необслуженные адреса.
Дополнительные условия на успешность отправки по первому выбранному
адресу столь туманны, что пользоваться этим не хочется.
Используется для реализации ETRN.
Флаги могут быть: f, ff, r, rf, rff.
f означает обработку сообщений, не обращая внимания на правила повтора.
ff означает обработку сообщений, не обращая внимания на правила повтора
и состояние "замороженности". Если используется флаг r, то строка
рассматривается как регулярное выражение.
Ключ -S[флаги] строка.
Аналогично ключу -R, но сравнение строки производится с адресами
отправителей, а не получателей. Если используется одновременно с ключом
-R, то оба условия должны быть выполнены для отбора сообщения
в обработку.
Если exim выполняется под именем runq,
то он работает, как если бы exim запускался с ключом -q.
Если exim выполняется под именем newaliases, то он работает,
как если бы он выполнялся с опцией -bi. Мимикрия под поведение sendmail,
который в данном режиме перестраивает базу данных алиасов. Так как
exim не имеет единого файла алиасов, то требуемое действие задается
опцией bi_command в конфигурационном файле (например, перестройка
требуемых баз данных с помощью exim_dbmbuild).
Добавление ключа -dкатегория при вызове exim
позволяет вывести отладочную информацию на stderr. Категория представляет
собой строку имен, перед каждым из которых стоит знак плюс или
минус, например: -all+filter. Имена: acl, auth, deliver,
dns, dnsbl (black list), exec, filter, hints_lookup, host_lookup, ident,
interface, lists, load, lookup, memory, process_info, queue_run, receive,
resolver, retry, rewrite, route, tls, transport, uid, verify, all.
По умолчанию: +all-filter-interface-load-memory-resolver.
Отладочные ключи командной строки:
- -bV (проверка синтаксиса файла конфигурации)
- -N (имитирует отправку письма,
т.е. письмо проходит весь обычный путь за исключением того, что вместо
запуска транспорта сразу делается отметка об успешной доставке)
- -be (проверка механизма подстановки строк)
- -bf имя-файла (проверка работы фильтра пользователя)
- -bF имя-файла (проверка работы системного фильтра)
- -bh ip-адрес
(проверка блокировки приема почты с указанного хоста; имитируется
SMTP сессия с использованием stdin и stdout; используется утилитой
exim_checkaccess)
- -bP имя-опции
(выводит значение опции конфигурационного файла; опции с атрибутом
hide показываются только администратору (пароль mysql ;);
если аргумент опущен, то показываются все опции;
можно также использовать ключевые слова router_list, transport_list,
authenticator_list, routers, transports, authenticators)
- -brt (проверка
правила повторения попытки послать сообщения; в качестве аргумента
указывается адрес или имя домена; выдается текст подошедшего
правила)
- -brw (проверка
правила преобразования адресов; в качестве аргумента
указывается адрес или локальная часть; exim выводит, как бы он преобразовал
этот адрес, если бы он встретился в различных ситуациях)
- -bt (проверка
возможности отправить сообщение по указанному адресу; если адрес не
указан, то exim переходит в интерактивный режим)
Принимает почту от сервера верхнего уровня (там же стоит антиспам и антивирус) и локальных клиентов,
раздаёт по локальным POP/IMAP серверам (LMTP, cyrus-imap) и наверх.
Локальных ящиков не имеет. Доступа в Интернет здесь нет.
- установить пакет exim
- настройка /etc/exim/exim.conf
- primary_hostname = (имя хоста полезно задать явно, если хост имеет
множество интерфейсов)
- # ldap_default_servers = имя::389
- domainlist local_domains = (здесь нет почтовых ящиков)
- domainlist relay_to_domains =
- domainlist our_domain_with_internal_mail = (список доменов, для которых
мы принимаем почту на внутренний сервер)
- domainlist our_domain_with_external_mail = (список доменов, для которых
мы принимаем почту на внешний сервер)
- domainlist our_domain_without_mail = (список наших доменов,
у которых нет почты)
- hostlist relay_from_hosts = 127.0.0.1
- hostlist local_network = (список блоков адресов через ":")
- hostlist local_MTA = (список адресов внутренних SMTP серверов)
- acl_smtp_rcpt = rcpt (acl_check_rcpt оставить как образец)
- acl_smtp_mime = check_mime
- acl_smtp_data = check_data
- av_scanner = clamd:/var/run/clamav/clamd.sock
(антивирус clamav должен быть уже запущен)
- # заготовка под TLS
- #tls_advertise_hosts = +local_network (или все, если ваш сертификат заверен
общепризнанным CA, иначе могут быть проблемы)
- #tls_certificate = /etc/exim/имя-файла.crt
- #tls_privatekey = /etc/exim/имя-файла.key (права доступа - exim:exim, 400!)
- qualify_domain = имя-домена
- never_users = root
- #host_lookup = * (не надо, иначе невозможно получать почту с адресов,
DNS сервер которых возвращает "SERV FAILED")
- rfc1413_hosts = (какой ident в наше время?)
- rfc1413_query_timeout = 0s
- sender_unqualified_hosts = +local_network
- ignore_bounce_errors_after = 2d
- timeout_frozen_after = 14d
- auth_advertise_hosts =
- accept_8bitmime = true
- acl_smtp_auth = auth
- acl_smtp_etrn = etrn
- acl_smtp_expn = expn
- acl_smtp_vrfy = vrfy
- admin_groups = exim
- check_log_inodes = 10
- check_log_space = 10M
- check_spool_inodes = 1000
- check_spool_space = 50M
- delay_warning = 8h:24h:48h
- helo_accept_junk_hosts = * (спамеров фильтруется мало, а раздолбаев -
много)
- #helo_try_verify_hosts = * (верификацию rDNS надо делать позже,
чтобы запись была в журнале)
- host_reject_connection = (это невежливо)
- local_interfaces = 127.0.0.1.25 : основной-ip-адрес.25 : запасной-канал.25
(чтобы не проверял виртуальные интерфейсы)
- log_selector = +incoming_interface +incoming_port +delivery_size +smtp_confirmation +smtp_protocol_error +smtp_syntax_error +received_recipients +sender_on_delivery -retry_defer
- message_body_visible = 8000 (чем больше, тем больше требуется памяти и CPU)
- message_size_limit = 50M
- pipelining_advertise_hosts = +local_network : +relay_from_hosts
- recipients_max = 100
- recipients_max_reject = true
- smtp_accept_max_per_connection = 100
- smtp_accept_max_per_host = 20
- smtp_accept_reserve = 8
- smtp_connect_backlog = 50
- smtp_enforce_sync = false (глупая проверка - спамеров попадается мало,
а суетливых администраторов много)
- # overload limit
- queue_run_max = 5
- deliver_queue_load_max = 20
- queue_only_load = 40
- smtp_load_reserve = 90
- smtp_accept_max = 90
- smtp_reserve_hosts = +local_network : +relay_from_hosts
- smtp_accept_reserve = 8
- секция acl
begin acl
auth:
deny
rcpt:
# postmaster должен получать всё :(
accept local_parts = postmaster
domains = +local_domains : +relay_to_domains : +our_domain_with_internal_mail :
+our_domain_with_external_mail
# проверка наличия у нас такого ящика
deny domains = +local_domains : +relay_to_domains : +our_domain_with_internal_mail : +our_domain_with_external_mail
!local_parts = /etc/exim/our_users
# или проверка на наличие в LDAP
# condition = ${if eq {${lookup ldap{ldap:///uid=${quote_ldap:$local_part},ou=People,dc=имя-каталога?uid} \
{$value}fail}} {$local_part} {no} {yes}}
message = User unknown (имя-нашего-домена)
# при расхождении в LDAP между uid и email (нельзя смешивать accept и fail, можно иметь несколько mail для uid)
# deny domains = +local_domains : +relay_to_domains : +our_domain_with_internal_mail
# condition = ${lookup ldap{ldap:///ou=People,dc=имя-каталога?mail?sub?(&(objectClass=inetOrgPerson)\
# (mail=${local_part}@${domain}))} {no} fail}
# message = User unknown (имя-нашего-домена)
accept hosts = +local_MTA
control = submission/sender_retain
accept hosts = +relay_from_hosts
control = submission
accept hosts = +local_network
control = submission/domain=имя-нашего-домена
accept domains = +relay_to_domains : +our_domain_with_internal_mail : +our_domain_with_external_mail
deny message = There are no open relay here!
check_mime:
warn decode = default
deny message = Blacklisted file extension detected ($mime_filename)
condition = ${if match \
{${lc:$mime_filename}} \
{\N(\.wav|\.cpl|\.pif|\.bat|\.scr|\.lnk|\.com|\.exe)$\N} \
{1}{0}}
accept
check_data:
deny message = NUL characters in the message body are not allowed
log_message = NUL characters in the message body are not allowed
condition = ${if > {$body_zerocount}{0} }
deny message = Virus found ($malware_name)
malware = *
accept
etrn:
deny
expn:
deny
vrfy:
deny
- маршрутизаторы:
- почта, приходящая на локальные ящики, пересылается для исследования
begin routers
localmail:
driver = redirect
domains = имя-хоста
data = имя-почтового-ящика-исследователя
- список рассылки:
noc:
driver = redirect
local_parts = noc
domains = имя-домена
data = адреса-через-запятую
- перенаправления из текстового файла:
system_aliases:
driver = redirect
domains = +our_domain_with_internal_mail
data = ${lookup{$local_part}lsearch{/usr/exim/aliases}}
- вся внутренняя почта пересылается на внутренний сервер POP3/IMAP4:
lmtp_to_pop_int:
driver = accept
domains = +our_domain_with_internal_mail
transport = lmtp_to_pop_int
no_more
- исходящая почта через SMART хост:
out:
driver = accept
transport = smart_host
no_more
- dnslookup: закоментировать полностью
- user_forward: закоментировать полностью
- localuser: закоментировать полностью
- транспорты
- пересылка на один из Cyrus-IMAP по LMTP:
lmtp_to_pop_int:
driver = smtp
hosts = IP-адрес-сервера
# hosts_require_auth = IP-адрес-сервера
# hosts_require_tls = IP-адрес-сервера
# serialize_hosts = IP-адрес-сервера
# tls_certificate = /usr/exim/exim.crt
# tls_privatekey = /usr/exim/exim.key
protocol = lmtp
# Cyrus-IMAP не принимает нули
transport_filter = /usr/bin/tr -d \\000
- исходящая почта посылается наружу:
smart_host:
driver = smtp
hosts = адрес
# hosts_nopass_tls = true
hosts_override = true
interface = наш-правильный-IP-адрес
- секция retry: для каждого внутреннего сервера и домена добавить правило:
имя-хоста refused F,2w,5m
- аутентификатор для доступа к Cyrus-IMAP (главное, это правильно посчитать скобочки ;)
plain_client:
driver = plaintext
public_name = PLAIN
client_send = ^${if or{{eq{$host_address}{адрес1}}{eq{$host_address}{адрес2}}}{имя}fail}\
^${if or{{eq{$host_address}{адрес1}}{eq{$host_address}{адрес2}}}{пароль}fail}
- тестируем работоспособность: /usr/sbin/exim -bV
- тестируем маршрутизацию (по всем направлениям!):
/usr/sbin/exim -bt адрес
- открыть сетевые экраны к LMTP для IMAP серверов
- тестируем отправку почты по LMTP к IMAP серверам: /usr/sbin/exim -v адрес
(надо ввести поля From:, To:, Subject:, пустую строку, тело письма, ^D)
- открыть сетевые экраны к внутренним и внешним SMTP серверам
- тестируем отправку почты по SMTP: /usr/exim/bin/exim -v адрес
(надо ввести поля From:, To:, Subject:, пустую строку, тело письма, ^D)
- установить пакет system-switch-mail
- запустить system-switch-mail-nox и сделать exim MTA по умолчанию
- проверка приёма почты снаружи
- адаптация остальных частей почтовой инфраструктуры, закрытие сетевых экранов и т.д.
Принимает почту из внешнего мира, фильтрует от спама и вирусов, раздает на
внутренние серверы по SMTP. Есть вариант с использованием MySQL для определения маршрута почты
и использованием LMTP для cyrus-imap.
Локальных ящиков не имеет. Принимает почту изнутри по SMTP
для рассылки наружу. Находится внутри DMZ, так что входящие соединения пробрасываются
на входном сетевом экране с помощью DNAT, а исходящие - SNAT.
Антиспам и антивирус (clamav).
- создать группу exim (себя в неё) и пользователя exim по аналогии с mail
- распаковать дистрибутив
- exim может использовать различные библиотеки DBM, но лучше если это будет
Berkeley BD 4 без режима эмуляции ndbm (USE_DB в OS/Makefile-Linux) во
избежание путаницы с неверной версией ndbm.h, к тому же она использует
один файл на базу данных
- скопировать src/EDITME в Local/Makefile и отредактировать его:
- BIN_DIRECTORY=/usr/exim/bin
- CONFIGURE_FILE=/usr/exim/configure
- EXIM_USER=exim
- EXIM_GROUP=exim
- SPOOL_DIRECTORY=/var/spool/exim
- включить все маршрутизаторы, кроме iplookup
- включить все транспорты
- нестандартные форматы локальных почтовых ящиков не включать
- включить средства просмотра: dbm, lsearch, dsearch, dnsdb, mysql (клиент
должен быть собран или установлен предварительно)
- LOOKUP_INCLUDE и LOOKUP_LIBS для MySQL
LOOKUP_INCLUDE=-I /usr/local/mysql/include/mysql
LOOKUP_LIBS=-L/usr/local/mysql/lib/mysql -lmysqlclient
или (mysql и mysql-devel не забывать)
LOOKUP_INCLUDE=-I /usr/include/mysql
LOOKUP_LIBS=-L/usr/lib64/mysql -lmysqlclient
- не собирать eximon.bin
- WITH_CONTENT_SCAN=yes
- FIXED_NEVER_USERS=root
- ALT_CONFIG_PREFIX=/usr/exim
- ALT_CONFIG_ROOT_ONLY=yes
- включить все механизмы аутентификации (кроме dovecot?)
- AUTH_LIBS=-lsasl2 (пакеты cyrus-sasl и cyrus-sasl-devel)
- включить поддержку TLS (через OpenSSL)
SUPPORT_TLS=yes
TLS_LIBS=-lssl -lcrypto
- не надо документации в формате info
- LOG_FILE_PATH=syslog:/var/log/exim/%s (директорию надо создать с
правами для пользователя exim вручную)
- SYSLOG_LOG_PID=yes
- ротация журналов предполагается с помощью внешних средств (logrotate),
но настройки можно оставить
- встроенный perl не нужен
- PAM не нужен
- RADIUS не нужен
- pwcheck и saslauthd не нужны
- tcpwrapper не нужен
- MAX_NAMED_LIST=16 (достаточно? лучше 32)
- PID_FILE_PATH=/var/run/exim.pid (в RH Linux в /var/lock
предназначен для других вещей)
- SUPPORT_MOVE_FROZEN_MESSAGES=yes
- на всякий случай просмотреть
- make
- make install (если была старая версия, то конфигурация не замещается,
старые версии утилит переименовываются; в общем, лучше посмотреть,
что получилось)
- /usr/exim/bin: exim-4.67-1 (и символьная ссылка exim, suid),
exim_dumpdb, exim_fixdb, exim_tidydb, exinext, exiwhat, exim_dbmbuild,
exicyclog, exigrep, eximstats, exipick, exiqgrep, exiqsumm,
exim_lock, exim_checkaccess
- /usr/exim/configure (тут же поставить ему права root:exim, 0640)
- создает /var/spool/exim (молча!)
- документация не копируется (даже exim(8))
- настройка /usr/exim/configure
- primary_hostname = (имя хоста полезно задать явно, если хост имеет
множество интерфейсов, в данном случае ситуация усугубляется тем, что exim
находится в DMZ и доступ к нему и от него осуществляется через DNAT и SNAT)
- domainlist local_domains = (здесь нет почтовых ящиков)
- domainlist relay_to_domains =
- domainlist our_domain_with_internal_mail = (список доменов, для которых
мы принимаем почту на внутренний сервер)
- domainlist our_domain_with_external_mail = (список доменов, для которых
мы принимаем почту на внешний сервер)
- domainlist our_domain_without_mail = (список наших доменов,
у которых нет почты)
- hostlist relay_from_hosts = 127.0.0.1
- hostlist local_network = (список блоков адресов через ":")
- local_MTA = (список адресов внутренних SMTP серверов)
- acl_smtp_rcpt = rcpt (acl_check_rcpt оставить как образец)
- qualify_domain = имя-домена
- never_users = root
- #host_lookup = * (не надо, иначе невозможно получать почту с адресов,
DNS сервер которых возвращает "SERV FAILED")
- rfc1413_hosts = (какой ident в наше время?)
- rfc1413_query_timeout = 0s
- sender_unqualified_hosts = +local_network
- ignore_bounce_errors_after = 2d
- timeout_frozen_after = 14d
- accept_8bitmime = true
- acl_smtp_auth = auth
- acl_smtp_mime = check_mime
- acl_smtp_data = check_data
- av_scanner = clamd:/var/run/clamav/clamd.sock
(антивирус clamav должен быть уже запущен)
- acl_smtp_etrn = etrn
- acl_smtp_expn = expn
- acl_smtp_vrfy = vrfy
- admin_groups = exim
- auth_advertise_hosts =
- check_log_inodes = 10
- check_log_space = 10M
- check_spool_inodes = 1000
- check_spool_space = 50M
- delay_warning = 8h:24h:48h
- helo_accept_junk_hosts = * (спамеров фильтруется мало, а раздолбаев -
много)
- #helo_try_verify_hosts = * (верификацию rDNS надо делать позже,
чтобы запись была в журнале)
- host_reject_connection = (это невежливо)
- hostlist dialup_hosts = /usr/exim/dialup_hosts (коллекция динамических адресов)
- hostlist unwelcome_hosts = /usr/exim/unwelcome_hosts
- hostlist open_relay_hosts = /usr/exim/open_relay_hosts
- local_interfaces = 127.0.0.1.25 : основной-ip-адрес.25 : запасной-канал.25
(чтобы не проверял виртуальные интерфейсы)
- log_selector = +incoming_interface +incoming_port +delivery_size +smtp_confirmation +smtp_protocol_error +smtp_syntax_error +received_recipients +sender_on_delivery -retry_defer
- message_body_visible = 8000 (чем больше, тем больше требуется памяти и CPU)
- message_size_limit = 50M
- [hide mysql_servers = имя-сервера/имя-БД/имя/пароль] (MySQL для получения данных маршрутизации)
- pipelining_advertise_hosts = +local_network : +relay_from_hosts
- recipients_max = 100
- recipients_max_reject = true
- smtp_accept_max_per_connection = 100
- smtp_accept_max_per_host = 20
- smtp_accept_reserve = 8
- smtp_connect_backlog = 50
- smtp_enforce_sync = true (глупая проверка - спамеров попадается мало,
а суетливых администраторов много)
- # замедлитель
- smtp_ratelimit_hosts = * (или !+local_MTA)
- smtp_ratelimit_mail = 2,0.5s,1.05,4m (65 секунд задержки на сотом)
- smtp_ratelimit_rcpt = 4,0.25s,1.03,4m (5 секунд задержки на сотом)
- # overload limit
- queue_run_max = 5
- deliver_queue_load_max = 20
- queue_only_load = 40
- smtp_load_reserve = 60
- smtp_accept_max = 60
- smtp_reserve_hosts = +local_network : +modems_pool
- smtp_accept_reserve = 8
- # заготовка под TLS
- #tls_advertise_hosts = +local_network (или все, если ваш сертификат заверен
общепризнанным CA, иначе могут быть проблемы)
- #tls_certificate = /usr/exim/имя-файла.crt
- #tls_privatekey = /usr/exim/имя-файла.key (права доступа - exim:exim, 400!)
- секция acl
begin acl
auth:
deny
rcpt:
# postmaster должен получать всё :(
accept local_parts = postmaster
domains = +local_domains : +relay_to_domains : +our_domain_with_internal_mail :
+our_domain_with_external_mail
deny domains = имя-нашего-домена
!local_parts = /usr/exim/users_имя-нашего-домена \
[: mysql;select ... from ... where ...]
message = User unknown (имя-нашего-домена)
accept hosts = +local_MTA
control = submission/sender_retain
accept hosts = +relay_from_hosts
control = submission
accept hosts = +local_network
control = submission/domain=имя-нашего-домена
require verify = sender
deny message = Wrong HELO. You are not $sender_helo_name.
!hosts = +relay_from_hosts : +local_network
!recipients = /usr/exim/friendly_to_unwelcome_hosts
condition = ${if match {$sender_helo_name}{имя-нашего-домена|наш-IP}{yes}{no}}
deny message = Wrong sender address. You are not $sender_address
!hosts = +relay_from_hosts : +local_network
condition = ${if match {$sender_address}{postmaster@имя-нашего-домена}{yes}{no}}
deny hosts = +open_relay_hosts
!recipients = /usr/exim/friendly_to_open_relay_hosts
message = Sorry, we dont accept mail from open relay.
deny hosts = +dialup_hosts
!recipients = /usr/exim/friendly_to_dialup_hosts
message = Sorry, we dont accept mail from dialup and so on.
deny !recipients = /usr/exim/friendly_to_dialup_hosts
!hosts = список-исключений
dnslists = dul.dnsbl.sorbs.net
message = Sorry, we dont accept mail from dialup and so on ($dnslist_domain).
deny message = dnsbl: $sender_host_address is found in $dnslist_domain
log_message = dnsbl: $sender_host_address is found in $dnslist_domain: $dnslist_value
!hosts = список-исключений
!recipients = /usr/exim/friendly_to_dnsbl
dnslists = list.dsbl.org : dnsbl.njabl.org
deny !hosts = /usr/exim/double_check_exclusion
!recipients = /usr/exim/friendly_to_double_check_error
!verify = reverse_host_lookup
message = Your mail server $sender_fullhost has reverse DNS error.
warn dnslists = cbl.abuseat.org
add_header = X-SPAM-Warning: $sender_host_address is in a black list at $dnslist_domain
log_message = X-SPAM-Warning: $sender_host_address is in a black list at $dnslist_domain
accept domains = +relay_to_domains :+our_domain_with_internal_mail:+our_domain_with_external_mail
deny message = There are no open relay here!
check_mime:
warn decode = default
deny message = Blacklisted file extension detected ($mime_filename)
condition = ${if match \
{${lc:$mime_filename}} \
{\N(\.wav|\.cpl|\.pif|\.bat|\.scr|\.lnk|\.com|\.exe)$\N} \
{1}{0}}
accept
check_data:
deny message = NUL characters in the message body are not allowed
log_message = NUL characters in the message body are not allowed
condition = ${if > {$body_zerocount}{0} }
deny message = Virus found ($malware_name)
malware = *
accept
etrn:
deny
expn:
deny
vrfy:
deny
- маршрутизаторы:
- почта, приходящая на локальные ящики, пересылается куда надо
begin routers
localmail:
driver = redirect
domains = имя-хоста
data = имя-почтового-ящика
- почта, помеченная как возможный спам, посылается на выделенный ящик:
spam_warning:
driver = redirect
domains = имя-нашего-домена
condition = ${if and { {def:header_X-SPAM-Warning:} {= {$body_zerocount}{0}} } {yes}{no} }
data = выделенный ящик
- список рассылки:
noc:
driver = redirect
local_parts = noc
domains = имя-домена
data = адреса-через-запятую
- перенаправления из MySQL:
redirect_mysql:
driver = redirect
data = ${lookup mysql{select ... from ... where ...}{$value}fail}
- перенаправления наружу из текстового файла:
имя-домена-out:
driver = redirect
domains = имя-домена
data = ${lookup{$local_part}lsearch{/usr/exim/users_out}}
- приём почты согласно информации из MySQL:
accept_mysql:
driver = accept
local_parts = ${lookup mysql{select localpart from mail_accept where localpart='${quote_mysql:$local_part}' and domain='${quote_mysql:$domain}'}{$value}fail}
transport = ${lookup mysql{select transport from mail_accept where localpart='${quote_mysql:$local_part}' and domain='${quote_mysql:$domain}'}{$value}fail}
no_more
- вся остальная внутренняя почта пересылается на внутренний сервер POP3:
pop_int:
driver = accept
domains = +our_domain_with_internal_mail
transport = smtp_to_pop_int
no_more
- исходящая почта:
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
no_more
- system_aliases: закоментировать полностью
- user_forward: закоментировать полностью
- localuser: по вкусу
- транспорты
- пересылка на внутренний сервер
smtp_to_pop_int:
driver = smtp
hosts = имя-внутреннего-POP-сервера
hosts_override = true
- пересылка на один из Cyrus-IMAP по LMTP (маршрутизация из MySQL):
lmtp_to_имя-сервера:
driver = smtp
hosts = IP-адрес-сервера
hosts_require_auth = IP-адрес-сервера
hosts_require_tls = IP-адрес-сервера
serialize_hosts = IP-адрес-сервера
tls_certificate = /usr/exim/exim.crt
tls_privatekey = /usr/exim/exim.key
protocol = lmtp
# Cyrus-IMAP не принимает нули
transport_filter = /usr/bin/tr -d \\000
- исходящая почта посылается наружу:
remote_smtp:
driver = smtp
hosts_nopass_tls = true
interface = наш-IP-адрес
hosts_avoid_esmtp = список-дефективных-ESMTP-серверов
- local_delivery:
- driver = appendfile
- file = /var/spool/mail/$local_part (в Solaris - /var/mail)
- delivery_date_add
- envelope_to_add
- return_path_add
- group = mail (иначе при отправке письма по локальному адресу пытается
создать lock-файл в директории /var/spool/mail сбросив права до
uid/gid, что невозможно)
- mode = 0660
- секция retry: для каждого внутреннего сервера и домена добавить правило:
имя-хоста refused F,2w,5m
- аутентификатор для доступа к Cyrus-IMAP (главное, это правильно посчитать скобочки ;)
plain_client:
driver = plaintext
public_name = PLAIN
client_send = ^${if or{{eq{$host_address}{адрес1}}{eq{$host_address}{адрес2}}}{имя}fail}\
^${if or{{eq{$host_address}{адрес1}}{eq{$host_address}{адрес2}}}{пароль}fail}
- тестируем работоспособность: /usr/exim/bin/exim -bV
- открыть сетевые экраны к MySQL серверу
- тестируем маршрутизацию (по всем направлениям!):
/usr/exim/bin/exim -bt адрес
- открыть сетевые экраны к LMTP для IMAP серверов
- тестируем отправку почты по LMTP к IMAP серверам: /usr/exim/bin/exim -v адрес
(надо ввести поля From:, To:, Subject:, пустую строку, тело письма, ^D)
- открыть сетевые экраны к внутренним и внешним SMTP серверам
- тестируем отправку почты по SMTP: /usr/exim/bin/exim -v адрес
(надо ввести поля From:, To:, Subject:, пустую строку, тело письма, ^D)
- обеспечение автоматического запуска (или позаимствовать из готового пакета
и использовать стандартные механизмы chkconfig и service):
- сделать /etc/sysconfig/exim из /etc/sysconfig/sendmail
- сделать /etc/rc.d/init.d/exim из /etc/rc.d/init.d/sendmail
(только reload сделать через HUP)
- насоздавать символьных ссылок rc0.d/K30exim, rc1.d/K30exim,
rc2.d/S80exim, rc3.d/S80exim, rc4.d/S80exim, rc5.d/S80exim
rc6.d/K30exim (chkconfig --add exim)
- остановить sendmail (service, chkconfig)
- запустить exim (service, chkconfig)
- проброс тестового порта 10025 на входном сетевом экране на этот сервер порт 25
- проверка приёма почты снаружи
- смена пробрасываемого порта на нормальный 25 и останов старого почтового сервера
- адаптация остальных частей почтовой инфраструктуры, закрытие сетевых экранов и т.д.
Принимает почту из внешнего мира раздает на
внутренние сервера для раскладки их по ящикам. Локальных ящиков не имеет.
- создать группу exim (себя в неё) и пользователя exim по аналогии с mail
- распаковать дистрибутив
- exim может использовать различные библиотеки DBM, но лучше если это будет
Berkeley BD 4 без режима эмуляции ndbm (USE_DB в OS/Makefile-Linux) во
избежание путаницы с неверной версией ndbm.h, к тому же она использует
один файл на базу данных
- скопировать src/EDITME в Local/Makefile и отредактировать его:
- на всякий случай просмотреть
- make
- make install (если была старая версия, то конфигурация не замещается,
старые версии утилит переименовываются; в общем, лучше посмотреть,
что получилось)
- /usr/exim/bin: exim-4.50-1 (и символьная ссылка exim, suid),
exim_dumpdb, exim_fixdb, exim_tidydb, exinext, exiwhat, exim_dbmbuild,
exicyclog, exigrep, eximstats, exipick, exiqgrep, exiqsumm,
exim_lock, exim_checkaccess
- /usr/exim/configure (тут же поставить ему права root:exim, 0640)
- создает /var/spool/exim (молча!)
- документация не копируется (даже exim(8))
- настройка /usr/exim/configure для прозрачной передачи полученной почты
sendmail-у
- primary_hostname = (имя хоста полезно задать явно, если хост имеет
множество интерфейсов)
- domainlist local_domains = (здесь нет почтовых ящиков)
- domainlist relay_to_domains =
- domainlist our_domain_with_mail = (список доменов, для которых
мы принимаем почту)
- domainlist our_domain_without_mail = (список наших доменов,
у которых нет почты)
- hostlist relay_from_hosts = 127.0.0.1
- hostlist modems_pool = (список блоков адресов)
- hostlist local_network = (список блоков адресов)
- localpartlist forward_deol = (список локальных форвардов)
- localpartlist alias_deol = (список алиасов)
- localpartlist forward_deol_out = (список форвардов наружу)
- acl_smtp_rcpt = rcpt (acl_check_rcpt оставить как образец)
- qualify_domain = deol.ru
- never_users = root
- #host_lookup = * (не надо, иначе невозможно получать почту с адресов,
сервер которых возвращает "SERV FAILED")
- rfc1413_hosts = (какой ident в наше время?)
- rfc1413_query_timeout = 0s
- ignore_bounce_errors_after = 7d (надо успеть посмотреть что там)
- timeout_frozen_after = 14d
- accept_8bitmime = true
- acl_smtp_auth = auth
- acl_smtp_data = check_data
- acl_smtp_etrn = etrn
- acl_smtp_expn = expn
- acl_smtp_vrfy = vrfy
- admin_groups = exim
- auth_advertise_hosts =
- check_log_inodes = 10
- check_log_space = 10M
- check_spool_inodes = 1000
- check_spool_space = 100M
- delay_warning = 8h:24h:48h
- #dns_again_means_nonexist =
- freeze_tell = свой адрес (извещения о замороженных письмах на время отладки)
- helo_accept_junk_hosts = * (спамеров фильтруется мало, а раздолбаев -
много)
- #helo_try_verify_hosts = * (верификацию rDNS надо делать позже)
- host_reject_connection = (это невежливо)
- hostlist dialup_hosts = /usr/exim/dialup_hosts
- hostlist unwelcome_hosts = /usr/exim/unwelcome_hosts
- hostlist open_relay_hosts = /usr/exim/open_relay_hosts
- local_interfaces = 127.0.0.1.25 : основной-ip-адрес.25 : запасной-канал.25
(чтобы не проверял виртуальные интерфейсы)
- log_selector = +incoming_interface +incoming_port +delivery_size +smtp_confirmation +smtp_protocol_error +smtp_syntax_error +received_recipients +sender_on_delivery -retry_defer
- message_body_visible = 30000
- message_size_limit = 10M
- move_frozen_messages = true (только после отладки!, в 4.0.3 пропал!)
- recipients_max = 100
- recipients_max_reject = true
- smtp_accept_max = 100
- smtp_accept_max_per_connection = 100
- smtp_accept_max_per_host = 10
- smtp_accept_reserve = 5
- smtp_connect_backlog = 50
- smtp_enforce_sync = false (глупая проверка - спамеров попадается мало,
а суетливых администраторов много)
- smtp_ratelimit_hosts = *
- smtp_ratelimit_mail = 2,0.5s,1.05,4m (65 секунд задержки на сотом)
- smtp_ratelimit_rcpt = 4,0.25s,1.03,4m (5 секунд задержки на сотом)
- smtp_reserve_hosts = +local_network : +modems_pool
- system_filter = ???
- system_filter_directory_transport = ???
- system_filter_file_transport = ???
- system_filter_pipe_transport = ???
- system_filter_reply_transport = ???
- tls_advertise_hosts = +local_network (или все, если ваш сертификат заверен
общепризнанным CA, иначе могут быть проблемы)
- tls_certificate = /usr/exim/имя-файла.crt
- tls_privatekey = /usr/exim/имя-файла.key (права доступа - exim:exim, 400!)
- секция acl
- маршрутизаторы:
- входящая почта пересылается на pop-сервер
pop:
driver = accept
domains = +our_domain_with_mail
transport = smtp_to_pop
no_more
- исходящая почта
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 127.0.0.0/8
no_more
- user_forward: закоментировать полностью
- транспорты
- секция retry: для каждого внутреннего сервера добавить правило:
имя-хоста refused F,2w,5m
- тестируем работоспособность: /usr/exim/bin/exim -bV
- тестируем маршрутизацию: /usr/exim/bin/exim -bt адрес
- тестируем отправку почты по SMTP: /usr/exim/bin/exim -v адрес
(надо ввести поля From:, To:, Subject:, пустую строку, тело письма, ^D)
- обеспечение автоматического запуска:
- сделать /etc/sysconfig/exim из /etc/sysconfig/sendmail
- сделать /etc/rc.d/init.d/exim из /etc/rc.d/init.d/sendmail
(только reload сделать через HUP)
- насоздавать символьных ссылок rc0.d/K30exim, rc1.d/K30exim,
rc2.d/S80exim, rc3.d/S80exim, rc4.d/S80exim, rc5.d/S80exim
rc6.d/K30exim
- отредактировать нстройки tcp_wrapper (/etc/hosts.allow и /etc/hosts.deny;
имя сервиса - exim)
- дырка в ipchains
- дырка в IOS ACL внешнем
- дырка в IOS ACL для клиентов
- замена DNS MX
- подождать 3 дня и закрыть старый сервер
- сайт разработчика (есть зеркало в России)
- дистрибутив
- Specification of the Exim Mail Transfer Agent by Philip Hazel (входит в состав поставки: doc/spec.txt)
- изменения в новой версии, не отраженные в спецификации: doc/NewStuff
- язык для написания фильтров: doc/filter.txt
- библиотека регулярных выражений: doc/pcre.txt
- форум: FAQ по Exim MTA
|
Bog BOS: exim - почтовый сервер (MTA) для борьбы со спамом
|
Copyright © 1996-2024 Sergey E. Bogomolov; www.bog.pp.ru