mirror of
https://github.com/bol-van/zapret.git
synced 2026-09-22 08:14:50 +09:00
Compare commits
124 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 845f4b43ef | |||
| a485030423 | |||
| 6821093493 | |||
| 0dea2d6ad0 | |||
| 16e71fc5fc | |||
| b2795989b7 | |||
| dbfc20a5bc | |||
| 2aa301bf0b | |||
| 324aa12ecf | |||
| af5cf623be | |||
| 9556eff091 | |||
| ca42c88ce0 | |||
| 62cdc8bf13 | |||
| 643c254fab | |||
| 3f2ef1feee | |||
| 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 | |||
| 7364bab8a7 | |||
| 1f48453989 | |||
| dc5efebee2 | |||
| 10c9499647 | |||
| a50082df92 | |||
| 0c33bbfb37 | |||
| ea1be413a6 | |||
| 850d4023fb | |||
| 4872b8e4e8 | |||
| 75eaefa950 | |||
| 582ade3190 | |||
| efd369bb0e | |||
| 784465bdcf | |||
| 40a80cd328 | |||
| 73f21b0524 | |||
| 34698479d0 | |||
| 0830633f42 | |||
| fc837e14fa | |||
| 0e288262b5 | |||
| dce049d6b8 | |||
| d103602d86 | |||
| aaf8f18a7d | |||
| de19cc3cd4 | |||
| 1e56703d4b | |||
| cd0f1c4bdf | |||
| 135b152497 | |||
| 56456c1e0c | |||
| d6a8d1dc33 | |||
| 04b3b6abcb | |||
| fd58ecf8a5 |
@@ -1,3 +1,4 @@
|
|||||||
* text=auto eol=lf
|
* text=auto eol=lf
|
||||||
*.cmd eol=crlf
|
*.cmd eol=crlf
|
||||||
*.bat eol=crlf
|
*.bat eol=crlf
|
||||||
|
init.d/windivert.filter.examples/** eol=crlf
|
||||||
|
|||||||
@@ -7,13 +7,19 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
1. Здесь не место для вопросов, касающихся компьютерной грамотности и навыков использования ОС
|
Issues - это место для обращений к разработчику.
|
||||||
2. Здесь не место для вопросов "у меня не работает" без технических подробностей
|
Discussions - место для обсуждения вопросов между пользователями.
|
||||||
3. Здесь не место для вопросов "как мне открыть ютуб", "что писать в ...", "перестало открываться".
|
Не тратье время разработчика на ерунду. Вам не будут здесь обьяснять как скопировать, что "писать в", почему сразу же закрывается окно, почему не открывается сайт или госуслуги. Здесь не место обсуждению любых шаманств , т.е. манипуляций без понимания, в стиле 4pda.
|
||||||
4. Здесь не место для обсуждения сборок
|
Пишите только конкретные проблемы на техническом уровне в оригинальном zapret (не в сборках), которые вы заметили, и которые являются или могут являться багами в софте.
|
||||||
5. Вирусов здесь нет. У вас либо чья-то сборка, либо ваш антивирус давно пора отправить на покой. Антивирусы в основном жалуются на upx и windivert, которые убраны НЕ будут. upx - это паковщик для сокращения требуемого места на openwrt, windivert - замена iptables для windows, потенциальный инструмент хакера или компонент зловредной программы, но сам по себе вирусом не является. Не согласны - удаляйте софт. За агрессивные наезды "почему автор распространяет вирусы" молча схватите бан.
|
Или если вы считаете, что ваше обращение обосновано, технически грамотно и по адресу.
|
||||||
|
Все, что будет нарушать эти критерии, может быть молча удалено, закрыто или перенесено в дискуссии на усмотрение разработчика.
|
||||||
|
Если сомневаетесь - пишите лучше сразу в дискуссии.
|
||||||
|
|
||||||
Все означенное обсуждать в дискуссиях или на форумах.
|
Прочитайте для начала docs/quick_start.md или docs/quick_start_windows.md.
|
||||||
При нарушении будет закрываться или конвертироваться в дискуссии.
|
Там обьясняется для кого этот софт, какие требуются знания, почему это не простая волшебная таблетка.
|
||||||
Issue только для обсуждения проблем самого софта. Неработа стратегии или ваше неумение настроить - это ваша проблема, а не проблема софта.
|
|
||||||
Однокнопочные решения дают только сборщики, поэтому "открытие сайта" не является функцией программы, и нет смысла жаловаться, что он не открывается. Но можно это обсудить в дискуссиях. Не захламляйте issues !
|
Вирусов здесь нет. У вас либо чья-то сборка, либо ваш антивирус давно пора отправить на покой. Антивирусы в основном жалуются на upx и windivert, которые убраны НЕ будут. upx - это паковщик для сокращения требуемого места на openwrt, windivert - замена iptables для windows, потенциальный инструмент хакера или компонент зловредной программы, но сам по себе вирусом не является. Не согласны - удаляйте софт. За агрессивные наезды "почему автор распространяет вирусы" молча схватите бан.
|
||||||
|
|
||||||
|
|
||||||
|
Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions.
|
||||||
|
There're also no viruses here. All virus claims and everyting non-technical and non-bugs will be instantly deleted, closed or moved to Discussions.
|
||||||
|
|||||||
+146
-24
@@ -41,12 +41,15 @@ CURL_MAX_TIME_QUIC=${CURL_MAX_TIME_QUIC:-$CURL_MAX_TIME}
|
|||||||
CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2}
|
CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2}
|
||||||
MIN_TTL=${MIN_TTL:-1}
|
MIN_TTL=${MIN_TTL:-1}
|
||||||
MAX_TTL=${MAX_TTL:-12}
|
MAX_TTL=${MAX_TTL:-12}
|
||||||
|
MIN_AUTOTTL_DELTA=${MIN_AUTOTTL_DELTA:-1}
|
||||||
|
MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
|
||||||
USER_AGENT=${USER_AGENT:-Mozilla}
|
USER_AGENT=${USER_AGENT:-Mozilla}
|
||||||
HTTP_PORT=${HTTP_PORT:-80}
|
HTTP_PORT=${HTTP_PORT:-80}
|
||||||
HTTPS_PORT=${HTTPS_PORT:-443}
|
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 +414,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 +813,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 +1073,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 +1106,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 +1125,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 +1165,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 +1206,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 +1233,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 +1277,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 +1286,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
|
||||||
@@ -1256,8 +1332,8 @@ pktws_check_domain_http_bypass_()
|
|||||||
# $2 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
|
# $2 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
|
||||||
# $3 - domain
|
# $3 - domain
|
||||||
|
|
||||||
local ok ttls s f f2 e desync pos fooling frag sec="$2" delta orig splits
|
local ok ttls attls 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'
|
||||||
|
|
||||||
@@ -1268,6 +1344,7 @@ pktws_check_domain_http_bypass_()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||||
|
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||||
need_wssize=1
|
need_wssize=1
|
||||||
for e in '' '--wssize 1:6'; do
|
for e in '' '--wssize 1:6'; do
|
||||||
need_split=
|
need_split=
|
||||||
@@ -1302,25 +1379,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 +1414,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 +1493,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.
|
||||||
for delta in 1 2 3 4 5; do
|
# missing ACK is transmitted in the first data packet of TLS/HTTP proto
|
||||||
|
for delta in $attls; 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 $attls; 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 +1526,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 +1735,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 +1931,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 +2311,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"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -534,3 +534,30 @@ nfqws: ts fooling
|
|||||||
blockcheck: test ts fooling
|
blockcheck: test ts fooling
|
||||||
blockcheck: auto enable tcp timestamps in windows
|
blockcheck: auto enable tcp timestamps in windows
|
||||||
tpws,nfqws: special handling of IP-like hostnames. strip :port from hostname:port
|
tpws,nfqws: special handling of IP-like hostnames. strip :port from hostname:port
|
||||||
|
|
||||||
|
v71.4
|
||||||
|
|
||||||
|
nfqws,tpws: fix possible crashes or high memory usage if hostlist has duplicate hostnames
|
||||||
|
init.d: custom scripts 50-discord-media, 50-stun4all
|
||||||
|
init.d: windivert filters for discord media, stun, wireguard
|
||||||
|
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
|
||||||
|
|
||||||
|
v72.1
|
||||||
|
|
||||||
|
nfqws: --ip-id=seq|seqgroup|rnd|zero
|
||||||
|
blockcheck: MIN_AUTOTTL_DELTA,MAX_AUTOTTL_DELTA
|
||||||
|
init.d: 50-quic4all custom
|
||||||
|
|||||||
+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) ради подробностей.
|
||||||
Но еще лучше будет подбирать такие стратегии, которые ломают минимум.
|
Но еще лучше будет подбирать такие стратегии, которые ломают минимум.
|
||||||
Есть стратегии довольно безобидные, а есть сильно ломающие, которые подходят только для точечного пробития отдельных ресурсов,
|
Есть стратегии довольно безобидные, а есть сильно ломающие, которые подходят только для точечного пробития отдельных ресурсов,
|
||||||
|
|||||||
+95
-19
@@ -1,4 +1,4 @@
|
|||||||
# zapret v71.3
|
# zapret v72.1
|
||||||
|
|
||||||
# SCAMMER WARNING
|
# SCAMMER WARNING
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@ ___
|
|||||||
- [Fake mods](#fake-mods)
|
- [Fake mods](#fake-mods)
|
||||||
- [TCP segmentation](#tcp-segmentation)
|
- [TCP segmentation](#tcp-segmentation)
|
||||||
- [Sequence numbers overlap](#sequence-numbers-overlap)
|
- [Sequence numbers overlap](#sequence-numbers-overlap)
|
||||||
|
- [IP_ID assignment](#ip_id-assignment)
|
||||||
- [ipv6 specific modes](#ipv6-specific-modes)
|
- [ipv6 specific modes](#ipv6-specific-modes)
|
||||||
- [Original modding](#original-modding)
|
- [Original modding](#original-modding)
|
||||||
- [Duplicates](#duplicates)
|
- [Duplicates](#duplicates)
|
||||||
@@ -180,7 +181,8 @@ 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
|
--ip-id=zero|seq|seqgroup|rnd ; ipv4 ip_id assignment scheme
|
||||||
|
--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 +196,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 +245,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 +325,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 +356,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 +415,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).
|
||||||
@@ -383,6 +441,21 @@ All unix OS except Solaris preserve last received data. This is not the case for
|
|||||||
Disorder requires `seqovl` to be less than split position. Otherwise `seqovl` is not possible and will be cancelled.
|
Disorder requires `seqovl` to be less than split position. Otherwise `seqovl` is not possible and will be cancelled.
|
||||||
Method allows to avoid separate fakes. Fakes and real data are mixed.
|
Method allows to avoid separate fakes. Fakes and real data are mixed.
|
||||||
|
|
||||||
|
### IP_ID assignment
|
||||||
|
|
||||||
|
Some DPIs check ipv4 ip_id value. OS normally increment ip_id value every packet. Some anti-DPI software may send fakes or tcp segments with the same ip_id as original causing block trigger.
|
||||||
|
|
||||||
|
Sequental ip_id will be broken in case of sending fakes or additional tcp segments because OS knows nothing about them. But still there are options how to assignt ip_id to generated packets.
|
||||||
|
|
||||||
|
`ip-id` parameter sets ip_id assignment scheme for a desync profile :
|
||||||
|
|
||||||
|
* `seq` (default) : increment ip_id for every next packet. in `multidisorder` case increase ip_id for the number of tcp segments then decrease by 1 every packet.
|
||||||
|
* `seqgroup` : same as `seq` but send fake replacements with the same ip_id as original parts. related only to fake tcp segments with the same size and same sequence as originals.
|
||||||
|
* `rnd` : assign random ip_id
|
||||||
|
* `zero` : always set zero. Linux and BSD will send zero, Windows will replace zero with it's own counter.
|
||||||
|
|
||||||
|
ipv6 header lacks ip_id field, `ip-id` parameter ignored for ipv6.
|
||||||
|
|
||||||
### ipv6 specific modes
|
### ipv6 specific modes
|
||||||
|
|
||||||
`hopbyhop`, `destopt` and `ipfrag1` desync modes (they're not the same as `hopbyhop` fooling !) are ipv6 only. One `hop-by-hop`,
|
`hopbyhop`, `destopt` and `ipfrag1` desync modes (they're not the same as `hopbyhop` fooling !) are ipv6 only. One `hop-by-hop`,
|
||||||
@@ -701,6 +774,9 @@ Set up bridge networking.
|
|||||||
|
|
||||||
### IPTABLES for nfqws
|
### IPTABLES for nfqws
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> Starting from Linux kernel 6.17 there's CONFIG_NETFILTER_XTABLES_LEGACY parameter which is not set by default. Many distributions will likely not turn it on making iptables-legacy non working. This is part of iptables deprecation. However iptables-nft still works because their backend is based on nftables.
|
||||||
|
|
||||||
This is the common way to redirect some traffic to nfqws :
|
This is the common way to redirect some traffic to nfqws :
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -1145,7 +1221,7 @@ If `MODE_FILTER=hostlist` all present lists are passed to **nfqws** or **tpws**.
|
|||||||
If all include lists are empty it works like no include lists exist at all.
|
If all include lists are empty it works like no include lists exist at all.
|
||||||
If you need "all except" mode you dont have to delete zapret-hosts-users.txt. Just make it empty.
|
If you need "all except" mode you dont have to delete zapret-hosts-users.txt. Just make it empty.
|
||||||
|
|
||||||
Subdomains auto apply. For example, "ru" in the list affects "*.ru" .
|
Subdomains auto apply. For example, "ru" in the list affects "\*.ru" .
|
||||||
`^` prefix symbol disables subdomain match.
|
`^` prefix symbol disables subdomain match.
|
||||||
|
|
||||||
**tpws** and **nfqws** automatically reload lists if their modification time or file size is changed.
|
**tpws** and **nfqws** automatically reload lists if their modification time or file size is changed.
|
||||||
@@ -1243,7 +1319,7 @@ Change postnat scheme mark bit
|
|||||||
|
|
||||||
If uncommented pass to zapret only packets marked with this bit
|
If uncommented pass to zapret only packets marked with this bit
|
||||||
|
|
||||||
`#FILTER_MARK_POSTNAT=0x10000000`
|
`#FILTER_MARK=0x10000000`
|
||||||
|
|
||||||
Bit must be set in your own rules.
|
Bit must be set in your own rules.
|
||||||
* iptables - in mangle PREROUTING and mangle OUTPUT before zapret rules (iptables -I _after_ zapret rules application).
|
* iptables - in mangle PREROUTING and mangle OUTPUT before zapret rules (iptables -I _after_ zapret rules application).
|
||||||
|
|||||||
+177
-20
@@ -1,4 +1,4 @@
|
|||||||
# zapret v71.3
|
# zapret v72.1
|
||||||
|
|
||||||
# ВНИМАНИЕ, остерегайтесь мошенников
|
# ВНИМАНИЕ, остерегайтесь мошенников
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@ zapret является свободным и open source.
|
|||||||
- [МОДИФИКАЦИЯ ФЕЙКОВ](#модификация-фейков)
|
- [МОДИФИКАЦИЯ ФЕЙКОВ](#модификация-фейков)
|
||||||
- [TCP СЕГМЕНТАЦИЯ](#tcp-сегментация)
|
- [TCP СЕГМЕНТАЦИЯ](#tcp-сегментация)
|
||||||
- [ПЕРЕКРЫТИЕ SEQUENCE NUMBERS](#перекрытие-sequence-numbers)
|
- [ПЕРЕКРЫТИЕ SEQUENCE NUMBERS](#перекрытие-sequence-numbers)
|
||||||
|
- [НАЗНАЧЕНИЕ IP_ID](#назначение-ip_id)
|
||||||
- [СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6](#специфические-режимы-ipv6)
|
- [СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6](#специфические-режимы-ipv6)
|
||||||
- [МОДИФИКАЦИЯ ОРИГИНАЛА](#модификация-оригинала)
|
- [МОДИФИКАЦИЯ ОРИГИНАЛА](#модификация-оригинала)
|
||||||
- [ДУБЛИКАТЫ](#дубликаты)
|
- [ДУБЛИКАТЫ](#дубликаты)
|
||||||
@@ -43,6 +44,7 @@ zapret является свободным и open source.
|
|||||||
- [IPTABLES ДЛЯ NFQWS](#iptables-для-nfqws)
|
- [IPTABLES ДЛЯ NFQWS](#iptables-для-nfqws)
|
||||||
- [NFTABLES ДЛЯ NFQWS](#nftables-для-nfqws)
|
- [NFTABLES ДЛЯ NFQWS](#nftables-для-nfqws)
|
||||||
- [FLOW OFFLOADING](#flow-offloading)
|
- [FLOW OFFLOADING](#flow-offloading)
|
||||||
|
- [ОСОБЕННОСТИ ЖЕЛЕЗОК](#особенности-железок)
|
||||||
- [ДУРЕНИЕ СО СТОРОНЫ СЕРВЕРА](#дурение-со-стороны-сервера)
|
- [ДУРЕНИЕ СО СТОРОНЫ СЕРВЕРА](#дурение-со-стороны-сервера)
|
||||||
- [tpws](#tpws)
|
- [tpws](#tpws)
|
||||||
- [TCP СЕГМЕНТАЦИЯ В TPWS](#tcp-сегментация-в-tpws)
|
- [TCP СЕГМЕНТАЦИЯ В TPWS](#tcp-сегментация-в-tpws)
|
||||||
@@ -206,7 +208,8 @@ 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
|
--ip-id=seq|seqgroup|rnd|zero ; режим назначения ip_id для генерированных пакетов
|
||||||
|
--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
|
||||||
@@ -217,25 +220,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. поддомены автоматически учитываются, если хост не начинается с '^'.
|
||||||
@@ -275,6 +282,13 @@ dvtws, собираемый из тех же исходников (см. [док
|
|||||||
невозможна. Если вы потом удалите файл, и у процесса не будет прав на создание файла в его директории, лог больше не
|
невозможна. Если вы потом удалите файл, и у процесса не будет прав на создание файла в его директории, лог больше не
|
||||||
будет вестись. Вместо удаления лучше использовать truncate. В шелле это можно сделать через команду ": >filename"
|
будет вестись. Вместо удаления лучше использовать truncate. В шелле это можно сделать через команду ": >filename"
|
||||||
|
|
||||||
|
Многие параметры, загружающие двоичные данные из файлов, поддерживают загрузку из hex-строки или из файла.
|
||||||
|
hex строка начинается с "0x". Имя файла можно писать как есть или использовать префикс "@".
|
||||||
|
Если перед префиксом "@" указано "+<число>", то это означает смещение полезных данных внутри файла.
|
||||||
|
Файл может загружаться целиком с нулевой позиции, к нему могут применяться модификации, требующие полного файла (TLS),
|
||||||
|
но передача пойдет с позиции offset. offset должен быть меньше длины файла. Если к блоку данных применяется мод,
|
||||||
|
который уменьшает размер данных, и offset окажется не меньше новой длины данных, будет ошибка.
|
||||||
|
|
||||||
### АТАКА ДЕСИНХРОНИЗАЦИИ DPI
|
### АТАКА ДЕСИНХРОНИЗАЦИИ DPI
|
||||||
|
|
||||||
Суть ее в следующем. Берется оригинальный запрос, модифицируется, добавляется поддельная информация (фейки)
|
Суть ее в следующем. Берется оригинальный запрос, модифицируется, добавляется поддельная информация (фейки)
|
||||||
@@ -370,6 +384,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.
|
||||||
@@ -402,17 +420,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 убирает часть фейков.
|
||||||
|
|
||||||
Для определения позиций нарезки используются маркеры.
|
Для определения позиций нарезки используются маркеры.
|
||||||
|
|
||||||
* **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала.
|
* **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала.
|
||||||
@@ -477,6 +539,27 @@ Windows оставляет старые данные, поэтому disorder с
|
|||||||
В варианте `disorder` допустимо применение всех вариантов маркеров.
|
В варианте `disorder` допустимо применение всех вариантов маркеров.
|
||||||
Они автоматически нормализуются к текущему пакету в серии. Можно сплитать на `midsld` и делать seqovl на `midsld-1`.
|
Они автоматически нормализуются к текущему пакету в серии. Можно сплитать на `midsld` и делать seqovl на `midsld-1`.
|
||||||
|
|
||||||
|
### НАЗНАЧЕНИЕ IP_ID
|
||||||
|
|
||||||
|
Некоторые DPI секут поле ipv4 заголовка ip_id. Защита заключается в распознавании нехарактерного для разных ОС порядка назначения ip_id,
|
||||||
|
но характерного для некоторого anti-DPI софта. Обычно ОС инкрементируют ip_id для каждого следующего пакета.
|
||||||
|
Например, на ТСПУ повторение ненулевых ip_id фейка и не фейка вызывает триггер блока на диапазонах IP `googlevideo.com`.
|
||||||
|
|
||||||
|
Если отсылаются фейки или дополнительные tcp сегменты, то в любом случае последовательность будет нарушена, поскольку ОС ничего не будет знать о всунутых фейках
|
||||||
|
и не увеличит свой счетчик ip_id на количество фейков или дополнительных tcp сегментов.
|
||||||
|
Чтобы сохранить последовательность, потребовалось бы перехватывать все соединение до конца, что очень затратно по ресурсам.
|
||||||
|
Поэтому после отработки серии генерированных пакетов ip_id возвращается к тому значению, о котором знает ОС.
|
||||||
|
|
||||||
|
Параметр `ip-id` относится к профилю и задает режим назначения ip_id при отсылке генерированных в nfqws пакетов.
|
||||||
|
|
||||||
|
* `seq` (по умолчанию) : взять последний ip_id реального пакета. последующие генерированыне пакеты получают увеличенные на 1 ip_id, кроме случая `multidisorder`.
|
||||||
|
для `multidisorder` в пределах сегментов, где есть сплит-позиции, значение ip_id увеличивается на количество частей, затем уменьшается на 1 с каждой отосланной частью.
|
||||||
|
* `seqgroup` : то же, что и `seq`, но фейки того же размера, что и оригинальные сегменты, маскирующиеся под оригинал получают те же ip_id.
|
||||||
|
* `rnd` : всем генерированным пакетам назначать случайный ip_id
|
||||||
|
* `zero` : всем генерированным пакетам назначать ip_id=0 . в этом случае Linux и BSD отошлют 0, Windows назначит последовательные ip_id всем пакетам (тем самым автоматически решается проблема сбоя счетчика пакетов).
|
||||||
|
|
||||||
|
В заголовках ipv6 поле ip_id отсутствует, параметр игнорируется для ipv6.
|
||||||
|
|
||||||
### СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6
|
### СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6
|
||||||
|
|
||||||
Режимы десинхронизации `hopbyhop`, `destopt` и `ipfrag1` (не путать с fooling !) относятся только к ipv6 и заключается
|
Режимы десинхронизации `hopbyhop`, `destopt` и `ipfrag1` (не путать с fooling !) относятся только к ipv6 и заключается
|
||||||
@@ -782,7 +865,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
|
||||||
@@ -817,6 +900,9 @@ wireless extensions считаются deprecated и на новых ядрах
|
|||||||
|
|
||||||
### IPTABLES ДЛЯ NFQWS
|
### IPTABLES ДЛЯ NFQWS
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> Начиная с ядер Linux 6.17 присутствует параметр конфигурации ядра CONFIG_NETFILTER_XTABLES_LEGACY, который по умолчанию в дистрибутиве может быть "not set". Отсутствие этой настройки выключает iptables-legacy. Это часть процесса депрекации iptables. Тем не менее iptables-nft будут работать, поскольку используют backend nftables.
|
||||||
|
|
||||||
iptables для задействования атаки на первые пакеты данных в tcp соединении :
|
iptables для задействования атаки на первые пакеты данных в tcp соединении :
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -931,6 +1017,73 @@ iptables target `FLOWOFFLOAD` - это проприетарное изобрет
|
|||||||
Управление offload в nftables реализовано в базовом ядре linux без патчей.
|
Управление offload в nftables реализовано в базовом ядре linux без патчей.
|
||||||
nftables - единственный способ включения offload на классическом Linux.
|
nftables - единственный способ включения offload на классическом Linux.
|
||||||
|
|
||||||
|
### ОСОБЕННОСТИ ЖЕЛЕЗОК
|
||||||
|
|
||||||
|
На устройствах mediatek замечены 2 проблемы.
|
||||||
|
|
||||||
|
Драйвер mediatek ethernet отбрасывает tcp и udp пакеты с неверной чексуммой на аппаратном уровне, это не отключается.
|
||||||
|
Как следствие не будет работать fooling badsum через роутер, но будет с него.
|
||||||
|
|
||||||
|
Другая проблема mediatek, затрагивающая как ethernet, так и wireless, проявляется на udp, когда включен offload rx-gro-list.
|
||||||
|
Пока отсутствует nfqueue, все хорошо. Как только nfqueue появляется, часть пакетов выпадает.
|
||||||
|
Особенно заметно это проявляется на дурении QUIC с kyber.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>shell код лечения</b></summary>
|
||||||
|
|
||||||
|
```
|
||||||
|
append_separator_list()
|
||||||
|
{
|
||||||
|
# $1 - var name to receive result
|
||||||
|
# $2 - separator
|
||||||
|
# $3 - quoter
|
||||||
|
# $4,$5,... - elements
|
||||||
|
local _var="$1" sep="$2" quo="$3" i
|
||||||
|
|
||||||
|
eval i="\$$_var"
|
||||||
|
shift; shift; shift
|
||||||
|
while [ -n "$1" ]; do
|
||||||
|
if [ -n "$i" ] ; then
|
||||||
|
i="$i$sep$quo$1$quo"
|
||||||
|
else
|
||||||
|
i="$quo$1$quo"
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
eval $_var="\$i"
|
||||||
|
}
|
||||||
|
resolve_lower_devices()
|
||||||
|
{
|
||||||
|
# $1 - bridge interface name
|
||||||
|
[ -d "/sys/class/net/$1" ] && {
|
||||||
|
find "/sys/class/net/$1" -follow -maxdepth 1 -name "lower_*" |
|
||||||
|
{
|
||||||
|
local l lower lowers
|
||||||
|
while read lower; do
|
||||||
|
lower="$(basename "$lower")"
|
||||||
|
l="${lower#lower_*}"
|
||||||
|
[ "$l" != "$lower" ] && append_separator_list lowers ' ' '' "$l"
|
||||||
|
done
|
||||||
|
printf "$lowers"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# it breaks nfqueue
|
||||||
|
lans=$(resolve_lower_devices br-lan)
|
||||||
|
for int in $lans; do
|
||||||
|
ethtool -K $int rx-gro-list off
|
||||||
|
done
|
||||||
|
```
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Этот код нужно вызывать после вставания интерфейса LAN, когда все bridge members уже занесены в bridge.
|
||||||
|
Можно использовать хук в `/etc/hotplug.d/iface`. Должен быть установлен `ethtool`.
|
||||||
|
|
||||||
|
Проблемы mediatek были подтверждены на MT7621 (TP-Link Archer C6U v1) и MT7981 (Xiaomi AX3000T).
|
||||||
|
Другие чипсеты могут быть так же подвержены проблеме, а могут и не быть. Более широкой статистики нет.
|
||||||
|
|
||||||
|
|
||||||
### ДУРЕНИЕ СО СТОРОНЫ СЕРВЕРА
|
### ДУРЕНИЕ СО СТОРОНЫ СЕРВЕРА
|
||||||
|
|
||||||
Это тоже возможно.
|
Это тоже возможно.
|
||||||
@@ -1510,7 +1663,7 @@ LISTS_RELOAD=- отключает перезагрузку листов.
|
|||||||
Файл есть, но несмотря на это дурится все, кроме exclude.
|
Файл есть, но несмотря на это дурится все, кроме exclude.
|
||||||
Если вам нужен именно такой режим - не обязательно удалять `zapret-hosts-users.txt`. Достаточно сделать его пустым.
|
Если вам нужен именно такой режим - не обязательно удалять `zapret-hosts-users.txt`. Достаточно сделать его пустым.
|
||||||
|
|
||||||
Поддомены учитываются автоматически. Например, строчка "ru" вносит в список "*.ru". Строчка "*.ru" в списке не сработает.
|
Поддомены учитываются автоматически. Например, строчка "ru" вносит в список "\*.ru". Строчка "\*.ru" в списке не сработает.
|
||||||
Можно использовать символ `^` в начале хоста, чтобы отказаться от автоматического учета поддоменов.
|
Можно использовать символ `^` в начале хоста, чтобы отказаться от автоматического учета поддоменов.
|
||||||
|
|
||||||
Список доменов РКН может быть получен скриптами
|
Список доменов РКН может быть получен скриптами
|
||||||
@@ -1673,6 +1826,10 @@ 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
|
||||||
|
MIN_TTL,MAX_TTL - пределы тестов с TTL. MAX_TTL=0 отключает тесты.
|
||||||
|
MIN_AUTOTTL_DELTA,MAX_AUTOTTL_DELTA - пределы тестов с autottl по дельте. MAX_AUTOTTL_DELTA=0 отключает тесты.
|
||||||
|
SIMULATE=1 - включить режим симуляции для отладки логики скрипта. отключаются реальные запросы через curl, заменяются рандомным результатом.
|
||||||
|
SIM_SUCCESS_RATE=<percent> - вероятность успеха симуляции в процентах
|
||||||
```
|
```
|
||||||
|
|
||||||
Пример запуска с переменными:\
|
Пример запуска с переменными:\
|
||||||
@@ -1848,7 +2005,7 @@ nfqws начнет получать адреса пакетов из локал
|
|||||||
`DESYNC_MARK_POSTNAT=0x20000000`
|
`DESYNC_MARK_POSTNAT=0x20000000`
|
||||||
|
|
||||||
***Если раскоментировано, пометка пакетов, которые должны быть обработаны zapret.***\
|
***Если раскоментировано, пометка пакетов, которые должны быть обработаны zapret.***\
|
||||||
`#FILTER_MARK_POSTNAT=0x10000000`
|
`#FILTER_MARK=0x10000000`
|
||||||
|
|
||||||
Бит должен быть установлен вашими собственными правилами.
|
Бит должен быть установлен вашими собственными правилами.
|
||||||
* Для iptables - в цепочках mangle PREROUTING и mangle OUTPUT перед правилами zapret (iptables -I _после_ применения правил zapret).
|
* Для iptables - в цепочках mangle PREROUTING и mangle OUTPUT перед правилами zapret (iptables -I _после_ применения правил zapret).
|
||||||
|
|||||||
+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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# 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 :
|
||||||
|
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}"
|
||||||
|
|
||||||
|
alloc_dnum DNUM_DISCORD_MEDIA
|
||||||
|
alloc_qnum QNUM_DISCORD_MEDIA
|
||||||
|
|
||||||
|
zapret_custom_daemons()
|
||||||
|
{
|
||||||
|
# $1 - 1 - add, 0 - stop
|
||||||
|
|
||||||
|
local opt="--qnum=$QNUM_DISCORD_MEDIA $NFQWS_OPT_DESYNC_DISCORD_MEDIA"
|
||||||
|
do_nfqws $1 $DNUM_DISCORD_MEDIA "$opt"
|
||||||
|
}
|
||||||
|
zapret_custom_firewall()
|
||||||
|
{
|
||||||
|
# $1 - 1 - run, 0 - stop
|
||||||
|
|
||||||
|
local DISABLE_IPV6=1
|
||||||
|
local port_range=$(replace_char - : $DISCORD_MEDIA_PORT_RANGE)
|
||||||
|
local f="-p udp --dport $port_range -m u32 --u32"
|
||||||
|
# this is simplified test to skip writing monstrous rule. instead of checking 64 bytes for zeroes only check 2 dwords for zero
|
||||||
|
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x52&&0>>22&0x3C@8=0x00010046&&0>>22&0x3C@16=0&&0>>22&0x3C@76=0" '' $QNUM_DISCORD_MEDIA
|
||||||
|
}
|
||||||
|
zapret_custom_firewall_nft()
|
||||||
|
{
|
||||||
|
# stop logic is not required
|
||||||
|
|
||||||
|
local DISABLE_IPV6=1
|
||||||
|
local f="udp dport $DISCORD_MEDIA_PORT_RANGE udp length == 82 @ih,0,32 0x00010046 @ih,64,128 0x00000000000000000000000000000000 @ih,192,128 0x00000000000000000000000000000000 @ih,320,128 0x00000000000000000000000000000000 @ih,448,128 0x00000000000000000000000000000000"
|
||||||
|
nft_fw_nfqws_post "$f" '' $QNUM_DISCORD_MEDIA
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# this custom script runs desync to all IETF QUIC initials
|
||||||
|
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||||
|
|
||||||
|
# can override in config :
|
||||||
|
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---dpi-desync=fake --dpi-desync-repeats=2}"
|
||||||
|
|
||||||
|
alloc_dnum DNUM_QUIC4ALL
|
||||||
|
alloc_qnum QNUM_QUIC4ALL
|
||||||
|
|
||||||
|
zapret_custom_daemons()
|
||||||
|
{
|
||||||
|
# $1 - 1 - add, 0 - stop
|
||||||
|
|
||||||
|
local opt="--qnum=$QNUM_QUIC4ALL $NFQWS_OPT_DESYNC_QUIC"
|
||||||
|
do_nfqws $1 $DNUM_QUIC4ALL "$opt"
|
||||||
|
}
|
||||||
|
zapret_custom_firewall()
|
||||||
|
{
|
||||||
|
# $1 - 1 - run, 0 - stop
|
||||||
|
|
||||||
|
local f='-p udp -m u32 --u32'
|
||||||
|
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=264:65535&&0>>22&0x3C@8>>28=0xC&&0>>22&0x3C@9=0x00000001" "$f 44>>16=264:65535&&48>>28=0xC&&49=0x00000001" $QNUM_QUIC4ALL
|
||||||
|
}
|
||||||
|
zapret_custom_firewall_nft()
|
||||||
|
{
|
||||||
|
# stop logic is not required
|
||||||
|
|
||||||
|
local f="udp length >= 264 @ih,0,4 0xC @ih,8,32 0x00000001"
|
||||||
|
nft_fw_nfqws_post "$f" "$f" $QNUM_QUIC4ALL
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# 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 :
|
||||||
|
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---dpi-desync=fake --dpi-desync-repeats=2}"
|
||||||
|
|
||||||
|
alloc_dnum DNUM_STUN4ALL
|
||||||
|
alloc_qnum QNUM_STUN4ALL
|
||||||
|
|
||||||
|
zapret_custom_daemons()
|
||||||
|
{
|
||||||
|
# $1 - 1 - add, 0 - stop
|
||||||
|
|
||||||
|
local opt="--qnum=$QNUM_STUN4ALL $NFQWS_OPT_DESYNC_STUN"
|
||||||
|
do_nfqws $1 $DNUM_STUN4ALL "$opt"
|
||||||
|
}
|
||||||
|
zapret_custom_firewall()
|
||||||
|
{
|
||||||
|
# $1 - 1 - run, 0 - stop
|
||||||
|
|
||||||
|
local f='-p udp -m u32 --u32'
|
||||||
|
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=28:65535&&0>>22&0x3C@12=0x2112A442&&0>>22&0x3C@8&0xC0000003=0" "$f 44>>16=28:65535&&52=0x2112A442&&48&0xC0000003=0" $QNUM_STUN4ALL
|
||||||
|
}
|
||||||
|
zapret_custom_firewall_nft()
|
||||||
|
{
|
||||||
|
# stop logic is not required
|
||||||
|
|
||||||
|
local f="udp length >= 28 @ih,32,32 0x2112A442 @ih,0,2 0 @ih,30,2 0"
|
||||||
|
nft_fw_nfqws_post "$f" "$f" $QNUM_STUN4ALL
|
||||||
|
}
|
||||||
@@ -1,7 +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: @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
|
||||||
@@ -25,6 +27,6 @@ zapret_custom_firewall_nft()
|
|||||||
{
|
{
|
||||||
# stop logic is not required
|
# stop logic is not required
|
||||||
|
|
||||||
local f="udp length 156 @th,64,32 0x01000000"
|
local f="udp length 156 @ih,0,32 0x01000000"
|
||||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
|
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws.
|
||||||
|
Задействуются через `winws --wf-raw-part=@filename`. Может быть несколько частичных фильтров. Они могут сочетаться с --wf-tcp и --wf-udp.
|
||||||
|
Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики.
|
||||||
|
Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку.
|
||||||
|
Дофильтрация производится силами winws.
|
||||||
|
|
||||||
|
Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language
|
||||||
|
Пример инстанса для пробития медиапотоков в 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-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.
|
||||||
|
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.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
outbound and
|
||||||
|
udp.PayloadLength>=256 and
|
||||||
|
udp.Payload[0]>=0xC0 and udp.Payload[0]<0xD0 and
|
||||||
|
udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1
|
||||||
@@ -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);
|
||||||
|
|||||||
+445
-86
@@ -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,43 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef BSD
|
static uint16_t IP4_IP_ID_FIX(const struct ip *ip, t_ip_id_mode mode)
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
return ip ? ip->ip_id ? ip->ip_id : (uint16_t)random() : 0;
|
if (ip)
|
||||||
|
{
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case IPID_RND:
|
||||||
|
return (uint16_t)(random()%0xFFFF + 1);
|
||||||
|
case IPID_SEQ:
|
||||||
|
case IPID_SEQ_GROUP:
|
||||||
|
return ip->ip_id ? ip->ip_id : (uint16_t)random();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#define IP4_IP_ID_NEXT(ip_id) net16_add(ip_id,+1)
|
}
|
||||||
#define IP4_IP_ID_PREV(ip_id) net16_add(ip_id,-1)
|
return 0;
|
||||||
#else
|
}
|
||||||
// in linux kernel sets increasing ip_id if it's zero
|
static uint16_t IP4_IP_ID_ADD(uint16_t ip_id, uint16_t inc, t_ip_id_mode mode)
|
||||||
#define IP4_IP_ID_FIX(x) 0
|
{
|
||||||
#define IP4_IP_ID_NEXT(ip_id) ip_id
|
switch(mode)
|
||||||
#define IP4_IP_ID_PREV(ip_id) ip_id
|
{
|
||||||
#endif
|
case IPID_RND:
|
||||||
|
return (uint16_t)(random()%0xFFFF + 1);;
|
||||||
|
case IPID_SEQ_GROUP:
|
||||||
|
case IPID_SEQ:
|
||||||
|
if (ip_id)
|
||||||
|
{
|
||||||
|
ip_id = net16_add(ip_id, inc);
|
||||||
|
if (!ip_id) ip_id = net16_add(ip_id, ((int16_t)inc) < 0 ? -1 : 1); // do not allow zero
|
||||||
|
}
|
||||||
|
return ip_id;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#define IP4_IP_ID_NEXT(ip_id,mode) IP4_IP_ID_ADD(ip_id,+1,mode)
|
||||||
|
#define IP4_IP_ID_PREV(ip_id,mode) IP4_IP_ID_ADD(ip_id,-1,mode)
|
||||||
|
|
||||||
|
|
||||||
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
|
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
|
||||||
@@ -887,7 +914,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
|
||||||
@@ -976,7 +1003,7 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
|
|||||||
timestamps = tcp_find_timestamps(dis->tcp);
|
timestamps = tcp_find_timestamps(dis->tcp);
|
||||||
sack = tcp_has_sack(dis->tcp);
|
sack = tcp_has_sack(dis->tcp);
|
||||||
nmss = tcp_find_mss(dis->tcp);
|
nmss = tcp_find_mss(dis->tcp);
|
||||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
ip_id = IP4_IP_ID_FIX(dis->ip,dp->ip_id_mode);
|
||||||
|
|
||||||
len = sizeof(pkt);
|
len = sizeof(pkt);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
|
||||||
@@ -1046,7 +1073,7 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
|
|||||||
|
|
||||||
if (dp->dup_fooling_mode)
|
if (dp->dup_fooling_mode)
|
||||||
{
|
{
|
||||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
ip_id = IP4_IP_ID_FIX(dis->ip,dp->ip_id_mode);
|
||||||
|
|
||||||
len = sizeof(pkt);
|
len = sizeof(pkt);
|
||||||
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
|
if (!prepare_udp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst,
|
||||||
@@ -1107,8 +1134,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;
|
||||||
@@ -1329,7 +1356,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
}
|
}
|
||||||
pkt1_len = sizeof(pkt1);
|
pkt1_len = sizeof(pkt1);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_ACK, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, SCALE_NONE, timestamps,
|
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_ACK, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, SCALE_NONE, timestamps,
|
||||||
DF,ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
|
DF, ttl_orig, IP4_TOS(dis->ip), IP4_IP_ID_FIX(dis->ip,dp->ip_id_mode), IP6_FLOW(dis->ip6),
|
||||||
FOOL_NONE, 0, 0, 0, NULL, 0, pkt1, &pkt1_len))
|
FOOL_NONE, 0, 0, 0, NULL, 0, pkt1, &pkt1_len))
|
||||||
{
|
{
|
||||||
DLOG_ERR("cannot prepare split SYNACK ACK part\n");
|
DLOG_ERR("cannot prepare split SYNACK ACK part\n");
|
||||||
@@ -1365,6 +1392,10 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
bSack = tcp_has_sack(dis->tcp);
|
bSack = tcp_has_sack(dis->tcp);
|
||||||
nmss = tcp_find_mss(dis->tcp);
|
nmss = tcp_find_mss(dis->tcp);
|
||||||
|
|
||||||
|
uint16_t ip_id=0;
|
||||||
|
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id;
|
||||||
|
if (!ip_id) ip_id = IP4_IP_ID_FIX(dis->ip,dp->ip_id_mode);
|
||||||
|
|
||||||
if (!replay)
|
if (!replay)
|
||||||
{
|
{
|
||||||
if (tcp_syn_segment(dis->tcp))
|
if (tcp_syn_segment(dis->tcp))
|
||||||
@@ -1374,7 +1405,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
case DESYNC_SYNACK:
|
case DESYNC_SYNACK:
|
||||||
pkt1_len = sizeof(pkt1);
|
pkt1_len = sizeof(pkt1);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, TH_SYN | TH_ACK, 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_SYN | TH_ACK, 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))
|
||||||
{
|
{
|
||||||
@@ -1398,11 +1429,12 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
}
|
}
|
||||||
pkt1_len = sizeof(pkt1);
|
pkt1_len = sizeof(pkt1);
|
||||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, bSack, nmss, 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, bSack, nmss, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||||
DF,ttl_orig,IP4_TOS(dis->ip),IP4_IP_ID_FIX(dis->ip),IP6_FLOW(dis->ip6),
|
DF, ttl_orig, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
|
||||||
0, 0, 0, 0, dp->fake_syndata, dp->fake_syndata_size, pkt1, &pkt1_len))
|
0, 0, 0, 0, dp->fake_syndata, dp->fake_syndata_size, pkt1, &pkt1_len))
|
||||||
{
|
{
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
}
|
}
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
DLOG("sending SYN with fake data : ");
|
DLOG("sending SYN with fake data : ");
|
||||||
hexdump_limited_dlog(dp->fake_syndata, dp->fake_syndata_size, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(dp->fake_syndata, dp->fake_syndata_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))
|
||||||
@@ -1429,7 +1461,7 @@ 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;
|
|
||||||
bool bHaveHost = false, bHostIsIp = false;
|
bool bHaveHost = false, bHostIsIp = false;
|
||||||
t_l7proto l7proto = UNKNOWN;
|
t_l7proto l7proto = UNKNOWN;
|
||||||
|
|
||||||
@@ -1619,6 +1651,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
{
|
{
|
||||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||||
autottl_rediscover(ctrack_replay, dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, ifout);
|
autottl_rediscover(ctrack_replay, dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, ifout);
|
||||||
|
ip_id = IP4_IP_ID_FIX(dis->ip,dp->ip_id_mode);
|
||||||
// re-evaluate start/cutoff limiters
|
// re-evaluate start/cutoff limiters
|
||||||
if (replay)
|
if (replay)
|
||||||
{
|
{
|
||||||
@@ -1813,6 +1846,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 +1926,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 +1948,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,dp->ip_id_mode);
|
||||||
|
if (dp->tcp_mod.seq) sequence += fake_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bFake = true;
|
bFake = true;
|
||||||
@@ -1895,7 +1978,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 +1991,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,dp->ip_id_mode);
|
||||||
bFake = true;
|
bFake = true;
|
||||||
break;
|
break;
|
||||||
case DESYNC_HOPBYHOP:
|
case DESYNC_HOPBYHOP:
|
||||||
@@ -1916,6 +2000,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 +2032,186 @@ 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,dp->ip_id_mode);
|
||||||
|
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;
|
||||||
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP) ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
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,dp->ip_id_mode);
|
||||||
|
if (pos_split_host) ip_id_after_host = IP4_IP_ID_NEXT(ip_id_after_host,dp->ip_id_mode);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
|
||||||
|
{
|
||||||
|
if (dis->ip) ((struct ip*)pkt2)->ip_id = ip_id;
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
|
||||||
|
{
|
||||||
|
ip_id_after_host = ip_id;
|
||||||
|
if (dis->ip) ((struct ip*)pkt3)->ip_id = ip_id;
|
||||||
|
}
|
||||||
|
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,dp->ip_id_mode);
|
||||||
|
|
||||||
|
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 +2219,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 +2242,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;
|
||||||
}
|
}
|
||||||
@@ -1996,7 +2261,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
fooling_orig, 0, 0, 0,
|
fooling_orig, 0, 0, 0,
|
||||||
seg, seg_len, pkt1, &pkt1_len))
|
seg, seg_len, 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,dp->ip_id_mode);
|
||||||
DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ", i + 1, from, to - 1, to - from, seqovl);
|
DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ", i + 1, from, to - 1, to - from, 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))
|
||||||
@@ -2017,17 +2282,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, dp->ip_id_mode);
|
||||||
|
|
||||||
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 +2315,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 +2325,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;
|
||||||
}
|
}
|
||||||
@@ -2066,7 +2339,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
fooling_orig, 0, 0, 0,
|
fooling_orig, 0, 0, 0,
|
||||||
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);
|
ip_id = IP4_IP_ID_PREV(ip_id,dp->ip_id_mode);
|
||||||
DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ", i + 2, from, to - 1, to - from, seqovl);
|
DLOG("sending multisplit part %d %zu-%zu len=%zu seqovl=%u : ", i + 2, from, to - 1, to - from, 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))
|
||||||
@@ -2074,32 +2347,44 @@ 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,dp->ip_id_mode);
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
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 +2394,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 +2410,15 @@ 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)
|
||||||
|
{
|
||||||
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP) ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
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,27 +2426,34 @@ 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);
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
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 (order <= 1)
|
||||||
|
{
|
||||||
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
|
||||||
|
{
|
||||||
if (dis->ip) ((struct ip*)fakeseg2)->ip_id = ip_id;
|
if (dis->ip) ((struct ip*)fakeseg2)->ip_id = ip_id;
|
||||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
}
|
||||||
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)
|
||||||
|
{
|
||||||
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,
|
||||||
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, fakeseg, &seg_len))
|
pat, split_pos, fakeseg, &seg_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP) ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
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 +2465,56 @@ 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);
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
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 (order <= 2)
|
||||||
|
{
|
||||||
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
|
||||||
|
{
|
||||||
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
}
|
||||||
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 = 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 +2522,17 @@ 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)
|
||||||
|
{
|
||||||
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP) ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
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 +2543,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;
|
||||||
}
|
}
|
||||||
@@ -2241,7 +2562,7 @@ 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_NEXT(ip_id);
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
DLOG("sending 1st tcp segment 0-%zu len=%zu seqovl=%u : ", split_pos - 1, split_pos, seqovl);
|
DLOG("sending 1st tcp segment 0-%zu len=%zu seqovl=%u : ", split_pos - 1, 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))
|
||||||
@@ -2259,20 +2580,28 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (order <= 1)
|
||||||
|
{
|
||||||
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
|
||||||
|
{
|
||||||
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
||||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
}
|
||||||
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);
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP) ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
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))
|
||||||
@@ -2284,31 +2613,40 @@ 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, dis->len_payload - split_pos, pkt1, &pkt1_len))
|
dis->data_payload + split_pos, dis->len_payload - split_pos, 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,dp->ip_id_mode);
|
||||||
DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ", split_pos, dis->len_payload - 1, dis->len_payload - split_pos);
|
||||||
hexdump_limited_dlog(dis->data_payload + split_pos, dis->len_payload - split_pos, PKTDATA_MAXDUMP); DLOG("\n");
|
hexdump_limited_dlog(dis->data_payload + split_pos, dis->len_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 (order <= 2)
|
||||||
|
{
|
||||||
|
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
|
||||||
|
{
|
||||||
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
||||||
|
ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
}
|
||||||
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)
|
||||||
|
goto unsplitted_part;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
@@ -2341,6 +2679,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
|
||||||
|
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
|
||||||
return VERDICT_DROP;
|
return VERDICT_DROP;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -2356,6 +2696,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,dp->ip_id_mode);
|
||||||
|
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 +2739,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 +2867,10 @@ 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=0;
|
||||||
|
|
||||||
|
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id;
|
||||||
|
if (!ip_id) ip_id = IP4_IP_ID_FIX(dis->ip,dp->ip_id_mode);
|
||||||
|
|
||||||
if (IsQUICInitial(dis->data_payload, dis->len_payload))
|
if (IsQUICInitial(dis->data_payload, dis->len_payload))
|
||||||
{
|
{
|
||||||
@@ -2765,6 +3119,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
{
|
{
|
||||||
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
|
||||||
autottl_rediscover(ctrack_replay, dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, ifout);
|
autottl_rediscover(ctrack_replay, dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, ifout);
|
||||||
|
ip_id = IP4_IP_ID_FIX(dis->ip,dp->ip_id_mode);
|
||||||
// re-evaluate start/cutoff limiters
|
// re-evaluate start/cutoff limiters
|
||||||
if (replay)
|
if (replay)
|
||||||
{
|
{
|
||||||
@@ -2856,27 +3211,31 @@ 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,dp->ip_id_mode);
|
||||||
}
|
}
|
||||||
bFake = true;
|
bFake = true;
|
||||||
}
|
}
|
||||||
@@ -2911,7 +3270,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 +3295,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,11 +3314,9 @@ 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
|
|
||||||
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_udp && dp->desync_ipfrag_pos_udp < dis->transport_len) ? dp->desync_ipfrag_pos_udp : sizeof(struct udphdr);
|
size_t ipfrag_pos = (dp->desync_ipfrag_pos_udp && dp->desync_ipfrag_pos_udp < dis->transport_len) ? dp->desync_ipfrag_pos_udp : sizeof(struct udphdr);
|
||||||
|
|
||||||
@@ -2992,6 +3349,8 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
|
|||||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
|
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
|
||||||
goto send_orig;
|
goto send_orig;
|
||||||
|
|
||||||
|
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
|
||||||
|
|
||||||
return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL);
|
return ct_new_postnat_fix(ctrack, dis->ip, dis->ip6, NULL);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
+467
-154
@@ -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,150 @@ 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"
|
" --ip-id=zero|seq|seqgroup|rnd\t\t\t\t; ipv4 ip_id assignment scheme\n"
|
||||||
"\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n"
|
" --dpi-desync=[<mode0>,]<mode>[,<mode2>]\t\t; try to desync dpi state. modes :\n"
|
||||||
"\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper\n"
|
"\t\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\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 +1895,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 +1909,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
|
||||||
}
|
}
|
||||||
@@ -1752,6 +1960,7 @@ enum opt_indices {
|
|||||||
IDX_HOSTNOSPACE,
|
IDX_HOSTNOSPACE,
|
||||||
IDX_DOMCASE,
|
IDX_DOMCASE,
|
||||||
IDX_METHODEOL,
|
IDX_METHODEOL,
|
||||||
|
IDX_IP_ID,
|
||||||
IDX_DPI_DESYNC,
|
IDX_DPI_DESYNC,
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
IDX_DPI_DESYNC_FWMARK,
|
IDX_DPI_DESYNC_FWMARK,
|
||||||
@@ -1789,12 +1998,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 +2054,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,
|
||||||
@@ -1878,6 +2093,7 @@ static const struct option long_options[] = {
|
|||||||
[IDX_HOSTNOSPACE] = {"hostnospace", no_argument, 0, 0},
|
[IDX_HOSTNOSPACE] = {"hostnospace", no_argument, 0, 0},
|
||||||
[IDX_DOMCASE] = {"domcase", no_argument, 0, 0},
|
[IDX_DOMCASE] = {"domcase", no_argument, 0, 0},
|
||||||
[IDX_METHODEOL] = {"methodeol", no_argument, 0, 0},
|
[IDX_METHODEOL] = {"methodeol", no_argument, 0, 0},
|
||||||
|
[IDX_IP_ID] = {"ip-id", required_argument, 0, 0},
|
||||||
[IDX_DPI_DESYNC] = {"dpi-desync", required_argument, 0, 0},
|
[IDX_DPI_DESYNC] = {"dpi-desync", required_argument, 0, 0},
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
[IDX_DPI_DESYNC_FWMARK] = {"dpi-desync-fwmark", required_argument, 0, 0},
|
[IDX_DPI_DESYNC_FWMARK] = {"dpi-desync-fwmark", required_argument, 0, 0},
|
||||||
@@ -1915,12 +2131,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 +2187,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 +2216,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 +2259,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())
|
||||||
{
|
{
|
||||||
@@ -2266,6 +2489,21 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
dp->methodeol = true;
|
dp->methodeol = true;
|
||||||
break;
|
break;
|
||||||
|
case IDX_IP_ID:
|
||||||
|
if (!strcmp(optarg,"zero"))
|
||||||
|
dp->ip_id_mode = IPID_ZERO;
|
||||||
|
else if (!strcmp(optarg,"seq"))
|
||||||
|
dp->ip_id_mode = IPID_SEQ;
|
||||||
|
else if (!strcmp(optarg,"seqgroup"))
|
||||||
|
dp->ip_id_mode = IPID_SEQ_GROUP;
|
||||||
|
else if (!strcmp(optarg,"rnd"))
|
||||||
|
dp->ip_id_mode = IPID_RND;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DLOG_ERR("invalid ip_id mode : %s\n",optarg);
|
||||||
|
exit_clean(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case IDX_DPI_DESYNC:
|
case IDX_DPI_DESYNC:
|
||||||
{
|
{
|
||||||
char *mode = optarg, *mode2, *mode3;
|
char *mode = optarg, *mode2, *mode3;
|
||||||
@@ -2487,8 +2725,8 @@ int main(int argc, char **argv)
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
dp->split_count += ct;
|
dp->split_count += ct;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case IDX_DPI_DESYNC_SPLIT_HTTP_REQ:
|
case IDX_DPI_DESYNC_SPLIT_HTTP_REQ:
|
||||||
// obsolete arg
|
// obsolete arg
|
||||||
DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n", MAX_SPLITS);
|
DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n", MAX_SPLITS);
|
||||||
@@ -2536,16 +2774,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 +2865,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 +2905,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 +2936,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 +3221,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 +3230,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 +3334,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 +3406,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 +3434,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
|
||||||
|
|||||||
+29
-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,11 +78,26 @@ 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;
|
||||||
|
typedef enum {IPID_SEQ=0,IPID_SEQ_GROUP,IPID_RND,IPID_ZERO} t_ip_id_mode;
|
||||||
|
|
||||||
struct desync_profile
|
struct desync_profile
|
||||||
{
|
{
|
||||||
@@ -93,6 +110,8 @@ struct desync_profile
|
|||||||
|
|
||||||
t_synack_split synack_split;
|
t_synack_split synack_split;
|
||||||
|
|
||||||
|
t_ip_id_mode ip_id_mode;
|
||||||
|
|
||||||
bool hostcase, hostnospace, domcase, methodeol;
|
bool hostcase, hostnospace, domcase, methodeol;
|
||||||
char hostspell[4];
|
char hostspell[4];
|
||||||
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
|
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
|
||||||
@@ -102,7 +121,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 +145,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 +224,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;
|
||||||
|
|||||||
+9
-4
@@ -25,7 +25,7 @@
|
|||||||
memcpy(elem->str, keystr, keystr_len); \
|
memcpy(elem->str, keystr, keystr_len); \
|
||||||
elem->str[keystr_len] = 0; \
|
elem->str[keystr_len] = 0; \
|
||||||
oom = false; \
|
oom = false; \
|
||||||
HASH_ADD_KEYPTR(hh, *ppool, elem->str, strlen(elem->str), elem); \
|
HASH_ADD_KEYPTR(hh, *ppool, elem->str, keystr_len, elem); \
|
||||||
if (oom) \
|
if (oom) \
|
||||||
{ \
|
{ \
|
||||||
free(elem->str); \
|
free(elem->str); \
|
||||||
@@ -33,9 +33,12 @@
|
|||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
|
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
|
||||||
|
etype *elem_find; \
|
||||||
|
HASH_FIND(hh, *ppool, keystr, keystr_len, elem_find); \
|
||||||
|
if (!elem_find) { \
|
||||||
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
|
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
|
||||||
elem->flags = flg;
|
elem->flags = flg; \
|
||||||
|
}
|
||||||
|
|
||||||
#undef uthash_nonfatal_oom
|
#undef uthash_nonfatal_oom
|
||||||
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
|
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
|
||||||
@@ -576,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)))
|
||||||
@@ -588,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);
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -25,7 +25,7 @@
|
|||||||
memcpy(elem->str, keystr, keystr_len); \
|
memcpy(elem->str, keystr, keystr_len); \
|
||||||
elem->str[keystr_len] = 0; \
|
elem->str[keystr_len] = 0; \
|
||||||
oom = false; \
|
oom = false; \
|
||||||
HASH_ADD_KEYPTR(hh, *ppool, elem->str, strlen(elem->str), elem); \
|
HASH_ADD_KEYPTR(hh, *ppool, elem->str, keystr_len, elem); \
|
||||||
if (oom) \
|
if (oom) \
|
||||||
{ \
|
{ \
|
||||||
free(elem->str); \
|
free(elem->str); \
|
||||||
@@ -33,9 +33,12 @@
|
|||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
|
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
|
||||||
|
etype *elem_find; \
|
||||||
|
HASH_FIND(hh, *ppool, keystr, keystr_len, elem_find); \
|
||||||
|
if (!elem_find) { \
|
||||||
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
|
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
|
||||||
elem->flags = flg;
|
elem->flags = flg; \
|
||||||
|
}
|
||||||
|
|
||||||
#undef uthash_nonfatal_oom
|
#undef uthash_nonfatal_oom
|
||||||
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
|
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
|
||||||
|
|||||||
Reference in New Issue
Block a user