В этой статье пойдет речь о создании эффективного почтового сервера на базе MTA exim. Первый вопрос, который, конечно же приходит в голову - "А почему именно exim?". Отвечают на этот вопрос по-разному, поэтому я скажу, что меня так привлекает в exim-е: - логичная схема обработки почты; - высокая скорость работы; - удобный формат конфигурационного файла; - широчайшие возможности по поиску каких-либо значений в файлах, СУБД, LDAP - встроенная поддержка smtp-аутентификации - небольшое число найденных уязвимостей (фактически я знаю только об одной, найденной недавно, она касалась версий exim-a до 4.20 включительно) - очень большое количество возможностей, а также чрезвычайная гибкость - возможность полной замены sendmail(т.е. можно сделать ln -sf /usr/local/sbin/exim /usr/libexec/sendmail :-)) На мой взгляд, exim является весьма и весьма удачным продуктом, не зря он используется по умолчанию в ОС Debian GNU Linux. Два больших минуса exim-a состоят в том, что отсутствует качественная документация на русском языке необходимость правки Makefile для включения тех или иных возможностей exim-а. Итак, для начала подумаем, что должна содержать "идеальная" с точки зрения удобства администрирования и использования почтовая система. Сформулируем ряд требований к почтовой системе: 1) простота управления пользователями 2) возможность предоставления доступа для отправки почты пользователям локальной сети и мобильным пользователям (при помощи smtp аутентификации) 3) максимальная защита от хакерских атак, вирусов и спама Базовой системой для установки MTA явилась FreeBSD 5.2.1, что обусловило определенные особенности установки. Перечислю весь набор программного обеспечения для организации mail сервера: - exim-4.34 - MTA (mail transfer agent - агент передачи почты) - courier-3.0.4 - imap сервер, для доступа к почте пользователей, не имеющих локальных пользовательских учетных записей (виртуальные пользователи) - clamav - для поиска вирусов - spamassasin - для поиска спамерских писем - postgresql-7.4.2 - для хранения всех данных о пользователях почтовой системы - squirrelmail - просто приятный веб-интерфейс для почты (требует веб-сервер и php) Конечно, можно собрать все вышеперечисленные компоненты и вручную, но я не поклонник такого подхода. Во-первых надо очень четко представлять порядок сборки различных компонентов. Во-вторых, необходимо разбираться в куче опций для связки различных библиотек. В-третьих, надо четко представлять себе все пути и знать, каких пользователей надо добавлять. Ну и в-четвертых, это дело очень сложно обновлять. Потому мы воспользуемся услугами системы портов (если у вас, например, Debian GNU Linux, то нужный пакет называется exim4-daemon-heavy). Для этого ставим следующие порты: - databases/pogstgresql7 - mail/exim (при компиляции необходимо указать следующие опции: make WITH_PGSQL=yo - mail/p5-Mail-SpamAssassin - security/clamav - mail/courier-imap (при компиляции опять же указываем: make WITH_CRAM=yo WITH_POSTGRESQL=yo - mail/squirrelmail После сборки всего нужного переходим к стадии настройки. Тут придется затратить порядочное количество времени на настройку всех компонентов почтовой системы, и целью этой статьи является минимизация этого времени :) Итак, начнем с настройки СУБД postgresql, как основы для построения почтовой системы. Во-первых postgresql работает с правами системного пользователя pgsql (обратите внимание, этот пользователь имеет реальный shell и домашний каталог - /usr/local/pgsql/). Поэтому для начала задаем пароль для данного пользователя: # passwd pgsql Далее делаем su pgsql и начинаем создание базы данных: # su pgsql % psql вводим пароль пользователя pgsql и попадаем в командную строку sql запросов. Для подробного ознакомления с возможностями СУБД, советую обратиться к руководству или же одной из книг. создаем БД: CREATE DATABASE users; присоединяемся к данной БД: \c users создаем таблицу пользовательских аккаунтов, а также constraint'ы для нее: CREATE TABLE accounts ( uid serial NOT NULL, login character varying(128), "password" character varying(128), maildir character varying(255), gecos character varying(255), gid integer DEFAULT 150, home character varying(255), mailquota integer DEFAULT 20 ); ALTER TABLE ONLY accounts ADD CONSTRAINT uid_k PRIMARY KEY (uid); ALTER TABLE ONLY accounts ADD CONSTRAINT login_k UNIQUE (login); создаем таблицу алиасов: CREATE TABLE aliases ( mail character varying(128) NOT NULL, alias character varying(128) ); ALTER TABLE ONLY aliases ADD CONSTRAINT mail_k PRIMARY KEY (mail); Поясню назначение таблиц и полей: Таблица accounts предназначена для хранения данных о виртуальных пользователях почтовой системы, назначение полей: -uid - уникальный номер пользователя, имеет автоинкрементный тип -login - строка, содержащая имя пользователя в формате "имя@домен" для возможности доставки почты для пользователей различных доменов -password - пароль в открытом виде (для возможности безопасной cram-md5 аутентификации) -maildir - путь к постовому ящику в формате maildir -gecos - комментарий (для чего-нибудь, да пригодится :) ) -gid - идентификатор группы (не нужен реально, но зачем-то требуется для courier'а) -home - аналогично gid -mailquota - число в мегабайтах, указывающее квоту для пользователя Таблица aliases представляет собой просто замену /etc/aliases, содержит два поля - mail (исходный адрес) и alias (адрес для перенаправления). После этого будем считать, что postgresql у нас работает. Однако, для полного использования возможностей этой СУБД лучше почитать документацию. Далее перейдем к настройке собственно MTA exim. Конфигурационный файл для версии "из портов" хранится в /usr/local/etc/exim/configure. Для начала я бы хотел пояснить значение некоторых терминов и рассказать о базовых принципах работы exim'a. Представим себе путь прохождения любого почтового сообщения. Любое письмо состоит из так называемого "конверта" и собственно данных. То, с чем мы привыкли работать в почтовых клиентах, как раз является "данными" и не имеет к конверту никакого отношения. В конверте описываются 2 параметра: mail from: и rcpt to:, которые указывают отправителя и получателей соответственно. Сеанс работы с MTA может предваряться "приветствием" - стандартным (HELO) и расширенным (EHLO). В приветствии должно указываться FQDN клиента, хотя, по ряду причин, не стоит слишком строго следить за именно FQDN, т.к. многие машины могут находиться за NAT'ом. MTA в ответ на HELO или EHLO сообщает о своих возможностях, обеспечивая тем самым синхронизацию клиента и сервера. Далее exim осуществляет проверку целевых адресов на предмет их допустимости для данного сервера. Этот этап может предваряться аутентификацией и установкой TLS-сессии. Если пользователь прошел какой-либо из этих этапов, ему присваиваются определенные флаги, которые в дальнейшем могут использоваться на этапе проверки конверта. По умолчанию exim осуществляет проверку недопустимых символов в адресах и позволяет отпарвлять почту только из локальных доменов и только на локальные домены. Кроме того, при успешной аутентификации письмо проходит и в интернет. Для остальных писем релей (передача писем) запрещена. Все проверки в exim4 осуществляются на основании механизма acl (access control list - список доступа). Также может осуществляться проверка данных (этот механизм добавляется при установке патча exiscan, который при установке портов уже ставится). После успешной прохождения этого этапа exim просматривает rewrite правила, для переписывания отдельных частей конверта (может использоваться в целях перенаправления всех писем на какой-либо смарт-хост, например). Далее письмо попадает на цепочку так называемых "роутеров", которые определяют, как именно доставлять письмо. Среди роутеров фигурирует dnslookup, доставляющий письма на основании MX записей в DNS, проверка файла алиасов и .forward файлов ну и локальная доставка. Каждый роутер имеет некое условие срабатывания и соответствующий транспорт. При выполнении условия, exim выбирает указанный транспорт для доставки письма, иначе письмо проходит на следующий роутер (поэтому важен порядок описания роутеров в конфигурационном файле). Транспорты же определяют порядок доставки письма. Таким образом, настройка exim'а состоит из нескольких частей: -настройка глобальных параметров -настройка acl's -настройка роутеров -настройка транспортов -настройка аутентификаторов -настройка очереди -настройка rewrite правил В настройке exim'а широко используются различные списки (hostlist, domainlist и dnslist) и так называемые lookup'ы, при помощи которых exim извлекает данные из внешних источников. Многие мои знакомые, пытаясь освоить exim, считали lookup'ы самой запутанной темой, потому я остановлюсь на этом вопросе чуть подробнее. Существует два типа поиска: поиск по одному ключу (single-key) и поиск по запросу (query). Первый используется для поиска в локальных файлах, а второй - в различного рода базах (sql, ldap и прочее). Любые lookup'ы могут быть вложенными, то есть в одном поиске используются результаты другого. Поиск на основе single key строится примерно так: ${lookup{$var_to_search}lsearch{/path/to/file}} особо следует отметить расставление фигурных скобок. Если вы знакомы с функциональными языками, вроде лиспа, то такой синтаксис для вас будет привычен, иначе просто нужно считать каждую конструкцию списком, который обрабатывает exim. Тогда все строковые и другие константы тоже заключаются в фигурные скобки. То есть вышеприведенный пример можно рассматривать как $список -> ${lookupсписок} -> ${lookup {$var_to_search} driver{driver_arguments}}. При этом сам файл, в котором осуществляется поиск должен выглядеть так: $var_to_search: значение Приведу более конкретный пример - построение списка доменов из файла на основании адреса отправителя (пример из документации): domainlist domains = ${lookup{$sender_host_address}lsearch{/some/file}} при этом сам файл должен выглядеть следующим образом: 192.168.3.4: domain1 : domain2 : ... 192.168.1.9: domain3 : domain4 : ... При этом поиск осуществляется по первому полю. Отличие query-style поиска в том, что мы явно не указываем, что искать, указывая вместо этого запрос. Так, например выглядит типичный запрос к sql базе: ${lookup driver{query}{action_if_query_succeed}{action_if_query_failed}} Например: domainlist domains = ${lookup pgsql{select domains from domains where \ sender='$sender_host_address'}{$value}fail} При успешном выполнении запроса возвращается значение из базы, иначе выполняется специальное действие fail, означающее неудачный запрос. Несколько пугающими бывают запросы к ldap. Разберу их поподробнее. уазание сервера и порта ldap выглядит следующим образом: ldap_default_servers = 127.0.0.1::389 запросы к директории выглядят так: ${lookup ldap{ldap://ldap.test.ru/dc=${domain},ou=mail,o=tehnopark?mail?sub?\ (&(objectClass=inetOrgPerson)\ (mail=${local_part}@${domain}))}{$value} fail} Форма запроса описана в стандарте, но, думаю, ее стоит дополнительно пояснить. В запросе мы указываем адрес ldap сервера (ldap://ldap.test.ru/), basedn для поиска (dc=${domain},ou=mail,o=tehnopark), значение, которое нужно вернуть (mail), описание запроса (также в постфиксной форме, характерной для функциональных языков: (&(objectClass=inetOrgPerson)(mail=${local_part}@${domain}))) Когда требуется аутентификация на сервере, тогда просто указываем нечто вроде ${lookup ldap {user="cn=manager,o=tehnopark of innovation,c=RU" pass=secret ldap:///o=tehnopark%20of%20innovation,c=RU?sn?sub?(cn=foo)} {$value}fail} Заметьте необходимость замены пробелов на %20, как того требует стандарт. Более подробно обо всем этом можно узнать на http://www.exim.org/exim-html-4.30/doc/html/spec_9.html#CHAP9 Думаю, для дальнейшего понимания статьи, этого вполне достаточно. Итак, собственно конфигурационный файл exim'a. Кое-где я добавил свои комментарии, чтобы улучшить понимание различных директив. ###################################################################### # Runtime configuration file for Exim # ###################################################################### # Здесь мы определяем макросы, описывающие различные пути CONFIG_PREFIX=/usr/local/etc/exim ACL_PREFIX=CONFIG_PREFIX/acls CERTDIR=CONFIG_PREFIX/certs # Здесь мы указываем, где находить наш postgresql сервер, соединение # осуществляется через локальный сокет, команда hide помогает спрятать эту # настройку при вызове exim -bP, когда exim выводит все конфигурационные опции в # стандартный вывод. Учтите, # что сам /usr/local/etc/exim/configure должен иметь владельца root:wheel и # иметь права доступа 0600, что отличается от того, что принято по умолчанию # (0644) hide pgsql_servers = (/tmp/.s.PGSQL.5432)/users/pgsql/pAsSwOrD # Тут мы описываем списки доменов # Local_domains включает домены, считающиеся локальными, то есть те домены, для # которых exim делает локальную доставку, для остальных доменов почта # доставляется по MX записям в DNS. Обратите внимание на дополнительные файлы # ACL_PREFIX/localdomains и ACL_PREFIX/hostingdomains, в которых перечислены # домены, разделенные переводом строки (то есть, по одному домену на каждую # строку) domainlist local_domains = unona.test.ru : ACL_PREFIX/localdomains : ACL_PREFIX/hostingdomains # Дополнительная настройка domainlist hosting_domains = ACL_PREFIX/hostingdomains # Список хостов, почту на которые мы явно отвергаем hostlist host_reject = ACL_PREFIX/hostreject domainlist relay_to_domains = # Список адресов, с которых разрешена передача почты во внешний мир hostlist relay_from_hosts = localhost : 192.168.1.0/24 : ACL_PREFIX/relayfromhosts # Проверка получателя acl_smtp_rcpt = acl_check_rcptъ # Проверка mime содержимого acl_smtp_mime = acl_check_mime # Проверка на спам и вирусы acl_smtp_data = acl_check_virus # Здесь мы описываем наш антивирус av_scanner = clamd:127.0.0.1 3310 # И spamassasin spamd_address = 127.0.0.1 783 # Настройки пользователя и группы по умолчанию exim_user = mailnull exim_group = mail # Никогда не осуществляем доставку под рутом - root должен быть алиасом на # другого локального пользователя. Кстати, это _обязательное_ условие, заданное # еще на этапе компиляции never_users = root # Настройки директории для очереди spool_directory = /var/spool/exim # Разделяем spool_directory на несколько более маленьких - аналог хеш таблицы, # ускоряет обработку spool'а split_spool_directory # Пытаемся сделать соответствие прямой и обратной зоны dns для каждого хоста. # Несколько затратно, но весьма полезно host_lookup = * # Убираем проверку identd на клиентской стороне. Из-за неправильно настроенных # firewall'ов это часто вызывает длительные тайм-ауты, кроме того, этот сервис # поднят не у многих rfc1413_query_timeout = 0s # Указываем кое-какие лимиты (их назначение ясно из названия) smtp_accept_max = 50 smtp_connect_backlog = 40 smtp_accept_max_per_host = 10 smtp_accept_queue = 22 smtp_accept_queue_per_connection = 10 recipients_max = 16 recipients_max_reject = true message_size_limit = 16M accept_8bitmime # Игнорируем сообщения, которые приходят нам же, давность которых более 12-ти часов ignore_bounce_errors_after = 12h # Удаляем замороженные сообщения, давность которых больше недели. timeout_frozen_after = 7d # Настройки TLS tls_certificate = CERTDIR/mailed.crt tls_privatekey = CERTDIR/mailed.key tls_advertise_hosts = * tls_verify_certificates = * # Следующая опция закомментирована, но весьма полезна, позволяя авторизироваться # только через безопасный ssl канал #auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}} ###################################################################### # ACL CONFIGURATION # # Specifies access control lists for incoming SMTP mail # ###################################################################### begin acl # Этот список доступа описывает проверки, осуществляемые при вызове любой RCPT # команды acl_check_rcpt: # Вначале проверяем достоверность отправителя require verify = sender # Принимаем соединения от локальных MUA (то есть не через TCP/IP) accept hosts = : ############################################################################# # Проверка соответствия почтового адреса стандарту deny message = Restricted characters in address domains = +local_domains local_parts = ^[.] : ^.*[@%!/|] accept domains = +local_domains # Здесь прописаны так называемые dnsbl, то есть черные списки MTA с открытым # релеем, мы проверяем ip адрес отправителя на соответствие таким спискам и # блокируем письмо, если отправитель был найден в таком списке deny message = host is listed in $dnslist_domain dnslists = blackholes.mail-abuse.org:relays.mail-abuse.org # Правило на проверку всех почтовых адресов, кроме локальных (менее строгое) deny message = Restricted characters in address domains = !+local_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ ############################################################################# # Принимаем почту для пользователя postmaster локальных доменов, не взирая на # отправителя accept local_parts = postmaster domains = +local_domains # Deny unless the sender address can be verified. accept domains = +local_domains endpass verify = recipient # Если домен в списке relay_to_domains, то разрешаем релей accept domains = +relay_to_domains endpass verify = recipient accept domains= +hosting_domains endpass verify= recipient accept hosts = +relay_from_hosts # Принимаем любые соединения, которые были успешно авторизованы accept authenticated = * # Реализация нашего бан-листа deny hosts= +host_reject message= You are banned. Go away. # Запрещаем все, что не разрешено, закрывая тем самым релей для спамеров deny message = relay not permitted # Список доступа для проверки mime частей сообщения acl_check_mime: # Произодим декодирование mime сообщений. Полезно для дальнейшей проверки на # вирусы warn decode = default # Можно очень быстро отсеять сообщения, просто запретив некоторые mime # вложения, чаще всего содержащие вирусы, хотя, конечно, это не панацея deny message = Blacklisted file extension detected condition = ${if match \ {${lc:$mime_filename}} \ {\N(\.wav|\.cpl|\.pif|\.bat|\.scr|\.lnk|\.com)$\N} \ {1}{0}} # Много ли у нас людей, знающих китайский? А вот китайского спама это поубавит # :) deny message = Sorry, noone speaks chinese here condition = ${if eq{$mime_charset}{gb2312}{1}{0}} accept # Проверка содержимого на вирусы и спам acl_check_virus: # Мы не запрещаем письма со спамом, а просто добавляем заголовок, # содержащий количество спамерских очков, а пользователь на своей # стороне уже просто настраивает свои фильтры. Так мы исключаем жалобы # со стороны пользователей о потерянных письмах warn message = X-Spam-Score: $spam_score ($spam_bar) spam = nobody:true # Добавляем заголовки, указывающие, что письма были проверены # spamasssasin'ом warn message = X-Spam-Scanned: Yes warn message = X-Spam-Scanner: SpamAssassin running on mail.test.ru # Вот что-что, а вирусы нам не нужны. deny message = Message rejected: virus found. Your message was successfully trashed. hosts = * malware = * accept ###################################################################### # ROUTERS CONFIGURATION # # Specifies how addresses are handled # ###################################################################### # THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT! # # An address is passed to each router in turn until it is accepted. # ###################################################################### begin routers # Роутер, осуществляющий поиск по MX записям в DNS dnslookup: driver = dnslookup domains = ! +local_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more # Все останльные роутеры обслуживают доставку локальной почты # Драйвер алиасов пользователя. Обратите внимание на lookup в pgsql базе. Что # интересно, этот lookup работает даже для иерархических алиасов, например, # postmaster -> root -> cebka -> cebka@jet.msk.su Также определяются транспорты # для передачи почты в файл (>/path/to/file) и в pipe # (|/usr/local/libexec/slocal) system_aliases: driver = redirect allow_fail allow_defer data = ${lookup pgsql{select alias from aliases where mail ='$local_part@$domain'}{$value}fail} user = mailnull group = mail file_transport = address_file pipe_transport = address_pipe # Для локальных пользователей также создаем возможность перенаправления почты # через ~/.forward файл. Если включена директива allow_filter, то в .forward # файле можно использовать язык sieve фильтров. Для подробностей см. # документацию на www.exim.org, т.к. на рассмотрение этой темы уйдет слишком # много времени userforward: driver = redirect check_local_user file = $home/.forward no_verify no_expn check_ancestor # allow_filter file_transport = address_file pipe_transport = address_pipe reply_transport = address_reply condition = ${if exists{$home/.forward} {yes} {no} } # Локальная доставка, если данный пользователь найдем в базе localuser: driver = accept condition = ${lookup pgsql {select uid from accounts where login = '$local_part@$domain'}{yes}{no}} transport = local_delivery cannot_route_message = Unknown user ###################################################################### # TRANSPORTS CONFIGURATION # ###################################################################### # ORDER DOES NOT MATTER # # Only one appropriate transport is called for each delivery. # ###################################################################### begin transports # Драйвер для доставки через соединения с удаленными smtp серверами remote_smtp: driver = smtp # Этот транспорт доставляет почту в локальные maildir'ы. Путь к maildir хранится # опять же в таблице accounts. Разрешения на директорию 0700 для возможности # работы с данными директориями imap сервера. При этом владельцем является # группа и пользователь из accounts (потому при вставлении записей в эту таблицу # надо начинать значения uid с достаточно большого числа, например, 2000 и # пересекаться с реальными пользователями оно должно только если реальному # пользователю нужен локальный доступ к maildir'у). # Также из таблицы accounts извлекается данные о размере квоты, и # устанавливается порог в 75% от квоты, когда пользователю посылается указанное # предупреждение об подходе к порогу квоты local_delivery: driver = appendfile directory = ${lookup pgsql{select maildir from accounts where login = '$local_part@$domain'}{$value}fail} create_directory directory_mode = 0770 maildir_format delivery_date_add envelope_to_add return_path_add group = ${lookup pgsql{select gid from accounts where login = '$local_part@$domain'}{$value}fail} user = ${lookup pgsql{select uid from accounts where login = '$local_part@$domain'}{$value}fail} mode = 0660 no_mode_fail_narrower quota = ${lookup pgsql{select mailquota from accounts where login = '$local_part@$domain'}{$value}fail}M quota_warn_message = "\ To: $local_part@domain\n\ From: postmaster@test.ru\n\ Subject: Your maildir is going full\n\ This message is automaticaly gnerated by your mail server.\n\ This means, that your mailbox is 75% full. If you would \n\ override this limit new mail would not be delivered to you!\n" quota_warn_threshold = 75% # Транспорт, осуществляющий доставку в pipe address_pipe: driver = pipe return_output # Транспорт, осуществляющий доставку прямо в файл address_file: driver = appendfile delivery_date_add envelope_to_add return_path_add # Этот транспорт используется для автоматического ответа на сообщения об ошибках address_reply: driver = autoreply ###################################################################### # RETRY CONFIGURATION # ###################################################################### begin retry # Настройки по умолчанию, которые я не трогал, управляют интервала повторной # передачи сообщений # This single retry rule applies to all domains and all errors. It specifies # retries every 15 minutes for 2 hours, then increasing retry intervals, # starting at 1 hour and increasing each time by a factor of 1.5, up to 16 # hours, then retries every 6 hours until 4 days have passed since the first # failed delivery. # Address or Domain Error Retries # ----------------- ----- ------- * * F,2h,15m; G,16h,1h,1.5; F,4d,6h ###################################################################### # REWRITE CONFIGURATION # ###################################################################### begin rewrite # Создаем правило, по переписыванию заголовка To: с *@test.ru на локальный # smart-host - @unona.test.ru. Это было сделано для локальных пользователей, # по идее с хранением пользователей в postgres, уже не нужно, показано для # примера. *@test.ru $1@unona.test.ru T ###################################################################### # AUTHENTICATION CONFIGURATION # ###################################################################### # Описания аутентификации begin authenticators # CRAM-MD5 аутентификация, требует наличия пароля в открытом виде, имя # пользователя должно быть в формате user@domain, как оно хранится в таблице # accounts lookup_cram: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${lookup pgsql {select password from accounts where login='$1'}{$value}fail} server_set_id = $1 # LOGIN аутентификация - не требует хранения пароля в открытом виде, однако, по # сети пароль передается в открытом виде - требуется лишь выполнение условия # server_condition - $1 - имя пользователя, а $2 - пароль. LOGIN безопасен # только при установлении ssl соединения. login: driver = plaintext public_name = LOGIN server_prompts = Username:: : Password:: server_condition = ${lookup pgsql {select login from accounts where login='$1' and password='$2'}{yes}{no}} server_set_id = $1 ###################################################################### # CONFIGURATION FOR local_scan() # ###################################################################### # If you have built Exim to include a local_scan() function that contains # tables for private options, you can define those options here. Remember to # uncomment the "begin" line. It is commented by default because it provokes # an error with Exim binaries that are not built with LOCAL_SCAN_HAS_OPTIONS # set in the Local/Makefile. # begin local_scan # End of Exim configuration file Далее необходимо создать сертификат для smtp сервера. В ходе эксплуатации выяснилось, что некоторые клиенты, например, The Bat!, требуют, чтобы в CN сертификта (подробнее о сертификатах и способах их генерации можно прочитать в моей статье из данного журнала, располагающейся по адресу http://cebka.pp.ru/my/openssl.txt) содержалось имя (FQDN) сервера. Например, для сервера на mail.test.ru серификат должен содержать CN: mail.test.ru. Содержание остальных полей некритично. Создать сертификат можно, например, так: # openssl genrsa -out mailed.key 2048 # openssl req -new -x509 -key mailed.key -days 365 -out mailed.crt При этом все поля сертификата будут запрошены. Учтите, что файл секретного ключа не должен быть зашифрован, иначе exim не сможет его прочитать, просто установите владельцем этого файла root:wheel и установите права 0600. После этого можно попробовать запустить exim в режиме отладки: exim -bd -d+all и понаблюдать за выводимыми сообщениями. Чтобы включить exim вместо sendmail делаем следующие действия: в файле /etc/rc.conf нужны следующие строки: sendmail_enable="NONE" exim_enable="YES" # А также для spamassasin и clamav: clamav_clamd_enable="YES" spamd_enable="YES" Далее настраиваем доставку почты для локальных приложений через exim, для чего файл /etc/mail/mailer.conf у нас должен выглядеть следующим образом: sendmail /usr/local/sbin/exim send-mail /usr/local/sbin/exim mailq /usr/local/sbin/exim -bp newaliases /usr/local/sbin/exim -bi hoststat /usr/local/sbin/exim purgestat /usr/local/sbin/exim Далее перейдем к настройке clamav: заходим в /usr/local/etc/ и копируем clamav.conf.sample в clamav.conf и правим его таким образом, чтобы он принимал соединения через tcp/ip, а не через локальный сокет, для чего в clamav.confнужны следующие строки: TCPSocket 3310 TCPAddr 127.0.0.1 Далее копируем freshclam.conf.sample в freshclam.conf. Этот файл указывает настройки для программы freshclam, использующейся для обновления антифирусных баз clamav. SpamAssasin работает без дополнительных настроек. Перейдем к следующей части - настройка courier'a. Этот imap сервер для своей работы использует несколько процессов, которые, в свою очередь, настраиваются из различных конфигурационных файлов. В моем примере запущено 3 процесса - authdaemon, courier-imapd и courier-imapd-ssl. Причем во внешний мир открыт только courier-imapd-ssl. Для начала создадим сертификат для imapd-ssl и для TLS соединений с imapd: правим файл /usr/local/etc/couier-imap/imapd.cnf на предмет своего dn для сертификата, для чего в части req_dn прописываем свои настройки (не забудте, что cn должен совпадать с FQDN imap сервера): [ req_dn ] C=RU ST=Moskow region L=Moskow O=Tehnopark OU=Internet technologies CN=test.ru emailAddress=postmaster@test.ru Далее генерируем сертификат специальным скриптом: cd /usr/local/share/courier-imap/ ./mkimapdcert После чего настроим imap аутентификацию: cd /usr/local/etc/courier-imap/ cp authdaemonrc.dist authdaemonrc далее в authdaemonrc заменяем список модулей для аутентификации на: authmodulelist="authpgsql" Теперь courier знает, что ему нужно аутентифицироваться через pgsql. Надо только настроить сам pgsql модуль, настройки которого хранятся в authpqsqlrc. Он должен содержать следующее: # Соединяемся с СУБД через локальный сокет (не указан адрес) PGSQL_PORT 5432 PGSQL_USERNAME pgsql PGSQL_PASSWORD pAsSwOrD PGSQL_DATABASE users # Настройки таблицы для аутентификации, здесь мы указываем, в каких полях # таблицы хранятся различные пользовательские данные: PGSQL_USER_TABLE accounts PGSQL_CLEAR_PWFIELD password DEFAULT_DOMAIN test.ru PGSQL_UID_FIELD uid PGSQL_GID_FIELD gid PGSQL_LOGIN_FIELD login PGSQL_HOME_FIELD home PGSQL_NAME_FIELD gecos PGSQL_MAILDIR_FIELD maildir Перейдем к настройке непосредственно imapd: скоприуем imapd.dist в imapd. Правим следующие строчки (для остальных настроек вполне подходят значения по умолчанию): # imapd слушает только на локальном адресе, для внешних соединений мы будем # использовать imapd-ssl ADDRESS=127.0.0.1 # По умолчанию в NO, делаем в YES, чтобы imapd мог запускаться IMAPDSTART=YES Этих настроек, в принципе, хватает. Далее копируем imapd-ssl.dist в imapd-ssl и правим следующие строчки: IMAPDSSLSTART=YES После чего делаем запуск courier-imap при старте системы. Для этого заходим в /usr/local/etc/rc.d и снова немного попереименовываем файлы: # mv courier-imap-imapd-ssl.sh.sample courier-imap-imapd-ssl.sh # mv courier-imap-imapd.sh.sample courier-imap-imapd.sh После этого считаем, что наша почтовая система практически готова. Нужно только немного понастраивать squirrelmail для чего заходим в /usr/local/www/squirrelmail и запускаем скрипт ./configure. В принципе, интерфейс конфигурации понятен без лишних пояснений, потому я не буду особо останавливаться на этой проблеме (не забудьте, главное, указать imap и smtp сервера). Делаем симлинк на /usr/local/www/squirrelmail из какого-либо VirtualHost'а или из под непосредственно DocumentRoot самого apache. Вот, в принципе, и все. Есть некоторые особенности запуска squirrelmail в при включенном safe_mode в php. Во-первых все php файлы и каталоги squirrelmail должны принадлежать тому пользователю, из под которого работает apache (настройка VirtualHost или глобальная, по умолчанию - www:nogroup). Кроме того необходимо сменить разрешения в /var/spool/squirrelmail: # chmod 1777 /var/spool/squirrelmail/attach # chmod 1777 /var/spool/squirrelmail/pref Ну и владельца установить того же, что и на /usr/local/www/squirrelmail. Теперь дам ссылки на пару полезных скриптов, написанных в ходе эксплуатации системы: -скрипт статистики clamav'а: http://cebka.pp.ru/samag/clamstat.tar.bz2 -скрипт проверки пересечения uid'ов из БД и системных: http://cebka.pp.ru/samag/uidchk.pl
|