Настройка почтовой системы. Агент пересылки почты Exim

  1. Основные термины
  2. Введение
  3. Структура таблиц в базе данных
  4. Агент доставки почты Dovecot
  5. Агент пересылки почты Exim
  6. Веб интерфейс Roundcube
  7. Заключение
  8. Список литературы
  9. Комментарии

4. Агент пересылки почты Exim

Exim является одним из лучших MTA, т.к. он чертовски быстр, бесплатен, обладает большим количеством возможностей и поддерживаемых технологий, а также возможностью гибкой и тонкой настройки под любые задачи. Одной из самых классных фич Exim,а являются списки контроля доступа (ACL), с помощью которых можно управлять потоком писем практически не ограничивая себя ни в чем. Exim из коробки поддерживает различные форматы почтовых ящиков. Также стоит отметить возможность поиска конфигурации в обычных файлах и различных базах данных (PostgreSQL, MySQL, LDAP и д.р.). В общем, у него есть куча достоинств, которые можно перечислять практически до бесконечности...

Теперь пару слов про конфигурцию MTA... Как уже было сказано ранее Exim у нас будет заниматься только приемом и передачей почтовых сообщений, поэтому в конфиге можно увидеть, что запускаю я его под пользователем smmsp. smmsp — является стандартным системным пользователем, из описания которого можно увидеть, что он предназначен для процесса, занимающегося пересылкой почты. То есть Exim будет работать от пользователя, не имеющего доступа к почтовым ящикам пользователей, что является несомненным плюсом в безопасности почтовой системы. Если вы сделаете также, то вам необходимо будет переназначить права на служебные папки и файлы Exim,а (/var/log/exim, /var/spool/exim) и переназначать их после каждой переустановки/обновлении Exim (поскольку после установки права переназначаются).

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

Теперь самое интересное — защита от спама. Я нигде не использую внешние средства фильтрации, такие как SpamAssasin или DSPAM, поскольку предпочитаю рубить его еще до приема текста сообщения. Вот тут мощь и гибкость списков контроля доступа Exim,а раскрываются во всей красе. Определение хоста (желающего отправить почту на наш сервер) как спамера происходит на основе баллов. Это значит, что практически все проверки в ACL не являются запрещающими, а накидывающими некоторое количество баллов при попадании под какое-нибудь правило. Хосты, набравшие сравнительно большое количество баллов, благополучно размещаются в локальном черном списке (таблица blacklist_tb). Хосты, набравшие такое количество баллов, что их нельзя отнести ни к легитимным хостам, ни к спам хостам заворачиваются в серый список на 29 минут (таблица greylist_tb). По прошествии 29 минут, если хост повторил передачу, то от него принимается письмо и отправитель заносится в белый список, точнее хэш сумма от отправителя и получателя (таблица whitelist_tb). От остальных хостов почта принимается в обычном порядке. Чисткой устаревших записей в таблицах занимается скрипт. Также отмечу, что с целью упрощения отладки правил в ACL и решения проблем, в случае их возникновения на этапе приема письма, в данной конфигурации я сохраняю информацию о проведенных проверках в ACL, которые не прошла отправляющая сторона (см. переменную acl_c_spamlog).

Хочу отметить, что не маловажным при конфигурировании почтового сервера будет использование таких технологий, как SPF и DKIM. Поскольку такие почтовики, как yandex, gmail и другие гиганты очень сильно не доверяют хостам, не имеющих даже той же записи SPF. Например, пока я не настроил на своих серверах DKIM, почтовик гугла помечал все письма с моих серверов как спам и размещал их в соответствующей папке у пользователей.

4.1 Установка

На момент написания статьи в портах доступна версия 4.80.1. Устанавливаем Exim:

  1. # cd /usr/ports/mail/exim
  2. # make install clean

Из предложенных опций я дополнительно выбрал следующие:

  • CONTENT_SCAN — включить поддержку внешних сканеров (например: ClamAV).
  • PGSQL — поддержка СУБД PostgreSQL.
  • READLINE — включить библиотеку readline(3).
  • SPF — поддержка Sender Policy Framework.

Остальные опции я не изменял. Поскольку работа с почтовыми ящиками пользователей полностью возложена на плечи Dovecot, то можно выключить некоторые ненужные опции, к примеру, поддержку не нужных форматов почтовых ящиков (Maildir, Mailstore).

4.2 Настройка

