From 67a8ee47e3b788c891af2a1d663d20f2d7b6221c Mon Sep 17 00:00:00 2001 From: bol-van Date: Thu, 15 Jan 2026 20:02:53 +0300 Subject: [PATCH] zapret-antidpi: oob --- docs/changes.txt | 2 + lua/zapret-antidpi.lua | 91 +++++++++++++++++++++++++++++++++++++++++- lua/zapret-lib.lua | 12 ++++++ 3 files changed, 103 insertions(+), 2 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 0c21361..c6abf49 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -183,3 +183,5 @@ v0.8.1 0.8.5 * nfqws2: do not require / in the beginning of URI in http +* zapret-lib: rawsend_dissect_segmented support URG +* zapret-antidpi: oob diff --git a/lua/zapret-antidpi.lua b/lua/zapret-antidpi.lua index dc8658f..077391b 100644 --- a/lua/zapret-antidpi.lua +++ b/lua/zapret-antidpi.lua @@ -511,11 +511,10 @@ function multisplit(ctx, desync) end end --- internal function for code deduplication. do not call directly + function pos_normalize(pos, low, hi) return (pos>=low and pos "..dseq) + desync.dis.tcp.th_seq = dseq + end + if pos==0 then + return VERDICT_MODIFY + elseif pos==1 then + local data = desync.reasm_data or desync.dis.payload + if not desync.arg.drop_ack and #data==0 then + DLOG("oob: sending empty ACK") + if not rawsend_dissect(desync.dis) then return end + end + if #data>0 then + local oob = desync.arg.char or (desync.arg.byte and bu8(desync.arg.byte) or nil) or "\x00" + local dis_oob = deepcopy(desync.dis) + local urp + if not desync.arg.urp or desync.arg.urp=='b' then + urp = 1 + dis_oob.tcp.th_urp = 0 + elseif desync.arg.urp=='e' then + urp = #data+1 + dis_oob.tcp.th_urp = urp + else + urp = resolve_pos(data, desync.l7payload, desync.arg.urp) + DLOG("oob: resolved urp marker to "..urp-1) + if not urp then + DLOG("oob: cannot resolve urp marker '"..desync.arg.urp.."'") + instance_cutoff_shim(ctx, desync) + return + end + dis_oob.tcp.th_urp = urp + end + DLOG("oob: th_urp "..dis_oob.tcp.th_urp) + -- one byte OOB payload + dis_oob.payload = string.sub(data, 1, urp-1) .. oob .. string.sub(data, urp) + dis_oob.tcp.th_flags = bitor(dis_oob.tcp.th_flags, TH_URG) + DLOG("oob: sending OOB") + if not rawsend_dissect_segmented(desync, dis_oob, desync.tcp_mss, desync_opts(desync)) then + instance_cutoff_shim(ctx, desync) + return + end + if not desync.replay then + instance_cutoff_shim(ctx, desync) + end + end + return VERDICT_DROP + else + -- drop replay and cutoff + if desync.replay then + DLOG("oob: dropping replay piece") + if desync.replay_piece_last then + instance_cutoff_shim(ctx, desync) + end + return VERDICT_DROP + end + instance_cutoff_shim(ctx, desync) + end + else + -- reverse pos - outgoing + local pos = pos_get(desync, 's', true) + if pos>1 then + DLOG("oob: unexpected outgoing position "..pos) + instance_cutoff_shim(ctx, desync) + return + end + local dack = u32add(desync.dis.tcp.th_ack, 1) + DLOG("oob: increasing incoming ack : "..desync.dis.tcp.th_ack.." => "..dack) + desync.dis.tcp.th_ack = dack + return VERDICT_MODIFY + end +end + -- nfqws1 : "--dpi-desync=udplen" -- standard args : direction, payload -- arg : min=N . do not act on payloads smaller than N bytes diff --git a/lua/zapret-lib.lua b/lua/zapret-lib.lua index 03834a6..856842f 100644 --- a/lua/zapret-lib.lua +++ b/lua/zapret-lib.lua @@ -310,6 +310,7 @@ function pos_str(desync, pos) return pos.mode..pos_get(desync, pos.mode) end + -- convert array a to packed string using 'packer' function. only numeric indexes starting from 1, order preserved function barray(a, packer) if a then @@ -1075,6 +1076,8 @@ function rawsend_dissect_segmented(desync, dis, mss, options) local extra_len = l3l4_extra_len(discopy) if extra_len >= mss then return false end local max_data = mss - extra_len + local urp = dis.tcp.th_urp + local oob = bitand(dis.tcp.th_flags, TH_URG)~=0 if #discopy.payload > max_data then local pos=1 local len @@ -1083,6 +1086,15 @@ function rawsend_dissect_segmented(desync, dis, mss, options) while pos <= #payload do len = #payload - pos + 1 if len > max_data then len = max_data end + if oob then + if urp>=pos and urp<(pos+len)then + discopy.tcp.th_flags = bitor(dis.tcp.th_flags, TH_URG) + discopy.tcp.th_urp = urp-pos+1 + else + discopy.tcp.th_flags = bitand(dis.tcp.th_flags, bitnot(TH_URG)) + discopy.tcp.th_urp = 0 + end + end discopy.payload = string.sub(payload,pos,pos+len-1) apply_ip_id(desync, discopy, options and options.ipid) if not rawsend_dissect_ipfrag(discopy, options) then