Настройка связки Postfix, Courier-Imap и LDAP

.

Оригинал: http://www.unix.nordcomp.ru/articles.html?page=2&id=12


Введение.
---------

Целью данного HOW-TO является создание легко управляемой и
масштабируемой почтовой системы, все записи о пользователях которой
хранятся в LDAP.

Описываемый процесс установки производился на Linux Mandrake 9.1.
Сразу хотелось бы отметить, что поставляемые с этим дистрибутивом
rpm-пакеты postfix'а и courier-imap'а не подойдут. К сожалению, после
многих попыток было обнаружено, что настроить их на нормальную работу
по данной схеме невозможно. Симптомы следующие: Postfix в логах
ругался, что не может выложить почту в Maildir пользователя, якобы
доступ на запись запрещён, а courier-imap в свою очередь всегда
отказывал в доступе, ссылаясь на неправильный пароль. После установки
postfix и courier-imap из сырцов с абсолютно той же конфигурацией
вышеуказаные проблемы исчезли. Оставим это на совести сборщиков
дистрибутива и перейдём к описанию процесса настройки.


OpenLDAP


Установка

OpenLDAP был установлен из rpm'ов, поставляемых с дистрибутивом и был
признан годным к употреблению. При желании можно было собрать также из
сырцов, но так как данная сборка работала вполне корректно, то я
оставил её как есть. В целом потребовались следующие пакеты:

· openldap-2.0.27-5.3md
· openldap-guide-2.0.27-5.3m
· openldap-clients-2.0.27-5.3md
· openldap-servers-2.0.27-5.3md
· libldap2-2.0.27-5.3mdk
· libldap2-devel-2.0.27-5.3mdk
· libldap2-devel-static-2.0.27-5.3mdk

development-пакеты openldap потребуются при сборке postfix из сырцов.


Конфигурация

/etc/openldap/slapd.conf - конфигурационный файл сервиса slapd

# Включите данные схемы
include /usr/share/openldap/schema/core.schema
include /usr/share/openldap/schema/cosine.schema
include /usr/share/openldap/schema/corba.schema
include /usr/share/openldap/schema/inetorgperson.schema
include /usr/share/openldap/schema/nis.schema
include /usr/share/openldap/schema/openldap.schema
include /usr/share/openldap/schema/qmail.schema
# Последняя схема была найдена среди исходников courier-imap, и я посчитал
# необходимым включить её в slapd.conf.
include /etc/openldap/schema/authldap.schema
pidfile /var/run/ldap/slapd.pid
argsfile /var/run/ldap/slapd.args
modulepath /usr/lib/openldap
database ldbm
suffix "dc=home,dc=ru"
rootdn "cn=root,dc=home,dc=ru"
# Пароль rootpw лучше всего указывать в зашифрованном виде.
# Для генерации шифрованного пароля используйте утилиту slappasswd
# Например: slappaswd -h {MD5}
rootpw {MD5}6Q2kox8osDMVzi5zSKI6YQ==
directory /var/lib/ldap
index objectClass,uid,uidNumber,gidNumber eq
index cn,mail,surname,givenname eq,subinitial
# logging
loglevel 256
# Basic ACL
access to attr=userPassword
by self write
by anonymous auth
by dn="cn=courier,ou=daemons,dc=home,dc=ru" read
by * none
access to attr=accountStatus
by dn="cn=courier,ou=daemons,dc=home,dc=ru" read
by dn="cn=postfix,ou=daemons,dc=home,dc=ru" read
access to *
by * read


В принципе это основные моменты конфигурационного файла. Можно
несколько усложнить конфигурацию: настроить более сложные правила
доступа к LDAP-записям и т.д. Но это можно сделать позднее при
необходимости. Главное, что текущей настройки достаточно для
нормального запуска OpenLDAP. Если возникнут какие-либо проблемы,
внимательно изучите логи, обычно там находится вся необходимая
информация.

Запускается ldap простой командой: service ldap start

