Aдминистраторы во всем мире пользуются proxy-сервером Squid для регулирования доступа пользователей к ресурсам Internet. Squid позволяет проводить авторизацию пользователей и принимать решение о предоставлении доступа к тому или иному ресурсу на основе полученных данных. Для Squid доступно множество схем авторизации: с помощью системных модулей PAM, по IP-адресу и т. п. — все это благодаря наличию возможности подключения внешних программ для проведения соответствующих операций. Кроме того, Squid имеет развернутую систему протоколирования, а ведущиеся журналы доступа дают богатую пищу для анализа.

В крупных организациях неудобно вести несколько баз пользователей для отдельной авторизации на том или ином сервере, поэтому администраторы стараются унифицировать формат хранения соответствующих данных и сделать их доступными для различных серверов. В перспективе такое решение может быть использовано как «первый шаг» на пути к организации единого хранилища. Оно, конечно, не будет однократной регистрацией (Single Sign-On, SSO) в полном смысле, так как SSO подразумевает однократное введение пользовательских данных, после чего доступ к ресурсам осуществляется автоматически. Но этот вариант весьма интересен с точки зрения унификации данных при минимальных начальных инвестициях (в данном случае придется приобрести только продукт Novell, поскольку Squid распространяется бесплатно) без учета конечной стоимости владения. Кроме того, в принципе может быть разработана аналогичная схема по переводу учетных данных пользователей систем UNIX в Novell NDS, без необходимости локального определения пользователя.

Одним из возможных хранилищ является, как уже было сказано, Novell NDS, где можно размещать учетные данные и предоставлять их как по протоколу IPX, так и по протоколу LDAP. Каталог — это база данных, оптимизированная для чтения, поскольку изначально предполагается, что операции чтения производятся намного чаще операций записи, в противном случае быстрее и удобнее было бы пользоваться обычной СУБД, например MySQL. Данные в каталогах хранятся в соответствии со своими атрибутами и классами, что значительно ускоряет поиск. Упрощенным протокол LDAP называется потому, что стандартный сервер каталогов не поддерживает транзакции и другие функции, присущие серверу баз данных. Таким образом, каталоги предназначены для иерархического хранения в них простых данных, например имя пользователя, его электронный адрес и т. п. Более подробное описание LDAP опубликовано в документе RFC 2251 «The Lightweight Directory Access Protocol (v3)» (см. также статью В. Шабата «Каталоги LDAP и их применение» в этом номере).

В последние версии NDS включена поддержка LDAP. Многие же крупные организации хранят пользовательские данные именно в NDS (LDAP), поэтому схему авторизации в Squid стоит выполнить таким образом, чтобы авторизация проводилась непосредственно в NDS, поскольку это исключает необходимость вести отдельную базу данных по пользователям Squid. Еще интереснее было бы иметь возможность предоставления прав доступа к пользовательским ресурсам на основе учетных данных NDS. Собственно, эти две задачи мы и попробуем решить.

Итак, проблема следующая: пользователь, желающий получить доступ к ресурсам Internet, должен подтвердить свое право на обращение к ресурсам вообще, а затем proxy-сервер, опираясь на его учетные данные, примет решение о допуске пользователя к ресурсу. Графически эта схема выглядит примерно так, как показано на Рисунке 1.

Нам потребуется загрузить и установить proxy-сервер Squid. Исходные коды программ лучше загружать и компилировать самостоятельно, так как в двоичных пакетах могут отсутствовать нужные опции. Итак, после загрузки из Internet файл Squid-2.5.STABLE1.tar.gz распаковывается в каталоге, где будет проводиться его компиляция. Обратите внимание, что поддержка внешних списков доступа, на которые опирается предлагаемая схема, появилась в Squid, начиная с версии 2.5. Следовательно, использование Squid в нашем случае ограничено версиями 2.5 и выше. Из каталога, куда распакован Squid, запускается сценарий configure со следующей командной строкой: ./configure --enable-external-acl-helpers=ldap_group. Ключевой для понимания является комбинация --enable-external-acl-helpers=ldap_group, поэтому мы остановимся на ней подробнее. Указанный параметр активизирует поддержку групп LDAP. Squid поддерживает так называемые «внешние списки доступа» (external acl), благодаря которым списки можно реализовать путем вызова внешних программ и анализа их данных. Сама программа ldap_group размещена в каталоге дистрибутива Squid, подкаталоге helpers/external_acl/ ldap_group. Она отвечает не за авторизацию, а только за определение права обращения пользователя к ресурсу, исходя из его членства в той или иной группе NDS. Выбранная программа для авторизации не входит в дистрибутив Squid, ее настройка описана ниже. Для компиляции необходимы библиотеки и заголовки сервера OpenLDAP, поэтому нужно либо установить пакет с соответствующими библиотеками и заголовками, либо скомпилировать и установить сам сервер OpenLDAP.

