Реализована система вложенной оркестрации.
Для этого первый оркестратор выполняет execution_plan/execution_plan_cancel
и запоминает таблицу plan в desync.
Если последующий оркестратор видит desync.plan, он берет его оттуда. Он и не сможет выполнить cancel, потому что ему передается ctx=nil. Инстансы имеют ctx только до тех пор, пока их вызывает C код. ctx - это связь с C кодом. После cancel она обрывается, nfqws2 забывает о последующих инстансах, и lua код должен уметь работать в таких условиях.
Для этого в zapret-lib предусматриваются различные прокладки (shims), которые прозрачно заменяют механизмы C кода на дублирующие механизмы lua.
desync.plan сохраняется на протяжении всей обработки плана оркестраторами.
Чтобы выполнить какой-то инстанс, оркестратор берет первый элемент из desync.plan и удаляет его оттуда. Затем выполняет. Взятие с удалением делается через хелпер plan_instance_pop.
Оркестратор может по своему усмотрению удалить план, что сразу же скажется на действиях вышестоящего оркестратора - он потеряет план и перестанет дальше вызывать функции.
Оркестратор condition. Выполняет replay_execution_plan, если функция “iff”, имя которой передается в аргументе, возвращает значение true (или false, если задан аргумент ‘neg’). В противном случае очищает execution plan.
Может быть полезен для протокольных детекторов lua. “iff” функция может детектить какой-то протокол, детект которого не зашит в nfqws2.
тест-пример
nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua
--lua-desync=condition:iff=cond_random
--lua-desync=argdebug:testarg=1
--lua-desync=argdebug:testarg=2:morearg=blablabla
Оркестратор stopif. Очищает execution plan, если функция “iff”, имя которой передается в аргументе, возвращает значение true (или false, если задан аргумент ‘neg’).
Чем это отличается от condition ? Оркестраторы ничего не знают друг о друге. Если, допустим, у вас circular , и в какой-то стратегии вы захотите поставить условие на эту стратегию, то condition вопрос не решит. Он либо прекратит выполнение, либо выполнит все оставшиеся функции от всех стратегий, потому что ничего не знает о параметре “strategy” оркестратора circular. Но stopif вопрос решает. Если выполняется условие, сносится plan, circular прекращает выполнение инстансов. А если не выполняется, то circular продолжает выполнять plan дальше, как будто бы stopif не существовало. Надо только самому stopif поставить strategy=N, чтобы circular его считал частью стратегии.
nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua
--in-range=-s1
--lua-desync=circular
--in-range=x
--lua-desync=stopif:iff=cond_random:strategy=1 --lua-desync=argdebug:strategy=1
--lua-desync=argdebug:strategy=2
Цель создания подобных кирпичиков - универсализировать создание кастомных стратегий и избавить от необходимости переписывания/дублирования не относящегося к стратегиии кода.
Чтобы добавить фильтр протокола “openvpn” без доделывания nfqws2, вам нужно лишь написать протокольный детектор и применить condition/stopif в зависимости от ситуации
Пример протокольного детектора. Ищет подстроку в пейлоаде, заданную в аругменте “pattern”.
function cond_payload_str(desync)
if not desync.arg.pattern then
error("cond_payload_str: missing 'pattern'")
end
return string.find(desync.dis.payload,desync.arg.pattern,1,true)
end
nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua
--lua-desync=condition:iff=cond_payload_str:pattern=1234
--lua-desync=argdebug:testarg=1
echo aaz1234zzz | ncat -4u 1.1.1.1 443
echo aaze124zzz | ncat -4u 1.1.1.1 443
Конечно, можно пойти и иным путем. Можно вызвать подобную функцию в формате --lua-desync.
Она перепишет desync.l7payload и desync.l7proto, чтобы дальнейшие инстансы могли проверять новый тип пейлоада и протокола сеанса. В стандартных antidpi функциях есть аргументы “standard payload”. Они как раз и работают с desync.l7payload. (правда, о новом типе пейлоада C код не узнает, --payload не станет его принимать, но на уровне lua функций фильтр будет работать)
Но кто сказал, что здесь может быть только протокольный детектор ? Здесь может быть что угодно. Любое вообразимое условие, которое можно запрограммировать в lua коде.
Например, вам надо поймать SYN,ACK в ответ на SYN. Можно через range, а можно написать iif функцию