Squid+LDAP. Часть 3

Левинца Егор

Обсуждение статьи на форуме проекта Pro-LDAP.ru.

Содержание

3. Отбор записей по критериям: ext_ldap_group_acl (squid_ldap_group)

Существует расхожее мнение, что предназначение этого хелпера — предоставлять различный уровень доступа в Интернет пользователям согласно тем группам, в которые они входят. Но это лишь частный случай его использования, хотя и самый распространённый. Есть и другие. Поэтому, на наш взгляд, более правильно будет сформулировать предназначение хелпера ext_ldap_group_acl так: определение того, соответствует ли запись из каталога LDAP (пользовательская или иная) указанному критерию путём выполнения операций поиска в каталоге со специально сформированными фильтрами. Существенный момент: если в хелперах аутентификации был всего один "плавающий" параметр — имя пользователя, остальные условия возможно было задать только статично, то в этом хелпере "плавающих" параметров уже два: содержимое переменной %LOGIN (или иной) и строка, содержащая имя группы (или другой критерий). Само самой, пространство для манёвра возрастает многократно.

Проще будет разобраться со всем этим на примерах. И начнём мы с самого востребованного варианта: определения принадлежности пользователя той или иной группе.

3.1 Пользователи и группы

С точки зрения squid пользователей разделяют на группы, чтобы предоставить этим группам разные права на доступ в Интернет. Работу хелпера ext_ldap_group_acl мы продемонстрируем на примере следующей задачи: пользователи делятся на две группы, одной из которых будет предоставляться полный доступ в Интернет, другой — ограниченный.

Прежде чем начать, следует остановиться на двух разновидностях групп в LDAP: POSIX-группах (RFC 2307) и группах RFC 2307bis. Если коротко, каталог с POSIX-группами отражает POSIX-реальность, то есть один сервер является некой законченной единицей со своим доменным именем, пользователями и группами. Это прекрасно иллюстрируется на примере адресов электронной почты: user1@serv1.mycompany.ru в POSIX-реальности означает, что на почтовом сервере с доменным именем serv1.mycompany.ru зарегистрирована учётная запись пользователя user1, других доменных имён этот сервер не обслуживает. Каталоги же с группами неофициального RFC 2307bis отражают современные реалии: на одном сервере может обслуживаться несколько доменов со своими пользователями и группами, то есть на почтовом сервере serv1.mycompany.ru могут обслуживаться ящики user1@mycompany.ru, user2@somedomain.ru, user1@otherdomain.ru и вообще не обслуживаться ящики с доменным именем serv1.mycompany.ru.

Основным отличием между этими двумя видами групп LDAP является то, как в них представлено членство в группах. Записи POSIX-групп строятся на объектном классе posixGroup, члены группы определяются атрибутом memberUid, значением которого является строка с именем пользователя (логином), например, memberUid: vitaly. Такие группы характерны для каталогов, построенных для систем, основным сервисом которых является samba3 (особенно с использованием IDEALX-скриптов). Записи групп RFC 2307bis строятся на объектных классах groupOfNames или groupOfUniqueNames, соответственно членство в группах определяется атрибутами member или uniqueMember. И в том, и в другом случае значениями этих атрибутов являются DN (уникальные имена) записей-членов этих групп, например, member: uid=vitaly,ou=People,dc=mycompany,dc=ru. Такие группы широко используются в OpenLDAP, например в групповых условиях ACL или наложении memberof.

В каталоге можно одновременно определять группы разных видов. Хелпер ext_ldap_group_acl работает с любыми из них (и даже, как Вы увидите позже, с разделениями на "группы", которые вовсе группами и не являются). Так что дилемма "какую же структуру каталога выбрать для squid?", на наш взгляд, не должна ставиться излишне остро: проектируйте каталог под свою основную задачу, а squid подстроится под любую структуру. Различные варианты работы с группами мы сейчас и продемонстрируем.

Напоследок несколько слов об именовании групп. Структура DN допускает наличие пробела в названиях групп. Названия с пробелами становятся более читабельными и симпатичными, и многие администраторы ими пользуются. Возвращаясь к нашей дилемме "какую же структуру каталога выбрать для squid?", ещё раз повторяем: проектируйте каталог по своему вкусу, squid сможет обработать любые варианты названий групп (имена с пробелами мы рассмотрим в варианте 2). Ну и, конечно, регистр символов в названиях групп значения не имеет.

3.1.1. Вариант 1: классический (группы пользователей согласно RFC 2307bis)

Задача: Группы пользователей определены записями, построенными на объектном классе groupOfNames:

# Группы имён RFC2307bis
dn: cn=Inet_Full_Access_RFC2307bis,ou=Groups,dc=mycompany,dc=ru
objectClass: groupOfNames
cn: Inet_Full_Access_RFC2307bis
member: uid=vasily,ou=Managers,dc=mycompany,dc=ru
member: uid=vitaly,ou=People,dc=mycompany,dc=ru

dn: cn=Inet_Limited_Access_RFC2307bis,ou=Groups,dc=mycompany,dc=ru
objectClass: groupOfNames
cn: Inet_Limited_Access_RFC2307bis
member: uid=anton,ou=People,dc=mycompany,dc=ru
member: uid=alex,ou=People,dc=mycompany,dc=ru

Требуется предоставить членам группы Inet_Full_Access_RFC2307bis полный доступ в интернет, а членам группы Inet_Limited_Access_RFC2307bis — только доступ к определённым сайтам ("белый список"). Пользователи проходят Basic-аутентификацию.

Решение:

Сначала разберёмся с работой хелпера, вызвав его из командной строки:

# ext_ldap_group_acl -b 'ou=Groups,dc=mycompany,dc=ru' -f '(&(objectClass=groupOfNames)(cn=%g)(member=%u))' \
  -B 'dc=mycompany,dc=ru' -F 'uid=%s' -d
