Сценарии

Общие сведения о Сценариях

Сценарии – это lua-скрипты, являющиеся дополнением к основным параметрам конфигурации Виртуальных Серверов.

С помощью Сценариев (lua-скриптов) можно:

  • выбирать Сервер Балансировки (Content Switching (cs));

  • изменять содержимое запросов/ответов (Rewrite);

  • отвечать на HTTP-запрос (Responder);

  • прерывать нежелательные соединения.

lua-скрипты применяются к:

  • Виртуальному Серверу для:

    • выбора Сервера Балансировки (Content Switching (cs));

    • ответа на HTTP-запрос (Responder);

    • изменения содержимого запросов (Rewrite);

    • прерывания нежелательного соединения;

  • Серверу балансировки для:

    • ответа на HTTP-запрос (Responder) (например, при условии получении ответа);

    • изменения содержимого ответов (Rewrite);

    • прерывания нежелательного соединения (например, при условии получении ответа).

Условия выполнения того или иного действия определяются:

  • логическими выражениями if, elseif, else, end;

  • любыми данными, полученными из запроса, а также их комбинацией. Например:

    • if client.http_req.host == "abc.ru" then – если имя хоста из запроса эквивалентно «abc.ru», то выполнить какое-либо действие;

    • if (client.http_req.host == "abc.ru" and client.remote_p.ip == "10.140.0.200") then – если имя хоста из запроса эквивалентно «abc.ru», и запрос пришел с IP-адреса 10.140.0.200, то выполнить какое-либо действие.

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

Пример для curl qwe.123.ru/abczxc (см. Пример выражений для работы с данными):

> GET /abczxc HTTP/1.1
> Host: qwe.123.ru
> User-Agent: curl/7.81.0
Таблица 1. Пример выражений для работы с данными
Выражение Результат Комментарий

if client.http_req.path == "/abcZxc"

true

Эквивалентно

if client.http_req.path == "/abc"

false

if (client.http_req.path:find("zx"))

true

Содержит значение

client.http_req.host:match("(.*).123.ru")

qwe

Вернет строку, значение ДО « .123.ru»

Использование в Сценариях балансировки

Обработка правил в Сценариях балансировки осуществляется через глобальные переменные:

  • storage – содержит методы для работы с путями к каталогам, которые будут доступны при вызове из lua-скрипта;

  • client – содержит методы для работы с клиентом и запросом.

Обработка правил Сценария останавливается после выражения: client.action = "xxx".

Описание полей приведено в таблице ниже.

Таблица 2. Описание полей переменной storage
Поле Тип поля Описание

storage:path(name)

Строка

Возвращает путь к каталогу, к которому можно обращаться по его наименованию (name) из Lua-скрипта.

В текущей версии name принимает только значение www.

Пример: выражение storage.path("www") вернет /var/lib/tdc/www

storage:sub_path(name, path)

Строка

Формирует полный путь (path) к файлу или подкаталогу внутри указанного каталога (name).

В текущей версии name принимает только значение www.

Пример: выражение storage:sub_path("www", "page.html") вернет /var/lib/tdc/www/page.html

Таблица 3. Описание полей переменной client
Поле Тип поля Описание

client.local

Структура

Псевдоним, то же самое, что client.local_p. Доступно только для чтения

client.local_p

Структура

Содержит поля локальной точки подключения. Доступно только для чтения

client.local_p.ip

Строка

Возвращает локальный IP-адрес подключения (IP-адрес Виртуального Сервера, vip.ip)

client.local_p.port

Строка

Возвращает локальный порт подключения (порт Виртуального Сервера, vip.port)

client.remote

Структура

Псевдоним, то же самое, что client.remote_p. Доступно только для чтения

client.remote_p

Структура

Содержит поля удаленной точки подключения (клиента). Доступно только для чтения

client.remote_p.ip

Строка

Возвращает IP-адрес клиента. Доступно только для чтения

client.remote_p.port

Целое

Возвращает порт клиента. Доступно только для чтения

client.action

Строка

Определяет действие, которое необходимо выполнить.

Для Сценария балансировки:

  • client.action = "bs" – возвращает Сервер Балансировки, определенный в client.bs;

  • client.action = "gw" – возвращает Шлюз, определенный в client.gw;

  • client.action = "respond" – возвращает ответ клиенту, не передавая запрос на Реальный Сервер. Содержимое ответа описывается в client.respond.status;

  • client.action = "drop" – сбрасывает соединение;

