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

Глава 3. Синтаксис CPL

3.1. Общие правила синтаксиса

Файл CPL — обычный текстовый файл в кодировке UTF-8. Каждая строка содержит либо определение (define), либо правило внутри слоя, либо комментарий.

Структура файла:

; 1. Определения (в любом порядке)
define subnet internal_nets
    10.0.0.0/8
end

define condition work_hours
    weekday=(1,2,3,4,5) hour=9..18
end

; 2. Слои с правилами
<Proxy>
    condition=work_hours client.address=internal_nets allow
    deny

<Forward>
    forward(upstream:3128)

Определения (define-блоки) должны располагаться перед слоями, в которых они используются. Слои могут следовать в любом порядке — движок обрабатывает их в фиксированном порядке приоритетов, не зависящем от порядка в файле (см. Глава 4).

3.2. Комментарии

Комментарий начинается с символа ; и продолжается до конца строки:

; Это комментарий на отдельной строке
<Proxy>
    url.domain=example.com deny    ; Комментарий после правила
    allow

3.3. Регистронезависимость

Имена условий, действий и ключевые слова — регистронезависимы:

; Все три записи эквивалентны:
url.domain=example.com DENY
URL.Domain=example.com deny
Url.Domain=example.com Deny

Значения строковых условий — регистрозависимы, если не указан модификатор regex с флагом (?i):

; Различаются:
request.header.X-Custom="Value"    ; совпадает только с "Value"
request.header.X-Custom="value"    ; совпадает только с "value"

; Регистронезависимый regex:
request.header.X-Custom.regex="(?i)value"    ; совпадает с любым регистром

3.4. Кавычки и экранирование

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

Без кавычек:

url.domain=example.com
client.address=10.0.0.0/8
url.extension=jpg

Допустимые символы без кавычек: a-zA-Z0-9_.-/:*

В двойных кавычках:

category="Entertainment and Videos"
url.path.regex="^/api/v[0-9]+/users$"
request.header.User-Agent="Mozilla/5.0"

В одинарных кавычках:

category='Entertainment and Videos'

Escape-последовательности (внутри двойных кавычек):

Последовательность Значение
\" Двойная кавычка
\\ Обратный слэш
\n Перевод строки
\r Возврат каретки
\t Табуляция

Неизвестные escape-последовательности сохраняются как есть — это важно для regex-паттернов:

; \. и \* сохраняются для regex
url.host.regex="^www\d+\.example\.com$"

Продолжение строки:

Символ \ в конце строки объединяет текущую строку со следующей:

url.domain=example.com \
    http.method=POST \
    deny

Это эквивалентно записи в одну строку:

url.domain=example.com http.method=POST deny

3.5. Переменные и подстановки

Redcoat поддерживает подстановку переменных в формате $(variable). Переменные раскрываются препроцессором до парсинга правил.

Подстановка в действиях:

<Proxy>
    category=Malware redirect("https://blockpage.corp/blocked?url=$(url)&client=$(client.address)")

Встроенные переменные:

Переменная Описание
$(url) Запрошенный URL
$(client.address) IP-адрес клиента
$(user), $(user.name) Имя аутентифицированного пользователя
$(group) Группа пользователя
$(appliance.name) Имя устройства
$(date) Текущая дата (YYYY-MM-DD)
$(time) Текущее время (HH:MM:SS)
$(timestamp) Unix timestamp
$(request.header.Name) Значение заголовка запроса
$(response.header.Name) Значение заголовка ответа
$(1) ... $(32) Capture groups из regex в rewrite/redirect

Пользовательские переменные:

Переменные могут быть определены в конфигурации и использованы в файле политики:

; Если в конфигурации определено: realm = "Corporate_LDAP"
<Proxy>
    authenticate($(realm))

Включение файлов (include):

include "defines/networks.cpl"           ; Обязательное включение
include.if_exists "local/overrides.cpl"   ; Необязательное (пропускается, если файл не найден)

Максимальная глубина вложенности include: 32 уровня. Циклические включения обнаруживаются и вызывают ошибку парсинга.

3.6. Булевы выражения

CPL-триггеры (условия) используют следующие булевы операторы:

Неявный AND (конъюнкция): Несколько триггеров на одной строке объединяются логическим И:

url.domain=example.com time=0900..1700 deny
; Истинно, если домен = example.com И время между 9:00 и 17:00

OR через список значений: Альтернативные значения в скобках через запятую или ||:

url.domain=(example.com, another.com) deny
; Эквивалентно: url.domain=(example.com || another.com) deny

NOT (отрицание): Префикс ! перед значением или оператор !=:

client.address=!corporate_subnet deny
url.domain!=trusted.com deny

Важно: Ключевые слова AND и OR зарезервированы для значений внутри одного триггера. Между триггерами AND неявный (пробел), OR недоступен. Для OR-логики между разными триггерами используйте define condition с несколькими строками.

3.7. Специальные символы и кавычки

Некоторые символы имеют специальное значение в CPL:

Символ Значение Пример
; Комментарий (до конца строки) ; This is a comment
= Разделитель имени триггера и значения url.domain=example.com
Пробел Разделитель выражений в правиле url.domain=example.com deny
\ Продолжение строки url.domain=example.com \
< > Заголовки слоёв <Proxy>
( ) Значение свойства или список значений cache(no), (a, b)

Если значение содержит специальные символы, его необходимо заключить в кавычки:

user="John Doe"                        ; значение содержит пробел
url="www.example.com/script.cgi?param=value"  ; значение содержит '='
deny("You don't have access to that page!")   ; несколько спецсимволов

Можно использовать как одинарные ('), так и двойные (") кавычки. Внутри двойных кавычек можно использовать все символы кроме двойной кавычки. Внутри одинарных — все кроме одинарной.

Совет: Внутри define action и define url_rewrite используйте двойные кавычки ("), а не одинарные ('), для ограничения строк.