Кнопки



Яндекс цитирования


Главная » Документы » Как ставить Exim+dovecot

Как ставить Exim+dovecot


Приветствую! Теперь на sys.net.ru  будут публикации не только о Linux, но и о BSD-системах. Я, как закоренелый BSD-шник, постараюсь периодически наполнять сайт свежими материалами... Итак, мой дебют - почтовый сервер.

Потребовался простейший почтовый сервер с поддержкой нескольких доменов...

Потребовался простейший почтовый сервер с поддержкой нескольких доменов на базе FreeBSD 6.1 и последовав примеру хостера, я решил сделать связку exim+dovecot, использовав для аутентификации mysql. Как руководство для себя использовал http://www.opennet.ru/docs/134.shtml , однако конфигурационные файлы указанного и моего приемра различаются, т.к. exim поднялся до версии 4.60, а dovecot - до 1.0.b3 и мне пришлось кое-что править ручками. Данная инструкция позволяет быстро собрать 100% работающий почтовый сервер на базе FreeBSD из родных портов этой системы с поддержкой протоколов smtp, pop3 и imap с хранением учетных записей пользователей в базе данных mysql, а почты - в папке /var/mail.

Итак, приступим.

1. Подготовка


Для работы с сервером баз данных есть необходимое условие - чтобы в системе был установлен mysql-client, т.к. и exim и dovecot используют его библиотеки. Сам сервер может находиться где угодно. Необходимо создать базу данных и, из соображений безопасности, завести отдельного пользователся для это БД:
CREATE DATABASE mail;
GRANT ALL PRIVILEGES ON mail.* TO mailuser@localhost IDENTIFIED BY 'my_password';

Создавать таблицы мы будем после компиляции серверов.

Также для компиляции потребуется gmake. Впрочем, если Вы его не установите, система портов сама его достанет и установит;).

2. Компиляция exim


Поскольку устанавливать серверы мы будем из портов, то, соответственно, они должны присутствовать в Вашей системе. В портах уже присутствует exim-mysql, поэтому компилировать будем именно его:

cd /usr/ports/mail/exim-mysql
make&&make install

Не забудьте прописать в /etc/rc.conf строку exim_enable="YES", чтобы он стартовал при запуске системы.

3. Компиляция dovecot


Здесь нет ничего особенного, за исключением того, что перейдя в /usr/ports/mail/dovecot и набрав команду make, выскочит запрос о том, с какими опциями мы захотим скомпилировать dovecot? Лично я отказался от всего кроме mysql. Если Вы выбрали ошибочную конфигурацию и при этом умудрились нажать OK, то этот процесс можно прервать, нажав Ctrl+C... Снова make... Но что это??? На этот раз нас ничего не спросили??? Дело в том, что выбранные в первый раз опции сохранились в файле /var/db/ports/dovecot/options и если удалить этот файл - при попытке компиляции снова будет задан вопрос. Либо можно набрать  make rmconfig - результат будет тот же.

cd /usr/ports/mail/dovecotmake -DWITH_MYSQL -DWITHOUT_VPOPMAIL -DWITHOUT_LDAP && make -DWITH_MYSQL -DWITHOUT_VPOPMAIL -DWITHOUT_LDAP install
После установки будет предложено создать пользователя и группу dovecot - соглашайтесь, т.к. процесс авторизации будет выполняться именно этим пользователем.

4. База данных


Пример базы взят из указанного выше примера http://www.opennet.ru/docs/134.shtml. Ниже - дамп базы данных, отличие от примера состоит в uid и gid, которые прописаны в CREATE TABLE таблицы users. Дело в том, что uid, указанный в примере (1003) не совпадает с uid, под которыми создается пользователь exim'а (26). Именно с правами доступа могут быть связаны некоторые сложности работы сервера.

CREATE TABLE `aliases` (
  `local_part` varchar(64) NOT NULL default '',
  `domain` varchar(128) NOT NULL default 'bsd.home',
  `recipients` text,
  PRIMARY KEY  (`local_part`,`domain`)
) ENGINE=MyISAM;

