Обработка соединений на Lua

В этом разделе:

Общие сведения.

Требования к скрипту для обработки соединений.

Примеры.

Используемые таблицы.

Доступные вспомогательные модули.

Общие сведения

Компонент Dr.Web Firewall для Linux поддерживает взаимодействие с интерпретатором программ на языке Lua (используется версия 5.3.4; поставляется совместно с Dr.Web для почтовых серверов UNIX). Скрипты на Lua могут быть использованы компонентом для предварительной проверки соединения перед тем, как направить его на анализ компоненту SpIDer Gate.

Соединение будет проанализировано с помощью скрипта, если в настройках компонента Dr.Web Firewall для Linux (в параметре InterceptHook) задан путь к этому скрипту. В противном случае обработка соединения производится с использованием настроек по умолчанию и правил обработки, заданных в настройках компонента (параметры RuleSet*).

Дополнительные примеры скриптов для обработки соединений доступны по ссылке:
https://github.com/DoctorWebLtd/drweb-lua-examples/tree/master/firewall.

Требования к скрипту для обработки соединений

Скрипт должен содержать глобальную функцию, являющуюся точкой входа в модуль проверки соединения (эту функцию Dr.Web Firewall для Linux будет вызывать для обработки поступающих соединений). Функция обработки должна соответствовать следующим соглашениям о вызове:

имя функции — intercept_hook;

единственный аргумент — таблица Lua InterceptContext (предоставляет из функции доступ к информации об обрабатываемом соединении; см. описание таблицы ниже);

единственное возвращаемое значение — строковое значение из таблицы ниже:

Значение

Описание вердикта

pass

Пропустить соединение без проверки компонентом SpIDer Gate

check

Проверить соединение с помощью компонента SpIDer Gate

reject

Отказать в соединении (клиент, инициировавший соединение, получит TCP-пакет с флагом RST)

drop

Разорвать соединение (клиент, инициировавший соединение, ничего не получит)

Примеры
 

1.Простой скрипт передает в Dr.Web Firewall для Linux вердикт pass, тем самым указывая, что соединения не нужно проверять:

-- Функция проверки соединения, написанная пользователем
function intercept_hook(ctx)
  return "pass" -- не проверять соединение
end

2.Скрипт указывает Dr.Web Firewall для Linux направить на проверку все устанавливаемые соединения, кроме:

исходящих локальных соединений от приложений, исполняемых с правами пользователя из группы drweb;

соединений с привилегированных портов (независимо от владельца и направления соединения);

исходящих соединений с IP-адресов из локальной подсети.

function intercept_hook(ctx)
  -- Не проверять соединения, инициированные с локального
  -- узла (divert == "output") приложением от имени группы
  -- "drweb" (group == "drweb")
  if ctx.divert == "output" and ctx.group == "drweb" then
    return "pass"
  end

  -- Не проверять соединения, инициированные с
  -- привилегированных портов (от 0 до 1024)
  if ctx.src.port >= 0 and ctx.src.port <= 1024 then
    return "pass"
  end

  -- Не проверять соединения с адресов из локальной подсети
  -- (диапазона IP-адресов 127.0.0.1/8)
  if ctx.src.ip.belongs("127.0.0.0/8") then
    return "pass"
  end

  -- По умолчанию соединение проверяется
  return "check"
end

Используемые таблицы

1. Таблица InterceptContext

Таблица используется для передачи в функцию intercept_hook данных об обрабатываемом соединении, на основании которых будет выполнено одно из следующих действий:

пропуск соединения;

разрыв соединения,

передача соединения на проверку в SpIDer Gate.

Компонент Dr.Web Firewall для Linux заполняет эту таблицу данными. Часть данных в этой таблице известна уже к моменту вызова функции intercept_hook, а другая часть (т. н. «ленивые» данные) будет вычислена непосредственно в момент запроса значения соответствующего поля из этой таблицы.

Поле

Описание

Тип данных

src

Адрес и порт клиента, инициировавшего соединение

Пример:

if ctx.src.port >= 0 and ctx.src.port <= 1024 then
  return "pass"
end

Таблица TcpEndpoint

dst

Адрес и порт сервера, соединение к которому запросил клиент

Пример:

if ctx.dst.ip.belongs("10.20.30.41/8") then
  return "reject"
end

Таблица TcpEndpoint

divert

Тип перехваченного соединения:

"output" — исходящее соединение;

"input" — входящее соединение;

"forward" — транзитное соединение.

Пример:

if ctx.divert == "forward" then
  return "check"
end

Строка

iface_in

Имя интерфейса, с которого инициировано соединение.

Если имя интерфейса не удалось определить, имеет значение nil.

Строка

iface_out

Имя интерфейса, на который были направлены пакеты после инициации соединения