Конфигурационный файл Exim распологается здесь — /usr/local/etc/exim/configure. Файл очень большой, но при желании его можно разбить на небольшие и отвечающие за определенный функционал файлы, как например, это сделали во второй версии Dovecot (смотрите в документации Exim директиву include). У меня конфигурационный файл имеет следующий вид:

  1. ####################################################################
  2. #                     Конфигурационный файл Exim                   #
  3. ####################################################################
  4.  
  5.  
  6. # Это стандартный конфигурационный файл, который можно использовать
  7. # для простых конфигураций. Смотрите документацию, чтобы узнать
  8. # какие опции можно использовать в данном файле. Их гораздо больше,
  9. # чем представлено здесь. Документация находится в doc/spec.txt
  10. # в дистрибутиве Exim в обычном текстовом формате. Другие форматы
  11. # (PostScript, Texinfo, HTML, PDF) доступны на ftp. Документацию
  12. # так же можно найти на официальном сайте.
  13.  
  14.  
  15. # Данный файл разделен на несколько частей, все части, кроме первой,
  16. # начинаются с ключевого слова "begin". Пустые строки и строки,
  17. # начинающиеся с символа # игнорируются.
  18.  
  19.  
  20. ####################################################################
  21. #                              Важно знать                         #
  22. ####################################################################
  23. # После изменения конфигурационного файла вы должны послать сигнал #
  24. # HUP демону Exim, чтобы тот перечитал файл. Однако, любой другой  #
  25. # запускаемый процесс Exim, например, процесс запущенный MUA       #
  26. # для отправки сообщения увидит новый конфигурационный файл.       #
  27. #                                                                  #
  28. # Не обязательно посылать сигнал HUP процессу Exim, когда изменяются#
  29. # дополнительные (вспомогательные) файлы подключенные из конфига.  #
  30. # Данные файлы читаются каждый раз, когда это необходимо.          #
  31. #                                                                  #
  32. # Хорошей идеей будет тестирование нового конфигурационного файла  #
  33. # на предмет синтаксических ошибок (например,                      #
  34. # exim -C /config/file.new -bV)                                    #
  35. ####################################################################
  36.  
  37.  
  38. ######################################################################
  39. #                    Определение макросов                            #
  40. ######################################################################
  41. EXTRA_PREFIX = /usr/local/etc/exim/extra
  42. DKIM_DIRECTORY = /usr/local/etc/exim/dkim
  43.  
  44. # Запрос, возвращающий синонимы для почтового адреса, если они есть
  45. CHECK_VIRTUAL_ALIASES = \
  46.   ${lookup pgsql{SELECT "aliases_tb"."mailaddr" FROM "aliases_tb" \
  47.     INNER JOIN "domains_tb" ON ("aliases_tb"."domain_id" = "domains_tb"."id") \
  48.     WHERE "aliases_tb"."aliasname" = '${quote_pgsql:$local_part}' AND \
  49.       "domains_tb"."domainname" = '${quote_pgsql:$domain}' AND \
  50.       "aliases_tb"."active" = 'true' AND "domains_tb"."active" = 'true'}}
  51.  
  52. # Запрос проверяет существование пользователя в почтовой системе
  53. CHECK_VIRTUAL_USER = \
  54.   ${lookup pgsql{SELECT "users_tb"."id" FROM "users_tb" \
  55.     INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
  56.     WHERE "users_tb"."username" = '${quote_pgsql:$local_part}' AND \
  57.       "domains_tb"."domainname" = '${quote_pgsql:$domain}' AND \
  58.       "users_tb"."active" = 'true' AND "domains_tb"."active" = 'true'}{yes}fail}
  59.  
  60. # Запрос возвращает идентификатор группы пользователя в системе
  61. GET_VIRTUAL_GROUP = \
  62.   ${lookup pgsql{SELECT "users_tb"."gid" FROM "users_tb" \
  63.     INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
  64.     WHERE "username" = '${quote_pgsql:$local_part}' AND \
  65.       "domains_tb"."domainname" = '${quote_pgsql:$domain}'}}
  66.  
  67. # Запрос возвращает идентификатор пользователя в системе
  68. GET_VIRTUAL_USER = \
  69.   ${lookup pgsql{SELECT "users_tb"."uid" FROM "users_tb" \
  70.     INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
  71.     WHERE "username" = '${quote_pgsql:$local_part}' AND \
  72.       "domains_tb"."domainname" = '${quote_pgsql:$domain}'}}
  73.  
  74. # Запрос возвращает домашнюю директорию пользователя
  75. GET_VIRTUAL_DIR = \
  76.   ${lookup pgsql{\
  77.     SELECT "users_tb"."homedir" || '${quote_pgsql:/$domain/$local_part/Maildir}' FROM "users_tb" \
  78.     INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
  79.     WHERE "username" = '${quote_pgsql:$local_part}' AND \
  80.       "domains_tb"."domainname" = '${quote_pgsql:$domain}'}}
  81.  
  82. # Запрос возвращает данные о предалах квот в килобайтах
  83. GET_VIRTUAL_QUOTA = \
  84.   ${lookup pgsql{\
  85.     SELECT "users_tb"."quota" || 'K' FROM "users_tb" \
  86.     INNER JOIN "domains_tb" ON ("users_tb"."domain_id" = "domains_tb"."id") \
  87.     WHERE "username" = '${quote_pgsql:$local_part}' AND \
  88.       "domains_tb"."domainname" = '${quote_pgsql:$domain}'}}
  89.  
  90.  
  91. ####################################################################
  92. #                    Основные параметры
  93. ####################################################################
  94.  
  95. # Данные для поключения к базе данных
  96. hide pgsql_servers = 192.168.7.253/vmail/vmail/1234
  97.  
  98. # Укажите здесь имя своего хоста. Правильно будет указать его в
  99. # формате FQDN. Если данный параметр не задан, то будет использован
  100. # результат вызова функции uname(). В большинстве случаев задавать
  101. # параметр не требуется, так как uname() возвращает верное значение.
  102.  
  103. primary_hostname = mx.info-x.org
  104.  
  105.  
  106. # В следующих трех параметрах задается два списка доменов и один
  107. # список хостов. На эти списки можно ссылаться далее в
  108. # конфигурационном файле, используя следующий синтаксис
  109. # +local_domains, +relay_to_domains, и +relay_from_hosts.
  110. # Во всех списках элементы разделены двоеточием:
  111.  
  112. domainlist local_domains = ${lookup pgsql{SELECT "domainname" FROM "domains_tb" WHERE "domainname" = '${quote_pgsql:$domain}' AND "active" = 'true'}}
  113. domainlist relay_to_domains = ${lookup pgsql{SELECT "domainname" FROM "domains_tb" WHERE "domainname" = '${quote_pgsql:$domain}' AND "active" = 'true'}}
  114. hostlist   relay_from_hosts = localhost : 192.168.7.0/24
  115. hostlist   blacklist = ${lookup pgsql{SELECT "ip" FROM "blacklist_tb" WHERE "ip" = '${quote_pgsql:$sender_host_address}'}}
  116. hostlist   badhosts = ${lookup pgsql{SELECT "ip" FROM "badhosts_tb" WHERE "ip" = '${quote_pgsql:$sender_host_address}'}}
  117.  
  118. # Большинство требований к правилам доступа может быть удовлетворено
  119. # заданием вышеуказанных опций. В боевых конфигурациях вам может
  120. # потребоваться изменить ACL,ки, которые находятся далее в этом файле.
  121.  
  122. # В первом параметре указываются ваши локальные домены, например:
  123. #
  124. #   domainlist local_domains = my.first.domain : my.second.domain
  125. #
  126. # Вы можете использовать символ "@", что означает "имя локального хоста",
  127. # как сделано выше в файле. Это имя, которое задается с помощью
  128. # параметра primary_hostname. Если вам не нужны локальные доставки,
  129. # то удалите символ "@". Если вы хотите принимать сообщения с адресом
  130. # назначения в виде "user@[IP]", "user@[192.168.23.44]", то вы можете
  131. # добавить "@[]", как элемент списка локальных доменов. Так же вам
  132. # потребуется раскомментировать параметр "allow_domain_literals" ниже.
  133. # Такое не приветствуется в сегодняшнем интернете.
  134.  
  135. # Во втором параметре указываются домены, которым ваш хост может
  136. # пересылать письма. Если вы не хотите осуществлять пересылку, то
  137. # оставьте значение этого параметра пустым. Однако, если ваш хост
  138. # является резервным или шлюзом для некоторых доменов, то вы
  139. # должны указать их здесь. Например:
  140. #
  141. # domainlist relay_to_domains = *.myco.com : my.friend.org
  142. #
  143. # Это позволяет любому хосту пересылать письма через ваш, указанным
  144. # доменам. Смотрите секцию "Control of relaying" в документации, чтобы
  145. # получить больше информации.
  146.  
  147. # В третьем параметре указываются хосты, которым можно отправлять
  148. # письма в Интернет через ваш хост. Так здесь можно указать список
  149. # локальных сетей, ну и localhost. Например:
  150. #
  151. # hostlist relay_from_hosts = 127.0.0.1 : 192.168.0.0/16
  152. #
  153. # "/16"  - это маска переменной длины (CIDR). Учтите, что вы должны
  154. # включить 127.0.0.1, чтобы разрешить процессам на вашей машине
  155. # отправить письма, используя адрес loopback. 
  156.  
  157. # Эти три параметра могут содержать различные элементы, включая
  158. # wildcard имена, регулярные выражения, а так же данные из других
  159. # источников. За дополнительной информацией обращайтесь к
  160. # документации. Данные списки используются в ACL,ках для проверки
  161. # входящей почты. Имена ACL,ок заданы здесь:
  162.  
  163. acl_smtp_connect = acl_check_connect
  164. acl_smtp_mail = acl_check_mail
  165. acl_smtp_rcpt = acl_check_rcpt
  166. acl_smtp_predata = acl_check_predata
  167. acl_smtp_data = acl_check_data
  168.  
  169. # Вы не должны изменять эти параметры, если не понимаете
  170. # как работают ACL,ки.
  171.  
  172. # Если Exim скомпилирован с поддержкой content-scanning, то вы можете
  173. # отправлять входящие сообщения на проверку антивирусу. Для этого вам
  174. # потребуется сделать изменения в двух местах. Первое - здесь, где
  175. # вы определяете интерфейс к сканеру. Тут указан ClamAV; смотрите
  176. # документацию, чтобы узнать, как подключить другие антивирусы.
  177. # Второй место в ACL,ке acl_check_data (смотрите ниже).
  178.  
  179. av_scanner = clamd:/var/run/clamav/clamd.sock
  180.  
  181. # Для проверки на спам, эта опция предоставляет интерфейс к SpamAssassin.
  182. # Так же вам необходимо будет сделать изменения в ACL,ке acl_check_data.
  183.  
  184. # spamd_address = 127.0.0.1 783
  185.  
  186.  
  187. # Если Exim скомпилирован с поддержкой TLS, то возможно вы захотите
  188. # задать следующие параметры, чтобы Exim позволял клиентам
  189. # устанавливать защищенные соединения. В секции аутентификаторов
  190. # ниже, находятся шаблоны конфигураций для аутентификации
  191. # пользователей открытым текстом. Аутентификация открытым текстом
  192. # будет безопасной, если соединение шифруется.
  193.  
  194. # Разрешить любому клиенту использовать TLS.
  195. tls_advertise_hosts = *
  196.  
  197. # Где Exim взять TLS сертификат и приватный ключ. Приватный ключ
  198. # не должен быть защищен паролем. Вы можете объединить сертификат
  199. # и приватный ключ в один файл, тогда вам понадобится только первый
  200. # параметр, в другом случае используйте оба параметра.
  201.  
  202. tls_certificate = /usr/local/etc/exim/exim.crt
  203. tls_privatekey = /usr/local/etc/exim/exim.pem
  204.  
  205. # Для пользователей, которые могут отправить письма откуда угодно,
  206. # вам может понадобиться изменить порты, на которых Exim будет
  207. # принимать подключения. Например, если фаервол в удаленной сети
  208. # блочит 25 порт. Конечно, выделен стандартный порт в таком случае,
  209. # порт 587  (за деталями в RFC 4409). Почтовые клиенты Microsoft
  210. # не могут корректно работать в таком режиме, поэтому (если у вас
  211. # в сети есть такие продукты, то вы можете сделать TLS доступ для
  212. # пользователей).
  213.  
  214. daemon_smtp_ports = 25 : 465 : 587
  215. tls_on_connect_ports = 465
  216.  
  217.  
  218. # Укажите здесь домен, который будет добавляться к адресатам
  219. # в письмах, если там домен не указан. Домен может быть только один,
  220. # символ "@" писать не нужно. Например, "caesar@rome.example"
  221. # полный адрес, в котором указан пользователь и домен (то есть FQDN). Но
  222. # адрес "caesar" не полный (то есть это не FQDN), а просто имя пользователя.
  223. # По умолчанию не полные адреса принимаются только с локальных хостов.
  224. # Смотрите параметр recipient_unqualified_hosts, если вы хотите разрешить
  225. # принимать и добавлять домен в письмах от удаленных хостов. Если
  226. # этот параметр не задан, то используется значение параметра
  227. # primary_hostname.
  228.  
  229. qualify_domain = info-x.org
  230.  
  231.  
  232. # Если в письме не задан FQDN получателя (а только логин), то подставить
  233. # в письмо в адрес получателя указанный здесь домен. Если этот параметр
  234. # не задан, то используется значение параметра qualify_domain.
  235.  
  236. qualify_recipient = info-x.org
  237.  
  238.  
  239. # Раскомментируйте данный параметр, если вы хотите, чтобы Exim
  240. # принимал письма с адресатами вида "user@[10.11.12.13]". Это
  241. # не нарушает RFC, но в наше время такая плюшка ни к чему. Учтите,
  242. # что этот старый формат может использоваться спамерами. Если вам
  243. # действительно необходимо работать с такими письмами, то
  244. # раскомментируйте параметр и смотрите ниже роутер "domain_literal".
  245.  
  246. # allow_domain_literals
  247.  
  248.  
  249. # Не использовать указанные здесь идентификаторы для доставки почты.
  250. # Можно использовать имена пользователей, список разделяется двоеточием.
  251. # Попытка использования данных идентификаторов для передачи почты
  252. # будет отражена в логе паники, а доставка будет отложена. Есть еще
  253. # более строгий вариант этого параметра - вшивание в код при сборке
  254. # макроса (или переменной, что там не смотрел) FIXED_NEVER_USERS.
  255. # Список пользователей в FIXED_NEVER_USERS уже никак не изменить
  256. # после сборки Exim,а. Значением по умолчанию для FIXED_NEVER_USERS
  257. # является - "root", но чтобы быть абсолютно уверенным (что пользователь
  258. # root никак не задействуется), значение этого параметра по умолчанию
  259. # тоже "root".
  260.  
  261. # Учтите, что настройки по умолчанию не позволят доставлять почту руту,
  262. # как обычному пользователю. Но это не проблема, так как большинство
  263. # конфигураций имеет алиас, который перенаправляет письма для рута
  264. # на нужный адрес.
  265.  
  266. #exim_user = mailnull
  267. #exim_group = mailnull
  268. exim_user = smmsp
  269. exim_group = smmsp
  270. never_users = root
  271.  
  272.  
  273. # Следующий параметр заставляет Exim делать обратный запрос к DNS
  274. # для проверки IP адреса, с которого идет передача писем. Если вы
  275. # считаете, что это пустая трата времени или на это уходит слишком
  276. # много времени, то укажите здесь адреса, для которых нужно делать
  277. # такие запросы или закомментируйте/удалите этот параметр вообще.
  278.  
  279. #host_lookup = *
  280.  
  281.  
  282. # Следующие параметры заставляют Exim делать обратные запросы (ident)
  283. # для входящих SMTP соединений (RFC 1413). Вы можете указать здесь
  284. # хосты, для которых необходимо делать данные запросы и задать
  285. # таймаут. Если выставить таймаут в 0, то данные запросы делаться
  286. # не будут. Вызовы RFC 1413 не требуют много ресурсов и являются
  287. # хорошим средством для выявления проблем с передаваемой почтой, 
  288. # но могут возникнуть проблемы с некоторыми хостами из-за файерволов.
  289. # Так же может быть, что из-за таймаута Exim не будет знать, что
  290. # соединение закрыто, что вызовет задержки в работе. (Начиная с релиза
  291. # 4.61 таймаут уменьшен до 5 секунд.)
  292.  
  293. rfc1413_hosts = *
  294. rfc1413_query_timeout = 0s
  295.  
  296.  
  297. # По умолчанию Exim принимает только почту, в которой адресаты заданы
  298. # верно, то есть в FQDN. Если вы хотите, чтобы Exim работал с почтой
  299. # не имеющей адресатов в FQDN, то укажите здесь хосты с которых
  300. # можно отправлять такие письма. В таком случае, Exim просто добавит
  301. # к адресату значение параметра qualify_domain и/или qualify_recipient.
  302. #
  303. # sender_unqualified_hosts =
  304. # recipient_unqualified_hosts =
  305.  
  306.  
  307. # Если вы хотите, чтобы Exim поддерживал хак с процентом для некоторых
  308. # доменов, то раскомментируйте опцию ниже и укажите список доменов. 
  309. # Данный хак позволяет использовать адрес вот такого вида x%y@z (где
  310. # z - один из указанных в этой опции доменов), который будут перенаправлен
  311. # на адрес x@y. Если домен z не из списка, то часть адреса x%y будет
  312. # интерпретирована как есть. В наши дни в использование данного хака
  313. # нет необходимости. Используйте данную фишку, если только она вам
  314. # действительно необходима.
  315. #
  316. # percent_hack_domains =
  317. #
  318. # Если вы включите данный функционал, то не забудьте так же поправить
  319. # правила в секции ACL - уберите проверку символа % в локальной части.
  320.  
  321.  
  322. # Когда Exim не может доставить рикошет к отправителю, то он
  323. # замораживает его. Есть так же другие обстоятельства, при которых
  324. # Exim может заморозить рикошет. Они остаются в очереди пока
  325. # не истечет заданное здесь время.
  326.  
  327. # Данная опция размораживает рикошет по прошествии 2-х дней,
  328. # далее Exim снова пытается его доставить и игнорирует любые
  329. # ошибки о доставке.
  330.  
  331. ignore_bounce_errors_after = 2d
  332.  
  333. # Замороженные сообщения удаляются из очереди, когда истечет
  334. # указанное здесь время.
  335.  
  336. timeout_frozen_after = 7d
  337.  
  338.  
  339. # По умолчанию, ожидающие сообщения в очереди Exim,а хранятся
  340. # в одной директории, называемой "input", которая находится в Exim
  341. # директории spool. (По умолчанию эта директория задается на этапе
  342. # компиляции и имеет такой путь - /var/spool/exim/.) Exim работает
  343. # быстрее, когда очередь сохраняет небольшой размер, но бывают
  344. # обстоятельства, при которых такое не всегда возможно. Если вы
  345. # раскомментируете параметр ниже, то сообщения будут храниться
  346. # в 62 поддиректориях в директории "input", вместо одной общей.
  347. # Поддиректории именуются 0, 1, ... A, B, ... a, b, ... z. Это хорошо
  348. # тем, что:
  349. # 1) если ваша ОС тормозит, когда в директории много файлов, то
  350. # такой подход поможет не допустить этого.
  351. # 2) Exim может обрабатывать очередь в каждой директории отдельно,
  352. # вместо одной общей, что приведет к увеличению производительности
  353. # при больших размерах очереди.
  354.  
  355. split_spool_directory = true
  356.  
  357.  
  358. # Если вы находитесь в такой части мире, где ASCII не достаточен
  359. # для большей части текста, то вы наверняка знакомы с RFC2047.
  360. # По умолчанию, Exim придерживается спецификации, которая
  361. # делает ограничение в 76 символов в строке. 
  362. #
  363. # check_rfc2047_length = false
  364. #
  365. # Разрабы Exim,а получали много жалоб от российских админов о
  366. # проблемах в работе с включенной опцией, потому что некоторые
  367. # популярные почтовые клиенты имеют баги.
  368.  
  369. # If you wish to be strictly RFC compliant, or if you know you'll be
  370. # exchanging email with systems that are not 8-bit clean, then you may
  371. # wish to disable advertising 8BITMIME.  Uncomment this option to do so.
  372. # accept_8bitmime = false
  373.  
  374. # Не использовать протокол IPv6
  375. disable_ipv6 = true
  376. # 
  377. freeze_tell = admin@info-x.org
  378. #helo_try_verify_hosts = *
  379. # не робит с некоторыми клиентами
  380. #helo_verify_hosts = *
  381. # Ограничение размера почтового сообщения
  382. message_size_limit = 30M
  383. # Проверять заголовки DKIM у каждого отправителя
  384. dkim_verify_signers = $sender_address_domain
  385.  
  386. bounce_return_message = true
  387. bounce_return_body = true
  388. bounce_return_size_limit = 20K
  389.  
  390. smtp_accept_max = 50
  391. smtp_accept_max_per_connection = 100
  392. smtp_accept_max_per_host = 10
  393. smtp_connect_backlog = 50
  394. smtp_enforce_sync = yes
  395. smtp_banner = $smtp_active_hostname ESMTP MTA :)
  396.  
  397. # Здесь можно задать опции для библиотеки OpenSSL, которые будут использоваться
  398. # в рамках установки защищенного соединения с клиентами. Задается как список,
  399. # разделенные пробелами, где каждый элемент может быть добавлен "+added"
  400. # или исключен "-substracted" из текущего набора опций.
  401. # Внимание: для тех, у кого библиотека OpenSSL версии >= 1.0.0, желательно
  402. # в целях повышения надежности задать опцию "+no_compression" ("CRIME" attack)
  403. # (см. https://lists.exim.org/lurker/message/20121009.173420.ed5bd052.en.html)
  404. openssl_options = +no_sslv2
  405.  
  406. # В данной опции возможно задать разрешенные шифры (ciphers) для входящих SLL/TLS
  407. # соединений (Exim должен быть скомпилирован с поддержкой OpenSSL. Для тех,
  408. # кто использует GnuTLS параметр задается по-другому, см. документацию).
  409. # Дополнительную информацию по шифрам можно получить по команде man ciphers.
  410. tls_require_ciphers = ${if =={$received_port}{25}\
  411.                            {DEFAULT}\
  412.                            {HIGH:MEDIUM:!LOW:!ADH:!RC4:!MD5:!EXP:!aNULL:!eNULL:!NULL}}
  413.  
  414. # Что пишем в лог?
  415. log_selector = +all_parents \
  416.                +connection_reject \
  417.                +incoming_interface \
  418.                +lost_incoming_connection \
  419.                +received_recipients \
  420.                +received_sender \
  421.                +smtp_confirmation \
  422.                +smtp_protocol_error \
  423.                +smtp_syntax_error \
  424.                -queue_run
  425.  
  426. #####################################################################
  427. #                        Параметры ACL
  428. #####################################################################
  429.  
  430. begin acl
  431.  
  432. # Проверки выполняются по порядку до первого попадания в правило,
  433. # где указано принять или отклонить письмо.
  434.  
  435. acl_check_connect:
  436.   # Сохраняем в переменную содержимое обратной записи (PTR) для IP подключенного клиента
  437.   warn set acl_c_reverse_address = ${escape:${lookup dnsdb{ptr=$sender_host_address}{$value}}}
  438.  
  439.   accept
  440.  
  441. acl_check_mail:
  442.   warn set acl_c_spamscore = 0
  443.  
  444.   # Блочим клиентов из локального черного списка
  445.   deny message = Your IP address in local blacklist
  446.        hosts = +blacklist
  447.  
  448.   deny message = Your IP address in local blacklist. Please contact with postmaster if you consider that your address got there by mistake.
  449.        hosts = +badhosts
  450.  
  451.   # Различные проверки HELO/EHLO
  452.   #---------------------------------------------------------
  453.  
  454.   # Накидываем сверху очков за неверный HELO/EHLO
  455.   warn !authenticated = *
  456.        hosts = !+relay_from_hosts
  457.        condition = ${if and{\
  458.                            {!match{$sender_helo_name}{\N(?i)^([a-z0-9]([a-z0-9\-]{0,61}[a-z0-9])?\.)+[a-z]{2,6}$\N}}\
  459.                            {!eqi{$sender_helo_name}{[$sender_host_address]}}\
  460.                         }\
  461.                     }
  462.        set acl_c_spamscore = ${eval:$acl_c_spamscore + 25}
  463.        set acl_c_spamlog = $acl_c_spamlog Bad HELO/EHLO;
  464.  
  465.   # Накидываем очки, за использование в HELO любых данных,
  466.   # принадлежащих нашему серверу
  467.   warn !authenticated = *
  468.        hosts = !+relay_from_hosts
  469.        set acl_m_islocal = ${lookup pgsql{SELECT "domainname" FROM "domains_tb" \
  470.                               WHERE "domainname" = '${quote_pgsql:$sender_helo_name}'}{yes}{no}}
  471.        condition = ${if or{\
  472.                            {eq{$sender_helo_name}{$interface_address}}\
  473.                            {eqi{$sender_helo_name}{$primary_hostname}}\
  474.                            {eq{$acl_m_islocal}{yes}}\
  475.                           }\
  476.                     }
  477.        set acl_c_spamscore = ${eval:$acl_c_spamscore + 50}
  478.        set acl_c_spamlog = $acl_c_spamlog Your HELO is one of local domain name;
  479.  
  480.   # Проверки DNS
  481.   #---------------------------------------------------------
  482.   # warn message = your reversed address is $acl_c_reverse_address
  483.  
  484.   # Добавляем очков за то, что нет указателя в DNS для данного IP
  485.   warn !authenticated = *
  486.        hosts = !+relay_from_hosts
  487.        condition = ${if eq{$acl_c_reverse_address}{}}
  488.        set acl_c_spamscore = ${eval:$acl_c_spamscore + 30}
  489.        set acl_c_spamlog = $acl_c_spamlog PTR == NULL;
  490.  
  491.   # Добавляем еще очков за то, что обратная DNS запись не совпадает с прямой.
  492.   warn !authenticated = *
  493.        hosts = !+relay_from_hosts
  494.        condition = ${if !eqi{$acl_c_reverse_address}{$sender_helo_name}}
  495.        set acl_c_spamscore = ${eval:$acl_c_spamscore + 30}
  496.        set acl_c_spamlog = $acl_c_spamlog PTR != HELO;
  497.  
  498.   # Добавляем очков за то, что IP клиента из диапазона динамических адресов
  499.   warn !authenticated = *
  500.        hosts = !+relay_from_hosts
  501.        condition = ${lookup{$acl_c_reverse_address}wildlsearch{EXTRA_PREFIX/dynamic_pools}{yes}{no}}
  502.        set acl_c_spamscore = ${eval:$acl_c_spamscore + 50}
  503.        set acl_c_spamlog = $acl_c_spamlog PTR in dynamic pools;
  504.  
  505.   # Проверка SPF
  506.   #---------------------------------------------------------
  507.  
  508.   # Накидываем очки за попытку отправить почту с сервера,
  509.   # не указанного в SPF
  510.   warn !authenticated = *
  511.        hosts = !+relay_from_hosts
  512.        spf = fail : softfail
  513.        set acl_c_spamscore = ${eval:$acl_c_spamscore + 50}
  514.        set acl_c_spamlog = $acl_c_spamlog SPF fail;
  515.  
  516.   # За отсутствие записи SPF накидываем достаточное 
  517.   # для попадания в серый список количество очков
  518.   warn !authenticated = *
  519.        hosts = !+relay_from_hosts
  520.        spf = none
  521.        set acl_c_spamscore = ${eval:$acl_c_spamscore + 50}
  522.        set acl_c_spamlog = $acl_c_spamlog SPF none;
  523.  
  524.   # Накидываем немного очков за некорректно оформленную SPF запись 
  525.   # или при возникновении ошибки при ее получении
  526.   warn !authenticated = *
  527.        hosts = !+relay_from_hosts
  528.        spf = permerror : temperror : neutral
  529.        set acl_c_spamscore = ${eval:$acl_c_spamscore + 25}
  530.        set acl_c_spamlog = $acl_c_spamlog SPF syntax error or not received;
  531.  
  532.   # Проверка IP в черных списках. За каждое срабатывание правила
  533.   # накидываем еще немного очков.
  534.   #---------------------------------------------------------
  535.   warn !authenticated = *
  536.        hosts          = !+relay_from_hosts
  537.        dnslists       = xen.spamhaus.org
  538.        add_header     = X-Warning: $sender_host_address is in a black list at $dnslist_domain
  539.        set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
  540.        set acl_c_spamlog = $acl_c_spamlog Blacklist xen.spamhaus.org;
  541.  
  542.   warn !authenticated = *
  543.        hosts          = !+relay_from_hosts
  544.        dnslists       = relay.mail-abuse.org
  545.        add_header     = X-Warning: $sender_host_address is in a black list at $dnslist_domain
  546.        set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
  547.        set acl_c_spamlog = $acl_c_spamlog Blacklist relay.mail-abuse.org;
  548.  
  549.   warn !authenticated = *
  550.        hosts          = !+relay_from_hosts
  551.        dnslists       = bl.spamcop.net
  552.        add_header     = X-Warning: $sender_host_address is in a black list at $dnslist_domain
  553.        set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
  554.        set acl_c_spamlog = $acl_c_spamlog Blacklist bl.spamcop.net;
  555.  
  556.   warn !authenticated = *
  557.        hosts          = !+relay_from_hosts
  558.        dnslists       = relays.ordb.org
  559.        add_header     = X-Warning: $sender_host_address is in a black list at $dnslist_domain
  560.        set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
  561.        set acl_c_spamlog = $acl_c_spamlog Blacklist relays.ordb.org;
  562.  
  563.   warn !authenticated = *
  564.        hosts          = !+relay_from_hosts
  565.        dnslists       = dns.rfc-ignorant.org
  566.        add_header     = X-Warning: $sender_host_address is in a black list at $dnslist_domain
  567.        set acl_c_spamscore = ${eval:$acl_c_spamscore+25}
  568.        set acl_c_spamlog = $acl_c_spamlog Blacklist dns.rfc-ignorant.org;
  569.  
  570.   # Проверяем авторизованного пользователя на предмет подмены адреса отправителя
  571.   deny message = Address ($sender_address) does not match with authenticated data ($authenticated_id). Check your email program settings.
  572.        authenticated = *
  573.        condition = ${if !eq{$sender_address}{$authenticated_id}{yes}{no}}
  574.  
  575.   accept
  576.  
  577. # Данная ACL используется для каждой команды RCPT при получении писем.
  578.  
  579. acl_check_rcpt:
  580.  
  581.   # Принять, если отправитель - локальный хост (т.е. не через TCP/IP).
  582.  
  583.   accept  hosts = :
  584.           control = dkim_disable_verify
  585.  
  586.   ###################################################################
  587.   # Следующая секция ACL проверяет локальную часть адреса на предмет
  588.   # содержания символов [@%!/|.(точка)] в правильных местах.
  589.   #
  590.   # Символы кроме точек часто находятся не на своих местах, такое часто
  591.   # делают люди, которые надеются обойти ограничения. Поэтому, несмотря
  592.   # на то, что они допустимы в локальных частях, эти правила блокируют 
  593.   # такие попытки.
  594.   #
  595.   # Пустые компоненты адреса (случай, когда в адресе стоят две точки
  596.   # подряд) запрещены в RFC 2822, но Exim позволяет обойти такое
  597.   # ограничение, потому что они встретились (х/з как тут перевести:
  598.   # ....but Exim allows them because they have been encountered).
  599.   # (Предполагается, что адрес имеет вид
  600.   # "firstinitial.secondinitial.familyname", но что делать тем кто не имеет
  601.   # "secondinitial"). Однако, локальная часть адреса, начинающаяся с
  602.   # точки или содержащая /../ может доставить неприятности, если
  603.   # используется как часть файла (например, для списка рассылки).
  604.   # Такое же замечание справедливо и для локальных частей,
  605.   # которые содержат наклонные черты. Символ переадресации
  606.   # вывода (<, |, >) может также доставить проблемы, если локальная
  607.   # часть легкомысленно включена в командную строку оболочки.
  608.   #
  609.   # В связи с этим для проверки используется два правила. Первое
  610.   # используется для писем направленных для локальных доменов.
  611.   # Строка "domains = +local_domains" реализовывает сказанное:
  612.   # только локальные домены. Правило блокирует локальные части,
  613.   # начинающиеся с точки или содержащие символы @ % ! / или |.
  614.   # Если у вас есть локальные учетки имеющие в названии данные
  615.   # символы, то вам необходимо модифицировать данное правило.
  616.  
  617.   deny    message       = Restricted characters in address
  618.           domains       = +local_domains
  619.           local_parts   = ^[.] : ^.*[@%!/|]
  620.  
  621.   # Второе правило применяется для остальных доменов и оно
  622.   # не такое строгое как предыдущее.
  623.   # Строка "domains = !+local_domains" указывает для каких доменов
  624.   # применять правило. Данное правило позволяет локальным
  625.   # пользователям отправлять письма во внешний мир, где адресаты
  626.   # могут иметь косую или вертикальную черту в локальной части.
  627.   # Так же правило блокирует адреса, локальная часть которых
  628.   # начинается с точки, косой или вертикальной черты, но допускает
  629.   # их использование в любом другом месте локальной части.
  630.   # Локальная часть такого вида - /../ запрещена. Использование
  631.   # символов @ % и ! запрещено, как и в предыдущем правиле.
  632.   # Это сделано, чтобы локальные пользователи (или вирусы на их
  633.   # компьютерах) не могли каким-либо образом осуществить
  634.   # атаку на удаленный хост.
  635.  
  636.   deny    message       = Restricted characters in address
  637.           domains       = !+local_domains
  638.           local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
  639.   ###################################################################
  640.  
  641.   # Добавляем очков за то, что адрес отправителя совпадает с адресом получаетеля
  642.   warn condition = ${if eq{$sender_address}{$local_part@$domain}{yes}{no}}
  643.        set acl_c_spamscore = ${eval:$acl_c_spamscore+20}
  644.        set acl_c_spamlog = $acl_c_spamlog Sender == recipient;
  645.  
  646.   # Добавляем очков за отправку письма на адрес-ловушку
  647.   # P.S. В качестве адресов ловушек используются давно забытые заброшенные
  648.   # адреса или специально созданные. То есть это обычный почтовый ящик.
  649.   warn local_parts = spam : spamtrap
  650.        domains     = +local_domains
  651.        set acl_c_spamscore = ${eval:$acl_c_spamscore+50}
  652.        set acl_c_spamlog = $acl_c_spamlog Spamtrap;
  653.  
  654.   # Отправляем на следующую ACL,ку клиентов, набравших достаточное
  655.   # количество очков для попадения в локальный черный список.
  656.   accept condition = ${if >={$acl_c_spamscore}{100}{yes}{no}}
  657.  
  658.   # Принимать письма для пользователя postmaster для любого локального
  659.   # домена независимо от источника и без проверки отправителя.
  660.  
  661.   #accept  local_parts   = postmaster
  662.   #        domains       = +local_domains
  663.  
  664.   # Не принимать письма, если не удалось проверить отправителя.
  665.  
  666.   #require verify = sender
  667.  
  668.   deny !authenticated = *
  669.        hosts = +relay_from_hosts
  670.        !verify = sender
  671.  
  672.   # Добавляем очков за невозможность проверки существования адреса отправителя
  673.   warn hosts = !+relay_from_hosts
  674.        !verify = sender/callout=3m,defer_ok
  675.        set acl_c_spamscore = ${eval:$acl_c_spamscore+20}
  676.        set acl_c_spamlog = $acl_c_spamlog Callout error;
  677.  
  678.   # Проверять получателя во входящих письмах. Эта правило будет
  679.   # проводить проверку локальной части для локальных доменов, а
  680.   # а для удаленных проверку доменной части. Единственным способом
  681.   # проверять локальную часть для удаленных доменов использовать
  682.   # механизм обратных вызовов (добавить /callout), но сначала
  683.   # прочитайте в документации про этот механизм.
  684.  
  685.   require verify = recipient
  686.  
  687.   # Принимать письма, которые приходят с хостов, для которых этот хост
  688.   # является релеем. Подразумевается, что эти хосты скорее всего MUA,
  689.   # так что здесь установлен модификатор  control=submission, который
  690.   # заставляет Exim работать в режиме передачи. Это позволит подправить 
  691.   # некоторые ошибки в письме, например, нет заголовка Date. Если этот
  692.   # хост является релеем для других MTA, то вам может понадобиться
  693.   # отключить эту плюшку. Если вы хотите пересылать письма с MTA
  694.   # и в "режиме передачи" с MUA, то вы должны разделить это правило
  695.   # на два и обрабатывать такие письма отдельно.
  696.  
  697.   accept  hosts         = +relay_from_hosts
  698.           control       = submission
  699.           control       = dkim_disable_verify
  700.  
  701.   # Принимать сообщение, если оно отправлено клиентом, прошедшим
  702.   # аутентификацию.
  703.  
  704.   accept  authenticated = *
  705.           control       = submission
  706.           control       = dkim_disable_verify
  707.  
  708.   # Запрещаем пересылать письма через нашу машину неизвестным
  709.   # хостам.
  710.  
  711.   require message = relay not permitted
  712.           domains = +local_domains : +relay_to_domains
  713.  
  714.   ###################################################################
  715.   # Этот тест закомментирован, потому что подходит не для каждого случая.
  716.   # Если вы включите этот тест, то будет производится проверка
  717.   # Client SMTP Authorization (csa) хоста отправителя. Эта проверка включает
  718.   # в себя просмотр записей SRV в DNS. CSA предложен для внедрения
  719.   # в Интернет в мае 2005. Вы можете добавить дополнительные проверки
  720.   # к этому тесту для того, чтобы не проверять какие-нибудь хосты методом
  721.   # CSA.
  722.   #
  723.   # require verify = csa
  724.   ###################################################################
  725.  
  726.   accept
  727.  
  728. acl_check_predata:
  729.   # Запрещаем письма, отправленные нескольким адресатам от "пустого" отправителя.
  730.   deny message = Sorry, sender address <> disallowed for many rcpt commands
  731.        senders = :
  732.        condition = ${if >{$rcpt_count}{1}{yes}{no}}
  733.  
  734.   # Я пишу в лог дополнительную ифномарцию о сообщениях, которые
  735.   # набрали немного спам очков, чтобы добавить еще какие-нибудь проверки,
  736.   # если это сообщение все же окажется спамом.
  737.   warn condition = ${if <{$acl_c_spamscore}{50}{yes}{no}}
  738.        condition = ${if >{$acl_c_spamscore}{0}{yes}{no}}
  739.        logwrite  = Debug: $acl_c_spamlog
  740.  
  741.   # Принимаем сообщение, которые набрали мало спам очков
  742.   accept condition = ${if <{$acl_c_spamscore}{50}{yes}{no}}
  743.  
  744.   # Помучаем хост небольшой задержкой
  745.   warn delay = 20s
  746.  
  747.   # Блочим клиентов с большим количеством спам очков и добавляем их
  748.   # в локальный черный список.
  749.   deny message = Sorry, your spam score very high
  750.        condition = ${if >={$acl_c_spamscore}{100}{yes}{no}}
  751.        condition = ${lookup pgsql{\
  752.                    DELETE FROM "blacklist_tb" WHERE "ip" = '$sender_host_address';\
  753.                    INSERT INTO "blacklist_tb" VALUES ('$sender_host_address', DEFAULT)}{yes}{yes}}
  754.  
  755.   # Реализация серого списка. Сюда попадают клиенты, набравшие недостаточное
  756.   # количество спам очков для попадания в локальный черный список, но
  757.   # превысившие минимальный порог для прохождения письма. Эти хосты нельзя
  758.   # отнести ни к легитимным ни к спам хостам, поэтому лучше еще помучить
  759.   # их серым списком.
  760.   #---------------------------------------------------------
  761.   accept condition = ${lookup pgsql{\
  762.                      SELECT "ip" FROM "whitelist_tb" WHERE "ip" = '$sender_host_address' \
  763.                         AND "addrhash" = md5('$sender_address')\
  764.                      }{yes}{no}}
  765.  
  766.   defer message = Message deferred. Your address already exists in Greylist. Try again later.
  767.         condition =  ${lookup pgsql{\
  768.                       SELECT "ip" FROM "greylist_tb" WHERE "ip" = '$sender_host_address' \
  769.                         AND "addrhash" = md5('$sender_address$local_part@$domain') \
  770.                         AND "ctime" + 1740 > date_part('epoch'::text, now())\
  771.                       }{yes}{no}}
  772.         delay = ${eval:$acl_c_spamscore/2}s
  773.  
  774.   accept condition = ${lookup pgsql{\
  775.                      SELECT "ip" FROM "greylist_tb" WHERE "ip" = '$sender_host_address' \
  776.                        AND "addrhash" = md5('$sender_address$local_part@$domain') \
  777.                        AND "ctime" + 1740 <= date_part('epoch'::text, now())\
  778.                      }{yes}{no}}
  779.          condition = ${lookup pgsql{\
  780.                      DELETE FROM "greylist_tb" WHERE "ip" = '$sender_host_address' \
  781.                        AND "addrhash" = md5('$sender_address$local_part@$domain'); \
  782.                      INSERT INTO "whitelist_tb" VALUES('$sender_host_address', \
  783.                        md5('$sender_address'), DEFAULT)\
  784.                      }{yes}{yes}}
  785.  
  786.   defer message = Message deferred. Your address added to Greylist. Try again later.
  787.         condition = ${lookup pgsql{\
  788.                     INSERT INTO "greylist_tb" VALUES('$sender_host_address',\
  789.                       md5('$sender_address$local_part@$domain'), DEFAULT);\
  790.                     }{yes}{yes}}
  791.         delay = ${eval:$acl_c_spamscore/2}s
  792.  
  793.   deny
  794.  
  795. # Этот ACL используется после того, как получено тело письма. В этом ACL
  796. # вы можете проверять тело письма или его заголовки, в частности здесь
  797. # можно отправить тело письма на проверку антивирусом или спам сканером.
  798. # Примеры некоторых тестов приведены ниже и закомментированы.
  799. # Без этих тестов данная ACL принимает все сообщения. Если вы хотите
  800. # использовать данные тесты, то Exim должен быть собран с
  801. # соответствующими опциями (WITH_CONTENT_SCAN=yes in Local/Makefile).
  802.  
  803. acl_check_data:
  804.  
  805.   # Блочить письма с вирусами. Чтобы использовать данный тест
  806.   # вы должны задать параметр av_scanner.
  807.    deny malware    = *
  808.            message    = This message contains a virus ($malware_name).
  809.  
  810.   # Добавить заголовки о набранных очках в спам тестах. Чтобы использовать
  811.   # данный тест вы должны установить SpamAssassin и задать
  812.   # параметр spamd_address.
  813.   #
  814.   # warn    spam       = nobody
  815.   #         add_header = X-Spam_score: $spam_score\n\
  816.   #                      X-Spam_score_int: $spam_score_int\n\
  817.   #                      X-Spam_bar: $spam_bar\n\
  818.   #                      X-Spam_report: $spam_report
  819.  
  820.   # Блочить письма с неверным синтаксисом заголовков. При очень большом потоке
  821.   # писем лучше отключить эту проверку.
  822.   deny message = Invalid header syntax
  823.        !verify = header_syntax
  824.  
  825.   # Добавляем заголовок в письмо с количеством набранным спам очков
  826.   warn add_header = X-Spamscore: $acl_c_spamscore
  827.  
  828.   # Принять сообщение.
  829.   accept
  830.  
  831.  
  832.  
  833. #####################################################################
  834. #                      Параметры  роутеров
  835. #####################################################################
  836. #      Здесь важен порядок, в котором заданы роутеры.
  837. #     Адрес передается по порядку в роутеры до тех пор,
  838. #               пока какой-нибудь не подойдет.
  839. #####################################################################
  840.  
  841. begin routers
  842.  
  843. # Этот роутер направляет почту на удаленные машины через SMTP,
  844. # когда получатель указан в виде IP адреса, например,
  845. # <user@[192.168.35.64]>. В RFC требуется, чтобы почтовик умел
  846. # работать с такими письмами. Однако, в наши дни такие адреса
  847. # практически нигде не используются, разве что только спамерами.
  848. # Поэтому данный роутер по умолчанию закомментирован. Если
  849. # вы его раскомментируете, то вы также должны раскомментировать
  850. # параметр allow_domain_literals, тобы Exim не считал такие адреса
  851. # синтаксически неверными.
  852.  
  853. # domain_literal:
  854. #   driver = ipliteral
  855. #   domains = ! +local_domains
  856. #   transport = remote_smtp
  857.  
  858.  
  859. # Данный роутер отправляет письма, если они не предназначены
  860. # локальным, на удаленные домены. Знак восклицания в записи
  861. # "domains = ! +local_domains" означает отрицание, что можно
  862. # читать как "не".
  863. #
  864. # Любой домен, адрес которого 0.0.0.0 или 127.0.0.0/8 обрабатывается
  865. # так, как будто у него нет DNS записи. Учтите, адрес 0.0.0.0 тоже самое,
  866. # что и 0.0.0.0/32, который означает в большинстве систем, что это
  867. # локальный хост. Если DNS запрос не дал результатов, то адрес
  868. # не направляется в другие роутеры, так как здесь указан параметр
  869. # no_more => вылазит ошибка, что адрес недоступен.
  870.  
  871. dnslookup:
  872.   driver = dnslookup
  873.   domains = ! +local_domains
  874.   transport = remote_smtp
  875.   ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
  876.   no_more
  877.  
  878.  
  879. # Остальные роутеры обрабатывают адреса в локальных доменах,
  880. # которые определены в "domainlist local_domains".
  881.  
  882.  
  883. # Роутер обрабатывает алиасы, ища их в файле с именем
  884. # SYSTEM_ALIASES_FILE. Значение подставляется автоматом
  885. # на этапе сборки. По умолчанию файл  располагается здесь:
  886. # /etc/aliases. Если у вас данный файл располагается в другом
  887. # месте, то вам необходимо указать правильный путь до него
  888. # в параметре "data".
  889. #
  890. ##### NB  Данный файл должен всегда существовать в системе. 
  891. ##### NB  Практически в каждой Unix системе он есть, потому что
  892. ##### NB  используется Sendmail. В наши дни, в некоторых системах
  893. ##### NB  данный файл может отсутствовать. Файл должен
  894. ##### NB  содержать как минимум одну запись - для "postmaster".
  895. #
  896. # Если ваш алис разворачивается в трубу (pipe) или файл,тогда вам
  897. # нужно задать пользователя, под которым будет происходить работа
  898. # с трубой или файлом. Если вам необходимо, то вы можете
  899. # раскомментировать (и изменить) опцию "user" ниже, а так же
  900. # добавить опцию "group". Есть другой способ - указать опцию
  901. # "user" в транспортах.
  902.  
  903. system_aliases:
  904.   driver = redirect
  905.   allow_fail
  906.   allow_defer
  907.   data = ${lookup{$local_part}lsearch{/etc/aliases}}
  908.   user = mailnull
  909.   group = mail
  910.   file_transport = address_file
  911.   pipe_transport = address_pipe
  912.  
  913. virtual_aliases:
  914.   driver = redirect
  915.   allow_fail
  916.   allow_defer
  917.   data = CHECK_VIRTUAL_ALIASES
  918.   user = mailnull
  919.   group = mail
  920.  
  921. # Этот роутер пересылает почту согласно файлу .forward в директории
  922. # пользователя. Если вы хотите фильтровать почту, тогда файл
  923. # .forward должен начинаться со строки "# Exim filter" или "# Sieve filter",
  924. # так же необходимо раскомментировать опцию "allow_filter".
  925.  
  926. # Опция no_verify нужна для того, чтобы пропустить данный роутер,
  927. # когда Exim проверяет адрес. Аналогично, опция no_expn нужна,
  928. # чтобы роутер пропускался, когда Exim обрабатывает команду EXPN.
  929.  
  930. # Если вы хотите, чтобы роутер понимал локальную часть адреса
  931. # с суффиксами (символом "-" или "+") так, как будто их нет, то
  932. # раскомментируйте пару опций local_part_suffix. Например, адрес
  933. # xxxx-foo@your.domain будет воспринят как xxxx@your.domain
  934. # данным роутером. Если вы раскомментируете эти опции, то вам
  935. # нужно будет сделать подобные изменения в роутере localuser
  936. # (так надо, потому что данный роутер не используется при проверке
  937. # существования пользователя).
  938.  
  939. # Опция check_ancestor означает, что если файл .forward генерирует
  940. # адрес, который является предыдущим для этого (то есть обратно
  941. # отправителю), то такое правило будет просто опущено.
  942. # Предотвращает случай, когда есть такие алиасы A -> B, а у B
  943. # B -> A.
  944.  
  945. #  Один из трех транспортов используется при пересылке,
  946. # в зависимости от указанных правил в файле .forward.
  947.  
  948. #userforward:
  949. #  driver = redirect
  950. #  check_local_user
  951. # local_part_suffix = +* : -*
  952. # local_part_suffix_optional
  953. #  file = $home/.forward
  954. # allow_filter
  955. #  no_verify
  956. #  no_expn
  957. #  check_ancestor
  958. #  file_transport = address_file
  959. #  pipe_transport = address_pipe
  960. #  reply_transport = address_reply
  961. #  condition = ${if exists{$home/.forward} {yes} {no} }
  962.  
  963. # Данный роутер срабатывает, если письмо пришло для зарегистрированного
  964. # пользователя в системе. Если доставка не удалась, то генерируется
  965. # сообщение об ошибке - "Unknown user".
  966.  
  967. virtual_user:
  968.   driver = accept
  969.   transport = dovecot_delivery
  970.   domains = +local_domains
  971.   condition = CHECK_VIRTUAL_USER
  972.   no_more
  973.  
  974. #####################################################################
  975. #                        Настройка транспортов
  976. #####################################################################
  977. #                    Порядок транспортов не имеет значения.
  978. #     Только один транспорт отрабатывает при каждой доставке.
  979. #####################################################################
  980.  
  981. # Транспорт используется только после обработки письма роутером.
  982.  
  983. begin transports
  984.  
  985.  
  986. # Этот транспорт используется для доставки писем по SMTP.
  987. # Практически для всех доменов я использую технологию DKIM.
  988. # Подписывать сообщение или нет, определяется в параметре
  989. # dkim_private_key, если он будет пуст, либо 0, либо false, то
  990. # сообщение подписано не будет.
  991. #
  992. # Сгенерировать ключ для домена можно так:
  993. #     openssl genrsa -out domain.key 1024
  994. # Вывод конмады (открытый ключ):
  995. #     openssl rsa -in info-x.org.key -pubout
  996. # Разместить в DNS записе домена, например:
  997. #     _dkim._domainkey.example.net IN TXT "v=DKIM1; k=rsa; t=s; p=your_key"
  998. # Описание ключей можно без проблем найти в RFC.
  999. # Полезным будет добавление еще одной записи в зону:
  1000. #     _adsp._domainkey.example.net IN TXT "dkim=all"
  1001. # Данная запись означает, что все сообщения для данного домена
  1002. # должны быть подписаны. То есть принимающая сторона, увидев
  1003. # данную запись будет принимать соответствующие решения, если
  1004. # например, вдруг письмо, отправленное с этого домена окажется
  1005. # не подписанным.
  1006.  
  1007. remote_smtp:
  1008.   driver = smtp
  1009.   dkim_domain = ${lc:${domain:$h_from:}}
  1010.   dkim_selector = _dkim
  1011.   dkim_private_key = ${if exists{DKIM_DIRECTORY/${dkim_domain}.key}{DKIM_DIRECTORY/${dkim_domain}.key}{false}}
  1012.   dkim_canon = relaxed
  1013.   dkim_strict = yes
  1014.  
  1015.  
  1016. # Этот транспорт используется для доставки писем в ящики локальных
  1017. # пользователей в традиционном для BSD формате - mailbox.
  1018. # По умолчанию процесс доставки запускается с правами пользователя
  1019. # (uid, gid), поэтому необходимо, чтобы был установлен sticky бит
  1020. # на директорию /var/mail. В некоторых системых доставка
  1021. # осуществляется по другому - вместо sticky бита используется общая
  1022. # группа. Закомментированные опции показывают как такое может быть
  1023. # реализовано в Exim.
  1024.  
  1025. #local_delivery:
  1026. #  driver = appendfile
  1027. #  file = /var/mail/$local_part
  1028. #  delivery_date_add
  1029. #  envelope_to_add
  1030. #  return_path_add
  1031. #  group = mail
  1032. #  user = $local_part
  1033. #  mode = 0660
  1034. #  no_mode_fail_narrower
  1035.  
  1036. # Транспорт доставки писем для виртуальных пользователей.
  1037. # При использовании данного транспорта Exim сам будет сохранять письма
  1038. # в почтовый ящик.
  1039. # Раньше у меня он работал так, но щас письма доставляются с использованием
  1040. # Dovecot LDA. Поэтому этот транспорт не используется в данной конфигурации.
  1041. # Удалять не стал, вдруг пригодится где-нибудь.
  1042. #virtual_delivery:
  1043. #  driver = appendfile
  1044. #  create_directory
  1045. #  delivery_date_add
  1046. #  envelope_to_add
  1047. #  return_path_add
  1048. #  message_prefix =
  1049. #  message_suffix =
  1050. #  maildir_format
  1051. #  maildir_tag = ,S=$message_size
  1052. #  maildir_use_size_file
  1053. #  mode = 0600
  1054. #  directory_mode = 0700
  1055. #  group = GET_VIRTUAL_GROUP
  1056. #  user = GET_VIRTUAL_USER
  1057. #  directory = GET_VIRTUAL_DIR
  1058. #  quota = GET_VIRTUAL_QUOTA
  1059. #  quota_size_regex = ,S=(\d+)
  1060. #  quota_is_inclusive = false
  1061.  
  1062. # Транспорт доставки писем для виртуальных пользователей.
  1063. # Сохранение писем в ящик возложено на плечи Dovecot LDA.
  1064. dovecot_delivery:
  1065.   driver = pipe
  1066.   command = /usr/local/libexec/dovecot/dovecot-lda -e -d $local_part@$domain  -f $sender_address -a $original_local_part@$original_domain
  1067.   message_prefix =
  1068.   message_suffix =
  1069.   delivery_date_add
  1070.   envelope_to_add
  1071.   return_path_add
  1072.   return_fail_output
  1073.   log_output
  1074.   umask = 077
  1075.   group = GET_VIRTUAL_GROUP
  1076.   user = GET_VIRTUAL_USER
  1077.   temp_errors = 64 : 69 : 70: 71 : 72 : 73 : 74 : 75 : 78
  1078.  
  1079. # Этот транспорт используется при доставке писем, адресаты
  1080. # которых были сгенерированы через файл алиасов или .forward.
  1081. # Если pipe что-нибудь выводит на стандартный дескриптор вывода,
  1082. # то этот вывод используется как сообщение об ошибке
  1083. # и направляется отправителю. Если вы хотите, чтобы сообщение
  1084. # отправлялось только в случае ошибки, то используйте опцию
  1085. # return_fail_output вместо return_output. если оно вам нужно, то
  1086. # можете сделать различные транспорты для файла алиасов
  1087. # и файла .forward.
  1088.  
  1089. address_pipe:
  1090.   driver = pipe
  1091.   return_output
  1092.  
  1093.  
  1094. # Этот транспорт используется для доставки писем в файлы,
  1095. # адреса которых были сгенерированы файлом алиасов или
  1096. # файлом .forward.
  1097.  
  1098. address_file:
  1099.   driver = appendfile
  1100.   delivery_date_add
  1101.   envelope_to_add
  1102.   return_path_add
  1103.  
  1104.  
  1105. # Транспорт используется для обработки автоответов.
  1106.  
  1107. address_reply:
  1108.   driver = autoreply
  1109.  
  1110.  
  1111.  
  1112. ######################################################################
  1113. #                   Конфигурация повторных попыток передачи
  1114. ######################################################################
  1115.  
  1116. begin retry
  1117.  
  1118. # Это единственное правило применяется для всех доменов и для всех типах
  1119. # ошибок. Повторные попытки будут происходить каждые 15 минут в течении
  1120. # 2 часов. После чего эти интервалы будут увеличены, начиная с 1 часа и 
  1121. # увеличивая каждый раз в 1.5 раза до 16 часов. После повторная передача
  1122. # будет производиться каждые 6 часов, до тех пор, пока не пройдет 4 дня
  1123. # с первой неудачной попытки.
  1124.  
  1125. # Осторожно: Если вы не сконфигурируете повторную передачу (т.е., если
  1126. # этой секции не будет или она будет пустой), то Exim не будет делать
  1127. # повторных попыток передачи вообще. Поэтому, не удаляйте это правило,
  1128. # если в этом нет необходимости.
  1129.  
  1130. # Address or Domain    Error       Retries
  1131. # -----------------    -----       -------
  1132.  
  1133. *                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h
  1134.  
  1135.  
  1136.  
  1137. ######################################################################
  1138. #                      Параметры перезаписи
  1139. ######################################################################
  1140.  
  1141. # There are no rewriting specifications in this default configuration file.
  1142.  
  1143. begin rewrite
  1144.  
  1145.  
  1146.  
  1147. ######################################################################
  1148. #                   Параметры аутентификации
  1149. ######################################################################
  1150.  
  1151. # Следующие аутентификаторы поддерживают аутентификацию открытым
  1152. # текстом, используя стандартные механизмы PLAIN и LOGIN. Данные
  1153. # механизмы поддерживает большинство почтовых клиентов.
  1154. #
  1155. # Аутентификаторы не настроены до конца, поэтому вам необходимо
  1156. # задать параметр server_condition, чтобы Exim мог проверять
  1157. # переданные учетные данные. 
  1158. #
  1159. # По  умолчанию в правиле RCPT ACL есть проверка на предмет
  1160. # зареганого пользователя и если он прошел его, то письмо будет принято
  1161. # независимо от того, окуда оно будет отправляться.
  1162.  
  1163. begin authenticators
  1164.  
  1165. # PLAIN метод. Клиент отправляет идентификатор сессии (который тут
  1166. # не используется), логин и пароль. После, доступ к логину и паролю
  1167. # можно получить через переменные $auth2 и $auth3 и проверить
  1168. # их корректность.
  1169.  
  1170. # Аутентификация пользователя проводится средствами Dovecot.
  1171. # Правило server_advertise_condition = ${if def:tls_cipher } запрещает
  1172. # пользователям проходить аутентификаю, если соединение не защищено.
  1173.  
  1174. PLAIN:
  1175.   driver                     = dovecot
  1176.   public_name                = PLAIN
  1177.   server_set_id              = $auth1
  1178.   server_socket              = /var/run/dovecot/auth-client
  1179.   server_advertise_condition = ${if def:tls_cipher }
  1180.  
  1181. # LOGIN метод. Здесь нет идентификатора сессии, поэтому логин
  1182. # и пароль доступны через переменные $auth1 и $auth2.
  1183.  
  1184. # Аутентификация пользователя проводится средствами Dovecot.
  1185. # Правило server_advertise_condition = ${if def:tls_cipher } запрещает
  1186. # пользователям проходить аутентификаю, если соединение не защищено.
  1187.  
  1188. LOGIN:
  1189.   driver                     = dovecot
  1190.   public_name                = LOGIN
  1191.   server_set_id              = $auth1
  1192.   server_socket              = /var/run/dovecot/auth-client
  1193.   server_advertise_condition = ${if def:tls_cipher }
  1194.  
  1195.  
  1196. ######################################################################
  1197. #                   Конфигурация local_scan()
  1198. ######################################################################
  1199.  
  1200. # Если вы собрали Exim с поддержкой функции local_scan(), которая
  1201. # содержит таблицы для приватных опций, то здесь вы можете указать их.
  1202. # Не забудьте раскомментировать строку с "begin". По умолчанию
  1203. # закомментирована, потому что вылезет ошибка, если Exim собран
  1204. # без данной плюшки.
  1205.  
  1206. # begin local_scan
  1207.  
  1208.  
  1209. # Конец конфигурационного файла

