mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-16 14:58:17 +00:00
Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca14fbe9c8 | ||
|
|
c81968b94b | ||
|
|
a2d567c7a0 | ||
|
|
5026199f24 | ||
|
|
68435f64ea | ||
|
|
d84dfaf61d | ||
|
|
4c13c63d27 | ||
|
|
5dde1264ce | ||
|
|
cc989c52ed | ||
|
|
0446b1493b | ||
|
|
97cd8cebca | ||
|
|
2d02eeb578 | ||
|
|
fe318a42e8 | ||
|
|
73c10e3f15 | ||
|
|
17cf260fd0 | ||
|
|
fa15c635bb | ||
|
|
74690047b5 | ||
|
|
d24453da69 | ||
|
|
af200628cd | ||
|
|
76fe7bff82 | ||
|
|
1d1eedbb3b | ||
|
|
274b331825 | ||
|
|
69f900b3da | ||
|
|
da9faabf97 | ||
|
|
60934f5ab8 | ||
|
|
eb7043fc12 | ||
|
|
681c53c3b4 | ||
|
|
65f6923383 | ||
|
|
f0f59261bb | ||
|
|
06cf59d050 | ||
|
|
f0bff44219 | ||
|
|
da0016ed0e | ||
|
|
704c73f821 | ||
|
|
201dd40b46 | ||
|
|
aa13a1f5d2 | ||
|
|
2a3b6f2a8b | ||
|
|
801dec81c8 | ||
|
|
14359afb93 | ||
|
|
372c6748ca | ||
|
|
87d2fcd5a1 | ||
|
|
74ddd4f9d2 | ||
|
|
6b7507deb5 | ||
|
|
f8156a3d38 | ||
|
|
67a8ee47e3 | ||
|
|
93d81ca4b2 | ||
|
|
3d9a36600b | ||
|
|
c3adb3f045 | ||
|
|
f919533873 | ||
|
|
17bdfe16b1 | ||
|
|
bc0102fbdc | ||
|
|
10d72b3242 | ||
|
|
9dd14dfc7c | ||
|
|
10201f1abf | ||
|
|
236550918b | ||
|
|
72a269e88d | ||
|
|
d3199eebd3 | ||
|
|
ffcb14726d | ||
|
|
aa5a1f4183 | ||
|
|
ca186a6566 | ||
|
|
dced388652 | ||
|
|
1f7d10bf5b | ||
|
|
6b1b4adddb | ||
|
|
cfe7b76352 | ||
|
|
62fd0dc432 | ||
|
|
050a01bda2 | ||
|
|
4c5d84c19e | ||
|
|
d430b4775d | ||
|
|
807565968e | ||
|
|
e062b1795e | ||
|
|
3417e50438 | ||
|
|
70f5a88ec0 | ||
|
|
4b3fba3fb2 | ||
|
|
9cded5448a | ||
|
|
2302ac6949 | ||
|
|
0be76b902e | ||
|
|
fa89e011fb | ||
|
|
622a81001d | ||
|
|
4d793b73a4 | ||
|
|
a47b6a529b |
@@ -2,9 +2,11 @@
|
||||
Скопируйте эту директорию под другим именем в blockcheck2.d, отредактируйте list файлы, впишите туда свои стратегии.
|
||||
В диалоге blockcheck2.sh выберите тест с названием вашей директории.
|
||||
Можно комментировать строки символом '#' в начале строки.
|
||||
Параметры со спец символами типа "<" должны быть эскейпнуты по правилам shell.
|
||||
Альтернативный путь до файлов стратегий можно задать переменными LIST_HTTP, LIST_HTTPS_TLS12, LIST_HTTPS_TLS13, LIST_QUIC.
|
||||
|
||||
This is simple strategy tester from a file.
|
||||
Copy this folder, write your strategies into list files and select your test in blockcheck2 dialog.
|
||||
Lines can be commented using the '#' symbol at the line start.
|
||||
Parameters with special symbols like "<" must be escaped.
|
||||
Strategy list files paths can be overriden in env variables : LIST_HTTP, LIST_HTTPS_TLS12, LIST_HTTPS_TLS13, LIST_QUIC.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload=http_req --lua-desync=http_hostcase
|
||||
--payload=http_req --lua-desync=http_methodeol
|
||||
--payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_ts=-1000
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_ts=-1000
|
||||
--payload=tls_client_hello --lua-desync=fake:blob=0x00000000:tcp_md5:repeats=1 --lua-desync=fake:blob=fake_default_tls:tcp_md5:tls_mod=rnd,dupsid:repeats=1 --lua-desync=multisplit:pos=2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_ts=-1000
|
||||
--payload tls_client_hello --lua-desync=tcpseg:pos=0,-1:seqovl=1 --lua-desync=drop
|
||||
--payload tls_client_hello --lua-desync=luaexec:code="desync.pat=tls_mod(fake_default_tls,'rnd,rndsni,dupsid,padencap',desync.reasm_data)" --lua-desync=tcpseg:pos=0,-1:seqovl=#pat:seqovl_pattern=pat --lua-desync=drop
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=11
|
||||
--payload quic_initial --lua-desync=send:ipfrag --lua-desync=drop
|
||||
|
||||
39
blockcheck2.d/standard/17-oob.sh
Normal file
39
blockcheck2.d/standard/17-oob.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_oob()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local dropacks urp
|
||||
for urp in b 0 2 midsld; do
|
||||
pktws_curl_test_update "$1" "$2" --in-range=-s1 --lua-desync=oob:urp=$urp$dropack
|
||||
done
|
||||
}
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_OOB_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_oob "$@"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_OOB_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_oob "$@"
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls12 "$1" "$2"
|
||||
}
|
||||
@@ -1,18 +1,22 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_simple_split_tests()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain/uri
|
||||
# $3 - splits
|
||||
# $4 - PRE args for nfqws2
|
||||
local pos ok ok_any pre="$4"
|
||||
local splitf splitfs="multisplit $MULTIDISORDER"
|
||||
local pos ok ok_any pre="$4" func
|
||||
local splitf splitfs="multisplit multidisorder"
|
||||
|
||||
ok_any=0
|
||||
for splitf in $splitfs; do
|
||||
func=$splitf
|
||||
[ "$func" = multidisorder ] && func=$MULTIDISORDER
|
||||
eval need_$splitf=0
|
||||
ok=0
|
||||
for pos in $3; do
|
||||
pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$splitf:pos=$pos && ok=1
|
||||
pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$func:pos=$pos && ok=1
|
||||
done
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] || eval need_$splitf=1
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
@@ -41,8 +45,6 @@ pktws_check_https_tls()
|
||||
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; }
|
||||
|
||||
pktws_simple_split_tests "$1" "$2" "$splits_tls" "$3"
|
||||
}
|
||||
|
||||
@@ -50,6 +52,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -62,5 +67,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
@@ -34,6 +36,7 @@ pktws_seqovl_tests_tls()
|
||||
# $1 - test function
|
||||
# $2 - domain/uri
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
local ok ok_any
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local pat rnd_mod padencap_mod split f f2
|
||||
@@ -47,14 +50,14 @@ pktws_seqovl_tests_tls()
|
||||
ok=0
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=1 --lua-desync=drop && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=#$pat:seqovl_pattern=$pat --lua-desync=drop && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=tcpseg:pos=0,-1:seqovl=#pat:seqovl_pattern=$pat --lua-desync=drop && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=tcpseg:pos=0,-1:seqovl=#$pat:seqovl_pattern=$pat --lua-desync=drop && ok=1
|
||||
ok_any=$ok
|
||||
|
||||
ok=0
|
||||
for split in 10 10,sniext+1 10,sniext+4 10,midsld; do
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=1 && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=#$pat:seqovl_pattern=$pat && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=multisplit:pos=$split:seqovl=#pat:seqovl_pattern=$pat && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=multisplit:pos=$split:seqovl=#$pat:seqovl_pattern=$pat && ok=1
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
for split in '1 2' 'sniext sniext+1' 'sniext+3 sniext+4' 'midsld-1 midsld' '1 2,midsld'; do
|
||||
@@ -67,21 +70,13 @@ pktws_seqovl_tests_tls()
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_seqovl_tests_tls "$1" "$2" "$3"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_seqovl_tests_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_seqovl_tests_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -90,5 +85,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_seqovl_tests_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ pktws_check_https_tls()
|
||||
|
||||
local PAYLOAD="--payload=tls_client_hello" ok=0 pre="$3" split
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=0x1603 ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
@@ -40,6 +38,8 @@ pktws_check_https_tls12()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -49,5 +49,7 @@ pktws_check_https_tls13()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ pktws_check_http()
|
||||
|
||||
need_fake=0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok_any=0
|
||||
ok=0
|
||||
@@ -40,7 +40,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
@@ -55,8 +55,8 @@ pktws_check_http()
|
||||
done
|
||||
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_fake=1
|
||||
[ $ok = 1 ] && okany=1
|
||||
[ $okany = 1 ]
|
||||
[ $ok = 1 ] && ok_any=1
|
||||
[ $ok_any = 1 ]
|
||||
}
|
||||
|
||||
pktws_fake_https_vary_()
|
||||
@@ -76,7 +76,7 @@ pktws_fake_https_vary()
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -86,8 +86,6 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ok_any ttls attls f fake fooling
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
@@ -125,14 +123,17 @@ pktws_check_https_tls()
|
||||
done
|
||||
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_fake=1
|
||||
[ $ok = 1 ] && okany=1
|
||||
[ $okany = 1 ]
|
||||
[ $ok = 1 ] && ok_any=1
|
||||
[ $ok_any = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -145,5 +146,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ pktws_check_faked()
|
||||
local PAYLOAD="--payload=$3"
|
||||
local FAKED_PATTERN="$5"
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fakedsplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
@@ -42,7 +42,7 @@ pktws_check_faked()
|
||||
for split in $splits; do
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty --out-range="<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty --out-range="<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
@@ -77,7 +77,6 @@ pktws_check_https_tls()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
[ "$NOTEST_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
pktws_check_faked $1 "$2" tls_client_hello "$splits" "$FAKED_PATTERN_HTTPS" "$3"
|
||||
@@ -87,6 +86,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -99,5 +101,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
|
||||
pktws_hostfake_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5" disorder
|
||||
@@ -22,7 +21,7 @@ pktws_hostfake_vary()
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -37,8 +36,8 @@ pktws_check_hostfake()
|
||||
local ok ttls attls f fooling
|
||||
local PAYLOAD="--payload=$3"
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
need_hostfakesplit=0
|
||||
ok=0
|
||||
@@ -58,7 +57,7 @@ pktws_check_hostfake()
|
||||
pktws_hostfake_vary $testf $domain "ip${IPVV}_autottl=-$ttl,3-20" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
done
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && eval need_hostfake=1
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_hostfakesplit=1
|
||||
[ $ok = 1 ]
|
||||
}
|
||||
|
||||
@@ -77,14 +76,15 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_hostfake $1 "$2" tls_client_hello "$3"
|
||||
}
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -97,5 +97,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ pktws_check_http()
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
|
||||
@@ -46,7 +46,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload=empty "--out-range=<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -82,7 +82,7 @@ pktws_fake_https_vary()
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -92,8 +92,6 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$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,midsld,1220 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
@@ -148,6 +146,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -156,5 +157,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ pktws_check_http()
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_fakedsplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
@@ -46,7 +46,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -83,7 +83,7 @@ pktws_fake_https_vary()
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -93,8 +93,6 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_FAKED_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 PAYLOAD="--payload=tls_client_hello"
|
||||
@@ -149,6 +147,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -157,5 +158,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ pktws_hostfake_vary()
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "$5"
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5"
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5"
|
||||
}
|
||||
|
||||
pktws_check_hostfake()
|
||||
@@ -33,8 +33,8 @@ pktws_check_hostfake()
|
||||
|
||||
[ "$need_hostfakesplit" = 0 ] && return 0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
@@ -69,7 +69,7 @@ pktws_check_http()
|
||||
local FAKE="$FAKE_HTTP"
|
||||
|
||||
if [ -n "$FAKE_HTTP" ]; then
|
||||
fake=bfake
|
||||
fake=fake_http
|
||||
else
|
||||
fake=fake_default_http
|
||||
fi
|
||||
@@ -83,13 +83,11 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
local FAKE="$FAKE_HTTPS"
|
||||
|
||||
if [ -n "$FAKE_HTTPS" ]; then
|
||||
fake=bfake
|
||||
fake=fake_tls
|
||||
else
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
@@ -101,6 +99,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -109,5 +110,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -15,3 +15,7 @@ MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
|
||||
|
||||
# can use MULTIDISORER=multidisorder_legacy
|
||||
MULTIDISORDER=${MULTIDISORDER:-multidisorder}
|
||||
|
||||
TCP_MD5=tcp_md5
|
||||
# OpenBSD can occupy 24 bytes in tcp options in SYN packet leaving no space for the md5 header
|
||||
[ "$UNAME" = OpenBSD ] && TCP_MD5=$TCP_MD5:tcp_nop_del
|
||||
|
||||
126
blockcheck2.sh
126
blockcheck2.sh
@@ -26,7 +26,6 @@ CURL=${CURL:-curl}
|
||||
|
||||
TEST_DEFAULT=${TEST_DEFAULT:-standard}
|
||||
DOMAINS_DEFAULT=${DOMAINS_DEFAULT:-rutracker.org}
|
||||
QNUM=${QNUM:-59781}
|
||||
SOCKS_PORT=${SOCKS_PORT:-1993}
|
||||
WS_UID=${WS_UID:-1}
|
||||
WS_GID=${WS_GID:-3003}
|
||||
@@ -35,8 +34,6 @@ DVTWS2=${DVTWS2:-${ZAPRET_BASE}/nfq2/dvtws2}
|
||||
WINWS2=${WINWS2:-${ZAPRET_BASE}/nfq2/winws2}
|
||||
MDIG=${MDIG:-${ZAPRET_BASE}/mdig/mdig}
|
||||
DESYNC_MARK=0x10000000
|
||||
IPFW_RULE_NUM=${IPFW_RULE_NUM:-1}
|
||||
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}
|
||||
@@ -45,12 +42,20 @@ HTTP_PORT=${HTTP_PORT:-80}
|
||||
HTTPS_PORT=${HTTPS_PORT:-443}
|
||||
QUIC_PORT=${QUIC_PORT:-443}
|
||||
UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org}
|
||||
PARALLEL_OUT=/tmp/zapret_parallel
|
||||
SIM_SUCCESS_RATE=${SIM_SUCCESS_RATE:-10}
|
||||
|
||||
HDRTEMP=/tmp/zapret-hdr
|
||||
IPFW_RULE_MAX=${IPFW_RULE_MAX:-999}
|
||||
IPFW_RULE_NUM=${IPFW_RULE_NUM:-$(($$ % $IPFW_RULE_MAX + 1))}
|
||||
IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-$(($$ % 64536 + 1000))}
|
||||
QNUM=${QNUM:-$(($$ % 64536 + 1000))}
|
||||
|
||||
NFT_TABLE=blockcheck
|
||||
IPSET_FILE=/tmp/blockcheck_ipset_$$.txt
|
||||
PARALLEL_OUT=/tmp/zapret_parallel_$$
|
||||
HDRTEMP=/tmp/zapret-hdr-$$
|
||||
NFT_TABLE=blockcheck$$
|
||||
IPT_OUT_CHAIN=blockcheck_output_$$
|
||||
IPT_IN_CHAIN=blockcheck_input_$$
|
||||
IPT_COMMENT="-m comment --comment blockcheck_$$"
|
||||
|
||||
DNSCHECK_DNS=${DNSCHECK_DNS:-8.8.8.8 1.1.1.1 77.88.8.1}
|
||||
DNSCHECK_DOM=${DNSCHECK_DOM:-pornhub.com ej.ru rutracker.org www.torproject.org bbc.com}
|
||||
@@ -59,7 +64,6 @@ DNSCHECK_DIG1=/tmp/dig1.txt
|
||||
DNSCHECK_DIG2=/tmp/dig2.txt
|
||||
DNSCHECK_DIGS=/tmp/digs.txt
|
||||
|
||||
IPSET_FILE=/tmp/blockcheck_ipset.txt
|
||||
|
||||
unset PF_STATUS
|
||||
PF_RULES_SAVE=/tmp/pf-zapret-save.conf
|
||||
@@ -240,7 +244,7 @@ mdig_vars()
|
||||
# $1 - ip version 4/6
|
||||
# $2 - hostname
|
||||
|
||||
hostvar=$(echo $2 | sed -e 's/[\./?&#@%*$^:~=!()+-]/_/g')
|
||||
hostvar=$(echo $2 | sed -e 's/[\./?&#@%*$^:~=!()+-]/_/g' | tr 'A-Z' 'a-z')
|
||||
cachevar=DNSCACHE_${hostvar}_$1
|
||||
countvar=${cachevar}_COUNT
|
||||
eval count=\$${countvar}
|
||||
@@ -297,7 +301,7 @@ mdig_resolve_all()
|
||||
mdig_vars "$1" "$sdom"
|
||||
if [ -n "$count" ]; then
|
||||
n=0
|
||||
while [ "$n" -le $count ]; do
|
||||
while [ "$n" -lt $count ]; do
|
||||
eval ip__=\$${cachevar}_$n
|
||||
if [ -n "$ips__" ]; then
|
||||
ips__="$ips__ $ip__"
|
||||
@@ -408,8 +412,14 @@ zp_already_running()
|
||||
CYGWIN)
|
||||
win_process_exists $PKTWSD || win_process_exists winws || win_process_exists goodbyedpi
|
||||
;;
|
||||
*)
|
||||
FreeBSD|OpenBSD)
|
||||
process_exists $PKTWSD || process_exists tpws || process_exists dvtws
|
||||
;;
|
||||
Linux)
|
||||
process_exists $PKTWSD || process_exists tpws || process_exists nfqws
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
esac
|
||||
}
|
||||
check_already()
|
||||
@@ -633,11 +643,11 @@ curl_with_dig()
|
||||
# $2 - domain name
|
||||
# $3 - port
|
||||
# $4+ - curl params
|
||||
local dom=$2 port=$3
|
||||
local dom="$2" port=$3
|
||||
local sdom suri ip
|
||||
|
||||
split_by_separator "$dom" / sdom suri
|
||||
mdig_resolve $1 ip $sdom
|
||||
mdig_resolve $1 ip "$sdom"
|
||||
shift ; shift ; shift
|
||||
if [ -n "$ip" ]; then
|
||||
curl_with_subst_ip "$sdom" "$port" "$ip" "$@"
|
||||
@@ -652,12 +662,12 @@ curl_probe()
|
||||
# $3 - port
|
||||
# $4 - subst ip
|
||||
# $5+ - curl params
|
||||
local ipv=$1 dom=$2 port=$3 subst=$4
|
||||
local ipv=$1 dom="$2" port=$3 subst=$4
|
||||
shift; shift; shift; shift
|
||||
if [ -n "$subst" ]; then
|
||||
curl_with_subst_ip $dom $port $subst "$@"
|
||||
curl_with_subst_ip "$dom" $port $subst "$@"
|
||||
else
|
||||
curl_with_dig $ipv $dom $port "$@"
|
||||
curl_with_dig $ipv "$dom" $port "$@"
|
||||
fi
|
||||
}
|
||||
curl_test_http()
|
||||
@@ -668,7 +678,7 @@ curl_test_http()
|
||||
# $4 - "detail" - detail info
|
||||
|
||||
local code loc hdrt="${HDRTEMP}_${!:-$$}.txt" dom="$(tolower "$2")"
|
||||
curl_probe $1 $2 $HTTP_PORT "$3" -SsD "$hdrt" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
|
||||
curl_probe $1 "$2" $HTTP_PORT "$3" -SsD "$hdrt" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
|
||||
code=$?
|
||||
rm -f "$hdrt"
|
||||
return $code
|
||||
@@ -680,6 +690,7 @@ curl_test_http()
|
||||
code=$(hdrfile_http_code "$hdrt")
|
||||
[ "$code" = 301 -o "$code" = 302 -o "$code" = 307 -o "$code" = 308 ] && {
|
||||
loc=$(hdrfile_location "$hdrt")
|
||||
split_by_separator "$dom" / dom
|
||||
tolower "$loc" | grep -qE "^https?://.*$dom(/|$)" ||
|
||||
tolower "$loc" | grep -vqE '^https?://' || {
|
||||
echo suspicious redirection $code to : $loc
|
||||
@@ -703,7 +714,7 @@ curl_test_https_tls12()
|
||||
# $3 - subst ip
|
||||
|
||||
# do not use tls 1.3 to make sure server certificate is not encrypted
|
||||
curl_probe $1 $2 $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1
|
||||
curl_probe $1 "$2" $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1
|
||||
}
|
||||
curl_test_https_tls13()
|
||||
{
|
||||
@@ -712,7 +723,7 @@ curl_test_https_tls13()
|
||||
# $3 - subst ip
|
||||
|
||||
# force TLS1.3 mode
|
||||
curl_probe $1 $2 $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1
|
||||
curl_probe $1 "$2" $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1
|
||||
}
|
||||
|
||||
curl_test_http3()
|
||||
@@ -721,7 +732,7 @@ curl_test_http3()
|
||||
# $2 - domain name
|
||||
|
||||
# force QUIC only mode without tcp
|
||||
curl_with_dig $1 $2 $QUIC_PORT $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME_QUIC --http3-only $CURL_OPT "https://$2" -o /dev/null 2>&1
|
||||
curl_with_dig $1 "$2" $QUIC_PORT $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME_QUIC --http3-only $CURL_OPT "https://$2" -o /dev/null 2>&1
|
||||
}
|
||||
|
||||
ipt_aux_scheme()
|
||||
@@ -731,24 +742,24 @@ ipt_aux_scheme()
|
||||
# $3 - port
|
||||
|
||||
# to avoid possible INVALID state drop
|
||||
[ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn -j ACCEPT
|
||||
[ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! $IPT_COMMENT --syn -j ACCEPT
|
||||
|
||||
local icmp_filter="-p icmp -m icmp --icmp-type"
|
||||
[ "$IPV" = 6 ] && icmp_filter="-p icmpv6 -m icmp6 --icmpv6-type"
|
||||
IPT_ADD_DEL $1 INPUT $icmp_filter time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
IPT_ADD_DEL $1 INPUT $icmp_filter time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK $IPT_COMMENT -j DROP
|
||||
|
||||
# for strategies with incoming packets involved (autottl)
|
||||
IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID -j ACCEPT
|
||||
IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID $IPT_COMMENT -j ACCEPT
|
||||
if [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ]; then
|
||||
# the only way to reliable disable ipv6 defrag. works only in 4.16+ kernels
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -p $2 -m frag -j CT --notrack
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -p $2 -m frag $IPT_COMMENT -j CT --notrack
|
||||
elif [ "$IPV" = 4 ]; then
|
||||
# enable fragments
|
||||
IPT_ADD_DEL $1 OUTPUT -f -j ACCEPT
|
||||
IPT_ADD_DEL $1 OUTPUT -f $IPT_COMMENT -j ACCEPT
|
||||
fi
|
||||
# enable everything generated by nfqws (works only in OUTPUT, not in FORWARD)
|
||||
# raw table may not be present
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CT --notrack
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK $IPT_COMMENT -j CT --notrack
|
||||
}
|
||||
ipt_scheme()
|
||||
{
|
||||
@@ -758,18 +769,18 @@ ipt_scheme()
|
||||
|
||||
local ip
|
||||
|
||||
$IPTABLES -t mangle -N blockcheck_output 2>/dev/null
|
||||
$IPTABLES -t mangle -F blockcheck_output
|
||||
IPT OUTPUT -t mangle -j blockcheck_output
|
||||
$IPTABLES -t mangle -N $IPT_OUT_CHAIN 2>/dev/null
|
||||
$IPTABLES -t mangle -F $IPT_OUT_CHAIN
|
||||
IPT OUTPUT -t mangle -j $IPT_OUT_CHAIN
|
||||
|
||||
# prevent loop
|
||||
$IPTABLES -t mangle -A blockcheck_output -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_output ! -p $1 -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_output -p $1 ! --dport $2 -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN ! -p $1 -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -p $1 ! --dport $2 -j RETURN
|
||||
|
||||
for ip in $3; do
|
||||
$IPTABLES -t mangle -A blockcheck_output -d $ip -j CONNMARK --or-mark $DESYNC_MARK
|
||||
$IPTABLES -t mangle -A blockcheck_output -d $ip -j NFQUEUE --queue-num $QNUM
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -d $ip -j CONNMARK --or-mark $DESYNC_MARK
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -d $ip -j NFQUEUE --queue-num $QNUM
|
||||
done
|
||||
|
||||
ipt_aux_scheme 1 $1 $2
|
||||
@@ -845,9 +856,9 @@ pktws_ipt_unprepare()
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
ipt_aux_scheme 0 $1 $2
|
||||
IPT_DEL OUTPUT -t mangle -j blockcheck_output
|
||||
$IPTABLES -t mangle -F blockcheck_output 2>/dev/null
|
||||
$IPTABLES -t mangle -X blockcheck_output 2>/dev/null
|
||||
IPT_DEL OUTPUT -t mangle -j $IPT_OUT_CHAIN
|
||||
$IPTABLES -t mangle -F $IPT_OUT_CHAIN 2>/dev/null
|
||||
$IPTABLES -t mangle -X $IPT_OUT_CHAIN 2>/dev/null
|
||||
;;
|
||||
nftables)
|
||||
nft delete table inet $NFT_TABLE 2>/dev/null
|
||||
@@ -875,17 +886,17 @@ pktws_ipt_prepare_tcp()
|
||||
|
||||
pktws_ipt_prepare tcp $1 "$2"
|
||||
|
||||
# for autottl mode
|
||||
# for autottl mode and tcp_mss detection
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
$IPTABLES -N blockcheck_input -t mangle 2>/dev/null
|
||||
$IPTABLES -F blockcheck_input -t mangle 2>/dev/null
|
||||
IPT INPUT -t mangle -j blockcheck_input
|
||||
$IPTABLES -t mangle -A blockcheck_input ! -p tcp -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_input -p tcp ! --sport $1 -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_input -p tcp ! --tcp-flags SYN,ACK SYN,ACK -j RETURN
|
||||
$IPTABLES -N $IPT_IN_CHAIN -t mangle 2>/dev/null
|
||||
$IPTABLES -F $IPT_IN_CHAIN -t mangle 2>/dev/null
|
||||
IPT INPUT -t mangle -j $IPT_IN_CHAIN
|
||||
$IPTABLES -t mangle -A $IPT_IN_CHAIN ! -p tcp -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_IN_CHAIN -p tcp ! --sport $1 -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_IN_CHAIN -p tcp ! --tcp-flags SYN,ACK SYN,ACK -j RETURN
|
||||
for ip in $2; do
|
||||
$IPTABLES -A blockcheck_input -t mangle -s $ip -j NFQUEUE --queue-num $QNUM
|
||||
$IPTABLES -A $IPT_IN_CHAIN -t mangle -s $ip -j NFQUEUE --queue-num $QNUM
|
||||
done
|
||||
;;
|
||||
nftables)
|
||||
@@ -909,9 +920,9 @@ pktws_ipt_unprepare_tcp()
|
||||
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
IPT_DEL INPUT -t mangle -j blockcheck_input
|
||||
$IPTABLES -t mangle -F blockcheck_input 2>/dev/null
|
||||
$IPTABLES -t mangle -X blockcheck_input 2>/dev/null
|
||||
IPT_DEL INPUT -t mangle -j $IPT_IN_CHAIN
|
||||
$IPTABLES -t mangle -F $IPT_IN_CHAIN 2>/dev/null
|
||||
$IPTABLES -t mangle -X $IPT_IN_CHAIN 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -939,7 +950,8 @@ pktws_start()
|
||||
"$DVTWS2" --port=$IPFW_DIVERT_PORT --lua-init=@"$ZAPRET_BASE/lua/zapret-lib.lua" --lua-init=@"$ZAPRET_BASE/lua/zapret-antidpi.lua" "$@" >/dev/null &
|
||||
;;
|
||||
CYGWIN)
|
||||
"$WINWS2" $WF --ipset="$IPSET_FILE" --lua-init=@"$ZAPRET_BASE/lua/zapret-lib.lua" --lua-init=@"$ZAPRET_BASE/lua/zapret-antidpi.lua" "$@" >/dev/null &
|
||||
# allow multiple PKTWS instances with the same wf filter but different ipset
|
||||
"$WINWS2" --wf-dup-check=0 $WF --ipset="$IPSET_FILE" --lua-init=@"$ZAPRET_BASE/lua/zapret-lib.lua" --lua-init=@"$ZAPRET_BASE/lua/zapret-antidpi.lua" "$@" >/dev/null &
|
||||
;;
|
||||
esac
|
||||
PID=$!
|
||||
@@ -990,7 +1002,7 @@ curl_test()
|
||||
if [ "$PARALLEL" = 1 ]; then
|
||||
rm -f "${PARALLEL_OUT}"*
|
||||
for n in $(seq -s ' ' 1 $REPEATS); do
|
||||
$1 "$IPV" $2 $3 "$4" >"${PARALLEL_OUT}_$n" &
|
||||
$1 "$IPV" "$2" $3 "$4" >"${PARALLEL_OUT}_$n" &
|
||||
pids="${pids:+$pids }$!"
|
||||
done
|
||||
n=1
|
||||
@@ -1009,7 +1021,7 @@ curl_test()
|
||||
while [ $n -lt $REPEATS ]; do
|
||||
n=$(($n+1))
|
||||
[ $REPEATS -gt 1 ] && printf "[attempt $n] "
|
||||
if $1 "$IPV" $2 $3 "$4" ; then
|
||||
if $1 "$IPV" "$2" $3 "$4" ; then
|
||||
[ $REPEATS -gt 1 ] && echo 'AVAILABLE'
|
||||
else
|
||||
code=$?
|
||||
@@ -1034,7 +1046,7 @@ ws_curl_test()
|
||||
# $2 - test function
|
||||
# $3 - domain
|
||||
# $4,$5,$6, ... - ws params
|
||||
local code ws_start=$1 testf=$2 dom=$3
|
||||
local code ws_start=$1 testf=$2 dom="$3"
|
||||
|
||||
[ "$SIMULATE" = 1 ] && {
|
||||
n=$(random 0 99)
|
||||
@@ -1050,7 +1062,7 @@ ws_curl_test()
|
||||
shift
|
||||
shift
|
||||
$ws_start "$@"
|
||||
curl_test $testf $dom
|
||||
curl_test $testf "$dom"
|
||||
code=$?
|
||||
ws_kill
|
||||
return $code
|
||||
@@ -1060,11 +1072,11 @@ pktws_curl_test()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3,$4,$5, ... - nfqws/dvtws params
|
||||
local testf=$1 dom=$2 strategy code
|
||||
local testf=$1 dom="$2" strategy code
|
||||
|
||||
shift; shift;
|
||||
echo - $testf ipv$IPV $dom : $PKTWSD ${WF:+$WF }${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }$@${PKTWS_EXTRA_POST:+ $PKTWS_EXTRA_POST}${PKTWS_EXTRA_POST_1:+ "$PKTWS_EXTRA_POST_1"}${PKTWS_EXTRA_POST_2:+ "$PKTWS_EXTRA_POST_2"}${PKTWS_EXTRA_POST_3:+ "$PKTWS_EXTRA_POST_3"}${PKTWS_EXTRA_POST_4:+ "$PKTWS_EXTRA_POST_4"}${PKTWS_EXTRA_POST_5:+ "$PKTWS_EXTRA_POST_5"}${PKTWS_EXTRA_POST_6:+ "$PKTWS_EXTRA_POST_6"}${PKTWS_EXTRA_POST_7:+ "$PKTWS_EXTRA_POST_7"}${PKTWS_EXTRA_POST_8:+ "$PKTWS_EXTRA_POST_8"}${PKTWS_EXTRA_POST_9:+ "$PKTWS_EXTRA_POST_9"}
|
||||
ws_curl_test pktws_start $testf $dom ${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }"$@"${PKTWS_EXTRA_POST:+ $PKTWS_EXTRA_POST}${PKTWS_EXTRA_POST_1:+ "$PKTWS_EXTRA_POST_1"}${PKTWS_EXTRA_POST_2:+ "$PKTWS_EXTRA_POST_2"}${PKTWS_EXTRA_POST_3:+ "$PKTWS_EXTRA_POST_3"}${PKTWS_EXTRA_POST_4:+ "$PKTWS_EXTRA_POST_4"}${PKTWS_EXTRA_POST_5:+ "$PKTWS_EXTRA_POST_5"}${PKTWS_EXTRA_POST_6:+ "$PKTWS_EXTRA_POST_6"}${PKTWS_EXTRA_POST_7:+ "$PKTWS_EXTRA_POST_7"}${PKTWS_EXTRA_POST_8:+ "$PKTWS_EXTRA_POST_8"}${PKTWS_EXTRA_POST_9:+ "$PKTWS_EXTRA_POST_9"}
|
||||
ws_curl_test pktws_start $testf "$dom" ${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }"$@"${PKTWS_EXTRA_POST:+ $PKTWS_EXTRA_POST}${PKTWS_EXTRA_POST_1:+ "$PKTWS_EXTRA_POST_1"}${PKTWS_EXTRA_POST_2:+ "$PKTWS_EXTRA_POST_2"}${PKTWS_EXTRA_POST_3:+ "$PKTWS_EXTRA_POST_3"}${PKTWS_EXTRA_POST_4:+ "$PKTWS_EXTRA_POST_4"}${PKTWS_EXTRA_POST_5:+ "$PKTWS_EXTRA_POST_5"}${PKTWS_EXTRA_POST_6:+ "$PKTWS_EXTRA_POST_6"}${PKTWS_EXTRA_POST_7:+ "$PKTWS_EXTRA_POST_7"}${PKTWS_EXTRA_POST_8:+ "$PKTWS_EXTRA_POST_8"}${PKTWS_EXTRA_POST_9:+ "$PKTWS_EXTRA_POST_9"}
|
||||
|
||||
code=$?
|
||||
[ "$code" = 0 ] && {
|
||||
@@ -1086,11 +1098,11 @@ xxxws_curl_test_update()
|
||||
# $2 - test function
|
||||
# $3 - domain
|
||||
# $4,$5,$6, ... - nfqws2/dvtws2 params
|
||||
local code xxxf=$1 testf=$2 dom=$3
|
||||
local code xxxf=$1 testf=$2 dom="$3"
|
||||
shift
|
||||
shift
|
||||
shift
|
||||
$xxxf $testf $dom "$@"
|
||||
$xxxf $testf "$dom" "$@"
|
||||
code=$?
|
||||
[ $code = 0 ] && strategy="${strategy:-$@}"
|
||||
return $code
|
||||
@@ -1314,7 +1326,6 @@ check_domain_http_tcp()
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_tcp $2
|
||||
ws_kill
|
||||
|
||||
check_domain_prolog $1 $2 $4 || return
|
||||
@@ -1342,7 +1353,6 @@ check_domain_http_udp()
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_udp $2
|
||||
ws_kill
|
||||
|
||||
check_domain_prolog $1 $2 $3 || return
|
||||
|
||||
@@ -95,7 +95,7 @@ end_with_newline()
|
||||
}
|
||||
trim()
|
||||
{
|
||||
awk '{gsub(/^ +| +$/,"")}1'
|
||||
awk '{gsub(/^[ \t]+|[ \t]+$/,"")}1'
|
||||
}
|
||||
split_by_separator()
|
||||
{
|
||||
@@ -119,7 +119,7 @@ dir_is_not_empty()
|
||||
# $1 - directory
|
||||
local n
|
||||
[ -d "$1" ] || return 1
|
||||
n=$(ls "$1" | wc -c | xargs)
|
||||
n=$(ls -A "$1" | wc -c | xargs)
|
||||
[ "$n" != 0 ]
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ setup_md5()
|
||||
{
|
||||
[ -n "$MD5" ] && return
|
||||
MD5=md5sum
|
||||
exists $MD5 || MD5=md5
|
||||
exists $MD5 || MD5="md5 -q"
|
||||
}
|
||||
|
||||
md5f()
|
||||
@@ -394,9 +394,9 @@ shell_name()
|
||||
process_exists()
|
||||
{
|
||||
if exists pgrep; then
|
||||
pgrep ^$1$ >/dev/null
|
||||
pgrep "^$1$" >/dev/null
|
||||
elif exists pidof; then
|
||||
pidof $1 >/dev/null
|
||||
pidof "$1" >/dev/null
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -36,8 +36,8 @@ ask_list()
|
||||
# $3 - (optional) default value
|
||||
local M_DEFAULT
|
||||
eval M_DEFAULT="\$$1"
|
||||
local M_ALL=$M_DEFAULT
|
||||
local M="" m M_OLD
|
||||
local M_DEFAULT_VAR="$M_DEFAULT"
|
||||
local M="" m
|
||||
|
||||
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;}
|
||||
|
||||
@@ -53,5 +53,5 @@ ask_list()
|
||||
echo selected : $M
|
||||
eval $1="\"$M\""
|
||||
|
||||
[ "$M" != "$M_DEFAULT" ]
|
||||
[ "$M" != "$M_DEFAULT_VAR" ]
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ check_system()
|
||||
|
||||
get_free_space_mb()
|
||||
{
|
||||
df -m $PWD | awk '/[0-9]%/{print $(NF-2)}'
|
||||
df -m "$1" | awk '/[0-9]%/{print $(NF-2)}'
|
||||
}
|
||||
get_ram_kb()
|
||||
{
|
||||
@@ -779,7 +779,9 @@ select_fwtype()
|
||||
echo WARNING ! if you need large lists it may be necessary to fall back to iptables+ipset firewall
|
||||
}
|
||||
echo select firewall type :
|
||||
ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE
|
||||
ask_list FWTYPE "iptables nftables" "$FWTYPE"
|
||||
# always write config var to prevent auto discovery every time
|
||||
write_config_var FWTYPE
|
||||
}
|
||||
|
||||
dry_run_nfqws_()
|
||||
|
||||
@@ -77,8 +77,7 @@ nft_rule_exists()
|
||||
nft_add_rule ruletest "$2"
|
||||
rule=$(nft list chain inet $ZAPRET_NFT_TABLE ruletest | sed -n '3s/\t//gp')
|
||||
nft_flush_chain ruletest
|
||||
local yes=$(nft list chain inet $ZAPRET_NFT_TABLE $1 | sed -n "s/^[\t]*$rule\$/1/p")
|
||||
[ -n "$yes" ]
|
||||
nft list chain inet $ZAPRET_NFT_TABLE $1 | trim | grep -qxF "$rule"
|
||||
}
|
||||
|
||||
nft_del_all_chains_from_table()
|
||||
|
||||
@@ -178,3 +178,20 @@ v0.8.1
|
||||
* nfqws2: alternative representation of payload filter in execution_plan item
|
||||
* nfqws2: --payload-disable
|
||||
* nfqws2: gracefully shutdown on SIGINT and SIGTERM
|
||||
* nfqws2: harden wireguard detection. do not detect if reserved bytes 1..3 != 0
|
||||
|
||||
0.8.5
|
||||
|
||||
* nfqws2: do not require / in the beginning of URI in http
|
||||
* zapret-lib: rawsend_dissect_segmented support URG
|
||||
* zapret-antidpi: oob
|
||||
* blockcheck2: 17-oob.sh
|
||||
* nfqws2: set desync.tcp_mss to minimum of both ends or default if at least one is unknown
|
||||
* zapret-lib: tcp_nop_del
|
||||
* blockcheck2: tcp_nop_del in SYN packets with md5 in openbsd
|
||||
|
||||
0.8.6
|
||||
|
||||
* winws2, blockcheck2: allow multiple instances in windows, linux, freebsd (not openbsd)
|
||||
* nfqws2: fix critical bug - wrong ipv6 dissection
|
||||
* zapret-auto: fix standard_failure_detector http redirect regression
|
||||
|
||||
@@ -5,6 +5,7 @@ make -C /opt/zapret2 systemd
|
||||
|
||||
FreeBSD :
|
||||
|
||||
pkg install pkgconf
|
||||
pkg search luajit-2
|
||||
# see what's the version available
|
||||
pkg install luajit-2.1.0.20250728
|
||||
|
||||
@@ -182,6 +182,7 @@
|
||||
- [fakeddisorder](#fakeddisorder)
|
||||
- [hostfakesplit](#hostfakesplit)
|
||||
- [tcpseg](#tcpseg)
|
||||
- [oob](#oob)
|
||||
- [UDP Fooling](#udp-fooling)
|
||||
- [udplen](#udplen)
|
||||
- [dht\_dn](#dht_dn)
|
||||
@@ -263,7 +264,10 @@
|
||||
- [openrc integration principles](#openrc-integration-principles)
|
||||
- [openrc cheat sheet](#openrc-cheat-sheet)
|
||||
- [Alternative installation on systemd](#alternative-installation-on-systemd)
|
||||
- [Other firmwares](#other-firmwares)
|
||||
- [Other firmwares](#other-firmwares)
|
||||
- [Windows](#windows)
|
||||
- [Windows 7](#windows-7)
|
||||
- [Windows Server](#windows-server)
|
||||
|
||||
|
||||
# Introduction
|
||||
@@ -276,6 +280,8 @@ The core component of zapret2 is the **nfqws2** program (**dvtws2** on BSD, **wi
|
||||
|
||||
Consequently, the Lua code is the next most critical part of the project. The base package includes the [zapret-lib.lua](#zapret-liblua-base-function-library) helper library, the [zapret-antidpi.lua](#zapret-antidpilua-dpi-attack-program-library) DPI attack library, and the [zapret-auto.lua](#zapret-autolua-automation-and-orchestration-library) orchestration library for dynamic decision-making. Additionally, it features `zapret-tests.lua` for testing C functions, `zapret-wgobfs.lua` for WireGuard protocol obfuscation, and `zapret-pcap.lua` for capturing traffic into .cap files.
|
||||
|
||||
Project requires LuaJIT-2.1+ or PUC Lua 5.3+. Older versions are not tested and not supported.
|
||||
|
||||
Traffic redirection from the kernel is handled by [iptables](#traffic-interception-using-iptables) and [nftables](#traffic-interception-using-nftables) in [Linux](#traffic-interception-in-the-linux-kernel), [ipfw](#traffic-interception-in-the-freebsd-kernel) in [FreeBSD](#traffic-interception-in-the-freebsd-kernel), and [pf](#traffic-interception-in-the-openbsd-kernel) in [OpenBSD](#traffic-interception-in-the-openbsd-kernel). On [Windows](#traffic-interception-in-the-windows-kernel), this functionality is built directly into the winws2 process via the WinDivert driver. The kernel interception scheme, nfqws2, and the Lua code constitute the project's minimal working core. Everything else is supplementary, secondary, or optional.
|
||||
|
||||
Secondary components include Linux [startup scripts](#startup-scripts) (`init.d`, `common`, `ipset`, `install_easy.sh`, `uninstall_easy.sh`) and [blockcheck2](#blockcheck2), a tool for automated strategy testing. The purpose of the startup scripts is to coordinate the initialization of tables and nfqws2 instances while accounting for the specifics of various distributions (OpenWrt, systemd, OpenRC). They also provide support for synchronized updates of various [lists](#list-management-system) and [loading](#create_ipsetsh) IP lists into kernel-space (ipset). Users can implement these tasks using their own tools if preferred or if the provided [startup scripts](#startup-scripts) do not meet their needs. These scripts store all settings in a [config](#config-file) file located in the project root; this config is specific to the scripts, and nfqws2 is unaware of it.
|
||||
@@ -697,6 +703,7 @@ Specific parameters for winws2:
|
||||
--wf-raw-part=<filter>|@<filename> ; WinDivert constructor: partial WinDivert raw filter. Combined using the OR principle.
|
||||
--wf-filter-lan=0|1 ; WinDivert constructor: filter out non-global IP addresses. Default is yes.
|
||||
--wf-raw=<filter>|@<filename> ; full WinDivert filter. Overrides the constructor.
|
||||
--wf-dup-check[=0|1] ; 1 (default) = do not allow duplicate winws2 instances with the same wf filter
|
||||
--wf-save=<filename> ; save the final complete WinDivert filter to a file
|
||||
LOGICAL NETWORK FILTER:
|
||||
--ssid-filter=ssid1[,ssid2,ssid3,...] ; list of WiFi networks; interception is enabled only when connected to these, otherwise it is disabled.
|
||||
@@ -1307,7 +1314,7 @@ desync
|
||||
| l7payload | string | [payload type](#protocol-detection) of the current packet or packet group | defaults to "unknown" if undetermined |
|
||||
| l7proto | string | [flow protocol](#protocol-detection) | defaults to "unknown" if undetermined |
|
||||
| reasm_data | string | result of reassembling a multi-packet message, or the payload itself if no reassembly occurred | currently applied only to TCP |
|
||||
| reasm_offset | string | offset of the current replayed packet within the reassembled data | currently applied only to TCP |
|
||||
| reasm_offset | number | offset of the current replayed packet within the reassembled data | currently applied only to TCP |
|
||||
| decrypt_data | string | result of reassembling and decrypting the payload or payloads of multiple packets | used for QUIC |
|
||||
| tcp_mss | number | MSS of the remote end of the TCP connection | always present, only for TCP |
|
||||
| track | table | data bound to the conntrack entry | only if conntrack is present; may be absent |
|
||||
@@ -3025,9 +3032,10 @@ On any OS, it is possible to maintain a continuous linear `ip_id` order for a pe
|
||||
| tcp_ack | A positive or negative offset for the TCP Acknowledgment Number. |
|
||||
| tcp_ts | A positive or negative offset for the TCP Timestamp. This only functions if the Timestamp option is already present. |
|
||||
| tcp_md5 | Add a TCP MD5 Signature header if it is not already present. Defaults to random bytes, but a 16-byte hex string can be specified. |
|
||||
| tcp_flags_set | Set TCP flags. Flags are provided as a comma-separated list: FIN, SYN, RST, PUSH, ACK, URG, ECE, CWR. |
|
||||
| tcp_flags_set | Set TCP flags. Flags are provided as a comma-separated list: FIN, SYN, RST, PUSH, ACK, URG, ECE, CWR. |
|
||||
| tcp_flags_unset | Clear (unset) TCP flags. Follows the same format as `tcp_flags_set`. |
|
||||
| tcp_ts_up | Move the TCP Timestamp option to the very beginning of the options list, if present. |
|
||||
| tcp_nop_del | Delete all NOP TCP options to free space in the header |
|
||||
| fool | Name of the custom fooling function. It takes a dissect and a `fooling_options` table. |
|
||||
|
||||
IPv6 extension headers are added in the following order:
|
||||
@@ -3144,6 +3152,10 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
Sends dissect `dis` with automatic TCP segmentation based on MSS, applying `options.fooling` and `options.ipid`.
|
||||
The `ipid` is applied to each fragment. Segmentation is not possible for UDP and is not performed.
|
||||
|
||||
- if dis is nil, desync.dis is used.
|
||||
- if mss is nil, desync.tcp_mss is used.
|
||||
- if options is nil, options are created from desync.arg
|
||||
|
||||
### rawsend_payload_segmented
|
||||
|
||||
```
|
||||
@@ -3795,6 +3807,42 @@ No verdict is issued.
|
||||
|
||||
Using `tcpseg`, you can perform `seqovl` without segmentation by using markers "0,-1". To replace the current dissect, it can be combined with `drop`.
|
||||
|
||||
### oob
|
||||
|
||||
```
|
||||
function oob(ctx, desync)
|
||||
```
|
||||
|
||||
- arg: [standard fooling](#standard-fooling)
|
||||
- arg: [standard ipid](#standard-ipid)
|
||||
- arg: [standard ipfrag](#standard-ipfrag)
|
||||
- arg: [standard reconstruct](#standard-reconstruct)
|
||||
- arg: [standard rawsend](#standard-rawsend)
|
||||
- arg: char - one OOB character
|
||||
- arg: byte - one OOB byte 0..255
|
||||
- arg: urp - urgent pointer [marker](#markers), "b" or "e". "b" is default.
|
||||
|
||||
Function intercepts TCP handshake shifting sequence numbers one byte to the left then inserts OOB byte into the first non-empty payload.
|
||||
After it's done it executes [instance cutoff](#instance_cutoff).
|
||||
|
||||
Target OS throws away OOB byte from the stream but DPI may analyze message with OOB byte as it's part thus breaking the message.
|
||||
|
||||
- OOB is obsolete but still supported in most OS. There are two RFCs. One assumes that th_urp points to the OOB byte,
|
||||
another one - to the next byte. Therefore, the value th_urp=0 is invalid according to one of the standards, but it can still work.
|
||||
To enable it, specify "urp=b".
|
||||
- Marker "urp" defines 0-based position of the OOB byte. Resulting th_urp , except the "b" case, is set incremented by 1. This is what most of the modern OS expect.
|
||||
- "urp=e" inserts an OOB byte after the very last byte of the payload - generally useless for DPI bypass, since DPI gets the entire original message.
|
||||
- For protocols in which the server initially waits for a client request, `--in-range=-s1` is enough. In Windows `--wf-tcp-in` is not needed. Automatically intercepted incoming packets with the SYN flag are sufficient.
|
||||
- For protocols in which the server sends data before the first message from client all incoming packets before that message should be intercepted. In Windows `--wf-tcp-in` is required.
|
||||
- Cannot be filtered by payload because after the start it's not possible to stop and not to insert the byte. Inserting a byte without OOB breaks the data.
|
||||
- oob is "lasting" desync. If profile switch occurs before oob is finished it must be duplicated to that profile or TCP will break because of sequence desync.
|
||||
- If this function is called for the first time not from the very beginning of the tcp connection it [cuts off](#instance_cutoff) immediately.
|
||||
- Hostlist filtering is possible only with '--ipcache-hostname'.
|
||||
- Can't work with functions that resend modified payload. multisplit, multidisorder, fakedsplit, fakeddisorder, etc will send duplicates without OOB.
|
||||
- If the payload is [multi-segment](#handling-multi-packet-payloads), the entire [reasm](#handling-multi-packet-payloads) is sent. OOB is inserted into the segment where urp hits.
|
||||
In this segment the th_urp is normalized by segment offset, the TH_URG flag is set. The rest of the parts are sent as is. The function drops the whole replay then [cuts itself off](#instance_cutoff).
|
||||
|
||||
|
||||
## UDP Fooling
|
||||
|
||||
There are far fewer options for UDP than for TCP due to the simplicity of the protocol. There isn't much that can be done with it.
|
||||
@@ -5052,7 +5100,7 @@ On classic Linux distributions with systemd, you can use the provided template u
|
||||
|
||||
This method does not apply ip/nf tables rules - you will have to handle that separately, as well as write the rules themselves. The rules must be placed somewhere so they are applied after the system starts. For example, you can create a separate systemd unit that runs a shell script or `nft -f /path/to/file.nft`.
|
||||
|
||||
## Other firmwares
|
||||
# Other firmwares
|
||||
|
||||
For static binaries, the host environment doesn't matter: PC, Android, set-top box, router, or any other device. Any firmware or Linux distribution will work; static binaries run on everything. They only require a kernel with the necessary build options or modules. However, in addition to binaries, the project uses scripts that rely on certain standard utilities.
|
||||
|
||||
@@ -5096,3 +5144,41 @@ It was chosen for this project based on the following characteristics:
|
||||
* All `iptables` modules are available in the repository and can be installed via `opkg`.
|
||||
* The repository contains a vast number of standard programs and additional software.
|
||||
* The availability of an SDK, allowing you to compile any missing components.
|
||||
|
||||
|
||||
# Windows
|
||||
|
||||
zapret was initially written for unix. It uses unix emulation layer cygwin on Windows to help migration.
|
||||
|
||||
If winws2 is run standalone cygwin1.dll is required in it's directory. If winws2 is run inside cygwin environment - cygwin1.dll must NOT be present in it's directory or it won't run.
|
||||
|
||||
cygwin emulate shared PID namespace and deliver signals only within one cygwin1.dll instance !
|
||||
To send signals sending program (kill, killall) must be run with the same cygwin1.dll as winws2.
|
||||
|
||||
It's possible to install cygwin and use winws2 inside cygwin installation.
|
||||
But it may be more comfortable to use [zapret-win-bundle](https://github.com/bol-van/zapret-win-bundle) which includes minimal cygwin.
|
||||
cygwin prompt is pre-configured with aliases for blockcheck, blockcheck2, winws, winws2, winws2 with standard Lua scripts.
|
||||
|
||||
32-bit Windows versions are not supported by zapret-win-bundle.
|
||||
|
||||
## Windows 7
|
||||
|
||||
Requirements for windows driver signing have changed in 2021.
|
||||
Official free updates of windows 7 ended in 2020.
|
||||
After 2020 for the years paid updates were available (ESU).
|
||||
One of the updates from ESU enables signatures used in windivert 2.2.2-A.
|
||||
There are several options :
|
||||
|
||||
1. Take `windivert64.sys` and `windivert.dll` version `2.2.0-C` or `2.2.0-D` from [here](https://reqrypt.org/download) and replace existing files.
|
||||
|
||||
2. [Hack ESU](https://hackandpwn.com/windows-7-esu-patching)
|
||||
|
||||
3. Use "BypassESU" patcher. Google it by name.
|
||||
|
||||
4. Use [UpdatePack7R2](https://blog.simplix.info). If you are in Russia or Belarus temporary change region in Control Panel.
|
||||
|
||||
## Windows Server
|
||||
|
||||
winws2 is linked against wlanapi.dll which is absent by default.
|
||||
To solve this problem run power shell as administrator and execute command `Install-WindowsFeature -Name Wireless-Networking`.
|
||||
Then reboot the system.
|
||||
|
||||
101
docs/manual.md
101
docs/manual.md
@@ -181,6 +181,7 @@
|
||||
- [fakeddisorder](#fakeddisorder)
|
||||
- [hostfakesplit](#hostfakesplit)
|
||||
- [tcpseg](#tcpseg)
|
||||
- [oob](#oob)
|
||||
- [Дурение udp](#дурение-udp)
|
||||
- [udplen](#udplen)
|
||||
- [dht\_dn](#dht_dn)
|
||||
@@ -261,7 +262,10 @@
|
||||
- [Принципы интеграции с openrc](#принципы-интеграции-с-openrc)
|
||||
- [Шпаргалка openrc](#шпаргалка-openrc)
|
||||
- [Альтернативная установка на systemd](#альтернативная-установка-на-systemd)
|
||||
- [Другие прошивки](#другие-прошивки)
|
||||
- [Другие прошивки](#другие-прошивки)
|
||||
- [Особенности Windows](#особенности-windows)
|
||||
- [Windows 7](#windows-7)
|
||||
- [Windows Server](#windows-server)
|
||||
|
||||
# Введение
|
||||
|
||||
@@ -280,6 +284,8 @@ zapret2 является пакетным манипулятором, основ
|
||||
Поэтому следующая по важности часть проекта - Lua код. В базовый комплект входит библиотека функций-хелперов [zapret-lib.lua](#библиотека-базовых-функций-zapret-liblua), библиотека программ автономных атак на DPI [zapret-antidpi.lua](#библиотека-программ-атаки-на-dpi-zapret-antidpilua), библиотека функций принятия динамических решений (оркестрации) [zapret-auto.lua](#библиотека-программ-автоматизации-и-оркестрации-zapret-autolua).
|
||||
Дополнительно присутствует набор тестов C функций `zapret-tests.lua`, средство обфускации wireguard протокола `zapret-wgobfs.lua` и средство записи дампа пакетов в cap файлы `zapret-pcap.lua`.
|
||||
|
||||
Проект может работать с LuaJIT-2.1+ или с PUC Lua 5.3+. Более старые версии могут иметь несовместимости, не тестируются и не поддерживаются.
|
||||
|
||||
Функции перенаправления трафика из ядра в [Linux](#перехват-трафика-в-ядре-linux) возложены на [iptables](#перехват-трафика-с-помощью-iptables) и [nftables](#перехват-трафика-с-помощью-nftables), в [FreeBSD](#перехват-трафика-в-ядре-freebsd) - на [ipfw](#перехват-трафика-в-ядре-freebsd), в [OpenBSD](#перехват-трафика-в-ядре-openbsd) - на [pf](#перехват-трафика-в-ядре-openbsd), в [Windows](#перехват-трафика-в-ядре-windows) - встроены в сам процесс winws2 посредством драйвера windivert.
|
||||
Схема перехвата трафика из ядра , nfqws2 и lua код составляют минимально рабочее ядро проекта. Все остальное является дополнительным, второстепенным и опциональным.
|
||||
|
||||
@@ -753,6 +759,7 @@ LUA DESYNC ACTION:
|
||||
--wf-raw-part=<filter>|@<filename> ; windivert конструктор : частичный windivert raw фильтр. обьединяется по принципу ИЛИ.
|
||||
--wf-filter-lan=0|1 ; windivert конструктор : отфильтровывать неглобальные IP адреса. по умолчанию - да.
|
||||
--wf-raw=<filter>|@<filename> ; полный windivert фильтр. замещает конструктор.
|
||||
--wf-dup-check[=0|1] ; управление проверкой на повторный запуск с теми же параметрами фильтра --wf ( по умолчанию 1 )
|
||||
--wf-save=<filename> ; сохранить полный итоговый windivert фильтр в файл
|
||||
LOGICAL NETWORK FILTER:
|
||||
--ssid-filter=ssid1[,ssid2,ssid3,...] ; список сетей wifi, при наличии подключения к которым перехват включается, а иначе не включается.
|
||||
@@ -1446,7 +1453,7 @@ desync
|
||||
| l7payload | string | тип [пейлоада](#распознавание-протоколов) текущего пакета или группы пакетов | если неизвестно - unknown |
|
||||
| l7proto | string | тип [протокола потока](#распознавание-протоколов) | если неизвестно - unknown |
|
||||
| reasm_data | string | результат сборки многопакетного сообщения, либо сам пейлоад, если сборки не было | пока применяется только для tcp |
|
||||
| reasm_offset | string | смещение текущего переигрываемого пакета в сборке | пока применяется только для tcp |
|
||||
| reasm_offset | number | смещение текущего переигрываемого пакета в сборке | пока применяется только для tcp |
|
||||
| decrypt_data | string | результат сборки и дешифровки пейлоада или пейлоадов нескольких пакетов | применяется для quic |
|
||||
| tcp_mss | number | MSS противоположного конца tcp соединения | присутствует всегда, только для tcp |
|
||||
| track | table | данные, привязанные к записи conntrack | только если есть conntrack, может не быть |
|
||||
@@ -3204,6 +3211,7 @@ Windows заменяет нулевые ip_id на собственную пос
|
||||
| tcp_flags_set | установить флаги TCP. флаги представлены списком через зяпятую : FIN,SYN,RST,PUSH,ACK,FIN,URG,ECE,CWR |
|
||||
| tcp_flags_unset | снять флаги TCP. аналогично tcp_flags_set |
|
||||
| tcp_ts_up | поднять tcp timestamp опцию в самое начало, если она есть |
|
||||
| tcp_nop_del | удалить все TCP опции NOP для освобождения места в заголовке TCP |
|
||||
| fool | имя кастомной функции фулинга. она берет диссект и таблицу fooling_options |
|
||||
|
||||
ipv6 extension headers добавляются в следующем порядке:
|
||||
@@ -3323,6 +3331,10 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
Отправить диссект dis с автоматической tcp сегментацией на базе mss с применением `options.fooling` и `options.ipid`.
|
||||
ipid применяется к каждому фрагменту. Для udp сегментация невозможна и не выполняется.
|
||||
|
||||
- Если dis отсутствует, берется desync.dis.
|
||||
- Если mss отсутствует, берется desync.tcp_mss.
|
||||
- Если options отсутствуют, они создаются на базе desync.arg.
|
||||
|
||||
### rawsend_payload_segmented
|
||||
|
||||
```
|
||||
@@ -3982,6 +3994,41 @@ function tcpseg(ctx, desync)
|
||||
|
||||
С помощью tcpseg можно сделать seqovl без сегментации, используя маркеры "0,-1". Для замещения текущего диссекта можно комбинировать с drop.
|
||||
|
||||
### oob
|
||||
|
||||
```
|
||||
function oob(ctx, desync)
|
||||
```
|
||||
|
||||
- arg: [standard fooling](#standard-fooling)
|
||||
- arg: [standard ipid](#standard-ipid)
|
||||
- arg: [standard ipfrag](#standard-ipfrag)
|
||||
- arg: [standard reconstruct](#standard-reconstruct)
|
||||
- arg: [standard rawsend](#standard-rawsend)
|
||||
- arg: char - 1 символ oob
|
||||
- arg: byte - числовое значение байта OOB 0..255
|
||||
- arg: urp - позиционный [маркер](#маркеры) для urgent pointer, "b" или "e". по умолчанию - "b"
|
||||
|
||||
Функция перехватывает TCP handshake, сдвигая sequence влево на 1 байт, затем вставляет 1 байт OOB в первый отсылаемый пейлоад и отсылает его.
|
||||
После отработки функция уходит в [cutoff](#instance_cutoff) по обоим направлениям.
|
||||
|
||||
ОС получателя выбрасывает OOB байт из потока, DPI может не выбрасывать и получать оригинальное сообщение со вставленным в него посторонним байтом, что может портить смысл всего сообщения.
|
||||
|
||||
- OOB - устаревший, но все еще поддерживаемый в ОС механизм. Имеется 2 стандарта. Один предполагает, что th_urp указывает на байт OOB,
|
||||
другой - на следующий за ним байт. Поэтому значение th_urp=0 невалидно по одному из стандартов, но все еще может работать.
|
||||
Чтобы задействовать его укажите "urp=b". Как показывает практика, "b" работает только на Linux серверах, остальные ломает.
|
||||
- Значение маркера urp означает позицию самого OOB байта. th_urp , кроме случая "b", увеличивается на 1 - согласно интерпретации RFC, поддерживаемой в основных ОС.
|
||||
- "urp=e" вставляет OOB байт после самого последнего байта пейлоада - для обхода DPI как правило бесполезно, поскольку DPI получает все оригинальное сообщение.
|
||||
- Для протоколов, в которых в самом начале сервер ждет запроса от клиента, требуется разрешение входящих в пределах `--in-range=-s1`. В Windows `--wf-tcp-in` не нужен. Достаточно автоматически перехватываемых SYN. К таким протоколам относятся http и tls.
|
||||
- Для протоколов, где сервер что-то шлет до первого сообщения от клиента, требуется разрешить все входящие пакеты до отсылки первого исходящего пакета с данными. В Windows `--wf-tcp-in` обязателен.
|
||||
- Не может быть отфильтровано по пейлоаду, поскольку после начала модификации tcp handshake соскок уже невозможен, иначе поедут sequence.
|
||||
- oob - длящаяся десинхронизация. Если возможно переключение профилей до момента окончания работы oob, oob должен быть дублирован в другой профиль, иначе TCP будет сломан из-за десинхронизации sequence.
|
||||
- Функция помечает специальный флаг, что была вызвана с самого начала соединения. Если управление получено после перескока профиля, происходит немедленный cutoff.
|
||||
- Фильтрация по хостлистам возможна только при `--ipcache-hostname`. Если в кэше хоста еще нет, и профиль получает управление не с начала соединения, срабатывает предыдущий пункт.
|
||||
- Не может работать с функциями, предполагающими отправку текущего пейлоада - multisplit, multidisorder, fakedsplit, fakeddisorder и тд. Они будут работать, но будут слать дубль без OOB. Ожидаемый результат "разбить на сегменты и всунуть OOB" как в tpws получить таким образом невозможно.
|
||||
- Если пейлоад [многопакетный](#особенности-приема-многопакетных-пейлоадов) - отсылается весь [reasm](#особенности-приема-многопакетных-пейлоадов). OOB вставляется в тот сегмент, куда попал urp.
|
||||
В этом сегменте th_urp нормализуется по смещению сегмента, выставляется флаг TH_URG. Остальные части шлются как есть. Функция дропает весь replay, затем уходит в [cutoff](#instance_cutoff) по обоим направлениям.
|
||||
|
||||
## Дурение udp
|
||||
|
||||
Для udp намного меньше вариантов, чем для tcp, в силу простоты данного протокола. С ним особо нечего делать.
|
||||
@@ -5238,7 +5285,7 @@ rc-update add zapret2
|
||||
|
||||
Этот способ не поднимает правила ip/nf tables - вам это придется сделать отдельно, как и написать сами правила. Правила нужно прописать куда-то, чтобы они поднимались после старта системы. Например, можно сделать отдельный systemd unit с запуском шелл скрипта или `nft -f /path/to/file.nft`.
|
||||
|
||||
## Другие прошивки
|
||||
# Другие прошивки
|
||||
|
||||
Для статических бинарников не имеет значения на чем они запущены: PC, android, приставка, роутер, любой другой девайс.
|
||||
Подойдет любая прошивка, дистрибутив Linux. Статические бинарники запустятся на всем.
|
||||
@@ -5300,3 +5347,51 @@ OpenWrt является одной из немногих относительн
|
||||
* в репозитории есть все модули iptables, их можно доустановить через opkg
|
||||
* в репозитории есть огромное количество стандартных программ и дополнительного софта
|
||||
* наличие SDK, позволяющего собрать недостающее
|
||||
|
||||
|
||||
# Особенности Windows
|
||||
|
||||
zapret изначально был написан для unix. Для облегчения портирования под Windows используется обертка cygwin, эмулирующая unix среду.
|
||||
Если winws2 запускается отдельно - требуется cygwin1.dll в той же директории, если в составе cygwin среды - cygwin1.dll не должно быть в той же директории,
|
||||
иначе не запустится !
|
||||
|
||||
cygwin эмулирует общее пространство PID процессов и сигналы только в пределах одного cygwin1.dll !
|
||||
Чтобы иметь возможность послать сигнал, нужно, чтобы winws2 и программа для посылки сигнала (kill, killall) запускались с одним cygwin1.dll.
|
||||
|
||||
Можно использовать отдельно установленную среду cygwin, а можно скачать готовый [zapret-win-bundle](https://github.com/bol-van/zapret-win-bundle), где уже
|
||||
присутствует минимальный комплект cygwin. cygwin prompt настроен с aliases на запуск blockcheck, blockcheck2, winws, winws2, winws2 со станадртными Lua скриптами,
|
||||
чтобы не возиться с путями, а сосредоточиться на главном.
|
||||
|
||||
32-битные версии Windows в zapret-win-bundle не поддерживаются.
|
||||
|
||||
## Windows 7
|
||||
|
||||
Требования к подписи драйверов windows изменились в 2021 году.
|
||||
Официальные бесплатные обновления windows 7 закончились в 2020.
|
||||
После этого несколько лет продолжали идти платные обновления по программе ESU.
|
||||
Именно в этих ES* обновлениях находится обновление ядра windows 7, позволяющее загрузить драйвер
|
||||
windivert 2.2.2-A, который идет в поставке zapret.
|
||||
Поэтому варианты следующие :
|
||||
|
||||
1) Взять `windivert64.sys` и `windivert.dll` версии 2.2.0-C или 2.2.0-D [отсюда](https://reqrypt.org/download) и заменить эти 2 файла.
|
||||
|
||||
2) Взломать ESU : [Ссылка 1](https://hackandpwn.com/windows-7-esu-patching) [Ссылка 2](http://www.bifido.net/tweaks-and-scripts/8-extended-security-updates-installer.html)
|
||||
|
||||
3) Использовать готовый патчер-взламыватель ESU - "BypassESU". Его надо искать по названию.
|
||||
|
||||
4) Использовать [UpdatePack7R2 от simplix](https://blog.simplix.info)
|
||||
> [!WARNING]
|
||||
> Но с этим паком есть проблема. Автор из Украины, он очень обиделся на русских.
|
||||
> Если в панели управления стоит регион RU или BY, появляется неприятный диалог.
|
||||
> Чтобы эту проблему обойти, можно поставить временно любой другой регион, потом вернуть.
|
||||
> Так же нет никаких гарантий, что автор не поместил туда какой-то зловредный код.
|
||||
> Использовать на свой страх и риск.
|
||||
|
||||
Более безопасный вариант - скачать последнюю нормальную [довоенную версию : 22.2.10](https://nnmclub.to/forum/viewtopic.php?t=1530323).
|
||||
Ее достаточно, чтобы windivert 2.2.2-A заработал на windows 7.
|
||||
|
||||
## Windows Server
|
||||
|
||||
winws2 слинкован с wlanapi.dll, который по умолчанию не установлен в Windows Server.
|
||||
Для решения этой проблемы запустите power shell под администратором и выполните команду `Install-WindowsFeature -Name Wireless-Networking`.
|
||||
После чего перезагрузите систему.
|
||||
|
||||
@@ -59,8 +59,7 @@ zapret2 - инструмент для таких энтузиастов. Но э
|
||||
## С чего начать
|
||||
|
||||
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
|
||||
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое, руководствуясь [талмудом](manual.md) как справочником.
|
||||
|
||||
### Механика обработки трафика
|
||||
|
||||
|
||||
13
files/fake/sip.bin
Normal file
13
files/fake/sip.bin
Normal file
@@ -0,0 +1,13 @@
|
||||
REGISTER sip:192.168.1.1 SIP/2.0
|
||||
Via: SIP/2.0/UDP 192.168.1.2:42931;rport;branch=z9hG4bKPj3fd2e8713ffcd90c43f6ce69f6c98461
|
||||
Max-Forwards: 50
|
||||
From: <sip:703@192.168.1.1>;tag=ca565d7bd4e24a6d80c631d395ee117e
|
||||
To: <sip:703@192.168.1.1>
|
||||
Call-ID: dfec38302b8cea3d83c1452527c895c1
|
||||
CSeq: 26139 REGISTER
|
||||
User-Agent: MicroSIP/3.21.5
|
||||
Contact: <sip:703@192.168.1.2:42931;ob>
|
||||
Expires: 300
|
||||
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
|
||||
Content-Length: 0
|
||||
|
||||
@@ -288,7 +288,7 @@ ask_config_tmpdir()
|
||||
echo /tmp in openwrt is tmpfs. on low RAM systems there may be not enough RAM to store downloaded files
|
||||
echo default tmpfs has size of 50% RAM
|
||||
echo "RAM : $(get_ram_mb) Mb"
|
||||
echo "DISK : $(get_free_space_mb) Mb"
|
||||
echo "DISK : $(get_free_space_mb "$EXEDIR/tmp") Mb"
|
||||
echo select temp file location
|
||||
[ -z "$TMPDIR" ] && TMPDIR=/tmp
|
||||
ask_list TMPDIR "/tmp $EXEDIR/tmp" && {
|
||||
|
||||
@@ -38,6 +38,7 @@ standard fooling :
|
||||
* tcp_flags_set=<list> - set tcp flags in comma separated list
|
||||
* tcp_flags_unset=<list> - unset tcp flags in comma separated list
|
||||
* tcp_ts_up - move timestamp tcp option to the top if present (workaround for badack without badseq fooling)
|
||||
* tcp_nop_del - delete NOP tcp options to free space in tcp header
|
||||
|
||||
* fool=fool_function - custom fooling function : fool_func(dis, fooling_options)
|
||||
|
||||
@@ -511,11 +512,10 @@ 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
|
||||
@@ -1055,6 +1055,105 @@ function tcpseg(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : not available
|
||||
-- tpws : close analog is "--split-pos=.. --oob" but works not the same way
|
||||
-- standard args : fooling, ip_id, rawsend, reconstruct, ipfrag
|
||||
-- arg : char - oob char
|
||||
-- arg : byte - oob byte
|
||||
-- arg : urp - urgent pointer position marker, 'b' or 'e'. default - 0
|
||||
function oob(ctx, desync)
|
||||
if not desync.track then return end
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
local key = desync.func_instance.."_syn"
|
||||
if not desync.track.lua_state[key] then
|
||||
if bitand(desync.dis.tcp.th_flags, TH_SYN+TH_ACK)~=TH_SYN then
|
||||
DLOG("oob: must be applied since the very beginning of the tcp connection - SYN packet")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
desync.track.lua_state[key] = true
|
||||
end
|
||||
if desync.outgoing then
|
||||
-- direct pos - outgoing
|
||||
local pos = pos_get(desync, 's', false)
|
||||
if pos<=1 then
|
||||
local dseq = u32add(desync.dis.tcp.th_seq, -1)
|
||||
DLOG("oob: decreasing outgoing seq : "..desync.dis.tcp.th_seq.." => "..dseq)
|
||||
desync.dis.tcp.th_seq = dseq
|
||||
end
|
||||
if pos==0 then
|
||||
return VERDICT_MODIFY
|
||||
elseif pos==1 then
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
if #data==0 then
|
||||
-- empty ACK
|
||||
return VERDICT_MODIFY
|
||||
else
|
||||
local oob = desync.arg.char or (desync.arg.byte and bu8(desync.arg.byte) or nil) or "\x00"
|
||||
if #oob~=1 then
|
||||
error("oob: OOB must be exactly one byte")
|
||||
end
|
||||
local dis_oob = deepcopy(desync.dis)
|
||||
local urp
|
||||
if not desync.arg.urp or desync.arg.urp=='b' then
|
||||
urp = 1
|
||||
dis_oob.tcp.th_urp = 0
|
||||
elseif desync.arg.urp=='e' then
|
||||
urp = #data+1
|
||||
dis_oob.tcp.th_urp = urp
|
||||
else
|
||||
urp = resolve_pos(data, desync.l7payload, desync.arg.urp)
|
||||
DLOG("oob: resolved urp marker to "..urp-1)
|
||||
if not urp then
|
||||
DLOG("oob: cannot resolve urp marker '"..desync.arg.urp.."'")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
dis_oob.tcp.th_urp = urp
|
||||
end
|
||||
DLOG("oob: th_urp "..dis_oob.tcp.th_urp)
|
||||
-- one byte OOB payload
|
||||
dis_oob.payload = string.sub(data, 1, urp-1) .. oob .. string.sub(data, urp)
|
||||
dis_oob.tcp.th_flags = bitor(dis_oob.tcp.th_flags, TH_URG)
|
||||
DLOG("oob: sending OOB")
|
||||
if not rawsend_dissect_segmented(desync, dis_oob) then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
if not desync.replay then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
return VERDICT_DROP
|
||||
else
|
||||
-- drop replay and cutoff
|
||||
if desync.replay then
|
||||
DLOG("oob: dropping replay piece")
|
||||
if desync.replay_piece_last then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
return VERDICT_DROP
|
||||
end
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
else
|
||||
-- reverse pos - outgoing
|
||||
local pos = pos_get(desync, 's', true)
|
||||
if pos>1 then
|
||||
DLOG("oob: unexpected outgoing position "..pos)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
local dack = u32add(desync.dis.tcp.th_ack, 1)
|
||||
DLOG("oob: increasing incoming ack : "..desync.dis.tcp.th_ack.." => "..dack)
|
||||
desync.dis.tcp.th_ack = dack
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=udplen"
|
||||
-- standard args : direction, payload
|
||||
-- arg : min=N . do not act on payloads smaller than N bytes
|
||||
|
||||
@@ -58,6 +58,7 @@ function automate_host_record(desync)
|
||||
end
|
||||
-- per-connection storage
|
||||
function automate_conn_record(desync)
|
||||
if not desync.track then return nil end
|
||||
if not desync.track.lua_state.automate then
|
||||
desync.track.lua_state.automate = {}
|
||||
end
|
||||
@@ -180,13 +181,16 @@ function standard_failure_detector(desync, crec)
|
||||
end
|
||||
elseif not arg.no_http_redirect and desync.l7payload=="http_reply" and desync.track.hostname then
|
||||
local hdis = http_dissect_reply(desync.dis.payload)
|
||||
if hdis and (hdis.code==302 or hdis.code==307) and hdis.headers.location and hdis.headers.location then
|
||||
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers.location.value)
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. looks like DPI redirect.")
|
||||
else
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. NOT a DPI redirect.")
|
||||
if hdis and (hdis.code==302 or hdis.code==307) then
|
||||
local idx_loc = array_field_search(hdis.headers, "header_low", "location")
|
||||
if idx_loc then
|
||||
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers[idx_loc].value)
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers[idx_loc].value.."'. looks like DPI redirect.")
|
||||
else
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers[idx_loc].value.."'. NOT a DPI redirect.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,9 +18,14 @@ function luaexec(ctx, desync)
|
||||
if not desync.arg.code then
|
||||
error("luaexec: no 'code' parameter")
|
||||
end
|
||||
local fname = desync.func_instance.."_luaexec_code"
|
||||
local fname = desync.func_instance.."_code"
|
||||
if not _G[fname] then
|
||||
_G[fname] = load(desync.arg.code, fname)
|
||||
local err
|
||||
_G[fname], err = load(desync.arg.code, fname)
|
||||
if not _G[fname] then
|
||||
error(err)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- allow dynamic code to access desync
|
||||
_G.desync = desync
|
||||
@@ -242,9 +247,9 @@ end
|
||||
|
||||
-- if seq is over 2G s and p position comparision can be wrong
|
||||
function pos_counter_overflow(desync, mode, reverse)
|
||||
if not desync.track or not desync.track.tcp or (mode~='s' and mode~='p') then return false end
|
||||
if not desync.track or (mode~='s' and mode~='p') then return false end
|
||||
local track_pos = reverse and desync.track.pos.reverse or desync.track.pos.direct
|
||||
return track_pos.tcp.rseq_over_2G
|
||||
return track_pos.tcp and track_pos.tcp.rseq_over_2G
|
||||
end
|
||||
-- these functions duplicate range check logic from C code
|
||||
-- mode must be n,d,b,s,x,a
|
||||
@@ -310,6 +315,7 @@ function pos_str(desync, pos)
|
||||
return pos.mode..pos_get(desync, pos.mode)
|
||||
end
|
||||
|
||||
|
||||
-- convert array a to packed string using 'packer' function. only numeric indexes starting from 1, order preserved
|
||||
function barray(a, packer)
|
||||
if a then
|
||||
@@ -628,7 +634,7 @@ end
|
||||
-- find first tcp options of specified kind in dissect.tcp.options
|
||||
function find_tcp_option(options, kind)
|
||||
if options then
|
||||
for i, opt in pairs(options) do
|
||||
for i, opt in ipairs(options) do
|
||||
if opt.kind==kind then return i end
|
||||
end
|
||||
end
|
||||
@@ -638,7 +644,7 @@ end
|
||||
-- find first ipv6 extension header of specified protocol in dissect.ip6.exthdr
|
||||
function find_ip6_exthdr(exthdr, proto)
|
||||
if exthdr then
|
||||
for i, hdr in pairs(exthdr) do
|
||||
for i, hdr in ipairs(exthdr) do
|
||||
if hdr.type==proto then return i end
|
||||
end
|
||||
end
|
||||
@@ -788,6 +794,7 @@ end
|
||||
-- tcp_flags_set=<list> - set tcp flags in comma separated list
|
||||
-- tcp_flags_unset=<list> - unset tcp flags in comma separated list
|
||||
-- tcp_ts_up - move timestamp tcp option to the top if it's present. this allows linux not to accept badack segments without badseq. this is very strange discovery but it works.
|
||||
-- tcp_nop_del - delete NOP tcp options to free space in tcp header
|
||||
|
||||
-- fool - custom fooling function : fool_func(dis, fooling_options)
|
||||
function apply_fooling(desync, dis, fooling_options)
|
||||
@@ -849,6 +856,13 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
if fooling_options.tcp_flags_set then
|
||||
dis.tcp.th_flags = bitor(dis.tcp.th_flags, parse_tcp_flags(fooling_options.tcp_flags_set))
|
||||
end
|
||||
if fooling_options.tcp_nop_del then
|
||||
for i=#dis.tcp.options,1,-1 do
|
||||
if dis.tcp.options[i].kind==TCP_KIND_NOOP then
|
||||
table.remove(dis.tcp.options,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
if tonumber(fooling_options.tcp_ts) then
|
||||
local idx = find_tcp_option(dis.tcp.options,TCP_KIND_TS)
|
||||
if idx and (dis.tcp.options[idx].data and #dis.tcp.options[idx].data or 0)==8 then
|
||||
@@ -1052,7 +1066,7 @@ function rawsend_dissect_ipfrag(dis, options)
|
||||
if not rawsend_dissect(fragments[i], options.rawsend, reconstruct_frag) then return false end
|
||||
end
|
||||
else
|
||||
for i, d in pairs(fragments) do
|
||||
for i, d in ipairs(fragments) do
|
||||
DLOG("sending ip fragment "..i)
|
||||
-- C function
|
||||
if not rawsend_dissect(d, options.rawsend, reconstruct_frag) then return false end
|
||||
@@ -1068,13 +1082,18 @@ end
|
||||
|
||||
-- send dissect with tcp segmentation based on mss value. appply specified rawsend options.
|
||||
function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
dis = dis or desync.dis
|
||||
local discopy = deepcopy(dis)
|
||||
options = options or desync_opts(desync)
|
||||
apply_fooling(desync, discopy, options and options.fooling)
|
||||
|
||||
if dis.tcp then
|
||||
mss = mss or desync.tcp_mss
|
||||
local extra_len = l3l4_extra_len(discopy)
|
||||
if extra_len >= mss then return false end
|
||||
local max_data = mss - extra_len
|
||||
local urp = dis.tcp.th_urp
|
||||
local oob = bitand(dis.tcp.th_flags, TH_URG)~=0
|
||||
if #discopy.payload > max_data then
|
||||
local pos=1
|
||||
local len
|
||||
@@ -1083,6 +1102,15 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
while pos <= #payload do
|
||||
len = #payload - pos + 1
|
||||
if len > max_data then len = max_data end
|
||||
if oob then
|
||||
if urp>=pos and urp<(pos+len)then
|
||||
discopy.tcp.th_flags = bitor(dis.tcp.th_flags, TH_URG)
|
||||
discopy.tcp.th_urp = urp-pos+1
|
||||
else
|
||||
discopy.tcp.th_flags = bitand(dis.tcp.th_flags, bitnot(TH_URG))
|
||||
discopy.tcp.th_urp = 0
|
||||
end
|
||||
end
|
||||
discopy.payload = string.sub(payload,pos,pos+len-1)
|
||||
apply_ip_id(desync, discopy, options and options.ipid)
|
||||
if not rawsend_dissect_ipfrag(discopy, options) then
|
||||
@@ -1102,20 +1130,20 @@ end
|
||||
|
||||
-- send specified payload based on existing L3/L4 headers in the dissect. add seq to tcp.th_seq.
|
||||
function rawsend_payload_segmented(desync, payload, seq, options)
|
||||
options = options or desync_opts(desync)
|
||||
local dis = deepcopy(desync.dis)
|
||||
-- save some cpu and ram
|
||||
local dis = (payload or seq and seq~=0) and deepcopy(desync.dis) or desync.dis
|
||||
if payload then dis.payload = payload end
|
||||
if dis.tcp and seq then
|
||||
dis.tcp.th_seq = dis.tcp.th_seq + seq
|
||||
end
|
||||
return rawsend_dissect_segmented(desync, dis, desync.tcp_mss, options)
|
||||
return rawsend_dissect_segmented(desync, dis, nil, options)
|
||||
end
|
||||
|
||||
|
||||
-- check if desync.outgoing comply with arg.dir or def if it's not present or "out" of they are not present both. dir can be "in","out","any"
|
||||
function direction_check(desync, def)
|
||||
local dir = desync.arg.dir or def or "out"
|
||||
return desync.outgoing and desync.arg.dir~="in" or not desync.outgoing and dir~="out"
|
||||
return desync.outgoing and dir~="in" or not desync.outgoing and dir~="out"
|
||||
end
|
||||
-- if dir "in" or "out" cutoff current desync function from opposite direction
|
||||
function direction_cutoff_opposite(ctx, desync, def)
|
||||
@@ -1158,9 +1186,9 @@ function replay_drop_set(desync, v)
|
||||
if v == nil then v=true end
|
||||
local rdk = replay_drop_key(desync)
|
||||
if v then
|
||||
if desync.replay then desync.track.lua_state[replay_drop_key] = true end
|
||||
if desync.replay then desync.track.lua_state[rdk] = true end
|
||||
else
|
||||
desync.track.lua_state[replay_drop_key] = nil
|
||||
desync.track.lua_state[rdk] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1168,7 +1196,7 @@ end
|
||||
-- return true if the caller should return VERDICT_DROP
|
||||
function replay_drop(desync)
|
||||
if desync.track then
|
||||
local drop = desync.replay and desync.track.lua_state[replay_drop_key]
|
||||
local drop = desync.replay and desync.track.lua_state[replay_drop_key(desync)]
|
||||
if not desync.replay or desync.replay_piece_last then
|
||||
-- replay stopped or last piece of reasm
|
||||
replay_drop_set(desync, false)
|
||||
@@ -1481,7 +1509,7 @@ function gzip_file(filename, data, expected_ratio, level, memlevel, compress_blo
|
||||
if not f then
|
||||
error("gzip_file: "..err)
|
||||
end
|
||||
if not write_block_size then compress_block_size=16384 end
|
||||
if not compress_block_size then compress_block_size=16384 end
|
||||
if not expected_ratio then expected_ratio=2 end
|
||||
|
||||
gz = gzip_init(nil, level, memlevel)
|
||||
@@ -1530,6 +1558,9 @@ function writefile(filename, data)
|
||||
end
|
||||
local s,err = f:write(data)
|
||||
f:close()
|
||||
if not s then
|
||||
error("writefile: "..err)
|
||||
end
|
||||
end
|
||||
|
||||
-- DISSECTORS
|
||||
@@ -1545,7 +1576,7 @@ function http_dissect_header(header)
|
||||
end
|
||||
-- make table with structured http header representation
|
||||
function http_dissect_headers(http, pos)
|
||||
local eol,pnext,header,value,idx,headers,pos_endheader,pos_startvalue,pos_headers_next
|
||||
local eol,pnext,header,value,idx,headers,pos_endheader,pos_startvalue,pos_headers_end
|
||||
headers={}
|
||||
while pos do
|
||||
eol,pnext = find_next_line(http,pos)
|
||||
@@ -1604,9 +1635,10 @@ function http_dissect_reply(http)
|
||||
s = string.sub(http,1,8)
|
||||
if s~="HTTP/1.1" and s~="HTTP/1.0" then return nil end
|
||||
pos = string.find(http,"[ \t\r\n]",10)
|
||||
if not pos then return nil end
|
||||
code = tonumber(string.sub(http,10,pos-1))
|
||||
if not code then return nil end
|
||||
pos = find_next_line(http,pos)
|
||||
s,pos = find_next_line(http,pos)
|
||||
local hdis = { code = code }
|
||||
hdis.headers, hdis.pos_headers_end = http_dissect_headers(http,pos)
|
||||
if hdis.pos_headers_end then
|
||||
|
||||
@@ -688,13 +688,13 @@ function test_rawsend(opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
local function rawsend_dissect_print(dis, options)
|
||||
local function rawsend_dissect_print(dis, options, reconstruct)
|
||||
if options then
|
||||
options.ifout = ifout
|
||||
else
|
||||
options = { ifout = ifout }
|
||||
end
|
||||
local b = rawsend_dissect(dis, options)
|
||||
local b = rawsend_dissect(dis, options, reconstruct)
|
||||
if not b then
|
||||
print("rawsend_dissect failed")
|
||||
rawsend_fail_warning()
|
||||
@@ -760,8 +760,17 @@ function test_rawsend(opts)
|
||||
print("send ipv6 udp")
|
||||
test_assert(rawsend_dissect_print(dis, {repeats=3}))
|
||||
|
||||
ip2 = deepcopy(ip6)
|
||||
ip2.ip6_plen = UDP_BASE_LEN + #payload;
|
||||
raw_ip = reconstruct_ip6hdr(ip2, {ip6_last_proto = IPPROTO_UDP})
|
||||
raw_udp = reconstruct_udphdr({uh_sport = udp.uh_sport, uh_dport = udp.uh_dport, uh_ulen = UDP_BASE_LEN + #payload})
|
||||
raw_udp = csum_udp_fix(raw_ip,raw_udp,payload)
|
||||
raw = raw_ip .. raw_udp .. payload
|
||||
print("send ipv6 udp using pure rawsend without dissect")
|
||||
test_assert(rawsend_print(raw, {repeats=7}))
|
||||
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k)
|
||||
test_assert(rawsend_dissect_print(d))
|
||||
end
|
||||
@@ -771,7 +780,7 @@ function test_rawsend(opts)
|
||||
test_assert(rawsend_dissect_print(dis, {repeats=3}))
|
||||
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop ext header")
|
||||
test_assert(rawsend_dissect_print(d))
|
||||
end
|
||||
@@ -780,7 +789,7 @@ function test_rawsend(opts)
|
||||
table.insert(ip6.exthdr, { type = IPPROTO_DSTOPTS, data = "\x00\x00\x00\x00\x00\x00" })
|
||||
ip6.ip6_flow = 0x60001234;
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop, destopt ext headers in unfragmentable part and another destopt ext header in fragmentable part")
|
||||
test_assert(rawsend_dissect_print(d, {fwmark = 0x50EA}))
|
||||
end
|
||||
@@ -788,7 +797,7 @@ function test_rawsend(opts)
|
||||
fix_ip6_next(ip6) -- required to forge next proto in the second fragment
|
||||
ip6.ip6_flow = 0x6000AE38;
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80, ipfrag_next = IPPROTO_TCP})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop, destopt ext headers in unfragmentable part and another destopt ext header in fragmentable part. forge next proto in fragment header of the second fragment to TCP")
|
||||
-- reconstruct dissect using next proto fields in the dissect. do not auto fix next proto chain.
|
||||
-- by default reconstruct fixes next proto chain
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
-- arg : secret - shared secret. any string. must be the same on both peers
|
||||
-- arg : padmin - min random garbage bytes. 0 by default
|
||||
-- arg : padmax - max random garbage bytes. 16 by default
|
||||
-- NOTE : this function does not depend on zapret-lib.lua and should not be run under orchestrator (uses direct instance_cutoff)
|
||||
function wgobfs(ctx, desync)
|
||||
local padmin = desync.arg.padmin and tonumber(desync.arg.padmin) or 0
|
||||
local padmax = desync.arg.padmax and tonumber(desync.arg.padmax) or 16
|
||||
@@ -46,7 +47,7 @@ function wgobfs(ctx, desync)
|
||||
if padmin>padmax then
|
||||
error("wgobfs: padmin>padmax")
|
||||
end
|
||||
if desync.l7payload=="wireguard_initiation" or desync.l7payload=="wireguard_response" or desync.l7payload=="wireguard_cookie" and #desync.dis.payload<65506 then
|
||||
if (desync.l7payload=="wireguard_initiation" or desync.l7payload=="wireguard_response" or desync.l7payload=="wireguard_cookie") and #desync.dis.payload<65506 then
|
||||
DLOG("wgobfs: encrypting '"..desync.l7payload.."'. size "..#desync.dis.payload)
|
||||
local key = genkey()
|
||||
-- in aes-gcm every message require it's own crypto secure random iv
|
||||
|
||||
@@ -80,15 +80,15 @@ static bool dom_valid(char *dom)
|
||||
{
|
||||
if (!dom || *dom=='.') return false;
|
||||
for (; *dom; dom++)
|
||||
if (*dom < 0x20 || (*dom & 0x80) || !(*dom == '.' || *dom == '-' || *dom == '_' || (*dom >= '0' && *dom <= '9') || (*dom >= 'a' && *dom <= 'z') || (*dom >= 'A' && *dom <= 'Z')))
|
||||
return false;
|
||||
if (!(*dom == '.' || *dom == '-' || *dom == '_' || (*dom >= '0' && *dom <= '9') || (*dom >= 'a' && *dom <= 'z') || (*dom >= 'A' && *dom <= 'Z')))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void invalid_domain_beautify(char *dom)
|
||||
{
|
||||
for (int i = 0; *dom && i < 64; i++, dom++)
|
||||
if (*dom < 0x20 || *dom<0) *dom = '?';
|
||||
if (*dom < 0x20 || (*dom & 0x80)) *dom = '?';
|
||||
if (*dom) *dom = 0;
|
||||
}
|
||||
|
||||
@@ -436,7 +436,7 @@ int dns_parse_query()
|
||||
_setmode(_fileno(stdin), _O_BINARY);
|
||||
#endif
|
||||
l = fread(a,1,sizeof(a),stdin);
|
||||
if (!l || !feof(stdin))
|
||||
if (!l || ferror(stdin))
|
||||
{
|
||||
fprintf(stderr, "could not read DNS reply blob from stdin\n");
|
||||
return 10;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
CC ?= cc
|
||||
PKG_CONFIG ?= pkg-config
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 -s $(OPTIMIZE) -flto=auto -Wno-address-of-packed-member
|
||||
LIBS = -lz -lm
|
||||
@@ -26,8 +27,8 @@ OSNAME!=uname
|
||||
|
||||
.endif
|
||||
|
||||
LUA_LIB!= pkg-config --libs $(LUA_PKG)
|
||||
LUA_CFLAGS!= pkg-config --cflags $(LUA_PKG)
|
||||
LUA_LIB!= $(PKG_CONFIG) --libs $(LUA_PKG)
|
||||
LUA_CFLAGS!= $(PKG_CONFIG) --cflags $(LUA_PKG)
|
||||
|
||||
.if "${LUA_JIT}" == "1"
|
||||
LUA_CFLAGS+=-DLUAJIT
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
CC ?= cc
|
||||
PKG_CONFIG ?= pkg-config
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
|
||||
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
|
||||
@@ -16,7 +17,6 @@ RES_CYGWIN32 = windows/res/32/winmanifest.o windows/res/32/winicon.o
|
||||
RES_CYGWIN64 = windows/res/64/winmanifest.o windows/res/64/winicon.o
|
||||
SRC_FILES = *.c crypto/*.c
|
||||
|
||||
|
||||
LUA_JIT?=1
|
||||
|
||||
ifeq ($(LUA_JIT),1)
|
||||
@@ -29,13 +29,13 @@ $(info trying luajit $(LUAJIT_VER) lua $(LUAJIT_LUA_VER))
|
||||
|
||||
LUA_LIB_NAME=
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := $(shell pkg-config --cflags $(LUA_PKG) 2>/dev/null)
|
||||
LUA_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKG) 2>/dev/null)
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := -I/usr/local/include/luajit-$(LUAJIT_VER) -I/usr/include/luajit-$(LUAJIT_VER)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(LUA_LIB),)
|
||||
LUA_LIB := $(shell pkg-config --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB := $(shell $(PKG_CONFIG) --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB_DIR :=
|
||||
|
||||
ifeq ($(LUA_LIB),)
|
||||
@@ -87,13 +87,13 @@ else
|
||||
endif
|
||||
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := $(shell pkg-config --cflags $(LUA_PKG) 2>/dev/null)
|
||||
LUA_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKG) 2>/dev/null)
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := -I/usr/local/include/lua$(LUA_VER) -I/usr/local/include/lua-$(LUA_VER) -I/usr/include/lua$(LUA_VER) -I/usr/include/lua-$(LUA_VER)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(LUA_LIB),)
|
||||
LUA_LIB := $(shell pkg-config --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB := $(shell $(PKG_CONFIG) --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB_DIR :=
|
||||
ifeq ($(LUA_LIB),)
|
||||
ifneq ($(wildcard /usr/local/lib/liblua-$(LUA_VER).*),)
|
||||
|
||||
@@ -339,21 +339,28 @@ void proto_skip_udp(const uint8_t **data, size_t *len)
|
||||
|
||||
bool proto_check_ipv6(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len >= sizeof(struct ip6_hdr) && (data[0] & 0xF0) == 0x60 &&
|
||||
(len - sizeof(struct ip6_hdr)) >= ntohs(((struct ip6_hdr*)data)->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
return len >= sizeof(struct ip6_hdr) && (data[0] & 0xF0) == 0x60;
|
||||
}
|
||||
bool proto_check_ipv6_payload(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len >= (ntohs(((struct ip6_hdr*)data)->ip6_ctlun.ip6_un1.ip6_un1_plen) + sizeof(struct ip6_hdr));
|
||||
}
|
||||
// move to transport protocol
|
||||
// proto_type = 0 => error
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, const uint8_t **last_header_type)
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
|
||||
{
|
||||
size_t hdrlen;
|
||||
uint8_t HeaderType;
|
||||
uint16_t plen;
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr*)*data;
|
||||
|
||||
if (proto_type) *proto_type = 0; // put error in advance
|
||||
|
||||
HeaderType = (*data)[6]; // NextHeader field
|
||||
if (last_header_type) *last_header_type = (*data)+6;
|
||||
HeaderType = ip6->ip6_nxt;
|
||||
if (proto_type) *proto_type = HeaderType;
|
||||
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
*data += sizeof(struct ip6_hdr); *len -= sizeof(struct ip6_hdr); // skip ipv6 base header
|
||||
if (plen < *len) *len = plen;
|
||||
while (*len) // need at least one byte for NextHeader field
|
||||
{
|
||||
switch (HeaderType)
|
||||
@@ -384,7 +391,6 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, con
|
||||
}
|
||||
if (*len < hdrlen) return; // error
|
||||
HeaderType = **data;
|
||||
if (last_header_type) *last_header_type = *data;
|
||||
// advance to the next header location
|
||||
*len -= hdrlen;
|
||||
*data += hdrlen;
|
||||
@@ -392,60 +398,18 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, con
|
||||
// we have garbage
|
||||
}
|
||||
|
||||
bool proto_set_last_ip6_proto(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
||||
{
|
||||
size_t hdrlen;
|
||||
uint8_t HeaderType, *pproto, *data;
|
||||
|
||||
if (len<sizeof(struct ip6_hdr)) return false;
|
||||
|
||||
pproto = &ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
|
||||
data = (uint8_t*)(ip6+1);
|
||||
len -= sizeof(struct ip6_hdr);
|
||||
while (len) // need at least one byte for NextHeader field
|
||||
{
|
||||
switch (*pproto)
|
||||
{
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_MH: // mobility header
|
||||
case IPPROTO_HIP: // Host Identity Protocol Version v2
|
||||
case IPPROTO_SHIM6:
|
||||
if (len < 2) return false; // error
|
||||
hdrlen = 8 + (data[1] << 3);
|
||||
break;
|
||||
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
||||
hdrlen = 8;
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
// special case. length in ah header is in 32-bit words minus 2
|
||||
if (len < 2) return false; // error
|
||||
hdrlen = 8 + (data[1] << 2);
|
||||
break;
|
||||
default:
|
||||
// we found some meaningful payload. it can be tcp, udp, icmp or some another exotic shit
|
||||
*pproto = proto;
|
||||
return true;
|
||||
}
|
||||
if (len < hdrlen) return false; // error
|
||||
pproto = data;
|
||||
len -= hdrlen; data += hdrlen;
|
||||
}
|
||||
*pproto = proto;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
||||
{
|
||||
size_t hdrlen;
|
||||
uint8_t HeaderType, last_proto, *data;
|
||||
uint16_t plen;
|
||||
|
||||
if (len<sizeof(struct ip6_hdr)) return false;
|
||||
|
||||
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
last_proto = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
|
||||
data = (uint8_t*)(ip6+1);
|
||||
len -= sizeof(struct ip6_hdr);
|
||||
if (plen < len) len = plen;
|
||||
while (len) // need at least one byte for NextHeader field
|
||||
{
|
||||
if (last_proto==proto) return data; // found
|
||||
@@ -498,11 +462,11 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis)
|
||||
proto_skip_ipv4(&data, &len);
|
||||
dis->len_l3 = data-p;
|
||||
}
|
||||
else if (proto_check_ipv6(data, len))
|
||||
else if (proto_check_ipv6(data, len) && proto_check_ipv6_payload(data, len))
|
||||
{
|
||||
dis->ip6 = (const struct ip6_hdr *) data;
|
||||
p = data;
|
||||
proto_skip_ipv6(&data, &len, &dis->proto, NULL);
|
||||
proto_skip_ipv6(&data, &len, &dis->proto);
|
||||
dis->len_l3 = data-p;
|
||||
}
|
||||
else
|
||||
@@ -2063,7 +2027,7 @@ bool make_writeable_dir()
|
||||
char testfile[PATH_MAX];
|
||||
snprintf(testfile,sizeof(testfile),"%s/test_XXXXXX",wrdir);
|
||||
int fd = mkstemp(testfile);
|
||||
if (fd>0)
|
||||
if (fd>=0)
|
||||
{
|
||||
close(fd);
|
||||
unlink(testfile);
|
||||
|
||||
@@ -135,8 +135,8 @@ void str_udphdr(char *s, size_t s_len, const struct udphdr *udphdr);
|
||||
bool proto_check_ipv4(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv4(const uint8_t **data, size_t *len);
|
||||
bool proto_check_ipv6(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, const uint8_t **last_header_type);
|
||||
bool proto_set_last_ip6_proto(struct ip6_hdr *ip6, size_t len, uint8_t proto);
|
||||
bool proto_check_ipv6_payload(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type);
|
||||
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto);
|
||||
bool proto_check_tcp(const uint8_t *data, size_t len);
|
||||
void proto_skip_tcp(const uint8_t **data, size_t *len);
|
||||
|
||||
@@ -425,17 +425,6 @@ static bool send_delayed(t_ctrack *ctrack)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rawpacket_queue_csum_fix(struct rawpacket_tailhead *q, const struct dissect *dis, const t_ctrack_positions *tpos, const struct sockaddr_storage* dst, uint32_t fwmark, uint32_t desync_fwmark, const char *ifin, const char *ifout)
|
||||
{
|
||||
// this breaks const pointer to l4 header
|
||||
if (dis->tcp)
|
||||
verdict_tcp_csum_fix(VERDICT_PASS, (struct tcphdr *)dis->tcp, dis->transport_len, dis->ip, dis->ip6);
|
||||
else if (dis->udp)
|
||||
verdict_udp_csum_fix(VERDICT_PASS, (struct udphdr *)dis->udp, dis->transport_len, dis->ip, dis->ip6);
|
||||
return rawpacket_queue(q, dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, tpos);
|
||||
}
|
||||
|
||||
|
||||
static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, uint32_t seq, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
|
||||
{
|
||||
ReasmClear(reasm);
|
||||
@@ -870,9 +859,11 @@ static uint8_t desync(
|
||||
if (dis->tcp)
|
||||
{
|
||||
// recommended mss value for generated packets
|
||||
if (rpos && rpos->mss)
|
||||
lua_pushf_int(params.L, "tcp_mss", rpos->mss);
|
||||
if (pos && pos->mss && rpos && rpos->mss)
|
||||
// use minimum MSS of two ends or can fail with "message too long"
|
||||
lua_pushf_int(params.L, "tcp_mss", rpos->mss > pos->mss ? pos->mss : rpos->mss);
|
||||
else
|
||||
// this value should always work
|
||||
lua_pushf_global(params.L, "tcp_mss", "DEFAULT_MSS");
|
||||
}
|
||||
ref_arg = luaL_ref(params.L, LUA_REGISTRYINDEX);
|
||||
@@ -1163,7 +1154,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
return verdict;
|
||||
}
|
||||
|
||||
HostFailPoolPurgeRateLimited(&dp->hostlist_auto_fail_counters);
|
||||
HostFailPoolPurgeRateLimited(&dp->hostlist_auto_fail_counters, &dp->hostlist_auto_last_purge);
|
||||
|
||||
//ConntrackPoolDump(¶ms.conntrack);
|
||||
|
||||
@@ -1335,7 +1326,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_client))
|
||||
{
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
if (rawpacket_queue(&ctrack->delayed, &dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ctrack->pos))
|
||||
{
|
||||
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed));
|
||||
}
|
||||
@@ -1699,7 +1690,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
return verdict;
|
||||
}
|
||||
|
||||
HostFailPoolPurgeRateLimited(&dp->hostlist_auto_fail_counters);
|
||||
HostFailPoolPurgeRateLimited(&dp->hostlist_auto_fail_counters, &dp->hostlist_auto_last_purge);
|
||||
//ConntrackPoolDump(¶ms.conntrack);
|
||||
|
||||
if (bReverseFixed)
|
||||
@@ -1793,7 +1784,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
}
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_client))
|
||||
{
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
if (rawpacket_queue(&ctrack->delayed, &dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ctrack->pos))
|
||||
{
|
||||
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed));
|
||||
}
|
||||
@@ -1833,7 +1824,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
if (!reasm_client_start(ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
if (rawpacket_queue(&ctrack->delayed, &dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ctrack->pos))
|
||||
{
|
||||
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed));
|
||||
}
|
||||
@@ -2024,6 +2015,8 @@ static uint8_t dpi_desync_packet_play(
|
||||
struct dissect dis;
|
||||
uint8_t verdict = VERDICT_PASS;
|
||||
|
||||
// NOTE ! OS can pass wrong checksum to queue. cannot rely on it !
|
||||
|
||||
proto_dissect_l3l4(data_pkt, len_pkt, &dis);
|
||||
if (!!dis.ip != !!dis.ip6)
|
||||
{
|
||||
@@ -2034,16 +2027,20 @@ static uint8_t dpi_desync_packet_play(
|
||||
if (dis.tcp)
|
||||
{
|
||||
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||
// we fix csum before pushing to replay queue
|
||||
if (!replay_piece_count) verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
|
||||
// fix csum if unmodified and if OS can pass wrong csum to queue (depends on OS)
|
||||
// modified means we have already fixed the checksum or made it invalid intentionally
|
||||
// this is the only point we VIOLATE const to fix the checksum in the original buffer to avoid copying to mod_pkt
|
||||
verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
if (dis.udp)
|
||||
{
|
||||
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||
// we fix csum before pushing to replay queue
|
||||
if (!replay_piece_count) verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
|
||||
// fix csum if unmodified and if OS can pass wrong csum to queue (depends on OS)
|
||||
// modified means we have already fixed the checksum or made it invalid intentionally
|
||||
// this is the only point we VIOLATE const to fix the checksum in the original buffer to avoid copying to mod_pkt
|
||||
verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2052,6 +2049,8 @@ static uint8_t dpi_desync_packet_play(
|
||||
}
|
||||
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)
|
||||
{
|
||||
// NOTE ! OS can pass wrong checksum to queue. cannot rely on it !
|
||||
|
||||
ipcachePurgeRateLimited(¶ms.ipcache, params.ipcache_lifetime);
|
||||
return dpi_desync_packet_play(0, 0, 0, fwmark, ifin, ifout, NULL, data_pkt, len_pkt, mod_pkt, len_mod_pkt);
|
||||
}
|
||||
|
||||
@@ -599,14 +599,14 @@ bool packet_range_parse(const char *s, struct packet_range *range)
|
||||
|
||||
void fill_random_bytes(uint8_t *p,size_t sz)
|
||||
{
|
||||
size_t k,sz16 = sz>>1;
|
||||
for(k=0;k<sz16;k++) ((uint16_t*)p)[k]=(uint16_t)random();
|
||||
size_t k;
|
||||
for (k=0 ; (k+1)<sz ; k+=2) phton16(p+k, (uint16_t)random());
|
||||
if (sz & 1) p[sz-1]=(uint8_t)random();
|
||||
}
|
||||
void fill_random_az(uint8_t *p,size_t sz)
|
||||
{
|
||||
size_t k;
|
||||
for(k=0;k<sz;k++) p[k] = 'a'+(random() % ('z'-'a'));
|
||||
for(k=0;k<sz;k++) p[k] = 'a'+(random() % ('z'-'a'+1));
|
||||
}
|
||||
void fill_random_az09(uint8_t *p,size_t sz)
|
||||
{
|
||||
|
||||
160
nfq2/lua.c
160
nfq2/lua.c
@@ -71,16 +71,20 @@ static int luacall_bitlshift(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitlshift",2);
|
||||
int64_t v=(int64_t)luaL_checklint(L,1);
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,(((uint64_t)v) << luaL_checkinteger(L,2)) & 0xFFFFFFFFFFFF);
|
||||
lua_Integer shift = luaL_checkinteger(L,2);
|
||||
if (shift>48 || shift<0 || v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint64_t u = v & 0xFFFFFFFFFFFF;
|
||||
lua_pushlint(L,(u << shift) & 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>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
lua_pushlint(L,((uint64_t)v) >> luaL_checkinteger(L,2));
|
||||
lua_Integer shift = luaL_checkinteger(L,2);
|
||||
if (shift>48 || shift<0 || v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint64_t u = v & 0xFFFFFFFFFFFF;
|
||||
lua_pushlint(L,u >> shift);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitand(lua_State *L)
|
||||
@@ -93,7 +97,7 @@ static int luacall_bitand(lua_State *L)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum&=(uint64_t)v;
|
||||
sum &= (uint64_t)v;
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
@@ -108,7 +112,22 @@ static int luacall_bitor(lua_State *L)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum|=(uint64_t)v;
|
||||
sum |= (uint64_t)(v & 0xFFFFFFFFFFFF);
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bitxor(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"bitxor",1,100);
|
||||
int argc = lua_gettop(L);
|
||||
int64_t v;
|
||||
uint64_t sum=0;
|
||||
for(int i=1;i<=argc;i++)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
|
||||
sum ^= (uint64_t)(v & 0xFFFFFFFFFFFF);
|
||||
}
|
||||
lua_pushlint(L,sum);
|
||||
return 1;
|
||||
@@ -146,21 +165,6 @@ 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;
|
||||
uint64_t sum=0;
|
||||
for(int i=1;i<=argc;i++)
|
||||
{
|
||||
v=(int64_t)luaL_checklint(L,i);
|
||||
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_bitget(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bitget",3);
|
||||
@@ -170,10 +174,10 @@ static int luacall_bitget(lua_State *L)
|
||||
uint64_t what = (uint64_t)iwhat;
|
||||
lua_Integer from = luaL_checkinteger(L,2);
|
||||
lua_Integer to = luaL_checkinteger(L,3);
|
||||
if (from>to || from>47 || to>47)
|
||||
if (from<0 || to<0 || from>to || from>47 || to>47)
|
||||
luaL_error(L, "bit range invalid");
|
||||
|
||||
what = (what >> from) & ~((lua_Integer)-1 << (to-from+1));
|
||||
what = (what >> from) & ~((uint64_t)-1 << (to-from+1));
|
||||
|
||||
lua_pushlint(L,what);
|
||||
return 1;
|
||||
@@ -190,7 +194,7 @@ static int luacall_bitset(lua_State *L)
|
||||
int64_t iset = (int64_t)luaL_checklint(L,4);
|
||||
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)
|
||||
if (from<0 || to<0 || from>to || from>47 || to>47)
|
||||
luaL_error(L, "bit range invalid");
|
||||
|
||||
uint64_t mask = ~((uint64_t)-1 << (to-from+1));
|
||||
@@ -423,7 +427,7 @@ static int luacall_brandom(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"brandom",1);
|
||||
lua_Integer len = luaL_checkinteger(L,1);
|
||||
|
||||
if (len<0) luaL_error(L, "brandom: invalid arg");
|
||||
uint8_t *p = malloc(len);
|
||||
if (!p) luaL_error(L, "out of memory");
|
||||
fill_random_bytes(p,len);
|
||||
@@ -436,7 +440,7 @@ static int luacall_brandom_az(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"brandom_az",1);
|
||||
lua_Integer len = luaL_checkinteger(L,1);
|
||||
|
||||
if (len<0) luaL_error(L, "brandom_az: invalid arg");
|
||||
uint8_t *p = malloc(len);
|
||||
if (!p) luaL_error(L, "out of memory");
|
||||
fill_random_az(p,len);
|
||||
@@ -449,7 +453,7 @@ static int luacall_brandom_az09(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"brandom_az09",1);
|
||||
lua_Integer len = luaL_checkinteger(L,1);
|
||||
|
||||
if (len<0) luaL_error(L, "brandom_az09: invalid arg");
|
||||
uint8_t *p = malloc(len);
|
||||
if (!p) luaL_error(L, "out of memory");
|
||||
fill_random_az09(p,len);
|
||||
@@ -461,6 +465,7 @@ static int luacall_brandom_az09(lua_State *L)
|
||||
|
||||
// hacky function. breaks immutable string behavior.
|
||||
// if you change a string, it will change in all variables that hold the same string
|
||||
/*
|
||||
static int luacall_memcpy(lua_State *L)
|
||||
{
|
||||
// memcpy(to,to_offset,from,from_offset,size)
|
||||
@@ -481,7 +486,7 @@ static int luacall_memcpy(lua_State *L)
|
||||
memcpy(to+off_to,from+off_from,size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
static int luacall_parse_hex(lua_State *L)
|
||||
{
|
||||
@@ -531,6 +536,7 @@ static int luacall_bcryptorandom(lua_State *L)
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
lua_Integer len = luaL_checkinteger(L,1);
|
||||
if (len<0) luaL_error(L, "bcryptorandom: invalid arg");
|
||||
|
||||
uint8_t *p = malloc(len);
|
||||
if (!p) luaL_error(L, "out of memory");
|
||||
@@ -686,7 +692,8 @@ static int luacall_hkdf(lua_State *L)
|
||||
const uint8_t *ikm = lua_type(L,3) == LUA_TNIL ? NULL : (uint8_t*)luaL_checklstring(L,3,&ikm_len);
|
||||
size_t info_len=0;
|
||||
const uint8_t *info = lua_type(L,4) == LUA_TNIL ? NULL : (uint8_t*)luaL_checklstring(L,4,&info_len);
|
||||
size_t okm_len = (size_t)luaL_checkinteger(L,5);
|
||||
lua_Integer okm_len = luaL_checkinteger(L,5);
|
||||
if (okm_len<0) luaL_error(L, "hkdf: invalid arg");
|
||||
|
||||
uint8_t *okm = malloc(okm_len);
|
||||
if (!okm) luaL_error(L, "out of memory");
|
||||
@@ -950,7 +957,7 @@ static int luacall_execution_plan(lua_State *L)
|
||||
|
||||
lua_pushf_args(L,&func->args, -1, false);
|
||||
lua_pushf_str(L,"func", func->func);
|
||||
lua_pushf_int(L,"func_n", ctx->func_n);
|
||||
lua_pushf_int(L,"func_n", n);
|
||||
lua_pushf_str(L,"func_instance", instance);
|
||||
lua_pushf_range(L,"range", range);
|
||||
|
||||
@@ -1179,7 +1186,7 @@ void lua_pushf_tcphdr_options(lua_State *L, const struct tcphdr *tcp, size_t len
|
||||
uint8_t *t = (uint8_t*)(tcp+1);
|
||||
uint8_t *end = (uint8_t*)tcp + (tcp->th_off<<2);
|
||||
uint8_t opt;
|
||||
if ((end-(uint8_t*)tcp) < len) end=(uint8_t*)tcp + len;
|
||||
if ((end-(uint8_t*)tcp) > len) end=(uint8_t*)tcp + len;
|
||||
lua_Integer idx=1;
|
||||
while(t<end)
|
||||
{
|
||||
@@ -1263,7 +1270,7 @@ void lua_pushf_iphdr(lua_State *L, const struct ip *ip, size_t len)
|
||||
if (ip && len>=sizeof(struct ip))
|
||||
{
|
||||
uint16_t hl = ip->ip_hl<<2;
|
||||
bool b_has_opt = hl>sizeof(struct tcphdr) && hl<=len;
|
||||
bool b_has_opt = hl>sizeof(struct ip) && hl<=len;
|
||||
lua_createtable(L, 0, 11+b_has_opt);
|
||||
lua_pushf_int(L,"ip_v",ip->ip_v);
|
||||
lua_pushf_int(L,"ip_hl",ip->ip_hl);
|
||||
@@ -1273,11 +1280,11 @@ void lua_pushf_iphdr(lua_State *L, const struct ip *ip, size_t len)
|
||||
lua_pushf_int(L,"ip_off",ntohs(ip->ip_off));
|
||||
lua_pushf_int(L,"ip_ttl",ip->ip_ttl);
|
||||
lua_pushf_int(L,"ip_p",ip->ip_p);
|
||||
lua_pushf_int(L,"ip_sum",ip->ip_sum);
|
||||
lua_pushf_int(L,"ip_sum",ntohs(ip->ip_sum));
|
||||
lua_pushf_raw(L,"ip_src",&ip->ip_src,sizeof(struct in_addr));
|
||||
lua_pushf_raw(L,"ip_dst",&ip->ip_dst,sizeof(struct in_addr));
|
||||
if (b_has_opt)
|
||||
lua_pushf_raw(L,"options",(uint8_t*)(ip+1),hl-sizeof(struct tcphdr));
|
||||
lua_pushf_raw(L,"options",(uint8_t*)(ip+1),hl-sizeof(struct ip));
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
@@ -1292,6 +1299,7 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
|
||||
// assume ipv6 packet structure was already checked for validity
|
||||
size_t hdrlen;
|
||||
uint8_t HeaderType, *data;
|
||||
uint16_t plen;
|
||||
lua_Integer idx = 1;
|
||||
|
||||
lua_pushliteral(L, "exthdr");
|
||||
@@ -1301,6 +1309,8 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
|
||||
HeaderType = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
|
||||
data=(uint8_t*)(ip6+1);
|
||||
len-=sizeof(struct ip6_hdr);
|
||||
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
if (plen < len) len = plen;
|
||||
while (len > 0) // need at least one byte for NextHeader field
|
||||
{
|
||||
switch (HeaderType)
|
||||
@@ -1432,11 +1442,11 @@ void lua_pushf_ctrack(lua_State *L, const t_ctrack *ctrack, const t_ctrack_posit
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
if (!tpos) tpos = &ctrack->pos;
|
||||
|
||||
lua_pushliteral(L, "track");
|
||||
if (ctrack)
|
||||
{
|
||||
if (!tpos) tpos = &ctrack->pos;
|
||||
|
||||
lua_createtable(L, 0, 9);
|
||||
|
||||
if (ctrack->incoming_ttl)
|
||||
@@ -1449,7 +1459,7 @@ void lua_pushf_ctrack(lua_State *L, const t_ctrack *ctrack, const t_ctrack_posit
|
||||
lua_pushf_reg(L, "lua_state", ctrack->lua_state);
|
||||
lua_pushf_bool(L, "lua_in_cutoff", ctrack->b_lua_in_cutoff);
|
||||
lua_pushf_bool(L, "lua_out_cutoff", ctrack->b_lua_out_cutoff);
|
||||
lua_pushf_lint(L, "t_start", (lua_Number)ctrack->t_start.tv_sec + ctrack->t_start.tv_nsec/1000000000.);
|
||||
lua_pushf_number(L, "t_start", (lua_Number)ctrack->t_start.tv_sec + ctrack->t_start.tv_nsec/1000000000.);
|
||||
|
||||
lua_pushliteral(L, "pos");
|
||||
lua_createtable(L, 0, 5);
|
||||
@@ -1553,7 +1563,7 @@ void lua_pushf_range(lua_State *L, const char *name, const struct packet_range *
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
lua_pushf_table(L, name);
|
||||
lua_getfield(L, -1, "range");
|
||||
lua_getfield(L, -1, name);
|
||||
lua_pushf_bool(L, "upper_cutoff",range->upper_cutoff);
|
||||
lua_pushf_pos(L, "from", &range->from);
|
||||
lua_pushf_pos(L, "to", &range->to);
|
||||
@@ -1599,12 +1609,11 @@ static void lua_reconstruct_extract_options(lua_State *L, int idx, bool *badsum,
|
||||
static bool lua_reconstruct_ip6exthdr(lua_State *L, int idx, struct ip6_hdr *ip6, size_t *len, uint8_t proto, bool preserve_next)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
// proto = last header type
|
||||
if (*len<sizeof(struct tcphdr)) return false;
|
||||
|
||||
uint8_t *last_proto = &ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
|
||||
uint8_t filled = sizeof(struct ip6_hdr);
|
||||
size_t filled = sizeof(struct ip6_hdr);
|
||||
lua_getfield(L,idx,"exthdr");
|
||||
if (lua_type(L,-1)==LUA_TTABLE)
|
||||
{
|
||||
@@ -1624,10 +1633,10 @@ static bool lua_reconstruct_ip6exthdr(lua_State *L, int idx, struct ip6_hdr *ip6
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lua_type(L,-1)!=LUA_TTABLE) goto err2;
|
||||
if (lua_type(L,-1)!=LUA_TTABLE) goto err;
|
||||
|
||||
lua_getfield(L,-1, "type");
|
||||
if (lua_type(L,-1)!=LUA_TNUMBER) goto err3;
|
||||
if (lua_type(L,-1)!=LUA_TNUMBER) goto err;
|
||||
type = (uint8_t)lua_tointeger(L,-1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
@@ -1636,9 +1645,9 @@ static bool lua_reconstruct_ip6exthdr(lua_State *L, int idx, struct ip6_hdr *ip6
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L,-1, "data");
|
||||
if (lua_type(L,-1)!=LUA_TSTRING) goto err3;
|
||||
p=(uint8_t*)lua_tolstring(L,-1,&l);
|
||||
if (!l || (l+2)>left || ((type==IPPROTO_AH) ? (l<6 || ((l+2) & 3)) : ((l+2) & 7))) goto err3;
|
||||
if (lua_type(L,-1)!=LUA_TSTRING) goto err;
|
||||
if (!(p=(uint8_t*)lua_tolstring(L,-1,&l))) l=0;
|
||||
if (!l || (l+2)>left || ((type==IPPROTO_AH) ? (l<6 || ((l+2) & 3)) : ((l+2) & 7))) goto err;
|
||||
memcpy(data+2,p,l);
|
||||
l+=2;
|
||||
data[0] = next; // may be overwritten later
|
||||
@@ -1657,13 +1666,8 @@ static bool lua_reconstruct_ip6exthdr(lua_State *L, int idx, struct ip6_hdr *ip6
|
||||
lua_pop(L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
return true;
|
||||
err2:
|
||||
lua_pop(L, 2);
|
||||
goto err;
|
||||
err3:
|
||||
lua_pop(L, 3);
|
||||
err:
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
LUA_STACK_GUARD_UNWIND(L)
|
||||
return false;
|
||||
}
|
||||
bool lua_reconstruct_ip6hdr(lua_State *L, int idx, struct ip6_hdr *ip6, size_t *len, uint8_t last_proto, bool preserve_next)
|
||||
@@ -1696,17 +1700,20 @@ bool lua_reconstruct_ip6hdr(lua_State *L, int idx, struct ip6_hdr *ip6, size_t *
|
||||
lua_getfield(L,idx,"ip6_src");
|
||||
if (lua_type(L,-1)!=LUA_TSTRING) goto err;
|
||||
p = lua_tolstring(L,-1,&l);
|
||||
if (l!=sizeof(struct in6_addr)) goto err;
|
||||
if (!p || l!=sizeof(struct in6_addr)) goto err;
|
||||
ip6->ip6_src = *(struct in6_addr*)p;
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L,idx,"ip6_dst");
|
||||
if (lua_type(L,-1)!=LUA_TSTRING) goto err;
|
||||
p = lua_tolstring(L,-1,&l);
|
||||
if (l!=sizeof(struct in6_addr)) goto err;
|
||||
if (!p || l!=sizeof(struct in6_addr)) goto err;
|
||||
ip6->ip6_dst = *(struct in6_addr*)p;
|
||||
lua_pop(L, 1);
|
||||
return lua_reconstruct_ip6exthdr(L, idx, ip6, len, last_proto, preserve_next);
|
||||
|
||||
bool b = lua_reconstruct_ip6exthdr(L, idx, ip6, len, last_proto, preserve_next);
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
return b;
|
||||
err:
|
||||
lua_pop(L, 1);
|
||||
|
||||
@@ -1774,14 +1781,14 @@ bool lua_reconstruct_iphdr(lua_State *L, int idx, struct ip *ip, size_t *len)
|
||||
lua_getfield(L,idx,"ip_src");
|
||||
if (lua_type(L,-1)!=LUA_TSTRING) goto err;
|
||||
p = lua_tolstring(L,-1,&l);
|
||||
if (l!=sizeof(struct in_addr)) goto err;
|
||||
if (!p || l!=sizeof(struct in_addr)) goto err;
|
||||
ip->ip_src = *(struct in_addr*)p;
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L,idx,"ip_dst");
|
||||
if (lua_type(L,-1)!=LUA_TSTRING) goto err;
|
||||
p = lua_tolstring(L,-1,&l);
|
||||
if (l!=sizeof(struct in_addr)) goto err;
|
||||
if (!p || l!=sizeof(struct in_addr)) goto err;
|
||||
ip->ip_dst = *(struct in_addr*)p;
|
||||
lua_pop(L, 1);
|
||||
|
||||
@@ -1857,10 +1864,10 @@ static bool lua_reconstruct_tcphdr_options(lua_State *L, int idx, struct tcphdr
|
||||
{
|
||||
// uses 'key' (at index -2) and 'value' (at index -1)
|
||||
|
||||
if (!left || lua_type(L,-1)!=LUA_TTABLE) goto err2;
|
||||
if (!left || lua_type(L,-1)!=LUA_TTABLE) goto err;
|
||||
|
||||
lua_getfield(L,-1, "kind");
|
||||
if (lua_type(L,-1)!=LUA_TNUMBER) goto err3;
|
||||
if (lua_type(L,-1)!=LUA_TNUMBER) goto err;
|
||||
|
||||
kind = (uint8_t)lua_tointeger(L,-1);
|
||||
lua_pop(L, 1);
|
||||
@@ -1878,7 +1885,7 @@ static bool lua_reconstruct_tcphdr_options(lua_State *L, int idx, struct tcphdr
|
||||
lua_getfield(L,-1, "data");
|
||||
l = 0;
|
||||
p = lua_type(L,-1)==LUA_TSTRING ? (uint8_t*)lua_tolstring(L,-1,&l) : NULL;
|
||||
if ((2+l)>left) goto err3;
|
||||
if ((2+l)>left) goto err;
|
||||
if (p) memcpy(data+2,p,l);
|
||||
l+=2;
|
||||
data[0] = kind;
|
||||
@@ -1894,7 +1901,7 @@ static bool lua_reconstruct_tcphdr_options(lua_State *L, int idx, struct tcphdr
|
||||
end:
|
||||
while(filled & 3)
|
||||
{
|
||||
if (!left) goto err1;
|
||||
if (!left) goto err;
|
||||
*data = TCP_KIND_NOOP; data++; left--; filled++;
|
||||
}
|
||||
}
|
||||
@@ -1905,16 +1912,8 @@ end:
|
||||
lua_pop(L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
return true;
|
||||
err1:
|
||||
lua_pop(L, 1);
|
||||
goto err;
|
||||
err2:
|
||||
lua_pop(L, 2);
|
||||
goto err;
|
||||
err3:
|
||||
lua_pop(L, 3);
|
||||
err:
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
LUA_STACK_GUARD_UNWIND(L)
|
||||
return false;
|
||||
}
|
||||
bool lua_reconstruct_tcphdr(lua_State *L, int idx, struct tcphdr *tcp, size_t *len)
|
||||
@@ -1969,8 +1968,9 @@ bool lua_reconstruct_tcphdr(lua_State *L, int idx, struct tcphdr *tcp, size_t *l
|
||||
|
||||
tcp->th_off = 5;
|
||||
|
||||
bool b = lua_reconstruct_tcphdr_options(L, idx, tcp, len);
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
return lua_reconstruct_tcphdr_options(L, idx, tcp, len);
|
||||
return b;
|
||||
err:
|
||||
lua_pop(L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
@@ -2121,12 +2121,14 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
|
||||
|
||||
lua_getfield(L,idx,"payload");
|
||||
p = lua_tolstring(L,-1,&lpayload);
|
||||
if (p && lpayload)
|
||||
if (p)
|
||||
{
|
||||
if (left<lpayload) goto err;
|
||||
memcpy(data,p,lpayload);
|
||||
data+=lpayload; left-=lpayload;
|
||||
}
|
||||
else
|
||||
lpayload = 0;
|
||||
lua_pop(L, 1);
|
||||
|
||||
l = data-buf;
|
||||
@@ -2200,8 +2202,7 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
return true;
|
||||
err:
|
||||
lua_pop(L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
LUA_STACK_GUARD_UNWIND(L)
|
||||
return false;
|
||||
}
|
||||
static int luacall_reconstruct_dissect(lua_State *L)
|
||||
@@ -2212,7 +2213,7 @@ static int luacall_reconstruct_dissect(lua_State *L)
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
size_t l;
|
||||
uint8_t buf[RECONSTRUCT_MAX_SIZE];
|
||||
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
|
||||
l = sizeof(buf);
|
||||
|
||||
bool ip6_preserve_next, badsum;
|
||||
@@ -2277,7 +2278,7 @@ static int luacall_csum_tcp_fix(lua_State *L)
|
||||
|
||||
if (proto_check_ipv4(b_ip, l_ip))
|
||||
ip = (struct ip*)b_ip;
|
||||
else if (proto_check_ipv6(b_ip, sizeof(struct ip6_hdr) + ntohs(((struct ip6_hdr*)b_ip)->ip6_ctlun.ip6_un1.ip6_un1_plen)))
|
||||
else if (proto_check_ipv6(b_ip, l_ip))
|
||||
ip6 = (struct ip6_hdr*)b_ip;
|
||||
else
|
||||
luaL_error(L, "invalid ip header");
|
||||
@@ -2318,7 +2319,7 @@ static int luacall_csum_udp_fix(lua_State *L)
|
||||
|
||||
if (proto_check_ipv4(b_ip, l_ip))
|
||||
ip = (struct ip*)b_ip;
|
||||
else if (proto_check_ipv6(b_ip, sizeof(struct ip6_hdr) + ntohs(((struct ip6_hdr*)b_ip)->ip6_ctlun.ip6_un1.ip6_un1_plen)))
|
||||
else if (proto_check_ipv6(b_ip, l_ip))
|
||||
ip6 = (struct ip6_hdr*)b_ip;
|
||||
else
|
||||
luaL_error(L, "invalid ip header");
|
||||
@@ -2412,6 +2413,7 @@ static void lua_rawsend_extract_options(lua_State *L, int idx, int *repeats, uin
|
||||
{
|
||||
lua_getfield(L,idx,"repeats");
|
||||
*repeats=(int)lua_tointeger(L,-1);
|
||||
if (*repeats<0) luaL_error(L, "rawsend: negative repeats");
|
||||
if (!*repeats) *repeats=1;
|
||||
lua_pop(L,1);
|
||||
}
|
||||
@@ -2471,7 +2473,7 @@ static int luacall_rawsend_dissect(lua_State *L)
|
||||
uint32_t fwmark;
|
||||
sockaddr_in46 sa;
|
||||
bool b, badsum, ip6_preserve_next;
|
||||
uint8_t buf[RECONSTRUCT_MAX_SIZE];
|
||||
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
|
||||
len = sizeof(buf);
|
||||
|
||||
luaL_checktype(L,1,LUA_TTABLE);
|
||||
@@ -3260,7 +3262,7 @@ static void lua_init_const(void)
|
||||
{"IPTOS_ECN_ECT1",IPTOS_ECN_ECT1},
|
||||
{"IPTOS_ECN_ECT0",IPTOS_ECN_ECT0},
|
||||
{"IPTOS_ECN_CE",IPTOS_ECN_CE},
|
||||
{"IPTOS_DSCP_MASK",0xF0},
|
||||
{"IPTOS_DSCP_MASK",0xFC},
|
||||
{"IP6F_MORE_FRAG",0x0001}, // in ip6.h it's defined depending of machine byte order
|
||||
{"IPV6_FLOWLABEL_MASK",0x000FFFFF},
|
||||
{"IPV6_FLOWINFO_MASK",0x0FFFFFFF},
|
||||
@@ -3377,7 +3379,7 @@ static void lua_init_functions(void)
|
||||
{"divint",luacall_divint},
|
||||
|
||||
// hacky function, write to immutable strings
|
||||
{"memcpy",luacall_memcpy},
|
||||
//{"memcpy",luacall_memcpy},
|
||||
|
||||
// random blob generation
|
||||
{"brandom",luacall_brandom},
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#define LUA_STACK_GUARD_ENTER(L) int _lsg=lua_gettop(L);
|
||||
#define LUA_STACK_GUARD_LEAVE(L,N) if ((_lsg+N)!=lua_gettop(L)) luaL_error(L,"stack guard failure");
|
||||
#define LUA_STACK_GUARD_RETURN(L,N) LUA_STACK_GUARD_LEAVE(L,N); return N;
|
||||
|
||||
#define LUA_STACK_GUARD_UNWIND(L) lua_settop(L,_lsg);
|
||||
|
||||
void desync_instance(const char *func, unsigned int dp_n, unsigned int func_n, char *instance, size_t inst_size);
|
||||
|
||||
|
||||
29
nfq2/nfqws.c
29
nfq2/nfqws.c
@@ -56,6 +56,8 @@ bool bQuit = false;
|
||||
|
||||
static void onhup(int sig)
|
||||
{
|
||||
if (bQuit) return;
|
||||
|
||||
const char *msg = "HUP received ! Lists will be reloaded.\n";
|
||||
size_t wr = write(1, msg, strlen(msg));
|
||||
bReload = true;
|
||||
@@ -82,12 +84,16 @@ static void ReloadCheck()
|
||||
|
||||
static void onusr1(int sig)
|
||||
{
|
||||
if (bQuit) return;
|
||||
|
||||
printf("\nCONNTRACK DUMP\n");
|
||||
ConntrackPoolDump(¶ms.conntrack);
|
||||
printf("\n");
|
||||
}
|
||||
static void onusr2(int sig)
|
||||
{
|
||||
if (bQuit) return;
|
||||
|
||||
printf("\nHOSTFAIL POOL DUMP\n");
|
||||
|
||||
struct desync_profile_list *dpl;
|
||||
@@ -102,12 +108,16 @@ static void onusr2(int sig)
|
||||
}
|
||||
static void onint(int sig)
|
||||
{
|
||||
if (bQuit) return;
|
||||
|
||||
const char *msg = "INT received !\n";
|
||||
size_t wr = write(1, msg, strlen(msg));
|
||||
bQuit = true;
|
||||
}
|
||||
static void onterm(int sig)
|
||||
{
|
||||
if (bQuit) return;
|
||||
|
||||
const char *msg = "TERM received !\n";
|
||||
size_t wr = write(1, msg, strlen(msg));
|
||||
bQuit = true;
|
||||
@@ -181,7 +191,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
|
||||
char ifout[IFNAMSIZ], ifin[IFNAMSIZ];
|
||||
size_t modlen;
|
||||
uint32_t mark;
|
||||
uint8_t mod[RECONSTRUCT_MAX_SIZE];
|
||||
uint8_t mod[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
|
||||
|
||||
ph = nfq_get_msg_packet_hdr(nfa);
|
||||
id = ph ? ntohl(ph->packet_id) : 0;
|
||||
@@ -311,7 +321,7 @@ static int nfq_main(void)
|
||||
int res, fd, e;
|
||||
ssize_t rd;
|
||||
FILE *Fpid = NULL;
|
||||
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned));
|
||||
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
|
||||
|
||||
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
|
||||
{
|
||||
@@ -625,7 +635,7 @@ static int win_main()
|
||||
WINDIVERT_ADDRESS wa;
|
||||
char ifname[IFNAMSIZ];
|
||||
int res=0;
|
||||
uint8_t packet[RECONSTRUCT_MAX_SIZE];
|
||||
uint8_t packet[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
|
||||
|
||||
if (params.daemon) daemonize();
|
||||
|
||||
@@ -1159,7 +1169,7 @@ static bool parse_ip_list(char *opt, ipset *pp)
|
||||
|
||||
static bool parse_strlist(char *opt, struct str_list_head *list)
|
||||
{
|
||||
char *e, *p = optarg;
|
||||
char *e, *p = opt;
|
||||
while (p)
|
||||
{
|
||||
e = strchr(p, ',');
|
||||
@@ -1431,6 +1441,7 @@ static void exithelp(void)
|
||||
" --wf-filter-lan=0|1\t\t\t\t\t; add excluding filter for non-global IP (default : 1)\n"
|
||||
" --wf-filter-loopback=0|1\t\t\t\t; add excluding filter for loopback (default : 1)\n"
|
||||
" --wf-raw=<filter>|@<filename>\t\t\t\t; full raw windivert filter string or filename. replaces --wf-tcp,--wf-udp,--wf-raw-part\n"
|
||||
" --wf-dup-check=0|1\t\t\t\t\t; 1 (default) = do not allow duplicate winws2 instances with the same wf filter\n"
|
||||
" --wf-save=<filename>\t\t\t\t\t; save windivert filter string to a file and exit\n"
|
||||
"\nLOGICAL NETWORK FILTER:\n"
|
||||
" --ssid-filter=ssid1[,ssid2,ssid3,...]\t\t\t; enable winws2 only if any of specified wifi SSIDs connected\n"
|
||||
@@ -1625,6 +1636,7 @@ enum opt_indices {
|
||||
IDX_WF_RAW_PART,
|
||||
IDX_WF_FILTER_LAN,
|
||||
IDX_WF_FILTER_LOOPBACK,
|
||||
IDX_WF_DUP_CHECK,
|
||||
IDX_WF_SAVE,
|
||||
IDX_SSID_FILTER,
|
||||
IDX_NLM_FILTER,
|
||||
@@ -1717,6 +1729,7 @@ static const struct option long_options[] = {
|
||||
[IDX_WF_FILTER_LAN] = {"wf-filter-lan", required_argument, 0, 0},
|
||||
[IDX_WF_FILTER_LOOPBACK] = {"wf-filter-loopback", required_argument, 0, 0},
|
||||
[IDX_WF_SAVE] = {"wf-save", required_argument, 0, 0},
|
||||
[IDX_WF_DUP_CHECK] = {"wf-dup-check", optional_argument, 0, 0},
|
||||
[IDX_SSID_FILTER] = {"ssid-filter", required_argument, 0, 0},
|
||||
[IDX_NLM_FILTER] = {"nlm-filter", required_argument, 0, 0},
|
||||
[IDX_NLM_LIST] = {"nlm-list", optional_argument, 0, 0},
|
||||
@@ -1752,7 +1765,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
int result, v;
|
||||
int option_index = 0;
|
||||
bool bSkip = false, bDry = false, bTemplate;
|
||||
bool bSkip = false, bDry = false, bDupCheck = true, bTemplate;
|
||||
struct hostlist_file *anon_hl = NULL, *anon_hl_exclude = NULL;
|
||||
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
|
||||
uint64_t payload_type=0;
|
||||
@@ -2488,6 +2501,9 @@ int main(int argc, char **argv)
|
||||
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
|
||||
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
|
||||
break;
|
||||
case IDX_WF_DUP_CHECK:
|
||||
bDupCheck = !optarg || !!atoi(optarg);
|
||||
break;
|
||||
case IDX_SSID_FILTER:
|
||||
hash_ssid_filter = hash_jen(optarg, strlen(optarg));
|
||||
if (!parse_strlist(optarg, ¶ms.ssid_filter))
|
||||
@@ -2683,7 +2699,8 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
}
|
||||
HANDLE hMutexArg;
|
||||
HANDLE hMutexArg = NULL;
|
||||
if (bDupCheck)
|
||||
{
|
||||
char mutex_name[128];
|
||||
snprintf(mutex_name, sizeof(mutex_name), "Global\\winws2_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u",
|
||||
|
||||
@@ -85,6 +85,7 @@ struct desync_profile
|
||||
bool hostlist_auto_retrans_reset;
|
||||
|
||||
hostfail_pool *hostlist_auto_fail_counters;
|
||||
time_t hostlist_auto_last_purge;
|
||||
|
||||
struct func_list_head lua_desync;
|
||||
};
|
||||
|
||||
@@ -112,15 +112,14 @@ void HostFailPoolPurge(hostfail_pool **pp)
|
||||
HostFailPoolDel(pp, elem);
|
||||
}
|
||||
}
|
||||
static time_t host_fail_purge_prev=0;
|
||||
void HostFailPoolPurgeRateLimited(hostfail_pool **pp)
|
||||
void HostFailPoolPurgeRateLimited(hostfail_pool **pp, time_t *purge_prev)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
// do not purge too often to save resources
|
||||
if (host_fail_purge_prev != now)
|
||||
if (*purge_prev != now)
|
||||
{
|
||||
HostFailPoolPurge(pp);
|
||||
host_fail_purge_prev = now;
|
||||
*purge_prev = now;
|
||||
}
|
||||
}
|
||||
void HostFailPoolDump(hostfail_pool *p)
|
||||
|
||||
@@ -75,9 +75,9 @@ void funclist_destroy(struct func_list_head *head);
|
||||
|
||||
|
||||
typedef struct hostfail_pool {
|
||||
char *str; /* key */
|
||||
int counter; /* value */
|
||||
time_t expire; /* when to expire record (unixtime) */
|
||||
char *str;
|
||||
int counter;
|
||||
time_t expire; // when to expire record (unixtime)
|
||||
UT_hash_handle hh; /* makes this structure hashable */
|
||||
} hostfail_pool;
|
||||
|
||||
@@ -86,7 +86,7 @@ hostfail_pool *HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time);
|
||||
hostfail_pool *HostFailPoolFind(hostfail_pool *p,const char *s);
|
||||
void HostFailPoolDel(hostfail_pool **pp, hostfail_pool *elem);
|
||||
void HostFailPoolPurge(hostfail_pool **pp);
|
||||
void HostFailPoolPurgeRateLimited(hostfail_pool **pp);
|
||||
void HostFailPoolPurgeRateLimited(hostfail_pool **pp, time_t *purge_prev);
|
||||
void HostFailPoolDump(hostfail_pool *p);
|
||||
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ bool l7_payload_match(t_l7payload l7payload, uint64_t filter_l7p)
|
||||
}
|
||||
bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
|
||||
{
|
||||
char *p;
|
||||
char *p, *e;
|
||||
const char *pstr;
|
||||
size_t lstr;
|
||||
t_l7payload pl;
|
||||
@@ -86,17 +86,17 @@ bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
|
||||
memcpy(buf,"all",4);
|
||||
return true;
|
||||
}
|
||||
for(pl=0, p=buf, *buf=0 ; pl<L7P_LAST ; pl++)
|
||||
for(pl=0, p=buf, e=p+size, *buf=0 ; pl<L7P_LAST ; pl++)
|
||||
{
|
||||
if (l7p & (1<<pl))
|
||||
{
|
||||
pstr = l7payload_str(pl);
|
||||
lstr = strlen(pstr);
|
||||
if (size < ((p!=buf) + lstr + 1)) return false;
|
||||
if ((p + (p!=buf) + lstr + 1) > e) return false;
|
||||
if (p!=buf) *p++=','; // not first
|
||||
memcpy(p,pstr,lstr);
|
||||
p[lstr]=0;
|
||||
p+=lstr;
|
||||
p += lstr;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -243,24 +243,38 @@ void ResolveMultiPos(const uint8_t *data, size_t sz, t_l7payload l7payload, cons
|
||||
}
|
||||
|
||||
|
||||
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS ","PUT /","DELETE /","CONNECT ","TRACE /",NULL };
|
||||
const char *HttpMethod(const uint8_t *data, size_t len)
|
||||
static const char *http_methods[] = { "GET ","POST ","HEAD ","OPTIONS ","PUT ","DELETE ","CONNECT ","TRACE ",NULL };
|
||||
static const char *HttpMethod(const uint8_t *data, size_t len)
|
||||
{
|
||||
const char **method;
|
||||
size_t method_len;
|
||||
for (method = http_methods; *method; method++)
|
||||
|
||||
if (len>=4)
|
||||
{
|
||||
method_len = strlen(*method);
|
||||
if (method_len <= len && !memcmp(data, *method, method_len))
|
||||
return *method;
|
||||
for (method = http_methods; *method; method++)
|
||||
{
|
||||
method_len = strlen(*method);
|
||||
if (method_len <= len && !memcmp(data, *method, method_len))
|
||||
return *method;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
bool IsHttp(const uint8_t *data, size_t len)
|
||||
{
|
||||
return !!HttpMethod(data,len);
|
||||
if (!HttpMethod(data,len)) return false;
|
||||
// GET /uri HTTP/1.1
|
||||
// skip method
|
||||
for(; len && *data!=' ' && *data!='\t' && *data!='\r' && *data!='\n'; data++, len--);
|
||||
if (!len || *data!=' ' && *data!='\t') return false;
|
||||
for(; len && (*data==' '|| *data=='\t'); data++, len--);
|
||||
// skip URI
|
||||
for(; len && *data!=' ' && *data!='\t' && *data!='\r' && *data!='\n'; data++, len--);
|
||||
if (!len || *data!=' ' && *data!='\t') return false;
|
||||
for(; len && (*data==' '|| *data=='\t'); data++, len--);
|
||||
if (len<10 || *data=='\r' || *data=='\n') return false;
|
||||
return !memcmp(data,"HTTP/1.",7);
|
||||
}
|
||||
|
||||
static bool IsHostAt(const uint8_t *p)
|
||||
{
|
||||
return \
|
||||
@@ -394,10 +408,11 @@ ssize_t HttpPos(t_marker posmarker, int16_t pos, const uint8_t *data, size_t sz)
|
||||
case PM_HTTP_METHOD:
|
||||
// recognize some tpws pre-applied hacks
|
||||
method=data;
|
||||
if (sz<10) break;
|
||||
if (sz<12) break;
|
||||
if (*method=='\n' || *method=='\r') method++;
|
||||
if (*method=='\n' || *method=='\r') method++;
|
||||
for (p=method,i=0;i<7;i++) if (*p>='A' && *p<='Z') p++;
|
||||
// max length is PROPPATCH
|
||||
for (p=method,i=0;i<9;i++) if (*p>='A' && *p<='Z') p++;
|
||||
if (i<3 || *p!=' ') break;
|
||||
return CheckPos(sz,method-data+pos);
|
||||
case PM_HOST:
|
||||
@@ -985,6 +1000,10 @@ bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, si
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_quic_v2(uint32_t version)
|
||||
{
|
||||
return (version == 0x709A50C4) || (version == 0x6b3343cf);
|
||||
}
|
||||
/* Returns the QUIC draft version or 0 if not applicable. */
|
||||
uint8_t QUICDraftVersion(uint32_t version)
|
||||
{
|
||||
@@ -1016,7 +1035,7 @@ uint8_t QUICDraftVersion(uint32_t version)
|
||||
return 34;
|
||||
/* QUIC Version 2 */
|
||||
/* TODO: for the time being use 100 as a number for V2 and let see how v2 drafts evolve */
|
||||
if ((version == 0x709A50C4) || (version == 0x6b3343cf))
|
||||
if (is_quic_v2(version))
|
||||
return 100;
|
||||
|
||||
return 0;
|
||||
@@ -1026,10 +1045,6 @@ static bool is_quic_draft_max(uint32_t draft_version, uint8_t max_version)
|
||||
{
|
||||
return draft_version && draft_version <= max_version;
|
||||
}
|
||||
static bool is_quic_v2(uint32_t version)
|
||||
{
|
||||
return (version == 0x709A50C4) || (version == 0x6b3343cf);
|
||||
}
|
||||
|
||||
static bool quic_hkdf_expand_label(const uint8_t *secret, uint8_t secret_len, const char *label, uint8_t *out, size_t out_len)
|
||||
{
|
||||
@@ -1140,7 +1155,7 @@ bool QUICIsLongHeader(const uint8_t *data, size_t len)
|
||||
uint32_t QUICExtractVersion(const uint8_t *data, size_t len)
|
||||
{
|
||||
// long header, fixed bit, type=initial
|
||||
return QUICIsLongHeader(data, len) ? ntohl(*(uint32_t*)(data + 1)) : 0;
|
||||
return QUICIsLongHeader(data, len) ? pntoh32(data + 1) : 0;
|
||||
}
|
||||
bool QUICExtractDCID(const uint8_t *data, size_t len, quic_cid_t *cid)
|
||||
{
|
||||
@@ -1177,6 +1192,7 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
|
||||
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
|
||||
pn_offset += tvb_get_varint(data + pn_offset, &token_len);
|
||||
pn_offset += token_len;
|
||||
if (pn_offset >= data_len) return false;
|
||||
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
|
||||
pn_offset += tvb_get_varint(data + pn_offset, &payload_len);
|
||||
if (payload_len<20 || (pn_offset + payload_len)>data_len) return false;
|
||||
@@ -1429,12 +1445,12 @@ bool IsMTProto(const uint8_t *data, size_t len)
|
||||
if (len>=64)
|
||||
{
|
||||
/*
|
||||
uint8_t decrypt[64];
|
||||
uint8_t decrypt[64] __attribute__((aligned));
|
||||
aes_ctr_crypt(data+8, 32, data+40, data, 64, decrypt);
|
||||
return !memcmp(decrypt+56,"\xEF\xEF\xEF\xEF",4);
|
||||
*/
|
||||
// this way requires only one AES instead of 4
|
||||
uint8_t decrypt[16], iv[16];
|
||||
uint8_t decrypt[16] __attribute__((aligned)), iv[16];
|
||||
aes_context ctx;
|
||||
|
||||
memcpy(iv, data+40, 16);
|
||||
|
||||
@@ -90,16 +90,12 @@ ssize_t TLSPos(t_marker posmarker, int16_t pos, const uint8_t *data, size_t sz);
|
||||
ssize_t ResolvePos(const uint8_t *data, size_t sz, t_l7payload l7payload, const struct proto_pos *sp);
|
||||
void ResolveMultiPos(const uint8_t *data, size_t sz, t_l7payload l7payload, const struct proto_pos *marker, int marker_count, ssize_t *pos, int *pos_count);
|
||||
|
||||
extern const char *http_methods[9];
|
||||
const char *HttpMethod(const uint8_t *data, size_t len);
|
||||
bool IsHttp(const uint8_t *data, size_t len);
|
||||
bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs);
|
||||
bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs);
|
||||
// header must be passed like this : "\nHost:"
|
||||
bool HttpExtractHeader(const uint8_t *data, size_t len, const char *header, char *buf, size_t len_buf);
|
||||
bool HttpExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host);
|
||||
bool IsHttpReply(const uint8_t *data, size_t len);
|
||||
const char *HttpFind2ndLevelDomain(const char *host);
|
||||
// must be pre-checked by IsHttpReply
|
||||
int HttpReplyCode(const uint8_t *data, size_t len);
|
||||
// must be pre-checked by IsHttpReply
|
||||
|
||||
Reference in New Issue
Block a user