Игорь Полянский
В данной статье речь пойдет о том, как управлять единой учетной записью
пользователя посредством MS Active Directory вне зависимости от того, на какой
платформе он работает, будь то Windows или UNIX-подобные системы. Забегая
вперед, скажу, что если с Windows-клиентами все ясно, то интеграция с каталогом
от Microsoft тем способом, который будет здесь описан, подходит не для всех
UNIX-подобных операционных систем. Так уж сложилось – все они разные, да и Active
Directory вовсе не идеальная среда для интеграции разнородных систем. Тогда
зачем я все это пишу? А за тем, что очень многие организации изначально
ориентированы на платформу Windows и в качестве каталога применяют Active Directory,
а когда в сети начинает появляться UNIX, то встает вопрос об интеграции, и не
всегда хорошие коммерческие решения подходят, либо из-за стоимости, либо в силу
других причин. Я изначально рассматривал вариант с ведением второго каталога
для UNIX-клиентов на базе OpenLdap, но хотелось все-таки управлять учетными
записями из единой точки, а именно из Active Directory, потому что этот каталог
широко используется у нас в сети.
Вариант Samba + winbind меня не устраивал,
поскольку по роду задач samba вообще не нужна, к тому же это лишние службы на
каждой машине, использование которых все-таки не решает проблем с
централизованным управлением пользовательскими данными, поэтому это решение мне
показалось неразумным и неизящным.
Более всего привлекал вариант с использованием
сервера NIS, который входит в продукт, известный как Services For Unix от
компании Microsoft и синхронизация записей Active Directory to NIS. Зайдя на
microsoft.com в надежде скачать SFU3.5, которая в отличие от предыдущей версии
SFU3.0 бесплатна, я набрел на ряд интересных статей, прочитав которые, пошел по
другому пути.
Как уже говорилось в начале, не все UNIX-подобные
системы могут проходить аутентификацию и запрашивать данные о пользователе в Active
Directory описанным здесь способом, а только те, которые умеют работать с PAM и
pam-модулями. Как вы, наверное, догадались, я буду описывать способ
взаимодействия с ldap-сервером, входящим в Active Directory через модули pam_ldap
и nss_ldap.
Итак, начнем. В качестве подопытных будут
выступать MS Windows 2000 Server Standart с установленной Active Directory (в
дальнейшем AD), Linux Manrdake 10.0, Solaris 9 x86, FreeBSD 4.10. Над Windows
2000/XP опыты ставить бессмысленно – все и так работает. Как минимум
понадобится DNS-сервер, который может быть установлен на том же Windows 2000 Server.
Свежеустановленная AD не имеет традиционной ldap-схемы для UNIX: userid, grouid,
login shell, home directory. Нам нужно её расширить, и для этого я воспользуюсь
SFU3.5. Вообще-то существует несколько способов это сделать: вручную создав
ldif-файл с нужной схемой и импортировав его при помощи каких-либо программ
сторонних разработчиков, например такой, как AD4Unix (www.padl.com/download/MKSADPlugins.msi),
или с помощью SFU от Microsoft. Первый способ я оставляю гуру, вышеозначенную
программу MKSADPlugins.msi вам установить вряд ли удастся, если Windows 2000 Server
работает с альтернативной локалью, отличной от US, что для России уместно. В
пользу же SFU, на мой взгляд, говорит то, что она сделана в том же КБ, где Windows
и AD, плюс в своем составе имеет много утилит от UNIX.
Пройдя добровольно-принудительную процедуру
получения .NET Passport, вы сможете бесплатно скачать и использовать SFU3.5 (www.microsoft.com/windows/sfu).
Размер программы примерно 230 Мб. Прежде чем устанавливать SFU, нужно
инсталлировать Active Directory Schema MMC snap-in следующей командой:
regsvr32
с:\WINNT\system32\schmmgmt.dll
Для расширения схемы AD достаточно установить
только NIS-сервер из состава SFU. Для успешного завершения установки необходимо
быть либо членом групп Domain Admins и Schema Admins, либо работать с правами
Администратора. После установки будет предложено перегрузить машину. NIS-сервер
как таковой не понадобится и его можно остановить и благополучно забыть о нём.
В свойствах пользователя, группы, компьютера в Active Directory Users and Computers
добавится вкладка UNIX Attributes.