Итак, после завершения выполнения сценария configure компиляция производится командой make all, а установка proxy-сервера — командой make install. Теперь можно перейти непосредственно к программе авторизации пользователя в NDS. Программа ldap_auth, автором которой является Алан Спаркс, была выбрана потому, что она оказалась наиболее простой и прозрачной для внесения изменений. Нам потребовалось только добавить поддержку протоколирования в демон syslogd, в остальном же все осталось в первозданном виде. Схема авторизации Squid через внешние программы крайне проста. Программа авторизации возвращает строку ОК в случае правильной авторизации или ERR, если авторизация не была успешной. Данные в программу передаются через stdin. Для компиляции ldap_auth также необходимы заголовки и библиотеки OpenLDAP. После завершения компиляции двоичный файл ldap_auth следует скопировать в каталог libexec в том каталоге, где установлен Squid. Там же должен находиться файл squid_ldap_ group, ответственный за определение принадлежности пользователя к группе NDS. Далее обратимся непосредственно к конфигурации proxy-сервера Squid. В нашем случае она выглядит примерно так (ниже приводится только тот блок, где описываются схема авторизации и списки доступа):

auth_param basic program /opt/squid/libexec/ldap_auth 10.0.0.2 389 o=OURORG cn
auth_param basic realm Big Organization Proxy
auth_param basic children 5
auth_param basic credentialsttl 4 hours
external_acl_type nds_all %LOGIN /opt/squid/libexec/squid_ ldap_group -h 10.0.0.2 -b "o=OURORG" -f "(&(cn=%v)(groupmembership=cn=%a,,o=OURORG))"
external_acl_type nds_ftp %LOGIN /opt/squid/libexec/squid_ ldap_group -h 10.0.0.2 -b "o=OURORG" -f "(&(cn=%v)(groupmembership=cn=%a, o=OURORG))"
external_acl_type nds_mail %LOGIN /opt/squid/libexec/squid_ ldap_group -h 10.0.0.2 -b "o=OURORG" -f "(&(cn=%v)(groupmembership=cn=%a, o=OURORG))"
external_acl_type nds_funny %LOGIN /opt/squid/libexec/squid_ ldap_group -h 10.0.0.2 -b "o=OURORG" -f "(&(cn=%v)(groupmembership=cn=%a, o=OURORG))"
external_acl_type nds_porno %LOGIN /opt/squid/libexec/squid_ ldap_group -h 10.0.0.2 -b "o=OURORG" -f "(&(cn=%v)(groupmembership=cn=%a, o=OURORG))"
external_acl_type nds_banners %LOGIN /opt/squid/libexec/ squid_ldap_group -h 10.0.0.2 -b "o=OURORG" -f "(&(cn=%v) (groupmembership=cn=%a, o=OURORG))"
acl all src 0.0.0.0/0.0.0.0
acl users external nds_all proxy_all
acl users_ftp external nds_ftp proxy_ftp
acl users_mail external nds_mail proxy_mail
acl users_funny external nds_funny proxy_funny
acl users_porno external nds_porno proxy_porno
acl users_banners external nds_banners proxy_banners
acl funny dstdomain "/opt/squid/etc/funny.domains"
acl funmail_allow dstdomain "/opt/squid/etc/funmail.allow"
acl mail dstdomain "/opt/squid/etc/mail.domains"
acl porno dstdomain "/opt/squid/etc/porno.domains"
acl porno_ip dst "/opt/squid/etc/porno.ip"
acl banners url_regex -i "/opt/squid/etc/banners.exp"
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255
acl ftp proto FTP
acl CONNECT method CONNECT
http_access allow manager
http_access allow users_ftp ftp !funny
http_access allow users_ftp ftp !porno
http_access allow users_mail mail
http_access allow users_porno porno
http_access allow users_funny funny
http_access allow users_banners banners
http_access deny banners
http_access deny porno
http_access deny ftp
http_access allow users
http_access deny all