В сборке от Mandrake OpenLDAP запускается под непривелегированным
пользователем ldap. Это следует учесть, если вы будете собирать
OpenLDAP из сырцов, обязательно создайте пользователя и группу ldap,
дайте этому пользователю права на запись в каталог /var/lib/ldap и
запускайте демон slapd с параметрами: -u ldap -g ldap. Запускать slapd
от суперпользователя, как говорит Григорий, "дурной тон"...

/etc/ldap.conf

host 127.0.0.1
base dc=home,dc=ru
ldap_version 3
rootbinddn cn=root,dc=home,dc=ru
scope one
pam_filter objectclass=posixAccount
pam_login_attribute uid
pam_member_attribute gid
pam_password crypt
nss_base_passwd ou=Users,dc=home,dc=ru?one
nss_base_shadow ou=Users,dc=home,dc=ru?one
ssl off


Данный файл является конфигурацией ldap-клиента.


Добавление записей в LDAP

В LDAP будут хранится записи структуры каталога и пользовательских
записей. Всё это можно представить в виде древовидной структуры:

dc=home,dc=ru-+
|
+- ou = users -+
| |
| +- uid = crux
|
+- ou = mailusers -+
| |
| +- uid = crux
|
+- ou = daemons -+
|
+- cn = postfix
|
+- cn = courier


Т.е. имеется главный контейнер "home.ru". Далее выделяются контейнеры
ou=users - где будут хранится описания пользователей (типа адресной
книги), ou=mailusers - вся информация по почтовым пользователям
(адреса, мыло, локальное хранилище почты и т.д.), ou=daemons -
ldap-пользователи сервисов postfix и courier-imap (именно под данными
пользователями указанные сервисы будут подключаться к ldap-серверу для
получения необходимой им информации). В принципе, можно было обойтись
без контейнера mailusers, а всю необходимую информацию включить в
аттрибуты пользователей контейнера ou=users. Но в будущем мне может
потребоваться помимо пользователей почты включить также пользователей
Samba, Squid. При миграции аккаунтов возможны совпадения логинов
различных пользователей, также для некоторых пользователей было бы
желательно иметь различные пароли для разных сервисов. Поэтому такая
схема (может быть некорректная с точки зрения теории) достаточно гибка
и позволит мне без проблем проводить миграцию пользовательских учётных
записей любых сервисов в LDAP.

Переложим данную структуру в ldif-файлы:

Базовое дерево:

#base.ldif
dn: dc=home,dc=ru
objectClass: dcObject
dc: home
dn: ou=Users,dc=home,dc=ru
objectClass: organizationalUnit
ou: Users
description: Home Users
dn: ou=mailusers, dc=home, dc=ru
objectclass: top
objectclass: organizationalunit
ou: mailusers
description: users with mailaccounts at my home.
dn: ou=daemons, dc=home, dc=ru
objectclass: top
objectclass: organizationalunit
ou: daemons
description: daemons thats connect to LDAP


Добавим пользователей:

#users.ldif
dn: uid=crux,ou=Users,dc=home,dc=ru
uid: crux
cn: Lettiev V.V.
cn: Vladimir Lettiev
sn: Admin
givenName: Vladimir
title: Systems Administrator
mail: [1]crux@home.ru
telephoneNumber: 24-55-07
objectClass: Person
objectClass: OrganizationalPerson
objectClass: inetOrgPerson
dn: uid=crux,ou=mailusers,dc=home,dc=ru
uid: crux
cn: Lettiev V.V.
mail: [2]Vladimir.Lettiev@home.ru
mail: [3]crux@home.ru
mail: [4]root@home.ru
uidNumber: 1000
gidNumber: 1000
mailHost: mail.home.ru
homeDirectory: /var/imap/home/crux
mailMessageStore: /var/imap/home/crux/Maildir
mailQuota: 200000000S, 20000C
mailbox: crux/Maildir/
objectClass: qmailuser
objectClass: couriermailaccount
userPassword: {MD5}d+HKEvhLk8ZqwCRTrp574g==
accountStatus: active
mailForwardingAddress: [5]crux@home.ru
dn: cn=postfix,ou=daemons,dc=home,dc=ru
objectClass: top
objectClass: person
cn: postfix
sn: postfix
userPassword: {crypt}lT3u7UFC2hdWA
dn: cn=courier,ou=daemons,dc=home,dc=ru
objectClass: top
objectClass: person
cn: courier
sn: courier
userPassword: {crypt}hjUyfu886SJhA


