Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-16 22:59:46 +00:00

137 Commits

Author SHA1 Message Date
bol-van
2983c681d7 update docs 2026-01-04 14:28:02 +03:00
bol-van
68eefd9dd7 update docs 2026-01-04 14:21:14 +03:00
bol-van
73f6f7c522 update docs 2026-01-04 14:18:54 +03:00
bol-van
df83a29b98 update docs 2026-01-04 14:17:07 +03:00
bol-van
9881cc4da2 update docs 2026-01-04 13:00:37 +03:00
bol-van
44f8ad6747 update docs 2026-01-04 12:38:33 +03:00
bol-van
c651367d6a update docs 2026-01-04 12:35:08 +03:00
bol-van
90f88271c5 update docs 2026-01-04 12:34:07 +03:00
bol-van
9ba8d6cbdf update docs 2026-01-04 12:18:17 +03:00
bol-van
27efbb37d7 update docs 2026-01-04 12:16:57 +03:00
bol-van
d725bd8fd7 update docs 2026-01-04 12:13:58 +03:00
bol-van
0ef50d04dc update docs 2026-01-04 12:13:33 +03:00
bol-van
fdae4b1812 update docs 2026-01-04 12:08:36 +03:00
bol-van
d0644f6160 update docs 2026-01-04 12:06:01 +03:00
bol-van
b4f1765574 update docs 2026-01-04 12:04:58 +03:00
bol-van
8454d48fcd update docs 2026-01-04 12:01:30 +03:00
bol-van
70d7a77d06 update docs 2026-01-04 11:56:51 +03:00
bol-van
2a48f82feb update docs 2026-01-04 11:54:34 +03:00
bol-van
c5d997ce48 update docs 2026-01-04 11:52:55 +03:00
bol-van
c950edb380 update docs 2026-01-04 11:39:23 +03:00
bol-van
0d96b03f49 blockcheck2: additional NOTEST 2026-01-04 11:38:47 +03:00
bol-van
9772641813 init.d: 80-dns-intercept use mangle iptable 2026-01-03 20:19:28 +03:00
bol-van
7307a03ff7 init.d: 80-dns-intercept print_op 2026-01-03 20:16:49 +03:00
bol-van
b529198f24 80-dns-intercept: remove DISABLE_IPVx filters 2026-01-03 19:59:51 +03:00
bol-van
5f5cfb434c update docs 2026-01-03 19:48:42 +03:00
bol-van
2f1aa5734e winws2: --wf-filter-loopback 2026-01-03 19:44:29 +03:00
bol-van
062360f3f3 update docs 2026-01-03 19:24:12 +03:00
bol-van
7122808425 init.d: dns intercept scheme 2026-01-03 19:14:35 +03:00
bol-van
515921522e init.d: ressurect lanif 2026-01-03 17:50:11 +03:00
bol-van
c0ce825a95 update lame issue warning 2026-01-03 15:04:39 +03:00
bol-van
c4b23d21ce init.d: sysv functions fix wrong interface order 2026-01-03 14:55:39 +03:00
bol-van
0847d9f140 nfqws2: replace printf with write in sighup 2026-01-03 13:24:18 +03:00
bol-van
b239690e33 AI inspired fixes 2026-01-03 13:15:01 +03:00
bol-van
4f6510daf1 base.sh: detect hard links to busybox 2026-01-03 00:39:29 +03:00
bol-van
0cad2329a1 install_bin: fix and 2026-01-03 00:39:03 +03:00
bol-van
24d9eb1fe2 nfqws2: use query name in dns response extraction 2026-01-03 00:12:43 +03:00
bol-van
f98445d36b update docs 2026-01-02 22:45:02 +03:00
bol-van
7278bb1b87 nfqws2: fix non-working dns ipcache if --debug=0 2026-01-02 20:01:23 +03:00
bol-van
5b58997e3e update docs 2026-01-02 19:53:22 +03:00
bol-van
93a6487eb5 update docs 2026-01-02 19:39:31 +03:00
bol-van
fdca797671 nfqws2: cache dns response IP addresses if --ipcache-hostname enabled 2026-01-02 19:29:33 +03:00
bol-van
bb9e78e8fb nfqws2: optimize udp protocol detect code 2026-01-02 17:44:52 +03:00
bol-van
2a15a1a778 Merge pull request #61 from Pavel4e5/typos
Typos
2026-01-02 17:26:44 +03:00
Pavel4e5
bf89b415bb Merge branch 'bol-van:master' into typos 2026-01-02 18:42:40 +05:00
bol-van
735936efc5 zapret-tests: test_swap 2026-01-01 14:26:23 +03:00
bol-van
9d09d8adcc nfqws2: fix comment 2025-12-31 18:07:30 +03:00
bol-van
3874e16075 nfqws2: print luajit status at startup 2025-12-31 16:10:22 +03:00
bol-van
cbb05967ba update docs 2025-12-31 10:49:19 +03:00
bol-van
665bd5f318 zapret-lib: check NFQWS2_COMPAT_VER 2025-12-31 10:48:42 +03:00
bol-van
fa1d7c30c3 blockcheck2: --payload= 2025-12-31 10:42:54 +03:00
Pavel4e5
940f94162d update docs 2025-12-31 02:47:05 +05:00
Pavel4e5
60108bf378 zapret-antidpi: correct error message 2025-12-31 02:40:33 +05:00
bol-van
5a68245e32 update docs 2025-12-30 15:33:28 +03:00
bol-van
b2dbdd4dd7 update docs 2025-12-30 15:32:55 +03:00
bol-van
5bc65c3b91 update docs 2025-12-30 15:20:49 +03:00
bol-van
6bf7f2c7c0 nfqws2: use luaL_loadbuffer 2025-12-30 15:11:15 +03:00
bol-van
44a80abb3f nfqws2: use luaL_loadbuffer 2025-12-30 15:05:42 +03:00
bol-van
89f0f39b83 update docs 2025-12-30 13:27:07 +03:00
bol-van
ad6f1db149 blockcheck2: http_unixeol test 2025-12-30 13:26:51 +03:00
bol-van
9154fe1677 zapret-lib, zapret-antidpi: http_reconstruct_req, http_unixeol 2025-12-30 13:26:15 +03:00
bol-van
5e63a0f5c5 update docs 2025-12-30 11:24:08 +03:00
bol-van
0521053991 github actions: use pigz -11 instead of gzip 2025-12-30 11:10:10 +03:00
bol-van
7b7ed1ad60 update docs 2025-12-30 10:51:07 +03:00
bol-van
2915647c63 update docs 2025-12-30 10:50:19 +03:00
bol-van
958a4e918b update docs 2025-12-30 10:48:11 +03:00
bol-van
cb332dad74 update docs 2025-12-30 10:44:05 +03:00
bol-van
17e9e0a8e6 update docs 2025-12-29 20:40:50 +03:00
bol-van
78b348a193 nfqws2: bu48 crash fix 2025-12-29 19:25:28 +03:00
bol-van
8103a02689 nfqws2: fix wrong bitset on 32-bit platforms 2025-12-29 19:14:25 +03:00
bol-van
a2dedc45c0 update docs 2025-12-29 18:19:30 +03:00
bol-van
f0d3a63df9 update docs 2025-12-29 18:18:57 +03:00
bol-van
c6ca25a656 nfqws2: lua gzip notice in help text 2025-12-29 18:16:43 +03:00
bol-van
71b87f749d actions: gzip lua in embedded release 2025-12-29 18:13:49 +03:00
bol-van
3d756c9702 nfqws2: support gzipped lua 2025-12-29 18:10:41 +03:00
bol-van
13864fe5c5 zapret-antidpi,zapret-lib: separate tls_client_hello_mod function 2025-12-29 17:16:15 +03:00
bol-van
cc2601af2f blockcheck2: fix missing --blob 2025-12-29 16:49:52 +03:00
bol-van
07319a329e update docs 2025-12-29 14:57:28 +03:00
bol-van
52f5c2697b update docs 2025-12-29 14:54:53 +03:00
bol-van
6b0dde5643 update docs 2025-12-29 14:53:16 +03:00
bol-van
e42265e071 update docs 2025-12-29 14:51:03 +03:00
bol-van
939f7a9558 update docs 2025-12-29 14:49:47 +03:00
bol-van
b62ebd8fcb update docs 2025-12-29 14:46:50 +03:00
bol-van
521fafc05d update docs 2025-12-29 14:46:01 +03:00
bol-van
419d6769bd update docs 2025-12-29 14:42:36 +03:00
bol-van
dde3f59d32 update docs 2025-12-29 14:42:19 +03:00
bol-van
78e1fb85ac zapret-antidpi: use TLS_EXT_SERVER_NAME 2025-12-29 14:08:34 +03:00
bol-van
f73790b871 zapret-lib: tls comments 2025-12-29 13:45:33 +03:00
bol-van
33f3378094 zapret-antidpi: extend tls clone function 2025-12-29 13:19:12 +03:00
bol-van
af7a6f6c10 zapret-antidpi: fix sniext add case 2025-12-29 13:10:35 +03:00
bol-van
9cc348e5bd zapret-antidpi: extend tls clone function 2025-12-29 13:03:48 +03:00
bol-van
8628c34941 zapret-lib: fix reconstruct handshake without record layer 2025-12-29 12:08:11 +03:00
bol-van
eec9f3e87c zapret-lib: tls dissector/reconstructor 2025-12-29 11:59:52 +03:00
bol-van
e4a8f51775 nfqws2: do not treat quic handshake messages as initials 2025-12-28 18:04:41 +03:00
bol-van
fb962df188 nfqws2: detect incoming quic_initial (w/o decryption) 2025-12-28 17:12:18 +03:00
bol-van
173dcd47d1 nfqws2: detect incoming quic_initial (w/o decryption) 2025-12-28 17:09:25 +03:00
bol-van
3439dc4f21 zapret-tests: remove unneeded code 2025-12-28 16:39:11 +03:00
bol-van
6e04162a20 github actions: remove arm-old target - luajit fail reason revealed 2025-12-28 15:32:09 +03:00
bol-van
883a3d6233 update docs 2025-12-28 15:14:01 +03:00
bol-van
e8cde6b0a2 rename sip.bin 2025-12-28 14:43:28 +03:00
bol-van
43872a21a6 more fakes 2025-12-28 13:45:10 +03:00
bol-van
ff2c3e81f9 update docs 2025-12-28 13:01:54 +03:00
bol-van
bcbfb45c53 update docs 2025-12-28 12:53:19 +03:00
bol-van
fa6a75f139 update docs 2025-12-28 12:51:10 +03:00
bol-van
e96c06598c update docs 2025-12-28 12:50:35 +03:00
bol-van
58320aecbe nfqws2: swap24 2025-12-28 12:49:09 +03:00
bol-van
ba526b75e1 update docs 2025-12-28 12:40:00 +03:00
bol-van
b9321619fc update docs 2025-12-28 12:37:58 +03:00
bol-van
d1a489a196 nfqws2: support 48-bit arithmetics 2025-12-28 12:32:26 +03:00
bol-van
cf91697dfb update docs 2025-12-28 10:55:08 +03:00
bol-van
401886bf32 update docs 2025-12-28 10:51:38 +03:00
bol-van
8baf81a840 update docs 2025-12-28 10:51:18 +03:00
bol-van
417cd8335a update docs 2025-12-28 10:48:26 +03:00
bol-van
5a9d40ad3f update docs 2025-12-28 10:47:42 +03:00
bol-van
af0be0fd94 update docs 2025-12-28 10:46:59 +03:00
bol-van
68e0c367c9 blockcheck2: fix broken parts 2025-12-28 10:27:21 +03:00
bol-van
0969d22391 nfqws2: wrong type fix 2025-12-27 19:55:10 +03:00
bol-van
94daca8ced nfqws2: wrong type fix 2025-12-27 19:51:34 +03:00
bol-van
1982984a86 nfqws2: fix crash 2025-12-27 19:50:12 +03:00
bol-van
6a520f508a winws2: no EACCES check in windows 2025-12-27 11:52:10 +03:00
bol-van
70d0dd5d79 nfqws2: permissions info if EACCES on lua files 2025-12-27 10:44:27 +03:00
bol-van
4ca0f6b574 update docs 2025-12-26 16:19:45 +03:00
bol-van
76e85d8969 update docs 2025-12-26 16:18:08 +03:00
bol-van
f458a76880 update docs 2025-12-26 14:28:43 +03:00
bol-van
6077d363ec more fakes 2025-12-26 13:02:53 +03:00
bol-van
c70f114c3a zapret-antidpi: dht_dn 3 by default 2025-12-26 10:51:37 +03:00
bol-van
2c037dca73 init.d: 50-dht4all NFQWS_OPT_DHT_PKT_OUT 2025-12-26 10:50:20 +03:00
bol-van
fe2fc0337f update docs 2025-12-25 20:51:08 +03:00
bol-van
b3a86d0d8a update docs 2025-12-25 20:48:31 +03:00
bol-van
5618be9a71 update docs 2025-12-25 20:47:35 +03:00
bol-van
715ae4bf1c update docs 2025-12-25 20:16:10 +03:00
bol-van
f44b6bf769 update docs 2025-12-25 20:15:07 +03:00
bol-van
e75857c448 update docs 2025-12-25 20:13:34 +03:00
bol-van
bc008e2cf3 update docs 2025-12-25 19:53:23 +03:00
bol-van
752226208b update docs 2025-12-25 19:49:03 +03:00
bol-van
9e2222549e init.d: 50-wg4all catch also response and cookie 2025-12-25 16:38:09 +03:00
bol-van
b0686b16f7 update docs 2025-12-25 16:20:51 +03:00
bol-van
d5b2c41daa update docs 2025-12-25 16:19:07 +03:00
50 changed files with 2583 additions and 452 deletions

View File

@@ -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.

View File

@@ -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 }}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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; }

View File

@@ -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}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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()
{

View File

@@ -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"

View File

@@ -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]

File diff suppressed because it is too large Load Diff

View File

@@ -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

Binary file not shown.

BIN
files/fake/bitcoin.bin Normal file

Binary file not shown.

Binary file not shown.

BIN
files/fake/ntp4.bin Normal file

Binary file not shown.

View 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
View File

@@ -0,0 +1 @@
EHLO delta.peach.mil

Binary file not shown.

BIN
files/fake/tls_alert.bin Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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

View File

@@ -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
}

View 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
}

View File

@@ -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()

View File

@@ -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}"
}

View File

@@ -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=

View File

@@ -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)

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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, &params.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},

View File

@@ -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(&params.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(&params.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,
&params.wf_raw_part, wf_filter_lan) :
&params.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,
&params.wf_raw_part, wf_filter_lan);
&params.wf_raw_part, wf_filter_lan, wf_filter_loopback);
cleanup_windivert_portfilters(&params);
if (!b)
{

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}