mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-16 22:59:46 +00:00
Compare commits
137 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2983c681d7 | ||
|
|
68eefd9dd7 | ||
|
|
73f6f7c522 | ||
|
|
df83a29b98 | ||
|
|
9881cc4da2 | ||
|
|
44f8ad6747 | ||
|
|
c651367d6a | ||
|
|
90f88271c5 | ||
|
|
9ba8d6cbdf | ||
|
|
27efbb37d7 | ||
|
|
d725bd8fd7 | ||
|
|
0ef50d04dc | ||
|
|
fdae4b1812 | ||
|
|
d0644f6160 | ||
|
|
b4f1765574 | ||
|
|
8454d48fcd | ||
|
|
70d7a77d06 | ||
|
|
2a48f82feb | ||
|
|
c5d997ce48 | ||
|
|
c950edb380 | ||
|
|
0d96b03f49 | ||
|
|
9772641813 | ||
|
|
7307a03ff7 | ||
|
|
b529198f24 | ||
|
|
5f5cfb434c | ||
|
|
2f1aa5734e | ||
|
|
062360f3f3 | ||
|
|
7122808425 | ||
|
|
515921522e | ||
|
|
c0ce825a95 | ||
|
|
c4b23d21ce | ||
|
|
0847d9f140 | ||
|
|
b239690e33 | ||
|
|
4f6510daf1 | ||
|
|
0cad2329a1 | ||
|
|
24d9eb1fe2 | ||
|
|
f98445d36b | ||
|
|
7278bb1b87 | ||
|
|
5b58997e3e | ||
|
|
93a6487eb5 | ||
|
|
fdca797671 | ||
|
|
bb9e78e8fb | ||
|
|
2a15a1a778 | ||
|
|
bf89b415bb | ||
|
|
735936efc5 | ||
|
|
9d09d8adcc | ||
|
|
3874e16075 | ||
|
|
cbb05967ba | ||
|
|
665bd5f318 | ||
|
|
fa1d7c30c3 | ||
|
|
940f94162d | ||
|
|
60108bf378 | ||
|
|
5a68245e32 | ||
|
|
b2dbdd4dd7 | ||
|
|
5bc65c3b91 | ||
|
|
6bf7f2c7c0 | ||
|
|
44a80abb3f | ||
|
|
89f0f39b83 | ||
|
|
ad6f1db149 | ||
|
|
9154fe1677 | ||
|
|
5e63a0f5c5 | ||
|
|
0521053991 | ||
|
|
7b7ed1ad60 | ||
|
|
2915647c63 | ||
|
|
958a4e918b | ||
|
|
cb332dad74 | ||
|
|
17e9e0a8e6 | ||
|
|
78b348a193 | ||
|
|
8103a02689 | ||
|
|
a2dedc45c0 | ||
|
|
f0d3a63df9 | ||
|
|
c6ca25a656 | ||
|
|
71b87f749d | ||
|
|
3d756c9702 | ||
|
|
13864fe5c5 | ||
|
|
cc2601af2f | ||
|
|
07319a329e | ||
|
|
52f5c2697b | ||
|
|
6b0dde5643 | ||
|
|
e42265e071 | ||
|
|
939f7a9558 | ||
|
|
b62ebd8fcb | ||
|
|
521fafc05d | ||
|
|
419d6769bd | ||
|
|
dde3f59d32 | ||
|
|
78e1fb85ac | ||
|
|
f73790b871 | ||
|
|
33f3378094 | ||
|
|
af7a6f6c10 | ||
|
|
9cc348e5bd | ||
|
|
8628c34941 | ||
|
|
eec9f3e87c | ||
|
|
e4a8f51775 | ||
|
|
fb962df188 | ||
|
|
173dcd47d1 | ||
|
|
3439dc4f21 | ||
|
|
6e04162a20 | ||
|
|
883a3d6233 | ||
|
|
e8cde6b0a2 | ||
|
|
43872a21a6 | ||
|
|
ff2c3e81f9 | ||
|
|
bcbfb45c53 | ||
|
|
fa6a75f139 | ||
|
|
e96c06598c | ||
|
|
58320aecbe | ||
|
|
ba526b75e1 | ||
|
|
b9321619fc | ||
|
|
d1a489a196 | ||
|
|
cf91697dfb | ||
|
|
401886bf32 | ||
|
|
8baf81a840 | ||
|
|
417cd8335a | ||
|
|
5a9d40ad3f | ||
|
|
af0be0fd94 | ||
|
|
68e0c367c9 | ||
|
|
0969d22391 | ||
|
|
94daca8ced | ||
|
|
1982984a86 | ||
|
|
6a520f508a | ||
|
|
70d0dd5d79 | ||
|
|
4ca0f6b574 | ||
|
|
76e85d8969 | ||
|
|
f458a76880 | ||
|
|
6077d363ec | ||
|
|
c70f114c3a | ||
|
|
2c037dca73 | ||
|
|
fe2fc0337f | ||
|
|
b3a86d0d8a | ||
|
|
5618be9a71 | ||
|
|
715ae4bf1c | ||
|
|
f44b6bf769 | ||
|
|
e75857c448 | ||
|
|
bc008e2cf3 | ||
|
|
752226208b | ||
|
|
9e2222549e | ||
|
|
b0686b16f7 | ||
|
|
d5b2c41daa |
6
.github/ISSUE_TEMPLATE/issue-warning.md
vendored
6
.github/ISSUE_TEMPLATE/issue-warning.md
vendored
@@ -11,7 +11,11 @@ Issues - это место для обращений к разработчику
|
||||
Discussions - место для обсуждения вопросов между пользователями.
|
||||
|
||||
Все, что выходит за рамки багов и технически грамотных предложений, идей,
|
||||
вопросы типа "как мне это запустить", "что нажать", "что вписать" - будет безжалостно удаляться.
|
||||
вопросы типа "как мне это запустить", "что нажать", "что вписать", "перестало открываться" - будет безжалостно удаляться.
|
||||
Если вы не знаете как пользоваться, для вас что-то сложно, здесь - не место обучению программе или linux и не место для вопросов подобного рода.
|
||||
Поймите, пожалуйста, что zapret - это инструмент, а не готовое решение для пользователя. В его функциях нет кнопки "открыть сайты", поэтому
|
||||
если они перестали открываться - это не issue. Функцию "открыть сайты" дают только сборки - ищите их и все вопросы адресуйте туда.
|
||||
Если вы игнорируете данное требование, вы не достигните своих целей , а только добавите желания удалить ваш issue или при настойчивости забанить.
|
||||
Идите в дискуссии, не захламляйте issues.
|
||||
|
||||
Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions.
|
||||
|
||||
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@@ -26,8 +26,6 @@ jobs:
|
||||
tool: aarch64-unknown-linux-musl
|
||||
- arch: arm
|
||||
tool: arm-unknown-linux-musleabi
|
||||
- arch: arm-old
|
||||
tool: arm-unknown-linux-musleabi
|
||||
# - arch: armhf
|
||||
# tool: arm-unknown-linux-musleabihf
|
||||
# - arch: armv7
|
||||
@@ -77,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
|
||||
@@ -110,7 +108,7 @@ jobs:
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
export STAGING_DIR=$RUNNER_TEMP
|
||||
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]] || [[ "$ARCH" == arm-old ]]; then
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]] ; then
|
||||
# use classic lua
|
||||
wget -qO- https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
@@ -529,7 +527,6 @@ jobs:
|
||||
*-android-x86_64 ) run_dir android-x86_64 ;;
|
||||
*-freebsd-x86_64 ) run_dir freebsd-x86_64 ;;
|
||||
*-linux-arm ) run_dir linux-arm ;;
|
||||
*-linux-arm-old ) run_dir linux-arm-old ;;
|
||||
*-linux-arm64 ) run_dir linux-arm64 ;;
|
||||
*-linux-mips64 ) run_dir linux-mips64 ;;
|
||||
*-linux-mipselsf ) run_dir linux-mipsel ;;
|
||||
@@ -556,6 +553,7 @@ jobs:
|
||||
rm -rf binaries/{android*,freebsd*,win*} \
|
||||
init.d/{openrc,pfsense,runit,s6,systemd,windivert.filter.examples} \
|
||||
nfq2 ip2net mdig docs Makefile
|
||||
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
|
||||
pktws_curl_test_update $1 $2 --payload http_req --lua-desync=$s
|
||||
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
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ pktws_check_http()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local PAYLOAD="--payload http_req" repeats ok
|
||||
local PAYLOAD="--payload=http_req" repeats ok
|
||||
|
||||
[ "$NOTEST_MISC_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for repeats in 1 20 100 260; do
|
||||
# send starting bytes of original payload
|
||||
@@ -20,7 +22,9 @@ pktws_check_https_tls12()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local PAYLOAD="--payload tls_client_hello" repeats ok
|
||||
local PAYLOAD="--payload=tls_client_hello" repeats ok
|
||||
|
||||
[ "$NOTEST_MISC_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for repeats in 1 20 100 260; do
|
||||
# send starting bytes of original payload
|
||||
|
||||
@@ -26,7 +26,7 @@ pktws_check_http()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
local splits_http='method+2 midsld method+2,midsld'
|
||||
local PAYLOAD="--payload http_req"
|
||||
local PAYLOAD="--payload=http_req"
|
||||
|
||||
[ "$NOTEST_MULTI_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
@@ -39,7 +39,7 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,midsld,1220 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload tls_client_hello"
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ pktws_check_http()
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local PAYLOAD="--payload http_req"
|
||||
local PAYLOAD="--payload=http_req"
|
||||
|
||||
local ok pat= split f f2
|
||||
|
||||
@@ -37,7 +37,7 @@ pktws_seqovl_tests_tls()
|
||||
local ok ok_any
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local pat rnd_mod padencap_mod split f f2
|
||||
local PAYLOAD="--payload tls_client_hello"
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
|
||||
pat=${SEQOVL_PATTERN_HTTPS:+seqovl_pat}
|
||||
pat=${pat:-fake_default_tls}
|
||||
|
||||
@@ -5,7 +5,9 @@ pktws_check_http()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local PAYLOAD="--payload http_req" split
|
||||
local PAYLOAD="--payload=http_req" split
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split}
|
||||
@@ -19,7 +21,9 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
local PAYLOAD="--payload tls_client_hello" ok=0 pre="$3" split
|
||||
local PAYLOAD="--payload=tls_client_hello" ok=0 pre="$3" split
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
|
||||
@@ -40,7 +40,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
|
||||
@@ -42,7 +42,7 @@ pktws_check_faked()
|
||||
for split in $splits; do
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload empty --out-range="<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty --out-range="<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
|
||||
@@ -46,7 +46,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -71,7 +71,7 @@ pktws_fake_https_vary_()
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
|
||||
@@ -46,7 +46,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -71,7 +71,7 @@ pktws_fake_https_vary_()
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
|
||||
@@ -29,7 +29,7 @@ pktws_check_hostfake()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ttls attls f fake fooling
|
||||
local ok ttls attls f fooling
|
||||
|
||||
[ "$need_hostfakesplit" = 0 ] && return 0
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ pktws_check_http3()
|
||||
[ "$NOTEST_QUIC" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local repeats fake pos fool
|
||||
local PAYLOAD="--payload quic_initial"
|
||||
local PAYLOAD="--payload=quic_initial"
|
||||
|
||||
if [ -n "$FAKE_QUIC" ]; then
|
||||
fake=fake_quic
|
||||
|
||||
@@ -172,15 +172,23 @@ unique()
|
||||
|
||||
is_linked_to_busybox()
|
||||
{
|
||||
local IFS F P
|
||||
|
||||
local IFS F P BB
|
||||
|
||||
BB="$(which busybox)"
|
||||
|
||||
IFS=:
|
||||
for path in $PATH; do
|
||||
F=$path/$1
|
||||
P="$(readlink $F)"
|
||||
if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi
|
||||
[ "${P%busybox*}" != "$P" ] && return
|
||||
F="$path/$1"
|
||||
if [ -L "$F" ]; then
|
||||
P="$(readlink $F)"
|
||||
if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi
|
||||
[ "${P%busybox*}" != "$P" ] && return
|
||||
elif [ -f "$F" -a -n "$BB" ]; then
|
||||
# possible hardlink
|
||||
[ $(get_dir_inode "$F") = $(get_dir_inode "$BB") ] && return
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
get_dir_inode()
|
||||
{
|
||||
|
||||
@@ -18,6 +18,18 @@ nft_list_table()
|
||||
nft -t list table inet $ZAPRET_NFT_TABLE
|
||||
}
|
||||
|
||||
nft_add_chain()
|
||||
{
|
||||
# $1 - chain
|
||||
# $2 - params
|
||||
nft add chain inet $ZAPRET_NFT_TABLE $1 "{ $2 }"
|
||||
}
|
||||
nft_delete_chain()
|
||||
{
|
||||
# $1 - chain
|
||||
nft delete chain inet $ZAPRET_NFT_TABLE $1
|
||||
}
|
||||
|
||||
nft_create_set()
|
||||
{
|
||||
# $1 - set name
|
||||
@@ -52,7 +64,7 @@ nft_flush_chain()
|
||||
nft_chain_empty()
|
||||
{
|
||||
# $1 - chain name
|
||||
local count=$(nft list chain inet $ZAPRET_NFT_TABLE prerouting | wc -l)
|
||||
local count=$(nft list chain inet $ZAPRET_NFT_TABLE $1 | wc -l)
|
||||
[ "$count" -le 4 ]
|
||||
}
|
||||
nft_rule_exists()
|
||||
@@ -163,10 +175,10 @@ cat << EOF | nft -f -
|
||||
add chain inet $ZAPRET_NFT_TABLE postnat_hook { type filter hook postrouting priority 101; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE postnat_hook
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE prerouting_hook { type filter hook prerouting priority -99; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE prerouting_hook
|
||||
add chain inet $ZAPRET_NFT_TABLE prerouting
|
||||
flush chain inet $ZAPRET_NFT_TABLE prerouting
|
||||
add chain inet $ZAPRET_NFT_TABLE prerouting_hook { type filter hook prerouting priority -99; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE prerouting_hook
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE prenat_hook { type filter hook prerouting priority -101; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE prenat_hook
|
||||
@@ -185,6 +197,7 @@ cat << EOF | nft -f -
|
||||
|
||||
add set inet $ZAPRET_NFT_TABLE wanif { type ifname; }
|
||||
add set inet $ZAPRET_NFT_TABLE wanif6 { type ifname; }
|
||||
add set inet $ZAPRET_NFT_TABLE lanif { type ifname; }
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
flush chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
@@ -230,8 +243,6 @@ cat << EOF | nft -f - 2>/dev/null
|
||||
delete chain inet $ZAPRET_NFT_TABLE flow_offload_always
|
||||
delete chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
EOF
|
||||
# unfortunately this approach breaks udp desync of the connection initiating packet (new, first one)
|
||||
# delete chain inet $ZAPRET_NFT_TABLE predefrag
|
||||
}
|
||||
nft_del_flowtable()
|
||||
{
|
||||
@@ -257,14 +268,17 @@ nft_create_or_update_flowtable()
|
||||
nft_flush_ifsets()
|
||||
{
|
||||
cat << EOF | nft -f - 2>/dev/null
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif6
|
||||
|
||||
for set in wanif wanif6 lanif; do
|
||||
flush set inet $ZAPRET_NFT_TABLE $set
|
||||
done
|
||||
EOF
|
||||
}
|
||||
nft_list_ifsets()
|
||||
{
|
||||
nft list set inet $ZAPRET_NFT_TABLE wanif
|
||||
nft list set inet $ZAPRET_NFT_TABLE wanif6
|
||||
for set in wanif wanif6 lanif; do
|
||||
nft list set inet $ZAPRET_NFT_TABLE $set
|
||||
done
|
||||
nft list flowtable inet $ZAPRET_NFT_TABLE ft 2>/dev/null
|
||||
}
|
||||
|
||||
@@ -402,7 +416,9 @@ nft_fill_ifsets()
|
||||
# calling all in one shot helps not to waste cpu time many times
|
||||
|
||||
script="flush set inet $ZAPRET_NFT_TABLE wanif
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif6"
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif6
|
||||
flush set inet $ZAPRET_NFT_TABLE lanif"
|
||||
nft_script_add_ifset_element lanif "$1"
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || nft_script_add_ifset_element wanif "$2"
|
||||
[ "$DISABLE_IPV6" = "1" ] || nft_script_add_ifset_element wanif6 "$3"
|
||||
|
||||
@@ -133,3 +133,32 @@ v0.7.6
|
||||
* nfqws2: autohostlist reset retransmitter to break long wait
|
||||
* zapret-auto: stadard_failure_detector reset retransmitter to break long wait
|
||||
* nfqws2, init.d, windivert : dht and wg detection changes
|
||||
|
||||
v0.8.0
|
||||
|
||||
* init.d: 50-dht4all NFQWS_OPT_DHT_PKT_OUT
|
||||
* nfqws2: (LUA_COMPAT_VER=4) support 48-bit arithmetics
|
||||
* github actions: remove arm-old target - luajit fail reason revealed
|
||||
* nfqws2: do not treat quic handshake messages as initials
|
||||
* zapret-lib: tls dissector/reconstructor
|
||||
* 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
|
||||
|
||||
0.8.2
|
||||
|
||||
* nfqws2: do not start if NFQWS2_COMPAT_VER unexpected
|
||||
* nfqws2: cache dns response IP addresses if --ipcache-hostname enabled
|
||||
* winws2: remove hardcoded filter for loopback
|
||||
* init.d: ressurect @lanif in nft scheme
|
||||
* init.d: fix broken @wanif/@wanif6 fill in sysv nft scheme
|
||||
* init.d: 80-dns-intercept
|
||||
* winws2: --wf-filter-loopback
|
||||
* blockcheck2: NOTEST_MISC_HTTP[S], NOTEST_SYNDATA_HTTP[S]
|
||||
|
||||
809
docs/manual.md
809
docs/manual.md
File diff suppressed because it is too large
Load Diff
@@ -36,12 +36,12 @@ zapret2 является дальнейшим развитием проекта
|
||||
или хотя бы область , в которой их можно искать, плюс владеющий базовыми навыками программирования.
|
||||
|
||||
*nfqws2* оставляет в себе практически тот же функционал - распознавание протоколов, реассемблинг, дешифровка, управление профилями, хостлисты, ipset-ы, базовая фильтрация.
|
||||
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования LUA.
|
||||
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования Lua.
|
||||
|
||||
LUA код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
|
||||
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
|
||||
Имеется библиотека хелперов, написанных на LUA, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
и с большей гибкостью.
|
||||
|
||||
Вы всегда сможете взять и дописать что-то свое. В этом и есть смысл, чтобы борьбой с DPI смог заняться любой, кто разбирается в пакетах.
|
||||
@@ -53,7 +53,7 @@ zapret2 - инструмент для таких энтузиастов. Но э
|
||||
## С чего начать
|
||||
|
||||
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть LUA код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
|
||||
|
||||
### Механика обработки трафика
|
||||
@@ -102,11 +102,11 @@ nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-antidpi.
|
||||
--payload=tls_client_hello,http_req --lua-desync=multisplit:pos=1:seqovl=5:seqovl_pattern=0x1603030000
|
||||
```
|
||||
|
||||
Данный пример предполагает, что в той же директории находятся файлы `zapret-lib.lua` - библиотека хелперов на LUA и `zapret-antidpi.lua` - библиотека базовых стратегий.
|
||||
`--lua-init` может содержать LUA код в виде строки. Так удобно писать простой код, например присвоить константу переменной, чтобы не создавать файлы ради этой мелочи.
|
||||
Данный пример предполагает, что в той же директории находятся файлы `zapret-lib.lua` - библиотека хелперов на Lua и `zapret-antidpi.lua` - библиотека базовых стратегий.
|
||||
`--lua-init` может содержать Lua код в виде строки. Так удобно писать простой код, например присвоить константу переменной, чтобы не создавать файлы ради этой мелочи.
|
||||
Либо подцепляется файл, если значение параметра начинается с `@`. Код из `--lua-init` выполняется 1 раз при старте.
|
||||
|
||||
Далее указаны параметры `--lua-desync`. Они содержат имя LUA функции, вызываемой при обработке каждого пакета, проходящего через профиль мультистратегии.
|
||||
Далее указаны параметры `--lua-desync`. Они содержат имя Lua функции, вызываемой при обработке каждого пакета, проходящего через профиль мультистратегии.
|
||||
После двоеточия и через двоеточия следуют параметры для данной функции в формате `param[=value]`. В примере реализована стратегия
|
||||
|
||||
```
|
||||
@@ -122,7 +122,7 @@ nfqws --qnum 200 --debug \
|
||||
Тип пейлоада - тип данных, содержащихся в пакете или группе пакетов. Например, протокол соединения может быть tls, а пейлоады - tls_client_hello, tls_server_hello, unknown.
|
||||
|
||||
Другое важное отличие - отсутствие жестко определенных фаз десинхронизации. То, что вы раньше писали как `fake,multisplit` реализуется двумя
|
||||
последовательно вызываемыми LUA функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
|
||||
последовательно вызываемыми Lua функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
|
||||
Может даже несколько раз вызываться одна и так же функция с разными параметрами. Так, например, можно послать несколько фейков, причем с разными фулингами.
|
||||
Конкретный вызов `--lua-desync` функции называется инстансом. Инстанс - это связка имени функции, номера вызова внутри профиля и номера самого профиля.
|
||||
Это похоже на одну программу, которую можно запустить много раз с разными параметрами.
|
||||
@@ -130,11 +130,11 @@ nfqws --qnum 200 --debug \
|
||||
Другое немаловажное отличие - поддержка автоматической tcp сегментации средствами `zapret-lib.lua`. Вам больше не нужно думать о размерах отсылаемых tcp пакетов.
|
||||
По каждому соединению отслеживается MSS. Если пакет не влезает в MSS, выполняется сегментация.
|
||||
Например, это может случиться при отправке tls фейка с kyber. Или если вы режете kyber tls так, что одна из частей получается размером 1600 байт,
|
||||
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. Функция LUA `rawsend_dissect_segmented` отправит
|
||||
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. Функция Lua `rawsend_dissect_segmented` отправит
|
||||
несколько tcp сегментов с начальным sequence -10000 общим размером 10000 байт, в последнем из которых будет кусок оригинального сообщения.
|
||||
|
||||
В *nfqws2* нет жестко зашитых параметров кастомных фейков типа `--dpi-desync-fake-tls`, `dpi-desync-fake-http` и тд.
|
||||
Вместо них есть блобы. Блоб (blob) - это переменная LUA типа *string*, содержащая блок двоичных данных произвольной длины. От 1 байта до гигабайтов.
|
||||
Вместо них есть блобы. Блоб (blob) - это переменная Lua типа *string*, содержащая блок двоичных данных произвольной длины. От 1 байта до гигабайтов.
|
||||
*nfqws2* автоматически инициализирует блобы со стандартными фейками tls, http, quic, как это и было в *nfqws1*.
|
||||
Блобы могут быть заданы как hex-строка прямо в параметре desync функции, либо пред-загружены при старте с помощью параметра `--blob=name:0xHEX|[+ofs]@filename`
|
||||
|
||||
@@ -169,13 +169,13 @@ range задается как `mX-mY`, `mX<mY`, `-mY`, `<mY`, `mX-`.
|
||||
Что будет, если вы не напишите фильтр `--payload` для fake или multisplit ? В *nfqws1* без `--dpi-desync-any-protocol` они работали только по известным пейлоадам.
|
||||
В *nfqws2* "any protocol" - режим по умолчанию. Однако, функции из библиотеки `zapret-antidpi.lua` написаны так, что по умолчанию работают только по известным пейлоадам
|
||||
и не работают по пустым пакетам или unknown - точно так же, как это было в *nfqws1*.
|
||||
Но лучше все-же писать фильтры `--payload`, потому что они работают на уровне C кода, который выполняется существенно быстрее, чем LUA.
|
||||
Но лучше все-же писать фильтры `--payload`, потому что они работают на уровне C кода, который выполняется существенно быстрее, чем Lua.
|
||||
|
||||
Диссект пакета проходит поочередно по всем `--lua-desync` инстансам профиля, для которых не выполняется условие отсечения (cutoff).
|
||||
Отсечение может быть по range, payload или добровольное отсечение. Последний вариант - когда инстанс сам отказывается обрабатывать пакеты
|
||||
по входящему, исходящему или обоим направлениям. Например, задача стратегии wsize - отреагировать только на пакет с tcp флагами SYN,ACK. После этого он не нужен, в коде вызывается функция отсечения.
|
||||
Это сделано для экономии ресурсов процессора.
|
||||
Если все инстансы в профиле точно никогда больше не будут вызваны по соединению + направлению - вошли в превышение верхней границы range или выполнили добровольный cutoff, то движок LUA не вызывается вообще.
|
||||
Если все инстансы в профиле точно никогда больше не будут вызваны по соединению + направлению - вошли в превышение верхней границы range или выполнили добровольный cutoff, то движок Lua не вызывается вообще.
|
||||
|
||||
От инстанса к инстансу содержимое диссекта может ими меняться. Следующий инстанс видит изменения предыдущего.
|
||||
Каждый инстанс выносит свой вердикт - что делать с текущим диссектом. VERDICT_PASS - означает отправить как есть,
|
||||
@@ -301,19 +301,21 @@ nfqws2 --lua-desync=send:ipfrag:ipfrag_pos_udp=8 --lua-desync=drop
|
||||
Но это решаемо. А что не решаемо - это перехват вторых частей kyber tls hello. Их невозможно опознать без связи с предыдущими фрагментами. Поэтому перехватывается весь порт.
|
||||
Для HTTP вопрос решаемый, поскольку там нет реассемблирования запросов, но http сейчас стал настолько редким, что и смысла нет заморачиваться.
|
||||
|
||||
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`. Зачем ? В основном для сокращения вызовов LUA кода, который заведомо медленнее C кода.
|
||||
Если пакет не попадет в профили с LUA - ни о каком вызове кода LUA речи быть не может. Если пакет попал в профиль с LUA, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все LUA инстансы входят в состояние instance cutoff, соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов LUA не будет вообще. Не просто вызовов, а даже обращения к движку LUA с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
|
||||
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`. Зачем ? В основном для сокращения вызовов Lua кода, который заведомо медленнее C кода.
|
||||
Если пакет не попадет в профили с Lua - ни о каком вызове кода Lua речи быть не может. Если пакет попал в профиль с Lua, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все Lua инстансы входят в состояние instance cutoff, соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов Lua не будет вообще. Не просто вызовов, а даже обращения к движку Lua с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
|
||||
|
||||
Почему именно `-d10` ? Чтобы хватило для отработки большинства вариантов стратегий, учитывая возможные ретрансмиссии и плохую связь. В winws2 по умолчанию включен параметр `--wf-tcp-empty=0`. Он блокирует перехват пустых пакетов с ACK, что позволяет примерно в 2 раза сэкономить на процессоре при интенсивных скачиваниях. Пустые ACK в большинстве стратегий не нужны. Но это же и ломает счетчик "n" - он не будет показывать реальное количество пакетов по соединению. Счетчик "d" работать будет как надо.
|
||||
|
||||
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы LUA даже в пределах первых 10 пакетов с данными.
|
||||
Почему нет "-d10" на udp ? Потому что используется windivert фильтр на пейлоад. Счетчики будут считать не реальное количество пакетов в потоке, а количество перехваченных с отфильтрованными пейлоадами. Причем если интервал между ними будет более 1 минуты, то счет будет начинаться заново, поскольку таймаут udp по умолчанию - 60 сек. После таймаута запись conntrack будет удалена. Следующий пакет пойдет как новый поток.
|
||||
|
||||
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы Lua даже в пределах первых 10 пакетов с данными.
|
||||
С другой стороны, даже при совпадении протокола соединения (`--filter-l7`) может пробежать не интересующий нас пейлоад.
|
||||
По умолчанию многие функции из `zapret-antidpi.lua` реагируют только на известные типы пейлоада, но не на конкретные, а на любые известные.
|
||||
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола http будет отправлен блок данных с tls или фраза, похожая на сообщение из xmpp, то тип пейлоада выскочит tls_client_hello или xmpp_stream, например. Лучше от этого сразу уберечься. Тем более что в других видах протоколов - xmpp, например, -
|
||||
пейлоады могут проскакивать нескольких типов вполне ожидаемо. Но работать надо не по всем.
|
||||
|
||||
В фейке для TLS по умолчанию - fake_default_tls - однократно при старте меняется SNI с "www.microsoft.com" на случайный и рандомизируется поле "random" в TLS handshake.
|
||||
Это делается простой строчкой LUA кода. Больше нет никаких специальных параметров *nfqws2* для модификации пейлоадов.
|
||||
Это делается простой строчкой Lua кода. Больше нет никаких специальных параметров *nfqws2* для модификации пейлоадов.
|
||||
В профиле для youtube на лету меняется SNI на "www.google.com", копируется поле TLS "session id" с обрабатываемого в данный момент TLS handshake.
|
||||
|
||||
```
|
||||
@@ -359,17 +361,14 @@ start "zapret: http,https,quic" /min "%~dp0winws2.exe" ^
|
||||
--lua-desync=multidisorder:pos=midsld ^
|
||||
--new ^
|
||||
--filter-udp=443 --filter-l7=quic --hostlist="%~dp0files\list-youtube.txt" ^
|
||||
--out-range=-d10 ^
|
||||
--payload=quic_initial ^
|
||||
--lua-desync=fake:blob=quic_google:repeats=11 ^
|
||||
--new ^
|
||||
--filter-udp=443 --filter-l7=quic ^
|
||||
--out-range=-d10 ^
|
||||
--payload=quic_initial ^
|
||||
--lua-desync=fake:blob=fake_default_quic:repeats=11 ^
|
||||
--new ^
|
||||
--filter-l7=wireguard,stun,discord ^
|
||||
--out-range=-d10 ^
|
||||
--payload=wireguard_initiation,wireguard_cookie,stun,discord_ip_discovery ^
|
||||
--lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2
|
||||
```
|
||||
@@ -381,9 +380,9 @@ start "zapret: http,https,quic" /min "%~dp0winws2.exe" ^
|
||||
Надо послать исходный запрос с известным пейлоадом с seqovl случайного размера от 5 до 10 символов со случайным содержимым, состоящим из букв от ‘a’ до ‘z’.
|
||||
Здесь раскрывается не декларативный характер стратегий, а алгоритмический. Стратегия - это программа, и пишите ее вы на языке программирования.
|
||||
Для облегчения простых или стандартных действий есть готовые средства, так что далеко не всегда надо писать свою функцию.
|
||||
Частенько можно обойтись простенькими кусками LUA кода в дополнение к имеющимся.
|
||||
Частенько можно обойтись простенькими кусками Lua кода в дополнение к имеющимся.
|
||||
|
||||
Здесь используется функция `luaexec`, предназначенная для динамического выполнения LUA кода в процессе обработки текущего диссекта.
|
||||
Здесь используется функция `luaexec`, предназначенная для динамического выполнения Lua кода в процессе обработки текущего диссекта.
|
||||
Она инициализирует требуемый blob, записывая его в таблицу desync, которая передается от инстанса к инстансу.
|
||||
Следующий инстанс `tcpseg` использует `rnd` как blob - источник seqovl паттерна.
|
||||
|
||||
@@ -414,4 +413,4 @@ nfqws2 \
|
||||
### Очень важный совет
|
||||
|
||||
Научитесь пользоваться `--debug` логом. Без него будет очень сложно понять *nfqws2* на начальном этапе и приспособиться к новой схеме.
|
||||
Ошибок будет много. Особенно, когда вы начнете писать свой LUA код. Их надо читать.
|
||||
Ошибок будет много. Особенно, когда вы начнете писать свой Lua код. Их надо читать.
|
||||
|
||||
BIN
files/fake/bgp_open.bin
Normal file
BIN
files/fake/bgp_open.bin
Normal file
Binary file not shown.
BIN
files/fake/bitcoin.bin
Normal file
BIN
files/fake/bitcoin.bin
Normal file
Binary file not shown.
BIN
files/fake/dtls_serverhello.bin
Normal file
BIN
files/fake/dtls_serverhello.bin
Normal file
Binary file not shown.
BIN
files/fake/ntp4.bin
Normal file
BIN
files/fake/ntp4.bin
Normal file
Binary file not shown.
4
files/fake/rtsp_options.bin
Normal file
4
files/fake/rtsp_options.bin
Normal file
@@ -0,0 +1,4 @@
|
||||
OPTIONS rtsp://10.2.2.2:8554/ RTSP/1.0
|
||||
CSeq: 2
|
||||
User-Agent: LibVLC/3.0.16 (LIVE555 Streaming Media v2016.11.28)
|
||||
|
||||
1
files/fake/smtp_ehlo.bin
Normal file
1
files/fake/smtp_ehlo.bin
Normal file
@@ -0,0 +1 @@
|
||||
EHLO delta.peach.mil
|
||||
BIN
files/fake/snmp_get_next_request.bin
Normal file
BIN
files/fake/snmp_get_next_request.bin
Normal file
Binary file not shown.
BIN
files/fake/tls_alert.bin
Normal file
BIN
files/fake/tls_alert.bin
Normal file
Binary file not shown.
BIN
files/fake/tls_clienthello_google_com_tlsrec.bin
Normal file
BIN
files/fake/tls_clienthello_google_com_tlsrec.bin
Normal file
Binary file not shown.
BIN
files/fake/tls_serverhello_google_com_tls13.bin
Normal file
BIN
files/fake/tls_serverhello_google_com_tls13.bin
Normal file
Binary file not shown.
@@ -3,6 +3,8 @@
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---payload dht --lua-desync=dht_dn}"
|
||||
# set it to "keepalive" to fool all packets, not just the first. or set number of packets to be fooled.
|
||||
NFQWS_OPT_DHT_PKT_OUT=${NFQWS_OPT_DHT_PKT_OUT:-20}
|
||||
|
||||
alloc_dnum DNUM_DHT4ALL
|
||||
alloc_qnum QNUM_DHT4ALL
|
||||
@@ -19,7 +21,7 @@ zapret_custom_firewall()
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f uf4 uf6
|
||||
local first_packet_only="$ipt_connbytes 1:1"
|
||||
local first_packet_only=$(ipt_first_packets $NFQWS_OPT_DHT_PKT_OUT)
|
||||
|
||||
f='-p udp -m u32 --u32'
|
||||
uf4='0>>22&0x3C@4>>16=13:0xFFFF&&0>>22&0x3C@8>>16=0x6431:0x6432'
|
||||
@@ -31,7 +33,7 @@ zapret_custom_firewall_nft()
|
||||
# stop logic is not required
|
||||
|
||||
local f
|
||||
local first_packet_only="$nft_connbytes 1"
|
||||
local first_packet_only=$(nft_first_packets $NFQWS_OPT_DHT_PKT_OUT)
|
||||
|
||||
f="udp length ge 13 meta l4proto udp @ih,0,16 0x6431-0x6432"
|
||||
nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# this custom script runs desync to all wireguard handshake initiation packets
|
||||
# this custom script runs desync to all wireguard handshake initiation, response and cookie packets
|
||||
# NOTE: this works for original wireguard and may not work for 3rd party implementations such as xray
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation,wireguard_response,wireguard_cookie --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_WG4ALL
|
||||
alloc_qnum QNUM_WG4ALL
|
||||
@@ -21,7 +21,9 @@ zapret_custom_firewall()
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f='-p udp -m u32 --u32'
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x9c&&0>>22&0x3C@8=0x01000000" "$f 44>>16=0x9c&&48=0x01000000" $QNUM_WG4ALL
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=156&&0>>22&0x3C@8=0x01000000" "$f 44>>16=156&&48=0x01000000" $QNUM_WG4ALL
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=100&&0>>22&0x3C@8=0x02000000" "$f 44>>16=100&&48=0x02000000" $QNUM_WG4ALL
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=72&&0>>22&0x3C@8=0x03000000" "$f 44>>16=72&&48=0x03000000" $QNUM_WG4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
@@ -29,4 +31,8 @@ zapret_custom_firewall_nft()
|
||||
|
||||
local f="udp length 156 @ih,0,32 0x01000000"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
|
||||
local f="udp length 100 @ih,0,32 0x02000000"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
|
||||
local f="udp length 72 @ih,0,32 0x03000000"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
|
||||
}
|
||||
|
||||
59
init.d/custom.d.examples.linux/80-dns-intercept
Normal file
59
init.d/custom.d.examples.linux/80-dns-intercept
Normal file
@@ -0,0 +1,59 @@
|
||||
# this custom script feeds dns response data to main nfqws2 instance
|
||||
# DISABLE_IPV{4,6} filters are not used intentionally. despite of not having wan ipv6 it's possible to query LAN DNS server over local ipv6
|
||||
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
local filt="-p udp --sport 53"
|
||||
local jump="-j NFQUEUE --queue-num $QNUM --queue-bypass"
|
||||
local rule chain lan lanifs
|
||||
|
||||
get_lanif lanifs
|
||||
|
||||
# router
|
||||
for lan in $lanifs; do
|
||||
rule="-o $lan $filt $jump"
|
||||
ipt_print_op $1 "$rule" "nfqws FORWARD (qnum $QNUM)"
|
||||
ipt_add_del $1 FORWARD -t mangle $rule
|
||||
ipt_print_op $1 "$rule" "nfqws FORWARD (qnum $QNUM)" 6
|
||||
ipt6_add_del $1 FORWARD -t mangle $rule
|
||||
done
|
||||
# dns client server
|
||||
for chain in INPUT OUTPUT ; do
|
||||
rule="$filt $jump"
|
||||
ipt_print_op $1 "$rule" "nfqws $chain (qnum $QNUM)"
|
||||
ipt_add_del $1 $chain -t mangle $rule
|
||||
ipt_print_op $1 "$rule" "nfqws $chain (qnum $QNUM)" 6
|
||||
ipt6_add_del $1 $chain -t mangle $rule
|
||||
done
|
||||
}
|
||||
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local rule="udp sport 53 queue num $QNUM bypass"
|
||||
|
||||
# dns client
|
||||
nft_print_op "oifname @lanif $rule" "nfqws forward (qnum $QNUM)" "4+6"
|
||||
nft_add_chain forward_dns_feed "type filter hook forward priority mangle;"
|
||||
nft_add_rule forward_dns_feed oifname @lanif $rule
|
||||
|
||||
# router
|
||||
nft_print_op "$rule" "nfqws input (qnum $QNUM)" "4+6"
|
||||
nft_add_chain input_dns_feed "type filter hook input priority mangle;"
|
||||
nft_add_rule input_dns_feed $rule
|
||||
|
||||
# dns server
|
||||
nft_print_op "$rule" "nfqws output (qnum $QNUM)" "4+6"
|
||||
nft_add_chain output_dns_feed "type filter hook output priority mangle;"
|
||||
nft_add_rule output_dns_feed $rule
|
||||
}
|
||||
|
||||
zapret_custom_firewall_nft_flush()
|
||||
{
|
||||
local chain
|
||||
for chain in forward_dns_feed input_dns_feed output_dns_feed; do
|
||||
nft_delete_chain $chain 2>/dev/null
|
||||
done
|
||||
}
|
||||
@@ -62,6 +62,20 @@ network_find_wanX_devices()
|
||||
call_for_multiple_items network_get_device $2 "$ifaces"
|
||||
}
|
||||
|
||||
get_wanif46()
|
||||
{
|
||||
# $1 - 4/6
|
||||
# $2 - var to receive interface list
|
||||
local ifaces
|
||||
network_find_wan${1}_all ifaces
|
||||
call_for_multiple_items network_get_device $2 "$ifaces"
|
||||
}
|
||||
get_lanif()
|
||||
{
|
||||
# $1 - var to receive interface list
|
||||
call_for_multiple_items network_get_device $1 "$OPENWRT_LAN"
|
||||
}
|
||||
|
||||
|
||||
fw_nfqws_prepost_x()
|
||||
{
|
||||
@@ -71,10 +85,8 @@ fw_nfqws_prepost_x()
|
||||
# $4 - 4/6
|
||||
# $5 - post/pre
|
||||
|
||||
local ifaces DWAN
|
||||
network_find_wan${4}_all ifaces
|
||||
call_for_multiple_items network_get_device DWAN "$ifaces"
|
||||
|
||||
local DWAN
|
||||
get_wanif46 $4 DWAN
|
||||
[ -n "$DWAN" ] && _fw_nfqws_${5}${4} $1 "$2" $3 "$(unique $DWAN)"
|
||||
}
|
||||
fw_nfqws_post4()
|
||||
|
||||
@@ -75,6 +75,26 @@ NFQWS2="${NFQWS2:-$ZAPRET_BASE/nfq2/nfqws2}"
|
||||
LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua --lua-init=@$ZAPRET_BASE/lua/zapret-auto.lua"
|
||||
NFQWS2_OPT_BASE="$USEROPT --fwmark=$DESYNC_MARK $LUAOPT"
|
||||
|
||||
get_wanif46()
|
||||
{
|
||||
# $1 - 4/6
|
||||
# $2 - var to receive interface list
|
||||
case $1 in
|
||||
6)
|
||||
eval $2="\${IFACE_WAN6:-$IFACE_WAN}"
|
||||
;;
|
||||
4)
|
||||
eval $2="\$IFACE_WAN"
|
||||
;;
|
||||
*)
|
||||
eval $2=
|
||||
esac
|
||||
}
|
||||
get_lanif()
|
||||
{
|
||||
# $1 - var to receive interface list
|
||||
eval $1="\$IFACE_LAN"
|
||||
}
|
||||
|
||||
fw_nfqws_post4()
|
||||
{
|
||||
@@ -119,7 +139,7 @@ nft_wanif6_filter_present()
|
||||
}
|
||||
nft_fill_ifsets_overload()
|
||||
{
|
||||
nft_fill_ifsets "$IFACE_WAN" "${IFACE_WAN6:-$IFACE_WAN}" "$IFACE_LAN"
|
||||
nft_fill_ifsets "$IFACE_LAN" "$IFACE_WAN" "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ select_test_method()
|
||||
elif exists zsh && [ "$UNAME" != CYGWIN ] ; then
|
||||
TEST=zsh
|
||||
elif [ "$UNAME" != CYGWIN ]; then
|
||||
if exists hexdump and exists dd; then
|
||||
if exists hexdump && exists dd; then
|
||||
# macos does not use ELF
|
||||
TEST=elf
|
||||
ELF=
|
||||
|
||||
@@ -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
|
||||
@@ -287,6 +321,39 @@ function wssize(ctx, desync)
|
||||
return verdict
|
||||
end
|
||||
|
||||
-- nfqws1 : not available
|
||||
-- standard args : direction
|
||||
-- arg: blob - blob name to store cloned tls client hello (stored in desync, not global)
|
||||
-- arg: fallback - copy this blob if could not clone
|
||||
-- arg: sni_snt - server name type value in existing names
|
||||
-- arg: sni_snt_new - server name type value for new names
|
||||
-- arg: sni_del_ext - delete sni extension
|
||||
-- arg: sni_del - delete all names
|
||||
-- arg: sni_first - add name to the beginning
|
||||
-- arg: sni_last - add name to the end
|
||||
function tls_client_hello_clone(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
if direction_check(desync) then
|
||||
if not desync.arg.blob then
|
||||
error("tls_client_hello_clone: 'blob' arg required")
|
||||
end
|
||||
if desync.l7payload=="tls_client_hello" then
|
||||
desync[desync.arg.blob] = tls_client_hello_mod(desync.reasm_data or desync.dis.payload, desync.arg)
|
||||
if desync[desync.arg.blob] then
|
||||
DLOG("tls_client_hello_clone: cloned to desync."..desync.arg.blob)
|
||||
end
|
||||
end
|
||||
if not desync[desync.arg.blob] and desync.arg.fallback then
|
||||
DLOG("tls_client_hello_clone: desync."..desync.arg.blob.."="..desync.arg.fallback)
|
||||
desync[desync.arg.blob] = blob(desync, desync.arg.fallback)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=syndata"
|
||||
-- standard args : fooling, rawsend, reconstruct, ipfrag
|
||||
-- arg : blob=<blob> - fake payload. must fit to single packet. no segmentation possible. default - 16 zero bytes.
|
||||
@@ -340,6 +407,7 @@ end
|
||||
-- nfqws1 : "--dpi-desync=fake"
|
||||
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
|
||||
-- arg : blob=<blob> - fake payload
|
||||
-- arg : optional - skip if blob is absent
|
||||
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>,dupsid,padencap . sni=%var is supported
|
||||
function fake(ctx, desync)
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -349,6 +417,10 @@ function fake(ctx, desync)
|
||||
if not desync.arg.blob then
|
||||
error("fake: 'blob' arg required")
|
||||
end
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("fake: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local fake_payload = blob(desync, desync.arg.blob)
|
||||
if desync.reasm_data and desync.arg.tls_mod then
|
||||
fake_payload = tls_mod_shim(desync, fake_payload, desync.arg.tls_mod, desync.reasm_data)
|
||||
@@ -368,6 +440,7 @@ end
|
||||
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
|
||||
-- arg : seqovl_pattern=<blob> . override pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function multisplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
@@ -375,7 +448,10 @@ function multisplit(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("multisplit: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -393,7 +469,14 @@ function multisplit(ctx, desync)
|
||||
local seqovl=0
|
||||
if i==0 and desync.arg.seqovl and tonumber(desync.arg.seqovl)>0 then
|
||||
seqovl = tonumber(desync.arg.seqovl)
|
||||
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
local pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("multisplit: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
if b_debug then DLOG("multisplit: sending part "..(i+1).." "..(pos_start-1).."-"..(pos_end-1).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
|
||||
@@ -445,7 +528,14 @@ function multidisorder_send(desync, data, seqovl, pos)
|
||||
DLOG("multidisorder: seqovl cancelled because seqovl "..(seqovl-1).." is not less than the first split pos "..(pos[1]-1))
|
||||
else
|
||||
ovl = seqovl - 1
|
||||
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
local pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("multidisorder: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,ovl)..part
|
||||
end
|
||||
end
|
||||
@@ -464,6 +554,7 @@ end
|
||||
-- arg : seqovl=N . decrease seq number of the second segment in the original order by N and fill N bytes with pattern (default - all zero). N must be less than the first split pos.
|
||||
-- arg : seqovl_pattern=<blob> . override pattern
|
||||
-- arg : blob=<blob> - use this data instead of reasm_data
|
||||
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function multidisorder(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
@@ -471,7 +562,10 @@ function multidisorder(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("multidisorder: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -512,6 +606,7 @@ end
|
||||
-- arg : pos=<postmarker list> . position marker list. example : "1,host,midsld+1,-10"
|
||||
-- arg : seqovl=N . decrease seq number of the second segment in the original order by N and fill N bytes with pattern (default - all zero). N must be less than the first split pos.
|
||||
-- arg : seqovl_pattern=<blob> . override pattern
|
||||
-- arg : optional - use zero pattern if seqovl_pattern blob is absent
|
||||
function multidisorder_legacy(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
@@ -567,6 +662,7 @@ end
|
||||
-- arg : nofake1, nofake2 - do not send individual fakes
|
||||
-- arg : disorder_after=<posmarker> - send after_host part in 2 disordered segments. if posmarker is empty string use marker "-1"
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : optional - skip if blob is absent
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function hostfakesplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
@@ -574,7 +670,10 @@ function hostfakesplit(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("hostfakesplit: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -680,6 +779,7 @@ end
|
||||
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
|
||||
-- arg : seqovl_pattern=<blob> . override seqovl pattern
|
||||
-- arg : blob=<blob> - use this data instead of reasm_data
|
||||
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function fakedsplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
@@ -687,7 +787,10 @@ function fakedsplit(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("fakedsplit: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -719,7 +822,14 @@ function fakedsplit(ctx, desync)
|
||||
local seqovl=0
|
||||
if desync.arg.seqovl and tonumber(desync.arg.seqovl)>0 then
|
||||
seqovl = tonumber(desync.arg.seqovl)
|
||||
pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("fakedsplit: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
if b_debug then DLOG("fakedsplit: sending real part 1 : 0-"..(pos-2).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
|
||||
@@ -773,6 +883,7 @@ end
|
||||
-- arg : seqovl=N . decrease seq number of the second segment by N and fill N bytes with pattern (default - all zero). N must be less than the split pos.
|
||||
-- arg : seqovl_pattern=<blob> . override seqovl pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function fakeddisorder(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
@@ -780,7 +891,10 @@ function fakeddisorder(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("fakeddisorder: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -817,7 +931,14 @@ function fakeddisorder(ctx, desync)
|
||||
DLOG("fakeddisorder: seqovl cancelled because seqovl "..seqovl.." is not less than the split pos "..(pos-1))
|
||||
seqovl = 0
|
||||
else
|
||||
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
local pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("fakeddisorder: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
else
|
||||
@@ -874,6 +995,7 @@ end
|
||||
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
|
||||
-- arg : seqovl_pattern=<blob> . override pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
|
||||
function tcpseg(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
@@ -883,7 +1005,10 @@ function tcpseg(ctx, desync)
|
||||
if not desync.arg.pos then
|
||||
error("tcpseg: no pos specified")
|
||||
end
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("tcpseg: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -897,7 +1022,14 @@ function tcpseg(ctx, desync)
|
||||
local seqovl=0
|
||||
if desync.arg.seqovl and tonumber(desync.arg.seqovl)>0 then
|
||||
seqovl = tonumber(desync.arg.seqovl)
|
||||
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
local pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("tcpseg: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
if b_debug then DLOG("tcpseg: sending "..(pos[1]-1).."-"..(pos[2]-1).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
|
||||
@@ -953,7 +1085,7 @@ end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=tamper" for dht proto
|
||||
-- standard args : direction
|
||||
-- arg : dn=N - message starts from "dN". 2 by default
|
||||
-- arg : dn=N - message starts from "dN". 3 by default
|
||||
function dht_dn(ctx, desync)
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
@@ -961,7 +1093,7 @@ function dht_dn(ctx, desync)
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
if desync.l7payload=="dht" and direction_check(desync) then
|
||||
local N = tonumber(desync.arg.dn) or 2
|
||||
local N = tonumber(desync.arg.dn) or 3
|
||||
-- remove "d1" from the start not breaking bencode
|
||||
local prefix = "d"..tostring(N)..":"..string.rep("0",N).."1:x"
|
||||
desync.dis.payload = prefix..string.sub(desync.dis.payload,2)
|
||||
|
||||
1168
lua/zapret-lib.lua
1168
lua/zapret-lib.lua
File diff suppressed because it is too large
Load Diff
@@ -251,12 +251,12 @@ function test_aes_ctr()
|
||||
end
|
||||
|
||||
function test_ub()
|
||||
for k,f in pairs({{u8,bu8,0xFF,8}, {u16,bu16,0xFFFF,16}, {u24,bu24,0xFFFFFF,24}, {u32,bu32,0xFFFFFFFF,32}}) do
|
||||
for k,f in pairs({{u8,bu8,0xFF,8}, {u16,bu16,0xFFFF,16}, {u24,bu24,0xFFFFFF,24}, {u32,bu32,0xFFFFFFFF,32}, {u48,bu48,0xFFFFFFFFFFFF,48}}) do
|
||||
local v = math.random(0,f[3])
|
||||
local pos = math.random(1,20)
|
||||
local s = brandom(pos-1)..f[2](v)..brandom(20)
|
||||
local v2 = f[1](s,pos)
|
||||
print("u"..tostring(f[4]).." pos="..tostring(pos).." "..tostring(v).." "..tostring(v2))
|
||||
print(string.format("u%u pos=%u %016X %016X",f[4],pos,v,v2))
|
||||
test_assert(v==v2)
|
||||
end
|
||||
end
|
||||
@@ -264,38 +264,76 @@ end
|
||||
function test_bit()
|
||||
local v, v2, v3, v4, b1, b2, pow
|
||||
|
||||
v = math.random(0,0xFFFFFFFF)
|
||||
b1 = math.random(1,16)
|
||||
for i=1,100 do
|
||||
v = math.random(0,0xFFFFFFFFFFFF)
|
||||
b1 = math.random(1,16)
|
||||
|
||||
v2 = bitrshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = divint(v, pow)
|
||||
print(string.format("rshift(0x%X,%u) = 0x%X 0x%X/%u = 0x%X", v,b1,v2, v,pow,v3))
|
||||
v2 = bitrshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = divint(v, pow)
|
||||
print(string.format("rshift(0x%X,%u) = 0x%X 0x%X/%u = 0x%X", v,b1,v2, v,pow,v3))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v = math.random(0,0xFFFFFFFFF)
|
||||
b1 = math.random(1,12)
|
||||
v2 = bitlshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = (v * pow) % 0x1000000000000
|
||||
print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u %% 0x100000000000 = 0x%X", v,b1,v2, v,pow,v3))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v2 = math.random(0,0xFFFFFFFFFFFF)
|
||||
v3 = bitxor(v, v2)
|
||||
v4 = bitor(v, v2) - bitand(v, v2)
|
||||
print(string.format("xor(0x%X,0x%X) = %X or/and/minus = %X", v, v2, v3, v4))
|
||||
test_assert(v3==v4)
|
||||
|
||||
b1 = math.random(1,31)
|
||||
b2 = b1 + math.random(1,16)
|
||||
v2 = bitget(v, b1, b2)
|
||||
pow = 2^(b2-b1+1) - 1
|
||||
v3 = bitand(bitrshift(v,b1), pow)
|
||||
print(string.format("bitget(0x%X,%u,%u) = 0x%X bitand/bitrshift/pow = 0x%X", v, b1, b2, v2, v3))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v4 = math.random(0,pow)
|
||||
v2 = bitset(v, b1, b2, v4)
|
||||
v3 = bitor(bitlshift(v4, b1), bitand(v, bitnot(bitlshift(pow, b1))))
|
||||
print(string.format("bitset(0x%X,%u,%u,0x%X) = 0x%X bitand/bitnot/bitlshift/pow = 0x%X", v, b1, b2, v4, v2, v3))
|
||||
test_assert(v2==v3)
|
||||
end
|
||||
end
|
||||
|
||||
function test_swap()
|
||||
local v1, v2, v3
|
||||
|
||||
v1 = math.random(0,0xFFFF)
|
||||
v2 = swap16(v1)
|
||||
v3 = divint(v1,0x100) + v1%0x100*0x100
|
||||
print("swap16: "..(v2==v3 and "OK" or "FAIL"))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v2 = bitlshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = (v * pow) % 0x100000000
|
||||
print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u %% 0x10000000 = 0x%X", v,b1,v2, v,pow,v3))
|
||||
v1 = math.random(0,0xFFFFFF)
|
||||
v2 = swap24(v1)
|
||||
v3 = divint(v1,0x10000) + divint(v1,0x100)%0x100*0x100 + v1%0x100*0x10000
|
||||
print("swap24: "..(v2==v3 and "OK" or "FAIL"))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v2 = math.random(0,0xFFFFFFFF)
|
||||
v3 = bitxor(v, v2)
|
||||
v4 = bitor(v, v2) - bitand(v, v2)
|
||||
print(string.format("xor(0x%X,0x%X) = %X or/and/minus = %X", v, v2, v3, v4))
|
||||
test_assert(v3==v4)
|
||||
|
||||
b2 = b1 + math.random(1,15)
|
||||
v2 = bitget(v, b1, b2)
|
||||
pow = 2^(b2-b1+1) - 1
|
||||
v3 = bitand(bitrshift(v,b1), pow)
|
||||
print(string.format("bitget(0x%X,%u,%u) = 0x%X bitand/bitrshift/pow = 0x%X", v, b1, b2, v2, v3))
|
||||
v1 = math.random(0,0xFFFFFFFF)
|
||||
v2 = swap32(v1)
|
||||
v3 = divint(v1,0x1000000) + divint(v1,0x10000)%0x100*0x100 + divint(v1,0x100)%0x100*0x10000 + v1%0x100*0x1000000
|
||||
print("swap32: "..(v2==v3 and "OK" or "FAIL"))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v4 = math.random(0,pow)
|
||||
v2 = bitset(v, b1, b2, v4)
|
||||
v3 = bitor(bitlshift(v4, b1), bitand(v, bitnot(bitlshift(pow, b1))))
|
||||
print(string.format("bitset(0x%X,%u,%u,0x%X) = 0x%X bitand/bitnot/bitlshift/pow = 0x%X", v, b1, b2, v4, v2, v3))
|
||||
v1 = math.random(0,0xFFFFFFFFFFFF)
|
||||
v2 = swap48(v1)
|
||||
v3 = divint(v1,0x10000000000) +
|
||||
divint(v1,0x100000000)%0x100*0x100 +
|
||||
divint(v1,0x1000000)%0x100*0x10000 +
|
||||
divint(v1,0x10000)%0x100*0x1000000 +
|
||||
divint(v1,0x100)%0x100*0x100000000 +
|
||||
v1%0x100*0x10000000000
|
||||
print("swap48: "..(v2==v3 and "OK" or "FAIL"))
|
||||
test_assert(v2==v3)
|
||||
end
|
||||
|
||||
@@ -305,7 +343,8 @@ function test_ux()
|
||||
{ add=u8add, fname="u8add", max = 0xFF },
|
||||
{ add=u16add, fname="u16add", max = 0xFFFF },
|
||||
{ add=u24add, fname="u24add", max = 0xFFFFFF },
|
||||
{ add=u32add, fname="u32add", max = 0xFFFFFFFF }
|
||||
{ add=u32add, fname="u32add", max = 0xFFFFFFFF },
|
||||
{ add=u48add, fname="u48add", max = 0xFFFFFFFFFFFF }
|
||||
}) do
|
||||
io.write(test.fname.." : ")
|
||||
for i=1,1000 do
|
||||
@@ -315,7 +354,7 @@ function test_ux()
|
||||
usum = test.add(v1,v2,v3)
|
||||
sum = bitand((v1+v2+v3)%(test.max+1),test.max)
|
||||
if sum~=usum then
|
||||
print("FAIL")
|
||||
print(string.format("FAIL: 0x%012X + 0x%012X + 0x%012X = 0x%012X 0x%012X",v1,v2,v3,usum,sum))
|
||||
end
|
||||
test_assert(sum==usum)
|
||||
end
|
||||
@@ -324,7 +363,7 @@ function test_ux()
|
||||
end
|
||||
|
||||
function test_bin(...)
|
||||
test_run({test_ub, test_bit, test_ux},...)
|
||||
test_run({test_ub, test_bit, test_swap, test_ux},...)
|
||||
end
|
||||
|
||||
|
||||
|
||||
115
nfq2/desync.c
115
nfq2/desync.c
@@ -1475,6 +1475,7 @@ static void quic_reasm_cancel(t_ctrack *ctrack, const char *reason)
|
||||
static void udp_standard_protocol_probe(const uint8_t *data_payload, size_t len_payload, t_ctrack *ctrack, t_l7proto *l7proto, t_l7payload *l7payload)
|
||||
{
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_QUIC_INITIAL,L7_QUIC,IsQUICInitial,false},
|
||||
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
|
||||
{L7P_STUN,L7_STUN,IsStunMessage,false},
|
||||
{L7P_DNS_QUERY,L7_DNS,IsDNSQuery,false},
|
||||
@@ -1491,6 +1492,88 @@ static void udp_standard_protocol_probe(const uint8_t *data_payload, size_t len_
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), data_payload, len_payload, ctrack, l7proto, l7payload);
|
||||
}
|
||||
|
||||
static const uint8_t *dns_extract_name(const uint8_t *a, const uint8_t *b, const uint8_t *e, char *name, size_t name_size)
|
||||
{
|
||||
size_t nl, off;
|
||||
const uint8_t *p;
|
||||
bool bptr = (*a & 0xC0)==0xC0;
|
||||
|
||||
if (bptr)
|
||||
{
|
||||
// name pointer
|
||||
off = (*a & 0x3F)<<8 | a[1];
|
||||
p = b + off;
|
||||
}
|
||||
else
|
||||
// real name
|
||||
p = a;
|
||||
|
||||
if (p>=e) return NULL;
|
||||
for (nl=0; *p ;)
|
||||
{
|
||||
if ((p+*p+1)>=e || (*p+1)>=(name_size-nl)) return NULL;
|
||||
if (nl) name[nl++] = '.';
|
||||
memcpy(name + nl, p + 1, *p);
|
||||
nl += *p;
|
||||
p += *p + 1;
|
||||
}
|
||||
name[nl] = 0;
|
||||
return bptr ? a+2 : p+1;
|
||||
}
|
||||
static bool feed_dns_response(const uint8_t *a, size_t len)
|
||||
{
|
||||
if (!params.cache_hostname) return true;
|
||||
|
||||
// check of minimum header length and response flag
|
||||
uint16_t k, off, dlen, qcount = a[4]<<8 | a[5], acount = a[6]<<8 | a[7];
|
||||
char s_ip[40];
|
||||
const uint8_t *b = a, *p;
|
||||
const uint8_t *e = b + len;
|
||||
size_t nl;
|
||||
char name[256] = "";
|
||||
|
||||
if (len<12 || !(a[2]&0x80)) return false;
|
||||
a+=12; len-=12;
|
||||
for(k=0;k<qcount;k++)
|
||||
{
|
||||
// remember original query name
|
||||
if (!(p = dns_extract_name(a, b, e, name, sizeof(name)))) return false;
|
||||
len -= p-a;
|
||||
// must be A or AAAA query. others are not interesting
|
||||
if ((len<4) || p[0] || p[1]!=1 && p[1]!=28 || p[2] || p[3]!=1) return false;
|
||||
// skip type, class
|
||||
a=p+4; len-=4;
|
||||
}
|
||||
if (!*name) return false;
|
||||
for(k=0;k<acount;k++)
|
||||
{
|
||||
// 11 higher bits indicate pointer
|
||||
if (len<12 || (*a & 0xC0)!=0xC0) return false;
|
||||
|
||||
dlen = a[10]<<8 | a[11];
|
||||
if (len<(dlen+12)) return false;
|
||||
if (a[4]==0 && a[5]==1 && a[2]==0) // IN class and higher byte of type = 0
|
||||
{
|
||||
switch(a[3])
|
||||
{
|
||||
case 1: // A
|
||||
if (dlen!=4) break;
|
||||
if (params.debug && inet_ntop(AF_INET, a+12, s_ip, sizeof(s_ip)))
|
||||
DLOG("DNS response : %s\n", s_ip);
|
||||
ipcache_put_hostname((struct in_addr *)(a+12), NULL, name, false);
|
||||
break;
|
||||
case 28: // AAAA
|
||||
if (dlen!=16) break;
|
||||
if (params.debug && inet_ntop(AF_INET6, a+12, s_ip, sizeof(s_ip)))
|
||||
DLOG("DNS response : %s\n", s_ip);
|
||||
ipcache_put_hostname(NULL, (struct in6_addr *)(a+12), name, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
len -= 12+dlen; a += 12+dlen;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t dpi_desync_udp_packet_play(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||
@@ -1651,22 +1734,13 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
if (dis->len_payload)
|
||||
{
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
if (bReverse)
|
||||
|
||||
udp_standard_protocol_probe(dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
|
||||
if (!bReverse)
|
||||
{
|
||||
udp_standard_protocol_probe(dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct blob_collection_head *fake;
|
||||
if (IsQUICInitial(dis->data_payload, dis->len_payload))
|
||||
if (l7payload==L7P_QUIC_INITIAL)
|
||||
{
|
||||
DLOG("packet contains QUIC initial\n");
|
||||
l7payload = L7P_QUIC_INITIAL;
|
||||
|
||||
l7proto = L7_QUIC;
|
||||
// update ctrack l7proto here because reasm can happen
|
||||
if (ctrack && ctrack->l7proto == L7_UNKNOWN) ctrack->l7proto = l7proto;
|
||||
|
||||
uint8_t clean[UDP_MAX_REASM], *pclean;
|
||||
size_t clean_len;
|
||||
|
||||
@@ -1788,15 +1862,14 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
quic_reasm_cancel(ctrack, "QUIC initial decryption failed");
|
||||
}
|
||||
}
|
||||
else // not QUIC initial
|
||||
{
|
||||
// not quic initial - stop reasm
|
||||
reasm_client_cancel(ctrack);
|
||||
|
||||
udp_standard_protocol_probe(dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
}
|
||||
}
|
||||
|
||||
reasm_client_cancel(ctrack);
|
||||
|
||||
if (l7payload==L7P_DNS_RESPONSE)
|
||||
feed_dns_response(dis->data_payload, dis->len_payload);
|
||||
|
||||
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(host);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#define BUFMIN 128
|
||||
#define BUFCHUNK (1024*128)
|
||||
|
||||
int z_readfile(FILE *F, char **buf, size_t *size)
|
||||
int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
|
||||
{
|
||||
z_stream zs;
|
||||
int r;
|
||||
@@ -38,7 +38,7 @@ int z_readfile(FILE *F, char **buf, size_t *size)
|
||||
if ((bufsize - *size) < BUFMIN)
|
||||
{
|
||||
bufsize += BUFCHUNK;
|
||||
newbuf = *buf ? realloc(*buf, bufsize) : malloc(bufsize);
|
||||
newbuf = *buf ? realloc(*buf, bufsize + extra_alloc) : malloc(bufsize + extra_alloc);
|
||||
if (!newbuf)
|
||||
{
|
||||
r = Z_MEM_ERROR;
|
||||
@@ -57,7 +57,7 @@ int z_readfile(FILE *F, char **buf, size_t *size)
|
||||
if (*size < bufsize)
|
||||
{
|
||||
// free extra space
|
||||
if ((newbuf = realloc(*buf, *size))) *buf = newbuf;
|
||||
if ((newbuf = realloc(*buf, *size + extra_alloc))) *buf = newbuf;
|
||||
}
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
#include <zlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
int z_readfile(FILE *F,char **buf,size_t *size);
|
||||
int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc);
|
||||
bool is_gzip(FILE* F);
|
||||
|
||||
@@ -367,6 +367,19 @@ void phton32(uint8_t *p, uint32_t v)
|
||||
p[2] = (uint8_t)(v>>8);
|
||||
p[3] = (uint8_t)v;
|
||||
}
|
||||
uint64_t pntoh48(const uint8_t *p)
|
||||
{
|
||||
return ((uint64_t)p[0] << 40) | ((uint64_t)p[1] << 32) | ((uint64_t)p[2] << 24) | ((uint64_t)p[3] << 16) | ((uint64_t)p[4] << 8) | p[5];
|
||||
}
|
||||
void phton48(uint8_t *p, uint64_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v>>40);
|
||||
p[1] = (uint8_t)(v>>32);
|
||||
p[2] = (uint8_t)(v>>24);
|
||||
p[3] = (uint8_t)(v>>16);
|
||||
p[4] = (uint8_t)(v>>8);
|
||||
p[5] = (uint8_t)v;
|
||||
}
|
||||
uint64_t pntoh64(const uint8_t *p)
|
||||
{
|
||||
return ((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) | ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32) | ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) | ((uint64_t)p[6] << 8) | p[7];
|
||||
@@ -383,6 +396,20 @@ void phton64(uint8_t *p, uint64_t v)
|
||||
p[7] = (uint8_t)v;
|
||||
}
|
||||
|
||||
uint16_t swap16(uint16_t u)
|
||||
{
|
||||
// __builtin_bswap16 is absent in ancient lexra gcc 4.6
|
||||
return (u>>8) | ((u&0xFF)<<8);
|
||||
}
|
||||
uint32_t swap24(uint32_t u)
|
||||
{
|
||||
return (u>>16) & 0xFF | u & 0xFF00 | (u<<16) & 0xFF0000;
|
||||
}
|
||||
uint64_t swap48(uint64_t u)
|
||||
{
|
||||
return ((u & 0xFF0000000000) >> 40) | ((u & 0xFF00000000) >> 24) | ((u & 0xFF000000) >> 8) | ((u & 0xFF0000) << 8) | ((u & 0xFF00) << 24) | ((u & 0xFF) << 40);
|
||||
}
|
||||
|
||||
|
||||
#define INVALID_HEX_DIGIT ((uint8_t)-1)
|
||||
static inline uint8_t parse_hex_digit(char c)
|
||||
|
||||
@@ -61,9 +61,15 @@ uint32_t pntoh24(const uint8_t *p);
|
||||
void phton24(uint8_t *p, uint32_t v);
|
||||
uint32_t pntoh32(const uint8_t *p);
|
||||
void phton32(uint8_t *p, uint32_t v);
|
||||
uint64_t pntoh48(const uint8_t *p);
|
||||
void phton48(uint8_t *p, uint64_t v);
|
||||
uint64_t pntoh64(const uint8_t *p);
|
||||
void phton64(uint8_t *p, uint64_t v);
|
||||
|
||||
uint16_t swap16(uint16_t u);
|
||||
uint32_t swap24(uint32_t u);
|
||||
uint64_t swap48(uint64_t u);
|
||||
|
||||
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size);
|
||||
char hex_digit(uint8_t v);
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||
|
||||
if (is_gzip(F))
|
||||
{
|
||||
r = z_readfile(F,&zbuf,&zsize);
|
||||
r = z_readfile(F,&zbuf,&zsize,0);
|
||||
fclose(F);
|
||||
if (r==Z_OK)
|
||||
{
|
||||
|
||||
@@ -76,7 +76,7 @@ static bool AppendIpset(ipset *ips, const char *filename)
|
||||
|
||||
if (is_gzip(F))
|
||||
{
|
||||
r = z_readfile(F,&zbuf,&zsize);
|
||||
r = z_readfile(F,&zbuf,&zsize,0);
|
||||
fclose(F);
|
||||
if (r==Z_OK)
|
||||
{
|
||||
|
||||
241
nfq2/lua.c
241
nfq2/lua.c
@@ -9,9 +9,11 @@
|
||||
#elif defined(__CYGWIN__)
|
||||
#include <processthreadsapi.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include "lua.h"
|
||||
#include "params.h"
|
||||
#include "gzip.h"
|
||||
#include "helpers.h"
|
||||
#include "conntrack.h"
|
||||
#include "crypto/sha.h"
|
||||
@@ -69,16 +71,16 @@ static int luacall_bitlshift(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitlshift",2);
|
||||
int64_t v=(int64_t)luaL_checklint(L,1);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,((uint32_t)v) << luaL_checkinteger(L,2));
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,(((uint64_t)v) << luaL_checkinteger(L,2)) & 0xFFFFFFFFFFFF);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitrshift(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitrshift",2);
|
||||
int64_t v=(int64_t)luaL_checklint(L,1);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,((uint32_t)v) >> luaL_checkinteger(L,2));
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,((uint64_t)v) >> luaL_checkinteger(L,2));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitand(lua_State *L)
|
||||
@@ -86,12 +88,12 @@ static int luacall_bitand(lua_State *L)
|
||||
lua_check_argc_range(L,"bitand",2,100);
|
||||
int argc = lua_gettop(L);
|
||||
int64_t v;
|
||||
uint32_t sum=0xFFFFFFFF;
|
||||
uint64_t sum=0xFFFFFFFFFFFF;
|
||||
for(int i=1;i<=argc;i++)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum&=(uint32_t)v;
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum&=(uint64_t)v;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
@@ -101,33 +103,60 @@ static int luacall_bitor(lua_State *L)
|
||||
lua_check_argc_range(L,"bitor",1,100);
|
||||
int argc = lua_gettop(L);
|
||||
int64_t v;
|
||||
uint32_t sum=0;
|
||||
uint64_t sum=0;
|
||||
for(int i=1;i<=argc;i++)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum|=(uint32_t)v;
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum|=(uint64_t)v;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitnot(lua_State *L)
|
||||
static int lua_bitnotx(lua_State *L, int64_t max)
|
||||
{
|
||||
lua_check_argc(L,"bitnot",1);
|
||||
lua_pushlint(L,~(uint32_t)luaL_checklint(L,1));
|
||||
int64_t v=(int64_t)luaL_checklint(L,1);
|
||||
if (v>max || v<-max) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,~(uint64_t)v & max);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitnot8(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot8",1);
|
||||
return lua_bitnotx(L, 0xFF);
|
||||
}
|
||||
static int luacall_bitnot16(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot16",1);
|
||||
return lua_bitnotx(L, 0xFFFF);
|
||||
}
|
||||
static int luacall_bitnot24(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot24",1);
|
||||
return lua_bitnotx(L, 0xFFFFFF);
|
||||
}
|
||||
static int luacall_bitnot32(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot32",1);
|
||||
return lua_bitnotx(L, 0xFFFFFFFF);
|
||||
}
|
||||
static int luacall_bitnot48(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot48",1);
|
||||
return lua_bitnotx(L, 0xFFFFFFFFFFFF);
|
||||
}
|
||||
static int luacall_bitxor(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"bitxor",1,100);
|
||||
int argc = lua_gettop(L);
|
||||
int64_t v;
|
||||
uint32_t sum=0;
|
||||
uint64_t sum=0;
|
||||
for(int i=1;i<=argc;i++)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum^=(uint32_t)v;
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum^=(uint64_t)v;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
@@ -137,11 +166,11 @@ static int luacall_bitget(lua_State *L)
|
||||
lua_check_argc(L,"bitget",3);
|
||||
|
||||
int64_t iwhat = (int64_t)luaL_checklint(L,1);
|
||||
if (iwhat>0xFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint32_t what = (uint32_t)iwhat;
|
||||
if (iwhat>0xFFFFFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint64_t what = (uint64_t)iwhat;
|
||||
lua_Integer from = luaL_checkinteger(L,2);
|
||||
lua_Integer to = luaL_checkinteger(L,3);
|
||||
if (from>to || from>31 || to>31)
|
||||
if (from>to || from>47 || to>47)
|
||||
luaL_error(L, "bit range invalid");
|
||||
|
||||
what = (what >> from) & ~((lua_Integer)-1 << (to-from+1));
|
||||
@@ -154,17 +183,17 @@ static int luacall_bitset(lua_State *L)
|
||||
lua_check_argc(L,"bitset",4);
|
||||
|
||||
int64_t iwhat = (int64_t)luaL_checklint(L,1);
|
||||
if (iwhat>0xFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint32_t what = (uint32_t)iwhat;
|
||||
if (iwhat>0xFFFFFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint64_t what = (uint64_t)iwhat;
|
||||
lua_Integer from = luaL_checkinteger(L,2);
|
||||
lua_Integer to = luaL_checkinteger(L,3);
|
||||
int64_t iset = (int64_t)luaL_checklint(L,4);
|
||||
if (iset>0xFFFFFFFF || iset<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint32_t set = (uint32_t)iset;
|
||||
if (from>to || from>31 || to>31)
|
||||
if (iset>0xFFFFFFFFFFFF || iset<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint64_t set = (uint64_t)iset;
|
||||
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;
|
||||
@@ -229,6 +258,20 @@ static int luacall_u32(lua_State *L)
|
||||
lua_pushlint(L,pntoh32(p+offset));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_u48(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"u48",1,2);
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
size_t l;
|
||||
lua_Integer offset;
|
||||
const uint8_t *p = (uint8_t*)luaL_checklstring(L,1,&l);
|
||||
offset = (argc>=2 && lua_type(L,2)!=LUA_TNIL) ? luaL_checkinteger(L,2)-1 : 0;
|
||||
if (offset<0 || (offset+6)>l) luaL_error(L, "out of range");
|
||||
|
||||
lua_pushlint(L,pntoh48(p+offset));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_swap16(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"swap16",1);
|
||||
@@ -236,8 +279,17 @@ static int luacall_swap16(lua_State *L)
|
||||
int64_t i = (int64_t)luaL_checklint(L,1);
|
||||
if (i>0xFFFF || i<-(int64_t)0xFFFF) luaL_error(L, "out of range");
|
||||
uint16_t u = (uint16_t)i;
|
||||
// __builtin_bswap16 is absent in ancient lexra gcc 4.6
|
||||
lua_pushinteger(L,(u>>8) | ((u&0xFF)<<8));
|
||||
lua_pushinteger(L,swap16(u));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_swap24(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"swap24",1);
|
||||
|
||||
int64_t i =(int64_t)luaL_checklint(L,1);
|
||||
if (i>0xFFFFFF || i<-(int64_t)0xFFFFFF) luaL_error(L, "out of range");
|
||||
uint32_t u = (uint32_t)i;
|
||||
lua_pushlint(L,swap24(u));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_swap32(lua_State *L)
|
||||
@@ -250,16 +302,26 @@ static int luacall_swap32(lua_State *L)
|
||||
lua_pushlint(L,__builtin_bswap32(u));
|
||||
return 1;
|
||||
}
|
||||
static int lua_uxadd(lua_State *L, uint32_t max)
|
||||
static int luacall_swap48(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"swap48",1);
|
||||
|
||||
int64_t i =(int64_t)luaL_checklint(L,1);
|
||||
if (i>0xFFFFFFFFFFFF || i<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint64_t u = (uint64_t)i;
|
||||
lua_pushlint(L, swap48(u));
|
||||
return 1;
|
||||
}
|
||||
static int lua_uxadd(lua_State *L, int64_t max)
|
||||
{
|
||||
int64_t v;
|
||||
uint32_t sum=0;
|
||||
uint64_t sum=0;
|
||||
int argc = lua_gettop(L);
|
||||
for(int i=1;i<=argc;i++)
|
||||
{
|
||||
v = (int64_t)luaL_checklint(L,i);
|
||||
if (v>max || v<-(int64_t)max) luaL_error(L, "out of range");
|
||||
sum+=(uint32_t)v;
|
||||
if (v>max || v<-max) luaL_error(L, "out of range");
|
||||
sum+=(uint64_t)v;
|
||||
}
|
||||
lua_pushlint(L, sum & max);
|
||||
return 1;
|
||||
@@ -284,6 +346,11 @@ static int luacall_u32add(lua_State *L)
|
||||
lua_check_argc_range(L,"u32add",1,100);
|
||||
return lua_uxadd(L, 0xFFFFFFFF);
|
||||
}
|
||||
static int luacall_u48add(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"u48add",1,100);
|
||||
return lua_uxadd(L, 0xFFFFFFFFFFFF);
|
||||
}
|
||||
|
||||
static int luacall_bu8(lua_State *L)
|
||||
{
|
||||
@@ -328,6 +395,17 @@ static int luacall_bu32(lua_State *L)
|
||||
lua_pushlstring(L,(char*)v,4);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bu48(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bu48",1);
|
||||
|
||||
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[6];
|
||||
phton48(v,(uint64_t)i);
|
||||
lua_pushlstring(L,(char*)v,6);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int luacall_divint(lua_State *L)
|
||||
{
|
||||
@@ -2792,11 +2870,35 @@ static bool lua_basic_init()
|
||||
#else
|
||||
DLOG_CONDUP("LUA v%u.%u\n",ver/100,ver%100);
|
||||
#endif
|
||||
|
||||
#if LUA_VERSION_NUM >= 504
|
||||
lua_setwarnf(params.L,lua_warn,NULL);
|
||||
#endif
|
||||
lua_atpanic(params.L,lua_panic);
|
||||
luaL_openlibs(params.L); /* Load Lua libraries */
|
||||
|
||||
lua_getfield(params.L, LUA_REGISTRYINDEX, "_LOADED");
|
||||
if (lua_type(params.L, -1)==LUA_TTABLE)
|
||||
{
|
||||
lua_getfield(params.L, -1, "jit");
|
||||
if (lua_type(params.L, -1)==LUA_TTABLE)
|
||||
{
|
||||
lua_getfield(params.L, -1, "status");
|
||||
if (lua_type(params.L, -1)==LUA_TFUNCTION)
|
||||
{
|
||||
const char *s;
|
||||
int n = lua_gettop(params.L);
|
||||
|
||||
lua_call(params.L, 0, LUA_MULTRET);
|
||||
DLOG_CONDUP(lua_toboolean(params.L, n) ? "JIT: ON" : "JIT: OFF");
|
||||
for (n++; (s = lua_tostring(params.L, n)); n++)
|
||||
DLOG_CONDUP(" %s", s);
|
||||
DLOG_CONDUP("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
lua_settop(params.L, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2822,20 +2924,80 @@ static bool lua_desync_functions_exist()
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lua_file_open_test(const char *filename, bool *b_gzip, char *fname)
|
||||
{
|
||||
FILE *F = fopen(filename,"rb");
|
||||
if (F)
|
||||
{
|
||||
if (fname) snprintf(fname,PATH_MAX,"%s",filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t l = strlen(filename);
|
||||
char *fngz = malloc(l+4);
|
||||
if (!fngz) return false;
|
||||
memcpy(fngz, filename, l);
|
||||
memcpy(fngz+l,".gz",4);
|
||||
if (fname) snprintf(fname,PATH_MAX,"%s",fngz);
|
||||
F = fopen(fngz,"rb");
|
||||
free(fngz);
|
||||
}
|
||||
if (F)
|
||||
{
|
||||
if (b_gzip) *b_gzip = is_gzip(F);
|
||||
fclose(F);
|
||||
}
|
||||
return !!F;
|
||||
}
|
||||
|
||||
bool lua_test_init_script_files(void)
|
||||
{
|
||||
struct str_list *str;
|
||||
LIST_FOREACH(str, ¶ms.lua_init_scripts, next)
|
||||
{
|
||||
if (str->str[0]=='@' && !file_open_test(str->str+1, O_RDONLY))
|
||||
if (str->str[0]=='@' && !lua_file_open_test(str->str+1, NULL, NULL))
|
||||
{
|
||||
DLOG_ERR("LUA file '%s' not accessible\n",str->str+1);
|
||||
#ifndef __CYGWIN__
|
||||
int e = errno;
|
||||
#endif
|
||||
DLOG_ERR("LUA file '%s' or '%s.gz' not accessible\n", str->str+1, str->str+1);
|
||||
#ifndef __CYGWIN__
|
||||
if (e==EACCES)
|
||||
DLOG_ERR("I drop my privileges and do not run Lua as root\ncheck file permissions and +x rights on all directories in the path\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int luaL_doZfile(lua_State *L, const char *filename)
|
||||
{
|
||||
bool b_gzip;
|
||||
char fname[PATH_MAX];
|
||||
if (!lua_file_open_test(filename, &b_gzip, fname))
|
||||
luaL_error(L, "could not open lua file '%s' or '%s.gz'", filename, filename);
|
||||
if (b_gzip)
|
||||
{
|
||||
size_t size;
|
||||
char *buf;
|
||||
int r;
|
||||
FILE *F = fopen(fname, "rb");
|
||||
if (!F)
|
||||
luaL_error(L, "could not open lua file '%s'", fname);
|
||||
r = z_readfile(F, &buf, &size, 0);
|
||||
fclose(F);
|
||||
if (r != Z_OK)
|
||||
luaL_error(L, "could not unzip lua file '%s'", fname);
|
||||
r = luaL_loadbuffer(L, buf, size, fname);
|
||||
free(buf);
|
||||
if (!r) r=lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
return luaL_dofile(L, filename);
|
||||
}
|
||||
|
||||
static bool lua_init_scripts(void)
|
||||
{
|
||||
struct str_list *str;
|
||||
@@ -2854,7 +3016,7 @@ static bool lua_init_scripts(void)
|
||||
DLOG("LUA RUN STR: %s\n",s);
|
||||
}
|
||||
}
|
||||
if ((status = str->str[0]=='@' ? luaL_dofile(params.L, str->str+1) : luaL_dostring(params.L, str->str)))
|
||||
if ((status = str->str[0]=='@' ? luaL_doZfile(params.L, str->str+1) : luaL_dostring(params.L, str->str)))
|
||||
{
|
||||
lua_perror(params.L);
|
||||
return false;
|
||||
@@ -3082,10 +3244,14 @@ static void lua_init_functions(void)
|
||||
{"bitand",luacall_bitand},
|
||||
{"bitor",luacall_bitor},
|
||||
{"bitxor",luacall_bitxor},
|
||||
{"bitxor",luacall_bitxor},
|
||||
{"bitget",luacall_bitget},
|
||||
{"bitset",luacall_bitset},
|
||||
{"bitnot",luacall_bitnot},
|
||||
{"bitnot",luacall_bitnot48},
|
||||
{"bitnot8",luacall_bitnot8},
|
||||
{"bitnot16",luacall_bitnot16},
|
||||
{"bitnot24",luacall_bitnot24},
|
||||
{"bitnot32",luacall_bitnot32},
|
||||
{"bitnot48",luacall_bitnot48},
|
||||
|
||||
// WARNING : lua 5.1 and luajit does not correctly implement integers. they seem to be stored as float which can't hold 64-bit.
|
||||
// convert part of the blob (string) to number
|
||||
@@ -3093,19 +3259,24 @@ static void lua_init_functions(void)
|
||||
{"u16",luacall_u16},
|
||||
{"u24",luacall_u24},
|
||||
{"u32",luacall_u32},
|
||||
{"u48",luacall_u48},
|
||||
// add any number of arguments as they would be unsigned int of specific size
|
||||
{"u8add",luacall_u8add},
|
||||
{"u16add",luacall_u16add},
|
||||
{"u24add",luacall_u24add},
|
||||
{"u32add",luacall_u32add},
|
||||
{"u48add",luacall_u48add},
|
||||
// convert number to blob (string) - big endian
|
||||
{"bu8",luacall_bu8},
|
||||
{"bu16",luacall_bu16},
|
||||
{"bu24",luacall_bu24},
|
||||
{"bu32",luacall_bu32},
|
||||
{"bu48",luacall_bu48},
|
||||
// swap byte order
|
||||
{"swap16",luacall_swap16},
|
||||
{"swap24",luacall_swap24},
|
||||
{"swap32",luacall_swap32},
|
||||
{"swap48",luacall_swap48},
|
||||
|
||||
// integer division
|
||||
{"divint",luacall_divint},
|
||||
|
||||
38
nfq2/nfqws.c
38
nfq2/nfqws.c
@@ -51,14 +51,15 @@
|
||||
#define MAX_CONFIG_FILE_SIZE 16384
|
||||
|
||||
struct params_s params;
|
||||
static bool bReload = false;
|
||||
static volatile sig_atomic_t bReload = false;
|
||||
#ifdef __CYGWIN__
|
||||
bool bQuit = false;
|
||||
#endif
|
||||
|
||||
static void onhup(int sig)
|
||||
{
|
||||
printf("HUP received ! Lists will be reloaded.\n");
|
||||
const char *msg = "HUP received ! Lists will be reloaded.\n";
|
||||
size_t wr = write(1, msg, strlen(msg));
|
||||
bReload = true;
|
||||
}
|
||||
static void ReloadCheck()
|
||||
@@ -683,11 +684,6 @@ static int win_main()
|
||||
DLOG("windivert: passing impostor packet\n");
|
||||
verdict = VERDICT_PASS;
|
||||
}
|
||||
else if (wa.Loopback)
|
||||
{
|
||||
DLOG("windivert: passing loopback packet\n");
|
||||
verdict = VERDICT_PASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
mark = 0;
|
||||
@@ -1257,7 +1253,7 @@ static bool wf_make_pf(char *opt, const char *l4, const char *portname, char *bu
|
||||
// HTTP/1.? 30(2|7)
|
||||
#define DIVERT_HTTP_REDIRECT "tcp.PayloadLength>=12 and tcp.Payload32[0]==0x48545450 and tcp.Payload16[2]==0x2F31 and tcp.Payload[6]==0x2E and tcp.Payload16[4]==0x2033 and tcp.Payload[10]==0x30 and (tcp.Payload[11]==0x32 or tcp.Payload[11]==0x37)"
|
||||
|
||||
#define DIVERT_PROLOG "!impostor and !loopback"
|
||||
#define DIVERT_PROLOG "!impostor"
|
||||
|
||||
static bool wf_make_filter(
|
||||
char *wf, size_t len,
|
||||
@@ -1268,12 +1264,14 @@ static bool wf_make_filter(
|
||||
const char *pf_tcp_src_in, const char *pf_tcp_dst_in,
|
||||
const char *pf_udp_src_in, const char *pf_udp_dst_out,
|
||||
const struct str_list_head *wf_raw_part,
|
||||
bool bFilterOutLAN)
|
||||
bool bFilterOutLAN, bool bFilterOutLoopback)
|
||||
{
|
||||
struct str_list *wfpart;
|
||||
bool bHaveTCP = *pf_tcp_src_in || *pf_tcp_dst_out;
|
||||
|
||||
snprintf(wf, len, "%s", DIVERT_PROLOG);
|
||||
if (bFilterOutLoopback)
|
||||
snprintf(wf + strlen(wf), len - strlen(wf), " and !loopback");
|
||||
if (IfIdx)
|
||||
snprintf(wf + strlen(wf), len - strlen(wf), " and ifIdx=%u and subIfIdx=%u", IfIdx, SubIfIdx);
|
||||
if (ipv4 ^ ipv6)
|
||||
@@ -1397,6 +1395,7 @@ static void exithelp(void)
|
||||
" --wf-tcp-empty=[0|1]\t\t\t\t\t; enable processing of empty tcp packets without flags SYN,RST,FIN (default : 0)\n"
|
||||
" --wf-raw-part=<filter>|@<filename>\t\t\t; partial raw windivert filter string or filename\n"
|
||||
" --wf-filter-lan=0|1\t\t\t\t\t; add excluding filter for non-global IP (default : 1)\n"
|
||||
" --wf-filter-loopback=0|1\t\t\t\t; add excluding filter for loopback (default : 1)\n"
|
||||
" --wf-raw=<filter>|@<filename>\t\t\t\t; full raw windivert filter string or filename. replaces --wf-tcp,--wf-udp,--wf-raw-part\n"
|
||||
" --wf-save=<filename>\t\t\t\t\t; save windivert filter string to a file and exit\n"
|
||||
"\nLOGICAL NETWORK FILTER:\n"
|
||||
@@ -1407,7 +1406,7 @@ static void exithelp(void)
|
||||
"\nDESYNC ENGINE INIT:\n"
|
||||
" --writeable[=<dir_name>]\t\t\t\t; create writeable dir for LUA scripts and pass it in WRITEABLE env variable (only one dir possible)\n"
|
||||
" --blob=<item_name>:[+ofs]@<filename>|0xHEX\t\t; load blob to LUA var <item_name>\n"
|
||||
" --lua-init=@<filename>|<lua_text>\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved.\n"
|
||||
" --lua-init=@<filename>|<lua_text>\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved. gzipped files are supported.\n"
|
||||
" --lua-gc=<int>\t\t\t\t\t\t; forced garbage collection every N sec. default %u sec. triggers only when a packet arrives. 0 = disable.\n"
|
||||
"\nMULTI-STRATEGY:\n"
|
||||
" --new\t\t\t\t\t\t\t; begin new profile\n"
|
||||
@@ -1495,10 +1494,6 @@ void config_from_file(const char *filename)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void check_dp(const struct desync_profile *dp)
|
||||
{
|
||||
}
|
||||
|
||||
static void ApplyDefaultBlobs(struct blob_collection_head *blobs)
|
||||
{
|
||||
load_const_blob_to_collection("fake_default_tls",fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),blobs,BLOB_EXTRA_BYTES);
|
||||
@@ -1594,6 +1589,7 @@ enum opt_indices {
|
||||
IDX_WF_RAW,
|
||||
IDX_WF_RAW_PART,
|
||||
IDX_WF_FILTER_LAN,
|
||||
IDX_WF_FILTER_LOOPBACK,
|
||||
IDX_WF_SAVE,
|
||||
IDX_SSID_FILTER,
|
||||
IDX_NLM_FILTER,
|
||||
@@ -1683,6 +1679,7 @@ static const struct option long_options[] = {
|
||||
[IDX_WF_RAW] = {"wf-raw", required_argument, 0, 0},
|
||||
[IDX_WF_RAW_PART] = {"wf-raw-part", required_argument, 0, 0},
|
||||
[IDX_WF_FILTER_LAN] = {"wf-filter-lan", required_argument, 0, 0},
|
||||
[IDX_WF_FILTER_LOOPBACK] = {"wf-filter-loopback", required_argument, 0, 0},
|
||||
[IDX_WF_SAVE] = {"wf-save", required_argument, 0, 0},
|
||||
[IDX_SSID_FILTER] = {"ssid-filter", required_argument, 0, 0},
|
||||
[IDX_NLM_FILTER] = {"nlm-filter", required_argument, 0, 0},
|
||||
@@ -1726,7 +1723,7 @@ int main(int argc, char **argv)
|
||||
struct packet_range range_in = PACKET_RANGE_NEVER, range_out = PACKET_RANGE_ALWAYS;
|
||||
#ifdef __CYGWIN__
|
||||
char wf_save_file[256]="";
|
||||
bool wf_ipv4 = true, wf_ipv6 = true, wf_filter_lan = true, wf_tcp_empty = false;
|
||||
bool wf_ipv4 = true, wf_ipv6 = true, wf_filter_lan = true, wf_filter_loopback = true, wf_tcp_empty = false;
|
||||
unsigned int IfIdx = 0, SubIfIdx = 0;
|
||||
unsigned int hash_wf_tcp_in = 0, hash_wf_udp_in = 0, hash_wf_tcp_out = 0, hash_wf_udp_out = 0, hash_wf_raw = 0, hash_wf_raw_part = 0, hash_ssid_filter = 0, hash_nlm_filter = 0;
|
||||
#endif
|
||||
@@ -2136,7 +2133,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
check_dp(dp);
|
||||
if (bTemplate)
|
||||
{
|
||||
if (dp->name && dp_list_search_name(¶ms.desync_templates, dp->name))
|
||||
@@ -2228,7 +2224,7 @@ int main(int argc, char **argv)
|
||||
DLOG_ERR("Invalid port filter : %s\n", optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
// deny tcp if not set
|
||||
// deny udp if not set
|
||||
if (!port_filters_deny_if_empty(&dp->pf_udp))
|
||||
exit_clean(1);
|
||||
break;
|
||||
@@ -2438,6 +2434,9 @@ int main(int argc, char **argv)
|
||||
case IDX_WF_FILTER_LAN:
|
||||
wf_filter_lan = !!atoi(optarg);
|
||||
break;
|
||||
case IDX_WF_FILTER_LOOPBACK:
|
||||
wf_filter_loopback = !!atoi(optarg);
|
||||
break;
|
||||
case IDX_WF_SAVE:
|
||||
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
|
||||
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
|
||||
@@ -2477,7 +2476,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
check_dp(dp);
|
||||
if (bTemplate)
|
||||
{
|
||||
if (dp->name && dp_list_search_name(¶ms.desync_templates, dp->name))
|
||||
@@ -2607,13 +2605,13 @@ int main(int argc, char **argv)
|
||||
params.wf_pf_tcp_dst_out, params.wf_pf_tcp_src_out,
|
||||
params.wf_pf_tcp_dst_in, params.wf_pf_tcp_src_in,
|
||||
params.wf_pf_udp_dst_in, params.wf_pf_udp_src_out,
|
||||
¶ms.wf_raw_part, wf_filter_lan) :
|
||||
¶ms.wf_raw_part, wf_filter_lan, wf_filter_loopback) :
|
||||
wf_make_filter(params.windivert_filter, WINDIVERT_MAX, IfIdx, SubIfIdx, wf_ipv4, wf_ipv6,
|
||||
wf_tcp_empty,
|
||||
params.wf_pf_tcp_src_out, params.wf_pf_tcp_dst_out,
|
||||
params.wf_pf_tcp_src_in, params.wf_pf_tcp_dst_in,
|
||||
params.wf_pf_udp_src_in, params.wf_pf_udp_dst_out,
|
||||
¶ms.wf_raw_part, wf_filter_lan);
|
||||
¶ms.wf_raw_part, wf_filter_lan, wf_filter_loopback);
|
||||
cleanup_windivert_portfilters(¶ms);
|
||||
if (!b)
|
||||
{
|
||||
|
||||
@@ -12,4 +12,4 @@ extern bool bQuit;
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
// when something changes that can break LUA compatibility this version should be increased
|
||||
#define LUA_COMPAT_VER 3
|
||||
#define LUA_COMPAT_VER 4
|
||||
|
||||
35
nfq2/pools.c
35
nfq2/pools.c
@@ -138,13 +138,17 @@ void HostFailPoolDump(hostfail_pool *p)
|
||||
static struct str_list *strlist_entry_alloc(const char *str)
|
||||
{
|
||||
struct str_list *entry = malloc(sizeof(struct str_list));
|
||||
if (!entry) return false;
|
||||
entry->str = strdup(str);
|
||||
if (!entry->str)
|
||||
if (!entry) return NULL;
|
||||
if (str)
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
if (!(entry->str = strdup(str)))
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
entry->str = NULL;
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -244,14 +248,13 @@ static struct str2_list *str2list_entry_copy(const struct str2_list *entry)
|
||||
{
|
||||
struct str2_list *e2 = str2list_entry_alloc();
|
||||
if (!e2) return NULL;
|
||||
e2->str1 = strdup(entry->str1);
|
||||
e2->str2 = strdup(entry->str2);
|
||||
if (!e2->str1 || !e2->str2)
|
||||
{
|
||||
str2list_entry_destroy(e2);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry->str1) if (!(e2->str1 = strdup(entry->str1))) goto err;
|
||||
if (entry->str2) if (!(e2->str2 = strdup(entry->str2))) goto err;
|
||||
return e2;
|
||||
err:
|
||||
str2list_entry_destroy(e2);
|
||||
return NULL;
|
||||
}
|
||||
bool str2list_copy(struct str2_list_head *to, const struct str2_list_head *from)
|
||||
{
|
||||
@@ -287,7 +290,7 @@ void funclist_destroy(struct func_list_head *head)
|
||||
static struct func_list *funclist_entry_alloc(const char *func)
|
||||
{
|
||||
struct func_list *entry = malloc(sizeof(struct func_list));
|
||||
if (!entry) return false;
|
||||
if (!entry) return NULL;
|
||||
entry->func = strdup(func);
|
||||
if (!entry->func)
|
||||
{
|
||||
@@ -321,7 +324,7 @@ static struct func_list *funclist_entry_copy(const struct func_list *entry)
|
||||
if (!str2list_copy(&e2->args, &entry->args))
|
||||
{
|
||||
funclist_entry_destroy(e2);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
return e2;
|
||||
}
|
||||
@@ -350,7 +353,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -616,7 +619,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1317,9 +1317,9 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
|
||||
|
||||
bool IsQUICInitial(const uint8_t *data, size_t len)
|
||||
{
|
||||
// too small packets are not likely to be initials with client hello
|
||||
// too small packets are not likely to be initials
|
||||
// long header, fixed bit
|
||||
if (len < 256 || (data[0] & 0xC0)!=0xC0) return false;
|
||||
if (len < 128 || (data[0] & 0xF0)!=0xC0) return false;
|
||||
|
||||
uint32_t ver = QUICExtractVersion(data,len);
|
||||
if (QUICDraftVersion(ver) < 11) return false;
|
||||
@@ -1330,8 +1330,8 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
|
||||
|
||||
uint64_t offset=5, sz;
|
||||
|
||||
// DCID. must be present
|
||||
if (!data[offset] || data[offset] > QUIC_MAX_CID_LENGTH) return false;
|
||||
// DCID
|
||||
if (data[offset] > QUIC_MAX_CID_LENGTH) return false;
|
||||
offset += 1 + data[offset];
|
||||
|
||||
// SCID
|
||||
@@ -1349,8 +1349,7 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
|
||||
offset += sz;
|
||||
if (offset > len) return false;
|
||||
|
||||
// client hello cannot be too small. likely ACK
|
||||
return sz>=96;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user