Теперь необходимо записать эти данные в LDAP-каталог. Выполнятеся это
следующей последовательностью команд:

# ldapadd -W -x -D "cn=root,dc=home,dc=ru" -f base.ldif
# ldapadd -W -x -D "cn=root,dc=home,dc=ru" -f users.ldif


Если всё прошло гладко и сообщений об ошибках не поступило, то можно
переходить к следующему этапу.


Postfix

MTA Postfix считается одним из самых безопасных, надёжным и простым в
настройке почтовым сервисом. В данном примере используется версия 2.0.10.


Установка

$ tar -xzf postfix-2.0.10.tar.gz
$ cd postfix-2.0.10


Соберём makefiles с поддержкой LDAP ( devel-файлы LDAP должны
находится в /usr/include, а библиотеки в /usr/lib )

$ make makefiles CCARGS="-I/usr/include -DHAS_LDAP"
AUXLIBS="-L/usr/lib -lldap -L/usr/lib -llber"
$ make


Теперь надо создать пользователя postfix и группу postdrop (или
убедится, что они уже есть)

# groupadd postdrop
# adduser -s /bin/false -G postdrop -d /var/spool/postfix postfix


Теперь можно выполнить инсталляцию postfix

# make install


По ходу инсталяции будут задаваться вопросы, касаемые местоположения
разных компонентов системы, фактически можно просто нажимать Enter,
всё что предлагается по умолчанию вполне удобно.


Конфигурация

/etc/postfix/main.cf

queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/libexec/postfix
mail_owner = postfix
# Имя нашего MAIL хоста
myhostname = mail.home.ru
mydomain = home.ru
myorigin = $mydomain
inet_interfaces = all
# Получать почту для доменов mail.home.ru и home.ru
mydestination = $myhostname, $mydomain
unknown_local_recipient_reject_code = 450
# Сеть, которой мы доверяем
mynetworks = 192.168.1.0/24, 127.0.0.0/8
biff = no

# Доставка для виртуальных доменов
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps
message_size_limit = 10280000
mailbox_size_limit = 20480000

# Вся почта пользователей будет принадлежать одному пользователю
# (например, vmail), с uid=1001 и gid=1001
virtual_uid_maps = static:1001
virtual_gid_maps = static:1001
virtual_recipient_maps = ldap:ldapsource
virtual_mailbox_size_limit = ldap:ldapquota
virtual_minimum_uid = 500

# Корневая папка, внутри которой будет хранится вся почта пользователей
virtual_mailbox_base =/var/imap/home
virtual_result_attribute = mailbox
virtual_mailbox_maps = ldap:ldapsource
virtual_maildir_extended = yes

ldapquota_timeout = 10
ldapquota_server_host = localhost
ldapquota_search_base = ou=mailusers,dc=home,dc=ru
ldapqouta_server_port = 389
ldapqouta_domain = home.ru, mail.home.ru
ldapquota_query_filter = (&(mail=%s)(accountstatus=active))
ldapquota_result_attribute = mailquota

# Параметры подключения к LDAP (юзер и пароль)
ldapquota_bind = yes
ldapquota_bind_dn = cn=postfix,ou=daemons,dc=home,dc=ru
ldapquota_bind_pw = secretpass
ldapsource_timeout = 10
ldapsource_server_host = localhost
ldapsource_search_base = ou=mailusers,dc=home,dc=ru
ldapsource_server_port = 389
ldapsource_domain = home.ru, mail.home.ru
ldapsource_query_filter = (&(mail=%s)(accountstatus=active))
ldapsource_result_attribute = mailbox