Если имя интерфейса не удалось определить, имеет значение nil.

Строка

uid

Идентификатор пользователя, от имени которого инициировано исходящее соединение.

Если тип соединения (divert) не "output", либо UID не удалось определить, имеет значение nil.

Число

gid

Идентификатор группы, от имени которой инициировано исходящее соединение

Если тип соединения (divert) не "output", либо GID не удалось определить, имеет значение nil.

Число

user

Пользователь, от имени которого инициировано исходящее соединение.

Если тип соединения (divert) не "output", либо имя пользователя не удалось определить, имеет значение nil.

Строка

group

Группа, от имени которой инициировано исходящее соединение.

Если тип соединения (divert) не "output", либо имя группы не удалось определить, имеет значение nil.

Строка

pid

Идентификатор процесса (PID), от имени которого инициировано исходящее соединение.

Если тип соединения (divert) не "output", либо PID не удалось определить, имеет значение nil.

Число

exe_path

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

Если поле divert (см, выше) имеет значение input или forward, а также если путь к исполняемому файлу по тем или иным причинам не удалось определить, имеет значение nil.

Строка

Переопределенные метаметоды: Нет

2. Таблица TcpEndpoint

Таблица описывает адрес точки соединения (клиента или сервер).

Поле

Описание

Тип данных

ip

IP-адрес

таблица IpAddress

port

Номер порта

Число

Переопределенные метаметоды:

__tostring — функция, преобразующая TcpEndpoint в строку, например: "127.0.0.1:443" (IPv4) или "[::1]:80" (IPv6);

__concat — функция, присоединяющая TcpEndpoint к строке

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

Для взаимодействия с Dr.Web для почтовых серверов UNIX в пространство Lua-программы могут быть импортированы следующие специфические модули, перечисленные в таблице.

Имя модуля

Назначение

Модуль предоставляет функции для записи сообщений из Lua-программы в журнал компонента Dr.Web для почтовых серверов UNIX, запустившего программу на Lua, а также средства асинхронного запуска Lua-процедур

Модуль, предоставляющий инструменты для запроса данных из внешних источников путем обращения к модулю Dr.Web LookupD

Содержимое модуля drweb

1.Функции

Модуль предоставляет набор функций.

Для записи сообщений из программы Lua в журнал компонента Dr.Web для почтовых серверов UNIX:

log(<уровень>, <сообщение>) записывает строку <сообщение> в журнал Dr.Web для почтовых серверов UNIX на уровне <уровень> (требуемый уровень задается строкой: «debug», «info», «notice», «warning», «error»);

debug(<сообщение>) записывает строку <сообщение> в журнал Dr.Web для почтовых серверов UNIX на уровне DEBUG;

info(<сообщение>) записывает строку <сообщение> в журнал Dr.Web для почтовых серверов UNIX на уровне INFO;

notice(<сообщение>) записывает строку <сообщение> в журнал Dr.Web для почтовых серверов UNIX на уровне NOTICE;

warning(<сообщение>) записывает строку <сообщение> в журнал Dr.Web для почтовых серверов UNIX на уровне WARNING;

error(<сообщение>) записывает строку <сообщение> в журнал Dr.Web для почтовых серверов UNIX на уровне ERROR.

Для управления синхронизацией Lua-процедур:

sleep(<с>) приостанавливает выполнение экземпляра процедуры Lua на указанное число секунд;

async(<функция Lua>[, <список аргументов>]) асинхронно запускает указанную функцию с передачей ей заданного списка аргументов. Вызов функции async завершается немедленно, возвращаемое значение (таблица Future) позволяет получить результат выполнения функции <функция Lua>.

Для представления информации об IP-адресе в виде таблицы IpAddress:

ip(<адрес>) представляет IP-адрес, переданный в виде строки <адрес>, экземпляром таблицы IpAddress. Допускается использовать как IPv4-, так и IPv6.

Для загрузки внешних данных из текстового файла:

load_set(<путь к файлу>) формирует из содержимого указанного текстового файла таблицу со значениями true; в качестве ключей используются строки, прочитанные из файла. Пустые строки и строки, состоящие только из пробельных символов будут проигнорированы;

load_array(<путь к файлу>) формирует из содержимого указанного текстового файла массив строк. Пустые строки и строки, состоящие только из пробельных символов будут проигнорированы.

2.Таблицы

Таблица Future описывает отложенный результат выполнения функции при помощи функции async.

Поле

Описание

Тип данных

wait

Функция, возвращающая результат функции, запущенной при помощи функции async. Если функция еще не завершила свое выполнение, ожидает завершения и возвращает результат. Если функция завершилась до момента вызова wait, результат возвращается немедленно. Если запущенная функция завершилась с ошибкой, вызов wait генерирует ту же ошибку.