Как видите, теперь у каждого пользователя есть
атрибуты, применяемые в UNIX-системах. Первое поле «NIS Domain» будет содержать
краткую форму имени нашего домена. Этот параметр нужен для службы NIS, и хотя в
нашем случае она не применяется, без нее не активируются другие поля. С
остальными полями, я думаю, затруднений не возникнет, может быть, за
исключением GID. Прежде чем выбрать из этого поля группу, её надо создать или в
свойствах уже имеющейся задать UNIX-атрибуты. Проблема с группами заключается в
том, что нельзя задать одно и то же имя для пользователя и группы, а в мире
UNIX такой подход весьма распространен. В таком случае можно использовать
только численное представление, правда, я сомневаюсь, что это хороший выход из
создавшейся ситуации. Ещё потребуется создать учетную запись, которая будет
применяться для взаимодействия UNIX-машин с ldap-сервером. Это своего рода дыра
в безопасности, поэтому сей аккаунт не должен принадлежать кому-либо и доступ к
важным ресурсам ему должен быть запрещен. Тем не менее он должен иметь право на
поиск объектов в каталоге. На этом этапе вы готовы управлять единой учетной
записью при помощи Active Directory.
Переходим к настройке клиентских машин. Я
использовал Linux Mandrake 10.0 Official и всё необходимое ПО устанавливал из
rpm-пакетов, входивших в состав дистрибутива. Понадобится установить pam_ldap и
nss_ldap. После установки этих пакетов нужно отредактировать несколько
конфигурационных файлов. Pam_ldap и nss_ldap для настроек используют один и тот
же файл ldap.conf. Также нужно будет отредактировать nsswitch.conf и как
минимум один файл, находящийся в /etc/pam.d, а именно system-auth. Не забудьте
сделать копии оригинальных файлов. Итак, файл ldap.conf должен содержать
следующее:
# Базовые настройки,
необходимые для подключения к AD. domain, loc и server.domain.loc вы должны
изменить
# в соответствии со своими
настройками
base dc=domain,dc=loc
scope sub
uri ldap://server.domain.loc
port 389
ldap_version 3
# Тот самый аккаунт, как
видите, он был создан в контейнере Users с именем ldap и паролем qwerty
binddn cn=ldap,cn=Users,dc=domain,dc=loc
bindpw qwerty
# Когда вы будете вводить имя
пользователя и пароль, будут применяться следующие объекты и атрибуты из AD:
pam_filter objectclass=User
pam_login_attribute sAMAccountName
pam_password ad
# Эти записи нужны для
ускорения поиска. Можете их вообще не вставлять. Обратите внимание, все
пользователи в этом
# примере хранятся в «Organization
Unit –> firma»
nss_base_passwd ou=firma,dc=domain,dc=loc?sub
nss_base_shadow ou=firma,dc=domain,dc=loc?sub
nss_base_group ou=firma,dc=domain,dc=loc?sub
# Эти записи относятся к
модулю nss_ldap, преображают объекты и атрибуты AD к виду, принятому в LDAP
nss_map_objectclass posixAccount
User
nss_map_objectclass shadowAccount
User
nss_map_attribute uid sAMAccountName
nss_map_attribute uidNumber
msSFU30UidNumber
nss_map_attribute gidNumber
msSFU30GidNumber
nss_map_attribute cn sAMAccountName
nss_map_attribute uniqueMember
member
nss_map_attribute homeDirectory
msSFU30HomeDirectory
nss_map_attribute loginShell
msSFU30LoginShell
nss_map_attribute gecos name
nss_map_objectclass posixGroup
Group
Далее на очереди файл nsswitch.conf, тут всё просто – находите строчки:
passwd: files nisplus
nis
shadow: files nisplus
nis
group: files nisplus nis
и меняете их на:
passwd: files ldap
shadow: files ldap
group: files ldap
Редактируем файл /etc/pam.d/system-auth:
#%PAM-1.0
auth required pam_env.so
auth sufficient pam_unix.so
likeauth nullok
auth sufficient /lib/security/pam_ldap.so
use_first_pass
auth required pam_deny.so
account required pam_unix.so
account [default=bad success=ok
user_unknown=ignore service_err=ignore system_err=ignore] lib/security/pam_ldap.so
password required
pam_cracklib.so retry=3 minlen=2 dcredit=0 ucredit=0 ucredit=0
password sufficient pam_unix.so
nullok use_authtok md5 shadow
password sufficient /lib/security/pam_ldap.so
use_authtok
password required pam_deny.so
session required pam_limits.so
session required pam_unix.so
session required /lib/security/pam_mkhomedir.so
skel=/etc/skel umask=0022
session optional /lib/security/pam_ldap.so
В этом примере строчки, содержащие модуль pam_ldap.so,
были добавлены в соответствии с рекомендациями Microsoft. Суть их такова, что
сначала система применяет правила для локального пользователя, если такой
учетной записи нет, то информация берется из AD. Но есть одна маленькая
проблема, которая может стать большой. Дело в том, что домашний каталог
автоматически не создается и по умолчанию таковым считается /. Вам придется
создавать домашние каталоги руками на каждой машине, что не очень удобно. Для
этого можно использовать модуль pam_mkhomedir. При регистрации в данной системе
модуль смотрит, есть ли домашний каталог, если нет, то он его создает и
копирует туда файлы из /etc/skel. Вы можете в соответствии со своими
требованиями менять и порядок модулей, и их опции для разных служб. В таких
перестановках надо быть осторожным, потому как можно прийти к неожиданным
результатам вплоть до невозможности регистрироваться в системе даже под учетной
записью root. Для начала логично почитать что-нибудь о PAM. После этих
манипуляций можно попробовать зарегистрироваться на Linux-машине пользователем,
который не упоминается в файлах passwd, shadow, group, но его UNIX-атрибуты
присутствуют в AD.
Если всё прошло отлично, то при первом входе
среди прочих надписей увидим следующее:
Creating directory
'/home/test'.
Creating directory
'/home/test/tmp'.
Посмотрим, кем нас считает система:
[test@linux-pc test]$
id
uid=10000(test)
gid=10000(testgroup) groups=10000(testgroup)
Настраиваем Solaris 9 x86. В Solaris есть свои модули pam_ldap
и nss_ldap, только вот незадача – они не совсем совместимы с Active Directory,
поэтому Microsoft рекомендует использовать модули от PADL (www.padl.com), те
же, что применяются в Linux. Чтобы скомпилировать эти модули, потребуется
установить ряд GNU-утилит, получить их можно на www.sunfreeware.com. Оглашаю
весь список:
n autoconf-2.57-sol9-intel-local.gz
n automake-1.7.2-sol9-intel-local.gz
n gcc-3.2.1-sol9-intel-local.gz
n m4-1.4-sol9-intel-local.gz
n make-3.80-sol9-intel-local.gz
Плюс к этому берем с сайта www.blastwave.org пакет
berkeleydb3-3.11-i386-CSW.pkg.gz.
Перед тем как собирать pam_ldap и nss_ldap,
создадим символическую ссылку в /usr/local/bin на perl:
ln -s /usr/bin/perl /usr/local/bin/perl
На файлы из каталогов /opt/csw/bin, /opt/csw/lib,
/opt/csw/include, созданные в процессе инсталляции
berkeleydb3-3.11-i386-CSW.pkg.gz, сделаем символические ссылки в аналогичные
каталоги, расположенные в /usr. Сделаем резервную копию оригинальных модулей pam_ldap
и nss_ldap:
cp /usr/lib/security/pam_ldap.so.1
/usr/lib/security/pam_ldap.so.1.bak;
cp /usr/lib/nss_ldap.so.1 /usr/lib/nss_ldap.so.1.bak
Объявим переменные среды:
PATH=/usr/local/bin:$PATH
LD_LIBRARY_PATH=/usr/local/lib
export LD_LIBRARY_PATH
Это сработает для оболочек, совместимых по
синтаксису с sh, например, bash, ksh. Если вы пользуетесь другим
интерпретатором, посмотрите документацию к нему.
Соберем модули от PADL, перейдя в соответствующие
директории, созданные в процессе разархивации файлов, полученных с www.padl.com/download:
cd pam_ldap-176
./configure
make
make install
cd nss_ldap-226
./configure --enable-schema-mapping
make
make install
Если все прошло удачно, редактируем ldap.conf и nsswitch.conf
аналогично Linux, за исключением строчки:
uri ldap://server.domain.loc
которую заменим на:
host server.domain.loc
Linux воспринимает оба формата, Solaris почему-то
только host. Настройки PAM в Solaris хранятся в файле /etc/pam.conf. На этом
этапе, следуя советам Microsoft, я получил неработоспособную систему, поэтому
кое-что поменял и добавил (представлены фрагменты с внесенными изменениями):
# login service (explicit because
of pam_dial_auth)
login auth requisite pam_authtok_get.so.1
login auth required pam_dhkeys.so.1
login auth sufficient pam_unix_auth.so.1
login auth required pam_dial_auth.so.1
login auth sufficient pam_ldap.so.1
use_first_pass
# Default definitions for Authentication
management
# Used when service name is not
explicitly mentioned for authenctication
other auth requisite pam_authtok_get.so.1
other auth required pam_dhkeys.so.1
other auth sufficient pam_unix_auth.so.1
other auth sufficien pam_ldap.so.1
use_first_pass
# Default definition for Session
management
# Used when service name is not
explicitly mentioned for session management
other session required
pam_unix_session.so.1
other session sufficient pam_mkhomedir.so
skel=/etc/skel/ umask=0022
# Default definition for Password
management
# Used when service name is not
explicitly mentioned for password management
other password required
pam_dhkeys.so.1
other password requisite
pam_authtok_get.so.1
other password requisite
pam_authtok_check.so.1
other password required
pam_authtok_store.so.1
other password sufficient
pam_ldap.so.1 use_authtok
Здесь смысл примерно такой же,
как и в случае с Linux. Pam_mkhomedir для Solaris не существует, но его можно
собрать самостоятельно. Я следовал инструкциям на http://keutel.de/pam_mkhomedir и
получил работоспособный модуль, проделав следующие шаги на машине с Solaris:
n Скачал и распаковал исходный код Linux-PAM: http://www.kernel.org/pub/linux/libs/pam/pre/library/Linux-PAM-0.77.tar.gz,
допустим, в /tmp.
n Скачал исходный код: http://keutel.de/pam_mkhomedir/pam_mkhomedir.c
тоже в /tmp и скомпилировал следующей командой (в одну строчку), находясь в /tmp:
/usr/local/bin/gcc
-D_REENTRANT -g -O2 -Wall -fPIC -c -ILinux-PAM-0.77/libpam/include
-ILinux-PAM-0.77/libpamc/include \
-ILinux-PAM-0.77/modules/pammodutil/include
-DPAM_DYNAMIC pam_mkhomedir.c -o pam_mkhomedir.o
n Получил готовый модуль следующей командой:
/usr/ccs/bin/ld -o pam_mkhomedir.so
-B dynamic -G -lc pam_mkhomedir.o
К сожалению, FreeBSD 4.x не умеет работать с nss_ldap
и значит запрашивать данные о пользователе в AD, плюс не может менять пароль
стандартными средствами с помощью pam_ldap. Но всё же доступ к машине, как с
консоли, так и к службам ssh, ftp и т. д. можно получить, пройдя аутентификацию
в Active Directory. Для этого установите pam_ldap, отредактируйте два файла – ldap.conf
и pam.conf. В ldap.conf достаточно внести следующий фрагмент:
base dc=domain,dc=loc
scope sub
uri ldap://server.domain.loc
port 389
ldap_version 3
binddn cn=ldap,cn=Users,dc=domain,dc=loc
bindpw qwerty
pam_filter objectclass=User
pam_login_attribute sAMAccountName
pam_password ad
В этом случае пароль из AD будет запрашиваться
при входе с консоли, ftp и ssh, если пароль отвергнут, поиск будет продолжен в
локальных файлах.
login auth sufficient /usr/local/lib/pam_ldap.so
login auth sufficient pam_skey.so
login auth sufficient pam_opie.so no_fake_prompts
#login auth requisite pam_opieaccess.so
login auth requisite pam_cleartext_pass_ok.so
#login auth sufficient pam_kerberosIV.so
try_first_pass
#login auth sufficient pam_krb5.so try_first_pass
login auth required pam_unix.so try_first_pass
login account required pam_unix.so
login password required pam_permit.so
login session required pam_permit.so
# Same requirement for ftpd as
login
ftpd auth sufficient /usr/local/lib/pam_ldap.so
ftpd auth sufficient pam_skey.so
ftpd auth sufficient pam_opie.so no_fake_prompts
#ftpd auth requisite pam_opieaccess.so
ftpd auth requisite pam_cleartext_pass_ok.so
#ftpd auth sufficient pam_kerberosIV.so
try_first_pass
#ftpd auth sufficient pam_krb5.so try_first_pass
ftpd auth required pam_unix.so try_first_pass
# OpenSSH with PAM support requires
similar modules.
# The session one is a bit strange,
though...
sshd auth sufficient /usr/local/lib/pam_ldap.so
sshd auth sufficient pam_skey.so
sshd auth sufficient pam_opie.so no_fake_prompts
#sshd auth requisite pam_opieaccess.so
#sshd auth sufficient pam_kerberosIV.so
try_first_pass
#sshd auth
sufficient pam_krb5.so try_first_pass
sshd auth required pam_unix.so try_first_pass
sshd account required pam_unix.so
sshd password required pam_permit.so
sshd session required pam_permit.so
Локально пароль можно вообще не хранить. Для
этого при помощи команды vipw отредактируйте файл паролей. Сотрите
зашифрованный пароль во втором поле и поставьте там * (звёздочка).
По сведениям, взятым на http://www.padl.com/OSS/nss_ldap.html,
FreeBSD 5.1 и выше уже работает с nss_ldap, но проверить это лично не удалось
по причине отсутствия дистрибутива.
Осталось прикрутить SSL. Хотя это вовсе не
обязательно, наверняка вы захотите использовать шифрование по двум причинам.
Первая – безопасность, ведь запросы к ldap, в том числе пароли, передаются в
открытом виде, вторая – возможность пользователю самому менять пароль в AD
посредством стандартной команды passwd. Необходимо проделать некоторые
операции, как на Windows-сервере, так и на клиентских машинах.
На сервере:
n Убедиться, что поддерживается шифрование 128 bit,
иначе вы не сможете удаленно поменять пароль. Windows 2000 sp2 и выше это
умеет, в противном случае установите Encryption pack.
n Установить сервис сертификатов, входящий в
дистрибутив. Без этого сервер не будет принимать соединения по протоколу ldaps.
В процессе инсталляции сервиса сертификатов будет предложено создать корневой
сертификат. Заполнив поля (можно не все), вы получите файл сертификата, лежащий
в директории с:\. Делать с ним ничего не придется. В журнале событий (event viewer)
должна появиться запись о возможности принятия соединений LDAPS (прим.: у меня
это сообщение появилось на следующий день, может, потому, что я не перегружал
машину, а до этого все попытки коннекта на ldaps:636 терпели неудачу).
Проверить, что сервер работает корректно, можно простым способом. С любой
Windows-машины в домене или на самом сервере выполните «Start –> Search
–> For People».

