39. Списки контроля доступа

Перевод выполнен Алексеем Паутовым в рамках некоммерческого проекта RussianLDP (http://www.rldp.ru/). Именно на этом сайте и надлежит искать новые версии, если таковые будут.

39. Списки контроля доступа

Списки контроля доступа (Access Control Lists, ACL) заданы в отдельной секции рабочего конфигурационного файла, озаглавленной begin acl. Каждое определение ACL начинается с имени, завершённого двоеточием. Это полная секция ACL, которая содержит лишь одну очень маленькую ACL:

begin acl
small_acl:
  accept   hosts = one.host.only

Вы можете иметь так много списков, как Вы хотите в секции ACL, порядок их появления не имеет значения. Списки заканчиваются автоматически.

Большинство ACL используются для контроля поведения exim, когда он получает определённые SMTP-команды. Это применяется к входящим TCP/IP-соединениям и тогда, когда локальный процесс передаёт сообщения, используя SMTP через задание опции -bs. Самое обычное использование для контроля, каких получателей принимать во входящих сообщениях. Кроме того, можете задать ACL, которые используются для проверки не-SMTP сообщений. Конфигурационный файл по умолчанию содержит примеры реалистичных ACL для проверки команд RCPT. Это обсуждается в главе 7.

39.1. Тестирование ACL

Опция командной строки -bh предоставляет способ тестирования конфигурации ACL локально путём запуска поддельной сессии SMTP, с которой Вы взаимодействуете. Хост relay-test.mail-abuse.org предоставляет сервис для проверки релейной конфигурации (для получения дополнительных деталей смотрите раздел 39.40).

39.2. Определение, когда используются ACL

Для использования ACL Вы должны назвать их в одной из релевантных опций в главной части конфигурации. Эти опции:

Опция
Где используется
acl_not_smtp ACL для не-SMTP сообщений
acl_smtp_auth ACL для AUTH
acl_smtp_connect ACL для начала SMTP-соединения
acl_smtp_data ACL после завершения DATA
acl_smtp_etrn ACL для ETRN
acl_smtp_expn ACL для EXPN
acl_smtp_helo ACL для HELO или EHLO
acl_smtp_mail ACL для MAIL
acl_smtp_mailauth ACL для параметра AUTH команды MAIL
acl_smtp_mime ACL для контентного сканирования MIME-частей
acl_smtp_predata ACL в начале команды DATA
acl_smtp_quit ACL для QUIT
acl_smtp_rcpt ACL для RCPT
acl_smtp_starttls ACL для STARTTLS
acl_smtp_vrfy ACL для VRFY
Например, если Вы устанавливаете:
acl_smtp_rcpt = small_acl
то небольшой ACL, определённый выше, используется каждый раз, когда exim получает команду RCPT в диалоге SMTP. Большинство тестов политик для входящих сообщений может быть сделано по прибытии команды RCPT. Отклонение RCPT должно вызвать ошибку адреса получателя содержащегося в команде RCPT, тогда как отклонение в другой момент времени может вызвать дальнейшие попытки MTA доставить сообщение. Поэтому рекомендуется, чтобы Вы делали как можно больше тестов во время RCPT.

39.3. Не-SMTP ACL

Не-SMTP ACL применяется ко всем входящим неинтерактивным сообщениям, то есть к пакетному SMTP он применяется так же, как и к не-SMTP сообщениям. Эта ACL работает лишь до функции local_scan(). Любые виды отклонения сообщений рассматриваются как постоянные, поскольку нет способа послать код временнной ошибки для этих видов сообщений. Многие условия ACL (например, проверки хостов и состояния SMTP-соединения, типа шифрования и аутентификации) неуместны и запрещены в этой ACL.

39.4. ACL подключения

Проверка ACL, заданная путём acl_smtp_connect, происходит после теста, заданного host_reject_connection (который теперь является аномалией) и любых сконфигурированных тестов TCP Wrappers.

39.5. ACL DATA

Две ACL ассоциированы с командой DATA, поскольку это двухстадийная команда с двумя ответами, посылаемыми клиенту. Когда получена команда DATA, обрабатывается ACL, заданная путём acl_smtp_predata. Это даёт контроль после всех команд RCPT, но до получения самого сообщения. Этим даётся возможность дать отрицательный ответ на команду DATA до того, как переданы данные. Строки заголовков, добавляемые путём MAIL или RCPT ACL, невидимы в это время, но любые, которые тут заданы, видимы при работе ACL acl_smtp_data.

Вы не можете проверить содержимое сообщения, например, для проверки адресов в заголовках во время RCPT, или когда получена команда DATA. Такие тесты должны быть в ACL, которая работает после получения сообщения, до посылки финального ответа на DATA. Для обоих этих ACL невозможно отклонить индивидуальных получателей. Ответ о ошибке отклоняет всё сообщение. К сожалению, известны MTA, которые некорректно обрабатывают жёсткий (5xx) ответ на команду DATA (до или после данных): они пытаются оставить сообщение в своей очереди и пробуют доставить его позже, но это их проблема, хотя они впустую тратят Ваши ресурсы.

39.6. ACL MIME

Опция acl_smtp_mime доступна, лишь когда exim собран с расширением контентного сканирования. Для деталей обратитесь к главе 40.

39.7. ACL QUIT

ACL для SMTP-команды QUIT является аномальной, результат ACL не затрагивает код ответа на QUIT, который всегда 221. Таким образом, фактически, ACL не управляет каким-либо доступом. Поэтому, разрешены лишь имена команд accept и warn.

Эта ACL может быть использована для задач типа специального протоколирования конца SMTP-сессии. Например, Вы можете использовать переменные ACL в другом ACL для подсчёта числа сообщений, получателей и т.п., и протоколировать общее время QUIT, используя один или более модификаторов logwrite в команде warn.

Предупреждение: Для этого могут использоваться лишь переменные $acl_c x, поскольку переменные $acl_m x сбрасываются после каждого входящего сообщения.

Вам не нужно ставить в конце accept, но если Вы так поступаете, можете использовать модификатор message для задания собственного текста, который посылается как часть 221 ответа на QUIT.

Эта ACL запускается лишь для нормального QUIT. Для определённых случаев катастрофических ошибок (например, ошибки открытия лог-файла или когда exim падает в результате катастрофической ошибки) все SMTP-команды от клиента получают ответ о временной ошибке, пока не будет передана команда QUIT, или соединение не закроется. В этих специальных случаях ACL QUIT не запускается.

39.8. Нахождение ACL для использования

Значение опции acl_smtp_ xxx раскрывается перед использованием, таким образом, Вы можете использовать различные ACL для разных ситуаций. Результирующая строка не должна быть именем ACL в конфигурационном файле: есть другие возможности. Раскрыв строку, exim ищет ACL следующим образом:

  • Если строка начинается со слэша, exim использует её как имя файла и читает его содержимое как ACL. Строки обрабатываются таким же образом, как строки в конфигурационном файле exim. В частности, поддерживается продолжение строк, пустые строки игнорируются, как и строки, чей первый символ, не являющийся пробелом, #. Если файл не существует или не может быть прочитан, происходит ошибка (типично вызывается временная ошибка любой вызываемой для запуска ACL). Например:
    acl_smtp_data = /etc/acls/ \
       ${lookup{$sender_host_address}lsearch \
       {/etc/acllist}{$value}{default}}
    
    В примере ищется используемый файл ACL на основе IP-адреса хоста, в случае неудачи поиска используется значение по умолчанию. Если ACL успешно прочитана из файла, она сохраняется в памяти при работе процесса exim, таким образом, она может быть повторно использована без необходимости перечитывать файл.
  • Если строка не начинается со слэша и не содержит каких-либо пробелов, exim ищет секцию ACL в конфигурации ACL, чьё имя совпадает со строкой.
  • Если имя ACL не найдено или строка содержит пробелы, exim обрабатывает строку как ACL. Это может сэкономить ввод в случаях, когда Вы хотите сделать что-то типа этого:
    acl_smtp_vrfy = accept
    
    для разрешения свободного использования команды VRFY. Такая строка может содержать символы новой строки, она обрабатывается таким же способом, как и ACL, читаемая из файла.

39.9. Коды возврата ACL

Исключая ACL QUIT, которая не затрагивает код возврата SMTP (смотрите выше секцию 39.7), результат работы ACL accept, deny или defer ("проверка не может быть завершена" (например, упала БД)). Эти результаты вызывают использование кодов ответа 2xx, 5xx и 4xx в диалоге SMTP, соответственно. Четвёртое возвращаемое значение, error, происходит при ошибках, типа неправильного синтаксиса в ACL. Она также вызывает код возврата 4xx.

Для не-SMTP ACL defer и error рассматриваются так же, как и deny, поскольку не существует механизма для передачи временных ошибок отправителям не-SMTP сообщений.

ACL, которые релевантны приёму сообщений, также могут вернуть discard. Это имеет тот же самый эффект что и accept, но вызывает отбрасывание всего сообщения или адреса отдельного отправителя. Другими словами, это средство для организации чёрной дыры (сообщения уходят в никуда). Используйте это с осторожностью.

Если ACL для MAIL возвращает discard, все получатели отбрасываются и для последующих команд RCPT не запускается никаких ACL. Эффект discard в ACL RCPT отбрасывание лишь одного адреса получателя. Если не осталось получателей сообщения, когда получены данные сообщения, ACL DATA не запускается. Если discard возвращается из DATA или не-SMTP ACL, отбрасываются все получатели. Не разрешается возвращать discard для ACL acl_smtp_predata. Функция local_scan() запускается всегда, даже если не осталось получателей: она может создать новых получателей.

39.10. Незаданные опции ACL

Действия по умолчанию, когда не задана любая из опций acl_ xxx не одинаковы для всех. Отметьте: Эти умолчания применяются, лишь когда релевантная ACL вообще не определена. Для любых определёных ACL действие по умолчанию, когда контроль достигает конца утверждения ACL, deny.

Для acl_not_smtp, acl_smtp_auth, acl_smtp_connect, acl_smtp_data, acl_smtp_helo, acl_smtp_mail, acl_smtp_mailauth, acl_smtp_mime, acl_smtp_predata, acl_smtp_quit и acl_smtp_starttls, действие при незаданной ACL accept.

Для других (acl_smtp_etrn, acl_smtp_expn, acl_smtp_rcpt и acl_smtp_vrfy) действие, когда ACL не определена, deny. Это означает, что acl_smtp_rcpt должна быть определена для получения любых сообщений через SMTP-соединение. Для примера смотрите ACL в конфигурационном файле по умолчанию.

39.11. Данные для ACL сообщений

Когда работают MAIL или RCPT ACL или любые из DATA ACL, установлены переменные, которые содержат информацию о хосте и отправителе сообщения (например, $sender_host_address и $sender_address) и могут использоваться в утверждениях ACL. В случае RCPT (но не MAIL или DATA), $domain и $local_part установлены из аргументов адреса. Полная команда SMTP доступна в $smtp_command.

Когда работает ACL для параметра AUTH команды MAIL, переменные, которые содержат информацию о хосте, установлены, но $sender_address ещё не установлена. Раздел 33.2 содержит обсуждение этого параметра и как его использовать.

Переменная $message_size установлена в значение параметра SIZE команды MAIL во время MAIL, RCPT и до данных или в -1, если параметр не был задан. Значение обновляется до истинного размера сообщения во время работы финальной ACL DATA (после получения сообщения).

Переменная $rcpt_count увеличивается на единицу для каждой полученной команды RCPT. Переменная $recipients_count увеличивается на единицу для каждой принятой команды RCPT, таким образом, когда обрабатывается RCPT ACL, она содержит число предыдущих принятых получателей. Во время DATA (для обоих DATA ACL) $rcpt_count содержит общее число команд RCPT, а $recipients_count содержит общее число принятых получателей (в данном абзаце есть разница между числом принятых команд и числом принятых получателей, поскольку получатель может не существовать, тогда команда RCPT принята, а вот получатель нет).

39.12. Данные для ACL не-сообщений

Когда ACL работает для AUTH, EHLO, ETRN, EXPN, HELO, STARTTLS или VRFY, оставшаяся строка SMTP-команды помещается в $smtp_command_argument, а вся команда SMTP доступна в $smtp_command. Эти переменные могут быть протестированы, используя условие condition. Например, вот ACL для использования с AUTH, которая настаивает на том, чтобы сессия была зашифрована или использовался метод CRAM-MD5. Другими словами, она не разрешает аутентификационные методы, которые используют пароль в открытом виде для нешифрованных соединений.

acl_check_auth:
   accept encrypted = *
   accept condition = ${if eq{${uc:$smtp_command_argument}} {CRAM-MD5}}
   deny   message   = TLS encryption or CRAM-MD5 required

Иной способ применения этих ограничений: переделать аутентификаторы, использующие пароли в открытом виде, чтобы о них не оповещалось, когда соединение не шифрованное. Для этого Вы можете использовать общую аутентификационную опцию server_advertise_condition.

39.13. Формат ACL

Индивидуальная ACL содержит множество утверждений. Каждое утверждение начинается с команды, опционально сопровождаемой множеством условий и модификаторов (modifiers). Модификаторы могут изменять работу команд, задавать сообщения об ошибках, протоколы, устанавливать переменные, вставлять задержки и изменять обработку принятых сообщений.

Если выполняются все условия, выполняется команда. Одни и те же условия могут использоваться (с различными аргументами) более одного раза в одном и том же утверждении. Это предоставляет средство задания соединения and между условиями. Например:

deny  dnslists = list1.example
dnslists = list2.example

Если нет условий, команда всегда выполняется. Exim останавливает оценку условия и модификаторов, когда он достигает условия, которое неуспешно. Что происходит потом, зависит от команды (и в одном случае от специального модификатора). Не все условия имеют смысл в каждой тестируемой точке. Например, Вы не можете проверить адрес отправителя в ACL, которая запускается для команды VRFY.

39.14. Команды ACL

Команды ACL таковы:

  • accept: Если все условия удовлетворяются, ACL возвращает accept. Если любое из условий не выполняется, происходящее зависит от того, есть ли среди условий endpass (синтаксис смотрите ниже). Если неуспешное условие до endpass, управление передаётся следующему утверждению ACL, если оно после endpass, ACL возвращает deny. Рассмотрите это утверждение, используемое для проверки команды RCPT:
    accept domains = +local_domains
    endpass
    verify = recipient
    

    Если домен получателя не совпадает с условием domains, управление передаётся следующему утверждению. Если оно совпадает, проверяется получатель и команда принимается в случае успешной проверки. Однако, если проверка неудачна, ACL приводит к deny, поскольку неудачное выражение после endpass.

  • defer: Если все условия удовлетворяются, ACL возвращает defer, который вызывает в SMTP-сессии выдачу ответа 4xx. Для не-SMTP ACL defer то же самое, что и deny, поскольку в этом случае нет способа дать временную ошибку. Для команды RCPT defer почти также использует роутер redirect и :defer: при проверке, но команда defer может использоваться в любом ACL, и для получателя это может быть более простым подходом.
  • deny: Если все условия удовлетворяются, ACL возвращает deny. Если любое из условий не выполняется, управление передаётся следующему утверждению ACL. Например:
    deny dnslists = blackholes.mail-abuse.org
    
    отклоняет команды от хостов, которые в чёрных списках DNS (блэк-листах).
  • discard: Эта команда ведёт себя так же, как и accept, исключая, что она возвращает из ACL discard вместо accept. Это разрешается только для ACL, которые имеют отношение к получению сообщений, и они вызывают отказ от получателя. Если модификатор log_message установлен при работе discard, его содержимое добавляется к строке, автоматически записываемой в протокол. Если discard используется в ACL для RCPT, отказываются лишь от одного получателя, если используется для MAIL, DATA или в не-SMTP ACL, отказываются от всех получателей сообщения. Получатели, от которых отказались до DATA, не фигурируют в строках протоколов, когда установлен селектор log_recipients.
  • drop: Эта команда ведёт себя так же, как и deny, исключая, что соединения SMTP принудительно закрываются после отсылки 5xx сообщения об ошибке. Например:
    drop   message   = I don't take more than 20 RCPTs
           condition = ${if > {$rcpt_count}{20}}
    
    Нет никаких отличий между deny и drop во время ACL соединения. Соединения всегда разрываются после посыла ответа 550.
  • require: Если выполняются все условия, управление передаётся следующему утверждению ACL. Если любое из условий не выполняется, ACL возвращает deny. Например, при проверке команды RCPT:
    require verify = sender
    
    управление передаётся следующему утверждению, лишь если отправитель сообщения может быть проверен. Иначе, оно отклонит команду.
  • warn: Если все условия выполняются, во входящее сообщение добавляются строки заголовков и/или в главный протокол exim пишутся строки. Во всех случаях управление передаётся следующему утверждению ACL. Текст, добавляемый в заголовки и строки протоколов, задается путём модификаторов, если их нет, команда warn лишь проверяет своё условие и подчиняется любым непосредственным модификаторам, типа set и logwrite. Дополнительная информация о добавлении строк заголовков есть в секции 39.19.

Если любое условие в утверждении warn не может быть завершено (то есть своего рода отсрочка), строки заголовков не добавляются, и сконфигурированные строки протоколов не записываются. Никакие дальнейшие условия или модификаторы в утверждении warn не обрабатываются. Инцидент протоколируется, но ACL продолжает обрабатываться со следующего утверждения. Если в ACL, которая не тестирует входящее сообщение, в команде warn присутствует модификатор message, он игнорируется, а инцидент протоколируется.

Утверждение warn может использовать модификатор log_message для записи строки в главный протокол, когда условия утверждения верны. Если идентичную строку запрашивают несколько раз в одном сообщении, фактически, лишь одна копия пишется в протокол. Если Вы хотите вместо этого принудительно записывать дубликаты, используйте модификатор logwrite.

Когда одно из условий warn неудачная проверка адреса, текст сообщения о неудаче проверки находится в $acl_verify_message. Если Вы хотите его протоколировать, Вы должны установить это явно. Например:

warn   !verify = sender
       log_message = sender verify failed: $acl_verify_message

В конце каждой ACL присутствует неявное безоговорочное deny. Как Вы видели из примеров выше, условия и модификаторы пишутся в одну линию, на первом месте, в той же строке команда, последующие на дальнейших строках. Если у Вас очень длинное условие, вы можете продолжить его на нескольких строках путём обычного механизма обратного слэша. Обычно условия выравниваются вертикально.

39.15. Переменные ACL

Есть некоторые специальные переменные, которые могут быть установлены в течение обработки ACL. Они могут использоваться для передачи информации между различными ACL, различными вызовами одной и той же ACL в одном и том же SMTP-соединении, между ACL и роутерами, транспортами и фильтрами, которые используются для доставки сообщения. Есть два набора этих переменных:

  • Значения от $acl_c0 до $acl_c19 сохраняются в течение SMTP-сессии. Они никогда не сбрасываются. Таким образом, значение, которое установлено при получении одного сообщения, остаётся доступным при получении следующего сообщения в том же SMTP-соединении.
  • Значения от $acl_m0 до $acl_m19 сохраняются лишь, когда сообщение получается. После этого они сбрасываются. Также они сбрасываются MAIL, RSET, EHLO, HELO и после начала сессии TLS.

Когда сообщение принято, текущие значения всех переменных ACL сохраняются с сообщением и впоследствии становятся доступными во время доставки. Переменные ACL устанавливаются путём модификатора, называемого set. Например:

accept hosts = whatever
       set acl_m4 = some value

Отметьте: Начальный символ доллара не используется при именовании устанавливаемой переменной. Если Вы хотите установить переменную не предпринимая каких-либо действий, можете использовать команду warn без любых других модификаторов или условий.

39.16. Обработка условий и модификаторов

Восклицательный знак, предшествующий выражению, отрицает его результат. Например:

deny   domains = *.dom.example
      !verify  = recipient
заставляет ACL вернуть deny, если домен отправителя заканчивается на dom.example, и адрес получателя не может быть проверен. Иногда отрицание может использоваться на правой стороне условия. Например, эти два утверждения эквивалентны:
deny  hosts = !192.168.3.4
deny !hosts = 192.168.3.4

Однако, для многих условий (verify был хорошим примером) допустимо лишь левостороннее отрицание всего условия. Аргументы условия и модификаторы раскрываются. Принудительный отказ раскрытия вызывает игнорирование условия, то есть оно ведёт себя как будто условие истинно. Рассмотрите эти два утверждения:

accept  senders = ${lookup{$host_name}lsearch {/some/file}{$value}fail}
accept  senders = ${lookup{
        $host_name}lsearch {/some/file}{$value}{}}

Каждое условие пытается искать список приемлемых отправителей. Если поиск успешен, возврашённый список просматривается, но если поиск неудачен, поведение различается в этих двух случаях. В первом случае fail вызывает игнорирование условия, не рарешая никаких дальнейших выражений. Поэтому команда accept успешна. Однако, второе утверждение генерирует пустой список, когда поиск неудачен. Никакой отправитель не может совпасть с пустым списком, следовательно, условие неуспешно, и поэтому accept также неудачен.

Модификаторы ACL кажутся смешанными с условиями в утверждениях ACL. Некоторые из них определяют действия, которые берутся как условия для проверки утверждений, другие определяют текст для сообщений, который используется при отказе в доступе или при генерации предупреждения. Модификатор control затрагивает способ обработки входящих сообщений.

Позиционирование модификаторов в утверждении ACL важно, поскольку обработка команды прекрашается, как только известен её результат. В силу вступят лишь те модификаторы, которые успели вcтретиться. Например, рассмотрите использование модификатора message:

require message = Can't verify sender
verify  = sender
message = Can't verify recipient
verify  = recipient
message = This message cannot be used

Если проверка отправителя неудачна, exim знает, что результат утверждения deny, следовательно, он не движется дальше. Был просмотрен первый модификатор, таким образом, его текст используется как сообщение об ошибке. Если проверка отправителя успешна, но проверка получателя неудачна, используется второе сообщение. Если проверка получателя успешна, текущим становиться третье сообщение, но оно никогда не используется, поскольку больше нет условий, способных вызвать отказ.

Для команды deny, с другой строны, всегда используется последний модификатор message, поскольку все условия должны быть истины, для того, чтобы случилось отклонение получателя. Задание более, чем одного модификатора message не имеет смысла, и сообщение может быть определено даже после всех условий. Например:

deny   hosts = ...
      !senders = *@my.domain.example
       message = Invalid sender from client host

Результат deny не происходит, пока не будет достигнут конец утверждения, по достижении которого, exim установит сообщение.

39.17. Модификаторы ACL

Модификаторы ACL таковы:

add_header = <text>
Этот модификатор задаёт одну или более строк заголовков которые должны быть добавлены во входящее сообщение, предполагая, разумеется, что сообщение в конечном счёте принято. Для деталей смотрите раздел 39.19.

control = <text>
Этот модификатор затрагивает последующую обработку SMTP-соединения или входящего сообщения, которое принято. Эффект первого типа управления длится для всей продолжительности соединения, тогда как эффект второго типа длится лишь пока не получено текущее соединение. Специфические для сообщения средства управления всегда применяются ко всему сообщению, а не к индивидуальным получателям, даже если модификатор control появляется в RCPT ACL.

Eсть довольно много средств управления, которые могут быть применены, они описываются отдельно в секции 39.18. Модификатор control может использоваться несколькими различными способами. Например:

  • Он может быть в конце утверждения accept:
       accept  ...some conditions
       control = queue_only
    
    В этом случае управление применяется, когда это условие приводит к accept, другими словами, когда все выражения верны.
  • Он может быть в середине утверждения accept:
        accept  ...some conditions...
        control = queue_only
        ...some more conditions...
    
    Если первый набор условий истиннен, управление применяется, даже если утверждение не принимается, поскольку одна из вторых установок условия ложна. В этом случае некоторое последующее утверждение должно уступить accept для релевантного управления.
  • Он может использоваться с warn для применения управления, оставляя решение о приёме или отказе следующей команде. Например:
        warn    ...some conditions...
        control = freeze
        accept  ...
    
    Этот пример warn не содержит message, log_message или logwrite, таким образом, он ничего не добавляет к сообщению и не пишет протоколов.
  • Если Вы хотите безоговорочно применить управление, можете использовать его с командой require. Например:
    require  control = no_multiline_response
    

delay = <time>
Этот модификатор заставляет exim ждать интервал времени до процедуры. Интервал даётся в обычной нотации exim. Этот модификатор может появиться в любой ACL. Задержка происходит срезу при обработке модификатора. Однако, когда exim тестируется с использование опции -bh, задержка не применяется (вместо этого выводится соответствующее сообщение). Как и control, delay может использоваться с accept или deny, например:

deny    ...some conditions...
delay = 30s

Задержка происходит, если все услоия истинны до возвращения deny. Сравните с:

deny    delay = 30s
...some conditions...
которое ждёт 30s до обработки условия. Модификатор delay также может быть использован с warn и вместе с control:
warn    ...some conditions...
delay = 2m
control = freeze
accept  ...

endpass
Этот модификатор, у которого нет аргументов, распознаётся лишь в утверждении accept. Он отмечет границу между условием, чья неудача вызывает передачу управления следующему утверждению, и условием, чья неудача заставляет ACL вернуть deny. Смотрите описание accept выше.

log_message = <text>
Этот модификатор устанавливает сообщение, которое используется как часть сообщения протокола, если ACL запрещает доступ или утверждение warn истинно. Например:

require log_message = wrong cipher suite $tls_cipher
encrypted   = DES-CBC3-SHA

Модификатор log_message добавляется к любому основному сообщению об ошибке, которое может существовать, поскольку условие неудачно. Например, когда проверяется адрес получателя, перенаправление :fail: могло уже установить сообщение. Хотя обычно сообщение задано до условия, к которому оно применяется, раскрытие не происходит, пока exim не решает, что в доступе надо отказать. Это означает, что любые переменные, которые установлены путём выражения, доступны для включения в сообщение. Например, переменные $dnslist_ <xxx> установлены после того, как был успешный поиск в чёрных списках DNS. Если раскрытие log_message неудачно или результат пустая строка, модификатор игнорируется.

Если Вы хотите использовать утверждение warn для протоколирования результата проверки адреса, можете использовать $acl_verify_message для включения сообщения об ошибке проверки.

Если log_message используется с утверждением warn, в начало протоколируемого сообщения добавляется Warning:. Если то же самое предупреждающее сообщение запрашивается более одного раза при получении одного почтового сообщения, пишется лишь одна копия. Если Вы хотите записывать все копии, используйте logwrite вместо log_message. При отсутствии обоих, log_message и message, ничего не пишется для успешного утверждения warn.

Если отсутствует log_message и нет основного сообщения об ошибке (например, из неудачи проверки адреса), но присутствует message, текст message используется для протоколирования отказа. Однако, если какой-либо текст для протокола содержит символы новой строки, лишь первая строка пишется. При отсутствии log_message и message для протоколирования отклонения используется встроенное сообщение.

logwrite = <text>
Этот модификатор пишет сообщение в протокол, как только с ним сталкиваются при обработке ACL (сравните с log_message, который, исключая случай warn, используется лишь, если утверждение ACL отказывает в доступе). Модификатор logwrite может использоваться для протоколирования особых инцидентов в ACL. Например:

accept <some special conditions>
       control  = freeze
       logwrite = froze message because ...

По умолчанию сообщение пишется в главный протокол. Однако, оно может начинаться с двоеточия, сопровождаемого списком имён протоколов, разделённых двоеточиями, а затем иным двоеточием, точно определяющим, который протокол будет записан. Например:

logwrite = :main,reject: text for main and reject logs
logwrite = :panic: text for panic log only

message = <text>
Этот модификатор устанавливает текстовую строку, которая раскрывается и используется как сообщение об ошибке, если текущее утверждение заставляет ACL отказать в доступе. Раскрытие происходит в то время, когда exim принимает решение об отказе в доступе не во время обработки message. Если раскрытие неудачно или генерирует пустую строку, модификатор игнорируется. Для ACL, которые вызываются путём SMTP-команд, сообщение возвращается как часть SMTP-ответа об ошибке. Текст является буквальным: любые кавычки берутся как опечатки, но, поскольку строка раскрывается, экранирование обратным слэшом так или иначе обрабатывается. Если сообщение содержит символы новой строки, оно увеличивается до многострочного SMTP-ответа. Как и log_message, содержимое message не раскрывается до тех пор, пока выражение не стало неуспешным.

Если message используется в утверждении, которое проверяет адрес, заданное сообщение перезадаёт любое сообщение, которое сгенерировано путём процесса проверки. Однако, оригинальное сообщение доступно в переменной $acl_verify_message, таким образом, Вы можете включить его в свое сообщение, если этого желаете. В частности, если хотите текст из элемента :fail: в роутере redirect для возвращения обратно как части ответа SMTP, Вы не должны использовать модификатор message или использовать $acl_verify_message.

Для совместимости с предыдущими релизами exim модификатор message, который используется с командой warn, ведёт себя подобно модификатору add_header, но это применение сейчас устарело. Однако, message действует лишь когда все условия истинны, везде где он появляется в команде ACL, тогда как add_header действует, как только с ним сталкиваются. Если message используется с warn в ACL, которая не имеет отношения к получению сообщения, он не имеет эффекта.

message <acl_name> = <value>
Этот модификатор помещает значение в одну из переменных ACL (смотрите раздел 39.15).

39.18. Использование модификатора control

Модификатор control поддерживает следующие установки:

control = allow_auth_unadvertised
Этот модификатор позволяет клиентскому хосту использовать команду SMTP AUTH, даже когда о ней не оповещалось в ответе на HELO. Кроме того, поскольку есть некоторые очень кривые клиенты, exim принимает AUTH после HELO (а не EHLO), когда этот контроль установлен. Это должно использоваться, лишь если Вам это действительно необходимо, и Вы должны ограничить его использование теми кривыми клиентами, которые без этого не работают. Например:

warn hosts   = 192.168.34.25
     control = allow_auth_unadvertised

Обычно, когда сервер exim получает команду AUTH, он проверяет имя аутентификационного механизма, который дан в команде, на совпадение с механизмом, о котором оповещалось. Когда эта установка установлена, проверка на оповещение о механизме обходится. Любые сконфигурированные механизмы могут быть использованы клиентом. Это управление разрешено лишь в соединениях и ACL HELO.

control = caseful_local_part
Смотрите ниже.

control = caselower_local_part
Эти два средства управления разрешены лишь в ACL, определённых путём acl_smtp_rcpt (то есть, в течение обработки RCPT). По умолчанию содержимое $local_part приводится к нижнему регистру до обработки ACL. Если задана caseful_local_part, любые заглавные буквы в оригинальной локальной части восстановлены в $local_part для остальной ACL, или пока не столкнётся с управлением, установленным в caselower_local_part. Эти средства управления применяются лишь к текущему получателю.

Кроме того, они применяются лишь к обработке локальной части, которая имеет место непосредственно в ACL (например, как ключ в поисках). Если присутствует проверка получателя, регистрозависмая обработка локальной части в процессе проверки контролируется конфигурацией роутера (смотрите общую роутеров caseful_local_part).

Это средство могло бы использоваться, например, для добавления спамерских очков к локальной части, содержащей буквы верхнего регистра. Например, используя $acl_m4 для накопления спамерских очков:

warn  control = caseful_local_part
      set acl_m4 = ${eval: $acl_m4 + ${if match{$local_part}{[A-Z]}{1}{0}}}
      control = caselower_local_part
Заметьте, что мы возвращаем назад версию в нижнем регистре, предполагая, что это потребуется для последующих тестов.

control = enforce_sync
Смотрите ниже.

control = no_enforce_sync
Эти средства управления дают возможность селективной SMTP-синхронизации. Глобальная опция smtp_enforce_sync задаёт начальное состояние переключателя (оно истинно по умолчанию). Смотрите описание этой опции в части 14 для дополнительной информации о проверке SMTP-синхронизации.

Эффект этих двух средств управления длится до конца SMTP-соединения. Они могут появиться в любой ACL, кроме одной для не-SMTP сообщений. Самое верное место их размещения в ACL, заданной путём acl_smtp_connect, которая запускается после входящего SMTP-соединения до первой проверки синхронизации. Ожидаемое использование для отключения проверок синхронизации для плохо себя ведущих хостов, с которыми Вам надо работать.

control = fakedefer/<message>
Это средство управления работает точно так же, как и fakereject (описано ниже), исключая, что оно вызывает 450 SMTP-ответ после получения данных вместо ответа 550. При использовании fakedefer Вы должны учесть, что она вызвает повтор сообщений при наступлении времени повтора у отправителя. Поэтому, Вы не должны использовать fakedefer, если сообщение нужно доставить обычным образом.

control = fakereject/<message>
Это средство управления разрешено лишь для ACL MAIL, RCPT, и DATA, другими словами, лишь когда получается SMTP-сообщение. Если exim принимает сообщение, вместо финального ответа 250 посылается 550 отклонение сообщения. Однако, exim продолжает нормальную доставку сообщения. Средство управления применяется лишь к текущему сообщению, но не к любым последующим, которые могут быть получены в том же самом SMTP-соединении. Текст для 550 ответа берётся из модификатора control. Если сообщения не предоставлено, используется следующее:

550-Your message has been rejected but is being
550-kept for evaluation.
550-If it was a legitimate message, it may still be
550 delivered to the target recipient(s).
Это средство должно использоваться с черезвычайной осторожностью.

control = freeze
Это средство управления разрешено лишь для ACL MAIL, RCPT, DATA и не-SMTP ACL, другими словами, лишь когда получается сообщение. Если сообщение принято, оно помещается в очередь exim и замораживается. Средство управления применяется лишь к текущему сообщению, а не к любым последующим, которые могут быть получены в том же самом SMTP-соединении.

Этот модификатор может опционально сопровождаться /no_tell. Если установлена глобальная опция freeze_tell, она игнорируется для текущего сообщения (то есть, никому не сообщается о заморозке) при условии, что все модификаторы control=freeze для текущего сообщения имеют опцию /no_tell.

control = no_mbox_unspool
Это средство управления доступно, когда exim скомпилен с поддержкой расширения контекстного сканирования. Контекстное сканирование может требовать копию текущего сообщения или частей его для записи в формате mbox в файл спула для передачи сканеру на вирусы или спам. Обычно такие копии удаляются, когда они более не нужны. Если это средство управления установлено, копии не удаляются. Средство управления применяется лишь к текущему сообщению, а не к любым последующим, которые могут быть получены в том же самом SMTP соединении. Оно предоставялет средство отладки.

control = no_multiline_response
Это средство управления разрешено для любых ACL, кроме одной для не-SMTP сообщений. Кажется, что существуют кривые клиенты, которые при использовании не могут обрабатывать многострочные SMTP-ответы, несмотря на то, что фактически RFC 2821 определил их более 20 лет назад. Когда эта установка установлена, подавляются многострочные SMTP-ответы, об отклонении из ACL. Один способ сделать это, состоял бы в том, чтобы сделать эти ответы одной длинной строкой. Однако, RFC 2821 определяет максимум 512 байт на ответ (там сказано "use multiline responses for more"), и некоторые из ответов могли бы перекрыть это. Так что, это средство в конечном счёте является лишь подачкой для кривых клиентов и осуществляется путём двух простых вещей:

  • Дополнительная информация, которая обычно выводится как часть отклонения, вызванного ошибкой проверки отправителя, опускается. Посылается лишь финальная строка (обычно, sender verification failed).
  • Если модификатор message предоставляет многострочный ответ, выводится лишь первая строка. Установка переключателя может, размеется, быть сделана зависимой от вызывающего хоста. Его эффект длится до конца SMTP-подключения.

control = queue_only
Это средство управления разрешено лишь для ACL MAIL, RCPT, DATA и не-SMTP ACL, другими словами, лишь когда получается сообщение. Если сообщение принято, оно помещается в очередь exim и оставляется там для доставки обработчиком очереди. Немедленный процесс доставки не запускается. Другими словами, оно имеет эффект глобальной опции queue_only. Однако, средство управления применяется лишь к текущему сообщению, а не к любым последующим, которые могут быть получены в том же самом SMTP-соединении.

control = submission/<options>
Это средство управления разрешено лишь для ACL MAIL, RCPT и начального DATA ACL (последний заданный путём acl_smtp_predata). Его установка говорит exim, что текущее сообщение передано от локального MUA. В этом случае exim работает в режиме передачи (submission mode) и при необходимости применяет определённые исправления к сообщению. Например, он добавляет строку заголовков Date:, если её нет. Это средство управления не разрешено в ACL acl_smtp_data, поскольку она срабатывает слишком поздно (сообщение уже создано).

Часть 43 описывает обработку, которую exim применяет к сообщениям. Раздел 43.1 охватывает обработку, которая происходит в режиме передачи: доступные для этого средства управления и опции описаны там. Средство управления применяется лишь для текущего сообщения, а не к любым последующим, которые могут быть получены в том же самом SMTP-соединении.

control = suppress_local_fixups
Это средство управления применяется к локально переданным (не TCP/IP) сообщениям и это дополнение к control = submission/<options>. Оно отменяет исправления, которые обычно применяются к локально переданным сообщениям. Конкретно:

  • Любые заголовки Sender: оставляются как есть (в этом отношении это динамическая версия local_sender_retain).
  • Не добавляются заголовки Message-ID:, From: и Date:.
  • Нет проверки, что From: соответствует фактическому отправителю.

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

  • Локально переданное, применяются исправления: по умолчанию.
  • Локально переданное, не применяются исправления: использование control = suppress_local_fixups.
  • Удалённо переданное, не применяются исправления: по умолчанию.
  • Удалённо переданное, применяются исправления: control = submission.

39.19. Добавление строк заголовков в ACL

Модификатор add_header может быть использован для добавления одной или более дополнительных строк заголовков во входящее сообщение, как в этом примере:

warn dnslists = sbl.spamhaus.org : \
                dialup.mail-abuse.org
     add_header = X-blacklisted-at: $dnslist_domain

Модификатор add_header разрешается в MAIL, RCPT, PREDATA, DATA, MIME и не-SMTP ACL (лругими словами, тех, которые имеют отношение к получению сообщения). Сообщение должно быть в конечном счёте принято, чтобы add_header имел какой-то существенный эффект. Вы можете использовать add_header с любыми ACL-командами, включая deny (хотя потенциально это полезно лишь в ACL RCPT).

Если данные для модификатора add_header содержат один или более символов новой строки, которые не сопровождаются пустым местом или табуляциями, предполагается, что это несколько строк заголовков. Каждая из них проверена на правильность синтаксиса, в начале каждой строки, не являющейся правильной строкой заголовка, добавляется X-ACL-Warn:. Добавленные строки накапливаются в течение ACL MAIL, RCPT и предданных. Они добавляются в сообщение до обработки ACL DATA и MIME. Однако, если идентичные строки запрошены более одного раза, фактически, в сообщение добавляется лишь одна копия.

Последующие строки заголовков мoгут быть накоплены в течение ACL DATA и MIME, после которых они добавляются в сообщение с таким же подавлением дубликатов. Таким образом, возможно добавить две идентичные строки в SMTP-сообщение, но лишь если одна добавлена до DATA и одна после. В случае не-SMTP сообщений новые заголовки аккумулируются в течение не-SMTP ACL и в конце добавляются в сообщение. Если сообщение отклоняется после DATA или путём не-SMTP ACL, все добавленные строки заголовков включаются в запись, производимую в протокол отклонённых.

Строки заголовков невидимы в раскрытии строк, пока они не добавлены в сообщение. Из этого следует, что строки заголовоков, заданные в ACL MAIL, RCPT и предданных, невидимы до запуска DATA ACL и MIME ACL. Таким же образом, строки заголовков, которые добавлены путём DATA или MIME ACL, невидимы в этих ACL. Из-за этого ограничения Вы не можете использовать строки заголовков как способ передачи данных между (например) ACL MAIL и ACL RCPT. Если Вы хотите это сделать, можете использовать переменные ACL, как описано в разделе 39.15.

Модификатор add_header действует немедленно, как только с ним столкнулись в процессе обработки ACL. Заметьте различие между этими двумя случаями:

accept add_header = ADDED: some text
       <some condition>

accept <some condition>
       add_header = ADDED: some text

В первом случае строки заголовоков всегда добавляются, вне завсимости от того, истинно условие или нет. Во втором случае строки заголовков добавлятся, лишь если условие истинно. Несколько add_header могут быть в одном утверждении ACL. Все встречащиеся до неудачного условия выполняются.

Для совместимости с предыдущими релизами exim модификатор message для команды warn действует таким же образом, как и add_header, исключая что он вступает в силу, лишь если все условия истинны, даже если он появляется до некоторых из них. Кроме того, выполянется лишь последнее появление message. Это использование message теперь осуждается. Если в команде warn представлены оба add_header и message, оба обработаны согласно их спецификациям.

По умолчанию новая строка заголовка добавляется в конце существующих строк. Однако, Вы можете задать, что любая особенная строка заголовка должна быть добавлена в начале (до всех строк Received:), немедленно после первого блока строк Received: или немедленно до любой строки, которая не Received: или Resent-something:.

Это сделано путём определения :at_start:, :after_received: или :at_start_rfc: (или для завершения :at_end:) до текста строки заголовка, соответственно. Текст заголовка не может начинаться с двоеточия, поскольку вначале должно быть имя заголовка. Например:

warn add_header = \
       :after_received:X-My-Header: something or other...

Если более, чем в одном модификаторе add_header предоставляется более одной строки заголовка, каждая рассматривается независимо и может быть помещена по-другому. Если Вы добавляете более одной строки в начале или после блока Received:, они завершаются в обратном порядке.

Предупреждение: Это средство сейчас применяется лишь к строкам заголовков, которые добавлены в ACL. Оно НЕ работает для строк заголовков, которые добавлены в системном фильтре, роутере или транспорте.

39.20. Условия ACL

Некоторые условия, перечисленные в этой секции, доступны, лишь если exim скомпилирован с поддержкой расширения контентного сканирования. Они кратко включены здесь для завершённости. Более детальное описание может быть найдено в обсуждении контентного сканирования в части 40. Не все условия уместны во всех обстоятельствах. Например, проверка отправителей и получателей не имеет смысла в ACL, которая запускается как результат прихода команды ETRN, проверки заголовков сообщения могут быть сделаны лишь в ACL, заданной путём acl_smtp_data или acl_not_smtp. Вы можете использовать некоторые условия (с иными параметрами) более, чем в одном утверждении ACL. Этим предоставляется способ определения соединения and (и). Условия таковы:

  • acl = <name of acl or ACL string or file name >

    Возможные значения аргумента такие же, как и для опций acl_smtp_xxx. Запускается именованная или встроенная ACL. Если она возвращает accept, условие истинно, если deny, условие ложно. Если она возвращает defer, текущая ACL возвращает defer, исключая условия в команде warn. В этом случае возврат defer делает условие ложным. Это означает, что дальнейшая обработка команды warn прекращается, но обработка ACL продолжается.

    Если вложенные acl возвращают drop, и внешнее условие отказывает в доступе, соединеие рвётся. Если они возвращают discard, команда должна быть accept или discard, и действие предпринимается немедленно: никакие дальнейшие условия не проверяются.

    ACL могут быть вложены до 20 уровней: предел существует лишь для поимки циклов. Это условие разрешает использовать различные ACL в разных условиях. Например, различные ACL могут быть использованы для обработки команд RCPT для различных локальных пользователей или доменов.

  • authenticated = <string list>
    Если SMTP-соединение не аутентифицировано, условие ложно. Иначе имя аутентификатора сверяется со списком. Для тестирования аутентификации путём любого аутентификатора, Вы можете задать:
    authenticated = *
    
  • condition = <string>
    Эта возможность позвоялет создавать нестандартные условия. Если результат раскрытия пустая строка, число ноль или одна из строк no или false, условие ложно. Если результат ненулевое число или одна из строк yes или true, условие истинно. Для любых других значений предполагается, что произошла какая-то ошибка, и ACL возвращает defer.
  • decode = <location>
    Это выражение доступно, лишь если exim собран с расширением контентного сканирования, и разрешено лишь в ACL, заданной путём acl_smtp_mime. Он вызывает декодирование текущей части MIME в файл. Для дополнительных деталей смотрите раздел 40.
  • demime = <extension list>
    Это выражение доступно, лишь если exim собран с расширением контентного сканирования. Его использование описано в части 40.6.
  • dnslists = <list of domain names and other data>
    Это условие проверяет записи в чёрных списках DNS. Они также известны как RBL lists, после оригинального Realtime Blackhole List, но отметьте, что это использование списков в mail-abuse.org сейчас приносит большую нагрузку. Есть очень много различных вариантов этого выражения для краткого описания. Для деталей смотрите разделы 39.21-39.29.
  • domains = <domain list>
    Это условие уместно лишь после команды RCPT. Оно проверяет, что домен получателя в списке доменов. Если включена обработка символа процента, она производится до этого теста. Если проверка поиском удачна, результат поиска помещается в $domain_data до слеующего теста domains.
  • encrypted = <string list>
    Если SMTP-соединение нешифрованное, условие ложно. Иначе, имя метода шифрования используется для проверки по списку. Для тестирования на шифрование без тестирования на определённый метод шифрования установите:
    encrypted = *
    
  • hosts = < host list>

    Это условие проверяет, что вызывающий хост совпадает со списком хостов. Если Вы производите поиски имени или шаблонов имён хостов и IP-адресов в одном и том же списке хостов, обычно Вы должны вначале поместить IP-адрес. Например, у Вас могло бы быть:

    accept hosts = 10.9.8.7 : dbm;/etc/friendly/hosts
    

    Причина этого в обработке exim списков слева направо. Он может тестировать IP-адреса без поиска в DNS, но, когда он достигает пункта, требующего имени хоста, он завершается с неудачей, если не может найти имя хоста для сравнения с шаблоном. Если вышеупомянутый список даётся в обратном порядке, утверждение accept неудачно для хоста, чьё имя не может быть найдено, даже если его IP 10.9.8.7.

    Если Вам действительно нужно вначале проверять имена и всё ещё распознавать IP-адреса, даже если поиск неудачен, можете переписать ACL так:

    accept hosts = dbm;/etc/friendly/hosts
    accept hosts = 10.9.8.7
    

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

    Если условие hosts удовлетворяется путём поиска, результат поиска становится доступен в переменной $host_data. Это позволяет, например, установить утверждение типа такого:

    deny  hosts = net-lsearch;/some/file
    message = $host_data
    
    которое позволяет сделать персональное сообщение об ошибке для каждого отказанного хоста.
  • local_parts = <local part list>
    Это условие доступно лишь после команды RCPT. Оно проверяет, что локальная часть адреса получателя находится в списке. Если включена обработка символа процента, она завершется до этого теста. Если проверка успешна путём поиска, результат поиска помещается в $local_part_data, которая остаётся установленной до следующего теста local_parts.
  • malware = <option>
    Это условие доступно, лишь когда exim скомпилирован с поддержкой расширения контентного сканирования. Оно вызывает сканирование входящего сообщения на вирусы. Для дополнительных деталей смотрите раздел 40.
  • mime_regex = <list of regular expressions>
    Это условие доступно, лишь когда exim скомпилирован с поддержкой расширения контентного сканирования, и оно разрешено лишь для ACL, заданной путём acl_smtp_mime. Она вызывает сканирование текeщей MIME-части на совпадение с любым регулярным выражением. Для дополнительных деталей смотрите раздел 40.
  • ratelimit = <parameters>
    Это условие может быть использовано для ограничения частоты, с которой пользователь или хост посылают сообщения. Детали даны в разделе 39.30.
  • recipients = <address list>
    Это условие уместно лишь после команды RCPT. Оно проверяет входящий адрес получателя по списку получателей.
  • regex = <list of regular expressions>
    Это условие доступно, лишь когда exim скомпилирован с поддержкой расширения контентного сканирования, и оно доступно лишь в DATA, MIME и не-SMTP ACL. Оно вызывает сканирование входящего сообщения на совпадение с любым регулярным выражением. Для дополнительных деталей смотрите раздел 40.
  • sender_domains = <domain list>
    Это условие тестирует домен отправителя сообщения с заданным списком доменов. Отметьте: домен адреса отправителя $sender_address_domain. Он не помещается в $domain в процессе тестирования этого условия. Это исключение из общего правила тестирования списков доменов. Так сделано для того, чтобы если это условие используется в ACL для команды RCPT, домен получателя (который находится в $domain) мог влиять на проверку отправителя. Предупреждение: Плохая идея использовать это условие как контроль релеинга, поскольку адреса отправителя легко и обычно подделываются.
  • senders = <address list>
    Это условие тестирует отправителя сообщения по данному списку. Для тестирования рикошетов у которых пустой отправитель установите:
    senders = :
    

    Предупреждение: Плохая идея использовать это условие как контроль релеинга, поскольку адреса отправителя легко и обычно подделываются.

  • spam = <username>
    Это условие доступно, лишь когда exim скомпилирован с поддержкой расширения контентного сканирования. Оно вызывает сканирование входящего сообщения с помощью SpamAssassin. Для дополнительных деталей смотрите раздел 40.
  • verify = certificate
    Это условие истинно, если SMTP-сессия шифрована, клиент передал сертификат, и сертификат был проверен. Сервер запрашивает сертификат, лишь если клиент совпадает с tls_verify_hosts или tls_try_verify_hosts (смотрите часть 38).
  • verify = csa
    Это условие проверяет, авторизован ли хост (клиент) посылать почту. Детали, как это работает, даны в разделе 39.37.
  • verify = header_sender/ <options>
    Это условие уместно лишь в ACL, которая запускается после получения сообщения, то есть в ACL, заданной путём acl_smtp_data или acl_not_smtp. Оно проверяет наличие адреса поддающегося проверке по крайней мере в одном из заголовков Sender:, Reply-To: или From:. Каждый адрес предполагается адресом отправителя (следовательно, именем теста). Однако, адрес, появляющийся в одном из этих заголовков, не должен быть адресом, принимающим рикошеты: лишь адрес отправителя в конверте должен принимать рикошеты. Поэтому, если Вы используете опцию обратного вызова в этой проверке, Вы могли бы хотеть переделать её для непустого адреса в команде MAIL. Детали проверки адреса и опции даны позднее, начиная с секции 39.31 (обратные вызовы описаны в разделе 39.32). Вы можете комбиировать эти условия с условием senders для ограничения его лишь рикошетами:
    deny    senders = :
    message = A valid sender header is required for bounces
           !verify  = header_sender
    
  • verify = header_syntax
    Это условие уместно лишь в ACL, которая запускается после приёма сообщения, то есть, в ACL, заданных путём acl_smtp_data или acl_not_smtp. Она проверяет синтаксис всех строк заголовков, которые могут содержать адреса ((Sender:, From:, Reply-To:, To:, Cc: и Bcc:). Неквалифицированные адреса (локальные части без домена) разрешены лишь в локально сгенерированных сообщениях и от хостов, которые совпадают с sender_unqualified_hosts или с recipient_unqualified_hosts, соотвественно. Отметьте, что это условие лишь проверка синтаксиса. Однако, обычная уловка спамеров использовать для отправки синтаксически неверные заголовки, типа
    To: @
    
    и это условие может использоваться для отклонения таких сообщений, хотя они не очень часто используются.
  • verify = helo
    Это условие истинно, если команда HELO или EHLO была передана с клиентского хоста, и её содержимое было проверено. До него не было никаких попыток проверить содержимое HELO/EHLO, и оно выполняется как только встречаются с этим условием. Смотрите описание опций helo_verify_hosts и helo_try_verify_hosts для деталей о том, как запросить проверку независимо от этого условия.
  • verify = not_blind
    Это условие проверяет, что в сообщении нет получателей скрытой копии (bcc). Каждый получатель конверта должен быть в строке заголовка To: или в Cc:, чтобы это условие было истинным. Локальная часть проверяется регистрозависимо, домен проверяется регистронезависимо. Если существуют строки Resent-To: или Resent-Cc:, они также проверяются. Это условие может использоваться лишь в DATA или не-SMTP ACL. Конечно, есть множество законных сообщений, использующих скрытых получателей. Эта проверка не должна самостоятельно использоваться для блокировки сообщений.
  • verify = recipient/ <options>
    Это условие уместно лишь после команды RCPT. Оно проверяет текущего получателя. Детали проверки адреса даны позднее, начиная с секции 39.31. После проверки получателя, значение $address_data последнее значение, установленное при роутинге адреса. Оно применяется даже если проверка была неуспешной. Когда проверенный адрес переадресован на один адрес, проверка продолжается с новым адресом, и в этом случае последующее значение для $address_data значение дочернего адреса.
  • verify = reverse_host_lookup
    Это условие обеспечивает, что проверенное имя хоста было найдено из IP-адреса клиентского хоста. Это, возможно, уже случилось, если имя хоста необходимо для проверки списка хостов, или если хост совпадает с host_lookup. Проверка обеспечивает, что имя хоста, полученное из обратного поиска DNS, или один из его алиасов, когда он самостоятельно ищется в DNS, действительно приводит к оригинальному IP-адресу. Если это условие используется для локально сгенерированных сообщений (когда нет клиентского хоста), оно всегда успешно.
  • verify = sender/<options>
    Это условие уместно лишь после команды MAIL или RCPT или после того, как сообщение было получено (ACL acl_smtp_data или acl_not_smtp). Если отправитель сообщения пустой (это рикошет), условие истинно. Иначе, проверяется адрес отправителя. Если есть данные в переменной конца роутинга $address_data, её значение помещется в $sender_address_data в конце проверки. Это значение может быть использовано в последующих условиях и модификаторах в том же самом утверждении ACL. Оно не сохраняется после окончания текущего утверждения. Если Вы хотите сохранить значение надолго, можете сохранить его в переменной ACL. Детали проверки адреса даны позднее, начиная с секции 39.31. Exim кэширует результат проверки отправителя, чтобы не делать его более одного раза на сообщение.
  • verify = sender = <address>/<options>
    Это вариант предыдущей опции, в котором модифицированный адрес проверен как отправитель.

39.21. Использование списков DNS

В самой его простой форме условие dnslists проверяет, находится ли вызывающий хост по крайней мере в одном из DNS-списков путём поиска инвертированного IP-адреса в одном или более DNS-домене. Например, если IP-адрес вызывающего хоста 192.168.62.43 и утверждение ACL:

deny dnslists = blackholes.mail-abuse.org : \
                dialups.mail-abuse.org
ищутся следующие записи:
43.62.168.192.blackholes.mail-abuse.org
43.62.168.192.dialups.mail-abuse.org

Как только exim находит существующую запись DNS, обработка списка останавливается. таким образом, многочисленные записи в списке связаны союзом or. Если Вы хотите тестировать хост более, чем одним списком (и союзом and), можете использовать два раздельных условия:

deny dnslists = blackholes.mail-abuse.org
     dnslists = dialups.mail-abuse.org

Если происходит таймаут поиска в DNS или иным образом невозможно дать окончательный ответ, exim ведёт себя, как будто хост не совпал с элементом списка, то есть, как будто запись DNS не существует. Если в списке DNS есть дальнейшие элементы, они обрабатываются.

Это обычное необходимое действие, когда dnslists используется с deny (что является самым частым использованием), поскольку это препятствует ошибке DNS блокировать почту. Однако, Вы можете изменить это поведение путём помещения одного из следующих специальных элементов в список:

+include_unknown    behave as if the item is on the list
+exclude_unknown    behave as if the item is not on the list (default)
+defer_unknown      give a temporary error

Каждый из них применяется к любым последующим элементам списка. Например:

deny dnslists = +defer_unknown : foo.bar.example

Тестирование списка доменов останавливается, как только найдено соответствие. Если Вы хотите предупреждать для одного списка и блокировать для другого, можете задать два различных утверждения:

deny  dnslists = blackholes.mail-abuse.org
warn  message  = X-Warn: sending host is on dialups list
      dnslists = dialups.mail-abuse.org

Поиски в списках DNS кэшируются exim на продолжительность сессии SMTP, таким образом, поиск, основанный на IP-адресе, производится максимум один раз для любого входящего SMTP-соединения. Exim не разделяет информацию между несколькими входящими соединениями (но Ваш локальный кэширующий сервер имён должен быть активен).

39.22. Задание IP-адреса для поиска в списках DNS

По умолчанию IP-адрес, который используется в поиске по списку DNS, это IP-адрес вызывающего хоста. Однако, Вы можете задать иной IP-адрес, путём перечисления его после доменного имени, отделённого слэшем. Например:

deny dnslists = black.list.tld/192.168.1.2

Эта особенность не очень полезна с явными IP-адресами: она предназначена для использования с искомыми IP-адресами, например, IP-адресами MX-хостов или серверов имён почтового адреса отправителя. Для примеров смотрите ниже, секцию 39.24.

39.23. DNS-списки, основанные на именах доменов

Есть некоторые списки, которые основаны на доменных именах, вместо инвертированных IP-адресов (например, смотрите ссылку domain based zones на http://www.rfc-ignorant.org/). С этими листами реверсирование компонентов не используется. Вы можете изменить имя, которое ищется в списках DNS, путём внесения его после имени домена, отделённое слэшем. Например:

deny  message  = Sender's domain is listed at $dnslist_domain
      dnslists = dsn.rfc-ignorant.org/$sender_address_domain

Этот специфический пример полезен лишь в ACL, которые обрабатываются после команд RCPT или DATA, когда доступен адрес отправителя. Если (например) отправитель сообщения user@tld.example, имя, искомое этим примером:

tld.example.dsn.rfc-ignorant.org

Одиночное условие dnslists может содержать в себе оба вхождения для имён и IP-адресов. Например:

deny dnslists = sbl.spamhaus.org : \
                dsn.rfc-ignorant.org/$sender_address_domain

Первый элемент проверяет адрес отправляющего хоста; второй проверяет доменное имя. Всё условие верно, если успешен любой из поисков DNS.

39.24. Поиски в DNS, основанные на нескольких ключах

Синтаксис, описанный выше, для поиска в чёрных списках DNS по явно заданным значениям (имени или IP-адреса) упрощение. В DNS-списке после доменного имени, сопровождаемого слэшем, фактически, может быть список элементов. Как и во всех списках exim, разделителем по умолчанию является двоеточие. Однако, поскольку это подсписок в списке доменов чёрных списков DNS, необходимо удвоить разделители:

dnslists = black.list.tld/name.1::name.2
или изменить символ разделителя, например так:
dnslists = black.list.tld/<;name.1;name.2

Если элемент в списке IP-адрес, он инвертируется до добавления области чёрного списка DNS. Если он не IP-адрес, иныерсии не происходит. Рассмотрите это условие:

dnslists = black.list.tld/<;192.168.1.2;a.domain

Происходящие поиски в DNS:

2.1.168.192.black.list.tld
a.domain.black.list.tld

Как только найдена запись в DNS (которая совпадает с заданным возвращаемым IP-адресом, если задано, смотрите раздел 39.27), дальнейший поиск не производится. Если происходит временная ошибка поиска в DNS, пробуется остальная часть списка доменов/IP-адресов. Временная ошибка для всего элемента списка DNS происходит лишь если безуспешны поиски по остальным DNS-подспискам. Другими словами, успешный поиск для любого элемента подсписка отменяет временную ошибку для предыдущего элемента.

Способность подставлять список элементов после слэша в некотором смысле лишь синтаксическое удобство. Следующие два примера имеют один и тот же эффект:

dnslists = black.list.tld/a.domain : black.list.tld/b.domain
dnslists = black.list.tld/a.domain::b.domain

Однако, когда данные для списка получаются путём поиска, вторая форма обычно намного более удобна. Рассмотрите этот пример:

deny message  = The mail servers for the domain \
$sender_address_domain \
are listed at $dnslist_domain ($dnslist_value); \
see $dnslist_text.
    dnslists = sbl.spamhaus.org/<|${lookup dnsdb {>|a=<|\
    ${lookup dnsdb {>|mxh = $sender_address_domain} }} }

Отметьте использование >| в поиске dnsdb для задания сепаратора в нескольких DNS-записях. Внутренний поиск dnsdb производит список хостов MX, внешний dnsdb поиск находит IP-адреса этих хостов. Результат раскрытия условия мог бы быть чем-то вроде этого:

dnslists = sbl.spahmaus.org/<|192.168.2.3|
192.168.5.6|...

Таким образом, этот пример проверяет, действительно ли IP-адрес почтового сервера отправителя находится в чёрном списке Spamhaus.

39.25. Данные, возвращаемые списками DNS

DNS-списки построены с использованием записей в DNS. Оригинальный RBL использовал лишь адрес 127.0.0.1 на правой стороне каждой записи, но списки RBL+ и некоторые другие списки используют несколько различных значений. Значения, используемые списками RBL+, таковы:

127.1.0.1  RBL
127.1.0.2  DUL
127.1.0.3  DUL and RBL
127.1.0.4  RSS
127.1.0.5  RSS and RBL
127.1.0.6  RSS and DUL
127.1.0.7  RSS and DUL and RBL
Некоторые списки DNS могут возвращать более одной адресной записи.

39.26. Переменные устанавливаемые из списков DNS

Когда в списке DNS найдено вхождение, переменная $dnslist_domain содержит имя совпавшего домена, $dnslist_text содержит содержимое ассоциированной TXT-записи. Если поиском DNS возвращено более одной записи, все IP-адреса, включённые в $dnslist_value, разделяются запятыми и пробелами.

Вы можете использовать эти переменные в модификаторах message и log_message, хотя они появляются до условия в ACL, они не раскрываются, пока не произойдёт неудача. Например:

deny    hosts = !+local_networks
message = $sender_host_address is listed at $dnslist_domain
dnslists = rbl-plus.mail-abuse.example

39.27. Дополнительные совпадения условий для списков DNS

Вы можете добавить символ = и IP-адрес после доменного имени dnslists для ограничения его действия DNS-записями с соответствующей правой стороной. Например,

deny dnslists = rblplus.mail-abuse.org=127.0.0.2
отклоняет лишь те хосты, которые приводят к 127.0.0.2. Без этих дополнительных данных любая адресная запись предполагается совпадающей. Если в списке найдено более одной записи, они все проверяются на соответствие правой стороне.

Для проверки можно задать более, чем один IP-адрес, используя двоеточие как разделитель. Они альтернативы, если совпадает любой из них, условие dnslists истинно. Например:

deny  dnslists = a.b.c=127.0.0.2,127.0.0.3

Если Вы хотите задать ограниченный список адресов, и также определить имена или IP-адреса для поиска, ограниченный список адресов должен быть задан первым. Например:

deny dnslists = dsn.rfc-ignorant.org \
=127.0.0.2/$sender_address_domain

Если символ & используется вместо =, сравнение для каждого перечисленного IP-адреса завершается путём поразрядного and вместо теста равенства. Другими словами, перечисленные адреса используются как битовые маски. Сравнение истинно, если все биты в маске представлены в тестируемом адресе. Например:

dnslists = a.b.c&0.0.0.3
совпадает с адресом x.x.x.3,x.x.x.7, x.x.x.11 и т.д. Если Вы хотите проверить, что представлен тот или иной бит (в противоположность представленным обоим), Вы должны использовать несколько значений. Например:
dnslists = a.b.c&0.0.0.1,0.0.0.2
совпадает, если последний компонент адреса нечётное число или удвоенное нечетное число.

39.28. Отрицательные условия сравнения DNS

Вы можете предоставлять отрицательный список IP-адресов как часть условия dnslists. Тогда как

deny  dnslists = a.b.c=127.0.0.2,127.0.0.3
средство запрет, если хост в чёрном списке домена a.b.c, и IP-адрес приводит к списку в котором 127.0.0.2 или 127.0.0.3,
deny  dnslists = a.b.c!=127.0.0.2,127.0.0.3
средство запрет, если хост в чёрном списке домена a.b.c, и IP-адрес не приводит к списку, в котором 127.0.0.2 и 127.0.0.3. Другими словами, результат тестирования инвертирован, если восклицательный знак появляется перед символом = (или &).

Отметьте: Этот вид отрицания не то же самое, что и отрицание домена, хостов или списков адресов (почему и синтаксис различается). Если Вы используете только один список, синтаксис отрицания немного Вам даст. Предыдущий пример эквивалентен:

deny  dnslists = a.b.c
     !dnslists = a.b.c=127.0.0.2,127.0.0.3

Однако, если Вы используете составные списки, синтаксис отрицания более ясен. Рассмотрите этот пример:

deny  dnslists = sbl.spamhaus.org : \
      list.dsbl.org : dnsbl.njabl.org!=127.0.0.3 : \
      relays.ordb.org

Используя только позитивные списки, это было бы так:

deny  dnslists = sbl.spamhaus.org :  list.dsbl.org
deny  dnslists = dnsbl.njabl.org
     !dnslists = dnsbl.njabl.org=127.0.0.3
deny  dnslists = relays.ordb.org
который менее ясен и тяжелее поддерживать.

39.29. Списки DNS и IPv6

Если exim просят сделать поиск по списку DNS для адреса IPv6, он его инвертирует и откусывает по кусочкам. Например, если адрес вызывающего хоста 3ffe:ffff:836f:0a00:000a:0800:200a:c031, exim мог бы искать

1.3.0.c.a.0.0.2.0.0.8.0.a.0.0.0.0.0.a.0.f.6.3.8.
f.f.f.f.e.f.f.3.blackholes.mail-abuse.org
(разбито на две строки, чтобы вписать в страницу). К сожалению, некоторые списки DNS содержат групповые записи, подразумевающие IPv4, плохо взаимодействующие с IPv6. Например, DNS-запись
*.3.some.list.example.    A    127.0.0.1
вероятно, предназначен для помещения записи 3.0.0.0/8 сети IPv4 в список. К сожалению, это также соответствует всем сетям 3::/4, для IPv6. Вы можете исключить адреса IPv6 из DNS-поисков, используя подходящее условие condition, как в этом примере:
deny   condition = ${if isip4{$sender_host_address}}
       dnslists  = some.list.example

39.30. Ограничение нормы отправителей

Условие ACL ratelimit может быть использовано для измерения и контроля частоты с которой клиент посылает электронную почту. Это более мощное средство, чем опции smtp_ratelimit_*, поскольку эти опции управляют частотой команд лишь в одной SMTP-сессии, тогда как условие ratelimit работает для всех соединений (параллельных и последовательных) от того же самого хоста. Синтаксис условия ratelimit таков:

ratelimit = <m> / <p> / <options> / <key>

Если средний клиент, посылающий с частотой меньше m сообщений за период времени p, условие ложно, иначе, оно истинно. Как побочный эффект, условие ratelimit устанавливает переменную раскрытия $sender_rate в вычисленную частоту клиента, $sender_rate_limit в сконфигурированное значение m, а $sender_rate_period в сконфигуриованное значение p.

Параметр p является постоянной временной константой в форме интервалов времени exim, например, 8h для восьми часов. Большее постоянное время, означает, что exim требуется большее время, чтобы забыть прошлое поведение клиента. Параметр m задает максимальное число сообщений, которые клиенту разрешено посылать в каждый интервал времени. Также он определяет число сообщений, разрешённых в быстром пакетном режиме. Путём увеличения обоих, m и p, но оставляя неизменной константу m/p, Вы позволяете клиенту посылать больше сообщений в пакетном режиме без изменения его общего предела посылки. Наоборот, если малы оба m и p, сообщения должны посылаться в пределах лимита.

Есть скрипт util/ratelimit.pl, который извлекает частоту частоту отсылки из протоколов, помогая выбрать соответствующие значения для m и p при развёртывании условия ACL ratelimit. Скрипт выводит инструкцию по использованию, когда он запускается без аргументов.

Для поиска данных, для вычисления средней частоты клиента посылки клиентом, используется ключ. Эти данные сохраняются в БД поддерживаемой exim в его спул-каталоге, наряду с другими БД подсказок. Ключ по умолчанию $sender_host_address, который применяет ограничения к каждому IP-адресу клиентского хоста. Путём изменения ключа Вы можете изменить то, как exim идентифицирует клиентов для ограничения частоты. Например, для ограничения частоты отсыла для каждого аутентифицированного пользователя, независимо от компьютера, с которого отсылается, установите ключ в $authenticated_id. Вы должны гарантировать, что ключ является значимым: например, $authenticated_id является значимым, лишь если клиент аутентифицировался, и Вы можете проверять его с условием ACL authenticated.

Внутренне exim включает сглаживание константы p и опции ключа поиска, поскольку они изменяют значение сохранённых данных. Это не истинно для лимита m, таким образом, Вы можете изменять сконфигурированную максимальную частоту, а exim продолжает помнить предыдущее поведение клиента, но если Вы изменяете другие параметры частоты exim забывает прошлое поведение.

Каждое условие ratelimit может иметь до двух опций. Первая опция задаёт, что exim считает мерой частоты, вторая определяет, как exim обрабатывает черезмерно быстрых клиентов. Опции разделены слэшами, как и другие параметры. Опция per_conn ограничивает частоту подключения клиента.

Опция per_mail ограничивает частоту посылки сообщений клиентом. Это значение по умолчанию, если не заданы опции per_*.

Опция per_byte ограничивает полосу пропускания электронной почты отправителя. Отметьте, что её лучше использовать в DATA ACL: если это используется в более ранней ACL, она полагается на параметр SIZE в команде MAIL, которая может быть неточной или вообще отсутствовать. Вы можете сопровождать лимит m в конфигурации K, M, или G для задания, соответственно, килобайт, мегабайт или гигабайт.

Опция per_cmd заставляет exim пересчитывать частоту при каждой обработке условия. Это может быть использовано для ограничения частоты команд SMTP. Алиас per_rcpt предоставлен для использования в RCPT ACL вместо per_cmd для большей ясности, что эффект ограничение частоты, с которой принимаются получатели. Отметьте, что в этом случае движок ограничения частоты будет видеть сообщения с несколькими получателями, как большой высокоскоростной пакетный режим.

Если средняя частота клиента больше, чем максимум, движок ограничения частоты может воздействовать двумя возможными способами, зависящими от наличия опций strict или leaky. Это не зависит от других контрмер (типа отклонения сообщения), которые могут быть заданы путём остальной части ACL. Режим по умолчанию leaky, который избегает сверхагрессивной частоты повтора клиента, препятствуя отправке им любой почты.

Опция strict означает, что клиентские записи частоты всегда обновляются. Эффект этого: exim измеряет среднюю частоту клиента пытаться послать электронную почту, которая может быть значительно выше максимума. Если клиент превысит предел, он будет подвергнут контрмерам, пока он не замедлится ниже максимальной частоты. Период сглаживания определяет время, которое требуется высокой частоте отсылки для экспоненциального снижения до 37% её пикового значения, что означает, что Вы можете не работать время (число периодов сглаживания), которое клиент подвергается контрмерам после резкого превышения лимита по этой формуле:

ln(peakrate/maxrate)

Опция leaky означает, что записи клиентской частоты не обновляются, если он превысил лимит. Эффект этого: exim измеряет среднюю частоту успешного отсыла почты клиентом, которая не может быть больше максимума. Если клиент превышает лимит, он подвергнется контрмерам, но он всё ещё будет способен посылать почту со сконфигурированной максимальной частотой, вне зависимости от частоты его попыток. Это в общем случае лучший выбор, если у Вас есть клиенты с автоматическими повторами.

Другие средства ACL exim используются чтобы задать, какие контрмеры предпринимаются, когда превышен лимит частоты. Это может быть что-то из записи предупреждений (например, когда измеряется существующая частота отсылки для задания политики) через временные задержки для замедления быстрых отправителей, до отклонения сообщений. Например:

# Log all senders' rates
warn
  ratelimit = 0 / 1h / strict
  log_message = Sender rate $sender_rate / $sender_rate_period

# Slow down fast senders; note the need to truncate $sender_rate
# at the decimal point.
warn
  ratelimit = 100 / 1h / per_rcpt / strict
  delay     = ${eval: ${sg{
$sender_rate}{[.].*}{}} - $sender_rate_limit }s

# Keep authenticated users under control
deny
  authenticated = *
  ratelimit = 100 / 1d / strict / $authenticated_id

# System-wide rate limit
defer
  message = Sorry, too busy. Try again later.
  ratelimit = 10 / 1s / $primary_hostname

# Restrict incoming rate from each host, with a default
# set using a macro and special cases looked up in a table.
defer
  message = Sender rate exceeds $sender_rate_limit \
    messages per $sender_rate_period
  ratelimit = ${lookup {$sender_host_address} \
cdb {DB/ratelimits.cdb} {$value} {RATELIMIT}}

Предупреждение: Если у Вас нагруженный сервер с большим количеством тестов ratelimit, особенно с опцией per_rcpt, Вы можете пострадать от узкого места производительности, вызванного путём блокировок в БД подсказок ограничений частоты. Кроме создания менее сложных ACL, можете уменьшить проблему путём использования RAM-диска для каталога подсказок exim (обычно это /var/spool/exim/db/). Однако, это означает, что exim потеряет все свои подсказки после перезагрузки (включая подсказки повторов, кэш обратного вызова и данные ограничения частоты).

39.31. Проверка адресов

Несколько условий verify, описанных в секции 39.20, вызывают проверку адреса. Эти условия могут сопровождаться опциями, которые модифицируют процесс проверки. Опции отделены от ключевого слова и друг от друга слэшами, и некоторые из них содержат параметры. Например:

verify = sender/callout
verify = recipient/defer_ok/callout=10s,defer_ok

Первая стадия проверки адреса, которая всегда происходит, это запуск адреса через роутер в режиме проверки (verify mode). Роутеры могут детектировать различие между проверкой и роутингом для доставки, и их действия могут быть множеством различных общих опций, типа verify и verify_only (смотрите часть 15). Если роутинг неудачен, проверка неудачна. Доступные опции таковы:

  • Если задана опция callout, успешный роутинг к одному или более удалённых хостов сопровождается обратным вызовом (callout) к тем же хостам как дополнительная проверка. Обратные вызовы и их субопции обсуждаются в следующей секции.
  • Если при проверке роутинга присходит ошибка отсрочки, ACL обычно возвращает defer. Однако, если Вы включаете defer_ok в опцию, вместо этого условие становится принудительно верным. Отметьте, что это главная проверочная опция, также как и субопции для обратных вызовов.
  • Опция no_details охвачена в секции 39.35, в которой обсуждаются отчёты о неудаче проверки адреса отправителя.
  • Опция success_on_redirect приводит к тому, что проверка всегда успешна немедленно после успешного редиректа. По умолчанию, если редирект генерирует лишь один адрес, этот адрес также проверяется. Дальнейшее обсуждение смотрите в разделе 39.36.

После неудачи проверки адреса $acl_verify_message содержит сообщение об ошибке, которое ассоциировано с ошибкой. Оно может быть сохранено, путём такого кодирования:

warn  !verify = sender
       set acl_m0 = $acl_verify_message

Если Вы пишете собственное сообщение об отклонении или сообщение в протоколы, когда отказано в доступе, можете использовать эту переменную для включения информации об ошибке проверки.

В дополнение, $sender_verify_failure или $recipient_verify_failure (соответственно), содержат одно из следующих слов:

  • qualify: Адрес был неквалифицированный (без домена), и сообщение не являлось локальным или прибывшим со свободного хоста.
  • route: Ошибка роутинга.
  • mail: Роутинг успешен и была предпринята попытка обратного вызова, отклонение произошло до команды MAIL (то есть в начале соединения, HELO или MAIL).
  • recipient: В обратном вызове была отклонена команда RCPT.
  • postmaster: В обратном вызове была выполнена проверка постмастера.

Как ожидается, основным использованием этих переменных будет различение между отклонением MAIL и RCPT в обратных вызовах.

39.32. Проверка обратным вызовом

Для нелокальных адресов роутинг проверяет домен, но он не способен сделать какую-либо проверку локальной части адреса. Есть ситуации, когда желательно какое-то средство проверки локальной части. Одним из способов это сделать, может быть создание SMTP callback к хосту доставки для адреса отправителя или callforward к последующему хосту для адреса получателя, чтобы увидеть, принимает ли хост адрес. Мы используем термин callback для охвата обоих случаев. Отметьте, что для адреса отправителя, обратный вызов не к хосту клиента, который пытается доставить сообщение, а к одному из хостов, которые принимают входящую почту для домена отправителя.

Exim по умолчанию не производит обратных вызовов. Если Вы хотите, чтобы они происходили, Вы должны запросить их путём установки соответствующих опций в условии verify, как описано ниже. Это средство должно использоваться с осторожностью, поскольку оно может добавить много затрат ресурсов на проверку адреса. Однако, exim кэширует результаты обратных вызовов, что помогает уменьшить их стоимость. Детали о кэшировании даны в секции 39.34.

Обратные вызовы для получателей обычно используются лишь между хостами, которыми управляет один и тот же администратор. Например, корпоративный шлюз может использовать обратные вызовы для проверки допустимости получателей на внутреннем почтовом сервере. Успешный обратный вызов не гарантирует, что реальная доставка на адрес была бы успешной, с другой стороны, неудачный обратный вызов гарантирует, что доставка была бы неудачной.

Если опция callout представлена в условии, проверяющем адрес, вторая стадия проверки происходит, если адрес успешно маршрутизирован к одному или более удалённым хостам. Обычный случай: роутинг путём роутера dnslookup или manualroute, где роутер определяет хосты. Однако, если роутер, который не устанавливал маршруты хостов в транспорте smtp с установкой hosts, используются хосты транспорта. Если в транспорте smtp установлена hosts_override, всегда используются её хосты, вне зависимости, предоставлен или нет роутером список хостов.

Используемый порт берётся из транспорта, если он задан, и это удалённый транспорт. Для роутеров, которые лишь делают проверку, транспорт не нужно задавать. Иначе используется порт SMTP по умолчанию. Если удалённый транспорт задаёт исходящий интерфейс, используется он, иначе интерфейс не определён.

Для проверки обратным вызовом отправителя exim создаёт SMTP-соединение к удалённому хосту для проверки, может ли быть доставлен на адрес отправителя рикошет. Посылаются следующие SMTP-команды:

HELO <smtp active host name>
MAIL FROM:<>
RCPT TO:<the address to be tested>
QUIT

Вместо HELO используется LHLO, если транспортная опция protocol установлена в lmtp. Проверка обратным вызовом получателя подобна. По умолчанию она также использует пустой адрес для отправителя. Такое значение по умолчанию выбрано потому, что большинство хостов не используют адрес отправителя при проверка получателя. Использование тех же самых адресов средство для использования одной записи в кэше для каждого получателя. Однако, некоторые сервера используют для проверки адрес отправителя. Они обслуживаются опциями use_sender и use_postmaster, описанными в следующей секции.

Если ответ на команду RCPT код 2xx, проверка успешна. Если 5xx, проверка неудачна. Для любых других обстоятельств, exim пробует следующий хост, если он есть. Если есть проблемы со всеми удалёнными хостами, ACL вернёт defer, если для опции callout не дан параметр defer_ok, в случае чего условие принудительно успешно.

39.33. Дополнительные параметры для обратных вызовов

Опция callout может сопровождаться символом = и несколькими опциональными параметрами, разделёнными запятыми. Например:

verify = recipient/callout=10s,defer_ok

Старый синтаксис, имевший callout_defer_ok и check_postmaster как отдельные опции проверки, оставлен для обратной совместимости, но его использование не приветствуется. Дополнительный параметры для callout таковы: <a time interval>
Этим определяется интервал, который применяется к попытке обратного вызова к каждому хосту. Например:

verify = sender/callout=5s

По умолчанию он 30 секунд. Таймаут используется для каждого ответа с удалённого хоста. Также он используется для инициации связи, если не перезадан путём параметра connect. connect = <time interval>
Этот параметр делает возможным установить различные (обычно меньшие) таймауты для создания SMTP-cоединения. Например:

verify = sender/callout=5s,connect=1s
Если не задано, то по умолчанию этот таймаут равен значению общего таймаута. defer_ok
Когда этот параметр присутствует, ошибки соединения с любым хостом или любые другие виды временных ошибок обрабатываются как успех ACL. Однако, при таких обстоятельствех кэш не обновляется. fullpostmaster
Эта опция работает как и опция postmaster (смотрите ниже), но если проверка на postmaster@domain неудачна, она пробует просто postmaster без домена в соответствии со спецификацией RFC 2821. RFC заявляет, что неквалифицированный адрес postmaster должен быть принят. mailfrom = <email address>
Когда проверка адресов в строках заголовков использует проверочную опцию header_sender, exim по умолчанию ведёт себя как будто адреса являются адресами отправителя из конверта. Проверка обратным вызовом поэтому проверяет, может ли быть доставлен рикошет путём использования пустого адреса в команде MAIL. Однако, спорно, что эти адреса никогда бы не могли бы использоваться как отправители конверта, а поэтому рикошеты (с пустым отправителем) могли быть правомерно отклонены. Параметр обратного вызова mailfrom позволяет определить, какой адрес использовать в команде MAIL. Например:
require  verify = header_sender/callout=mailfrom=abcd@x.y.z
Этот параметр доступен лишь в опции header_sender. maxwait = <time interval>
Этот параметр устанавливает полный таймаут для выпонения проверки обратным вызовом. Например:
verify = sender/callout=5s,maxwait=30s

По умолчанию этот таймаут равен четырём таймаутам для индивидуальных SMTP-команд. Общий таймаут применяется, когда существует более одного хоста, который можно попробовать. Таймаут проверяется до того, как пробуется следующий хост. Это предотвращает очень большие задержки, если существует большое количество хостов, и у всех у них таймаут (например, когда сетевой таймаут). no_cache
Когда дан этот параметр, кэш обратных вызовов не читается и не обновляется. postmaster
Когда установлен этот параметр, успешная проверка обратным вызовом сопровождается подобной проверкой на локальную часть postmaster для того же самого домена. Если этот адрес отклоняется, обратный вызов неудачен (но смотрите fullpostmaster, выше). Результат проверки постмастера записывается в кэш: если она неудачна, это используется для неудачи следующего обратного вызова для домена без создания соединения, пока не истечёт время записи в кэше. postmaster_mailfrom = <email address>
По умолчанию проверка постмастера использует в команде MAIL пустой адрес отправителя. Вы можете использовать этот параметр для проверки с использованием иного адреса. Например:

require  verify = sender/callout=postmaster_mailfrom=abc@x.y.z

Если представлены обе опции, postmaster и postmaster_mailfrom, отвергается самая правая. Параметр postmaster эквивалентен этому примеру:

require  verify = sender/callout=postmaster_mailfrom=

Предупреждение: Меры кэширования для проверки постмастера не принимают во внимание адрес отправителя. Предполагается, что будет использоваться пустой или фиксированный непустой адрес. Всё, что exim запоминает, что проверка постмастера для домена успешна или неудачна. random
Когда установлен этот параметр, до обычной проверки обратным вызовом exim проверяет случайную локальную часть того же домена. Локальная часть реально не случайна: она задаётся путём раскрытия опции callout_random_local_part, которая по умолчанию такова:

$primary_host_name-$tod_epoch-testing

Идея состоит в том, чтобы попробовать определить, принимает ли удалённый хост все локальные части без проверки. Если этот так, нет никакого смысла в выполнении обратного вызова для определённых локальных частей. Если проверка random успешна, результат сохраняется в записи кэша и используется для принудительного успеха последующих проверок обратным вызовом без создания соединения до тех пор, пока не истечёт время жизни записи. use_postmaster
Этот параметр применяется лишь к обратным вызовам проверки получателя. Например:

deny  !verify = recipient/callout=use_postmaster

Он вызывает использование в команде MAIL непустого адреса при выполнении обратного вызова проверки получателя, а также для проверки random, если она сконфигурирована. Локальная часть адреса postmaster, а домен содержимое $qualify_domain. use_sender:
Этот параметр применяется лишь к обратным вызовам проверки получателя. Например:

require  verify = recipient/callout=use_sender

Он вызывает использование фактического адреса отправителя в команде MAIL при проверке обратным вызовом вместо пустого адреса. Нет необходимости использовать эту опцию, если Вы не знаете, что вызываемые хосты используют отправителя при проверке получателя. Если её использовать неразборчиво, она уменьшает полноценность кэширования обратных вызовов.

Если Вы используете любой параметр, который устанавливает непустого отправителя для команды MAIL (mailfrom, postmaster_mailfrom, use_postmaster или use_sender), Вы должны подумать о возможных циклах. Проверка получателя обычно производится между двумя хостами под одним и тем же управлением и хост, который получает обратный вызов, обычно не конфигурируется для непосредственного проведения обратного вызова. Поэтому, обычно безопасно использовать use_postmaster или use_sender в этих случаях.

Однако, если Вы используете непустой адрес отправителя для обратного вызова к произвольному хосту, есть вероятность, что удалённый хост сам инициирует обратный вызов к Вашему хосту. Поскольку он проверяет отправителя сообщения, он, вероятно, будет использовать пустой адрес в MAIL, избегая цикла обратных вызовов. Однако, в целях безопастности лучше всего было бы настроить собственные ACL, чтобы они не проводили проверку отправителя, когда адрес получателя является адресом, который Вы используете для отправителя заголовка или проверки постмастера обратным вызовом.

Другая проблема, над которой стоит подумать при использовании непустых отправителей для обратных вызовов, кэширование. Когда Вы устанавливаете mailfrom или use_sender, в записях кэша в качестве ключа используется комбинация отправитель/получатель: таким образом, для любого данного получателя выполняется намного больше обратных вызовов, чем когда используется пустой отправитель или постмастер.

39.34. Кэширование обратных вызовов

Exim кэширует результаты обратных вызовов с целью уменьшить количество используемых ресурсов, если не задан параметр no_cache с опцией callout. База данных подсказок, называемая callout, используется для кэша. Используются два различных типа записей: первые типы записей результат проверок обратным вызовом для специфических адресов, а другие информационные записи, которые применяются ко всему домену (например, что он принимает локальную часть postmaster).

Когда оригинальный обратный вызов неудачен, дается детальное SMTP-сообщение об ошибке. Однако, для последующих ошибок используются кэшированные данные и это сообщение недоступно.

Времена жизни для негативных и позитивных записей адресного кэша независимы, и могут быть установлены путём глобальной опции callout_negative_expire (значение по умолчанию: 2 часа) и callout_positive_expire (значение по умолчанию: 24 часа), соответственно.

Если хост даёт отрицательный ответ в SMTP-соединении или отклоняет любую команду до и включительно

MAIL FROM:<>
(но не включая команду MAIL с непустым адресом), любая попытка обратного вызова обязана стать неудачной. Exim помнит такие ошибки в записях кэша доменов, который используется для неудачи обратных вызовов для домена без создания нового соединения, пока не кончится время жизни записи. Есть два отдельных времени окончания записей для кэша доменов: callout_domain_negative_expire (значение по умолчанию: три часа) и callout_domain_positive_expire (значение по умолчанию: семь дней).

Записи доменов истекают, когда достигается негативное время жизни, если обратный вызов не может быть сделан для домена или если неудачна проверка постмастера. Иначе, они истекают по достижении времени истечения. Это гарантирует, например, что хост, остановивший приём случайных локальных частей, в конечном счёте будет замечен.

Механизм кэширования обратных вызовов основан на домене проверяемого адреса. Если домен роутится к нескольким хостам, предполагается, что их поведение будет одинаковым.

39.35. Отчёты проверки адресов отправителя

Когда проверка отправителя неудачна в ACL, детали об ошибке даются как дополнительные строки до 550-го ответа на релевантную SMTP-команду (RCPT или DATA). Например, если используется обратный вызов отправителя, Вы могли бы видеть:

MAIL FROM:<xyz@abc.example> 250 OK
RCPT TO:<pqr@def.example>
550-Verification failed for <xyz@abc.example>
550-Called:   192.168.34.43
550-Sent:     RCPT TO:<xyz@abc.example>
550-Response: 550 Unknown local part xyz in
<xyz@abc.example>
550 Sender verification failed

Если таким же образом была неудачна более, чем одна команда RCPT, делали даются лишь для первой из них. Однако, некоторые администраторы не хотят отсылать об этом слишком много информации. Вы можете подавить детализацию путём добавления /no_details к утверждению ACL, которое запрашивает проверку отправителя. Например:

verify = sender/no_details

39.36. Перенаправление при проверке

Возникает дилемма, когда локальный адрес редиректится путём алиасинга или форвардинга во время проверки: должны ли быть проверены сгенерированные адреса, или успешного раскрытия оригинального адреса достаточно для подтверждения? По умолчанию, exim выбирает следующий прагматический подход:

  • Когда входящий адрес переадресован лишь к одному дочернему адресу, проверка продолжается с дочерним адресом, и если проверка неудачна, оригинальная проверка также неудачна.
  • Когда входящий адрес переадресован более, чем к одному дочернему адресу, проверка не продолжается. Возвращается успешный результат.

Это кажется наиболее разумным поведением для общего использования алиасинга как способ редиректа различных локальных частей к тому же самому почтовому ящику. Это означает, например, что пара записей алиасов формы

A.Wol:   aw123
aw123:   :fail: Gone away, no forwarding address
работает как ожидается, вызывая ошибку с обоими локальными частями. Когда редирект генерирует более одного адреса, поведение больше походит на список рассылки, где существования алиаса достаточно для успешности проверки.

Однако, возможно изменить поведение по умолчанию так, что все успешные редиректы считаются как успешная проверка, однако генерируется много новых адресов. Это определено путём проверочной опции success_on_redirect. Например:

require verify = recipient/success_on_redirect/callout=10s

В этом примере проверка успешна, если роутер генерирует новый адрес и обратный вызов не происходит, поскольку никакой адрес не роутится на удалённый хост.

39.37. Клиентская SMTP-авторизация (CSA)

Клиентская SMTP-авторизация представляет собой систему, которая позволяет давать объявление, каким машинам можно, а каким нельзя посылать электронную почту. Это делается путём помещения специальной SRV записи в DNS: она ищется, используя домен из HELO клиента. Клиентская SMTP-авторизация выполняется в exim путём условия ACL:

verify = csa

Оно неудачно, если клиент не авторизован. Если существует проблема в DNS, не найдена действительная CSA SRV запись или если клиент авторизован, условие успешно. Эти три случая можно различить, используя переменную раскрытия $csa_status, которая может принимать одно из значений fail, defer, unknown или ok. Условие самостоятельно не отсрочивает доставку, поскольку, вероятно, это вызвало бы проблемы для закооной почты.

Сообщения об ошибках производимые кодом CSA включают немного больше деталей. Если $csa_status defer, это может быть потому, что проблемы при поиске записи CSA SRV или проблемы поиска целевой записи CSA. Есть четыре причины, чтобы $csa_status был fail:

  • Клиентское имя хоста явно не разрешено.
  • IP-адрес клиента не совпадает с какими-либо целевыми IP-адресами CSA.
  • Клиентское имя хоста авторизовано, но у него нет допустимых IP-адресов (например, целевые адреса IPv6, клиент использует IPv4).
  • Клиентское имя хоста не имеет записи CSA SRV, но родительский домен явно утверждает, что все субдомены должны быть явно разрешены. Условие проверки CSA может принимать аргумент, являющейся доменом для использования в запроса DNS. Значение по умолчанию:
    verify = csa/$sender_helo_name
    

Это воплощение включает расширение CSA. Если запрос домена буквальный адрес, типа [192.0.2.95], или если это голый IP-адрес, exim ищет записи записи в обратных DNS, как будто домен HELO был (например) 95.2.0.192.in-addr.arpa. Поэтому, это значит сказать:

verify = csa/$sender_host_address

Фактически, это проверка, выполянемая exim если клиент не сказал HELO. Это расширение может быть отключено путём установки опции в главной конфигурации dns_csa_use_reverse в ложь.

Если непосредственно для домена не найдена запись CSA SRV, поиск выполянется через его родительские домены для записи, которая могла бы сделать утверждение о субдоменах. Максимальная глубина этого поиска ограничена, используя опцию главной конфигурации dns_csa_search_limit, которая по умолчанию равна 5. Exim не ищет CSA SRV в домене верхнего уровня, таким образом, установка по умолчанию обработки домена HELO семь (hostname.five.four.three.two.one.com). Это охватывает большинство легитимных доменов HELO.

Поиск dnsdb также имеет поддержку для CSA. Хотя dnsdb также поддерживает прямые поиски SRV, этого недостаточно из-за поведения высшего домена для поиска CSA, и (как с поисками PTR) dnsdb также превращает IP-адреса в поиске в обратном пространстве DNS. Результат успешного поиска, типа:

${lookup dnsdb {csa=$sender_helo_name}}
имеет два поля разделённых пробелами: код авторизации и имя целевого хоста. Авторизационный код может быть Y для yes, N для no, X для явно требуемого разрешения, но отсутствия или ? для неизвестного.

39.38. Проверка тега адреса рикошета

Проверка тэга адреса рикошета (Bounce address tag validation, BATV), это схема, посредством которой отправители конверта исходящего сообщения имеют добавленный к ним шифрованный тэг с меткой времени. Подлинные входящие рикошеты всегда должны быть адресованы получателям, которые имеют действительный тэг. Эта схема дает способ детектировать нежелательные рикошеты, вызванные подделкой адреса (часто называемые сопутствующим спамом), поскольку получатели таких сообщений не содержат в себе действительный тэг.

Есть два элемента раскрытия для помощи в реализации схемы BATV prvs (частная подпись private signature) в конфигурации exim. Эта схема подписывает оригинальный адрес отправителя конверта путём использования простого разделённого ключа для добавления хэша адреса и некоторой, основанной на времени рандомизированной информации. Элемент раскрытия prvs создаёт подписанный адрес, а элемент раскрытия prvscheck проверяет его. Синтаксис этих пунктов описан в разделе 11.5.

Как пример, предположим, что секретные ключи (по ключу на адрес) были сохранены в БД MySQL. Запрос для поиска ключа для адреса мог быть определён макросом типа этого:

PRVSCHECK_SQL = ${lookup mysql{SELECT secret FROM batv_prvs \
                WHERE sender='${quote_mysql:$prvscheck_address}'}{$value}}

Предположим также, что отправители, использующие BATV, заданы списком адресов, называемым batv_senders. Тогда в ACL для команд RCPT Вы могли бы использовать это:

# Bounces: drop unsigned addresses for BATV senders
deny message = This address does not send an unsigned reverse path.
     senders = :
     recipients = +batv_senders

# Bounces: In case of prvs-signed address, check signature.
deny message = Invalid reverse path signature.
     senders = :
     condition  = ${prvscheck {$local_part@$domain}\
  {PRVSCHECK_SQL}{1}}
     !condition = $prvscheck_result

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

Адреса, не подписанные prvs, не отклоняются вторым утверждением, поскольку раскрытие prvscheck приносит пустую строку, если его первый аргумент не prvs-подписанный адрес, вызывая, таким образом, что условие condition становится ложным. Если первый аргумент синтаксически верный prvs-подписанный адрес, возвращается третья строка (в этом случае 1), независимо от успеха проверок шифрования и таймаута.

Переменная $prvscheck_result содержит результат проверок (пустая для ошибки, 1 для успеха). Есть ещё две проблемы, которые Вы должны рассмотреть при осуществлении prvs-подписей. Во-первых, Вы должны гарантировать, что prvs-подписанный адрес не блокируется ACL. Такие адреса содержат символы слэша, но конфигурация exim по умолчанию содержит это утверждение в ACL RCPT:

deny    message       = Restricted characters in address
domains       = +local_domains
local_parts   = ^[.] : ^.*[@%!/|]

Это консервативное правило, которое блокирует локальные части, содержащие слэши. Вы должны удалить слэш в последней строке. Во-вторых, Вы должны гарантировать, что роутеры примут prvs-подписанные адреса и корректно доставят их. Самый простой способ обработать их: использовать роутер redirect для удаления сигнатуры с подобной конфигурацией:

batv_redirect:
  driver = redirect
  data = ${prvscheck {$local_part@$domain}{PRVSCHECK_SQL}}

Это работает потому, что если третий аргумент prvscheck пустой, результат раскрытия prvs-подписанного адреса декодированное значение оригинального адреса. Этот роутер, вероятно, должен быть первым в роутерах, которые обрабатывают локальные адреса. Для создания BATV-подписанного адреса в первом месте может использоваться транспорт такой формы:

external_smtp_batv:
  driver = smtp
  return_path = ${prvs {$return_path} \
       {${lookup mysql{SELECT secret FROM batv_prvs WHERE \
       sender='${quote_mysql:$sender_address}'} {$value}fail}}}

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

39.39. Использование ACL для управления релеингом

MTA, как говорят, передает (relay) сообщение, если оно передаётся с некоторого хоста и непосредственно доставляется на другой хост, как результат удалённого адреса, содержавшегося в нём. Переадресация локальных частей через файл алиасов или форвардов, а затем передача сообщения на другой хост не релеинг, а редирект в результате обработки символа процента (percent hack).

Существует два вида релеинга, которые называют incoming и outgoing. Хост, действующий как шлюз или резервный MX, имеет отношение ко входящему релеингу от произвольных хостов к специфически установленным доменам. С другой стороны, хост, выступающий в роли умного хоста для множества клиентов, имеет отношение к исходящему релеингу от этих клиентов ко всему интернету. Часто некоторые хосты выполняют обе функции, но в принципе эти два вида релеинга полностью независимы. То, что не требуется, передача почты с произвольного удалённого хоста через Вашу систему к произвольным доменам.

Вы можете осуществить контроль релея путём подходящих утверждений ACL, которые выполняются для каждой команды RCPT. Для удобства часто самое лёгкое, использовать средство именованного списка exim для задания вовлечённых доменов и хостов. Например, предположим, что Вы хотите следующее:

  • Доставлять множество доменов в почтовые ящики локального хоста (или локально обрабатывать их каким-то другим способом). Скажем, это my.dom1.example и my.dom2.example.
  • Релеить почту для множества других доменов, для которых Вы являетесь вторичным MX. Это могли бы быть friend1.example и friend2.example.
  • Релеить почту от хостов в Вашей локальной сети к любым вовлечённым доменам. Предположим, Ваша LAN 192.168.45.0/24.

В главной части конфигурации Вы помещаете следующие определения:

domainlist local_domains = my.dom1.example : my.dom2.example
domainlist relay_domains = friend1.example : friend2.example
hostlist   relay_hosts   = 192.168.45.0/24

Теперь Вы можете использовать эти определения в ACL, работающих для каждой команды RCPT:

acl_check_rcpt:
   accept domains = +local_domains : +relay_domains
   accept hosts   = +relay_hosts

Первое утверждение принимает любую команду RCPT, которая содержит адрес в локальном или релейном домене. Для любых других доменов управление передаётся второму утверждению, которое принимает команды, лишь если они приходят с релейных хостов. Практически, Вы, вероятно, захотите создать свою более сложную ACL чем эта, например, путём включения отправителя и проверки получателя. Конфигурация по умолчанию включает более всесторонний пример, который описан в части 7.

39.40. Проверка конфигурации релея

Вы можете проверить характеристики релея Вашей конфигурации таким же образом, как и проверяете поведение любой ACL для входящих SMTP-подключений, путём использования опции -bh, для запуска поддельной SMTP-сессии, с которой Вы взаимодействуете.

Для особого тестирования на нежелательный релеинг, хост relay-test.mail-abuse.org предоставляет полезный сервис. Если Вы подключитесь по telnet на этот хост с хоста на котором запущен exim, используя обычный порт telnet, Вы увидите обычное сообщение о соединении telnet, а затем будет довольно долгая задержка. Будьте терпеливы. Удалённый хост создаёт SMTP-соединение обратно на Ваш хост и пробует множество обычных исследований на тестирование уязвимости открытых релей. Результаты тестов, в конечном счёте, появятся на Вашем терминале.