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

zapret-lib, zapret-antidpi: use numeric indexes in http dissects

This commit is contained in:
bol-van
2026-01-11 12:29:53 +03:00
parent 0b595ae3a8
commit 4554b7c15b
5 changed files with 60 additions and 27 deletions

View File

@@ -169,3 +169,8 @@ v0.8.1
* nfqws2: ignore trailing spaces and tabs in hostlists and ipsets. "host.com " or "1.2.3.4 " are ok now
* init.d: 99-lan-filter custom script
* mdig: --eagain, --eagain-delay
0.8.4
* winws2: fix loopback large packets processing (up to 64K)
* zapret-lib, zapret-antidpi: use numeric indexes in http dissects

View File

@@ -2356,7 +2356,8 @@ function http_reconstruct_req(hdis, unixeol)
Parses an HTTP request or response. The `http` parameter is a multi-line string.
The parsed result is a table with nested sub-tables.
Headers provide the start and end positions for both the header name and the value itself.
Field names in the `headers` table correspond to lowercase header names. All positions are relative to the `http` string.
To find a header by name use [array_field_search](#array_search) with field name "header_low" which contains header name in lower case.
The HTTP request reconstructor takes a parsed table and recreates the raw string. The `unixeol` parameter replaces the standard HTTP line ending (0D0A) with 0A. This is non-standard and will break almost all servers except for Nginx.
@@ -2366,9 +2367,11 @@ The HTTP request reconstructor takes a parsed table and recreates the raw string
.uri
string /test_uri
.headers
.content-length
.1
.header
string Content-Length
.header_low
string content-length
.value
string 330
.pos_start
@@ -2379,9 +2382,11 @@ The HTTP request reconstructor takes a parsed table and recreates the raw string
number 56
.pos_value_start
number 59
.host
.2
.header
string Host
.header_low
string host
.value
string testhost.com
.pos_start
@@ -3370,6 +3375,7 @@ function http_methodeol(ctx, desync)
- arg: [standard direction](#standard-direction)
Inserts `\r\n` before the method, stripping the last two characters from the `User-Agent:` header content. This only works with Nginx; it breaks other servers.
If used with other http tampering functions should be the last !
### http_unixeol

View File

@@ -2522,7 +2522,9 @@ function http_reconstruct_req(hdis, unixeol)
Разборка HTTP запроса или ответа http. http представляет собой многострочный текст.
Разборка представляет собой таблицу с вложенными подтаблицами.
В заголовках выдаются позиции начала и конца названия заголовка и самого значения.
Названия полей в таблице headers соответствуют названию заголовков в нижнем регисте. Все позиции - внутри строки http.
Все позиции - внутри строки http.
Для нахождения хедеров по названию используйте [array_field_search](#array_search) по полю "header_low", которое содержит название хедера в нижнем регистре.
Реконструктор http запроса берет таблицу-разбор и воссоздает raw string. Параметр unixeol заменяет стандартный для http перевод сктроки 0D0A на 0A. Это нестандарт и ломает все сервера, кроме nginx.
@@ -2532,9 +2534,11 @@ function http_reconstruct_req(hdis, unixeol)
.uri
string /test_uri
.headers
.content-length
.1
.header
string Content-Length
.header_low
string content-length
.value
string 330
.pos_start
@@ -2545,9 +2549,11 @@ function http_reconstruct_req(hdis, unixeol)
number 56
.pos_value_start
number 59
.host
.2
.header
string Host
.header_low
string host
.value
string testhost.com
.pos_start
@@ -3552,6 +3558,7 @@ function http_methodeol(ctx, desync)
- arg: [standard direction](#standard-direction)
Вставляет '\r\n' перед методом, отрезая 2 последних символа из содержимого заголовка `User-Agent:`. Работает только на nginx, остальные сервера ломает.
Если используется совместно с другими функциями http тамперинга, должен идти последним.
### http_unixeol

View File

@@ -149,12 +149,17 @@ function http_hostcase(ctx, desync)
error("http_hostcase: invalid host spelling '"..spell.."'")
else
local hdis = http_dissect_req(desync.dis.payload)
if hdis.headers.host then
DLOG("http_hostcase: 'Host:' => '"..spell.."'")
desync.dis.payload = string.sub(desync.dis.payload,1,hdis.headers.host.pos_start-1)..spell..string.sub(desync.dis.payload,hdis.headers.host.pos_header_end+1)
return VERDICT_MODIFY
if hdis then
local idx_host = array_field_search(hdis.headers, "header_low", "host")
if idx_host then
DLOG("http_hostcase: 'Host:' => '"..spell.."'")
desync.dis.payload = string.sub(desync.dis.payload,1,hdis.headers[idx_host].pos_start-1)..spell..string.sub(desync.dis.payload,hdis.headers[idx_host].pos_header_end+1)
return VERDICT_MODIFY
else
DLOG("http_hostcase: 'Host:' header not found")
end
else
DLOG("http_hostcase: 'Host:' header not found")
DLOG("http_hostcase: http dissect error")
end
end
end
@@ -162,6 +167,7 @@ end
-- nfqws1 : "--methodeol"
-- standard args : direction
-- NOTE : if using with other http tampering methodeol should be the last !
function http_methodeol(ctx, desync)
if not desync.dis.tcp then
instance_cutoff_shim(ctx, desync)
@@ -170,17 +176,22 @@ function http_methodeol(ctx, desync)
direction_cutoff_opposite(ctx, desync)
if desync.l7payload=="http_req" and direction_check(desync) then
local hdis = http_dissect_req(desync.dis.payload)
local ua = hdis.headers["user-agent"]
if ua then
if (ua.pos_end - ua.pos_value_start) < 2 then
DLOG("http_methodeol: 'User-Agent:' header is too short")
if hdis then
local idx_ua = array_field_search(hdis.headers, "header_low", "user-agent")
if idx_ua then
local ua = hdis.headers[idx_ua]
if (ua.pos_end - ua.pos_value_start) < 2 then
DLOG("http_methodeol: 'User-Agent:' header is too short")
else
DLOG("http_methodeol: applied")
desync.dis.payload="\r\n"..string.sub(desync.dis.payload,1,ua.pos_end-2)..(string.sub(desync.dis.payload,ua.pos_end+1) or "");
return VERDICT_MODIFY
end
else
DLOG("http_methodeol: applied")
desync.dis.payload="\r\n"..string.sub(desync.dis.payload,1,ua.pos_end-2)..(string.sub(desync.dis.payload,ua.pos_end+1) or "");
return VERDICT_MODIFY
DLOG("http_methodeol: 'User-Agent:' header not found")
end
else
DLOG("http_methodeol: 'User-Agent:' header not found")
DLOG("http_methodeol: http dissect error")
end
end
end
@@ -197,10 +208,11 @@ function http_unixeol(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 idx_ua = array_field_search(hdis.headers, "header_low", "user-agent")
if idx_ua 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)
hdis.headers[idx_ua].value = hdis.headers[idx_ua].value .. string.rep(" ", #desync.dis.payload - #http)
end
local http = http_reconstruct_req(hdis, true)
if #http==#desync.dis.payload then
@@ -211,7 +223,7 @@ function http_unixeol(ctx, desync)
DLOG("http_unixeol: reconstruct differs in size from original: "..#http.."!="..#desync.dis.payload)
end
else
DLOG("http_unixeol: user-agent header absent")
DLOG("http_unixeol: 'User-Agent:' header absent")
end
else
DLOG("http_unixeol: could not dissect http")

View File

@@ -579,7 +579,6 @@ function array_search(a, v)
return k
end
end
return nil
end
-- linear search array a for a[index].f==v. return index
function array_field_search(a, f, v)
@@ -588,7 +587,6 @@ function array_field_search(a, f, v)
return k
end
end
return nil
end
-- find pos of the next eol and pos of the next non-eol character after eol
@@ -1568,7 +1566,7 @@ function http_dissect_headers(http, pos)
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 }
headers[#headers+1] = { header_low = 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
@@ -1619,11 +1617,16 @@ function http_dissect_reply(http)
code = tonumber(string.sub(http,10,pos-1))
if not code then return nil end
pos = find_next_line(http,pos)
return { code = code, headers = http_dissect_headers(http,pos) }
local hdis = { code = code }
hdis.headers, hdis.pos_headers_end = http_dissect_headers(http,pos)
if hdis.pos_headers_end then
hdis.body = string.sub(http, hdis.pos_headers_end)
end
return hdis
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 ""
return headers and bitable(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"