Для Сценария модификации ответа:

  • client.action = "respond" – возвращает ответ клиенту, не передавая запрос на Реальный Сервер. Содержимое ответа описывается в client.respond.status;

  • client.action = "drop" – сбрасывает соединение;

  • client.action = "pass" – используется для модификации ответов, после этого ответ передается клиенту

При использовании аутентификации пользователя:

  • client.action = "auth" – останавливает обработку для аутентификации пользователя

client.bs

Строка

Определяет имя Сервера Балансировки. Пример: client.bs = "lb1".

При использовании в Сценарии балансировки свойство чтения и записи применяется, если client.action = "bs".

При использовании в Сценарии модификации ответа доступно только чтение, ответ будет содержать имя Сервера Балансировки

client.gw

Строка

Определяет имя Шлюза. Пример: client.gw = "gw1"

client:bs_state(lbs_name)

Строка

Возвращает статус Сервера Балансировки (lbs_name). Пример: client:bs_state("ws1").

Возвращаемые значения:

  • NOT_FOUND;

  • ONLINE;

  • OFFLINE;

  • UNKNOWN

client.http_req

Структура или nil

Класс для работы с HTTP-запросами. Описание полей приведено в таблице (см. таблицу Описание полей структуры client.http_req)

В текущей версии Termidesk Connect значение nil для балансировки уровня L7 вернуться не может.

client.http_resp

Структура

Класс для работы с HTTP-ответами. Существует только для Сценария модификации ответа. Описание полей приведено в таблице (см. таблицу Описание полей структуры client.http_resp)

client.rs.ip

Строка

Возвращает IP-адрес Реального Сервера

client.rs.port

Строка

Возвращает порт Реального Сервера

client.respond

Структура

Класс для генерации HTTP-ответа. Применяется, если client.action == "respond". Описание полей приведено в таблице (см. таблицу Описание полей структуры client.respond)

client.aaa

Структура

Класс для работы с AAA. Описание полей приведено в таблице (см. таблицу Описание полей структуры client.aaa)

client.proxy_proto

Структура или nil

Опциональное поле. Содержит nil или заголовок PROXY-протокола, если он был получен. Описание полей приведено в таблице (см. таблицу Описание полей структуры client.proxy_proto и client.proxy_proto.ssl)

client.proxy_proto.ssl

Структура или nil

Содержит nil или значение TLV PP2_TYPE_SSL, если оно было передано. Описание полей приведено в таблице (см. таблицу Описание полей структуры client.proxy_proto и client.proxy_proto.ssl)

client.sso

Структура

Класс для работы с SSO. Описание полей приведено в таблице (см. таблицу Описание полей структуры client.sso)

client.tls

Структура

Класс для чтения информации из сертификата клиента. Содержит данные начального этапа установления TLS-соединения. Описание полей приведено в таблице (см. таблицу Описание полей структуры client.tls)

Некоторые поля структуры поддерживаются только для mTLS.

Примеры из таблицы ниже отражены в этом ответе на запрос к узлу termideskconnect по протоколу HTTP:

GET /termideskconnect?test=query HTTP/1.0
Host: connect.termidesk.ru
User-Agent: Mozilla Firefox/3.0.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Cookie: sessionid=100TC
Таблица 4. Описание полей структуры client.http_req
Поле Тип поля Описание

Работа с заголовками – client.http_req.header

client.http_req.header:count()

Целое

Возвращает количество заголовков

client.http_req.header:get(i)

Строка

Возвращает пару: ключ и значение. Пример: X-Forwarded-For : 1.2.3.4

client.http_req.header:del([i])

Таблица (список строк)

Удаляет значение заголовка, индекс (i) опционален:

  • если индекс не задан, то удалятся все заголовки;

  • если индекс меньше 1, то удалится первый заголовок (равносильно i = 1);

  • если индекс больше, чем client.http_req.header:count(), то удалится последний заголовок

client.http_req.header:field_count(name)

Целое

Возвращает количество всех заголовков с именем name

client.http_req.header:field_get(name [,i])

Строка или nil

Возвращает пару: ключ (имя заголовка с учетом регистра) и значение:

  • если индекс не задан, то i = client.http_req.header:size_field(name), возвращается последний найденный заголовок с именем name;

  • если индекс меньше 1 или больше client.http_req.header:field_count(name), то ключ и значение будут nil.

Значения параметров:

  • name – имя заголовка, строка без учета регистра;

  • i – индекс повторения заголовка name

