МАРК КРИЧМАР
Интеграция SQUID + LDAP
О настройках самого сервера LDAP написано достаточно много, поэтому останавливаться на этом не буду. Интеграция службы каталогов с разными службами освещена тоже достаточно подробно, см., например: http://www.linuxrsp.ru/artic/LDAP-HOWTO.html.
В этой статье я не нашел, как подружить proxy-сервер SQUID с вышеозначенной службой, это и сподвигло меня на сей труд, не судите строго.
В данный момент подобная конфигурация работает на платформе Dell PowerEdge 2500, операционная система Linux RHAS release 2.1 (Pensacola). Тестировалось на различных версиях RH Linux, на других дистрибутивах *NIX-like систем не пробовал, но затруднений возникнуть не должно.
Итак, начнем. Задача достаточно проста – заставить SQUID не только авторизовать пользователей, но и забыть, наконец, об acl-листах, в которых описаны группы. Согласитесь, приятней добавить пользователя в определенную группу LDAP и все, а пользователь получает почтовый ящик и доступ в Интернет через proxy-сервер. Причем ничего не надо перезапускать.
Первым делом скачиваем свежую версию SQUID, я рассматриваю на примере SQUID-2.5.STABLE2.tar.gz.
Распаковываем:
tar zxvf SQUID-2.5.STABLE2.tar.gz
Переходим в созданный каталог с исходниками proxy-сервера и начинаем собирать:
./configure --enable-delay-pools --enable-cache-err-language=Russian-1251 --enable-linux-netfilter /
--enable-external-acl-helper=ldap_group --enable-basic-auth-helpers=LDAP
Небольшое пояснение, обо всех параметрах запуска смысла писать нет, достаточно понятно, а вот два последних нам как раз и нужны для интеграции с LDAP-сервером.
Последний ключ --enable-basic-auth-helpers=LDAP, собственно, и указывает кэширующему серверу SQUID, что проверку пары логин-пароль на предмет правильности он поручает внешней программе.
Ключ --enable-external-acl-helper=ldap_group необходим, чтобы группы в LDAP соотносились с группами в понимании SQUID.
Далее, следуя INSTALL:
make all
make install
Копируем 2 файла:
cp helpers/basic_auth/LDAP/squid_ldap_auth /usr/local/squid/libexec
cp helpers/external_acl/ldap_group/squid_ldap_group /usr/local/squid/libexec
Переходим во вновь созданное дерево кэширующего сервера SQUID, в моем случае /usr/local/squid/sbin:
cd /usr/local/squid/sbin
Создаем кэш:
./squid –z
Теперь необходимо внести изменения в конфигурационный файл SQUID.
Следующая строчка заставляет кэширующий сервер доверять авторизацию внешней программе.
auth_param basic program /usr/local/squid/libexec/squid_ldap_auth –P –b dc=mydomain,dc=ru /
Понятно, что всё пишется на одной строке.
Другие auth_param нужно закомментировать.
Теперь пояснения по поводу параметров:
- -P – оставлять соединение с LDAP-сервером открытым, для большого числа пользователей, для малого числа, LDAP смысла поднимать нет;
- -b – с чего начинать поиск, в моем случае – с самого верха;
- -f – применить (&(uid=%s)(description=active)) данный фильтр, для проверки пары логин-пароль. В жизни приходится сталкиваться с тем, что необходимо лишить пользователя доступа к Интернету, но не удалять же из-за этого его запись, тем более, мы не запрещаем ему пользоваться почтой, которая тоже работает через LDAP. Поэтому я и использовал поле description в LDAP для своих нужд.
Небольшое пояснение по поводу пары логин-пароль, это, как вы уже догадались, два поля в LDAP: uid и userpassword, логин и пароль соответственно.
И последний параметр -h 127.0.0.1, где, собственно, запущен LDAP-сервер, в данном случае на одной машине с кэширующим сервером.
Следующая строчка в файле squid.conf настраивает кэширующий сервер на поддержку внешних групп, так называемых acl-листов.
external_acl_type ldap_group %LOGIN /usr/local/squid/libexec/squid_ldap_group –P –b dc=mydomain,dc=ru /
–f (&(uid=%v)(member=ou=%a,dc=mydomain,dc=ru)) –h 127.0.0.1 –p 389
Опять же все на одной строке.
Ключи -P, -b и -f, -h имеют те же значения, что и выше. Ключ -p – порт, который слушает LDAP-сервер, этот параметр можно опустить, если используется стандартный порт.
По поводу параметров фильтра требуется специальное пояснение, каждая запись пользователя, кроме всего прочего, должна быть членом класса groupOfNames, в этом случае у каждого пользователя появляется обязательное поле member.
Пример ldif-файла для создания пользователя, группы я приведу в конце.
Ну и наконец, описываю сами группы, механизм тот же самый, что и при стандартном описании, сравним:
Старое:
acl users proxy_auth dima petya vasya
authenticate_program /usr/local/squid/bin/ncsa_auth /usr/local/squid/etc/passwd
Новое:
acl users external ldap_group accounts
acl admin external ldap_group admin
acl icq_only external ldap_group icq
Далее все как обычно:
http_access allow admin
и так далее.
Описание стандартных настроек кэширующего сервера выходит за рамки данной статьи, предполагается, что вы уже знакомы с ними.
А теперь поподробнее о настройке LDAP-сервера.
Конфигурационный файл должен иметь такое содержание:
#
include /usr/local/etc/openldap/schema/core.schema
include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/inetorgperson.schema
include /usr/local/etc/openldap/schema/nis.schema
# Эта схема для поддержки qmail
include /usr/local/etc/openldap/schema/qmail.schema
pidfile /usr/local/var/slapd.pid
argsfile /usr/local/var/slapd.args
# В поле userPassword лежит пароль пользователя. Его может прочитать и изменить только сам пользователь, ну и себя
# любимого не забыл.
access to attr=userPassword
by self write
by anonymous auth
by dn="cn=Manager,dc=mydomain,dc=ru" write
by * none
# Если в этом поле active – Интернет есть, иначе – нет
access to attr=description
by self read
by anonymous read
by dn="cn=Manager,dc= mydomain,dc=ru" write
by * none
# На одной строчке
access to attr=title,ou,telephoneNumber,cn,sn,givenName,o, initials,physicalDeliveryOfficeName,destinationIndicator
by self write
by anonymous read
by users read
by dn="cn=Manager,dc= mydomain,dc=ru" write
access to *
by self read
by anonymous read
by users read
by dn="cn=Manager,dc= mydomain,dc=ru" write
database ldbm
suffix "dc= mydomain,dc=ru"
rootdn "cn=Manager,dc= mydomain,dc=ru"
rootpw secret
directory /usr/local/var/openldap-ldbm
index objectClass,mail,cn,sn,uid eq
Затем создаем файл example.ldif с описанием корневого дерева и групп пользователей, например, такого содержания:
# Корень нашего дерева директорий
dn: dc=mydomain,dc=ru
objectClass: top
# Группа админов
dn: ou=admin,dc=mydomain,dc=ru
objectClass: top
objectClass: organizationalUnit
ou: admin
# Группа для пользователей icq
dn: ou=icq,dc=mydomain,dc=ru
objectClass: top
objectClass: organizationalUnit
ou: icq
# Группа для простых пользователей
dn: ou=accounts,dc=mydomain,dc=ru
objectClass: top
objectClass: organizationalUnit
ou: accounts
# Добавляем 1 пользователя в группу admin
dn: uid=boss,ou=admin,dc=mydomain,dc=ru
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
# Это для Qmail
objectClass: qmailUser
# Обязательный класс, чтобы появилось поле member
objectClass: groupOfNames
#Если active то все пучком:)
description: active
# Сюда я забиваю время создания данной записи, на всякий случай
destinationIndicator: 01.02.03
# Здесь я указываю лимит в байтах, который установлен
#для данного пользователя
preferredLanguage: 50000000
# Это поле только для Qmail
accountStatus: active
# Именно по этому полю проверяется принадлежность пользователя к группе
member: ou=admin,dc=mydomain,dc=ru
sn:: 0J/Rg9GC0LjQvQ==
cn:: 0J/Rg9GC0LjQvSDQktC70LDQtNC40LzQuNGAINCS0LvQsNC00LjQvNC40YDQvtCy0LjRhw==
serPassword: 123
telephoneNumber: 111-11-11
title:: 0J/RgNC10LfQuNC00LXQvdGC
ou:: 0JzQvtGB0LrQstCwINC60YDQtdC80LvRjA==
givenName:: 0JLQu9Cw0LTQuNC80LjRgA==
initials:: 0JLQu9Cw0LTQuNC80LjRgNC+0LLQuNGH
mail: boss@mydomain.ru
uid: boss
# Это поле только для Qmail
mailMessageStore: /var/qmail/maildirs/boss
# Это поле только для Qmail
mailHost: mailhost.boss.ru
# Добавляем 1 пользователя в группу icq
dn: uid=icq_user,ou=icq,dc=mydomain,dc=ru
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: groupOfNames
description: active
member: ou=icq,dc=mydomain,dc=ru
sn: Sidoriv
cn: Sidorov Fedor Petrovich
userPassword: 321
telephoneNumber: 999-99-99
title: Doctor
ou: Departament
givenName: Fedor
initials: Petrovich
mail: icq_user@mydomain.ru
uid: icq_user
# Добавляем 1 пользователя в группу accounts
dn: uid=Ivan,ou=accounts,dc=mydomain,dc=ru
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: groupOfNames
description: active
member: ou=icq,dc=mydomain,dc=ru
sn: Ivanov
cn: Ivanov Ivan Ivanovich
userPassword: 333
telephoneNumber: 999-99-99
title: Doctor
ou: Departament
givenName: Ivan
initials: Ivanovich
mail: Ivan@mydomain.ru
uid: Ivan
Запись для первого поля почти реальная, форма, а не содержание. Последние две записи несколько аскетичные, если вам не нужна ни адресная книга, ни поддержка QMail, то это как раз необходимый минимум.
Небольшое пояснение. Поля sn, cn и др. заполнены русским текстом в формате utf8. Ничего не имею против английского, но некоторые пользователи жалуются. К тому же появляется адресная книга вашей фирмы, не советую пользоваться адресной книгой в Outlook Express, на редкость неудобная реализация. Я пользуюсь той, что идет в пакете Mozilla, но это дело вкуса.
Теперь пора добавить наши данные.
В случае работающего OpenLDAP:
/path/ldapadd –x –D “cn=Manager,dc=mydomain,dc=ru” –W –f /path/example.ldif
/path/ – реальное местоположение утилиты ldapadd и файла example.ldif.
В заключение хочется добавить, что лень и нехватка времени заставили меня написать некоторое количество скриптов, в основном на Perl, которые проверяют и расходование трафика пользователями и блокировки доступа в Интернет с посылкой уведомления по почте.
Мои пользователи через веб-интерфейс правят свои учетные записи на предмет рабочих телефонов, места работы, смены пароля – это реализовано на PHP.
Этим я хочу сказать, что трудностей с созданием ваших программ для манипулирования LDAP быть не должно.
Для создания записей в OpenLDAP я пользуюсь GQ-0.6.0: http://biot.com/gq.
Вот, собственно, и всё. Удачи!
Благодарность Henrik Nordstrom hno@squid-cache.org за то, что написал модуль squid_ldap_group и объяснил мне, как им пользоваться.