Задача: установить и настроить Exim 4.69 (последния в портах версия на момент написания статьи).
Итак, имеем FreeBSD 6.3:
[root@mail /var/mail]# uname -mrs
FreeBSD 6.3-RELEASE i386
Включаем/выключаем нужные опции (посмотреть весь список можно в Makefile).
.if ${.CURDIR} == ${PORTSDIR}/mail/exim
WITH_MYSQL= yes
LOG_FILE_PATH?= syslog
WITH_CONTENT_SCAN= yes
WITH_DEFAULT_CHARSET?= koi8-r
WITHOUT_IPV6= yes
WITHOUT_NIS= yes
.endif
[root@mail /usr/ports/mail/exim]# make install clean
В /etc/rc.conf прописываем следующие строки:
sendmail_enable="NONE"
exim_enable="YES"
Меняем файл /etc/mail/mailer.conf на следующий:
[root@cisco3 /etc/mail]# cat 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
Файл /usr/local/etc/exim/configure:
# Основное имя хоста
primary_hostname = mx1.domain.ru
# Параметры подключения к БД в формате "хост/имя_базы/пользователь/пароль"
hide mysql_servers = db_host/exim/exim/PASSWORD
# Список локальных доменов
domainlist local_domains = ${lookup mysql{SELECT domain FROM domain WHERE domain='${domain}' AND active='1'}}
# Список доменов/хостов, для которых хост является входящим релеем
domainlist relay_to_domains = ${lookup mysql{SELECT domain FROM domain WHERE domain='${domain}' AND active='1'}}
# Список доменов/хостов, для которых хост является исходящим релеем. Т.е. без авторизации. hostlist relay_from_hosts = localhost : 127.0.0.0/8 : 192.168.0.0/16
# Включаем ограничения (будут объявлены ниже, в секции ACL)
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
# Пусть к сокету clamd (Предполагается что clamd уже установлен и настроен)
av_scanner = clamd:/var/run/clamav/clamd.sock
# Разрешаем всем клиентам использовать TLS
# Пути к TLS-сертификату и приватному ключу
tls_certificate = /etc/mail/ca.crt
tls_privatekey = /etc/mail/ca.key
# Список портов, которых будем слушать
daemon_smtp_ports = 25 : 465 : 587
# 465 порт нужен если хотим принимать почту с почтовых серверов Microsoft с использованием TLS.
tls_on_connect_ports = 465
# Имя домена, добавляемое ко всем адресам, идущим без "@" и имени домена. Например, для системных пользователей.
qualify_domain = mx1.domain.ru
# Запрещаем принимать почту с адресов типа user@[10.11.12.13]
allow_domain_literals = false
# Пользователь и группа, от которой работает Exim
exim_user = mailnull
exim_group = mail
never_users = root
# Эта опция заставляет делать обратный DNS-запрос для каждого входящего IP-адреса. Могут быть проблемы с некоторыми почтовыми серверами.
# На сколько задерживаем сообщение о доставке, если его не удалось доставить :)
ignore_bounce_errors_after = 2d
# Сколько хранить "замороженные" сообщения
timeout_frozen_after = 7d
# Опция повышает производительность разбивая директорию spool на поддиректории.
split_spool_directory = true
# Почта с этих хостов/доменов будет приниматься несмотря на ошибки в HELO/EHLO
helo_accept_junk_hosts = 192.168.0.0/16
# Через какое время повторять отправку "замороженных" сообщений
# Максимальное число одновременных соединений
# Максимальное число сообщений, принимаемых за одну tcp-сессию
smtp_accept_max_per_connection = 50
# Максимальное число соединений с одного хоста/домена
smtp_accept_max_per_host = 20
# Максимальное число параллельных процессов доставки
# Ограничение на размер части письма, вкладываемого в сообщение об ошибке
# Максимальный размер сообщения
# Не писать дату и время в логи. В нашем случае их пишет syslogd
# Описание тех самых ограничений, которые объявлены выше
begin acl
acl_check_rcpt:
# Разрешаем сообщения с локалхоста не по TCP/IP
# Запрещаем использование нестандартных символов в адресах локальных получателей
deny message = Restricted characters in address
domains = +local_domains
local_parts = ^[.] : ^.*[@%!/|]
# Запрещаем использование нестандартных символов в адресах удаленных получателей
deny message = Restricted characters in address
domains = !+local_domains
local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
# Разрешаем почту на postmaster без проверок
accept local_parts = postmaster
domains = +local_domains
# Включаем проверку отправителя
# Запрещаем соединения с теми, кто не предоставляет приветствие по RFC (HELO/EHLO)
deny message = "HELO/EHLO required by RFC"
condition = ${if eq{$sender_helo_name}{}{yes}{no}}
# Разрешаем аутентифицированные соединения
# Запрещаем соединения с теми, кто подставляет в приветствие IP-адрес вместо имени
deny message = "Do not put IP address in HELO!"
hosts = * : !+relay_from_hosts
condition = ${if eq{$sender_helo_name}{$sender_host_address}{true}{false}}
# Запрещаем соединения с теми, кто подставляет IP-адрес нашего сервера в приветствии
deny condition = ${if eq{$sender_helo_name}{$interface_address}{yes}{no}}
hosts = !127.0.0.1 : !localhost : *
message = "Do not put my IP address in HELO!"
# Запрещаем соединения с теми, у кого в приветствии только цифры
deny condition = ${if match{$sender_helo_name}{\N^\d+$\N}{yes}{no}}
hosts = !127.0.0.1 : !localhost : *
message = "There is only numbers in HELO!"
# Запрещаем соединения с теми, у кого в имени хоста присутствуют adsl, dialup и т.д.
deny message = "Bad hostname!"
condition = ${if match{$sender_host_name}{adsl|dialup|pool|peer|dhcp} {yes}{no}}
# Задержка установления соединения. Как один из методов борьбы со спамом.
warn
set acl_m0 = 30s
# Убираем задержку для "своих" доменов/хостов
warn
hosts = +relay_from_hosts
set acl_m0 = 0s
# Проверка на существование пользователей в локальных доменах
accept domains = +local_domains
endpass
message = "User unknown"
verify = recipient
# Проверка на существование пользователей в релейных доменах
accept domains = +relay_to_domains
endpass
message = "Not routeable address"
verify = recipient
# Если не подошло ни под одно правило - скорее всего ищут открытый релей
deny message = "There is no open relay"
acl_check_data:
# Запрещаем сообщения содержащие вирусы
deny malware = *
message = This message contains a virus ($malware_name).
# Принимаем сообщение
# Поиск маршрута к хосту в DNS
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 goto FROM alias WHERE address='${quote_mysql:$local_part@$domain}' OR address='${quote_mysql:@$domain}'}}
# Включаем доставку по SMTP на удаленные хосты
remote_smtp:
driver = smtp
# Доставка до локальных получателей
mysql_delivery:
driver = appendfile
check_string = ""
create_directory
delivery_date_add
# Т.к. мы строим мультидоменный почтовый сервер, то и почта будет храниться в каталогах вида /var/mail/exim/domain.ru/user@domain.ru
directory = ${lookup mysql{SELECT CONCAT('/var/mail/exim/', `domain`, '/', `maildir`) FROM `mailbox` WHERE `username`='${local_part}@${domain}'}}
directory_mode = 770
envelope_to_add
group = mail
maildir_format
maildir_tag = ,S=$message_size
message_prefix = ""
message_suffix = ""
mode = 0600
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
# Описание типа аутентификации plain
PLAIN:
driver = plaintext
server_set_id = $auth2
server_prompts = :
server_condition = ${lookup mysql{SELECT username FROM mailbox WHERE username = '${quote_mysql:$1}' AND password = '${quote_mysql:$2}'}{yes}{no}
#EOF
Далее создаем базу exim на локальном или удаленном хосте при помощи этого дампа (дамп с сайта lissyara.su):
# Не забудьте поменять занчения localhost, user, password на свои :)
--
-- БД: `exim`
--
USE mysql;
INSERT INTO `user` (`Host`, `User`, `Password`)
VALUES ('localhost','exim',password('exim'));
INSERT INTO `db` (`Host`, `Db`, `User`, `Select_priv`)
VALUES ('localhost','exim','exim','Y');
FLUSH PRIVILEGES;
GRANT USAGE ON exim.* TO exim@localhost;
GRANT SELECT, INSERT, DELETE, UPDATE ON exim.* TO exim@localhost;
CREATE DATABASE `exim`;
USE `exim`;
-- --------------------------------------------------------
--
-- Структура таблицы `alias`
--
CREATE TABLE `alias` (
`address` varchar(255) NOT NULL default '',
`goto` text NOT NULL,
`domain` varchar(255) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`address`),
KEY `address` (`address`)
) TYPE=MyISAM COMMENT='Aliases';
-- --------------------------------------------------------
--
-- Структура таблицы `domain`
--
CREATE TABLE `domain` (
`domain` varchar(255) NOT NULL default '',
`description` varchar(255) NOT NULL default '',
`aliases` int(10) NOT NULL default '0',
`mailboxes` int(10) NOT NULL default '0',
`maxquota` int(10) NOT NULL default '0',
`transport` varchar(255) default NULL,
`backupmx` tinyint(1) NOT NULL default '0',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`domain`),
KEY `domain` (`domain`)
) TYPE=MyISAM COMMENT='Domains';
-- --------------------------------------------------------
--
-- Структура таблицы `mailbox`
--
CREATE TABLE `mailbox` (
`username` varchar(255) NOT NULL default '',
`password` varchar(255) NOT NULL default '',
`name` varchar(255) NOT NULL default '',
`maildir` varchar(255) NOT NULL default '',
`quota` int(10) NOT NULL default '0',
`domain` varchar(255) NOT NULL default '',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`modified` datetime NOT NULL default '0000-00-00 00:00:00',
`active` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`username`),
KEY `username` (`username`)
) TYPE=MyISAM COMMENT='Mailboxes';
Осталось заполнить таблицы базы и можно запускать Exim:
[root@mail ~]# /usr/local/etc/rc.d/exim start
Итог: Установлен и настроен почтовый сервер Exim 4.69 с возможностью обслуживания множества доменов одновременно. Настроена проверка сообщений на вирусы с помощью clamav. Почта сохраняется в каталоги вида domain.ru/username@domain.ru. Все домены, пользователи и алиасы хранятся в БД MySQL.
Используемая литература:
PS: Возможно что-то недописал или забыл. В ближайшее время отредактирую.