client.http_req.header:field_set(name, value [,i])

Таблица (список строк)

Устанавливает значение заголовка (key, value) по индексу повторения (i):

  • если value число, то оно конвертируется в строку;

  • если индекс не задан, то удалятся все существующие заголовки, где name = key. Запишется только один заголовок;

  • если индекс меньше 1, то перезапишется первый заголовок (равносильно i = 1);

  • если индекс больше client.http_req.header:field_count(name), то перезапишется последнее вхождение заголовка;

  • если заданные key и value не найдены, то произойдет новая запись.

Значения параметров:

  • name – имя заголовка, строка без учета регистра;

  • value – значение, строка или число;

  • i – индекс повторения заголовка name

client.http_req.header:field_del(name, [i])

Таблица (список строк)

Удаляет заголовок (name) по индексу повторения (i):

  • если индекс не задан, то удалятся все существующие заголовки с именем name;

  • если индекс меньше 1, то удалится первое вхождение заголовка name (равносильно i = 1);

  • если индекс больше, чем client.http_req.header:field_count(name), то удалится последнее вхождение заголовка name;

  • если name не найден, то действий не произойдет.

Значения параметров:

  • name – имя заголовка, строка без учета регистра;

  • i – индекс повторения заголовка name, опциональный параметр

client.http_req.header:field_push(name, value [,i])

Строка

Добавляет (продвигает) заголовок (key, value) по индексу повторения (i):

  • если value число, то оно конвертируется в строку;

  • если индекс не задан или больше client.http_req.header:field_count(name), то заголовок добавится в конец;

  • если индекс меньше 1, то заголовок добавится в начало (равносильно i = 1);

  • если заданные key и value не найдены, то произойдет новая запись.

Значения параметров:

  • name – имя заголовка, строка без учета регистра;

  • value – значение, строка или число;

  • i – индекс повторения заголовка name, опциональный параметр

client.http_req.header[name]

Таблица (список строк)

Возвращает таблицу строк значений заголовка name

client.http_req.header[name] = value

Таблица (список строк)

Удаляет или перезаписывает все вхождения заголовка name

client.http_req.header = value

Таблица (список строк)

Устанавливает значение для всех заголовков

Дополнительные свойства и методы

http_req.version

Целое

Возвращает версию протокола HTTP: целое число, в котором младший десяток соответствует значению после точки, старший десяток – перед точкой.

Поддерживаются версии: 1.0, 1.1.

Пример: для HTTP/1.0 будет возвращен ответ: 10

http_req.method

Строка

Возвращает метод запроса (GET, POST, HEAD, DELETE, PATCH, PUT, OPTIONS, CONNECT, TRACE и др.). Пример: GET

http_req.path

Строка

Возвращает путь запроса. Пример: termideskconnect

http_req.query

Строка

Возвращает запрос. Пример: test=query

http_req.path_and_query

Строка

Возвращает полный путь запроса. Пример: termideskconnect?test=query

http_req.host

Строка

Возвращает значение заголовка Host. Пример: connect.termidesk.ru

client.http_req.has_body

Логический

Возвращает значение true, если тело запроса было передано в Сценарий балансировки

http_req.body

Строка

Возвращает тело HTTP-запроса. Поле существует, если client.http_req.has_body = true

Таблица 5. Описание полей структуры client.http_resp
Поле Тип поля Описание

client.http_resp.header:count()

Целое

Возвращает количество заголовков

client.http_resp.header:get(i)

Строка

Возвращает пару: ключ и значение

client.http_resp.header:del([i])

Таблица (список строк)

Удаляет значение заголовка, индекс (i) опционален:

  • если индекс не задан, то удалятся все заголовки;

  • если индекс меньше 1, то удалится первый заголовок (равносильно i = 1);

  • если индекс больше, чем client.http_resp.header:count(), то удалится последний заголовок

client.http_resp.header:field_count(name)

Целое

Возвращает количество всех заголовков с именем name

client.http_resp.header:field_get(name [,i])

Строка или nil

Возвращает пару: ключ (имя заголовка с учетом регистра) и значение:

  • если индекс не задан, то i = client.http_resp.header:size_field(name), возвращается последний найденный заголовок с именем name;

  • если индекс меньше 1 или больше client.http_resp.header:field_count(name), то ключ и значение будут nil.

Значения параметров:

  • name – имя заголовка, строка без учета регистра;

  • i – индекс повторения заголовка name