Не вдаваясь в подробности общих параметров конфигурации, отметим, что /opt/squid, корневой каталог proxy-сервера, был указан при компиляции Squid в качестве параметра --prefix=/opt/squid к сценарию configure наравне с другими опциями. При самостоятельной компиляции программных пакетов именно каталог /opt следует указывать в качестве корневого, так как в результате пакет не разбрасывается по файловой системе (например, в каталоги /usr или /usr/local), а хранится в одном месте, что значительно упрощает конфигурацию и не создает беспорядка. Кстати, возможность использования опции -prefix — еще один довод в пользу самостоятельной компиляции программы. Далее мы будем исходить из того, что конфигурация Squid записана в каталог /opt/squid/etc, внешние программы — в каталог /opt/squid/libexec, файлы протокола находятся в каталоге /opt/squid/var/logs, а сам демон Squid помещен в каталог /opt/squid/sbin.

При конфигурации Squid очень важно четко задать права запуска и работы сервера. Общепринятым является запуск сервера с правами пользователя nobody и группы nogroup, что и указано в параметрах cache_effective_user и cache_effective_group.

В блоке конфигурации, где параметры начинаются со строки auth_param, описана процедура авторизации пользователя на proxy-сервере. Ниже приводятся комментарии к каждой строке.

auth_param basic program /opt/squid/libexec/ldap_auth 10.0.0.2 389 o=OURORG cn

Данная строка сообщает proxy-серверу, что авторизацию надо проводить по базовому методу через вызов внешней программы /opt/squid/libexec/ldap_auth. В качестве ключей к ней передаются соответственно IP-адрес сервера NDS (10.0.0.2) и порт TCP (в нашем случае защищенное соединение с сервером не используется, поэтому порт всегда будет 389 (LDAP), если вы, конечно, не настроили изначально NDS на другой порт — тогда укажите порт, на котором находится сервер LDAP NDS). Затем серверу LDAP передается исходная точка поиска. Синтаксис LDAP подробно описан в RFC 2251, и мы на нем останавливаться не будем. Этот параметр указывает на ту запись в каталоге, от которой будет вестись поиск. Следовательно, если действительный корень вашей организации, к примеру, o=OURORG, c=ru и под записью c=ru также есть какие-то записи, то они не будут найдены. Последним параметром (cn) передается атрибут LDAP, под ним подразумевается уникальный идентификатор пользователя. Именно он служит именем пользователя. По умолчанию таким атрибутом считается uid, но его может и не быть на сервере каталогов, а вот cn присутствует всегда. Атрибутом, содержащим пароль пользователя, де-факто признан userPassword, поэтому он не упоминается в настройках вообще. Хотя при желании его можно изменить в исходном коде программы ldap_auth.

auth_param basic realm Big Organization Proxy

Этой строкой задается текст, отображаемый в окне авторизации пользователя.

auth_param basic children 5

Так регулируется количество дочерних процессов внешней авторизации, которые можно запустить одновременно. Их число зависит от размеров вашей организации: к примеру, для организации, где доступ в Internet имеют 100 человек, пяти дочерних процессов не хватит. В то же время количество процессов не должно быть чрезмерно завышенным в целях экономии ресурсов сервера.

auth_param basic credentialsttl 10 hours

Строка определяет время, в течение которого пользовательские данные будут храниться в кэше сервера; его безопасности следует уделить особое внимание, так как учетные данные хранятся в памяти сервера в открытом виде. При перезапуске сервера данное значение сбрасывается. Кроме того, в случае перезапуска обозревателя Internet авторизоваться придется повторно. Рекомендуемое время, 10 ч, немногим больше стандартного рабочего дня.

Следующий блок конфигурации со строками, начинающимися с external_acl_type, является основополагающим в нашей схеме, так как именно в нем описывается разграничение доступа к ресурсам Internet в зависимости от учетных данных пользователя.

Рисунок 2. Дерево NDS (LDAP)