# Параметры подключения к LDAP (юзер и пароль)
ldapsource_bind = yes
ldapsource_bind_dn = cn=postfix,dc=home,dc=ru
ldapsource_bind_pw = secretpass
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) (Mandrake Linux)
debug_peer_level = 4
debugger_command =
PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
xxgdb $daemon_directory/$process_name $process_id & sleep 5
delay_warning_time = 4
sendmail_path = /usr/sbin/sendmail
newaliases_path = /usr/bin/newaliases
mailq_path = /usr/bin/mailq
setgid_group = postdrop
manpage_directory = /usr/local/man


В данной конфигурации postfix будет доставлять почту виртуальным
пользователям, т.е. фактически пользователи не существуют в системе,
они присутствуют лишь в LDAP. Местоположение Maildir какалога
определяется атрибутом mailbox пользователя. Вся почта пользователей
будет принадлежать одному реальному пользователю
vmail(uid=1001,gid=1001). Почтовая квота также определяется из
атрибута пользователя mailQuota. Можно также было производить поиск
alias'ов из LDAP-каталога, но в данном случае это излишне, потому что
alias'ы прописываются пользователям в качестве дополнительных
атрибутов mail.

Можно проверить конфигурацию postfix (команда: postfix check), если
же не появились сообщения об ошибках, то это значит, что всё ок и
можно запустить Postfix (команда postfix start).


Тестирование

Необходимо создать пользователя vmail и хранилище почты:

# mkdir -p -m 0700 /var/imap/home
# addgroup -g 1001 vmail
# adduser -u 1001 -s /bin/false -d /var/imap/home vmail
# chown -R vmail.vmail /var/imap


А также создать Maildir-каталог пользователю crux

# mkdir -m 0700 /var/imap/home/crux
# maildirmake /var/imap/home/crux/Maildir
# chown -R vmail.vmail /var/imap/home/crux


Если у вас нет утилитки maildirmake, то это не проблема, под
созданием Maildir каталога, имеется ввиду создание каталогов:

<userHomeDir>/Maildir
<userHomeDir>/Maildir/cur
<userHomeDir>/Maildir/new
<userHomeDir>/Maildir/tmp


Права на все каталоги - 0700.

Вообще, на будущее, для простого создания почтовых пользователей
можно написать небольшой скрипт.

Проверим отправку сообщений:

$ mail -s "test message" [6]crux@home.ru
Privet Crux
.
CC:


Письмо отправилось. Замечательно, теперь необходимо настроить
Courier-Imap для того чтобы пользователи смогли получать свою почту.


Courier-Imap

Courier-Imap - это превосходный IMAP, POP3 сервер. Поддержка ldap
встроена, и при компиляции он не требует devel-файлов OpenLDAP.


Установка

$ tar xzf courier-imap-1.7.3.tar.gz
$ cd courier-imap-1.7.3
$ ./configure --prefix=/usr/local
$ make
$ make check
# make install
# make install-configure


Конфигурация

/usr/local/etc/authdaemonrc

authmodulelist="authldap"
authmodulelistorig="authldap"
daemons=5
version=""
authdaemonvar=/usr/local/var/authdaemon


/usr/local/etc/authldaprc

LDAP_SERVER localhost
LDAP_PORT 389
LDAP_BASEDN ou=mailaccounts,dc=home,dc=ru
LDAP_BINDDN cn=courier, ou=daemons, dc=home, dc=ru
LDAP_BINDPW supersecret
LDAP_TIMEOUT 5
LDAP_MAIL mail
LDAP_FILTER (objectClass=CourierMailAccount)
LDAP_GLOB_UID vmail
LDAP_GLOB_GID vmail
LDAP_HOMEDIR homeDirectory
LDAP_MAILDIR mailMessageStore
LDAP_DEFAULTDELIVERY defaultDelivery
LDAP_MAILDIRQUOTA mailQuota
LDAP_FULLNAME cn
LDAP_CRYPTPW userPassword
LDAP_DEREF never
LDAP_TLS 0


/usr/local/etc/ipmapd