client.http_resp.header:field_set(name, value [,i])

Таблица (список строк)

Устанавливает значение заголовка (key, value) по индексу повторения (i):

  • если value число, то оно конвертируется в строку;

  • если индекс не задан, то удалятся все существующие заголовки, где name = key. Запишется только один заголовок;

  • если индекс меньше 1, то перезапишется первый заголовок (равносильно i = 1);

  • если индекс больше client.http_resp.header:field_count(name), то перезапишется последнее вхождение заголовка;

  • если заданные key и value не найдены, то произойдет новая запись.

Значения параметров:

  • name – имя заголовка, строка без учета регистра;

  • value – значение, строка или число;

  • i – индекс повторения заголовка name, параметр опционален

client.http_resp.header:field_del(name, [i])

Таблица (список строк)

Удаляет заголовок (name) по индексу повторения (i):

  • если индекс не задан, то удалятся все существующие заголовки с именем name;

  • если индекс меньше 1, то удалится первое вхождение заголовока name (равносильно i = 1);

  • если индекс больше, чем client.http_resp.header:field_count(name), то удалится последнее вхождение заголовока name;

  • если name не найден, то действий не произойдет.

Значения параметров:

  • name – имя заголовка, строка без учета регистра;

  • i – индекс повторения заголовка name, опциональный параметр

client.http_resp.header:field_push(name, value [,i])

Строка

Добавляет (продвигает) заголовок (key, value) по индексу повторения (i):

  • если value число, то оно конвертируется в строку;

  • если индекс не задан или больше client.http_resp.header:field_count(name), то заголовок добавится в конец;

  • если индекс меньше 1, то заголовок добавится в начало (равносильно i = 1);

  • если заданные key и value не найдены, то произойдет новая запись.

Значения параметров:

  • name – имя заголовка, строка без учета регистра;

  • value – значение, строка или число;

  • i – индекс повторения заголовка name, опциональный параметр

client.http_resp.header[name]

Таблица (список строк)

Возвращает таблицу строк значений заголовка name

client.http_resp.header[name] = value

Таблица (список строк)

Удаляет или перезаписывает все вхождения заголовка name

client.http_resp.header = value

Таблица (список строк)

Устанавливает значение для всех заголовков

client.http_resp.status

Целое

Возвращает или устанавливает код HTTP-ответа. Пример: 200

client.http_resp.has_body

Логический

Возвращает true, если тело ответа было передано в Сценарий модификации ответов

http_resp.body

Строка

Возвращает тело HTTP ответа. Поле существует, если client.http_resp.has_body = true

Таблица 6. Описание полей структуры client.respond
Поле Тип поля Описание

Работа с заголовками

client.respond.header

Структура

Класс для работы с заголовками ответа. Методы и свойства аналогичны client.http_req.header

client.respond.version

Целое

Возвращает или устанавливает версию протокола HTTP как целое число:

  • 11 – версия HTTP 1.1;

  • 10 – версия HTTP 1.0

client.respond.status

Целое

Возвращает или устанавливает код HTTP-ответа. Пример: 200

client.respond.body

Строка

Возвращает или устанавливает тело HTTP-ответа

Таблица 7. Описание полей структуры client.aaa
Поле Тип поля Описание

client.aaa.profile

Строка

Задает AAA-Профиль.

Название AAA-Профиля выбирается из конфигурации, в случае несовпадения выводится ошибка

client.aaa:user_id()

Строка

Возвращает идентификатор пользователя в формате user@realm.

Для того, чтобы поле было непустое, необходимо установить client.action="auth"

client.aaa:attempts()

Целое

Возвращает количество неудачных попыток аутентификации за указанный в конфигурации период

client.aaa:field_count(name)

Строки

Возвращает, устанавливает или удаляет атрибуты пользователя, которые создаются во время процедуры аутентификации.

Значения параметров:

  • user – имя пользователя;

  • password – пароль, введенный пользователем по запросу;

  • memberOf – атрибут группы пользователя из Active Directory.

Поддерживается добавление индивидуальных атрибутов, которые будут храниться в течение жизни сессии

client.aaa:field_set(name, value [,i])

client.aaa:field_get(name [,i])

client.aaa:field_push(name, value [,i])

client.aaa:field_del(name [,i])

Таблица 8. Описание полей структуры client.proxy_proto и client.proxy_proto.ssl
Поле Тип поля Описание

Структура proxy_proto

proxy_proto.address_family

Перечисление

