Перейти к содержанию

Глава 23. Дополнительные условия

Условия этой главы покрывают прочие аспекты транзакции, не вошедшие в предыдущие главы: определение режима прокси (transparent vs explicit) и пользовательские атрибуты.

23.1. is_transparent=

Проверяет, было ли соединение клиента перехвачено через transparent proxy (без явной настройки прокси на клиенте). Transparent proxy перехватывает трафик на сетевом уровне с помощью SO_ORIGINAL_DST или аналогичных механизмов.

Статус: планируется. Использование в CPL файле приведёт к ошибке парсинга.

Аналог в BlueCoat: tunneled= (BlueCoat) — проверяет, является ли транзакция туннелированной (CONNECT). Условие is_transparent= в Redcoat проверяет другой аспект: способ подключения клиента к прокси, а не тип HTTP-транзакции.

Синтаксис:

is_transparent=yes|no

where:

  • yes — соединение перехвачено через transparent proxy.
  • no — клиент подключён не через transparent interception.

Слои и транзакции: Proxy.

Пример:

<Proxy>
    ; Для transparent-клиентов — показать captive portal
    is_transparent=yes session.has_valid_session=no redirect(302, "https://portal.corp.local/")

    ; Разные правила для transparent и explicit
    is_transparent=yes category=Streaming deny

См. также: is_explicit= (раздел 23.2), proxy.port= (глава 7).

23.2. is_explicit=

Проверяет, подключился ли клиент к прокси через явную (explicit) настройку — клиент осознанно настроен на использование прокси-сервера (через системные настройки, PAC-файл или переменные окружения).

Статус: планируется. Использование в CPL файле приведёт к ошибке парсинга.

Синтаксис:

is_explicit=yes|no

where:

  • yes — клиент подключён через explicit proxy.
  • no — клиент подключён не через explicit proxy.

Слои и транзакции: Proxy.

Пример:

<Proxy>
    ; Explicit-клиентам доступна полная аутентификация
    is_explicit=yes authenticate(corporate_realm)

    ; Блокировать SOCKS через explicit proxy
    is_explicit=yes socks.version=5 deny

См. также: is_transparent= (раздел 23.1).

23.3. Атрибуты пользователя (attribute.*)

Проверяет атрибуты аутентифицированного пользователя, полученные из LDAP-директории или RADIUS-ответа при аутентификации. Атрибуты загружаются автоматически при успешной аутентификации — все атрибуты из LDAP-записи пользователя становятся доступны для условий политики.

Совместимость: BlueCoat attribute.name= (C-002 в матрице Layer Support).

Синтаксис:

attribute.<name>=<value>
attribute.<name>!=<value>
has_attribute.<name>=yes|no

where:

  • <name> — имя LDAP/RADIUS атрибута (например, department, title, Service-Type). Регистрозависимо.
  • <value> — ожидаемое значение атрибута. Можно использовать кавычки для значений с пробелами: attribute.title="Senior Developer".
  • has_attribute.<name>=yes — проверяет только наличие атрибута (без проверки значения).
  • Поддерживается отрицание: attribute.<name>!=value и has_attribute.<name>=no.

Слои и транзакции: Proxy, Cache, Forward, SSL, SSL-Intercept, Admin, DNS-Proxy, Exception, Diagnostic.

Источник атрибутов:

Backend Источник Пример атрибутов
LDAP Запись пользователя (objectClass=*) departmentNumber, title, mail, employeeType
RADIUS Access-Accept ответ Service-Type, Filter-Id (планируется)

Примеры:

<Proxy>
    authenticate(LDAPRealm)

<Proxy>
    ; Разрешить только инженерам
    attribute.departmentNumber=Engineering ALLOW
    deny

    ; Блокировать по уровню риска
    attribute.risk_level=high deny

    ; Проверка наличия атрибута
    has_attribute.vpn_connected=yes ALLOW