Содержимое файла /usr/local/etc/exim/extra/dynamic_pools:
  1. ^.*([0-9]+).([0-9]+).([0-9]+).([0-9]+).*
  2. ^.*dhcp.*
  3. ^.*host.*
  4. ^.*dsl.*
  5. ^.*dial.*
  6. ^.*broad.*
  7. ^.*band.*
  8. ^.*user.*
  9. ^.*pool.*
  10. ^.*client.*
  11. ^.*cable.*
  12. ^.*pppoe.*
  13. ^.*hsd.*
  14. ^.*dyn.*
  15. ^.*static.*
  16. ^.*ppp.*
  17. ^.*speedy.*
  18. ^.*customer.*

Выше я говорил, что записи из таблиц (необходимых для работы серого списка) подчищаются скриптом, который у меня запускается раз в день. Собственно, вот код этого скрипта (для его работы необходим установленный модуль p5-DBD-Pg):
  1. #!/usr/bin/env perl
  2.  
  3. use DBI;
  4. use strict;
  5. use warnings;
  6.  
  7. my $db_user = 'vmail';
  8. my $db_pass = 'vmail';
  9. my $db_host = '192.168.7.253';
  10. my $db_port = 5432;
  11. my $db_dsn = "DBI:Pg:db=mail_system;host=$db_host;port=$db_port";
  12. my %con_attr = (
  13.         'RaiseError' => 1,
  14.         'PrintError' => 1,
  15.         'AutoCommit' => 1
  16. );
  17.  
  18. my $query = '
  19.         DELETE FROM "blacklist_tb" WHERE "ctime" <= date_part($$epoch$$, now()) - 1209600;
  20.         DELETE FROM "greylist_tb" WHERE "ctime" <= date_part($$epoch$$, now()) - 604800;
  21.         DELETE FROM "whitelist_tb" WHERE "ctime" <= date_part($$epoch$$, now()) - 2678400;
  22. ';
  23.  
  24. my $dbh = DBI->connect($db_dsn, $db_user, $db_pass, \%con_attr) ||
  25.                 die("Can't connect to databse: $DBI::errstr\n");
  26.  
  27. $dbh->do($query) || die("Can't execute query: ".$dbh->errstr);
  28.  
  29. $dbh->disconnect();
  30.  
  31. exit(0);