ADDRESS=0
PORT=143
MAXDAEMONS=40
MAXPERIP=4
PIDFILE=/var/run/imapd.pid
TCPDOPTS="-nodnslookup -noidentlookup"
AUTHMODULES="authdaemon"
AUTHMODULES_ORIG="authdaemon"
DEBUG_LOGIN=0
IMAP_CAPABILITY="IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT
THREAD=REFERENCES SORT QUOTA IDLE"
IMAP_CAPABILITY_ORIG="IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT
THREAD=REFERENCES SORT QUOTA AUTH=CRAM-MD5 AUTH=CRAM-SHA1 IDLE"
IMAP_IDLE_TIMEOUT=60
IMAP_CAPABILITY_TLS="$IMAP_CAPABILITY AUTH=PLAIN"
IMAP_CAPABILITY_TLS_ORIG="$IMAP_CAPABILITY_ORIG AUTH=PLAIN"
IMAP_DISABLETHREADSORT=0
IMAP_CHECK_ALL_FOLDERS=0
IMAP_OBSOLETE_CLIENT=0
IMAP_ULIMITD=65536
IMAP_USELOCKS=0
IMAP_ENHANCEDIDLE=0
IMAP_TRASHFOLDERNAME=Trash
IMAP_EMPTYTRASH=Trash:7
IMAP_MOVE_EXPUNGE_TO_TRASH=0
SENDMAIL=/usr/sbin/sendmail
HEADERFROM=X-IMAP-Sender
IMAPDSTART=YES


/usr/local/etc/pop3d

PIDFILE=/var/run/pop3d.pid
MAXDAEMONS=40
MAXPERIP=4
AUTHMODULES="authdaemon"
AUTHMODULES_ORIG="authdaemon"
DEBUG_LOGIN=0
POP3AUTH=""
POP3AUTH_ORIG="LOGIN CRAM-MD5 CRAM-SHA1"
POP3AUTH_TLS=""
POP3AUTH_TLS_ORIG="LOGIN PLAIN"
PORT=110
ADDRESS=0
TCPDOPTS="-nodnslookup -noidentlookup"
POP3DSTART=YES


Запуск

Для того чтобы запустить IMAP и POP3 сервисы, воспользуйтесь
следующими командами:

# /usr/local/libexec/imapd.rc start
# /usr/local/libexec/pop3d.rc start


Следует отметить, что если вы отключаете какой-либо из этих двух
сервисов, то второй тоже должен быть отстановлен, т.к. скрипты запуска
сделаны таким образом, что они запускают или останавливают сервис
authdaemon.ldap и если один из сервисов остановить, то будет
остановлен и authdaemon.ldap, соотвественно оставшийся сервис (скажем
pop3) не сможет обрабатывать запросы, т.к. не сможет подключиться к
authdaemon.ldap.

Теперь можно проверить почтовый ящик crux@home.ru.

$ telnet localhost 110
Trying 127.0.0.1...
Connected to localhost (127.0.0.1).
Escape character is '^]'.
+OK Hello there.
user crux@home.ru
+OK Password required.
pass mysuperpass
+OK logged in.
list
+OK POP3 clients that break here, they violate STD53.
1 374
.
quit
+OK Bye-bye.
Connection closed by foreign host.


Как видно письмо присутствует в ящике. Также следует отметить, что в
качестве логина использовался не "crux", а crux@home.ru. Т.к. в
качестве атрибута пользователя, по которому ведётся поиск в LDAP
используется "mail", если бы в параметре LDAP_MAIL файла authldaprc мы
поставили бы атрибут "uid", то в таком случае логин был бы просто
"crux". Но представьте себе ситуацию, когда у вас есть почтовые адреса
admin@mail.home.ru и admin@net.home.ru и они принадлежат двум
разным людям, то если использовать в качестве логина пользователя его
uid, то можем получить, например, что первый admin будет входить под
логином admin1, a другой под admin2 - что неочевидно (исходя из
названия мыла), да и не очень удобно.

Обновлено: 13.03.2015