Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-20 00:05:48 +00:00

nfqws2: post payload filter and range in exec plan, zapret-lib: duplicate range check logic

This commit is contained in:
bol-van
2025-12-02 20:47:52 +03:00
parent 04ceb589e0
commit 6010307667
7 changed files with 146 additions and 15 deletions

View File

@@ -54,13 +54,73 @@ function desync_orchestrator_example(ctx, desync)
local desync_copy = deepcopy(desync)
execution_plan_cancel(ctx)
for i=1,#plan do
apply_execution_plan(desync_copy, plan[i])
DLOG("orchestrator: executing '"..desync_copy.func_instance.."'")
_G[plan[i].func](ctx, desync_copy)
if not payload_match_filter(desync.l7payload, plan[i].payload_filter) then
DLOG("orchestrator: not calling '"..desync_copy.func_instance.."' because payload '"..desync.l7payload.."' does not match filter '"..plan[i].payload_filter.."'")
elseif not pos_check_range(desync, plan[i].range) then
DLOG("orchestrator: not calling '"..desync_copy.func_instance.."' because pos "..pos_str(desync,plan[i].range.from).." "..pos_str(desync,plan[i].range.to).." is out of range '"..pos_range_str(plan[i].range).."'")
else
apply_execution_plan(desync_copy, plan[i])
DLOG("orchestrator: executing '"..desync_copy.func_instance.."'")
_G[plan[i].func](ctx, desync_copy)
end
end
end
end
-- these function duplicate range check logic from C code
-- mode must be n,d,b,s,x,a
-- pos is {mode,pos}
-- range is {from={mode,pos}, to={mode,pos}, upper_cutoff}
-- upper_cutoff = true means non-inclusive upper boundary
function pos_get(desync, mode)
if desync.track then
if mode=='n' then
return desync.outgoing and desync.track.pcounter_orig or desync.track.pcounter_reply
elseif mode=='d' then
return desync.outgoing and desync.track.pdcounter_orig or desync.track.pdcounter_reply
elseif mode=='b' then
return desync.outgoing and desync.track.pbcounter_orig or desync.track.pbcounter_reply
elseif mode=='s' and desync.track.tcp then
return desync.outgoing and (desync.track.tcp.seq - desync.track.tcp.seq0) or (desync.track.tcp.ack - desync.track.tcp.ack0)
end
end
return 0
end
function pos_check_from(desync, range)
if range.from.mode == 'x' then return false end
if range.from.mode ~= 'a' then
if desync.track then
return pos_get(desync, range.from.mode) >= range.from.pos
else
return false
end
end
return true;
end
function pos_check_to(desync, range)
local ps
if range.to.mode == 'x' then return false end
if range.to.mode ~= 'a' then
if desync.track then
ps = pos_get(desync, range.to.mode)
return (ps < range.to.pos) or not range.upper_cutoff and (ps == range.to.pos)
else
return false
end
end
return true;
end
function pos_check_range(desync, range)
return pos_check_from(desync,range) and pos_check_to(desync,range)
end
function pos_range_str(range)
return range.from.mode..range.from.pos..(range.upper_cutoff and '<' or '-')..range.to.mode..range.to.pos
end
function pos_str(desync, pos)
return pos.mode..pos_get(desync, pos.mode)
end
-- prepare standard rawsend options from desync
-- repeats - how many time send the packet
-- ifout - override outbound interface (if --bind_fix4, --bind-fix6 enabled)
@@ -825,17 +885,21 @@ function direction_cutoff_opposite(ctx, desync, def)
instance_cutoff(ctx, true)
end
end
-- return true if l7payload matches filter l7payload_filter - comma separated list of payload types
function payload_match_filter(l7payload, l7payload_filter, def)
local argpl = l7payload_filter or def or "known"
local neg = string.sub(argpl,1,1)=="~"
local pl = neg and string.sub(argpl,2) or argpl
return neg ~= (in_list(pl, "all") or in_list(pl, l7payload) or in_list(pl, "known") and l7payload~="unknown" and l7payload~="empty")
end
-- check if desync payload type comply with payload type list in arg.payload
-- if arg.payload is not present - check for known payload - not empty and not unknown (nfqws1 behavior without "--desync-any-protocol" option)
-- if arg.payload is prefixed with '~' - it means negation
function payload_check(desync, def)
local b
local argpl = desync.arg.payload or def or "known"
local neg = string.sub(argpl,1,1)=="~"
local pl = neg and string.sub(argpl,2) or argpl
b = neg ~= (in_list(pl, "all") or in_list(pl, desync.l7payload) or in_list(pl, "known") and desync.l7payload~="unknown" and desync.l7payload~="empty")
if not b then
local b = payload_match_filter(desync.l7payload, desync.arg.payload, def)
if not b and b_debug then
local argpl = desync.arg.payload or def or "known"
DLOG("payload_check: payload '"..desync.l7payload.."' does not pass '"..argpl.."' filter")
end
return b

View File