INSERT INTO aliases VALUES ('postmaster', 'bsd.home', 'admin');
INSERT INTO aliases VALUES ('mailer-daemon', 'bsd.home', 'postmaster');
INSERT INTO aliases VALUES ('root', 'bsd.home', 'postmaster');
INSERT INTO aliases VALUES ('bin', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('daemon', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('sync', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('mail', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('pop', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('uucp', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('ftp', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('nobody', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('www', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('named', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('postgres', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('mysql', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('squid', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('operator', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('abuse', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('hostmaster', 'bsd.home', 'root');
INSERT INTO aliases VALUES ('webmaster', 'bsd.home', 'root');

CREATE TABLE `domains` (
  `domain` varchar(128) NOT NULL default '',
  `type` enum('LOCAL','RELAY','VIRTUAL') default 'LOCAL',
  PRIMARY KEY  (`domain`)
) ENGINE=MyISAM;

INSERT INTO domains VALUES ('bsd.home', 'LOCAL');

CREATE TABLE `userforward` (
  `local_part` varchar(64) NOT NULL default '',
  `domain` varchar(128) NOT NULL default '',
  `recipients` text,
  PRIMARY KEY  (`local_part`,`domain`)
) ENGINE=MyISAM;

CREATE TABLE `users` (
  `login` varchar(64) NOT NULL default '',
  `name` varchar(128) NOT NULL default '',
  `password` varchar(64) NOT NULL default '',
  `decrypt` varchar(64) NOT NULL default '',
  `uid` int(10) unsigned default '26',
  `gid` int(10) unsigned default '6',
  `domain` varchar(128) NOT NULL default 'bsd.home',
  `quota` tinyint(4) default '0',
  `status` enum('0','1') default '1',
  PRIMARY KEY  (`login`,`domain`)
) ENGINE=MyISAM;

INSERT INTO users (login,name,password,decrypt) VALUES ('admin','Администратор',encrypt('my_password'),'my_password');

5. Конфигурация exim


Файл /usr/local/etc/exim/configure

primary_hostname = bsd.home
domainlist local_domains = ${lookup mysql{SELECT domain FROM domains WHERE domain='${domain}' AND (type='LOCAL' OR type='VIRTUAL')}}
domainlist relay_to_domains = ${lookup mysql{SELECT domain FROM domains WHERE domain='${domain}' AND type='RELAY'}}
hostlist   relay_from_hosts = localhost
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
qualify_domain = bsd.home
qualify_recipient = bsd.home
exim_user = mailnull
exim_group = mail
never_users = root
host_lookup = *
rfc1413_hosts = *
rfc1413_query_timeout = 30s
ignore_bounce_errors_after = 2d
timeout_frozen_after = 7d
hide mysql_servers = localhost/mail/mailuser/my_password
begin acl
acl_check_rcpt:
accept  hosts = :
deny    message       = Restricted characters in address
    domains       = +local_domains
    local_parts   = ^[.] : ^.*[@%!/|]
deny    message       = Restricted characters in address
          domains       = !+local_domains
          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
 accept  local_parts   = postmaster
          domains       = +local_domains
  require verify        = sender
  accept  hosts         = +relay_from_hosts
          control       = submission
  accept  authenticated = *
          control       = submission
  accept  domains       = +local_domains
          endpass
          verify        = recipient
  accept  domains       = +relay_to_domains
          endpass
          verify        = recipient
  deny    message       = relay not permitted
acl_check_data:
  accept

begin routers
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 recipients FROM aliases WHERE local_part='${local_part}' AND domain='${domain}'}}
userforward:
    driver = redirect
    allow_fail
    allow_defer
    data = ${lookup mysql{SELECT recipients FROM userforward WHERE local_part='${local_part}' AND domain='${domain}'}}

virtual_localuser:
    driver = accept
    domains = ${lookup mysql{SELECT domain from domains WHERE domain='${domain}'}}
    local_parts = ${lookup mysql{SELECT login from users WHERE login='${local_part}' AND domain='${domain}'}}
    transport = local_delivery
localuser:
  driver = accept
  check_local_user
  transport = local_delivery
  cannot_route_message = Unknown user
begin transports
remote_smtp:
  driver = smtp

local_delivery:
    driver = appendfile
    check_string = ""
    create_directory
    delivery_date_add
    directory = /var/mail/$domain/$local_part
    directory_mode = 770
    envelope_to_add
    group = mail
    maildir_format
    maildir_tag = ,S=$message_size
    message_prefix = ""
    message_suffix = ""
    mode = 0660
    quota = ${lookup mysql{SELECT quota FROM users WHERE login='${local_part}' AND domain='${domain}'}{${value}M}}
    quota_size_regex = S=(\d+)$
    quota_warn_threshold = 75%
    return_path_add
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

auth_plain:
    driver = plaintext
    public_name = PLAIN
    server_condition = ${lookup mysql{SELECT login FROM users WHERE login = '${quote_mysql:${local_part:$2}}' AND domain = '${quote_mysql:${domain:$2}}' AND decrypt = '${quote_mysql:$3}' AND status = '1'}{yes}{no}}
    server_prompts = :
    server_set_id = $2

auth_login:
    driver = plaintext
    public_name = LOGIN
    server_condition = ${lookup mysql{SELECT login FROM users WHERE login = '${quote_mysql:${local_part:$1}}'  AND domain = '${quote_mysql:${domain:$1}}' AND decrypt = '${quote_mysql:$2}' AND status = '1'}{yes}{no}}
    server_prompts = Username:: : Password::
    server_set_id = $1

auth_cram_md5:
    driver = cram_md5
    public_name = CRAM-MD5
    server_secret = ${lookup mysql{SELECT decrypt FROM users WHERE login = '${quote_mysql:${local_part:$1}}' AND domain = '${quote_mysql:${domain:$1}}' AND status = '1'}{$value}fail}
    server_set_id = $1

6. Конфигурация dovecot


Файл /usr/local/etc/dovecot.conf

base_dir = /var/run/dovecot/
protocols = imap pop3
ssl_disable = yes    #если нам не нужен SSL
disable_plaintext_auth = no #Иначе не пустит на сервер с простой аутентификацией
log_path = /var/log/dovecot
log_timestamp = "%b %d %H:%M:%S "
syslog_facility = mail
login_user = dovecot
login_process_size = 64
login_greeting = Dovecot at mail.bsd.home is ready. PREVED! ;)
verbose_proctitle = yes
first_valid_uid = 25
first_valid_gid = 6
mail_extra_groups = mail
default_mail_env = maildir:/var/mail/%d/%n
umask = 0007 # Эту опцию я опишу ниже
protocol imap {
    login_executable = /usr/local/libexec/dovecot/imap-login
    mail_executable = /usr/local/libexec/dovecot/imap
    imap_client_workarounds = delay-newmail outlook-idle netscape-eoh tb-extra-mailbox-sep
}
protocol pop3 {
    login_executable = /usr/local/libexec/dovecot/pop3-login
    mail_executable = /usr/local/libexec/dovecot/pop3
    pop3_uidl_format = %08Xu%08Xv
    pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
}
auth_executable = /usr/local/libexec/dovecot/dovecot-auth
auth default {
    mechanisms = plain
    passdb pam {
    }
    passdb sql {
        args = /usr/local/etc/dovecot-mysql.conf
    }
    userdb passwd {
    }
    userdb sql {
        args = /usr/local/etc/dovecot-mysql.conf
    }
    user = root
}

Опция umask задает права на доступ к файлам и папкам, которые создает dovecot. Если оставить эту опцию по умолчанию - будут создаваться папки с разрешением rwx------, а это не есть гуд, надо еще и членам группы mail дать достьуп туда.

login_greeting можете написать любой, хоть "Эксчендж", хоть "ПРЕВЕД МЕДВЕД!" - это сообщение, которое будет выдаваться сервером при соединении.

default_mail_env я заменил - теперь почтовый ящик физически находится в /var/mail/bsd.home/admin/

Файл /usr/local/etc/dovecot-mysql.conf

driver = mysql
default_pass_scheme = CRYPT
connect = host=localhost dbname=mail user=mailuser password=my_password
password_query = SELECT password FROM users WHERE login = '%n' AND domain = '%d' AND status = '1'
user_query = SELECT uid, gid FROM users WHERE login = '%n' AND domain = '%d'

7. Финал


Теперь самое время проверить работоспособность сервера... Вы не забыли указать в своем DNS зоны и MX-записи? ;)
Для быстрого создания пользователей в пределах одного домена я сделал скрипт на perl, который требует только наличие в системе консольного mysql-клиента. При этом предполагается, что домен bsd.home уже добавлен в таблицу domains.

#!/usr/local/bin/perl

$email=@ARGV[0];
$pass=@ARGV[1];
$dbhost="localhost";
$dbname="mail";
$dbuser="mailuser";
$dbpass="letter";
$query="";

$email=~/([-a-z0-9]+)\@(.+)/;
$login=$1;
$domain=$2;
$query.="INSERT INTO users VALUES(\"$login\",'',ENCRYPT(\"$pass\"),\"$pass\",26,26,\"$domain\",'0','1');";
open(SQL,"|/usr/local/bin/mysql -h $dbhost -u $dbuser -p$dbpass $dbname")||die "Cannot open pipe to mysql";
print SQL $query;
close SQL;

Итак, добавили пользователей, можно пробовать. Запустите серверы командами /usr/local/etc/rc.d/exim.sh start и /usr/local/etc/rc.d/dovecot start . Кроме отладочных сообщений и предупреждений ничего более не должно выводиться. Проверьте, слушают-ли серверы порты:

#sockstat -4
USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS
dovecot  pop3-login 1464  0  tcp4   *:110                 *:*
...
dovecot  imap-login 1181  0  tcp4   *:143                 *:*
...
mailnull exim-4.60- 1125  6  tcp4   *:25                  *:*

Проверим, отправляется-ли почта:

-bash2-2.05b$ telnet 127.0.0.1 25
Trying 127.0.0.1...
Connected to localhost.home.
Escape character is '^]'.
220 bsd.home ESMTP Exim 4.60 Mon, 23 Oct 2006 17:59:40 +0500
HELO bsd.home
250 bsd.home Hello localhost.home [127.0.0.1]
MAIL FROM: admin@bsd.homeadmin@bsd.home
250 OK
RCPT TO: admin@bsd.homeadmin@bsd.home
250 Accepted
DATA
354 Enter message, ending with "." on a line by itself
Subject: Hello, there!
Helo, it's a test
PREVED!
.
250 OK id=1GbzPa-0000Oi-EZ
QUIT
221 bsd.home closing connection
Connection closed by foreign host.

Да, отправилось. Теперь попробуем принять по протоколу POP3:

-bash2-2.05b$ telnet 127.0.0.1 110
Trying 127.0.0.1...
Connected to localhost.home.
Escape character is '^]'.
+OK Dovecot at mail.bsd.home is ready. PREVED! ;)
USER admin@bsd.homeadmin@bsd.home
+OK
PASS my_password
+OK Logged in.
STAT
+OK 1 481
RETR 1
+OK 481 octets
Return-path: < admin@bsd.homeadmin@bsd.home>
Envelope-to: admin@bsd.homeadmin@bsd.home
Delivery-date: Mon, 23 Oct 2006 18:00:35 +0500
Received: from localhost.home ([127.0.0.1] helo=bsd.home)
        by bsd.home with smtp (Exim 4.60 (FreeBSD))
        (envelope-from < admin@bsd.homeadmin@bsd.home>)
        id 1GbzPa-0000Oi-EZ
        for admin@bsd.homeadmin@bsd.home; Mon, 23 Oct 2006 18:00:34 +0500
Subject: Hello, there!
Message-Id: < E1GbzPa-0000Oi-EZ@bsd.homeE1GbzPa-0000Oi-EZ@bsd.home>
From: admin@bsd.homeadmin@bsd.home
Date: Mon, 23 Oct 2006 18:00:33 +0500

Helo, it's a test
PREVED!
.
QUIT
+OK Logging out.
Connection closed by foreign host.

Принято. Попробуйте поработать с почтой по протоколу IMAP, например, через Mozilla Thunderbird.

Успехов!

8. Благодарности

 Благодарю c0re за рецензию статьи и полезные советы (20.11.2006).