Еще один момент — для полноценной замены системного MTA sendmail, необходимо привести содержимое файла /etc/mail/mailer.conf к следующему виду:
  1. sendmail        /usr/local/sbin/exim
  2. send-mail       /usr/local/sbin/exim
  3. mailq           /usr/local/sbin/exim -bp
  4. newaliases      /usr/local/sbin/exim -bi
  5. hoststat        /usr/local/sbin/exim
  6. purgestat       /usr/local/sbin/exim

И добавить в файл /etc/periodic.conf следующее:
  1. daily_status_include_submit_mailq="NO"
  2. daily_clean_hoststat_enable="NO"
  3. daily_queuerun_enable="NO"
  4. daily_submit_queuerun="NO"

4.3 Запуск и проверка конфигурации

Для автоматического запуска Exim во время старта системы необходимо добавить следующие строки в /etc/rc.conf:

  1. # echo 'sendmail_enable="NONE"' >> /etc/rc.conf
  2. # echo 'sendmail_submit_enable="NO"' >> /etc/rc.conf
  3. # echo 'exim_enable="YES"' >> /etc/rc.conf

Теперь можно запустить сервис:
  1. # service exim start
  2. # sockstat -4 -l | grep exim
  3. smmsp    exim-4.80. 88757 3  tcp4   *:25                  *:*
  4. smmsp    exim-4.80. 88757 4  tcp4   *:465                 *:*
  5. smmsp    exim-4.80. 88757 5  tcp4   *:587                 *:*