Вызов внешнего обработчика списков доступа (ACL) начинается с параметра external_acl_type, а в следующем аргументе передается имя списка доступа. Параметр %LOGIN указывает, что для начала работы необходимо, чтобы пользователь был авторизован. Далее идет собственно вызов обработчика списка доступа, в нашем случае это /opt/squid/libexec/ squid_ldap_group. Обработчику в командной строке передаются последовательно IP-адрес сервера LDAP через ключ -h, затем исходная точка поиска через ключ -b и наконец фильтр поиска. Синтаксис фильтров LDAP описан в том же RFC 2251 и в общем случае представляет собой условия поиска в каталоге на основании указанных атрибутов или классов LDAP. На Рисунке 2 графически представлено дерево, в рамках которого будут производиться авторизация и распределение прав.

Как видно на Рисунке 2, в дереве OURORG зарегистрированы пользователь User и пять групп: proxy_mail, proxy_ftp, proxy_all, proxy_porno, proxy_funny. К группе proxy_all относятся те, у кого есть доступ к Internet, но не доступны ресурсы остальных групп. В группу proxy_mail входят пользователи, имеющие доступ к почте Web. Членам группы proxy_ftp позволен доступ к серверам FTP. Группа proxy_funny может обращаться к развлекательным ресурсам. И, наконец, название группы proxy_porno говорит само за себя.

Допустим, пользователю User необходимо предоставить возможность работать с ресурсами Internet и с почтой Web. Для этого внесем его в группы proxy_all и proxy_mail, как показано на Рисунке 3.

В формате обмена данными LDAP (LDAP Data Interchange Format, LDIF) наше дерево примет следующий вид:

version: 1

dn: cn=User,o=OURORG

sn: Novell NDS User

securityEquals: cn=proxy_all,o=OURORG

securityEquals: cn=proxy_mail,o=OURORG

objectClass: inetOrgPerson

objectClass: organizationalPerson

objectClass: person

objectClass: top

objectClass: ndsLoginProperties

groupMembership: cn=proxy_all,o=OURORG

groupMembership: cn=proxy_mail,o=OURORG

description: User has an Internet account

cn: User

dn: cn=proxy_all,o=OURORG

equivalentToMe: cn=User,o=OURORG

objectClass: groupOfNames

objectClass: top

member: cn=User,o=OURORG

cn: proxy_all

dn: cn=proxy_banners,o=OURORG

objectClass: groupOfNames

objectClass: top

cn: proxy_banners

dn: cn=proxy_ftp,o=OURORG

objectClass: groupOfNames

objectClass: top

cn: proxy_ftp

dn: cn=proxy_funny,o=OURORG

objectClass: groupOfNames

objectClass: top

cn: proxy_funny

dn: cn=proxy_mail,o=OURORG

equivalentToMe: cn=User,o=OURORG

objectClass: groupOfNames

objectClass: top

member: cn=User,o=OURORG

cn: proxy_mail

dn: cn=proxy_porno,o=OURORG

objectClass: groupOfNames

objectClass: top

cn: proxy_porno

Рисунок 3. Принадлежность пользователя User группам NDS (LDAP).

На самом деле в файле LDIF будут присутствовать и другие атрибуты пользователя и групп, но здесь они пропущены, так как не имеют прямого отношения к решаемой задаче.

При внимательном рассмотрении файла LDIF можно заметить, что после добавления пользователя в группу у него появляется новый атрибут — member. В нашем случае после добавления пользователя в группы proxy_all и proxy_mail у него появились атрибуты

securityEquals: cn=proxy_all,o=OURORG

securityEquals: cn=proxy_mail,o=OURORG

groupMembership: cn=proxy_all,o=OURORG

groupMembership: cn=proxy_mail,o=OURORG

В соответствующих группам записях появились атрибуты

equivalentToMe: cn=User,o=OURORG

member: cn=User,o=OURORG

Основываясь на указанных атрибутах, можно построить схему распределения прав между пользователями, что мы и сделаем.

Итак, фильтр поиска LDAP, на который мы уже обращали внимание, на самом деле просто просматривает запись пользователя в NDS в поисках атрибута groupMembership, указывающего на принадлежность пользователя к группе, а также атрибута cn, содержащего уникальный идентификатор пользователя. Proxy-сервер Squid допускает использование шаблонов имени пользователя и имени группы: %v — для имени пользователя и %a — для имени группы. Естественно, Squid не будет угадывать имена групп, поэтому они описываются ниже.

