Виртуальный хостинг (поддержка более чем одного домена на одном
физическом сервере) -- одно из главных направлений деятельности многих
ISP, при этом в качестве программного обеспечения сервера Web, как
правило, используется Apache. Однако это только одна сторона медали,
кроме этого, клиенты должны иметь доступ для управления собственным
Web-сайтом.
Перед началом работ мы сформулировали для себя два основных
требования:
1. информация заказчика должна храниться в гибкой форме, обеспечивая
удобство управления;
2. сервер ftp должен быть устойчивым и защищенным и ограничивать
доступ пользователей, при обращениях к нашему специфическому
хранилищу информации, пределами их домашнего каталога. Для работы
с этим ресурсом разрешен только протокол ftp, что не дает
возможности пользователям применять другие инструменты управления
(telnet и др.).
Ранее сведения о пользователях сохранялись с помощью типичной для UNIX
системы хранения паролей, но нам хотелось бы уйти от этой практики. В
качестве механизма для хранения информации о пользователе мы решили
использовать LDAP (Lightweight Directory Access Protocol). LDAP --
широко применяемый для целей аутентификации протокол, для которого
написаны интерфейсные модули на большом количестве языков
программирования. Нашей целью стала разработка средств управления на
языке Perl.
Установка и использование OpenLDAP
LDAP -- это протокол для доступа к службе каталогов в архитектуре
клиент-сервер. Он берет свое начало от X.500, но сегодня он может
использоваться для доступа и к другим службам каталогов. Нам
требовался пакет "все в одном", где бы наряду с собственно
протоколом был реализован механизм хранения баз данных. Мы выбрали
наиболее позднюю из стабильных версий OpenLDAP (1.2.11) для среды
Linux 2.2.x. Предполагалось, что единственной целью системы будет
аутентификация пользователей ftp; таким образом, разработка базы
данных значительно упрощалась. Интеграция этих функций в уже
существующую базу данных LDAP потребовала бы большего времени и сил.
Процесс установки происходил в соответствии со стандартной
документацией, которую можно найти по адресу:
http://www.openldap.org/ -- там же находятся соответствующие
исходные коды программ.
Файл slapd.conf -- основной конфигурационный файл для slapd (slapd --
это сервер LDAP в проекте OpenLDAP). В нем есть три директивы, на
которые надо обратить внимание:
В этих директивах rootdn и rootpw -- имя и пароль пользователя,
которые необходимы для доступа к базе данных, о чем будет рассказано
позже. Строки, приведенные выше, -- это просто пример задания
директив; на самом деле рекомендуется использовать зашифрованный
пароль -- в документации вы найдете соответствующие указания.
При установке пакета уделите должное внимание ограничению доступа. По
умолчанию ваша база данных может быть доступна для любого компьютера,
который подключен к Internet. Таким образом, необходимо корректно
определить параметры доступа и установить, где необходимо, различные
фильтры и экраны для того, чтобы ситуация оставалась под контролем.
После того как slapd установлен и запущен, следующая ключевая проблема
-- создание класса объектов для хранения учетных записей
пользователей. На данном этапе схема работы с OpenLDAP может быть
расширена для настройки базы данных под нужды конкретной задачи (LDAP
использует концепции классов и объектов вместо таких элементов, как
поля и таблицы реляционных баз данных).
Нам было важно создать формат данных, который был бы понятен нашему
серверу ftp. Мы воспользовались рекомендуемой Джоном Моррисси
конфигурацией для модуля mod_ldap ProFTPD, которая более подробно
описана ниже.
В результате содержимое нашего файла local.oc.conf выглядело следующим
образом:
Многие из указанных атрибутов хорошо знакомы системным
администраторам, хотя это, возможно, не касается атрибута cn. Это
сокращение означает common name (общее имя). В данном классе мы
используем его для хранения имени домена. Поскольку наша конфигурация
ориентирована на домены, в любой работе администратор, скорее всего,
будет использовать имя домена, например, для поиска.
В вышеприведенной схеме каждый домен, о котором знает система, имеет
соответствующую учетную запись на сервере ftp (имя домена -- cn, имя
ftp-записи -- uid). Каждый домен имеет по одной учетной записи.
Ниже приведена краткая суммарная информация об атрибутах класса:
objectclass -- класс элемента (ftpAccount);
cn -- имя домена (описывалось ранее);
uid -- имя учетной записи ftp;
userPassword -- пароль для аутентификации на сервере ftp (см. ниже);
accountStatus -- атрибут для административных целей (открыт?, оплата
позднее? и т. д.);
loginShell -- не используется (поскольку пользователи не имеют доступа
к оболочке);
Обратите внимание, что атрибуты uidNumber и gidNumber не применяются,
поскольку вместо них мы используем значения, заданные при конфигурации
нашего ftp-сервера. Детали приведены ниже.
В главном конфигурационном файле сервера slapd с именем slapd.conf
необходимо указать ссылку на local.oc.conf следующим образом:
include /usr/local/etc/openldap/local.oc.conf
Это все, что требуется для того, чтобы наш новый класс "ожил". Надо
помнить только одну вещь -- наша база данных еще не содержит ни одной
реальной учетной записи.
Заполнение базы данных
Во-первых, имеющаяся информация об обслуживаемых доменах была
экспортирована в файл формата CSV. Типичная строка такого файла:
где поля содержат: имя домена; имя учетной записи, используемый для
загрузки файлов по ftp; шифрованный пароль для данной записи; домашний
каталог (где хранятся страницы Web).
Затем был написан сценарий на языке Perl, который считывал данные из
файла CSV и создавал соответствующие записи в базе данных LDAP. Это
сценарий domains2ldap (см. Листинг 2). Если вы будете его
использовать, отредактируйте в соответствии со своими потребностями.
Прежде всего, необходимо изменить информацию о пользователе, который
имеет право вносить изменения в базу данных, и о том, где находится
база данных. Для этого потребуется Net::LDAP. Он доступен по адресу:
http://www.cpan.org (сервер CPAN), под именем perl-ldap. Я
использовал версию 0.22.
Управление базой данных вручную
Помимо сценария OpenLDAP поставляется с некоторыми инструментами для
работы с базой данных.
Для того чтобы добавить новую запись вручную, в файл /tmp/add.tmp
следует поместить что-нибудь вроде нижеприведенного:
Данный пример составлен для виртуального сервера Web
www.foobar.com с доступом через ftp по учетной записи ftpfoo.
Пароль хранится в шифрованной форме, но, вместо этого, вы можете
использовать обычный текст, предварив его ключевым словом {clear}.
(Некоторые вопросы, связанные с данной конфигурацией, мы обсудим
ниже.)
Параметр -D должен ссылаться на пользователя с правом добавления
данных. В типичном случае этот параметр идентичен параметру rootdn,
который пояснялся ранее при описании файла slapd.conf. Далее, параметр
-W -- это пароль для пользователя rootdn, который хранится в rootpw.
Такая команда выполняет добавление записи в базу данных от имени
пользователя Admin, которому предоставлены требуемые права.
Уничтожить запись еще проще. Следующая команда удаляет запись,
созданную предыдущей строкой.
Для получения более подробной информации об этих командах (и о команде
ldapmodify) используйте документацию.
Связывание с сервером FTP
В качестве сервера ftp мы выбрали ProFTPD
(http://www.proftpd.org/). Он надежен, удобен в конфигурировании и
(как ранее упоминалось) имеет модуль, с помощью которого пользователи
могут быть аутентифицированы через LDAP.
Сначала мы установили версию 1.2.0rc2, но столкнулись с проблемами в
имевшейся версии модуля mod_ldap -- он просто не работал. Ситуация
была разрешена получением обновленной версии от автора модуля по
адресу: http://horde.net/~jwm/software/proftpd-ldap/
После копирования нового модуля в каталог contrib дерева исходных
текстов ProFTPD, система была с.компилирована следующим образом:
./configure -with-modules=mod ldap
make
make install
Архитектура вашей системы может потребовать внесения некоторых
изменений, для чего будет полезна документация на сервере Web ProFTPD.
Ниже приведены ключевые элементы конфигурационного файла ProFTPD
(proftpd.conf), требующиеся для выполнения аутентификации на базе
LDAP:
LDAPServer ldap.your-domain.com
LDAPDNInfo "cn=Admin,dc=your-domain,dc=com" "your-secret-password"
LDAPDoAuth on "dc=your-domain,dc=com" "uid=%u"
LDAPDefaultAuthScheme "crypt"
LDAPDoUIDLookups off
LDAPDoGIDLookups off
LDAPNegativeCache on
LDAPDefaultGID 50
LDAPDefaultUID 50
В нашем случае все домашние каталоги учетных записей принадлежали
одной обобщенной комбинации пользователь/группа -- весь доступ
определялся ProFTPD. Таким образом, просмотр был запрещен, и
сконфигурированы GID и UID, используемые по умолчанию. Кроме того, по
умолчанию пароль является зашифрованным. Если вы внимательно
просмотрите domain2ldap (см. Листинг 2), то увидите, что импортируемые
(зашифрованные) пароли предваряются ключевым словом {crypt}. В этом
нет непосредственной необходимости -- что следует из строки
LDAPDefault-AuthScheme, -- но неплохо бы заранее подумать о том, что
может случиться (например, однажды понадобится использовать простые
текстовые пароли).
На данном этапе все должно идти как по маслу. Если это не так,
проверьте регистрационные журналы (logs) обоих серверов -- ProFTPD и
slapd, вдруг вы заметите очевидные ошибки. К сожалению, в нашем случае
причина неработоспособности модуля mod_ldap не лежала на поверхности:
поиск по базе данных LDAP проходил успешно, вот только ProFTPD каждый
раз во время аутентификации пользователя упорно отвечал отказом.
Некоторые замечения о виртуальном хостинге
Как показано в данной статье, доступ к каталогам при виртуальном
хостинге осуществляется на основе параметров "имя
пользователя/пароль". Все пользователи оповещаются о том, с каким
хостом они будут работать. Кроме того, для упрощения доступа мы
добавляем в DNS запись ftpadmin.their-domain.com, поскольку размещаем
у себя и пользовательские DNS.
В каждом домене было бы хорошо использовать отдельные базы данных
аутентификации. В большинстве случаев не получается выделить каждому
сайту Web отдельный IP-адрес, более подходящим кажется применение
основанного на имени (Named-Based) виртуального хостинга Apache, что
дает возможность пользователям иметь свои, отдельные анонимные
ftp-сайты, служащие для загрузки информации (но работающие физически
на том же сервере).
К сожалению, такая возможность не поддерживается протоколом ftp, в
котором отсутствует эквивалент системы Host-Header протокола HTTP.
Таким образом, сервер не способен определить, в какой конкретный домен
пользователь хочет получить доступ, если домены используют один и тот
же IP-адрес.