petr inet_full_access_rfc2307bis<Enter>
Connected OK
user filter 'uid=petr', searchbase 'dc=mycompany,dc=ru'
ext_ldap_group_acl WARNING, User 'petr' not found in 'dc=mycompany,dc=ru'
ERR
vasily iNet_fuLl_accEss_rfc2307bIs<Enter>
Connected OK
user filter 'uid=vasily', searchbase 'dc=mycompany,dc=ru'
group filter '(&(objectClass=groupOfNames)(cn=iNet_fuLl_accEss_rfc2307bIs)(member=uid=vasily,ou=Managers,dc=mycompany,dc=ru))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
OK
vitaly INET_FULL_ACCESS_RFC2307BIS<Enter>
Connected OK
user filter 'uid=vitaly', searchbase 'dc=mycompany,dc=ru'
group filter '(&(objectClass=groupOfNames)(cn=INET_FULL_ACCESS_RFC2307BIS)(member=uid=vitaly,ou=People,dc=mycompany,dc=ru))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
OK
anton Inet_Full_Access_RFC2307bis<Enter>
Connected OK
user filter 'uid=anton', searchbase 'dc=mycompany,dc=ru'
group filter '(&(objectClass=groupOfNames)(cn=Inet_Full_Access_RFC2307bis)(member=uid=anton,ou=People,dc=mycompany,dc=ru))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
ERR
anton Inet_Limited_Access_RFC2307bis<Enter>
Connected OK
user filter 'uid=anton', searchbase 'dc=mycompany,dc=ru'
group filter '(&(objectClass=groupOfNames)(cn=Inet_Limited_Access_RFC2307bis)(member=uid=anton,ou=People,dc=mycompany,dc=ru))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
OK

Мы выбрали именно эту задачу для нашего первого варианта, поскольку на её примере можно показать наиболее комплексный вариант работы ext_ldap_group_acl. Мы задаём параметры сразу для двух поисковых запросов LDAP: с помощью аргументов -B и -F задаются, соответственно, база поиска и фильтр для нахождения записи пользователя, а с помощью аргументов -b и -f — база поиска и фильтр для определения членства пользователя в группе. Аргумент -B можно не указывать, если базы поиска пользователей и групп совпадают, к примеру, когда в качестве базы поиска используется корневая запись dc=mycompany,dc=ru и диапазон поиска sub.

В фильтрах для поиска пользователя и группы используются разные шаблоны. Шаблон %s в фильтре поиска пользователя имеет тот же смысл, что и в рассмотренных нами ранее хелперах аутентификации: вместо него подставляется предоставляемое имя пользователя. После чего выполняется первая операция поиска в каталоге: ищется запись пользователя с базой поиска dc=mycompany,dc=ru (-B), диапазоном sub (по умолчанию, значение можно переопределить аргументом -s) и сформированным фильтром. Если в результате в каталоге не было найдено записи, удовлетворяющей этим критериям, то работа хелпера на данном этапе прекращается и выдаётся ERR.

Тут необходимо отметить, что, также как и в хелперах аутентификации, операцию поиска записи пользователя можно заменить на конструирование записи из DN той ветки дерева, в которой находятся записи пользователя, и RDN, построенного из имени атрибута, переданного в аргументе -u, и имени пользователя:

# ext_ldap_group_acl -b 'ou=Groups,dc=mycompany,dc=ru' -f '(&(objectClass=groupOfNames)(cn=%g)(member=%u))' \
   -B 'ou=People,dc=mycompany,dc=ru' -u uid -d
anton Inet_Limited_Access_RFC2307bis<Enter>
Connected OK
group filter '(&(objectClass=groupOfNames)(cn=Inet_Limited_Access_RFC2307bis)(member=uid=anton, ou=People,dc=mycompany,dc=ru))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
OK
В нашем случае записи пользователей находятся в разных ветках, поэтому такой вариант нас не устраивает.

Возвращаемся к нашему основному примеру. Если запись пользователя успешно найдена (или сконструирована), начинает формироваться второй поисковый фильтр для группы. Тут свои шаблоны: вместо %g подставляется предоставляемое имя группы, а вместо %u, — внимание, тонкий момент, — DN записи, найденной в предыдущем поиске (или сконструированной). Такая подстановка шаблона происходит только в случае определения параметров для поиска (конструирования) записи пользователя (-B, -F или -u). Затем выполняется вторая операция поиска в каталоге: ищется запись группы с базой поиска ou=Groups,dc=mycompany,dc=ru (-b), тем же диапазоном sub и вновь сформированным фильтром (запись с объектным классом groupOfNames, атрибут cn которой содержит переданное имя группы, а атрибут member — DN записи пользователя). Если была найдена хотя бы одна запись, удовлетворяющая заданным критериям, хелпер возвращает OK, если нет — ERR. Как видите, всё просто.

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

Осталось только продемонстрировать вызов хелпера из squid. Вот часть squid.conf, соответствующая условиям нашего примера:

# Настройки хелпера Basic-аутентификации
auth_param basic program /path/to/basic_ldap_auth -b "dc=mycompany,dc=ru" -f "(uid=%s)" -H ldap://127.0.0.1:389
# Настройки вызова хелпера ext_ldap_group_acl
external_acl_type ldap_group_rfc2307bis ttl=900 children=10 %LOGIN /path/to/ext_ldap_group_acl \
    -b "ou=Groups,dc=mycompany,dc=ru" -f "(&(objectClass=groupOfNames)(cn=%g)(member=%u))" \
    -B "dc=mycompany,dc=ru" -F "uid=%s" -H ldap://127.0.0.1:389
# ACL с использованием внешнего хелпера для двух групп из каталога LDAP
acl acl_ldap_group_full_access external ldap_group_rfc2307bis Inet_Full_Access_RFC2307bis
acl acl_ldap_group_limited_access external ldap_group_rfc2307bis Inet_Limited_Access_RFC2307bis
# ACL "белого списка"
acl acl_whitelist url_regex -i "/etc/squid3/whitelist_sites.txt"
# Правила доступа
http_access allow acl_ldap_group_full_access
http_access allow acl_ldap_group_limited_access acl_whitelist
http_access deny all

В строке 2 настраивается Basic-аутентификация. При успешном её прохождении в переменную squid %LOGIN помещается имя пользователя, прошедшего проверку подлинности.

Строки 4-6 представляют для нас наибольший интерес, поскольку в них настраивается вызов интересующего нас хелпера. За ключевым словом external_acl_type следует название определяемого нами нового внешнего типа ACL (будет использоваться в дальнейшем в директивах acl). Далее, вплоть до переменной %LOGIN, помещаются параметры взаимодействия squid с настраиваемым хелпером. Для примера мы привели два: ttl — время в секундах хранения положительного результата проверки хелпером в кэше squid и children — количество процессов хелпера, порождаемых squid. Таких параметров достаточно много, большинство из них имеют разумные значения по умолчанию, подробности смотрите в комментариях к директиве external_acl_type файла squid.conf.default. Далее указывается переменная squid, которая будет передаваться в качестве первого параметра работающему хелперу (в нашем случае — %LOGIN). Наконец, оформляется вызов самого хелпера, аналогично тому, как мы это делали из командной строки (не забывайте, что значения аргументов должны заключаться в двойные кавычки). Для удобства мы разбили сроку вызова на три, оформив это как стандартный многострочный вызов командного интерпретатора (\).

