Левинца Егор
Обсуждение статьи на форуме проекта Pro-LDAP.ru.
"Ещё одно HOWTO про squid? Их и так уже полно в Интернете!" Это правда, squid — один из самых документированных OpenSource-продуктов. Ежегодно десятки энтузиастов более или менее подробно описывают свои наработки и открытия в блогах и HOWTO-руководствах, а ведь есть ещё превосходная документация на официальном сайте, подробнейшие комментарии в конфигурационном файле squid.conf, множество man-страниц... И, тем не менее, у тех, кто принимается за настройку, остаётся ещё очень много вопросов. На наш взгляд, это связано с трудностью нахождения баланса. С одной стороны, есть готовые HOWTO-решения частных задач, которые могут сразу заработать (а могут и не заработать) в Вашем окружении. Следуя им, есть все шансы не заметить и упустить тонкие и важные детали настроек, кроме того, Вы загоняете себя в те рамки, которые были удобны авторам HOWTO, но не обязательно будут лучшим решением для Вас. С другой стороны, погружаясь в чтение подробнейшей документации, всегда есть риск "за деревьями не увидеть леса", то есть упустить важные общие направления, погрязнув в деталях. Для обретения баланса, как всегда, требуется найти "золотую середину": чётко осознавать ту задачу, которая перед Вами стоит, возможности того окружения, в котором Вы будете эту задачу решать, и, конечно же, возможности самого инструмента, который у Вас в руках.
Не пытаясь объять необъятное, в этом руководстве, — надеемся, это всё-таки не будет HOWTO-руководством, — мы постараемся рассмотреть отдельный пласт задач — интеграция сервера squid с каталогом LDAP. Поверьте, здесь тоже есть с чем разобраться, начиная с классической дилеммы "какую структуру каталога выбрать?" и заканчивая сотнями мелочей, которые могут возникнуть в процессе интеграции. Итак, поехали!
Наверное, все, кто когда-либо настраивали squid, использовали те или иные хелперы, многим даже известен принцип их работы. Тем не менее, не лишним будет напомнить, что же это такое, а также осветить некоторые моменты их настройки, связанные с особенностями синтаксиса конфигурационного файла squid.conf.
В терминологии squid хелпер — это интерактивная программа, на вход которой подаётся один или несколько параметров (не путайте с аргументами командной строки), обработав которые, она выдаёт принятое ей положительное или отрицательное решение в виде строки, которая начинается с OK или ERR соответственно. Две основных категории хелперов — это хелперы аутентификации и так называемые хелперы внешних ACL.
Хелперы аутентификации на основании переданных им параметров, — в простейшей Basic-аутентификации это имя пользователя и пароль, — проводят проверку подлинности пользователя. При вызове такого хелпера из squid в случае успешного прохождения аутентификации пользователем во внутреннюю переменную squid %LOGIN помещается имя этого пользователя.
Внешние же хелперы, анализируя переданные им параметры, пытаются выяснить правомерность того или иного обращения к squid. Например, в классическом варианте применения ext_ldap_group_acl (squid_ldap_group) этот хелпер, на основании переменной %LOGIN и переданного ему названия группы, пытается определить, является ли указанный в переменной пользователь членом этой группы.
Поскольку нас в первую очередь интересует интеграция squid с каталогом LDAP, то мы рассмотрим поставляемые в составе squid хелперы аутентификации squid_ldap_auth и digest_ldap_auth, а также внешний хелпер squid_ldap_group. Обратите внимание, что с выходом в августе 2012 года squid версии 3.2 названия многих хелперов изменились на более логичные. Так, squid_ldap_auth теперь называется basic_ldap_auth, а squid_ldap_group — ext_ldap_group_acl. Тем не менее, это одни и те же программы с одними и теми же аргументами. В примерах мы будем придерживаться новых названий хелперов, чтобы соответствовать реалиям сегодняшнего дня.
Кроме штатных, поставляемых с дистрибутивом (пакетом) squid хелперов, можно сконфигурировать сервер на использование любой другой внешней программы, удовлетворяющей всё тем же критериям: она должна считывать параметры со стандартного потока ввода и выдавать на стандартный вывод итоговое сообщение, начинающееся с OK либо ERR. Программа может быть написана на любом компилируемом или интерпретируемом языке, и даже на языке интерпретатора команд оболочки. Примеры таких хелперов будут приведёны ниже.
Наконец, несколько слов о том, как хелперы настраиваются в конфигурационном файле squid.conf. Первое, на что хотелось бы обратить внимание, — это оформление вызова хелперов в squid.conf. Обычно перед тем, как вызов хелпера будет помещён в конфигурационный файл, его тестируют прямо из командной оболочки (примеры будут приведены далее). При этом многим аргументам командной строки передаются сложные текстовые значения, содержащие пробелы, и эти значения обрамляются кавычками. Так вот, если вызов из командной строки позволяет для обрамления текстовых значений аргументов использовать как одинарные, так и двойные кавычки, то при оформлении этого вызова в файле squid.conf для обрамления текстовых значений аргументов допускается использовать только двойные кавычки. Если вы ошибётесь, squid просто не будет вызывать этот хелпер, хотя и ошибок не выдаст. Например, при вызове хелпера из оболочки значения его аргументов вполне можно заключить в одинарные кавычки:
# /path/to/basic_ldap_auth -b 'dc=mycompany,dc=ru' -f 'uid=%s' -d
Но в squid.conf те же значения аргументов хелпера обрамляются двойными кавычками:
auth_param basic program /path/to/basic_ldap_auth -b "dc=mycompany,dc=ru" -f "uid=%s"
Второе, на что необходимо обратить внимание — это работа со значениями, содержащими пробелы. Типичная ситуация — многие системные администраторы используют пробелы в названиях групп LDAP, например группа с RDN cn=Inet Full Access. Если подобные группы используются для разграничения доступа в ACL squid, то наличие пробела необходимо учитывать как при тестировании хелпера из командной строки, так и при оформлении директивы acl
в squid.conf
. Чтобы не быть голословными, мы рассмотрим подобный случай в дальнейшем на примере.
Хотелось бы коротко напомнить, как работает операция поиска LDAP, поскольку эти знания являются ключевыми для последующего понимания взаимодействия squid и LDAP-каталога. Данные в каталоге можно логически представить в виде дерева подчинённых друг другу записей. Для описания совокупности всех записей в каталоге даже существует соответствующий термин — информационное дерево каталога (Directory Information Tree, DIT). Для наглядности введём дерево, на которое мы будем опираться в дальнейших примерах:
# Корневая запись dn: dc=mycompany,dc=ru objectClass: organization objectClass: dcObject dc: mycompany o: My Company # Ветка "Люди" dn: ou=People,dc=mycompany,dc=ru objectClass: organizationalUnit ou: People dn: uid=vitaly,ou=People,dc=mycompany,dc=ru objectClass: inetOrgPerson uid: vitaly cn: Vitaly Fridzon sn: Fridzon userPassword: vitalyPassword dn: uid=anton,ou=People,dc=mycompany,dc=ru objectClass: inetOrgPerson uid: anton cn: Anton Ponkrashov sn: Ponkrashov userPassword: antonPassword dn: uid=alex,ou=People,dc=mycompany,dc=ru objectClass: inetOrgPerson uid: alex cn: Aleksey Savrasenko sn: Savrasenko userPassword: alexPassword # Ветка "Руководство" dn: ou=Managers,dc=mycompany,dc=ru objectClass: organizationalUnit ou: People dn: uid=vasily,ou=Managers,dc=mycompany,dc=ru objectClass: inetOrgPerson uid: vasily cn: Vasily Karasev sn: Karasev userPassword: vasilyPassword # Ветка "Группы" dn: ou=Groups,dc=mycompany,dc=ru objectClass: organizationalUnit ou: Groups
Примечание: В нашем каталоге пароли (значения атрибутов userPassword
в записях пользователей) указаны в открытом виде. Это сделано для простоты и удобства работы с последующими примерами. В реальном каталоге, конечно же, такого быть не должно! Используйте хэши паролей или другие схемы аутентификации.
Операция поиска LDAP — это процесс отбора из всех записей каталога тех, которые удовлетворяют заданным критериям. Поиск осуществляется "сверху-вниз", то есть начиная от какой-то определённой записи каталога (она называется базой поиска, в английском варианте — basedn) в сторону подчинённых ей записей. Итак, первым критерием поиска является базовая запись, то есть запись, с которой поиск будет начинаться. Вторым критерием является так называемый диапазон поиска (в английском варианте — scope), то есть какие именно записи (начиная от базовой и вниз по дереву) будут рассматриваться в качестве предмета, по которому во время поиска будет производиться отбор. Стандартные диапазоны поиска: base (поиск затрагивает только базовую запись), one (поиск затрагивает записи на один уровень ниже базовой, но не саму базовую запись) и sub (поиск по всему дереву, начиная с указанной базовой записи и включая её саму). Во многих LDAP-клиентах, в том числе в связанных с LDAP стандартных хелперах squid, диапазон поиска по умолчанию задан в sub, но это значение можно переопределить. Приведём несколько примеров LDAP-поиска по нашему каталогу с помощью ldapsearch.
# ldapsearch -x -LLL -b 'dc=mycompany,dc=ru' 1.1 dn: dc=mycompany,dc=ru dn: ou=People,dc=mycompany,dc=ru dn: uid=vitaly,ou=People,dc=mycompany,dc=ru dn: uid=anton,ou=People,dc=mycompany,dc=ru dn: uid=alex,ou=People,dc=mycompany,dc=ru dn: ou=Managers,dc=mycompany,dc=ru dn: uid=vasily,ou=Managers,dc=mycompany,dc=ru dn: ou=Groups,dc=mycompany,dc=ru
Поиск от корневой записи dc=mycompany,dc=ru с диапазоном sub (по умолчанию). Возвращаются все имеющиеся в каталоге записи.
# ldapsearch -x -LLL -b 'ou=People,dc=mycompany,dc=ru' 1.1 dn: ou=People,dc=mycompany,dc=ru dn: uid=alex,ou=People,dc=mycompany,dc=ru dn: uid=anton,ou=People,dc=mycompany,dc=ru dn: uid=vitaly,ou=People,dc=mycompany,dc=ru
Поиск с указанием более "узкой" базовой записи ou=People,dc=mycompany,dc=ru с диапазоном sub (по умолчанию). Возвращаются все записи указанной ветки, в том числе сама базовая запись.
# ldapsearch -x -LLL -b 'ou=People,dc=mycompany,dc=ru' -s one 1.1 dn: uid=alex,ou=People,dc=mycompany,dc=ru dn: uid=anton,ou=People,dc=mycompany,dc=ru dn: uid=vitaly,ou=People,dc=mycompany,dc=ru
Поиск с той же базовой записью, что и в предыдущем примере, но с диапазоном one. Возвращаются только записи людей, то есть только записи, дочерние по отношению к базовой.
Как видите, всё очень просто и прозрачно.
Наконец, третьим и, пожалуй, важнейшим для нас критерием поиска является поисковый фильтр, то есть набор условий, по которым из всех записей, удовлетворивших первым двум критериям, выбирается итоговое подмножество записей, которое и будет результатом поиска. Условий может быть одно или несколько (во втором случае они объединяются с помощью логических операций), каждое из них проверяет, соответствует ли тот или иной атрибут записи указанному значению или шаблону.
# ldapsearch -x -LLL -b 'dc=mycompany,dc=ru' '(objectClass=inetOrgPerson)' 1.1 dn: uid=vitaly,ou=People,dc=mycompany,dc=ru dn: uid=anton,ou=People,dc=mycompany,dc=ru dn: uid=alex,ou=People,dc=mycompany,dc=ru dn: uid=vasily,ou=Managers,dc=mycompany,dc=ru
Поиск с теми же условиями, что и в первом примере, с добавлением фильтра "нас интересуют только записи с объектным классом inetOrgPerson
". Как видите, возвращены записи из обоих веток People и Manages. Аналогичных результатов можно добиться и другим фильтром:
# ldapsearch -x -LLL -b 'dc=mycompany,dc=ru' '(uid=*)' 1.1 dn: uid=vitaly,ou=People,dc=mycompany,dc=ru dn: uid=anton,ou=People,dc=mycompany,dc=ru dn: uid=alex,ou=People,dc=mycompany,dc=ru dn: uid=vasily,ou=Managers,dc=mycompany,dc=ru
В данном случае фильтр означает "отбор записей, у которых есть атрибут uid
". Еще один, более комплексный вариант такого отбора:
# ldapsearch -x -LLL -b 'dc=mycompany,dc=ru' '(&(objectClass=inetOrgPerson)(uid=*))' 1.1 dn: uid=vitaly,ou=People,dc=mycompany,dc=ru dn: uid=anton,ou=People,dc=mycompany,dc=ru dn: uid=alex,ou=People,dc=mycompany,dc=ru dn: uid=vasily,ou=Managers,dc=mycompany,dc=ru
Мы объединили оба наших фильтра логическим "И". Результат тот же.
# ldapsearch -x -LLL -b 'dc=mycompany,dc=ru' '(uid=vasily)' 1.1 dn: uid=vasily,ou=Managers,dc=mycompany,dc=ru
Поиск с теми же условиями, что и в первом примере, с добавлением фильтра "только записи, у которых есть атрибут uid
со значением vasily". Примеры неудачного поиска:
# ldapsearch -x -LLL -b 'dc=mycompany,dc=ru' '(uid=petr)' 1.1 # ldapsearch -x -LLL -b 'ou=People,dc=mycompany,dc=ru' '(uid=vasily)' 1.1
В первом случае в каталоге нет записей с атрибутом uid
, имеющим значение petr. Во втором случае в ветке People нет записей с атрибутом uid
, имеющим значение vasily.
Трудно изложить концепцию фильтрации в двух словах, но и приведённых примеров достаточно, чтобы чувствовать себя уверенно в последующей работе. Подробнее о поисковых фильтрах LDAP можно почитать в RFC 4515, а о самом поиске — в RFC 4511.
После такой обстоятельной вводной части пора переходить к настройке squid.
Последнее изменение страницы — 13 октября 2016 года.
Обсуждение статьи на форуме проекта Pro-LDAP.ru.