mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-15 14:36:09 +00:00
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b91fb6a424 | ||
|
|
97e16b5611 | ||
|
|
8fe63df846 | ||
|
|
494abc0e53 | ||
|
|
ef300e5d21 | ||
|
|
1f70b21a4d | ||
|
|
520bf5142f | ||
|
|
b2a611adba | ||
|
|
24320b6671 | ||
|
|
709db5d135 | ||
|
|
6515cd3227 | ||
|
|
574ad480f8 | ||
|
|
bebb2ccabf | ||
|
|
4923ac7bc5 | ||
|
|
605af78ce8 | ||
|
|
b496bac9ab | ||
|
|
9ba7ad6263 | ||
|
|
36a980469f | ||
|
|
284b345482 | ||
|
|
5866bc7721 | ||
|
|
bcf11b8f72 | ||
|
|
ee11c760fd | ||
|
|
e1c6802b52 | ||
|
|
8d2b7d9ef2 | ||
|
|
733171fb3c | ||
|
|
9eaf346253 | ||
|
|
1cfec4d737 | ||
|
|
39c6a71481 | ||
|
|
35b97450fe | ||
|
|
cfb8b9f11f | ||
|
|
5e737f314b | ||
|
|
6a26ea85a3 | ||
|
|
1eb780bb06 | ||
|
|
db2412a6b4 | ||
|
|
de15c25def | ||
|
|
3ee6d2fb48 | ||
|
|
9822fd0b36 | ||
|
|
38454aabfa | ||
|
|
14503e0a57 | ||
|
|
ef421bad9c | ||
|
|
e963b6f20b | ||
|
|
c52a3a2e75 | ||
|
|
b2f7fac102 | ||
|
|
ea566720a5 | ||
|
|
22c7ee257e | ||
|
|
a5a81424c8 | ||
|
|
fba42f8a00 | ||
|
|
b4aff06c35 | ||
|
|
2b85262ee2 | ||
|
|
3b92197bb3 | ||
|
|
9d49f35324 | ||
|
|
ed4eb043a2 | ||
|
|
3a66f86621 | ||
|
|
c80efcc983 | ||
|
|
c65b28c3f7 | ||
|
|
6d74e6e873 | ||
|
|
200ca70f82 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -551,7 +551,7 @@ jobs:
|
||||
(
|
||||
cd ${{ env.repo_dir }}
|
||||
rm -rf binaries/{android*,freebsd*,win*} \
|
||||
init.d/{openrc,pfsense,runit,s6,systemd} \
|
||||
init.d/{openrc,pfsense,runit,s6,systemd,windivert.filter.examples} \
|
||||
nfq2 ip2net mdig docs Makefile
|
||||
)
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
|
||||
|
||||
58
blockcheck2.d/custom/10-list.sh
Normal file
58
blockcheck2.d/custom/10-list.sh
Normal file
@@ -0,0 +1,58 @@
|
||||
LIST_HTTP="${LIST_HTTP:-$TESTDIR/list_http.txt}"
|
||||
LIST_HTTPS_TLS12="${LIST_HTTPS_TLS12:-$TESTDIR/list_https_tls12.txt}"
|
||||
LIST_HTTPS_TLS13="${LIST_HTTPS_TLS13:-$TESTDIR/list_https_tls13.txt}"
|
||||
LIST_QUIC="${LIST_QUIC:-$TESTDIR/list_quic.txt}"
|
||||
|
||||
check_list()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - file
|
||||
|
||||
local line ok=0
|
||||
[ -f "$3" ] || {
|
||||
echo "no strategy file '$3'"
|
||||
return 1
|
||||
}
|
||||
while IFS= read -r line; do
|
||||
case "$line" in
|
||||
""|\#*) continue ;;
|
||||
esac
|
||||
line=$(echo "$line" | tr -d "\r\n")
|
||||
eval pktws_curl_test_update "$1" "$2" $line && ok=1
|
||||
done < "$3"
|
||||
|
||||
[ "$ok" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
check_list "$1" "$2" "$LIST_HTTP"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
check_list "$1" "$2" "$LIST_HTTPS_TLS12"
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
check_list "$1" "$2" "$LIST_HTTPS_TLS13"
|
||||
}
|
||||
|
||||
pktws_check_http3()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
check_list "$1" "$2" "$LIST_QUIC"
|
||||
}
|
||||
10
blockcheck2.d/custom/README.txt
Normal file
10
blockcheck2.d/custom/README.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Простой тестер стратегий по списку из файла.
|
||||
Скопируйте эту директорию под другим именем в blockcheck2.d, отредактируйте list файлы, впишите туда свои стратегии.
|
||||
В диалоге blockcheck2.sh выберите тест с названием вашей директории.
|
||||
Можно комментировать строки символом '#' в начале строки.
|
||||
Альтернативный путь до файлов стратегий можно задать переменными 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.
|
||||
Strategy list files paths can be overriden in env variables : LIST_HTTP, LIST_HTTPS_TLS12, LIST_HTTPS_TLS13, LIST_QUIC.
|
||||
4
blockcheck2.d/custom/list_http.txt
Normal file
4
blockcheck2.d/custom/list_http.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# write nfqws2 parameters here
|
||||
--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
|
||||
3
blockcheck2.d/custom/list_https_tls12.txt
Normal file
3
blockcheck2.d/custom/list_https_tls12.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
# write nfqws2 parameters here
|
||||
--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
|
||||
4
blockcheck2.d/custom/list_https_tls13.txt
Normal file
4
blockcheck2.d/custom/list_https_tls13.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# write nfqws2 parameters here
|
||||
--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
|
||||
3
blockcheck2.d/custom/list_quic.txt
Normal file
3
blockcheck2.d/custom/list_quic.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
# write nfqws2 parameters here
|
||||
--payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=11
|
||||
--payload quic_initial --lua-desync=send:ipfrag --lua-desync=drop
|
||||
12
blockcheck2.d/standard/10-http-basic.sh
Normal file
12
blockcheck2.d/standard/10-http-basic.sh
Normal file
@@ -0,0 +1,12 @@
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
local s
|
||||
|
||||
[ "$NOTEST_BASIC_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for s in 'http_hostcase' 'http_hostcase:spell=hoSt' 'http_domcase' 'http_methodeol'; do
|
||||
pktws_curl_test_update $1 $2 --payload http_req --lua-desync=$s
|
||||
done
|
||||
}
|
||||
38
blockcheck2.d/standard/15-misc.sh
Normal file
38
blockcheck2.d/standard/15-misc.sh
Normal file
@@ -0,0 +1,38 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local PAYLOAD="--payload http_req" repeats ok
|
||||
|
||||
for repeats in 1 20 100 260; do
|
||||
# send starting bytes of original payload
|
||||
pktws_curl_test_update "$1" "$2" $PAYLOAD --lua-desync=tcpseg:pos=0,method+2:ip_id=rnd:repeats=$repeats && ok=1
|
||||
pktws_curl_test_update "$1" "$2" $PAYLOAD --lua-desync=tcpseg:pos=0,midsld:ip_id=rnd:repeats=$repeats && ok=1
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local PAYLOAD="--payload tls_client_hello" repeats ok
|
||||
|
||||
for repeats in 1 20 100 260; do
|
||||
# send starting bytes of original payload
|
||||
pktws_curl_test_update "$1" "$2" $PAYLOAD --lua-desync=tcpseg:pos=0,1:ip_id=rnd:repeats=$repeats && ok=1
|
||||
pktws_curl_test_update "$1" "$2" $PAYLOAD --lua-desync=tcpseg:pos=0,midsld:ip_id=rnd:repeats=$repeats && ok=1
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls12 "$1" "$2"
|
||||
}
|
||||
66
blockcheck2.d/standard/20-multi.sh
Normal file
66
blockcheck2.d/standard/20-multi.sh
Normal file
@@ -0,0 +1,66 @@
|
||||
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"
|
||||
|
||||
ok_any=0
|
||||
for splitf in multisplit multidisorder; do
|
||||
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
|
||||
done
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] || eval need_$splitf=1
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
done
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
local splits_http='method+2 midsld method+2,midsld'
|
||||
local PAYLOAD="--payload http_req"
|
||||
|
||||
[ "$NOTEST_MULTI_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_simple_split_tests "$1" "$2" "$splits_http"
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload tls_client_hello"
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_simple_split_tests "$1" "$2" "$splits_tls" "$3"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
local need_multisplit_save=$need_multisplit need_multidisorder_save=$need_multidisorder
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
need_multisplit=$need_multisplit_save; need_multidisorder=$need_multidisorder_save
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
94
blockcheck2.d/standard/23-seqovl.sh
Normal file
94
blockcheck2.d/standard/23-seqovl.sh
Normal file
@@ -0,0 +1,94 @@
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local PAYLOAD="--payload http_req"
|
||||
|
||||
local ok pat= split f f2
|
||||
|
||||
pat=${SEQOVL_PATTERN_HTTP:+seqovl_pat}
|
||||
pat=${pat:-fake_default_http}
|
||||
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=1 --lua-desync=drop
|
||||
pktws_curl_test_update $1 $2 ${SEQOVL_PATTERN_HTTP:+--blob=$pat:@"$SEQOVL_PATTERN_HTTP" }$PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=#$pat:seqovl_pattern=$pat --lua-desync=drop
|
||||
|
||||
ok=0
|
||||
for split in method+2 method+2,midsld; do
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=1 && ok=1
|
||||
pktws_curl_test_update $1 $2 ${SEQOVL_PATTERN_HTTP:+--blob=$pat:@"$SEQOVL_PATTERN_HTTP" }$PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=#$pat:seqovl_pattern=$pat && ok=1
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
for split in 'method+1 method+2' 'midsld-1 midsld' 'method+1 method+2,midsld'; do
|
||||
f="$(extract_arg 1 $split)"
|
||||
f2="$(extract_arg 2 $split)"
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f
|
||||
pktws_curl_test_update $1 $2 ${SEQOVL_PATTERN_HTTP:+--blob=$pat:@"$SEQOVL_PATTERN_HTTP" }$PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f:seqovl_pattern=$pat
|
||||
done
|
||||
}
|
||||
|
||||
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
|
||||
local PAYLOAD="--payload tls_client_hello"
|
||||
|
||||
pat=${SEQOVL_PATTERN_HTTPS:+seqovl_pat}
|
||||
pat=${pat:-fake_default_tls}
|
||||
rnd_mod="--lua-init=$pat=tls_mod($pat,'rnd')"
|
||||
padencap_mod="--lua-desync=luaexec:code=desync.pat=tls_mod($pat,'rnd,dupsid,padencap',desync.reasm_data)"
|
||||
|
||||
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
|
||||
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
|
||||
[ "$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
|
||||
f="$(extract_arg 1 $split)"
|
||||
f2="$(extract_arg 2 $split)"
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
|
||||
done
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
[ "$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
|
||||
pktws_seqovl_tests_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_seqovl_tests_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_seqovl_tests_tls "$1" "$2"
|
||||
}
|
||||
149
blockcheck2.d/standard/25-fake.sh
Normal file
149
blockcheck2.d/standard/25-fake.sh
Normal file
@@ -0,0 +1,149 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
[ "$NOTEST_FAKE_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local testf=$1 domain="$2"
|
||||
local ok ok_any ttls attls f ff fake fooling
|
||||
local PAYLOAD="--payload=http_req"
|
||||
|
||||
if [ -n "$FAKE_HTTP" ]; then
|
||||
fake=fake_http
|
||||
else
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
need_fake=0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok_any=0
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
# orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
|
||||
# missing ACK is transmitted in the first data packet of TLS/HTTP proto
|
||||
for ff in $fake 0x00000000; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD "--lua-desync=fake:blob=${ff}:ip${IPVV}_ttl=$ttl:repeats=$FAKE_REPEATS" $f && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
done
|
||||
[ "$ok" = 1 ] && break
|
||||
done
|
||||
for fooling in $FOOLINGS_TCP; do
|
||||
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
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
for ff in $fake 0x00000000; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:ip${IPVV}_autottl=-$ttl,3-20:repeats=$FAKE_REPEATS $f && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_fake=1
|
||||
[ $ok = 1 ] && okany=1
|
||||
[ $okany = 1 ]
|
||||
}
|
||||
|
||||
pktws_fake_https_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5"
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
}
|
||||
pktws_fake_https_vary()
|
||||
{
|
||||
local ok_any=0 fooling="$3"
|
||||
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
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $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"
|
||||
|
||||
shift; shift
|
||||
|
||||
if [ -n "$FAKE_HTTPS" ]; then
|
||||
fake=fake_tls
|
||||
else
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
|
||||
need_fake=0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok_any=0
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
# orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
|
||||
# missing ACK is transmitted in the first data packet of TLS/HTTP proto
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_fake_https_vary $testf $domain "ip${IPVV}_ttl=$ttl" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
[ "$ok" = 1 ] && break
|
||||
done
|
||||
for fooling in $FOOLINGS_TCP; do
|
||||
pktws_fake_https_vary $testf $domain "$fooling" "$pre"
|
||||
done
|
||||
for ttl in $attls; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_fake_https_vary $testf $domain "ip${IPVV}_autottl=-$ttl,3-20" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
done
|
||||
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_fake=1
|
||||
[ $ok = 1 ] && okany=1
|
||||
[ $okany = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
local need_fake_save=$need_fake
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
need_fake=$need_fake_save
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
103
blockcheck2.d/standard/30-faked.sh
Normal file
103
blockcheck2.d/standard/30-faked.sh
Normal file
@@ -0,0 +1,103 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_faked()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - payload_type
|
||||
# $4 - splits
|
||||
# $5 - pattern
|
||||
# $6 - PRE args for nfqws2
|
||||
local testf=$1 domain="$2" pre="$6"
|
||||
local ok ok_any ttls attls f fooling
|
||||
local splitf splitfs= split splits="$4"
|
||||
local PAYLOAD="--payload=$3"
|
||||
local FAKED_PATTERN="$5"
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fakedsplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
# do not test fakeddisorder if multidisorder works
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }fakeddisorder"
|
||||
|
||||
ok_any=0
|
||||
for splitf in $splitfs; do
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
# orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
|
||||
# missing ACK is transmitted in the first data packet of TLS/HTTP proto
|
||||
for split in $splits; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; 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:ip${IPVV}_ttl=$ttl:repeats=$FAKE_REPEATS $f && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
done
|
||||
[ "$ok" = 1 ] && break
|
||||
done
|
||||
for fooling in $FOOLINGS_TCP; do
|
||||
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
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
for split in $splits; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; 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:ip${IPVV}_autottl=-$ttl,3-20:repeats=$FAKE_REPEATS $f && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
done
|
||||
done
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && eval need_$splitf=1
|
||||
[ $ok = 1 ] && ok_any=1
|
||||
done
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
[ "$NOTEST_FAKED_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local splits='method+2 midsld method+2,midsld'
|
||||
pktws_check_faked $1 "$2" http_req "$splits" "$FAKED_PATTERN_HTTP" "$3"
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
local need_fakedsplit_save=$need_fakedsplit need_fakeddisorder_save=$need_fakeddisorder
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
need_fakedsplit=$need_fakedsplit_save need_fakeddisorder=$need_fakeddisorder_save
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
101
blockcheck2.d/standard/35-hostfake.sh
Normal file
101
blockcheck2.d/standard/35-hostfake.sh
Normal file
@@ -0,0 +1,101 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
|
||||
pktws_hostfake_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5" disorder
|
||||
shift; shift; shift
|
||||
|
||||
for disorder in '' 'disorder_after:'; do
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}$fooling:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake1:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake2:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}midhost=midsld:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake1:midhost=midsld:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake2:midhost=midsld:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1
|
||||
done
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
}
|
||||
pktws_hostfake_vary()
|
||||
{
|
||||
local ok_any=0 fooling="$3"
|
||||
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
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
|
||||
pktws_check_hostfake()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - payload_type
|
||||
# $4 - PRE args for nfqws2
|
||||
local testf=$1 domain="$2" pre="$4"
|
||||
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)
|
||||
|
||||
need_hostfakesplit=0
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
# orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
|
||||
# missing ACK is transmitted in the first data packet of TLS/HTTP proto
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_hostfake_vary $testf $domain "ip${IPVV}_ttl=$ttl" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
[ "$ok" = 1 ] && break
|
||||
done
|
||||
for fooling in $FOOLINGS_TCP; do
|
||||
pktws_hostfake_vary $testf $domain "$fooling" "$pre"
|
||||
done
|
||||
for ttl in $attls; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
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 = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
[ "$NOTEST_HOSTFAKE_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_hostfake $1 "$2" http_req
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $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
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
local need_hostfakesplit_save=$need_hostfakesplit
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
need_hostfakesplit=$need_hostfakesplit_save
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
160
blockcheck2.d/standard/50-fake-multi.sh
Normal file
160
blockcheck2.d/standard/50-fake-multi.sh
Normal file
@@ -0,0 +1,160 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
[ "$NOTEST_FAKE_MULTI_HTTP" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local testf=$1 domain="$2"
|
||||
local ok ttls attls f ff fake fooling splitf splitfs= split splits='method+2 midsld method+2,midsld'
|
||||
local PAYLOAD="--payload=http_req"
|
||||
|
||||
if [ -n "$FAKE_HTTP" ]; then
|
||||
fake=fake_http
|
||||
else
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
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
|
||||
# do not test fake + multidisorder if multidisorder works
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }multidisorder"
|
||||
|
||||
for splitf in $splitfs; do
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
for split in $splits; do
|
||||
# orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
|
||||
# missing ACK is transmitted in the first data packet of TLS/HTTP proto
|
||||
for ff in $fake 0x00000000; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD "--lua-desync=fake:blob=${ff}:ip${IPVV}_ttl=$ttl:repeats=$FAKE_REPEATS" --lua-desync=$splitf:pos=$split $f && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
done
|
||||
done
|
||||
[ "$ok" = 1 ] && break
|
||||
done
|
||||
for fooling in $FOOLINGS_TCP; do
|
||||
for split in $splits; do
|
||||
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
|
||||
done
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
for split in $splits; do
|
||||
for ff in $fake 0x00000000; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:ip${IPVV}_autottl=-$ttl,3-20:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $f && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
pktws_fake_https_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5"
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
}
|
||||
pktws_fake_https_vary()
|
||||
{
|
||||
local ok_any=0 fooling="$3"
|
||||
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
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $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,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
|
||||
shift; shift
|
||||
|
||||
if [ -n "$FAKE_HTTPS" ]; then
|
||||
fake=fake_tls
|
||||
else
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
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
|
||||
# do not test fake + multidisorder if multidisorder works
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }multidisorder"
|
||||
|
||||
ok_any=0
|
||||
for splitf in $splitfs; do
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
for split in $splits; do
|
||||
# orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
|
||||
# missing ACK is transmitted in the first data packet of TLS/HTTP proto
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_fake_https_vary $testf $domain "ip${IPVV}_ttl=$ttl" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
done
|
||||
[ "$ok" = 1 ] && break
|
||||
done
|
||||
for fooling in $FOOLINGS_TCP; do
|
||||
for split in $splits; do
|
||||
pktws_fake_https_vary $testf $domain "$fooling" "$pre"
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
for split in $splits; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_fake_https_vary $testf $domain "ip${IPVV}_autottl=-$ttl,3-20" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
done
|
||||
done
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
done
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
161
blockcheck2.d/standard/55-fake-faked.sh
Normal file
161
blockcheck2.d/standard/55-fake-faked.sh
Normal file
@@ -0,0 +1,161 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
[ "$NOTEST_FAKE_FAKED_HTTP" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local testf=$1 domain="$2"
|
||||
local ok ttls attls f ff fake fooling splitf splitfs= split splits='method+2 midsld method+2,midsld'
|
||||
local PAYLOAD="--payload=http_req"
|
||||
|
||||
if [ -n "$FAKE_HTTP" ]; then
|
||||
fake=fake_http
|
||||
else
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
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
|
||||
# do not test fake + fakeddisorder if fakeddisorder works
|
||||
[ "$need_fakeddisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }fakeddisorder"
|
||||
|
||||
for splitf in $splitfs; do
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
for split in $splits; do
|
||||
# orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
|
||||
# missing ACK is transmitted in the first data packet of TLS/HTTP proto
|
||||
for ff in $fake 0x00000000; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; 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}:ip${IPVV}_ttl=$ttl:repeats=$FAKE_REPEATS" --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:ip${IPVV}_ttl=$ttl:repeats=$FAKE_REPEATS $f && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
done
|
||||
done
|
||||
[ "$ok" = 1 ] && break
|
||||
done
|
||||
for fooling in $FOOLINGS_TCP; do
|
||||
for split in $splits; do
|
||||
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
|
||||
done
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
for split in $splits; do
|
||||
for ff in $fake 0x00000000; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; 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:ip${IPVV}_autottl=-$ttl,3-20:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:ip${IPVV}_autottl=-$ttl,3-20:repeats=$FAKE_REPEATS $f && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
pktws_fake_https_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5"
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
|
||||
}
|
||||
pktws_fake_https_vary()
|
||||
{
|
||||
local ok_any=0 fooling="$3"
|
||||
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
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $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"
|
||||
|
||||
shift; shift
|
||||
|
||||
if [ -n "$FAKE_HTTPS" ]; then
|
||||
fake=fake_tls
|
||||
else
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + fakedsplit if fakedsplit works
|
||||
[ "$need_fakedsplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
# do not test fake + fakeddisorder if fakeddisorder works
|
||||
[ "$need_fakeddisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }fakeddisorder"
|
||||
|
||||
ok_any=0
|
||||
for splitf in $splitfs; do
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
for split in $splits; do
|
||||
# orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
|
||||
# missing ACK is transmitted in the first data packet of TLS/HTTP proto
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_fake_https_vary $testf $domain "ip${IPVV}_ttl=$ttl" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
done
|
||||
[ "$ok" = 1 ] && break
|
||||
done
|
||||
for fooling in $FOOLINGS_TCP; do
|
||||
for split in $splits; do
|
||||
pktws_fake_https_vary $testf $domain "$fooling" "$pre"
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
for split in $splits; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_fake_https_vary $testf $domain "ip${IPVV}_autottl=-$ttl,3-20" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
done
|
||||
done
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
done
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
113
blockcheck2.d/standard/60-fake-hostfake.sh
Normal file
113
blockcheck2.d/standard/60-fake-hostfake.sh
Normal file
@@ -0,0 +1,113 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_hostfake_vary_()
|
||||
{
|
||||
local testf=$1 domain="$2" fooling="$3" pre="$4" post="$5" disorder
|
||||
shift; shift; shift
|
||||
|
||||
for disorder in '' 'disorder_after:'; do
|
||||
pktws_curl_test_update $testf $domain $pre ${FAKE:+--blob=$fake:@"$FAKE" }$PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}$fooling:repeats=$FAKE_REPEATS $post && ok=1
|
||||
pktws_curl_test_update $testf $domain $pre ${FAKE:+--blob=$fake:@"$FAKE" }$PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake1:$fooling:repeats=$FAKE_REPEATS $post && ok=1
|
||||
pktws_curl_test_update $testf $domain $pre ${FAKE:+--blob=$fake:@"$FAKE" }$PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake2:$fooling:repeats=$FAKE_REPEATS $post && ok=1
|
||||
pktws_curl_test_update $testf $domain $pre ${FAKE:+--blob=$fake:@"$FAKE" }$PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}midhost=midsld:$fooling:repeats=$FAKE_REPEATS $post && ok=1
|
||||
pktws_curl_test_update $testf $domain $pre ${FAKE:+--blob=$fake:@"$FAKE" }$PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake1:midhost=midsld:$fooling:repeats=$FAKE_REPEATS $post && ok=1
|
||||
pktws_curl_test_update $testf $domain $pre ${FAKE:+--blob=$fake:@"$FAKE" }$PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake2:midhost=midsld:$fooling:repeats=$FAKE_REPEATS $post && ok=1
|
||||
done
|
||||
}
|
||||
pktws_hostfake_vary()
|
||||
{
|
||||
local fooling="$3"
|
||||
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_check_hostfake()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ttls attls f fake fooling
|
||||
|
||||
[ "$need_hostfakesplit" = 0 ] && return 0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_hostfake_vary $testf $domain "ip${IPVV}_ttl=$ttl" "$pre" "$f" && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
[ "$ok" = 1 ] && break
|
||||
done
|
||||
for fooling in $FOOLINGS_TCP; do
|
||||
pktws_hostfake_vary $testf $domain "$fooling" "$pre" && ok=1
|
||||
done
|
||||
for ttl in $attls; do
|
||||
for f in '' "--payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip${IPVV}_ttl=1"; do
|
||||
pktws_hostfake_vary $testf $domain "ip${IPVV}_autottl=-$ttl,3-20" "$pre" "$f" && {
|
||||
ok=1
|
||||
[ "$SCANLEVEL" = force ] || break
|
||||
}
|
||||
done
|
||||
done
|
||||
[ "$ok" = 1 ]
|
||||
}
|
||||
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTP" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local PAYLOAD="--payload=http_req"
|
||||
local FAKE="$FAKE_HTTP"
|
||||
|
||||
if [ -n "$FAKE_HTTP" ]; then
|
||||
fake=bfake
|
||||
else
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
pktws_check_hostfake "$1" "$2"
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $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
|
||||
else
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
|
||||
pktws_check_hostfake "$1" "$2" "$3"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
28
blockcheck2.d/standard/90-quic.sh
Normal file
28
blockcheck2.d/standard/90-quic.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
pktws_check_http3()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_QUIC" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local repeats fake pos
|
||||
local PAYLOAD="--payload quic_initial"
|
||||
|
||||
if [ -n "$FAKE_QUIC" ]; then
|
||||
fake=fake_quic
|
||||
else
|
||||
fake=fake_default_quic
|
||||
fi
|
||||
|
||||
for repeats in 1 2 5 10 20; do
|
||||
pktws_curl_test_update $1 $2 ${FAKE_QUIC:+--blob=$fake:@"$FAKE_QUIC" }$PAYLOAD --lua-desync=fake:blob=$fake:repeats=$repeats && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
|
||||
for pos in 8 16 32 64; do
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:ipfrag:ipfrag_pos_udp=$pos --lua-desync=drop && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
|
||||
for pos in 8 16 32 64; do
|
||||
pktws_curl_test_update $1 $2 ${FAKE_QUIC:+--blob=$fake:@"$FAKE_QUIC" }$PAYLOAD --lua-desync=fake:blob=$fake:repeats=$FAKE_REPEATS --lua-desync=send:ipfrag:ipfrag_pos_udp=$pos --lua-desync=drop && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
}
|
||||
7
blockcheck2.d/standard/def.inc
Normal file
7
blockcheck2.d/standard/def.inc
Normal file
@@ -0,0 +1,7 @@
|
||||
FOOLINGS46_TCP=${FOOLINGS46_TCP:-"tcp_md5 badsum tcp_seq=-3000 tcp_seq=1000000 tcp_ack=-66000:tcp_ts_up tcp_ts=-1000 tcp_flags_unset=ACK tcp_flags_set=SYN"}
|
||||
FOOLINGS6_TCP=${FOOLINGS6_TCP:-"ip6_hopbyhop ip6_hopbyhop:ip6_hopbyhop2 ip6_destopt ip6_routing ip6_ah"}
|
||||
FOOLINGS_TCP="$FOOLINGS46_TCP"
|
||||
[ "$IPV" = 6 ] && FOOLINGS_TCP="$FOOLINGS_TCP $FOOLINGS6_TCP"
|
||||
FOOLINGS_UDP="badsum"
|
||||
|
||||
FAKE_REPEATS=${FAKE_REPEATS:-1}
|
||||
1906
blockcheck2.sh
Executable file
1906
blockcheck2.sh
Executable file
File diff suppressed because it is too large
Load Diff
@@ -105,6 +105,10 @@ split_by_separator()
|
||||
[ -n "$3" ] && eval $3="\$before"
|
||||
[ -n "$4" ] && eval $4="\$after"
|
||||
}
|
||||
tolower()
|
||||
{
|
||||
echo "$@" | tr 'A-Z' 'a-z'
|
||||
}
|
||||
|
||||
dir_is_not_empty()
|
||||
{
|
||||
|
||||
58
common/dialog.sh
Normal file
58
common/dialog.sh
Normal file
@@ -0,0 +1,58 @@
|
||||
read_yes_no()
|
||||
{
|
||||
# $1 - default (Y/N)
|
||||
local A
|
||||
read A
|
||||
[ -z "$A" ] || ([ "$A" != "Y" ] && [ "$A" != "y" ] && [ "$A" != "N" ] && [ "$A" != "n" ]) && A=$1
|
||||
[ "$A" = "Y" ] || [ "$A" = "y" ] || [ "$A" = "1" ]
|
||||
}
|
||||
ask_yes_no()
|
||||
{
|
||||
# $1 - default (Y/N or 0/1)
|
||||
# $2 - text
|
||||
local DEFAULT=$1
|
||||
[ "$1" = "1" ] && DEFAULT=Y
|
||||
[ "$1" = "0" ] && DEFAULT=N
|
||||
[ -z "$DEFAULT" ] && DEFAULT=N
|
||||
printf "$2 (default : $DEFAULT) (Y/N) ? "
|
||||
read_yes_no $DEFAULT
|
||||
}
|
||||
ask_yes_no_var()
|
||||
{
|
||||
# $1 - variable name for answer : 0/1
|
||||
# $2 - text
|
||||
local DEFAULT
|
||||
eval DEFAULT="\$$1"
|
||||
if ask_yes_no "$DEFAULT" "$2"; then
|
||||
eval $1=1
|
||||
else
|
||||
eval $1=0
|
||||
fi
|
||||
}
|
||||
ask_list()
|
||||
{
|
||||
# $1 - mode var
|
||||
# $2 - space separated value list
|
||||
# $3 - (optional) default value
|
||||
local M_DEFAULT
|
||||
eval M_DEFAULT="\$$1"
|
||||
local M_ALL=$M_DEFAULT
|
||||
local M=""
|
||||
local m
|
||||
|
||||
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;}
|
||||
|
||||
n=1
|
||||
for m in $2; do
|
||||
echo $n : $m
|
||||
n=$(($n+1))
|
||||
done
|
||||
printf "your choice (default : $M_DEFAULT) : "
|
||||
read m
|
||||
[ -n "$m" ] && M=$(echo $2 | cut -d ' ' -f$m 2>/dev/null)
|
||||
[ -z "$M" ] && M="$M_DEFAULT"
|
||||
echo selected : $M
|
||||
eval $1="\"$M\""
|
||||
|
||||
[ "$M" != "$M_OLD" ]
|
||||
}
|
||||
28
common/elevate.sh
Normal file
28
common/elevate.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
require_root()
|
||||
{
|
||||
local exe preserve_env
|
||||
echo \* checking privileges
|
||||
[ $(id -u) -ne "0" ] && {
|
||||
echo root is required
|
||||
exe="$EXEDIR/$(basename "$0")"
|
||||
exists sudo && {
|
||||
echo elevating with sudo
|
||||
exec sudo -E sh "$exe"
|
||||
}
|
||||
exists su && {
|
||||
echo elevating with su
|
||||
case "$UNAME" in
|
||||
Linux)
|
||||
preserve_env="--preserve-environment"
|
||||
;;
|
||||
FreeBSD|OpenBSD|Darwin)
|
||||
preserve_env="-m"
|
||||
;;
|
||||
esac
|
||||
exec su $preserve_env root -c "sh \"$exe\""
|
||||
}
|
||||
echo su or sudo not found
|
||||
exitp 2
|
||||
}
|
||||
HAVE_ROOT=1
|
||||
}
|
||||
64
common/fwtype.sh
Normal file
64
common/fwtype.sh
Normal file
@@ -0,0 +1,64 @@
|
||||
linux_ipt_avail()
|
||||
{
|
||||
exists iptables && exists ip6tables
|
||||
}
|
||||
linux_maybe_iptables_fwtype()
|
||||
{
|
||||
linux_ipt_avail && FWTYPE=iptables
|
||||
}
|
||||
linux_nft_avail()
|
||||
{
|
||||
exists nft
|
||||
}
|
||||
linux_fwtype()
|
||||
{
|
||||
[ -n "$FWTYPE" ] && return
|
||||
|
||||
FWTYPE=unsupported
|
||||
|
||||
linux_get_subsys
|
||||
if [ "$SUBSYS" = openwrt ] ; then
|
||||
# linux kernel is new enough if fw4 is there
|
||||
if [ -x /sbin/fw4 ] && linux_nft_avail ; then
|
||||
FWTYPE=nftables
|
||||
else
|
||||
linux_maybe_iptables_fwtype
|
||||
fi
|
||||
else
|
||||
SUBSYS=
|
||||
# generic linux
|
||||
# flowtable is implemented since kernel 4.16
|
||||
if linux_nft_avail && linux_min_version 4 16; then
|
||||
FWTYPE=nftables
|
||||
else
|
||||
linux_maybe_iptables_fwtype
|
||||
fi
|
||||
fi
|
||||
|
||||
export FWTYPE
|
||||
}
|
||||
|
||||
get_fwtype()
|
||||
{
|
||||
[ -n "$FWTYPE" ] && return
|
||||
|
||||
local UNAME="$(uname)"
|
||||
|
||||
case "$UNAME" in
|
||||
Linux)
|
||||
linux_fwtype
|
||||
;;
|
||||
FreeBSD)
|
||||
if exists ipfw ; then
|
||||
FWTYPE=ipfw
|
||||
else
|
||||
FWTYPE=unsupported
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
FWTYPE=unsupported
|
||||
;;
|
||||
esac
|
||||
|
||||
export FWTYPE
|
||||
}
|
||||
39
common/virt.sh
Normal file
39
common/virt.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
get_virt()
|
||||
{
|
||||
local vm s v UNAME
|
||||
UNAME=$(uname)
|
||||
case "$UNAME" in
|
||||
Linux)
|
||||
if exists systemd-detect-virt; then
|
||||
vm=$(systemd-detect-virt --vm)
|
||||
elif [ -f /sys/class/dmi/id/product_name ]; then
|
||||
read s </sys/class/dmi/id/product_name
|
||||
for v in KVM QEMU VMware VMW VirtualBox Xen Bochs Parallels BHYVE Hyper-V; do
|
||||
case "$s" in
|
||||
"$v"*)
|
||||
vm=$v
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
echo "$vm" | awk '{print tolower($0)}'
|
||||
}
|
||||
check_virt()
|
||||
{
|
||||
echo \* checking virtualization
|
||||
local vm="$(get_virt)"
|
||||
if [ -n "$vm" ]; then
|
||||
if [ "$vm" = "none" ]; then
|
||||
echo running on bare metal
|
||||
else
|
||||
echo "!!! WARNING. $vm virtualization detected !!!"
|
||||
echo '!!! WARNING. vmware and virtualbox are known to break most of the DPI bypass techniques when network is NATed using internal hypervisor NAT !!!'
|
||||
echo '!!! WARNING. if this is your case make sure you are bridged not NATed !!!'
|
||||
fi
|
||||
else
|
||||
echo cannot detect
|
||||
fi
|
||||
}
|
||||
123
config.default
Normal file
123
config.default
Normal file
@@ -0,0 +1,123 @@
|
||||
# this file is included from init scripts
|
||||
# change values here
|
||||
|
||||
# can help in case /tmp has not enough space
|
||||
#TMPDIR=/opt/zapret/tmp
|
||||
|
||||
# redefine user for zapret daemons. required on Keenetic
|
||||
#WS_USER=nobody
|
||||
|
||||
# override firewall type : iptables,nftables,ipfw
|
||||
#FWTYPE=iptables
|
||||
# nftables only : set this to 0 to use pre-nat mode. default is post-nat.
|
||||
# pre-nat mode disables some bypass techniques for forwarded traffic but allows to see client IP addresses in debug log
|
||||
#POSTNAT=0
|
||||
|
||||
# options for ipsets
|
||||
# maximum number of elements in sets. also used for nft sets
|
||||
SET_MAXELEM=522288
|
||||
# too low hashsize can cause memory allocation errors on low RAM systems , even if RAM is enough
|
||||
# too large hashsize will waste lots of RAM
|
||||
IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
|
||||
# dynamically generate additional ip. $1 = ipset/nfset/table name
|
||||
#IPSET_HOOK="/etc/zapret.ipset.hook"
|
||||
|
||||
# options for ip2net. "-4" or "-6" auto added by ipset create script
|
||||
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
|
||||
IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
|
||||
# options for auto hostlist
|
||||
AUTOHOSTLIST_RETRANS_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_TIME=60
|
||||
# 1 = debug autohostlist positives to ipset/zapret-hosts-auto-debug.log
|
||||
AUTOHOSTLIST_DEBUGLOG=0
|
||||
|
||||
# number of parallel threads for domain list resolves
|
||||
MDIG_THREADS=30
|
||||
|
||||
# ipset/*.sh can compress large lists
|
||||
GZIP_LISTS=1
|
||||
# command to reload ip/host lists after update
|
||||
# comment or leave empty for auto backend selection : ipset or ipfw if present
|
||||
# on BSD systems with PF no auto reloading happens. you must provide your own command
|
||||
# set to "-" to disable reload
|
||||
#LISTS_RELOAD="pfctl -f /etc/pf.conf"
|
||||
|
||||
# mark bit used by nfqws to prevent loop
|
||||
DESYNC_MARK=0x40000000
|
||||
DESYNC_MARK_POSTNAT=0x20000000
|
||||
|
||||
# do not pass outgoing traffic to tpws/nfqws not marked with this bit
|
||||
# this setting allows to write your own rules to limit traffic that should be fooled
|
||||
# for example based on source IP or incoming interface name
|
||||
# no filter if not defined
|
||||
#FILTER_MARK=0x10000000
|
||||
|
||||
|
||||
NFQWS2_ENABLE=0
|
||||
# redirect outgoing traffic with connbytes limiter applied in both directions.
|
||||
NFQWS2_PORTS_TCP=80,443
|
||||
NFQWS2_PORTS_UDP=443
|
||||
# PKT_OUT means connbytes dir original
|
||||
# PKT_IN means connbytes dir reply
|
||||
# this is --dpi-desync-cutoff=nX kernel mode implementation for linux. it saves a lot of CPU.
|
||||
NFQWS2_TCP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||||
NFQWS2_TCP_PKT_IN=3
|
||||
NFQWS2_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||||
NFQWS2_UDP_PKT_IN=0
|
||||
# redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter
|
||||
# normally it's needed only for stateless DPI that matches every packet in a single TCP session
|
||||
# typical example are plain HTTP keep alives
|
||||
# this mode can be very CPU consuming. enable with care !
|
||||
#NFQWS2_PORTS_TCP_KEEPALIVE=80
|
||||
#NFQWS2_PORTS_UDP_KEEPALIVE=
|
||||
# use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir
|
||||
# hostlist markers are replaced to empty string if MODE_FILTER does not satisfy
|
||||
# <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list
|
||||
NFQWS2_OPT="
|
||||
--filter-tcp=80 --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_md5 --lua-desync=multisplit:pos=method+2 <HOSTLIST> --new
|
||||
--filter-tcp=443 --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_md5:tcp_seq=-10000 --lua-desync=multidisorder:pos=1,midsld <HOSTLIST> --new
|
||||
--filter-udp=443 --payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=6 <HOSTLIST_NOAUTO> --new
|
||||
"
|
||||
|
||||
# none,ipset,hostlist,autohostlist
|
||||
MODE_FILTER=none
|
||||
|
||||
# donttouch,none,software,hardware
|
||||
FLOWOFFLOAD=donttouch
|
||||
|
||||
# openwrt: specify networks to be treated as WAN. default wans are interfaces with default route
|
||||
#OPENWRT_WAN4="wan vpn"
|
||||
#OPENWRT_WAN6="wan6 vpn6"
|
||||
|
||||
# for routers based on desktop linux and macos. has no effect in openwrt.
|
||||
# optionally CHOOSE WAN/WAN6 NETWORK INTERFACES
|
||||
# or leave them commented if its not router
|
||||
# it's possible to specify multiple interfaces like this : IFACE_WAN="eth0 eth1 eth2"
|
||||
# if IFACE_WAN6 is not defined it take the value of IFACE_WAN
|
||||
#IFACE_WAN=eth1
|
||||
#IFACE_WAN6="ipsec0 wireguard0 he_net"
|
||||
|
||||
# should start/stop command of init scripts apply firewall rules ?
|
||||
# not applicable to openwrt with firewall3+iptables
|
||||
INIT_APPLY_FW=1
|
||||
# firewall apply hooks
|
||||
#INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret.hook.pre_up"
|
||||
#INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up"
|
||||
#INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret.hook.pre_down"
|
||||
#INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret.hook.post_down"
|
||||
|
||||
# do not work with ipv4
|
||||
#DISABLE_IPV4=1
|
||||
# do not work with ipv6
|
||||
DISABLE_IPV6=1
|
||||
|
||||
# drop icmp time exceeded messages for nfqws tampered connections
|
||||
# in POSTNAT mode this can interfere with default mtr/traceroute in tcp or udp mode. use source port not redirected to nfqws
|
||||
# set to 0 if you are not expecting connection breakage due to icmp in response to TCP SYN or UDP
|
||||
FILTER_TTL_EXPIRED_ICMP=1
|
||||
|
||||
# select which init script will be used to get ip or host list
|
||||
# possible values : get_user.sh get_antizapret.sh get_combined.sh get_reestr.sh get_hostlist.sh
|
||||
# comment if not required
|
||||
#GETLIST=
|
||||
@@ -12,3 +12,25 @@ v0.1.2
|
||||
* nfqws2: 'known' protocol and payload filter
|
||||
* nfqws2: 'aes_ctr' luacall
|
||||
* zapret-antidpi: rst
|
||||
* github actions: remove FFI from luajit
|
||||
|
||||
v0.1.4
|
||||
|
||||
* winws2: set low mandatory level in process token if possible : no --wlan-filter or --nlm-filter (no windivert reinit required)
|
||||
* nfqws2: optimize debug logging to file
|
||||
|
||||
v0.1.5
|
||||
|
||||
* nfqws2: # and % arg substitution
|
||||
* zapret-antidpi: luaexec
|
||||
* zapret-pcap: simple packet capture to .cap file
|
||||
|
||||
v0.2
|
||||
|
||||
* blockcheck2
|
||||
* nfqws2: several crash fixes
|
||||
* nfqws2: bu8,bu16,bu24,bu32,swap16,swap32 functions now work with negative int
|
||||
* nfqws2: getpid,gettid,uname,get_clock luacalls
|
||||
* zapret-lib: bugfixes
|
||||
* zapret-lib: remove ip6_hopbyhop_x2 fooling, separately add second hopbyhop header using ip6_hopbyhop2
|
||||
* zapret-pcap
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# zapret2 v0.1
|
||||
# zapret2 v0.2
|
||||
|
||||
## Зачем это нужно
|
||||
|
||||
@@ -115,10 +115,10 @@ nfqws --qnum 200 --debug \
|
||||
Конкретный вызов `--lua-desync` функции называется инстансом. Инстанс - это связка имени функции, номера вызова внутри профиля и номера самого профиля.
|
||||
Это похоже на одну программу, которую можно запустить много раз с разными параметрами.
|
||||
|
||||
Другое немаловажное отличие - поддержка автоматической tcp сегментации. Вам больше не нужно думать о размерах отсылаемых tcp пакетов.
|
||||
Другое немаловажное отличие - поддержка автоматической tcp сегментации средствами `zapret-lib.lua`. Вам больше не нужно думать о размерах отсылаемых tcp пакетов.
|
||||
По каждому соединению отслеживается MSS. Если пакет не влезает в MSS, выполняется сегментация.
|
||||
Например, это может случиться при отправке tls фейка с kyber. Или если вы режете kyber tls так, что одна из частей получается размером 1600 байт,
|
||||
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. В *nfqws2* будет отправлено
|
||||
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. Функция LUA `rawsend_dissect_segmented` отправит
|
||||
несколько tcp сегментов с начальным sequence -10000 общим размером 10000 байт, в последнем из которых будет кусок оригинального сообщения.
|
||||
|
||||
В *nfqws2* нет жестко зашитых параметров кастомных фейков типа `--dpi-desync-fake-tls`, `dpi-desync-fake-http` и тд.
|
||||
@@ -365,6 +365,37 @@ start "zapret: http,https,quic" /min "%~dp0winws2.exe" ^
|
||||
--lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2
|
||||
```
|
||||
|
||||
И напоследок стоит продемонстрировать как делаются нестандартные вещи. То, что очень непросто запрограммировать в чисто описательном виде
|
||||
в фиксированном коде, не превращая программу в монстро-комбайн, перегруженный частными функциями и разваливающийся под своей тяжестью со временем,
|
||||
когда эти частные функции перестают быть нужны и забываются.
|
||||
|
||||
Надо послать исходный запрос с известным пейлоадом с seqovl случайного размера от 5 до 10 символов со случайным содержимым, состоящим из букв от ‘a’ до ‘z’.
|
||||
Здесь раскрывается не декларативный характер стратегий, а алгоритмический. Стратегия - это программа, и пишите ее вы на языке программирования.
|
||||
Для облегчения простых или стандартных действий есть готовые средства, так что далеко не всегда надо писать свою функцию.
|
||||
Частенько можно обойтись простенькими кусками LUA кода в дополнение к имеющимся.
|
||||
|
||||
Здесь используется функция `luaexec`, предназначенная для динамического выполнения LUA кода в процессе обработки текущего диссекта.
|
||||
Она инициализирует требуемый blob, записывая его в таблицу desync, которая передается от инстанса к инстансу.
|
||||
Следующий инстанс `tcpseg` использует `rnd` как blob - источник seqovl паттерна.
|
||||
|
||||
Символы `%` и `#` используются для разименования блобов и подстановки их размера соответственно. Реализовано на уровне C кода.
|
||||
desync функция получает уже подставленные значения. В данном случае seqovl устанавливается как размер сгенерированного блоба.
|
||||
|
||||
Функция `tcpseg` предназначена для отсылки tcp сегмента - части текущего пейлоада (или реасма - сборки нескольких пакетов, например в случае tls kyber).
|
||||
`pos=0,-1` - это диапазон, состоящий из двух маркеров - начала и конца. 0 - положительный абсолютный маркер, соответствующий началу пакета.
|
||||
-1 - отрицательный абсолютный маркер, соответствующий концу пакета. Получается, мы отсылаем целиком текущий пейлоад, но с seqovl.
|
||||
`tcpseg` не дропает пакет. Его надо дропнуть отдельно. По умолчанию `tcpseg` работает только с известными пейлоадами, а функция `drop` - с любыми.
|
||||
Поэтому нужно ей указать дропать только известные пейлоады.
|
||||
|
||||
Такая связка из 3 инстансов решает поставленную задачу без кучи частных параметров вида `--dpi-desync...`.
|
||||
|
||||
```
|
||||
nfqws2 \
|
||||
--lua-desync=luaexec:code='desync.rnd=brandom_az(math.random(5,10))' \
|
||||
--lua-desync=tcpseg:pos=0,-1:seqovl=#rnd:seqovl_pattern=rnd \
|
||||
--lua-desync=drop:payload=known
|
||||
```
|
||||
|
||||
### Какие есть еще параметры
|
||||
|
||||
Как узнать какие есть еще функции и какие у них бывают параметры ? Смотрите `zapret-antidpi.lua`. Перед каждой функцией подробно описано какие параметры она берет.
|
||||
|
||||
@@ -25,8 +25,9 @@ standard fooling :
|
||||
* ip6_autottl=delta,min-max - set ip.ip_ttl to auto discovered ttl
|
||||
|
||||
* ip6_hopbyhop[=hex] - add hopbyhop ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
* ip6_hopbyhop2[=hex] - add 2 hopbyhop ipv6 headers with optional data. data size must be 6+N*8. all zero by default.
|
||||
* ip6_hopbyhop2[=hex] - add second hopbyhop ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
* ip6_destopt[=hex] - add destopt ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
* ip6_destopt2[=hex] - add second destopt ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
* ip6_routing[=hex] - add routing ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
* ip6_ah[=hex] - add authentication ipv6 header with optional data. data size must be 6+N*4. 0000 + 4 random bytes by default.
|
||||
|
||||
@@ -35,7 +36,7 @@ standard fooling :
|
||||
* tcp_ts=N - add N to timestamp value
|
||||
* tcp_md5[=hex] - add MD5 header with optional 16-byte data. all zero by default.
|
||||
* tcp_flags_set=<list> - set tcp flags in comma separated list
|
||||
* tcp_unflags_set=<list> - unset 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)
|
||||
|
||||
* fool=fool_function - custom fooling function : fool_func(dis, fooling_options)
|
||||
@@ -70,18 +71,6 @@ standard ipfrag :
|
||||
]]
|
||||
|
||||
|
||||
-- dummy test function. does nothing.
|
||||
-- no args
|
||||
function pass(ctx, desync)
|
||||
DLOG("pass")
|
||||
end
|
||||
|
||||
-- prints desync to DLOG
|
||||
function pktdebug(ctx, desync)
|
||||
DLOG("desync:")
|
||||
var_debug(desync)
|
||||
end
|
||||
|
||||
-- drop packet
|
||||
-- standard args : direction, payload
|
||||
function drop(ctx, desync)
|
||||
@@ -378,6 +367,8 @@ end
|
||||
-- arg : pos=<posmarker list> . position marker list. for example : "1,host,midsld+1,-10"
|
||||
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
|
||||
-- arg : seqovl_pattern=<blob> . override pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function multisplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
@@ -385,7 +376,7 @@ function multisplit(ctx, desync)
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
local spos = desync.arg.pos or "2"
|
||||
@@ -411,7 +402,7 @@ function multisplit(ctx, desync)
|
||||
end
|
||||
end
|
||||
replay_drop_set(desync)
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
else
|
||||
DLOG("multisplit: no valid split positions")
|
||||
end
|
||||
@@ -420,7 +411,7 @@ function multisplit(ctx, desync)
|
||||
end
|
||||
-- drop replayed packets if reasm was sent successfully in splitted form
|
||||
if replay_drop(desync) then
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -430,6 +421,8 @@ end
|
||||
-- arg : pos=<postmarker list> . position marker list. example : "1,host,midsld+1,-10"
|
||||
-- arg : seqovl=N . decrease seq number of the second segment in the original order by N and fill N bytes with pattern (default - all zero). N must be less than the first split pos.
|
||||
-- arg : seqovl_pattern=<blob> . override pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function multidisorder(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
@@ -437,7 +430,7 @@ function multidisorder(ctx, desync)
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
local spos = desync.arg.pos or "2"
|
||||
@@ -474,7 +467,7 @@ function multidisorder(ctx, desync)
|
||||
end
|
||||
end
|
||||
replay_drop_set(desync)
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
else
|
||||
DLOG("multidisorder: no valid split positions")
|
||||
end
|
||||
@@ -483,7 +476,7 @@ function multidisorder(ctx, desync)
|
||||
end
|
||||
-- drop replayed packets if reasm was sent successfully in splitted form
|
||||
if replay_drop(desync) then
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -494,6 +487,8 @@ end
|
||||
-- arg : midhost=<posmarker> - additionally split segment containing host at specified posmarker. must be within host+1 .. endhost-1 or split won't happen. example : "midsld"
|
||||
-- arg : nofake1, nofake2 - do not send individual fakes
|
||||
-- arg : disorder_after=<posmarker> - send after_host part in 2 disordered segments. if posmarker is empty string use marker "-1"
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function hostfakesplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
@@ -501,7 +496,7 @@ function hostfakesplit(ctx, desync)
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
local pos = resolve_range(data, desync.l7payload, "host,endhost-1", true)
|
||||
@@ -584,7 +579,7 @@ function hostfakesplit(ctx, desync)
|
||||
if not rawsend_payload_segmented(desync,part,pos[2], opts_orig) then return VERDICT_PASS end
|
||||
|
||||
replay_drop_set(desync)
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
else
|
||||
DLOG("hostfakesplit: host range cannot be resolved")
|
||||
end
|
||||
@@ -593,7 +588,7 @@ function hostfakesplit(ctx, desync)
|
||||
end
|
||||
-- drop replayed packets if reasm was sent successfully in splitted form
|
||||
if replay_drop(desync) then
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -605,6 +600,8 @@ end
|
||||
-- arg : pattern=<blob> . fill fake parts with this pattern
|
||||
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
|
||||
-- arg : seqovl_pattern=<blob> . override seqovl pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function fakedsplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
@@ -612,7 +609,7 @@ function fakedsplit(ctx, desync)
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
local spos = desync.arg.pos or "2"
|
||||
@@ -674,7 +671,7 @@ function fakedsplit(ctx, desync)
|
||||
end
|
||||
|
||||
replay_drop_set(desync)
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
end
|
||||
else
|
||||
DLOG("fakedsplit: cannot resolve pos '"..desync.arg.pos.."'")
|
||||
@@ -684,7 +681,7 @@ function fakedsplit(ctx, desync)
|
||||
end
|
||||
-- drop replayed packets if reasm was sent successfully in splitted form
|
||||
if replay_drop(desync) then
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -696,6 +693,8 @@ end
|
||||
-- arg : pattern=<blob> . fill fake parts with this pattern
|
||||
-- arg : seqovl=N . decrease seq number of the second segment by N and fill N bytes with pattern (default - all zero). N must be less than the split pos.
|
||||
-- arg : seqovl_pattern=<blob> . override seqovl pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function fakeddisorder(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
@@ -703,7 +702,7 @@ function fakeddisorder(ctx, desync)
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
local spos = desync.arg.pos or "2"
|
||||
@@ -775,7 +774,7 @@ function fakeddisorder(ctx, desync)
|
||||
end
|
||||
|
||||
replay_drop_set(desync)
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
end
|
||||
else
|
||||
DLOG("fakeddisorder: cannot resolve pos '"..desync.arg.pos.."'")
|
||||
@@ -785,7 +784,7 @@ function fakeddisorder(ctx, desync)
|
||||
end
|
||||
-- drop replayed packets if reasm was sent successfully in splitted form
|
||||
if replay_drop(desync) then
|
||||
return VERDICT_DROP
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -795,6 +794,7 @@ end
|
||||
-- arg : pos=<postmarker list> . position marker list. 2 pos required, only 2 first pos used. example : "host,endhost"
|
||||
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
|
||||
-- arg : seqovl_pattern=<blob> . override pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
function tcpseg(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
@@ -805,7 +805,7 @@ function tcpseg(ctx, desync)
|
||||
error("tcpseg: no pos specified")
|
||||
end
|
||||
-- by default process only outgoing known payloads
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
if b_debug then DLOG("tcpseg: pos: "..desync.arg.pos) end
|
||||
|
||||
@@ -3,6 +3,41 @@ NOT3=bitnot(3)
|
||||
NOT7=bitnot(7)
|
||||
math.randomseed(os.time())
|
||||
|
||||
|
||||
-- basic desync function
|
||||
-- execute given lua code. "desync" is temporary set as global var to be accessible to the code
|
||||
-- useful for simple fast actions without writing a func
|
||||
-- arg: code=<lua_code>
|
||||
function luaexec(ctx, desync)
|
||||
if not desync.arg.code then
|
||||
error("luaexec: no 'code' parameter")
|
||||
end
|
||||
local fname = desync.func_instance.."_luaexec_code"
|
||||
if not _G[fname] then
|
||||
_G[fname] = load(desync.arg.code, fname)
|
||||
end
|
||||
-- allow dynamic code to access desync
|
||||
_G.desync = desync
|
||||
_G[fname]()
|
||||
_G.desync = nil
|
||||
end
|
||||
|
||||
-- basic desync function
|
||||
-- does nothing just acknowledges when it's called
|
||||
-- no args
|
||||
function pass(ctx, desync)
|
||||
DLOG("pass")
|
||||
end
|
||||
|
||||
-- basic desync function
|
||||
-- prints desync to DLOG
|
||||
function pktdebug(ctx, desync)
|
||||
DLOG("desync:")
|
||||
var_debug(desync)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- prepare standard rawsend options from desync
|
||||
-- repeats - how many time send the packet
|
||||
-- ifout - override outbound interface (if --bind_fix4, --bind-fix6 enabled)
|
||||
@@ -163,6 +198,9 @@ function blob(desync, name, def)
|
||||
end
|
||||
return blob
|
||||
end
|
||||
function blob_or_def(desync, name, def)
|
||||
return name and blob(desync,name,def) or def
|
||||
end
|
||||
|
||||
-- repeat pattern as needed to extract part of it with any length
|
||||
-- pat="12345" len=10 offset=4 => "4512345123"
|
||||
@@ -413,7 +451,7 @@ end
|
||||
-- ip6_autottl=delta,min-max - set ip.ip_ttl to auto discovered ttl
|
||||
|
||||
-- ip6_hopbyhop[=hex] - add hopbyhop ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_hopbyhop2 - add 2 hopbyhop ipv6 headers with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_hopbyhop2[=hex] - add second hopbyhop ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_destopt[=hex] - add destopt ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_routing[=hex] - add routing ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_ah[=hex] - add authentication ipv6 header with optional data. data size must be 6+N*4. 0000 + 4 random bytes by default.
|
||||
@@ -423,7 +461,7 @@ end
|
||||
-- tcp_ts=N - add N to timestamp value
|
||||
-- tcp_md5[=hex] - add MD5 header with optional 16-byte data. all zero by default.
|
||||
-- tcp_flags_set=<list> - set tcp flags in comma separated list
|
||||
-- tcp_unflags_set=<list> - unset 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.
|
||||
|
||||
-- fool - custom fooling function : fool_func(dis, fooling_options)
|
||||
@@ -459,6 +497,7 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
if not ttl and tonumber(arg_ttl) then
|
||||
ttl = tonumber(arg_ttl)
|
||||
end
|
||||
--io.stderr:write("TTL "..tostring(ttl).."\n")
|
||||
return ttl
|
||||
end
|
||||
local function move_ts_top()
|
||||
@@ -506,14 +545,14 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
end
|
||||
if dis.ip6 then
|
||||
local bin
|
||||
if fooling_options.ip6_hopbyhop_x2 then
|
||||
bin = prepare_bin(fooling_options.ip6_hopbyhop2_x2,"\x00\x00\x00\x00\x00\x00")
|
||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
||||
elseif fooling_options.ip6_hopbyhop then
|
||||
if fooling_options.ip6_hopbyhop then
|
||||
bin = prepare_bin(fooling_options.ip6_hopbyhop,"\x00\x00\x00\x00\x00\x00")
|
||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
||||
end
|
||||
if fooling_options.ip6_hopbyhop2 then
|
||||
bin = prepare_bin(fooling_options.ip6_hopbyhop2,"\x00\x00\x00\x00\x00\x00")
|
||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
||||
end
|
||||
-- for possible unfragmentable part
|
||||
if fooling_options.ip6_destopt then
|
||||
bin = prepare_bin(fooling_options.ip6_destopt,"\x00\x00\x00\x00\x00\x00")
|
||||
@@ -666,6 +705,7 @@ function packet_len(dis)
|
||||
return l3l4_len(dis) + #dis.payload
|
||||
end
|
||||
|
||||
-- option : ipfrag.ipfrag_disorder - send fragments from last to first
|
||||
function rawsend_dissect_ipfrag(dis, options)
|
||||
if options and options.ipfrag and options.ipfrag.ipfrag then
|
||||
local frag_func = options.ipfrag.ipfrag=="" and "ipfrag2" or options.ipfrag.ipfrag
|
||||
@@ -708,17 +748,18 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
apply_fooling(desync, discopy, options and options.fooling)
|
||||
|
||||
if dis.tcp then
|
||||
local extra_len = l3l4_extra_len(dis)
|
||||
local extra_len = l3l4_extra_len(discopy)
|
||||
if extra_len >= mss then return false end
|
||||
local max_data = mss - extra_len
|
||||
if #discopy.payload > max_data then
|
||||
local pos=1
|
||||
local len
|
||||
local payload=discopy.payload
|
||||
|
||||
while pos <= #dis.payload do
|
||||
len = #dis.payload - pos + 1
|
||||
while pos <= #payload do
|
||||
len = #payload - pos + 1
|
||||
if len > max_data then len = max_data end
|
||||
discopy.payload = string.sub(dis.payload,pos,pos+len-1)
|
||||
discopy.payload = string.sub(payload,pos,pos+len-1)
|
||||
if not rawsend_dissect_ipfrag(discopy, options) then
|
||||
-- stop if failed
|
||||
return false
|
||||
@@ -842,6 +883,20 @@ function genhost(len, template)
|
||||
end
|
||||
end
|
||||
|
||||
function is_absolute_path(path)
|
||||
if string.sub(path,1,1)=='/' then return true end
|
||||
local un = uname()
|
||||
return string.sub(un.sysname,1,6)=="CYGWIN" and string.sub(path,2,2)==':'
|
||||
end
|
||||
function append_path(path,file)
|
||||
return string.sub(path,#path,#path)=='/' and path..file or path.."/"..file
|
||||
end
|
||||
function writeable_file_name(filename)
|
||||
if is_absolute_path(filename) then return filename end
|
||||
local writedir = os.getenv("WRITEABLE")
|
||||
if not writedir then return filename end
|
||||
return append_path(writedir, filename)
|
||||
end
|
||||
|
||||
-- arg : wsize=N . tcp window size
|
||||
-- arg : scale=N . tcp option scale factor
|
||||
@@ -876,7 +931,6 @@ end
|
||||
-- option : ipfrag_pos_udp - udp frag position. ipv4 : starting from L4 header. ipb6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
-- option : ipfrag_pos_tcp - tcp frag position. ipv4 : starting from L4 header. ipb6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
-- option : ipfrag_next - next protocol field in ipv6 fragment extenstion header of the second fragment. same as first by default.
|
||||
-- option : ipfrag_disorder - send fragments from last to first
|
||||
function ipfrag2(dis, ipfrag_options)
|
||||
local function frag_idx(exthdr)
|
||||
-- fragment header after hopbyhop, destopt, routing
|
||||
|
||||
39
lua/zapret-pcap.lua
Normal file
39
lua/zapret-pcap.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
function pcap_write_header(file)
|
||||
-- big endian, nanoseconds in timestamps, ver 2.4, max packet size - 0x4000 (16384), 0x65 - l3 packets without l2
|
||||
file:write("\xA1\xB2\x3C\x4D\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x65")
|
||||
end
|
||||
function pcap_write_packet(file, raw)
|
||||
local sec, nsec = clock_gettime();
|
||||
file:write(bu32(sec)..bu32(nsec)..bu32(#raw)..bu32(#raw))
|
||||
file:write(raw)
|
||||
file:close()
|
||||
end
|
||||
function pcap_write(file, raw)
|
||||
local pos = file:seek()
|
||||
if (pos==0) then
|
||||
pcap_write_header(file)
|
||||
end
|
||||
pcap_write_packet(file, raw)
|
||||
end
|
||||
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-pcap.lua --writeable=zdir --in-range=a --lua-desync=pcap:file=test.pcap
|
||||
-- arg : file=<filename> - file for storing pcap data. if --writeable is specified and filename is relative - append filename to writeable path
|
||||
-- arg : keep - do not overwrite file, append packets to existing
|
||||
function pcap(ctx, desync)
|
||||
if not desync.arg.file or #desync.arg.file==0 then
|
||||
error("pcap requires 'file' parameter")
|
||||
end
|
||||
local fn_cache_name = desync.func_instance.."_fn"
|
||||
if not _G[fn_cache_name] then
|
||||
_G[fn_cache_name] = writeable_file_name(desync.arg.file)
|
||||
if not desync.arg.keep then
|
||||
-- overwrite file
|
||||
os.remove(_G[fn_cache_name])
|
||||
end
|
||||
end
|
||||
local f = io.open(_G[fn_cache_name], "a")
|
||||
if not f then
|
||||
error("pcap: could not write to '".._G[fn_cache_name].."'")
|
||||
end
|
||||
pcap_write(f, raw_packet(ctx))
|
||||
end
|
||||
@@ -5,20 +5,20 @@ function test_assert(b)
|
||||
assert(b, "test failed")
|
||||
end
|
||||
|
||||
function test_run(tests)
|
||||
function test_run(tests,...)
|
||||
for k,f in pairs(tests) do
|
||||
f()
|
||||
f(...)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function test_all()
|
||||
test_run({test_crypto, test_bin, test_ipstr, test_dissect, test_csum, test_resolve, test_rawsend})
|
||||
function test_all(...)
|
||||
test_run({test_crypto, test_bin, test_ipstr, test_dissect, test_csum, test_resolve, test_rawsend},...)
|
||||
end
|
||||
|
||||
|
||||
function test_crypto()
|
||||
test_run({test_random, test_aes, test_aes_gcm, test_aes_ctr, test_hkdf, test_hash})
|
||||
function test_crypto(...)
|
||||
test_run({test_random, test_aes, test_aes_gcm, test_aes_ctr, test_hkdf, test_hash},...)
|
||||
end
|
||||
|
||||
function test_random()
|
||||
@@ -211,19 +211,44 @@ function test_aes_ctr()
|
||||
test_assert(decrypted==clear_text)
|
||||
|
||||
print("* decrypting with bad key")
|
||||
decrypted = aes_ctr(bu8(u8(string.sub(key,1,1))+1)..string.sub(key,2), iv, encrypted)
|
||||
decrypted = aes_ctr(bu8(bitand(u8(string.sub(key,1,1))+1,0xFF))..string.sub(key,2), iv, encrypted)
|
||||
print("decrypted: "..str_or_hex(decrypted))
|
||||
print( decrypted==clear_text and "DECRYPT OK" or "DECRYPT ERROR" )
|
||||
test_assert(decrypted~=clear_text)
|
||||
|
||||
print("* decrypting with bad iv")
|
||||
decrypted = aes_ctr(key, bu8(u8(string.sub(iv,1,1))+1)..string.sub(iv,2), encrypted)
|
||||
decrypted = aes_ctr(key, bu8(bitand(u8(string.sub(iv,1,1))+1,0xFF))..string.sub(iv,2), encrypted)
|
||||
print("decrypted: "..str_or_hex(decrypted))
|
||||
print( decrypted==clear_text and "DECRYPT OK" or "DECRYPT ERROR" )
|
||||
test_assert(decrypted~=clear_text)
|
||||
end
|
||||
end
|
||||
|
||||
-- openssl enc -aes-256-ctr -d -in rnd.bin -out rnd_decrypted.bin -K c39383634d87eb3b6e56edf2c8c0ba99cc8cadf000fb2cd737e37947eecde5fd -iv d745164b233f10b93945526ffe94b87f
|
||||
print("* aes_ctr const tests")
|
||||
|
||||
local data="\x9d\x9c\xa0\x78\x2e\x17\x84\xfc\x87\xc7\xf5\xdf\x5b\xb5\x71\xfd\xb9\xcb\xd2\x4d\xae\x2f\xf0\x19\xf3\xad\x79\xa8\x9a\xb4\xed\x28\x88\x3c\xe1\x78\x91\x23\x27\xd4\x8d\x94\xb3\xd0\x81\x88\xd2\x55\x95\x8a\x88\x70\x67\x99\x75\xb2\xee\x30\x0f\xe7\xc6\x32\x10"
|
||||
local iv="\xd7\x45\x16\x4b\x23\x3f\x10\xb9\x39\x45\x52\x6f\xfe\x94\xb8\x7f"
|
||||
local tests = {
|
||||
{
|
||||
key="\xc3\x93\x83\x63\x4d\x87\xeb\x3b\x6e\x56\xed\xf2\xc8\xc0\xba\x99\xcc\x8c\xad\xf0\x00\xfb\x2c\xd7\x37\xe3\x79\x47\xee\xcd\xe5\xfd",
|
||||
result="\x8C\x2C\x15\x99\x83\x37\x33\xEE\xA1\x70\xA7\x4A\x44\x2E\x6F\x56\x22\x41\xE1\xFC\xC5\x84\x21\x1C\x16\xC6\xE9\x75\x22\x57\x55\x4A\x02\x04\xCE\xAD\xE9\x0A\x45\xAB\x4E\x38\xB8\xB2\x6F\x95\xDA\x46\x4F\x9E\xB1\xFF\xF4\x40\x8A\x57\x25\xD2\xF6\xB6\x93\x65\x75"
|
||||
},
|
||||
{
|
||||
key="\xc3\x93\x83\x63\x4d\x87\xeb\x3b\x6e\x56\xed\xf2\xc8\xc0\xba\x99\xcc\x8c\xad\xf0\x00\xfb\x2c\xd7",
|
||||
result="\xB0\x4C\xC9\xDB\x0C\xE5\x67\x51\x1D\x24\x3C\x15\x87\x1B\xF9\x62\x84\x8C\xD0\x57\x33\x93\xE0\x71\x91\x3A\x11\x26\xCA\x77\xA7\x54\xBD\xC6\x5E\x96\x60\x2C\x94\x0F\xBA\x3E\x79\xDC\x48\xA0\x22\x97\xA7\x77\x55\xC8\x14\xEA\xC2\xF5\xA0\x88\x6F\xE2\x44\x32\x68"
|
||||
},
|
||||
{
|
||||
key="\xc3\x93\x83\x63\x4d\x87\xeb\x3b\x6e\x56\xed\xf2\xc8\xc0\xba\x99",
|
||||
result="\xD9\xAC\xC7\x7D\xC8\xC9\xF1\x59\x9A\xDF\x15\xF3\x58\x61\xFD\x2B\x1D\x01\x9A\x5F\x04\x53\xA2\xA8\xFD\x52\xDC\x8A\xE9\x3B\x2E\x5E\x0D\x13\xCB\xBD\x16\xED\xC1\xF2\x0D\x68\x62\xB7\xD5\x0F\x8D\xD4\xEB\xA1\xC5\x75\xF2\x0B\x26\x75\x1D\x7E\x5A\x37\xA6\x8A\xCD"
|
||||
}
|
||||
}
|
||||
for k,t in pairs(tests) do
|
||||
local decrypted = aes_ctr(t.key, iv, data)
|
||||
io.write("KEY SIZE "..(#t.key*8).." ")
|
||||
print( decrypted==t.result and "DECRYPT OK" or "DECRYPT ERROR" )
|
||||
test_assert(decrypted==t.result)
|
||||
end
|
||||
end
|
||||
|
||||
function test_ub()
|
||||
for k,f in pairs({{u8,bu8,0xFF,8}, {u16,bu16,0xFFFF,16}, {u24,bu24,0xFFFFFF,24}, {u32,bu32,0xFFFFFFFF,32}}) do
|
||||
@@ -274,8 +299,8 @@ function test_bit()
|
||||
test_assert(v2==v3)
|
||||
end
|
||||
|
||||
function test_bin()
|
||||
test_run({test_ub, test_bit})
|
||||
function test_bin(...)
|
||||
test_run({test_ub, test_bit},...)
|
||||
end
|
||||
|
||||
|
||||
@@ -536,9 +561,46 @@ function test_resolve()
|
||||
print("resolve_pos http non-existent : "..tostring(pos))
|
||||
end
|
||||
|
||||
function test_rawsend()
|
||||
function test_rawsend(opts)
|
||||
local ifout = (opts and opts.ifout) and opts.ifout
|
||||
local function rawsend_fail_warning()
|
||||
if not opts or not opts.ifout or #opts.ifout==0 then
|
||||
local un = uname()
|
||||
if string.sub(un.sysname,1,6)=="CYGWIN" then
|
||||
print("windivert requires interface name in the form '<int>.<int>'. take it from winws2 output with '--debug' option and call test_rawsend({ifout=interface_name})")
|
||||
end
|
||||
end
|
||||
end
|
||||
local function rawsend_dissect_print(dis, options)
|
||||
if options then
|
||||
options.ifout = ifout
|
||||
else
|
||||
options = { ifout = ifout }
|
||||
end
|
||||
local b = rawsend_dissect(dis, options)
|
||||
if not b then
|
||||
print("rawsend_dissect failed")
|
||||
rawsend_fail_warning()
|
||||
end
|
||||
return b
|
||||
end
|
||||
local function rawsend_print(raw, options)
|
||||
if options then
|
||||
options.ifout = ifout
|
||||
else
|
||||
options = { ifout = ifout }
|
||||
end
|
||||
print("rawsend: "..string2hex(raw))
|
||||
local b = rawsend(raw, options)
|
||||
if not b then
|
||||
print("rawsend failed")
|
||||
rawsend_fail_warning()
|
||||
end
|
||||
return b
|
||||
end
|
||||
local ip, ip6, udp, dis, ddis, raw_ip, raw_udp, raw
|
||||
local payload = brandom(math.random(100,1200))
|
||||
local b
|
||||
|
||||
ip = {
|
||||
ip_tos = 0,
|
||||
@@ -555,20 +617,21 @@ function test_rawsend()
|
||||
}
|
||||
dis = {ip = ip, udp = udp, payload = payload}
|
||||
print("send ipv4 udp")
|
||||
test_assert(rawsend_dissect(dis, {repeats=3}))
|
||||
|
||||
test_assert(rawsend_dissect_print(dis, {repeats=3}))
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
print("send ipv4 udp frag "..k)
|
||||
test_assert(rawsend_dissect(d))
|
||||
test_assert(rawsend_dissect_print(d))
|
||||
end
|
||||
|
||||
raw_ip = reconstruct_iphdr(ip)
|
||||
local ip2=ip
|
||||
ip2.ip_len = IP_BASE_LEN + UDP_BASE_LEN + #payload
|
||||
raw_ip = reconstruct_iphdr(ip2)
|
||||
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 ipv4 udp using pure rawsend without dissect")
|
||||
test_assert(rawsend(raw, {repeats=5}))
|
||||
test_assert(rawsend_print(raw, {repeats=5}))
|
||||
|
||||
ip6 = {
|
||||
ip6_flow = 0x60000000,
|
||||
@@ -578,22 +641,22 @@ function test_rawsend()
|
||||
}
|
||||
dis = {ip6 = ip6, udp = udp, payload = payload}
|
||||
print("send ipv6 udp")
|
||||
test_assert(rawsend_dissect(dis, {repeats=3}))
|
||||
test_assert(rawsend_dissect_print(dis, {repeats=3}))
|
||||
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
print("send ipv6 udp frag "..k)
|
||||
test_assert(rawsend_dissect(d))
|
||||
test_assert(rawsend_dissect_print(d))
|
||||
end
|
||||
|
||||
ip6.exthdr={{ type = IPPROTO_HOPOPTS, data = "\x00\x00\x00\x00\x00\x00" }}
|
||||
print("send ipv6 udp with hopbyhop ext header")
|
||||
test_assert(rawsend_dissect(dis, {repeats=3}))
|
||||
test_assert(rawsend_dissect_print(dis, {repeats=3}))
|
||||
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop ext header")
|
||||
test_assert(rawsend_dissect(d))
|
||||
test_assert(rawsend_dissect_print(d))
|
||||
end
|
||||
|
||||
table.insert(ip6.exthdr, { type = IPPROTO_DSTOPTS, data = "\x00\x00\x00\x00\x00\x00" })
|
||||
@@ -602,7 +665,7 @@ function test_rawsend()
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(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(d, {fwmark = 0x50EA}))
|
||||
test_assert(rawsend_dissect_print(d, {fwmark = 0x50EA}))
|
||||
end
|
||||
|
||||
fix_ip6_next(ip6) -- required to forge next proto in the second fragment
|
||||
@@ -612,6 +675,6 @@ function test_rawsend()
|
||||
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
|
||||
test_assert(rawsend_dissect(d, {fwmark = 0x409A, repeats=2}, {ip6_preserve_next = true}))
|
||||
test_assert(rawsend_dissect_print(d, {fwmark = 0x409A, repeats=2}, {ip6_preserve_next = true}))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,15 +11,12 @@ 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
|
||||
local function genkey()
|
||||
-- cache key in lua_state of conntrack is present
|
||||
if desync.track and desync.track.lua_state.wgobfs_key then
|
||||
key = desync.track.lua_state.wgobfs_key
|
||||
end
|
||||
-- cache key in a global var bound to instance name
|
||||
local key_cache_name = desync.func_instance.."_key"
|
||||
key = _G[key_cache_name]
|
||||
if not key then
|
||||
key = hkdf("sha256", "wgobfs_salt", desync.arg.secret, nil, 16)
|
||||
if desync.track then
|
||||
desync.track.lua_state.wgobfs_key = key
|
||||
end
|
||||
_G[key_cache_name] = key
|
||||
end
|
||||
return key
|
||||
end
|
||||
|
||||
@@ -3,46 +3,74 @@
|
||||
|
||||
#define AES_BLOCKLEN 16
|
||||
|
||||
|
||||
// add 64-bit value to 16-byte big endian counter
|
||||
#if defined(__GNUC__) && !defined(__llvm__)
|
||||
__attribute__((optimize ("no-strict-aliasing")))
|
||||
#endif
|
||||
void ctr_add(uint8_t *counter, uint64_t add)
|
||||
{
|
||||
#ifndef __BYTE_ORDER__
|
||||
#error "__BYTE_ORDER__ not defined"
|
||||
#endif
|
||||
uint64_t *c = (uint64_t*)counter;
|
||||
|
||||
#if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
|
||||
uint64_t sum = c[1] + add;
|
||||
if (sum < c[1]) // overflow
|
||||
c[0]++;
|
||||
c[1] = sum;
|
||||
#else
|
||||
uint64_t lsw = __builtin_bswap64(c[1]);
|
||||
uint64_t sum = lsw + add;
|
||||
if (sum < lsw) // overflow
|
||||
c[0] = __builtin_bswap64(__builtin_bswap64(c[0]) + 1);
|
||||
c[1] = __builtin_bswap64(sum);
|
||||
#endif
|
||||
}
|
||||
|
||||
// increment 16-byte big endian counter
|
||||
static inline void ctr_increment(uint8_t *counter)
|
||||
{
|
||||
for (int8_t bi = (AES_BLOCKLEN - 1); (bi >= 0) && !++counter[bi]; bi--);
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && !defined(__llvm__)
|
||||
__attribute__((optimize ("no-strict-aliasing")))
|
||||
#endif
|
||||
void aes_ctr_xcrypt_buffer(aes_context *ctx, const uint8_t *iv, const uint8_t *in, size_t length, uint8_t *out)
|
||||
{
|
||||
uint8_t bi, buffer[AES_BLOCKLEN], ivc[AES_BLOCKLEN];
|
||||
size_t i;
|
||||
uint8_t bi, ivc[AES_BLOCKLEN], buffer[AES_BLOCKLEN];
|
||||
size_t i, l16 = length & ~0xF;
|
||||
|
||||
memcpy(ivc,iv,AES_BLOCKLEN);
|
||||
memcpy(ivc, iv, AES_BLOCKLEN);
|
||||
|
||||
for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
|
||||
for (i = 0; i < l16; i += 16)
|
||||
{
|
||||
if (bi == AES_BLOCKLEN) /* we need to regen xor complement in buffer */
|
||||
{
|
||||
memcpy(buffer, ivc, AES_BLOCKLEN);
|
||||
aes_cipher(ctx, buffer, buffer);
|
||||
aes_cipher(ctx, ivc, buffer);
|
||||
ctr_increment(ivc);
|
||||
*((uint64_t*)(out + i)) = *((uint64_t*)(in + i)) ^ ((uint64_t*)buffer)[0];
|
||||
*((uint64_t*)(out + i + 8)) = *((uint64_t*)(in + i + 8)) ^ ((uint64_t*)buffer)[1];
|
||||
}
|
||||
|
||||
/* Increment ivc and handle overflow */
|
||||
for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
|
||||
{
|
||||
/* inc will owerflow */
|
||||
if (ivc[bi] == 255)
|
||||
{
|
||||
ivc[bi] = 0;
|
||||
continue;
|
||||
}
|
||||
ivc[bi] += 1;
|
||||
break;
|
||||
}
|
||||
bi = 0;
|
||||
}
|
||||
out[i] = in[i] ^ buffer[bi];
|
||||
if (i<length)
|
||||
{
|
||||
memcpy(buffer, ivc, AES_BLOCKLEN);
|
||||
aes_cipher(ctx, buffer, buffer);
|
||||
|
||||
for (bi=0 ; i < length; i++, bi++)
|
||||
out[i] = in[i] ^ buffer[bi];
|
||||
}
|
||||
}
|
||||
|
||||
int aes_ctr_crypt(const uint8_t *key, const size_t key_len, const uint8_t *iv, const uint8_t *in, size_t length, uint8_t *out)
|
||||
int aes_ctr_crypt(const uint8_t *key, unsigned int key_len, const uint8_t *iv, const uint8_t *in, size_t length, uint8_t *out)
|
||||
{
|
||||
int ret=0;
|
||||
int ret = 0;
|
||||
aes_context ctx;
|
||||
|
||||
aes_init_keygen_tables();
|
||||
|
||||
if (!(ret=aes_setkey(&ctx, AES_ENCRYPT, key, key_len)))
|
||||
if (!(ret = aes_setkey(&ctx, AES_ENCRYPT, key, key_len)))
|
||||
aes_ctr_xcrypt_buffer(&ctx, iv, in, length, out);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -4,4 +4,5 @@
|
||||
#include "aes.h"
|
||||
|
||||
void aes_ctr_xcrypt_buffer(aes_context *ctx, const uint8_t *iv, const uint8_t *in, size_t length, uint8_t *out);
|
||||
int aes_ctr_crypt(const uint8_t *key, const size_t key_len, const uint8_t *iv, const uint8_t *in, size_t length, uint8_t *out);
|
||||
int aes_ctr_crypt(const uint8_t *key, unsigned int key_len, const uint8_t *iv, const uint8_t *in, size_t length, uint8_t *out);
|
||||
void ctr_add(uint8_t *counter, uint64_t add);
|
||||
|
||||
@@ -5,6 +5,8 @@ int aes_gcm_crypt(int mode, uint8_t *output, const uint8_t *input, size_t input_
|
||||
int ret = 0;
|
||||
gcm_context ctx;
|
||||
|
||||
gcm_initialize();
|
||||
|
||||
if (!(ret = gcm_setkey(&ctx, key, (const uint)key_len)))
|
||||
{
|
||||
ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len);
|
||||
|
||||
304
nfq2/darkmagic.c
304
nfq2/darkmagic.c
@@ -20,8 +20,14 @@
|
||||
#include "nfqws.h"
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include <sys/cygwin.h>
|
||||
|
||||
#include <wlanapi.h>
|
||||
#include <netlistmgr.h>
|
||||
#include <aclapi.h>
|
||||
#include <wchar.h>
|
||||
#include <KnownFolders.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#ifndef ERROR_INVALID_IMAGE_HASH
|
||||
#define ERROR_INVALID_IMAGE_HASH __MSABI_LONG(577)
|
||||
@@ -88,26 +94,22 @@ uint8_t tcp_find_scale_factor(const struct tcphdr *tcp)
|
||||
if (scale && scale[1]==3) return scale[2];
|
||||
return SCALE_NONE;
|
||||
}
|
||||
bool tcp_has_fastopen(const struct tcphdr *tcp)
|
||||
{
|
||||
uint8_t *opt;
|
||||
// new style RFC7413
|
||||
opt = tcp_find_option((struct tcphdr*)tcp, TCP_KIND_FASTOPEN);
|
||||
if (opt) return true;
|
||||
// old style RFC6994
|
||||
opt = tcp_find_option((struct tcphdr*)tcp, 254);
|
||||
return opt && opt[1]>=4 && opt[2]==0xF9 && opt[3]==0x89;
|
||||
}
|
||||
uint16_t tcp_find_mss(const struct tcphdr *tcp)
|
||||
{
|
||||
uint8_t *t = tcp_find_option((struct tcphdr *)tcp, TCP_KIND_MSS);
|
||||
return (t && t[1]==4) ? *(uint16_t*)(t+2) : 0;
|
||||
}
|
||||
bool tcp_has_sack(struct tcphdr *tcp)
|
||||
bool tcp_synack_segment(const struct tcphdr *tcphdr)
|
||||
{
|
||||
uint8_t *t = tcp_find_option(tcp, TCP_KIND_SACK_PERM);
|
||||
return !!t;
|
||||
/* check for set bits in TCP hdr */
|
||||
return ((tcphdr->th_flags & (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN)) == (TH_ACK|TH_SYN));
|
||||
}
|
||||
bool tcp_syn_segment(const struct tcphdr *tcphdr)
|
||||
{
|
||||
/* check for set bits in TCP hdr */
|
||||
return ((tcphdr->th_flags & (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN)) == TH_SYN);
|
||||
}
|
||||
|
||||
|
||||
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport)
|
||||
{
|
||||
@@ -549,67 +551,19 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis)
|
||||
}
|
||||
|
||||
|
||||
bool tcp_synack_segment(const struct tcphdr *tcphdr)
|
||||
{
|
||||
/* check for set bits in TCP hdr */
|
||||
return ((tcphdr->th_flags & (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN)) == (TH_ACK|TH_SYN));
|
||||
}
|
||||
bool tcp_syn_segment(const struct tcphdr *tcphdr)
|
||||
{
|
||||
/* check for set bits in TCP hdr */
|
||||
return ((tcphdr->th_flags & (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN)) == TH_SYN);
|
||||
}
|
||||
bool tcp_ack_segment(const struct tcphdr *tcphdr)
|
||||
{
|
||||
/* check for set bits in TCP hdr */
|
||||
return ((tcphdr->th_flags & (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN)) == TH_ACK);
|
||||
}
|
||||
|
||||
void tcp_rewrite_wscale(struct tcphdr *tcp, uint8_t scale_factor)
|
||||
{
|
||||
uint8_t *scale,scale_factor_old;
|
||||
|
||||
if (scale_factor!=SCALE_NONE)
|
||||
{
|
||||
scale = tcp_find_option(tcp,3); // tcp option 3 - scale factor
|
||||
if (scale && scale[1]==3) // length should be 3
|
||||
{
|
||||
scale_factor_old=scale[2];
|
||||
// do not allow increasing scale factor
|
||||
if (scale_factor>=scale_factor_old)
|
||||
DLOG("Scale factor %u unchanged\n", scale_factor_old);
|
||||
else
|
||||
{
|
||||
scale[2]=scale_factor;
|
||||
DLOG("Scale factor change %u => %u\n", scale_factor_old, scale_factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// scale_factor=SCALE_NONE - do not change
|
||||
void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_factor)
|
||||
{
|
||||
uint16_t winsize_old;
|
||||
|
||||
winsize_old = htons(tcp->th_win); // << scale_factor;
|
||||
tcp->th_win = htons(winsize);
|
||||
DLOG("Window size change %u => %u\n", winsize_old, winsize);
|
||||
|
||||
tcp_rewrite_wscale(tcp, scale_factor);
|
||||
}
|
||||
|
||||
|
||||
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6)
|
||||
{
|
||||
return ip ? ip->ip_ttl : ip6 ? ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
|
||||
uint32_t w_win32_error=0;
|
||||
|
||||
static BOOL RemoveTokenPrivs()
|
||||
static BOOL RemoveTokenPrivs(void)
|
||||
{
|
||||
BOOL bRes = FALSE;
|
||||
HANDLE hToken;
|
||||
@@ -643,15 +597,153 @@ static BOOL RemoveTokenPrivs()
|
||||
if (!bRes) w_win32_error = GetLastError();
|
||||
return bRes;
|
||||
}
|
||||
static BOOL WinSandbox()
|
||||
|
||||
static SID_IDENTIFIER_AUTHORITY label_authority = SECURITY_MANDATORY_LABEL_AUTHORITY;
|
||||
BOOL LowMandatoryLevel(void)
|
||||
{
|
||||
// unfortunately there's no way to remove or disable Administrators group in the current process's token
|
||||
// only possible run child process with restricted token
|
||||
// but at least it's possible to permanently remove privileges
|
||||
// this is not much but better than nothing
|
||||
return RemoveTokenPrivs();
|
||||
BOOL bRes = FALSE;
|
||||
HANDLE hToken;
|
||||
char buf1[32];
|
||||
TOKEN_MANDATORY_LABEL label_low;
|
||||
|
||||
label_low.Label.Sid = (PSID)buf1;
|
||||
InitializeSid(label_low.Label.Sid, &label_authority, 1);
|
||||
label_low.Label.Attributes = 0;
|
||||
*GetSidSubAuthority(label_low.Label.Sid, 0) = SECURITY_MANDATORY_LOW_RID;
|
||||
|
||||
// S-1-16-12288 : Mandatory Label\High Mandatory Level
|
||||
// S-1-16-8192 : Mandatory Label\Medium Mandatory Level
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_DEFAULT, &hToken))
|
||||
{
|
||||
bRes = SetTokenInformation(hToken, TokenIntegrityLevel, &label_low, sizeof(label_low));
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
if (!bRes) w_win32_error = GetLastError();
|
||||
return bRes;
|
||||
}
|
||||
|
||||
BOOL SetMandatoryLabelFile(LPCSTR lpFileName, DWORD dwMandatoryLabelRID, DWORD dwAceFlags)
|
||||
{
|
||||
BOOL bRes=FALSE;
|
||||
DWORD dwErr, dwFileAttributes;
|
||||
char buf_label[16], buf_pacl[32];
|
||||
PSID label = (PSID)buf_label;
|
||||
PACL pacl = (PACL)buf_pacl;
|
||||
LPWSTR lpFileNameW = NULL;
|
||||
size_t szFileName;
|
||||
|
||||
szFileName = strlen(lpFileName);
|
||||
if (!(lpFileNameW = (LPWSTR)LocalAlloc(LMEM_FIXED,(szFileName+1)*sizeof(WCHAR))))
|
||||
goto err;
|
||||
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, lpFileName, -1, lpFileNameW, szFileName+1))
|
||||
goto err;
|
||||
|
||||
if (!strncmp(lpFileName,"\\\\.\\",4))
|
||||
dwFileAttributes = 0;
|
||||
else
|
||||
{
|
||||
dwFileAttributes = GetFileAttributesW(lpFileNameW);
|
||||
if (dwFileAttributes == INVALID_FILE_ATTRIBUTES) goto err;
|
||||
}
|
||||
InitializeSid(label, &label_authority, 1);
|
||||
*GetSidSubAuthority(label, 0) = dwMandatoryLabelRID;
|
||||
if (InitializeAcl(pacl, sizeof(buf_pacl), ACL_REVISION) && AddMandatoryAce(pacl, (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? ACL_REVISION_DS : ACL_REVISION, dwAceFlags, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, label))
|
||||
{
|
||||
dwErr = SetNamedSecurityInfoW(lpFileNameW, SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pacl);
|
||||
SetLastError(dwErr);
|
||||
bRes = dwErr==ERROR_SUCCESS;
|
||||
}
|
||||
err:
|
||||
if (!bRes) w_win32_error = GetLastError();
|
||||
LocalFree(lpFileNameW);
|
||||
return bRes;
|
||||
}
|
||||
|
||||
BOOL SetMandatoryLabelFileW(LPCWSTR lpFileNameW, DWORD dwMandatoryLabelRID, DWORD dwAceFlags)
|
||||
{
|
||||
BOOL bRes=FALSE;
|
||||
DWORD dwErr, dwFileAttributes;
|
||||
char buf_label[16], buf_pacl[32];
|
||||
PSID label = (PSID)buf_label;
|
||||
PACL pacl = (PACL)buf_pacl;
|
||||
|
||||
if (!wcsncmp(lpFileNameW,L"\\\\.\\",4))
|
||||
dwFileAttributes = 0;
|
||||
else
|
||||
{
|
||||
dwFileAttributes = GetFileAttributesW(lpFileNameW);
|
||||
if (dwFileAttributes == INVALID_FILE_ATTRIBUTES) goto err;
|
||||
}
|
||||
|
||||
InitializeSid(label, &label_authority, 1);
|
||||
*GetSidSubAuthority(label, 0) = dwMandatoryLabelRID;
|
||||
if (InitializeAcl(pacl, sizeof(buf_pacl), ACL_REVISION) && AddMandatoryAce(pacl, (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? ACL_REVISION_DS : ACL_REVISION, dwAceFlags, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, label))
|
||||
{
|
||||
dwErr = SetNamedSecurityInfoW((LPWSTR)lpFileNameW, SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pacl);
|
||||
SetLastError(dwErr);
|
||||
bRes = dwErr==ERROR_SUCCESS;
|
||||
}
|
||||
err:
|
||||
if (!bRes) w_win32_error = GetLastError();
|
||||
return bRes;
|
||||
}
|
||||
|
||||
bool ensure_file_access(const char *filename)
|
||||
{
|
||||
return SetMandatoryLabelFile(filename, SECURITY_MANDATORY_LOW_RID, 0);
|
||||
}
|
||||
bool ensure_dir_access(const char *dir)
|
||||
{
|
||||
return SetMandatoryLabelFile(dir, SECURITY_MANDATORY_LOW_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
|
||||
}
|
||||
|
||||
bool prepare_low_appdata()
|
||||
{
|
||||
bool b = false;
|
||||
PWSTR pszPath = NULL;
|
||||
HRESULT hr = SHGetKnownFolderPath(&FOLDERID_LocalAppDataLow, 0, NULL, &pszPath);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
size_t l = cygwin_conv_path(CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, pszPath, NULL, 0);
|
||||
char *buf = (char*)malloc(l+8);
|
||||
if (buf)
|
||||
{
|
||||
if (!cygwin_conv_path(CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, pszPath, buf, l))
|
||||
{
|
||||
b = true;
|
||||
setenv("APPDATALOW", buf, 1);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
CoTaskMemFree(pszPath);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
#define WINDIVERT_DEVICE_NAME "WinDivert"
|
||||
static bool b_isandbox_set = false;
|
||||
bool win_sandbox(void)
|
||||
{
|
||||
// there's no way to return privs
|
||||
if (!b_isandbox_set)
|
||||
{
|
||||
if (!RemoveTokenPrivs())
|
||||
return FALSE;
|
||||
|
||||
// set low mandatory label on windivert device to allow administrators with low label access the driver
|
||||
if (logical_net_filter_present() && !SetMandatoryLabelFile("\\\\.\\" WINDIVERT_DEVICE_NAME, SECURITY_MANDATORY_LOW_RID, 0))
|
||||
return FALSE;
|
||||
if (!LowMandatoryLevel())
|
||||
return false;
|
||||
// for LUA code to find where to store files
|
||||
b_isandbox_set = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static HANDLE w_filter = NULL;
|
||||
static OVERLAPPED ovl = { .hEvent = NULL };
|
||||
@@ -745,8 +837,6 @@ bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_lis
|
||||
if (LIST_EMPTY(ssid_filter)) ssid_filter=NULL;
|
||||
if (LIST_EMPTY(nlm_filter)) nlm_filter=NULL;
|
||||
|
||||
if (!WinSandbox()) return false;
|
||||
|
||||
if (nlm_filter)
|
||||
{
|
||||
if (SUCCEEDED(w_win32_error = CoInitialize(NULL)))
|
||||
@@ -1004,6 +1094,13 @@ bool logical_net_filter_match(void)
|
||||
return wlan_filter_match(wlan_filter_ssid) && nlm_filter_match(nlm_filter_net);
|
||||
}
|
||||
|
||||
bool logical_net_filter_present(void)
|
||||
{
|
||||
return (wlan_filter_ssid && !LIST_EMPTY(wlan_filter_ssid)) || (nlm_filter_net && !LIST_EMPTY(nlm_filter_net));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool logical_net_filter_match_rate_limited(void)
|
||||
{
|
||||
DWORD dwTick = GetTickCount() / 1000;
|
||||
@@ -1093,14 +1190,17 @@ static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len,
|
||||
return false;
|
||||
}
|
||||
usleep(0);
|
||||
|
||||
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, NULL, &ovl))
|
||||
{
|
||||
*len = recv_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
w_win32_error = GetLastError();
|
||||
|
||||
switch(w_win32_error)
|
||||
{
|
||||
case ERROR_IO_PENDING:
|
||||
@@ -1156,6 +1256,8 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
|
||||
{
|
||||
WINDIVERT_ADDRESS wa;
|
||||
|
||||
if (!ifout) return false;
|
||||
|
||||
memset(&wa,0,sizeof(wa));
|
||||
// pseudo interface id IfIdx.SubIfIdx
|
||||
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
|
||||
@@ -1168,17 +1270,22 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
|
||||
wa.TCPChecksum=1;
|
||||
wa.UDPChecksum=1;
|
||||
wa.IPv6 = (dst->sa_family==AF_INET6);
|
||||
|
||||
if (!windivert_send(data,len,&wa))
|
||||
{
|
||||
DLOG_ERR("windivert send error. win32 code %u\n",w_win32_error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#else // *nix
|
||||
|
||||
bool ensure_file_access(const char *filename)
|
||||
{
|
||||
return !chown(filename, params.uid, -1);
|
||||
}
|
||||
|
||||
static int rawsend_sock4=-1, rawsend_sock6=-1;
|
||||
static bool b_bind_fix4=false, b_bind_fix6=false;
|
||||
static void rawsend_clean_sock(int *sock)
|
||||
@@ -1783,3 +1890,54 @@ bool set_socket_buffers(int fd, int rcvbuf, int sndbuf)
|
||||
dbgprint_socket_buffers(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool make_writeable_dir()
|
||||
{
|
||||
char wdir[PATH_MAX], *wrdir;
|
||||
if (*params.writeable_dir)
|
||||
wrdir = params.writeable_dir;
|
||||
else
|
||||
{
|
||||
#ifdef __CYGWIN__
|
||||
char *env = getenv("APPDATALOW");
|
||||
if (!env) return false;
|
||||
#else
|
||||
char *env = getenv("TMPDIR");
|
||||
if (!env) env = "/tmp";
|
||||
#endif
|
||||
snprintf(wdir,sizeof(wdir),"%s/zapret2",env);
|
||||
wrdir = wdir;
|
||||
}
|
||||
if (mkdir(wrdir,0755) && errno!=EEXIST)
|
||||
return false;
|
||||
|
||||
bool b = false;
|
||||
#ifdef __CYGWIN__
|
||||
size_t l = cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, wrdir, NULL, 0);
|
||||
WCHAR *wwrdir = (WCHAR*)malloc(l);
|
||||
if (wwrdir)
|
||||
{
|
||||
if (!cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, wrdir, wwrdir, l))
|
||||
b = SetMandatoryLabelFileW(wwrdir, SECURITY_MANDATORY_LOW_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
|
||||
free(wwrdir);
|
||||
}
|
||||
#else
|
||||
if (ensure_dir_access(wrdir))
|
||||
b = true;
|
||||
else
|
||||
{
|
||||
// could not chown. may be still accessible ?
|
||||
char testfile[PATH_MAX];
|
||||
snprintf(testfile,sizeof(testfile),"%s/test_XXXXXX",wrdir);
|
||||
int fd = mkstemp(testfile);
|
||||
if (fd>0)
|
||||
{
|
||||
close(fd);
|
||||
unlink(testfile);
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (b) setenv("WRITEABLE",wrdir,1);
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -83,23 +83,30 @@ uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind);
|
||||
uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
|
||||
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
|
||||
uint16_t tcp_find_mss(const struct tcphdr *tcp);
|
||||
bool tcp_has_sack(struct tcphdr *tcp);
|
||||
|
||||
bool tcp_has_fastopen(const struct tcphdr *tcp);
|
||||
bool tcp_synack_segment(const struct tcphdr *tcphdr);
|
||||
bool tcp_syn_segment(const struct tcphdr *tcphdr);
|
||||
|
||||
bool ip_has_df(const struct ip *ip);
|
||||
|
||||
|
||||
bool make_writeable_dir();
|
||||
bool ensure_file_access(const char *filename);
|
||||
#ifdef __CYGWIN__
|
||||
extern uint32_t w_win32_error;
|
||||
|
||||
bool ensure_dir_access(const char *filename);
|
||||
bool prepare_low_appdata();
|
||||
bool win_sandbox(void);
|
||||
bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_list_head *nlm_filter);
|
||||
bool win_dark_deinit(void);
|
||||
bool logical_net_filter_present(void);
|
||||
bool logical_net_filter_match(void);
|
||||
bool nlm_list(bool bAll);
|
||||
bool windivert_init(const char *filter);
|
||||
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa);
|
||||
bool windivert_send(const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa);
|
||||
#else
|
||||
#define ensure_dir_access(dir) ensure_file_access(dir)
|
||||
// should pre-do it if dropping privileges. otherwise its not necessary
|
||||
bool rawsend_preinit(bool bind_fix4, bool bind_fix6);
|
||||
#endif
|
||||
@@ -156,13 +163,6 @@ struct dissect
|
||||
};
|
||||
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis);
|
||||
|
||||
bool tcp_synack_segment(const struct tcphdr *tcphdr);
|
||||
bool tcp_syn_segment(const struct tcphdr *tcphdr);
|
||||
bool tcp_ack_segment(const struct tcphdr *tcphdr);
|
||||
// scale_factor=SCALE_NONE - do not change
|
||||
void tcp_rewrite_wscale(struct tcphdr *tcp, uint8_t scale_factor);
|
||||
void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_factor);
|
||||
|
||||
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6);
|
||||
|
||||
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, const struct ip *ip, const struct ip6_hdr *ip6hdr);
|
||||
|
||||
@@ -659,7 +659,7 @@ static uint8_t desync(
|
||||
struct func_list *func;
|
||||
int ref_arg = LUA_NOREF, status;
|
||||
bool b, b_cutoff_all, b_unwanted_payload;
|
||||
t_lua_desync_context ctx = { .dp = dp,.ctrack = ctrack };
|
||||
t_lua_desync_context ctx = { .dp = dp, .ctrack = ctrack, .dis = dis };
|
||||
const char *sDirection = bIncoming ? "in" : "out";
|
||||
struct packet_range *range;
|
||||
size_t l;
|
||||
@@ -787,7 +787,7 @@ static uint8_t desync(
|
||||
}
|
||||
lua_pushlightuserdata(params.L, &ctx);
|
||||
lua_rawgeti(params.L, LUA_REGISTRYINDEX, ref_arg);
|
||||
lua_pushf_args(&func->args);
|
||||
lua_pushf_args(&func->args, -1);
|
||||
lua_pushf_str("func", func->func);
|
||||
lua_pushf_int("func_n", func_n);
|
||||
lua_pushf_str("func_instance", instance);
|
||||
@@ -1169,7 +1169,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
if (l7proto == L7_UNKNOWN)
|
||||
{
|
||||
l7proto = L7_HTTP;
|
||||
if (ctrack) ctrack->l7proto = l7proto;
|
||||
if (ctrack && ctrack->l7proto == L7_UNKNOWN) ctrack->l7proto = l7proto;
|
||||
}
|
||||
|
||||
// we do not reassemble http
|
||||
@@ -1201,7 +1201,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
if (l7proto == L7_UNKNOWN)
|
||||
{
|
||||
l7proto = L7_TLS;
|
||||
if (ctrack->l7proto == L7_UNKNOWN) ctrack->l7proto = l7proto;
|
||||
if (ctrack && ctrack->l7proto == L7_UNKNOWN) ctrack->l7proto = l7proto;
|
||||
}
|
||||
|
||||
if (bReqFull) TLSDebug(rdata_payload, rlen_payload);
|
||||
@@ -1271,7 +1271,6 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
};
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
|
||||
}
|
||||
|
||||
if (ctrack && ctrack->req_seq_finalized)
|
||||
{
|
||||
uint32_t dseq = ctrack->seq_last - ctrack->req_seq_end;
|
||||
|
||||
@@ -417,26 +417,9 @@ bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset)
|
||||
char hex_digit(uint8_t v)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
if (offset%=patsize)
|
||||
{
|
||||
size = patsize-offset;
|
||||
size = bufsize>size ? size : bufsize;
|
||||
memcpy(buf,pattern+offset,size);
|
||||
buf += size;
|
||||
bufsize -= size;
|
||||
}
|
||||
while (bufsize)
|
||||
{
|
||||
size = bufsize>patsize ? patsize : bufsize;
|
||||
memcpy(buf,pattern,size);
|
||||
buf += size;
|
||||
bufsize -= size;
|
||||
}
|
||||
return v<=9 ? '0'+v : (v<=0xF) ? v+'A'-0xA : '?';
|
||||
}
|
||||
|
||||
int fprint_localtime(FILE *F)
|
||||
|
||||
@@ -65,7 +65,7 @@ uint64_t pntoh64(const uint8_t *p);
|
||||
void phton64(uint8_t *p, uint64_t v);
|
||||
|
||||
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size);
|
||||
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset);
|
||||
char hex_digit(uint8_t v);
|
||||
|
||||
int fprint_localtime(FILE *F);
|
||||
|
||||
|
||||
278
nfq2/lua.c
278
nfq2/lua.c
@@ -1,8 +1,19 @@
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/thr.h>
|
||||
#elif defined(__linux__)
|
||||
#include <sys/syscall.h>
|
||||
#elif defined(__CYGWIN__)
|
||||
#include <processthreadsapi.h>
|
||||
#endif
|
||||
|
||||
#include "lua.h"
|
||||
#include "params.h"
|
||||
#include "helpers.h"
|
||||
#include "conntrack.h"
|
||||
#include "crypto/sha.h"
|
||||
#include "crypto/aes-gcm.h"
|
||||
#include "crypto/aes-ctr.h"
|
||||
@@ -185,12 +196,33 @@ static int luacall_u32(lua_State *L)
|
||||
lua_pushinteger(L,pntoh32(p+offset));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_swap16(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"swap16",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
if (i>0xFFFF || i<-(lua_Integer)0xFFFF) luaL_error(L, "out of range");
|
||||
uint16_t u = (uint16_t)i;
|
||||
// __builtin_bswap16 is absent in ancient lexra gcc 4.6
|
||||
lua_pushinteger(L,(u>>8) | ((u&0xFF)<<8));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_swap32(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"swap32",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
if (i>0xFFFFFFFF || i<-(lua_Integer)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint32_t u = (uint32_t)i;
|
||||
lua_pushinteger(L,__builtin_bswap32(u));
|
||||
return 1;
|
||||
}
|
||||
static int luacall_bu8(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"bu8",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
if (i & ~(uint64_t)0xFF) luaL_error(L, "out of range");
|
||||
if (i>0xFF || i<-(lua_Integer)0xFF) luaL_error(L, "out of range");
|
||||
uint8_t v=(uint8_t)i;
|
||||
lua_pushlstring(L,(char*)&v,1);
|
||||
return 1;
|
||||
@@ -200,7 +232,7 @@ static int luacall_bu16(lua_State *L)
|
||||
lua_check_argc(L,"bu16",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
if (i & ~(uint64_t)0xFFFF) luaL_error(L, "out of range");
|
||||
if (i>0xFFFF || i<-(lua_Integer)0xFFFF) luaL_error(L, "out of range");
|
||||
uint8_t v[2];
|
||||
phton16(v,(uint16_t)i);
|
||||
lua_pushlstring(L,(char*)v,2);
|
||||
@@ -211,7 +243,7 @@ static int luacall_bu24(lua_State *L)
|
||||
lua_check_argc(L,"bu24",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
if (i & ~(uint64_t)0xFFFFFF) luaL_error(L, "out of range");
|
||||
if (i>0xFFFFFF || i<-(lua_Integer)0xFFFFFF) luaL_error(L, "out of range");
|
||||
uint8_t v[3];
|
||||
phton24(v,(uint32_t)i);
|
||||
lua_pushlstring(L,(char*)v,3);
|
||||
@@ -222,7 +254,7 @@ static int luacall_bu32(lua_State *L)
|
||||
lua_check_argc(L,"bu32",1);
|
||||
|
||||
lua_Integer i = luaL_checkinteger(L,1);
|
||||
if (i & ~(uint64_t)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
if (i>0xFFFFFFFF || i<-(lua_Integer)0xFFFFFFFF) luaL_error(L, "out of range");
|
||||
uint8_t v[4];
|
||||
phton32(v,(uint32_t)i);
|
||||
lua_pushlstring(L,(char*)v,4);
|
||||
@@ -409,7 +441,6 @@ static int luacall_aes(lua_State *L)
|
||||
if (input_len!=16)
|
||||
luaL_error(L, "aes: wrong data length %u. should be 16.", (unsigned)input_len);
|
||||
|
||||
aes_init_keygen_tables();
|
||||
aes_context ctx;
|
||||
uint8_t output[16];
|
||||
if (aes_setkey(&ctx, bEncrypt, key, key_len) || aes_cipher(&ctx, input, output))
|
||||
@@ -525,7 +556,72 @@ static int luacall_hkdf(lua_State *L)
|
||||
}
|
||||
|
||||
|
||||
static int luacall_getpid(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"getpid", 0);
|
||||
lua_pushinteger(L, getpid());
|
||||
return 1;
|
||||
}
|
||||
static int luacall_gettid(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"gettid", 0);
|
||||
#ifdef __OpenBSD__
|
||||
lua_pushinteger(L, getthrid());
|
||||
#elif defined(__FreeBSD__)
|
||||
long tid;
|
||||
if (thr_self(&tid))
|
||||
lua_pushnil(L);
|
||||
else
|
||||
lua_pushinteger(L, tid);
|
||||
#elif defined(__linux__)
|
||||
lua_pushinteger(L, syscall(SYS_gettid));
|
||||
#elif defined(__CYGWIN__)
|
||||
lua_pushinteger(L, GetCurrentThreadId());
|
||||
#else
|
||||
// unsupported OS ?
|
||||
lua_pushnil(L);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
static int luacall_uname(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"uname", 0);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
struct utsname udata;
|
||||
if (uname(&udata))
|
||||
lua_pushnil(L);
|
||||
else
|
||||
{
|
||||
lua_createtable(params.L, 0, 5);
|
||||
lua_pushf_str("sysname", udata.sysname);
|
||||
lua_pushf_str("nodename", udata.nodename);
|
||||
lua_pushf_str("release", udata.release);
|
||||
lua_pushf_str("version", udata.version);
|
||||
lua_pushf_str("machine", udata.machine);
|
||||
}
|
||||
LUA_STACK_GUARD_RETURN(L,1)
|
||||
}
|
||||
static int luacall_clock_gettime(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"uname", 0);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts))
|
||||
{
|
||||
lua_pushnil(L);
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushinteger(L, ts.tv_sec);
|
||||
lua_pushinteger(L, ts.tv_nsec);
|
||||
}
|
||||
LUA_STACK_GUARD_RETURN(L,2)
|
||||
}
|
||||
static int luacall_instance_cutoff(lua_State *L)
|
||||
{
|
||||
// out : func_name.profile_number[0]
|
||||
@@ -609,6 +705,23 @@ bool lua_instance_cutoff_check(const t_lua_desync_context *ctx, bool bIn)
|
||||
return b;
|
||||
}
|
||||
|
||||
static int luacall_raw_packet(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"raw_packet",1);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
const t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "raw_packet expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
|
||||
lua_pushlstring(L, (const char*)ctx->dis->data_pkt, ctx->dis->len_pkt);
|
||||
|
||||
LUA_STACK_GUARD_RETURN(L,1)
|
||||
}
|
||||
|
||||
|
||||
void lua_pushf_nil(const char *field)
|
||||
{
|
||||
@@ -708,8 +821,27 @@ void lua_pushf_global(const char *field, const char *global)
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
|
||||
void lua_push_blob(int idx_desync, const char *blob)
|
||||
{
|
||||
lua_getfield(params.L, idx_desync, blob);
|
||||
if (lua_type(params.L,-1)==LUA_TNIL)
|
||||
{
|
||||
lua_pop(params.L,1);
|
||||
lua_getglobal(params.L, blob);
|
||||
}
|
||||
}
|
||||
void lua_pushf_blob(int idx_desync, const char *field, const char *blob)
|
||||
{
|
||||
lua_pushstring(params.L, field);
|
||||
lua_push_blob(idx_desync, blob);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
|
||||
|
||||
void lua_pushf_tcphdr_options(const struct tcphdr *tcp, size_t len)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
lua_pushliteral(params.L,"options");
|
||||
lua_newtable(params.L);
|
||||
|
||||
@@ -743,10 +875,14 @@ void lua_pushf_tcphdr_options(const struct tcphdr *tcp, size_t len)
|
||||
}
|
||||
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
|
||||
void lua_pushf_tcphdr(const struct tcphdr *tcp, size_t len)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
lua_pushliteral(params.L, "tcp");
|
||||
if (tcp && len>=sizeof(struct tcphdr))
|
||||
{
|
||||
@@ -766,9 +902,13 @@ void lua_pushf_tcphdr(const struct tcphdr *tcp, size_t len)
|
||||
else
|
||||
lua_pushnil(params.L);
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
void lua_pushf_udphdr(const struct udphdr *udp, size_t len)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
lua_pushliteral(params.L, "udp");
|
||||
if (udp && len>=sizeof(struct udphdr))
|
||||
{
|
||||
@@ -781,9 +921,13 @@ void lua_pushf_udphdr(const struct udphdr *udp, size_t len)
|
||||
else
|
||||
lua_pushnil(params.L);
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
void lua_pushf_iphdr(const struct ip *ip, size_t len)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
lua_pushliteral(params.L, "ip");
|
||||
if (ip && len>=sizeof(struct ip))
|
||||
{
|
||||
@@ -807,9 +951,13 @@ void lua_pushf_iphdr(const struct ip *ip, size_t len)
|
||||
else
|
||||
lua_pushnil(params.L);
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
void lua_pushf_ip6exthdr(const struct ip6_hdr *ip6, size_t len)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L);
|
||||
|
||||
// assume ipv6 packet structure was already checked for validity
|
||||
size_t hdrlen;
|
||||
uint8_t HeaderType, *data;
|
||||
@@ -866,9 +1014,13 @@ void lua_pushf_ip6exthdr(const struct ip6_hdr *ip6, size_t len)
|
||||
|
||||
end:
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
void lua_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
lua_pushliteral(params.L, "ip6");
|
||||
if (ip6)
|
||||
{
|
||||
@@ -884,9 +1036,13 @@ void lua_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len)
|
||||
else
|
||||
lua_pushnil(params.L);
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
void lua_push_dissect(const struct dissect *dis)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
if (dis)
|
||||
{
|
||||
lua_createtable(params.L, 0, 7);
|
||||
@@ -900,6 +1056,8 @@ void lua_push_dissect(const struct dissect *dis)
|
||||
}
|
||||
else
|
||||
lua_pushnil(params.L);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 1)
|
||||
}
|
||||
void lua_pushf_dissect(const struct dissect *dis)
|
||||
{
|
||||
@@ -910,6 +1068,8 @@ void lua_pushf_dissect(const struct dissect *dis)
|
||||
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
lua_pushliteral(params.L, "track");
|
||||
if (ctrack)
|
||||
{
|
||||
@@ -956,18 +1116,49 @@ void lua_pushf_ctrack(const t_ctrack *ctrack)
|
||||
else
|
||||
lua_pushnil(params.L);
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
void lua_pushf_args(const struct ptr_list_head *args)
|
||||
|
||||
void lua_pushf_args(const struct ptr_list_head *args, int idx_desync)
|
||||
{
|
||||
// var=val - pass val string
|
||||
// var=%val - subst 'val' blob
|
||||
// var=#val - subst 'val' blob length
|
||||
// var=\#val - no subst, skip '\'
|
||||
// var=\%val - no subst, skip '\'
|
||||
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
struct ptr_list *arg;
|
||||
const char *var, *val;
|
||||
|
||||
idx_desync = lua_absindex(params.L, idx_desync);
|
||||
|
||||
lua_pushliteral(params.L,"arg");
|
||||
lua_newtable(params.L);
|
||||
LIST_FOREACH(arg, args, next)
|
||||
{
|
||||
lua_pushf_str((char*)arg->ptr1,arg->ptr2 ? (char*)arg->ptr2 : "");
|
||||
var = (char*)arg->ptr1;
|
||||
val = arg->ptr2 ? (char*)arg->ptr2 : "";
|
||||
if (val[0]=='\\' && (val[1]=='%' || val[1]=='#'))
|
||||
// escape char
|
||||
lua_pushf_str(var, val+1);
|
||||
else if (val[0]=='%')
|
||||
lua_pushf_blob(idx_desync, var, val+1);
|
||||
else if (val[0]=='#')
|
||||
{
|
||||
lua_push_blob(idx_desync, val+1);
|
||||
lua_Integer len = lua_rawlen(params.L, -1);
|
||||
lua_pop(params.L,1);
|
||||
lua_pushf_int(var, len);
|
||||
}
|
||||
else
|
||||
lua_pushf_str(var, val);
|
||||
}
|
||||
lua_rawset(params.L,-3);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
|
||||
|
||||
@@ -1007,6 +1198,8 @@ static void lua_reconstruct_extract_options(lua_State *L, int idx, bool *badsum,
|
||||
|
||||
static bool lua_reconstruct_ip6exthdr(int idx, struct ip6_hdr *ip6, size_t *len, uint8_t proto, bool preserve_next)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
// proto = last header type
|
||||
if (*len<sizeof(struct tcphdr)) return false;
|
||||
|
||||
@@ -1062,16 +1255,21 @@ static bool lua_reconstruct_ip6exthdr(int idx, struct ip6_hdr *ip6, size_t *len,
|
||||
|
||||
*len = filled;
|
||||
lua_pop(params.L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return true;
|
||||
err2:
|
||||
lua_pop(params.L, 2);
|
||||
return false;
|
||||
goto err;
|
||||
err3:
|
||||
lua_pop(params.L, 3);
|
||||
err:
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return false;
|
||||
}
|
||||
bool lua_reconstruct_ip6hdr(int idx, struct ip6_hdr *ip6, size_t *len, uint8_t last_proto, bool preserve_next)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
const char *p;
|
||||
size_t l;
|
||||
if (*len<sizeof(struct ip6_hdr) || lua_type(params.L,idx)!=LUA_TTABLE) return false;
|
||||
@@ -1111,6 +1309,8 @@ bool lua_reconstruct_ip6hdr(int idx, struct ip6_hdr *ip6, size_t *len, uint8_t l
|
||||
return lua_reconstruct_ip6exthdr(idx, ip6, len, last_proto, preserve_next);
|
||||
err:
|
||||
lua_pop(params.L, 1);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1139,6 +1339,8 @@ bool lua_reconstruct_iphdr(int idx, struct ip *ip, size_t *len)
|
||||
const char *p;
|
||||
size_t l, lopt=0;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
if (*len<sizeof(struct ip) || lua_type(params.L,-1)!=LUA_TTABLE) return false;
|
||||
|
||||
ip->ip_v = IPVERSION;
|
||||
@@ -1202,9 +1404,11 @@ bool lua_reconstruct_iphdr(int idx, struct ip *ip, size_t *len)
|
||||
|
||||
ip4_fix_checksum(ip);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return true;
|
||||
err:
|
||||
lua_pop(params.L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return false;
|
||||
}
|
||||
static int luacall_reconstruct_iphdr(lua_State *L)
|
||||
@@ -1226,6 +1430,8 @@ static bool lua_reconstruct_tcphdr_options(int idx, struct tcphdr *tcp, size_t *
|
||||
{
|
||||
if (*len<sizeof(struct tcphdr)) return false;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
uint8_t filled = sizeof(struct tcphdr);
|
||||
|
||||
lua_getfield(params.L,idx,"options");
|
||||
@@ -1297,21 +1503,26 @@ end:
|
||||
*len = filled;
|
||||
|
||||
lua_pop(params.L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return true;
|
||||
err1:
|
||||
lua_pop(params.L, 1);
|
||||
return false;
|
||||
goto err;
|
||||
err2:
|
||||
lua_pop(params.L, 2);
|
||||
return false;
|
||||
goto err;
|
||||
err3:
|
||||
lua_pop(params.L, 3);
|
||||
err:
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return false;
|
||||
}
|
||||
bool lua_reconstruct_tcphdr(int idx, struct tcphdr *tcp, size_t *len)
|
||||
{
|
||||
if (*len<sizeof(struct tcphdr) || lua_type(params.L,-1)!=LUA_TTABLE) return false;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
idx = lua_absindex(params.L, idx);
|
||||
|
||||
lua_getfield(params.L,idx,"th_sport");
|
||||
@@ -1358,9 +1569,11 @@ bool lua_reconstruct_tcphdr(int idx, struct tcphdr *tcp, size_t *len)
|
||||
|
||||
tcp->th_off = 5;
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return lua_reconstruct_tcphdr_options(idx, tcp, len);
|
||||
err:
|
||||
lua_pop(params.L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return false;
|
||||
}
|
||||
static int luacall_reconstruct_tcphdr(lua_State *L)
|
||||
@@ -1382,6 +1595,8 @@ bool lua_reconstruct_udphdr(int idx, struct udphdr *udp)
|
||||
{
|
||||
if (lua_type(params.L,-1)!=LUA_TTABLE) return false;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
lua_getfield(params.L,idx,"uh_sport");
|
||||
if (lua_type(params.L,-1)!=LUA_TNUMBER) goto err;
|
||||
udp->uh_sport = htons((uint16_t)lua_tointeger(params.L,-1));
|
||||
@@ -1400,9 +1615,11 @@ bool lua_reconstruct_udphdr(int idx, struct udphdr *udp)
|
||||
udp->uh_sum = htons((uint16_t)lua_tointeger(params.L,-1));
|
||||
lua_pop(params.L, 1);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return true;
|
||||
err:
|
||||
lua_pop(params.L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return false;
|
||||
}
|
||||
static int luacall_reconstruct_udphdr(lua_State *L)
|
||||
@@ -1443,6 +1660,8 @@ bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bo
|
||||
struct udphdr *udp=NULL;
|
||||
const char *p;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
idx = lua_absindex(params.L, idx);
|
||||
|
||||
lua_getfield(params.L,idx,"ip");
|
||||
@@ -1578,9 +1797,11 @@ bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bo
|
||||
}
|
||||
|
||||
*len = l;
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return true;
|
||||
err:
|
||||
lua_pop(params.L, 1);
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
return false;
|
||||
}
|
||||
static int luacall_reconstruct_dissect(lua_State *L)
|
||||
@@ -1829,6 +2050,7 @@ static int luacall_rawsend(lua_State *L)
|
||||
if (!extract_dst(data, len, (struct sockaddr*)&sa))
|
||||
luaL_error(L, "bad ip4/ip6 header");
|
||||
DLOG("rawsend repeats=%d size=%zu ifout=%s fwmark=%08X\n", repeats,len,ifout ? ifout : "",fwmark);
|
||||
|
||||
b = rawsend_rep(repeats, (struct sockaddr*)&sa, fwmark, ifout, data, len);
|
||||
lua_pushboolean(L, b);
|
||||
|
||||
@@ -1853,7 +2075,7 @@ static int luacall_rawsend_dissect(lua_State *L)
|
||||
luaL_checktype(L,1,LUA_TTABLE);
|
||||
lua_rawsend_extract_options(L,2, &repeats, &fwmark, &ifout);
|
||||
lua_reconstruct_extract_options(params.L, 3, &badsum, &ip6_preserve_next, NULL);
|
||||
|
||||
|
||||
if (!lua_reconstruct_dissect(1, buf, &len, badsum, ip6_preserve_next))
|
||||
luaL_error(L, "invalid dissect data");
|
||||
|
||||
@@ -2244,6 +2466,8 @@ void lua_shutdown()
|
||||
if (params.L)
|
||||
{
|
||||
DLOG("LUA SHUTDOWN\n");
|
||||
// conntrack holds lua state. must clear it before lua shoudown
|
||||
ConntrackPoolDestroy(¶ms.conntrack);
|
||||
lua_close(params.L);
|
||||
params.L=NULL;
|
||||
}
|
||||
@@ -2328,6 +2552,20 @@ static bool lua_desync_functions_exist()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lua_test_init_script_files(void)
|
||||
{
|
||||
struct str_list *str;
|
||||
LIST_FOREACH(str, ¶ms.lua_init_scripts, next)
|
||||
{
|
||||
if (str->str[0]=='@' && !file_open_test(str->str+1, O_RDONLY))
|
||||
{
|
||||
DLOG_ERR("LUA file '%s' not accessible\n",str->str+1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lua_init_scripts(void)
|
||||
{
|
||||
struct str_list *str;
|
||||
@@ -2380,13 +2618,16 @@ static void lua_sec_harden(void)
|
||||
{
|
||||
lua_getfield(params.L, -1, bad[i].field);
|
||||
lua_pushstring(params.L, bad[i].field2);
|
||||
DLOG(" %s.%s.%s", bad[i].global, bad[i].field, bad[i].field2);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushstring(params.L, bad[i].field);
|
||||
DLOG(" %s.%s", bad[i].global, bad[i].field);
|
||||
}
|
||||
lua_pushnil(params.L);
|
||||
lua_rawset(params.L, -3);
|
||||
lua_pop(params.L,1 + !!bad[i].field2);
|
||||
DLOG(" %s.%s", bad[i].global, bad[i].field);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2562,11 +2803,14 @@ static void lua_init_functions(void)
|
||||
{"u16",luacall_u16},
|
||||
{"u24",luacall_u24},
|
||||
{"u32",luacall_u32},
|
||||
// convert number to blob (string)
|
||||
// convert number to blob (string) - big endian
|
||||
{"bu8",luacall_bu8},
|
||||
{"bu16",luacall_bu16},
|
||||
{"bu24",luacall_bu24},
|
||||
{"bu32",luacall_bu32},
|
||||
// swap byte order
|
||||
{"swap16",luacall_swap16},
|
||||
{"swap32",luacall_swap32},
|
||||
|
||||
// integer division
|
||||
{"divint",luacall_divint},
|
||||
@@ -2592,6 +2836,14 @@ static void lua_init_functions(void)
|
||||
|
||||
// voluntarily stop receiving packets
|
||||
{"instance_cutoff",luacall_instance_cutoff},
|
||||
// get raw packet data
|
||||
{"raw_packet",luacall_raw_packet},
|
||||
|
||||
// system functions
|
||||
{"uname",luacall_uname},
|
||||
{"clock_gettime",luacall_clock_gettime},
|
||||
{"getpid",luacall_getpid},
|
||||
{"gettid",luacall_gettid},
|
||||
|
||||
// convert table representation to blob or vise versa
|
||||
{"reconstruct_tcphdr",luacall_reconstruct_tcphdr},
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define LUA_STACK_GUARD_RETURN(L,N) LUA_STACK_GUARD_LEAVE(L,N); return N;
|
||||
|
||||
|
||||
bool lua_test_init_script_files(void);
|
||||
bool lua_init(void);
|
||||
void lua_shutdown(void);
|
||||
void lua_dlog_error(void);
|
||||
@@ -35,6 +36,7 @@ void lua_do_gc(void);
|
||||
|
||||
#if LUA_VERSION_NUM < 502
|
||||
int lua_absindex(lua_State *L, int idx);
|
||||
#define lua_rawlen lua_objlen
|
||||
#endif
|
||||
|
||||
// push - create object and push to the stack
|
||||
@@ -56,6 +58,9 @@ void lua_pushf_lud(const char *field, void *p);
|
||||
void lua_pushf_table(const char *field);
|
||||
void lua_pushi_table(lua_Integer idx);
|
||||
|
||||
void lua_push_blob(int idx_desync, const char *blob);
|
||||
void lua_pushf_blob(int idx_desync, const char *field, const char *blob);
|
||||
|
||||
void lua_pushf_tcphdr_options(const struct tcphdr *tcp, size_t len);
|
||||
void lua_pushf_tcphdr(const struct tcphdr *tcp, size_t len);
|
||||
void lua_pushf_udphdr(const struct udphdr *udp, size_t len);
|
||||
@@ -64,7 +69,7 @@ void lua_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len);
|
||||
void lua_push_dissect(const struct dissect *dis);
|
||||
void lua_pushf_dissect(const struct dissect *dis);
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack);
|
||||
void lua_pushf_args(const struct ptr_list_head *args);
|
||||
void lua_pushf_args(const struct ptr_list_head *args, int idx_desync);
|
||||
void lua_pushf_global(const char *field, const char *global);
|
||||
|
||||
bool lua_reconstruct_ip6hdr(int idx, struct ip6_hdr *ip6, size_t *len, uint8_t last_proto, bool preserve_next);
|
||||
@@ -77,6 +82,7 @@ typedef struct {
|
||||
const char *func, *instance;
|
||||
const struct desync_profile *dp;
|
||||
const t_ctrack *ctrack;
|
||||
const struct dissect *dis;
|
||||
} t_lua_desync_context;
|
||||
|
||||
bool lua_instance_cutoff_check(const t_lua_desync_context *ctx, bool bIn);
|
||||
|
||||
89
nfq2/nfqws.c
89
nfq2/nfqws.c
@@ -12,6 +12,7 @@
|
||||
#include "gzip.h"
|
||||
#include "pools.h"
|
||||
#include "lua.h"
|
||||
#include "crypto/aes.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -303,6 +304,8 @@ static int nfq_main(void)
|
||||
print_id();
|
||||
if (params.droproot && !test_list_files())
|
||||
goto err;
|
||||
if (!lua_test_init_script_files())
|
||||
goto err;
|
||||
|
||||
sec_harden();
|
||||
|
||||
@@ -461,6 +464,8 @@ static int dvt_main(void)
|
||||
print_id();
|
||||
if (params.droproot && !test_list_files())
|
||||
goto exiterr;
|
||||
if (!lua_test_init_script_files())
|
||||
goto exiterr;
|
||||
|
||||
if (!lua_init())
|
||||
goto exiterr;
|
||||
@@ -601,11 +606,6 @@ static int win_main()
|
||||
return ERROR_TOO_MANY_OPEN_FILES; // code 4 = The system cannot open the file
|
||||
}
|
||||
|
||||
if (!lua_init())
|
||||
{
|
||||
res=ERROR_INVALID_PARAMETER; goto ex;
|
||||
}
|
||||
|
||||
if (!win_dark_init(¶ms.ssid_filter, ¶ms.nlm_filter))
|
||||
{
|
||||
DLOG_ERR("win_dark_init failed. win32 error %u (0x%08X)\n", w_win32_error, w_win32_error);
|
||||
@@ -635,6 +635,19 @@ static int win_main()
|
||||
{
|
||||
res=w_win32_error; goto ex;
|
||||
}
|
||||
if (!win_sandbox())
|
||||
{
|
||||
res=w_win32_error;
|
||||
DLOG_ERR("Cannot init Windows sandbox\n");
|
||||
goto ex;
|
||||
}
|
||||
|
||||
|
||||
// init LUA only here because of possible sandbox. no LUA code with high privs
|
||||
if (!params.L && !lua_init())
|
||||
{
|
||||
res=ERROR_INVALID_PARAMETER; goto ex;
|
||||
}
|
||||
|
||||
DLOG_CONDUP("windivert initialized. capture is started.\n");
|
||||
|
||||
@@ -1020,7 +1033,7 @@ bool lua_call_param_add(char *opt, struct ptr_list_head *args)
|
||||
struct func_list *parse_lua_call(char *opt, struct func_list_head *flist)
|
||||
{
|
||||
char *name, *e, *p, c;
|
||||
bool b;
|
||||
bool b,last;
|
||||
struct func_list *f = NULL;
|
||||
|
||||
if (!(name = item_name(&opt)))
|
||||
@@ -1031,14 +1044,18 @@ struct func_list *parse_lua_call(char *opt, struct func_list_head *flist)
|
||||
|
||||
for (p = opt; p && *p; )
|
||||
{
|
||||
if ((e = strchr(p, ':')))
|
||||
for(e=p; *e && *e!=':'; e++)
|
||||
{
|
||||
c = *e;
|
||||
*e = 0;
|
||||
if (e[0]=='\\' && e[1]==':')
|
||||
memmove(e,e+1,strlen(e)); // swallow escape symbol
|
||||
}
|
||||
|
||||
last = !*e;
|
||||
c = *e;
|
||||
*e = 0;
|
||||
|
||||
b = lua_call_param_add(p, &f->args);
|
||||
if (e) *e++ = c;
|
||||
if (!last) *e++ = c;
|
||||
if (!b) goto err;
|
||||
|
||||
p = e;
|
||||
@@ -1153,7 +1170,7 @@ static void LuaDesyncDebug(struct desync_profile *dp)
|
||||
LIST_FOREACH(arg, &func->args, next)
|
||||
{
|
||||
if (n) DLOG(",");
|
||||
DLOG(arg->ptr2 ? "%s=\"%s\"" : "%s=nil", (char*)arg->ptr1, (char*)arg->ptr2);
|
||||
DLOG(arg->ptr2 ? "%s=\"%s\"" : "%s=\"\"", (char*)arg->ptr1, (char*)arg->ptr2);
|
||||
n++;
|
||||
}
|
||||
DLOG(" range_in=%c%u%c%c%u range_out=%c%u%c%c%u payload_type=",
|
||||
@@ -1390,6 +1407,7 @@ static void exithelp(void)
|
||||
" --nlm-list[=all]\t\t\t\t\t; list Network List Manager (NLM) networks. connected only or all.\n"
|
||||
#endif
|
||||
"\nDESYNC ENGINE INIT:\n"
|
||||
" --writeable[=<dir_name>]\t\t\t\t; create writeable dir for LUA scripts and pass it in WRITEABLE env variable (only one dir possible)\n"
|
||||
" --blob=<item_name>:[+ofs]@<filename>|0xHEX\t\t; load blob to LUA var <item_name>\n"
|
||||
" --lua-init=@<filename>|<lua_text>\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved.\n"
|
||||
" --lua-gc=<int>\t\t\t\t\t\t; forced garbage collection every N sec. default %u sec. triggers only when a packet arrives. 0 = disable.\n"
|
||||
@@ -1528,6 +1546,8 @@ enum opt_indices {
|
||||
IDX_SOCKARG,
|
||||
#endif
|
||||
|
||||
IDX_WRITEABLE,
|
||||
|
||||
IDX_BLOB,
|
||||
IDX_LUA_INIT,
|
||||
IDX_LUA_GC,
|
||||
@@ -1608,6 +1628,7 @@ static const struct option long_options[] = {
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
[IDX_SOCKARG] = {"sockarg", required_argument, 0, 0},
|
||||
#endif
|
||||
[IDX_WRITEABLE] = {"writeable", optional_argument, 0, 0},
|
||||
[IDX_BLOB] = {"blob", required_argument, 0, 0},
|
||||
[IDX_LUA_INIT] = {"lua-init", required_argument, 0, 0},
|
||||
[IDX_LUA_GC] = {"lua-gc", required_argument, 0, 0},
|
||||
@@ -1662,10 +1683,12 @@ int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) exithelp();
|
||||
|
||||
aes_init_keygen_tables(); // required for aes
|
||||
set_console_io_buffering();
|
||||
set_env_exedir(argv[0]);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
prepare_low_appdata();
|
||||
if (service_run(argc, argv))
|
||||
{
|
||||
// we were running as service. now exit.
|
||||
@@ -1680,11 +1703,10 @@ int main(int argc, char **argv)
|
||||
uint64_t payload_type=0;
|
||||
struct packet_range range_in = PACKET_RANGE_NEVER, range_out = PACKET_RANGE_ALWAYS;
|
||||
#ifdef __CYGWIN__
|
||||
char wf_save_file[256];
|
||||
char wf_save_file[256]="";
|
||||
bool wf_ipv4 = true, wf_ipv6 = true, wf_filter_lan = true, wf_tcp_empty = false;
|
||||
unsigned int IfIdx = 0, SubIfIdx = 0;
|
||||
unsigned int hash_wf_tcp_in = 0, hash_wf_udp_in = 0, hash_wf_tcp_out = 0, hash_wf_udp_out = 0, hash_wf_raw = 0, hash_wf_raw_part = 0, hash_ssid_filter = 0, hash_nlm_filter = 0;
|
||||
*wf_save_file = 0;
|
||||
#endif
|
||||
|
||||
srandom(time(NULL));
|
||||
@@ -1954,6 +1976,17 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case IDX_WRITEABLE:
|
||||
params.writeable_dir_enable = true;
|
||||
if (optarg)
|
||||
{
|
||||
strncpy(params.writeable_dir, optarg, sizeof(params.writeable_dir));
|
||||
params.writeable_dir[sizeof(params.writeable_dir) - 1] = 0;
|
||||
}
|
||||
else
|
||||
*params.writeable_dir = 0;
|
||||
break;
|
||||
|
||||
case IDX_BLOB:
|
||||
load_blob_to_collection(optarg, ¶ms.blobs, MAX_BLOB_SIZE, BLOB_EXTRA_BYTES);
|
||||
break;
|
||||
@@ -2398,12 +2431,24 @@ int main(int argc, char **argv)
|
||||
|
||||
DLOG_CONDUP("we have %d user defined desync profile(s) and default low priority profile 0\n", desync_profile_count);
|
||||
|
||||
if (params.writeable_dir_enable)
|
||||
{
|
||||
if (!make_writeable_dir())
|
||||
{
|
||||
DLOG_ERR("could not make writeable dir for LUA\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
DLOG("LUA writeable dir : %s\n", getenv("WRITEABLE"));
|
||||
}
|
||||
#ifndef __CYGWIN__
|
||||
if (params.debug_target == LOG_TARGET_FILE && params.droproot && chown(params.debug_logfile, params.uid, -1))
|
||||
fprintf(stderr, "could not chown %s. log file may not be writable after privilege drop\n", params.debug_logfile);
|
||||
if (params.droproot && *params.hostlist_auto_debuglog && chown(params.hostlist_auto_debuglog, params.uid, -1))
|
||||
DLOG_ERR("could not chown %s. auto hostlist debug log may not be writable after privilege drop\n", params.hostlist_auto_debuglog);
|
||||
if (params.droproot)
|
||||
#endif
|
||||
{
|
||||
if (params.debug_target == LOG_TARGET_FILE && !ensure_file_access(params.debug_logfile))
|
||||
DLOG_ERR("could not make '%s' accessible. log file may not be writable after privilege drop\n", params.debug_logfile);
|
||||
if (*params.hostlist_auto_debuglog && !ensure_file_access(params.hostlist_auto_debuglog))
|
||||
DLOG_ERR("could not make '%s' accessible. auto hostlist debug log may not be writable after privilege drop\n", params.hostlist_auto_debuglog);
|
||||
}
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
dp = &dpl->dp;
|
||||
@@ -2415,14 +2460,20 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
if (params.droproot && dp->hostlist_auto && chown(dp->hostlist_auto->filename, params.uid, -1))
|
||||
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", dp->hostlist_auto->filename);
|
||||
if (params.droproot)
|
||||
#endif
|
||||
{
|
||||
if (dp->hostlist_auto && ensure_file_access(dp->hostlist_auto->filename))
|
||||
DLOG_ERR("could not make '%s' accessible. auto hostlist file may not be writable after privilege drop\n", dp->hostlist_auto->filename);
|
||||
|
||||
}
|
||||
LuaDesyncDebug(dp);
|
||||
}
|
||||
|
||||
if (!test_list_files())
|
||||
exit_clean(1);
|
||||
if (!lua_test_init_script_files())
|
||||
exit_clean(1);
|
||||
|
||||
if (!LoadAllHostLists())
|
||||
{
|
||||
|
||||
@@ -88,21 +88,21 @@ const uint8_t fake_tls_clienthello_default[680] = {
|
||||
|
||||
const char * tld[6] = { "com","org","net","edu","gov","biz" };
|
||||
|
||||
int DLOG_FILE(FILE *F, const char *format, va_list args)
|
||||
int DLOG_FILE_VA(FILE *F, const char *format, va_list args)
|
||||
{
|
||||
return vfprintf(F, format, args);
|
||||
}
|
||||
int DLOG_CON(const char *format, int syslog_priority, va_list args)
|
||||
int DLOG_CON_VA(const char *format, int syslog_priority, va_list args)
|
||||
{
|
||||
return DLOG_FILE(syslog_priority==LOG_ERR ? stderr : stdout, format, args);
|
||||
return DLOG_FILE_VA(syslog_priority==LOG_ERR ? stderr : stdout, format, args);
|
||||
}
|
||||
int DLOG_FILENAME(const char *filename, const char *format, va_list args)
|
||||
int DLOG_FILENAME_VA(const char *filename, const char *format, va_list args)
|
||||
{
|
||||
int r;
|
||||
FILE *F = fopen(filename,"at");
|
||||
if (F)
|
||||
{
|
||||
r = DLOG_FILE(F, format, args);
|
||||
r = DLOG_FILE_VA(F, format, args);
|
||||
fclose(F);
|
||||
}
|
||||
else
|
||||
@@ -118,6 +118,21 @@ static void syslog_log_function(int priority, const char *line)
|
||||
{
|
||||
syslog(priority,"%s",log_buf);
|
||||
}
|
||||
|
||||
static int DLOG_FILENAME(const char *filename, const char *format, ...)
|
||||
{
|
||||
int r;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
r = DLOG_FILENAME_VA(filename, format, args);
|
||||
va_end(args);
|
||||
return r;
|
||||
}
|
||||
static void file_log_function(int priority, const char *line)
|
||||
{
|
||||
DLOG_FILENAME(params.debug_logfile,"%s",log_buf);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
static enum android_LogPriority syslog_priority_to_android(int priority)
|
||||
{
|
||||
@@ -163,7 +178,7 @@ static int DLOG_VA(const char *format, int syslog_priority, bool condup, va_list
|
||||
if (condup && !(params.debug && params.debug_target==LOG_TARGET_CONSOLE))
|
||||
{
|
||||
va_copy(args2,args);
|
||||
DLOG_CON(format,syslog_priority,args2);
|
||||
DLOG_CON_VA(format,syslog_priority,args2);
|
||||
va_end(args2);
|
||||
}
|
||||
if (params.debug)
|
||||
@@ -171,10 +186,11 @@ static int DLOG_VA(const char *format, int syslog_priority, bool condup, va_list
|
||||
switch(params.debug_target)
|
||||
{
|
||||
case LOG_TARGET_CONSOLE:
|
||||
r = DLOG_CON(format,syslog_priority,args);
|
||||
r = DLOG_CON_VA(format,syslog_priority,args);
|
||||
break;
|
||||
case LOG_TARGET_FILE:
|
||||
r = DLOG_FILENAME(params.debug_logfile,format,args);
|
||||
log_buffered(file_log_function,syslog_priority,format,args);
|
||||
r = 1;
|
||||
break;
|
||||
case LOG_TARGET_SYSLOG:
|
||||
// skip newlines
|
||||
@@ -271,10 +287,39 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
|
||||
bcut = true;
|
||||
}
|
||||
if (!size) return;
|
||||
for (k = 0; k < size; k++) DLOG("%02X ", data[k]);
|
||||
DLOG(bcut ? "... : " : ": ");
|
||||
for (k = 0; k < size; k++) DLOG("%c", data[k] >= 0x20 && data[k] <= 0x7F ? (char)data[k] : '.');
|
||||
if (bcut) DLOG(" ...");
|
||||
|
||||
char *p, *buf = malloc(size*4 + 16);
|
||||
if (buf)
|
||||
{
|
||||
p=buf;
|
||||
for (k = 0; k < size; k++)
|
||||
{
|
||||
*p++ = hex_digit(data[k] >> 4);
|
||||
*p++ = hex_digit(data[k] & 0xF);
|
||||
*p++ = ' ';
|
||||
}
|
||||
if (bcut)
|
||||
{
|
||||
*p++='.';
|
||||
*p++='.';
|
||||
*p++='.';
|
||||
*p++=' ';
|
||||
}
|
||||
*p++=':';
|
||||
*p++=' ';
|
||||
for (k = 0; k < size; k++)
|
||||
*p++ = data[k] >= 0x20 && data[k] <= 0x7F ? (char)data[k] : '.';
|
||||
if (bcut)
|
||||
{
|
||||
*p++=' ';
|
||||
*p++='.';
|
||||
*p++='.';
|
||||
*p++='.';
|
||||
}
|
||||
*p = 0;
|
||||
DLOG("%s", buf);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void dp_init(struct desync_profile *dp)
|
||||
@@ -381,9 +426,7 @@ void cleanup_params(struct params_s *params)
|
||||
#endif
|
||||
|
||||
ConntrackPoolDestroy(¶ms->conntrack);
|
||||
|
||||
dp_list_destroy(¶ms->desync_profiles);
|
||||
|
||||
hostlist_files_destroy(¶ms->hostlists);
|
||||
ipset_files_destroy(¶ms->ipsets);
|
||||
ipcacheDestroy(¶ms->ipcache);
|
||||
|
||||
@@ -161,6 +161,8 @@ struct params_s
|
||||
uint64_t reasm_payload_disable;
|
||||
|
||||
struct str_list_head lua_init_scripts;
|
||||
bool writeable_dir_enable;
|
||||
char writeable_dir[PATH_MAX];
|
||||
|
||||
int lua_gc;
|
||||
lua_State *L;
|
||||
|
||||
@@ -748,7 +748,7 @@ bool TLSMod(const struct fake_tls_mod *tls_mod, const uint8_t *payload, size_t p
|
||||
char *s1 = NULL;
|
||||
if (params.debug)
|
||||
if ((s1 = malloc(slen + 1)))
|
||||
memcpy(s1, sni, slen); s1[slen] = 0;
|
||||
{memcpy(s1, sni, slen); s1[slen] = 0;}
|
||||
if (slen_delta)
|
||||
{
|
||||
if ((*fake_tls_size + slen_delta) > fake_tls_buf_size)
|
||||
@@ -1151,8 +1151,6 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
|
||||
pn_offset += tvb_get_varint(data + pn_offset, &payload_len);
|
||||
if (payload_len<20 || (pn_offset + payload_len)>data_len) return false;
|
||||
|
||||
aes_init_keygen_tables();
|
||||
|
||||
uint8_t sample_enc[16];
|
||||
aes_context ctx;
|
||||
if (aes_setkey(&ctx, 1, aeshp, sizeof(aeshp)) || aes_cipher(&ctx, data + pn_offset + 4, sample_enc)) return false;
|
||||
@@ -1390,12 +1388,29 @@ bool IsStunBindingRequest(const uint8_t *data, size_t len)
|
||||
ntohl(*(uint32_t*)(&data[4]))==0x2112A442 && // magic cookie
|
||||
ntohs(*(uint16_t*)(&data[2]))==len-20;
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__llvm__)
|
||||
__attribute__((optimize ("no-strict-aliasing")))
|
||||
#endif
|
||||
bool IsMTProto(const uint8_t *data, size_t len)
|
||||
{
|
||||
if (len>=64)
|
||||
{
|
||||
/*
|
||||
uint8_t decrypt[64];
|
||||
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];
|
||||
aes_context ctx;
|
||||
|
||||
memcpy(iv, data+40, 16);
|
||||
ctr_add(iv,3);
|
||||
if (!aes_setkey(&ctx, AES_ENCRYPT, data+8, 32) && !aes_cipher(&ctx, iv, decrypt))
|
||||
{
|
||||
*((uint32_t*)(decrypt+8)) ^= *((uint32_t*)(data+56));
|
||||
return !memcmp(decrypt+8,"\xEF\xEF\xEF\xEF",4);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
11
nfq2/sec.c
11
nfq2/sec.c
@@ -37,9 +37,6 @@ SYS_exec_with_loader,
|
||||
#ifdef SYS_osf_execve
|
||||
SYS_osf_execve,
|
||||
#endif
|
||||
#ifdef SYS_uselib
|
||||
SYS_uselib,
|
||||
#endif
|
||||
#ifdef SYS_chmod
|
||||
SYS_chmod,
|
||||
#endif
|
||||
@@ -69,14 +66,6 @@ SYS_symlinkat,
|
||||
SYS_link,
|
||||
#endif
|
||||
SYS_linkat,
|
||||
SYS_truncate,
|
||||
#ifdef SYS_truncate64
|
||||
SYS_truncate64,
|
||||
#endif
|
||||
SYS_ftruncate,
|
||||
#ifdef SYS_ftruncate64
|
||||
SYS_ftruncate64,
|
||||
#endif
|
||||
#ifdef SYS_mknod
|
||||
SYS_mknod,
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user