Библиотека сайта 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