mirror of
https://github.com/bol-van/zapret.git
synced 2026-09-19 14:54:51 +09:00
Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c8e4ed15d | |||
| 8c06a6335d | |||
| f12cae3674 | |||
| 170281bfa6 | |||
| 5d4747458f | |||
| 5774e883d6 | |||
| 80b801c1ca | |||
| 9d8ee398c3 | |||
| 4d35d8d1ec | |||
| 977d117417 | |||
| cc8313db51 | |||
| 1e51f90130 | |||
| da6b89e739 | |||
| 90470440a7 | |||
| a5c9d79417 | |||
| c003ef2a7b | |||
| 42541fcab8 | |||
| 20b5952978 | |||
| 4b6aa1b5f9 | |||
| 9e141dcefd | |||
| b1b992eb3f | |||
| 2d061c911a | |||
| a213084188 | |||
| 1c7ec32b96 | |||
| dcd9cfbb2b | |||
| beb0692d28 | |||
| 140af2b741 | |||
| f8cc109f0b | |||
| b4a2f44d56 | |||
| 14d05d8012 | |||
| 71d5afeaf4 | |||
| 45df8bfb09 | |||
| 784058cf66 | |||
| ce367b1a91 | |||
| a832c19974 | |||
| 2c14109163 | |||
| c467e696e3 | |||
| 528c27a01a | |||
| c2f1e708fc | |||
| 211a4f4673 | |||
| fd81053d79 | |||
| 1bb9f260dd | |||
| 26f3cbd06f | |||
| e384f88931 | |||
| 59bce0036b | |||
| 0a48c923b8 | |||
| ed4782887f | |||
| 80b6b75934 | |||
| 245ce41550 | |||
| db5dca28b0 | |||
| 6dad239fe3 | |||
| aa4982a526 | |||
| 61808b37d8 | |||
| 4b90ee920c | |||
| 170e9d7ffd | |||
| d8f9ba29c3 | |||
| 4914b813e7 | |||
| c3fdec9bf0 | |||
| 1cbdf9b891 | |||
| 706dd7b2d9 | |||
| b2468a9095 | |||
| acfbbc58ac | |||
| fd506dfe08 | |||
| 1ee25e01ea | |||
| 521c385adb | |||
| 17971e87b4 | |||
| 4dc1d035d8 | |||
| 07eee8af25 | |||
| 06e7818240 | |||
| 00b0f3c940 | |||
| 17df2adbe0 | |||
| 40342745f7 | |||
| 54d4cdb2d5 | |||
| b251ea839c | |||
| 595cf863fc | |||
| 91d5b90ded | |||
| 33a7132920 | |||
| d9b23f14a2 | |||
| 06613b4fd5 |
+141
-22
@@ -47,6 +47,7 @@ HTTPS_PORT=${HTTPS_PORT:-443}
|
|||||||
QUIC_PORT=${QUIC_PORT:-443}
|
QUIC_PORT=${QUIC_PORT:-443}
|
||||||
UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org}
|
UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org}
|
||||||
PARALLEL_OUT=/tmp/zapret_parallel
|
PARALLEL_OUT=/tmp/zapret_parallel
|
||||||
|
SIM_SUCCESS_RATE=${SIM_SUCCESS_RATE:-10}
|
||||||
|
|
||||||
HDRTEMP=/tmp/zapret-hdr
|
HDRTEMP=/tmp/zapret-hdr
|
||||||
|
|
||||||
@@ -411,6 +412,13 @@ check_system()
|
|||||||
else
|
else
|
||||||
uname -a
|
uname -a
|
||||||
fi
|
fi
|
||||||
|
[ -f /etc/os-release ] && {
|
||||||
|
. /etc/os-release
|
||||||
|
[ -n "$PRETTY_NAME" ] && echo "distro: $PRETTY_NAME"
|
||||||
|
[ -n "$OPENWRT_RELEASE" ] && echo "openwrt release: $OPENWRT_RELEASE"
|
||||||
|
[ -n "$OPENWRT_BOARD" ] && echo "openwrt board: $OPENWRT_BOARD"
|
||||||
|
[ -n "$OPENWRT_ARCH" ] && echo "openwrt arch: $OPENWRT_ARCH"
|
||||||
|
}
|
||||||
echo firewall type is $FWTYPE
|
echo firewall type is $FWTYPE
|
||||||
echo CURL=$CURL
|
echo CURL=$CURL
|
||||||
$CURL --version
|
$CURL --version
|
||||||
@@ -803,7 +811,7 @@ nft_scheme()
|
|||||||
make_comma_list iplist $3
|
make_comma_list iplist $3
|
||||||
|
|
||||||
nft add table inet $NFT_TABLE
|
nft add table inet $NFT_TABLE
|
||||||
nft "add chain inet $NFT_TABLE postnat { type filter hook output priority 102; }"
|
nft "add chain inet $NFT_TABLE postnat { type filter hook postrouting priority 102; }"
|
||||||
nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} $1 dport $2 mark and $DESYNC_MARK == 0 ip${ipver} daddr {$iplist} ct mark set ct mark or $DESYNC_MARK queue num $QNUM"
|
nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} $1 dport $2 mark and $DESYNC_MARK == 0 ip${ipver} daddr {$iplist} ct mark set ct mark or $DESYNC_MARK queue num $QNUM"
|
||||||
# for strategies with incoming packets involved (autottl)
|
# for strategies with incoming packets involved (autottl)
|
||||||
nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }"
|
nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }"
|
||||||
@@ -1063,6 +1071,17 @@ ws_curl_test()
|
|||||||
# $3 - domain
|
# $3 - domain
|
||||||
# $4,$5,$6, ... - ws params
|
# $4,$5,$6, ... - ws params
|
||||||
local code ws_start=$1 testf=$2 dom=$3
|
local code ws_start=$1 testf=$2 dom=$3
|
||||||
|
|
||||||
|
[ "$SIMULATE" = 1 ] && {
|
||||||
|
n=$(random 0 99)
|
||||||
|
if [ "$n" -lt "$SIM_SUCCESS_RATE" ]; then
|
||||||
|
echo "SUCCESS"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo "FAILED"
|
||||||
|
return 7
|
||||||
|
fi
|
||||||
|
}
|
||||||
shift
|
shift
|
||||||
shift
|
shift
|
||||||
shift
|
shift
|
||||||
@@ -1085,7 +1104,7 @@ tpws_curl_test()
|
|||||||
shift; shift;
|
shift; shift;
|
||||||
strategy="$@"
|
strategy="$@"
|
||||||
strategy_append_extra_tpws
|
strategy_append_extra_tpws
|
||||||
report_append "ipv${IPV} $dom $testf : tpws ${WF:+$WF }$strategy"
|
report_append "$dom" "$testf ipv${IPV}" "tpws ${WF:+$WF }$strategy"
|
||||||
}
|
}
|
||||||
return $code
|
return $code
|
||||||
}
|
}
|
||||||
@@ -1104,7 +1123,7 @@ pktws_curl_test()
|
|||||||
[ "$code" = 0 ] && {
|
[ "$code" = 0 ] && {
|
||||||
strategy="$@"
|
strategy="$@"
|
||||||
strategy_append_extra_pktws
|
strategy_append_extra_pktws
|
||||||
report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy"
|
report_append "$dom" "$testf ipv${IPV}" "$PKTWSD ${WF:+$WF }$strategy"
|
||||||
}
|
}
|
||||||
return $code
|
return $code
|
||||||
}
|
}
|
||||||
@@ -1144,8 +1163,35 @@ tpws_curl_test_update()
|
|||||||
|
|
||||||
report_append()
|
report_append()
|
||||||
{
|
{
|
||||||
|
# $1 - domain
|
||||||
|
# $2 - test function + ipver
|
||||||
|
# $3 - value
|
||||||
|
local hashstr hash hashvar hashcountvar val ct
|
||||||
|
|
||||||
|
# save resources if only one domain
|
||||||
|
[ "$DOMAINS_COUNT" -gt 1 ] && {
|
||||||
|
hashstr="$2 : $3"
|
||||||
|
hash="$(echo -n "$hashstr" | md5f)"
|
||||||
|
hashvar=RESHASH_${hash}
|
||||||
|
hashcountvar=${hashvar}_COUNTER
|
||||||
|
|
||||||
|
NRESHASH=${NRESHASH:-0}
|
||||||
|
|
||||||
|
eval val="\$$hashvar"
|
||||||
|
if [ -n "$val" ]; then
|
||||||
|
eval ct="\$$hashcountvar"
|
||||||
|
ct=$(($ct + 1))
|
||||||
|
eval $hashcountvar="\$ct"
|
||||||
|
else
|
||||||
|
eval $hashvar=\"$hashstr\"
|
||||||
|
eval $hashcountvar=1
|
||||||
|
eval RES_$NRESHASH="\$hash"
|
||||||
|
NRESHASH=$(($NRESHASH+1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
NREPORT=${NREPORT:-0}
|
NREPORT=${NREPORT:-0}
|
||||||
eval REPORT_${NREPORT}=\"$@\"
|
eval REPORT_${NREPORT}=\"$2 $1 : $3\"
|
||||||
NREPORT=$(($NREPORT+1))
|
NREPORT=$(($NREPORT+1))
|
||||||
}
|
}
|
||||||
report_print()
|
report_print()
|
||||||
@@ -1158,6 +1204,22 @@ report_print()
|
|||||||
n=$(($n+1))
|
n=$(($n+1))
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
result_intersection_print()
|
||||||
|
{
|
||||||
|
local n=0 hash hashvar hashcountvar ct val
|
||||||
|
while : ; do
|
||||||
|
eval hash=\"\$RES_$n\"
|
||||||
|
[ -n "$hash" ] || break
|
||||||
|
hashvar=RESHASH_${hash}
|
||||||
|
hashcountvar=${hashvar}_COUNTER
|
||||||
|
eval ct=\"\$$hashcountvar\"
|
||||||
|
[ "$ct" = "$DOMAINS_COUNT" ] && {
|
||||||
|
eval val=\"\$$hashvar\"
|
||||||
|
echo "$val"
|
||||||
|
}
|
||||||
|
n=$(($n + 1))
|
||||||
|
done
|
||||||
|
}
|
||||||
report_strategy()
|
report_strategy()
|
||||||
{
|
{
|
||||||
# $1 - test function
|
# $1 - test function
|
||||||
@@ -1169,23 +1231,26 @@ report_strategy()
|
|||||||
strategy="$(echo "$strategy" | xargs)"
|
strategy="$(echo "$strategy" | xargs)"
|
||||||
echo "!!!!! $1: working strategy found for ipv${IPV} $2 : $3 $strategy !!!!!"
|
echo "!!!!! $1: working strategy found for ipv${IPV} $2 : $3 $strategy !!!!!"
|
||||||
echo
|
echo
|
||||||
# report_append "ipv${IPV} $2 $1 : $3 ${WF:+$WF }$strategy"
|
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
echo "$1: $3 strategy for ipv${IPV} $2 not found"
|
echo "$1: $3 strategy for ipv${IPV} $2 not found"
|
||||||
echo
|
echo
|
||||||
report_append "ipv${IPV} $2 $1 : $3 not working"
|
report_append "$2" "$1 ipv${IPV}" "$3 not working"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
test_has_split()
|
|
||||||
{
|
|
||||||
contains "$1" split || contains "$1" disorder
|
|
||||||
}
|
|
||||||
test_has_fakedsplit()
|
test_has_fakedsplit()
|
||||||
{
|
{
|
||||||
contains "$1" fakedsplit || contains "$1" fakeddisorder
|
contains "$1" fakedsplit || contains "$1" fakeddisorder
|
||||||
}
|
}
|
||||||
|
test_has_split()
|
||||||
|
{
|
||||||
|
contains "$1" multisplit || contains "$1" multidisorder || test_has_fakedsplit "$1"
|
||||||
|
}
|
||||||
|
test_has_hostfakesplit()
|
||||||
|
{
|
||||||
|
contains "$1" hostfakesplit
|
||||||
|
}
|
||||||
test_has_fake()
|
test_has_fake()
|
||||||
{
|
{
|
||||||
[ "$1" = fake ] || starts_with "$1" fake,
|
[ "$1" = fake ] || starts_with "$1" fake,
|
||||||
@@ -1210,7 +1275,7 @@ pktws_curl_test_update_vary()
|
|||||||
# $5,$6,... - strategy
|
# $5,$6,... - strategy
|
||||||
|
|
||||||
local testf=$1 sec=$2 domain=$3 desync=$4 proto splits= pos fake ret=1
|
local testf=$1 sec=$2 domain=$3 desync=$4 proto splits= pos fake ret=1
|
||||||
local fake1=- fake2=- fake3=-
|
local fake1=- fake2=- fake3=- fake4=-
|
||||||
|
|
||||||
shift; shift; shift; shift
|
shift; shift; shift; shift
|
||||||
|
|
||||||
@@ -1219,18 +1284,27 @@ pktws_curl_test_update_vary()
|
|||||||
test_has_fake $desync && {
|
test_has_fake $desync && {
|
||||||
fake1="--dpi-desync-fake-$proto=0x00000000"
|
fake1="--dpi-desync-fake-$proto=0x00000000"
|
||||||
[ "$sec" = 0 ] || {
|
[ "$sec" = 0 ] || {
|
||||||
fake2="--dpi-desync-fake-tls=0x00000000 --dpi-desync-fake-tls=! --dpi-desync-fake-tls-mod=rnd,rndsni,dupsid"
|
fake2='--dpi-desync-fake-tls=0x00000000 --dpi-desync-fake-tls=! --dpi-desync-fake-tls-mod=rnd,rndsni,dupsid'
|
||||||
fake3="--dpi-desync-fake-tls-mod=rnd,dupsid,rndsni,padencap"
|
# this splits actual fake to '1603' and modified standard fake from offset 2
|
||||||
|
fake3='--dpi-desync-fake-tls=0x1603 --dpi-desync-fake-tls=!+2 --dpi-desync-fake-tls-mod=rnd,dupsid,rndsni --dpi-desync-fake-tcp-mod=seq'
|
||||||
|
fake4='--dpi-desync-fake-tls-mod=rnd,dupsid,rndsni,padencap'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if test_has_fakedsplit $desync ; then
|
if test_has_fakedsplit $desync ; then
|
||||||
splits="method+2 midsld"
|
splits="method+2 midsld"
|
||||||
[ "$sec" = 0 ] || splits="1 midsld"
|
[ "$sec" = 0 ] || splits="1 midsld"
|
||||||
|
# do not send fake first
|
||||||
|
fake1='--dpi-desync-fakedsplit-mod=altorder=1'
|
||||||
elif test_has_split $desync ; then
|
elif test_has_split $desync ; then
|
||||||
splits="method+2 midsld"
|
splits="method+2 midsld"
|
||||||
[ "$sec" = 0 ] || splits="1 midsld 1,midsld"
|
[ "$sec" = 0 ] || splits="1 midsld 1,midsld"
|
||||||
fi
|
fi
|
||||||
for fake in '' "$fake1" "$fake2" "$fake3" ; do
|
test_has_hostfakesplit $desync && {
|
||||||
|
fake1="--dpi-desync-hostfakesplit-mod=altorder=1"
|
||||||
|
fake2="--dpi-desync-hostfakesplit-midhost=midsld"
|
||||||
|
fake3="--dpi-desync-hostfakesplit-mod=altorder=1 --dpi-desync-hostfakesplit-midhost=midsld"
|
||||||
|
}
|
||||||
|
for fake in '' "$fake1" "$fake2" "$fake3" "$fake4" ; do
|
||||||
[ "$fake" = "-" ] && continue
|
[ "$fake" = "-" ] && continue
|
||||||
if [ -n "$splits" ]; then
|
if [ -n "$splits" ]; then
|
||||||
for pos in $splits ; do
|
for pos in $splits ; do
|
||||||
@@ -1257,7 +1331,7 @@ pktws_check_domain_http_bypass_()
|
|||||||
# $3 - domain
|
# $3 - domain
|
||||||
|
|
||||||
local ok ttls s f f2 e desync pos fooling frag sec="$2" delta orig splits
|
local ok ttls s f f2 e desync pos fooling frag sec="$2" delta orig splits
|
||||||
local need_split need_disorder need_fakedsplit need_fakeddisorder need_fake need_wssize
|
local need_split need_disorder need_fakedsplit need_hostfakesplit need_fakeddisorder need_fake need_wssize
|
||||||
local splits_http='method+2 midsld method+2,midsld'
|
local splits_http='method+2 midsld method+2,midsld'
|
||||||
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||||
|
|
||||||
@@ -1302,25 +1376,33 @@ pktws_check_domain_http_bypass_()
|
|||||||
done
|
done
|
||||||
|
|
||||||
need_fakedsplit=1
|
need_fakedsplit=1
|
||||||
|
need_hostfakesplit=1
|
||||||
need_fakeddisorder=1
|
need_fakeddisorder=1
|
||||||
need_fake=1
|
need_fake=1
|
||||||
for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do
|
for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit hostfakesplit fake,hostfakesplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do
|
||||||
[ "$need_fake" = 0 ] && test_has_fake "$desync" && continue
|
[ "$need_fake" = 0 ] && test_has_fake "$desync" && continue
|
||||||
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
|
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
|
||||||
|
[ "$need_hostfakesplit" = 0 ] && contains "$desync" hostfakesplit && continue
|
||||||
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
|
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
|
||||||
ok=0
|
ok=0
|
||||||
for ttl in $ttls; do
|
for ttl in $ttls; do
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-ttl=$ttl $e && {
|
# 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 '' '--orig-ttl=1 --orig-mod-start=s1 --orig-mod-cutoff=d1'; do
|
||||||
|
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-ttl=$ttl $f $e && {
|
||||||
[ "$SCANLEVEL" = quick ] && return
|
[ "$SCANLEVEL" = quick ] && return
|
||||||
ok=1
|
ok=1
|
||||||
need_wssize=0
|
need_wssize=0
|
||||||
break
|
[ "$SCANLEVEL" = force ] || break
|
||||||
}
|
}
|
||||||
done
|
done
|
||||||
|
[ "$ok" = 1 ] && break
|
||||||
|
done
|
||||||
# only skip tests if TTL succeeded. do not skip if TTL failed but fooling succeeded
|
# only skip tests if TTL succeeded. do not skip if TTL failed but fooling succeeded
|
||||||
[ $ok = 1 -a "$SCANLEVEL" != force ] && {
|
[ $ok = 1 -a "$SCANLEVEL" != force ] && {
|
||||||
[ "$desync" = fake ] && need_fake=0
|
[ "$desync" = fake ] && need_fake=0
|
||||||
[ "$desync" = fakedsplit ] && need_fakedsplit=0
|
[ "$desync" = fakedsplit ] && need_fakedsplit=0
|
||||||
|
[ "$desync" = hostfakesplit ] && need_hostfakesplit=0
|
||||||
[ "$desync" = fakeddisorder ] && need_fakeddisorder=0
|
[ "$desync" = fakeddisorder ] && need_fakeddisorder=0
|
||||||
}
|
}
|
||||||
f=
|
f=
|
||||||
@@ -1329,12 +1411,21 @@ pktws_check_domain_http_bypass_()
|
|||||||
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
|
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
|
||||||
for fooling in $f; do
|
for fooling in $f; do
|
||||||
ok=0
|
ok=0
|
||||||
|
f2=
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && {
|
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && {
|
||||||
warn_fool $fooling $desync
|
warn_fool $fooling $desync
|
||||||
[ "$SCANLEVEL" = quick ] && return
|
[ "$SCANLEVEL" = quick ] && return
|
||||||
need_wssize=0
|
need_wssize=0
|
||||||
ok=1
|
ok=1
|
||||||
}
|
}
|
||||||
|
[ "$fooling" = badseq ] && {
|
||||||
|
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && continue
|
||||||
|
# --dpi-desync-badseq-increment=0 leaves modified by default ack increment
|
||||||
|
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling --dpi-desync-badseq-increment=0 $e && {
|
||||||
|
[ "$SCANLEVEL" = quick ] && return
|
||||||
|
need_wssize=0
|
||||||
|
}
|
||||||
|
}
|
||||||
[ "$fooling" = md5sig ] && {
|
[ "$fooling" = md5sig ] && {
|
||||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && continue
|
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && continue
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling --dup=1 --dup-cutoff=n2 --dup-fooling=md5sig $e && {
|
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling --dup=1 --dup-cutoff=n2 --dup-fooling=md5sig $e && {
|
||||||
@@ -1399,18 +1490,30 @@ pktws_check_domain_http_bypass_()
|
|||||||
|
|
||||||
need_fakedsplit=1
|
need_fakedsplit=1
|
||||||
need_fakeddisorder=1
|
need_fakeddisorder=1
|
||||||
|
need_hostfakesplit=1
|
||||||
need_fake=1
|
need_fake=1
|
||||||
for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do
|
for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit hostfakesplit fake,hostfakesplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do
|
||||||
[ "$need_fake" = 0 ] && test_has_fake "$desync" && continue
|
[ "$need_fake" = 0 ] && test_has_fake "$desync" && continue
|
||||||
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
|
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
|
||||||
|
[ "$need_hostfakesplit" = 0 ] && contains "$desync" hostfakesplit && continue
|
||||||
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
|
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
|
||||||
ok=0
|
ok=0
|
||||||
for orig in '' 1 2 3; 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 delta in 1 2 3 4 5; do
|
||||||
|
for f in '' '--orig-ttl=1 --orig-mod-start=s1 --orig-mod-cutoff=d1'; do
|
||||||
|
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-ttl=1 --dpi-desync-autottl=-$delta $f $e && ok=1
|
||||||
|
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
||||||
|
done
|
||||||
|
done
|
||||||
|
[ "$SCANLEVEL" = force ] && {
|
||||||
|
for orig in 1 2 3; do
|
||||||
for delta in 1 2 3 4 5; do
|
for delta in 1 2 3 4 5; do
|
||||||
pktws_curl_test_update_vary $1 $2 $3 $desync ${orig:+--orig-autottl=+$orig} --dpi-desync-ttl=1 --dpi-desync-autottl=-$delta $e && ok=1
|
pktws_curl_test_update_vary $1 $2 $3 $desync ${orig:+--orig-autottl=+$orig} --dpi-desync-ttl=1 --dpi-desync-autottl=-$delta $e && ok=1
|
||||||
done
|
done
|
||||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
||||||
done
|
done
|
||||||
|
}
|
||||||
[ "$ok" = 1 ] &&
|
[ "$ok" = 1 ] &&
|
||||||
{
|
{
|
||||||
echo "WARNING ! although autottl worked it requires testing on multiple domains to find out reliable delta"
|
echo "WARNING ! although autottl worked it requires testing on multiple domains to find out reliable delta"
|
||||||
@@ -1420,6 +1523,7 @@ pktws_check_domain_http_bypass_()
|
|||||||
[ "$SCANLEVEL" = force ] || {
|
[ "$SCANLEVEL" = force ] || {
|
||||||
[ "$desync" = fake ] && need_fake=0
|
[ "$desync" = fake ] && need_fake=0
|
||||||
[ "$desync" = fakedsplit ] && need_fakedsplit=0
|
[ "$desync" = fakedsplit ] && need_fakedsplit=0
|
||||||
|
[ "$desync" = hostfakesplit ] && need_hostfakesplit=0
|
||||||
[ "$desync" = fakeddisorder ] && need_fakeddisorder=0
|
[ "$desync" = fakeddisorder ] && need_fakeddisorder=0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1628,17 +1732,19 @@ check_domain_prolog()
|
|||||||
|
|
||||||
local code
|
local code
|
||||||
|
|
||||||
|
[ "$SIMULATE" = 1 ] && return 0
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo \* $1 ipv$IPV $3
|
echo \* $1 ipv$IPV $3
|
||||||
|
|
||||||
echo "- checking without DPI bypass"
|
echo "- checking without DPI bypass"
|
||||||
curl_test $1 $3 && {
|
curl_test $1 $3 && {
|
||||||
report_append "ipv${IPV} $3 $1 : working without bypass"
|
report_append "$3" "$1 ipv${IPV}" "working without bypass"
|
||||||
[ "$SCANLEVEL" = force ] || return 1
|
[ "$SCANLEVEL" = force ] || return 1
|
||||||
}
|
}
|
||||||
code=$?
|
code=$?
|
||||||
curl_has_reason_to_continue $code || {
|
curl_has_reason_to_continue $code || {
|
||||||
report_append "ipv${IPV} $3 $1 : test aborted, no reason to continue. curl code $(curl_translate_code $code)"
|
report_append "$3" "$1 ipv${IPV}" "test aborted, no reason to continue. curl code $(curl_translate_code $code)"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
@@ -1822,6 +1928,7 @@ ask_params()
|
|||||||
[ -n "$dom" ] && DOMAINS="$dom"
|
[ -n "$dom" ] && DOMAINS="$dom"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DOMAINS_COUNT="$(echo "$DOMAINS" | wc -w | trim)"
|
||||||
|
|
||||||
local IPVS_def=4
|
local IPVS_def=4
|
||||||
[ -n "$IPVS" ] || {
|
[ -n "$IPVS" ] || {
|
||||||
@@ -2201,6 +2308,18 @@ cleanup
|
|||||||
echo
|
echo
|
||||||
echo \* SUMMARY
|
echo \* SUMMARY
|
||||||
report_print
|
report_print
|
||||||
|
[ "$DOMAINS_COUNT" -gt 1 ] && {
|
||||||
|
echo
|
||||||
|
echo \* COMMON
|
||||||
|
result_intersection_print
|
||||||
|
echo
|
||||||
|
[ "$SCANLEVEL" = force ] || {
|
||||||
|
echo "blockcheck optimizes test sequence. To save time some strategies can be skipped if their test is considered useless."
|
||||||
|
echo "That's why COMMON intersection can miss strategies that would work for all domains."
|
||||||
|
echo "Use \"force\" scan level to test all strategies and generate trustable intersection."
|
||||||
|
echo "Current scan level was \"$SCANLEVEL\"".
|
||||||
|
}
|
||||||
|
}
|
||||||
echo
|
echo
|
||||||
echo "Please note this SUMMARY does not guarantee a magic pill for you to copy/paste and be happy."
|
echo "Please note this SUMMARY does not guarantee a magic pill for you to copy/paste and be happy."
|
||||||
echo "Understanding how strategies work is very desirable."
|
echo "Understanding how strategies work is very desirable."
|
||||||
|
|||||||
+10
-5
@@ -297,10 +297,10 @@ minsleep()
|
|||||||
|
|
||||||
replace_char()
|
replace_char()
|
||||||
{
|
{
|
||||||
local a=$1
|
local a="$1"
|
||||||
local b=$2
|
local b="$2"
|
||||||
shift; shift
|
shift; shift
|
||||||
echo "$@" | tr $a $b
|
echo "$@" | tr "$a" "$b"
|
||||||
}
|
}
|
||||||
|
|
||||||
replace_str()
|
replace_str()
|
||||||
@@ -318,6 +318,12 @@ setup_md5()
|
|||||||
exists $MD5 || MD5=md5
|
exists $MD5 || MD5=md5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
md5f()
|
||||||
|
{
|
||||||
|
setup_md5
|
||||||
|
$MD5 | cut -d ' ' -f1
|
||||||
|
}
|
||||||
|
|
||||||
setup_random()
|
setup_random()
|
||||||
{
|
{
|
||||||
[ -n "$RCUT" ] && return
|
[ -n "$RCUT" ] && return
|
||||||
@@ -330,7 +336,6 @@ random()
|
|||||||
{
|
{
|
||||||
# $1 - min, $2 - max
|
# $1 - min, $2 - max
|
||||||
local r rs
|
local r rs
|
||||||
setup_md5
|
|
||||||
setup_random
|
setup_random
|
||||||
if [ -c /dev/urandom ]; then
|
if [ -c /dev/urandom ]; then
|
||||||
read rs </dev/urandom
|
read rs </dev/urandom
|
||||||
@@ -338,7 +343,7 @@ random()
|
|||||||
rs="$RANDOM$RANDOM$(date)"
|
rs="$RANDOM$RANDOM$(date)"
|
||||||
fi
|
fi
|
||||||
# shells use signed int64
|
# shells use signed int64
|
||||||
r=1$(echo $rs | $MD5 | sed 's/[^0-9]//g' | $RCUT)
|
r=1$(echo $rs | md5f | sed 's/[^0-9]//g' | $RCUT)
|
||||||
echo $(( ($r % ($2-$1+1)) + $1 ))
|
echo $(( ($r % ($2-$1+1)) + $1 ))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -703,7 +703,7 @@ removable_pkgs_openwrt()
|
|||||||
for pkg in $PKGS2; do
|
for pkg in $PKGS2; do
|
||||||
check_package_exists_openwrt $pkg && PKGS="${PKGS:+$PKGS }$pkg"
|
check_package_exists_openwrt $pkg && PKGS="${PKGS:+$PKGS }$pkg"
|
||||||
done
|
done
|
||||||
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS"
|
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32 ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS"
|
||||||
}
|
}
|
||||||
|
|
||||||
openwrt_fix_broken_apk_uninstall_scripts()
|
openwrt_fix_broken_apk_uninstall_scripts()
|
||||||
@@ -744,7 +744,7 @@ check_prerequisites_openwrt()
|
|||||||
iptables)
|
iptables)
|
||||||
pkg_iptables=iptables
|
pkg_iptables=iptables
|
||||||
check_package_exists_openwrt iptables-zz-legacy && pkg_iptables=iptables-zz-legacy
|
check_package_exists_openwrt iptables-zz-legacy && pkg_iptables=iptables-zz-legacy
|
||||||
PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra"
|
PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32"
|
||||||
check_package_exists_openwrt ip6tables-zz-legacy && pkg_iptables=ip6tables-zz-legacy
|
check_package_exists_openwrt ip6tables-zz-legacy && pkg_iptables=ip6tables-zz-legacy
|
||||||
[ "$DISABLE_IPV6" = 1 ] || PKGS="$PKGS $pkg_iptables ip6tables-mod-nat ip6tables-extra"
|
[ "$DISABLE_IPV6" = 1 ] || PKGS="$PKGS $pkg_iptables ip6tables-mod-nat ip6tables-extra"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -541,3 +541,17 @@ nfqws,tpws: fix possible crashes or high memory usage if hostlist has duplicate
|
|||||||
init.d: custom scripts 50-discord-media, 50-stun4all
|
init.d: custom scripts 50-discord-media, 50-stun4all
|
||||||
init.d: windivert filters for discord media, stun, wireguard
|
init.d: windivert filters for discord media, stun, wireguard
|
||||||
readme: hardware problems description
|
readme: hardware problems description
|
||||||
|
|
||||||
|
v72
|
||||||
|
|
||||||
|
winws: --wf-raw-part
|
||||||
|
nfqws: --dpi-desync=hostfakesplit
|
||||||
|
nfqws: --dpi-desync-fake-tcp-mod=seq
|
||||||
|
nfqws: --dpi-desync-fake-tls=!+offset , --dpi-desync-fake-xxx=[+offset]@filename
|
||||||
|
nfqws: --dpi-desync-fakedsplit-mod=altorder for fakedsplit/fakeddisorder
|
||||||
|
nfqws: --dpi-desync-hostfakesplit-mod=altorder
|
||||||
|
nfqws: fakedsplit/fakeddisorder normalize fake split pattern offset to reasm offset
|
||||||
|
nfqws: optimize ipv4 ip_id. apply ip_id on all OS the same way.
|
||||||
|
blockcheck: print PRETTY_NAME and some OPENWRT_xxx from /etc/os-release
|
||||||
|
blockcheck: new strategies
|
||||||
|
blockcheck: curl test simulation : SIMULATE=1
|
||||||
|
|||||||
+33
-20
@@ -16,7 +16,7 @@
|
|||||||
в простыню [readme.md](readme.md).
|
в простыню [readme.md](readme.md).
|
||||||
|
|
||||||
Обход DPI является хакерской методикой. Под этим словом понимается метод,
|
Обход DPI является хакерской методикой. Под этим словом понимается метод,
|
||||||
которому сопротивляется окружающая среда, которому автоматически не
|
которому оказывается активное противодействие и поэтому автоматически не
|
||||||
гарантирована работоспособность в любых условиях и на любых ресурсах, требуется
|
гарантирована работоспособность в любых условиях и на любых ресурсах, требуется
|
||||||
настройка под специфические условия у вашего провайдера. Условия могут меняться
|
настройка под специфические условия у вашего провайдера. Условия могут меняться
|
||||||
со временем, и методика может начинать или переставать работать, может
|
со временем, и методика может начинать или переставать работать, может
|
||||||
@@ -52,6 +52,18 @@
|
|||||||
1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив.
|
1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив.
|
||||||
Для openwrt и прошивок используйте вариант `openwrt-embedded`.
|
Для openwrt и прошивок используйте вариант `openwrt-embedded`.
|
||||||
Для экономия места в /tmp можно качать через curl в stdout и сразу распаковывать.
|
Для экономия места в /tmp можно качать через curl в stdout и сразу распаковывать.
|
||||||
|
Пример под openwrt для версии zapret 71.4 (для других URL отличается) :
|
||||||
|
```
|
||||||
|
$ curl -Lo - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4-openwrt-embedded.tar.gz | tar -zx
|
||||||
|
$ wget -O - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4-openwrt-embedded.tar.gz | tar -zx
|
||||||
|
```
|
||||||
|
Пример под традиционный linux для версии zapret 71.4 (для других URL отличается) :
|
||||||
|
```
|
||||||
|
$ curl -Lo - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4.tar.gz | tar -zx
|
||||||
|
$ wget -O - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4.tar.gz | tar -zx
|
||||||
|
```
|
||||||
|
curl должен быть предварительно установлен. Но он в любом случае понадобится далее.
|
||||||
|
Вариант с wget будет работать только если установленный wget поддерживает https.
|
||||||
|
|
||||||
2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и
|
2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и
|
||||||
сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`.
|
сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`.
|
||||||
@@ -129,10 +141,14 @@
|
|||||||
или `tpws` и запомнить найденные стратегии для дальнейшего применения.
|
или `tpws` и запомнить найденные стратегии для дальнейшего применения.
|
||||||
|
|
||||||
Следует понимать, что скрипт проверяет доступность только конкретного
|
Следует понимать, что скрипт проверяет доступность только конкретного
|
||||||
домена, который вы вводите в начале. Вероятно, все остальные домены
|
домена, который вы вводите в начале, конкретной программой curl.
|
||||||
блокированы подобным образом, **но не факт**. В большинстве случаев можно
|
У разных клиентов есть свой фингерпринт. У броузеров один, у curl другой.
|
||||||
объединить несколько стратегий в одну универсальную, и это **крайне
|
Может применяться или не применяться многопакетный TLS с постквантовой криптографией (kyber).
|
||||||
желательно**. Необходимо понимать как работают стратегии. zapret **не может
|
От этого может зависеть работоспособность стратегий.
|
||||||
|
Обычно остальные домены блокированы подобным образом, **но не факт**.
|
||||||
|
Бывают специальные блокировки. Некоторые параметры требуют тюнинга под "общий знаменатель".
|
||||||
|
В большинстве случаев можно объединить несколько стратегий в одну универсальную, и это **крайне
|
||||||
|
желательно**, но это требует понимания как работают стратегии. zapret **не может
|
||||||
пробить блокировку по IP адресу**. Для проверки нескольких доменов вводите
|
пробить блокировку по IP адресу**. Для проверки нескольких доменов вводите
|
||||||
их через пробел.
|
их через пробел.
|
||||||
|
|
||||||
@@ -143,19 +159,7 @@
|
|||||||
> направления (IP сервера). скрипт не всегда может выдать вам в итогах
|
> направления (IP сервера). скрипт не всегда может выдать вам в итогах
|
||||||
> оптимальную стратегию, которую надо просто переписать в настройки. В
|
> оптимальную стратегию, которую надо просто переписать в настройки. В
|
||||||
> некоторых случаях надо реально думать что происходит, анализируя результат
|
> некоторых случаях надо реально думать что происходит, анализируя результат
|
||||||
> на разных стратегиях. Если вы применяете большой TTL, чтобы достать до
|
> на разных стратегиях.
|
||||||
> магистрала, то не лишним будет добавить дополнительный ограничитель
|
|
||||||
> `--dpi-desync-fooling`, чтобы не сломать сайты на более коротких
|
|
||||||
> дистанциях. `md5sig` наиболее совместим, но работает **только** на linux
|
|
||||||
> серверах. `badseq` может работать только на https и не работать на http.
|
|
||||||
> Чтобы выяснить какие дополнительные ограничители работают, смотрите
|
|
||||||
> результат теста аналогичных стратегий без TTL с каждым из этих
|
|
||||||
> ограничителей.
|
|
||||||
>
|
|
||||||
> При использовании `autottl` следует протестировать как можно больше разных
|
|
||||||
> доменов. Эта техника может на одних провайдерах работать стабильно, на
|
|
||||||
> других потребуется выяснить при каких параметрах она стабильна, на третьих
|
|
||||||
> полный хаос, и проще отказаться.
|
|
||||||
>
|
>
|
||||||
> Далее, имея понимание что работает на http, https, quic нужно
|
> Далее, имея понимание что работает на http, https, quic нужно
|
||||||
> сконструировать параметры запуска `tpws` и/или `nfqws` с использованием
|
> сконструировать параметры запуска `tpws` и/или `nfqws` с использованием
|
||||||
@@ -202,8 +206,8 @@
|
|||||||
> Но здесь совсем "копи-пастный" вариант. Чем больше вы объедините стратегий и
|
> Но здесь совсем "копи-пастный" вариант. Чем больше вы объедините стратегий и
|
||||||
> сократите их общее количество, тем будет лучше.
|
> сократите их общее количество, тем будет лучше.
|
||||||
>
|
>
|
||||||
> Если вам не нужно дурение отдельных протоколов, лучше всего будет их
|
> Если вам не нужно дурение отдельных протоколов, лучше всего будет убрать
|
||||||
> убрать из системы перехвата трафика через параметры `TPWS_PORTS`,
|
> лишние порты из системы перехвата трафика через параметры `TPWS_PORTS`,
|
||||||
> `NFQWS_PORTS_TCP`, `NFQWS_PORTS_UDP` и убрать соответствующие им профили
|
> `NFQWS_PORTS_TCP`, `NFQWS_PORTS_UDP` и убрать соответствующие им профили
|
||||||
> мультистратегии.
|
> мультистратегии.
|
||||||
>
|
>
|
||||||
@@ -230,6 +234,15 @@
|
|||||||
> В этом примере `wssize` будет применяться всегда к порту tcp `443` вне
|
> В этом примере `wssize` будет применяться всегда к порту tcp `443` вне
|
||||||
> зависимости от параметра `MODE_FILTER`. Хостлист будет игнорироваться,
|
> зависимости от параметра `MODE_FILTER`. Хостлист будет игнорироваться,
|
||||||
> если таковой имеется. К http применять `wssize` вредно и бессмысленно.
|
> если таковой имеется. К http применять `wssize` вредно и бессмысленно.
|
||||||
|
>
|
||||||
|
> Иногда требуется дописать к стратегиям свои собственные параметры.
|
||||||
|
> Например, нужно изменить количество повторов фейков или задать свой фейк.
|
||||||
|
> Это делается через шелл-переменные `PKTWS_EXTRA`, `TPWS_EXTRA`.
|
||||||
|
>
|
||||||
|
> ```PKTWS_EXTRA="--dpi-desync-repeats=10 --dpi-desync-fake-tls=/tmp/tls.bin" ./blockcheck.sh```
|
||||||
|
>
|
||||||
|
> Перебор всех комбинаций может привести к ожиданию неделями, поэтому выбран разумный
|
||||||
|
> костяк проверки, на который вы можете навешивать свои кустомизации.
|
||||||
|
|
||||||
7. Запустите скрипт облегченной установки - `install_easy.sh` Выберите `nfqws`
|
7. Запустите скрипт облегченной установки - `install_easy.sh` Выберите `nfqws`
|
||||||
и/или `tpws`, затем согласитесь на редактирование параметров. Откроется
|
и/или `tpws`, затем согласитесь на редактирование параметров. Откроется
|
||||||
|
|||||||
+44
-55
@@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
## Немного разъяснений
|
## Немного разъяснений
|
||||||
|
|
||||||
Обход DPI является хакерской методикой. Под этим словом понимается метод, которому сопротивляется окружающая среда,
|
Обход DPI является хакерской методикой. Под этим словом понимается метод, которому оказывается активное противодействие и поэтому
|
||||||
которому автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах,
|
автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах,
|
||||||
требуется настройка под специфические условия у вашего провайдера. Условия могут меняться со временем,
|
требуется настройка под специфические условия у вашего провайдера. Условия могут меняться со временем,
|
||||||
и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации.
|
и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации.
|
||||||
Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать.
|
Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать.
|
||||||
@@ -30,24 +30,7 @@
|
|||||||
|
|
||||||
Будем считать, что у вас есть windows 7 или выше. Задача - обойти блокировки с самой системы.
|
Будем считать, что у вас есть windows 7 или выше. Задача - обойти блокировки с самой системы.
|
||||||
|
|
||||||
> [!NOTE]
|
## Я ЧТО-ТО ДЕЛАЛ, НЕ ПОМОГЛО, КАК ТЕПЕРЬ ЭТО УДАЛИТЬ
|
||||||
> Есть решение самое простое, а есть "как положено".
|
|
||||||
|
|
||||||
## САМОЕ ПРОСТОЕ РЕШЕНИЕ
|
|
||||||
|
|
||||||
_"Совсем ничего не могу, все очень сложно, дайте мне таблетку."_ ©Простой пользователь
|
|
||||||
|
|
||||||
1) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.
|
|
||||||
2) Запустите `zapret-winws/preset_russia.cmd` от имени администратора. Возможно, заведется сразу.
|
|
||||||
|
|
||||||
> То же самое с ограничителем по автоматически создаваемому хост-листу `preset_russia_autohostlist.cmd`.
|
|
||||||
> Что такое `autohostlist` - читайте [readme.md](./readme.md). Проще говоря, мы обходим только то, что долго и упорно не хочет открываться.
|
|
||||||
> Сначала не будет, но надо пытаться много раз, и тогда сработает, а дальше будет всегда срабатывать.
|
|
||||||
> Остальное не будет ломаться. Использовать только, если первый вариант тоже работает.
|
|
||||||
|
|
||||||
Не помогла _"таблетка"_ ? Это вовсе не значит, что ничего не получится. Но придется делать по нормальному.
|
|
||||||
|
|
||||||
## НЕ ПОМОГЛО, КАК ТЕПЕРЬ ЭТО УДАЛИТЬ
|
|
||||||
|
|
||||||
Если вы не устанавливали zapret как службу или запланированную задачу (а это требует редактирования cmd файлов),
|
Если вы не устанавливали zapret как службу или запланированную задачу (а это требует редактирования cmd файлов),
|
||||||
достаточно закрыть окно с winws и запустить windivert_delete.cmd.
|
достаточно закрыть окно с winws и запустить windivert_delete.cmd.
|
||||||
@@ -55,13 +38,16 @@ _"Совсем ничего не могу, все очень сложно, да
|
|||||||
После чего можно удалить папку с zapret. На этом деинсталляция закончена.
|
После чего можно удалить папку с zapret. На этом деинсталляция закончена.
|
||||||
Если же вы устанавливали zapret как службу, то вы наверняка знаете как ее удалить.
|
Если же вы устанавливали zapret как службу, то вы наверняка знаете как ее удалить.
|
||||||
|
|
||||||
## РЕШЕНИЕ "КАК ПОЛОЖЕНО"
|
Если вдруг среди того, на что вы нажимали, есть слова "general", "alt", ".bat", "автозапуск", или же есть файлы, которые отсутствуют
|
||||||
|
в оригинальных репозиториях, то это сборка. Вы не получите ответа как ее удалить от разработчика zapret.
|
||||||
|
Спрашивайте самих сборщиков. Разработчик не предоставляет простого решения, этим занимаются сборщики, но они и сами отвечают за свои продукты.
|
||||||
|
|
||||||
1) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.
|
## Настройка
|
||||||
|
|
||||||
2) Если у вас Windows 7 x64, однократно запустите `win7/install_win7.cmd`. Батник заменит файлы windivert на совместимую с Windows 7 версию.
|
1. Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.
|
||||||
|
|
||||||
|
2. Если у вас Windows 7 x64, однократно запустите `win7/install_win7.cmd`. Батник заменит файлы windivert на совместимую с Windows 7 версию.
|
||||||
|
|
||||||
> [!WARNING]
|
|
||||||
> Для 32-битных систем Windows нет готового полного варианта.
|
> Для 32-битных систем Windows нет готового полного варианта.
|
||||||
|
|
||||||
> На windows 11 arm64 выполните `arm64/install_arm64.cmd` от имени администратора и перезагрузите компьютер.
|
> На windows 11 arm64 выполните `arm64/install_arm64.cmd` от имени администратора и перезагрузите компьютер.
|
||||||
@@ -72,11 +58,11 @@ _"Совсем ничего не могу, все очень сложно, да
|
|||||||
> более-менее научились с ним дружить.
|
> более-менее научились с ним дружить.
|
||||||
> Если проблема имеет место , используйте исключения. Если не помогает - отключайте антивирус совсем.
|
> Если проблема имеет место , используйте исключения. Если не помогает - отключайте антивирус совсем.
|
||||||
|
|
||||||
3) Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам zapret.
|
3. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам zapret.
|
||||||
|
|
||||||
4) Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. nat не подходит
|
4. Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. nat не подходит
|
||||||
|
|
||||||
5) Запустите `blockcheck\blockcheck.cmd`. blockcheck в начале проверяет **DNS**.
|
5. Запустите `blockcheck\blockcheck.cmd`. blockcheck в начале проверяет **DNS**.
|
||||||
Если выводятся сообщения о подмене адресов, то нужно будет решить проблему с **DNS**.
|
Если выводятся сообщения о подмене адресов, то нужно будет решить проблему с **DNS**.
|
||||||
blockcheck перейдет в этом случае на **DoH** _(DNS over HTTPS)_ и будет пытаться получить и использовать реальные IP адреса.
|
blockcheck перейдет в этом случае на **DoH** _(DNS over HTTPS)_ и будет пытаться получить и использовать реальные IP адреса.
|
||||||
Но если вы не настроите решение этой проблемы, обход будет работать только для тех программ,
|
Но если вы не настроите решение этой проблемы, обход будет работать только для тех программ,
|
||||||
@@ -92,35 +78,29 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
|
|||||||
>
|
>
|
||||||
> Тут все разжевано как и где это включается : https://hackware.ru/?p=13707
|
> Тут все разжевано как и где это включается : https://hackware.ru/?p=13707
|
||||||
|
|
||||||
6) blockcheck позволяет выявить рабочую стратегию обхода блокировок.
|
6. blockcheck позволяет выявить рабочую стратегию обхода блокировок.
|
||||||
Лог скрипта будет сохранен в `blockcheck\blockcheck.log`.
|
Лог скрипта будет сохранен в `blockcheck\blockcheck.log`.
|
||||||
Запомните/перепишите найденные стратегии.
|
Запомните/перепишите найденные стратегии.
|
||||||
|
|
||||||
> [!WARNING]
|
Следует понимать, что скрипт проверяет доступность только конкретного
|
||||||
> Следует понимать, что blockcheck проверяет доступность только конкретного домена, который вы вводите в начале.
|
домена, который вы вводите в начале, конкретной программой curl.
|
||||||
> Вероятно, все остальные домены блокированы подобным образом, но не факт.
|
У разных клиентов есть свой фингерпринт. У броузеров один, у curl другой.
|
||||||
|
Может применяться или не применяться многопакетный TLS с постквантовой криптографией (kyber).
|
||||||
|
От этого может зависеть работоспособность стратегий.
|
||||||
|
Обычно остальные домены блокированы подобным образом, **но не факт**.
|
||||||
|
Бывают специальные блокировки. Некоторые параметры требуют тюнинга под "общий знаменатель".
|
||||||
|
В большинстве случаев можно объединить несколько стратегий в одну универсальную, и это **крайне
|
||||||
|
желательно**, но это требует понимания как работают стратегии. zapret **не может
|
||||||
|
пробить блокировку по IP адресу**. Для проверки нескольких доменов вводите их через пробел.
|
||||||
|
|
||||||
> [!TIP]
|
> Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у
|
||||||
> В большинстве случаев можно обьединить несколько стратегий в одну универсальную, и это крайне желательно.
|
> вас может быть несколько маршрутов с различной длиной по ХОПам, с DPI на
|
||||||
|
> разных хопах. Приходится преодолевать целый зоопарк DPI, которые еще и
|
||||||
> Необходимо понимать [как работают стратегии](./readme.md/#nfqws).
|
> включаются в работу хаотичным образом или образом, зависящим от
|
||||||
> zapret не может пробить блокировку по IP адресу. Для проверки нескольких доменов вводите их через пробел.
|
> направления (IP сервера). скрипт не всегда может выдать вам в итогах
|
||||||
>
|
> оптимальную стратегию, которую надо просто переписать в настройки. В
|
||||||
> Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов
|
> некоторых случаях надо реально думать что происходит, анализируя результат
|
||||||
> с различной длиной по ХОПам, с DPI на разных хопах. Приходится преодолевать целый зоопарк DPI,
|
> на разных стратегиях.
|
||||||
> которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера).
|
|
||||||
> blockcheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки.
|
|
||||||
> В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях.
|
|
||||||
> Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель
|
|
||||||
> `--dpi-desync-fooling`, чтобы не сломать сайты на более коротких дистанциях.
|
|
||||||
> _md5sig_ наиболее совместим, но работатет только на linux серверах.
|
|
||||||
> badseq может работать только на https и не работать на http.
|
|
||||||
> Чтобы выяснить какие дополнительные ограничители работают, смотрите результат теста аналогичных стратегий без TTL
|
|
||||||
> с каждым из этих ограничителей.
|
|
||||||
>
|
|
||||||
> При использовании autottl следует протестировать как можно больше разных доменов. Эта техника
|
|
||||||
> может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах
|
|
||||||
> она стабильна, на третьих полный хаос, и проще отказаться.
|
|
||||||
>
|
>
|
||||||
> Далее, имея понимание что работает на http, https, quic, нужно сконструировать параметры запуска winws
|
> Далее, имея понимание что работает на http, https, quic, нужно сконструировать параметры запуска winws
|
||||||
> с использованием мультистратегии. Как работают мультистратегии описано в [readme.md](./readme.md#множественные-стратегии).
|
> с использованием мультистратегии. Как работают мультистратегии описано в [readme.md](./readme.md#множественные-стратегии).
|
||||||
@@ -183,12 +163,21 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
|
|||||||
>
|
>
|
||||||
> В этих примерах wssize будет применяться всегда к порту tcp 443, а хостлист будет игнорироваться.
|
> В этих примерах wssize будет применяться всегда к порту tcp 443, а хостлист будет игнорироваться.
|
||||||
> К http применять wssize вредно и бессмысленно.
|
> К http применять wssize вредно и бессмысленно.
|
||||||
|
>
|
||||||
|
> Иногда требуется дописать к стратегиям свои собственные параметры.
|
||||||
|
> Например, нужно изменить количество повторов фейков или задать свой фейк.
|
||||||
|
> Это делается через шелл-переменные `PKTWS_EXTRA`, `TPWS_EXTRA`. Пользуйтесь шеллом `cygwin/cygwin-admin.cmd`.
|
||||||
|
>
|
||||||
|
> ```PKTWS_EXTRA="--dpi-desync-repeats=10 --dpi-desync-fake-tls=/tmp/tls.bin" blockcheck```
|
||||||
|
>
|
||||||
|
> Перебор всех комбинаций может привести к ожиданию неделями, поэтому выбран разумный
|
||||||
|
> костяк проверки, на который вы можете навешивать свои кустомизации.
|
||||||
|
|
||||||
7) Протестируйте найденные стратегии на winws. Winws следует брать из zapret-winws.
|
7. Протестируйте найденные стратегии на winws. Winws следует брать из zapret-winws.
|
||||||
Для этого откройте командную строку windows от имени администратора в директории zapret-winws.
|
Для этого откройте командную строку windows от имени администратора в директории zapret-winws.
|
||||||
Проще всего это сделать через `_CMD_ADMIN.cmd`. Он сам поднимет права и зайдет в нужную директорию.
|
Проще всего это сделать через `_CMD_ADMIN.cmd`. Он сам поднимет права и зайдет в нужную директорию.
|
||||||
|
|
||||||
8) Обеспечьте удобную загрузку обхода блокировок.
|
8. Обеспечьте удобную загрузку обхода блокировок.
|
||||||
|
|
||||||
> Есть 2 варианта. Ручной запуск через ярлык или автоматический при старте системы, вне контекста текущего пользователя.
|
> Есть 2 варианта. Ручной запуск через ярлык или автоматический при старте системы, вне контекста текущего пользователя.
|
||||||
> Последний вариант разделяется на запуск через планировщик задач и через службы windows.
|
> Последний вариант разделяется на запуск через планировщик задач и через службы windows.
|
||||||
@@ -203,7 +192,7 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
|
|||||||
>
|
>
|
||||||
> Аналогично настраиваются и службы windows. Смотрите `service_*.cmd`
|
> Аналогично настраиваются и службы windows. Смотрите `service_*.cmd`
|
||||||
|
|
||||||
9) Если ломаются отдельные незаблокированные ресурсы, нужно пользоваться ограничивающим
|
9. Если ломаются отдельные незаблокированные ресурсы, нужно пользоваться ограничивающим
|
||||||
ipset или хост листом. Читайте основной талмуд [readme.md](./readme.md) ради подробностей.
|
ipset или хост листом. Читайте основной талмуд [readme.md](./readme.md) ради подробностей.
|
||||||
Но еще лучше будет подбирать такие стратегии, которые ломают минимум.
|
Но еще лучше будет подбирать такие стратегии, которые ломают минимум.
|
||||||
Есть стратегии довольно безобидные, а есть сильно ломающие, которые подходят только для точечного пробития отдельных ресурсов,
|
Есть стратегии довольно безобидные, а есть сильно ломающие, которые подходят только для точечного пробития отдельных ресурсов,
|
||||||
|
|||||||
+73
-17
@@ -1,4 +1,4 @@
|
|||||||
# zapret v71.4
|
# zapret v72
|
||||||
|
|
||||||
# SCAMMER WARNING
|
# SCAMMER WARNING
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ nfqws takes the following parameters:
|
|||||||
--dup-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment for dup. default -66000
|
--dup-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment for dup. default -66000
|
||||||
--dup-start=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
|
--dup-start=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
|
||||||
--dup-cutoff=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
--dup-cutoff=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
||||||
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit hostfakesplit fakeddisorder ipfrag2 udplen tamper
|
||||||
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
|
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
|
||||||
--dpi-desync-ttl=<int> ; set ttl for desync packet
|
--dpi-desync-ttl=<int> ; set ttl for desync packet
|
||||||
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used.
|
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used.
|
||||||
@@ -194,27 +194,31 @@ nfqws takes the following parameters:
|
|||||||
; full list is only used by multisplit and multidisorder
|
; full list is only used by multisplit and multidisorder
|
||||||
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
|
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
|
||||||
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
|
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
|
||||||
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap
|
--dpi-desync-split-seqovl-pattern=[+ofs]@<filename>|0xHEX ; pattern for the fake part of overlap
|
||||||
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder
|
--dpi-desync-fakedsplit-pattern=[+ofs]@<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder
|
||||||
|
--dpi-desync-fakedsplit-mod=mod[,mod] ; mods can be none,altorder=0|1|2|3 + 0|8|16
|
||||||
|
--dpi-desync-hostfakesplit-midhost=marker+N|marker-N ; additionally split real hostname at specified marker. must be within host..endhost or won't be splitted.
|
||||||
|
--dpi-desync-hostfakesplit-mod=mod[,mod] ; can be none, host=<hostname>, altorder=0|1
|
||||||
--dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8.
|
--dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8.
|
||||||
--dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32.
|
--dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32.
|
||||||
--dpi-desync-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment. default -600000
|
--dpi-desync-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment. default -600000
|
||||||
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000
|
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000
|
||||||
--dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000
|
--dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000
|
||||||
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
|
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
|
||||||
--dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request
|
--dpi-desync-fake-tcp-mod=mod[,mod] ; comma separated list of tcp fake mods. available mods : none,seq
|
||||||
--dpi-desync-fake-tls=<filename>|0xHEX|! ; file containing fake TLS ClientHello (for https). '!' = standard fake
|
--dpi-desync-fake-http=[+ofs]@<filename>|0xHEX ; file containing fake http request
|
||||||
|
--dpi-desync-fake-tls=[+ofs]@<filename>|0xHEX|![+offset] ; file containing fake TLS ClientHello (for https). '!' = standard fake
|
||||||
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
||||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
|
--dpi-desync-fake-unknown=[+ofs]@<filename>|0xHEX ; file containing unknown protocol fake payload
|
||||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload
|
--dpi-desync-fake-syndata=[+ofs]@<filename>|0xHEX ; file containing SYN data payload
|
||||||
--dpi-desync-fake-quic=<filename>|0xHEX ; file containing fake QUIC Initial
|
--dpi-desync-fake-quic=[+ofs]@<filename>|0xHEX ; file containing fake QUIC Initial
|
||||||
--dpi-desync-fake-wireguard=<filename>|0xHEX ; file containing fake wireguard handshake initiation
|
--dpi-desync-fake-wireguard=[+ofs]@<filename>|0xHEX ; file containing fake wireguard handshake initiation
|
||||||
--dpi-desync-fake-dht=<filename>|0xHEX ; file containing fake DHT (d1..e)
|
--dpi-desync-fake-dht=[+ofs]@<filename>|0xHEX ; file containing fake DHT (d1..e)
|
||||||
--dpi-desync-fake-discord=<filename>|0xHEX ; file containing fake Discord voice connection initiation packet (IP Discovery)
|
--dpi-desync-fake-discord=[+ofs]@<filename>|0xHEX ; file containing fake Discord voice connection initiation packet (IP Discovery)
|
||||||
--dpi-desync-fake-stun=<filename>|0xHEX ; file containing fake STUN message
|
--dpi-desync-fake-stun=[+ofs]@<filename>|0xHEX ; file containing fake STUN message
|
||||||
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; file containing unknown udp protocol fake payload
|
--dpi-desync-fake-unknown-udp=[+ofs]@<filename>|0xHEX ; file containing unknown udp protocol fake payload
|
||||||
--dpi-desync-udplen-increment=<int> ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length.
|
--dpi-desync-udplen-increment=<int> ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length.
|
||||||
--dpi-desync-udplen-pattern=<filename>|0xHEX ; udp tail fill pattern
|
--dpi-desync-udplen-pattern=[+ofs]@<filename>|0xHEX ; udp tail fill pattern
|
||||||
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
|
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
|
||||||
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
||||||
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed)
|
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed)
|
||||||
@@ -239,6 +243,10 @@ nfqws takes the following parameters:
|
|||||||
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
|
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Many parameters dealing with binary data support loading from hex string prefixed by "0x" or from a file.
|
||||||
|
Filename can be "as is" or prefixed with "@". If there's "+number" prefix before "@" it means offset of data inside the file.
|
||||||
|
Offset must be less that data size.
|
||||||
|
|
||||||
### DPI desync attack
|
### DPI desync attack
|
||||||
|
|
||||||
The idea is to take original message, modify it, add additional fake information in such a way that the server OS accepts original data only
|
The idea is to take original message, modify it, add additional fake information in such a way that the server OS accepts original data only
|
||||||
@@ -315,6 +323,9 @@ Resulting order would be : `fake1 fake1 fake1 fake2 fake2 fake2 fake3 fake3 fake
|
|||||||
|
|
||||||
### FAKE mods
|
### FAKE mods
|
||||||
|
|
||||||
|
By default all tcp fakes are sent with the same sequence as original packet.
|
||||||
|
This can be changed by `--dpi-desync-fake-tcp-mod=seq`. In the latter case all fakes are sent as if they would be tcp segments of a single fake.
|
||||||
|
|
||||||
**nfqws** has built-in TLS fake. It can be customized with `--dpi-desync-fake-tls` option.
|
**nfqws** has built-in TLS fake. It can be customized with `--dpi-desync-fake-tls` option.
|
||||||
Customized fake data can be anything - valid TLS Client Hello or arbitrary data.
|
Customized fake data can be anything - valid TLS Client Hello or arbitrary data.
|
||||||
It's possible to use TLS Client Hello with any fingerprint and any SNI.
|
It's possible to use TLS Client Hello with any fingerprint and any SNI.
|
||||||
@@ -343,8 +354,37 @@ Example : `--dpi-desync-fake-tls=iana_org.bin --dpi-desync-fake-tls-mod=rndsni -
|
|||||||
|
|
||||||
* `multisplit`. split request at specified in `--dpi-desync-split-pos` positions
|
* `multisplit`. split request at specified in `--dpi-desync-split-pos` positions
|
||||||
* `multidisorder`. same as `multisplit` but send in reverse order
|
* `multidisorder`. same as `multisplit` but send in reverse order
|
||||||
* `fakedsplit`. split request into 2 segments adding fakes in the middle of them : fake 1st segment, 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
|
* `fakedsplit`. sequental one position split with fake mix
|
||||||
* `fakeddisorder`. same as `fakedsplit` but with another order : fake 2nd segment, 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment
|
* `hostfakesplit` (altorder=0). fake host part of the request : before host, random fake host, real host (optionally split this part), random fake host repeat, after host
|
||||||
|
* `hostfakesplit` (altorder=1). fake host part of the request : before host, random fake host, after host, real host (optionally split this part)
|
||||||
|
* `fakedsplit`. reverse one position split with fake mix
|
||||||
|
|
||||||
|
`--dpi-desync-fakedsplit-mod=altorder=N` specifies number which influence to the presence of individual fakes in `fakedsplit`/`fakeddisorder`.
|
||||||
|
|
||||||
|
`fakedsplit` TCP segments of multi-packet messages with split pos :
|
||||||
|
|
||||||
|
* `altorder=0`. fake 1st segment, 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
|
||||||
|
* `altorder=1`. 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
|
||||||
|
* `altorder=2`. 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
|
||||||
|
* `altorder=3`. 1st segment, fake 2nd segment, 2nd segment
|
||||||
|
|
||||||
|
`fakeddisorder` TCP segments of multi-packet messages with split pos :
|
||||||
|
|
||||||
|
* `altorder=0`. fake 2nd segment, 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment
|
||||||
|
* `altorder=1`. 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment
|
||||||
|
* `altorder=2`. 2nd segment, fake 1st segment, 1st segment, fake 1st segment
|
||||||
|
* `altorder=3`. 1st segment, fake 1st segment, 1st segment
|
||||||
|
|
||||||
|
`fakedsplit`/`fakeddisorder` TCP segments of multi-packet messages without split pos :
|
||||||
|
|
||||||
|
* `altorder=0`. fake, original, fake
|
||||||
|
* `altorder=8`. original, fake
|
||||||
|
* `altorder=16`. original
|
||||||
|
|
||||||
|
Resulting `altorder=N` is the sum of two `altorder` parts mentioned above.
|
||||||
|
|
||||||
|
`--dpi-desync-fakedsplit-pattern` defines data payload of fakes in `fakedsplit`/`fakeddisorder`. By default pattern is simple `0x00`.
|
||||||
|
Offset of split part + offset of current packet in multi-packet message define offset in the pattern.
|
||||||
|
|
||||||
Positions are defined by markers.
|
Positions are defined by markers.
|
||||||
|
|
||||||
@@ -373,6 +413,22 @@ First relative markers are searched. If no suitable found absolute markers are s
|
|||||||
|
|
||||||
For example, `--dpi-desync-split-pos=method+2,midsld,5` means `method+2` for http, `midsld` for TLS and 5 for others.
|
For example, `--dpi-desync-split-pos=method+2,midsld,5` means `method+2` for http, `midsld` for TLS and 5 for others.
|
||||||
|
|
||||||
|
`--dpi-desync-fakedsplit-mod=altorder=N` switches `fakedsplit` to alternate segment ordering.
|
||||||
|
|
||||||
|
`hostfakesplit` only fakes hostname part of the request making it hard to destinguish between real and fake host names.
|
||||||
|
It works for tcp protocols with host : TLS and HTTP. Real hostname can be additionally split using `--dpi-desync-hostfakesplit-midhost` marker.
|
||||||
|
For example, `--dpi-desync-hostfakesplit-midhost=midsld`. Position must be within host range or split won't happen.
|
||||||
|
Multi-packet queries are supported if hostname part is not already split. If it is fooling is cancelled.
|
||||||
|
|
||||||
|
By default fake host names are generated randomly on the fly using `[0-9a-z]` pattern. If host length is >= 7 dot is placed to simulate 3-char TLD and last 3 chars are replaces with a random known 3-char TLD.
|
||||||
|
It's possible to set fake host template : `--dpi-desync-hostfakesplit-mod=host=<hostname>`.
|
||||||
|
Template hostname will be expanded to the left to original hostname size with random characters from `[0-9a-z]` pattern : "www.networksolutions.com" -> "h8xmdba4tv7a8.google.com".
|
||||||
|
If original hostname size is less than template size it will be cut : "habr.com" -> "ogle.com".
|
||||||
|
If original hostname size is larger than template size by one, dot will be appended to the left : "www.xxx.com" => ".google.com"..
|
||||||
|
That's why it's a good idea to use short hostnames in template : "ya.ru", "vk.com", "x.com".
|
||||||
|
|
||||||
|
`--dpi-desync-hostfakesplit-mod=altorder=1` switches `hostfakesplit` to alternate segment ordering. `altorder=1` sends the whole request with faked host sequentally, then real host segment.
|
||||||
|
|
||||||
### Sequence numbers overlap
|
### Sequence numbers overlap
|
||||||
|
|
||||||
`seqovl` adds to one of the original segment `seqovl` bytes to the beginning and decreases sequence number. For `split` - to the first segment, for `disorder` - to the beginning of the penultimate segment sent (second in the original sequence).
|
`seqovl` adds to one of the original segment `seqovl` bytes to the beginning and decreases sequence number. For `split` - to the first segment, for `disorder` - to the beginning of the penultimate segment sent (second in the original sequence).
|
||||||
|
|||||||
+79
-18
@@ -1,4 +1,4 @@
|
|||||||
# zapret v71.4
|
# zapret v72
|
||||||
|
|
||||||
# ВНИМАНИЕ, остерегайтесь мошенников
|
# ВНИМАНИЕ, остерегайтесь мошенников
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
--methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com"
|
--methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com"
|
||||||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||||||
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
||||||
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit hostfakesplit fakeddisorder ipfrag2 udplen tamper
|
||||||
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
|
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
|
||||||
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
|
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
|
||||||
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение --dpi-desync-ttl
|
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение --dpi-desync-ttl
|
||||||
@@ -218,25 +218,29 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
||||||
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
|
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
|
||||||
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
|
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
|
||||||
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; чем заполнять фейковую часть overlap
|
--dpi-desync-split-seqovl-pattern=[+ofs]@<filename>|0xHEX ; чем заполнять фейковую часть overlap
|
||||||
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; чем заполнять фейки в fakedsplit/fakeddisorder
|
--dpi-desync-fakedsplit-pattern=[+ofs]@<filename>|0xHEX ; чем заполнять фейки в fakedsplit/fakeddisorder
|
||||||
|
--dpi-desync-fakedsplit-mod=mod[,mod] ; может быть none, altorder=0|1|2|3 + 0|8|16
|
||||||
|
--dpi-desync-hostfakesplit-midhost=marker+N|marker-N ; маркер дополнительного разреза сегмента с оригинальным хостом. должен попадать в пределы хоста.
|
||||||
|
--dpi-desync-hostfakesplit-mod=mod[,mod] ; может быть none, host=<hostname>, altorder=0|1
|
||||||
--dpi-desync-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000
|
--dpi-desync-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000
|
||||||
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
|
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
|
||||||
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
|
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
|
||||||
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
||||||
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
--dpi-desync-fake-tcp-mod=mod[,mod] ; список через запятую режимов runtime модификации tcp фейков (любых) : none, seq
|
||||||
--dpi-desync-fake-tls=<filename>|0xHEX|! ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному. '!' = стандартный фейк
|
--dpi-desync-fake-http=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
||||||
|
--dpi-desync-fake-tls=[+ofs]@<filename>|0xHEX|![+offset] ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному. '!' = стандартный фейк
|
||||||
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,sni=<sni>,dupsid,padencap
|
||||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
--dpi-desync-fake-unknown=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
||||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
--dpi-desync-fake-syndata=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
||||||
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
|
--dpi-desync-fake-quic=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
|
||||||
--dpi-desync-fake-wireguard=<filename>|0xHEX ; файл, содержащий фейковый wireguard handshake initiation
|
--dpi-desync-fake-wireguard=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый wireguard handshake initiation
|
||||||
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
--dpi-desync-fake-dht=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||||
--dpi-desync-fake-discord=<filename>|0xHEX ; файл, содержащий фейковый пейлоад Discord протокола нахождения IP адреса для голосовых чатов для dpi-desync=fake, на замену стандартным нулям 64 байт
|
--dpi-desync-fake-discord=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад Discord протокола нахождения IP адреса для голосовых чатов для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||||
--dpi-desync-fake-stun=<filename>|0xHEX ; файл, содержащий фейковый пейлоад STUN протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
--dpi-desync-fake-stun=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад STUN протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||||
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
--dpi-desync-fake-unknown-udp=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||||
--dpi-desync-udplen-increment=<int> ; на сколько увеличивать длину udp пейлоада в режиме udplen
|
--dpi-desync-udplen-increment=<int> ; на сколько увеличивать длину udp пейлоада в режиме udplen
|
||||||
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
|
--dpi-desync-udplen-pattern=[+ofs]@<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
|
||||||
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
|
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
|
||||||
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
||||||
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются, если хост не начинается с '^'.
|
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются, если хост не начинается с '^'.
|
||||||
@@ -276,6 +280,13 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
невозможна. Если вы потом удалите файл, и у процесса не будет прав на создание файла в его директории, лог больше не
|
невозможна. Если вы потом удалите файл, и у процесса не будет прав на создание файла в его директории, лог больше не
|
||||||
будет вестись. Вместо удаления лучше использовать truncate. В шелле это можно сделать через команду ": >filename"
|
будет вестись. Вместо удаления лучше использовать truncate. В шелле это можно сделать через команду ": >filename"
|
||||||
|
|
||||||
|
Многие параметры, загружающие двоичные данные из файлов, поддерживают загрузку из hex-строки или из файла.
|
||||||
|
hex строка начинается с "0x". Имя файла можно писать как есть или использовать префикс "@".
|
||||||
|
Если перед префиксом "@" указано "+<число>", то это означает смещение полезных данных внутри файла.
|
||||||
|
Файл может загружаться целиком с нулевой позиции, к нему могут применяться модификации, требующие полного файла (TLS),
|
||||||
|
но передача пойдет с позиции offset. offset должен быть меньше длины файла. Если к блоку данных применяется мод,
|
||||||
|
который уменьшает размер данных, и offset окажется не меньше новой длины данных, будет ошибка.
|
||||||
|
|
||||||
### АТАКА ДЕСИНХРОНИЗАЦИИ DPI
|
### АТАКА ДЕСИНХРОНИЗАЦИИ DPI
|
||||||
|
|
||||||
Суть ее в следующем. Берется оригинальный запрос, модифицируется, добавляется поддельная информация (фейки)
|
Суть ее в следующем. Берется оригинальный запрос, модифицируется, добавляется поддельная информация (фейки)
|
||||||
@@ -371,6 +382,10 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
|
|
||||||
### МОДИФИКАЦИЯ ФЕЙКОВ
|
### МОДИФИКАЦИЯ ФЕЙКОВ
|
||||||
|
|
||||||
|
Любые tcp фейки отправляются с исходным sequence по умолчанию, даже если их несколько.
|
||||||
|
Если задать `--dpi-desync-fake-tcp-mod=seq`, то несколько фейков будут отправлены с увеличением sequence number таким образом,
|
||||||
|
как будто они являются tcp сегментами одного фейка.
|
||||||
|
|
||||||
В nfqws зашит базовый вариант фейка для TLS. Его можно переопределить опцией `--dpi-desync-fake-tls`.
|
В nfqws зашит базовый вариант фейка для TLS. Его можно переопределить опцией `--dpi-desync-fake-tls`.
|
||||||
Переопределение фейков дает возможность использовать любые данные в качестве фейка для TLS.
|
Переопределение фейков дает возможность использовать любые данные в качестве фейка для TLS.
|
||||||
Можно использовать фейковый Client Hello с любым фингерпринтом и с любым SNI.
|
Можно использовать фейковый Client Hello с любым фингерпринтом и с любым SNI.
|
||||||
@@ -403,17 +418,61 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
|
|
||||||
* `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях.
|
* `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях.
|
||||||
* `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке.
|
* `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке.
|
||||||
* `fakedsplit`. нарезаем запрос на 2 части, обрамляя каждую часть фейками : фейк 1-й части, 1 часть, фейк 1-й части, фейк 2-й части, 2 часть, фейк 2-й части
|
* `fakedsplit`. различные варианты замешивания фейков и оригиналов в прямом порядке
|
||||||
|
* `fakeddisorder`. различные варианты замешивания фейков и оригиналов в обратном порядке
|
||||||
|
* `hostfakesplit` (altorder=0). фейкование части запроса с хостом : оригинал до хоста, фейк хоста, оригинал хоста (+ опционально нарезка маркером midhost), фейк хоста, оригинал после хоста
|
||||||
|
* `hostfakesplit` (altorder=1). фейкование части запроса с хостом : оригинал до хоста, фейк хоста, оригинал после хоста, оригинал хоста (+опционально нарезка маркером midhost)
|
||||||
* `fakeddisorder`. аналогично `fakedsplit`, только в обратном порядке : фейк 2-й части, 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1 части.
|
* `fakeddisorder`. аналогично `fakedsplit`, только в обратном порядке : фейк 2-й части, 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1 части.
|
||||||
|
|
||||||
|
Для `fakedsplit` и `fakeddisorder` предусмотрены вариации порядка следования сегментов.
|
||||||
|
Параметр `--dpi-desync-fakedsplit-mod=altorder=N` задает число, влияющее на наличие отдельных фейков :
|
||||||
|
|
||||||
|
Режимы altorder для `fakedsplit` для части многопакетного запроса, где есть сплит-позиция :
|
||||||
|
* `altorder=0`. фейк 1-й части, 1 часть, фейк 1-й части, фейк 2-й части, 2 часть, фейк 2-й части
|
||||||
|
* `altorder=1`. 1 часть, фейк 1-й части, фейк 2-й части, 2 часть, фейк 2-й части
|
||||||
|
* `altorder=2`. 1 часть, фейк 2-й части, 2 часть, фейк 2-й части
|
||||||
|
* `altorder=3`. 1 часть, фейк 2-й части, 2 часть
|
||||||
|
|
||||||
|
Режимы altorder для `fakeddisorder` для части многопакетного запроса, где есть сплит-позиция :
|
||||||
|
* `altorder=0`. фейк 2-й части, 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1-й части
|
||||||
|
* `altorder=1`. 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1-й части
|
||||||
|
* `altorder=2`. 2 часть, фейк 1-й части, 1 часть, фейк 1-й части
|
||||||
|
* `altorder=3`. 2 часть, фейк 1-й части, 1 часть
|
||||||
|
|
||||||
|
Режимы altorder для `fakedsplit` и `fakeddisorder` для части многопакетного запроса, где нет сплит-позиции :
|
||||||
|
* `altorder=0`. фейк, оригинал, фейк
|
||||||
|
* `altorder=8`. оригинал, фейк
|
||||||
|
* `altorder=16`. оригинал
|
||||||
|
|
||||||
|
Итоговое число `altorder=N` вычисляется как сумма чисел из этих двух групп. По умолчанию `altorder=0`.
|
||||||
|
|
||||||
Содержимое фейков в `fakedsplit`/`fakeddisorder` определяется параметром `--dpi-desync-fakedsplit-pattern` (по умолчанию 0x00).
|
Содержимое фейков в `fakedsplit`/`fakeddisorder` определяется параметром `--dpi-desync-fakedsplit-pattern` (по умолчанию 0x00).
|
||||||
Данные фейков берутся из паттерна со смещением, соответствующим смещению отсылаемых частей.
|
Данные фейков берутся из паттерна со смещением, соответствующим смещению отсылаемых частей, учитывая смещения пакетов в многопакетных запросах.
|
||||||
Размеры фейков соответствуют длинам отсылаемых частей.
|
Размеры фейков соответствуют длинам отсылаемых частей.
|
||||||
Цель этих режимов - максимально усложнить выявление оригинальных данных среди фейков.
|
Цель этих режимов - максимально усложнить выявление оригинальных данных среди фейков.
|
||||||
|
|
||||||
Использование `fakedsplit` или `fakeddisorder` на TLS kyber с md5sig fooling может привести к ошибкам "message too long", если позиция сплита мала,
|
Использование `fakedsplit` или `fakeddisorder` на TLS kyber с md5sig fooling может привести к ошибкам "message too long", если позиция сплита мала,
|
||||||
поскольку будет превышение MTU из-за md5 tcp option.
|
поскольку будет превышение MTU из-за md5 tcp option.
|
||||||
|
|
||||||
|
Режим 'hostfakesplit' имеет задачу минимального вмешательства фейком - как раз по той части запроса, на основании которой DPI принимает решение о блокировке. Конкретно - имени хоста.
|
||||||
|
По умолчанию фейк хоста генерируется каждый раз случайно из набора `[a-z0-9]`. При длине более 7 символов за 3 символа до конца ставится точка, имитируя TLD, а последние 3 символа заполняются одним из нескольких известных TLD.
|
||||||
|
|
||||||
|
Можно переопределить шаблон генерации с помощью `--dpi-desync-hostfakesplit-mod=host=<hostname>`. В последнем случае справа всегда будет указанный hostname.
|
||||||
|
Слева он будет дополнен до размера оригинального хоста как поддомен со случайными символами. Пример : "www.networksolutions.com" -> "h8xmdba4tv7a8.google.com".
|
||||||
|
Если размер оригинального хоста меньше шаблона, шаблон будет порезан : "habr.com" -> "ogle.com".
|
||||||
|
Если размер оригинального хоста больше шаблона на 1, получится инвалидный пустой поддомен : "www.xxx.com" => ".google.com".
|
||||||
|
Поэтому стоит использовать максимально короткие хосты из разрешенных : "ya.ru", "vk.com".
|
||||||
|
|
||||||
|
`--dpi-desync-hostfakesplit-mod=altorder=1` позволяет сменить порядок следования частей на альтернативный вариант.
|
||||||
|
`altorder=1` шлет фрагменты в таком порядке, чтобы при последовательной сборке сегментов на DPI он получил полностью собранный оригинал запроса с подмененным хостом.
|
||||||
|
Реальный хост идет отдельным сегментом уже после. То есть в этом варианте применяется разновидность disorder. Сервер принимает фрагменты с нарушенным порядком sequence.
|
||||||
|
|
||||||
|
Опционально можно разрезать оригинальный фейк. Например, `--dpi-desync-hostfakesplit-midhost=midsld`. Позиция нарезки должна попадать внутрь хоста.
|
||||||
|
Многопакетные запросы поддерживаются только, если исходная нарезка пакетов не включает позиции имени хоста. В последнем случае дурение отменяется.
|
||||||
|
|
||||||
|
Вариант `fakedsplit` имеет несколько альтернативных порядков нарезки - от 0 до 3. Режим задается в параметре `--dpi-desync-fakedsplit-mod=altorder=N`.
|
||||||
|
Каждый следующий altorder убирает часть фейков.
|
||||||
|
|
||||||
Для определения позиций нарезки используются маркеры.
|
Для определения позиций нарезки используются маркеры.
|
||||||
|
|
||||||
* **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала.
|
* **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала.
|
||||||
@@ -783,7 +842,7 @@ L7 протокол становится известен обычно посл
|
|||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> user-mode реализация ipset создавалась не как удобная замена *nix версии, реализованной в ядре.
|
> user-mode реализация ipset создавалась не как удобная замена *nix версии, реализованной в ядре.
|
||||||
> Вариант в ядре работает гораздо эффективнее. Это создавалось для систем без подд3ержки ipset в ядре.
|
> Вариант в ядре работает гораздо эффективнее. Это создавалось для систем без поддержки ipset в ядре.
|
||||||
> Конкретно - Windows и ядра Linux, собранные без nftables и ipset модулей ядра. Например, в android нет ipset.
|
> Конкретно - Windows и ядра Linux, собранные без nftables и ipset модулей ядра. Например, в android нет ipset.
|
||||||
|
|
||||||
### ФИЛЬТРАЦИЯ ПО WIFI
|
### ФИЛЬТРАЦИЯ ПО WIFI
|
||||||
@@ -1744,6 +1803,8 @@ SECURE_DNS=0|1 - принудительно выключить или включ
|
|||||||
DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера
|
DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера
|
||||||
DOH_SERVER - конкретный DoH URL, отказ от поиска
|
DOH_SERVER - конкретный DoH URL, отказ от поиска
|
||||||
UNBLOCKED_DOM - незаблокированный домен, который используется для тестов IP block
|
UNBLOCKED_DOM - незаблокированный домен, который используется для тестов IP block
|
||||||
|
SIMULATE=1 - включить режим симуляции для отладки логики скрипта. отключаются реальные запросы через curl, заменяются рандомным результатом.
|
||||||
|
SIM_SUCCESS_RATE=<percent> - вероятность успеха симуляции в процентах
|
||||||
```
|
```
|
||||||
|
|
||||||
Пример запуска с переменными:\
|
Пример запуска с переменными:\
|
||||||
|
|||||||
+15
-1
@@ -47,7 +47,9 @@ Task of `iptables` is done inside `winws` through `windivert` filters. `Windiver
|
|||||||
--wf-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
|
--wf-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
|
||||||
--wf-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation. multiple comma separated values allowed.
|
--wf-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation. multiple comma separated values allowed.
|
||||||
--wf-udp=[~]port1[-port2] ; UDP port filter. ~ means negation. multiple comma separated values allowed.
|
--wf-udp=[~]port1[-port2] ; UDP port filter. ~ means negation. multiple comma separated values allowed.
|
||||||
--wf-raw=<filter>|@<filename> ; raw windivert filter string or filename
|
--wf-raw-part=<filter>|@<filename> ; partial raw windivert filter string or filename
|
||||||
|
--wf-filter-lan=0|1 ; add excluding filter for non-global IP (default : 1)
|
||||||
|
--wf-raw=<filter>|@<filename> ; full raw windivert filter string or filename. replaces --wf-tcp,--wf-udp,--wf-raw-part
|
||||||
--wf-save=<filename> ; save windivert filter string to a file and exit
|
--wf-save=<filename> ; save windivert filter string to a file and exit
|
||||||
--ssid-filter=ssid1[,ssid2,ssid3,...] ; enable winws only if any of specified wifi SSIDs connected
|
--ssid-filter=ssid1[,ssid2,ssid3,...] ; enable winws only if any of specified wifi SSIDs connected
|
||||||
--nlm-filter=net1[,net2,net3,...] ; enable winws only if any of specified NLM network is connected. names and GUIDs are accepted.
|
--nlm-filter=net1[,net2,net3,...] ; enable winws only if any of specified NLM network is connected. names and GUIDs are accepted.
|
||||||
@@ -60,6 +62,12 @@ Interface indexes can be discovered using this command : `netsh int ip show int`
|
|||||||
|
|
||||||
If you can't find index this way use `winws --debug` to see index there. Subinterface index is almost always 0 and you can omit it.
|
If you can't find index this way use `winws --debug` to see index there. Subinterface index is almost always 0 and you can omit it.
|
||||||
|
|
||||||
|
`--wf-raw-part` specifies partial windivert filter. Multiple filter parts are supported. They can also be combined with `--wf-tcp`,`--wf-udp`.
|
||||||
|
|
||||||
|
`--wf-raw` specifies full windivert filter that replaces `--wf-tcp`,`--wf-udp`,`--wf-raw-part`.
|
||||||
|
|
||||||
|
Kernel filtering with windivert language is much more effective than passing massive amount of traffic to winws. Use it if possible to save CPU resources.
|
||||||
|
|
||||||
Multiple `winws` processes are allowed. However, it's discouraged to intersect their filters.
|
Multiple `winws` processes are allowed. However, it's discouraged to intersect their filters.
|
||||||
|
|
||||||
`--ssid-filter` allows to enable `winws` only if specified wifi networks are connected. `winws` auto detects SSID appearance and disappearance.
|
`--ssid-filter` allows to enable `winws` only if specified wifi networks are connected. `winws` auto detects SSID appearance and disappearance.
|
||||||
@@ -165,3 +173,9 @@ clone the code in all cmd files to support multiple tasks `winws1,winws2,winws3,
|
|||||||
Tasks can also be controlled from GUI `taskschd.msc`.
|
Tasks can also be controlled from GUI `taskschd.msc`.
|
||||||
|
|
||||||
Also you can use windows services the same way with `service_*.cmd`.
|
Also you can use windows services the same way with `service_*.cmd`.
|
||||||
|
|
||||||
|
### Windows Server
|
||||||
|
|
||||||
|
winws is linked against wlanapi.dll which is absent by default.
|
||||||
|
To solve this problem run power shell as administrator and execute command `Install-WindowsFeature -Name Wireless-Networking`.
|
||||||
|
Then reboot the system.
|
||||||
|
|||||||
+22
-6
@@ -44,7 +44,7 @@ tpws в режиме socks можно запускать под более-ме
|
|||||||
|
|
||||||
Это вариант пакетного фильтра nfqws для Windows, построенный на базе windivert.
|
Это вариант пакетного фильтра nfqws для Windows, построенный на базе windivert.
|
||||||
Все функции работоспособны, однако функционал ipset в ядре отсутствует. Он реализован в user mode. Фильтры по большому количеству IP адресов невозможны.
|
Все функции работоспособны, однако функционал ipset в ядре отсутствует. Он реализован в user mode. Фильтры по большому количеству IP адресов невозможны.
|
||||||
Работа с проходящим трафиком, например в случае "расшаривания" соединения, не проверялась и не гарантируется.
|
Работа с проходящим трафиком, например в случае "расшаривания" соединения, невозможна.
|
||||||
Для работы с windivert требуются права администратора.
|
Для работы с windivert требуются права администратора.
|
||||||
Специфические для unix параметры, такие как `--uid`, `--user` и тд, исключены. Все остальные параметры аналогичны nfqws и dvtws.
|
Специфические для unix параметры, такие как `--uid`, `--user` и тд, исключены. Все остальные параметры аналогичны nfqws и dvtws.
|
||||||
|
|
||||||
@@ -67,7 +67,9 @@ secure boot могут быть проблемы из-за подписи дра
|
|||||||
--wf-l3=ipv4|ipv6 ; фильтр L3 протоколов. по умолчанию включены ipv4 и ipv6.
|
--wf-l3=ipv4|ipv6 ; фильтр L3 протоколов. по умолчанию включены ipv4 и ipv6.
|
||||||
--wf-tcp=[~]port1[-port2] ; фильтр портов для tcp. ~ означает отрицание
|
--wf-tcp=[~]port1[-port2] ; фильтр портов для tcp. ~ означает отрицание
|
||||||
--wf-udp=[~]port1[-port2] ; фильтр портов для udp. ~ означает отрицание
|
--wf-udp=[~]port1[-port2] ; фильтр портов для udp. ~ означает отрицание
|
||||||
--wf-raw=<filter>|@<filename> ; задать напрямую фильтр windivert из параметра или из файла. имени файла предшествует символ @.
|
--wf-raw-part=<filter>|@<filename> ; частичный windivert фильтр из параметра или из файла. имени файла предшествует символ @. может быть множество частей. сочетается с --wf-tcp,--wf-udp.
|
||||||
|
--wf-filter-lan=0|1 ; отфильтровывать адреса назначения, не являющиеся глобальными inet адресами ipv4 или ipv6. по умолчанию - 1.
|
||||||
|
--wf-raw=<filter>|@<filename> ; полный windivert фильтр из параметра или из файла. имени файла предшествует символ @. замещает --wf-raw-part,--wf-tcp,--wf-udp.
|
||||||
--wf-save=<filename> ; сохранить сконструированный фильтр windivert в файл для последующей правки вручную
|
--wf-save=<filename> ; сохранить сконструированный фильтр windivert в файл для последующей правки вручную
|
||||||
--ssid-filter=ssid1[,ssid2,ssid3,...] ; включать winws только когда подключена любая из указанных wifi сетей
|
--ssid-filter=ssid1[,ssid2,ssid3,...] ; включать winws только когда подключена любая из указанных wifi сетей
|
||||||
--nlm-filter=net1[,net2,net3,...] ; включать winws только когда подключена любая из указанных сетей NLM
|
--nlm-filter=net1[,net2,net3,...] ; включать winws только когда подключена любая из указанных сетей NLM
|
||||||
@@ -80,11 +82,19 @@ secure boot могут быть проблемы из-за подписи дра
|
|||||||
Некоторых типы соединений там не увидеть. В этом случае запускайте **winws** с параметром `--debug` и смотрите IfIdx там.
|
Некоторых типы соединений там не увидеть. В этом случае запускайте **winws** с параметром `--debug` и смотрите IfIdx там.
|
||||||
SubInterface используется windivert, но практически всегда **0**, его можно не указывать. Вероятно, он нужен в редких случаях.
|
SubInterface используется windivert, но практически всегда **0**, его можно не указывать. Вероятно, он нужен в редких случаях.
|
||||||
|
|
||||||
Конструктор фильтров автоматически включает входящие tcp пакеты с tcp synack и tcp rst для корректной работы функций
|
Конструктор стандартных фильтров автоматически включает входящие tcp пакеты с tcp synack и tcp rst для корректной работы функций
|
||||||
autottl и autohostlist. При включении autohostlist так же перенаправляются пакеты данных с http redirect с кодами 302 и 307.
|
autottl и autohostlist. При включении autohostlist так же перенаправляются пакеты данных с http redirect с кодами 302 и 307.
|
||||||
Всегда добавляется фильтр на исключение не-интернет адресов ipv4 и ipv6.
|
Если не указаное иное, добавляется фильтр на исключение не-интернет адресов ipv4 и ipv6.
|
||||||
Для сложных нестандартных сценариев могут потребоваться свои фильтры. Логично будет начать со стандартного шаблона,
|
Для сложных нестандартных сценариев могут потребоваться свои фильтры. Полный фильтр --wf-raw замещает все остальное.
|
||||||
сохраненного через `--wf-save`. Нужно править файл и подсовывать его в параметре `--wf-raw`. Максимальный размер фильтра - **16 Kb**.
|
Частичные фильтры `--wf-raw-part` совместимы друг с другом и `--wf-tcp` и `--wf-udp`. Они позволяют исключить написание
|
||||||
|
громоздких полных фильтров, сосредоточившись лишь на добавлении какого-то особенного пейлоада.
|
||||||
|
`--wf-save` позволяет записать итоговый windivert фильтр в файл. Максимальный размер фильтра - **16 Kb**.
|
||||||
|
|
||||||
|
Фильтрация windivert производится в ядре. Это несравнимо легче по ресурсам, чем перенаправлять пакеты в пространство user mode,
|
||||||
|
чтобы winws принимал решение. Поэтому пользуйтесь по максимуму возможностями windivert.
|
||||||
|
Например, если вам нужно дурить wireguard на все порты, вам придется перенаправить все порты на winws. Или же написать windivert фильтр, который отсечет wireguard по содержимому пакета.
|
||||||
|
Разница в нагрузке на процессор колоссальна. В первом случае - до 100% одного ядра cpu в зависимости от обьема исходящего udp трафика (привет, торрент и uTP), во втором - близко к 0.
|
||||||
|
Кроме нагрузки на процессор еще можете порезать себе скорость, тк одно ядро не будет справляться с обработкой вашего гигабитного интернета. А на старых ноутах еще и получите самолетный вой системы охлаждения, приводящий к ее износу.
|
||||||
|
|
||||||
Можно запускать несколько процессов **winws** с разными стратегиями. Однако, не следует делать пересекающиеся фильтры.
|
Можно запускать несколько процессов **winws** с разными стратегиями. Однако, не следует делать пересекающиеся фильтры.
|
||||||
|
|
||||||
@@ -257,3 +267,9 @@ _zapret-winws_ - это отдельный комплект для повсед
|
|||||||
Все батники требуется запускать от имени администратора.
|
Все батники требуется запускать от имени администратора.
|
||||||
|
|
||||||
Управлять задачами можно так же из графической программы управления планировщиком `taskschd.msc`
|
Управлять задачами можно так же из графической программы управления планировщиком `taskschd.msc`
|
||||||
|
|
||||||
|
## Особенности Windows Server
|
||||||
|
|
||||||
|
winws слинкован с wlanapi.dll, который по умолчанию не установлен в windows server.
|
||||||
|
Для решения этой проблемы запустите power shell под администратором и выполните команду `Install-WindowsFeature -Name Wireless-Networking`.
|
||||||
|
После чего перезагрузите систему.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering
|
# this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering
|
||||||
|
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||||
|
|
||||||
# can override in config :
|
# can override in config :
|
||||||
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---dpi-desync=tamper}"
|
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---dpi-desync=tamper}"
|
||||||
@@ -32,6 +33,6 @@ zapret_custom_firewall_nft()
|
|||||||
local f
|
local f
|
||||||
local first_packet_only="$nft_connbytes 1"
|
local first_packet_only="$nft_connbytes 1"
|
||||||
|
|
||||||
f="meta length 109-407 meta l4proto udp @th,64,16 0x6431"
|
f="meta length 109-407 meta l4proto udp @ih,0,16 0x6431"
|
||||||
nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL
|
nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# this custom script runs desync to all discord media packets
|
# this custom script runs desync to all discord media packets
|
||||||
|
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||||
|
|
||||||
# can override in config :
|
# can override in config :
|
||||||
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---dpi-desync=fake}"
|
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---dpi-desync=fake --dpi-desync-repeats=2}"
|
||||||
DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}"
|
DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}"
|
||||||
|
|
||||||
alloc_dnum DNUM_DISCORD_MEDIA
|
alloc_dnum DNUM_DISCORD_MEDIA
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# this custom script runs desync to all stun packets
|
# this custom script runs desync to all stun packets
|
||||||
|
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||||
|
|
||||||
# can override in config :
|
# can override in config :
|
||||||
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---dpi-desync=fake}"
|
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---dpi-desync=fake --dpi-desync-repeats=2}"
|
||||||
|
|
||||||
alloc_dnum DNUM_STUN4ALL
|
alloc_dnum DNUM_STUN4ALL
|
||||||
alloc_qnum QNUM_STUN4ALL
|
alloc_qnum QNUM_STUN4ALL
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# this custom script runs desync to all wireguard handshake initiation packets
|
# this custom script runs desync to all wireguard handshake initiation packets
|
||||||
# NOTE: this works for original wireguard and may not work for 3rd party implementations such as xray
|
# NOTE: this works for original wireguard and may not work for 3rd party implementations such as xray
|
||||||
|
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||||
|
|
||||||
# can override in config :
|
# can override in config :
|
||||||
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---dpi-desync=fake}"
|
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---dpi-desync=fake --dpi-desync-repeats=2}"
|
||||||
|
|
||||||
alloc_dnum DNUM_WG4ALL
|
alloc_dnum DNUM_WG4ALL
|
||||||
alloc_qnum QNUM_WG4ALL
|
alloc_qnum QNUM_WG4ALL
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws.
|
Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws.
|
||||||
Задействуются через `winws --wf-raw=@filename`.
|
Задействуются через `winws --wf-raw-part=@filename`. Может быть несколько частичных фильтров. Они могут сочетаться с --wf-tcp и --wf-udp.
|
||||||
Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики.
|
Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики.
|
||||||
Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку.
|
Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку.
|
||||||
Дофильтрация производится силами winws.
|
Дофильтрация производится силами winws.
|
||||||
|
|
||||||
Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language
|
Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language
|
||||||
Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw=@windivert.discord_media+stun.txt --filter-l7=stun,discord --dpi-desync=fake`
|
Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw-part=@windivert_part.discord_media.txt --wf-raw-part=@windivert_part.stun.txt --filter-l7=stun,discord --dpi-desync=fake`
|
||||||
|
|
||||||
|
|
||||||
These filters are invoked using `winws --wf-raw=@filename`.
|
These filters are invoked using `winws --wf-raw-part=@filename`. Multiple filter parts are supported. They can be combined with --wf-tcp and --wf-udp.
|
||||||
Filters are kernel mode and save great amount of CPU.
|
Filters are kernel mode and save great amount of CPU.
|
||||||
However windivert cannot filter by bit fields, lacks shift and bitwise logic operations.
|
However windivert cannot filter by bit fields, lacks shift and bitwise logic operations.
|
||||||
Filters are relaxed and can pass wrong payloads. Finer filtering is done by winws.
|
Filters are relaxed and can pass wrong payloads. Finer filtering is done by winws.
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
!impostor and !loopback and
|
|
||||||
(outbound and
|
|
||||||
((ip and
|
|
||||||
udp.DstPort>=50000 and udp.DstPort<=50099 and
|
|
||||||
udp.PayloadLength=74 and
|
|
||||||
udp.Payload32[0]=0x00010046 and
|
|
||||||
udp.Payload32[2]=0 and
|
|
||||||
udp.Payload32[3]=0 and
|
|
||||||
udp.Payload32[4]=0 and
|
|
||||||
udp.Payload32[5]=0 and
|
|
||||||
udp.Payload32[6]=0 and
|
|
||||||
udp.Payload32[7]=0 and
|
|
||||||
udp.Payload32[8]=0 and
|
|
||||||
udp.Payload32[9]=0 and
|
|
||||||
udp.Payload32[10]=0 and
|
|
||||||
udp.Payload32[11]=0 and
|
|
||||||
udp.Payload32[12]=0 and
|
|
||||||
udp.Payload32[13]=0 and
|
|
||||||
udp.Payload32[14]=0 and
|
|
||||||
udp.Payload32[15]=0 and
|
|
||||||
udp.Payload32[16]=0 and
|
|
||||||
udp.Payload32[17]=0)
|
|
||||||
or
|
|
||||||
(udp.PayloadLength>=20 and
|
|
||||||
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40)) and
|
|
||||||
( ((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or
|
|
||||||
((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
!impostor and !loopback and
|
|
||||||
(outbound and
|
|
||||||
udp.PayloadLength>=20 and
|
|
||||||
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40 and
|
|
||||||
( ((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or
|
|
||||||
((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
!impostor and !loopback and
|
|
||||||
(outbound and
|
|
||||||
udp.PayloadLength=148 and
|
|
||||||
udp.Payload[0]=0x01 and
|
|
||||||
( ((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or
|
|
||||||
((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
+2
-5
@@ -1,5 +1,4 @@
|
|||||||
!impostor and !loopback and
|
outbound and ip and
|
||||||
(outbound and
|
|
||||||
udp.DstPort>=50000 and udp.DstPort<=50099 and
|
udp.DstPort>=50000 and udp.DstPort<=50099 and
|
||||||
udp.PayloadLength=74 and
|
udp.PayloadLength=74 and
|
||||||
udp.Payload32[0]=0x00010046 and
|
udp.Payload32[0]=0x00010046 and
|
||||||
@@ -18,6 +17,4 @@
|
|||||||
udp.Payload32[14]=0 and
|
udp.Payload32[14]=0 and
|
||||||
udp.Payload32[15]=0 and
|
udp.Payload32[15]=0 and
|
||||||
udp.Payload32[16]=0 and
|
udp.Payload32[16]=0 and
|
||||||
udp.Payload32[17]=0 and
|
udp.Payload32[17]=0
|
||||||
(ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
outbound and
|
||||||
|
udp.PayloadLength>=20 and
|
||||||
|
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
outbound and
|
||||||
|
udp.PayloadLength=148 and
|
||||||
|
udp.Payload[0]=0x01
|
||||||
@@ -83,6 +83,8 @@ typedef struct
|
|||||||
bool b_cutoff; // mark for deletion
|
bool b_cutoff; // mark for deletion
|
||||||
bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff;
|
bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff;
|
||||||
|
|
||||||
|
uint16_t ip_id;
|
||||||
|
|
||||||
t_l7proto l7proto;
|
t_l7proto l7proto;
|
||||||
bool l7proto_discovered;
|
bool l7proto_discovered;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
|
|||||||
+2
-2
@@ -420,7 +420,7 @@ bool prepare_udp_segment4(
|
|||||||
|
|
||||||
memcpy(payload,data,len);
|
memcpy(payload,data,len);
|
||||||
if (padding)
|
if (padding)
|
||||||
fill_pattern(payload+len,padlen,padding,padding_size);
|
fill_pattern(payload+len,padlen,padding,padding_size,0);
|
||||||
else
|
else
|
||||||
memset(payload+len,0,padlen);
|
memset(payload+len,0,padlen);
|
||||||
udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
|
udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
|
||||||
@@ -509,7 +509,7 @@ bool prepare_udp_segment6(
|
|||||||
|
|
||||||
memcpy(payload,data,len);
|
memcpy(payload,data,len);
|
||||||
if (padding)
|
if (padding)
|
||||||
fill_pattern(payload+len,padlen,padding,padding_size);
|
fill_pattern(payload+len,padlen,padding,padding_size,0);
|
||||||
else
|
else
|
||||||
memset(payload+len,0,padlen);
|
memset(payload+len,0,padlen);
|
||||||
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
|
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
|
||||||
|
|||||||
+368
-74
@@ -170,18 +170,20 @@ bool desync_only_first_stage(enum dpi_desync_mode mode)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool desync_valid_second_stage(enum dpi_desync_mode mode)
|
|
||||||
{
|
|
||||||
return mode==DESYNC_NONE || mode==DESYNC_FAKEDDISORDER || mode==DESYNC_FAKEDSPLIT || mode==DESYNC_MULTISPLIT || mode==DESYNC_MULTIDISORDER || mode==DESYNC_IPFRAG2 || mode==DESYNC_UDPLEN || mode==DESYNC_TAMPER;
|
|
||||||
}
|
|
||||||
bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode)
|
bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode)
|
||||||
{
|
{
|
||||||
return mode==DESYNC_NONE || mode==DESYNC_FAKEDDISORDER || mode==DESYNC_FAKEDSPLIT || mode==DESYNC_MULTISPLIT || mode==DESYNC_MULTIDISORDER || mode==DESYNC_IPFRAG2;
|
return
|
||||||
|
mode == DESYNC_NONE || mode == DESYNC_FAKEDDISORDER || mode == DESYNC_FAKEDSPLIT || mode == DESYNC_MULTISPLIT || mode == DESYNC_MULTIDISORDER || mode == DESYNC_HOSTFAKESPLIT ||
|
||||||
|
mode == DESYNC_IPFRAG2;
|
||||||
}
|
}
|
||||||
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode)
|
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode)
|
||||||
{
|
{
|
||||||
return mode == DESYNC_NONE || mode == DESYNC_UDPLEN || mode == DESYNC_TAMPER || mode == DESYNC_IPFRAG2;
|
return mode == DESYNC_NONE || mode == DESYNC_UDPLEN || mode == DESYNC_TAMPER || mode == DESYNC_IPFRAG2;
|
||||||
}
|
}
|
||||||
|
bool desync_valid_second_stage(enum dpi_desync_mode mode)
|
||||||
|
{
|
||||||
|
return desync_valid_second_stage_tcp(mode) || desync_valid_second_stage_udp(mode);
|
||||||
|
}
|
||||||
enum dpi_desync_mode desync_mode_from_string(const char *s)
|
enum dpi_desync_mode desync_mode_from_string(const char *s)
|
||||||
{
|
{
|
||||||
if (!s)
|
if (!s)
|
||||||
@@ -206,6 +208,8 @@ enum dpi_desync_mode desync_mode_from_string(const char *s)
|
|||||||
return DESYNC_MULTISPLIT;
|
return DESYNC_MULTISPLIT;
|
||||||
else if (!strcmp(s, "multidisorder") || !strcmp(s, "disorder2"))
|
else if (!strcmp(s, "multidisorder") || !strcmp(s, "disorder2"))
|
||||||
return DESYNC_MULTIDISORDER;
|
return DESYNC_MULTIDISORDER;
|
||||||
|
else if (!strcmp(s, "hostfakesplit"))
|
||||||
|
return DESYNC_HOSTFAKESPLIT;
|
||||||
else if (!strcmp(s, "ipfrag2"))
|
else if (!strcmp(s, "ipfrag2"))
|
||||||
return DESYNC_IPFRAG2;
|
return DESYNC_IPFRAG2;
|
||||||
else if (!strcmp(s, "hopbyhop"))
|
else if (!strcmp(s, "hopbyhop"))
|
||||||
@@ -831,20 +835,25 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef BSD
|
|
||||||
// BSD pass to divert socket ip_id=0 and does not auto set it if sent via divert socket
|
|
||||||
static uint16_t IP4_IP_ID_FIX(const struct ip *ip)
|
static uint16_t IP4_IP_ID_FIX(const struct ip *ip)
|
||||||
{
|
{
|
||||||
return ip ? ip->ip_id ? ip->ip_id : (uint16_t)random() : 0;
|
return ip ? ip->ip_id ? ip->ip_id : (uint16_t)random() : 0;
|
||||||
}
|
}
|
||||||
#define IP4_IP_ID_NEXT(ip_id) net16_add(ip_id,+1)
|
static uint16_t IP4_IP_ID_ADD(uint16_t ip_id, uint16_t inc)
|
||||||
#define IP4_IP_ID_PREV(ip_id) net16_add(ip_id,-1)
|
{
|
||||||
#else
|
if (ip_id)
|
||||||
// in linux kernel sets increasing ip_id if it's zero
|
{
|
||||||
#define IP4_IP_ID_FIX(x) 0
|
ip_id += net16_add(ip_id, inc);
|
||||||
#define IP4_IP_ID_NEXT(ip_id) ip_id
|
if (!ip_id) ip_id = net16_add(ip_id, ((int16_t)inc) < 0 ? -1 : 1); // do not allow zero
|
||||||
#define IP4_IP_ID_PREV(ip_id) ip_id
|
}
|
||||||
#endif
|
return ip_id;
|
||||||
|
}
|
||||||
|
#define IP4_IP_ID_ADD(ip_id,inc) (ip_id ? net16_add(ip_id,inc) : 0)
|
||||||
|
#define IP4_IP_ID_NEXT(ip_id) IP4_IP_ID_ADD(ip_id,+1)
|
||||||
|
#define IP4_IP_ID_PREV(ip_id) IP4_IP_ID_ADD(ip_id,-1)
|
||||||
|
//#define IP4_IP_ID_FIX(x) 0
|
||||||
|
//#define IP4_IP_ID_NEXT(ip_id) ip_id
|
||||||
|
//#define IP4_IP_ID_PREV(ip_id) ip_id
|
||||||
|
|
||||||
|
|
||||||
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
|
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
|
||||||
@@ -887,7 +896,7 @@ static bool runtime_tls_mod(int fake_n,const struct fake_tls_mod_cache *modcache
|
|||||||
if (payload_len < 44)
|
if (payload_len < 44)
|
||||||
DLOG("fake[%d] cannot apply dupsid tls mod. data payload is too short.\n", fake_n);
|
DLOG("fake[%d] cannot apply dupsid tls mod. data payload is too short.\n", fake_n);
|
||||||
else if (fake_data[43] != payload[43])
|
else if (fake_data[43] != payload[43])
|
||||||
DLOG("fake[%d] cannot apply dupsid tls mod. fake and orig session id length mismatch.\n",fake_n);
|
DLOG("fake[%d] cannot apply dupsid tls mod. fake and orig session id length mismatch : %u!=%u.\n", fake_n, fake_data[43], payload[43]);
|
||||||
else if (payload_len < (44 + payload[43]))
|
else if (payload_len < (44 + payload[43]))
|
||||||
DLOG("fake[%d] cannot apply dupsid tls mod. data payload is not valid.\n", fake_n);
|
DLOG("fake[%d] cannot apply dupsid tls mod. data payload is not valid.\n", fake_n);
|
||||||
else
|
else
|
||||||
@@ -1107,8 +1116,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
bool bFake = false;
|
bool bFake = false;
|
||||||
|
|
||||||
struct sockaddr_storage src, dst;
|
struct sockaddr_storage src, dst;
|
||||||
uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100];
|
uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN + 100], pkt2[DPI_DESYNC_MAX_FAKE_LEN + 100], pkt3[DPI_DESYNC_MAX_FAKE_LEN + 100];
|
||||||
size_t pkt1_len, pkt2_len;
|
size_t pkt1_len, pkt2_len, pkt3_len;
|
||||||
uint8_t ttl_orig, ttl_fake, flags_orig, scale_factor;
|
uint8_t ttl_orig, ttl_fake, flags_orig, scale_factor;
|
||||||
uint32_t *timestamps;
|
uint32_t *timestamps;
|
||||||
bool bSack, DF;
|
bool bSack, DF;
|
||||||
@@ -1429,7 +1438,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
size_t multisplit_pos[MAX_SPLITS];
|
size_t multisplit_pos[MAX_SPLITS];
|
||||||
int multisplit_count;
|
int multisplit_count;
|
||||||
int i;
|
int i;
|
||||||
uint16_t ip_id;
|
uint16_t ip_id = IP4_IP_ID_FIX(dis->ip);
|
||||||
|
|
||||||
bool bHaveHost = false, bHostIsIp = false;
|
bool bHaveHost = false, bHostIsIp = false;
|
||||||
t_l7proto l7proto = UNKNOWN;
|
t_l7proto l7proto = UNKNOWN;
|
||||||
|
|
||||||
@@ -1813,6 +1823,51 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
else
|
else
|
||||||
DLOG("regular split pos is outside of this packet\n");
|
DLOG("regular split pos is outside of this packet\n");
|
||||||
}
|
}
|
||||||
|
else if (dp->desync_mode == DESYNC_HOSTFAKESPLIT || dp->desync_mode2 == DESYNC_HOSTFAKESPLIT)
|
||||||
|
{
|
||||||
|
struct proto_pos splits[2] = {
|
||||||
|
{.marker = PM_HOST,.pos = 0},
|
||||||
|
{.marker = PM_HOST_END,.pos = 0}
|
||||||
|
};
|
||||||
|
split_pos = 0;
|
||||||
|
ResolveMultiPos(rdata_payload, rlen_payload, l7proto, splits, 2, multisplit_pos, &multisplit_count);
|
||||||
|
if (multisplit_count != 2)
|
||||||
|
{
|
||||||
|
DLOG("hostfakesplit: host and endhost positions not found\n");
|
||||||
|
multisplit_count = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
for (i = j = 0; i < multisplit_count; i++)
|
||||||
|
{
|
||||||
|
multisplit_pos[j] = pos_normalize(multisplit_pos[i], reasm_offset, dis->len_payload);
|
||||||
|
if (multisplit_pos[j]) j++;
|
||||||
|
}
|
||||||
|
multisplit_count = j;
|
||||||
|
if (multisplit_count != 2)
|
||||||
|
{
|
||||||
|
DLOG("hostfakesplit: host or endhost are outside of this packet\n");
|
||||||
|
multisplit_count = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DLOG("normalized hostfakesplit pos: ");
|
||||||
|
for (i = 0; i < multisplit_count; i++) DLOG("%zu ", multisplit_pos[i]);
|
||||||
|
DLOG("\n");
|
||||||
|
multisplit_pos[2] = ResolvePos(rdata_payload, rlen_payload, l7proto, &dp->hostfakesplit_midhost);
|
||||||
|
if (multisplit_pos[2])
|
||||||
|
{
|
||||||
|
multisplit_pos[2] = pos_normalize(multisplit_pos[2], reasm_offset, dis->len_payload);
|
||||||
|
if (multisplit_pos[2] > multisplit_pos[0] && multisplit_pos[2] < multisplit_pos[1])
|
||||||
|
{
|
||||||
|
DLOG("normalized hostfakesplit midhost pos: %zu\n", multisplit_pos[2]);
|
||||||
|
multisplit_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
multisplit_count = 0;
|
multisplit_count = 0;
|
||||||
@@ -1848,12 +1903,13 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
|
|
||||||
{
|
{
|
||||||
struct blob_item *fake_item;
|
struct blob_item *fake_item;
|
||||||
|
size_t fake_size;
|
||||||
uint8_t *fake_data;
|
uint8_t *fake_data;
|
||||||
uint8_t fake_data_buf[FAKE_MAX_TCP];
|
uint8_t fake_data_buf[FAKE_MAX_TCP];
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
uint32_t sequence, sequence0;
|
||||||
|
|
||||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
sequence = sequence0 = ntohl(dis->tcp->th_seq);
|
||||||
|
|
||||||
LIST_FOREACH(fake_item, fake, next)
|
LIST_FOREACH(fake_item, fake, next)
|
||||||
{
|
{
|
||||||
n++;
|
n++;
|
||||||
@@ -1869,23 +1925,27 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
default:
|
default:
|
||||||
fake_data = fake_item->data;
|
fake_data = fake_item->data;
|
||||||
}
|
}
|
||||||
|
fake_data += fake_item->offset;
|
||||||
|
fake_size = fake_item->size - fake_item->offset;
|
||||||
|
|
||||||
pkt1_len = sizeof(pkt1);
|
pkt1_len = sizeof(pkt1);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, htonl(sequence), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||||
DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
||||||
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
||||||
fake_data, fake_item->size, pkt1, &pkt1_len))
|
fake_data, fake_size, pkt1, &pkt1_len))
|
||||||
{
|
{
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_orig_cancel(ctrack);
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
DLOG("sending fake[%d] : ", n);
|
DLOG("sending fake[%d] seq=+%u : ", n, sequence - sequence0);
|
||||||
hexdump_limited_dlog(fake_data,fake_item->size,PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(fake_data, fake_size, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
||||||
{
|
{
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_orig_cancel(ctrack);
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
ip_id = IP4_IP_ID_NEXT(ip_id);
|
ip_id = IP4_IP_ID_NEXT(ip_id);
|
||||||
|
if (dp->tcp_mod.seq) sequence += fake_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bFake = true;
|
bFake = true;
|
||||||
@@ -1895,7 +1955,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
if (reasm_offset) break;
|
if (reasm_offset) break;
|
||||||
pkt1_len = sizeof(pkt1);
|
pkt1_len = sizeof(pkt1);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (dp->desync_mode == DESYNC_RSTACK ? TH_ACK : 0), false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_RST | (dp->desync_mode == DESYNC_RSTACK ? TH_ACK : 0), false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||||
DF,ttl_fake,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
|
DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
||||||
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
||||||
NULL, 0, pkt1, &pkt1_len))
|
NULL, 0, pkt1, &pkt1_len))
|
||||||
{
|
{
|
||||||
@@ -1908,6 +1968,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
reasm_orig_cancel(ctrack);
|
reasm_orig_cancel(ctrack);
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id);
|
||||||
bFake = true;
|
bFake = true;
|
||||||
break;
|
break;
|
||||||
case DESYNC_HOPBYHOP:
|
case DESYNC_HOPBYHOP:
|
||||||
@@ -1916,6 +1977,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
fooling_orig = (dp->desync_mode == DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (dp->desync_mode == DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1;
|
fooling_orig = (dp->desync_mode == DESYNC_HOPBYHOP) ? FOOL_HOPBYHOP : (dp->desync_mode == DESYNC_DESTOPT) ? FOOL_DESTOPT : FOOL_IPFRAG1;
|
||||||
if (dis->ip6 && (dp->desync_mode2 == DESYNC_NONE || !desync_valid_second_stage_tcp(dp->desync_mode2) ||
|
if (dis->ip6 && (dp->desync_mode2 == DESYNC_NONE || !desync_valid_second_stage_tcp(dp->desync_mode2) ||
|
||||||
(!split_pos && (dp->desync_mode2 == DESYNC_FAKEDSPLIT || dp->desync_mode2 == DESYNC_FAKEDDISORDER)) ||
|
(!split_pos && (dp->desync_mode2 == DESYNC_FAKEDSPLIT || dp->desync_mode2 == DESYNC_FAKEDDISORDER)) ||
|
||||||
|
(multisplit_count < 2 && dp->desync_mode2 == DESYNC_HOSTFAKESPLIT) ||
|
||||||
(!multisplit_count && (dp->desync_mode2 == DESYNC_MULTISPLIT || dp->desync_mode2 == DESYNC_MULTIDISORDER))))
|
(!multisplit_count && (dp->desync_mode2 == DESYNC_MULTISPLIT || dp->desync_mode2 == DESYNC_MULTIDISORDER))))
|
||||||
{
|
{
|
||||||
reasm_orig_cancel(ctrack);
|
reasm_orig_cancel(ctrack);
|
||||||
@@ -1947,6 +2009,175 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
enum dpi_desync_mode desync_mode = dp->desync_mode2 == DESYNC_NONE ? dp->desync_mode : dp->desync_mode2;
|
enum dpi_desync_mode desync_mode = dp->desync_mode2 == DESYNC_NONE ? dp->desync_mode : dp->desync_mode2;
|
||||||
switch (desync_mode)
|
switch (desync_mode)
|
||||||
{
|
{
|
||||||
|
case DESYNC_HOSTFAKESPLIT:
|
||||||
|
// can be 2 or 3 split pos
|
||||||
|
// if 2 split pos : host, endhost
|
||||||
|
// if 3 split pos : host, endhost, midhost
|
||||||
|
if (multisplit_count >= 2)
|
||||||
|
{
|
||||||
|
uint8_t *seg;
|
||||||
|
size_t seg_len, host_size, pos_host, pos_endhost, pos_split_host, sz;
|
||||||
|
uint8_t *fakehost;
|
||||||
|
uint16_t ip_id_after_host;
|
||||||
|
|
||||||
|
seg = dis->data_payload;
|
||||||
|
seg_len = dis->len_payload;
|
||||||
|
pos_host = multisplit_pos[0];
|
||||||
|
pos_endhost = multisplit_pos[1];
|
||||||
|
pos_split_host = multisplit_count >= 3 ? multisplit_pos[2] : 0;
|
||||||
|
host_size = pos_endhost - pos_host;
|
||||||
|
|
||||||
|
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id;
|
||||||
|
|
||||||
|
// before_host segment
|
||||||
|
pkt1_len = sizeof(pkt1);
|
||||||
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0,
|
||||||
|
dis->tcp->th_seq, dis->tcp->th_ack,
|
||||||
|
dis->tcp->th_win, scale_factor, timestamps,
|
||||||
|
DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
||||||
|
fooling_orig, 0, 0, 0,
|
||||||
|
seg, pos_host, pkt1, &pkt1_len))
|
||||||
|
goto send_orig;
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id);
|
||||||
|
DLOG("sending hostfakesplit before_host part 0-%zu len=%zu : ", pos_host - 1, pos_host);
|
||||||
|
hexdump_limited_dlog(seg, pos_host, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
||||||
|
goto send_orig;
|
||||||
|
|
||||||
|
if (!(fakehost = malloc(host_size + 1)))
|
||||||
|
{
|
||||||
|
DLOG("fakehost out of memory\n");
|
||||||
|
goto send_orig;
|
||||||
|
}
|
||||||
|
if (*dp->hfs_mod.host)
|
||||||
|
{
|
||||||
|
if (host_size <= dp->hfs_mod.host_size)
|
||||||
|
{
|
||||||
|
// "google.com" => "gle.com"
|
||||||
|
// "google.com" => "google.com"
|
||||||
|
memcpy(fakehost, dp->hfs_mod.host + dp->hfs_mod.host_size - host_size, host_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// "google.com" => "nb4auv9.google.com"
|
||||||
|
// "google.com" => ".google.com"
|
||||||
|
sz = host_size - dp->hfs_mod.host_size;
|
||||||
|
memcpy(fakehost + sz, dp->hfs_mod.host, dp->hfs_mod.host_size);
|
||||||
|
fakehost[--sz] = '.';
|
||||||
|
if (sz)
|
||||||
|
{
|
||||||
|
fill_random_az(fakehost, 1);
|
||||||
|
sz--;
|
||||||
|
}
|
||||||
|
fill_random_az09(fakehost + 1, sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fill_random_az(fakehost, 1);
|
||||||
|
fill_random_az09(fakehost + 1, host_size - 1);
|
||||||
|
if (host_size >= 7)
|
||||||
|
{
|
||||||
|
fakehost[host_size - 4] = '.';
|
||||||
|
memcpy(fakehost + host_size - 3, tld[random() % (sizeof(tld) / sizeof(*tld))], 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fakehost[host_size] = 0;
|
||||||
|
DLOG("generated fake host: %s\n", fakehost);
|
||||||
|
|
||||||
|
// pkt2: fake_host segment
|
||||||
|
pkt2_len = sizeof(pkt2);
|
||||||
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0,
|
||||||
|
net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||||
|
DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
||||||
|
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
||||||
|
fakehost, host_size, pkt2, &pkt2_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
|
||||||
|
DLOG("sending hostfakesplit fake host %zu-%zu len=%zu : ", pos_host, pos_endhost - 1, host_size);
|
||||||
|
hexdump_limited_dlog(fakehost, host_size, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
|
||||||
|
ip_id_after_host = IP4_IP_ID_NEXT(ip_id);
|
||||||
|
if (pos_split_host) ip_id_after_host = IP4_IP_ID_NEXT(ip_id_after_host);
|
||||||
|
|
||||||
|
// pkt3: after_host segment
|
||||||
|
pkt3_len = sizeof(pkt3);
|
||||||
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0,
|
||||||
|
net32_add(dis->tcp->th_seq, pos_endhost), dis->tcp->th_ack,
|
||||||
|
dis->tcp->th_win, scale_factor, timestamps,
|
||||||
|
DF, ttl_orig, IP4_TOS(dis->ip), ip_id_after_host, IP6_FLOW(dis->ip6),
|
||||||
|
fooling_orig, 0, 0, 0,
|
||||||
|
seg + pos_endhost, seg_len - pos_endhost, pkt3, &pkt3_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
|
||||||
|
if (dp->hfs_mod.ordering == 1)
|
||||||
|
{
|
||||||
|
DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ", pos_endhost, seg_len - 1, seg_len - pos_endhost);
|
||||||
|
hexdump_limited_dlog(seg + pos_endhost, seg_len - pos_endhost, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt3, pkt3_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
sz = pos_split_host ? pos_split_host - pos_host : host_size;
|
||||||
|
pkt1_len = sizeof(pkt1);
|
||||||
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0,
|
||||||
|
net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack,
|
||||||
|
dis->tcp->th_win, scale_factor, timestamps,
|
||||||
|
DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
||||||
|
fooling_orig, 0, 0, 0,
|
||||||
|
seg + pos_host, sz, pkt1, &pkt1_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
|
||||||
|
DLOG("sending hostfakesplit real host %s%zu-%zu len=%zu : ", pos_split_host ? "part 1 " : "", pos_host, pos_host + sz - 1, sz);
|
||||||
|
hexdump_limited_dlog(seg + pos_host, sz, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
|
||||||
|
if (pos_split_host)
|
||||||
|
{
|
||||||
|
sz = pos_endhost - pos_split_host;
|
||||||
|
pkt1_len = sizeof(pkt1);
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id);
|
||||||
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0,
|
||||||
|
net32_add(dis->tcp->th_seq, pos_split_host), dis->tcp->th_ack,
|
||||||
|
dis->tcp->th_win, scale_factor, timestamps,
|
||||||
|
DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
||||||
|
fooling_orig, 0, 0, 0,
|
||||||
|
seg + pos_split_host, sz, pkt1, &pkt1_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
DLOG("sending hostfakesplit real host part 2 %zu-%zu len=%zu : ", pos_split_host, pos_endhost - 1, sz);
|
||||||
|
hexdump_limited_dlog(seg + pos_split_host, sz, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dp->hfs_mod.ordering == 0)
|
||||||
|
{
|
||||||
|
DLOG("sending hostfakesplit fake(2) host %zu-%zu len=%zu : ", pos_host, pos_endhost - 1, host_size);
|
||||||
|
hexdump_limited_dlog(fakehost, host_size, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
|
||||||
|
DLOG("sending hostfakesplit after_host part %zu-%zu len=%zu : ", pos_endhost, seg_len - 1, seg_len - pos_endhost);
|
||||||
|
hexdump_limited_dlog(seg + pos_endhost, seg_len - pos_endhost, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt3, pkt3_len))
|
||||||
|
goto send_orig_clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fakehost);
|
||||||
|
|
||||||
|
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_after_host);
|
||||||
|
|
||||||
|
return VERDICT_DROP;
|
||||||
|
send_orig_clean:
|
||||||
|
free(fakehost);
|
||||||
|
goto send_orig;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto unsplitted_part;
|
||||||
|
|
||||||
case DESYNC_MULTISPLIT:
|
case DESYNC_MULTISPLIT:
|
||||||
if (multisplit_count)
|
if (multisplit_count)
|
||||||
{
|
{
|
||||||
@@ -1954,7 +2185,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
size_t seg_len, from, to;
|
size_t seg_len, from, to;
|
||||||
unsigned int seqovl;
|
unsigned int seqovl;
|
||||||
|
|
||||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id;
|
||||||
|
|
||||||
for (i = 0, from = 0; i <= multisplit_count; i++)
|
for (i = 0, from = 0; i <= multisplit_count; i++)
|
||||||
{
|
{
|
||||||
@@ -1977,7 +2208,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
DLOG("seqovl is too large");
|
DLOG("seqovl is too large");
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern));
|
fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0);
|
||||||
memcpy(ovlseg + seqovl, dis->data_payload + from, to - from);
|
memcpy(ovlseg + seqovl, dis->data_payload + from, to - from);
|
||||||
seg = ovlseg;
|
seg = ovlseg;
|
||||||
}
|
}
|
||||||
@@ -2017,17 +2248,25 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
|
|
||||||
from = to;
|
from = to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (replay) ctrack_replay->ip_id = ip_id;
|
||||||
|
|
||||||
return VERDICT_DROP;
|
return VERDICT_DROP;
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
|
goto unsplitted_part;
|
||||||
|
|
||||||
case DESYNC_MULTIDISORDER:
|
case DESYNC_MULTIDISORDER:
|
||||||
if (multisplit_count)
|
if (multisplit_count)
|
||||||
{
|
{
|
||||||
uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], *seg;
|
uint8_t ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], *seg;
|
||||||
size_t seg_len, from, to;
|
size_t seg_len, from, to;
|
||||||
unsigned int seqovl;
|
unsigned int seqovl;
|
||||||
|
uint16_t ip_id_end;
|
||||||
|
|
||||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id;
|
||||||
|
|
||||||
|
ip_id_end = ip_id = IP4_IP_ID_ADD(ip_id, (uint16_t)multisplit_count);
|
||||||
|
|
||||||
for (i = multisplit_count - 1, to = dis->len_payload; i >= -1; i--)
|
for (i = multisplit_count - 1, to = dis->len_payload; i >= -1; i--)
|
||||||
{
|
{
|
||||||
@@ -2042,7 +2281,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
if (seqovl_pos >= from)
|
if (seqovl_pos >= from)
|
||||||
DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl for part %d.\n",seqovl,from,i+2);
|
DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl for part %d.\n", seqovl_pos, from, i + 2);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
seqovl = seqovl_pos;
|
seqovl = seqovl_pos;
|
||||||
@@ -2052,7 +2291,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
DLOG("seqovl is too large");
|
DLOG("seqovl is too large");
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern));
|
fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0);
|
||||||
memcpy(ovlseg + seqovl, dis->data_payload + from, to - from);
|
memcpy(ovlseg + seqovl, dis->data_payload + from, to - from);
|
||||||
seg = ovlseg;
|
seg = ovlseg;
|
||||||
}
|
}
|
||||||
@@ -2074,32 +2313,45 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
|
|
||||||
to = from;
|
to = from;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_end);
|
||||||
|
|
||||||
return VERDICT_DROP;
|
return VERDICT_DROP;
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
|
goto unsplitted_part;
|
||||||
|
|
||||||
case DESYNC_FAKEDDISORDER:
|
case DESYNC_FAKEDDISORDER:
|
||||||
if (split_pos)
|
|
||||||
{
|
{
|
||||||
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], fakeseg2[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg;
|
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], fakeseg2[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg;
|
||||||
size_t seg_len, fakeseg2_len;
|
size_t seg_len, fakeseg2_len;
|
||||||
unsigned int seqovl;
|
unsigned int seqovl;
|
||||||
|
int order;
|
||||||
|
|
||||||
if (dis->len_payload > sizeof(pat))
|
if (dis->len_payload > sizeof(pat))
|
||||||
{
|
{
|
||||||
DLOG("packet is too large\n");
|
DLOG("packet is too large\n");
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern));
|
|
||||||
|
|
||||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id;
|
||||||
|
|
||||||
if (seqovl_pos>=split_pos)
|
|
||||||
{
|
|
||||||
DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n",seqovl_pos,split_pos);
|
|
||||||
seqovl = 0;
|
seqovl = 0;
|
||||||
}
|
if (split_pos)
|
||||||
|
{
|
||||||
|
order = dp->fs_mod.ordering & 3;
|
||||||
|
if (seqovl_pos >= split_pos)
|
||||||
|
DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n", seqovl_pos, split_pos);
|
||||||
else
|
else
|
||||||
seqovl = seqovl_pos;
|
seqovl = seqovl_pos;
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
order = (dp->fs_mod.ordering >> 3) & 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
fill_pattern(pat, dis->len_payload, dp->fsplit_pattern, dp->fsplit_pattern_size, reasm_offset);
|
||||||
|
|
||||||
if (seqovl)
|
if (seqovl)
|
||||||
{
|
{
|
||||||
@@ -2109,7 +2361,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
DLOG("seqovl is too large\n");
|
DLOG("seqovl is too large\n");
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
fill_pattern(fakeseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern));
|
fill_pattern(fakeseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0);
|
||||||
memcpy(fakeseg + seqovl, dis->data_payload + split_pos, dis->len_payload - split_pos);
|
memcpy(fakeseg + seqovl, dis->data_payload + split_pos, dis->len_payload - split_pos);
|
||||||
seg = fakeseg;
|
seg = fakeseg;
|
||||||
}
|
}
|
||||||
@@ -2125,11 +2377,14 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
||||||
pat + split_pos, dis->len_payload - split_pos, fakeseg2, &fakeseg2_len))
|
pat + split_pos, dis->len_payload - split_pos, fakeseg2, &fakeseg2_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
|
||||||
|
if (order == 0)
|
||||||
|
{
|
||||||
DLOG("sending fake(1) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
DLOG("sending fake(1) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
||||||
hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
}
|
||||||
|
|
||||||
pkt1_len = sizeof(pkt1);
|
pkt1_len = sizeof(pkt1);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||||
@@ -2137,19 +2392,22 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
fooling_orig, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
fooling_orig, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
||||||
seg, seg_len, pkt1, &pkt1_len))
|
seg, seg_len, pkt1, &pkt1_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
|
||||||
DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu seqovl=%u : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos, seqovl);
|
DLOG("sending 2nd out-of-order tcp segment %zu-%zu len=%zu seqovl=%u : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos, seqovl);
|
||||||
hexdump_limited_dlog(seg, seg_len, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(seg, seg_len, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
|
||||||
if (dis->ip) ((struct ip*)fakeseg2)->ip_id = ip_id;
|
if (order <= 1)
|
||||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
{
|
||||||
|
|
||||||
DLOG("sending fake(2) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
DLOG("sending fake(2) 2nd out-of-order tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
||||||
hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg2, fakeseg2_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split_pos)
|
||||||
|
{
|
||||||
|
ip_id = IP4_IP_ID_PREV(ip_id);
|
||||||
|
|
||||||
seg_len = sizeof(fakeseg);
|
seg_len = sizeof(fakeseg);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||||
@@ -2157,7 +2415,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
||||||
pat, split_pos, fakeseg, &seg_len))
|
pat, split_pos, fakeseg, &seg_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
|
||||||
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
||||||
hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len))
|
||||||
@@ -2169,35 +2426,50 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
fooling_orig, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
fooling_orig, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
||||||
dis->data_payload, split_pos, pkt1, &pkt1_len))
|
dis->data_payload, split_pos, pkt1, &pkt1_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
|
||||||
DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
DLOG("sending 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
||||||
hexdump_limited_dlog(dis->data_payload, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(dis->data_payload, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
|
||||||
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
if (order <= 2)
|
||||||
|
{
|
||||||
DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
||||||
hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, seg_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id);
|
||||||
|
|
||||||
return VERDICT_DROP;
|
return VERDICT_DROP;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case DESYNC_FAKEDSPLIT:
|
case DESYNC_FAKEDSPLIT:
|
||||||
if (split_pos)
|
|
||||||
{
|
{
|
||||||
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg;
|
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN + 100], ovlseg[DPI_DESYNC_MAX_FAKE_LEN + 100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg;
|
||||||
size_t fakeseg_len, seg_len;
|
size_t fakeseg_len, seg_len;
|
||||||
|
int order;
|
||||||
|
|
||||||
|
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id;
|
||||||
|
|
||||||
if (dis->len_payload > sizeof(pat))
|
if (dis->len_payload > sizeof(pat))
|
||||||
{
|
{
|
||||||
DLOG("packet is too large\n");
|
DLOG("packet is too large\n");
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern));
|
|
||||||
|
|
||||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
fill_pattern(pat, dis->len_payload, dp->fsplit_pattern, dp->fsplit_pattern_size, reasm_offset);
|
||||||
|
|
||||||
|
if (split_pos)
|
||||||
|
{
|
||||||
|
order = dp->fs_mod.ordering & 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
order = (dp->fs_mod.ordering >> 3) & 3;
|
||||||
|
split_pos = dis->len_payload;
|
||||||
|
}
|
||||||
|
|
||||||
fakeseg_len = sizeof(fakeseg);
|
fakeseg_len = sizeof(fakeseg);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||||
@@ -2205,13 +2477,16 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
||||||
pat, split_pos, fakeseg, &fakeseg_len))
|
pat, split_pos, fakeseg, &fakeseg_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
|
||||||
|
if (order == 0)
|
||||||
|
{
|
||||||
DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
||||||
hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int seqovl = reasm_offset ? 0 : seqovl_pos;
|
unsigned int seqovl = (reasm_offset || split_pos>=dis->len_payload) ? 0 : seqovl_pos;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
// only linux return error if MTU is exceeded
|
// only linux return error if MTU is exceeded
|
||||||
for (;; seqovl = 0)
|
for (;; seqovl = 0)
|
||||||
@@ -2222,10 +2497,10 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
seg_len = split_pos + seqovl;
|
seg_len = split_pos + seqovl;
|
||||||
if (seg_len > sizeof(ovlseg))
|
if (seg_len > sizeof(ovlseg))
|
||||||
{
|
{
|
||||||
DLOG("seqovl is too large");
|
DLOG("seqovl is too large\n");
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
fill_pattern(ovlseg,seqovl,dp->seqovl_pattern,sizeof(dp->seqovl_pattern));
|
fill_pattern(ovlseg, seqovl, dp->seqovl_pattern, sizeof(dp->seqovl_pattern), 0);
|
||||||
memcpy(ovlseg + seqovl, dis->data_payload, split_pos);
|
memcpy(ovlseg + seqovl, dis->data_payload, split_pos);
|
||||||
seg = ovlseg;
|
seg = ovlseg;
|
||||||
}
|
}
|
||||||
@@ -2259,20 +2534,22 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
if (order <= 1)
|
||||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
{
|
||||||
DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ", split_pos - 1, split_pos);
|
||||||
hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(pat, split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split_pos < dis->len_payload)
|
||||||
|
{
|
||||||
fakeseg_len = sizeof(fakeseg);
|
fakeseg_len = sizeof(fakeseg);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, net32_add(dis->tcp->th_seq, split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||||
DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
||||||
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
dp->desync_fooling_mode, dp->desync_ts_increment, dp->desync_badseq_increment, dp->desync_badseq_ack_increment,
|
||||||
pat + split_pos, dis->len_payload - split_pos, fakeseg, &fakeseg_len))
|
pat + split_pos, dis->len_payload - split_pos, fakeseg, &fakeseg_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
|
||||||
DLOG("sending fake(1) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
DLOG("sending fake(1) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
||||||
hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
|
||||||
@@ -2290,25 +2567,27 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
|
||||||
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
if (order <= 2)
|
||||||
|
{
|
||||||
DLOG("sending fake(2) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
DLOG("sending fake(2) 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
||||||
hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(pat + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, fakeseg, fakeseg_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replay) ctrack_replay->ip_id = ip_id;
|
||||||
|
|
||||||
return VERDICT_DROP;
|
return VERDICT_DROP;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case DESYNC_IPFRAG2:
|
case DESYNC_IPFRAG2:
|
||||||
if (!reasm_offset)
|
if (!reasm_offset)
|
||||||
{
|
{
|
||||||
verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6);
|
verdict_tcp_csum_fix(verdict, dis->tcp, dis->transport_len, dis->ip, dis->ip6);
|
||||||
|
|
||||||
uint8_t pkt3[DPI_DESYNC_MAX_FAKE_LEN+100], *pkt_orig;
|
uint8_t *pkt_orig;
|
||||||
size_t pkt_orig_len;
|
size_t pkt_orig_len;
|
||||||
|
|
||||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
|
||||||
uint32_t ident = dis->ip ? ip_id ? ip_id : htons(1 + random() % 0xFFFF) : htonl(1 + random() % 0xFFFFFFFF);
|
uint32_t ident = dis->ip ? ip_id ? ip_id : htons(1 + random() % 0xFFFF) : htonl(1 + random() % 0xFFFFFFFF);
|
||||||
size_t ipfrag_pos = (dp->desync_ipfrag_pos_tcp && dp->desync_ipfrag_pos_tcp < dis->transport_len) ? dp->desync_ipfrag_pos_tcp : 24;
|
size_t ipfrag_pos = (dp->desync_ipfrag_pos_tcp && dp->desync_ipfrag_pos_tcp < dis->transport_len) ? dp->desync_ipfrag_pos_tcp : 24;
|
||||||
|
|
||||||
@@ -2356,6 +2635,17 @@ send_orig:
|
|||||||
if (tcp_orig_send(verdict, desync_fwmark, ifout, dp, ctrack_replay, dis, bFake))
|
if (tcp_orig_send(verdict, desync_fwmark, ifout, dp, ctrack_replay, dis, bFake))
|
||||||
verdict = ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, dis->tcp);
|
verdict = ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, dis->tcp);
|
||||||
return verdict;
|
return verdict;
|
||||||
|
|
||||||
|
unsplitted_part:
|
||||||
|
if (replay && dis->ip && ctrack_replay->ip_id)
|
||||||
|
{
|
||||||
|
DLOG("changing ip_id of unsplitted part\n");
|
||||||
|
dis->ip->ip_id = ctrack_replay->ip_id;
|
||||||
|
ctrack_replay->ip_id = IP4_IP_ID_NEXT(ctrack_replay->ip_id);
|
||||||
|
return VERDICT_MODIFY;
|
||||||
|
}
|
||||||
|
goto send_orig;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return : true - should continue, false - should stop with verdict
|
// return : true - should continue, false - should stop with verdict
|
||||||
@@ -2388,7 +2678,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
bool bFake = false;
|
bool bFake = false;
|
||||||
|
|
||||||
struct sockaddr_storage src, dst;
|
struct sockaddr_storage src, dst;
|
||||||
uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN+100], pkt2[DPI_DESYNC_MAX_FAKE_LEN+100];
|
uint8_t pkt1[DPI_DESYNC_MAX_FAKE_LEN + 100], pkt2[DPI_DESYNC_MAX_FAKE_LEN + 100], pkt3[DPI_DESYNC_MAX_FAKE_LEN + 100];
|
||||||
size_t pkt1_len, pkt2_len;
|
size_t pkt1_len, pkt2_len;
|
||||||
uint8_t ttl_orig, ttl_fake;
|
uint8_t ttl_orig, ttl_fake;
|
||||||
bool DF;
|
bool DF;
|
||||||
@@ -2516,7 +2806,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
{
|
{
|
||||||
struct blob_collection_head *fake;
|
struct blob_collection_head *fake;
|
||||||
bool bHaveHost = false, bHostIsIp = false;
|
bool bHaveHost = false, bHostIsIp = false;
|
||||||
uint16_t ip_id;
|
uint16_t ip_id = IP4_IP_ID_FIX(dis->ip);
|
||||||
|
|
||||||
if (IsQUICInitial(dis->data_payload, dis->len_payload))
|
if (IsQUICInitial(dis->data_payload, dis->len_payload))
|
||||||
{
|
{
|
||||||
@@ -2856,24 +3146,28 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
case DESYNC_FAKE:
|
case DESYNC_FAKE:
|
||||||
if (!reasm_offset)
|
if (!reasm_offset)
|
||||||
{
|
{
|
||||||
|
size_t fake_size;
|
||||||
|
uint8_t *fake_data;
|
||||||
struct blob_item *fake_item;
|
struct blob_item *fake_item;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
|
||||||
|
|
||||||
LIST_FOREACH(fake_item, fake, next)
|
LIST_FOREACH(fake_item, fake, next)
|
||||||
{
|
{
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
|
fake_data = fake_item->data + fake_item->offset;
|
||||||
|
fake_size = fake_item->size - fake_item->offset;
|
||||||
|
|
||||||
pkt1_len = sizeof(pkt1);
|
pkt1_len = sizeof(pkt1);
|
||||||
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
|
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
|
||||||
DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
DF, ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
||||||
dp->desync_fooling_mode, NULL, 0, 0,
|
dp->desync_fooling_mode, NULL, 0, 0,
|
||||||
fake_item->data, fake_item->size, pkt1, &pkt1_len))
|
fake_data, fake_size, pkt1, &pkt1_len))
|
||||||
{
|
{
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
DLOG("sending fake[%d] : ", n);
|
DLOG("sending fake[%d] : ", n);
|
||||||
hexdump_limited_dlog(fake_item->data,fake_item->size,PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(fake_data, fake_size, PKTDATA_MAXDUMP); DLOG("\n");
|
||||||
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt1, pkt1_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
ip_id = IP4_IP_ID_NEXT(ip_id);
|
ip_id = IP4_IP_ID_NEXT(ip_id);
|
||||||
@@ -2911,7 +3205,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
{
|
{
|
||||||
case DESYNC_UDPLEN:
|
case DESYNC_UDPLEN:
|
||||||
pkt1_len = sizeof(pkt1);
|
pkt1_len = sizeof(pkt1);
|
||||||
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), fooling_orig, dp->udplen_pattern, sizeof(dp->udplen_pattern), dp->udplen_increment, dis->data_payload, dis->len_payload, pkt1, &pkt1_len))
|
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), fooling_orig, dp->udplen_pattern, sizeof(dp->udplen_pattern), dp->udplen_increment, dis->data_payload, dis->len_payload, pkt1, &pkt1_len))
|
||||||
{
|
{
|
||||||
DLOG("could not construct packet with modified length. too large ?\n");
|
DLOG("could not construct packet with modified length. too large ?\n");
|
||||||
break;
|
break;
|
||||||
@@ -2936,7 +3230,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
memcpy(pkt2 + pkt2_len, dis->data_payload + 1, szcopy);
|
memcpy(pkt2 + pkt2_len, dis->data_payload + 1, szcopy);
|
||||||
pkt2_len += szcopy;
|
pkt2_len += szcopy;
|
||||||
pkt1_len = sizeof(pkt1);
|
pkt1_len = sizeof(pkt1);
|
||||||
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6), fooling_orig, NULL, 0 , 0, pkt2, pkt2_len, pkt1, &pkt1_len))
|
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), fooling_orig, NULL, 0, 0, pkt2, pkt2_len, pkt1, &pkt1_len))
|
||||||
{
|
{
|
||||||
DLOG("could not construct packet with modified length. too large ?\n");
|
DLOG("could not construct packet with modified length. too large ?\n");
|
||||||
break;
|
break;
|
||||||
@@ -2955,7 +3249,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
{
|
{
|
||||||
verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6);
|
verdict_udp_csum_fix(verdict, dis->udp, dis->transport_len, dis->ip, dis->ip6);
|
||||||
|
|
||||||
uint8_t pkt3[DPI_DESYNC_MAX_FAKE_LEN+100], *pkt_orig;
|
uint8_t *pkt_orig;
|
||||||
size_t pkt_orig_len;
|
size_t pkt_orig_len;
|
||||||
|
|
||||||
// freebsd do not set ip.id
|
// freebsd do not set ip.id
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ enum dpi_desync_mode {
|
|||||||
DESYNC_FAKEDDISORDER,
|
DESYNC_FAKEDDISORDER,
|
||||||
DESYNC_MULTISPLIT,
|
DESYNC_MULTISPLIT,
|
||||||
DESYNC_MULTIDISORDER,
|
DESYNC_MULTIDISORDER,
|
||||||
|
DESYNC_HOSTFAKESPLIT,
|
||||||
DESYNC_IPFRAG2,
|
DESYNC_IPFRAG2,
|
||||||
DESYNC_HOPBYHOP,
|
DESYNC_HOPBYHOP,
|
||||||
DESYNC_DESTOPT,
|
DESYNC_DESTOPT,
|
||||||
|
|||||||
+9
-1
@@ -338,10 +338,18 @@ bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize)
|
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset)
|
||||||
{
|
{
|
||||||
size_t size;
|
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)
|
while (bufsize)
|
||||||
{
|
{
|
||||||
size = bufsize>patsize ? patsize : bufsize;
|
size = bufsize>patsize ? patsize : bufsize;
|
||||||
|
|||||||
+1
-1
@@ -70,7 +70,7 @@ static inline uint32_t pntoh32(const uint8_t *p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size);
|
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);
|
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset);
|
||||||
|
|
||||||
int fprint_localtime(FILE *F);
|
int fprint_localtime(FILE *F);
|
||||||
|
|
||||||
|
|||||||
+448
-153
@@ -176,7 +176,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
|
|||||||
*ifin = 0;
|
*ifin = 0;
|
||||||
if (ifidx_in) if_indextoname(ifidx_in, ifin);
|
if (ifidx_in) if_indextoname(ifidx_in, ifin);
|
||||||
|
|
||||||
DLOG("packet: id=%d len=%d mark=%08X ifin=%s(%u) ifout=%s(%u)\n", id, ilen, mark, ifin, ifidx_in, ifout, ifidx_out);
|
DLOG("\npacket: id=%d len=%d mark=%08X ifin=%s(%u) ifout=%s(%u)\n", id, ilen, mark, ifin, ifidx_in, ifout, ifidx_out);
|
||||||
|
|
||||||
if (ilen >= 0)
|
if (ilen >= 0)
|
||||||
{
|
{
|
||||||
@@ -502,7 +502,7 @@ static int dvt_main(void)
|
|||||||
|
|
||||||
ReloadCheck();
|
ReloadCheck();
|
||||||
|
|
||||||
DLOG("packet: id=%u len=%zu\n", id, len);
|
DLOG("\npacket: id=%u len=%zu\n", id, len);
|
||||||
verdict = processPacketData(&mark, NULL, NULL, buf, &len);
|
verdict = processPacketData(&mark, NULL, NULL, buf, &len);
|
||||||
switch (verdict & VERDICT_MASK)
|
switch (verdict & VERDICT_MASK)
|
||||||
{
|
{
|
||||||
@@ -583,8 +583,7 @@ static int win_main(const char *windivert_filter)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
usleep(500000);
|
usleep(500000);
|
||||||
}
|
} while (!logical_net_filter_match());
|
||||||
while (!logical_net_filter_match());
|
|
||||||
DLOG_CONDUP("logical network now present\n");
|
DLOG_CONDUP("logical network now present\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,7 +626,7 @@ static int win_main(const char *windivert_filter)
|
|||||||
|
|
||||||
*ifname = 0;
|
*ifname = 0;
|
||||||
snprintf(ifname, sizeof(ifname), "%u.%u", wa.Network.IfIdx, wa.Network.SubIfIdx);
|
snprintf(ifname, sizeof(ifname), "%u.%u", wa.Network.IfIdx, wa.Network.SubIfIdx);
|
||||||
DLOG("packet: id=%u len=%zu %s IPv6=%u IPChecksum=%u TCPChecksum=%u UDPChecksum=%u IfIdx=%u.%u\n", id, len, wa.Outbound ? "outbound" : "inbound", wa.IPv6, wa.IPChecksum, wa.TCPChecksum, wa.UDPChecksum, wa.Network.IfIdx, wa.Network.SubIfIdx);
|
DLOG("\npacket: id=%u len=%zu %s IPv6=%u IPChecksum=%u TCPChecksum=%u UDPChecksum=%u IfIdx=%u.%u\n", id, len, wa.Outbound ? "outbound" : "inbound", wa.IPv6, wa.IPChecksum, wa.TCPChecksum, wa.UDPChecksum, wa.Network.IfIdx, wa.Network.SubIfIdx);
|
||||||
if (wa.Impostor)
|
if (wa.Impostor)
|
||||||
{
|
{
|
||||||
DLOG("windivert: passing impostor packet\n");
|
DLOG("windivert: passing impostor packet\n");
|
||||||
@@ -747,8 +746,16 @@ static bool parse_net32_signed(const char *opt, uint32_t *value)
|
|||||||
return sscanf(opt, "%d", (int32_t*)value) > 0;
|
return sscanf(opt, "%d", (int32_t*)value) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void load_file_or_exit(const char *filename, void *buf, size_t *size)
|
static void load_file_or_exit(const char *filename, void *buf, size_t *size, size_t *offset)
|
||||||
{
|
{
|
||||||
|
size_t ofs;
|
||||||
|
|
||||||
|
// 0xaabbcc
|
||||||
|
// filename
|
||||||
|
// @filename
|
||||||
|
// +123@filename
|
||||||
|
|
||||||
|
if (offset) *offset = 0;
|
||||||
if (filename[0] == '0' && filename[1] == 'x')
|
if (filename[0] == '0' && filename[1] == 'x')
|
||||||
{
|
{
|
||||||
if (!parse_hex_str(filename + 2, buf, size) || !*size)
|
if (!parse_hex_str(filename + 2, buf, size) || !*size)
|
||||||
@@ -760,12 +767,35 @@ static void load_file_or_exit(const char *filename, void *buf, size_t *size)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ofs = 0;
|
||||||
|
if (filename[0] == '+')
|
||||||
|
{
|
||||||
|
filename++;
|
||||||
|
if (sscanf(filename, "%zu", &ofs) != 1)
|
||||||
|
{
|
||||||
|
DLOG("offset read error: %s\n", filename);
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
while (*filename && *filename != '@') filename++;
|
||||||
|
if (*filename == '@') filename++;
|
||||||
|
}
|
||||||
|
else if (filename[0] == '@')
|
||||||
|
filename++;
|
||||||
if (!load_file_nonempty(filename, buf, size))
|
if (!load_file_nonempty(filename, buf, size))
|
||||||
{
|
{
|
||||||
DLOG_ERR("could not read %s\n", filename);
|
DLOG_ERR("could not read %s\n", filename);
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
DLOG("read %zu bytes from %s\n",*size,filename);
|
DLOG("read %zu bytes from '%s'. offset=%zu\n", *size, filename, ofs);
|
||||||
|
if (ofs >= *size)
|
||||||
|
{
|
||||||
|
DLOG("'%s' : offset %zu is out of data range %zu\n", filename, ofs, *size);
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
if (offset)
|
||||||
|
*offset = ofs;
|
||||||
|
else
|
||||||
|
memmove(buf, (uint8_t*)buf + ofs, *size -= ofs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -789,7 +819,8 @@ static bool parse_autottl(const char *s, autottl *t, int8_t def_delta, uint8_t d
|
|||||||
{
|
{
|
||||||
neg = false;
|
neg = false;
|
||||||
s++;
|
s++;
|
||||||
} else if (*s=='-')
|
}
|
||||||
|
else if (*s == '-')
|
||||||
s++;
|
s++;
|
||||||
switch (sscanf(s, "%u:%u-%u", &delta, &min, &max))
|
switch (sscanf(s, "%u:%u-%u", &delta, &min, &max))
|
||||||
{
|
{
|
||||||
@@ -1098,6 +1129,138 @@ err:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool parse_hostfakesplit_mod(char *opt, struct hostfakesplit_mod *hfs_mod)
|
||||||
|
{
|
||||||
|
char *e, *e2, *p, c, c2;
|
||||||
|
|
||||||
|
for (p = opt; p; )
|
||||||
|
{
|
||||||
|
for (e2 = p; *e2 && *e2 != ',' && *e2 != '='; e2++);
|
||||||
|
|
||||||
|
if ((e = strchr(e2, ',')))
|
||||||
|
{
|
||||||
|
c = *e;
|
||||||
|
*e = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*e2 == '=')
|
||||||
|
{
|
||||||
|
c2 = *e2;
|
||||||
|
*e2 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
e2 = NULL;
|
||||||
|
|
||||||
|
if (!strcmp(p, "host"))
|
||||||
|
{
|
||||||
|
if (!e2 || !e2[1] || e2[1] == ',') goto err;
|
||||||
|
strncpy(hfs_mod->host, e2 + 1, sizeof(hfs_mod->host) - 1);
|
||||||
|
hfs_mod->host[sizeof(hfs_mod->host) - 1 - 1] = 0;
|
||||||
|
hfs_mod->host_size = strlen(hfs_mod->host); // cache value
|
||||||
|
}
|
||||||
|
else if (!strcmp(p, "altorder"))
|
||||||
|
{
|
||||||
|
if (!e2 || !e2[1] || e2[1] == ',') goto err;
|
||||||
|
hfs_mod->ordering = atoi(e2 + 1);
|
||||||
|
if (hfs_mod->ordering < 0 || hfs_mod->ordering>1) goto err;
|
||||||
|
}
|
||||||
|
else if (strcmp(p, "none"))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (e2) *e2 = c2;
|
||||||
|
if (e) *e++ = c;
|
||||||
|
p = e;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
err:
|
||||||
|
if (e2) *e2 = c2;
|
||||||
|
if (e) *e++ = c;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool parse_fakedsplit_mod(char *opt, struct fakedsplit_mod *fs_mod)
|
||||||
|
{
|
||||||
|
char *e, *e2, *p, c, c2;
|
||||||
|
|
||||||
|
for (p = opt; p; )
|
||||||
|
{
|
||||||
|
for (e2 = p; *e2 && *e2 != ',' && *e2 != '='; e2++);
|
||||||
|
|
||||||
|
if ((e = strchr(e2, ',')))
|
||||||
|
{
|
||||||
|
c = *e;
|
||||||
|
*e = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*e2 == '=')
|
||||||
|
{
|
||||||
|
c2 = *e2;
|
||||||
|
*e2 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
e2 = NULL;
|
||||||
|
|
||||||
|
if (!strcmp(p, "altorder"))
|
||||||
|
{
|
||||||
|
if (!e2 || !e2[1] || e2[1] == ',') goto err;
|
||||||
|
fs_mod->ordering = atoi(e2 + 1);
|
||||||
|
// unsplitted altorder in 0x03 mask. 0x04 reserved. splitted altorder in 0x18 mask
|
||||||
|
if ((fs_mod->ordering & 0xFFFFFFE4) || (((fs_mod->ordering>>3) & 3)>2)) goto err;
|
||||||
|
}
|
||||||
|
else if (strcmp(p, "none"))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (e2) *e2 = c2;
|
||||||
|
if (e) *e++ = c;
|
||||||
|
p = e;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
err:
|
||||||
|
if (e2) *e2 = c2;
|
||||||
|
if (e) *e++ = c;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool parse_tcpmod(char *opt, struct tcp_mod *tcp_mod)
|
||||||
|
{
|
||||||
|
char *e, *e2, *p, c, c2;
|
||||||
|
|
||||||
|
for (p = opt; p; )
|
||||||
|
{
|
||||||
|
for (e2 = p; *e2 && *e2 != ',' && *e2 != '='; e2++);
|
||||||
|
|
||||||
|
if ((e = strchr(e2, ',')))
|
||||||
|
{
|
||||||
|
c = *e;
|
||||||
|
*e = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*e2 == '=')
|
||||||
|
{
|
||||||
|
c2 = *e2;
|
||||||
|
*e2 = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
e2 = NULL;
|
||||||
|
|
||||||
|
if (!strcmp(p, "seq"))
|
||||||
|
{
|
||||||
|
tcp_mod->seq = true;
|
||||||
|
}
|
||||||
|
else if (strcmp(p, "none"))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (e2) *e2 = c2;
|
||||||
|
if (e) *e++ = c;
|
||||||
|
p = e;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
err:
|
||||||
|
if (e2) *e2 = c2;
|
||||||
|
if (e) *e++ = c;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool parse_fooling(char *opt, unsigned int *fooling_mode)
|
static bool parse_fooling(char *opt, unsigned int *fooling_mode)
|
||||||
{
|
{
|
||||||
char *e, *p = opt;
|
char *e, *p = opt;
|
||||||
@@ -1165,11 +1328,10 @@ static void SplitDebug(void)
|
|||||||
for (int x = 0; x < dp->split_count; x++)
|
for (int x = 0; x < dp->split_count; x++)
|
||||||
DLOG("profile %d multisplit %s %d\n", dp->n, posmarker_name(dp->splits[x].marker), dp->splits[x].pos);
|
DLOG("profile %d multisplit %s %d\n", dp->n, posmarker_name(dp->splits[x].marker), dp->splits[x].pos);
|
||||||
if (!PROTO_POS_EMPTY(&dp->seqovl)) DLOG("profile %d seqovl %s %d\n", dp->n, posmarker_name(dp->seqovl.marker), dp->seqovl.pos);
|
if (!PROTO_POS_EMPTY(&dp->seqovl)) DLOG("profile %d seqovl %s %d\n", dp->n, posmarker_name(dp->seqovl.marker), dp->seqovl.pos);
|
||||||
|
if (!PROTO_POS_EMPTY(&dp->hostfakesplit_midhost)) DLOG("profile %d hostfakesplit midhost %s %d\n", dp->n, posmarker_name(dp->hostfakesplit_midhost.marker), dp->hostfakesplit_midhost.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * tld[]={"com","org","net","edu","gov","biz"};
|
|
||||||
|
|
||||||
static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tls_mod *tls_mod, uint8_t *fake_tls, size_t *fake_tls_size, size_t fake_tls_buf_size, struct fake_tls_mod_cache *modcache)
|
static bool onetime_tls_mod_blob(int profile_n, int fake_n, const struct fake_tls_mod *tls_mod, uint8_t *fake_tls, size_t *fake_tls_size, size_t fake_tls_buf_size, struct fake_tls_mod_cache *modcache)
|
||||||
{
|
{
|
||||||
const uint8_t *ext;
|
const uint8_t *ext;
|
||||||
@@ -1333,6 +1495,11 @@ static bool onetime_tls_mod(struct desync_profile *dp)
|
|||||||
}
|
}
|
||||||
if (!onetime_tls_mod_blob(dp->n, n, tls_mod, fake_tls->data, &fake_tls->size, fake_tls->size_buf, (struct fake_tls_mod_cache*)fake_tls->extra))
|
if (!onetime_tls_mod_blob(dp->n, n, tls_mod, fake_tls->data, &fake_tls->size, fake_tls->size_buf, (struct fake_tls_mod_cache*)fake_tls->extra))
|
||||||
return false;
|
return false;
|
||||||
|
if (fake_tls->offset >= fake_tls->size)
|
||||||
|
{
|
||||||
|
DLOG("profile %d fake[%d] tls mod shrinked data to %zu and offset %zu is now out of data range\n", dp->n, n, fake_tls->size, fake_tls->offset);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1341,13 +1508,14 @@ static struct blob_item *load_blob_to_collection(const char *filename, struct bl
|
|||||||
{
|
{
|
||||||
struct blob_item *blob = blob_collection_add(blobs);
|
struct blob_item *blob = blob_collection_add(blobs);
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
|
|
||||||
if (!blob || (!(blob->data = malloc(max_size + size_reserve))))
|
if (!blob || (!(blob->data = malloc(max_size + size_reserve))))
|
||||||
{
|
{
|
||||||
DLOG_ERR("out of memory\n");
|
DLOG_ERR("out of memory\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
blob->size = max_size;
|
blob->size = max_size;
|
||||||
load_file_or_exit(filename,blob->data,&blob->size);
|
load_file_or_exit(filename, blob->data, &blob->size, &blob->offset);
|
||||||
p = realloc(blob->data, blob->size + size_reserve);
|
p = realloc(blob->data, blob->size + size_reserve);
|
||||||
if (!p)
|
if (!p)
|
||||||
{
|
{
|
||||||
@@ -1358,8 +1526,13 @@ static struct blob_item *load_blob_to_collection(const char *filename, struct bl
|
|||||||
blob->size_buf = blob->size + size_reserve;
|
blob->size_buf = blob->size + size_reserve;
|
||||||
return blob;
|
return blob;
|
||||||
}
|
}
|
||||||
static struct blob_item *load_const_blob_to_collection(const void *data,size_t sz, struct blob_collection_head *blobs, size_t size_reserve)
|
static struct blob_item *load_const_blob_to_collection(const void *data, size_t sz, struct blob_collection_head *blobs, size_t size_reserve, size_t offset)
|
||||||
{
|
{
|
||||||
|
if (offset >= sz)
|
||||||
|
{
|
||||||
|
DLOG_ERR("offset %zu is out of data range %zu\n", offset, sz);
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
struct blob_item *blob = blob_collection_add(blobs);
|
struct blob_item *blob = blob_collection_add(blobs);
|
||||||
if (!blob || (!(blob->data = malloc(sz + size_reserve))))
|
if (!blob || (!(blob->data = malloc(sz + size_reserve))))
|
||||||
{
|
{
|
||||||
@@ -1368,6 +1541,7 @@ static struct blob_item *load_const_blob_to_collection(const void *data,size_t s
|
|||||||
}
|
}
|
||||||
blob->size = sz;
|
blob->size = sz;
|
||||||
blob->size_buf = sz + size_reserve;
|
blob->size_buf = sz + size_reserve;
|
||||||
|
blob->offset = offset;
|
||||||
memcpy(blob->data, data, sz);
|
memcpy(blob->data, data, sz);
|
||||||
return blob;
|
return blob;
|
||||||
}
|
}
|
||||||
@@ -1447,15 +1621,36 @@ static bool wf_make_filter(
|
|||||||
unsigned int IfIdx, unsigned int SubIfIdx,
|
unsigned int IfIdx, unsigned int SubIfIdx,
|
||||||
bool ipv4, bool ipv6,
|
bool ipv4, bool ipv6,
|
||||||
const char *pf_tcp_src, const char *pf_tcp_dst,
|
const char *pf_tcp_src, const char *pf_tcp_dst,
|
||||||
const char *pf_udp_src, const char *pf_udp_dst)
|
const char *pf_udp_src, const char *pf_udp_dst,
|
||||||
|
const struct str_list_head *wf_raw_part,
|
||||||
|
bool bFilterOutLAN)
|
||||||
{
|
{
|
||||||
char pf_dst_buf[8192], iface[64];
|
char pf_dst_buf[8192], iface[64];
|
||||||
|
struct str_list *wfpart;
|
||||||
|
int n;
|
||||||
const char *pf_dst;
|
const char *pf_dst;
|
||||||
const char *f_tcpin = *pf_tcp_src ? dp_list_have_autohostlist(¶ms.desync_profiles) ? "(" DIVERT_TCP_INBOUNDS " or (" DIVERT_HTTP_REDIRECT "))" : DIVERT_TCP_INBOUNDS : "";
|
const char *f_tcpin = *pf_tcp_src ? dp_list_have_autohostlist(¶ms.desync_profiles) ? "(" DIVERT_TCP_INBOUNDS " or (" DIVERT_HTTP_REDIRECT "))" : DIVERT_TCP_INBOUNDS : "";
|
||||||
const char *f_tcp_not_empty = (*pf_tcp_src && !dp_list_need_all_out(¶ms.desync_profiles)) ? DIVERT_TCP_NOT_EMPTY " and " : "";
|
const char *f_tcp_not_empty = (*pf_tcp_src && !dp_list_need_all_out(¶ms.desync_profiles)) ? DIVERT_TCP_NOT_EMPTY " and " : "";
|
||||||
snprintf(iface, sizeof(iface), " ifIdx=%u and subIfIdx=%u and", IfIdx, SubIfIdx);
|
snprintf(iface, sizeof(iface), " ifIdx=%u and subIfIdx=%u and", IfIdx, SubIfIdx);
|
||||||
|
|
||||||
if (!*pf_tcp_src && !*pf_udp_src) return false;
|
snprintf(wf, len, "%s and%s%s\n(",
|
||||||
|
DIVERT_PROLOG,
|
||||||
|
IfIdx ? iface : "",
|
||||||
|
ipv4 ? ipv6 ? "" : " ip and" : " ipv6 and"
|
||||||
|
);
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
if (!LIST_EMPTY(wf_raw_part))
|
||||||
|
{
|
||||||
|
LIST_FOREACH(wfpart, wf_raw_part, next)
|
||||||
|
{
|
||||||
|
snprintf(wf + strlen(wf), len - strlen(wf), "%s(\n%s\n )", n ? "\n or\n " : "\n ", wfpart->str);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pf_tcp_src || *pf_udp_src)
|
||||||
|
{
|
||||||
if (*pf_tcp_src && *pf_udp_src)
|
if (*pf_tcp_src && *pf_udp_src)
|
||||||
{
|
{
|
||||||
snprintf(pf_dst_buf, sizeof(pf_dst_buf), "(%s or %s)", pf_tcp_dst, pf_udp_dst);
|
snprintf(pf_dst_buf, sizeof(pf_dst_buf), "(%s or %s)", pf_tcp_dst, pf_udp_dst);
|
||||||
@@ -1463,21 +1658,26 @@ static bool wf_make_filter(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
pf_dst = *pf_tcp_dst ? pf_tcp_dst : pf_udp_dst;
|
pf_dst = *pf_tcp_dst ? pf_tcp_dst : pf_udp_dst;
|
||||||
snprintf(wf,len,
|
|
||||||
DIVERT_PROLOG " and%s%s\n ((outbound and %s%s%s)\n or\n (inbound and tcp%s%s%s%s%s%s%s))",
|
snprintf(wf + strlen(wf), len - strlen(wf), n++ ? "\n or\n " : "\n ");
|
||||||
IfIdx ? iface : "",
|
|
||||||
ipv4 ? ipv6 ? "" : " ip and" : " ipv6 and",
|
snprintf(wf + strlen(wf), len - strlen(wf),
|
||||||
|
"(\n (outbound and %s%s)\n or\n (inbound and tcp%s%s%s%s%s)\n )",
|
||||||
f_tcp_not_empty,
|
f_tcp_not_empty,
|
||||||
pf_dst,
|
pf_dst,
|
||||||
ipv4 ? ipv6 ? " and " DIVERT_NO_LOCALNETS_DST : " and " DIVERT_NO_LOCALNETSv4_DST : " and " DIVERT_NO_LOCALNETSv6_DST,
|
|
||||||
*pf_tcp_src ? "" : " and false",
|
*pf_tcp_src ? "" : " and false",
|
||||||
*f_tcpin ? " and " : "",
|
*f_tcpin ? " and " : "",
|
||||||
*f_tcpin ? f_tcpin : "",
|
*f_tcpin ? f_tcpin : "",
|
||||||
*pf_tcp_src ? " and " : "",
|
*pf_tcp_src ? " and " : "",
|
||||||
*pf_tcp_src ? pf_tcp_src : "",
|
*pf_tcp_src ? pf_tcp_src : "");
|
||||||
*pf_tcp_src ? " and " : "",
|
|
||||||
*pf_tcp_src ? ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_SRC : DIVERT_NO_LOCALNETSv4_SRC : DIVERT_NO_LOCALNETSv6_SRC : ""
|
}
|
||||||
);
|
strncat(wf, "\n)", len - strlen(wf) - 1);
|
||||||
|
|
||||||
|
if (bFilterOutLAN)
|
||||||
|
snprintf(wf + strlen(wf), len - strlen(wf), "\nand\n(\n outbound and %s\n or\n inbound and %s\n)\n",
|
||||||
|
ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_DST : DIVERT_NO_LOCALNETSv4_DST : DIVERT_NO_LOCALNETSv6_DST,
|
||||||
|
ipv4 ? ipv6 ? DIVERT_NO_LOCALNETS_SRC : DIVERT_NO_LOCALNETSv4_SRC : DIVERT_NO_LOCALNETSv6_SRC);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1496,143 +1696,149 @@ static void exithelp(void)
|
|||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
||||||
" @<config_file>|$<config_file>\t\t\t; read file for options. must be the only argument. other options are ignored.\n\n"
|
" @<config_file>|$<config_file>\t\t\t\t; read file for options. must be the only argument. other options are ignored.\n\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
" --debug=0|1|syslog|android|@<filename>\n"
|
" --debug=0|1|syslog|android|@<filename>\n"
|
||||||
#else
|
#else
|
||||||
" --debug=0|1|syslog|@<filename>\n"
|
" --debug=0|1|syslog|@<filename>\n"
|
||||||
#endif
|
#endif
|
||||||
" --version\t\t\t\t\t; print version and exit\n"
|
" --version\t\t\t\t\t\t; print version and exit\n"
|
||||||
" --dry-run\t\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
" --dry-run\t\t\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
||||||
" --comment=any_text\n"
|
" --comment=any_text\n"
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
" --qnum=<nfqueue_number>\n"
|
" --qnum=<nfqueue_number>\n"
|
||||||
#elif defined(BSD)
|
#elif defined(BSD)
|
||||||
" --port=<port>\t\t\t\t\t; divert port\n"
|
" --port=<port>\t\t\t\t\t\t; divert port\n"
|
||||||
#endif
|
#endif
|
||||||
" --daemon\t\t\t\t\t; daemonize\n"
|
" --daemon\t\t\t\t\t\t; daemonize\n"
|
||||||
" --pidfile=<filename>\t\t\t\t; write pid to file\n"
|
" --pidfile=<filename>\t\t\t\t\t; write pid to file\n"
|
||||||
#ifndef __CYGWIN__
|
#ifndef __CYGWIN__
|
||||||
" --user=<username>\t\t\t\t; drop root privs\n"
|
" --user=<username>\t\t\t\t\t; drop root privs\n"
|
||||||
" --uid=uid[:gid1,gid2,...]\t\t\t; drop root privs\n"
|
" --uid=uid[:gid1,gid2,...]\t\t\t\t; drop root privs\n"
|
||||||
#endif
|
#endif
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
" --bind-fix4\t\t\t\t\t; apply outgoing interface selection fix for generated ipv4 packets\n"
|
" --bind-fix4\t\t\t\t\t\t; apply outgoing interface selection fix for generated ipv4 packets\n"
|
||||||
" --bind-fix6\t\t\t\t\t; apply outgoing interface selection fix for generated ipv6 packets\n"
|
" --bind-fix6\t\t\t\t\t\t; apply outgoing interface selection fix for generated ipv6 packets\n"
|
||||||
#endif
|
#endif
|
||||||
" --ctrack-timeouts=S:E:F[:U]\t\t\t; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default %u:%u:%u:%u\n"
|
" --ctrack-timeouts=S:E:F[:U]\t\t\t\t; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default %u:%u:%u:%u\n"
|
||||||
" --ctrack-disable=[0|1]\t\t\t\t; 1 or no argument disables conntrack\n"
|
" --ctrack-disable=[0|1]\t\t\t\t\t; 1 or no argument disables conntrack\n"
|
||||||
" --ipcache-lifetime=<int>\t\t\t; time in seconds to keep cached hop count and domain name (default %u). 0 = no expiration\n"
|
" --ipcache-lifetime=<int>\t\t\t\t; time in seconds to keep cached hop count and domain name (default %u). 0 = no expiration\n"
|
||||||
" --ipcache-hostname=[0|1]\t\t\t; 1 or no argument enables ip->hostname caching\n"
|
" --ipcache-hostname=[0|1]\t\t\t\t; 1 or no argument enables ip->hostname caching\n"
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
"\nWINDIVERT FILTER:\n"
|
"\nWINDIVERT FILTER:\n"
|
||||||
" --wf-iface=<int>[.<int>]\t\t\t; numeric network interface and subinterface indexes\n"
|
" --wf-iface=<int>[.<int>]\t\t\t\t; numeric network interface and subinterface indexes\n"
|
||||||
" --wf-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
" --wf-l3=ipv4|ipv6\t\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||||
" --wf-tcp=[~]port1[-port2]\t\t\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n"
|
" --wf-tcp=[~]port1[-port2]\t\t\t\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n"
|
||||||
" --wf-udp=[~]port1[-port2]\t\t\t; UDP port filter. ~ means negation. multiple comma separated values allowed.\n"
|
" --wf-udp=[~]port1[-port2]\t\t\t\t; UDP port filter. ~ means negation. multiple comma separated values allowed.\n"
|
||||||
" --wf-raw=<filter>|@<filename>\t\t\t; raw windivert filter string or filename\n"
|
" --wf-raw-part=<filter>|@<filename>\t\t\t; partial raw windivert filter string or filename\n"
|
||||||
" --wf-save=<filename>\t\t\t\t; save windivert filter string to a file and exit\n"
|
" --wf-filter-lan=0|1\t\t\t\t\t; add excluding filter for non-global IP (default : 1)\n"
|
||||||
|
" --wf-raw=<filter>|@<filename>\t\t\t\t; full raw windivert filter string or filename. replaces --wf-tcp,--wf-udp,--wf-raw-part\n"
|
||||||
|
" --wf-save=<filename>\t\t\t\t\t; save windivert filter string to a file and exit\n"
|
||||||
"\nLOGICAL NETWORK FILTER:\n"
|
"\nLOGICAL NETWORK FILTER:\n"
|
||||||
" --ssid-filter=ssid1[,ssid2,ssid3,...]\t\t; enable winws only if any of specified wifi SSIDs connected\n"
|
" --ssid-filter=ssid1[,ssid2,ssid3,...]\t\t\t; enable winws only if any of specified wifi SSIDs connected\n"
|
||||||
" --nlm-filter=net1[,net2,net3,...]\t\t; enable winws only if any of specified NLM network is connected. names and GUIDs are accepted.\n"
|
" --nlm-filter=net1[,net2,net3,...]\t\t\t; enable winws only if any of specified NLM network is connected. names and GUIDs are accepted.\n"
|
||||||
" --nlm-list[=all]\t\t\t\t; list Network List Manager (NLM) networks. connected only or all.\n"
|
" --nlm-list[=all]\t\t\t\t\t; list Network List Manager (NLM) networks. connected only or all.\n"
|
||||||
#endif
|
#endif
|
||||||
"\nMULTI-STRATEGY:\n"
|
"\nMULTI-STRATEGY:\n"
|
||||||
" --new\t\t\t\t\t\t; begin new strategy\n"
|
" --new\t\t\t\t\t\t\t; begin new strategy\n"
|
||||||
" --skip\t\t\t\t\t\t; do not use this strategy\n"
|
" --skip\t\t\t\t\t\t\t; do not use this strategy\n"
|
||||||
" --filter-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
" --filter-l3=ipv4|ipv6\t\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||||
" --filter-tcp=[~]port1[-port2]|*\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n"
|
" --filter-tcp=[~]port1[-port2]|*\t\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n"
|
||||||
" --filter-udp=[~]port1[-port2]|*\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
|
" --filter-udp=[~]port1[-port2]|*\t\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
|
||||||
" --filter-l7=[http|tls|quic|wireguard|dht|discord|stun|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
" --filter-l7=[http|tls|quic|wireguard|dht|discord|stun|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
||||||
#ifdef HAS_FILTER_SSID
|
#ifdef HAS_FILTER_SSID
|
||||||
" --filter-ssid=ssid1[,ssid2,ssid3,...]\t\t; per profile wifi SSID filter\n"
|
" --filter-ssid=ssid1[,ssid2,ssid3,...]\t\t\t; per profile wifi SSID filter\n"
|
||||||
#endif
|
#endif
|
||||||
" --ipset=<filename>\t\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
" --ipset=<filename>\t\t\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||||
" --ipset-ip=<ip_list>\t\t\t\t; comma separated fixed subnet list\n"
|
" --ipset-ip=<ip_list>\t\t\t\t\t; comma separated fixed subnet list\n"
|
||||||
" --ipset-exclude=<filename>\t\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
" --ipset-exclude=<filename>\t\t\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||||
" --ipset-exclude-ip=<ip_list>\t\t\t; comma separated fixed subnet list\n"
|
" --ipset-exclude-ip=<ip_list>\t\t\t\t; comma separated fixed subnet list\n"
|
||||||
"\nHOSTLIST FILTER:\n"
|
"\nHOSTLIST FILTER:\n"
|
||||||
" --hostlist=<filename>\t\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
" --hostlist=<filename>\t\t\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||||
" --hostlist-domains=<domain_list>\t\t; comma separated fixed domain list\n"
|
" --hostlist-domains=<domain_list>\t\t\t; comma separated fixed domain list\n"
|
||||||
" --hostlist-exclude=<filename>\t\t\t; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
" --hostlist-exclude=<filename>\t\t\t\t; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||||
" --hostlist-exclude-domains=<domain_list>\t; comma separated fixed domain list\n"
|
" --hostlist-exclude-domains=<domain_list>\t\t; comma separated fixed domain list\n"
|
||||||
" --hostlist-auto=<filename>\t\t\t; detect DPI blocks and build hostlist automatically\n"
|
" --hostlist-auto=<filename>\t\t\t\t; detect DPI blocks and build hostlist automatically\n"
|
||||||
" --hostlist-auto-fail-threshold=<int>\t\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
|
" --hostlist-auto-fail-threshold=<int>\t\t\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
|
||||||
" --hostlist-auto-fail-time=<int>\t\t; all failed attemps must be within these seconds (default : %d)\n"
|
" --hostlist-auto-fail-time=<int>\t\t\t; all failed attemps must be within these seconds (default : %d)\n"
|
||||||
" --hostlist-auto-retrans-threshold=<int>\t; how many request retransmissions cause attempt to fail (default : %d)\n"
|
" --hostlist-auto-retrans-threshold=<int>\t\t; how many request retransmissions cause attempt to fail (default : %d)\n"
|
||||||
" --hostlist-auto-debug=<logfile>\t\t; debug auto hostlist positives\n"
|
" --hostlist-auto-debug=<logfile>\t\t\t; debug auto hostlist positives\n"
|
||||||
"\nTAMPER:\n"
|
"\nTAMPER:\n"
|
||||||
" --wsize=<window_size>[:<scale_factor>]\t\t; set window size. 0 = do not modify. OBSOLETE !\n"
|
" --wsize=<window_size>[:<scale_factor>]\t\t\t; set window size. 0 = do not modify. OBSOLETE !\n"
|
||||||
" --wssize=<window_size>[:<scale_factor>]\t; set window size for server. 0 = do not modify. default scale_factor = 0.\n"
|
" --wssize=<window_size>[:<scale_factor>]\t\t; set window size for server. 0 = do not modify. default scale_factor = 0.\n"
|
||||||
" --wssize-cutoff=[n|d|s]N\t\t\t; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
|
" --wssize-cutoff=[n|d|s]N\t\t\t\t; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
|
||||||
" --synack-split=[syn|synack|acksyn]\t\t; perform TCP split handshake : send SYN only, SYN+ACK or ACK+SYN\n"
|
" --synack-split=[syn|synack|acksyn]\t\t\t; perform TCP split handshake : send SYN only, SYN+ACK or ACK+SYN\n"
|
||||||
" --orig-ttl=<int>\t\t\t\t; set TTL for original packets\n"
|
" --orig-ttl=<int>\t\t\t\t\t; set TTL for original packets\n"
|
||||||
" --orig-ttl6=<int>\t\t\t\t; set ipv6 hop limit for original packets. by default ttl value is used\n"
|
" --orig-ttl6=<int>\t\t\t\t\t; set ipv6 hop limit for original packets. by default ttl value is used\n"
|
||||||
" --orig-autottl=[<delta>[:<min>[-<max>]]|-]\t; auto ttl mode for both ipv4 and ipv6. default: +%d:%u-%u\n"
|
" --orig-autottl=[<delta>[:<min>[-<max>]]|-]\t\t; auto ttl mode for both ipv4 and ipv6. default: +%d:%u-%u\n"
|
||||||
" --orig-autottl6=[<delta>[:<min>[-<max>]]|-]\t; overrides --orig-autottl for ipv6 only\n"
|
" --orig-autottl6=[<delta>[:<min>[-<max>]]|-]\t\t; overrides --orig-autottl for ipv6 only\n"
|
||||||
" --orig-mod-start=[n|d|s]N\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
|
" --orig-mod-start=[n|d|s]N\t\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
|
||||||
" --orig-mod-cutoff=[n|d|s]N\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
|
" --orig-mod-cutoff=[n|d|s]N\t\t\t\t; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
|
||||||
" --dup=<int>\t\t\t\t\t; duplicate original packets. send N dups before original.\n"
|
" --dup=<int>\t\t\t\t\t\t; duplicate original packets. send N dups before original.\n"
|
||||||
" --dup-replace=[0|1]\t\t\t\t; 1 or no argument means do not send original, only dups\n"
|
" --dup-replace=[0|1]\t\t\t\t\t; 1 or no argument means do not send original, only dups\n"
|
||||||
" --dup-ttl=<int>\t\t\t\t; set TTL for dups\n"
|
" --dup-ttl=<int>\t\t\t\t\t; set TTL for dups\n"
|
||||||
" --dup-ttl6=<int>\t\t\t\t; set ipv6 hop limit for dups. by default ttl value is used\n"
|
" --dup-ttl6=<int>\t\t\t\t\t; set ipv6 hop limit for dups. by default ttl value is used\n"
|
||||||
" --dup-autottl=[<delta>[:<min>[-<max>]]|-]\t; auto ttl mode for both ipv4 and ipv6. default: %d:%u-%u\n"
|
" --dup-autottl=[<delta>[:<min>[-<max>]]|-]\t\t; auto ttl mode for both ipv4 and ipv6. default: %d:%u-%u\n"
|
||||||
" --dup-autottl6=[<delta>[:<min>[-<max>]]|-]\t; overrides --dup-autottl for ipv6 only\n"
|
" --dup-autottl6=[<delta>[:<min>[-<max>]]|-]\t\t; overrides --dup-autottl for ipv6 only\n"
|
||||||
" --dup-fooling=<mode>[,<mode>]\t\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2\n"
|
" --dup-fooling=<mode>[,<mode>]\t\t\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2\n"
|
||||||
" --dup-ts-increment=<int|0xHEX>\t\t\t; ts fooling TSval signed increment for dup. default %d\n"
|
" --dup-ts-increment=<int|0xHEX>\t\t\t\t; ts fooling TSval signed increment for dup. default %d\n"
|
||||||
" --dup-badseq-increment=<int|0xHEX>\t\t; badseq fooling seq signed increment for dup. default %d\n"
|
" --dup-badseq-increment=<int|0xHEX>\t\t\t; badseq fooling seq signed increment for dup. default %d\n"
|
||||||
" --dup-badack-increment=<int|0xHEX>\t\t; badseq fooling ackseq signed increment for dup. default %d\n"
|
" --dup-badack-increment=<int|0xHEX>\t\t\t; badseq fooling ackseq signed increment for dup. default %d\n"
|
||||||
" --dup-start=[n|d|s]N\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
|
" --dup-start=[n|d|s]N\t\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
|
||||||
" --dup-cutoff=[n|d|s]N\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
|
" --dup-cutoff=[n|d|s]N\t\t\t\t\t; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n"
|
||||||
" --hostcase\t\t\t\t\t; change Host: => host:\n"
|
" --hostcase\t\t\t\t\t\t; change Host: => host:\n"
|
||||||
" --hostspell\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
|
" --hostspell\t\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
|
||||||
" --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
" --hostnospace\t\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
||||||
" --domcase\t\t\t\t\t; mix domain case : Host: TeSt.cOm\n"
|
" --domcase\t\t\t\t\t\t; mix domain case : Host: TeSt.cOm\n"
|
||||||
" --methodeol\t\t\t\t\t; add '\\n' before method and remove space from Host:\n"
|
" --methodeol\t\t\t\t\t\t; add '\\n' before method and remove space from Host:\n"
|
||||||
" --dpi-desync=[<mode0>,]<mode>[,<mode2>]\t; try to desync dpi state. modes :\n"
|
" --dpi-desync=[<mode0>,]<mode>[,<mode2>]\t\t; try to desync dpi state. modes :\n"
|
||||||
"\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n"
|
"\t\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n"
|
||||||
"\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper\n"
|
"\t\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder hostfakesplit ipfrag2 udplen tamper\n"
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
" --dpi-desync-fwmark=<int|0xHEX>\t\t; override fwmark for desync packet. default = 0x%08X (%u)\n"
|
" --dpi-desync-fwmark=<int|0xHEX>\t\t\t; override fwmark for desync packet. default = 0x%08X (%u)\n"
|
||||||
#elif defined(SO_USER_COOKIE)
|
#elif defined(SO_USER_COOKIE)
|
||||||
" --dpi-desync-sockarg=<int|0xHEX>\t\t; override sockarg (SO_USER_COOKIE) for desync packet. default = 0x%08X (%u)\n"
|
" --dpi-desync-sockarg=<int|0xHEX>\t\t\t; override sockarg (SO_USER_COOKIE) for desync packet. default = 0x%08X (%u)\n"
|
||||||
#endif
|
#endif
|
||||||
" --dpi-desync-ttl=<int>\t\t\t\t; set ttl for fakes packets\n"
|
" --dpi-desync-ttl=<int>\t\t\t\t\t; set ttl for fakes packets\n"
|
||||||
" --dpi-desync-ttl6=<int>\t\t\t; set ipv6 hop limit for fake packet. by default --dpi-desync-ttl value is used.\n"
|
" --dpi-desync-ttl6=<int>\t\t\t\t; set ipv6 hop limit for fake packet. by default --dpi-desync-ttl value is used.\n"
|
||||||
" --dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: %d:%u-%u\n"
|
" --dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-]\t; auto ttl mode for both ipv4 and ipv6. default: %d:%u-%u\n"
|
||||||
" --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dpi-desync-autottl for ipv6 only\n"
|
" --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-]\t; overrides --dpi-desync-autottl for ipv6 only\n"
|
||||||
" --dpi-desync-fooling=<mode>[,<mode>]\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2\n"
|
" --dpi-desync-fooling=<mode>[,<mode>]\t\t\t; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2\n"
|
||||||
" --dpi-desync-repeats=<N>\t\t\t; send every desync packet N times\n"
|
" --dpi-desync-repeats=<N>\t\t\t\t; send every desync packet N times\n"
|
||||||
" --dpi-desync-skip-nosni=0|1\t\t\t; 1(default)=do not act on ClientHello without SNI\n"
|
" --dpi-desync-skip-nosni=0|1\t\t\t\t; 1(default)=do not act on ClientHello without SNI\n"
|
||||||
" --dpi-desync-split-pos=N|-N|marker+N|marker-N\t; comma separated list of split positions\n"
|
" --dpi-desync-split-pos=N|-N|marker+N|marker-N\t\t; comma separated list of split positions\n"
|
||||||
"\t\t\t\t\t\t; markers: method,host,endhost,sld,endsld,midsld,sniext\n"
|
"\t\t\t\t\t\t\t; markers: method,host,endhost,sld,endsld,midsld,sniext\n"
|
||||||
"\t\t\t\t\t\t; full list is only used by multisplit and multidisorder\n"
|
"\t\t\t\t\t\t\t; full list is only used by multisplit and multidisorder\n"
|
||||||
"\t\t\t\t\t\t; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise\n"
|
"\t\t\t\t\t\t\t; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise\n"
|
||||||
" --dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment\n"
|
" --dpi-desync-split-seqovl=N|-N|marker+N|marker-N\t; use sequence overlap before first sent original split segment\n"
|
||||||
" --dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap\n"
|
" --dpi-desync-split-seqovl-pattern=[+ofs]@<filename>|0xHEX ; pattern for the fake part of overlap\n"
|
||||||
" --dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder\n"
|
" --dpi-desync-fakedsplit-pattern=[+ofs]@<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder\n"
|
||||||
" --dpi-desync-ipfrag-pos-tcp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
" --dpi-desync-fakedsplit-mod=mod[,mod]\t\t\t; mods can be none,altorder=0|1|2|3 + 0|8|16\n"
|
||||||
" --dpi-desync-ipfrag-pos-udp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
" --dpi-desync-hostfakesplit-midhost=marker+N|marker-N ; additionally split real hostname at specified marker. must be within host..endhost or won't be splitted.\n"
|
||||||
" --dpi-desync-ts-increment=<int|0xHEX>\t\t; ts fooling TSval signed increment. default %d\n"
|
" --dpi-desync-hostfakesplit-mod=mod[,mod]\t\t; mods can be none,host=<hostname>,altorder=0|1\n"
|
||||||
" --dpi-desync-badseq-increment=<int|0xHEX>\t; badseq fooling seq signed increment. default %d\n"
|
" --dpi-desync-ipfrag-pos-tcp=<8..%u>\t\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
||||||
" --dpi-desync-badack-increment=<int|0xHEX>\t; badseq fooling ackseq signed increment. default %d\n"
|
" --dpi-desync-ipfrag-pos-udp=<8..%u>\t\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
||||||
" --dpi-desync-any-protocol=0|1\t\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n"
|
" --dpi-desync-ts-increment=<int|0xHEX>\t\t\t; ts fooling TSval signed increment. default %d\n"
|
||||||
" --dpi-desync-fake-http=<filename>|0xHEX\t; file containing fake http request\n"
|
" --dpi-desync-badseq-increment=<int|0xHEX>\t\t; badseq fooling seq signed increment. default %d\n"
|
||||||
" --dpi-desync-fake-tls=<filename>|0xHEX|!\t; file containing fake TLS ClientHello (for https)\n"
|
" --dpi-desync-badack-increment=<int|0xHEX>\t\t; badseq fooling ackseq signed increment. default %d\n"
|
||||||
" --dpi-desync-fake-tls-mod=mod[,mod]\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap\n"
|
" --dpi-desync-any-protocol=0|1\t\t\t\t; 0(default)=desync only http and tls 1=desync any nonempty data packet\n"
|
||||||
" --dpi-desync-fake-unknown=<filename>|0xHEX\t; file containing unknown protocol fake payload\n"
|
" --dpi-desync-fake-tcp-mod=mod[,mod]\t\t\t; comma separated list of tcp fake mods. available mods : none,seq\n"
|
||||||
" --dpi-desync-fake-syndata=<filename>|0xHEX\t; file containing SYN data payload\n"
|
" --dpi-desync-fake-http=[+ofs]@<filename>|0xHEX\t\t; fake http request\n"
|
||||||
" --dpi-desync-fake-quic=<filename>|0xHEX\t; file containing fake QUIC Initial\n"
|
" --dpi-desync-fake-tls=[+ofs]@<filename>|0xHEX|![+offset] ; fake TLS ClientHello (for https)\n"
|
||||||
" --dpi-desync-fake-wireguard=<filename>|0xHEX\t; file containing fake wireguard handshake initiation\n"
|
" --dpi-desync-fake-tls-mod=mod[,mod]\t\t\t; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap\n"
|
||||||
" --dpi-desync-fake-dht=<filename>|0xHEX\t\t; file containing DHT protocol fake payload (d1...e)\n"
|
" --dpi-desync-fake-unknown=[+ofs]@<filename>|0xHEX\t; unknown protocol fake payload\n"
|
||||||
" --dpi-desync-fake-discord=<filename>|0xHEX\t; file containing discord protocol fake payload (Voice IP Discovery)\n"
|
" --dpi-desync-fake-syndata=[+ofs]@<filename>|0xHEX\t; SYN data payload\n"
|
||||||
" --dpi-desync-fake-stun=<filename>|0xHEX\t; file containing STUN protocol fake payload\n"
|
" --dpi-desync-fake-quic=[+ofs]@<filename>|0xHEX\t\t; fake QUIC Initial\n"
|
||||||
" --dpi-desync-fake-unknown-udp=<filename>|0xHEX\t; file containing unknown udp protocol fake payload\n"
|
" --dpi-desync-fake-wireguard=[+ofs]@<filename>|0xHEX\t; fake wireguard handshake initiation\n"
|
||||||
" --dpi-desync-udplen-increment=<int>\t\t; increase or decrease udp packet length by N bytes (default %u). negative values decrease length.\n"
|
" --dpi-desync-fake-dht=[+ofs]@<filename>|0xHEX\t\t; DHT protocol fake payload (d1...e)\n"
|
||||||
" --dpi-desync-udplen-pattern=<filename>|0xHEX\t; udp tail fill pattern\n"
|
" --dpi-desync-fake-discord=[+ofs]@<filename>|0xHEX\t; discord protocol fake payload (Voice IP Discovery)\n"
|
||||||
" --dpi-desync-start=[n|d|s]N\t\t\t; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
|
" --dpi-desync-fake-stun=[+ofs]@<filename>|0xHEX\t\t; STUN protocol fake payload\n"
|
||||||
" --dpi-desync-cutoff=[n|d|s]N\t\t\t; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n",
|
" --dpi-desync-fake-unknown-udp=[+ofs]@<filename>|0xHEX\t; unknown udp protocol fake payload\n"
|
||||||
|
" --dpi-desync-udplen-increment=<int>\t\t\t; increase or decrease udp packet length by N bytes (default %u). negative values decrease length.\n"
|
||||||
|
" --dpi-desync-udplen-pattern=[+ofs]@<filename>|0xHEX\t; udp tail fill pattern\n"
|
||||||
|
" --dpi-desync-start=[n|d|s]N\t\t\t\t; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N\n"
|
||||||
|
" --dpi-desync-cutoff=[n|d|s]N\t\t\t\t; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N\n",
|
||||||
CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN, CTRACK_T_UDP,
|
CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN, CTRACK_T_UDP,
|
||||||
IPCACHE_LIFETIME,
|
IPCACHE_LIFETIME,
|
||||||
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT, HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT,
|
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT, HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT,
|
||||||
@@ -1688,7 +1894,8 @@ void check_dp(const struct desync_profile *dp)
|
|||||||
// only linux has connbytes limiter
|
// only linux has connbytes limiter
|
||||||
if ((dp->desync_any_proto && !dp->desync_cutoff &&
|
if ((dp->desync_any_proto && !dp->desync_cutoff &&
|
||||||
(dp->desync_mode == DESYNC_FAKE || dp->desync_mode == DESYNC_RST || dp->desync_mode == DESYNC_RSTACK ||
|
(dp->desync_mode == DESYNC_FAKE || dp->desync_mode == DESYNC_RST || dp->desync_mode == DESYNC_RSTACK ||
|
||||||
dp->desync_mode==DESYNC_FAKEDSPLIT || dp->desync_mode==DESYNC_FAKEDDISORDER || dp->desync_mode2==DESYNC_FAKEDSPLIT || dp->desync_mode2==DESYNC_FAKEDDISORDER))
|
dp->desync_mode == DESYNC_FAKEDSPLIT || dp->desync_mode == DESYNC_FAKEDDISORDER || dp->desync_mode == DESYNC_HOSTFAKESPLIT ||
|
||||||
|
dp->desync_mode2 == DESYNC_FAKEDSPLIT || dp->desync_mode2 == DESYNC_FAKEDDISORDER || dp->desync_mode2 == DESYNC_HOSTFAKESPLIT))
|
||||||
||
|
||
|
||||||
dp->dup_repeats && !dp->dup_cutoff)
|
dp->dup_repeats && !dp->dup_cutoff)
|
||||||
{
|
{
|
||||||
@@ -1701,7 +1908,7 @@ void check_dp(const struct desync_profile *dp)
|
|||||||
DLOG_CONDUP("WARNING !!! fakes or dups will be sent on every processed packet\n");
|
DLOG_CONDUP("WARNING !!! fakes or dups will be sent on every processed packet\n");
|
||||||
DLOG_CONDUP("WARNING !!! make sure it's really what you want\n");
|
DLOG_CONDUP("WARNING !!! make sure it's really what you want\n");
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
DLOG_CONDUP("WARNING !!! in most cases this is acceptable only with custom payload based windivert filter (--wf-raw)\n");
|
DLOG_CONDUP("WARNING !!! in most cases this is acceptable only with custom payload based windivert filter (--wf-raw, --wf-raw-part)\n");
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1789,12 +1996,16 @@ enum opt_indices {
|
|||||||
IDX_DPI_DESYNC_SPLIT_SEQOVL,
|
IDX_DPI_DESYNC_SPLIT_SEQOVL,
|
||||||
IDX_DPI_DESYNC_SPLIT_SEQOVL_PATTERN,
|
IDX_DPI_DESYNC_SPLIT_SEQOVL_PATTERN,
|
||||||
IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN,
|
IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN,
|
||||||
|
IDX_DPI_DESYNC_FAKEDSPLIT_MOD,
|
||||||
|
IDX_DPI_DESYNC_HOSTFAKESPLIT_MIDHOST,
|
||||||
|
IDX_DPI_DESYNC_HOSTFAKESPLIT_MOD,
|
||||||
IDX_DPI_DESYNC_IPFRAG_POS_TCP,
|
IDX_DPI_DESYNC_IPFRAG_POS_TCP,
|
||||||
IDX_DPI_DESYNC_IPFRAG_POS_UDP,
|
IDX_DPI_DESYNC_IPFRAG_POS_UDP,
|
||||||
IDX_DPI_DESYNC_TS_INCREMENT,
|
IDX_DPI_DESYNC_TS_INCREMENT,
|
||||||
IDX_DPI_DESYNC_BADSEQ_INCREMENT,
|
IDX_DPI_DESYNC_BADSEQ_INCREMENT,
|
||||||
IDX_DPI_DESYNC_BADACK_INCREMENT,
|
IDX_DPI_DESYNC_BADACK_INCREMENT,
|
||||||
IDX_DPI_DESYNC_ANY_PROTOCOL,
|
IDX_DPI_DESYNC_ANY_PROTOCOL,
|
||||||
|
IDX_DPI_DESYNC_FAKE_TCP_MOD,
|
||||||
IDX_DPI_DESYNC_FAKE_HTTP,
|
IDX_DPI_DESYNC_FAKE_HTTP,
|
||||||
IDX_DPI_DESYNC_FAKE_TLS,
|
IDX_DPI_DESYNC_FAKE_TLS,
|
||||||
IDX_DPI_DESYNC_FAKE_TLS_MOD,
|
IDX_DPI_DESYNC_FAKE_TLS_MOD,
|
||||||
@@ -1841,6 +2052,8 @@ enum opt_indices {
|
|||||||
IDX_WF_TCP,
|
IDX_WF_TCP,
|
||||||
IDX_WF_UDP,
|
IDX_WF_UDP,
|
||||||
IDX_WF_RAW,
|
IDX_WF_RAW,
|
||||||
|
IDX_WF_RAW_PART,
|
||||||
|
IDX_WF_FILTER_LAN,
|
||||||
IDX_WF_SAVE,
|
IDX_WF_SAVE,
|
||||||
IDX_SSID_FILTER,
|
IDX_SSID_FILTER,
|
||||||
IDX_NLM_FILTER,
|
IDX_NLM_FILTER,
|
||||||
@@ -1915,12 +2128,16 @@ static const struct option long_options[] = {
|
|||||||
[IDX_DPI_DESYNC_SPLIT_SEQOVL] = {"dpi-desync-split-seqovl", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_SPLIT_SEQOVL] = {"dpi-desync-split-seqovl", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_SPLIT_SEQOVL_PATTERN] = {"dpi-desync-split-seqovl-pattern", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_SPLIT_SEQOVL_PATTERN] = {"dpi-desync-split-seqovl-pattern", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN] = {"dpi-desync-fakedsplit-pattern", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN] = {"dpi-desync-fakedsplit-pattern", required_argument, 0, 0},
|
||||||
|
[IDX_DPI_DESYNC_FAKEDSPLIT_MOD] = {"dpi-desync-fakedsplit-mod", required_argument, 0, 0},
|
||||||
|
[IDX_DPI_DESYNC_HOSTFAKESPLIT_MIDHOST] = {"dpi-desync-hostfakesplit-midhost", required_argument, 0, 0},
|
||||||
|
[IDX_DPI_DESYNC_HOSTFAKESPLIT_MOD] = {"dpi-desync-hostfakesplit-mod", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_IPFRAG_POS_TCP] = {"dpi-desync-ipfrag-pos-tcp", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_IPFRAG_POS_TCP] = {"dpi-desync-ipfrag-pos-tcp", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_IPFRAG_POS_UDP] = {"dpi-desync-ipfrag-pos-udp", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_IPFRAG_POS_UDP] = {"dpi-desync-ipfrag-pos-udp", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_TS_INCREMENT] = {"dpi-desync-ts-increment", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_TS_INCREMENT] = {"dpi-desync-ts-increment", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_BADSEQ_INCREMENT] = {"dpi-desync-badseq-increment", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_BADSEQ_INCREMENT] = {"dpi-desync-badseq-increment", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_BADACK_INCREMENT] = {"dpi-desync-badack-increment", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_BADACK_INCREMENT] = {"dpi-desync-badack-increment", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_ANY_PROTOCOL] = {"dpi-desync-any-protocol", optional_argument, 0, 0},
|
[IDX_DPI_DESYNC_ANY_PROTOCOL] = {"dpi-desync-any-protocol", optional_argument, 0, 0},
|
||||||
|
[IDX_DPI_DESYNC_FAKE_TCP_MOD] = {"dpi-desync-fake-tcp-mod", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_FAKE_HTTP] = {"dpi-desync-fake-http", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_FAKE_HTTP] = {"dpi-desync-fake-http", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_FAKE_TLS] = {"dpi-desync-fake-tls", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_FAKE_TLS] = {"dpi-desync-fake-tls", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC_FAKE_TLS_MOD] = {"dpi-desync-fake-tls-mod", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_FAKE_TLS_MOD] = {"dpi-desync-fake-tls-mod", required_argument, 0, 0},
|
||||||
@@ -1967,6 +2184,8 @@ static const struct option long_options[] = {
|
|||||||
[IDX_WF_TCP] = {"wf-tcp", required_argument, 0, 0},
|
[IDX_WF_TCP] = {"wf-tcp", required_argument, 0, 0},
|
||||||
[IDX_WF_UDP] = {"wf-udp", required_argument, 0, 0},
|
[IDX_WF_UDP] = {"wf-udp", required_argument, 0, 0},
|
||||||
[IDX_WF_RAW] = {"wf-raw", required_argument, 0, 0},
|
[IDX_WF_RAW] = {"wf-raw", required_argument, 0, 0},
|
||||||
|
[IDX_WF_RAW_PART] = {"wf-raw-part", required_argument, 0, 0},
|
||||||
|
[IDX_WF_FILTER_LAN] = {"wf-filter-lan", required_argument, 0, 0},
|
||||||
[IDX_WF_SAVE] = {"wf-save", required_argument, 0, 0},
|
[IDX_WF_SAVE] = {"wf-save", required_argument, 0, 0},
|
||||||
[IDX_SSID_FILTER] = {"ssid-filter", required_argument, 0, 0},
|
[IDX_SSID_FILTER] = {"ssid-filter", required_argument, 0, 0},
|
||||||
[IDX_NLM_FILTER] = {"nlm-filter", required_argument, 0, 0},
|
[IDX_NLM_FILTER] = {"nlm-filter", required_argument, 0, 0},
|
||||||
@@ -1994,9 +2213,9 @@ int main(int argc, char **argv)
|
|||||||
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
|
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
char windivert_filter[16384], wf_pf_tcp_src[4096], wf_pf_tcp_dst[4096], wf_pf_udp_src[4096], wf_pf_udp_dst[4096], wf_save_file[256];
|
char windivert_filter[16384], wf_pf_tcp_src[4096], wf_pf_tcp_dst[4096], wf_pf_udp_src[4096], wf_pf_udp_dst[4096], wf_save_file[256];
|
||||||
bool wf_ipv4=true, wf_ipv6=true;
|
bool wf_ipv4 = true, wf_ipv6 = true, wf_filter_lan = true;
|
||||||
unsigned int IfIdx = 0, SubIfIdx = 0;
|
unsigned int IfIdx = 0, SubIfIdx = 0;
|
||||||
unsigned int hash_wf_tcp=0,hash_wf_udp=0,hash_wf_raw=0,hash_ssid_filter=0,hash_nlm_filter=0;
|
unsigned int hash_wf_tcp = 0, hash_wf_udp = 0, hash_wf_raw = 0, hash_wf_raw_part = 0, hash_ssid_filter = 0, hash_nlm_filter = 0;
|
||||||
*windivert_filter = *wf_pf_tcp_src = *wf_pf_tcp_dst = *wf_pf_udp_src = *wf_pf_udp_dst = *wf_save_file = 0;
|
*windivert_filter = *wf_pf_tcp_src = *wf_pf_tcp_dst = *wf_pf_udp_src = *wf_pf_udp_dst = *wf_save_file = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2037,6 +2256,7 @@ int main(int argc, char **argv)
|
|||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
LIST_INIT(¶ms.ssid_filter);
|
LIST_INIT(¶ms.ssid_filter);
|
||||||
LIST_INIT(¶ms.nlm_filter);
|
LIST_INIT(¶ms.nlm_filter);
|
||||||
|
LIST_INIT(¶ms.wf_raw_part);
|
||||||
#else
|
#else
|
||||||
if (can_drop_root())
|
if (can_drop_root())
|
||||||
{
|
{
|
||||||
@@ -2536,16 +2756,47 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
char buf[sizeof(dp->seqovl_pattern)];
|
char buf[sizeof(dp->seqovl_pattern)];
|
||||||
size_t sz = sizeof(buf);
|
size_t sz = sizeof(buf);
|
||||||
load_file_or_exit(optarg,buf,&sz);
|
load_file_or_exit(optarg, buf, &sz, NULL);
|
||||||
fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz);
|
fill_pattern(dp->seqovl_pattern, sizeof(dp->seqovl_pattern), buf, sz, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN:
|
case IDX_DPI_DESYNC_FAKEDSPLIT_PATTERN:
|
||||||
{
|
{
|
||||||
char buf[sizeof(dp->fsplit_pattern)];
|
free(dp->fsplit_pattern);
|
||||||
size_t sz=sizeof(buf);
|
if (!(dp->fsplit_pattern = malloc(dp->fsplit_pattern_size=32768)))
|
||||||
load_file_or_exit(optarg,buf,&sz);
|
{
|
||||||
fill_pattern(dp->fsplit_pattern,sizeof(dp->fsplit_pattern),buf,sz);
|
DLOG_ERR("out of memory\n");
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
load_file_or_exit(optarg, dp->fsplit_pattern, &dp->fsplit_pattern_size, NULL);
|
||||||
|
dp->fsplit_pattern = realloc(dp->fsplit_pattern, dp->fsplit_pattern_size);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDX_DPI_DESYNC_FAKEDSPLIT_MOD:
|
||||||
|
if (!parse_fakedsplit_mod(optarg, &dp->fs_mod))
|
||||||
|
{
|
||||||
|
DLOG_ERR("Invalid fakedsplit mod : %s\n", optarg);
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDX_DPI_DESYNC_HOSTFAKESPLIT_MIDHOST:
|
||||||
|
if (!strcmp(optarg, "0"))
|
||||||
|
{
|
||||||
|
// allow zero = disable midhost split
|
||||||
|
dp->hostfakesplit_midhost.marker = PM_ABS;
|
||||||
|
dp->hostfakesplit_midhost.pos = 0;
|
||||||
|
}
|
||||||
|
else if (!parse_split_pos(optarg, &dp->hostfakesplit_midhost))
|
||||||
|
{
|
||||||
|
DLOG_ERR("Invalid argument for dpi-desync-hostfakesplit-midhost\n");
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDX_DPI_DESYNC_HOSTFAKESPLIT_MOD:
|
||||||
|
if (!parse_hostfakesplit_mod(optarg, &dp->hfs_mod))
|
||||||
|
{
|
||||||
|
DLOG_ERR("Invalid hostfakesplit mod : %s\n", optarg);
|
||||||
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDX_DPI_DESYNC_IPFRAG_POS_TCP:
|
case IDX_DPI_DESYNC_IPFRAG_POS_TCP:
|
||||||
@@ -2596,14 +2847,22 @@ int main(int argc, char **argv)
|
|||||||
case IDX_DPI_DESYNC_ANY_PROTOCOL:
|
case IDX_DPI_DESYNC_ANY_PROTOCOL:
|
||||||
dp->desync_any_proto = !optarg || atoi(optarg);
|
dp->desync_any_proto = !optarg || atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case IDX_DPI_DESYNC_FAKE_TCP_MOD:
|
||||||
|
if (!parse_tcpmod(optarg, &dp->tcp_mod))
|
||||||
|
{
|
||||||
|
DLOG_ERR("Invalid tcp mod : %s\n", optarg);
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case IDX_DPI_DESYNC_FAKE_HTTP:
|
case IDX_DPI_DESYNC_FAKE_HTTP:
|
||||||
load_blob_to_collection(optarg, &dp->fake_http, FAKE_MAX_TCP, 0);
|
load_blob_to_collection(optarg, &dp->fake_http, FAKE_MAX_TCP, 0);
|
||||||
break;
|
break;
|
||||||
case IDX_DPI_DESYNC_FAKE_TLS:
|
case IDX_DPI_DESYNC_FAKE_TLS:
|
||||||
{
|
{
|
||||||
dp->tls_fake_last = strcmp(optarg,"!") ?
|
if (optarg[0] == '!' && (optarg[1] == 0 || optarg[1] == '+'))
|
||||||
load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP,4+sizeof(dp->tls_mod_last.sni)) :
|
dp->tls_fake_last = load_const_blob_to_collection(fake_tls_clienthello_default, sizeof(fake_tls_clienthello_default), &dp->fake_tls, 4 + sizeof(dp->tls_mod_last.sni), optarg[1] == '+' ? (size_t)atoi(optarg + 1) : 0);
|
||||||
load_const_blob_to_collection(fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),&dp->fake_tls,4+sizeof(dp->tls_mod_last.sni));
|
else
|
||||||
|
dp->tls_fake_last = load_blob_to_collection(optarg, &dp->fake_tls, FAKE_MAX_TCP, 4 + sizeof(dp->tls_mod_last.sni));
|
||||||
if (!(dp->tls_fake_last->extra2 = malloc(sizeof(struct fake_tls_mod))))
|
if (!(dp->tls_fake_last->extra2 = malloc(sizeof(struct fake_tls_mod))))
|
||||||
{
|
{
|
||||||
DLOG_ERR("out of memory\n");
|
DLOG_ERR("out of memory\n");
|
||||||
@@ -2628,7 +2887,7 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case IDX_DPI_DESYNC_FAKE_SYNDATA:
|
case IDX_DPI_DESYNC_FAKE_SYNDATA:
|
||||||
dp->fake_syndata_size = sizeof(dp->fake_syndata);
|
dp->fake_syndata_size = sizeof(dp->fake_syndata);
|
||||||
load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size);
|
load_file_or_exit(optarg, dp->fake_syndata, &dp->fake_syndata_size, NULL);
|
||||||
break;
|
break;
|
||||||
case IDX_DPI_DESYNC_FAKE_QUIC:
|
case IDX_DPI_DESYNC_FAKE_QUIC:
|
||||||
load_blob_to_collection(optarg, &dp->fake_quic, FAKE_MAX_UDP, 0);
|
load_blob_to_collection(optarg, &dp->fake_quic, FAKE_MAX_UDP, 0);
|
||||||
@@ -2659,8 +2918,8 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
char buf[sizeof(dp->udplen_pattern)];
|
char buf[sizeof(dp->udplen_pattern)];
|
||||||
size_t sz = sizeof(buf);
|
size_t sz = sizeof(buf);
|
||||||
load_file_or_exit(optarg,buf,&sz);
|
load_file_or_exit(optarg, buf, &sz, NULL);
|
||||||
fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz);
|
fill_pattern(dp->udplen_pattern, sizeof(dp->udplen_pattern), buf, sz, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IDX_DPI_DESYNC_CUTOFF:
|
case IDX_DPI_DESYNC_CUTOFF:
|
||||||
@@ -2944,7 +3203,7 @@ int main(int argc, char **argv)
|
|||||||
if (optarg[0] == '@')
|
if (optarg[0] == '@')
|
||||||
{
|
{
|
||||||
size_t sz = sizeof(windivert_filter) - 1;
|
size_t sz = sizeof(windivert_filter) - 1;
|
||||||
load_file_or_exit(optarg+1,windivert_filter,&sz);
|
load_file_or_exit(optarg, windivert_filter, &sz, NULL);
|
||||||
windivert_filter[sz] = 0;
|
windivert_filter[sz] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2953,6 +3212,31 @@ int main(int argc, char **argv)
|
|||||||
windivert_filter[sizeof(windivert_filter) - 1] = '\0';
|
windivert_filter[sizeof(windivert_filter) - 1] = '\0';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case IDX_WF_RAW_PART:
|
||||||
|
hash_wf_raw_part ^= hash_jen(optarg, strlen(optarg));
|
||||||
|
{
|
||||||
|
char wfpart[sizeof(windivert_filter)];
|
||||||
|
if (optarg[0] == '@')
|
||||||
|
{
|
||||||
|
size_t sz = sizeof(wfpart) - 1;
|
||||||
|
load_file_or_exit(optarg, wfpart, &sz, NULL);
|
||||||
|
wfpart[sz] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strncpy(wfpart, optarg, sizeof(wfpart));
|
||||||
|
wfpart[sizeof(wfpart) - 1] = '\0';
|
||||||
|
}
|
||||||
|
if (!strlist_add(¶ms.wf_raw_part, wfpart))
|
||||||
|
{
|
||||||
|
DLOG_ERR("out of memory\n");
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IDX_WF_FILTER_LAN:
|
||||||
|
wf_filter_lan = !!atoi(optarg);
|
||||||
|
break;
|
||||||
case IDX_WF_SAVE:
|
case IDX_WF_SAVE:
|
||||||
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
|
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
|
||||||
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
|
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
|
||||||
@@ -3032,10 +3316,21 @@ int main(int argc, char **argv)
|
|||||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||||
{
|
{
|
||||||
dp = &dpl->dp;
|
dp = &dpl->dp;
|
||||||
|
|
||||||
// not specified - use desync_ttl value instead
|
// not specified - use desync_ttl value instead
|
||||||
if (dp->desync_ttl6 == 0xFF) dp->desync_ttl6 = dp->desync_ttl;
|
if (dp->desync_ttl6 == 0xFF) dp->desync_ttl6 = dp->desync_ttl;
|
||||||
if (dp->dup_ttl6 == 0xFF) dp->dup_ttl6 = dp->dup_ttl;
|
if (dp->dup_ttl6 == 0xFF) dp->dup_ttl6 = dp->dup_ttl;
|
||||||
if (dp->orig_mod_ttl6 == 0xFF) dp->orig_mod_ttl6 = dp->orig_mod_ttl;
|
if (dp->orig_mod_ttl6 == 0xFF) dp->orig_mod_ttl6 = dp->orig_mod_ttl;
|
||||||
|
if (!dp->fsplit_pattern)
|
||||||
|
{
|
||||||
|
if (dp->fsplit_pattern=calloc(64,1))
|
||||||
|
dp->fsplit_pattern_size=64;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DLOG_ERR("out of memory\n");
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!AUTOTTL_ENABLED(dp->desync_autottl6)) dp->desync_autottl6 = dp->desync_autottl;
|
if (!AUTOTTL_ENABLED(dp->desync_autottl6)) dp->desync_autottl6 = dp->desync_autottl;
|
||||||
if (!AUTOTTL_ENABLED(dp->orig_autottl6)) dp->orig_autottl6 = dp->orig_autottl;
|
if (!AUTOTTL_ENABLED(dp->orig_autottl6)) dp->orig_autottl6 = dp->orig_autottl;
|
||||||
if (!AUTOTTL_ENABLED(dp->dup_autottl6)) dp->dup_autottl6 = dp->dup_autottl;
|
if (!AUTOTTL_ENABLED(dp->dup_autottl6)) dp->dup_autottl6 = dp->dup_autottl;
|
||||||
@@ -3093,12 +3388,12 @@ int main(int argc, char **argv)
|
|||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
if (!*windivert_filter)
|
if (!*windivert_filter)
|
||||||
{
|
{
|
||||||
if (!*wf_pf_tcp_src && !*wf_pf_udp_src)
|
if (!*wf_pf_tcp_src && !*wf_pf_udp_src && LIST_EMPTY(¶ms.wf_raw_part))
|
||||||
{
|
{
|
||||||
DLOG_ERR("windivert filter : must specify port filter\n");
|
DLOG_ERR("windivert filter : must specify port or/and partial raw filter\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
if (!wf_make_filter(windivert_filter, sizeof(windivert_filter), IfIdx, SubIfIdx, wf_ipv4, wf_ipv6, wf_pf_tcp_src, wf_pf_tcp_dst, wf_pf_udp_src, wf_pf_udp_dst))
|
if (!wf_make_filter(windivert_filter, sizeof(windivert_filter), IfIdx, SubIfIdx, wf_ipv4, wf_ipv6, wf_pf_tcp_src, wf_pf_tcp_dst, wf_pf_udp_src, wf_pf_udp_dst, ¶ms.wf_raw_part, wf_filter_lan))
|
||||||
{
|
{
|
||||||
DLOG_ERR("windivert filter : could not make filter\n");
|
DLOG_ERR("windivert filter : could not make filter\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@@ -3121,7 +3416,7 @@ int main(int argc, char **argv)
|
|||||||
HANDLE hMutexArg;
|
HANDLE hMutexArg;
|
||||||
{
|
{
|
||||||
char mutex_name[128];
|
char mutex_name[128];
|
||||||
snprintf(mutex_name,sizeof(mutex_name),"Global\\winws_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u",hash_wf_tcp,hash_wf_udp,hash_wf_raw,hash_ssid_filter,hash_nlm_filter,IfIdx,SubIfIdx,wf_ipv4,wf_ipv6);
|
snprintf(mutex_name, sizeof(mutex_name), "Global\\winws_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u", hash_wf_tcp, hash_wf_udp, hash_wf_raw, hash_wf_raw_part, hash_ssid_filter, hash_nlm_filter, IfIdx, SubIfIdx, wf_ipv4, wf_ipv6);
|
||||||
|
|
||||||
hMutexArg = CreateMutexA(NULL, TRUE, mutex_name);
|
hMutexArg = CreateMutexA(NULL, TRUE, mutex_name);
|
||||||
if (hMutexArg && GetLastError() == ERROR_ALREADY_EXISTS)
|
if (hMutexArg && GetLastError() == ERROR_ALREADY_EXISTS)
|
||||||
|
|||||||
+9
-5
@@ -20,6 +20,7 @@ const char *progname = "nfqws";
|
|||||||
#error UNKNOWN_SYSTEM_TIME
|
#error UNKNOWN_SYSTEM_TIME
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const char * tld[6] = { "com","org","net","edu","gov","biz" };
|
||||||
|
|
||||||
int DLOG_FILE(FILE *F, const char *format, va_list args)
|
int DLOG_FILE(FILE *F, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
@@ -241,11 +242,11 @@ bool dp_fake_defaults(struct desync_profile *dp)
|
|||||||
{
|
{
|
||||||
struct blob_item *item;
|
struct blob_item *item;
|
||||||
if (blob_collection_empty(&dp->fake_http))
|
if (blob_collection_empty(&dp->fake_http))
|
||||||
if (!blob_collection_add_blob(&dp->fake_http,fake_http_request_default,strlen(fake_http_request_default),0))
|
if (!blob_collection_add_blob(&dp->fake_http,fake_http_request_default,strlen(fake_http_request_default),0,0))
|
||||||
return false;
|
return false;
|
||||||
if (blob_collection_empty(&dp->fake_tls))
|
if (blob_collection_empty(&dp->fake_tls))
|
||||||
{
|
{
|
||||||
if (!(item=blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(((struct fake_tls_mod*)0)->sni))))
|
if (!(item=blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(((struct fake_tls_mod*)0)->sni),0)))
|
||||||
return false;
|
return false;
|
||||||
if (!(item->extra2 = malloc(sizeof(struct fake_tls_mod))))
|
if (!(item->extra2 = malloc(sizeof(struct fake_tls_mod))))
|
||||||
return false;
|
return false;
|
||||||
@@ -253,13 +254,13 @@ bool dp_fake_defaults(struct desync_profile *dp)
|
|||||||
}
|
}
|
||||||
if (blob_collection_empty(&dp->fake_unknown))
|
if (blob_collection_empty(&dp->fake_unknown))
|
||||||
{
|
{
|
||||||
if (!(item=blob_collection_add_blob(&dp->fake_unknown,NULL,256,0)))
|
if (!(item=blob_collection_add_blob(&dp->fake_unknown,NULL,256,0,0)))
|
||||||
return false;
|
return false;
|
||||||
memset(item->data,0,item->size);
|
memset(item->data,0,item->size);
|
||||||
}
|
}
|
||||||
if (blob_collection_empty(&dp->fake_quic))
|
if (blob_collection_empty(&dp->fake_quic))
|
||||||
{
|
{
|
||||||
if (!(item=blob_collection_add_blob(&dp->fake_quic,NULL,620,0)))
|
if (!(item=blob_collection_add_blob(&dp->fake_quic,NULL,620,0,0)))
|
||||||
return false;
|
return false;
|
||||||
memset(item->data,0,item->size);
|
memset(item->data,0,item->size);
|
||||||
item->data[0] = 0x40;
|
item->data[0] = 0x40;
|
||||||
@@ -269,7 +270,7 @@ bool dp_fake_defaults(struct desync_profile *dp)
|
|||||||
{
|
{
|
||||||
if (blob_collection_empty(*fake))
|
if (blob_collection_empty(*fake))
|
||||||
{
|
{
|
||||||
if (!(item=blob_collection_add_blob(*fake,NULL,64,0)))
|
if (!(item=blob_collection_add_blob(*fake,NULL,64,0,0)))
|
||||||
return false;
|
return false;
|
||||||
memset(item->data,0,item->size);
|
memset(item->data,0,item->size);
|
||||||
}
|
}
|
||||||
@@ -297,6 +298,8 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
|||||||
}
|
}
|
||||||
static void dp_clear_dynamic(struct desync_profile *dp)
|
static void dp_clear_dynamic(struct desync_profile *dp)
|
||||||
{
|
{
|
||||||
|
free(dp->fsplit_pattern);
|
||||||
|
|
||||||
hostlist_collection_destroy(&dp->hl_collection);
|
hostlist_collection_destroy(&dp->hl_collection);
|
||||||
hostlist_collection_destroy(&dp->hl_collection_exclude);
|
hostlist_collection_destroy(&dp->hl_collection_exclude);
|
||||||
ipset_collection_destroy(&dp->ips_collection);
|
ipset_collection_destroy(&dp->ips_collection);
|
||||||
@@ -371,6 +374,7 @@ void cleanup_params(struct params_s *params)
|
|||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
strlist_destroy(¶ms->ssid_filter);
|
strlist_destroy(¶ms->ssid_filter);
|
||||||
strlist_destroy(¶ms->nlm_filter);
|
strlist_destroy(¶ms->nlm_filter);
|
||||||
|
strlist_destroy(¶ms->wf_raw_part);
|
||||||
#else
|
#else
|
||||||
free(params->user); params->user=NULL;
|
free(params->user); params->user=NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+26
-4
@@ -68,6 +68,8 @@
|
|||||||
|
|
||||||
#define MAX_GIDS 64
|
#define MAX_GIDS 64
|
||||||
|
|
||||||
|
extern const char * tld[6];
|
||||||
|
|
||||||
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG, LOG_TARGET_ANDROID };
|
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG, LOG_TARGET_ANDROID };
|
||||||
|
|
||||||
struct fake_tls_mod_cache
|
struct fake_tls_mod_cache
|
||||||
@@ -76,9 +78,23 @@ struct fake_tls_mod_cache
|
|||||||
};
|
};
|
||||||
struct fake_tls_mod
|
struct fake_tls_mod
|
||||||
{
|
{
|
||||||
char sni[64];
|
char sni[128];
|
||||||
uint32_t mod;
|
uint32_t mod;
|
||||||
};
|
};
|
||||||
|
struct hostfakesplit_mod
|
||||||
|
{
|
||||||
|
char host[128];
|
||||||
|
size_t host_size;
|
||||||
|
int ordering;
|
||||||
|
};
|
||||||
|
struct fakedsplit_mod
|
||||||
|
{
|
||||||
|
int ordering;
|
||||||
|
};
|
||||||
|
struct tcp_mod
|
||||||
|
{
|
||||||
|
bool seq;
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum {SS_NONE=0,SS_SYN,SS_SYNACK,SS_ACKSYN} t_synack_split;
|
typedef enum {SS_NONE=0,SS_SYN,SS_SYNACK,SS_ACKSYN} t_synack_split;
|
||||||
|
|
||||||
@@ -102,7 +118,7 @@ struct desync_profile
|
|||||||
// multisplit
|
// multisplit
|
||||||
struct proto_pos splits[MAX_SPLITS];
|
struct proto_pos splits[MAX_SPLITS];
|
||||||
int split_count;
|
int split_count;
|
||||||
struct proto_pos seqovl;
|
struct proto_pos seqovl,hostfakesplit_midhost;
|
||||||
|
|
||||||
char dup_start_mode, dup_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
char dup_start_mode, dup_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
||||||
bool dup_replace;
|
bool dup_replace;
|
||||||
@@ -126,12 +142,17 @@ struct desync_profile
|
|||||||
uint32_t desync_ts_increment, desync_badseq_increment, desync_badseq_ack_increment;
|
uint32_t desync_ts_increment, desync_badseq_increment, desync_badseq_ack_increment;
|
||||||
|
|
||||||
struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht,fake_discord,fake_stun;
|
struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht,fake_discord,fake_stun;
|
||||||
uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],fsplit_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP];
|
uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP];
|
||||||
size_t fake_syndata_size;
|
uint8_t *fsplit_pattern;
|
||||||
|
size_t fake_syndata_size, fsplit_pattern_size;
|
||||||
|
|
||||||
struct fake_tls_mod tls_mod_last;
|
struct fake_tls_mod tls_mod_last;
|
||||||
struct blob_item *tls_fake_last;
|
struct blob_item *tls_fake_last;
|
||||||
|
|
||||||
|
struct hostfakesplit_mod hfs_mod;
|
||||||
|
struct fakedsplit_mod fs_mod;
|
||||||
|
struct tcp_mod tcp_mod;
|
||||||
|
|
||||||
int udplen_increment;
|
int udplen_increment;
|
||||||
|
|
||||||
bool filter_ipv4,filter_ipv6;
|
bool filter_ipv4,filter_ipv6;
|
||||||
@@ -200,6 +221,7 @@ struct params_s
|
|||||||
|
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
struct str_list_head ssid_filter,nlm_filter;
|
struct str_list_head ssid_filter,nlm_filter;
|
||||||
|
struct str_list_head wf_raw_part;
|
||||||
#else
|
#else
|
||||||
bool droproot;
|
bool droproot;
|
||||||
char *user;
|
char *user;
|
||||||
|
|||||||
+3
-1
@@ -579,8 +579,9 @@ struct blob_item *blob_collection_add(struct blob_collection_head *head)
|
|||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve)
|
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve, size_t offset)
|
||||||
{
|
{
|
||||||
|
if (offset>=size) return NULL;
|
||||||
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
|
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
|
||||||
if (!entry) return NULL;
|
if (!entry) return NULL;
|
||||||
if (!(entry->data = malloc(size+size_reserve)))
|
if (!(entry->data = malloc(size+size_reserve)))
|
||||||
@@ -591,6 +592,7 @@ struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, co
|
|||||||
if (data) memcpy(entry->data,data,size);
|
if (data) memcpy(entry->data,data,size);
|
||||||
entry->size = size;
|
entry->size = size;
|
||||||
entry->size_buf = size+size_reserve;
|
entry->size_buf = size+size_reserve;
|
||||||
|
entry->offset = offset;
|
||||||
|
|
||||||
// insert to the end
|
// insert to the end
|
||||||
struct blob_item *itemc,*iteml=LIST_FIRST(head);
|
struct blob_item *itemc,*iteml=LIST_FIRST(head);
|
||||||
|
|||||||
+2
-1
@@ -157,13 +157,14 @@ struct blob_item {
|
|||||||
uint8_t *data; // main data blob
|
uint8_t *data; // main data blob
|
||||||
size_t size; // main data blob size
|
size_t size; // main data blob size
|
||||||
size_t size_buf;// main data blob allocated size
|
size_t size_buf;// main data blob allocated size
|
||||||
|
size_t offset; // optional offset to useful data
|
||||||
void *extra; // any data without size
|
void *extra; // any data without size
|
||||||
void *extra2; // any data without size
|
void *extra2; // any data without size
|
||||||
LIST_ENTRY(blob_item) next;
|
LIST_ENTRY(blob_item) next;
|
||||||
};
|
};
|
||||||
LIST_HEAD(blob_collection_head, blob_item);
|
LIST_HEAD(blob_collection_head, blob_item);
|
||||||
struct blob_item *blob_collection_add(struct blob_collection_head *head);
|
struct blob_item *blob_collection_add(struct blob_collection_head *head);
|
||||||
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve);
|
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve, size_t offset);
|
||||||
void blob_collection_destroy(struct blob_collection_head *head);
|
void blob_collection_destroy(struct blob_collection_head *head);
|
||||||
bool blob_collection_empty(const struct blob_collection_head *head);
|
bool blob_collection_empty(const struct blob_collection_head *head);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user