@@ -655,7 +655,7 @@ static uint8_t desync(
struct func_list *func;
int ref_arg = LUA_NOREF, status;
bool b, b_cutoff_all, b_unwanted_payload;
t_lua_desync_context ctx = { .dp = dp, .ctrack = ctrack, .dis = dis, .cancel = false };
t_lua_desync_context ctx = { .dp = dp, .ctrack = ctrack, .dis = dis, .cancel = false, .incoming = bIncoming };
const char *sDirection = bIncoming ? "in" : "out";
struct packet_range *range;
size_t l;

View File

@@ -761,19 +761,27 @@ static int luacall_execution_plan(lua_State *L)
lua_newtable(L);
struct func_list *func;
char instance[256];
char instance[256], pls[2048];
struct packet_range *range;
unsigned int n=1;
LIST_FOREACH(func, &ctx->dp->lua_desync, next)
{
if (n > ctx->func_n)
{
desync_instance(func->func, ctx->dp->n, n, instance, sizeof(instance));
range = ctx->incoming ? &func->range_in : &func->range_out;
lua_pushinteger(params.L, n - ctx->func_n);
lua_createtable(params.L, 0, 4);
lua_createtable(params.L, 0, 6);
lua_pushf_args(&func->args, -1);
lua_pushf_str("func", func->func);
lua_pushf_int("func_n", ctx->func_n);
lua_pushf_str("func_instance", instance);
lua_pushf_args(&func->args, -1);
lua_pushf_range("range", range);
if (l7_payload_str_list(func->payload_type, pls, sizeof(pls)))
lua_pushf_str("payload_filter", pls);
else
lua_pushf_nil("payload_filter");
lua_rawset(params.L,-3);
}
n++;
@@ -1253,7 +1261,33 @@ void lua_pushf_args(const struct ptr_list_head *args, int idx_desync)
LUA_STACK_GUARD_LEAVE(params.L, 0)
}
void lua_pushf_pos(const char *name, const struct packet_pos *pos)
{
LUA_STACK_GUARD_ENTER(params.L)
char smode[2]="?";
lua_pushf_table(name);
lua_getfield(params.L,-1,name);
*smode=pos->mode;
lua_pushf_str("mode",smode);
lua_pushf_int("pos",pos->pos);
lua_pop(params.L,1);
LUA_STACK_GUARD_LEAVE(params.L, 0)
}
void lua_pushf_range(const char *name, const struct packet_range *range)
{
LUA_STACK_GUARD_ENTER(params.L)
lua_pushf_table(name);
lua_getfield(params.L,-1,"range");
lua_pushf_bool("upper_cutoff",range->upper_cutoff);
lua_pushf_pos("from", &range->from);
lua_pushf_pos("to", &range->to);
lua_pop(params.L,1);
LUA_STACK_GUARD_LEAVE(params.L, 0)
}
static void lua_reconstruct_extract_options(lua_State *L, int idx, bool *badsum, bool *ip6_preserve_next, uint8_t *ip6_last_proto)

View File

@@ -73,6 +73,8 @@ void lua_push_dissect(const struct dissect *dis);
void lua_pushf_dissect(const struct dissect *dis);
void lua_pushf_ctrack(const t_ctrack *ctrack);
void lua_pushf_args(const struct ptr_list_head *args, int idx_desync);
void lua_pushf_pos(const char *name, const struct packet_pos *pos);
void lua_pushf_range(const char *name, const struct packet_range *range);
void lua_pushf_global(const char *field, const char *global);
bool lua_reconstruct_ip6hdr(int idx, struct ip6_hdr *ip6, size_t *len, uint8_t last_proto, bool preserve_next);
@@ -87,7 +89,7 @@ typedef struct {
const struct desync_profile *dp;
const struct dissect *dis;
t_ctrack *ctrack;
bool cancel;
bool incoming,cancel;
} t_lua_desync_context;
bool lua_instance_cutoff_check(const t_lua_desync_context *ctx, bool bIn);

View File

@@ -1683,6 +1683,7 @@ int main(int argc, char **argv)
{
if (argc < 2) exithelp();
aes_init_keygen_tables(); // required for aes
set_console_io_buffering();
set_env_exedir(argv[0]);

View File

@@ -66,6 +66,35 @@ bool l7_payload_match(t_l7payload l7payload, uint64_t filter_l7p)
{
return filter_l7p==L7P_ALL || (filter_l7p & (1<<l7payload)) || (filter_l7p & (1<<L7P_KNOWN)) && l7payload>L7P_KNOWN && l7payload<L7P_LAST;
}
bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
{
char *p;
const char *pstr;
size_t lstr;
t_l7payload pl;
if (!size) return false;
if (l7p==L7P_ALL)
{
if (size<4) return false;
memcpy(buf,"all",4);
return true;
}
for(pl=0, p=buf, *buf=0 ; pl<L7P_LAST ; pl++)
{
if (l7p & (1<<pl))
{
pstr = l7payload_str(pl);
lstr = strlen(pstr);
if (size < ((p!=buf) + lstr + 1)) return false;
if (p!=buf) *p++=','; // not first
memcpy(p,pstr,lstr);
p[lstr]=0;
p+=lstr;
}
}
return true;
}
static const char *posmarker_names[] = {"abs","host","endhost","sld","midsld","endsld","method","extlen","sniext"};

View File

@@ -55,6 +55,7 @@ typedef enum {
t_l7payload l7payload_from_name(const char *name);
const char *l7payload_str(t_l7payload l7);
bool l7_payload_match(t_l7payload l7payload, uint64_t filter_l7p);
bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size);
typedef enum {
PM_ABS=0,