Производительность: Атрибуты загружаются из LDAP одним дополнительным запросом при аутентификации. Условие attribute.* проверяется после индексного сопоставления, дополнительные затраты — около 50 нс.

Кеширование атрибутов: Атрибуты сохраняются в кеше аутентификации и IP-суррогате. При попадании в кеш или суррогат атрибуты автоматически восстанавливаются. IP-суррогат очищается при установке новой политики. При наличии заголовка Proxy-Authorization с другим именем пользователя суррогат пропускается, и учётные данные перепроверяются.

23.4. LDAP-атрибуты (ldap.attribute.*)

Специализированные формы проверки атрибутов LDAP-директории. В отличие от общего attribute.<name>= (раздел 23.3), эти формы позволяют проверять наличие атрибута, сравнивать его как число и проверять количество значений. Используют тот же источник — state.user_attributes, загружаемый при LDAP-аутентификации.

Совместимость: BlueCoat ldap.attribute.<name>=, .exists=, .as_number=, .count=.

Синтаксис:

ldap.attribute.<name>=<value>            ; сравнение значения (exact/wildcard/list)
ldap.attribute.<name>.exists=yes|no      ; наличие атрибута
ldap.attribute.<name>.as_number=<range>  ; значение как число (N, N..M, >N, <N)
ldap.attribute.<name>.count=<range>      ; количество значений атрибута

Примеры:

<Proxy>
    authenticate(LDAPRealm)

    ; Сравнение значения
    ldap.attribute.department=Engineering allow

    ; Наличие атрибута
    ldap.attribute.mail.exists=yes allow

    ; Числовое сравнение (employeeID в диапазоне)
    ldap.attribute.employeeID.as_number=1000..9999 allow

    ; Количество значений (членство хотя бы в одной группе)
    ldap.attribute.memberOf.count=1 allow
    deny

where:

  • <name> — имя LDAP-атрибута. Регистрозависимо.
  • .exists=yes|no — проверяет наличие атрибута в записи пользователя.
  • .as_number=<range> — значение атрибута парсится как целое (u64) и сравнивается с диапазоном. Если значение не число — условие не срабатывает.
  • .count=<range> — количество значений атрибута.

Ограничение: одно значение на атрибут

Текущее хранилище атрибутов содержит одно значение на имя атрибута. Поэтому ldap.attribute.<name>.count= возвращает 0 (атрибут отсутствует) или 1 (присутствует). Полноценная поддержка многозначных LDAP-атрибутов будет добавлена позже.

Слои: Proxy, Cache, Forward, SSL, SSL-Intercept, Admin, Exception, Diagnostic. Условие проверяется после индексного сопоставления.

См. также: attribute.*, has_attribute.* (раздел 23.3).

authenticate() + deny — приоритеты (CPL Reference 7.3):

  • deny имеет более высокий приоритет, чем authenticate() («Deny has precedence over authentication… does not depend on the order of the layers», CPL Ref 7.3). Поэтому если в слое есть authenticate(realm) и deny (любой — catch-all или условный), который применяется, неаутентифицированный пользователь получает отказ (403/exception) БЕЗ challenge. Имя пользователя при этом не попадёт в access log.
  • Чтобы гарантированно выдать challenge ПЕРЕД deny (например, ради логирования user id для отклонённых запросов), используйте authenticate.force(realm) (force_authenticate) — у него приоритет ВЫШЕ deny. Тогда неаутентифицированный пользователь сначала получит challenge, аутентифицируется, и лишь потом применится deny/allow.

Тип challenge зависит от Authentication Mode (не от политики): proxy*407 Proxy-Authenticate (клиент отвечает Proxy-Authorization); origin*401 WWW-Authenticate (клиент отвечает Authorization, OCS-style); form*302 redirect на captive-portal.

Пример (challenge-first через force):

<Proxy>
    authenticate.force(LdapRealm)   ; приоритет выше deny → challenge ПЕРВЫМ
    authenticated=yes ALLOW
    DENY                            ; применится только после аутентификации
