Глава 5. Правила (Rules)¶
5.1. Структура правила: условие → действие¶
Терминология: В BlueCoat всё, что стоит после условий (triggers) в правиле, называется свойством (property). Отдельного понятия «действие» (action) в спецификации нет —
allow,deny,force_denyописываются как «imperative gestures», но формально тоже являются свойствами. Термин «действие» используется в VPM (колонка «Action») и в документации Redcoat как удобное обозначение для подмножества свойств, управляющих решением по транзакции и поведением прокси. Блокиdefine actionи свойствоaction.<name>(yes/no)— часть стандартного синтаксиса BlueCoat CPL.
Каждое правило занимает одну строку и состоит из нуля или более условий и нуля или более действий:
Примеры:
; Одно условие, одно действие
url.domain=example.com deny
; Несколько условий, одно действие
url.domain=example.com http.method=POST deny
; Одно условие, несколько действий
category=Malware log(yes) deny
; Только действие (безусловное)
allow
; Только условие (scope opener — см. 5.4)
client.address=10.0.0.0/8
5.2. Множественные условия¶
AND (неявный): Несколько условий на одной строке объединяются логическим И. Все условия должны совпасть для срабатывания правила:
; Запрос должен быть из корпоративной сети И методом POST И к домену example.com
client.address=10.0.0.0/8 http.method=POST url.domain=example.com deny
OR (внутри значения): Список значений в скобках через запятую или || — логическое ИЛИ для одного условия:
; Любой из перечисленных методов
http.method=(GET, POST, PUT)
; Любой из перечисленных доменов
url.domain=(example.com || blocked.com)
; Любое из расширений
url.extension=(exe, msi, bat, cmd, ps1)
Важно: Явные ключевые слова AND и OR между условиями не поддерживаются — это отличие CPL от языков общего назначения. AND всегда неявный (пробел), OR — только внутри значений одного условия.
5.3. Отрицание условий¶
Отрицание инвертирует результат условия. Поддерживается два синтаксиса:
; Через !=
url.domain!=example.com deny ; все домены КРОМЕ example.com
; Через ! перед значением
url.domain=!example.com deny ; эквивалентно
; Отрицание с ссылкой на define
client.address=!corporate_net deny ; все IP НЕ из define subnet
; Отрицание булевых условий
authenticated=no deny ; неаутентифицированные
5.4. Наследование области видимости (scope)¶
Строка, содержащая только условия без действий, создаёт область видимости (scope). Последующие строки с бо́льшим отступом наследуют эти условия:
<Proxy>
client.address=10.0.0.0/8 ; scope opener
url.domain=internal.corp allow ; наследует client.address + свое условие
url.path=/admin deny ; наследует client.address + свое условие
; Отступ вернулся — scope завершён
category=Malware deny ; независимое правило
allow
Это эквивалентно:
<Proxy>
client.address=10.0.0.0/8 url.domain=internal.corp allow
client.address=10.0.0.0/8 url.path=/admin deny
category=Malware deny
allow
Guard слоя (условие в заголовке): Условия в заголовке слоя применяются ко всем правилам:
<Proxy client.address=10.0.0.0/8>
url.domain=internal.corp allow ; = client.address=10.0.0.0/8 url.domain=internal.corp allow
deny ; = client.address=10.0.0.0/8 deny
Действие по умолчанию (в заголовке): Действие в заголовке слоя наследуется правилами без явного действия:
<Proxy deny>
url.domain=example.com ; наследует deny
url.domain=trusted.com allow ; явный allow переопределяет
5.5. Терминальные и нетерминальные действия¶
Примечание: Разделение на «терминальные» и «нетерминальные» действия — упрощение, принятое в документации Redcoat для удобства понимания. В спецификации BlueCoat такого деления нет: все элементы после условий являются свойствами (properties), а порядок их применения определяется приоритетами и правилами конфликтов между слоями (см. раздел 5.5.3 «Приоритеты при конфликтах»). Тем не менее, деление на терминальные и нетерминальные полезно для понимания того, какие свойства прекращают дальнейшую обработку запроса.
Действия (свойства) CPL делятся на две группы по влиянию на обработку запроса:
Терминальные — немедленно определяют итоговое решение по транзакции. После срабатывания терминального свойства обработка оставшихся слоёв прекращается (с одним исключением — см. deny ниже).
Нетерминальные — накапливаются и применяются к транзакции, но не останавливают обработку. Слои продолжают оцениваться.
Терминальные действия¶
| Действие | Поведение | Слой Exception |
|---|---|---|
force_deny |
Немедленный запрет, обработка останавливается | Пропускается |
deny |
Запрет, но обработка передаётся в слой Exception | Выполняется |
redirect |
HTTP-перенаправление, обработка останавливается | Пропускается |
authenticate |
Запрос аутентификации (407/401), обработка останавливается | Пропускается |
rate_limit |
Превышен лимит запросов (429), обработка останавливается | Пропускается |
exception |
Показ страницы исключения, обработка останавливается | Пропускается |
force_exception |
Безусловная страница исключения | Пропускается |
Нетерминальные действия¶
| Действие | Назначение |
|---|---|
allow |
Разрешение (транзакция продолжается к серверу) |
forward, direct, socks_gateway |
Выбор маршрута upstream |
ssl.forward_proxy, ssl.intercept |
Решение о TLS-перехвате |
cache, bypass_cache, force_cache, ttl |
Управление кэшированием |
set, delete, append (заголовки) |
Модификация заголовков |
log, access_log, log.rewrite, log.suppress |
Управление логированием |
label |
Метка правила |
max_bitrate, bandwidth_class, priority |
Ограничение полосы |
dns.server, dns.respond, dns.cache |
Управление DNS |
trace, profile, debug.* |
Диагностика |
virus_check, icap_service |
Антивирусная проверка |
transform, inject_script, inject_css |
Трансформация контента |
Все нетерминальные действия одного правила выполняются совместно. Например, правило может одновременно установить заголовок, включить логирование и выбрать upstream-маршрут:
Различие между deny и force_deny¶
Это ключевое различие при построении политик:
-
deny— запрещает транзакцию, но передаёт управление в слой<Exception>, где можно кастомизировать страницу ошибки. Exception-слой получаетexception.id=policy_deniedи может подставить собственную страницу. -
force_deny— запрещает транзакцию немедленно, слой<Exception>пропускается. Используется для безусловной блокировки, когда кастомизация страницы ошибки не нужна или нежелательна.
; deny: Exception-слой может показать кастомную страницу
<Proxy>
category=Gambling deny
<Exception>
exception.id=policy_denied exception(custom_block_page)
; force_deny: Exception-слой НЕ вызывается
<Proxy>
category=Malware force_deny
Приоритеты при конфликтах¶
Когда несколько правил из разных слоёв возвращают противоречащие терминальные действия, применяется следующий приоритет:
| Приоритет | Действие | Описание |
|---|---|---|
| Высший | force_deny |
Безусловный запрет, не может быть переопределён |
force_exception |
Безусловная страница ошибки | |
authenticate.force |
Принудительная аутентификация (выше deny) | |
| Средний | deny |
Запрет (может быть переопределён allow) |
exception |
Страница ошибки | |
| Низший | allow |
Разрешение |
authenticate |
Запрос аутентификации (ниже deny) |
Важное правило: authenticate имеет приоритет ниже deny. Это означает, что если правило содержит и authenticate(realm), и deny, то deny выполнится без запроса аутентификации. Для обратного поведения используйте authenticate.force(realm):
<Proxy>
; deny выполнится БЕЗ запроса аутентификации:
url.domain=blocked.com authenticate(LDAP) deny
; authenticate.force выполнится ПЕРЕД deny:
url.domain=restricted.com authenticate.force(LDAP) deny
Первое совпавшее правило¶
Внутри каждого слоя правила обрабатываются сверху вниз. Как только найдено первое совпавшее правило, все его действия выполняются, а оставшиеся правила в этом слое пропускаются:
<Proxy>
url.domain=example.com log(yes) allow ; Правило 1
url.domain=example.com deny ; Правило 2 — НЕ будет оценено,
; т.к. Правило 1 уже совпало
deny ; Правило 3
Если в правиле несколько действий, все они выполняются:
<Proxy>
; Все три действия выполнятся для одного совпавшего правила:
url.domain=api.corp set(request.header.X-Internal, "true") log(yes) allow
5.6. Аутентификация и запрет доступа¶
Одна из наиболее важных взаимосвязей в CPL — это соотношение между аутентификацией (authenticate) и запретом доступа (deny). Запрет может быть выполнен как до, так и после аутентификации, и разные организации имеют разные требования к этому.
Deny имеет приоритет над authenticate¶
Действие deny имеет приоритет 10, а authenticate(realm) — приоритет 20 (ниже). Это означает, что если правило содержит оба действия, deny выполняется без запроса аутентификации:
define subnet corporate_subnet
10.10.12.0/24
end
<Proxy>
client.address=!corporate_subnet deny ; блокировка без аутентификации
authenticate(MyRealm) ; authenticate ниже по приоритету
В этой политике запросы извне корпоративной подсети будут отклонены, а пользователи внутри подсети — аутентифицированы. Однако имя пользователя не будет доступно в access log для отклонённых запросов, так как аутентификация не выполнялась.
Примечание: Категории контента определяются из URL запроса и могут быть определены до аутентификации. Поэтому
denyс проверкой категории отклоняет запрос до запроса учётных данных.
authenticate.force имеет приоритет над deny¶
Действие authenticate.force(realm) имеет приоритет 5 — выше deny (10). Это позволяет сначала аутентифицировать пользователя, а затем отклонить запрос. Имя пользователя будет доступно в access log:
define subnet corporate_subnet
10.10.12.0/24
end
<Proxy>
client.address=!corporate_subnet deny ; блокировка
authenticate.force(MyRealm) ; но СНАЧАЛА аутентификация (приоритет 5 > deny 10)
<Proxy>
; Имена пользователей будут видны в access log для отклонённых запросов
category=Gambling exception(content_filter_denied)
Полная таблица приоритетов¶
Действия в одном правиле выполняются в порядке их приоритетов (от наименьшего числового значения к наибольшему):
| Приоритет | Действие | Описание |
|---|---|---|
| 0 | force_deny |
Безусловный запрет, Exception-слой пропускается |
| 1 | force_exception |
Безусловная страница ошибки |
| 5 | authenticate.force(realm) |
Принудительная аутентификация (выше deny!) |
| 10 | deny |
Запрет, Exception-слой вызывается |
| 11 | deny.unauthorized |
Запрет с кодом 401 |
| 12 | exception(id) |
Страница ошибки |
| 19 | allow |
Разрешение |
| 20 | authenticate(realm) |
Запрос аутентификации (ниже deny!) |
| 30-39 | SSL/TLS действия | ssl.intercept, ssl.forward_proxy и др. |
| 40-49 | Forwarding | forward, direct, socks_gateway |
| 50-59 | Кэширование | cache, force_cache, bypass_cache, ttl |
| 60-69 | Модификация | redirect, rewrite, заголовки |
| 70-79 | QoS | rate_limit, max_bitrate, bandwidth_class |
| 80-89 | DNS | dns.respond, dns.server и др. |
| 90-99 | Логирование | log, access_log, label, trace |
Взаимодействие deny и Exception-слоя¶
Действие deny не прекращает обработку немедленно. Вместо этого оно сохраняется как отложенный запрет (pending deny), и управление передаётся в слой <Exception>. Это позволяет кастомизировать страницу ошибки:
<Proxy>
category=Gambling deny
<Exception>
; Эта секция вызывается ТОЛЬКО если был pending deny
; Условие exception.id=policy_denied устанавливается автоматически
exception.id=policy_denied exception(custom_gambling_block_page)
Действие force_deny прекращает обработку немедленно — слой <Exception> пропускается, показывается стандартная страница ошибки.
SOCKS аутентификация¶
Для протокола SOCKS аутентификация происходит при установлении соединения (до получения запроса). Поэтому идентификационная информация пользователя доступна до оценки категории контента:
define subnet corporate_subnet
10.10.12.0/24
end
<Proxy>
client.address=!corporate_subnet deny
socks.authenticate(MyRealm) ; SOCKS auth до категоризации
<Proxy>
; Имена пользователей доступны для SOCKS-аутентифицированных
category=Gambling exception(content_filter_denied)
Примечание: Это поведение корректно только для SOCKS-аутентифицированных пользователей.
authenticate() как нетерминальное действие¶
Важная особенность: правило, содержащее только authenticate(realm) (без других действий), является нетерминальным. При встрече такого правила для неаутентифицированного пользователя оно сохраняется как отложенная аутентификация (pending auth), и движок продолжает оценивать следующие правила в слое.
Если следующее правило содержит deny — deny побеждает, пользователь отклоняется без запроса аутентификации. Если следующие правила содержат только allow или нетерминальные действия — возвращается запрос аутентификации (пользователь видит требование ввести учётные данные).
<Proxy>
; Правило 1: authenticate — сохраняется как pending auth
authenticate(LDAP_Realm)
; Правило 2: deny для категории — побеждает pending auth
; Результат: deny БЕЗ запроса аутентификации
category=Malware deny
; Правило 3: allow — для остальных возвращается отложенная аутентификация (запрос учётных данных)
allow
Для пользователя, запрашивающего Malware-сайт: deny (без 407). Для остального: 407 Proxy-Authenticate (запрос учётных данных).
Приоритет deny > authenticate. Это поведение — общее правило:
denyвсегда приоритетнееauthenticate(), независимо от порядка слоёв. Чтобы запрос аутентификации выдавался ПЕРЕД deny (и имя пользователя логировалось для отклонённых запросов), используйтеauthenticate.force(realm)— его приоритет вышеdeny.Тип запроса аутентификации определяется режимом аутентификации, а не политикой:
proxy*→ 407 (Proxy-Authenticate/ ответProxy-Authorization);origin*→ 401 (WWW-Authenticate/ ответAuthorization, как у исходного сервера);form*→ перенаправление 302.
Для уже аутентифицированного пользователя правило authenticate(realm) пропускается (если пользователь уже аутентифицирован в этом или совместимом realm).
Конфликтующие действия¶
Хотя правила в файле политики могут устанавливать одно и то же свойство неоднократно, конкретные действия могут конфликтовать:
- Если блок
define actionсодержит два конфликтующих действия, это ошибка времени компиляции. - Если два разных блока
define actionвыполняются и содержат конфликтующие действия, ошибка фиксируется в event log, и одно действие выбирается произвольно.
Потенциальные конфликты:
| Конфликт | Пример |
|---|---|
| Противоречивые значения | cache(yes) cache(no) |
| Взаимоисключающие | forward(proxy:3128) direct |
| Неэффективная комбинация | cache(yes) bypass_cache |
Построение политики безопасности (Blacklist vs Whitelist)¶
Whitelist подход (рекомендуемый для безопасности) — по умолчанию всё запрещено, разрешается только явно указанное:
define subnet corporate_subnet
10.10.12.0/24
end
; 1. Разрешить доступ корпоративным пользователям
<Proxy>
client.address=corporate_subnet allow
; 2. Требовать аутентификацию
<Proxy>
authenticate(corp_realm)
; 3. Фильтрация нежелательного контента
<Proxy>
url.domain=forbidden.com deny
category=(Gambling, Hacking, Chat) deny
; ... дополнительные слои
Blacklist подход — по умолчанию всё разрешено, блокируется только явно указанное:
Два подхода не являются взаимоисключающими. Лучшая стратегия часто комбинирует оба: whitelist для общей структуры, blacklist для специфических ограничений.
Исключения из общих правил¶
Исключения из общего правила можно выразить двумя способами:
Через порядок правил внутри слоя — наиболее специфические правила (исключения) располагаются первыми, общее правило — последним:
<Proxy>
; Исключение: HR-персонал имеет доступ к payroll
condition=payroll_location group=HR_staff allow
; Общее правило: payroll закрыт для всех
condition=payroll_location deny
Через порядок слоёв — общие правила в одном слое, исключения в следующем:
; Общее правило
<Proxy>
condition=payroll_location deny
; Исключение (в следующем слое — имеет приоритет)
<Proxy>
condition=payroll_location group=HR_staff allow
Гарантированный запрет¶
Действие deny может быть переопределено действием allow в последующем слое. Для гарантированного запрета, который не может быть переопределён, используйте force_deny или force_exception:
; Этот запрет гарантирован — никакие последующие allow его не отменят
<Proxy>
client.address=!corporate_subnet force_deny