Итак, мы определили новый внешний тип ACL. Теперь создадим ACL этого типа (строки 8 и 9). За ключевым словом acl следует название определяемого ACL. Затем указывается ключевое слово external, за которым следует название нашего типа ACL (ldap_group_rfc2307bis). Наконец, указывается название группы, которое будет передаваться в качестве второго параметра работающему хелперу. Например, в строке 8 мы определили ACL с именем acl_ldap_group_full_access типа ldap_group_rfc2307bis для группы Inet_Full_Access_RFC2307bis.

По условиям нашей задачи необходимо определить ещё "белый список" сайтов, которые разрешено посещать членам группы с ограниченным доступом. Мы сделаем это с помощью ACL типа url_regexp (строка 11). Непосредственно список шаблонов адресов сайтов будет находиться в файле /etc/squid3/whitelist_sites.txt, в каждой строке которого указывается по одному шаблону, например:

pro-ldap\.ru
yandex\.(ru|net)

Осталось только определить правила доступа на основе наших ACL. В строке 13 разрешается полный доступ для acl_ldap_group_full_access (группы Inet_Full_Access_RFC2307bis). В строке 14 разрешается доступ в том случае, когда одновременно соблюдаются условия acl_ldap_group_limited_access и acl_whitelist (пользователь из группы Inet_Limited_Access_RFC2307bis обращается к сайту, URL которого соответствует шаблону из "белого списка"). Последним правилом (срока 15) запрещается доступ в Интернет (ключевое слово deny и ACL по умолчанию all), таким образом любые пользователи, не входящие в указанные группы, а также пользователи из ограниченной группы, обращающиеся к адресам не из "белого списка", доступ не получают.

3.1.2. Вариант 2: POSIX-группы (группы пользователей согласно RFC 2307)

Задача: Группы пользователей определены записями, построенными на объектном классе posixGroup:

# Posix-группы RFC2307
dn: cn=Inet Full Access 1,ou=Groups,dc=mycompany,dc=ru
objectClass: posixGroup
cn: Inet Full Access 1
gidNumber: 1000
memberUid: vasily

dn: cn=Inet Full Access 2,ou=Groups,dc=mycompany,dc=ru
objectClass: posixGroup
cn: Inet Full Access 2
gidNumber: 1001
memberUid: vitaly

dn: cn=Inet Limited Access,ou=Groups,dc=mycompany,dc=ru
objectClass: posixGroup
cn: Inet Limited Access
gidNumber: 1002
memberUid: anton
memberUid: alex

Требуется предоставить членам групп Inet Full Access 1 и Inet Full Access 2 полный доступ в интернет, а членам группы Inet Limited Access запретить доступ к определённым сайтам ("чёрный список"). В названиях групп имеются символы пробела. На этот раз будем производить Digest-аутентификацию пользователей.

Решение:

В первую очередь разберёмся с работой хелпера. При этом, кроме того, что группы строятся на объектном классе posixGroup, членство в котором определяется атрибутом memberUid (значение которого — имя пользователя), необходимо обратить внимание, что значения RDN записей групп содержат пробелы, и это вносит определённые коррективы при передаче параметров хелперу как при вызове из командной строки, так и из squid. Вызов хелпера из командной строки:

# ext_ldap_group_acl -b 'ou=Groups,dc=mycompany,dc=ru' -f '(&(objectClass=posixGroup)(cn=%g)(memberUid=%u))' -d
vasily Inet Full Access 1<Enter>
Connected OK
group filter '(&(objectClass=posixGroup)(cn=Inet)(memberUid=vasily))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
group filter '(&(objectClass=posixGroup)(cn=Full)(memberUid=vasily))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
group filter '(&(objectClass=posixGroup)(cn=Access)(memberUid=vasily))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
group filter '(&(objectClass=posixGroup)(cn=1)(memberUid=vasily))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
ERR
vasily 'Inet Full Access 1'<Enter>
Connected OK
group filter '(&(objectClass=posixGroup)(cn='Inet)(memberUid=vasily))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
group filter '(&(objectClass=posixGroup)(cn=Full)(memberUid=vasily))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
group filter '(&(objectClass=posixGroup)(cn=Access)(memberUid=vasily))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
group filter '(&(objectClass=posixGroup)(cn=1')(memberUid=vasily))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
ERR
vasily Inet%20Full%20Access%201<Enter>
Connected OK
group filter '(&(objectClass=posixGroup)(cn=Inet Full Access 1)(memberUid=vasily))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
OK
vitaly Inet%20Full%20Access%202<Enter>
Connected OK
group filter '(&(objectClass=posixGroup)(cn=Inet Full Access 2)(memberUid=vitaly))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
OK
alex Inet%20Limited%20Access<Enter>
Connected OK
group filter '(&(objectClass=posixGroup)(cn=Inet Limited Access)(memberUid=alex))', searchbase 'ou=Groups,dc=mycompany,dc=ru'
OK

Мы задаём параметры только для одного поиска с помощью аргументов -b (база поиска записей групп) и -f (фильтр поиска групп). Как уже отмечалось, в фильтре аргумента -f можно использовать два шаблона: вместо %g подставляется предоставляемое имя группы, а вместо %u, — поскольку поиска записи пользователя не осуществлялось, — содержимое переменной squid %LOGIN, то есть имя пользователя.

Теперь обратим внимание на передачу хелперу параметров. В первых двух попытках мы передаём после имени пользователя сначала имя группы в чистом виде, а затем попытавшись "экранировать" его с помощью кавычек. В обоих случаях хелпер воспринимает разделённые пробелами слова как отдельные имена групп и выполняет сразу четыре поиска, ни один из которых успехом не увенчается (итоговое ERR). Хитрость в том, что пробелы при такой передаче параметров должны экранироваться по правилам экранирования символов URL, то есть конструкцией %20. В последних трёх попытках мы выполняем такое экранирование, в фильтр передаётся требуемое нам имя группы, и результат поиска положительный (OK).

Разобравшись с работой хелпера, оформим его вызов из squid.conf:

# Настройки хелпера Digest-аутентификации
auth_param digest program /path/to/digest_ldap_auth -b "dc=mycompany,dc=ru" -F "(uid=%s)" -A "l" -e -H ldap://127.0.0.1:389
auth_param digest realm Squid Digest Auth
# Настройки вызова хелпера ext_ldap_group_acl
external_acl_type ldap_group_rfc2307 %LOGIN /path/to/ext_ldap_group_acl \
    -b "ou=Groups,dc=mycompany,dc=ru" -f "(&(objectClass=posixGroup)(cn=%g)(memberUid=%u))" -H ldap://127.0.0.1:389
### ACL с использованием внешнего хелпера для групп из каталога LDAP (названия групп с пробелами)
## Неверные варианты:
#acl acl_ldap_group_full_access external ldap_group_rfc2307 Inet Full Access 1
#acl acl_ldap_group_full_access external ldap_group_rfc2307 "Inet Full Access 1"
#acl acl_ldap_group_full_access external ldap_group_rfc2307 'Inet Full Access 1'
#acl acl_ldap_group_full_access external ldap_group_rfc2307 Inet%20Full%20Access%201
#acl acl_ldap_group_full_access external ldap_group_rfc2307 Inet\ Full\ Access\ 1
## Правильный вариант:
acl acl_ldap_group_full_access external ldap_group_rfc2307 "/etc/squid3/full_access_groups.txt"
acl acl_ldap_group_limited_access external ldap_group_rfc2307 "/etc/squid3/limited_access_groups.txt"
# ACL "чёрного списка"
acl acl_blacklist url_regex -i "/etc/squid3/blacklist_sites.txt"
# Правила доступа
http_access allow acl_ldap_group_full_access
http_access allow acl_ldap_group_limited_access !acl_blacklist
http_access deny all

Многое в этом примере аналогично тому, что мы настраивали в первом варианте, поэтому приведём лишь краткое описание, подробнее останавливаясь лишь на тонких моментах.

В строках 2 и 3 настраивается Digest-аутентификация. При успешном её прохождении в переменную squid %LOGIN помещается имя пользователя, прошедшего проверку подлинности.

В строка 5 и 6 мы определяем новый внешний тип ACL ldap_group_rfc2307, указав актуальный для текущего примера вызов хелпера ext_ldap_group_acl.

Создадим ACL нового внешнего типа (строки 7-16). Поскольку имена наших групп содержат пробелы, то указать их не так просто. В строках 9-13 приводятся попытки указания имён групп с пробелами, не увенчавшиеся успехом. К сожалению, любой тип экранирования здесь не поможет. Единственный на текущий момент способ передачи имён групп с пробелами во внешний хелпер — это указание их во внешнем файле (строки 15-16). Тут есть интересный побочный эффект: в файле можно указать несколько названий групп по одному в строке, так что если у Вас есть несколько групп с аналогичными правами доступа, их можно указать в одном файле. Рассмотрим это на примере строки 15. За ключевым словом acl следует название ACL acl_ldap_group_full_access. Затем указывается ключевое слово external, за которым следует название нашего типа ACL (ldap_group_rfc2307). Наконец, указывается обращение к внешнему файлу /etc/squid3/full_access_groups.txt, в котором перечислены две группы с правами полного доступа:

Inet Full Access 1
Inet Full Access 2

Аналогично в строке 16 определяется ACL того же типа с именем acl_ldap_group_limited_access, группа для которого указана в файле /etc/squid3/limited_access_groups.txt:

Inet Limited Access

По условиям нашей задачи необходимо определить ещё "чёрный список" сайтов, которые запрещено посещать членам группы с ограниченным доступом. Как и в предыдущем варианте, мы сделаем это с помощью ACL типа url_regexp (строка 18), только в файле /etc/squid3/blacklist_sites.txt будут указаны шаблоны нежелательных сайтов, например:

banner
porno
xxx

Осталось только определить правила доступа на основе наших ACL. В строке 20 разрешается полный доступ для acl_ldap_group_full_access (групп Inet Full Access 1 и Inet Full Access 2). В строке 21 разрешается доступ в том случае, когда одновременно соблюдается условие acl_ldap_group_limited_access и не соблюдается условие acl_blacklist (пользователь из группы Inet Limited Access обращается к сайту, URL которого не соответствует шаблону из "чёрного списка"). Последним правилом (срока 22) запрещается доступ в Интернет (ключевое слово deny и ACL по умолчанию all), таким образом любые пользователи, не входящие в указанные группы, а также пользователи из ограниченной группы, обращающиеся к адресам из "чёрного списка", доступ не получают.

3.1.3. Вариант 3: обратное членство в группах (использование атрибута memberOf)

Задача: Наложение memberof настроено на объектный класс groupOfUniqueNames. Группы пользователей определены записями, построенными на этом объектном классе:

# Группы для memberOf
dn: cn=InetFullAccess,ou=Groups,dc=mycompany,dc=ru
objectClass: groupOfUniqueNames
cn: InetFullAccess
uniqueMember: uid=vasily,ou=Managers,dc=mycompany,dc=ru
uniqueMember: uid=vitaly,ou=People,dc=mycompany,dc=ru

dn: cn=InetLimitedAccess,ou=Groups,dc=mycompany,dc=ru
objectClass: groupOfUniqueNames
cn: InetLimitedAccess
uniqueMember: uid=anton,ou=People,dc=mycompany,dc=ru
uniqueMember: uid=alex,ou=People,dc=mycompany,dc=ru

Таким образом в записях пользователей появляются операционные атрибуты memberof, значения которых — DN соответствующих записей групп.

Требуется предоставить членам группы InetFullAccess полный доступ в интернет, а членам группы InetLimitedAccess запретить доступ к flash-контенту. Будем производить Negotiate-аутентификацию пользователей.

Решение:

С учётом обратного членства в группах (атрибута memberof) и получения в переменную %LOGIN принципалов Kerberos, вызов хелпера из командной строки будет выглядеть так:

# ext_ldap_group_acl -K -b 'dc=mycompany,dc=ru' -f '(&(uid=%u)(memberof=cn=%g,ou=Groups,dc=mycompany,dc=ru))' -d
vasily@mycompany.ru InetFullAccess<Enter>
Connected OK
group filter '(&(uid=vasily)(memberof=cn=InetFullAccess,ou=Groups,dc=mycompany,dc=ru))', searchbase 'dc=mycompany,dc=ru'
OK
vitaly@mycompany.ru InetFullAccess<Enter>
Connected OK
group filter '(&(uid=vitaly)(memberof=cn=InetFullAccess,ou=Groups,dc=mycompany,dc=ru))', searchbase 'dc=mycompany,dc=ru'
OK
anton@mycompany.ru InetFullAccess<Enter>
Connected OK
group filter '(&(uid=anton)(memberof=cn=InetFullAccess,ou=Groups,dc=mycompany,dc=ru))', searchbase 'dc=mycompany,dc=ru'
ERR
anton@mycompany.ru InetLimitedAccess<Enter>
Connected OK
group filter '(&(uid=anton)(memberof=cn=InetLimitedAccess,ou=Groups,dc=mycompany,dc=ru))', searchbase 'dc=mycompany,dc=ru'
OK

В первую очередь следует обратить внимание на аргумент -K, который сообщает хелперу, что из имени пользователя следует отбросить Kerberos-REALM. То есть, при передаче в переменную %LOGIN значения anton@mycompany.ru, оно будет преобразовано просто в anton.

Мы задаём параметры только для одного поиска, — в данном случае будем искать записи пользователей, — с помощью аргументов -b (база поиска) и -f (фильтр поиска). В фильтре аргумента -f используются два шаблона: вместо %u, — поскольку поиска записи пользователя не осуществлялось, — подставляется содержимое переменной squid %LOGIN, то есть имя пользователя (в нашем случае усечённое), а вместо %g — предоставляемое имя группы. Таким образом, если в каталоге имеется запись пользователя, значение атрибута uid которой соответствует переданному имени, а атрибута memberof — сформированному DN записи группы, то поиск выполнен успешно и принадлежность пользователя группе установлена (OK). Если поиск завершился неудачей, как в третьем случае, то пользователь не принадлежит данной группе (ERR). Как видите, всё достаточно просто.

Примечание: Задача определения членства в группе на основании атрибута memberof типична при интеграции squid c каталогом Microsoft AD или samba4. Наш пример легко преобразовать для такой интеграции: фильтр в аргументе -f будет иметь вид (&(samAccountName=%u)(memberof=cn=%g,cn=Users,dc=domain,dc=ru)), кроме того, необходимо указать учётные данные для подсоединения к каталогу (например, в аргументах -D и -W хелпера).

Разобравшись с работой хелпера, оформим его вызов из squid.conf:

# Настройки хелпера Negotiate-аутентификации
auth_param negotiate program /path/to/squid/negotiate_kerberos_auth -s HTTP/proxy.mycompany.ru
# Настройки вызова хелпера ext_ldap_group_acl
external_acl_type ldap_group_memberof %LOGIN /path/to/ext_ldap_group_acl -K \
    -b "dc=mycompany,dc=ru" -f "(&(uid=%u)(memberof=cn=%g,ou=Groups,dc=mycompany,dc=ru))" -H ldap://127.0.0.1:389
# ACL с использованием внешнего хелпера для групп из каталога LDAP
acl acl_ldap_group_full_access external ldap_group_memberof InetFullAccess
acl acl_ldap_group_limited_access external ldap_group_memberof InetLimitedAccess
# ACL определения flash-контента
acl acl_flash_url url_regex -i \.swf(\?.*)?$ \.fl.(\?.*)?$
acl acl_flash_content rep_mime_type -i ^application/x-shockwave-flash$ ^application/octet-stream$ ^video/x-fl ^video/fl
# Правила доступа
http_access allow acl_ldap_group_full_access
http_access allow acl_ldap_group_limited_access !acl_flash_url
http_reply_access deny acl_ldap_group_limited_access acl_flash_content
http_access deny all

Многое в этом примере аналогично тому, что мы настраивали в первом варианте, поэтому приведём лишь краткое описание, подробнее останавливаясь лишь на тонких моментах.

В строке 2 настраивается Negotiate-аутентификация. При успешном её прохождении в переменную squid %LOGIN помещается Kerberos-принципал пользователя, прошедшего проверку подлинности.

В строках 4 и 5 мы определяем новый внешний тип ACL ldap_group_memberof, указав актуальный для текущего примера вызов хелпера ext_ldap_group_acl. В строках 7 и 8 создаются ACL этого типа для групп с полным и ограниченным доступом.

Далее, согласно условиям нашей задачи, создаются два ACL для ограничения доступа к flash-контенту. Первый из них, — acl_flash_url типа url_regex (строка 10), — по сути, представляет собой тот же самый "чёрный список" шаблонов URL, что мы наблюдали во втором варианте, только оформленный без подключения внешнего файла. С его помощью мы ограничим доступ к flash-роликам (определив их по расширению файла) ещё до попытки их загрузки. Но современные реалии таковы, что flash-контент в основном выдаётся динамически и определить его по URL невозможно. Поэтому мы создаём второй ACL, — acl_flash_content типа rep_mime_type (строка 11), — в котором перечисляются шаблоны интересующих нас MIME-типов возвращаемого flash-контента.

Осталось определить правила доступа на основе наших ACL. В строке 13 разрешается полный доступ для acl_ldap_group_full_access (членов группы InetFullAccess). В строке 14 разрешается доступ в том случае, когда одновременно соблюдается условие acl_ldap_group_limited_access и не соблюдается условие acl_flash_url (пользователь из группы InetLimitedAccess обращается к сайту, URL которого не соответствует шаблону flash-роликов).

Далее (строка 15) следует правило http_reply_access, с помощью которого накладываются ограничения на возвращаемый контент. В нашем случае мы запрещаем (ключевое слово deny) доступ при одновременном соблюдении условий acl_ldap_group_limited_access и acl_flash_content (пользователю из группы InetLimitedAccess возвращается контент, MIME-тип которого соответствует шаблону flash-контента).

Последним правилом (срока 16) запрещается доступ в Интернет (ключевое слово deny и ACL по умолчанию all), таким образом любые пользователи, не входящие в указанные группы, а также пользователи из ограниченной группы, обращающиеся к flash-роликам, доступ не получают.

3.1.4. Вариант 4: разбиение пользователей "на группы" по подветкам каталога

Задача: Уровень доступа в Интернет определяется по принадлежности пользователя той или иной ветке DIT. Руководители (пользователи из ветки Managers) могут выходить в Интернет с любой рабочей станции в сети, остальные сотрудники (пользователи из ветки People) — только с рабочей станции с ip-адресом 10.0.0.10 ("Интернет-киоск"). Будет производиться NTLM-аутентификация пользователей.

Решение:

Необходимо учитывать, что хелпер NTLM-аутентификации возвращает в переменную %LOGIN имя пользователя в домене Windows NT. Кроме того, для определения принадлежности записи пользователя той или иной ветке дерева придётся использовать более хитрый фильтр, чем обычно. Вызов хелпера из командной строки будет выглядеть так:

# ext_ldap_group_acl -S -b 'dc=mycompany,dc=ru' -f '(&(uid=%u)(ou:dn:=%g))' -d
MYCOMPANY\vasily People<Enter>
Connected OK
group filter '(&(uid=vasily)(ou:dn:=People))', searchbase 'dc=mycompany,dc=ru'
ERR
MYCOMPANY\vasily Managers<Enter>
Connected OK
group filter '(&(uid=vasily)(ou:dn:=Managers))', searchbase 'dc=mycompany,dc=ru'
OK
MYCOMPANY\alex People<Enter>
Connected OK
group filter '(&(uid=alex)(ou:dn:=People))', searchbase 'dc=mycompany,dc=ru'
OK
MYCOMPANY\alex Managers<Enter>
Connected OK
group filter '(&(uid=alex)(ou:dn:=Managers))', searchbase 'dc=mycompany,dc=ru'
ERR

В первую очередь следует обратить внимание на аргумент -S, который сообщает хелперу, что из имени пользователя следует отбросить название домена Windows NT. То есть, при передаче в переменную %LOGIN значения MYCOMPANY\alex, оно будет преобразовано просто в alex.

Фильтр в аргументе -f состоит из двух элементов, соединенных логическим "И". Первый элемент оценивается как истина, когда в записи есть атрибут uid, значение которого соответствует переданному (и преобразованному) имени пользователя (шаблон %u). Второй элемент фильтра оценивается как истина, когда в уникальном имени (DN) записи присутствует RDN, состоящий из типа атрибута ou и значения, передаваемого в шаблоне %g. В первом и втором рассматриваемых случаях ищутся записи, в которых атрибут uid имеет значение vasily. В нашем каталоге такая запись одна — uid=vasily,ou=Managers,dc=mycompany,dc=ru. В первом случае второй элемент фильтра будет (ou:dn:=People), то есть DN записи содержит RDN, в котором атрибут ou имеет значение People. В DN нашей записи такого RDN нет, поэтому поиск завершается неудачей (ERR). Во втором случае второй элемент фильтра будет (ou:dn:=Managers), то есть DN записи содержит RDN, в котором атрибут ou имеет значение Managers. В DN нашей записи такой RDN есть, поэтому поиск завершается успешно (ОК). По условиям нашей задачи пользователь vasily принадлежит ветке Managers, но не принадлежит ветке People, поэтому может получать доступ в Интернет с любой рабочей станции в сети. Пользователь alex, принадлежащий ветке People, но не ветке Managers (третий и четвёртый случаи), может выходить в интернет только с определённой рабочей станции.

Разобравшись с работой хелпера, оформим его вызов из squid.conf:

# Настройки хелпера NTLM-аутентификации
auth_param ntlm program /path/to/ntlm_smb_lm_auth
# Настройки вызова хелпера ext_ldap_group_acl
external_acl_type ldap_group_tree %LOGIN /path/to/ext_ldap_group_acl -S \
    -b "dc=mycompany,dc=ru" -f "(&(uid=%u)(ou:dn:=%g))" -H ldap://127.0.0.1:389
# ACL с использованием внешнего хелпера для групп из каталога LDAP
acl acl_ldap_group_full_access external ldap_group_tree Managers
acl acl_ldap_group_limited_access external ldap_group_tree People
# ACL определения "Интернет-киоска"
acl acl_kiosk src 10.0.0.10
# Правила доступа
http_access allow acl_ldap_group_full_access
http_access allow acl_ldap_group_limited_access acl_kiosk
http_access deny all

Многое в этом примере аналогично тому, что мы настраивали в первом варианте, поэтому приведём лишь краткое описание, подробнее останавливаясь на тонких моментах.

В строке 2 настраивается NTLM-аутентификация. При успешном её прохождении в переменную squid %LOGIN помещается имя пользователя в домене Windows NT, прошедшего проверку подлинности.

В строках 4 и 5 мы определяем новый внешний тип ACL ldap_group_tree, указав актуальный для текущего примера вызов хелпера ext_ldap_group_acl. В строках 7 и 8 создаются ACL этого типа с полным и ограниченным доступом для веток Managers и People соответственно.

В строке 10 создаётся ACL для "Интернет-киоска". Это простой ACL типа src, в котором в качестве значения указывается ip-адрес источника обращения к серверу squid. В нашем случае ACL с именем acl_kiosk будет срабатывать, если обращение к squid осуществлялось с рабочей станции с ip-адресом 10.0.0.10 . При необходимости можно было бы указать несколько адресов или диапазон адресов.

Осталось определить правила доступа на основе наших ACL. В строке 12 разрешается полный доступ для acl_ldap_group_full_access (пользователей, записи которых находятся в ветке Managers). В строке 13 разрешается доступ в том случае, когда одновременно соблюдаются условия acl_ldap_group_limited_access и acl_kiosk (пользователь, запись которого находится в ветке People, обращается к серверу squid с разрешённого адреса).

Последним правилом (срока 14) запрещается доступ в Интернет (ключевое слово deny и ACL по умолчанию all), таким образом любые пользователи, записи которых находятся вне заданных веток, а также пользователи из ветки People, пытающиеся обратиться к squid с адреса, отличного от разрешённого, доступ не получают.

Итак, мы рассмотрели различные варианты построения каталога с точки зрения разбиения пользователей по группам, а также то, как хелпер ext_ldap_group_acl работает с подобными структурами каталога. Общий вывод таков: squid, как и любые другие программы, взаимодействующие с каталогом путём выполнения в нём операций поиска с настраиваемыми критериями, способен подстроиться под любую структуру. Стройте каталог как Вам удобно или необходимо, squid справится с Вашей структурой в любом случае.

3.2. Другое применение

Тут самое время вспомнить, что %LOGIN — не единственная внутренняя переменная squid. В очень перспективную переменную %SRC попадает ip-адрес машины, с которой происходит попытка выхода в Интернет. И это, конечно же, можно использовать для разграничения доступа.

Задача: Обеспечить выход в Интернет только с определённых ip-адресов. Закачку файлов разрешить только с ограниченного подмножества этих ip-адресов.

