вторник, 27 января 2009 г.

Интеграция qmail, LDAP и djbdns

Итак, классическая задача: необходимо установить и настроить почтовый
сервер предприятия, который смог бы размещать более тысячи почтовых
ящиков, был бы легко управляем и масштабируем. Кроме того, сервер
будет выполнять другие функции, как например сервер первичной зоны DNS
и т.д. Имеется достаточно мощный IBM PC сервер с уже установленной ОС
FreeBSD 4.9, процесс установки которой здесь не рассматривается.

Машина имеет два сетевых интерфейса, один из которых "смотрит" внутрь
и имеет соответственно внутренний ip, другой смотрит наружу и имеет
полноценный IANA адрес. Дополнительно рекомендуется установить из
пакетов/портов следующие компоненты: gmake-3.8xx (обязательно),
gnuls-4.xx (цветной "ls" для удобства), joe-2.8xx (удобный редактор).

Устанавливаем Berkley DB 4.2.52 (http://www.sleepycat.com).
Нам нужны библиотеки BDB для того, чтобы использовать BDB базу
данных в качестве backend для хранения данных slapd. После того,
как архив был скачан и сохранен в каталог /usr/local/src/sources,
компилируем и устанавливаем компоненты:

# mkdir /usr/local/src/sources/bdb
# mv db-4.2.52.tar.gz /usr/local/src/sources/bdb
# cd /usr/local/src/sources/bdb
# tar -zxvf db-4.2.52.tar.gz
# cd db-4.2.52
# ./dist/configure --prefix=/usr/local/bdb --mandir=/usr/share/man
--libdir=/usr/lib --includedir=/usr/include
# gmake
# gmake install


Устанавливаем OpenLDAP 2.1 (http://www.OpenLDAP.org). На момент написания
статьи последняя доступная -STABLE версия OpenLDAP была 20031217.

# mkdir /usr/local/src/sources/openldap
# mv openldap-stable-20031217.tgz /usr/local/src/sources/openldap
# cd /usr/local/src/sources/openldap
# tar -zxvf openldap-stable-20031217.tgz
# cd openldap-2.1.25
# ./configure --prefix=/usr/local/openldap --mandir=/usr/share/man
--libdir=/usr/lib --includedir=/usr/include
--localstatedir=/var/openldap --sysconfdir=/etc --enable-crypt
# gmake
# gmake install

Небольшие пояснения: используется директива --enable-crypt для
возможности хранения паролей для аутентификации сессии с slapd в
формате {CRYPT}. Эта директива не обязательна, и используется в целях
совместимости. После того, как бинарники, библиотеки и прочий хлам был
установлен, нужно создать аккаунт пользователя от прав которого будет
действовать slapd, ибо пускать его с правами root крайне дурной тон.

# pw groupadd ldap
# pw useradd -n ldap -s /sbin/nologin -d /var/openldap -g ldap


Далее расставляем соответствующие пермишены на каталог с БД backend и
конфигурационные файлы.

# chown -R ldap:ldap /var/openldap
# chown -R ldap:ldap /etc/openldap/slapd.conf


Правим конфиг slapd и ldap.conf. В качестве примера полностью
приводится конфигурационный файл.

# slapd.conf
#
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/misc.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/corba.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/nis.schema
include /etc/openldap/schema/openldap.schema
include /etc/openldap/schema/qmail.schema
pidfile /var/openldap/slapd.pid
argsfile /var/openldap/slapd.args
# Define ACL's
access to attrs=userPassword
by self write
by users none
by anonymous compare
access to attrs=mail,mailAlternateAddress,mailMessageStore,deliveryMode,accountStatus
by dn.base="uid=qmaild,ou=DAEMON,dc=komitex,dc=ru" read
by users none
access to dn.base="ou=CONFIG,dc=komitex,dc=ru"
by dn.sub="uid=*,ou=DAEMON,dc=komitex,dc=ru" read
by users none
access to dn.base="ou=DAEMON,dc=komitex,dc=ru"
by dn.sub="uid=*,ou=DAEMON,dc=komitex,dc=ru" read
by users none
access to dn=*
by users read
by anonymous auth
# Define SSL/TLS stuff
TLSCertificateKeyFile /etc/openldap/cert/cert.pem
TLSCertificateFile /etc/openldap/cert/cert.pem
TLSCipherSuite HIGH:MEDIUM:+SSLv2:+TLSv1

###################################################################
# ldbm database definitions
###################################################################
database bdb
suffix "dc=komitex,dc=ru"
rootdn "cn=ldapadmin,dc=komitex,dc=ru"
rootpw {SSHA}CENSORED
directory /var/openldap/openldap-data
# Indices to maintain
index objectClass eq
index mail eq,sub
index mailAlternateAddress eq,sub
index uid eq,sub
index accountStatus eq
index mailHost eq
index deliveryMode eq
index uidNumber,gidNumber eq


Как видно из конфигурации slapd, доступ к атрибутам, описывающим
конфигурацию пользователей почты, будет имеет только учетная запись,
предназначенная для qmail-LDAP. Доступ же к атрибуту userPassword
закрыт для всех, кроме владельца. Пароль для rootdn генерируется
утилитой slappasswd. Сертификат для slapd еще не создан, впрочем, как
и не существует (пока) файла qmail.schema. Об этом чуть позже.

На время оставим OpenLDAP в покое, и приступим к настройке DNS
сервера, в качестве которого будет использоваться пакет djbdns (http://cr.yp.to/djbdns/).
Предварительно потребуется также установить daemontools (http://cr.yp.to/daemontools/) и
ucspi-tcp (http://cr.yp.to/ucspi-tcp/). Это обязательные компоненты.

Устанавливаем daemontools

# mkdir -p /package
# chmod 1755 /package
# mv daemontools-0.76.tar.gz /package
# tar -zxvf daemontools-0.76.tar.gz
# rm daemontools-0.76.tar.gz
# cd admin/daemontools-0.76
# package/install


Далее требуется убедиться, что в rc.local была добавлена строка,
запускающая svscanboot. Можно перезагрузиться или запустить svscanboot
так, как это делается из rc.local.

Устанавливаем ucspi-tcp

# mkdir /usr/local/src/sources/ucspi-tcp
# mv ucspi-tcp-0.88.tar.gz /usr/local/src/sources/ucspi-tcp
# cd /usr/local/src/sources/ucspi-tcp
# tar -zxvf ucspi-tcp-0.88.tar.gz
# cd ucspi-tcp-0.88
# gmake
# gmake setup check


Утилиты установлены в /usr/local

Можно приступать к установке и настройке djbdns. Предварительно
несколько пояснений. Итак, на сервере будет функционировать сервер
первичной зоны DNS для домена komitex.ru, DNS кеш для клиентов во
внутренней сети, сервер трансфера зоны и dummy сервер для обратной
зоны в локальной сети.

Устанавливаем djbdns

# mkdir /usr/local/src/sources/djbdns
# mv djbdns-1.05.tar.gz /usr/local/sources/djbdns
# tar -zxvf djbdns-1.05.tar.gz
# cd djbdns-1.05
# gmake
# gmake setup check


Конфигурируем DNS кеш для клиентов во внутренней сети. Когда сервис
будет подыматься, он должен биндится на ip-адрес, принадлежащий
внутренней сети, в данном случае это адрес 192.168.0.1. Т.е. на
основной ip внутреннего сетевого интерфейса. Кроме того, нам
потребуется еще один ip на внутреннем интерфейсе, для того чтобы
забиндить туда walldns для разрешения имен в обратной зоне внутренней
сети. Поэтому у внутреннего интерфейса помимо основного ip-адреса еще
имеется и алиасный, куда и будет производить bind() наш walldns.

Конфигурируем dnscache. Нужно создать также аккаунты в системе.

# pw useradd -n Gdnscache
# pw useradd -n Gdnslog -s /sbin/nologin
# dnscache-conf Gdnscache Gdnslog /etc/dnscache 192.168.0.1


Нужно разрешить всем клиентам из внутренних сетей пользоваться кешем

# touch /etc/dnscache/root/ip/192.168


Последний штрих в /etc/resolv.conf. Добавим адрес сервера

# /etc/resolv.conf
domain komitex.ru
nameserver 192.168.0.1


Предполагаем также лукапы на домен komitex.ru направлять сразу на
локальный DNS сервер и также поступать с лукапами в обратную зону
локальной сети - будем направлять запрос сразу на алиасный ip, куда
будет забинден walldns.

# cd /etc/dnscache/root/servers
# touch komitex.ru
# echo "217.24.115.21" > komitex.ru
# touch 0.168.192.in-addr.arpa
# echo "192.168.0.139" > 0.168.192.in-addr.arpa


Можно запускать dnscache

# ln -s /etc/dnscache /service/dnscache
# svstat /service/dnscache


Проверим работу кеша, дав рекурсивный запрос

# dnsqr A www.nordcomp.ru
1 www.nordcomp.ru:
49 bytes, 1+1+0+0 records, response, noerror
query: 1 www.nordcomp.ru
answer: www.nordcomp.ru 86400 A 195.239.170.224


Пора запустить и tinydns. Он будет биндится на внешний ip
217.24.115.21, принадлежащий внешнему сетевому интерфейсу.

# pw useradd -n Gtinydns -s /sbin/nologin
# tinydns-conf Gtinydns Gdnslog /etc/tinydns 217.24.115.21


Редактируем файл данных /etc/tinydns/root/data.

# /etc/tinydns/root/data
# NS и SOA записи для домена komitex.ru
.komitex.ru:217.24.115.21:ns.komitex.ru
# Вторичный NS
&komitex.ru:217.24.114.30:ns.komisat.ru
# MX записи
@komitex.ru:217.24.115.21:mail.komitex.ru:5
@komitex.ru:217.24.114.23:ns.komisat.ru:10
# A записи
=pop.komitex.ru:217.24.115.21
=smtp.komitex.ru:217.24.115.21
=helga.komitex.ru:217.24.115.21
=komitex.komitex.ru:217.24.114.11
=proxy.komitex.ru:217.24.114.12
=hosting.komitex.ru:217.24.114.24
=webhosting.komitex.ru:217.24.114.17
=mandrake.komitex.ru:217.24.114.22
=www.komitex.ru:217.24.115.21
=ftp.komitex.ru:217.24.114.17
=stat.komitex.ru:217.24.114.11
=flex.komitex.ru:217.24.114.30


В этом файле содержится вся информация, нужная для tinydns. После
того, как файл отредактирован, создаем data.cdb просто сказав "gmake"
в каталоге с только что отредактированным файлом данных. Постольку
поскольку операции обновления cdb файлов атомарные, изменять данные
DNS зоны можно во время работы tinydns.

Запускаем tinydns

# ln -s /etc/tinydns /service/tinydns
# svstat /service/tinydns


Проверяем данные зоны, посылая нерекурсивные запросы

# dnsq soa komitex.ru 217.24.115.21
6 komitex.ru:
165 bytes, 1+1+2+3 records, response, authoritative, noerror
query: 6 komitex.ru
answer: komitex.ru 2560 SOA ns.komitex.ru hostmaster.komitex.ru
1072778137 16384 2048 1048576 2560
authority: komitex.ru 259200 NS ns.komitex.ru
authority: komitex.ru 259200 NS ns.komisat.ru
additional: ns.komitex.ru 259200 A 217.24.115.21
additional: ns.komisat.ru 259200 A 217.24.114.30
additional: ns.komisat.ru 86400 A 217.24.114.23


Нужно еще сделать возможным передачу зоны по запросу от вторичного DNS
сервера.

Конфигурируем axfrdns

# pw useradd -n Gaxfrdns -s /sbin/nologin
# axfrdns-conf Gaxfrdns Gdnslog /etc/axfrdns 217.24.115.21


Нужно разрешить вторичному DNS серверу брать зону с нас по tcp.

Редактируем файл /etc/axfrdns/tcp.

217.24.114.30:allow,AXFR="komitex.ru"
:allow,AXFR=""


Чтобы применить изменения, говорим "gmake" в том же каталоге.

Запускаем axfrdns

# ln -s /etc/axfrdns /service/axfrdns
# svstat /service/axfrdns


Осталось поднять walldns для обратной зоны внутренней сети. Это
необходимо для нормальной работы некоторых служб в сети, которые
обязательно хотят ресолвить имена клиентов через DNS. Для работы
walldns специально задан дополнительный адрес на внутреннем сетевом
интерфейсе.

# pw useradd -n Gwalldns -s /sbin/nologin
# walldns-conf Gwalldns Gdnslog /etc/walldns 192.168.0.139


Запускаем walldns

# ln -s /etc/walldns /service/walldns
# svstat /service/walldns


Проверим

# dnsq a 192.168.0.51 192.168.0.139
1 192.168.0.50:
46 bytes, 1+1+0+0 records, response, authoritative, noerror
query: 1 192.168.0.50
answer: 192.168.0.50 655360 A 192.168.0.50


На этом с DNS службами поконечно. Можно браться за OpenLDAP и qmail.


Установка qmail-LDAP


Потребуется "чистый" qmail-1.03 (http://cr.yp.to/software/qmail-1.03.tar.gz)
на который будет залит самый последний патч qmail-LDAP
(http://www.nrg4u.com/qmail/qmail-ldap-1.03-20031201.patch.gz).

# mkdir /usr/local/src/sources/qmail
# mv qmail-1.03.tar.gz /usr/local/src/sources/qmail
# cd /usr/local/src/sources/qmail
# tar -zxvf qmail-1.03.tar.gz


В распакованный каталог qmail скачиваем патч.

# patch -p1 < qmail-ldap-1.03-20031201.patch.gz


Редактируем Makefile. Значения уже рассматривались.

LDAPLIBS=-L/usr/lib -lldap -llber
LDAPINCLUDES=-I/usr/include
TLS=-DTLS_REMOTE -DTLS_SMTPD
TLSINCLUDES=-I/usr/local/include
TLSLIBS=-L/usr/local/lib -lssl -lcrypto
OPENSSLBIN=/usr/local/bin/openssl
OPENSSLBIN=openssl
MNW=-DMAKE_NETSCAPE_WORK
MDIRMAKE=-DAUTOMAILDIRMAKE
HDIRMAKE=-DAUTOHOMEDIRMAKE
SHADOWLIBS=-lcrypt


Подправим также 67-ю строчку в qmail-ldap.h. Это нужно для того, чтобы
qmail-LDAP не пытался разместить Maildir каталог в домашнем каталоге
пользователя, если такой атрибут присутствует у объекта в LDAP
каталоге.

#define LDAP_HOMEDIR "nohomeDirectory"


Создаем нужные аккаунты в системе, как написано в INSTALL.ids

# pw groupadd nofiles
# pw useradd alias -g nofiles -d /var/qmail/alias -s /nonexistent
# pw useradd qmaild -g nofiles -d /var/qmail -s /nonexistent
# pw useradd qmaill -g nofiles -d /var/qmail -s /nonexistent
# pw useradd qmailp -g nofiles -d /var/qmail -s /nonexistent
# pw groupadd qmail
# pw useradd qmailq -g qmail -d /var/qmail -s /nonexistent
# pw useradd qmailr -g qmail -d /var/qmail -s /nonexistent
# pw useradd qmails -g qmail -d /var/qmail -s /nonexistent
и каталог /var/qmail
# mkdir /var/qmail


Компилируем и устанавливаем

# gmake setup check
# cd /var/qmail/alias
# touch .qmail-mailer-daemon .qmail-postmaster .qmail-root
# chmod 644 .*


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

# pw groupadd virtmail
# pw useradd -n virtmail -g virtmail -s /sbin/nologin
# mkdir /var/qmail/users
# chown virtmail:virtmail /var/qmail/users
# chmod 700 /var/qmail/users


Немножко пошуршим в ~/control

# cd /var/qmail/control
# echo "helga.komitex.ru" > me
# echo "komitex.ru" > locals
# echo "helga.komitex.ru" >> locals
# echo "localhost" > ldapserver
# echo "dc=komitex,dc=ru" > ldapbasedn
# echo "1" > ldaprebind
# echo "1" > ldaplocaldelivery
# echo "30" > ldaptimeout
# echo "1009" > ldapgid
# echo "1006" > ldapuid
# echo "cn=qmaild,ou=DAEMON,dc=komitex,dc=ru" > ldaplogin
# echo "password" > ldappassword
# chmod 600 ldappassword
# echo "qmailUser" > ldapobjectClass
# echo "1000" > defaultquotacount
# echo "2000000" > defaultquotasize
# echo "You have exceeded your quota" > quotawarning
# echo "/var/qmail/bin/dirmaker" > dirmaker


Создадим скрипт, который будет создавать каталог пользователя для
почты

#!/bin/sh
# script /var/qmail/bin/dirmaker
/bin/mkdir -m 700 -p $1
# chown virtmail:virtmail /var/qmail/bin/dirmaker
# chmod u+s dirmaker


Редактируем конфигурацию служб qmail-LDAP

# qmail-smtpd.rules
192.168.:allow,SENDERCHECK="",RELAYCLIENT="",NOPBS=""
:allow,RCPTCHECK="",RETURNMXCHECK="",SANITYCHECK="",NOPBS=""

# qmail-pop3d.rules
127.0.0.1:allow,NOPBS=""
# default allow
:allow,NOPBS=""


Так как мы собираемся использовать функции проверки адресов
отправителя и получателя (SENDERCHEK="", RCPTCHECK="") нам нужно дать
разрешение на чтение файла ~control/ldappassword пользователю qmaild,
в противном случае лукапы qmail-verify будут оканчиваться "temporary
ldap lookup error".

# chmod 600 /var/qmail/control/ldappassword
# chown qmaild /var/qmail/control/ldappassword


В заключении собираем все обновления в *.cdb файлы - для этого теперь
достаточно сказать "gmake" в каталоге ~/control. Для полного счастья
сгенерим сертификат для работы TLS. Кроме того, этот же сертификат
будет использован для TLS/SSL соединений с демоном slapd.

# cd /usr/local/src/sources/qmail/qmail-1.03
# gmake cert
# mkdir /etc/openldap/cert
# chmod 700 /etc/openldap/cert
# cp /var/qmail/control/cert.pem /etc/openldap/cert
# chown ldap:ldap /etc/openldap/cert/cert.pem


Теперь можно запустить slapd и произвести начальное наполнение
каталога LDAP.

# /usr/local/openldap/libexec/slapd -u ldap -h "ldap:// ldaps:///"


Чтобы slapd стартовал при загрузке системы добавим в /etc/rc.local

# /etc/rc.local
...
# OpenLDAP stuff
if [ -x /usr/openldap/libexec/slapd ]; then
/usr/openldap/libexec/slapd -u ldap -h "ldap:/// ldaps:///"
echo -n " openldap"
fi


Создадим начальную структуру каталога LDAP

# ldapadd -W -D cn=ldapadmin,dc=komitex,dc=ru -f init.ldif

# init.ldif
dn: dc=komitex,dc=ru
objectClass: domain
dc: komitex
description: JSC Komitex
dn: ou=Users,dc=komitex,dc=ru
objectClass: organizationalUnit
ou: Users
description: JSC Komitex Users
dn: ou=Groups,dc=komitex,dc=ru
objectClass: organizationalUnit
ou: Groups
description: JSC Komitex Groups
dn: ou=CONFIG,dc=komitex,dc=ru
objectClass: organizationalUnit
ou: CONFIG
description: Configurational ROOT
dn: ou=DAEMON,dc=komitex,dc=ru
objectClass: organizationalUnit
ou: DAEMON
description: System Daemons


Добавим также объект, который будет использоваться qmail для доступа к
каталогу

# ldapadd -W -D cn=ldapadmin,dc=nordcomp,dc=ru -f qmaild.ldif

# qmaild.ldif
dn: uid=qmaild,ou=DAEMON,dc=komitex,dc=ru
objectClass: OpenLDAPperson
uid: qmaild
cn: qmail-LDAP Account
sn: qmail-LDAP Account
userPassword:


Зададим пароль, который мы указали в ~/control/ldappassword

# ldappasswd -W -s password -D cn=ldapadmin,dc=komitex,dc=ru
uid=qmaild,ou=Daemon,dc=komitex,dc=ru


Добавим тестовую запись в каталог

# test.ldif
dn: cn=Kitty,ou=Users,dc=komitex,dc=ru
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: qmailUser
cn: kitty
sn: kitty
uid: kitty
uidNumber: 2027
gidNumber: 500
homeDirectory: /home/kitty
loginShell: /bin/csh
mail: [10]kitty@komitex.ru
deliveryMode: noforward
accountStatus: active
mailMessageStore: /var/qmail/users/kitty
userPassword: {crypt}CENSORED

# ldapadd -W -D cn=ldapadmin,dc=komitex,dc=ru -f test.ldif


Пора запускать службы qmail. Наделаем символических ссылок в /service

# ln -s /var/qmail/boot/qmail /service/qmail
# ln -s /var/qmail/boot/qmail-smtpd /service/qmail-smtpd
# ln -s /var/qmail/boot/qmail-pop3d /service/qmail-pop3d


Проверим SMTP

helga# telnet 192.168.0.1 25
Trying 192.168.0.1...
Connected to helga.komitex.ru.
Escape character is '^]'.
220 helga.komitex.ru ESMTP
EHLO
250-helga.komitex.ru
250-PIPELINING
250-SIZE 0
250-STARTTLS
250 8BITMIME
MAIL FROM: [11]admin@net.nordcomp.ru
250 ok
RCPT TO: [12]kitty@komitex.ru
250 ok
DATA
354 go ahead punk, make my day
TEST
.
250 ok 1073248118 qp 14340 by helga.komitex.ru


и POP3 тоже

helga# telnet 192.168.0.1 110
Trying 192.168.0.1...
Connected to helga.komitex.ru.
Escape character is '^]'.
+OK <14426.1073248192@helga.komitex.ru.>;
USER kitty
+OK
PASS kiska-zaika
+OK
stat
+OK 3 958
QUIT
+OK
Connection closed by foreign host.

Комментариев нет:

Отправить комментарий