Если сервис не запустился, то смотрите логи (которые распологаются в /var/log/exim) и ищите проблему. Теперь проверим работоспособность сервиса, для этого подключимся telnet,ом к серверу и сымитируем обычную SMTP сессию. Не забываем, что перед проверкой работы сервиса необходимо создать пару почтовых ящиков в базе данных.
  1. # telnet 127.0.0.1 25
  2. Trying 127.0.0.1...
  3. Connected to localhost.
  4. Escape character is '^]'.
  5. 220 mx.info-x.org ESMTP MTA :)
  6. HELO localhost
  7. 250 mx.info-x.org Hello localhost [127.0.0.1]
  8. MAIL FROM: <test@info-x.org>
  9. 250 OK
  10. RCPT TO: <nekit@info-x.org>
  11. 250 Accepted
  12. DATA
  13. 354 Enter message, ending with "." on a line by itself
  14. From: <test@info-x.org>
  15. To: <nekit@info-x.org>
  16. Subject: Test message
  17. Hello world!!!
  18. .
  19. 250 OK id=1U9KRy-000M9i-7F
  20. QUIT
  21. 221 mx.info-x.org closing connection
  22. Connection closed by foreign host.

Посмотрим теперь на записи в логах:
  1. # cat /var/log/exim/mainlog | grep 1U9KRy-000M9i-7F
  2. 2013-02-24 01:09:28 1U9KRy-000M9i-7F <= test@info-x.org H=(localhost) [127.0.0.1] I=[127.0.0.1]:25 P=smtp S=387 from <test@info-x.org> for nekit@info-x.org
  3. 2013-02-24 01:09:28 1U9KRy-000M9i-7F => nekit <nekit@info-x.org> R=virtual_user T=dovecot_delivery
  4. 2013-02-24 01:09:28 1U9KRy-000M9i-7F Completed

Из логов видно, что почта ходит нормально, то есть отправляется и принимается. На этом шаге настройку MTA Exim можно считать завершенной. Также можно сказать, что у нас уже есть готовая почтовая система, которой могут пользоваться зарегистрированные пользователи. Напоследок стоит отметить, что не будет лишним проверить почтовый сервер на возможность использования его как открытого релея. Сервисов могущих помочь в этом сейчас довольно много в интернете.


Назад | Начало | Вперед