Далее в конфигурации Squid следует раздел привязки групп пользователей Squid к группам NDS. Обратите внимание, что речь идет именно об описании групп пользователей Squid, которые отличаются от групп NDS. Мы создали шесть групп пользователей и поставили в соответствие им группы NDS. Формат списков доступа следующий:

acl <имя acl> external <имя acl-external-type> <имя группы>

Параметр «имя группы» передается в external_acl_ type для размещения в шаблоне %a.

Строка конфигурации acl all src 0.0.0.0/0.0.0.0 описывает абсолютно всех пользователей, в том числе и тех, кто не указан в конфигурации Squid напрямую.

Далее нам необходимо описать, собственно говоря, те ресурсы, к которым будет определен доступ:

acl funny dstdomain «/opt/squid/etc/funny.domains»

acl mail dstdomain «/opt/squid/etc/mail.domains»

acl porno dstdomain «/opt/squid/etc/porno.domains»

Перечисленные файлы имеют формат «.доменное_имя», а записи разделяются построчно.

Например, в funny.domains будут содержаться записи наподобие

.games.rin.ru

.photosight.ru

.narod.ru

и т. п. Естественно, файлы могут дополняться и изменяться по вашему желанию.

Наконец, опишем раздел конфигурации, где определяется соответствие между пользователями и ресурсами. Он, в общем-то, не нуждается в дополнительных пояснениях, и, скорее всего, вы его измените.

http_access allow users_ftp ftp !funny

http_access allow users_ftp ftp !porno

http_access allow users_ftp ftp !mail

http_access allow users_mail mail

http_access allow users_porno porno

http_access allow users_funny funny

http_access allow users_banners banners

http_access deny banners

http_access deny porno

http_access deny porno_ip

http_access deny ftp

http_access allow users

http_access deny all

После создания этих списков конфигурацию можно считать завершенной. Правильность синтаксиса можно проверить командой /opt/squid/sbin/squid -k parse. В целях обеспечения безопасности для файлов конфигурации лучше определить режим доступа -rw-r-r, а владельцем файлов пользователя root сделать группу root.

Итак, после всех настроек у нас (теоретически) реализована следующая схема.

1) Пользователь User запускает обозреватель и обращается к ресурсу.

2) Proxy-сервер отправляет обозревателю Internet пользователя запрос "401: Authorization required".

3) Обозреватель Internet запускает процедуру авторизации и отображает окно, где просит ввести имя пользователя и пароль.

4) Пользователь User вводит свое имя и пароль (те же, что вводились им при входе в сеть Novell).

5) Proxy-сервер Squid запускает внешнюю процедуру авторизации, которая отправляет учетные данные пользователя в NDS и возвращает OK или ERR.

6) В случае получения OK Squid разрешает доступ к ресурсу, при этом он предварительно "проконсультируется" у NDS с помощью модуля squid_ldap_ group относительно принадлежности пользователя к группе, имеющей право на доступ к данному ресурсу.

7) Если пользователь не прошел авторизацию или не принадлежит к запрашиваемой группе, Squid возвращает обозревателю Internet страницу HTML с описанием причин отказа в доступе.

Следует отметить, что при добавлении пользователя в группу Novell реально доступ к ресурсу он получит только после повторного запуска Squid командой squid -k reconfigure или из сценария запуска Squid командой /etc/init.d/squid restart.

Представленная схема удобна прежде всего самим администраторам, так как позволяет сократить количество учетных записей и применять удобный и унифицированный интерфейс (например, Novell ConsoleOne) для манипуляций правами и учетными записями пользователей NDS.

Павел Покровский — специалист по информационной безопасности. С ним можно связаться по адресу: underling@yandex.ru.


Ресурсы Internet
Proxy-сервер Squid: http://www.squid-cache.org/

Novell NDS: http://www.novell.com/

OpenLDAP: http://www.openldap.org/

Auth_ldap: http://www.bayour.com/kerberos/squid-ldap_auth.tgz

RFC2251 (LDAP): http://www.faqs.org/rfcs/rfc2251.html.