mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-14 06:13:09 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bc65c3b91 | ||
|
|
6bf7f2c7c0 | ||
|
|
44a80abb3f | ||
|
|
89f0f39b83 | ||
|
|
ad6f1db149 | ||
|
|
9154fe1677 | ||
|
|
5e63a0f5c5 | ||
|
|
0521053991 | ||
|
|
7b7ed1ad60 | ||
|
|
2915647c63 | ||
|
|
958a4e918b | ||
|
|
cb332dad74 | ||
|
|
17e9e0a8e6 | ||
|
|
78b348a193 | ||
|
|
8103a02689 |
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -75,11 +75,11 @@ jobs:
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt update -qq
|
||||
if [[ "$ARCH" == lexra ]]; then
|
||||
sudo apt install -y libcap-dev libc6:i386 zlib1g:i386
|
||||
sudo apt install -y pigz libcap-dev libc6:i386 zlib1g:i386
|
||||
URL=https://github.com/$REPO/raw/refs/heads/master/$DIR.txz
|
||||
else
|
||||
# luajit buildvm requires 32 bit executable on host platform for 32 bit cross targets
|
||||
sudo apt install -y libcap-dev libc6-dev gcc-multilib
|
||||
sudo apt install -y pigz libcap-dev libc6-dev gcc-multilib
|
||||
URL=https://github.com/$REPO/releases/download/latest/$TOOL.tar.xz
|
||||
fi
|
||||
mkdir -p $HOME/tools
|
||||
@@ -553,7 +553,7 @@ jobs:
|
||||
rm -rf binaries/{android*,freebsd*,win*} \
|
||||
init.d/{openrc,pfsense,runit,s6,systemd,windivert.filter.examples} \
|
||||
nfq2 ip2net mdig docs Makefile
|
||||
gzip lua/*.lua
|
||||
pigz -11 lua/*.lua
|
||||
)
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ pktws_check_http()
|
||||
|
||||
[ "$NOTEST_BASIC_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for s in 'http_hostcase' 'http_hostcase:spell=hoSt' 'http_domcase' 'http_methodeol'; do
|
||||
for s in 'http_hostcase' 'http_hostcase:spell=hoSt' 'http_domcase' 'http_methodeol' 'http_unixeol'; do
|
||||
pktws_curl_test_update $1 $2 --payload http_req --lua-desync=$s
|
||||
done
|
||||
}
|
||||
|
||||
@@ -144,3 +144,11 @@ v0.8.0
|
||||
* zapret-antidpi: tls_client_hello_clone
|
||||
* zapret-antidpi: "optional" arg to blob taking functions
|
||||
* nfqws2: support gzipped lua file. auto use script.lua.gz
|
||||
|
||||
v0.8.1
|
||||
|
||||
* nfqws2: fix bu48 crash and wrong results in bitset
|
||||
* zapret-lib: http_reconstruct_req
|
||||
* zapret-antidpi: http_unixeol
|
||||
* blockcheck2: http_unixeol test
|
||||
|
||||
|
||||
@@ -158,6 +158,7 @@
|
||||
- [http\_hostcase](#http_hostcase)
|
||||
- [http\_domcase](#http_domcase)
|
||||
- [http\_methodeol](#http_methodeol)
|
||||
- [http\_unixeol](#http_unixeol)
|
||||
- [Замена window size](#замена-window-size)
|
||||
- [wsize](#wsize)
|
||||
- [wssize](#wssize)
|
||||
@@ -1834,7 +1835,9 @@ nfqws2 не использует никакие криптобиблиотеки
|
||||
function bcryptorandom(size)
|
||||
```
|
||||
|
||||
Генерирует raw строку - криптографически стойкий блок случайных данных указанного размера. Источник - `/dev/random`
|
||||
Генерирует raw строку - криптографически стойкий блок случайных данных указанного размера. Источник - `/dev/random`.
|
||||
Если пул энтропии исчерпывается, может вызывать зависания. Чтобы этого не было - установите haveged или rngd.
|
||||
Не стоит использовать для получения случайных данных, не требующих крипто-стойкости.
|
||||
|
||||
#### hash
|
||||
|
||||
@@ -2373,8 +2376,12 @@ function blob_or_def(desync, name, def)
|
||||
|
||||
```
|
||||
function barray(a, packer)
|
||||
function btable(a, packer)
|
||||
```
|
||||
|
||||
- barray использует только числовые индексы, начиная с 1. порядок соблюдается
|
||||
- btable использует все индексы, но не гарантирует порядок
|
||||
|
||||
Упаковка элементов массива a в порядке возрастания индекса от 1 до последнего.
|
||||
`packer` - функция, берущая элемент a и возвращающая raw string.
|
||||
Для числовых массивов в качестве packer можно использовать [функции паковки чисел](#bux).
|
||||
@@ -2463,6 +2470,7 @@ function dissect_nld(domain, level)
|
||||
```
|
||||
function http_dissect_req(http)
|
||||
function http_dissect_reply(http)
|
||||
function http_reconstruct_req(hdis)
|
||||
```
|
||||
|
||||
Разборка HTTP запроса или ответа http. http представляет собой многострочный текст.
|
||||
@@ -2470,6 +2478,8 @@ function http_dissect_reply(http)
|
||||
В заголовках выдаются позиции начала и конца названия заголовка и самого значения.
|
||||
Названия полей в таблице headers соответствуют названию заголовков в нижнем регисте. Все позиции - внутри строки http.
|
||||
|
||||
Реконструктор http запроса берет таблицу-разбор и воссоздает raw string.
|
||||
|
||||
<details>
|
||||
<summary><b>Пример разборки http запроса `http://testhost.com/testuri`</b></summary>
|
||||
<pre>
|
||||
@@ -2558,7 +2568,9 @@ function tls_reconstruct(tdis)
|
||||
7. Если есть record layer, реконструкция выполняется согласно длинам отдельных records. Если последняя часть не влезает, tls record расширяется под оставшиеся данные.
|
||||
8. При отсутствии изменений dissect+reconstruct дают бинарно идентичные блобы.
|
||||
|
||||
Функции не работают с DTLS. В случае ошибки возвращается nil.
|
||||
Функции не работают с DTLS.
|
||||
|
||||
`tls_dissect` возвращает таблицу - разбор raw строки tls со смещения offset (начиная с 1), `reconstruct_dissect` возвращает raw строку собранного разбора tdis. В случае ошибки возвращается nil.
|
||||
|
||||
Простейший способ получить образец диссекта : `--payload=tls_client_hello --lua-desync=luaexec:code="var_debug(tls_dissect(desync.reasm_data))"`.
|
||||
И вызвать TLS запрос.
|
||||
@@ -2876,9 +2888,11 @@ function tls_reconstruct(tdis)
|
||||
|
||||
Множество констант, связанных с TLS, определено в `zapret-lib.lua`. Прежде чем писать фиксированные значения, посмотрите нет ли нужной константы.
|
||||
|
||||
Таблица handshake индексируется по типу hadnshake. Самыми типичными являются `TLS_HANDSHAKE_TYPE_CLIENT` и `TLS_HANDSHAKE_TYPE_SERVER`.
|
||||
Таблица handshake индексируется по типу handshake. Самыми типичными являются `TLS_HANDSHAKE_TYPE_CLIENT` и `TLS_HANDSHAKE_TYPE_SERVER`.
|
||||
Они имеют значения 1 и 2 соответственно, поэтому может показаться, что элементы handshake идут от 1 и по возрастающей. Это не так.
|
||||
|
||||
extensions и другие списки индексируются по номеру с 1, а не по типу, потому что важен порядок их следования, и может быть несколько элементов одного типа.
|
||||
|
||||
Если вы что-то добавляете свое, вам нужно воспроизвести минимальный вариант исходной структуры.
|
||||
Можно заполнить только raw data field. Если нет подтаблицы dis - при реконструкции будет взято оно.
|
||||
Если есть dis, то он должен быть заполнен корректно согласно рассматриваемому элементу данных.
|
||||
@@ -3448,6 +3462,16 @@ function http_methodeol(ctx, desync)
|
||||
|
||||
Вставляет '\r\n' перед методом, отрезая 2 последних символа из содержимого заголовка `User-Agent:`. Работает только на nginx, остальные сервера ломает.
|
||||
|
||||
### http_unixeol
|
||||
|
||||
```
|
||||
function http_unixeol(ctx, desync)
|
||||
```
|
||||
|
||||
- arg: [standard direction](#standard-direction)
|
||||
|
||||
Заменяет перевод строки 0D0A на 0A. Разницу в длине добавляет пробелами в конец хедера "User-Agent". Работает только на nginx, остальные сервера ломает.
|
||||
|
||||
## Замена window size
|
||||
|
||||
### wsize
|
||||
@@ -4451,6 +4475,10 @@ NOTEST_QUIC=1 - отмена тестов 90-quic.sh
|
||||
|
||||
Простой тестировщик по списку стратегий из файлов. Стратегии должны быть на отдельных строчках, переносы строки не допускаются. Используются отдельные списки для протоколов - `list_http.txt`, `list_https_tls12.txt`, `list_https_tls13.txt`, `list_quic.sh`. В файлах поддерживаются комментарии, начинающиеся на `#`.
|
||||
|
||||
При записи параметров следует учитывать, что они будут интерпретироваься как параметры shell. Специальные символы нужно экранировать по правилам shell.
|
||||
Если вы оставите "<" без кавычек на всем параметре или возьмете в кавычки параметр `--luaexec=code=print("abc")`, будет ошибка. Если в lua коде используются строки - их стоит заключать в одинарные кавычки, а вокруг параметра - двойные.
|
||||
blockcheck2 будет выдавать параметры стратегий без экранирования.
|
||||
|
||||
Самый правильный способ применения - скопировать в свою поддиректорию внутри `blockcheck2.d` и заполнить txt файлы с тестами. Выбрать свое имя теста в диалоге.
|
||||
|
||||
## Summary
|
||||
@@ -4588,6 +4616,9 @@ ip листы разделяются на ipv4 и ipv6. ipv6 листы имею
|
||||
|
||||
В зависимости от режима хостлисты могут ресолвиться в ip листы через [mdig](#mdig) или применяться как есть. Если хостлисты применяются как есть в nfqws2, учитываются только имена доменов, а IP адреса и подсети - нет.
|
||||
|
||||
Включающие ip листы загоняются в сеты ядра и применяются в правилах таблиц только, если указан [MODE_FILTER=ipset](#файл-config).
|
||||
Исключающий ip лист загоняется в сеты ядра и применяется всегда в правилах таблиц.
|
||||
|
||||
| Хостлист | Тип | Назначение | ip листы |
|
||||
| :---------------------------- | :--------------- | :-------------- | :---------------------------------------------------- |
|
||||
| zapret-hosts-user.txt | пользовательский | включающий | zapret-ip-user.txt<br>zapret-ip-user6.txt |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
10
nfq2/lua.c
10
nfq2/lua.c
@@ -193,7 +193,7 @@ static int luacall_bitset(lua_State *L)
|
||||
if (from>to || from>47 || to>47)
|
||||
luaL_error(L, "bit range invalid");
|
||||
|
||||
lua_Integer mask = ~((lua_Integer)-1 << (to-from+1));
|
||||
uint64_t mask = ~((uint64_t)-1 << (to-from+1));
|
||||
set = (set & mask) << from;
|
||||
mask <<= from;
|
||||
what = what & ~mask | set;
|
||||
@@ -401,7 +401,7 @@ static int luacall_bu48(lua_State *L)
|
||||
|
||||
int64_t i = (int64_t)luaL_checklint(L,1);
|
||||
if (i>0xFFFFFFFFFFFF || i<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint8_t v[4];
|
||||
uint8_t v[6];
|
||||
phton48(v,(uint64_t)i);
|
||||
lua_pushlstring(L,(char*)v,6);
|
||||
return 1;
|
||||
@@ -2961,13 +2961,13 @@ static int luaL_doZfile(lua_State *L, const char *filename)
|
||||
FILE *F = fopen(fname, "rb");
|
||||
if (!F)
|
||||
luaL_error(L, "could not open lua file '%s'", fname);
|
||||
r = z_readfile(F, &buf, &size, 1);
|
||||
r = z_readfile(F, &buf, &size, 0);
|
||||
fclose(F);
|
||||
if (r != Z_OK)
|
||||
luaL_error(L, "could not unzip lua file '%s'", fname);
|
||||
buf[size] = 0;
|
||||
r = luaL_dostring(L, buf);
|
||||
r = luaL_loadbuffer(L, buf, size, fname);
|
||||
free(buf);
|
||||
if (!r) r=lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user