В свойствах укажите адрес сервера, порт 636,
контейнер для поиска.
В данном примере мы ищем объекты в контейнере Users.
Если поиск завершился успехом, значит ваш сервер настроен на прием запросов по
протоколу LDAPS порт 636.
На клиенте:
Самым простым решением для меня оказалось
использование программы stunnel. После установки stunnel нужно поправить два
файла stunnel.conf и ldap.conf. Stunnel.conf может выглядеть так:
chroot = /var/tmp/stunnel
pid = /stunnel.pid
setuid = stunnel
setgid = stunnel
# Some debugging stuff
debug = 7
output = /var/log/stunnel.log
# Use it for client mode
client = yes
# Service-level configuration
[ldap]
accept = 127.0.0.1:389
connect =
server.domain.loc:636
Из данного примера мы видим – stunnel работает в
клиентском режиме, слушает запросы на 127.0.0.1 порт 389 и пересылает их на
Windows-сервер порт 636 уже в зашифрованном виде. В зависимости от операционной
системы вам придется вручную создать пользователя stunnel и каталог /var/tmp/stunnel
с возможностью записи для этого пользователя. В файле ldap.conf просто поменяем
строчку:
ri ldap://server.domain.loc
на
host 127.0.0.1
Перегружаем машину, регистрируемся, пробуем
менять пароль. Параллельно tcpdump на другом терминале можно наблюдать наши
SSL-соединения.
В результате мы имеем централизованную систему
управления пользователями средствами Active Directory, что значительно
облегчает работу администратора. Интеграция таким способом позволяет внедрить
UNIX-системы в существующую структуру Windows-сетей и при этом отказаться от
ведения дополнительных каталогов или хранения пользовательских данных на каждой
машине.