Содержит тип адреса. Возможные значения:

  • PP_AF.UNPSEC – неопределенное;

  • PP_AF.INET – IPv4-адрес;

  • PP_AF.INET6 – IPv6-адрес;

  • PP_AF.UNIX – Unix-сокет

proxy_proto.command

Перечисление

Возможные значения:

  • PP_CMD.PROXY – если заголовок содержит команду;

  • PROXY PP_CMD.LOCAL – если заголовок содержит команду LOCAL

Для PROXY-протокола версии 1, всегда значение PP_CMD.PROXY.

proxy_proto.dest

Строка

Содержит адрес назначения:

  • если client.proxy_proto.address_family == PP_AF.INET или client.proxy_proto.address_family == PP_AF.INET6, то client.proxy_proto.dest.ip возвращает IP-адрес и client.proxy_proto.dest.port возвращает порт;

  • если client.proxy_proto.address_family == PP_AF.UNIX, то содержит строку c названием Unix-сокета;

  • если client.proxy_proto.address_family == PP_AF.UNSPEC, то содержит nil

proxy_proto.is_local_command

Логический

Значение true, если client.proxy_proto.command == PP_CMD.LOCAL

proxy_proto.is_proxy_command

Логический

Значение true, если client.proxy_proto.command == PP_CMD.PROXY

proxy_proto.is_sock_stream

Логический

Значение true, если client.proxy_proto.transport == PP_TRANSPORT.SOCK_STREAM

proxy_proto.is_sock_dgram

Логический

Значение true, если client.proxy_proto.transport == PP_TRANSPORT.SOCK_DGRAM

proxy_proto.is_sock_unspec

Логический

Значение true, если client.proxy_proto.transport == P_TRANSPORT.UNSPEC

proxy_proto.src

Строка, структура или nil

Содержит адрес источника:

  • если client.proxy_proto.address_family == PP_AF.INET или client.proxy_proto.address_family == PP_AF.INET6, то client.proxy_proto.src.ip возвращает IP-адрес и client.proxy_proto.src.port возвращает порт;

  • если client.proxy_proto.address_family == PP_AF.UNIX, то содержит строку c названием Unix-сокета;

  • если client.proxy_proto.address_family == PP_AF.UNSPEC, то содержит nil

proxy_proto:tlv_get(Type)

Строка

Возвращает TLV типа Type

proxy_proto.transport

Перечисление

Содержит тип транспортного протокола. Возможные значения:

  • PP_TRANSPORT.SOCK_STREAM – TCP-протокол;

  • PP_TRANSPORT.SOCK_DGRAM – UDP-протокол;

  • PP_TRANSPORT.UNSPEC — неопределенное

proxy_proto.version

Целое

Версия PROXY-протокола. Возможные значения:

  • 1 – версия 1;

  • 2 – версия 2

Структура proxy_proto.ssl

proxy_proto.ssl.cert_in_conn

Логический

Указывает на то, что пользователь предоставил сертификат в данном соединении

proxy_proto.ssl.cert_in_session

Логический

Указывает на то, что пользователь предоставил сертификат как минимум один раз в рамках TLS-сессии данного соединения

proxy_proto.ssl.cert_verified

Логический

Указывает на то, что пользователь предъявил сертификат и он был успешно проверен

proxy_proto.ssl.cipher

Строка

Название алгоритма шифрования

proxy_proto.ssl.cn

Строка

Значение поля Common Name сертификата

proxy_proto.ssl.key_algo

Строка

Название алгоритма, используемого для генерации ключа сертификата

proxy_proto.ssl.sig_algo

Строка

Название алгоритма, используемого для подписи сертификата

proxy_proto.ssl.tls

Логический

Указывает на то, что используется TLS-соединение

proxy_proto.ssl.version

Строка

Версия TLS

Таблица 9. Описание полей структуры client.sso
Поле Тип поля Описание

client.sso.profile

Строка

Задает SSO-Профиль

client.sso.user

Строка

Устанавливает имя пользователя, если требуется

client.sso.password

Строка

Устанавливает пароль пользователя, если требуется

client.sso:field_set

Структура

Устанавливает параметры SSO-Профиля. Примеры:

client.sso.profile = "ss-krb-del" client.sso:field_set("user", client.aaa:field_get("user")) client.sso:field_set("service", "HTTP/krb.test.loc")

Таблица 10. Описание полей структуры client.tls
Поле Тип поля Описание

client.tls:certificate()

Строка

