1. Устанавливаем Exim
# cd /usr/ports/mail/exim # make install clean
Опции установки выбрал такие (с заделом на будущее)
2. Отредактируем файл /etc/mail/mailer.conf, заменив sendmail на exim.
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
Обратите внимание, что в двух строках появились ключи.
3. Создаем рабочие папки для домена (или доменов – если нужно) и почтового ящика.
# mkdir -p /var/vmail/ # chown -R mailnull:mail /var/vmail
4. Конфигурационный файл принял такой вид
# CONF EXIM + MYSQL + DOVECOT + CLAMAV # Авторизация - довекот. квоты, кламав, БД в мускуле и системные - в файле # Имя нашей почтовой системы primary_hostname = mail.tst-amo.pp.ua # хост/БД/пользователь/пароль mysql_servers = localhost/mail/mailreader/ # Список доменов нашей почтовой системы domainlist local_domains = ${lookup mysql{select domain from domains where domain='${domain}'}} # Логгирование log_selector = +all log_file_path = /var/log/exim/%D-%slog # Список доменов, для которых наша почтовая система является резервной domainlist relay_to_domains = ${lookup mysql{select domain from domains where domain='${domain}'}} hostlist relay_from_hosts = localhost : 127.0.0.1 : 192.168.1.0/24 : 194.44.219.160/28 : 194.44.31.34 acl_smtp_rcpt = acl_check_rcpt acl_smtp_mime = acl_check_mime # Прикручиваем антивирус - при условии, что exim собран # с его поддержкой. В качестве антивиря юзаем ClamAV, # ибо - ПО должно быть свободным! :) # Итак, указываем местоположение сокета clamd. acl_smtp_data = acl_check_data av_scanner = clamd:/var/run/clamav/clamd.sock # Адрес куда слать на проверку спама (SpamAssasin), но я # это не юзаю. Не так много у меня спама... # spamd_address = 127.0.0.1 78 # SSL tls_certificate = /etc/ssl/certs/dovecot.pem tls_privatekey = /etc/ssl/private/dovecot.pem # Отключаем IPv6 disable_ipv6 #порт smtp daemon_smtp_ports = 25 : 465 tls_on_connect_ports = 465 # Дописываем домены отправителя и получателя, если они не указаны qualify_domain = tst-amo.pp.ua qualify_recipient = tst-amo.pp.ua allow_domain_literals = false exim_user = mailnull exim_group = mail never_users = root # Проверять прямую и обратную записи узла отправителя по DNS host_lookup = * # Отключаем проверку пользователей узла отправителя по протоколу ident rfc1413_hosts = * rfc1413_query_timeout = 5s # Запрещаем использовать знак % для явной маршрутизации почты #percent_hack_domains = # Настройки обработки ошибок доставки, используются значения по умолчанию ignore_bounce_errors_after = 2h timeout_frozen_after = 7d return_size_limit = 10K split_spool_directory = true syslog_timestamp = no # Лимит размера сообщения (50 мегабайт default) message_size_limit = 1000M ################ ### конфигурация ACL для входящей почты begin acl # Эти правила срабатывают для каждого получателя acl_check_rcpt: # принимать сообщения которые пришли с локалхоста, # не по TCP/IP accept hosts = : # Запрещаем письма содержащие в локальной части # символы @; %; !; /; |. Учтите, если у вас было # `percent_hack_domains` то % надо убрать. # Проверяются локальные домены deny message = "incorrect symbol in address" domains = +local_domains local_parts = ^[.] : ^.*[@%!/|] # Проверяем недопустимые символы для # нелокальных получателей: deny message = "incorrect symbol in address" domains = !+local_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ # Принимаем почту для постмастеров локальных доменов без # проверки отправителя (я закомментировал, т.к. это - # основной источник спама с мой ящик). accept local_parts = postmaster domains = +local_domains # Запрещаем, если невозможно проверить отправителя # (отсутствует в списке локальных пользователей) # У себя я это закоментил, по причине, что некоторые # железяки (принтеры, & etc) и программы (Касперский, DrWEB) # умеют слать почту, в случае проблем но не умеют ставить # нужного отправителя. Такие письма эта проверка не пускает. # require verify = sender # Запрещаем тех, кто не обменивается приветственными # сообщениями (HELO/EHLO) deny message = "HELO/EHLO require by SMTP RFC" condition = ${if eq{$sender_helo_name}{}{yes}{no}} # Принимаем сообщения от тех, кто аутентифицировался: # Вообще, большинство конфигов в рунете - это один и тот же # конфиг написанный Ginger, в котором этот пункт расположен # внизу. Но при таком расположении рубятся клиенты с adsl, # ppp, и прочие зарезанные на последующих проверках. Но это # же неправильно! Этом мои пользователи из дома! Потому # я это правило расположил до проверок. accept authenticated = * # Рубаем нах, тех, кто подставляет свой IP в HELO deny message = "Your IP in HELO - access denied!" hosts = * : !+relay_from_hosts : !81-196.lissyara.su condition = ${if eq{$sender_helo_name}\ {$sender_host_address}{true}{false}} # Рубаем тех, кто в HELO пихает мой IP (2500 мудаков за месяц!) deny condition = ${if eq{$sender_helo_name}\ {$interface_address}{yes}{no}} hosts = !127.0.0.1 : !localhost : * message = "main IP in your HELO! Access denied!" # Рубаем тех, кто в HELO пихает только цифры # (не бывает хостов ТОЛЬКО из цифр) deny condition = ${if match{$sender_helo_name}\ {\N^\d+$\N}{yes}{no}} hosts = !127.0.0.1 : !localhost : * message = "can not be only number in HELO!" # Рубаем хосты типа *adsl*; *dialup*; *pool*;.... # Нормальные люди с таких не пишут. Если будут # проблемы - уберёте проблемный пункт (у меня клиенты # имеют запись типа asdl-1233.zone.su - я ADSL убрал...) deny message = "your hostname is bad (adsl, poll, ppp & etc)." condition = ${if match{$sender_host_name} \ {adsl|dialup|pool|peer|dhcp} \ {yes}{no}} # Задержка. (это такой метод борьбы со спамом, # основанный на принципе его рассылки) На этом рубается # почти весь спам. Единственно - метод неприменим на # реально загруженных MTA - т.к. в результате ему # приходится держать много открытых соединений. # но на офисе в сотню-две человек - шикарный метод. # # более сложный вариант, смотрите в статье по exim и # курьер имап. Т.к. там метод боле умный (просто правил # больше :), то можно и на более загруженные сервера ставить) warn # Cтавим дефолтовую задержку в 30 секунд set acl_m0 = 30s warn # ставим задержку в 0 секунд своим хостам и # дружественным сетям (соседняя контора :)) hosts = +relay_from_hosts:192.168.1.0/24:194.44.219.160/28 set acl_m0 = 0s warn # пишем в логи задержку (если оно вам надо) logwrite = Delay $acl_m0 for $sender_host_name \ [$sender_host_address] with HELO=$sender_helo_name. Mail \ from $sender_address to $local_part@$domain. delay = $acl_m0 # Проверка получателя в локальных доменах. # Eсли не проходит, то проверяется следующий ACL, # и если непрошёл и там - deny accept domains = +local_domains endpass message = "In my mailserver not stored this user" verify = recipient # Проверяем получателя в релейных доменах # Опять-таки если не проходит -> следующий ACL, # и если непрошёл и там - deny accept domains = +relay_to_domains endpass message = "main server not know how relay to this address" verify = recipient # Рубаем тех, кто в блэк-листах. Серваки перебираются # сверху вниз, если не хост не найден на первом, то # запрашивается второй, и т.д. Если не найден ни в одном # из списка - то почта пропускается. deny message = you are in blacklist: $dnslist_domain --> $dnslist_text dnslists = opm.blitzed.org : \ cbl.abuseat.org : \ # bl.csma.biz : \ dynablock.njabl.org # Разрешаем почту от доменов в списке relay_from_hosts accept hosts = +relay_from_hosts # Если неподошло ни одно правило - чувак явно ищет # открытый релей. Пшёл прочь. :) deny message = "relay not permitted" ############## # Проверка вложений acl_check_mime: deny message = Данной сообщение содержит опасное вложение condition = ${if match{$mime_filename}{\N(?i)\.zip$\N}} decode = default condition = ${if match{${run{/usr/bin/unzip -l $mime_decoded_filename}}}{\N(?i)\.(exe|com|vbs|bat|pif|scr|hta|js|cmd|chm|cpl|jsp|reg|vbe|lnk|dll|sys)\n\N}} log_message = forbidden attachment: filename=$mime_filename, content-type=$mime_content_type, recipients=$recipients deny message = Данной сообщение содержит опасное вложение condition = ${if match{$mime_filename}{\N(?i)\.rar$\N}} decode = default condition = ${if match{${run{/usr/bin/unrar l $mime_decoded_filename}}}{\N(?i)\.(exe|com|vbs|bat|pif|scr|hta|js|cmd|chm|cpl|jsp|reg|vbe|lnk|dll|sys)\n\N}} log_message = forbidden attachment: filename=$mime_filename, content-type=$mime_content_type, recipients=$recipients accept ############### # Тут идут ACL проверяющие содержимое (тело) письма. # Без них будут пропускаться все сообщения. acl_check_data: # Заблокированные аккаунты deny senders = /usr/local/etc/exim/deny_senders message = "DENY!!!" # Проверка на вирусы deny message = VIRUS found ($malware_name) malware = * accept ############### begin routers check_malware: driver = redirect condition = ${if def:h_X-Quarantine-Me-Malware: {1}{0}} headers_remove = Subject headers_add = Subject: [CLAMAV: $acl_m2] $h_Subject data = postmaster@tst-amo.pp.ua file_transport = address_file dnslookup: driver = dnslookup domains = ! +local_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more system_aliases: driver = redirect allow_fail allow_defer # data = ${lookup mysql{select alias from aliases where email='${quote_mysql:$local_part}' and domain='${quote_mysql:$domain}'}} data = ${lookup mysql{select alias from aliases where email='${quote_mysql:$local_part}' }} user = mailnull group = mail file_transport = address_file pipe_transport = address_pipe system_aliases2: driver = redirect allow_fail allow_defer data = ${lookup{$local_part}lsearch{/etc/aliases}} user = mailnull group = mail file_transport = address_file pipe_transport = address_pipe userforward: driver = redirect check_local_user no_verify no_expn check_ancestor file_transport = address_file pipe_transport = address_pipe reply_transport = address_reply # data = ${lookup mysql{select alias from aliases where email='${quote_mysql:$local_part}' and domain='${quote_mysql:$domain}'}} data = ${lookup mysql{select alias from aliases where email='${quote_mysql:$local_part}' }} userforward2: driver = redirect check_local_user file = $home/.forward no_verify no_expn check_ancestor file_transport = address_file pipe_transport = address_pipe reply_transport = address_reply condition = ${if exists{$home/.forward} {yes} {no} } localuser: driver = accept domains = ${lookup mysql{select domain from domains where domain='${domain}'}} local_parts = ${lookup mysql{select email from users where email='${local_part}'}} transport = local_delivery cannot_route_message = Unknown user localuser2: driver = accept check_local_user transport = local_delivery transport_current_directory = / cannot_route_message = Unknown user ################## begin transports remote_smtp: driver = smtp local_delivery: driver = appendfile maildir_format maildir_tag = ,S=$message_size # directory = /home/mail/$domain/$local_part directory = /var/vmail/$local_part/Maildir create_directory delivery_date_add envelope_to_add return_path_add group = mail mode = 0660 no_mode_fail_narrower address_pipe: driver = pipe return_output address_file: driver = appendfile delivery_date_add envelope_to_add return_path_add address_reply: driver = autoreply begin retry * * F,2h,15m; G,16h,1h,1.5; F,4d,6h begin rewrite ############### begin authenticators # Для системных пользователей через EXIM #LOGIN: # driver = plaintext # public_name = LOGIN # server_prompts = "Username:: : Password::" # server_condition = "${if pam {$auth1:$auth2}{yes}{no}}" # server_set_id = $auth1 #PLAIN: # driver = plaintext # public_name = PLAIN # server_condition = "${if pam {$auth2:$auth3}{yes}{no}}" # server_set_id = $auth2 # Аутентификация через dovecot dovecot_login: driver = dovecot public_name = LOGIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 dovecot_plain: driver = dovecot public_name = PLAIN server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 dovecot_cram_md5: driver = dovecot public_name = CRAM-MD5 server_socket = /var/run/dovecot/auth-client server_set_id = $auth1 ########################
5. Отключаем sendmail и включаем exim:
# ee /etc/rc.conf sendmail_enable="NONE" sendmail_submit_enable="NO" exim_enable="YES"
11. Отправим тестовое письмо.
# mail -s ‘First letter for sentec mail server’ info@sentec.ru This is test message! . EOT #
Посмотрим, что в лог-файле:
# tail /var/log/exim/mainlog
Вот примерная картинка, которую мы увидим в случае успеха:
2010-10-26 21:34:24 1PAnPk-0005al-AG <= root@mail.sentec.ru U=root P=local S=323 2010-10-26 21:34:24 1PAnPk-0005al-AG => info <info@sentec.ru> R=localuser T=local_delivery 2010-10-26 21:34:24 1PAnPk-0005al-AG Completed
12. Теперь надо сделать так, чтобы мы смогли получать почту с нашего сервера.
Для этого ставим проверенный и надежный POP/IMAP-сервер Dovecot (голубятня :)).
# cd /usr/ports/mail/dovecot # make install clean
13. Создадим….
14. Создадим SSL-сертификаты (если нужен шифрованный трафик, если нет – пропускаем). Информация об издателе будет взята из файла dovecot-openssl.cnf.
# mkdir -p /etc/ssl/certs # mkdir -p /etc/ssl/private # /usr/local/share/examples/dovecot/mkcert.sh # ls -l /etc/ssl/certs && ls -l /etc/ssl/private
15. Запускаем dovecot.
# /usr/local/etc/rc.d/dovecot start
16. Настраиваем почтового клиента на получение-отправку почты с помощью разрешенных протоколов (SMTP/POP3/IMAP). Не забудьте, что в /etc/rc.firewall должны быть разрешены соответствующие порты: 25, 110, 143, 993.
На этом — все.