mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-14 06:13:09 +00:00
Compare commits
310 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2dedc45c0 | ||
|
|
f0d3a63df9 | ||
|
|
c6ca25a656 | ||
|
|
71b87f749d | ||
|
|
3d756c9702 | ||
|
|
13864fe5c5 | ||
|
|
cc2601af2f | ||
|
|
07319a329e | ||
|
|
52f5c2697b | ||
|
|
6b0dde5643 | ||
|
|
e42265e071 | ||
|
|
939f7a9558 | ||
|
|
b62ebd8fcb | ||
|
|
521fafc05d | ||
|
|
419d6769bd | ||
|
|
dde3f59d32 | ||
|
|
78e1fb85ac | ||
|
|
f73790b871 | ||
|
|
33f3378094 | ||
|
|
af7a6f6c10 | ||
|
|
9cc348e5bd | ||
|
|
8628c34941 | ||
|
|
eec9f3e87c | ||
|
|
e4a8f51775 | ||
|
|
fb962df188 | ||
|
|
173dcd47d1 | ||
|
|
3439dc4f21 | ||
|
|
6e04162a20 | ||
|
|
883a3d6233 | ||
|
|
e8cde6b0a2 | ||
|
|
43872a21a6 | ||
|
|
ff2c3e81f9 | ||
|
|
bcbfb45c53 | ||
|
|
fa6a75f139 | ||
|
|
e96c06598c | ||
|
|
58320aecbe | ||
|
|
ba526b75e1 | ||
|
|
b9321619fc | ||
|
|
d1a489a196 | ||
|
|
cf91697dfb | ||
|
|
401886bf32 | ||
|
|
8baf81a840 | ||
|
|
417cd8335a | ||
|
|
5a9d40ad3f | ||
|
|
af0be0fd94 | ||
|
|
68e0c367c9 | ||
|
|
0969d22391 | ||
|
|
94daca8ced | ||
|
|
1982984a86 | ||
|
|
6a520f508a | ||
|
|
70d0dd5d79 | ||
|
|
4ca0f6b574 | ||
|
|
76e85d8969 | ||
|
|
f458a76880 | ||
|
|
6077d363ec | ||
|
|
c70f114c3a | ||
|
|
2c037dca73 | ||
|
|
fe2fc0337f | ||
|
|
b3a86d0d8a | ||
|
|
5618be9a71 | ||
|
|
715ae4bf1c | ||
|
|
f44b6bf769 | ||
|
|
e75857c448 | ||
|
|
bc008e2cf3 | ||
|
|
752226208b | ||
|
|
9e2222549e | ||
|
|
b0686b16f7 | ||
|
|
d5b2c41daa | ||
|
|
46a7632f59 | ||
|
|
0642969a2d | ||
|
|
13af2ec1be | ||
|
|
50a1bb72d9 | ||
|
|
1696f1b552 | ||
|
|
b0ce5c0c1b | ||
|
|
87943846d9 | ||
|
|
8b359d0410 | ||
|
|
0430d9d9cd | ||
|
|
efcc1477dd | ||
|
|
100fff0461 | ||
|
|
1d14f8b0a4 | ||
|
|
6e5c6511d3 | ||
|
|
491a24d671 | ||
|
|
505e8ff82c | ||
|
|
1bbc56dc1b | ||
|
|
ad60550bf3 | ||
|
|
3043963e28 | ||
|
|
664bc60175 | ||
|
|
815801a7db | ||
|
|
05f54086cf | ||
|
|
b7a5f0410f | ||
|
|
da8bb9f5b8 | ||
|
|
9e52d767d1 | ||
|
|
3ff06303cb | ||
|
|
2a5c036909 | ||
|
|
a6e11540ff | ||
|
|
347c35e588 | ||
|
|
ea28460f1d | ||
|
|
0ac5df9d0e | ||
|
|
63767929a0 | ||
|
|
026c832f3f | ||
|
|
53ef85773e | ||
|
|
c41353cb8a | ||
|
|
d2f6c18adf | ||
|
|
00d1406791 | ||
|
|
a38acae652 | ||
|
|
90a991b5ee | ||
|
|
686721f96a | ||
|
|
479b067f1a | ||
|
|
ea1f34c833 | ||
|
|
b4fe028cb7 | ||
|
|
39c3640477 | ||
|
|
2236a95d49 | ||
|
|
8bb03d68b5 | ||
|
|
7b2a9a26ed | ||
|
|
b0ae1ac6f8 | ||
|
|
29c1d1f164 | ||
|
|
7cedbc5630 | ||
|
|
ccd943a02b | ||
|
|
49dc116c4b | ||
|
|
f70107fad3 | ||
|
|
40e9edcdcb | ||
|
|
905677b7ac | ||
|
|
87b7b644c7 | ||
|
|
2b410318ff | ||
|
|
afee286d91 | ||
|
|
f223a3e7e9 | ||
|
|
258e353a52 | ||
|
|
934d6e3e91 | ||
|
|
630fb94466 | ||
|
|
87617d379b | ||
|
|
1b6b3306aa | ||
|
|
2cf74b3ed6 | ||
|
|
0cd6f97b68 | ||
|
|
3e2ead29da | ||
|
|
ebffdfad08 | ||
|
|
205a3ca528 | ||
|
|
a014984f65 | ||
|
|
c62f49fa86 | ||
|
|
5bf3f4029d | ||
|
|
b475f11c7c | ||
|
|
021913aba2 | ||
|
|
154d7d9c60 | ||
|
|
7d6ddd557d | ||
|
|
600345b3ec | ||
|
|
7923535849 | ||
|
|
e8d8e3f7d2 | ||
|
|
c6e6b51077 | ||
|
|
c1acca07c3 | ||
|
|
4cc52b9d24 | ||
|
|
0c4ef51b2a | ||
|
|
1027cb666d | ||
|
|
1920bbf862 | ||
|
|
1a80e0cc0c | ||
|
|
ebcd07b865 | ||
|
|
eaecce9630 | ||
|
|
17b7eb7c4b | ||
|
|
12838003f8 | ||
|
|
fa820b3e98 | ||
|
|
af867002f4 | ||
|
|
c6bc68d414 | ||
|
|
801cacef58 | ||
|
|
0df18df3f1 | ||
|
|
4d9108822c | ||
|
|
72f0b61cc0 | ||
|
|
99ea6e6fe0 | ||
|
|
99482d06d4 | ||
|
|
65faaffe78 | ||
|
|
81b2aa9d02 | ||
|
|
e07239e717 | ||
|
|
a5ca736ad7 | ||
|
|
320f938418 | ||
|
|
5e53ecfacb | ||
|
|
d46edfdd55 | ||
|
|
ec6e438144 | ||
|
|
5b06f0b2a7 | ||
|
|
ec1f5b5eff | ||
|
|
774d9b79c0 | ||
|
|
176ccb6b8a | ||
|
|
f0e31c0fd1 | ||
|
|
7c3f1080e0 | ||
|
|
3f760c778b | ||
|
|
1b6b4c6b42 | ||
|
|
6361a3798a | ||
|
|
83feefdc18 | ||
|
|
6d249528e4 | ||
|
|
cf8874c4f5 | ||
|
|
82955888b8 | ||
|
|
eec1461867 | ||
|
|
5e5dd241d4 | ||
|
|
8f53a44f7e | ||
|
|
03fd5acc95 | ||
|
|
b40f5511d1 | ||
|
|
89a662ed0a | ||
|
|
c79822e5ef | ||
|
|
3fd50eefb7 | ||
|
|
2cdc45703a | ||
|
|
5c77e78ad9 | ||
|
|
48d59b436c | ||
|
|
d829464843 | ||
|
|
0fb44db47c | ||
|
|
77cd246540 | ||
|
|
b4d0ea465b | ||
|
|
89cbed43dc | ||
|
|
27ba59fa7f | ||
|
|
df30a86305 | ||
|
|
02349dcb1d | ||
|
|
7bcca64f08 | ||
|
|
14bf1ce69b | ||
|
|
0034e75321 | ||
|
|
f6c9f8b151 | ||
|
|
76acf483f9 | ||
|
|
e7e175dd82 | ||
|
|
68ac46d1d2 | ||
|
|
2ecd34cbca | ||
|
|
b5b1f71fcc | ||
|
|
f5f7de4086 | ||
|
|
a331d59d33 | ||
|
|
0a6d066e92 | ||
|
|
1216ef0364 | ||
|
|
52e38ee687 | ||
|
|
fd53a54cf3 | ||
|
|
c6b7e1fc43 | ||
|
|
a7a1520b40 | ||
|
|
04881b10b1 | ||
|
|
561e5e2718 | ||
|
|
e83e127c15 | ||
|
|
3590861ffe | ||
|
|
a12307d7f9 | ||
|
|
25a9f9e426 | ||
|
|
f4644e2a47 | ||
|
|
b9a0d42815 | ||
|
|
f76beba434 | ||
|
|
60b6ec2f49 | ||
|
|
ce95210d1c | ||
|
|
953d92b177 | ||
|
|
4d9b4c9ad8 | ||
|
|
ee7b72dc66 | ||
|
|
8eb588d6a4 | ||
|
|
08e1f8fba1 | ||
|
|
454eedeb36 | ||
|
|
7e761b3f03 | ||
|
|
3dd51ee3b1 | ||
|
|
07b1356c6c | ||
|
|
23445785c9 | ||
|
|
f4a7fe3aaf | ||
|
|
6d31036ca1 | ||
|
|
5ceb3aa301 | ||
|
|
7fd602885f | ||
|
|
af75c3d63d | ||
|
|
cb9789668f | ||
|
|
c16508e2e4 | ||
|
|
912eb1217a | ||
|
|
3a328089a3 | ||
|
|
4c76444b2d | ||
|
|
403413bb26 | ||
|
|
8ea6a17942 | ||
|
|
15731d6135 | ||
|
|
8255481787 | ||
|
|
d2a919f71d | ||
|
|
915130aed9 | ||
|
|
901ffdfe5a | ||
|
|
8caaf85b36 | ||
|
|
1dc5e23a41 | ||
|
|
ee859db268 | ||
|
|
37f7fbbdec | ||
|
|
81f6937187 | ||
|
|
cbf5be50d1 | ||
|
|
1966ea2298 | ||
|
|
d96350d2c7 | ||
|
|
5cb96559d0 | ||
|
|
dffba7cd13 | ||
|
|
5ad122da40 | ||
|
|
54871f4ef8 | ||
|
|
d06e4f4c82 | ||
|
|
322b050e45 | ||
|
|
5cb9cfc820 | ||
|
|
ede260d4fa | ||
|
|
9a7de03830 | ||
|
|
b9b14f254a | ||
|
|
653ed92cf8 | ||
|
|
0d99c68b1b | ||
|
|
6c75dcc002 | ||
|
|
b76e1f65a3 | ||
|
|
de8845b89d | ||
|
|
f1eae764ab | ||
|
|
03c650b33c | ||
|
|
64b12c51e5 | ||
|
|
2d8e031904 | ||
|
|
28f0cd6e73 | ||
|
|
9a9179a23b | ||
|
|
48123bf1f7 | ||
|
|
ece4e52676 | ||
|
|
1d24d1e040 | ||
|
|
d0fd6b4868 | ||
|
|
328408fa30 | ||
|
|
0343bb248d | ||
|
|
e4dd1574b8 | ||
|
|
1e3486ee14 | ||
|
|
efe7470732 | ||
|
|
8acd5690f4 | ||
|
|
c2e3176a46 | ||
|
|
658252d46a | ||
|
|
5aaf7b3d6c | ||
|
|
031ac7616d | ||
|
|
098417d19f | ||
|
|
2f0a74a11e | ||
|
|
40c37c3448 | ||
|
|
77fb530120 | ||
|
|
faa0274521 | ||
|
|
8a253d3d95 |
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@@ -108,7 +108,7 @@ jobs:
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
export STAGING_DIR=$RUNNER_TEMP
|
||||
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]]; 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
|
||||
(
|
||||
@@ -553,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
|
||||
gzip lua/*.lua
|
||||
)
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ pktws_simple_split_tests()
|
||||
# $3 - splits
|
||||
# $4 - PRE args for nfqws2
|
||||
local pos ok ok_any pre="$4"
|
||||
local splitf splitfs="multisplit multidisorder"
|
||||
local splitf splitfs="multisplit $MULTIDISORDER"
|
||||
|
||||
ok_any=0
|
||||
for splitf in multisplit multidisorder; do
|
||||
for splitf in $splitfs; do
|
||||
eval need_$splitf=0
|
||||
ok=0
|
||||
for pos in $3; do
|
||||
@@ -38,7 +38,7 @@ pktws_check_https_tls()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
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"
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
@@ -24,8 +24,8 @@ pktws_check_http()
|
||||
for split in 'method+1 method+2' 'midsld-1 midsld' 'method+1 method+2,midsld'; do
|
||||
f="$(extract_arg 1 $split)"
|
||||
f2="$(extract_arg 2 $split)"
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f
|
||||
pktws_curl_test_update $1 $2 ${SEQOVL_PATTERN_HTTP:+--blob=$pat:@"$SEQOVL_PATTERN_HTTP" }$PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f:seqovl_pattern=$pat
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f
|
||||
pktws_curl_test_update $1 $2 ${SEQOVL_PATTERN_HTTP:+--blob=$pat:@"$SEQOVL_PATTERN_HTTP" }$PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f:seqovl_pattern=$pat
|
||||
done
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ pktws_seqovl_tests_tls()
|
||||
for split in '1 2' 'sniext sniext+1' 'sniext+3 sniext+4' 'midsld-1 midsld' '1 2,midsld'; do
|
||||
f="$(extract_arg 1 $split)"
|
||||
f2="$(extract_arg 2 $split)"
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
|
||||
done
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
|
||||
@@ -7,7 +7,7 @@ pktws_check_http()
|
||||
|
||||
local PAYLOAD="--payload http_req" split
|
||||
|
||||
for split in '' multisplit multidisorder; do
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split}
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http $PAYLOAD ${split:+$PAYLOAD --lua-desync=$split}
|
||||
done
|
||||
@@ -21,7 +21,7 @@ pktws_check_https_tls()
|
||||
|
||||
local PAYLOAD="--payload tls_client_hello" ok=0 pre="$3" split
|
||||
|
||||
for split in '' multisplit multidisorder; do
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=0x1603 ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,dupsid,rndsni ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
|
||||
@@ -22,7 +22,7 @@ pktws_check_http()
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
|
||||
# do not test fake + multidisorder if multidisorder works
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }multidisorder"
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }$MULTIDISORDER"
|
||||
|
||||
for splitf in $splitfs; do
|
||||
ok=0
|
||||
@@ -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
|
||||
@@ -95,7 +95,7 @@ pktws_check_https_tls()
|
||||
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ok_any ttls attls f fake fooling splitf splitfs= split splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local ok ok_any ttls attls f fake fooling splitf splitfs= split splits='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"
|
||||
|
||||
shift; shift
|
||||
@@ -112,7 +112,7 @@ pktws_check_https_tls()
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
|
||||
# do not test fake + multidisorder if multidisorder works
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }multidisorder"
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }$MULTIDISORDER"
|
||||
|
||||
ok_any=0
|
||||
for splitf in $splitfs; do
|
||||
|
||||
@@ -71,7 +71,7 @@ pktws_fake_https_vary_()
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
|
||||
@@ -29,7 +29,7 @@ pktws_check_hostfake()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ttls attls f fake fooling
|
||||
local ok ttls attls f fooling
|
||||
|
||||
[ "$need_hostfakesplit" = 0 ] && return 0
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http3()
|
||||
{
|
||||
# $1 - test function
|
||||
@@ -5,7 +7,7 @@ pktws_check_http3()
|
||||
|
||||
[ "$NOTEST_QUIC" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local repeats fake pos
|
||||
local repeats fake pos fool
|
||||
local PAYLOAD="--payload quic_initial"
|
||||
|
||||
if [ -n "$FAKE_QUIC" ]; then
|
||||
@@ -18,6 +20,12 @@ pktws_check_http3()
|
||||
pktws_curl_test_update $1 $2 ${FAKE_QUIC:+--blob=$fake:@"$FAKE_QUIC" }$PAYLOAD --lua-desync=fake:blob=$fake:repeats=$repeats && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
|
||||
[ "$IPV" = 6 ] && {
|
||||
for fool in ip6_hopbyhop ip6_destopt ip6_hopbyhop:ip6_destopt; do
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:$fool --lua-desync=drop
|
||||
done
|
||||
}
|
||||
|
||||
for pos in 8 16 32 64; do
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:ipfrag:ipfrag_pos_udp=$pos --lua-desync=drop && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
|
||||
@@ -2,6 +2,16 @@ FOOLINGS46_TCP=${FOOLINGS46_TCP:-"tcp_md5 badsum tcp_seq=-3000 tcp_seq=1000000 t
|
||||
FOOLINGS6_TCP=${FOOLINGS6_TCP:-"ip6_hopbyhop ip6_hopbyhop:ip6_hopbyhop2 ip6_destopt ip6_routing ip6_ah"}
|
||||
FOOLINGS_TCP="$FOOLINGS46_TCP"
|
||||
[ "$IPV" = 6 ] && FOOLINGS_TCP="$FOOLINGS_TCP $FOOLINGS6_TCP"
|
||||
FOOLINGS6_UDP="${FOOLINGS6_UDP:-$FOOLINGS6_TCP}"
|
||||
FOOLINGS_UDP="${FOOLINGS_UDP:-badsum}"
|
||||
[ "$IPV" = 6 ] && FOOLINGS_UDP="$FOOLINGS_UDP $FOOLINGS6_UDP"
|
||||
|
||||
FAKE_REPEATS=${FAKE_REPEATS:-1}
|
||||
|
||||
MIN_TTL=${MIN_TTL:-1}
|
||||
MAX_TTL=${MAX_TTL:-12}
|
||||
MIN_AUTOTTL_DELTA=${MIN_AUTOTTL_DELTA:-1}
|
||||
MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
|
||||
|
||||
# can use MULTIDISORER=multidisorder_legacy
|
||||
MULTIDISORDER=${MULTIDISORDER:-multidisorder}
|
||||
|
||||
@@ -40,10 +40,6 @@ IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-59780}
|
||||
CURL_MAX_TIME=${CURL_MAX_TIME:-2}
|
||||
CURL_MAX_TIME_QUIC=${CURL_MAX_TIME_QUIC:-$CURL_MAX_TIME}
|
||||
CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2}
|
||||
MIN_TTL=${MIN_TTL:-1}
|
||||
MAX_TTL=${MAX_TTL:-12}
|
||||
MIN_AUTOTTL_DELTA=${MIN_AUTOTTL_DELTA:-1}
|
||||
MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
|
||||
USER_AGENT=${USER_AGENT:-Mozilla}
|
||||
HTTP_PORT=${HTTP_PORT:-80}
|
||||
HTTPS_PORT=${HTTPS_PORT:-443}
|
||||
|
||||
@@ -2,8 +2,6 @@ std_ports
|
||||
ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes"
|
||||
IPSET_EXCLUDE="-m set ! --match-set nozapret"
|
||||
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
|
||||
IPBAN_EXCLUDE="-m set ! --match-set ipban"
|
||||
IPBAN_EXCLUDE6="-m set ! --match-set ipban6"
|
||||
|
||||
ipt()
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ filter_apply_hostlist_target()
|
||||
{
|
||||
# $1 - var name of nfqws params
|
||||
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 parmNA
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 param11 param12 param13 parmNA
|
||||
eval v="\$$1"
|
||||
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
|
||||
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
|
||||
@@ -40,14 +40,15 @@ filter_apply_hostlist_target()
|
||||
parm5="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}"
|
||||
parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
|
||||
parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
|
||||
parm8="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}"
|
||||
parm9="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}"
|
||||
parm10="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}"
|
||||
parm11="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}"
|
||||
parm12="--hostlist=$HOSTLIST_AUTO"
|
||||
parm8="${AUTOHOSTLIST_RETRANS_RESET:+--hostlist-auto-retrans-reset=$AUTOHOSTLIST_RETRANS_RESET}"
|
||||
parm9="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}"
|
||||
parm10="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}"
|
||||
parm11="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}"
|
||||
parm12="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}"
|
||||
parm13="--hostlist=$HOSTLIST_AUTO"
|
||||
}
|
||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}"
|
||||
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm10:+ $parm12}"
|
||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}${parm12:+ $parm12}"
|
||||
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm13:+ $parm13}"
|
||||
}
|
||||
v="$(replace_str $HOSTLIST_NOAUTO_MARKER "$parmNA" "$v")"
|
||||
v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")"
|
||||
|
||||
@@ -30,6 +30,7 @@ IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
|
||||
# NOTE : set PKT_IN, PKT_OUT variables appropriately
|
||||
AUTOHOSTLIST_INCOMING_MAXSEQ=4096
|
||||
AUTOHOSTLIST_RETRANS_MAXSEQ=32768
|
||||
AUTOHOSTLIST_RETRANS_RESET=1
|
||||
AUTOHOSTLIST_RETRANS_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_TIME=60
|
||||
@@ -97,11 +98,12 @@ FLOWOFFLOAD=donttouch
|
||||
#OPENWRT_WAN4="wan vpn"
|
||||
#OPENWRT_WAN6="wan6 vpn6"
|
||||
|
||||
# for routers based on desktop linux and macos. has no effect in openwrt.
|
||||
# for routers based on classic linux. has no effect in openwrt.
|
||||
# CHOOSE LAN and optinally WAN/WAN6 NETWORK INTERFACES
|
||||
# or leave them commented if its not router
|
||||
# it's possible to specify multiple interfaces like this : IFACE_WAN="eth0 eth1 eth2"
|
||||
# if IFACE_WAN6 is not defined it take the value of IFACE_WAN
|
||||
#IFACE_LAN=eth0
|
||||
#IFACE_WAN=eth1
|
||||
#IFACE_WAN6="ipsec0 wireguard0 he_net"
|
||||
|
||||
|
||||
@@ -93,9 +93,54 @@ v0.7
|
||||
|
||||
v0.7.1
|
||||
|
||||
* init.d: fix non-working incoming redirect
|
||||
* init.d: nft fix non-working incoming redirect
|
||||
* nfqws2: cancel reasm if server window size is smaller than expected reasm size
|
||||
* nfqws2: add EOL at the end of truncated buffered DLOG line if it's too large. increase log line buffer
|
||||
* nfqws2: autohostlist reset fail counter if udp_in > threshold
|
||||
* nfqws2: reduced default retrans maxseq to 32768
|
||||
* nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+
|
||||
|
||||
v0.7.2
|
||||
|
||||
* zapret-lib: fix broken is_retransmission()
|
||||
* zapret-auto: add success detector logic
|
||||
* nfqws2: clean lua cutoff on profile change
|
||||
* zapret-auto: separate hostkey function
|
||||
|
||||
v0.7.4
|
||||
|
||||
* nfqws2, zapret-lib : check tcp sequence range overflow
|
||||
* zapret-lib: seq compare functions
|
||||
* nfqws2: add l3_len, l4_len to dissect
|
||||
* nfqws2: fix broken l7proto profile rediscovery
|
||||
* winws2: harden sandbox. disable child process execution , some UI interaction and desktop settings change
|
||||
|
||||
v0.7.5
|
||||
|
||||
* zapret-auto: orchestrator "repeater"
|
||||
* blockcheck2: check http3 with ipv6 exthdr
|
||||
* github actions: separate target arm-old with LUA classic, not JIT
|
||||
* zapret-auto: iff/neg in repeater
|
||||
* zapret-antidpi: multidisorder_legacy
|
||||
* ipset: remove get_reestr_hostlist.sh and get_reestr_resolve.sh because zapret-info does not and will probably not ever update
|
||||
* nfqws2: fix "reasm cancelled" if no incoming traffic redirected
|
||||
* blockcheck2: MULTIDISORDER=multidisorder_legacy
|
||||
|
||||
v0.7.6
|
||||
|
||||
* nfqws2: reevaluate profile on l7/host discovery in any direction
|
||||
* nfqws2: dtls protocol detection
|
||||
* 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
|
||||
|
||||
4485
docs/manual.md
4485
docs/manual.md
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,20 @@ VPN. Может использоваться для частичной проз
|
||||
традиционные Linux-системы, FreeBSD, OpenBSD, Windows. В некоторых случаях возможна самостоятельная прикрутка
|
||||
решения к различным прошивкам.
|
||||
|
||||
[Полный мануал](manual.md)
|
||||
|
||||
|
||||
## Поддержать разработчика
|
||||
|
||||
Если вы считаете проект полезным и желаете поддержать разработку, направляйте ваши пожертвования на следующие адреса криптокошельков :
|
||||
|
||||
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E` (предпочительно сеть ERC-20)
|
||||
|
||||
BTC `bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve`
|
||||
|
||||
ETH `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
|
||||
|
||||
|
||||
## Чем это отличается от zapret1
|
||||
|
||||
zapret2 является дальнейшим развитием проекта zapret.
|
||||
@@ -22,12 +36,12 @@ zapret2 является дальнейшим развитием проекта
|
||||
или хотя бы область , в которой их можно искать, плюс владеющий базовыми навыками программирования.
|
||||
|
||||
*nfqws2* оставляет в себе практически тот же функционал - распознавание протоколов, реассемблинг, дешифровка, управление профилями, хостлисты, ipset-ы, базовая фильтрация.
|
||||
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования LUA.
|
||||
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования Lua.
|
||||
|
||||
LUA код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
|
||||
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
|
||||
Имеется библиотека хелперов, написанных на LUA, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
и с большей гибкостью.
|
||||
|
||||
Вы всегда сможете взять и дописать что-то свое. В этом и есть смысл, чтобы борьбой с DPI смог заняться любой, кто разбирается в пакетах.
|
||||
@@ -38,8 +52,8 @@ zapret2 - инструмент для таких энтузиастов. Но э
|
||||
|
||||
## С чего начать
|
||||
|
||||
Хотелось бы избежать "талмуда" на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть LUA код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
|
||||
|
||||
### Механика обработки трафика
|
||||
@@ -88,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]`. В примере реализована стратегия
|
||||
|
||||
```
|
||||
@@ -108,7 +122,7 @@ nfqws --qnum 200 --debug \
|
||||
Тип пейлоада - тип данных, содержащихся в пакете или группе пакетов. Например, протокол соединения может быть tls, а пейлоады - tls_client_hello, tls_server_hello, unknown.
|
||||
|
||||
Другое важное отличие - отсутствие жестко определенных фаз десинхронизации. То, что вы раньше писали как `fake,multisplit` реализуется двумя
|
||||
последовательно вызываемыми LUA функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
|
||||
последовательно вызываемыми Lua функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
|
||||
Может даже несколько раз вызываться одна и так же функция с разными параметрами. Так, например, можно послать несколько фейков, причем с разными фулингами.
|
||||
Конкретный вызов `--lua-desync` функции называется инстансом. Инстанс - это связка имени функции, номера вызова внутри профиля и номера самого профиля.
|
||||
Это похоже на одну программу, которую можно запустить много раз с разными параметрами.
|
||||
@@ -116,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`
|
||||
|
||||
@@ -153,15 +167,15 @@ range задается как `mX-mY`, `mX<mY`, `-mY`, `<mY`, `mX-`.
|
||||
Следующий профиль снова принимает значения по умолчанию.
|
||||
|
||||
Что будет, если вы не напишите фильтр `--payload` для fake или multisplit ? В *nfqws1* без `--dpi-desync-any-protocol` они работали только по известным пейлоадам.
|
||||
В *nfqws2* "any protocol" - режим по умолчанию. Однако, функции из библиотеки `zapret-antidpi.lua` написаны так, что по умолчанию работают только по известные пейлоадам
|
||||
В *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 - означает отправить как есть,
|
||||
@@ -287,22 +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" и сразу же отпустит пакет.
|
||||
|
||||
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы LUA даже в пределах первых 10 пакетов с данными.
|
||||
Почему именно `-d10` ? Чтобы хватило для отработки большинства вариантов стратегий, учитывая возможные ретрансмиссии и плохую связь. В winws2 по умолчанию включен параметр `--wf-tcp-empty=0`. Он блокирует перехват пустых пакетов с ACK, что позволяет примерно в 2 раза сэкономить на процессоре при интенсивных скачиваниях. Пустые ACK в большинстве стратегий не нужны. Но это же и ломает счетчик "n" - он не будет показывать реальное количество пакетов по соединению. Счетчик "d" работать будет как надо.
|
||||
|
||||
Почему нет "-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, например, -
|
||||
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола 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.
|
||||
|
||||
```
|
||||
@@ -348,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
|
||||
```
|
||||
@@ -370,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 паттерна.
|
||||
|
||||
@@ -403,4 +413,4 @@ nfqws2 \
|
||||
### Очень важный совет
|
||||
|
||||
Научитесь пользоваться `--debug` логом. Без него будет очень сложно понять *nfqws2* на начальном этапе и приспособиться к новой схеме.
|
||||
Ошибок будет много. Особенно, когда вы начнете писать свой LUA код. Их надо читать.
|
||||
Ошибок будет много. Особенно, когда вы начнете писать свой Lua код. Их надо читать.
|
||||
|
||||
BIN
files/fake/bgp_open.bin
Normal file
BIN
files/fake/bgp_open.bin
Normal file
Binary file not shown.
BIN
files/fake/bitcoin.bin
Normal file
BIN
files/fake/bitcoin.bin
Normal file
Binary file not shown.
BIN
files/fake/dns.bin
Normal file
BIN
files/fake/dns.bin
Normal file
Binary file not shown.
BIN
files/fake/dtls_serverhello.bin
Normal file
BIN
files/fake/dtls_serverhello.bin
Normal file
Binary file not shown.
BIN
files/fake/ntp4.bin
Normal file
BIN
files/fake/ntp4.bin
Normal file
Binary file not shown.
4
files/fake/rtsp_options.bin
Normal file
4
files/fake/rtsp_options.bin
Normal file
@@ -0,0 +1,4 @@
|
||||
OPTIONS rtsp://10.2.2.2:8554/ RTSP/1.0
|
||||
CSeq: 2
|
||||
User-Agent: LibVLC/3.0.16 (LIVE555 Streaming Media v2016.11.28)
|
||||
|
||||
1
files/fake/smtp_ehlo.bin
Normal file
1
files/fake/smtp_ehlo.bin
Normal file
@@ -0,0 +1 @@
|
||||
EHLO delta.peach.mil
|
||||
BIN
files/fake/snmp_get_next_request.bin
Normal file
BIN
files/fake/snmp_get_next_request.bin
Normal file
Binary file not shown.
BIN
files/fake/tls_alert.bin
Normal file
BIN
files/fake/tls_alert.bin
Normal file
Binary file not shown.
BIN
files/fake/tls_clienthello_google_com_tlsrec.bin
Normal file
BIN
files/fake/tls_clienthello_google_com_tlsrec.bin
Normal file
Binary file not shown.
BIN
files/fake/tls_serverhello_google_com_tls13.bin
Normal file
BIN
files/fake/tls_serverhello_google_com_tls13.bin
Normal file
Binary file not shown.
@@ -1,31 +1,22 @@
|
||||
# this custom script runs standard mode with extra firewall rules
|
||||
|
||||
# config: use TPWS_ENABLE_OVERRIDE, NFQWS_ENABLE_OVERRIDE to enable standard mode daemons
|
||||
# config: use NFQWS2_ENABLE_OVERRIDE to enable standard mode daemons
|
||||
# standard and override switches cannot be enabled simultaneously !
|
||||
|
||||
TPWS_ENABLE_OVERRIDE=${TPWS_ENABLE_OVERRIDE:-0}
|
||||
NFQWS_ENABLE_OVERRIDE=${NFQWS_ENABLE_OVERRIDE:-0}
|
||||
NFQWS2_ENABLE_OVERRIDE=${NFQWS2_ENABLE_OVERRIDE:-0}
|
||||
|
||||
# config: some if these values must be set in config. not setting any of these makes this script meaningless.
|
||||
# pre vars put ipt/nft code to the rule beginning
|
||||
#FW_EXTRA_PRE_TPWS_IPT=
|
||||
#FW_EXTRA_PRE_TPWS_NFT=
|
||||
#FW_EXTRA_PRE_NFQWS_IPT="-m mark --mark 0x10000000/0x10000000"
|
||||
#FW_EXTRA_PRE_NFQWS_NFT="mark and 0x10000000 != 0"
|
||||
#FW_EXTRA_PRE_NFQWS2_IPT="-m mark --mark 0x10000000/0x10000000"
|
||||
#FW_EXTRA_PRE_NFQWS2_NFT="mark and 0x10000000 != 0"
|
||||
# post vars put ipt/nft code to the rule end
|
||||
#FW_EXTRA_POST_TPWS_IPT=
|
||||
#FW_EXTRA_POST_TPWS_NFT=
|
||||
#FW_EXTRA_POST_NFQWS_IPT=
|
||||
#FW_EXTRA_POST_NFQWS_NFT=
|
||||
#FW_EXTRA_POST_NFQWS2_IPT=
|
||||
#FW_EXTRA_POST_NFQWS2_NFT=
|
||||
|
||||
check_std_intersect()
|
||||
{
|
||||
[ "$TPWS_ENABLE_OVERRIDE" = 1 -a "$TPWS_ENABLE" = 1 ] && {
|
||||
echo "ERROR ! both TPWS_ENABLE_OVERRIDE and TPWS_ENABLE are enabled"
|
||||
return 1
|
||||
}
|
||||
[ "$NFQWS_ENABLE_OVERRIDE" = 1 -a "$NFQWS_ENABLE" = 1 ] && {
|
||||
echo "ERROR ! both NFQWS_ENABLE_OVERRIDE and NFQWS_ENABLE are enabled"
|
||||
[ "$NFQWS2_ENABLE_OVERRIDE" = 1 -a "$NFQWS2_ENABLE" = 1 ] && {
|
||||
echo "ERROR ! both NFQWS2_ENABLE_OVERRIDE and NFQWS2_ENABLE are enabled"
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
@@ -37,7 +28,7 @@ zapret_custom_daemons()
|
||||
|
||||
check_std_intersect || return
|
||||
|
||||
local TPWS_SOCKS_ENABLE=0 TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE
|
||||
local NFQWS2_ENABLE=$NFQWS2_ENABLE_OVERRIDE
|
||||
standard_mode_daemons "$1"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
@@ -46,10 +37,8 @@ zapret_custom_firewall()
|
||||
|
||||
check_std_intersect || return
|
||||
|
||||
local FW_EXTRA_PRE FW_EXTRA_POST TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_TPWS_IPT" FW_EXTRA_POST="$FW_EXTRA_POST_TPWS_IPT"
|
||||
zapret_do_firewall_standard_tpws_rules_ipt $1
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS_IPT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS_IPT"
|
||||
local FW_EXTRA_PRE FW_EXTRA_POST NFQWS2_ENABLE=$NFQWS2_ENABLE_OVERRIDE
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS2_IPT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS2_IPT"
|
||||
zapret_do_firewall_standard_nfqws_rules_ipt $1
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
@@ -58,9 +47,7 @@ zapret_custom_firewall_nft()
|
||||
|
||||
check_std_intersect || return
|
||||
|
||||
local FW_EXTRA_PRE FW_EXTRA_POST TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_TPWS_NFT" FW_EXTRA_POST="$FW_EXTRA_POST_TPWS_NFT"
|
||||
zapret_apply_firewall_standard_tpws_rules_nft
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS_NFT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS_NFT"
|
||||
local FW_EXTRA_PRE FW_EXTRA_POST NFQWS2_ENABLE=$NFQWS2_ENABLE_OVERRIDE
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS2_NFT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS2_NFT"
|
||||
zapret_apply_firewall_standard_nfqws_rules_nft
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering
|
||||
# this custom script runs desync to DHT packets with udp payload length >=5 , without ipset/hostlist filtering
|
||||
# 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_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,11 +21,11 @@ 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 length --length 109:407 -m u32 --u32'
|
||||
uf4='0>>22&0x3C@8>>16=0x6431'
|
||||
uf6='48>>16=0x6431'
|
||||
f='-p udp -m u32 --u32'
|
||||
uf4='0>>22&0x3C@4>>16=13:0xFFFF&&0>>22&0x3C@8>>16=0x6431:0x6432'
|
||||
uf6='44>>16=13:0xFFFF&&48>>16=0x6431:0x6432'
|
||||
fw_nfqws_post $1 "$f $uf4 $first_packet_only" "$f $uf6 $first_packet_only" $QNUM_DHT4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
@@ -31,8 +33,8 @@ 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="meta length 109-407 meta l4proto udp @ih,0,16 0x6431"
|
||||
f="udp length ge 13 meta l4proto udp @ih,0,16 0x6431-0x6432"
|
||||
nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# this custom script runs desync to all wireguard handshake initiation packets
|
||||
# this custom script runs desync to all wireguard handshake initiation, response and cookie packets
|
||||
# NOTE: this works for original wireguard and may not work for 3rd party implementations such as xray
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation,wireguard_response,wireguard_cookie --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_WG4ALL
|
||||
alloc_qnum QNUM_WG4ALL
|
||||
@@ -21,7 +21,9 @@ zapret_custom_firewall()
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f='-p udp -m u32 --u32'
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x9c&&0>>22&0x3C@8=0x01000000" "$f 44>>16=0x9c&&48=0x01000000" $QNUM_WG4ALL
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=156&&0>>22&0x3C@8=0x01000000" "$f 44>>16=156&&48=0x01000000" $QNUM_WG4ALL
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=100&&0>>22&0x3C@8=0x02000000" "$f 44>>16=100&&48=0x02000000" $QNUM_WG4ALL
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=72&&0>>22&0x3C@8=0x03000000" "$f 44>>16=72&&48=0x03000000" $QNUM_WG4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
@@ -29,4 +31,8 @@ zapret_custom_firewall_nft()
|
||||
|
||||
local f="udp length 156 @ih,0,32 0x01000000"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
|
||||
local f="udp length 100 @ih,0,32 0x02000000"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
|
||||
local f="udp length 72 @ih,0,32 0x03000000"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
|
||||
}
|
||||
|
||||
@@ -2,19 +2,6 @@
|
||||
|
||||
ZAPRET=/etc/init.d/zapret2
|
||||
|
||||
check_lan()
|
||||
{
|
||||
IS_LAN=
|
||||
[ -n "$OPENWRT_LAN" ] || OPENWRT_LAN=lan
|
||||
for lan in $OPENWRT_LAN; do
|
||||
[ "$INTERFACE" = "$lan" ] && {
|
||||
IS_LAN=1
|
||||
break
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
[ -n "$INTERFACE" ] && [ "$ACTION" = ifup -o "$ACTION" = ifdown ] && [ -x "$ZAPRET" ] && "$ZAPRET" enabled && {
|
||||
SCRIPT=$(readlink "$ZAPRET")
|
||||
if [ -n "$SCRIPT" ]; then
|
||||
|
||||
1
init.d/windivert.filter.examples/windivert_part.dht.txt
Normal file
1
init.d/windivert.filter.examples/windivert_part.dht.txt
Normal file
@@ -0,0 +1 @@
|
||||
udp.Length>=5 and udp.Payload[0]=0x64 and udp.Payload[1]>=0x31 and udp.Payload[1]<=0x32
|
||||
@@ -1,4 +1,4 @@
|
||||
outbound and
|
||||
udp.PayloadLength>=256 and
|
||||
udp.Payload[0]>=0xC0 and udp.Payload[0]<0xD0 and
|
||||
udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1
|
||||
udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1
|
||||
@@ -1,3 +1,3 @@
|
||||
outbound and
|
||||
udp.PayloadLength=148 and
|
||||
udp.Payload[0]=0x01
|
||||
udp.PayloadLength=148 and udp.Payload[0]=0x01 or
|
||||
udp.PayloadLength=92 and udp.Payload[0]=0x02 or
|
||||
udp.PayloadLength=64 and udp.Payload[0]=0x03
|
||||
@@ -233,10 +233,10 @@ select_getlist()
|
||||
echo
|
||||
if ask_yes_no $D "do you want to auto download ip/host list"; then
|
||||
if [ "$MODE_FILTER" = "hostlist" -o "$MODE_FILTER" = "autohostlist" ] ; then
|
||||
GETLISTS="get_refilter_domains.sh get_antizapret_domains.sh get_reestr_resolvable_domains.sh get_reestr_hostlist.sh"
|
||||
GETLISTS="get_refilter_domains.sh get_antizapret_domains.sh get_reestr_resolvable_domains.sh"
|
||||
GETLIST_DEF="get_antizapret_domains.sh"
|
||||
else
|
||||
GETLISTS="get_user.sh get_refilter_ipsum.sh get_antifilter_ip.sh get_antifilter_ipsmart.sh get_antifilter_ipsum.sh get_antifilter_ipresolve.sh get_antifilter_allyouneed.sh get_reestr_resolve.sh get_reestr_preresolved.sh get_reestr_preresolved_smart.sh"
|
||||
GETLISTS="get_user.sh get_refilter_ipsum.sh get_antifilter_ip.sh get_antifilter_ipsmart.sh get_antifilter_ipsum.sh get_antifilter_ipresolve.sh get_antifilter_allyouneed.sh get_reestr_preresolved.sh get_reestr_preresolved_smart.sh"
|
||||
GETLIST_DEF="get_antifilter_allyouneed.sh"
|
||||
fi
|
||||
ask_list GETLIST "$GETLISTS" "$GETLIST_DEF" && write_config_var GETLIST
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
ZREESTR="$TMPDIR/zapret.txt.gz"
|
||||
IPB="$TMPDIR/ipb.txt"
|
||||
ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv.gz
|
||||
|
||||
dl_checked()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
# $5 - maxtime
|
||||
curl -k --fail --max-time $5 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$2" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
return 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
return 2
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
reestr_list()
|
||||
{
|
||||
LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }'
|
||||
}
|
||||
reestr_extract_ip()
|
||||
{
|
||||
LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}'
|
||||
}
|
||||
|
||||
ipban_fin()
|
||||
{
|
||||
getipban
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
}
|
||||
|
||||
dl_checked "$ZURL_REESTR" "$ZREESTR" 204800 251658240 600 || {
|
||||
ipban_fin
|
||||
exit 2
|
||||
}
|
||||
|
||||
reestr_list | sort -u | zz "$ZHOSTLIST"
|
||||
|
||||
reestr_extract_ip <"$ZREESTR" >"$IPB"
|
||||
|
||||
rm -f "$ZREESTR"
|
||||
[ "$DISABLE_IPV4" != "1" ] && $AWK '/^([0-9]{1,3}\.){3}[0-9]{1,3}($|(\/[0-9]{2}$))/' "$IPB" | cut_local | ip2net4 | zz "$ZIPLIST_IPBAN"
|
||||
[ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6"
|
||||
rm -f "$IPB"
|
||||
|
||||
hup_zapret_daemons
|
||||
|
||||
ipban_fin
|
||||
|
||||
exit 0
|
||||
@@ -10,8 +10,8 @@ TMPLIST="$TMPDIR/list.txt"
|
||||
BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main"
|
||||
URL4="$BASEURL/reestr_resolved4.txt"
|
||||
URL6="$BASEURL/reestr_resolved6.txt"
|
||||
IPB4="$BASEURL/reestr_ipban4.txt"
|
||||
IPB6="$BASEURL/reestr_ipban6.txt"
|
||||
#IPB4="$BASEURL/reestr_ipban4.txt"
|
||||
#IPB6="$BASEURL/reestr_ipban6.txt"
|
||||
|
||||
dl()
|
||||
{
|
||||
@@ -35,12 +35,12 @@ dl()
|
||||
|
||||
getuser && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
dl "$URL4" "$ZIPLIST" 32768 4194304
|
||||
dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
dl "$URL4" "$ZIPLIST" 4096 4194304
|
||||
# dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
dl "$URL6" "$ZIPLIST6" 8192 4194304
|
||||
dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
dl "$URL6" "$ZIPLIST6" 2048 4194304
|
||||
# dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ TMPLIST="$TMPDIR/list.txt"
|
||||
BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main"
|
||||
URL4="$BASEURL/reestr_smart4.txt"
|
||||
URL6="$BASEURL/reestr_smart6.txt"
|
||||
IPB4="$BASEURL/reestr_ipban4.txt"
|
||||
IPB6="$BASEURL/reestr_ipban6.txt"
|
||||
#IPB4="$BASEURL/reestr_ipban4.txt"
|
||||
#IPB6="$BASEURL/reestr_ipban6.txt"
|
||||
|
||||
dl()
|
||||
{
|
||||
@@ -35,12 +35,12 @@ dl()
|
||||
|
||||
getuser && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
dl "$URL4" "$ZIPLIST" 32768 4194304
|
||||
dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
dl "$URL4" "$ZIPLIST" 4096 4194304
|
||||
# dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
dl "$URL6" "$ZIPLIST6" 8192 4194304
|
||||
dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
dl "$URL6" "$ZIPLIST6" 2048 4194304
|
||||
# dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ TMPLIST="$TMPDIR/list_nethub.txt"
|
||||
|
||||
BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main"
|
||||
URL="$BASEURL/reestr_hostname_resolvable.txt"
|
||||
IPB4="$BASEURL/reestr_ipban4.txt"
|
||||
IPB6="$BASEURL/reestr_ipban6.txt"
|
||||
#IPB4="$BASEURL/reestr_ipban4.txt"
|
||||
#IPB6="$BASEURL/reestr_ipban6.txt"
|
||||
|
||||
dl()
|
||||
{
|
||||
@@ -36,8 +36,8 @@ dl "$URL" "$ZHOSTLIST" 65536 67108864
|
||||
|
||||
hup_zapret_daemons
|
||||
|
||||
[ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
[ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
#[ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
#[ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
|
||||
getipban
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
ZREESTR="$TMPDIR/zapret.txt.gz"
|
||||
ZDIG="$TMPDIR/zapret-dig.txt"
|
||||
IPB="$TMPDIR/ipb.txt"
|
||||
ZIPLISTTMP="$TMPDIR/zapret-ip.txt"
|
||||
#ZURL=https://reestr.rublacklist.net/api/current
|
||||
ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv.gz
|
||||
|
||||
dl_checked()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
# $5 - maxtime
|
||||
curl -k --fail --max-time $5 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$2" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
return 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
return 2
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
reestr_list()
|
||||
{
|
||||
LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }'
|
||||
}
|
||||
reestr_extract_ip()
|
||||
{
|
||||
LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}'
|
||||
}
|
||||
|
||||
getuser && {
|
||||
# both disabled
|
||||
[ "$DISABLE_IPV4" = "1" ] && [ "$DISABLE_IPV6" = "1" ] && exit 0
|
||||
|
||||
dl_checked "$ZURL_REESTR" "$ZREESTR" 204800 251658240 600 || exit 2
|
||||
|
||||
echo preparing ipban list ..
|
||||
|
||||
reestr_extract_ip <"$ZREESTR" >"$IPB"
|
||||
[ "$DISABLE_IPV4" != "1" ] && $AWK '/^([0-9]{1,3}\.){3}[0-9]{1,3}($|(\/[0-9]{2}$))/' "$IPB" | cut_local | ip2net4 | zz "$ZIPLIST_IPBAN"
|
||||
[ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6"
|
||||
rm -f "$IPB"
|
||||
|
||||
echo preparing dig list ..
|
||||
reestr_list | sort -u >"$ZDIG"
|
||||
|
||||
rm -f "$ZREESTR"
|
||||
|
||||
echo digging started. this can take long ...
|
||||
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
filedigger "$ZDIG" 4 | cut_local >"$ZIPLISTTMP" || {
|
||||
rm -f "$ZDIG"
|
||||
exit 1
|
||||
}
|
||||
ip2net4 <"$ZIPLISTTMP" | zz "$ZIPLIST"
|
||||
rm -f "$ZIPLISTTMP"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
filedigger "$ZDIG" 6 | cut_local6 >"$ZIPLISTTMP" || {
|
||||
rm -f "$ZDIG"
|
||||
exit 1
|
||||
}
|
||||
ip2net6 <"$ZIPLISTTMP" | zz "$ZIPLIST6"
|
||||
rm -f "$ZIPLISTTMP"
|
||||
}
|
||||
rm -f "$ZDIG"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
@@ -287,6 +287,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("fake: '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 +373,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 +383,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 +406,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 +414,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 +435,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
|
||||
@@ -416,12 +465,62 @@ function multisplit(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
-- internal function for code deduplication. do not call directly
|
||||
function pos_normalize(pos, low, hi)
|
||||
return (pos>=low and pos<hi) and (pos-low+1) or nil
|
||||
end
|
||||
-- internal function for code deduplication. do not call directly
|
||||
function pos_array_normalize(pos, low, hi)
|
||||
-- remove positions outside of hi,low range. normalize others to low
|
||||
local i=1
|
||||
while i<=#pos do
|
||||
pos[i] = pos_normalize(pos[i], low, hi)
|
||||
if pos[i] then
|
||||
i = i + 1
|
||||
else
|
||||
table.remove(pos, i);
|
||||
end
|
||||
end
|
||||
end
|
||||
-- internal function for code deduplication. do not call directly
|
||||
function multidisorder_send(desync, data, seqovl, pos)
|
||||
for i=#pos,0,-1 do
|
||||
local pos_start = pos[i] or 1
|
||||
local pos_end = i<#pos and pos[i+1]-1 or #data
|
||||
local part = string.sub(data,pos_start,pos_end)
|
||||
local ovl=0
|
||||
if i==1 and seqovl and seqovl>0 then
|
||||
if seqovl>=pos[1] then
|
||||
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="\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
|
||||
if b_debug then DLOG("multidisorder: sending part "..(i+1).." "..(pos_start-1).."-"..(pos_end-1).." len="..#part.." seqovl="..ovl.." : "..hexdump_dlog(part)) end
|
||||
if not rawsend_payload_segmented(desync,part,pos_start-1-ovl) then
|
||||
return VERDICT_PASS
|
||||
end
|
||||
end
|
||||
return VERDICT_DROP
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=multidisorder"
|
||||
-- algorithm is not 100% the same as in nfqws1. multi-segment queries can produce different segment ordering.
|
||||
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
|
||||
-- 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 : 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
|
||||
@@ -429,7 +528,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
|
||||
@@ -440,32 +542,16 @@ function multidisorder(ctx, desync)
|
||||
if b_debug then DLOG("multidisorder: resolved split pos: "..table.concat(zero_based_pos(pos)," ")) end
|
||||
delete_pos_1(pos) -- cannot split at the first byte
|
||||
if #pos>0 then
|
||||
for i=#pos,0,-1 do
|
||||
local pos_start = pos[i] or 1
|
||||
local pos_end = i<#pos and pos[i+1]-1 or #data
|
||||
local part = string.sub(data,pos_start,pos_end)
|
||||
local seqovl=0
|
||||
if i==1 and desync.arg.seqovl then
|
||||
seqovl = resolve_pos(data, desync.l7payload, desync.arg.seqovl)
|
||||
if not seqovl then
|
||||
DLOG("multidisorder: seqovl cancelled because could not resolve marker '"..desync.arg.seqovl.."'")
|
||||
seqovl = 0
|
||||
else
|
||||
seqovl = seqovl - 1
|
||||
if seqovl>=(pos[1]-1) then
|
||||
DLOG("multidisorder: seqovl cancelled because seqovl "..seqovl.." is not less than the first split pos "..(pos[1]-1))
|
||||
seqovl = 0
|
||||
else
|
||||
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
end
|
||||
end
|
||||
if b_debug then DLOG("multidisorder: sending part "..(i+1).." "..(pos_start-1).."-"..(pos_end-1).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
|
||||
if not rawsend_payload_segmented(desync,part,pos_start-1-seqovl) then
|
||||
return VERDICT_PASS
|
||||
local seqovl
|
||||
if desync.arg.seqovl then
|
||||
seqovl = resolve_pos(data, desync.l7payload, desync.arg.seqovl)
|
||||
if not seqovl then
|
||||
DLOG("multidisorder: seqovl cancelled because could not resolve marker '"..desync.arg.seqovl.."'")
|
||||
end
|
||||
end
|
||||
if multidisorder_send(desync, data, seqovl, pos)==VERDICT_PASS then
|
||||
return VERDICT_PASS
|
||||
end
|
||||
replay_drop_set(desync)
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
else
|
||||
@@ -481,6 +567,60 @@ function multidisorder(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=multidisorder". segment ordering is the same as in nfqws1
|
||||
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
|
||||
-- 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)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
local data = desync.dis.payload
|
||||
local fulldata = desync.reasm_data
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
local range_low = (desync.reasm_offset or 0) + 1
|
||||
local range_hi = range_low + #data
|
||||
local spos = desync.arg.pos or "2"
|
||||
-- check debug to save CPU
|
||||
if b_debug then DLOG("multidisorder_legacy: split pos: "..spos) end
|
||||
local pos = resolve_multi_pos(fulldata, desync.l7payload, spos)
|
||||
if b_debug then DLOG("multidisorder_legacy: resolved split pos: "..table.concat(zero_based_pos(pos)," ")) end
|
||||
DLOG("multidisorder_legacy: reasm piece range: "..(range_low-1).."-"..(range_hi-2))
|
||||
pos_array_normalize(pos, range_low, range_hi)
|
||||
delete_pos_1(pos) -- cannot split at the first byte
|
||||
if #pos>0 then
|
||||
if b_debug then DLOG("multidisorder_legacy: normalized split pos: "..table.concat(zero_based_pos(pos)," ")) end
|
||||
local seqovl
|
||||
if desync.arg.seqovl then
|
||||
seqovl = resolve_pos(fulldata, desync.l7payload, desync.arg.seqovl)
|
||||
if seqovl then
|
||||
DLOG("multidisorder_legacy: resolved seqovl pos: "..(seqovl-1))
|
||||
seqovl = pos_normalize(seqovl, range_low, range_hi)
|
||||
if seqovl then
|
||||
DLOG("multidisorder_legacy: normalized seqovl pos: "..(seqovl-1))
|
||||
else
|
||||
DLOG("multidisorder_legacy: normalized seqovl pos is outside of the reasm piece range")
|
||||
end
|
||||
else
|
||||
DLOG("multidisorder_legacy: seqovl cancelled because could not resolve marker '"..desync.arg.seqovl.."'")
|
||||
end
|
||||
end
|
||||
return multidisorder_send(desync, data, seqovl, pos)
|
||||
else
|
||||
DLOG("multidisorder_legacy: no normalized split pos in this packet")
|
||||
-- send as is with applied options
|
||||
if rawsend_payload_segmented(desync) then
|
||||
return VERDICT_DROP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=hostfakesplit"
|
||||
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct. FOOLING AND REPEATS APPLIED ONLY TO FAKES.
|
||||
-- arg : host=<str> - hostname template. generate hosts like "random.template". example : e8nzn.vk.com
|
||||
@@ -488,6 +628,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
|
||||
@@ -495,7 +636,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
|
||||
@@ -601,6 +745,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
|
||||
@@ -608,7 +753,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
|
||||
@@ -616,7 +764,7 @@ function fakedsplit(ctx, desync)
|
||||
local pos = resolve_pos(data, desync.l7payload, spos)
|
||||
if pos then
|
||||
if pos == 1 then
|
||||
DLOG("multidisorder: split pos resolved to 0. cannot split.")
|
||||
DLOG("fakedsplit: split pos resolved to 0. cannot split.")
|
||||
else
|
||||
if b_debug then DLOG("fakedsplit: resolved split pos: "..tostring(pos-1)) end
|
||||
|
||||
@@ -640,7 +788,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
|
||||
@@ -694,6 +849,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
|
||||
@@ -701,7 +857,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
|
||||
@@ -709,7 +868,7 @@ function fakeddisorder(ctx, desync)
|
||||
local pos = resolve_pos(data, desync.l7payload, spos)
|
||||
if pos then
|
||||
if pos == 1 then
|
||||
DLOG("multidisorder: split pos resolved to 0. cannot split.")
|
||||
DLOG("fakeddisorder: split pos resolved to 0. cannot split.")
|
||||
else
|
||||
if b_debug then DLOG("fakeddisorder: resolved split pos: "..tostring(pos-1)) end
|
||||
|
||||
@@ -738,7 +897,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
|
||||
@@ -795,6 +961,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)
|
||||
@@ -804,7 +971,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
|
||||
@@ -818,7 +988,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
|
||||
@@ -874,7 +1051,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)
|
||||
@@ -882,7 +1059,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)
|
||||
|
||||
@@ -1,20 +1,48 @@
|
||||
-- standard automation/orchestration code
|
||||
-- this is related to making dynamic strategy decisions without rewriting or altering strategy function code
|
||||
-- orchestrators can decide which instances to call or not to call or pass them dynamic arguments
|
||||
-- failure detectors test potential block conditions for orchestrators
|
||||
-- failure and success detectors test potential block conditions for orchestrators
|
||||
|
||||
-- standard host key generator for per-host storage
|
||||
-- arg: reqhost - require hostname, do not work with ip
|
||||
-- arg: key - a string - table name inside autostate table. to allow multiple orchestrator instances to use single host storage
|
||||
function automate_host_record(desync)
|
||||
local hostkey, askey
|
||||
if desync.arg.reqhost then
|
||||
hostkey = desync.track and desync.track.hostname
|
||||
else
|
||||
hostkey = host_or_ip(desync)
|
||||
-- arg: nld=N - cut hostname to N level domain. NLD=2 static.intranet.microsoft.com => microsoft.com
|
||||
function standard_hostkey(desync)
|
||||
local hostkey = desync.track and desync.track.hostname
|
||||
if hostkey then
|
||||
if desync.arg.nld and tonumber(desync.arg.nld)>0 and not (desync.track and desync.track.hostname_is_ip) then
|
||||
-- dissect_nld returns nil if domain is invalid or does not have this NLD
|
||||
-- fall back to original hostkey if it fails
|
||||
local hktemp = dissect_nld(hostkey, tonumber(desync.arg.nld))
|
||||
if hktemp then
|
||||
hostkey = hktemp
|
||||
end
|
||||
end
|
||||
elseif not desync.arg.reqhost then
|
||||
hostkey = host_ip(desync)
|
||||
end
|
||||
return hostkey
|
||||
end
|
||||
|
||||
-- per-host storage
|
||||
-- arg: key - a string - table name inside autostate table. to allow multiple orchestrator instances to use single host storage
|
||||
-- arg: hostkey - hostkey generator function name
|
||||
function automate_host_record(desync)
|
||||
local hostkey, hkf, askey
|
||||
|
||||
if desync.arg.hostkey then
|
||||
if type(_G[desync.arg.hostkey])~="function" then
|
||||
error("automate: invalid hostkey function '"..desync.arg.hostkey.."'")
|
||||
end
|
||||
hkf = _G[desync.arg.hostkey]
|
||||
else
|
||||
hkf = standard_hostkey
|
||||
end
|
||||
hostkey = hkf(desync)
|
||||
if not hostkey then
|
||||
DLOG("automate: host record key unavailable")
|
||||
return nil
|
||||
end
|
||||
|
||||
askey = (desync.arg.key and #desync.arg.key>0) and desync.arg.key or desync.func_instance
|
||||
DLOG("automate: host record key 'autostate."..askey.."."..hostkey.."'")
|
||||
if not autostate then
|
||||
@@ -28,6 +56,7 @@ function automate_host_record(desync)
|
||||
end
|
||||
return autostate[askey][hostkey]
|
||||
end
|
||||
-- per-connection storage
|
||||
function automate_conn_record(desync)
|
||||
if not desync.track.lua_state.automate then
|
||||
desync.track.lua_state.automate = {}
|
||||
@@ -65,6 +94,13 @@ function automate_failure_counter(hrec, crec, fails, maxtime)
|
||||
end
|
||||
return false
|
||||
end
|
||||
-- resets failure counter if it has started counting
|
||||
function automate_failure_counter_reset(hrec)
|
||||
if hrec.failure_counter then
|
||||
DLOG("automate: failure counter reset")
|
||||
hrec.failure_counter = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- location is url compatible with Location: header
|
||||
-- hostname is original hostname
|
||||
@@ -78,6 +114,19 @@ function is_dpi_redirect(hostname, location)
|
||||
return false
|
||||
end
|
||||
|
||||
function standard_detector_defaults(arg)
|
||||
return {
|
||||
inseq = tonumber(arg.inseq) or 4096,
|
||||
retrans = tonumber(arg.retrans) or 3,
|
||||
maxseq = tonumber(arg.maxseq) or 32768,
|
||||
udp_in = tonumber(arg.udp_in) or 1,
|
||||
udp_out = tonumber(arg.udp_out) or 4,
|
||||
no_http_redirect = arg.no_http_redirect,
|
||||
no_rst = arg.no_rst,
|
||||
reset = arg.reset
|
||||
}
|
||||
end
|
||||
|
||||
-- standard failure detector
|
||||
-- works with tcp and udp
|
||||
-- detected failures:
|
||||
@@ -85,46 +134,48 @@ end
|
||||
-- incoming http redirection
|
||||
-- outgoing retransmissions
|
||||
-- udp too much out with too few in
|
||||
-- arg: seq=<rseq> - tcp: if packet is beyond this relative sequence number treat this connection as successful. default is 64K
|
||||
-- arg: maxseq=<rseq> - tcp: test retransmissions only within this relative sequence. default is 32K
|
||||
-- arg: retrans=N - tcp: retrans count threshold. default is 3
|
||||
-- arg: rst=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 1
|
||||
-- arg: reset - send RST to retransmitter to break long wait
|
||||
-- arg: inseq=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 4K
|
||||
-- arg: no_http_redirect - tcp: disable http_reply dpi redirect trigger
|
||||
-- arg: no_rst - tcp: disable incoming RST trigger
|
||||
-- arg: udp_out - udp: >= outgoing udp packets. default is 4
|
||||
-- arg: udp_in - udp: with <= incoming udp packets. default is 1
|
||||
function standard_failure_detector(desync, crec, arg)
|
||||
if crec.nocheck then return false end
|
||||
|
||||
local seq_rst = tonumber(arg.rst) or 1
|
||||
local retrans = tonumber(arg.retrans) or 3
|
||||
local maxseq = tonumber(arg.seq) or 0x10000
|
||||
local udp_in = tonumber(arg.udp_in) or 1
|
||||
local udp_out = tonumber(arg.udp_out) or 4
|
||||
|
||||
function standard_failure_detector(desync, crec)
|
||||
local arg = standard_detector_defaults(desync.arg)
|
||||
local trigger = false
|
||||
if desync.dis.tcp then
|
||||
local seq = pos_get(desync,'s')
|
||||
if maxseq and seq>maxseq then
|
||||
DLOG("standard_failure_detector: s"..seq.." is beyond s"..maxseq..". treating connection as successful")
|
||||
crec.nocheck = true
|
||||
return false
|
||||
end
|
||||
|
||||
if desync.outgoing then
|
||||
if #desync.dis.payload>0 and retrans and (crec.retrans or 0)<retrans then
|
||||
if #desync.dis.payload>0 and arg.retrans and arg.maxseq>0 and seq<=arg.maxseq and (crec.retrans or 0)<arg.retrans then
|
||||
if is_retransmission(desync) then
|
||||
crec.retrans = crec.retrans and (crec.retrans+1) or 1
|
||||
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..retrans)
|
||||
trigger = crec.retrans>=retrans
|
||||
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..arg.retrans)
|
||||
trigger = crec.retrans>=arg.retrans
|
||||
if trigger and arg.reset then
|
||||
local dis = deepcopy(desync.dis)
|
||||
dis.payload = nil
|
||||
dis_reverse(dis)
|
||||
dis.tcp.th_flags = TH_RST
|
||||
dis.tcp.th_win = desync.track and desync.track.pos.reverse.tcp.winsize or 64
|
||||
dis.tcp.options = nil
|
||||
if dis.ip6 then
|
||||
dis.ip6.ip6_flow = (desync.track and desync.track.pos.reverse.ip6_flow) and desync.track.pos.reverse.ip6_flow or 0x60000000;
|
||||
end
|
||||
DLOG("standard_failure_detector: sending RST to retransmitter")
|
||||
rawsend_dissect(dis, {ifout = desync.ifin})
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if seq_rst and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 then
|
||||
trigger = seq<=seq_rst
|
||||
if not arg.no_rst and arg.inseq>0 and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 and seq>=1 then
|
||||
trigger = seq<=arg.inseq
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: incoming RST s"..seq.." in range s"..seq_rst)
|
||||
DLOG("standard_failure_detector: incoming RST s"..seq.." in range s"..arg.inseq)
|
||||
else
|
||||
DLOG("standard_failure_detector: not counting incoming RST s"..seq.." beyond s"..seq_rst)
|
||||
DLOG("standard_failure_detector: not counting incoming RST s"..seq.." beyond s"..arg.inseq)
|
||||
end
|
||||
end
|
||||
elseif not arg.no_http_redirect and desync.l7payload=="http_reply" and desync.track.hostname then
|
||||
@@ -143,13 +194,13 @@ function standard_failure_detector(desync, crec, arg)
|
||||
end
|
||||
elseif desync.dis.udp then
|
||||
if desync.outgoing then
|
||||
if udp_out then
|
||||
local udp_in = udp_in or 0
|
||||
trigger = desync.track.pos.direct.pcounter>=udp_out and desync.track.pos.reverse.pcounter<=udp_in
|
||||
if arg.udp_out>0 then
|
||||
local pos_out = pos_get(desync,'n',false)
|
||||
local pos_in = pos_get(desync,'n',true)
|
||||
trigger = pos_out>=arg.udp_out and pos_in<=arg.udp_in
|
||||
if trigger then
|
||||
crec.nocheck = true
|
||||
if b_debug then
|
||||
DLOG("standard_failure_detector: udp_out "..desync.track.pos.direct.pcounter..">="..udp_out.." udp_in "..desync.track.pos.reverse.pcounter.."<="..udp_in)
|
||||
DLOG("standard_failure_detector: arg.udp_out "..pos_out..">="..arg.udp_out.." arg.udp_in "..pos_in.."<="..arg.udp_in)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -158,17 +209,102 @@ function standard_failure_detector(desync, crec, arg)
|
||||
return trigger
|
||||
end
|
||||
|
||||
-- standard success detector
|
||||
-- success means previous failures were temporary and counter should be reset
|
||||
-- detected successes:
|
||||
-- tcp: outgoing seq is beyond 'maxseq' and maxseq>0
|
||||
-- tcp: incoming seq is beyond 'inseq' and inseq>0
|
||||
-- udp: incoming packets count > `udp_in` and `udp_out`>0
|
||||
-- arg: maxseq=<rseq> - tcp: success if outgoing relative sequence is beyond this value. default is 32K
|
||||
-- arg: inseq=<rseq> - tcp: success if incoming relative sequence is beyond this value. default is 4K
|
||||
-- arg: udp_out - udp : must be nil or >0 to test udp_in
|
||||
-- arg: udp_in - udp: if number if incoming packets > udp_in it means success
|
||||
function standard_success_detector(desync, crec)
|
||||
local arg = standard_detector_defaults(desync.arg)
|
||||
if desync.dis.tcp then
|
||||
local seq = pos_get(desync,'s')
|
||||
if desync.outgoing then
|
||||
if arg.maxseq>0 and seq>arg.maxseq then
|
||||
DLOG("standard_success_detector: outgoing s"..seq.." is beyond s"..arg.maxseq..". treating connection as successful")
|
||||
return true
|
||||
end
|
||||
else
|
||||
if arg.inseq>0 and seq>arg.inseq then
|
||||
DLOG("standard_success_detector: incoming s"..seq.." is beyond s"..arg.inseq..". treating connection as successful")
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif desync.dis.udp then
|
||||
if not desync.outgoing then
|
||||
local pos = pos_get(desync,'n')
|
||||
if arg.udp_out>0 and pos>arg.udp_in then
|
||||
if b_debug then
|
||||
DLOG("standard_success_detector: arg.udp_in "..pos..">"..arg.udp_in)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- calls success and failure detectors
|
||||
-- resets counter if success is detected
|
||||
-- increases counter if failure is detected
|
||||
-- returns true if failure counter exceeds threshold
|
||||
function automate_failure_check(desync, hrec, crec)
|
||||
if crec.nocheck then return false end
|
||||
|
||||
local failure_detector, success_detector
|
||||
if desync.arg.failure_detector then
|
||||
if type(_G[desync.arg.failure_detector])~="function" then
|
||||
error("automate: invalid failure detector function '"..desync.arg.failure_detector.."'")
|
||||
end
|
||||
failure_detector = _G[desync.arg.failure_detector]
|
||||
else
|
||||
failure_detector = standard_failure_detector
|
||||
end
|
||||
if desync.arg.success_detector then
|
||||
if type(_G[desync.arg.success_detector])~="function" then
|
||||
error("automate: invalid success detector function '"..desync.arg.success_detector.."'")
|
||||
end
|
||||
success_detector = _G[desync.arg.success_detector]
|
||||
else
|
||||
success_detector = standard_success_detector
|
||||
end
|
||||
|
||||
if success_detector(desync, crec) then
|
||||
crec.nocheck = true
|
||||
DLOG("automate: success detected")
|
||||
automate_failure_counter_reset(hrec)
|
||||
return false
|
||||
end
|
||||
if failure_detector(desync, crec) then
|
||||
crec.nocheck = true
|
||||
DLOG("automate: failure detected")
|
||||
local fails = tonumber(desync.arg.fails) or 3
|
||||
local maxtime = tonumber(desync.arg.time) or 60
|
||||
return automate_failure_counter(hrec, crec, fails, maxtime)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- circularily change strategy numbers when failure count reaches threshold ('fails')
|
||||
-- works with tcp only
|
||||
-- this orchestrator requires redirection of incoming traffic to cache RST and http replies !
|
||||
-- each orchestrated instance must have strategy=N arg, where N starts from 1 and increment without gaps
|
||||
-- if 'final' arg is present in an orchestrated instance it stops rotation
|
||||
-- arg: fails=N - failture count threshold. default is 3
|
||||
-- arg: time=<sec> - if last failure happened earlier than `maxtime` seconds ago - reset failure counter. default is 60.
|
||||
-- arg: reqhost - pass with no tampering if hostname is unavailable
|
||||
-- arg: detector - failure detector function name.
|
||||
-- arg: success_detector - success detector function name
|
||||
-- arg: failure_detector - failure detector function name
|
||||
-- arg: hostkey - hostkey generator function name
|
||||
-- args for failure detector - see standard_failure_detector or your own detector
|
||||
-- test case: nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --in-range=-s1 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
-- args for success detector - see standard_success_detector or your own detector
|
||||
-- args for hostkey generator - see standard_hostkey or your own generator
|
||||
-- test case: --in-range=-s34228 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
function circular(ctx, desync)
|
||||
local function count_strategies(hrec)
|
||||
if not hrec.ctstrategy then
|
||||
@@ -223,26 +359,11 @@ function circular(ctx, desync)
|
||||
local verdict = VERDICT_PASS
|
||||
if hrec.final~=hrec.nstrategy then
|
||||
local crec = automate_conn_record(desync)
|
||||
local fails = tonumber(desync.arg.fails) or 3
|
||||
local maxtime = tonumber(desync.arg.time) or 60
|
||||
local failure_detector
|
||||
if desync.arg.detector then
|
||||
if type(_G[desync.arg.detector])~="function" then
|
||||
error("circular: invalid failure detector function '"..desync.arg.detector.."'")
|
||||
end
|
||||
failure_detector = _G[desync.arg.detector]
|
||||
else
|
||||
failure_detector = standard_failure_detector
|
||||
end
|
||||
if failure_detector(desync,crec,desync.arg) then
|
||||
-- failure happened. count failures.
|
||||
if automate_failure_counter(hrec, crec, fails, maxtime) then
|
||||
-- counter reaches threshold. circular strategy change
|
||||
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
|
||||
DLOG("circular: rotate strategy to "..hrec.nstrategy)
|
||||
if hrec.nstrategy == hrec.final then
|
||||
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
|
||||
end
|
||||
if automate_failure_check(desync, hrec, crec) then
|
||||
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
|
||||
DLOG("circular: rotate strategy to "..hrec.nstrategy)
|
||||
if hrec.nstrategy == hrec.final then
|
||||
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -271,7 +392,7 @@ function cond_random(desync)
|
||||
return math.random(0,99)<(tonumber(desync.arg.percent) or 50)
|
||||
end
|
||||
-- this iif function detects packets having 'arg.pattern' string in their payload
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --lua-desync=condition:iff=cond_payload_str:pattern=1234 --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
|
||||
-- test case : --lua-desync=condition:iff=cond_payload_str:pattern=1234 --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
|
||||
-- test case (true) : echo aaz1234zzz | ncat -4u 1.1.1.1 443
|
||||
-- test case (false) : echo aaze124zzz | ncat -4u 1.1.1.1 443
|
||||
function cond_payload_str(desync)
|
||||
@@ -293,7 +414,7 @@ end
|
||||
-- for example, this can be used by custom protocol detectors
|
||||
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
-- arg: neg - invert condition function result
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
|
||||
-- test case : --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
|
||||
function condition(ctx, desync)
|
||||
require_iff(desync, "condition")
|
||||
orchestrate(ctx, desync)
|
||||
@@ -309,7 +430,7 @@ end
|
||||
-- can be used with other orchestrators to stop execution conditionally
|
||||
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
-- arg: neg - invert condition function result
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --in-range=-s1 --lua-desync=circular --lua-desync=stopif:iff=cond_random:strategy=1 --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
-- test case : --in-range=-s1 --lua-desync=circular --lua-desync=stopif:iff=cond_random:strategy=1 --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
function stopif(ctx, desync)
|
||||
require_iff(desync, "stopif")
|
||||
orchestrate(ctx, desync)
|
||||
@@ -321,3 +442,61 @@ function stopif(ctx, desync)
|
||||
DLOG("stopif: false")
|
||||
end
|
||||
end
|
||||
|
||||
-- repeat following 'instances' 'repeats' times, execute others with no tampering
|
||||
-- arg: instances - number of following instances to be repeated. 1 by default
|
||||
-- arg: repeats - number of repeats
|
||||
-- arg: iff - condition function to continue execution. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
-- arg: neg - invert condition function result
|
||||
-- arg: stop - do not replay remaining execution plan after 'instances'
|
||||
-- arg: clear - clear execution plan after 'instances'
|
||||
-- test case : --lua-desync=repeater:repeats=2:instances=2 --lua-desync=argdebug:v=1 --lua-desync=argdebug:v=2 --lua-desync=argdebug:v=3
|
||||
function repeater(ctx, desync)
|
||||
local repeats = tonumber(desync.arg.repeats)
|
||||
if not repeats then
|
||||
error("repeat: missing 'repeats'")
|
||||
end
|
||||
local iff = desync.arg.iff or "cond_true"
|
||||
if type(_G[iff])~="function" then
|
||||
error(name..": invalid 'iff' function '"..iff.."'")
|
||||
end
|
||||
orchestrate(ctx, desync)
|
||||
local neg = desync.arg.neg
|
||||
local stop = desync.arg.stop
|
||||
local clear = desync.arg.clear
|
||||
local verdict = VERDICT_PASS
|
||||
local instances = tonumber(desync.arg.instances) or 1
|
||||
local repinst = desync.func_instance
|
||||
if instances>#desync.plan then
|
||||
instances = #desync.plan
|
||||
end
|
||||
-- save plan copy
|
||||
local plancopy = deepcopy(desync.plan)
|
||||
for r=1,repeats do
|
||||
if not logical_xor(_G[iff](desync), neg) then
|
||||
DLOG("repeater: break by iff")
|
||||
break
|
||||
end
|
||||
DLOG("repeater: "..repinst.." "..r.."/"..repeats)
|
||||
-- nested orchestrators can also pop
|
||||
local ct_end = #desync.plan - instances
|
||||
repeat
|
||||
local instance = plan_instance_pop(desync)
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
until #desync.plan <= ct_end
|
||||
-- rollback desync plan
|
||||
desync.plan = deepcopy(plancopy)
|
||||
end
|
||||
-- remove repeated instances from desync plan
|
||||
for i=1,instances do
|
||||
table.remove(desync.plan,1)
|
||||
end
|
||||
if clear then
|
||||
plan_clear(desync)
|
||||
return verdict
|
||||
elseif stop then
|
||||
return verdict
|
||||
end
|
||||
-- replay the rest
|
||||
return verdict_aggregate(verdict, replay_execution_plan(desync))
|
||||
end
|
||||
|
||||
1201
lua/zapret-lib.lua
1201
lua/zapret-lib.lua
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,6 @@ function pcap_write_packet(file, raw)
|
||||
local sec, nsec = clock_gettime();
|
||||
file:write(bu32(sec)..bu32(nsec)..bu32(#raw)..bu32(#raw))
|
||||
file:write(raw)
|
||||
file:close()
|
||||
end
|
||||
function pcap_write(file, raw)
|
||||
local pos = file:seek()
|
||||
@@ -16,7 +15,7 @@ function pcap_write(file, raw)
|
||||
pcap_write_packet(file, raw)
|
||||
end
|
||||
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-pcap.lua --writeable=zdir --in-range=a --lua-desync=pcap:file=test.pcap
|
||||
-- test case : --writeable=zdir --in-range=a --lua-desync=pcap:file=test.pcap
|
||||
-- arg : file=<filename> - file for storing pcap data. if --writeable is specified and filename is relative - append filename to writeable path
|
||||
-- arg : keep - do not overwrite file, append packets to existing
|
||||
function pcap(ctx, desync)
|
||||
@@ -36,4 +35,5 @@ function pcap(ctx, desync)
|
||||
error("pcap: could not write to '".._G[fn_cache_name].."'")
|
||||
end
|
||||
pcap_write(f, raw_packet(ctx))
|
||||
f:close()
|
||||
end
|
||||
|
||||
@@ -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,39 +264,44 @@ 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))
|
||||
test_assert(v2==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)
|
||||
|
||||
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))
|
||||
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,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)
|
||||
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)
|
||||
|
||||
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))
|
||||
test_assert(v2==v3)
|
||||
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)
|
||||
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_ux()
|
||||
@@ -305,7 +310,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 +321,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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-wgobfs.lua --in-range=a --out-range=a --lua-desync=wgobfs:secret=mycoolpassword
|
||||
-- test case : --in-range=a --out-range=a --lua-desync=wgobfs:secret=mycoolpassword
|
||||
-- encrypt standard wireguard messages - initiation, response, cookie - and change udp packet size
|
||||
-- do not encrypt data messages and keepalives
|
||||
-- wgobfs adds maximum of 30+padmax bytes to udp size
|
||||
|
||||
@@ -2,64 +2,65 @@
|
||||
#include "checksum.h"
|
||||
#include <netinet/in.h>
|
||||
|
||||
//#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
|
||||
//#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
|
||||
// #define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
|
||||
// #define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
|
||||
|
||||
static uint16_t from64to16(uint64_t x)
|
||||
{
|
||||
uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x>>16) + (uint16_t)(x>>32) + (uint16_t)(x>>48);
|
||||
return (uint16_t)u + (uint16_t)(u>>16);
|
||||
uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x >> 16) + (uint16_t)(x >> 32) + (uint16_t)(x >> 48);
|
||||
return (uint16_t)u + (uint16_t)(u >> 16);
|
||||
}
|
||||
|
||||
// this function preserves data alignment requirements (otherwise it will be damn slow on mips arch)
|
||||
// and uses 64-bit arithmetics to improve speed
|
||||
// taken from linux source code
|
||||
static uint16_t do_csum(const uint8_t * buff, size_t len)
|
||||
static uint16_t do_csum(const uint8_t *buff, size_t len)
|
||||
{
|
||||
uint8_t odd;
|
||||
size_t count;
|
||||
uint64_t result,w,carry=0;
|
||||
uint64_t result, w, carry = 0;
|
||||
uint16_t u16;
|
||||
|
||||
if (!len) return 0;
|
||||
if (!len)
|
||||
return 0;
|
||||
odd = (uint8_t)(1 & (size_t)buff);
|
||||
if (odd)
|
||||
{
|
||||
// any endian compatible
|
||||
u16 = 0;
|
||||
*((uint8_t*)&u16+1) = *buff;
|
||||
*((uint8_t *)&u16 + 1) = *buff;
|
||||
result = u16;
|
||||
len--;
|
||||
buff++;
|
||||
}
|
||||
else
|
||||
result = 0;
|
||||
count = len >> 1; /* nr of 16-bit words.. */
|
||||
count = len >> 1; /* nr of 16-bit words.. */
|
||||
if (count)
|
||||
{
|
||||
if (2 & (size_t) buff)
|
||||
if (2 & (size_t)buff)
|
||||
{
|
||||
result += *(uint16_t *) buff;
|
||||
result += *(uint16_t *)buff;
|
||||
count--;
|
||||
len -= 2;
|
||||
buff += 2;
|
||||
}
|
||||
count >>= 1; /* nr of 32-bit words.. */
|
||||
count >>= 1; /* nr of 32-bit words.. */
|
||||
if (count)
|
||||
{
|
||||
if (4 & (size_t) buff)
|
||||
if (4 & (size_t)buff)
|
||||
{
|
||||
result += *(uint32_t *) buff;
|
||||
result += *(uint32_t *)buff;
|
||||
count--;
|
||||
len -= 4;
|
||||
buff += 4;
|
||||
}
|
||||
count >>= 1; /* nr of 64-bit words.. */
|
||||
count >>= 1; /* nr of 64-bit words.. */
|
||||
if (count)
|
||||
{
|
||||
do
|
||||
{
|
||||
w = *(uint64_t *) buff;
|
||||
w = *(uint64_t *)buff;
|
||||
count--;
|
||||
buff += 8;
|
||||
result += carry;
|
||||
@@ -71,13 +72,13 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
|
||||
}
|
||||
if (len & 4)
|
||||
{
|
||||
result += *(uint32_t *) buff;
|
||||
result += *(uint32_t *)buff;
|
||||
buff += 4;
|
||||
}
|
||||
}
|
||||
if (len & 2)
|
||||
{
|
||||
result += *(uint16_t *) buff;
|
||||
result += *(uint16_t *)buff;
|
||||
buff += 2;
|
||||
}
|
||||
}
|
||||
@@ -85,54 +86,54 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
|
||||
{
|
||||
// any endian compatible
|
||||
u16 = 0;
|
||||
*(uint8_t*)&u16 = *buff;
|
||||
*(uint8_t *)&u16 = *buff;
|
||||
result += u16;
|
||||
}
|
||||
u16 = from64to16(result);
|
||||
if (odd) u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
|
||||
if (odd)
|
||||
u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
|
||||
return u16;
|
||||
}
|
||||
|
||||
uint16_t csum_partial(const void *buff, size_t len)
|
||||
{
|
||||
return do_csum(buff,len);
|
||||
return do_csum(buff, len);
|
||||
}
|
||||
|
||||
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum)
|
||||
{
|
||||
return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len+proto));
|
||||
return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len + proto));
|
||||
}
|
||||
|
||||
uint16_t ip4_compute_csum(const void *buff, size_t len)
|
||||
{
|
||||
return ~from64to16(do_csum(buff,len));
|
||||
return ~from64to16(do_csum(buff, len));
|
||||
}
|
||||
void ip4_fix_checksum(struct ip *ip)
|
||||
{
|
||||
ip->ip_sum = 0;
|
||||
ip->ip_sum = ip4_compute_csum(ip, ip->ip_hl<<2);
|
||||
ip->ip_sum = ip4_compute_csum(ip, ip->ip_hl << 2);
|
||||
}
|
||||
|
||||
uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum)
|
||||
{
|
||||
uint64_t a = (uint64_t)sum + htonl(len+proto) +
|
||||
*(uint32_t*)saddr + *((uint32_t*)saddr+1) + *((uint32_t*)saddr+2) + *((uint32_t*)saddr+3) +
|
||||
*(uint32_t*)daddr + *((uint32_t*)daddr+1) + *((uint32_t*)daddr+2) + *((uint32_t*)daddr+3);
|
||||
uint64_t a = (uint64_t)sum + htonl(len + proto) +
|
||||
*(uint32_t *)saddr + *((uint32_t *)saddr + 1) + *((uint32_t *)saddr + 2) + *((uint32_t *)saddr + 3) +
|
||||
*(uint32_t *)daddr + *((uint32_t *)daddr + 1) + *((uint32_t *)daddr + 2) + *((uint32_t *)daddr + 3);
|
||||
return ~from64to16(a);
|
||||
}
|
||||
|
||||
|
||||
void tcp4_fix_checksum(struct tcphdr *tcp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
void tcp4_fix_checksum(struct tcphdr *tcp, size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
{
|
||||
tcp->th_sum = 0;
|
||||
tcp->th_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_TCP,csum_partial(tcp,len));
|
||||
tcp->th_sum = csum_tcpudp_magic(src_addr->s_addr, dest_addr->s_addr, len, IPPROTO_TCP, csum_partial(tcp, len));
|
||||
}
|
||||
void tcp6_fix_checksum(struct tcphdr *tcp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
void tcp6_fix_checksum(struct tcphdr *tcp, size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
{
|
||||
tcp->th_sum = 0;
|
||||
tcp->th_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_TCP,csum_partial(tcp,len));
|
||||
tcp->th_sum = csum_ipv6_magic(src_addr, dest_addr, len, IPPROTO_TCP, csum_partial(tcp, len));
|
||||
}
|
||||
void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr)
|
||||
void tcp_fix_checksum(struct tcphdr *tcp, size_t len, const struct ip *ip, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
if (ip)
|
||||
tcp4_fix_checksum(tcp, len, &ip->ip_src, &ip->ip_dst);
|
||||
@@ -140,17 +141,17 @@ void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const st
|
||||
tcp6_fix_checksum(tcp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst);
|
||||
}
|
||||
|
||||
void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
void udp4_fix_checksum(struct udphdr *udp, size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
{
|
||||
udp->uh_sum = 0;
|
||||
udp->uh_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_UDP,csum_partial(udp,len));
|
||||
udp->uh_sum = csum_tcpudp_magic(src_addr->s_addr, dest_addr->s_addr, len, IPPROTO_UDP, csum_partial(udp, len));
|
||||
}
|
||||
void udp6_fix_checksum(struct udphdr *udp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
void udp6_fix_checksum(struct udphdr *udp, size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
{
|
||||
udp->uh_sum = 0;
|
||||
udp->uh_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_UDP,csum_partial(udp,len));
|
||||
udp->uh_sum = csum_ipv6_magic(src_addr, dest_addr, len, IPPROTO_UDP, csum_partial(udp, len));
|
||||
}
|
||||
void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr)
|
||||
void udp_fix_checksum(struct udphdr *udp, size_t len, const struct ip *ip, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
if (ip)
|
||||
udp4_fix_checksum(udp, len, &ip->ip_src, &ip->ip_dst);
|
||||
|
||||
118
nfq2/conntrack.c
118
nfq2/conntrack.c
@@ -70,24 +70,24 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s
|
||||
p->pool = NULL;
|
||||
}
|
||||
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
memset(c, 0, sizeof(*c));
|
||||
if (ip)
|
||||
if (dis->ip)
|
||||
{
|
||||
c->l3proto = IPPROTO_IP;
|
||||
c->dst.ip = bReverse ? ip->ip_src : ip->ip_dst;
|
||||
c->src.ip = bReverse ? ip->ip_dst : ip->ip_src;
|
||||
c->dst.ip = bReverse ? dis->ip->ip_src : dis->ip->ip_dst;
|
||||
c->src.ip = bReverse ? dis->ip->ip_dst : dis->ip->ip_src;
|
||||
}
|
||||
else if (ip6)
|
||||
else if (dis->ip6)
|
||||
{
|
||||
c->l3proto = IPPROTO_IPV6;
|
||||
c->dst.ip6 = bReverse ? ip6->ip6_src : ip6->ip6_dst;
|
||||
c->src.ip6 = bReverse ? ip6->ip6_dst : ip6->ip6_src;
|
||||
c->dst.ip6 = bReverse ? dis->ip6->ip6_src : dis->ip6->ip6_dst;
|
||||
c->src.ip6 = bReverse ? dis->ip6->ip6_dst : dis->ip6->ip6_src;
|
||||
}
|
||||
else
|
||||
c->l3proto = -1;
|
||||
extract_ports(tcphdr, udphdr, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
|
||||
extract_ports(dis->tcp, dis->udp, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
|
||||
return ctnew;
|
||||
}
|
||||
|
||||
static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bReverse, uint32_t len_payload)
|
||||
static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
@@ -136,29 +136,35 @@ static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bRever
|
||||
direct = bReverse ? &t->pos.server : &t->pos.client;
|
||||
reverse = bReverse ? &t->pos.client : &t->pos.server;
|
||||
|
||||
scale = tcp_find_scale_factor(tcp);
|
||||
mss = ntohs(tcp_find_mss(tcp));
|
||||
if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow);
|
||||
|
||||
direct->seq_last = ntohl(tcp->th_seq);
|
||||
direct->pos = direct->seq_last + len_payload;
|
||||
reverse->pos = reverse->seq_last = ntohl(tcp->th_ack);
|
||||
scale = tcp_find_scale_factor(dis->tcp);
|
||||
mss = ntohs(tcp_find_mss(dis->tcp));
|
||||
|
||||
direct->seq_last = ntohl(dis->tcp->th_seq);
|
||||
direct->pos = direct->seq_last + dis->len_payload;
|
||||
reverse->pos = reverse->seq_last = ntohl(dis->tcp->th_ack);
|
||||
if (t->pos.state == SYN)
|
||||
direct->uppos_prev = direct->uppos = direct->pos;
|
||||
else if (len_payload)
|
||||
else if (dis->len_payload)
|
||||
{
|
||||
direct->uppos_prev = direct->uppos;
|
||||
if (!((direct->pos - direct->uppos) & 0x80000000))
|
||||
direct->uppos = direct->pos;
|
||||
}
|
||||
direct->winsize = ntohs(tcp->th_win);
|
||||
direct->winsize = ntohs(dis->tcp->th_win);
|
||||
direct->winsize_calc = direct->winsize;
|
||||
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
|
||||
if (mss && !direct->mss) direct->mss = mss;
|
||||
if (scale != SCALE_NONE) direct->scale = scale;
|
||||
|
||||
if (!direct->rseq_over_2G && ((direct->seq_last - direct->seq0) & 0x80000000))
|
||||
direct->rseq_over_2G = true;
|
||||
if (!reverse->rseq_over_2G && ((reverse->seq_last - reverse->seq0) & 0x80000000))
|
||||
reverse->rseq_over_2G = true;
|
||||
}
|
||||
|
||||
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
@@ -166,34 +172,34 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos.server.pcounter++;
|
||||
t->pos.server.pdcounter += !!len_payload;
|
||||
t->pos.server.pbcounter += len_payload;
|
||||
t->pos.server.pdcounter += !!dis->len_payload;
|
||||
t->pos.server.pbcounter += dis->len_payload;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
t->pos.client.pcounter++;
|
||||
t->pos.client.pdcounter += !!len_payload;
|
||||
t->pos.client.pbcounter += len_payload;
|
||||
t->pos.client.pdcounter += !!dis->len_payload;
|
||||
t->pos.client.pbcounter += dis->len_payload;
|
||||
}
|
||||
|
||||
if (tcphdr)
|
||||
if (dis->tcp)
|
||||
{
|
||||
if (tcp_syn_segment(tcphdr))
|
||||
if (tcp_syn_segment(dis->tcp))
|
||||
{
|
||||
if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
t->pos.client.seq0 = ntohl(tcphdr->th_seq);
|
||||
t->pos.client.seq0 = ntohl(dis->tcp->th_seq);
|
||||
}
|
||||
else if (tcp_synack_segment(tcphdr))
|
||||
else if (tcp_synack_segment(dis->tcp))
|
||||
{
|
||||
// ignore SA dups
|
||||
uint32_t seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
uint32_t seq0 = ntohl(dis->tcp->th_ack) - 1;
|
||||
if (t->pos.state != SYN && t->pos.client.seq0 != seq0)
|
||||
ConntrackReInitTrack(t); // erase current entry
|
||||
if (!t->pos.client.seq0) t->pos.client.seq0 = seq0;
|
||||
t->pos.server.seq0 = ntohl(tcphdr->th_seq);
|
||||
t->pos.server.seq0 = ntohl(dis->tcp->th_seq);
|
||||
}
|
||||
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
|
||||
else if (dis->tcp->th_flags & (TH_FIN | TH_RST))
|
||||
{
|
||||
t->pos.state = FIN;
|
||||
}
|
||||
@@ -202,36 +208,24 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
if (t->pos.state == SYN)
|
||||
{
|
||||
t->pos.state = ESTABLISHED;
|
||||
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(dis->tcp->th_ack) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
ConntrackApplyPos(tcphdr, t, bReverse, len_payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos.server.seq_last = t->pos.server.pos;
|
||||
t->pos.server.pos += len_payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->pos.client.seq_last = t->pos.client.pos;
|
||||
t->pos.client.pos += len_payload;
|
||||
}
|
||||
ConntrackApplyPos(t, bReverse, dis);
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &t->pos.t_last);
|
||||
// make sure t_start gets exactly the same value as first t_last
|
||||
if (!t->t_start.tv_sec) t->t_start = t->pos.t_last;
|
||||
}
|
||||
|
||||
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
|
||||
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *ctr;
|
||||
|
||||
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
if (bReverse) *bReverse = false;
|
||||
@@ -250,22 +244,22 @@ static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
return ConntrackPoolDoubleSearchPool(&p->pool, ip, ip6, tcphdr, udphdr, ctrack, bReverse);
|
||||
return ConntrackPoolDoubleSearchPool(&p->pool, dis, ctrack, bReverse);
|
||||
}
|
||||
|
||||
static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
|
||||
static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *ctr;
|
||||
bool b_rev;
|
||||
uint8_t proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP : IPPROTO_NONE;
|
||||
uint8_t proto = dis->tcp ? IPPROTO_TCP : dis->udp ? IPPROTO_UDP : IPPROTO_NONE;
|
||||
|
||||
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = false), tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = false), dis);
|
||||
goto ok;
|
||||
}
|
||||
else
|
||||
@@ -273,16 +267,16 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, co
|
||||
connswap(&conn, &connswp);
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &connswp)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = true), tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = true), dis);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
b_rev = tcphdr && tcp_synack_segment(tcphdr);
|
||||
if ((tcphdr && tcp_syn_segment(tcphdr)) || b_rev || udphdr)
|
||||
b_rev = dis->tcp && tcp_synack_segment(dis->tcp);
|
||||
if ((dis->tcp && tcp_syn_segment(dis->tcp)) || b_rev || dis->udp)
|
||||
{
|
||||
if ((ctr = ConntrackNew(pp, b_rev ? &connswp : &conn)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, b_rev, tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, b_rev, dis);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
@@ -293,16 +287,16 @@ ok:
|
||||
if (bReverse) *bReverse = b_rev;
|
||||
return true;
|
||||
}
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
return ConntrackPoolFeedPool(&p->pool, ip, ip6, tcphdr, udphdr, len_payload, ctrack, bReverse);
|
||||
return ConntrackPoolFeedPool(&p->pool, dis, ctrack, bReverse);
|
||||
}
|
||||
|
||||
static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
|
||||
static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct dissect *dis)
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *t;
|
||||
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if (!(t = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
connswap(&conn, &connswp);
|
||||
@@ -312,9 +306,9 @@ static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, co
|
||||
HASH_DEL(*pp, t); ConntrackFreeElem(t);
|
||||
return true;
|
||||
}
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis)
|
||||
{
|
||||
return ConntrackPoolDropPool(&p->pool, ip, ip6, tcphdr, udphdr);
|
||||
return ConntrackPoolDropPool(&p->pool, dis);
|
||||
}
|
||||
|
||||
void ConntrackPoolPurge(t_conntrack *p)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "conntrack_base.h"
|
||||
#include "packet_queue.h"
|
||||
#include "protocol.h"
|
||||
#include "darkmagic.h"
|
||||
|
||||
//#define HASH_BLOOM 20
|
||||
#define HASH_NONFATAL_OOM 1
|
||||
@@ -100,11 +101,11 @@ typedef struct
|
||||
|
||||
void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin, uint32_t timeout_udp);
|
||||
void ConntrackPoolDestroy(t_conntrack *p);
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse);
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
|
||||
// do not create, do not update. only find existing
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse);
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
|
||||
void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis);
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis);
|
||||
void ConntrackPoolDump(const t_conntrack *p);
|
||||
void ConntrackPoolPurge(t_conntrack *p);
|
||||
void ConntrackClearHostname(t_ctrack *track);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#define CTRACK_T_SYN 60
|
||||
@@ -17,17 +18,19 @@ typedef struct
|
||||
uint64_t pcounter; // packet counter
|
||||
uint64_t pdcounter; // data packet counter (with payload)
|
||||
uint64_t pbcounter; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
||||
uint32_t ip6flow;
|
||||
|
||||
// tcp only state, not used in udp
|
||||
uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||
uint32_t uppos; // max seen position. useful to detect retransmissions
|
||||
uint32_t uppos_prev; // previous max seen position. useful to detect retransmissions
|
||||
uint32_t seq_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
|
||||
|
||||
// tcp only state, not used in udp
|
||||
uint32_t seq0; // starting seq and ack
|
||||
uint16_t winsize; // last seen window size
|
||||
uint16_t mss;
|
||||
uint32_t winsize_calc; // calculated window size
|
||||
uint8_t scale; // last seen window scale factor. SCALE_NONE if none
|
||||
bool rseq_over_2G;
|
||||
} t_ctrack_position;
|
||||
|
||||
typedef struct
|
||||
|
||||
@@ -547,6 +547,33 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis)
|
||||
}
|
||||
}
|
||||
|
||||
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6)
|
||||
{
|
||||
if (ip)
|
||||
{
|
||||
struct in_addr temp = ip->ip_src;
|
||||
ip->ip_src = ip->ip_dst;
|
||||
ip->ip_dst = temp;
|
||||
ip4_fix_checksum(ip);
|
||||
}
|
||||
if (ip6)
|
||||
{
|
||||
struct in6_addr temp = ip6->ip6_src;
|
||||
ip6->ip6_src = ip6->ip6_dst;
|
||||
ip6->ip6_dst = temp;
|
||||
}
|
||||
}
|
||||
void reverse_tcp(struct tcphdr *tcp)
|
||||
{
|
||||
uint16_t tport = tcp->th_sport;
|
||||
tcp->th_sport = tcp->th_dport;
|
||||
tcp->th_dport = tport;
|
||||
|
||||
uint32_t tseq = tcp->th_seq;
|
||||
tcp->th_seq = tcp->th_ack;
|
||||
tcp->th_ack = tseq;
|
||||
}
|
||||
|
||||
|
||||
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6)
|
||||
{
|
||||
@@ -718,13 +745,36 @@ bool prepare_low_appdata()
|
||||
return b;
|
||||
}
|
||||
|
||||
BOOL JobSandbox()
|
||||
{
|
||||
BOOL bRes = FALSE;
|
||||
HANDLE hJob;
|
||||
JOBOBJECT_BASIC_LIMIT_INFORMATION basic_limit;
|
||||
JOBOBJECT_BASIC_UI_RESTRICTIONS basic_ui;
|
||||
|
||||
if (hJob = CreateJobObjectW(NULL, NULL))
|
||||
{
|
||||
basic_limit.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
|
||||
// prevent child process creation
|
||||
basic_limit.ActiveProcessLimit = 1;
|
||||
// prevent some UI interaction and settings change
|
||||
basic_ui.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS | JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_GLOBALATOMS | JOB_OBJECT_UILIMIT_HANDLES | JOB_OBJECT_UILIMIT_READCLIPBOARD | JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
|
||||
bRes = SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &basic_limit, sizeof(basic_limit)) &&
|
||||
SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &basic_ui, sizeof(basic_ui)) &&
|
||||
AssignProcessToJobObject(hJob, GetCurrentProcess());
|
||||
w_win32_error = GetLastError();
|
||||
CloseHandle(hJob);
|
||||
}
|
||||
return bRes;
|
||||
}
|
||||
|
||||
|
||||
#define WINDIVERT_DEVICE_NAME "WinDivert"
|
||||
static bool b_isandbox_set = false;
|
||||
static bool b_sandbox_set = false;
|
||||
bool win_sandbox(void)
|
||||
{
|
||||
// there's no way to return privs
|
||||
if (!b_isandbox_set)
|
||||
if (!b_sandbox_set)
|
||||
{
|
||||
if (!RemoveTokenPrivs())
|
||||
return FALSE;
|
||||
@@ -734,8 +784,9 @@ bool win_sandbox(void)
|
||||
return FALSE;
|
||||
if (!LowMandatoryLevel())
|
||||
return false;
|
||||
// for LUA code to find where to store files
|
||||
b_isandbox_set = true;
|
||||
if (!JobSandbox())
|
||||
return false;
|
||||
b_sandbox_set = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1253,14 +1304,21 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
|
||||
{
|
||||
WINDIVERT_ADDRESS wa;
|
||||
|
||||
if (!ifout) return false;
|
||||
|
||||
memset(&wa,0,sizeof(wa));
|
||||
// pseudo interface id IfIdx.SubIfIdx
|
||||
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
|
||||
if (ifout && *ifout)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1 - typically loopback
|
||||
wa.Network.IfIdx=1;
|
||||
wa.Network.SubIfIdx=0;
|
||||
}
|
||||
wa.Outbound=1;
|
||||
wa.IPChecksum=1;
|
||||
|
||||
@@ -162,6 +162,8 @@ struct dissect
|
||||
size_t len_payload;
|
||||
};
|
||||
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis);
|
||||
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);
|
||||
void reverse_tcp(struct tcphdr *tcp);
|
||||
|
||||
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6);
|
||||
|
||||
|
||||
435
nfq2/desync.c
435
nfq2/desync.c
@@ -246,11 +246,13 @@ static bool is_retransmission(const t_ctrack_position *pos)
|
||||
}
|
||||
|
||||
// return true if retrans trigger fires
|
||||
static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int threshold, const char *client_ip_port, t_l7proto l7proto)
|
||||
static bool auto_hostlist_retrans
|
||||
(t_ctrack *ctrack, const struct dissect *dis, int threshold, const char *client_ip_port, t_l7proto l7proto,
|
||||
const struct sockaddr *client, const char *ifclient)
|
||||
{
|
||||
if (ctrack && ctrack->dp && ctrack->hostname_ah_check && !ctrack->failure_detect_finalized && ctrack->req_retrans_counter != RETRANS_COUNTER_STOP)
|
||||
{
|
||||
if (l4proto == IPPROTO_TCP && ctrack->pos.state!=SYN)
|
||||
if (dis->proto == IPPROTO_TCP && ctrack->pos.state!=SYN)
|
||||
{
|
||||
if (!seq_within(ctrack->pos.client.seq_last, ctrack->pos.client.seq0, ctrack->pos.client.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq))
|
||||
{
|
||||
@@ -269,6 +271,46 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho
|
||||
DLOG("retrans threshold reached : %u/%u\n", ctrack->req_retrans_counter, threshold);
|
||||
ctrack_stop_retrans_counter(ctrack);
|
||||
ctrack->failure_detect_finalized = true;
|
||||
if (dis->tcp && ctrack->dp->hostlist_auto_retrans_reset && (dis->ip || dis->ip6))
|
||||
{
|
||||
uint8_t pkt[sizeof(struct ip6_hdr)+sizeof(struct tcphdr)];
|
||||
struct ip *ip;
|
||||
struct ip6_hdr *ip6;
|
||||
struct tcphdr *tcp;
|
||||
uint16_t pktlen;
|
||||
|
||||
if (dis->ip)
|
||||
{
|
||||
ip = (struct ip*)pkt; ip6=NULL;
|
||||
pktlen = sizeof(struct ip) + sizeof(struct tcphdr);
|
||||
*ip = *dis->ip;
|
||||
ip->ip_hl = sizeof(struct ip)/4; // remove ip options
|
||||
ip->ip_len = htons(pktlen);
|
||||
ip->ip_id=0;
|
||||
tcp = (struct tcphdr*)(ip+1);
|
||||
*tcp = *dis->tcp;
|
||||
}
|
||||
else if (dis->ip6)
|
||||
{
|
||||
ip6 = (struct ip6_hdr*)pkt; ip=NULL;
|
||||
pktlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
|
||||
*ip6 = *dis->ip6;
|
||||
ip6->ip6_plen = htons(sizeof(struct tcphdr));
|
||||
ip6->ip6_nxt = IPPROTO_TCP;
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(ctrack->pos.server.ip6flow ? ctrack->pos.server.ip6flow : 0x60000000);
|
||||
tcp = (struct tcphdr*)(ip6+1);
|
||||
*tcp = *dis->tcp;
|
||||
}
|
||||
reverse_ip(ip,ip6); // also fixes ip4 checksum
|
||||
reverse_tcp(tcp);
|
||||
tcp->th_off = sizeof(struct tcphdr)/4; // remove tcp options
|
||||
tcp->th_flags = TH_RST;
|
||||
tcp->th_win = ctrack->pos.server.winsize;
|
||||
tcp_fix_checksum(tcp, sizeof(struct tcphdr), ip, ip6);
|
||||
|
||||
DLOG("sending RST to retransmitter. ifname=%s\n", ifclient ? ifclient : "");
|
||||
rawsend(client,0,ifclient,pkt,pktlen);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
DLOG("retrans counter : %u/%u\n", ctrack->req_retrans_counter, threshold);
|
||||
@@ -330,13 +372,13 @@ static void fill_client_ip_port(const struct sockaddr *client, char *client_ip_p
|
||||
else
|
||||
*client_ip_port = 0;
|
||||
}
|
||||
static void process_retrans_fail(t_ctrack *ctrack, uint8_t proto, const struct sockaddr *client)
|
||||
static void process_retrans_fail(t_ctrack *ctrack, const struct dissect *dis, struct sockaddr *client, const char *ifclient)
|
||||
{
|
||||
if (params.server) return; // no autohostlists in server mode
|
||||
|
||||
char client_ip_port[48];
|
||||
fill_client_ip_port(client, client_ip_port, sizeof(client_ip_port));
|
||||
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, proto, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto))
|
||||
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, dis, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto, client, ifclient))
|
||||
{
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : retrans threshold reached", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(ctrack->dp), client_ip_port, l7proto_str(ctrack->l7proto));
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
@@ -415,7 +457,8 @@ static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, ui
|
||||
static bool reasm_client_start(t_ctrack *ctrack, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
||||
{
|
||||
if (!ctrack) return false;
|
||||
if (proto==IPPROTO_TCP && ctrack->pos.server.winsize_calc < sz)
|
||||
// if winsize_calc==0 it means we dont know server window size - no incoming packets redirected ?
|
||||
if (proto==IPPROTO_TCP && ctrack->pos.server.winsize_calc && (ctrack->pos.server.winsize_calc < sz))
|
||||
{
|
||||
// this is rare but possible situation
|
||||
// server gave us too small tcp window
|
||||
@@ -505,7 +548,10 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, const struct dissect *
|
||||
return VERDICT_DROP;
|
||||
}
|
||||
|
||||
|
||||
static bool pos_overflow(const t_ctrack_position *pos, char mode)
|
||||
{
|
||||
return (mode=='s' || mode=='p') && pos && pos->rseq_over_2G;
|
||||
}
|
||||
static uint64_t pos_get(const t_ctrack_position *pos, char mode)
|
||||
{
|
||||
if (pos)
|
||||
@@ -524,7 +570,7 @@ static uint64_t pos_get(const t_ctrack_position *pos, char mode)
|
||||
static bool check_pos_from(const t_ctrack_position *pos, const struct packet_range *range)
|
||||
{
|
||||
uint64_t ps;
|
||||
if (range->from.mode == 'x') return false;
|
||||
if ((range->from.mode == 'x') || pos_overflow(pos,range->from.mode)) return false;
|
||||
if (range->from.mode != 'a')
|
||||
{
|
||||
if (pos)
|
||||
@@ -540,7 +586,7 @@ static bool check_pos_from(const t_ctrack_position *pos, const struct packet_ran
|
||||
static bool check_pos_to(const t_ctrack_position *pos, const struct packet_range *range)
|
||||
{
|
||||
uint64_t ps;
|
||||
if (range->to.mode == 'x') return false;
|
||||
if (range->to.mode == 'x' || pos_overflow(pos,range->to.mode)) return false;
|
||||
if (range->to.mode != 'a')
|
||||
{
|
||||
if (pos)
|
||||
@@ -707,7 +753,7 @@ static uint8_t desync(
|
||||
struct func_list *func;
|
||||
int ref_arg = LUA_NOREF, status;
|
||||
bool b, b_cutoff_all, b_unwanted_payload;
|
||||
t_lua_desync_context ctx = { .dp = dp, .ctrack = ctrack, .dis = dis, .cancel = false, .incoming = bIncoming };
|
||||
t_lua_desync_context ctx = { .magic = 0, .dp = dp, .ctrack = ctrack, .dis = dis, .cancel = false, .incoming = bIncoming };
|
||||
const char *sDirection = bIncoming ? "in" : "out";
|
||||
struct packet_range *range;
|
||||
size_t l;
|
||||
@@ -754,10 +800,12 @@ static uint8_t desync(
|
||||
DLOG("* lua '%s' : voluntary cutoff\n", instance);
|
||||
else if (check_pos_cutoff(pos, range))
|
||||
{
|
||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu is beyond range %c%u%c%c%u (ctrack %s)\n",
|
||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu overflow %u %u is beyond range %c%u%c%c%u (ctrack %s)\n",
|
||||
instance, sDirection,
|
||||
range->from.mode, pos_get(pos, range->from.mode),
|
||||
range->to.mode, pos_get(pos, range->to.mode),
|
||||
pos_overflow(pos, range->from.mode),
|
||||
pos_overflow(pos, range->to.mode),
|
||||
range->from.mode, range->from.pos,
|
||||
range->upper_cutoff ? '<' : '-',
|
||||
range->to.mode, range->to.pos,
|
||||
@@ -855,8 +903,14 @@ static uint8_t desync(
|
||||
lua_pushf_str("func", func->func);
|
||||
lua_pushf_int("func_n", ctx.func_n);
|
||||
lua_pushf_str("func_instance", instance);
|
||||
int initial_stack_top = lua_gettop(params.L);
|
||||
|
||||
// lua should not store and access ctx outside of this call
|
||||
// if this happens make our best to prevent access to bad memory
|
||||
// this is not crash-proof but better than nothing
|
||||
ctx.magic = MAGIC_CTX; // mark struct as valid
|
||||
status = lua_pcall(params.L, 2, LUA_MULTRET, 0);
|
||||
ctx.magic = 0; // mark struct as invalid
|
||||
|
||||
if (status)
|
||||
{
|
||||
lua_dlog_error();
|
||||
@@ -975,6 +1029,23 @@ static void setup_direction(
|
||||
}
|
||||
}
|
||||
|
||||
static void dp_changed(t_ctrack *ctrack)
|
||||
{
|
||||
if (ctrack)
|
||||
{
|
||||
if (ctrack->b_lua_in_cutoff)
|
||||
{
|
||||
DLOG("clearing lua in cutoff because of profile change\n");
|
||||
ctrack->b_lua_in_cutoff = false;
|
||||
}
|
||||
if (ctrack->b_lua_out_cutoff)
|
||||
{
|
||||
DLOG("clearing lua out cutoff because of profile change\n");
|
||||
ctrack->b_lua_out_cutoff = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t dpi_desync_tcp_packet_play(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||
uint32_t fwmark,
|
||||
@@ -1007,7 +1078,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
// in replay mode conntrack_replay is not NULL and ctrack is NULL
|
||||
|
||||
//ConntrackPoolDump(¶ms.conntrack);
|
||||
if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis->ip, dis->ip6, dis->tcp, NULL, &ctrack_replay, &bReverse) || bReverse)
|
||||
if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis, &ctrack_replay, &bReverse) || bReverse)
|
||||
return verdict;
|
||||
bReverseFixed = bReverse ^ params.server;
|
||||
setup_direction(dis, bReverseFixed, &src, &dst, &sdip4, &sdip6, &sdport);
|
||||
@@ -1039,7 +1110,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
if (!params.ctrack_disable)
|
||||
{
|
||||
ConntrackPoolPurge(¶ms.conntrack);
|
||||
if (ConntrackPoolFeed(¶ms.conntrack, dis->ip, dis->ip6, dis->tcp, NULL, dis->len_payload, &ctrack, &bReverse))
|
||||
if (ConntrackPoolFeed(¶ms.conntrack, dis, &ctrack, &bReverse))
|
||||
{
|
||||
dp = ctrack->dp;
|
||||
ctrack_replay = ctrack;
|
||||
@@ -1115,6 +1186,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
else
|
||||
bCheckDone = bCheckResult = bCheckExcluded = false;
|
||||
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
if (bReverse)
|
||||
{
|
||||
// protocol detection
|
||||
@@ -1186,7 +1258,6 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
struct blob_collection_head *fake;
|
||||
uint8_t *p, *phost = NULL;
|
||||
int i;
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
|
||||
if (replay_piece_count)
|
||||
{
|
||||
@@ -1199,7 +1270,8 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
rlen_payload = ctrack->reasm_client.size_present;
|
||||
}
|
||||
|
||||
process_retrans_fail(ctrack, IPPROTO_TCP, (struct sockaddr*)&src);
|
||||
process_retrans_fail(ctrack, dis, (struct sockaddr*)&src, ifin);
|
||||
|
||||
if (IsHttp(rdata_payload, rlen_payload))
|
||||
{
|
||||
DLOG("packet contains HTTP request\n");
|
||||
@@ -1284,90 +1356,90 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
}
|
||||
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n", host);
|
||||
}
|
||||
}
|
||||
|
||||
bool bDiscoveredL7;
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n", host);
|
||||
}
|
||||
|
||||
bool bDiscoveredL7;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
if ((bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != L7_UNKNOWN))
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
|
||||
|
||||
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
|
||||
if (bDiscoveredHostname)
|
||||
{
|
||||
DLOG("discovered hostname\n");
|
||||
if (ctrack_replay)
|
||||
{
|
||||
bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != L7_UNKNOWN;
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
|
||||
|
||||
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
|
||||
if (bDiscoveredHostname)
|
||||
{
|
||||
DLOG("discovered hostname\n");
|
||||
if (ctrack_replay)
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname = strdup(host);
|
||||
ctrack_replay->hostname_is_ip = bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname = strdup(host);
|
||||
ctrack_replay->hostname_is_ip = bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
ctrack_replay->hostname_discovered = true;
|
||||
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
|
||||
goto pass_reasm_cancel;
|
||||
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
}
|
||||
ctrack_replay->hostname_discovered = true;
|
||||
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
}
|
||||
|
||||
if (bDiscoveredL7 || bDiscoveredHostname)
|
||||
if (bDiscoveredL7 || bDiscoveredHostname)
|
||||
{
|
||||
struct desync_profile *dp_prev = dp;
|
||||
// search for desync profile again. it may have changed.
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, sdip4, sdip6, sdport,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
if (ctrack_replay)
|
||||
{
|
||||
struct desync_profile *dp_prev = dp;
|
||||
|
||||
// search for desync profile again. it may have changed.
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, sdip4, sdip6, sdport,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
ctrack_replay->dp = dp;
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
if (!dp) goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
dp_changed(ctrack_replay);
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
{
|
||||
if (!bCheckDone)
|
||||
{
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
bCheckDone = true;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->dp = dp;
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
if (!dp) goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
if (bCheckResult)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
else
|
||||
{
|
||||
if (!bCheckDone)
|
||||
if (ctrack_replay)
|
||||
{
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
bCheckDone = true;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
}
|
||||
if (bCheckResult)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
else
|
||||
{
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
|
||||
if (!ctrack_replay->hostname_ah_check)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
}
|
||||
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
|
||||
if (!ctrack_replay->hostname_ah_check)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1400,6 +1472,26 @@ static void quic_reasm_cancel(t_ctrack *ctrack, const char *reason)
|
||||
DLOG("%s\n", 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},
|
||||
{L7P_DNS_RESPONSE,L7_DNS,IsDNSResponse,false},
|
||||
{L7P_DHT,L7_DHT,IsDht,false},
|
||||
{L7P_DTLS_CLIENT_HELLO,L7_DTLS,IsDTLSClientHello,false},
|
||||
{L7P_DTLS_SERVER_HELLO,L7_DTLS,IsDTLSServerHello,false},
|
||||
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
|
||||
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
|
||||
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
|
||||
{L7P_WIREGUARD_KEEPALIVE,L7_WIREGUARD,IsWireguardKeepalive,false},
|
||||
{L7P_WIREGUARD_DATA,L7_WIREGUARD,IsWireguardData,true}};
|
||||
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), data_payload, len_payload, ctrack, l7proto, l7payload);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t dpi_desync_udp_packet_play(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||
@@ -1450,7 +1542,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
// in replay mode conntrack_replay is not NULL and ctrack is NULL
|
||||
|
||||
//ConntrackPoolDump(¶ms.conntrack);
|
||||
if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis->ip, dis->ip6, NULL, dis->udp, &ctrack_replay, &bReverse) || bReverse)
|
||||
if (!ConntrackPoolDoubleSearch(¶ms.conntrack, dis, &ctrack_replay, &bReverse) || bReverse)
|
||||
return verdict;
|
||||
bReverseFixed = bReverse ^ params.server;
|
||||
setup_direction(dis, bReverseFixed, &src, &dst, &sdip4, &sdip6, &sdport);
|
||||
@@ -1482,7 +1574,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
if (!params.ctrack_disable)
|
||||
{
|
||||
ConntrackPoolPurge(¶ms.conntrack);
|
||||
if (ConntrackPoolFeed(¶ms.conntrack, dis->ip, dis->ip6, NULL, dis->udp, dis->len_payload, &ctrack, &bReverse))
|
||||
if (ConntrackPoolFeed(¶ms.conntrack, dis, &ctrack, &bReverse))
|
||||
{
|
||||
dp = ctrack->dp;
|
||||
ctrack_replay = ctrack;
|
||||
@@ -1559,24 +1651,14 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
|
||||
if (dis->len_payload)
|
||||
{
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
if (bReverse)
|
||||
{
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_DNS_RESPONSE,L7_DNS,IsDNSResponse,false},
|
||||
{L7P_DHT,L7_DHT,IsDht,false},
|
||||
{L7P_STUN,L7_STUN,IsStunMessage,false},
|
||||
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
|
||||
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
|
||||
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
|
||||
{L7P_WIREGUARD_KEEPALIVE,L7_WIREGUARD,IsWireguardKeepalive,false},
|
||||
{L7P_WIREGUARD_DATA,L7_WIREGUARD,IsWireguardData,true}
|
||||
};
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
udp_standard_protocol_probe(dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct blob_collection_head *fake;
|
||||
bool bHaveHost = false, bHostIsIp = false;
|
||||
if (IsQUICInitial(dis->data_payload, dis->len_payload))
|
||||
{
|
||||
DLOG("packet contains QUIC initial\n");
|
||||
@@ -1709,114 +1791,97 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
}
|
||||
else // not QUIC initial
|
||||
{
|
||||
// received payload without host. it means we are out of the request retransmission phase. stop counter
|
||||
ctrack_stop_retrans_counter(ctrack);
|
||||
|
||||
// not quic initial - stop reasm
|
||||
reasm_client_cancel(ctrack);
|
||||
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
|
||||
{L7P_STUN,L7_STUN,IsStunMessage,false},
|
||||
{L7P_DNS_QUERY,L7_DNS,IsDNSQuery,false},
|
||||
{L7P_DHT,L7_DHT,IsDht,false},
|
||||
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
|
||||
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
|
||||
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
|
||||
{L7P_WIREGUARD_KEEPALIVE,L7_WIREGUARD,IsWireguardKeepalive,false},
|
||||
{L7P_WIREGUARD_DATA,L7_WIREGUARD,IsWireguardData,true}
|
||||
};
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
udp_standard_protocol_probe(dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
}
|
||||
}
|
||||
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n", host);
|
||||
}
|
||||
if (bHaveHost)
|
||||
{
|
||||
bHostIsIp = strip_host_to_ip(host);
|
||||
DLOG("hostname: %s\n", host);
|
||||
}
|
||||
|
||||
bool bDiscoveredL7;
|
||||
bool bDiscoveredL7;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
if ((bDiscoveredL7 = !ctrack_replay->l7proto_discovered && l7proto != L7_UNKNOWN))
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
|
||||
|
||||
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
|
||||
if (bDiscoveredHostname)
|
||||
{
|
||||
DLOG("discovered hostname\n");
|
||||
if (ctrack_replay)
|
||||
{
|
||||
bDiscoveredL7 = !ctrack_replay->l7proto_discovered && l7proto != L7_UNKNOWN;
|
||||
ctrack_replay->l7proto_discovered = true;
|
||||
}
|
||||
else
|
||||
bDiscoveredL7 = l7proto != L7_UNKNOWN;
|
||||
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
|
||||
|
||||
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
|
||||
if (bDiscoveredHostname)
|
||||
{
|
||||
DLOG("discovered hostname\n");
|
||||
if (ctrack_replay)
|
||||
ctrack_replay->hostname_discovered = true;
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname = strdup(host);
|
||||
ctrack_replay->hostname_is_ip = bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
ctrack_replay->hostname_discovered = true;
|
||||
free(ctrack_replay->hostname);
|
||||
ctrack_replay->hostname = strdup(host);
|
||||
ctrack_replay->hostname_is_ip = bHostIsIp;
|
||||
if (!ctrack_replay->hostname)
|
||||
{
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
goto pass;
|
||||
}
|
||||
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
|
||||
goto pass;
|
||||
DLOG_ERR("hostname dup : out of memory");
|
||||
goto pass;
|
||||
}
|
||||
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
|
||||
goto pass;
|
||||
}
|
||||
}
|
||||
|
||||
if (bDiscoveredL7 || bDiscoveredHostname)
|
||||
if (bDiscoveredL7 || bDiscoveredHostname)
|
||||
{
|
||||
struct desync_profile *dp_prev = dp;
|
||||
|
||||
// search for desync profile again. it may have changed.
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, sdip4, sdip6, sdport,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
if (ctrack_replay)
|
||||
{
|
||||
struct desync_profile *dp_prev = dp;
|
||||
ctrack_replay->dp = dp;
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
if (!dp)
|
||||
goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
dp_changed(ctrack_replay);
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
else if (ctrack_replay)
|
||||
{
|
||||
bCheckDone = ctrack_replay->bCheckDone;
|
||||
bCheckResult = ctrack_replay->bCheckResult;
|
||||
bCheckExcluded = ctrack_replay->bCheckExcluded;
|
||||
}
|
||||
|
||||
// search for desync profile again. it may have changed.
|
||||
dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, sdip4, sdip6, sdport,
|
||||
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
|
||||
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
|
||||
l7proto, ssid,
|
||||
&bCheckDone, &bCheckResult, &bCheckExcluded);
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
{
|
||||
if (!bCheckDone)
|
||||
{
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
bCheckDone = true;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->dp = dp;
|
||||
ctrack_replay->dp_search_complete = true;
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
if (!dp)
|
||||
goto pass_reasm_cancel;
|
||||
if (dp != dp_prev)
|
||||
{
|
||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||
}
|
||||
}
|
||||
else if (ctrack_replay)
|
||||
{
|
||||
bCheckDone = ctrack_replay->bCheckDone;
|
||||
bCheckResult = ctrack_replay->bCheckResult;
|
||||
bCheckExcluded = ctrack_replay->bCheckExcluded;
|
||||
}
|
||||
|
||||
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
|
||||
{
|
||||
if (!bCheckDone)
|
||||
{
|
||||
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
|
||||
bCheckDone = true;
|
||||
if (ctrack_replay)
|
||||
{
|
||||
ctrack_replay->bCheckDone = bCheckDone;
|
||||
ctrack_replay->bCheckResult = bCheckResult;
|
||||
ctrack_replay->bCheckExcluded = bCheckExcluded;
|
||||
}
|
||||
}
|
||||
if (bCheckResult)
|
||||
ctrack_stop_retrans_counter(ctrack_replay);
|
||||
else
|
||||
{
|
||||
if (ctrack_replay)
|
||||
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
|
||||
}
|
||||
}
|
||||
if (!bCheckResult && ctrack_replay)
|
||||
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
|
||||
}
|
||||
|
||||
process_udp_fail(ctrack_replay, tpos, (struct sockaddr*)&src);
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
|
||||
#ifdef __linux__
|
||||
#define DPI_DESYNC_FWMARK_DEFAULT 0x40000000
|
||||
#else
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
#define DPI_DESYNC_FWMARK_DEFAULT 512
|
||||
#else
|
||||
#define DPI_DESYNC_FWMARK_DEFAULT 0
|
||||
#endif
|
||||
|
||||
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, const uint8_t *data_pkt, size_t len_pkt, uint8_t *mod_pkt, size_t *len_mod_pkt);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#define BUFMIN 128
|
||||
#define BUFCHUNK (1024*128)
|
||||
|
||||
int z_readfile(FILE *F, char **buf, size_t *size)
|
||||
int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
|
||||
{
|
||||
z_stream zs;
|
||||
int r;
|
||||
@@ -38,7 +38,7 @@ int z_readfile(FILE *F, char **buf, size_t *size)
|
||||
if ((bufsize - *size) < BUFMIN)
|
||||
{
|
||||
bufsize += BUFCHUNK;
|
||||
newbuf = *buf ? realloc(*buf, bufsize) : malloc(bufsize);
|
||||
newbuf = *buf ? realloc(*buf, bufsize + extra_alloc) : malloc(bufsize + extra_alloc);
|
||||
if (!newbuf)
|
||||
{
|
||||
r = Z_MEM_ERROR;
|
||||
@@ -57,7 +57,7 @@ int z_readfile(FILE *F, char **buf, size_t *size)
|
||||
if (*size < bufsize)
|
||||
{
|
||||
// free extra space
|
||||
if ((newbuf = realloc(*buf, *size))) *buf = newbuf;
|
||||
if ((newbuf = realloc(*buf, *size + extra_alloc))) *buf = newbuf;
|
||||
}
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
#include <zlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
int z_readfile(FILE *F,char **buf,size_t *size);
|
||||
int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc);
|
||||
bool is_gzip(FILE* F);
|
||||
|
||||
@@ -367,6 +367,19 @@ void phton32(uint8_t *p, uint32_t v)
|
||||
p[2] = (uint8_t)(v>>8);
|
||||
p[3] = (uint8_t)v;
|
||||
}
|
||||
uint64_t pntoh48(const uint8_t *p)
|
||||
{
|
||||
return ((uint64_t)p[0] << 40) | ((uint64_t)p[1] << 32) | ((uint64_t)p[2] << 24) | ((uint64_t)p[3] << 16) | ((uint64_t)p[4] << 8) | p[5];
|
||||
}
|
||||
void phton48(uint8_t *p, uint64_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v>>40);
|
||||
p[1] = (uint8_t)(v>>32);
|
||||
p[2] = (uint8_t)(v>>24);
|
||||
p[3] = (uint8_t)(v>>16);
|
||||
p[4] = (uint8_t)(v>>8);
|
||||
p[5] = (uint8_t)v;
|
||||
}
|
||||
uint64_t pntoh64(const uint8_t *p)
|
||||
{
|
||||
return ((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) | ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32) | ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) | ((uint64_t)p[6] << 8) | p[7];
|
||||
@@ -383,6 +396,20 @@ void phton64(uint8_t *p, uint64_t v)
|
||||
p[7] = (uint8_t)v;
|
||||
}
|
||||
|
||||
uint16_t swap16(uint16_t u)
|
||||
{
|
||||
// __builtin_bswap16 is absent in ancient lexra gcc 4.6
|
||||
return (u>>8) | ((u&0xFF)<<8);
|
||||
}
|
||||
uint32_t swap24(uint32_t u)
|
||||
{
|
||||
return (u>>16) & 0xFF | u & 0xFF00 | (u<<16) & 0xFF0000;
|
||||
}
|
||||
uint64_t swap48(uint64_t u)
|
||||
{
|
||||
return ((u & 0xFF0000000000) >> 40) | ((u & 0xFF00000000) >> 24) | ((u & 0xFF000000) >> 8) | ((u & 0xFF0000) << 8) | ((u & 0xFF00) << 24) | ((u & 0xFF) << 40);
|
||||
}
|
||||
|
||||
|
||||
#define INVALID_HEX_DIGIT ((uint8_t)-1)
|
||||
static inline uint8_t parse_hex_digit(char c)
|
||||
|
||||
@@ -61,9 +61,15 @@ uint32_t pntoh24(const uint8_t *p);
|
||||
void phton24(uint8_t *p, uint32_t v);
|
||||
uint32_t pntoh32(const uint8_t *p);
|
||||
void phton32(uint8_t *p, uint32_t v);
|
||||
uint64_t pntoh48(const uint8_t *p);
|
||||
void phton48(uint8_t *p, uint64_t v);
|
||||
uint64_t pntoh64(const uint8_t *p);
|
||||
void phton64(uint8_t *p, uint64_t v);
|
||||
|
||||
uint16_t swap16(uint16_t u);
|
||||
uint32_t swap24(uint32_t u);
|
||||
uint64_t swap48(uint64_t u);
|
||||
|
||||
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size);
|
||||
char hex_digit(uint8_t v);
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||
|
||||
if (is_gzip(F))
|
||||
{
|
||||
r = z_readfile(F,&zbuf,&zsize);
|
||||
r = z_readfile(F,&zbuf,&zsize,0);
|
||||
fclose(F);
|
||||
if (r==Z_OK)
|
||||
{
|
||||
|
||||
@@ -76,7 +76,7 @@ static bool AppendIpset(ipset *ips, const char *filename)
|
||||
|
||||
if (is_gzip(F))
|
||||
{
|
||||
r = z_readfile(F,&zbuf,&zsize);
|
||||
r = z_readfile(F,&zbuf,&zsize,0);
|
||||
fclose(F);
|
||||
if (r==Z_OK)
|
||||
{
|
||||
|
||||
284
nfq2/lua.c
284
nfq2/lua.c
@@ -9,9 +9,11 @@
|
||||
#elif defined(__CYGWIN__)
|
||||
#include <processthreadsapi.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include "lua.h"
|
||||
#include "params.h"
|
||||
#include "gzip.h"
|
||||
#include "helpers.h"
|
||||
#include "conntrack.h"
|
||||
#include "crypto/sha.h"
|
||||
@@ -69,16 +71,16 @@ static int luacall_bitlshift(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitlshift",2);
|
||||
int64_t v=(int64_t)luaL_checklint(L,1);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,((uint32_t)v) << luaL_checkinteger(L,2));
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,(((uint64_t)v) << luaL_checkinteger(L,2)) & 0xFFFFFFFFFFFF);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitrshift(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitrshift",2);
|
||||
int64_t v=(int64_t)luaL_checklint(L,1);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,((uint32_t)v) >> luaL_checkinteger(L,2));
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,((uint64_t)v) >> luaL_checkinteger(L,2));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitand(lua_State *L)
|
||||
@@ -86,12 +88,12 @@ static int luacall_bitand(lua_State *L)
|
||||
lua_check_argc_range(L,"bitand",2,100);
|
||||
int argc = lua_gettop(L);
|
||||
int64_t v;
|
||||
uint32_t sum=0xFFFFFFFF;
|
||||
uint64_t sum=0xFFFFFFFFFFFF;
|
||||
for(int i=1;i<=argc;i++)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum&=(uint32_t)v;
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum&=(uint64_t)v;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
@@ -101,33 +103,60 @@ static int luacall_bitor(lua_State *L)
|
||||
lua_check_argc_range(L,"bitor",1,100);
|
||||
int argc = lua_gettop(L);
|
||||
int64_t v;
|
||||
uint32_t sum=0;
|
||||
uint64_t sum=0;
|
||||
for(int i=1;i<=argc;i++)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum|=(uint32_t)v;
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum|=(uint64_t)v;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitnot(lua_State *L)
|
||||
static int lua_bitnotx(lua_State *L, int64_t max)
|
||||
{
|
||||
lua_check_argc(L,"bitnot",1);
|
||||
lua_pushlint(L,~(uint32_t)luaL_checklint(L,1));
|
||||
int64_t v=(int64_t)luaL_checklint(L,1);
|
||||
if (v>max || v<-max) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,~(uint64_t)v & max);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitnot8(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot8",1);
|
||||
return lua_bitnotx(L, 0xFF);
|
||||
}
|
||||
static int luacall_bitnot16(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot16",1);
|
||||
return lua_bitnotx(L, 0xFFFF);
|
||||
}
|
||||
static int luacall_bitnot24(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot24",1);
|
||||
return lua_bitnotx(L, 0xFFFFFF);
|
||||
}
|
||||
static int luacall_bitnot32(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot32",1);
|
||||
return lua_bitnotx(L, 0xFFFFFFFF);
|
||||
}
|
||||
static int luacall_bitnot48(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitnot48",1);
|
||||
return lua_bitnotx(L, 0xFFFFFFFFFFFF);
|
||||
}
|
||||
static int luacall_bitxor(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"bitxor",1,100);
|
||||
int argc = lua_gettop(L);
|
||||
int64_t v;
|
||||
uint32_t sum=0;
|
||||
uint64_t sum=0;
|
||||
for(int i=1;i<=argc;i++)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum^=(uint32_t)v;
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum^=(uint64_t)v;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
@@ -137,11 +166,11 @@ static int luacall_bitget(lua_State *L)
|
||||
lua_check_argc(L,"bitget",3);
|
||||
|
||||
int64_t iwhat = (int64_t)luaL_checklint(L,1);
|
||||
if (iwhat>0xFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint32_t what = (uint32_t)iwhat;
|
||||
if (iwhat>0xFFFFFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint64_t what = (uint64_t)iwhat;
|
||||
lua_Integer from = luaL_checkinteger(L,2);
|
||||
lua_Integer to = luaL_checkinteger(L,3);
|
||||
if (from>to || from>31 || to>31)
|
||||
if (from>to || from>47 || to>47)
|
||||
luaL_error(L, "bit range invalid");
|
||||
|
||||
what = (what >> from) & ~((lua_Integer)-1 << (to-from+1));
|
||||
@@ -154,14 +183,14 @@ 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));
|
||||
@@ -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[4];
|
||||
phton48(v,(uint64_t)i);
|
||||
lua_pushlstring(L,(char*)v,6);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int luacall_divint(lua_State *L)
|
||||
{
|
||||
@@ -412,7 +490,7 @@ static int luacall_parse_hex(lua_State *L)
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
size_t l;
|
||||
const char *hex = lua_tolstring(L,1,&l);
|
||||
const char *hex = luaL_checklstring(L,1,&l);
|
||||
if ((l&1)) goto err;
|
||||
l>>=1;
|
||||
uint8_t *p = malloc(l);
|
||||
@@ -690,6 +768,22 @@ static int luacall_clock_gettime(lua_State *L)
|
||||
}
|
||||
LUA_STACK_GUARD_RETURN(L,2)
|
||||
}
|
||||
|
||||
static t_lua_desync_context *lua_desync_ctx()
|
||||
{
|
||||
if (lua_isnil(params.L,1))
|
||||
luaL_error(params.L, "missing ctx");
|
||||
if (!lua_islightuserdata(params.L,1))
|
||||
luaL_error(params.L, "bad ctx - invalid data type");
|
||||
|
||||
t_lua_desync_context *ctx = lua_touserdata(params.L,1);
|
||||
// ensure it's really ctx. LUA could pass us any lightuserdata pointer
|
||||
if (ctx->magic!=MAGIC_CTX)
|
||||
luaL_error(params.L, "bad ctx - magic bytes invalid");
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static int luacall_instance_cutoff(lua_State *L)
|
||||
{
|
||||
// out : instance_name.profile_number[0]
|
||||
@@ -699,16 +793,12 @@ static int luacall_instance_cutoff(lua_State *L)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
const t_lua_desync_context *ctx;
|
||||
|
||||
if (lua_isnil(L,1))
|
||||
// this can happen in orchestrated function. they do not have their own ctx and they cant cutoff
|
||||
DLOG("instance cutoff not possible because missing ctx\n");
|
||||
else
|
||||
{
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "instance_cutoff expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
const t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
bool bIn,bOut;
|
||||
@@ -720,7 +810,6 @@ static int luacall_instance_cutoff(lua_State *L)
|
||||
}
|
||||
else
|
||||
bIn = bOut = true;
|
||||
|
||||
if (ctx->ctrack)
|
||||
{
|
||||
DLOG("instance cutoff for '%s' in=%u out=%u\n",ctx->instance,bIn,bOut);
|
||||
@@ -785,11 +874,7 @@ static int luacall_lua_cutoff(lua_State *L)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "lua_cutoff expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
bool bIn,bOut;
|
||||
@@ -821,11 +906,7 @@ static int luacall_execution_plan(lua_State *L)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
const t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "execution_plan expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
@@ -862,11 +943,7 @@ static int luacall_execution_plan_cancel(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"execution_plan_cancel",1);
|
||||
|
||||
t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "execution_plan_cancel expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
DLOG("execution plan cancel from '%s'\n",ctx->instance);
|
||||
|
||||
@@ -881,11 +958,7 @@ static int luacall_raw_packet(lua_State *L)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
const t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "raw_packet expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
const t_lua_desync_context *ctx = lua_desync_ctx();
|
||||
|
||||
lua_pushlstring(L, (const char*)ctx->dis->data_pkt, ctx->dis->len_pkt);
|
||||
|
||||
@@ -1251,13 +1324,15 @@ void lua_push_dissect(const struct dissect *dis)
|
||||
|
||||
if (dis)
|
||||
{
|
||||
lua_createtable(params.L, 0, 7);
|
||||
lua_createtable(params.L, 0, 9);
|
||||
lua_pushf_iphdr(dis->ip, dis->len_l3);
|
||||
lua_pushf_ip6hdr(dis->ip6, dis->len_l3);
|
||||
lua_pushf_tcphdr(dis->tcp, dis->len_l4);
|
||||
lua_pushf_udphdr(dis->udp, dis->len_l4);
|
||||
lua_pushf_int("l4proto",dis->proto);
|
||||
lua_pushf_int("transport_len",dis->transport_len);
|
||||
lua_pushf_int("l3_len",dis->len_l3);
|
||||
lua_pushf_int("l4_len",dis->len_l4);
|
||||
lua_pushf_raw("payload",dis->data_payload,dis->len_payload);
|
||||
}
|
||||
else
|
||||
@@ -1279,13 +1354,15 @@ void lua_pushf_ctrack_pos(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
||||
lua_pushf_lint("pcounter", pos->pcounter);
|
||||
lua_pushf_lint("pdcounter", pos->pdcounter);
|
||||
lua_pushf_lint("pbcounter", pos->pbcounter);
|
||||
if (pos->ip6flow) lua_pushf_int("ip6_flow", pos->ip6flow);
|
||||
if (ctrack->ipproto == IPPROTO_TCP)
|
||||
{
|
||||
lua_pushliteral(params.L, "tcp");
|
||||
lua_createtable(params.L, 0, 10);
|
||||
lua_createtable(params.L, 0, 11);
|
||||
lua_pushf_lint("seq0", pos->seq0);
|
||||
lua_pushf_lint("seq", pos->seq_last);
|
||||
lua_pushf_lint("rseq", pos->seq_last - pos->seq0);
|
||||
lua_pushf_bool("rseq_over_2G", pos->rseq_over_2G);
|
||||
lua_pushf_int("pos", pos->pos - pos->seq0);
|
||||
lua_pushf_int("uppos", pos->uppos - pos->seq0);
|
||||
lua_pushf_int("uppos_prev", pos->uppos_prev - pos->seq0);
|
||||
@@ -1660,7 +1737,7 @@ bool lua_reconstruct_iphdr(int idx, struct ip *ip, size_t *len)
|
||||
if (lua_type(params.L,-1)==LUA_TSTRING)
|
||||
{
|
||||
p = lua_tolstring(params.L,-1,&lopt);
|
||||
if (lopt)
|
||||
if (p && lopt)
|
||||
{
|
||||
if (lopt>40 || ((sizeof(struct ip) + ((lopt+3)&~3)) > *len)) goto err;
|
||||
memcpy(ip+1,p,lopt);
|
||||
@@ -1992,7 +2069,7 @@ bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bo
|
||||
|
||||
lua_getfield(params.L,idx,"payload");
|
||||
p = lua_tolstring(params.L,-1,&lpayload);
|
||||
if (lpayload)
|
||||
if (p && lpayload)
|
||||
{
|
||||
if (left<lpayload) goto err;
|
||||
memcpy(data,p,lpayload);
|
||||
@@ -2135,7 +2212,7 @@ static int luacall_csum_ip4_fix(lua_State *L)
|
||||
}
|
||||
static int luacall_csum_tcp_fix(lua_State *L)
|
||||
{
|
||||
// csum_ip4_fix(ip_header, tcp_header, payload) returns tcp_header
|
||||
// csum_tcp_fix(ip_header, tcp_header, payload) returns tcp_header
|
||||
lua_check_argc(L,"csum_tcp_fix",3);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
@@ -2176,7 +2253,7 @@ static int luacall_csum_tcp_fix(lua_State *L)
|
||||
}
|
||||
static int luacall_csum_udp_fix(lua_State *L)
|
||||
{
|
||||
// csum_ip4_fix(ip_header, tcp_header, payload) returns tcp_header
|
||||
// csum_udp_fix(ip_header, udp_header, payload) returns udp_header
|
||||
lua_check_argc(L,"csum_udp_fix",3);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
@@ -2823,20 +2900,80 @@ static bool lua_desync_functions_exist()
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lua_file_open_test(const char *filename, bool *b_gzip, char *fname)
|
||||
{
|
||||
FILE *F = fopen(filename,"rb");
|
||||
if (F)
|
||||
{
|
||||
if (fname) snprintf(fname,PATH_MAX,"%s",filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t l = strlen(filename);
|
||||
char *fngz = malloc(l+4);
|
||||
if (!fngz) return false;
|
||||
memcpy(fngz, filename, l);
|
||||
memcpy(fngz+l,".gz",4);
|
||||
if (fname) snprintf(fname,PATH_MAX,"%s",fngz);
|
||||
F = fopen(fngz,"rb");
|
||||
free(fngz);
|
||||
}
|
||||
if (F)
|
||||
{
|
||||
if (b_gzip) *b_gzip = is_gzip(F);
|
||||
fclose(F);
|
||||
}
|
||||
return !!F;
|
||||
}
|
||||
|
||||
bool lua_test_init_script_files(void)
|
||||
{
|
||||
struct str_list *str;
|
||||
LIST_FOREACH(str, ¶ms.lua_init_scripts, next)
|
||||
{
|
||||
if (str->str[0]=='@' && !file_open_test(str->str+1, O_RDONLY))
|
||||
if (str->str[0]=='@' && !lua_file_open_test(str->str+1, NULL, NULL))
|
||||
{
|
||||
DLOG_ERR("LUA file '%s' not accessible\n",str->str+1);
|
||||
#ifndef __CYGWIN__
|
||||
int e = errno;
|
||||
#endif
|
||||
DLOG_ERR("LUA file '%s' or '%s.gz' not accessible\n", str->str+1, str->str+1);
|
||||
#ifndef __CYGWIN__
|
||||
if (e==EACCES)
|
||||
DLOG_ERR("I drop my privileges and do not run Lua as root\ncheck file permissions and +x rights on all directories in the path\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int luaL_doZfile(lua_State *L, const char *filename)
|
||||
{
|
||||
bool b_gzip;
|
||||
char fname[PATH_MAX];
|
||||
if (!lua_file_open_test(filename, &b_gzip, fname))
|
||||
luaL_error(L, "could not open lua file '%s' or '%s.gz'", filename, filename);
|
||||
if (b_gzip)
|
||||
{
|
||||
size_t size;
|
||||
char *buf;
|
||||
int r;
|
||||
FILE *F = fopen(fname, "rb");
|
||||
if (!F)
|
||||
luaL_error(L, "could not open lua file '%s'", fname);
|
||||
r = z_readfile(F, &buf, &size, 1);
|
||||
fclose(F);
|
||||
if (r != Z_OK)
|
||||
luaL_error(L, "could not unzip lua file '%s'", fname);
|
||||
buf[size] = 0;
|
||||
r = luaL_dostring(L, buf);
|
||||
free(buf);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
return luaL_dofile(L, filename);
|
||||
}
|
||||
|
||||
static bool lua_init_scripts(void)
|
||||
{
|
||||
struct str_list *str;
|
||||
@@ -2855,7 +2992,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;
|
||||
@@ -3000,10 +3137,14 @@ static void lua_init_const(void)
|
||||
{"IP_OFFMASK",IP_OFFMASK},
|
||||
{"IP_FLAGMASK",IP_RF|IP_DF|IP_MF},
|
||||
{"IPTOS_ECN_MASK",IPTOS_ECN_MASK},
|
||||
{"IPTOS_ECN_NOT_ECT",0},
|
||||
{"IPTOS_ECN_ECT1",IPTOS_ECN_ECT1},
|
||||
{"IPTOS_ECN_ECT0",IPTOS_ECN_ECT0},
|
||||
{"IPTOS_ECN_CE",IPTOS_ECN_CE},
|
||||
{"IPTOS_DSCP_MASK",0xF0},
|
||||
{"IP6F_MORE_FRAG",0x0001}, // in ip6.h it's defined depending of machine byte order
|
||||
{"IPV6_FLOWLABEL_MASK",0x000FFFFF},
|
||||
{"IPV6_FLOWINFO_MASK",0x0FFFFFFF},
|
||||
|
||||
{"IPPROTO_IP",IPPROTO_IP},
|
||||
{"IPPROTO_IPV6",IPPROTO_IPV6},
|
||||
@@ -3079,10 +3220,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
|
||||
@@ -3090,19 +3235,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},
|
||||
|
||||
@@ -101,7 +101,9 @@ bool lua_reconstruct_tcphdr(int idx, struct tcphdr *tcp, size_t *len);
|
||||
bool lua_reconstruct_udphdr(int idx, struct udphdr *udp);
|
||||
bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bool ip6_preserve_next);
|
||||
|
||||
#define MAGIC_CTX 0xE73DC935
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
unsigned int func_n;
|
||||
const char *func, *instance;
|
||||
const struct desync_profile *dp;
|
||||
|
||||
14
nfq2/nfqws.c
14
nfq2/nfqws.c
@@ -538,7 +538,7 @@ static int dvt_main(void)
|
||||
|
||||
DLOG("\npacket: id=%u len=%zu ifin=%s ifout=%s\n", id, len, ifin, ifout);
|
||||
modlen = sizeof(buf);
|
||||
verdict = processPacketData(&mark, NULL, NULL, buf, len, buf, &modlen);
|
||||
verdict = processPacketData(&mark, ifin, ifout, buf, len, buf, &modlen);
|
||||
switch (verdict & VERDICT_MASK)
|
||||
{
|
||||
case VERDICT_PASS:
|
||||
@@ -630,6 +630,7 @@ static int win_main()
|
||||
{
|
||||
res=w_win32_error; goto ex;
|
||||
}
|
||||
|
||||
if (!win_sandbox())
|
||||
{
|
||||
res=w_win32_error;
|
||||
@@ -637,7 +638,6 @@ static int win_main()
|
||||
goto ex;
|
||||
}
|
||||
|
||||
|
||||
// init LUA only here because of possible sandbox. no LUA code with high privs
|
||||
if (!params.L && !lua_init())
|
||||
{
|
||||
@@ -726,6 +726,7 @@ ex:
|
||||
static void exit_clean(int code)
|
||||
{
|
||||
cleanup_params(¶ms);
|
||||
|
||||
exit(code);
|
||||
}
|
||||
|
||||
@@ -1406,7 +1407,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"
|
||||
@@ -1435,6 +1436,7 @@ static void exithelp(void)
|
||||
" --hostlist-auto-fail-time=<int>\t\t\t; all failed attemps must be within these seconds (default : %d)\n"
|
||||
" --hostlist-auto-retrans-threshold=<int>\t\t; how many request retransmissions cause attempt to fail (default : %d)\n"
|
||||
" --hostlist-auto-retrans-maxseq=<int>\t\t\t; count retransmissions only within this relative sequence (default : %u)\n"
|
||||
" --hostlist-auto-retrans-reset=[0|1]\t\t\t; send RST to retransmitter to break long wait (default: 1)\n"
|
||||
" --hostlist-auto-incoming-maxseq=<int>\t\t\t; treat tcp connection as successful if incoming relative sequence exceedes this threshold (default : %u)\n"
|
||||
" --hostlist-auto-udp-out=<int>\t\t\t\t; udp failure condition : sent at least `udp_out` packets (default : %u)\n"
|
||||
" --hostlist-auto-udp-in=<int>\t\t\t\t; udp failure condition : received not more than `udp_in` packets (default : %u)\n"
|
||||
@@ -1553,6 +1555,7 @@ enum opt_indices {
|
||||
IDX_HOSTLIST_AUTO_FAIL_TIME,
|
||||
IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD,
|
||||
IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ,
|
||||
IDX_HOSTLIST_AUTO_RETRANS_RESET,
|
||||
IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ,
|
||||
IDX_HOSTLIST_AUTO_UDP_IN,
|
||||
IDX_HOSTLIST_AUTO_UDP_OUT,
|
||||
@@ -1641,6 +1644,7 @@ static const struct option long_options[] = {
|
||||
[IDX_HOSTLIST_AUTO_FAIL_TIME] = {"hostlist-auto-fail-time", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD] = {"hostlist-auto-retrans-threshold", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ] = {"hostlist-auto-retrans-maxseq", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_RETRANS_RESET] = {"hostlist-auto-retrans-reset", optional_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ] = {"hostlist-auto-incoming-maxseq", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_UDP_IN] = {"hostlist-auto-udp-in", required_argument, 0, 0},
|
||||
[IDX_HOSTLIST_AUTO_UDP_OUT] = {"hostlist-auto-udp-out", required_argument, 0, 0},
|
||||
@@ -1812,6 +1816,7 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "cannot create %s\n", params.debug_logfile);
|
||||
exit_clean(1);
|
||||
}
|
||||
fclose(F);
|
||||
params.debug = true;
|
||||
params.debug_target = LOG_TARGET_FILE;
|
||||
}
|
||||
@@ -2098,6 +2103,9 @@ int main(int argc, char **argv)
|
||||
case IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ:
|
||||
dp->hostlist_auto_incoming_maxseq = (uint32_t)atoi(optarg);
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_RETRANS_RESET:
|
||||
dp->hostlist_auto_retrans_reset = !optarg || !!atoi(optarg);
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_UDP_OUT:
|
||||
dp->hostlist_auto_udp_out = atoi(optarg);
|
||||
break;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -350,6 +350,7 @@ void dp_init(struct desync_profile *dp)
|
||||
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
|
||||
dp->hostlist_auto_retrans_maxseq = HOSTLIST_AUTO_RETRANS_MAXSEQ;
|
||||
dp->hostlist_auto_retrans_reset = true;
|
||||
dp->hostlist_auto_incoming_maxseq = HOSTLIST_AUTO_INCOMING_MAXSEQ;
|
||||
dp->hostlist_auto_udp_out = HOSTLIST_AUTO_UDP_OUT;
|
||||
dp->hostlist_auto_udp_in = HOSTLIST_AUTO_UDP_IN;
|
||||
|
||||
@@ -84,6 +84,7 @@ struct desync_profile
|
||||
int hostlist_auto_fail_threshold, hostlist_auto_fail_time, hostlist_auto_retrans_threshold;
|
||||
int hostlist_auto_udp_in, hostlist_auto_udp_out;
|
||||
uint32_t hostlist_auto_retrans_maxseq, hostlist_auto_incoming_maxseq;
|
||||
bool hostlist_auto_retrans_reset;
|
||||
|
||||
hostfail_pool *hostlist_auto_fail_counters;
|
||||
|
||||
|
||||
35
nfq2/pools.c
35
nfq2/pools.c
@@ -138,13 +138,17 @@ void HostFailPoolDump(hostfail_pool *p)
|
||||
static struct str_list *strlist_entry_alloc(const char *str)
|
||||
{
|
||||
struct str_list *entry = malloc(sizeof(struct str_list));
|
||||
if (!entry) return false;
|
||||
entry->str = strdup(str);
|
||||
if (!entry->str)
|
||||
if (!entry) return NULL;
|
||||
if (str)
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
if (!(entry->str = strdup(str)))
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
entry->str = NULL;
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -244,14 +248,13 @@ static struct str2_list *str2list_entry_copy(const struct str2_list *entry)
|
||||
{
|
||||
struct str2_list *e2 = str2list_entry_alloc();
|
||||
if (!e2) return NULL;
|
||||
e2->str1 = strdup(entry->str1);
|
||||
e2->str2 = strdup(entry->str2);
|
||||
if (!e2->str1 || !e2->str2)
|
||||
{
|
||||
str2list_entry_destroy(e2);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry->str1) if (!(e2->str1 = strdup(entry->str1))) goto err;
|
||||
if (entry->str2) if (!(e2->str2 = strdup(entry->str2))) goto err;
|
||||
return e2;
|
||||
err:
|
||||
str2list_entry_destroy(e2);
|
||||
return NULL;
|
||||
}
|
||||
bool str2list_copy(struct str2_list_head *to, const struct str2_list_head *from)
|
||||
{
|
||||
@@ -287,7 +290,7 @@ void funclist_destroy(struct func_list_head *head)
|
||||
static struct func_list *funclist_entry_alloc(const char *func)
|
||||
{
|
||||
struct func_list *entry = malloc(sizeof(struct func_list));
|
||||
if (!entry) return false;
|
||||
if (!entry) return NULL;
|
||||
entry->func = strdup(func);
|
||||
if (!entry->func)
|
||||
{
|
||||
@@ -321,7 +324,7 @@ static struct func_list *funclist_entry_copy(const struct func_list *entry)
|
||||
if (!str2list_copy(&e2->args, &entry->args))
|
||||
{
|
||||
funclist_entry_destroy(e2);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
return e2;
|
||||
}
|
||||
@@ -350,7 +353,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -616,7 +619,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -29,7 +29,9 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t **
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *l7proto_name[] = {"all","unknown","known","http","tls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto"};
|
||||
static const char *l7proto_name[] = {
|
||||
"all","unknown","known","http","tls","dtls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto"
|
||||
};
|
||||
const char *l7proto_str(t_l7proto l7)
|
||||
{
|
||||
if (l7>=L7_LAST) return NULL;
|
||||
@@ -46,7 +48,11 @@ bool l7_proto_match(t_l7proto l7proto, uint64_t filter_l7)
|
||||
}
|
||||
|
||||
static const char *l7payload_name[] = {
|
||||
"all","unknown","empty","known","http_req","http_reply","tls_client_hello","tls_server_hello","quic_initial",
|
||||
"all","unknown","empty","known",
|
||||
"http_req","http_reply",
|
||||
"tls_client_hello","tls_server_hello",
|
||||
"dtls_client_hello","dtls_server_hello",
|
||||
"quic_initial",
|
||||
"wireguard_initiation","wireguard_response","wireguard_cookie","wireguard_keepalive","wireguard_data",
|
||||
"dht","discord_ip_discovery","stun",
|
||||
"xmpp_stream", "xmpp_starttls", "xmpp_proceed", "xmpp_features",
|
||||
@@ -458,9 +464,10 @@ bool IsTLSRecordFull(const uint8_t *data, size_t len)
|
||||
}
|
||||
bool IsTLSHandshakeHello(const uint8_t *data, size_t len, uint8_t type, bool bPartialIsOK)
|
||||
{
|
||||
// return len >= 1 && (type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) && (bPartialIsOK || IsTLSHandshakeFull(data,len));
|
||||
|
||||
return len >= 1 && (type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) && (bPartialIsOK || IsTLSHandshakeFull(data,len));
|
||||
return len >= 6 &&
|
||||
(type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) &&
|
||||
data[4]==0x03 && data[5] <= 0x03 &&
|
||||
(bPartialIsOK || IsTLSHandshakeFull(data,len));
|
||||
}
|
||||
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len, bool bPartialIsOK)
|
||||
{
|
||||
@@ -1310,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;
|
||||
@@ -1323,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
|
||||
@@ -1342,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1401,7 +1407,11 @@ bool IsWireguardKeepalive(const uint8_t *data, size_t len)
|
||||
}
|
||||
bool IsDht(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len>=7 && data[0]=='d' && (data[1]=='1' || data[1]=='2') && data[2]==':' && data[len-1]=='e';
|
||||
return len>=5 && data[0]=='d' && data[2]==':' && data[len-1]=='e' &&
|
||||
(data[1]=='1' && data[3]=='a' && data[4]=='d' ||
|
||||
data[1]=='1' && data[3]=='r' && data[4]=='d' ||
|
||||
data[1]=='2' && data[3]=='i' && data[4]=='p' ||
|
||||
data[1]=='1' && data[3]=='e' && data[4]=='l');
|
||||
}
|
||||
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len)
|
||||
{
|
||||
@@ -1445,3 +1455,22 @@ bool IsMTProto(const uint8_t *data, size_t len)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsDTLS(const uint8_t *data, size_t len)
|
||||
{
|
||||
return ((len > 13) &&
|
||||
(data[0]>=0x14 && data[0]<=0x17) && /* Handshake, change-cipher-spec, Application-Data, Alert */
|
||||
((data[1] == 0xfe && data[2] == 0xff) || /* Versions */
|
||||
(data[1] == 0xfe && data[2] == 0xfd) ||
|
||||
(data[1] == 0xfe && data[2] == 0xfc) ||
|
||||
(data[1] == 0x01 && data[2] == 0x00)) &&
|
||||
(pntoh16(data+11)+13)<=len);
|
||||
}
|
||||
bool IsDTLSClientHello(const uint8_t *data, size_t len)
|
||||
{
|
||||
return IsDTLS(data,len) && data[0]==0x16 && data[13]==1;
|
||||
}
|
||||
bool IsDTLSServerHello(const uint8_t *data, size_t len)
|
||||
{
|
||||
return IsDTLS(data,len) && data[0]==0x16 && data[13]==2;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ typedef enum {
|
||||
L7_KNOWN,
|
||||
L7_HTTP,
|
||||
L7_TLS,
|
||||
L7_DTLS,
|
||||
L7_QUIC,
|
||||
L7_WIREGUARD,
|
||||
L7_DHT,
|
||||
@@ -34,6 +35,8 @@ typedef enum {
|
||||
L7P_HTTP_REPLY,
|
||||
L7P_TLS_CLIENT_HELLO,
|
||||
L7P_TLS_SERVER_HELLO,
|
||||
L7P_DTLS_CLIENT_HELLO,
|
||||
L7P_DTLS_SERVER_HELLO,
|
||||
L7P_QUIC_INITIAL,
|
||||
L7P_WIREGUARD_INITIATION,
|
||||
L7P_WIREGUARD_RESPONSE,
|
||||
@@ -155,6 +158,10 @@ bool IsDht(const uint8_t *data, size_t len);
|
||||
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len);
|
||||
bool IsStunMessage(const uint8_t *data, size_t len);
|
||||
bool IsMTProto(const uint8_t *data, size_t len);
|
||||
bool IsDTLS(const uint8_t *data, size_t len);
|
||||
bool IsDTLSClientHello(const uint8_t *data, size_t len);
|
||||
bool IsDTLSServerHello(const uint8_t *data, size_t len);
|
||||
|
||||
|
||||
#define QUIC_MAX_CID_LENGTH 20
|
||||
typedef struct quic_cid {
|
||||
|
||||
Reference in New Issue
Block a user