Функция

Переопределенные метаметоды: Нет

Таблица IpAddress описывает IP-адрес.

Поле

Описание

Тип данных

belongs

Функция для проверки IP-адреса из таблицы IpAddress на принадлежность указанным подсетям (диапазонам IP-адресов).

Принимает единственный аргумент — массив строк вида "<IP-адрес>" или "<IP-адрес>/<маска>", где <IP-адрес> — адрес узла либо сети (например, "127.0.0.1"), а <маска> — маска подсети, которая указывается в виде IP-адреса (например, "255.0.0.0"), либо в виде числа (например, "8").

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

true — если адрес совпадает хотя бы с одним из указанных IP-адресов либо принадлежит хотя бы одной из указанных подсетей (диапазону IP-адресов);

false — если адрес не совпадает ни с одним из указанных или не принадлежит ни одной из указанных подсетей

Функция

Переопределенные метаметоды:

__tostring — функция, преобразующая IpAddress в строку, например: "127.0.0.1" (IPv4) или "::1" (IPv6);

__concat — функция, присоединяющая IpAddress к строке;

__eq — функция для проверки равенства двух IpAddress;

__band — функция, позволяющая накладывать маску, например: dw.ip('192.168.1.2') & dw.ip('255.255.254.0')

3.Примеры

Вывод в журнал сообщений, сформированных процедурой, запускающейся асинхронно:

local dw = require "drweb"

-- Функция, возвращающая полученную в качестве аргумента строку
-- по истечении двух секунд ожидания
function out_msg(message)
 dw.sleep(2)
 return message
end

-- "Главная" функция
function intercept(ctx)
 -- Вывод строки на уровне NOTICE в журнал Dr.Web для почтовых серверов UNIX
 dw.notice("Intercept function started.")

 -- Асинхронный запуск двух экземпляров функции out_msg
 local f1 = dw.async(out_msg, "Hello,")
 local f2 = dw.async(out_msg, " world!")

 -- Ожидание завершения исполнения экземпляров функции
 -- out_msg и вывод их результатов в журнал
 -- Dr.Web для почтовых серверов UNIX на уровне DEBUG
 dw.log("debug", f1.wait() .. f2.wait())
end

Создание регулярной процедуы:

local dw = require "drweb"

-- Сохранить таблицу Future в глобальную переменную futurе, чтобы
-- предотвратить ее удаление сборщиком мусора
future = dw.async(function()
   while true do
     -- Каждый день выводит в журнал указанное сообщение
     dw.sleep(60 * 60 * 24)
     dw.notice("A brand new day began")
   end
end)

Преобразование IP-адреса из строки:

local dw = require "drweb"

local ipv4 = dw.ip("127.0.0.1")
local ipv6 = dw.ip("::1")
local mapped = dw.ip("::ffff:127.0.0.1")

 

Содержимое модуля drweb.lookup

1.Функции

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

lookup(<запрос>, <параметры>) запрашивает данные во внешнем хранилище, доступном через модуль Dr.Web LookupD. Аргумент <запрос> должен соответствовать секции запроса в настройках Dr.Web LookupD (строка <тип>@<тег>). Необязательный аргумент <параметры> описывает подстановки, которые будут использованы при формировании запроса. Могут быть использованы следующие автоматически разрешаемые маркеры:

$u, $U — заменяется на user — имя пользователя, переданное клиентским компонентом;

$d, $D — заменяется на domain — имя домена, переданное клиентским компонентом.

Аргументы задаются в виде таблицы, ключи и значения которой должны быть строками. Функция возвращает массив строк, являющихся результатами запроса;

check(<проверяемая строка>, <запрос>, <параметры>) возвращает true, если <проверяемая строка> найдена во внешнем хранилище, доступном через модуль Dr.Web LookupD. Аргументы <запрос> и <параметры> полностью аналогичны аргументам функции lookup (см. выше). Аргумент <проверяемая строка> должен быть строкой или таблицей, имеющей метаметод __tostring (т. е. приводимой к строке).

2.Примеры

Вывод в журнал списка пользователей, извлеченного из источника данных LookupD.LDAP.users:

local dw = require "drweb"
local dwl = require "drweb.lookup"

-- "Главная" функция
function intercept(ctx)
 -- Запись строки на уровне NOTICE в журнал Dr.Web для почтовых серверов UNIX
 dw.notice("Intercept function started.")

 -- Вывод в журнал Dr.Web для почтовых серверов UNIX результатов запроса
 -- к источнику данных 'ldap@users'
 for _, s in ipairs(dwl.lookup("ldap@users", {user="username"})) do
   dw.notice("Result for request to 'ldap@users': " .. s)
 end

end