From 9154fe167708a56f8262fbf40cdc4683f9f9402a Mon Sep 17 00:00:00 2001 From: bol-van Date: Tue, 30 Dec 2025 13:25:51 +0300 Subject: [PATCH] zapret-lib, zapret-antidpi: http_reconstruct_req, http_unixeol --- lua/zapret-antidpi.lua | 34 +++++++++++++++++++++++++++++++ lua/zapret-lib.lua | 45 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/lua/zapret-antidpi.lua b/lua/zapret-antidpi.lua index 7e142e1..5a67bd4 100644 --- a/lua/zapret-antidpi.lua +++ b/lua/zapret-antidpi.lua @@ -185,6 +185,40 @@ function http_methodeol(ctx, desync) end end +-- nfqws1 : not available +-- tpws : --unixeol +-- standard args : direction +function http_unixeol(ctx, desync) + if not desync.dis.tcp then + instance_cutoff_shim(ctx, desync) + return + end + direction_cutoff_opposite(ctx, desync) + if desync.l7payload=="http_req" and direction_check(desync) then + local hdis = http_dissect_req(desync.dis.payload) + if hdis then + if hdis.headers["user-agent"] then + local http = http_reconstruct_req(hdis, true) + if #http < #desync.dis.payload then + hdis.headers["user-agent"].value = hdis.headers["user-agent"].value .. string.rep(" ", #desync.dis.payload - #http) + end + local http = http_reconstruct_req(hdis, true) + if #http==#desync.dis.payload then + desync.dis.payload = http + DLOG("http_unixeol: applied") + return VERDICT_MODIFY + else + DLOG("http_unixeol: reconstruct differs in size from original: "..#http.."!="..#desync.dis.payload) + end + else + DLOG("http_unixeol: user-agent header absent") + end + else + DLOG("http_unixeol: could not dissect http") + end + end +end + -- nfqws1 : "--synack-split" -- standard args : rawsend, reconstruct, ipfrag -- arg : mode=syn|synack|acksyn . "synack" by default diff --git a/lua/zapret-lib.lua b/lua/zapret-lib.lua index 0b76fd6..c9a46aa 100644 --- a/lua/zapret-lib.lua +++ b/lua/zapret-lib.lua @@ -304,7 +304,7 @@ function pos_str(desync, pos) return pos.mode..pos_get(desync, pos.mode) end --- convert array a to packed string using 'packer' function +-- convert array a to packed string using 'packer' function. only numeric indexes starting from 1, order preserved function barray(a, packer) if a then local s="" @@ -314,6 +314,16 @@ function barray(a, packer) return s end end +-- convert table a to packed string using 'packer' function. any indexes, any order +function btable(a, packer) + if a then + local s="" + for k,v in pairs(a) do + s = s .. packer(v) + end + return s + end +end -- sequence comparision functions. they work only within 2G interval -- seq1>=seq2 @@ -1423,19 +1433,22 @@ function http_dissect_header(header) end -- make table with structured http header representation function http_dissect_headers(http, pos) - local eol,pnext,header,value,idx,headers,pos_endheader,pos_startvalue + local eol,pnext,header,value,idx,headers,pos_endheader,pos_startvalue,pos_headers_next headers={} while pos do eol,pnext = find_next_line(http,pos) header = string.sub(http,pos,eol) - if #header == 0 then break end + if #header == 0 then + pos_headers_end = pnext + break + end header,value,pos_endheader,pos_startvalue = http_dissect_header(header) if header then headers[string.lower(header)] = { header = header, value = value, pos_start = pos, pos_end = eol, pos_header_end = pos+pos_endheader-1, pos_value_start = pos+pos_startvalue-1 } end pos=pnext end - return headers + return headers, pos_headers_end end -- make table with structured http request representation function http_dissect_req(http) @@ -1457,9 +1470,21 @@ function http_dissect_req(http) pos = string.find(req,"[^ \t]",pos+1) if not pos then return nil end pnext = string.find(req,"[ \t]",pos+1) - if not pnext then pnext = #http + 1 end + if not pnext then pnext = #req + 1 end local uri = string.sub(req,pos,pnext-1) - return { method = method, uri = uri, headers = http_dissect_headers(http,hdrpos) } + pos = string.find(req,"[^ \t]",pnext) + local http_ver + if pos then + pnext = string.find(req,"[\r\n]",pos) + if not pnext then pnext = #req + 1 end + http_ver = string.sub(req,pos,pnext-1) + end + local hdis = { method = method, uri = uri, http_ver = http_ver } + hdis.headers, hdis.pos_headers_end = http_dissect_headers(http,hdrpos) + if hdis.pos_headers_end then + hdis.body = string.sub(http, hdis.pos_headers_end) + end + return hdis end function http_dissect_reply(http) if not http then return nil; end @@ -1472,6 +1497,14 @@ function http_dissect_reply(http) pos = find_next_line(http,pos) return { code = code, headers = http_dissect_headers(http,pos) } end +function http_reconstruct_headers(headers, unixeol) + local eol = unixeol and "\n" or "\r\n" + return headers and btable(headers, function(a) return a.header..": "..a.value..eol end) or "" +end +function http_reconstruct_req(hdis, unixeol) + local eol = unixeol and "\n" or "\r\n" + return hdis.method.." "..hdis.uri..(hdis.http_ver and (" "..hdis.http_ver) or "")..eol..http_reconstruct_headers(hdis.headers, unixeol)..eol..(hdis.body or "") +end function dissect_url(url) local p1,pb,pstart,pend