playground:playground2 Сравнение версий

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
playground:playground2 [2010/02/19 16:14]
213.95.41.13
playground:playground2 [2022/04/19 13:45] (текущий)
195.242.110.111 1
Строка 1: Строка 1:
-====== Привязывание почтовой системы к Active Directory ====== +@@hntdc
- +
-<​note>​Вы читаете статью,​ размещённую в Wiki-разделе. Если вам есть что добавить,​ вы хотите что-нибудь улучшить или уточнить - можете свободно это делать. Только предварительно ознакомтесь с [[:​terms|правилами ресурса]].</​note>​ +
- +
-Часто нет возможности отказаться от использования домена Windows с AD. Например из-за групповых политик. Но при этом нет никакой необходимости держать громоздкий негибкий и по слухам небозопастный Exchange для обработки почты. Что ж - выход есть, простой и элегантный. Вам всего лишь нужно организовать почтовый сервер на  базе Linux, который брал бы всю информацию о пользователях и их почтовых ящиках из Active Directory. +
- +
-===== Сервер на Postfix и Dovecot ===== +
- +
-В качестве программного обеспечения для нашего сервера мы будем использовать Postfix в связке с Dovecot. Как настроить полнофункциональную почтовую систему на базе этих двух приложений подробно описано в соответствующих статьях про [[Postfix]] и [[Dovecot]]. Здесь же я акцентирую внимание на интеграцию почтовой системы с сервером AD. +
- +
-Итак. В Postfix все ваши домены будут обрабатываться через механизм виртуальных доменов. В AD информация о почтовых ящиках будет храниться в поле proxyAddresses,​ которое в отсутствии Exchange пустует. Postfix не будет для каждого письма опрашивать AD на предмет наличия пользователя и соответствия имени пользователя адресу электронной почты. Вместо этого раз в час Postfix будет импортировать данные обо всех пользователях из AD, что позволит избежать сразу многих неудобств и значительно упростить дальнейшее управление доменом. Dovecot же напротив будет опрашивать домен на предмет авторизации. +
- +
-Логин и пароль пользователя для доступа к Postfix и к Dovecot будут совпадать с доменными логином и паролем. +
- +
-Итак, все подробности по мере описания настройки. +
- +
-==== Настройка AD ==== +
- +
-Вам потребуется пользователь в AD, через которого Postfix и Dovecot будут получать информацию из дерева каталогов. Я назвал этого пользователя ''​ldap-user'',​ вы же можете выбрать любое другое имя. Кстати,​ в целях безопастности лучше запретите созданному пользователю вход на все компьютеры. +
- +
-К сожалению в отсутствии Exchange через окно редактирования свойст пользователя нельзя изменить значение поля ''​proxyAddresses''​. Поэтому для назначение почтовых ящиков пользователям вам понадобится ''​Редактор ADSI'',​ хотя конечно вы можете добавить необходимые поля редактирования в редактор свойств вручную,​ но делается это далеко не тривиально. +
- +
-В любом случае особенности настройки AD - не тема этой статьи. Для работы системы вам потребуется пользователь для доступа к AD, а за всей другой иформацией обращайтесь в справку Microsoft или на специализированные ресурсы. +
- +
-==== Настройка Postfix ==== +
- +
-Postfix настроим следующим образом:​ +
- +
-  - Он будет принимать почту для всех пользователей вашего Windows-домена,​ имеющих почтовые ящики. +
-  - У каждого пользователя будет один ящик, на который будет приходить почта со всех его адресов. +
-  - Кроме того Postfix будет автоматически рассылать почту для групповых((То есть да, вы сможете создавать в AD группы пользователей и назначать им адреса почты, и всем участникам этой группы будут приходить пистма.)) ящиков на ящики пользователей. +
-  - Пользователи смогут отсылать через Postfix письма только с тех ящиков,​ которые им принадлежат - напрямую или через группы. +
-  - Авторизация и локальная доставка почты будет обеспечиваться Dovecot. +
- +
-Итак, подробно о параметрах Postfix можно почитать в [[Postfix|соответствующей статье]],​ тут же я опишу лишь те настройки,​ которые необходимы для решения поставленной задачи. +
- +
-Сразу хочу обратить внимание:​ вам необходимо настроить SASL авторизацию и TLS шифрование для Postfix, поскольку мы будем позволять отсылать письма только зарегистрировавшимся пользователям,​ а механизм авторизации у нас будет PLAIN LOGIN((То есть открытым текстом. Именно поэтому всё нужно шифровать. Подробнее о причинах выбора PLAIN авторизации ниже.)). +
- +
-Авторизацию будет проводить Dovecot, поэтому в файле ''​main.cf''​ основных настроек Postfix у вас должны быть примерно следующие параметры:​ +
- +
-<​file>​ +
-smtpd_sasl_auth_enable = yes +
-smtpd_sasl_type = dovecot +
-smtpd_sasl_path = private/​auth-client +
- +
- +
-smtpd_sasl_security_options = noanonymous,​ noplaintext +
-smtpd_sasl_tls_security_options = noanonymous +
-# Можно так вместо предыдущих двух опций +
-#​smtpd_tls_auth_only = yes +
-</​file>​ +
- +
-Подробней об авторизации и о связывании [[Dovecot]] и [[Postfix]] можно почитать в соответствующих статьях. Теперь же о содержательных настройках,​ касающихся логики функционирования нашей почтовой системы. +
- +
-Для начала вам потребуется задать основной почтовый домен для вашей организации в параметре $myorigin, без этого работать ничего не будет. Вот примерно как должны выглядеть основные настройки адресов в Postfix: +
- +
-<​file>​ +
-myhostname = mail.example.com +
-mydestination = $myhostname +
-myorigin = $mydomain +
-mynetworks = 127.0.0.0/8  +
-</​file>​ +
- +
-<note important>​ +
-Обратите внимание:​ не нужно указывать локальные IP вашей сети в $mynetworks и обязательно нужно задать значение $myorigin((Если вы ещё не освоились с Postfix, то напомню,​ что значение $mydomain если не указано явно береться отсечением первой части до точки значения $myhostname.))! +
-</​note>​ +
- +
-Теперь нам нужно настроить собственно домены,​ для которых мы будем получать почту, а так же список разрешённых получателей и отправителей. Для этого нам потребуются три параметра,​ начинающихся на ''​virtual_'':​ +
- +
-<​file>​ +
-virtual_mailbox_domains = +
- ​$mydomain +
- ​example.ru +
-virtual_mailbox_maps = +
- ​hash:/​etc/​postfix/​local_mailboxes/​valid_users +
-virtual_alias_maps = +
- ​hash:/​etc/​postfix/​local_mailboxes/​aliases +
-</​file>​ +
- +
-Назначение первого,​ я надеюсь,​ понятно. В нём содержится список всех доменов,​ для которых будет принимать почту Postfix. В этом списке обязательно должен быть $mydomain, иначе работать ничего не будет. +
- +
-Второй парамерт указывает на карту, в которой содержится список пользователей AD, имеющих почтовые ящики. Он нужен для того, чтобы сообщить Postfix для каких пользователей он должен получать почту, а для каких - нет. Сам список должен состоять из имён аккаунтов (без домена!) пользователей,​ но поскольку карты Postfix должны обязательно содержать два поля на запись (см. статью про [[Postfix]]),​ то файл мог бы выглядеть так: +
- +
-<​file>​ +
-user1  OK +
-user2  OK +
-admin  OK +
-</​file>​ +
- +
-Вместо OK можно написать что угодно. Эта карта будет автоматически создаваться скриптом,​ запрашивающим данные из AD (см. ниже). +
- +
-Третий параметр,​ $virtual_alias_maps,​ отвечает за установление соответствия имён почтовых ящиков пользовательским аккаунтам. Он мог бы выглядеть так: +
- +
-<​file>​ +
-user1@example.com ​ user1 +
-user1@example.com ​ user1 +
-user2@example.com ​ user2 +
-abuse@example.com ​ user1, user2, admin +
-</​file>​ +
- +
-Формат файла я думаю понятен. В левой колонке адрес, а в правой - все его владельцы. Если владельцев много - значит ящик принадлежит группе пользователей в AD. Этот файл естественно тоже будет создаваться скриптом. +
- +
-Ну и наконец нам нужно настроить локальную доставку. Для этого, как я уже говорил,​ будет использоваться Dovecot. Поэтому все параметры доставки мы будет настраивать именно в нём, а Postfix лишь должен правильно пересылать письма. Для решения этой задачи в ''​main.cf''​ нужно указать транспорт на Dovecot: +
- +
-<​file>​ +
-dovecot_destination_recipient_limit = 1 +
-virtual_transport = dovecot +
-</​file>​ +
- +
-Ну и собственно описать сам транспорт в файле ''​master.cf'':​ +
- +
-<​file>​ +
-dovecot ​  ​unix ​ -       ​n ​      ​n ​      ​- ​      ​- ​      ​pipe +
-  flags=DRhu user=postfix-vuser:​postfix-vuser argv=/​usr/​lib/​dovecot/​deliver -f ${sender} -d ${user} +
-</​file>​ +
- +
-Обратите внимание,​ что в параматре ''​-d''​ я указал ''​${user}'',​ то есть в Dovecot будет отправлено только имя пользователя без домена. Тут надо обратить внимание на одну особенность:​ Postfix не умеет оперировать именами пользователей,​ он работает только с полными адресами почты. Поэтому если указывать в описанных выше картах Postfix только имя пользователя (как мы и делали),​ то к нему будет автоматически добавлен домен из $myorigin. Это не доставляет никаких неудобств,​ потому что мы-то оперируем только именами пользователей во всех конфигах,​ но об этом нужно помнить,​ в частности,​ при отправке писем на Dovecot. +
- +
-Итак, доставку писем пользователям мы организовали. Теперь нужно проконтролировать отправку. Тут всё проще. Поскольку наш Postfix использует SASL авторизацию,​ то мы просто можем ему сообщить,​ каким адресам отправителя соответствует какой аккаунт. Делается это с помощью аналогичной по структуре описанному выше файлу alias карты. Собственно и содержание должно быть тоже аналогично,​ поэтому мы будем использовать ту же карту. +
- +
-Для привязки SASL логинов к адресам отправителей служит следующий парамерт в файле ''​main.cf'':​ +
- +
-<​file>​ +
-smtpd_sender_login_maps = +
- ​hash:/​etc/​postfix/​local_mailboxes/​aliases +
-</​file>​ +
- +
-Однако указание этого параметра не заставит Postfix отклонять почту при несоответствии логина и адреса отправителя. Нужно ещё правильно расставить запреты в параметрах ''​smtpd_*_restrictions''​. Например это можно сделать так: +
- +
-<​file>​ +
-smtpd_recipient_restrictions = +
- ... +
- ​permit_mynetworks +
- ​permit_sasl_authenticated +
- ​reject_unauth_destination +
- ... +
- +
-smtpd_sender_restrictions = +
- ... +
- ​reject_authenticated_sender_login_mismatch +
- ​permit_mynetworks +
- ​permit_sasl_authenticated +
- ... +
-</​file>​ +
- +
-Обратите внимание на ограничение ''​reject_authenticated_sender_login_mismatch''​. Оно отклоняет все письма от авторизованных пользователей,​ если адрес отправителя не соответствует логину в параметре $smtpd_sender_login_maps. +
- +
-Собственно на этом настройка самого Postfix закончена. Теперь нужно лишь разжиться скриптом,​ который будет создавать файлы alias_maps и mailbox_maps по данным из AD. +
- +
-==== Скрипт генерации карт Postfix по данным из AD ==== +
- +
-Скрипт написан на Perl и требует модуля Net::LDAP и Perl версии 5.10((Последнее используется только для ''​say'',​ если вы понимаете что это такое.)). Что делает скрипт:​ +
- +
-  - Он опрашивает AD и выбирает всех пользователей,​ у которых есть записи в поле proxyAddresses. +
-  - Все эти пользователи добавляются в mailbox_maps,​ и все их ящики прописываются в alias_maps. +
-  - Дальше скрипт опрашивает AD и выбирает все группы,​ для которых задан парамерт proxyAddresses **или**((На всяких документах тут принято писать **и/​или**,​ но мы же с вами понимаем,​ что **и** - это своего рода подмножество **или**.)) параметр mail. +
-  - Для каждой полученной группы скрипт вычисляет всех пользователей,​ входящих в эту группу напрямую или опосредованно (через другие группы),​ и добавляет все необходимые псевдонимы в alias_maps. Кроме того скрипт так же добавляет пользователей,​ у которых нет своего ящика, но на которых ссылается ящик группы,​ в mailbox_maps. Таким образом все входящие в группу с прописанным почтовым ящиком пользвоатели будут получать коррекпонденцию для этой группы и смогут отправлять ответы. +
-  - Кроме того скрипт попутно выявляет дубликаты адресов (когда один адрес почты задан для нескольких объектов) и адреса,​ не соответствующие домену. В первом случае обрабатывается только первый найденный объект с указанным адресом,​ а во втором просто выдаётся предупреждение,​ но адрес тем не менее обрабатывается. +
- +
-Собственно сам скрипт:​ +
- +
-<code perl> +
-#​!/​usr/​bin/​perl +
- +
-# Автор: Неворотин Вадим (malamut@ubuntu.ru) +
-# Лицензия:​ GPLv3 +
- +
-use 5.010; +
-use Net::​LDAP;​ +
- +
-+
-## Параметры +
-+
- +
-$AD_IP = '​ldap://​192.168.6.22';​ #​ AD сервер. +
-# AD пользователь для коннекта. Указывать в большинстве случаев надо именно с именем Windows-домена +
-$AD_user = '​ldap-user@domain.local';​  +
-$AD_passwd = '​pass';​ #​ Пароль +
-$AD_base = '​OU=var,​DC=domain,​DC=local';​ #​ Исходная точка поиска в дереве AD +
- +
-# Разрешённые домены - для проверки адресов +
-@domains = ('​example.com','​example.ru'​);​ +
- +
-# Выходные файлы +
-$aliases_file = '/​etc/​postfix/​local_mailboxes/​aliases';​ +
-$users_file = '/​etc/​postfix/​local_mailboxes/​valid_users';​ +
- +
-# Хеш псевдонимов. Ключ - адрес почты, значение - список пользователей через запятую +
-%aliases = (); +
-# Список пользователей,​ имеющих почтовые ящики +
-@valid_users = (); +
- +
-# Соединяемся с сервером... +
-$ldap = Net::​LDAP->​new($AD_IP) or die "​Couldn'​t connect to $AD_IP!\n";​ +
-$msg = $ldap->​bind($AD_user,​ password => $AD_passwd);​ +
-$msg->​code && die "​Connection problem...\n";​ +
- +
-# Открываем файл псевдонимов +
-open ALIASES, ">​$aliases_file"​ or die "​Can'​t open $alaises_file\n";​ +
- +
-+
-## Берём всех пользователей и все группы +
-+
- +
-# Процедура проверяет свой аргумент (адрес почты) на соответствие разрешённым доменам. +
-sub check_domain { +
- @_ == 1 or die "​check_domain - OOPS!\n";​ +
- my $flag = 0; +
- foreach $domain (@domains) { +
- if ($_[0] =~ /​@($domain)/​) { +
- $flag = 1; +
-+
-+
- if (!$flag) { +
- say "​WARNING:​ incorrect domain in $_[0]";​ +
-+
-+
- +
-# Процедура проверяет вхождение первого элемента (адрес) в качестве ключа для хеша (третий аргумент) +
-# Второй аргумент - это предполагаемое значение ключа (имя пользователя или группы) +
-sub check_mail { +
- @_ > 1 or die "​check_mail - OOPS!\n";​ +
- $mail = shift @_; +
- $obj = shift @_; +
- %hash = @_; +
- if (exists($hash{$mail})) { +
- say "​WARNING:​ address $mail is used more than for one object:";​ +
- say "​\t",​$hash{$mail};​ +
- say "​\t",​$obj;​ +
- say "​I'​ll add it only for '​$hash{$mail}'";​ +
- return 1; +
-+
- return 0; +
-+
- +
-+
-## Пользователи +
-+
- +
-# emails - из proxyAddresses,​ login - из sAMAccountName +
- +
-# Параметры поиска в AD для пользователей +
-$filter = '​(&​(objectClass=user)(proxyAddresses=*))';​ +
-$attrs = ['​CN','​sAMAccountName','​proxyAddresses'​];​ +
- +
-# LDAP запрос +
-$result = $ldap->​search( +
- base => $AD_base, +
- filter => $filter, +
- attrs => $attrs); +
- +
-# Выделяем необходимую инфу из результатов +
-foreach $entry ($result->​entries) { +
- @addrs = $entry->​get_value('​proxyAddresses'​);​ +
- $obj = $entry->​get_value('​sAMAccountName'​);​ +
- foreach $mail (@addrs) { +
- check_domain($mail);​ +
- unless (check_mail($mail,​$obj,​%aliases)) { +
- $aliases{$mail} = $obj; +
- say ALIASES "​$mail\t$obj";​ +
-+
-+
-+
- +
-@valid_users = values %aliases; +
- +
-+
-## Группы  +
-+
- +
-# Проверяет вхождение элемента в массив. Короче - оператор in))) +
-sub check_element { +
- @_ > 1 or die "​check_element - OOPS!\n";​ +
- $element = shift @_; +
- @arr = @_; +
- foreach (@arr) { +
- if ($_ eq $element) { return 1 } +
-+
- return 0; +
-+
- +
-# Удаляет из массива повторяющиеся элементы +
-sub delete_duplicates { +
- my $el = undef; +
- my @result; +
- foreach (sort @_) { +
- if ($_ ne $el) { push @result, $_ } +
- $el = $_; +
-+
- return @result; +
-+
- +
-# Рекурсивно выбиряет по предоставленному DN всех пользователей. +
-# Нужно для выборки по DN группы всех входящих в неё пользвоателей +
-sub get_users { +
- @_ == 1 or die "​get_users - OOPS!\n";​ +
-  +
- my $base = $_[0]; +
- my $result = $ldap->​search( +
- base => $base, +
- scope => "​base",​ +
- filter => "​objectClass=*"​ ); +
- my $ent = $result->​entry(0);​ +
- +
- my @users = (); +
- if ( check_element("​user",​ $ent->​get_value("​objectClass"​)) ) { +
- push @users, ​ $ent->​get_value("​sAMAccountName"​);​ +
- } elsif ( check_element("​group",​ $ent->​get_value("​objectClass"​)) ) { +
- foreach my $member ($ent->​get_value("​member"​)) { +
- push @users, get_users($member);​ +
-+
-+
- return @users; +
-+
- +
-# Параметры поиска для групп +
-$filter = '​(&​(objectClass=group)(|(proxyAddresses=*)(mail=*)))';​ +
-$attrs = ['​member','​proxyAddresses','​mail','​sAMAccountName'​];​ +
- +
-# LDAP запрос +
-$result = $ldap->​search( +
- base => $AD_base, +
- filter => $filter, +
- attrs => $attrs); +
- +
-foreach $entry ($result->​entries) { +
- @mails = (); +
- push @mails, $entry->​get_value("​mail"​),​ $entry->​get_value("​proxyAddresses"​);​ +
- $obj = $entry->​get_value('​sAMAccountName'​);​ +
- +
- @users = (); +
- foreach $member ($entry->​get_value("​member"​)) { +
- push @users, get_users($member);​ +
-+
- @users = delete_duplicates(@users);​ +
- push @valid_users,​ @users; +
- if (! @users) {  +
- say "​WARNING:​ empty group ",​$entry->​dn;​ +
- next; +
-+
- +
- foreach $mail (@mails) { +
- check_domain($mail);​ +
- unless (check_mail($mail,​$obj,​%aliases)) { +
- $aliases{$mail} = $obj; +
- say ALIASES "​$mail\t",​ join(",​ ",​@users);​  +
- +
-+
-+
-+
- +
-# Открываем файл пользователей и пишем туда всех пользователей с почтовыми ящиками +
-open USERS, ">​$users_file"​ or die "​Can'​t open $users_file\n";​ +
- +
-@valid_users = delete_duplicates(@valid_users);​ +
-foreach (@valid_users) { +
- say USERS "​$_\tdovecot";​ +
-+
- +
-close USERS; +
- +
-# Close aliases file +
-close ALIASES; +
- +
-# Close connection to LDAP +
-$msg = $ldap->​unbind;​ +
- +
-`postmap hash:​$aliases_file`;​ +
-`postmap hash:​$users_file`;​ +
-</​code>​ +
- +
-Поменяйте в скрипте необходимые параметры (все они собраны в начале) и поставьте его выполняться через ''​cron''​. В принципе,​ Postfix трогать больше не потребуется. +
- +
-==== Настройка Dovecot ==== +
- +
-При настройке Dovecot в первую очередь нужно не забыть выставить сокет авторизации для Postfix, как это делать описано в статье про [[Dovecot]]. +
- +
-Теперь нужно указать механизмы авторизации. Мы будем использовать только PLAIN LOGIN, то есть механизмы с открытой передачей пароля. Правда при этом потребуем обязательного TLS шифрования,​ что обезопасит пользователей от кражи их аккаунтов. Некоторые говорят,​ что использование PLAIN небезопастно,​ однако тут надо учесть один немаловажный факт: при использовании PLAIN авторизации вы можете хранить пароли в виде хешей, а при использовании "​безопасных"​ методов вам придётся хранить все данные о пользователях открытым текстом. При этом PLAIN авторизацию можно обернуть в TLS шифрование,​ что обезопасит этот механизм,​ а гарантированно защитить базу паролей на сервере вы не сможете. В общем и целом - всегда используйте PLAIN с TLS шифрованием и храните все пароли в виде хешей. +
- +
-Тем более нам надо соединяться с AD и предоставлять ему определять правильность пароля,​ так что нам в любом случае нужен PLAIN механизм авторизации. +
- +
-Итак, в Dovecot авторизация должна быть настроена примерно следующим образом:​ +
- +
-<​file>​ +
-# Эта опция обязательна! Она требует TLS шифрования для PLAIN авторизации,​ без неё безопастность будет на 0 +
-disable_plaintext_auth = yes +
-# Включаем шифрование +
-ssl_disable = no +
-# Собственно описание механизма авторизации +
-auth default { +
-  # Поддерживаемые типы. Тут не должно быть ничего кроме plain и login +
-  mechanisms = plain login +
- +
-  # База паролей +
-  passdb ldap { +
-    args = /​etc/​dovecot/​dovecot-ldap-passdb.conf +
-  } +
-   +
-  # База пользователей +
-  userdb ldap { +
-    args = /​etc/​dovecot/​dovecot-ldap-userdb.conf +
-  } +
- +
-  # Пользователь,​ имеющий доступ к ящикам и сокету авторизации +
-  user = postfix-vuser +
-   +
-  # Сокеты +
-  socket listen { +
-    master { +
-      path = /​var/​run/​dovecot/​auth-master +
-      mode = 0600 +
-      user = postfix-vuser  +
-      group = postfix-vuser +
-    } +
-    client { +
-      path = /​var/​spool/​postfix/​private/​auth-client +
-      mode = 0660 +
-      user = postfix +
-      group = postfix +
-    } +
-  } +
-+
-</​file>​ +
- +
-Подробнее можно почитать с статье про [[Dovecot]]. Нас тут интересует использование LDAP в качестве базы пользователей и паролей. Кстати,​ сразу хочу сказать,​ файл dovecot-ldap-userdb.conf должен быть симлинком на dovecot-ldap-passdb.conf. То есть фактически это один и тот же файл. Такое разделение связано с механизмами обращения к LDAP в Dovecot, подробней см. в документации. +
- +
-Теперь содержимое dovecot-ldap-userdb.conf:​ +
- +
-<​file>​ +
-uris = ldap://​192.168.6.22 +
- +
-# LDAP account +
-dn = ldap-user@dncm.ru  +
-dnpass = Passw0rd +
- +
-# LDAP settings +
-ldap_version = 3 +
-base = ou=var, dc=dncm, dc=ru +
-scope = subtree +
- +
-# Password check  +
-auth_bind = yes +
-auth_bind_userdn = %n@dncm.ru +
-pass_filter = (&​(objectCategory=Person)(sAMAccountName=%n)) +
- +
-# Users check +
-user_filter = (&​(objectCategory=Person)(sAMAccountName=%n)) +
-user_global_uid = 900 +
-user_global_gid = 900 +
-</​file>​ +
- +