</Proxy>
Без force (authenticate(LdapRealm) + DENY) неаутентифицированный запрос был бы отклонён сразу (403), не увидев challenge.

См. также: user= (глава 12), group= (глава 12), authenticated= (12.1).

23.4a. SAML-атрибуты (saml.attribute.*)

Проверяет значение атрибута из SAML-assertion, полученного при аутентификации в SAML realm. Аналог ldap.attribute.* (раздел 23.4), но источник данных — атрибуты SAML-утверждения (assertion attributes), а не запись LDAP-директории.

Совместимость: BlueCoat saml.attribute.<attribute_name>=.

Синтаксис:

saml.attribute.<attribute_name>[.string_modifier][.case_sensitive]=pattern

где:

  • <attribute_name> — имя атрибута SAML-assertion;
  • pattern — значение для сравнения (точное совпадение, wildcard или список);
  • string_modifier — модификатор строкового сравнения (необязателен), как у прочих строковых условий;
  • case_sensitive — признак учёта регистра при сравнении (необязателен).

Примеры:

<Proxy>
    authenticate(SAMLRealm)

    ; Доступ по значению атрибута департамента из SAML-assertion
    saml.attribute.department=Engineering allow
    deny

Слои: Proxy, Cache, Forward, SSL, SSL-Intercept, Admin, Exception, Diagnostic.

См. также: LDAP-атрибуты ldap.attribute.* (23.4), attribute.* (23.3), realm= (12.5).

23.3a. Битрейт потокового видео (bitrate=)

Проверяет битрейт потокового видео (HLS/DASH), определённый из манифеста. Прокси автоматически парсит HLS master playlist (.m3u8) и DASH MPD (.mpd), извлекает доступные варианты битрейта и кеширует соответствие URL→битрейт. При последующих запросах за сегменты видео, условие bitrate= сопоставляет битрейт запрошенного варианта.

Совместимость: BlueCoat bitrate= (C-004 в матрице Layer Support). В BlueCoat поддерживает RTSP/MMS/RTMP — в Redcoat поддерживаются HTTP-based протоколы: HLS и DASH.

Синтаксис:

bitrate=<exact>
bitrate=<min>..<max>
bitrate=..<max>
bitrate=<min>..

where: значения в битах в секунду. Суффиксы: k = ×1000, m = ×1000000, g = ×1000000000. Примеры: 56k = 56000 bps, 2m = 2000000 bps, 1g = 1000000000 bps.

Слои и транзакции: Proxy, Cache.

Как работает:

  1. Клиент запрашивает HLS master playlist через прокси
  2. Прокси парсит ответ, извлекает BANDWIDTH= из #EXT-X-STREAM-INF
  3. Кеширует соответствие URL variant → битрейт (TTL 5 мин)
  4. При запросе сегмента видео — определяет битрейт из кеша
  5. CPL правило bitrate= проверяет этот битрейт

Примеры:

<Proxy>
    ; Запретить потоковое видео выше 2 Mbps
    bitrate=2000001..999999999 deny
    ALLOW

    ; Разрешить группе VIP до 10 Mbps, остальным до 1 Mbps
    group=VIP bitrate=10000001..999999999 deny
    bitrate=1000001..999999999 deny
    ALLOW

Производительность: Нулевые затраты для не-потокового трафика (одна проверка Content-Type). Для потокового: около 50 нс на поиск по таблице при каждом запросе сегмента. Разбор манифеста: менее 0,1 мс (один раз при первом запросе).

Поддерживаемые форматы:

Формат Content-Type Расширение Парсинг
HLS Master Playlist application/vnd.apple.mpegurl .m3u8 #EXT-X-STREAM-INF:BANDWIDTH=
DASH MPD application/dash+xml .mpd <Representation bandwidth="...">

