Библиотека сайта rus-linux.net
Ошибка базы данных: Table 'a111530_forumnew.rlf1_users' doesn't exist
Перевод почтового сервера с Kerio Mail на Linux
Автор: Александр Тарасов aka oioki
Дата: 29 марта 2009
Организации, в которой я работаю, потребовалось перевести почту с коммерческого сервера Kerio Mail 6 на свободный вариант - Linux-сервер на базе Postfix+Dovecot. Особенностью является и то, что большинство почтовых пользователей завязаны на Active Directory. В организации используется несколько доменов. Эта статья представляет собой описание действий по настройке и собственно переносу почты - может быть, кому-нибудь пригодится.
Базовая установка
На новый сервер решено ставить Ubuntu 8.04. Сразу поставим необходимые пакеты:
apt-get install postfix postfix-ldap dovecot-common dovecot-imapd dovecot-pop3d mailxОсновной идеей решения является то, что адрес электронной почты пользователя хранится в поле mail каждого пользователя Active Directory, желающего иметь почту. В организации используется несколько доменов, поэтому обращаться мы будем к глобальному каталогу, который работает на контроллере корневого домена леса - root.domain.ru.
Настройка Postfix
Postfix - агент передачи почты (Mail Transfer Agent, MTA). Занимается пересылкой почты, пришедшей на порт 25 (SMTP). Вот основной конфигурационный файл, далее объясню что к чему:smtpd_banner = mail.domain.ru: proud of postfix. biff = no append_dot_mydomain = no myhostname = mail.domain.ru myorigin = domain.ru mydestination = localhost relayhost = relay.domain.ru mynetworks = 10.0.0.0/16, 127.0.0.0/8 mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = all # Virtual mailbox settings virtual_mailbox_domains = /etc/postfix/domains.cf virtual_mailbox_base = /var/mail virtual_mailbox_maps = ldap:/etc/postfix/ldap-users.cf virtual_minimum_uid = 8 virtual_uid_maps = static:8 virtual_gid_maps = static:8 virtual_transport = dovecot dovecot_destination_recipient_limit = 1 message_size_limit = 20480000 # SASL Authentication smtpd_sasl_auth_enable = no smtpd_sasl_exceptions_networks = $mynetworks smtpd_sasl_security_options = noanonymous broken_sasl_auth_clients = yes smtpd_sasl_type = dovecot smtpd_sasl_path = private/auth smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, permit
dom1.domain.ru dom2.domain.ru dom3.domain.ru root.domain.ru
version = 3 server_host = root.domain.ru:3268 query_filter = (&(objectclass=user)(mail=%s)) result_attribute = samaccountname result_format = %s bind = yes bind_dn = root\mailbind bind_pw = topsecret
550 5.1.1 <fedor@dom.domain.ru>: Recipient address rejected: User unknown in virtual mailbox tableЕще нужно прописать в файле master.cf сервис dovecot:
dovecot unix - n n - - pipe flags=DRhu user=mail:mail argv=/usr/lib/dovecot/deliver -d $(recipient)
Настройка Dovecot
Dovecot выполняет роли доставщика писем от Postfix в локальные каталоги (/var/mail), а также POP3- и IMAP-сервера - доставляет письма конечным пользователям. Вот основной конфигурационный файл, далее будет все разъяснено подробнее.
login_greeting = Welcome to IMAP/POP3 server
base_dir = /var/run/dovecot/
mail_location = maildir:/var/mail/%d/%n
protocols = imap pop3
protocol imap {
listen = *:143
login_executable = /usr/lib/dovecot/imap-login
mail_executable = /usr/lib/dovecot/imap
imap_max_line_length = 65536
mail_plugin_dir = /usr/lib/dovecot/modules/imap
}
protocol pop3 {
listen = *:110
login_executable = /usr/lib/dovecot/pop3-login
mail_executable = /usr/lib/dovecot/pop3
pop3_uidl_format = %08Xu%08Xv
mail_plugin_dir = /usr/lib/dovecot/modules/pop3
}
protocol lda {
postmaster_address = postmaster@mail.domain.ru
hostname=mail.domain.ru
sendmail_path = /usr/lib/sendmail
auth_socket_path = /var/run/dovecot/auth-master
rejection_reason = Ваше сообщение "%s" адресату <%t> было отклонено
по следующей причине: %n%r.%n%nЕсли вы действительно хотите, чтобы
письмо дошло, пожалуйста, свяжитесь с почтовым администратором
<postmaster@mail.domain.ru>
}
plugin {
quota = maildir
quota_rule = *:storage=50M
quota_rule2 = Trash:ignore
quota_warning = storage=90%% /etc/dovecot/scripts/quota-warning.sh 90
}
log_timestamp = "%Y-%m-%d %H:%M:%S "
auth_verbose = no
auth_debug = no
auth_debug_passwords = no
mail_debug = no
mail_privileged_group = mail
first_valid_uid = 8
last_valid_uid = 8
maildir_copy_with_hardlinks = yes
disable_plaintext_auth = no
auth default {
mechanisms = plain
userdb passwd-file {
args = /etc/dovecot/quotas.conf
}
userdb static {
args = uid=8 gid=8 allow_all_users=yes
}
passdb ldap {
args = /etc/dovecot/ldap.conf
}
user = nobody
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0660
user = mail
group = mail
}
client {
path = /var/spool/postfix/private/auth
mode = 0660
user = postfix
group = postfix
}
}
}
/var/mail/почтовый_домен/левая_часть_адреса. Здесь все пользователи разрешены (allow_all_users=yes), потому что их существование уже было проверено ранее сервисом Postfix. Проверка пароля требуется в случае подключения POP3- или IMAP-клиентом. Здесь уже вступает в действие запись passdb. Как видно из конфигурационного файла, аутентификация происходит с помощью LDAP-запросов. Следующий файл описывает порядок работы:
ldap_version = 3 auth_bind = yes hosts = root.domain.ru:3268 base = dc=domain,dc=ru dn = mailbind@root.domain.ru dnpass = topsecret pass_filter = (&(objectclass=user)(mail=%u))
unlim@dom3.domain.ru::8:8::::userdb_quota_rule=*:storage=0 big@dom2.domain.ru::8:8::::userdb_quota_rule=*:storage=100M . . .
#!/bin/bash
ADMIN=postmaster@root.domain.ru
PERCENT=$1
message()
{
echo "MIME-Version: 1.0"
echo "Content-Type: text/plain; charset=utf-8"
echo "Content-Transfer-Encoding: 16bit"
echo "From: $ADMIN"
echo "To: $USER"
echo "Subject: Внимание! Ваш ящик почти заполнен."
echo "Уважаемый пользователь!"
echo "Ваш почтовый ящик заполнен на $PERCENT%."
echo "Учтите, что при превышении квоты будет невозможно хранить сообщения в вашем почтовом ящике."
echo "Для устранения проблемы требуется почистить свои почтовые папки (в первую очередь корзину)."
echo ""
date +'%e %B %Y, %k:%M'
}
message | sendmail -f $ADMIN "$USER"
Перенос привязки почты к ActiveDirectory
Привязка к AD, конечно теперь существует, но дело в том, что в Kerio привязка осуществлялась через собственный конфиг-файл, а мы собираемся прописать e-mail адреса в самой AD. Значит, нужно обработать конфигурационный файл Kerio Mail - он называется users.cfg - и выделить из него привязки к AD. Однако не все пользователи были привязаны к AD, а у тех, которые привязаны, логин на почту и AD совпадает. Это все надо учесть. Обработку файла произведем в три этапа:1. Выделим из файла users.cfg тройки (AD-логин,левая часть адреса,почтовый домен). Если пользователь аутентфицируется через внутреннюю базу Kerio (т.е. Auth_type=0), то AD-логин пока не пишем - забиваем строку-пустышку "ADLOGIN". Иначе пишем одинаковые логины. Вот скрипт на Perl:
#!/usr/bin/perl
$mydomain="$ARGV[0].domain.ru";
open(USERS,"users.cfg");
@users=<USERS>;
close(USERS);
for($j=0; $j<scalar(@users); $j++)
{
$line=$users[$j];
if ( $line =~ /\ \ \ \ \<variable\ name=\"Name\"\>.*\<\/variable\>\r\n/ )
{
$line =~ s/\ \ \ \ \<variable\ name=\"Name\"\>//;
$line =~ s/\<\/variable\>\r\n//;
$j++;
$domain=$users[$j];
$domain =~ s/\ \ \ \ \<variable\ name=\"Domain\"\>//;
$domain =~ s/\<\/variable\>\r\n//;
if ( $domain eq $mydomain )
{
for($k=$j+1; $k<scalar(@users); $k++)
{
$line2=$users[$k];
if ( $line2 =~ /\ \ \ \ \<variable\ name=\"Auth_type\"\>.*\<\/variable\>\r\n/ )
{
$line2 =~ s/\ \ \ \ \<variable\ name=\"Auth_type\"\>//;
$line2 =~ s/\<\/variable\>\r\n//;
if ( $line2 eq '0' )
{
print "ADLOGIN:$line:$domain:\n";
}
else
{
print "$line:$line:$domain:\n";
}
last;
}
}
}
}
}
ADLOGIN:user1:dom1.domain.ru: ADLOGIN:user2:dom1.domain.ru: user3:user3:dom1.domain.ru: . . .
2. Далее нужно сгенерировать LDIF-файл, описывающий действия, которые нужно произвести с базой данных ActiveDirectory. В данном случае мы меняем поле mail определенных пользователей нужным нам образом. Вот скрипт, генерирующий LDIF-файл. Кроме того, он ищет в AD логины, совпадающие с левыми частями интересующих нас почтовых адресов - таким образом восстанавливаем привязку к AD.
#!/usr/bin/perl
@data=<STDIN>;
for($j=0; $j<scalar(@data); $j++)
{
# Разбиваем строку на поля
($adlogin,$email,$domain) = split(/:/, $data[$j]);
# Если не было привязки к AD, попытаемся ее восстановить, найдя
if ( $adlogin eq 'ADLOGIN' )
{
$field = $email;
}
else
{
$field = $adlogin;
}
# Ищем Distinguished Name в Active Directory
open(CONVERTFD,"./dn-lookup $field |");
$dn = <CONVERTFD>;
close(CONVERTFD);
if ( $dn eq '' )
{
print STDERR "# Не найдено соответствие для почты $email\@$domain.\n";
}
else
{
if ( $adlogin eq 'ADLOGIN' )
{
print STDERR "# Привязка $email\@$domain к логину $email восстановлена.\n";
}
# Выводим код LDIF-операции
print $dn;
print "changetype: modify\n";
print "replace: mail\n";
print "mail: $email\@$domain\n";
print "-\n";
}
}
#!/bin/sh ldapsearch -h root.domain.ru -p 3268 -b "dc=root,dc=domain,dc=ru" "(sAMAccountName=$1)" \ -x -D "mailbind@ROOT.DOMAIN.RU" -w "topsecret" | grep "dn:" | head -n 1
CN=user1,CN=Users,DC=dom2,DC=domain,DC=ru changetype: modify replace: mail mail: user1@dom2.domain.ru - CN=user2,CN=Users,DC=dom2,DC=domain,DC=ru changetype: modify replace: mail mail: user2@dom2.domain.ru - CN=user3,CN=Users,DC=dom1,DC=domain,DC=ru changetype: modify replace: mail mail: user3@dom1.domain.ru -
ldapmodify -f step-2.out -h root.domain.ru -x -D "superadmin@ROOT.DOMAIN.RU"Потребуется ввести пароль пользователя superadmin, причем этот пользователь должен обладать правами на изменение каталога.
Перенос почты
Итак, теперь все готово для приема и отправки почты. Однако у нас есть уже существующие письма пользователей, которые необходимо аккуратно перенести. У нас она будет осуществляться с помощью такого скрипта:
#!/bin/sh
### Скрипт переноса из Kerio в Maildir-структуру
KERIOMAIL=/mnt/mail/Store/mail
### Список доменов
list_domains()
{
ls -1 $KERIOMAIL | grep -v "\#public"
}
### Копирование каталога пользователя $2 из домена $1
make_user()
{
DEST=$1/$2
SRC=$KERIOMAIL/$DEST
mkdir $DEST
mkdir -p $DEST/.Trash/new
mkdir -p $DEST/.Trash/cur
mkdir -p $DEST/.Trash/tmp
cp $SRC/Deleted\ Items/\#msgs/* $DEST/.Trash/new
mkdir -p $DEST/.Drafts/new
mkdir -p $DEST/.Drafts/cur
mkdir -p $DEST/.Drafts/tmp
cp $SRC/Drafts/\#msgs/* $DEST/.Drafts/new
mkdir -p $DEST/.Sent/new
mkdir -p $DEST/.Sent/cur
mkdir -p $DEST/.Sent/tmp
cp $SRC/Sent\ Items/\#msgs/* $DEST/.Sent/new
mkdir -p $DEST/new
mkdir -p $DEST/cur
mkdir -p $DEST/tmp
cp $SRC/INBOX/\#msgs/* $DEST/new
}
### Список пользователей домена $1
list_users()
{
ls -1 $KERIOMAIL/$1 | grep -v "\#public"
}
### Копирование домена $1
make_domain()
{
for user in `list_users $1`;
do
make_user $1 $user
done
}
### Пересоздаем каталоги с доменами
for domain in `list_domains`;
do
rm -Rf $domain
mkdir $domain
make_domain $domain
done