Если в каталоге LDAP уже имеются записи, содержащие ip-адреса (например, зона DNS или зарезервированные адреса DHCP), то можно по какому-либо их дополнительному признаку (значению атрибута) определять возможность доступа в Интернет с машины с таким адресом. Допустим, в каталоге есть описание прямой DNS-зоны для сервера bind (технология bind-sdb-ldap) с A-записями:

dn: relativeDomainName=team-10,zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru
objectClass: dNSZone
relativeDomainName: team-10
zoneName: mycompany.ru
dNSTTL: 86400
dNSClass: IN
aRecord: 10.0.0.10

dn: relativeDomainName=team-11,zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru
objectClass: dNSZone
relativeDomainName: team-11
zoneName: mycompany.ru
dNSTTL: 86400
dNSClass: IN
aRecord: 10.0.0.11

dn: relativeDomainName=team-12,zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru
objectClass: dNSZone
relativeDomainName: team-12
zoneName: mycompany.ru
dNSTTL: 86400
dNSClass: IN
aRecord: 10.0.0.12

Нам нужно, чтобы в Интернет можно было выходить с машин 10.0.0.11 и 10.0.0.12, а закачки осуществлять только с 10.0.0.12. Назначим соответствующие признаки в виде атрибутов tXTRecord:

dn: relativeDomainName=team-10,zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru
objectClass: dNSZone
relativeDomainName: team-10
zoneName: mycompany.ru
dNSTTL: 86400
dNSClass: IN
aRecord: 10.0.0.10

dn: relativeDomainName=team-11,zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru
objectClass: dNSZone
relativeDomainName: team-11
zoneName: mycompany.ru
dNSTTL: 86400
dNSClass: IN
aRecord: 10.0.0.11
tXTRecord: squidAccessAddr

dn: relativeDomainName=team-12,zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru
objectClass: dNSZone
relativeDomainName: team-12
zoneName: mycompany.ru
dNSTTL: 86400
dNSClass: IN
aRecord: 10.0.0.12
tXTRecord: squidAccessAddr
tXTRecord: squidDownloadAddr

Если в Вашей DNS-зоне TXT-записи несут полезную информацию, можно задействовать любой другой атрибут. Попробуем использовать хелпер для проверки доступа:

# ext_ldap_group_acl -b 'zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru' -s one -f '(&(aRecord=%u)(tXTRecord=%g))' -d
10.0.0.10 squidAccessAddr<Enter>
Connected OK
group filter '(&(aRecord=10.0.0.10)(tXTRecord=squidAccessAddr))', searchbase 'zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru'
ERR 
10.0.0.10 squidDownloadAddr<Enter>
Connected OK
group filter '(&(aRecord=10.0.0.10)(tXTRecord=squidDownloadAddr))', searchbase 'zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru'
ERR 
10.0.0.11 squidAccessAddr<Enter>
Connected OK
group filter '(&(aRecord=10.0.0.11)(tXTRecord=squidAccessAddr))', searchbase 'zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru'
OK 
10.0.0.11 squidDownloadAddr<Enter>
Connected OK
group filter '(&(aRecord=10.0.0.11)(tXTRecord=squidDownloadAddr))', searchbase 'zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru'
ERR 
10.0.0.12 squidAccessAddr<Enter>
Connected OK
group filter '(&(aRecord=10.0.0.12)(tXTRecord=squidAccessAddr))', searchbase 'zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru'
OK 
10.0.0.12 squidDownloadAddr<Enter>
Connected OK
group filter '(&(aRecord=10.0.0.12)(tXTRecord=squidDownloadAddr))', searchbase 'zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru'
OK 

Здесь всё достаточно очевидно: вместо шаблона %u в фильтр подставляется ip-адрес, вместо %g — определённый нами признак доступа в Интернет. Поиск с сформированным фильтром даёт ожидаемый результат.

Итак, когда в каталоге уже хранятся записи с ip-адресами, использовать их для контроля доступа разумно и удобно. Но что делать, если таких записей нет? Тогда можно завести искусственные записи исключительно для контроля доступа, например такие:

dn: cn=squidAccessAddrs,ou=SquidOptions,dc=mycompany,dc=ru
objectClass: applicationProcess
objectClass: ipHost
cn: squidAccessAddrs
ipHostNumber: 10.0.0.11
ipHostNumber: 10.0.0.12

dn: cn=squidDownloadAddrs,ou=SquidOptions,dc=mycompany,dc=ru
objectClass: applicationProcess
objectClass: ipHost
cn: squidDownloadAddrs
ipHostNumber: 10.0.0.12

В первой записи собраны адреса машин, имеющих право доступа в Интернет, во второй — машин, с которых пользователи могут осуществлять закачки. Протестируем работу хелпера:

# ext_ldap_group_acl -H ldap://127.0.0.1:9000 -b 'ou=SquidOptions,dc=mycompany,dc=ru' -s one -f '(&(ipHostNumber=%u)(cn=%g))' -d
10.0.0.10 squidAccessAddrs<Enter>
Connected OK
group filter '(&(ipHostNumber=10.0.0.10)(cn=squidAccessAddrs))', searchbase 'ou=SquidOptions,dc=mycompany,dc=ru'
ERR 
10.0.0.10 squidDownloadAddrs<Enter>
Connected OK
group filter '(&(ipHostNumber=10.0.0.10)(cn=squidDownloadAddrs))', searchbase 'ou=SquidOptions,dc=mycompany,dc=ru'
ERR 
10.0.0.11 squidAccessAddrs<Enter>
Connected OK
group filter '(&(ipHostNumber=10.0.0.11)(cn=squidAccessAddrs))', searchbase 'ou=SquidOptions,dc=mycompany,dc=ru'
OK 
10.0.0.11 squidDownloadAddrs<Enter>
Connected OK
group filter '(&(ipHostNumber=10.0.0.11)(cn=squidDownloadAddrs))', searchbase 'ou=SquidOptions,dc=mycompany,dc=ru'
ERR 
10.0.0.12 squidAccessAddrs<Enter>
Connected OK
group filter '(&(ipHostNumber=10.0.0.12)(cn=squidAccessAddrs))', searchbase 'ou=SquidOptions,dc=mycompany,dc=ru'
OK 
10.0.0.12 squidDownloadAddrs<Enter>
Connected OK
group filter '(&(ipHostNumber=10.0.0.12)(cn=squidDownloadAddrs))', searchbase 'ou=SquidOptions,dc=mycompany,dc=ru'
OK 

