|
UserGate Policy Language (UPL)
UPL (UserGate Policy Language) — язык описания политик UserGate. Термин "политика" употребляется здесь в контексте конфигурации правил, применяемых для принятия решений по требованиям аутентификации, правам доступа или преобразования контента. Правила настраиваются с использованием действий, условий и свойств. Для каждого правила настраивается одно из действий. Действия — настройки, которые управляют обработкой транзакции (OK, WARNING, PASS, DENY, FORCE_PASS, FORCE_DENY). При настройке правил, в которых не предусмотрено указание действия (например, правила DNS, NAT и маршрутизации, пропускной способности и т.п.), необходимо указать действия PASS или OK. Условия задаются знаками равно (=) или не равно (!=), например, зоны, адреса, GeoIP источников и назначения, сервисы, приложения и т.д.; все условия в правиле проверяются по логическому И, т.е. правило сработает, если будут выполнены все условия. Свойства правил задаются в круглых скобках и используются для указания дополнительной информации, например, название правил, их описание, функция журналирования и т.д. ПримечаниеПри настройке правил сначала указывается действие, потом условия и затем свойства.
UPL используется для создания правил в персональных слоях WAF. Также с помощью UPL в интерфейсе CLI создаются правила политик сети для следующих разделов:
Структура команды для создания правила:
где <level> — уровень, на котором необходимо создать правило. <position> — позиция, на которую будет помещено правило. <str-upl-syntax> строка, в которой описано правило в UPL синтаксисе. Структура команды для обновления существующего правила:
где <level> — уровень, на котором необходимо обновить правило. <position> — номер правила, которое необходимо обновить. <str-upl-syntax> строка, в которой описано правило в UPL синтаксисе. Структура команды для удаления правила:
где <level> — уровень, на котором необходимо удалить правило. <position> — номер правила, которое необходимо удалить. <all> — удалить все правила. Структура команды для отображения правила:
где <level> — раздел, правила которого нужно отобразить. <position> — номер правила, которое необходимо отобразить. <all> — отобразить все правила. Пример создания правила межсетевого экрана с использованием UPL (использован многострочный ввод):
После создания правило отобразиться в начале списка правил межсетевого экрана (на позиции 1). Данное правило запрещает HTTPS-трафик из зоны Trusted в зону Untrusted пользователям, идентифицированным системой. Правило работает в соответствии с расписанием "Working hours". При срабатывании правила в журнал будет записана информация о начале сессии. В последующих статьях данного раздела можно найти более подробную информацию об общих положениях языка UPL, определениях, встроенных библиотеках, условиях, действиях, свойствах и типах правил.
КомментарииЛюбая строка, начинающаяся с символа "%", является комментарием. Пример:
Комментарии могут быть в любом месте файла с описанием политик. ПравилаПравило политики (rule) состоит из условий и некоторого количества действий, записанных в любом порядке. Есть также свойства (properties), которые синтаксически выглядят как действие, но при этом активных действий не производят. Например, свойство name просто добавляет атрибут "имя" в правило. Правила обычно пишутся в одной строке, но могут быть разбиты на строки с помощью специального символа — обратного слеша "\". Когда правило выполняется, условие проверяется для текущей конкретной транзакции. Если условие оценивается как True (истина), выполняются все перечисленные действия и текущий слой заканчивается при наличии префиксов PASS / FORCE_PASS / DENY / FORCE_DENY / WARNING / OK. Ecли сработавшее правило не имеет префиксов PASS / FORCE_PASS / DENY / FORCE_DENY / WARNING / OK, то выполняются действия и дальше обрабатывается уже следующее правило. Если условие оценивается как False для этой транзакции, то дальше обрабатывается уже следующее правило. Все условия в правиле проверяются по логическому "И". Другими словами, правило сработает, когда будут выполнены все условия. В свою очередь, условие является логической комбинацией триггеров. Триггеры — это отдельные тесты, которые можно выполнить с компонентами запроса, ответа, связанными пользователями или состоянием системы. Действия — это настройки, которые управляют обработкой транзакции. Например, запретить (deny) или обработать объект (изменить заголовок — rewrite). Синтаксис: Rule ::= (PASS | FORCE_PASS | DENY| ( DENY '(' string ')') | FORCE_DENY | FORCE_DENY'(' string ') '| WARNING | OK)? Conditions '\'? Actions Conditions ::= condition '\'? Conditions Actions ::= action '\'? Actions Пример: Запрос будет запрещен, когда сработают оба триггера:
СлоиСлой (layer)— это конструкция UPL, используемая для группировки правил и принятия одного решения. Раздельные принятия решения помогают контролировать сложность политики. Это делается путем написания каждого решения в отдельном слое. У любого правила в слое может быть префикс PASS / FORCE_PASS / DENY / FORCE_DENY / OK / WARNING, когда срабатывает правило с таким префиксом, все остальные правила в слое пропускаются. В случае если сработало правило с префиксом FORCE_PASS или FORCE_DENY, то это является окончательным результатом обработки, в противном случае обработка переходит на следующий слой. После обработки всех слоев запрос будет заблокирован или пропущен в зависимости от того, что было последним — PASS / FORCE_PASS или DENY / FORCE_DENY. Если процессинг остановится на WARNING, будет добавлено предупреждение в тело ответа. Префикс OK подразумевает остановку обработки правил в текущем слое при выполнении условий и действий (если таковые указаны). Если префикс отсутствует при выполнении условий и действий, то остановка не подразумевается. Действия FORCE_PASS и FORCE_DENY похожи на PASS и DENY, за исключением того, что они могут быть переопределены на последующих слоях. FORCE_DENY и FORCE_PASS немедленно прекращают поверку правил как на текущем, так и на последующих слоях, и этот результат является окончательным. Синтаксис: Layer ::= '[' layer_type layer_name ']' layer_type ::= firewall | reverseproxy | reverseproxy_balancing layer_name ::= string atom ::= [a-z][0-9a-zA-Z_]+ string ::= '"' произвольная строка '"' Пример 1:
Пример 2:
Динамические значенияЗначения "адрес запроса" (url, url.host, url.path), "IP-адрес источника/назначения" (src.ip, dst.ip), "значения заголовков" (request и response) и "параметры запроса" (qparam) могут сравниваться между собой, а также использоваться в качестве аргумента в действиях (actions), где это предусмотрено. Условие (condition) в языке UPL является логической комбинацией триггеров. Триггеры — это отдельные тесты, которые можно выполнить с компонентами запроса, ответа, связанными пользователями или состоянием системы. Все триггеры условия сравниваются со значениями с помощью операторов "=" и "!=". В роли значения могут выступать константные значения, такие как строки, целочисленные значения, диапазоны значений, динамические значения. Синтаксис: condition ::= condition_name ('=' | '!=') condition_value condition_value ::= pattern | list list ::= '(' ((pattern ',')* pattern)? ')' pattern ::= word | string | integer | float | boolean| range | condition_name string ::= '"' произвольная строка '"' word ::= [a-zA-Z][0-9a-zA-Z_\-]* boolean ::= yes|no|true|false range ::= integer .. [integer] | [integer] .. integer | float .. [float] | [float] .. float numeric :: = integer | range http.methodПроверка используемого HTTP-метода. Метод можно указывать как в кавычках, так и без. Синтаксис: http.method = GET | CONNECT | DELETE | HEAD | POST | PUT | TRACE | OPTIONS | TUNNEL | LINK | UNLINK | PATCH | PROPFIND | PROPPATCH | MKCOL | COPY | MOVE | LOCK | UNLOCK | MKDIR | INDEX | RMDIR | COPY | MOVE http.request.versionПроверка версии HTTP-запроса. Синтаксис: http.request.version = 0.9 | 1.0 | 1.1 http.response.versionПроверка версии HTTP-ответа. Синтаксис: http.response.version = 0.9 | 1.0 | 1.1 http.response.codeПроверка HTTP-кода ответа. Валидные значения: 100 - 999. Синтаксис: http.response.code = NNN %(где NNN число от 100 до 999) http.request.body, http.request.body.nocase, http.response.body и http.response.body.nocaseПроверка тела запроса/ответа HTTP на содержание определенной сигнатуры. Пример:
request.header.<h_name> и response.header.<h_name>Проверка HTTP-заголовка запроса/ответа. h_name может принимать одно из поддерживаемых значений (смотрите список поддерживаемых HTTP-заголовков в Приложении). Синтаксис: request.header.<h_name>[.base64][.nocase] = string Пример:
request.header.<h_name>.substring и response.header.<h_name>.substringПроверка HTTP-заголовка запроса/ответа на вхождение подстроки. h_name может принимать одно из поддерживаемых значений (смотрите список поддерживаемых HTTP-заголовков в Приложении). Синтаксис: request.header.<h_name>[.base64]substring[.nocase] = string Пример:
request.header.<h_name>.regex и response.header.<h_name>.regexПроверка HTTP-заголовка запроса/ответа на регулярное выражение PCRE. h_name может принимать одно из поддерживаемых значений (смотрите список поддерживаемых HTTP-заголовков в Приложении). Синтаксис: request.header.<h_name>[.base64].regex = string Пример:
request.header.<h_name>.re2 и response.header.<h_name>.re2Проверка HTTP-заголовка запроса/ответа на регулярное выражение RE2. h_name может принимать одно из поддерживаемых значений (смотрите список поддерживаемых HTTP-заголовков в Приложении). Синтаксис: request.header.<h_name>[.base64].re2 = string Пример:
request.header.<h_name>.count и response.header.<h_name>.countПроверка количества заголовков <h_name> в HTTP-запросе/ответе. h_name может принимать одно из поддерживаемых значений (смотрите список поддерживаемых HTTP-заголовков в Приложении). Синтаксис: request.header.<h_name>.count = integer | range Пример:
request.header.<h_name>.length и response.header.<h_name>.lengthПроверка длины значений всех заголовков <h_name> в HTTP-запросе/ответе. h_name может принимать одно из поддерживаемых значений (смотрите список поддерживаемых HTTP-заголовков в Приложении). Синтаксис: request.header.<h_name>.length = integer | range Пример:
request.header_names, request.header_values, response.header_names и response.header_valuesПроверка имени/значения всех HTTP-заголовков запроса/ответа на значение. Синтаксис: request.header_values[.base64].regex = string request.header_values[.base64].re2 = string request.header_values[.base64].substring[.nocase] = string request.header_values.count = integer | range request.header_values.length = integer | range request.x_header.<xh_name> и response.x_header.<xh_name>Проверка HTTP-заголовка запроса/ответа на значение. xh_name — произвольный HTTP-заголовок. Синтаксис: request.x_header.<xh_name>[.base64][.nocase] = string request.x_header.<xh_name>[.base64].regex = string request.x_header.<xh_name>[.base64].re2 = string request.x_header.<xh_name>[.base64].substring[.nocase] = string request.x_header.<xh_name>.count = integer | range request.x_header.<xh_name>.length = integer | range Пример:
Возможны также суффиксы length, count, regex, re2 как и в случае с <h_name>.
request.header.Cookie.<cookie_name>Проверка заголовка запроса Cookie на значение. Синтаксис: request.header.Cookie.<cookie_name>[.base64][.(nocase | substring | substring.nocase | regex | re2)] = string Пример:
time, day, hour, minuteПроверка соответствия текущего времени заданному условию. Если не указан суффикс utc, время берется локальное, иначе — по Гринвичу. Синтаксис: day[.utc] = monday | tuesday | wednesday | thursday | friday | saturday | sunday | DD | list time[.utc] = HH:MM | range | lib.time(<name>) hour[.utc] = HH | range minute[.utc] = MM | range HH ::= 00 - 23 MM ::= 00 - 59 DD ::= 1 - 31 Пример:
Открытые интервалы учитываются по границе суток/часа.
url, url.host и url.addressПроверка url или его части на значение. Проверка использует нормализованный URI c декодированными *%*. Синтаксис: url[.(prefix | substring | suffix | regex | re2)] = string url.host[.(prefix | substring | suffix | regex | re2)] = string url.domain[.(prefix | substring | suffix | regex | re2)] = string url.address = ip_address | subnet | subnet_label url.port = [low_port]..[high_port] | port url.path[.base64][.(prefix | substring | suffix | regex | re2)] = string url.is_absolute = yes | no % полный или нет URL prefix ::= string % начало строки substring ::= string % подстрока suffix ::= string % окончание строки regex ::= string % регулярное выражение PCRE re2 ::= string % регулярное выражение RE2 url.address — это, по сути, синоним dst.ip. Пример:
qparam.<name>, qparam.values и qparam.namesПроверка значения параметров запроса. Проверка использует имена и значения параметров c декодированными *%*. Синтаксис: qparam.length = numeric % проверить общую длину query-параметров qparam.count = numeric % проверить количество query-параметров qparam.<name>[.(length | count)] = numeric qparam.<name>[.base64][.(nocase | substring | substring.nocase | regex | re2)] = string qparam.values[.base64].substring[.nocase] = string % проверить все значения на вхождение подстроки qparam.names[.base64].substring[.nocase] = string % проверить все имена на вхождение подстроки qparam.values[.base64].regex = string % проверить все значения на регулярное выражение qparam.names[.base64].regex = string % проверить все имена на регулярные выражения qparam.values[.base64].re2 = string % проверить все значения на регулярное выражение qparam.names[.base64].re2 = string % проверить все имена на регулярные выражения numeric ::= integer | range % число либо диапазон regex ::= string % регулярное выражение PCRE re2 ::= string % регулярное выражение RE2 Пример:
src и dstПроверка условия на IP-адрес, зону или GeoIP источника/назначения. Синтаксис: src.ip = ip_address | subnet | subnet_label | list | lib dst.ip = ip_address | subnet | subnet_label | list | lib src.zone = integer | zone_name dst.zone = integer | zone_name src.geoip = iso3166 | list dst.geoip = iso3166 | list src.mac = mac_address | list dst.mac = mac_address | list lib ::= lib.(network | url) '(' list_libs ')' list_libs :: = lib_name ','' list_libs lib_name ::= word | string iso3166 ::= [A-Z][A-Z] url.address — это, по сути, синоним dst.ip. response_timeПроверка времени ответа в миллисекундах. Синтаксис: response_time = integer Библиотеки (lib) — это элементы языка UPL, которые служат для доступа к встроенным и пользовательским библиотекам. Как правило, это достаточно большие списки, которые неудобно описывать через определения def. Обращение к библиотекам происходит по их именам. Синтаксис: library ::= lib.<url | useragent | network | time>(list_names) list_names ::= name list_names name ::= word | string url — список URL; Пример:
В файлах политик определения (def) служат для объединения наборов условий или действий. Каждое определение должно иметь уникальное пользовательское имя, по которому к нему можно обратиться из правил. def conditionНаборы условий. Все условия в одной строке проверяются по логическому И. Перевод строки означает логическое ИЛИ. Символ экранирования — обратный слэш ("\") в конце строки позволяет перенести условие по И на следующую строку. Синтаксис: def condition label_name conditions end conditions ::= condition '\'? [conditions] condition ::= name '=' value label_name ::= atom atom ::= [a-z][0-9a-zA-Z_]+ def varОпределение переменных. Служит для подсчета некоторых событий за определенный интервал времени. Для изменения значения предназначены действия inc и dec. Синтаксис: def var label_name init ::= integer window ::= time key ::= condition_name | condition_list end label_name ::= atom atom ::= [a-z][0-9a-zA-Z_]+ condition_list ::= '(' condition_name , condition_list ')' init — это начальное значение переменной, к которому она вернется по истечении времени window; key — поле или список полей, по которым группируются значения переменной (необязательный параметр). Свойства (properties) — это некие атрибуты правила, например, name или enabled. Они используются для предоставления дополнительной информации в процессе обработки правил. Синтаксис свойств точно такой же, как у действий. Синтаксис: property = prop_name | prop_name '(' list_params ')' prop_name ::= name | desc | id | rule_log | enabled list_params ::= value ',' list_params name и descАтрибуты имя и описание для правила. Синтаксис: Name ::= name '(' string|word ')' Description ::= desc '(' string ')' Пример:
enabledАтрибут, который включает или выключает работу правила. Синтаксис: Enable ::= enabled '(' boolean ')' boolean ::= yes | no | true | false % (по умолчанию false) rule_logУстанавливает атрибут журналирования правила. Значение session действительно только для правил межсетевого экрана, защиты от dos-атак и пропускной способности. Синтаксис: Logging ::= rule_log '(' boolean | session ')' LoggingFwRule ::= rule_log '(' boolean , interval, burst')' boolean ::= yes | no | true | false % (по умолчанию no) interval ::= "integer/[s,m,h,d]" burst ::= integer interval — среднее число пакетов, попадающих под условие limit в единицу времени (1/s, 1/m, 1/h, 1/d) , default = 3/h; profileУстанавливает профиль правила. Синтаксис: Profile ::= profile '(' string | word | list ')' certificateСертификат, используемый для поддержки HTTPS-соединения. Действительно только для правил reverse-прокси. Синтаксис: CertAuthEnabled ::= cert_auth_enabled '(' boolean ')' Certificate ::= certificate '(' certificate_name ')' certificate_name ::= string | word gatewayШлюз. Имя одного из существующих шлюзов. Действительно только для правил NAT и маршрутизации, и для условий сценария "Проверка состояния". Синтаксис: Gateway ::= gateway '(' string | word ')' Свойства правил межсетевого экранаreject_withУстанавливает способ, с помощью которого будет блокироваться трафик. Действительно только для правил межсетевого экрана. Синтаксис: Reject ::= reject_with '(' "tcp-reset-both" | "tcp-rst" | "host-unreach" ')' fragmentedПроверка на фрагментированность пакетов. Действительно только для правил межсетевого экрана. Синтаксис: Fragmented ::= fragmented '(' boolean ')' boolean ::= yes | no | true | false yes — проверяются только фрагментированные пакеты;
|
|
Имя |
Описание |
|---|---|
|
PASS |
Разрешение трафика. |
|
DENY |
Блокировка трафика. |
Условия
Свойства
name, desc, enabled, rule_log, reject_with.
Пример
[firewall "Firewall rules"]
% ----------------- 1 -----------------
DENY \
scenario = "Example torrent detection scenario" \
dst.zone = Untrusted \
dst.ip = lib.network("Botnets IP list") \
rule_log(session) \
reject_with("host-unreach") \
enabled(true) \
name("Example block RU RKN by IP list")
% ----------------- 2 -----------------
PASS \
scenario = "Example torrent detection scenario" \
src.zone = Trusted \
dst.zone = Untrusted \
rule_log(yes, "3/h", 5) \
enabled(true) \
name("Allow trusted to untrusted")
Правила защиты почтового трафика
Префиксы
|
Имя |
Описание |
|---|---|
|
PASS |
Пропуск трафика без изменений. |
|
DENY ("with error") |
Блокировка письма, при этом сообщается об ошибке доставки письма на сервер. |
|
DENY |
Блокировка письма без уведомления о блокировке. |
|
WARNING |
Маркировка почтовых сообщений. |
Условия
user, service, envelope_from, envelope_to.
Свойства
name, desc, enabled, rule_log, mark_hdr, mark, antispam_usergate, dnsbl.
Пример
[mailsecurity "Mail Security Rules"]
% ----------------- 1 -----------------
PASS \
user = (example, "CN=VPN users,DC=LOCAL") \
envelope_from = "Email froup from" \
envelope_to = "Email froup to" \
service = SMTP \
rule_log(yes) \
mark_hdr(Subject) \
enabled(true) \
name("Mail Pass Rule")
% ----------------- 2 -----------------
DENY("with error") \
service = (SMTPS, SMTP) \
rule_log(yes) \
mark_hdr(Subject) \
antispam_usergate(yes) \
enabled(true) \
name("Mail Drop Rule")
% ----------------- 3 -----------------
DENY \
src.zone = Untrusted \
service = SMTP \
mark_hdr(Subject) \
dnsbl(yes) \
enabled(false) \
name("DNSBL spam drop rule")
% ----------------- 4 -----------------
WARNING \
src.zone = Untrusted \
service = (SMTP, POP3, SMTPS, POP3S) \
mark_hdr(Subject) \
mark("[SPAM]") \
antispam_usergate(yes) \
enabled(false) \
name("SMTP and POP3 filtering")
Правила reverse-прокси
Префиксы
|
Имя |
Описание |
|---|---|
|
OK |
Всегда ОК. |
Условия
src.zone, src.geoip, src.ip, src.mac.
request.header.User-Agent, url.port.
Свойства
name, desc, enabled, rule_log, profile, certificate, is_https, ssl_profile,
Пример
[reverseproxy "Reverse proxy Rules"]
% ----------------- 1 -----------------
OK \
url.port = 80 \
src.zone = Untrusted \
desc("Example reverse proxy rule. This is an example rule which can be changed or deleted if necessary. ") \
profile("Example reverse proxy server") \
rewrite_path("example.com/path1", "example.local/path1") \
waf_profile("Example WAF profile") \
enabled(true) \
name("Example reverse proxy rule")
Правила балансировки reverse-прокси
Префиксы
|
Имя |
Описание |
|---|---|
|
OK |
Всегда ОК. |
Свойства
Пример
[reverseproxy_balancing "Reverse proxy load balancing Rules"]
% ----------------- 1 -----------------
OK \
profile("Example reverse proxy server") \
enabled(true) \
name("Reverse-proxy load balancing")
Правила временной блокировки IP-адреса
Префиксы
|
Имя |
Описание |
|---|---|
|
DENY |
Блокировка IP-адреса |
Условия
Свойства
Пример
В примере для конкретного источника (условие scr.ip) настроен подсчет количества кодов ответа 404. Если количество таких ответов за последние 30 секунд превысит 10, IP-адрес этого источника будет заблокирован на одну минуту.
def var counter_404
init = 0
window = 00:00:30
key = src.ip
end
def var block
init = 0
window = 00:01:00
key = src.ip
end
DENY var.block = 1.. log_message("Black list") enabled(true) name("Black list")
http.response.code = 404 inc(var.counter_404, 1) log_message("Incriment counter") enabled(true) name("Incriment counter")
DENY var.counter_404 = 10.. inc(var.block, 1) log_message("Enable block") enabled(true) name("Enable block")
|
HTTP Header |
Request/Response |
SET/REPLACE/ENCRYPT |
APPEND |
DELETE |
|---|---|---|---|---|
|
Accept |
Request |
|
|
|
|
Accept-Charset |
Request |
|
|
|
|
Accept-Encoding |
Request |
|
|
|
|
Accept-Language |
Request |
|
|
|
|
Accept-Ranges |
Response |
|
|
|
|
Age |
Response |
|||
|
Allow |
Request/Response |
|
|
|
|
Authorization |
Request |
|||
|
Cache-Control |
Request/Response |
|
|
|
|
Client-IP |
Request |
|
|
|
|
Connection |
Request/Response |
|
||
|
Content-Encoding |
Request/Response |
|
||
|
Content-Language |
Request/Response |
|
||
|
Content-Length |
Request/Response |
|||
|
Content-Location |
Request/Response |
|
|
|
|
Content-Range |
Request/Response |
|||
|
Content-Type |
Request/Response |
|||
|
Cookie |
Request |
|
|
|
|
Date |
Request/Response |
|||
|
ETag |
Response |
|
|
|
|
Expect |
Request |
|
||
|
Expires |
Request/Response |
|
|
|
|
From |
Request |
|
|
|
|
Host |
Request |
|||
|
If-Match |
Request |
|
||
|
If-Modified-Since |
Request |
|||
|
If-None-Match |
Request |
|
||
|
If-Range |
Request |
|||
|
If-Unmodified-Since |
Request |
|||
|
Last-Modified |
Request/Response |
|||
|
Location |
Response |
|
|
|
|
Max-Forwards |
Request |
|||
|
Meter |
Request/Response |
|
|
|
|
Pragma |
Request/Response |
|
|
|
|
Proxy-Authenticate |
Response |
|
||
|
Proxy-Authorization |
Request |
|
||
|
Proxy-Connection |
Request |
|
||
|
Range |
Request |
|
|
|
|
Referer |
Request |
|
|
|
|
Retry-After |
Response |
|
|
|
|
Server |
Response |
|
|
|
|
Set-Cookie |
Response |
|
|
|
|
TE |
Request |
|
||
|
Trailer |
Request/Response |
|
||
|
Transfer-Encoding |
Request/Response |
|
||
|
Upgrade |
Request/Response |
|
||
|
User-Agent |
Request |
|
|
|
|
Vary |
Response |
|
|
|
|
Via |
Request/Response |
|
|
|
|
Warning |
Request/Response |
|
|
|
|
WWW-Authenticate |
Response |