Возвращает строку сертификата, закодированная в формате Base64. Поддерживается только для mTLS

client.tls:version()

Строка

Возвращает версию протокола TLS из сертификата. Поддерживается только для mTLS

client.tls:serial_number()

Строка

Возвращает серийный номер сертификата. Поддерживается только для mTLS

client.tls:subject_get("name")

Таблица (список строк)

Возвращает поля субъекта сертификата. Поддерживается только для mTLS.

Значения параметра name:

  • client.tls:subject_get("commonName");

  • client.tls:subject_get("countryName");

  • client.tls:subject_get("stateOrProvinceName");

  • client.tls:subject_get("organizationName")

client.tls:issuer_get("name)

Таблица (список строк)

Возвращает поля издателя сертификата. Поддерживается только для mTLS.

Значения параметра name:

  • client.tls:issuer_get("organizationName");

  • client.tls:issuer_get("stateOrProvinceName");

  • client.tls:issuer_get("countryName")

client.tls.sni

Строка

Возвращает значение поля sni из подключения пользователя к Виртуальному Северу в сценарии, когда сесси терминируется на Termidesk Connect

client.tls.alpn

Строка

Возвращает значение поля ALPN в сценарии, когда сессия терминируется на Termidesk Connect

client.tls.cipher

Строка

Возвращает cipher-suite, выбранный при установке SSL-сессии с пользователем

Использование в Сценариях ошибок

Обработка правил Сценария ошибок осуществляется через глобальные переменные:

  • storage – аналогично Сценариям балансировки содержит методы для работы с путями к каталогам, которые будут доступны при вызове из lua-скрипта;

  • client – аналогично Сценариям балансировки содержит методы для работы с клиентом и запросом. Доступны все поля, кроме: client.bs, client.action, client.aaa, client.sso.

Описание используемых полей приведено в таблице (см. таблицу Описание полей для Сценариев ошибок).

Таблица 11. Описание полей для Сценариев ошибок
Поле Тип поля Описание

context.script_errors

Структура

Возвращает информацию об ошибке в lua-скрипте:

  • error_message — сообщение об ошибке;

  • filename — название файла, в котором произошла ошибка

context.error

Целое

Код ошибки

`context.bs `

Строка

Возвращает Сервер Балансировки

context.rs.ip

Строка

Возвращает IP-адрес Реального Сервера

context.rs.port

Целое

Возвращает порт Реального Сервера

context.bad_header

Строка

Заголовок, на котором был превышен лимит

error_to_string(context.error)

Строка

Возвращает код ошибки в виде строки

`status_to_string(status_code) `

Строка

Возвращает код HTTP-статуса в виде строки

Поддерживаемые коды ошибок перечислены в таблице (см. таблицу Описание кодов для Сценариев ошибок).

Таблица 12. Описание кодов для Сценариев ошибок
Поле Описание

Error.REQUEST_HEADER_LENGTH_LIMIT

Превышено ограничение на размер одного заголовка

Error.REQUEST_HEADERS_SIZE_LIMIT

Превышено ограничение на общий размер заголовков

Error.REQUEST_HEADER_COUNT_LIMIT

Превышено ограничение на количество заголовков

Error.REQUEST_BAD_CONTENT_LENGTH

Неправильное значение заголовка Content-Length

Error.REQUEST_MULTIPLE_CONTENT_LENGTH

Несколько заголовков Content-Length в одном запросе

Error.REQUEST_BAD_VERSION

Неправильная или неподдерживаемая версия HTTP

Error.REQUEST_MULTIPLE_UPGRADE

Несколько заголовков Upgrade или значений

Error.REQUEST_UPGRADE_NOT_ALLOWED

Upgrade запрещен настройками (поле upgrade_types в HTTP-Профиле)

Error.REQUEST_CONNECT_NOT_ALLOWED

Метод CONNECT запрещен настройками (поле allow-connect в HTTP-Профиле)

Error.BAD_REQUEST

Другие ошибки разбора HTTP-запроса

Error.SCRIPT_ERROR

Ошибка выполнения Сценария балансировки (lua-скрипта)

Error.BS_NOT_FOUND

Сервер Балансировки, который вернул Сценарий (lua-скрипт), не существует

Error.AUTHENTICATION_FAILED

Ошибка аутентификации пользователя

Error.BS_OFFLINE

Сервер Балансировки, который вернул Сценарий (lua-скрипт), находится в состоянии OFFLINE

Error.ERROR_CONNECTING_TO_RS

Ошибка подключения к Реальному Серверу

Error.ERROR_WRITING_REQUEST_TO_RS

Ошибка при передаче запроса Реальному Серверу

Error.ERROR_READING_RESPONSE_FROM_RS

Ошибка при чтении ответа от Реального Сервера

Error.RESPONSE_HEADER_LENGTH_LIMIT

Превышено ограничение на размер одного заголовка

Error.RESPONSE_HEADERS_SIZE_LIMIT

Превышено ограничение на общий размер заголовков

Error.RESPONSE_HEADER_COUNT_LIMIT

Превышено ограничение на количество заголовков

Error.RESPONSE_BAD_CONTENT_LENGTH

Неправильное значение заголовка Content-Length

Error.RESPONSE_MULTIPLE_CONTENT_LENGTH

Несколько заголовков Content-Length в одном запросе

Error.BAD_RESPONSE

Другие ошибки разбора HTTP-ответа

Использование в Сценариях SSL

Обработка правил в Сценариях SSL осуществляется через глобальную переменную:

  • handshake – содержит методы для работы с SSL-Политиками. Доступно только для Сценариев SSL.

Описание полей приведено в таблице ниже.

Таблица 13. Описание полей переменной handshake
Поле Тип поля Описание

handshake.sni

Строка

Возвращает имя сервера, к которому подключается клиент.

Поле доступно только на чтение, может быть пустым

handshake.alpn

Таблица (список строк)

Возвращает список протоколов в порядке очередности, которые могут быть выбраны сервером.

Поле доступно только на чтение

handshake.ciphers

Таблица (список строк)

Возвращает список алгоритмов шифрования, поддерживаемых клиентом.

Поле доступно только на чтение

handshake.ssl-profile

Строка

Возвращает идентификатор Серверного SSL-Профиля, используемого для установки соединения.

По умолчанию поле пустое. lua-скрипт может установить любой валидный идентификатор, сконфигурированный в системе.

Если значение остается пустым, то используется Серверный SSL-Профиль по-умолчанию из конфигурации Серевера Балансировки

handshake.action

Строка

Определяет действие, которое необходимо выполнить:

  • handshake — произвести рукопожатие и продолжить;

  • drop — сбросить соединение

Добавление Сценария

Добавление Сценария выполняется одним из способов:

  • из интерфейса командной строки Termidesk Connect;

  • из веб-интерфейса Termidesk Connect (см. подраздел Веб. Сценарии).

Пример команды с указанием порядка исполнения и имени файла Сценария:

set vs HTTP <имя> luarules 5 script test.lua

Файлы должны располагаться:

  • Сценарии балансировки в каталоге /var/lib/tdc/lbscripts/content-switching/;

  • Сценарии модификации ответов в каталоге /var/lib/tdc/lbscripts/response-modifying/;

  • Сценарии ошибок в каталоге /var/lib/tdc/lbscripts/error-reply/;

  • Сценарии SSL в каталоге /var/lib/tdc/lbscripts/ssl.

Порядковый номер определяет очередность выполнения файла Сценария: например, Сценарий с порядковым номером 10 будет исполнен раньше, чем Сценарий с порядковым номером 15.

При этом правила в файлах Сценариев также обрабатываются по порядку:

  • сначала правила из файла Сценария с наименьшим порядковым номером;

  • затем правила из файла Сценария со следующим порядковым номером, если не было совпадений.

Правила Сценария могут располагаться как в одном файле, так и в нескольких.

Примеры Сценариев для изменения содержимого запросов

Пример 1. Если имя хоста содержит текст «abc» и запрос пришел из сети 192.0.2.0/24, то добавить заголовок «XFF: <IP-адрес_пользователя_при_подключении>», и перенаправить запрос на Сервер Балансировки «lb1».

Код:

if (client.http_req.host:find("abc") and client.remote_p:is_network("192.0.2.0/24")) then
        client.http_req.header:field_set("XFF", client.remote_p.ip)
        client.bs = "lb1"
        client.action = "bs"
end

Результат:

WEB -- 03<p>Method GET</p><p>URL on server: /</p><p>REQ
Headers: </p>Host: abc.domain.ru
User-Agent: curl/7.81.0
Accept: */*
XFF: 192.0.2.5

Пример 2. Если имя хоста начинается с «abc», то добавить заголовок «XFF: <IP-адрес_пользователя_при_подключении>» и «Remote-port: <порт-источник_на_клиенте>», и перенаправить запрос на Сервер Балансировки «lb1».

Код:

function startswith(text, prefix)
  return text:find(prefix, 1, true) == 1
end

if startswith(client.http_req.host, "abc") then
  client.http_req.header:field_set("Remote-port", client.remote_p.port)
  client.http_req.header:field_set("XFF", client.remote_p.ip)
  client.bs = "lb1"
  client.action = "bs"
end

Пример 3. Если путь запроса содержит «app», то при наличии заголовка X-Forwarded-For добавить IP-адрес клиента в конец запроса. Если заголовка не было в запросе, то добавить новый. Перенаправить запрос на Сервер Балансировки «lb1».

Код:

if client.http_req.path:find("abc") then
        if client.http_req.header:field_count("X-Forwarded-For") > 0 then
                xff, xffip = client.http_req.header:field_get("X-Forwarded-For")
                client.http_req.header:field_set("X-Forwarded-For", xffip ..", "..client.remote_p.ip)
        else
                client.http_req.header:field_set("X-Forwarded-For", client.remote_p.ip)
        end
client.bs = "lb1"
client.action = "bs"

end

Пример 4. Подменить домен «ru» на домен «local» (например, если запрос идет к app.domain.ru, то в сторону Реального Сервера должен прийти app.domain.local). В начале пути запроса добавить «/external» и перенаправить запрос на Сервер Балансировки «lb1».

Код:

client.http_req.host =  client.http_req.host:match("(.*).ru") .. ".local"
client.http_req.path = "/external" .. client.http_req.path
client.bs = "lb1"
client.action = "bs"

Примеры Сценариев для ответа на запрос

Пример 1. Если метод не GET или не HEAD, то сбросить соединение.

Код:

if (client.http_req.method ~= "GET" and client.http_req.method ~= "HEAD") then
    client.action = "drop"
end

Пример 2. Перенаправить соединение с HTTP на HTTPS.

Код:

client.respond.status = 302
client.respond.header["Location"] = "https://" .. client.http_req.host .. client.http_req.path
client.respond.header["Connection"] = "close"
client.action = "respond"

Пример 3. Если запрос из сети 192.0.2.0/24, то ответить HTML-страницей и параметрами запроса.

Код:

if client.remote_p:is_network("192.0.2.0/24") then
    client.respond.header["Connection"] = "close"
    client.respond.header["Content-type"] = 'text/html
    client.respond.body = [[<html>
    <body>
    <meta charset="UTF-8">
    <h1>Lets goodbye!</h1>
    <p>Доступ запрещен</p>
    </body>
    </html>]] .. "IP: " .. client.remote_p.ip .. "\n TRY: " .. client.http_req.host .. client.http_req.path .. "\n" ..      " Vserver: " .. client.local_p.ip .. ":" .. client.local_p.port
client.action = 'respond'

Примеры Сценариев для выбора Сервера Балансировки

Пример 1. Передача любого запроса на Сервер Балансировки «lb1».

Код:

client.bs = "lb1"
client.action = "bs"

Пример 2. Если имя хоста в запросе точно соответствует «abc.domain.ru», то направить запрос на Сервер Балансировки «lb1». В противном случае вернуть код ответа 403 (по умолчанию вернется ошибка 503).

Код:

if client.http_req.host == "abc.domain.ru" then
        client.bs = "lb1"
        client.action = "bs"
else
        client.respond.status = 403
        client.action = "respond"
end

Пример 3. Если имя хоста содержит текст «abc» и запрос пришел из сети 192.0.2.0/24, то вернуть Сервер Балансировки «lb1». В противном случае вернуть код ответа 403 (по умолчанию вернется ошибка 503).

Код:

if (client.http_req.host:find("abc") and client.remote_p:is_network("192.0.2.0/24"))
then
        client.bs = "lb1"
        client.action = "bs"
else
        client.respond.status = 403
        client.action = "respond"
end

Пример 4. Если путь содержит:

  • «red», то вернуть Сервер Балансировки «lb1»;

  • «green», то вернуть Сервер Балансировки «lb2».

Если не сработало ни одно из условий выше, то вернуть Сервер Балансировки «lb-default».

Код:

if client.http_req.path:find("red") then
        client.bs = "lb1"
        client.action = "bs"
elseif client.http_req.path:find("green") then
        client.bs = "lb2"
        client.action = "bs"
else
        client.bs = "lb-default"
        client.action = "bs"
end