Пример простой и в дополнительных пояснениях не нуждается. Осталось только настроить squid. Но прежде чем мы это сделаем, необходимо отметить, что подобная организация контроля доступа имеет свои минусы и плюсы:

Взвесив сильные и слабые стороны применения хелпера ext_ldap_group_acl, Вы примете правильное решение.

3.2.1. Настройка вызова хелпера ext_ldap_group_acl в файле squid.conf

В простейшем случае (без использования аутентификации пользователей) мы решаем задачу авторизации на основе ip-адресов подключения. В качестве объектов для скачивания выберем (для определённости) аудио-файлы. Итак, наш squid.conf:

# Настройки вызова хелпера ext_ldap_group_acl для тестирования ip-адресов
external_acl_type LDAP_IP ttl=60 children=20 %SRC /path/to/ext_ldap_group_acl \
    -b "zoneName=mycompany.ru,ou=DNS,dc=mycompany,dc=ru" -f "(&(aRecord=%u)(tXTRecord=%g))"
# ACL ip-адреса локального хоста
acl acl_localhost src 127.0.0.1/255.255.255.255
# ACL проверки ip-адресов клиентов с использованием внешнего хелпера для групп из каталога LDAP
acl acl_valid_addresses external LDAP_IP squidAccessAddr
acl acl_download_addresses external LDAP_IP squidDownloadAddr
# ACL определения URL и контента категории "скачивание"
acl acl_download_url urlpath_regex -i "/etc/squid3/download_url.txt"
acl acl_download_content rep_mime_type -i "/etc/squid3/download_content.txt"
# Правила доступа
http_access deny !acl_localhost !acl_valid_addresses
http_access deny acl_download_url !acl_download_addresses
http_reply_access deny acl_download_content !acl_download_addresses
http_access allow all

В строках 1-3 определяется внешний тип ACL LDAP_IP с использованием вызова хелпера ext_ldap_group_acl. В данном случае мы взяли вариант с зоной DNS. В строках 6-8 на основе этого типа ACL определяются ACL для определения ip-адресов, с которых разрешён выход в Интернет (acl_valid_adresses), и ip-адресов, с которых можно выполнять скачивание (acl_download_adresses). В дополнение к ним в строках 4-5 определяется простой ACL типа src для поиска совпадения с ip-адресом локального хоста (которого обычно нет в DNS-зонах).

Далее в строках 9-11 определяются ACL для ограничения скачивания. Подобные ACL мы уже разбирали выше в разделе 3.1.3, но на этот раз списки регулярных выражений для поиска совпадений с URL и MIME-типами контента вынесены нами в отдельный файл, чтобы их можно было дополнять по мере необходимости. Как мы и договаривались, ограничивать будем доступ к музыкальным файлам. Итак, файл с регулярными выражениями для URL /etc/squid3/download_url.txt будет выглядеть так:

\.m4a(\?.+)?$
\.mp(3|a|ga)(\?.+)?$
\.ogg(\?.+)?$
\.wma(\?.+)?$

А файл с регулярными выражениями для MIME-типов контента /etc/squid3/download_content.txt так:

^application/force-download$
^application/ogg$
^audio/

Осталось разобраться с правилами доступа (строки 12-16). На этот раз мы отойдём от нашего традиционного подхода "запрещено всё, что не разрешено явно" и воспользуемся обратным подходом "всё, что явно не запрещено, разрешено". Сначала в строке 13 мы запрещаем доступ со всех ip-адресов, кроме локального хоста (acl_localhost) и тех, доступ с которых мы разрешили (acl_valid_addresses). Затем мы запрещаем доступ к определённым URL (строка 14) и возвращаемому контенту (строка 15) со всех адресов, кроме специально выделенных нами для скачивания файлов (acl_download_addresses). Если ни один из установленных нами запретов не сработал, пользователь получает доступ в Интернет (строка 16).

Напоследок совсем чуть-чуть усложним наш пример, добавив аутентификацию пользователей:

# Настройки хелпера Basic-аутентификации
auth_param basic program /path/to/basic_ldap_auth -b "dc=mycompany,dc=ru" -f "(uid=%s)"
# Настройки вызова хелпера ext_ldap_group_acl для тестирования ip-адресов
external_acl_type LDAP_IP ttl=60 children=20 %SRC /path/to/ext_ldap_group_acl \
    -b "ou=SquidOptions,dc=mycompany,dc=ru" -f "(&(ipHostNumber=%u)(cn=%g))"
# ACL аутентификации
acl acl_all_authed_users proxy_auth REQUIRED
# ACL ip-адреса локального хоста
acl acl_localhost src 127.0.0.1/255.255.255.255
# ACL проверки ip-адресов клиентов с использованием внешнего хелпера для групп из каталога LDAP
acl acl_valid_addresses external LDAP_IP squidAccessAddr
acl acl_download_addresses external LDAP_IP squidDownloadAddr
# ACL определения URL и контента категории "скачивание"
acl acl_download_url urlpath_regex -i "/etc/squid3/download_url.txt"
acl acl_download_content rep_mime_type -i "/etc/squid3/download_content.txt"
### Правила доступа
# Ограничения доступа на основе ip-адресов
http_access deny !acl_localhost !acl_valid_addresses
http_access deny acl_download_url !acl_download_addresses
http_reply_access deny acl_download_content !acl_download_addresses
# Разрешение доступа всем, кто прошёл проверку
http_access allow acl_all_authed_users
# Остальным доступ запрещён
http_access deny all

В этом примере мы использовали наши "искусственные" записи с ip-адресами для squid.

Мы добавили Basic-аутентификацию и ACL для её работы, это уже Вам хорошо известно. Небольшая тонкость в настройках правил доступа: поскольку ACL аутентификации проверяется после проверки доступа на основе ip-адресов, то пользователю, который захочет выйти в Интернет с машины, ip-адрес которой не попал в список разрешённых, или скачать что-то с машины, с которой делать это не разрешено, доступ будет запрещён сразу и приглашение для ввода пароля выводиться не будет.

Усложнять пример можно и дальше, добавив авторизацию на основе групп, но с этой задачей Вы уже вполне справитесь сами.

4. Что ещё можно выжать из каталога?

В разработке

5. Ссылки

Последнее изменение страницы — 21 октября 2016 года.

Содержание   Часть 1   Часть 2

Обсуждение статьи на форуме проекта Pro-LDAP.ru.