См. также: max_bitrate() (глава 32) — ограничение скорости передачи (throttle).

23.3b. Прочие потоковые условия (streaming.*)

Статус: в процессе реализации. Условия streaming.rtmp.* принимаются парсером (имена как в BlueCoat, политика загружается), но разбор протокола RTMP отсутствует — данные не заполняются, правило с ними не сработает.

streaming.rtmp.app_name=имя
streaming.rtmp.method=метод
streaming.rtmp.page_url=url
streaming.rtmp.stream_name=имя
streaming.rtmp.swf_url=url

Условия streaming.client= и streaming.content= (BlueCoat) парсером не принимаются (использование приведёт к ошибке загрузки политики). Для HTTP-стриминга используйте live= (раздел 9.12) и bitrate= (раздел 23.3a).

23.4. Условия X-Forwarded-For

Проверяет наличие и значение заголовка X-Forwarded-For (используется при каскадировании прокси). Эти условия реализуются через общие условия заголовков (глава 10) и не требуют отдельного парсера.

Синтаксис:

request.header.X-Forwarded-For.exists=yes|no
request.header.X-Forwarded-For.address=ip_or_subnet

Слои и транзакции: Proxy.

Пример:

<Proxy>
    ; Проверить наличие заголовка (каскадный прокси)
    request.header.X-Forwarded-For.exists=yes log.header.x-forwarded("true")

    ; Проверить адрес в X-Forwarded-For
    request.header.X-Forwarded-For.address=10.0.0.0/8 ALLOW

См. также: request.header.* (глава 10), client.address= (глава 7).


23.x. Условия классификации приложений (request.application.*)

Статус: в процессе реализации. Движок классификации приложений отсутствует. request.application.name= и request.application.operation= принимаются парсером, но правило с ними не сработает. Формы request.application.group= и request.application.attribute= (имена BlueCoat) парсером пока не принимаются; ближайшие принимаемые варианты — request.application.type= и request.application.behavior= (также в процессе реализации).

Группа условий для политик по веб-приложениям (имена как в BlueCoat):

request.application.name=имя_приложения
request.application.operation=операция

23.5. random= — вероятностная выборка

Условие вероятностной выборки: для каждого правила условие истинно приблизительно 1 раз из n (вероятность 1/n). Используется в сочетании с другими условиями — чтобы применить действие (трассировку, логирование, выборочную инспекцию) не ко всем подходящим транзакциям, а к их случайной доле. Например, random=10 совпадает примерно для 10 % транзакций, random=100 — для 1 %.

Семантика как в BlueCoat 7.3. «n: The condition evaluates to true approximately 1/n times for the policy rule.»

Синтаксис:

random=n

where:

  • n — условие истинно приблизительно 1/n раз (чем больше n, тем реже совпадение).

Слои и транзакции: все прокси-транзакции.

Пример:

<Diagnostics>
    ; Трассировать случайную выборку GET-запросов
    http.method=GET random=10 trace.request(yes)

См. также: trace.request() (34.1), условия времени (глава 14).

23.6. admin.access=

Проверяет тип (уровень) административного доступа в текущей управляющей транзакции. Используется в слое <Admin> для разграничения политик чтения и записи при доступе к управлению прокси.

Имя как в BlueCoat. Реализованы оба смысла: условие admin.access= (проверка) и действие admin.access(read-write) (установка уровня доступа, см. приложение A.1).

Синтаксис:

admin.access={read|write}

where:

  • read — доступ только на чтение (просмотр конфигурации/состояния);
  • write — доступ на запись (изменение конфигурации).

Слои и транзакции: <Admin>.

Пример:

<Admin>
    ; Операции записи разрешить только администраторам
    admin.access=write group=Administrators allow
    admin.access=write deny

    ; Чтение разрешено всем аутентифицированным
    admin.access=read authenticated=yes allow

См. также: слой <Admin> (4.10), authenticated= (12.1), group= (12.4), приложение A.1.