Compare commits

..

51 Commits

Author SHA1 Message Date
bol-van 21fc356476 blockcheck: fix brokern http3 test 2025-12-07 14:00:14 +03:00
bol-van 88b6b791e9 nfqws: add missing ssid_filter list init 2025-12-04 19:28:58 +03:00
bol-van 48185174cf update changes.txt 2025-12-04 14:56:29 +03:00
bol-van aa8d903bb1 blockcheck: fix broken DNS cache 2025-12-04 14:54:19 +03:00
bol-van cb653bedd6 blockcheck: check existense instead of curl 2025-12-02 08:54:10 +03:00
bol-van 534c88c96a fix 'which' function behavior with absolute paths 2025-12-02 08:53:38 +03:00
bol-van 7be9790839 remove obsolete file 2025-12-01 09:33:15 +03:00
bol-van 14d7f27b6a github: delete windivert filters from embedded build 2025-11-24 20:57:38 +03:00
bol-van 97cefbace9 update .gitattributes 2025-11-21 17:07:44 +03:00
bol-van 43cea80619 nfqws: fix crypto code 2025-11-18 15:14:42 +03:00
bol-van ce7d91a7ca blockcheck: fix broken ip block tests 2025-11-15 00:22:44 +03:00
bol-van 105ac57655 add 100.64.0.0/10 to default exclude 2025-11-11 14:55:38 +03:00
bol-van 06f5305617 nfqws: remove unneeded code 2025-11-11 09:42:48 +03:00
bol-van 45c3f00539 nfqws: do not increase retrans counter every reasm piece 2025-11-11 09:39:59 +03:00
bol-van 0c0c2547db blockcheck: shield curl 2025-11-10 12:48:44 +03:00
bol-van 60d182b97e update en WSL info 2025-11-08 22:12:23 +03:00
bol-van 907b530068 update WSL info 2025-11-08 22:11:15 +03:00
bol-van 8763768180 update WSL info 2025-11-08 22:06:48 +03:00
bol-van 793cd76621 update WSL info 2025-11-08 22:05:21 +03:00
bol-van 9b47b21918 nfqws: ipv6 ah header length is in 32-bit words, not 64-bit 2025-11-08 20:46:09 +03:00
bol-van caa364e0ed blockcheck: fix doh resolve failure if spaces in the path 2025-11-06 22:14:47 +03:00
bol-van 76992dc3d9 nfqws: remove duplicate defines 2025-11-05 17:08:34 +03:00
bol-van 0b8e0dc97d blockcheck: replace ipv6 only ntc.party to ej.ru 2025-10-30 16:19:52 +03:00
bol-van 1408c38522 blockcheck: fix - sign regression 2025-10-28 21:50:46 +03:00
bol-van cea968d259 blockcheck: filter out : 2025-10-28 18:24:32 +03:00
bol-van f91bca170a blockcheck: support URIs, support disabling HEAD for https 2025-10-28 14:45:15 +03:00
bol-van 9d5c9191be Merge pull request #1834 from ooovlad/fix-readme-typo
Fix the annoying typo that got me confused on my attempt to set up
2025-10-27 07:27:40 +03:00
Vlad f4ce79a97c Fix the annoying typo that got me confused when I was trying to set up the program
Please correct this typo in the file name, as it caused me to stumble twice when setting up zapret. I took the file name directly from the readme, and then I found out that it was incorrect. Then after a while I forgot about it and took the file name from the readme again. So I decided to make a pull request.
2025-10-27 00:02:33 +03:00
bol-van 845b9edf85 Merge pull request #1821 from ilyuXer/patch-1
Update readme.md
2025-10-25 08:47:11 +03:00
ilyuXer 5ec5ce8246 Update readme.md 2025-10-24 21:01:01 +03:00
bol-van 29935b0934 update docs 2025-10-17 15:11:08 +03:00
bol-van fe12b55181 update docs 2025-10-17 15:07:10 +03:00
bol-van 2cafc7ddeb nfqws: optimize 2025-10-17 14:35:42 +03:00
bol-van 2daf764760 nfqws: optimize 2025-10-17 14:20:54 +03:00
bol-van 078022bccf nfqws: minor bug 2025-10-17 14:15:36 +03:00
bol-van 57778b6249 nfqws: --dup-ip-id, --*-tcp-flags-*, --wssize-forced-cutoff 2025-10-17 14:10:30 +03:00
bol-van 845f4b43ef remove bad comments from custom scripts 2025-10-13 16:43:52 +03:00
bol-van a485030423 50-quic4all 2025-10-13 16:42:59 +03:00
bol-van 6821093493 50-quic4all 2025-10-13 16:41:49 +03:00
bol-van 0dea2d6ad0 blockcheck: MIN/MAX_AUTOTTL_DELTA 2025-10-13 16:14:19 +03:00
bol-van 16e71fc5fc nfqws: fix --ip-id when changing profiles 2025-10-13 15:52:16 +03:00
bol-van b2795989b7 update docs 2025-10-13 15:29:57 +03:00
bol-van dbfc20a5bc nfqws: ip_id improvements 2025-10-13 14:51:42 +03:00
bol-van 2aa301bf0b update docs 2025-10-13 12:55:04 +03:00
bol-van 324aa12ecf update docs 2025-10-13 12:35:43 +03:00
bol-van af5cf623be update docs 2025-10-13 12:35:07 +03:00
bol-van 9556eff091 update docs 2025-10-13 12:34:41 +03:00
bol-van ca42c88ce0 update docs 2025-10-13 12:33:54 +03:00
bol-van 62cdc8bf13 nfqws: random ip_id not zero 2025-10-12 20:15:52 +03:00
bol-van 643c254fab nfqws: --ip-id 2025-10-12 20:08:08 +03:00
bol-van 3f2ef1feee windivert_part.quic_initial_ietf.txt 2025-10-12 15:23:11 +03:00
25 changed files with 623 additions and 268 deletions
+1
View File
@@ -2,3 +2,4 @@
*.cmd eol=crlf *.cmd eol=crlf
*.bat eol=crlf *.bat eol=crlf
init.d/windivert.filter.examples/** eol=crlf init.d/windivert.filter.examples/** eol=crlf
files/** binary
+1 -1
View File
@@ -468,7 +468,7 @@ jobs:
( (
cd ${{ env.repo_dir }} cd ${{ env.repo_dir }}
rm -rf binaries/{android*,freebsd*,mac*,win*,x86_64/tpws_wsl.tgz} \ rm -rf binaries/{android*,freebsd*,mac*,win*,x86_64/tpws_wsl.tgz} \
init.d/{openrc,macos,pfsense,runit,s6,systemd} \ init.d/{openrc,macos,pfsense,runit,s6,systemd,windivert.filter.examples} \
tpws nfq ip2net mdig docs files/huawei Makefile tpws nfq ip2net mdig docs files/huawei Makefile
) )
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }} tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
+62 -49
View File
@@ -41,6 +41,8 @@ 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}
@@ -54,7 +56,7 @@ HDRTEMP=/tmp/zapret-hdr
NFT_TABLE=blockcheck NFT_TABLE=blockcheck
DNSCHECK_DNS=${DNSCHECK_DNS:-8.8.8.8 1.1.1.1 77.88.8.1} DNSCHECK_DNS=${DNSCHECK_DNS:-8.8.8.8 1.1.1.1 77.88.8.1}
DNSCHECK_DOM=${DNSCHECK_DOM:-pornhub.com ntc.party rutracker.org www.torproject.org bbc.com} DNSCHECK_DOM=${DNSCHECK_DOM:-pornhub.com ej.ru rutracker.org www.torproject.org bbc.com}
DOH_SERVERS=${DOH_SERVERS:-"https://cloudflare-dns.com/dns-query https://dns.google/dns-query https://dns.quad9.net/dns-query https://dns.adguard.com/dns-query https://common.dot.dns.yandex.net/dns-query"} DOH_SERVERS=${DOH_SERVERS:-"https://cloudflare-dns.com/dns-query https://dns.google/dns-query https://dns.quad9.net/dns-query https://dns.adguard.com/dns-query https://common.dot.dns.yandex.net/dns-query"}
DNSCHECK_DIG1=/tmp/dig1.txt DNSCHECK_DIG1=/tmp/dig1.txt
DNSCHECK_DIG2=/tmp/dig2.txt DNSCHECK_DIG2=/tmp/dig2.txt
@@ -217,7 +219,7 @@ doh_resolve()
# $1 - ip version 4/6 # $1 - ip version 4/6
# $2 - hostname # $2 - hostname
# $3 - doh server URL. use $DOH_SERVER if empty # $3 - doh server URL. use $DOH_SERVER if empty
$MDIG --family=$1 --dns-make-query=$2 | $CURL --max-time $CURL_MAX_TIME_DOH -s --data-binary @- -H "Content-Type: application/dns-message" "${3:-$DOH_SERVER}" | $MDIG --dns-parse-query "$MDIG" --family=$1 --dns-make-query=$2 | "$CURL" --max-time $CURL_MAX_TIME_DOH -s --data-binary @- -H "Content-Type: application/dns-message" "${3:-$DOH_SERVER}" | "$MDIG" --dns-parse-query
} }
doh_find_working() doh_find_working()
{ {
@@ -245,7 +247,7 @@ mdig_vars()
# $1 - ip version 4/6 # $1 - ip version 4/6
# $2 - hostname # $2 - hostname
hostvar=$(echo $2 | sed -e 's/[\.-]/_/g') hostvar=$(echo $2 | sed -e 's/[\./?&#@%*$^:~=!()+-]/_/g')
cachevar=DNSCACHE_${hostvar}_$1 cachevar=DNSCACHE_${hostvar}_$1
countvar=${cachevar}_COUNT countvar=${cachevar}_COUNT
eval count=\$${countvar} eval count=\$${countvar}
@@ -276,41 +278,45 @@ mdig_cache()
mdig_resolve() mdig_resolve()
{ {
# $1 - ip version 4/6 # $1 - ip version 4/6
# $2 - hostname # $2 - var to receive result
# $3 - hostname, possibly with uri : rutracker.org/xxx/xxxx
local hostvar cachevar countvar count n sdom
local hostvar cachevar countvar count ip n split_by_separator "$3" / sdom
mdig_vars "$@" mdig_vars "$1" "$sdom"
if [ -n "$count" ]; then if [ -n "$count" ]; then
n=$(random 0 $(($count-1))) n=$(random 0 $(($count-1)))
eval ip=\$${cachevar}_$n eval $2=\$${cachevar}_$n
echo $ip
return 0 return 0
else else
mdig_cache "$@" && mdig_resolve "$@" mdig_cache "$1" "$sdom" && mdig_resolve "$1" "$2" "$sdom"
fi fi
} }
mdig_resolve_all() mdig_resolve_all()
{ {
# $1 - ip version 4/6 # $1 - ip version 4/6
# $2 - hostname # $2 - var to receive result
# $3 - hostname
local hostvar cachevar countvar count ip ips n local hostvar cachevar countvar count ip__ ips__ n sdom
mdig_vars "$@"
split_by_separator "$3" / sdom
mdig_vars "$1" "$sdom"
if [ -n "$count" ]; then if [ -n "$count" ]; then
n=0 n=0
while [ "$n" -le $count ]; do while [ "$n" -le $count ]; do
eval ip=\$${cachevar}_$n eval ip__=\$${cachevar}_$n
if [ -n "$ips" ]; then if [ -n "$ips__" ]; then
ips="$ips $ip" ips__="$ips__ $ip__"
else else
ips="$ip" ips__="$ip__"
fi fi
n=$(($n + 1)) n=$(($n + 1))
done done
echo "$ips" eval $2="\$ips__"
return 0 return 0
else else
mdig_cache "$@" && mdig_resolve_all "$@" mdig_cache "$1" "$sdom" && mdig_resolve_all "$1" "$2" "$sdom"
fi fi
} }
@@ -421,7 +427,7 @@ check_system()
} }
echo firewall type is $FWTYPE echo firewall type is $FWTYPE
echo CURL=$CURL echo CURL=$CURL
$CURL --version "$CURL" --version
} }
zp_already_running() zp_already_running()
@@ -477,7 +483,7 @@ check_prerequisites()
exitp 6 exitp 6
} }
local prog progs='curl' local prog progs="$CURL"
[ "$SKIP_PKTWS" = 1 ] || { [ "$SKIP_PKTWS" = 1 ] || {
case "$UNAME" in case "$UNAME" in
Linux) Linux)
@@ -593,12 +599,12 @@ curl_translate_code()
curl_supports_tls13() curl_supports_tls13()
{ {
local r local r
$CURL --tlsv1.3 -Is -o /dev/null --max-time 1 http://127.0.0.1:65535 2>/dev/null "$CURL" --tlsv1.3 -Is -o /dev/null --max-time 1 http://127.0.0.1:65535 2>/dev/null
# return code 2 = init failed. likely bad command line options # return code 2 = init failed. likely bad command line options
[ $? = 2 ] && return 1 [ $? = 2 ] && return 1
# curl can have tlsv1.3 key present but ssl library without TLS 1.3 support # curl can have tlsv1.3 key present but ssl library without TLS 1.3 support
# this is online test because there's no other way to trigger library incompatibility case # this is online test because there's no other way to trigger library incompatibility case
$CURL --tlsv1.3 --max-time 1 -Is -o /dev/null https://iana.org 2>/dev/null "$CURL" --tlsv1.3 --max-time 1 -Is -o /dev/null https://iana.org 2>/dev/null
r=$? r=$?
[ $r != 4 -a $r != 35 ] [ $r != 4 -a $r != 35 ]
} }
@@ -606,16 +612,16 @@ curl_supports_tls13()
curl_supports_tlsmax() curl_supports_tlsmax()
{ {
# supported only in OpenSSL and LibreSSL # supported only in OpenSSL and LibreSSL
$CURL --version | grep -Fq -e OpenSSL -e LibreSSL -e BoringSSL -e GnuTLS -e quictls || return 1 "$CURL" --version | grep -Fq -e OpenSSL -e LibreSSL -e BoringSSL -e GnuTLS -e quictls || return 1
# supported since curl 7.54 # supported since curl 7.54
$CURL --tls-max 1.2 -Is -o /dev/null --max-time 1 http://127.0.0.1:65535 2>/dev/null "$CURL" --tls-max 1.2 -Is -o /dev/null --max-time 1 http://127.0.0.1:65535 2>/dev/null
# return code 2 = init failed. likely bad command line options # return code 2 = init failed. likely bad command line options
[ $? != 2 ] [ $? != 2 ]
} }
curl_supports_connect_to() curl_supports_connect_to()
{ {
$CURL --connect-to 127.0.0.1:: -o /dev/null --max-time 1 http://127.0.0.1:65535 2>/dev/null "$CURL" --connect-to 127.0.0.1:: -o /dev/null --max-time 1 http://127.0.0.1:65535 2>/dev/null
[ "$?" != 2 ] [ "$?" != 2 ]
} }
@@ -623,7 +629,7 @@ curl_supports_http3()
{ {
# if it has http3 : curl: (3) HTTP/3 requested for non-HTTPS URL # if it has http3 : curl: (3) HTTP/3 requested for non-HTTPS URL
# otherwise : curl: (2) option --http3-only: is unknown # otherwise : curl: (2) option --http3-only: is unknown
$CURL --connect-to 127.0.0.1:: -o /dev/null --max-time 1 --http3-only http://127.0.0.1:65535 2>/dev/null "$CURL" --connect-to 127.0.0.1:: -o /dev/null --max-time 1 --http3-only http://127.0.0.1:65535 2>/dev/null
[ "$?" != 2 ] [ "$?" != 2 ]
} }
@@ -651,10 +657,10 @@ curl_with_subst_ip()
*:*) ip="[$ip]" ;; *:*) ip="[$ip]" ;;
esac esac
local connect_to="--connect-to $1::$ip${2:+:$2}" arg local connect_to="--connect-to $1::$ip${2:+:$2}" arg
shift ; shift ; shift shift ; shift ; shift;
[ "$CURL_VERBOSE" = 1 ] && arg="-v" [ "$CURL_VERBOSE" = 1 ] && arg="-v"
[ "$CURL_CMD" = 1 ] && echo $CURL ${arg:+$arg }$connect_to "$@" [ "$CURL_CMD" = 1 ] && echo $CURL ${arg:+$arg }$connect_to "$@"
ALL_PROXY="$ALL_PROXY" $CURL ${arg:+$arg }$connect_to "$@" ALL_PROXY="$ALL_PROXY" "$CURL" ${arg:+$arg }$connect_to "$@"
} }
curl_with_dig() curl_with_dig()
{ {
@@ -663,10 +669,13 @@ curl_with_dig()
# $3 - port # $3 - port
# $4+ - curl params # $4+ - curl params
local dom=$2 port=$3 local dom=$2 port=$3
local ip=$(mdig_resolve $1 $dom) local sdom suri ip
split_by_separator "$dom" / sdom suri
mdig_resolve $1 ip $sdom
shift ; shift ; shift shift ; shift ; shift
if [ -n "$ip" ]; then if [ -n "$ip" ]; then
curl_with_subst_ip $dom $port $ip "$@" curl_with_subst_ip "$sdom" "$port" "$ip" "$@"
else else
return 6 return 6
fi fi
@@ -729,7 +738,7 @@ curl_test_https_tls12()
# $3 - subst ip # $3 - subst ip
# do not use tls 1.3 to make sure server certificate is not encrypted # do not use tls 1.3 to make sure server certificate is not encrypted
curl_probe $1 $2 $HTTPS_PORT "$3" -ISs -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1 curl_probe $1 $2 $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1
} }
curl_test_https_tls13() curl_test_https_tls13()
{ {
@@ -738,7 +747,7 @@ curl_test_https_tls13()
# $3 - subst ip # $3 - subst ip
# force TLS1.3 mode # force TLS1.3 mode
curl_probe $1 $2 $HTTPS_PORT "$3" -ISs -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1 curl_probe $1 $2 $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1
} }
curl_test_http3() curl_test_http3()
@@ -747,7 +756,7 @@ curl_test_http3()
# $2 - domain name # $2 - domain name
# force QUIC only mode without tcp # force QUIC only mode without tcp
curl_with_dig $1 $2 $QUIC_PORT -ISs -A "$USER_AGENT" --max-time $CURL_MAX_TIME_QUIC --http3-only $CURL_OPT "https://$2" -o /dev/null 2>&1 curl_with_dig $1 $2 $QUIC_PORT $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME_QUIC --http3-only $CURL_OPT "https://$2" -o /dev/null 2>&1
} }
ipt_aux_scheme() ipt_aux_scheme()
@@ -997,7 +1006,7 @@ check_domain_port_block()
echo echo
echo \* port block tests ipv$IPV $1:$2 echo \* port block tests ipv$IPV $1:$2
if netcat_setup; then if netcat_setup; then
ips=$(mdig_resolve_all $IPV $1) mdig_resolve_all $IPV ips $1
if [ -n "$ips" ]; then if [ -n "$ips" ]; then
for ip in $ips; do for ip in $ips; do
if netcat_test $ip $2; then if netcat_test $ip $2; then
@@ -1330,7 +1339,7 @@ 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_hostfakesplit 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'
@@ -1342,6 +1351,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=
@@ -1500,7 +1510,7 @@ pktws_check_domain_http_bypass_()
ok=0 ok=0
# orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server. # 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 # missing ACK is transmitted in the first data packet of TLS/HTTP proto
for delta in 1 2 3 4 5; do for delta in $attls; do
for f in '' '--orig-ttl=1 --orig-mod-start=s1 --orig-mod-cutoff=d1'; 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 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 [ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
@@ -1508,7 +1518,7 @@ pktws_check_domain_http_bypass_()
done done
[ "$SCANLEVEL" = force ] && { [ "$SCANLEVEL" = force ] && {
for orig in 1 2 3; do for orig in 1 2 3; do
for delta in 1 2 3 4 5; 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
@@ -1696,7 +1706,7 @@ check_dpi_ip_block()
echo "> testing $UNBLOCKED_DOM on it's original ip" echo "> testing $UNBLOCKED_DOM on it's original ip"
if curl_test $1 $UNBLOCKED_DOM; then if curl_test $1 $UNBLOCKED_DOM; then
unblocked_ip=$(mdig_resolve $IPV $UNBLOCKED_DOM) mdig_resolve $IPV unblocked_ip $UNBLOCKED_DOM
[ -n "$unblocked_ip" ] || { [ -n "$unblocked_ip" ] || {
echo $UNBLOCKED_DOM does not resolve. tests not possible. echo $UNBLOCKED_DOM does not resolve. tests not possible.
return 1 return 1
@@ -1705,7 +1715,7 @@ check_dpi_ip_block()
echo "> testing $blocked_dom on $unblocked_ip ($UNBLOCKED_DOM)" echo "> testing $blocked_dom on $unblocked_ip ($UNBLOCKED_DOM)"
curl_test $1 $blocked_dom $unblocked_ip detail curl_test $1 $blocked_dom $unblocked_ip detail
blocked_ips=$(mdig_resolve_all $IPV $blocked_dom) mdig_resolve_all $IPV blocked_ips $blocked_dom
for blocked_ip in $blocked_ips; do for blocked_ip in $blocked_ips; do
echo "> testing $UNBLOCKED_DOM on $blocked_ip ($blocked_dom)" echo "> testing $UNBLOCKED_DOM on $blocked_ip ($blocked_dom)"
curl_test $1 $UNBLOCKED_DOM $blocked_ip detail curl_test $1 $UNBLOCKED_DOM $blocked_ip detail
@@ -1756,6 +1766,8 @@ check_domain_http_tcp()
# $3 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk # $3 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
# $4 - domain # $4 - domain
local ips
# in case was interrupted before # in case was interrupted before
pktws_ipt_unprepare_tcp $2 pktws_ipt_unprepare_tcp $2
ws_kill ws_kill
@@ -1764,15 +1776,11 @@ check_domain_http_tcp()
[ "$SKIP_IPBLOCK" = 1 ] || check_dpi_ip_block $1 $4 [ "$SKIP_IPBLOCK" = 1 ] || check_dpi_ip_block $1 $4
[ "$SKIP_TPWS" = 1 ] || {
echo
tpws_check_domain_http_bypass $1 $3 $4
}
[ "$SKIP_PKTWS" = 1 ] || { [ "$SKIP_PKTWS" = 1 ] || {
echo echo
echo preparing $PKTWSD redirection echo preparing $PKTWSD redirection
pktws_ipt_prepare_tcp $2 "$(mdig_resolve_all $IPV $4)" mdig_resolve_all $IPV ips $4
pktws_ipt_prepare_tcp $2 "$ips"
pktws_check_domain_http_bypass $1 $3 $4 pktws_check_domain_http_bypass $1 $3 $4
@@ -1786,6 +1794,8 @@ check_domain_http_udp()
# $2 - port # $2 - port
# $3 - domain # $3 - domain
local ips
# in case was interrupted before # in case was interrupted before
pktws_ipt_unprepare_udp $2 pktws_ipt_unprepare_udp $2
ws_kill ws_kill
@@ -1795,7 +1805,8 @@ check_domain_http_udp()
[ "$SKIP_PKTWS" = 1 ] || { [ "$SKIP_PKTWS" = 1 ] || {
echo echo
echo preparing $PKTWSD redirection echo preparing $PKTWSD redirection
pktws_ipt_prepare_udp $2 "$(mdig_resolve_all $IPV $3)" mdig_resolve_all $IPV ips $3
pktws_ipt_prepare_udp $2 "$ips"
pktws_check_domain_http3_bypass $1 $3 pktws_check_domain_http3_bypass $1 $3
@@ -1854,6 +1865,9 @@ configure_curl_opt()
curl_supports_tls13 && TLS13=1 curl_supports_tls13 && TLS13=1
HTTP3= HTTP3=
curl_supports_http3 && HTTP3=1 curl_supports_http3 && HTTP3=1
HTTPS_HEAD=-I
[ "$CURL_HTTPS_GET" = 1 ] && HTTPS_HEAD=
} }
linux_ipv6_defrag_can_be_disabled() linux_ipv6_defrag_can_be_disabled()
@@ -1914,7 +1928,7 @@ ask_params()
curl_supports_connect_to || { curl_supports_connect_to || {
echo "installed curl does not support --connect-to option. pls install at least curl 7.49" echo "installed curl does not support --connect-to option. pls install at least curl 7.49"
echo "current curl version:" echo "current curl version:"
$CURL --version "$CURL" --version
exitp 1 exitp 1
} }
@@ -1922,7 +1936,7 @@ ask_params()
[ -n "$DOMAINS" ] || { [ -n "$DOMAINS" ] || {
DOMAINS="$DOMAINS_DEFAULT" DOMAINS="$DOMAINS_DEFAULT"
[ "$BATCH" = 1 ] || { [ "$BATCH" = 1 ] || {
echo "specify domain(s) to test. multiple domains are space separated." echo "specify domain(s) to test. multiple domains are space separated. URIs are supported (rutracker.org/forum/index.php)"
printf "domain(s) (default: $DOMAINS) : " printf "domain(s) (default: $DOMAINS) : "
read dom read dom
[ -n "$dom" ] && DOMAINS="$dom" [ -n "$dom" ] && DOMAINS="$dom"
@@ -2265,7 +2279,6 @@ sigsilent()
exit 1 exit 1
} }
fsleep_setup fsleep_setup
fix_sbin_path fix_sbin_path
check_system check_system
+16
View File
@@ -4,6 +4,10 @@ which()
# 'command -v' replacement does not work exactly the same way. it outputs shell aliases if present # 'command -v' replacement does not work exactly the same way. it outputs shell aliases if present
# $1 - executable name # $1 - executable name
local IFS=: local IFS=:
[ "$1" != "${1#/}" ] && [ -x "$1" ] && {
echo "$1"
return 0
}
for p in $PATH; do for p in $PATH; do
[ -x "$p/$1" ] && { [ -x "$p/$1" ] && {
echo "$p/$1" echo "$p/$1"
@@ -93,6 +97,18 @@ trim()
{ {
awk '{gsub(/^ +| +$/,"")}1' awk '{gsub(/^ +| +$/,"")}1'
} }
split_by_separator()
{
# $1 - string
# $2 - separator
# $3 - var name to get "before" part
# $4 - var name to get "after" part
local before="${1%%$2*}"
local after="${1#*$2}"
[ "$after" = "$1" ] && after=
[ -n "$3" ] && eval $3="\$before"
[ -n "$4" ] && eval $4="\$after"
}
dir_is_not_empty() dir_is_not_empty()
{ {
-85
View File
@@ -1,85 +0,0 @@
apply_unspecified_desync_modes()
{
NFQWS_OPT_DESYNC_HTTP="${NFQWS_OPT_DESYNC_HTTP:-$NFQWS_OPT_DESYNC}"
NFQWS_OPT_DESYNC_HTTP_SUFFIX="${NFQWS_OPT_DESYNC_HTTP_SUFFIX:-$NFQWS_OPT_DESYNC_SUFFIX}"
NFQWS_OPT_DESYNC_HTTPS="${NFQWS_OPT_DESYNC_HTTPS:-$NFQWS_OPT_DESYNC}"
NFQWS_OPT_DESYNC_HTTPS_SUFFIX="${NFQWS_OPT_DESYNC_HTTPS_SUFFIX:-$NFQWS_OPT_DESYNC_SUFFIX}"
NFQWS_OPT_DESYNC_HTTP6="${NFQWS_OPT_DESYNC_HTTP6:-$NFQWS_OPT_DESYNC_HTTP}"
NFQWS_OPT_DESYNC_HTTP6_SUFFIX="${NFQWS_OPT_DESYNC_HTTP6_SUFFIX:-$NFQWS_OPT_DESYNC_HTTP_SUFFIX}"
NFQWS_OPT_DESYNC_HTTPS6="${NFQWS_OPT_DESYNC_HTTPS6:-$NFQWS_OPT_DESYNC_HTTPS}"
NFQWS_OPT_DESYNC_HTTPS6_SUFFIX="${NFQWS_OPT_DESYNC_HTTPS6_SUFFIX:-$NFQWS_OPT_DESYNC_HTTPS_SUFFIX}"
NFQWS_OPT_DESYNC_QUIC6="${NFQWS_OPT_DESYNC_QUIC6:-$NFQWS_OPT_DESYNC_QUIC}"
NFQWS_OPT_DESYNC_QUIC6_SUFFIX="${NFQWS_OPT_DESYNC_QUIC6_SUFFIX:-$NFQWS_OPT_DESYNC_QUIC_SUFFIX}"
}
get_nfqws_qnums()
{
# $1 - var name for ipv4 http
# $2 - var name for ipv4 https
# $3 - var name for ipv6 http
# $4 - var name for ipv6 https
local _qn _qns _qn6 _qns6
[ "$DISABLE_IPV4" = "1" ] || {
_qn=$QNUM
_qns=$_qn
[ "$NFQWS_OPT_DESYNC_HTTP $NFQWS_OPT_DESYNC_HTTP_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTPS $NFQWS_OPT_DESYNC_HTTPS_SUFFIX" ] || _qns=$(($QNUM+1))
}
[ "$DISABLE_IPV6" = "1" ] || {
_qn6=$(($QNUM+2))
_qns6=$(($QNUM+3))
[ "$DISABLE_IPV4" = "1" ] || {
if [ "$NFQWS_OPT_DESYNC_HTTP6 $NFQWS_OPT_DESYNC_HTTP6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTP $NFQWS_OPT_DESYNC_HTTP_SUFFIX" ]; then
_qn6=$_qn;
elif [ "$NFQWS_OPT_DESYNC_HTTP6 $NFQWS_OPT_DESYNC_HTTP6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTPS $NFQWS_OPT_DESYNC_HTTPS_SUFFIX" ]; then
_qn6=$_qns;
fi
if [ "$NFQWS_OPT_DESYNC_HTTPS6 $NFQWS_OPT_DESYNC_HTTPS6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTP $NFQWS_OPT_DESYNC_HTTP_SUFFIX" ]; then
_qns6=$_qn;
elif [ "$NFQWS_OPT_DESYNC_HTTPS6 $NFQWS_OPT_DESYNC_HTTPS6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTPS $NFQWS_OPT_DESYNC_HTTPS_SUFFIX" ]; then
_qns6=$_qns;
fi
}
[ "$NFQWS_OPT_DESYNC_HTTPS6 $NFQWS_OPT_DESYNC_HTTPS6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTP6 $NFQWS_OPT_DESYNC_HTTP6_SUFFIX" ] && _qns6=$_qn6;
}
if [ "$MODE_HTTP" = 1 ]; then
eval $1=$_qn
eval $3=$_qn6
else
eval $1=
eval $3=
fi
if [ "$MODE_HTTPS" = 1 ]; then
eval $2=$_qns
eval $4=$_qns6
else
eval $2=
eval $4=
fi
}
get_nfqws_qnums_quic()
{
# $1 - var name for ipv4 quic
# $2 - var name for ipv6 quic
local _qn _qn6
[ "$DISABLE_IPV4" = "1" ] || {
_qn=$(($QNUM+10))
}
[ "$DISABLE_IPV6" = "1" ] || {
_qn6=$(($QNUM+11))
[ "$DISABLE_IPV4" = "1" ] || {
if [ "$NFQWS_OPT_DESYNC_QUIC $NFQWS_OPT_DESYNC_QUIC_SUFFIX" = "$NFQWS_OPT_DESYNC_QUIC6 $NFQWS_OPT_DESYNC_QUIC6_SUFFIX" ]; then
_qn6=$_qn;
fi
}
}
if [ "$MODE_QUIC" = 1 ]; then
eval $1=$_qn
eval $2=$_qn6
else
eval $1=
eval $2=
fi
}
+21
View File
@@ -555,3 +555,24 @@ 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: print PRETTY_NAME and some OPENWRT_xxx from /etc/os-release
blockcheck: new strategies blockcheck: new strategies
blockcheck: curl test simulation : SIMULATE=1 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
72.2
nfqws: --wssize-forced-cutoff
nfqws: --orig-tcp-flags, --dup-tcp-flags, --dpi-desync-tcp-flags
nfqws: --dup-ip-id
73.3
blockcheck: support URIs
blockcheck: CURL_HTTPS_GET=1 suppresses -I curl option for https (HEAD -> GET)
73.4
blockcheck: fix broken dns cache
+33 -3
View File
@@ -1,4 +1,4 @@
# zapret v72 # zapret v72.2
# 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)
@@ -152,6 +153,7 @@ nfqws takes the following parameters:
--wsize=<window_size>[:<scale_factor>] ; set window size. 0 = do not modify. OBSOLETE ! --wsize=<window_size>[:<scale_factor>] ; set window size. 0 = do not modify. OBSOLETE !
--wssize=<window_size>[:<scale_factor>] ; set window size for server. 0 = do not modify. default scale_factor = 0. --wssize=<window_size>[:<scale_factor>] ; set window size for server. 0 = do not modify. default scale_factor = 0.
--wssize-cutoff=[n|d|s]N ; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N --wssize-cutoff=[n|d|s]N ; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--wssize-forced-cutoff=0|1 ; 1(default)=auto cutoff wssize on known protocol
--ctrack-timeouts=S:E:F[:U] ; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default 60:300:60:60 --ctrack-timeouts=S:E:F[:U] ; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default 60:300:60:60
--ctrack-disable=[0|1] ; 1 or no argument disables conntrack --ctrack-disable=[0|1] ; 1 or no argument disables conntrack
--ipcache-lifetime=<int> ; time in seconds to keep cached hop count and domain name (default 7200). 0 = no expiration --ipcache-lifetime=<int> ; time in seconds to keep cached hop count and domain name (default 7200). 0 = no expiration
@@ -166,6 +168,8 @@ nfqws takes the following parameters:
--orig-ttl6=<int> ; set ipv6 hop limit for original packets. by default ttl value is used --orig-ttl6=<int> ; set ipv6 hop limit for original packets. by default ttl value is used
--orig-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: +5:3-64. "0:0-0" or "-" disables autottl. --orig-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: +5:3-64. "0:0-0" or "-" disables autottl.
--orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --orig-autottl for ipv6 only --orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --orig-autottl for ipv6 only
--orig-tcp-flags-set=<int|0xHEX|flaglist> ; set these tcp flags (flags |= value). value can be int, hex or comma separated list : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--orig-tcp-flags-unset=<int|0xHEX|flaglist> ; unset these tcp flags (flags &= ~value)
--orig-mod-start=[n|d|s]N ; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N --orig-mod-start=[n|d|s]N ; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--orig-mod-cutoff=[n|d|s]N ; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N --orig-mod-cutoff=[n|d|s]N ; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--dup=<int> ; duplicate original packets. send N dups before original. --dup=<int> ; duplicate original packets. send N dups before original.
@@ -174,18 +178,24 @@ nfqws takes the following parameters:
--dup-ttl6=<int> ; set ipv6 hop limit for dups. by default ttl value is used --dup-ttl6=<int> ; set ipv6 hop limit for dups. by default ttl value is used
--dup-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-64. "0:0-0" or "-" disables autottl. --dup-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-64. "0:0-0" or "-" disables autottl.
--dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dup-autottl for ipv6 only --dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dup-autottl for ipv6 only
--dup-tcp-flags-set=<int|0xHEX|flaglist> ; set these tcp flags (flags |= value). value can be int, hex or comma separated list : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--dup-tcp-flags-unset=<int|0xHEX|flaglist> ; unset these tcp flags (flags &= ~value)
--dup-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2 --dup-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2
--dup-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment for dup. default -600000 --dup-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment for dup. default -600000
--dup-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment for dup. default -10000 --dup-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment for dup. default -10000
--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-ip-id=same|zero|seq|rnd ; ipv4 ip_id mode for dupped packets
--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
--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=[<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.
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-20. "0:0-0" or "-" disables autottl. --dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-20. "0:0-0" or "-" disables autottl.
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dpi-desync-autottl for ipv6 only --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dpi-desync-autottl for ipv6 only
--dpi-desync-tcp-flags-set=<int|0xHEX|flaglist> ; set these tcp flags (flags |= value). value can be int, hex or comma separated list : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--dpi-desync-tcp-flags-unset=<int|0xHEX|flaglist> ; unset these tcp flags (flags &= ~value)
--dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2 --dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync-repeats=<N> ; send every desync packet N times --dpi-desync-repeats=<N> ; send every desync packet N times
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?) --dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?)
@@ -296,6 +306,10 @@ Fakes are separate generated by nfqws packets carrying false information for DPI
* **datanoack** sends tcp fakes without ACK flag. Servers do not accept this but DPI may accept. * **datanoack** sends tcp fakes without ACK flag. Servers do not accept this but DPI may accept.
This mode may break NAT and may not work with iptables if masquerade is used, even from the router itself. This mode may break NAT and may not work with iptables if masquerade is used, even from the router itself.
Works with nftables properly. Likely requires external IP address (some ISPs pass these packets through their NAT). Works with nftables properly. Likely requires external IP address (some ISPs pass these packets through their NAT).
* Manipulate **tcp flags** with `--dpi-desync-tcp-flags-set` and `--dpi-desync-tcp-flags-unset`.
Invalid tcp flags combination may cause server to drop the packet but DPI can accept it.
For example, set SYN in fakes. This may not work with all servers.
`datanoack` can be replaced to `--dpi-desync-tcp-flags-unset=ACK`.
* **ts** adds to TSval ts increment value (-600000 by default). Servers discard packets with TSval in some range. * **ts** adds to TSval ts increment value (-600000 by default). Servers discard packets with TSval in some range.
Practical tests suggest increment between -100 and -0x80000000. Practical tests suggest increment between -100 and -0x80000000.
Timestamps are generated by client OS. In linux timestamps are enabled by default. In windows by default timestamps are disabled. Timestamps are generated by client OS. In linux timestamps are enabled by default. In windows by default timestamps are disabled.
@@ -439,6 +453,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`,
@@ -496,7 +525,7 @@ There are DPIs that analyze responses from the server, particularly the certific
In the disorder variant, a selective acknowledgement (SACK) usually arrives first, then a full ACK. In the disorder variant, a selective acknowledgement (SACK) usually arrives first, then a full ACK.
If, instead of ACK or SACK, there is an RST packet with minimal delay, DPI cuts you off at the request stage. If, instead of ACK or SACK, there is an RST packet with minimal delay, DPI cuts you off at the request stage.
If the RST is after a full ACK after a delay of about ping to the server, then probably DPI acts on the server response. The DPI may be satisfied with good ClientHello and stop monitoring the TCP session without checking ServerHello. Then you were lucky. 'fake' option could work. If the RST is after a full ACK after a delay of about ping to the server, then probably DPI acts on the server response. The DPI may be satisfied with good ClientHello and stop monitoring the TCP session without checking ServerHello. Then you were lucky. 'fake' option could work.
If it does not stop monitoring and persistently checks the ServerHello, --wssize parameter may help (see [CONNTRACK](#conntrack)). If it does not stop monitoring and persistently checks the ServerHello, `--wssize` parameter may help (see [CONNTRACK](#conntrack)).
Otherwise it is hardly possible to overcome this without the help of the server. Otherwise it is hardly possible to overcome this without the help of the server.
The best solution is to enable TLS 1.3 support on the server. TLS 1.3 sends the server certificate in encrypted form. The best solution is to enable TLS 1.3 support on the server. TLS 1.3 sends the server certificate in encrypted form.
This is recommendation to all admins of blocked sites. Enable TLS 1.3. You will give more opportunities to overcome DPI. This is recommendation to all admins of blocked sites. Enable TLS 1.3. You will give more opportunities to overcome DPI.
@@ -559,7 +588,7 @@ That's why conntrack is required to know when to stop applying low window size.
If you do not stop and set the low wssize all the time, the speed will drop catastrophically. If you do not stop and set the low wssize all the time, the speed will drop catastrophically.
Linux can overcome this using connbytes filter but other OS may not include similar filter. Linux can overcome this using connbytes filter but other OS may not include similar filter.
In http(s) case wssize stops after the first http request or TLS ClientHello. In http(s) case wssize stops after the first http request or TLS ClientHello unless `--wssize-forced-cutoff=0` is specified.
If you deal with a non-http(s) protocol you need `--wssize-cutoff`. It sets the threshold where wssize stops. If you deal with a non-http(s) protocol you need `--wssize-cutoff`. It sets the threshold where wssize stops.
@@ -567,6 +596,7 @@ Threshold can be prefixed with 'n' (packet number starting from 1), 'd' (data pa
's' (relative sequence number - sent by client bytes + 1). 's' (relative sequence number - sent by client bytes + 1).
If a http request or TLS ClientHello packet is detected wssize stops immediately ignoring wssize-cutoff option. If a http request or TLS ClientHello packet is detected wssize stops immediately ignoring wssize-cutoff option.
This action is called "forced wssize cutoff" and can disabled using `--wssize-forced-cutoff=0`.
If your protocol is prone to long inactivity, you should increase ESTABLISHED phase timeout using `--ctrack-timeouts`. If your protocol is prone to long inactivity, you should increase ESTABLISHED phase timeout using `--ctrack-timeouts`.
+44 -5
View File
@@ -1,4 +1,4 @@
# zapret v72 # zapret v72.3
# ВНИМАНИЕ, остерегайтесь мошенников # ВНИМАНИЕ, остерегайтесь мошенников
@@ -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)
- [МОДИФИКАЦИЯ ОРИГИНАЛА](#модификация-оригинала) - [МОДИФИКАЦИЯ ОРИГИНАЛА](#модификация-оригинала)
- [ДУБЛИКАТЫ](#дубликаты) - [ДУБЛИКАТЫ](#дубликаты)
@@ -183,11 +184,14 @@ dvtws, собираемый из тех же исходников (см. [док
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !) --wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !) --wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !)
--wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--wssize-forced-cutoff=0|1 ; 1(default)=автоматически отключать wssize в случае обнаружения известного протокола
--synack-split=[syn|synack|acksyn] ; выполнить tcp split handshake. вместо SYN,ACK отсылать только SYN, SYN+ACK или ACK+SYN --synack-split=[syn|synack|acksyn] ; выполнить tcp split handshake. вместо SYN,ACK отсылать только SYN, SYN+ACK или ACK+SYN
--orig-ttl=<int> ; модифицировать TTL оригинального пакета --orig-ttl=<int> ; модифицировать TTL оригинального пакета
--orig-ttl6=<int> ; модифицировать ipv6 hop limit оригинальных пакетов. если не указано, используется значение --orig-ttl --orig-ttl6=<int> ; модифицировать ipv6 hop limit оригинальных пакетов. если не указано, используется значение --orig-ttl
--orig-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +5:3-64. "0:0-0" или "-" отключает функцию --orig-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +5:3-64. "0:0-0" или "-" отключает функцию
--orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6 --orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
--orig-tcp-flags-set=<int|0xHEX|flaglist> ; устанавливать указанные tcp флаги (flags |= value). число , либо список через запятую : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--orig-tcp-flags-unset=<int|0xHEX|flaglist> ; удалять указанные tcp флаги (flags &= ~value)
--orig-mod-start=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N --orig-mod-start=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
--orig-mod-cutoff=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --orig-mod-cutoff=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--dup=<int> ; высылать N дубликатов до оригинала --dup=<int> ; высылать N дубликатов до оригинала
@@ -196,10 +200,13 @@ dvtws, собираемый из тех же исходников (см. [док
--dup-ttl6=<int> ; модифицировать ipv6 hop limit дубликатов. если не указано, используется значение --dup-ttl --dup-ttl6=<int> ; модифицировать ipv6 hop limit дубликатов. если не указано, используется значение --dup-ttl
--dup-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +1:3-64. "0:0-0" или "-" отключает функцию --dup-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +1:3-64. "0:0-0" или "-" отключает функцию
--dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6 --dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
--dup-tcp-flags-set=<int|0xHEX|flaglist> ; устанавливать указанные tcp флаги (flags |= value). число , либо список через запятую : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--dup-tcp-flags-unset=<int|0xHEX|flaglist> ; удалять указанные tcp флаги (flags &= ~value)
--dup-fooling=<fooling> ; дополнительные методики как сделать, чтобы дубликат не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2 --dup-fooling=<fooling> ; дополнительные методики как сделать, чтобы дубликат не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2
--dup-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000 --dup-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000
--dup-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000 --dup-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
--dup-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000 --dup-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
--dup-ip-id=same|zero|seq|rnd ; режим назначения ip_id для пакетов dup
--dup-start=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N --dup-start=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
--dup-cutoff=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --dup-cutoff=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". --hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
@@ -207,12 +214,15 @@ 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
--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=[<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
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. "0:0-0" или "-" отключает функцию --dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. "0:0-0" или "-" отключает функцию
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6 --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
--dpi-desync-tcp-flags-set=<int|0xHEX|flaglist> ; устанавливать указанные tcp флаги (flags |= value). число , либо список через запятую : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--dpi-desync-tcp-flags-unset=<int|0xHEX|flaglist> ; удалять указанные tcp флаги (flags &= ~value)
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2 --dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты) --dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
--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
@@ -353,6 +363,10 @@ hex строка начинается с "0x". Имя файла можно пи
выяснено, что многие провайдерские NAT не отбрасывают эти пакеты, потому работает даже с внутренним провайдерским IP. выяснено, что многие провайдерские NAT не отбрасывают эти пакеты, потому работает даже с внутренним провайдерским IP.
Но linux NAT оно не пройдет, так что за домашним роутером эта техника скорее всего не сработает, но может сработать с него. Но linux NAT оно не пройдет, так что за домашним роутером эта техника скорее всего не сработает, но может сработать с него.
Может сработать и через роутер, если подключение по проводу, и на роутере включено аппаратное ускорение. Может сработать и через роутер, если подключение по проводу, и на роутере включено аппаратное ускорение.
* Манипуляция tcp флагами с помощью `--dpi-desync-tcp-flags-set` и `--dpi-desync-tcp-flags-unset`. Можно сделать инвалидное
сочетание флагов, которое сервер не примет, а DPI - примет. Например, установить SYN в фейках. Но это может работать не на всех серверах.
`datanoack` может быть заменен `--dpi-desync-tcp-flags-unset=ACK`.
Пакеты с инвалидными флагами могут отбрасываться, проходя через NAT.
* `ts` прибавляет к значению TSval таймштампа tcp значение ts increment (по умолчанию -600000). Сервера отбрасывают пакеты * `ts` прибавляет к значению TSval таймштампа tcp значение ts increment (по умолчанию -600000). Сервера отбрасывают пакеты
с TSval в определенных пределах. По практическим тестам инкремент должен быть где-то от -100 до -0x80000000. с TSval в определенных пределах. По практическим тестам инкремент должен быть где-то от -100 до -0x80000000.
timestamps генерирует клиентская ОС. В linux таймштампы включены по умолчанию, в windows выключены по умолчанию. timestamps генерирует клиентская ОС. В linux таймштампы включены по умолчанию, в windows выключены по умолчанию.
@@ -467,7 +481,7 @@ hex строка начинается с "0x". Имя файла можно пи
`altorder=1` шлет фрагменты в таком порядке, чтобы при последовательной сборке сегментов на DPI он получил полностью собранный оригинал запроса с подмененным хостом. `altorder=1` шлет фрагменты в таком порядке, чтобы при последовательной сборке сегментов на DPI он получил полностью собранный оригинал запроса с подмененным хостом.
Реальный хост идет отдельным сегментом уже после. То есть в этом варианте применяется разновидность disorder. Сервер принимает фрагменты с нарушенным порядком sequence. Реальный хост идет отдельным сегментом уже после. То есть в этом варианте применяется разновидность disorder. Сервер принимает фрагменты с нарушенным порядком sequence.
Опционально можно разрезать оригинальный фейк. Например, `--dpi-desync-hostfakesplit-midhost=midsld`. Позиция нарезки должна попадать внутрь хоста. Опционально можно разрезать оригинальный хост. Например, `--dpi-desync-hostfakesplit-midhost=midsld`. Позиция нарезки должна попадать внутрь хоста.
Многопакетные запросы поддерживаются только, если исходная нарезка пакетов не включает позиции имени хоста. В последнем случае дурение отменяется. Многопакетные запросы поддерживаются только, если исходная нарезка пакетов не включает позиции имени хоста. В последнем случае дурение отменяется.
Вариант `fakedsplit` имеет несколько альтернативных порядков нарезки - от 0 до 3. Режим задается в параметре `--dpi-desync-fakedsplit-mod=altorder=N`. Вариант `fakedsplit` имеет несколько альтернативных порядков нарезки - от 0 до 3. Режим задается в параметре `--dpi-desync-fakedsplit-mod=altorder=N`.
@@ -537,6 +551,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 и заключается
@@ -626,7 +661,7 @@ ipcache представляет собой структуру в памяти
DPI может отстать от потока, если ClientHello его удовлетворил и не проверять ServerHello. DPI может отстать от потока, если ClientHello его удовлетворил и не проверять ServerHello.
Тогда вам повезло. Вариант fake может сработать. Тогда вам повезло. Вариант fake может сработать.
Если же он не отстает и упорно проверяет ServerHello, то можно попробовать заставить сервер высылать ServerHello частями Если же он не отстает и упорно проверяет ServerHello, то можно попробовать заставить сервер высылать ServerHello частями
через параметр --wssize (см. conntrack). через параметр `--wssize` (см. conntrack).
Если и это не помогает, то сделать с этим что-либо вряд ли возможно без помощи со стороны сервера. Если и это не помогает, то сделать с этим что-либо вряд ли возможно без помощи со стороны сервера.
Лучшее решение - включить на сервере поддержку TLS 1.3. В нем сертификат сервера передается в зашифрованном виде. Лучшее решение - включить на сервере поддержку TLS 1.3. В нем сертификат сервера передается в зашифрованном виде.
Это рекомендация ко всем админам блокируемых сайтов. Включайте TLS 1.3. Так вы дадите больше возможностей преодолеть DPI. Это рекомендация ко всем админам блокируемых сайтов. Включайте TLS 1.3. Так вы дадите больше возможностей преодолеть DPI.
@@ -679,7 +714,8 @@ conntrack - простенький, он не писался с учетом в
Если вы имеете дело с не http(s), то вам потребуется параметр `--wssize-cutoff`. Он устанавливает предел, с которого действие Если вы имеете дело с не http(s), то вам потребуется параметр `--wssize-cutoff`. Он устанавливает предел, с которого действие
wssize прекращается. Префикс d перед номером означает учитывать только пакеты с data payload, префикс s - relative sequence number, wssize прекращается. Префикс d перед номером означает учитывать только пакеты с data payload, префикс s - relative sequence number,
проще говоря количество переданных клиентом байтов + 1. проще говоря количество переданных клиентом байтов + 1.
Если проскочит пакет с http request или TLS ClientHello, действие wssize прекращается сразу же, не дожидаясь wssize-cutoff. Если проскочит пакет с http request или TLS ClientHello, действие wssize прекращается сразу же, не дожидаясь wssize-cutoff,
если не указан параметр `--wssize-forced-cutoff=0`.
Если ваш протокол склонен к долгому бездействию, следует увеличить таймаут фазы ESTABLISHED через параметр `--ctrack-timeouts`. Если ваш протокол склонен к долгому бездействию, следует увеличить таймаут фазы ESTABLISHED через параметр `--ctrack-timeouts`.
Таймаут по умолчанию низкий - всего 5 минут. Таймаут по умолчанию низкий - всего 5 минут.
Не забывайте, что nfqws кормится приходящими на него пакетами. Если вы ограничили поступление пакетов через connbytes, Не забывайте, что nfqws кормится приходящими на него пакетами. Если вы ограничили поступление пакетов через connbytes,
@@ -1629,7 +1665,7 @@ LISTS_RELOAD=- отключает перезагрузку листов.
В системе запуска это обыграно следующим образом. В системе запуска это обыграно следующим образом.
Присутствуют 2 include списка : Присутствуют 2 include списка :
`ipset/zapret-hosts-users.txt.gz` или `ipset/zapret-hosts-users.txt`, `ipset/zapret-hosts-user.txt.gz` или `ipset/zapret-hosts-user.txt`,
`ipset/zapret-hosts.txt.gz` или `ipset/zapret-hosts.txt` `ipset/zapret-hosts.txt.gz` или `ipset/zapret-hosts.txt`
и 1 exclude список и 1 exclude список
`ipset/zapret-hosts-user-exclude.txt.gz` или `ipset/zapret-hosts-user-exclude.txt` `ipset/zapret-hosts-user-exclude.txt.gz` или `ipset/zapret-hosts-user-exclude.txt`
@@ -1780,6 +1816,7 @@ CURL_MAX_TIME_QUIC - время таймаута curl для quic. если не
CURL_MAX_TIME_DOH - время таймаута curl для DoH серверов CURL_MAX_TIME_DOH - время таймаута curl для DoH серверов
CURL_CMD=1 - показывать команды curl CURL_CMD=1 - показывать команды curl
CURL_OPT - дополнительные параметры curl. `-k` - игнор сертификатов. `-v` - подробный вывод протокола CURL_OPT - дополнительные параметры curl. `-k` - игнор сертификатов. `-v` - подробный вывод протокола
CURL_HTTPS_GET=1 - использовать метод GET вместо HEAD для https
DOMAINS - список тестируемых доменов через пробел DOMAINS - список тестируемых доменов через пробел
IPVS=4|6|46 - тестируемые версии ip протокола IPVS=4|6|46 - тестируемые версии ip протокола
ENABLE_HTTP=0|1 - включить тест plain http ENABLE_HTTP=0|1 - включить тест plain http
@@ -1803,6 +1840,8 @@ SECURE_DNS=0|1 - принудительно выключить или включ
DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера
DOH_SERVER - конкретный DoH URL, отказ от поиска DOH_SERVER - конкретный DoH URL, отказ от поиска
UNBLOCKED_DOM - незаблокированный домен, который используется для тестов IP block UNBLOCKED_DOM - незаблокированный домен, который используется для тестов IP block
MIN_TTL,MAX_TTL - пределы тестов с TTL. MAX_TTL=0 отключает тесты.
MIN_AUTOTTL_DELTA,MAX_AUTOTTL_DELTA - пределы тестов с autottl по дельте. MAX_AUTOTTL_DELTA=0 отключает тесты.
SIMULATE=1 - включить режим симуляции для отладки логики скрипта. отключаются реальные запросы через curl, заменяются рандомным результатом. SIMULATE=1 - включить режим симуляции для отладки логики скрипта. отключаются реальные запросы через curl, заменяются рандомным результатом.
SIM_SUCCESS_RATE=<percent> - вероятность успеха симуляции в процентах SIM_SUCCESS_RATE=<percent> - вероятность успеха симуляции в процентах
``` ```
+2 -2
View File
@@ -7,7 +7,7 @@ tpws is static binary. It doesn't need a distribution.
Install `WSL` : `dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all` Install `WSL` : `dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all`
Copy `binaries/x86_64/tpws_wsl.tgz` to the target system. From release copy `binaries/linux-x86_64/tpws_wsl.tgz` to the target system.
Run : `wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz` Run : `wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz`
Run tpws : `wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 <fooling_options>` Run tpws : `wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 <fooling_options>`
@@ -16,7 +16,7 @@ Configure socks as `127.0.0.1:1080` in a browser or another program.
Cleanup : `wsl --unregister tpws` Cleanup : `wsl --unregister tpws`
Tested in windows 10 build 19041 (20.04). Tested in windows 10 build 19041 (20.04) with WSL1.
`--oob` , `--mss` and `--disorder` do not work. `--oob` , `--mss` and `--disorder` do not work.
RST detection in autohostlist scheme may not work. RST detection in autohostlist scheme may not work.
+6 -2
View File
@@ -12,7 +12,7 @@ tpws в режиме socks можно запускать под более-ме
Установить WSL : Установить WSL :
`dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all` `dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all`
Скопировать на целевую систему `binaries/x86_64/tpws_wsl.tgz`. Из релиза скопировать на целевую систему `binaries/linux-x86_64/tpws_wsl.tgz`.
Выполнить : Выполнить :
`wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz` `wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz`
@@ -24,8 +24,12 @@ tpws в режиме socks можно запускать под более-ме
Удаление : `wsl --unregister tpws` Удаление : `wsl --unregister tpws`
> [!NOTE] > [!NOTE]
> Проверено на windows 10 build 19041 (20.04). > Проверено на windows 10 build 19041 (20.04) под WSL1. На WSL2 эти команды могут не сработать.
Если у вас есть WSL2, значит у вас есть работающая виртуалка с linux.
Если вы умеете с ней обращаться, tpws на ней запустить возможно без всяких проблем.
Возможные проблемы: Возможные проблемы:
- Не работают функции `--oob` и `--mss` из-за ограничений реализации WSL. - Не работают функции `--oob` и `--mss` из-за ограничений реализации WSL.
@@ -15,7 +15,6 @@ zapret_custom_daemons()
local opt="--qnum=$QNUM_DISCORD_MEDIA $NFQWS_OPT_DESYNC_DISCORD_MEDIA" local opt="--qnum=$QNUM_DISCORD_MEDIA $NFQWS_OPT_DESYNC_DISCORD_MEDIA"
do_nfqws $1 $DNUM_DISCORD_MEDIA "$opt" do_nfqws $1 $DNUM_DISCORD_MEDIA "$opt"
} }
# size = 156 (8 udp header + 148 payload) && payload starts with 0x01000000
zapret_custom_firewall() zapret_custom_firewall()
{ {
# $1 - 1 - run, 0 - stop # $1 - 1 - run, 0 - stop
@@ -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
}
@@ -14,7 +14,6 @@ zapret_custom_daemons()
local opt="--qnum=$QNUM_STUN4ALL $NFQWS_OPT_DESYNC_STUN" local opt="--qnum=$QNUM_STUN4ALL $NFQWS_OPT_DESYNC_STUN"
do_nfqws $1 $DNUM_STUN4ALL "$opt" do_nfqws $1 $DNUM_STUN4ALL "$opt"
} }
# size = 156 (8 udp header + 148 payload) && payload starts with 0x01000000
zapret_custom_firewall() zapret_custom_firewall()
{ {
# $1 - 1 - run, 0 - stop # $1 - 1 - run, 0 - stop
@@ -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
@@ -3,6 +3,7 @@
172.16.0.0/12 172.16.0.0/12
192.168.0.0/16 192.168.0.0/16
169.254.0.0/16 169.254.0.0/16
100.64.0.0/10
::1 ::1
fc00::/7 fc00::/7
fe80::/10 fe80::/10
+5 -3
View File
@@ -5,9 +5,11 @@ int aes_gcm_crypt(int mode, uint8_t *output, const uint8_t *input, size_t input_
int ret = 0; int ret = 0;
gcm_context ctx; gcm_context ctx;
gcm_setkey(&ctx, key, (const uint)key_len); if (!(ret = gcm_setkey(&ctx, key, (const uint)key_len)))
ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len); {
gcm_zero_ctx(&ctx); ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len);
gcm_zero_ctx(&ctx);
}
return ret; return ret;
} }
+2 -2
View File
@@ -367,7 +367,7 @@ int aes_setkey(aes_context *ctx, // AES context provided by our caller
} }
#if AES_DECRYPTION #if AES_DECRYPTION
if (mode == DECRYPT) // expand our key for encryption or decryption if (mode == AES_DECRYPT) // expand our key for encryption or decryption
return(aes_set_decryption_key(ctx, key, keysize)); return(aes_set_decryption_key(ctx, key, keysize));
else /* ENCRYPT */ else /* ENCRYPT */
#endif /* AES_DECRYPTION */ #endif /* AES_DECRYPTION */
@@ -399,7 +399,7 @@ int aes_cipher(aes_context *ctx,
#if AES_DECRYPTION // whether AES decryption is supported #if AES_DECRYPTION // whether AES decryption is supported
if (ctx->mode == DECRYPT) if (ctx->mode == AES_DECRYPT)
{ {
for (i = (ctx->rounds >> 1) - 1; i > 0; i--) for (i = (ctx->rounds >> 1) - 1; i > 0; i--)
{ {
+3 -2
View File
@@ -246,7 +246,7 @@ int gcm_setkey(gcm_context *ctx, // pointer to caller-provided gcm context
* *
******************************************************************************/ ******************************************************************************/
int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
int mode, // GCM_ENCRYPT or GCM_DECRYPT int mode, // AES_ENCRYPT or AES_DECRYPT
const uchar *iv, // pointer to initialization vector const uchar *iv, // pointer to initialization vector
size_t iv_len, // IV length in bytes (should == 12) size_t iv_len, // IV length in bytes (should == 12)
const uchar *add, // ptr to additional AEAD data (NULL if none) const uchar *add, // ptr to additional AEAD data (NULL if none)
@@ -288,6 +288,7 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
for (i = 0; i < 16; i++) ctx->y[i] ^= work_buf[i]; for (i = 0; i < 16; i++) ctx->y[i] ^= work_buf[i];
gcm_mult(ctx, ctx->y, ctx->y); gcm_mult(ctx, ctx->y, ctx->y);
} }
if ((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ctx->base_ectr)) != 0) if ((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ctx->base_ectr)) != 0)
return(ret); return(ret);
@@ -427,7 +428,7 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
******************************************************************************/ ******************************************************************************/
int gcm_crypt_and_tag( int gcm_crypt_and_tag(
gcm_context *ctx, // gcm context with key already setup gcm_context *ctx, // gcm context with key already setup
int mode, // cipher direction: GCM_ENCRYPT or GCM_DECRYPT int mode, // cipher direction: AES_ENCRYPT or AES_DECRYPT
const uchar *iv, // pointer to the 12-byte initialization vector const uchar *iv, // pointer to the 12-byte initialization vector
size_t iv_len, // byte length if the IV. should always be 12 size_t iv_len, // byte length if the IV. should always be 12
const uchar *add, // pointer to the non-ciphered additional data const uchar *add, // pointer to the non-ciphered additional data
+25 -6
View File
@@ -111,7 +111,7 @@ bool tcp_has_sack(struct tcphdr *tcp)
// n prefix (nsport, nwsize) means network byte order // n prefix (nsport, nwsize) means network byte order
static void fill_tcphdr( static void fill_tcphdr(
struct tcphdr *tcp, uint32_t fooling, uint8_t tcp_flags, struct tcphdr *tcp, uint32_t fooling, uint16_t tcp_flags,
bool sack, bool sack,
uint16_t nmss, uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
@@ -142,7 +142,8 @@ static void fill_tcphdr(
tcp->th_off = 5; tcp->th_off = 5;
if ((fooling & FOOL_DATANOACK) && !(tcp_flags & (TH_SYN|TH_RST)) && data_len) if ((fooling & FOOL_DATANOACK) && !(tcp_flags & (TH_SYN|TH_RST)) && data_len)
tcp_flags &= ~TH_ACK; tcp_flags &= ~TH_ACK;
*((uint8_t*)tcp+13)= tcp_flags; tcp->th_flags = (uint8_t)tcp_flags;
tcp->th_x2 = (tcp_flags>>8) & 0xF;
tcp->th_win = nwsize; tcp->th_win = nwsize;
if (nmss) if (nmss)
{ {
@@ -231,7 +232,7 @@ static void fill_ip6hdr(struct ip6_hdr *ip6, const struct in6_addr *src, const s
bool prepare_tcp_segment4( bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t tcp_flags, uint16_t tcp_flags,
bool sack, bool sack,
uint16_t nmss, uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
@@ -271,7 +272,7 @@ bool prepare_tcp_segment4(
bool prepare_tcp_segment6( bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst, const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags, uint16_t tcp_flags,
bool sack, bool sack,
uint16_t nmss, uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
@@ -358,7 +359,7 @@ bool prepare_tcp_segment6(
bool prepare_tcp_segment( bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags, uint16_t tcp_flags,
bool sack, bool sack,
uint16_t nmss, uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
@@ -681,6 +682,20 @@ bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
return false; return false;
} }
void apply_tcp_flags(struct tcphdr *tcp, uint16_t fl)
{
if (tcp)
{
tcp->th_flags = (uint8_t)fl;
tcp->th_x2 = (fl>>8) & 0xF;
}
}
uint16_t get_tcp_flags(const struct tcphdr *tcp)
{
return tcp->th_flags | (tcp->th_x2<<8);
}
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport) void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport)
{ {
@@ -921,7 +936,6 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
{ {
case 0: // Hop-by-Hop Options case 0: // Hop-by-Hop Options
case 43: // routing case 43: // routing
case 51: // authentication
case 60: // Destination Options case 60: // Destination Options
case 135: // mobility case 135: // mobility
case 139: // Host Identity Protocol Version v2 case 139: // Host Identity Protocol Version v2
@@ -932,6 +946,11 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
case 44: // fragment. length fixed to 8, hdrlen field defined as reserved case 44: // fragment. length fixed to 8, hdrlen field defined as reserved
hdrlen = 8; hdrlen = 8;
break; break;
case 51: // authentication
// special case. length in ah header is in 32-bit words minus 2
if (*len < 2) return; // error
hdrlen = 8 + ((*data)[1] << 2);
break;
case 59: // no next header case 59: // no next header
return; // error return; // error
default: default:
+5 -3
View File
@@ -69,7 +69,7 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
// seq and wsize have network byte order // seq and wsize have network byte order
bool prepare_tcp_segment4( bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t tcp_flags, uint16_t tcp_flags,
bool sack, bool sack,
uint16_t nmss, uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
@@ -88,7 +88,7 @@ bool prepare_tcp_segment4(
uint8_t *buf, size_t *buflen); uint8_t *buf, size_t *buflen);
bool prepare_tcp_segment6( bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst, const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags, uint16_t tcp_flags,
bool sack, bool sack,
uint16_t nmss, uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
@@ -105,7 +105,7 @@ bool prepare_tcp_segment6(
uint8_t *buf, size_t *buflen); uint8_t *buf, size_t *buflen);
bool prepare_tcp_segment( bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags, uint16_t tcp_flags,
bool sack, bool sack,
uint16_t nmss, uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
@@ -178,6 +178,8 @@ bool ip_frag(
uint8_t *pkt2, size_t *pkt2_size); uint8_t *pkt2, size_t *pkt2_size);
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl); bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl);
uint16_t get_tcp_flags(const struct tcphdr *tcp);
void apply_tcp_flags(struct tcphdr *tcp, uint16_t fl);
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport); void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport);
void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst); void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
+185 -89
View File
@@ -835,25 +835,46 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
} }
static uint16_t IP4_IP_ID_FIX(const struct ip *ip) static uint16_t IP4_IP_ID_FIX(const struct ip *ip, t_ip_id_mode mode)
{ {
return ip ? ip->ip_id ? ip->ip_id : (uint16_t)random() : 0; if (ip)
}
static uint16_t IP4_IP_ID_ADD(uint16_t ip_id, uint16_t inc)
{
if (ip_id)
{ {
ip_id += net16_add(ip_id, inc); switch(mode)
if (!ip_id) ip_id = net16_add(ip_id, ((int16_t)inc) < 0 ? -1 : 1); // do not allow zero {
case IPID_SEQ:
case IPID_SEQ_GROUP:
return ip->ip_id ? ip->ip_id : (uint16_t)random();
case IPID_SAME:
return ip->ip_id;
case IPID_RND:
return (uint16_t)(random()%0xFFFF + 1);
default:
break;
}
} }
return ip_id; return 0;
} }
#define IP4_IP_ID_ADD(ip_id,inc) (ip_id ? net16_add(ip_id,inc) : 0) static uint16_t IP4_IP_ID_ADD(uint16_t ip_id, uint16_t inc, t_ip_id_mode mode)
#define IP4_IP_ID_NEXT(ip_id) IP4_IP_ID_ADD(ip_id,+1) {
#define IP4_IP_ID_PREV(ip_id) IP4_IP_ID_ADD(ip_id,-1) switch(mode)
//#define IP4_IP_ID_FIX(x) 0 {
//#define IP4_IP_ID_NEXT(ip_id) ip_id case IPID_SEQ_GROUP:
//#define IP4_IP_ID_PREV(ip_id) ip_id 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
}
case IPID_SAME:
return ip_id;
case IPID_RND:
return (uint16_t)(random()%0xFFFF + 1);;
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)
@@ -911,24 +932,52 @@ static bool runtime_tls_mod(int fake_n, const struct fake_tls_mod_cache *modcach
return b; return b;
} }
uint8_t orig_mod(const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis) static bool rewrite_tcp_flags(uint16_t *flags, uint16_t unset, uint16_t set, const char *what)
{ {
uint8_t ttl, ttl_orig; if (set || unset)
ttl = (ctrack && ctrack->orig_autottl) ? ctrack->orig_autottl : dis->ip6 ? dp->orig_mod_ttl6 : dp->orig_mod_ttl;
if (ttl && check_orig_mod_interval(dp, ctrack))
{ {
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; uint16_t fl_new = *flags & ~unset | set;
if (ttl_orig != ttl) if (fl_new!=*flags)
{ {
DLOG("rewrite original packet ttl %u => %u\n", ttl_orig, ttl); DLOG("rewrite %s tcp flags 0x%03X => 0x%03X\n", what, *flags, fl_new);
rewrite_ttl(dis->ip, dis->ip6, ttl); *flags = fl_new;
return true; return true;
} }
} }
return false; return false;
} }
static uint8_t orig_mod(const struct desync_profile *dp, const t_ctrack *ctrack, struct dissect *dis)
{
uint8_t ttl, ttl_orig;
bool bModded = false;
if (check_orig_mod_interval(dp, ctrack))
{
ttl = (ctrack && ctrack->orig_autottl) ? ctrack->orig_autottl : dis->ip6 ? dp->orig_mod_ttl6 : dp->orig_mod_ttl;
if (ttl)
{
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
if (ttl_orig != ttl)
{
DLOG("rewrite original packet ttl %u => %u\n", ttl_orig, ttl);
rewrite_ttl(dis->ip, dis->ip6, ttl);
bModded = true;
}
}
if (dis->tcp)
{
uint16_t flags = get_tcp_flags(dis->tcp);
if (rewrite_tcp_flags(&flags, dp->orig_tcp_flags_unset, dp->orig_tcp_flags_set, "original"))
{
apply_tcp_flags(dis->tcp,flags);
bModded = true;
}
}
}
return bModded;
}
static bool orig_send_rewrite( static bool orig_send_rewrite(
uint32_t fwmark, const char *ifout, const struct sockaddr *dst, uint32_t fwmark, const char *ifout, const struct sockaddr *dst,
uint8_t ttl_orig, uint8_t ttl_fake, const struct desync_profile *dp, const struct dissect *dis) uint8_t ttl_orig, uint8_t ttl_fake, const struct desync_profile *dp, const struct dissect *dis)
@@ -942,6 +991,7 @@ static bool orig_send_rewrite(
else else
DLOG("sending %u dups with ttl rewrite %u => %u\n", dp->dup_repeats, ttl_orig, ttl_fake); DLOG("sending %u dups with ttl rewrite %u => %u\n", dp->dup_repeats, ttl_orig, ttl_fake);
rewrite_ttl(dis->ip, dis->ip6, ttl_fake); rewrite_ttl(dis->ip, dis->ip6, ttl_fake);
// send dups // send dups
for (k = 0; k < dp->dup_repeats; k++) for (k = 0; k < dp->dup_repeats; k++)
{ {
@@ -965,9 +1015,10 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
size_t len; size_t len;
uint16_t ip_id, nmss; uint16_t ip_id, nmss;
struct sockaddr_storage src, dst; struct sockaddr_storage src, dst;
uint8_t ttl_orig, ttl_fake, flags_orig, scale_factor; uint8_t ttl_orig, ttl_dup, scale_factor;
uint16_t flags_dup;
uint32_t *timestamps; uint32_t *timestamps;
bool sack, DF; bool sack, DF, bTF;
extract_endpoints(dis->ip, dis->ip6, dis->tcp, NULL, &src, &dst); extract_endpoints(dis->ip, dis->ip6, dis->tcp, NULL, &src, &dst);
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
@@ -976,40 +1027,43 @@ static bool tcp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
if (dp->dup_repeats && check_dup_interval(dp, ctrack)) if (dp->dup_repeats && check_dup_interval(dp, ctrack))
{ {
ttl_fake = (ctrack && ctrack->dup_autottl) ? ctrack->dup_autottl : (dis->ip6 ? (dp->dup_ttl6 ? dp->dup_ttl6 : ttl_orig) : (dp->dup_ttl ? dp->dup_ttl : ttl_orig)); ttl_dup = (ctrack && ctrack->dup_autottl) ? ctrack->dup_autottl : (dis->ip6 ? (dp->dup_ttl6 ? dp->dup_ttl6 : ttl_orig) : (dp->dup_ttl ? dp->dup_ttl : ttl_orig));
if (dp->dup_fooling_mode) flags_dup = dis->tcp->th_flags;
bTF = rewrite_tcp_flags(&flags_dup, dp->dup_tcp_flags_unset, dp->dup_tcp_flags_set, "dup");
if (bTF || dp->dup_fooling_mode || (dis->ip && dp->dup_ip_id_mode!=IPID_SAME))
{ {
flags_orig = *((uint8_t*)dis->tcp + 13);
scale_factor = tcp_find_scale_factor(dis->tcp); scale_factor = tcp_find_scale_factor(dis->tcp);
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,
flags_orig, sack, nmss, flags_dup, sack, nmss,
dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
ip_has_df(dis->ip), ttl_fake, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6), ip_has_df(dis->ip), ttl_dup, IP4_TOS(dis->ip), ip_id, IP6_FLOW(dis->ip6),
dp->dup_fooling_mode, dp->dup_ts_increment, dp->dup_badseq_increment, dp->dup_badseq_ack_increment, dp->dup_fooling_mode, dp->dup_ts_increment, dp->dup_badseq_increment, dp->dup_badseq_ack_increment,
dis->data_payload, dis->len_payload, pkt, &len)) dis->data_payload, dis->len_payload, pkt, &len))
{ {
DLOG_ERR("dup: packet reconstruct failed\n"); DLOG_ERR("dup: packet reconstruct failed\n");
return false; return false;
} }
DLOG("sending %u dups with packet reconstruct. ttl %u => %u\n", dp->dup_repeats, ttl_orig, ttl_fake); DLOG("sending %u dups with packet reconstruct. ttl %u => %u\n", dp->dup_repeats, ttl_orig, ttl_dup);
// send dups // send dups
for (k = 0; k < dp->dup_repeats; k++) for (k = 0; k < dp->dup_repeats; k++)
{ {
if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, pkt, len)) if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, pkt, len))
return false; return false;
ip_id = IP4_IP_ID_NEXT(ip_id,dp->dup_ip_id_mode);
if (dis->ip) ((struct ip*)pkt)->ip_id = ip_id;
} }
} }
else else
{ {
if (!orig_send_rewrite(fwmark, ifout, (struct sockaddr *)&dst, ttl_orig, ttl_fake, dp, dis)) if (!orig_send_rewrite(fwmark, ifout, (struct sockaddr *)&dst, ttl_orig, ttl_dup, dp, dis))
return false; return false;
} }
if (dp->dup_replace) if (dp->dup_replace)
@@ -1053,9 +1107,9 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
{ {
ttl_fake = (ctrack && ctrack->dup_autottl) ? ctrack->dup_autottl : (dis->ip6 ? (dp->dup_ttl6 ? dp->dup_ttl6 : ttl_orig) : (dp->dup_ttl ? dp->dup_ttl : ttl_orig)); ttl_fake = (ctrack && ctrack->dup_autottl) ? ctrack->dup_autottl : (dis->ip6 ? (dp->dup_ttl6 ? dp->dup_ttl6 : ttl_orig) : (dp->dup_ttl ? dp->dup_ttl : ttl_orig));
if (dp->dup_fooling_mode) if (dp->dup_fooling_mode || (dis->ip && dp->dup_ip_id_mode!=IPID_SAME))
{ {
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,
@@ -1074,6 +1128,8 @@ static bool udp_orig_send(uint8_t verdict, uint32_t fwmark, const char *ifout, c
{ {
if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, pkt, len)) if (!rawsend((struct sockaddr *)&dst, fwmark, ifout, pkt, len))
return false; return false;
ip_id = IP4_IP_ID_NEXT(ip_id,dp->dup_ip_id_mode);
if (dis->ip) ((struct ip*)pkt)->ip_id = ip_id;
} }
} }
else else
@@ -1118,7 +1174,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
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], pkt3[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, pkt3_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, scale_factor;
uint32_t *timestamps; uint32_t *timestamps;
bool bSack, DF; bool bSack, DF;
uint16_t nmss; uint16_t nmss;
@@ -1149,12 +1205,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
DLOG("using cached desync profile %d\n", dp->n); DLOG("using cached desync profile %d\n", dp->n);
else if (!ctrack_replay->dp_search_complete) else if (!ctrack_replay->dp_search_complete)
{ {
if (!ctrack_replay->hostname && !bReverse)
{
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &ctrack_replay->hostname_is_ip) && *host)
if (!(ctrack_replay->hostname = strdup(host)))
DLOG_ERR("strdup(host): out of memory\n");
}
dp = ctrack_replay->dp = dp_find(&params.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->hostname_is_ip, ctrack_replay->l7proto, ssid, NULL, NULL, NULL); dp = ctrack_replay->dp = dp_find(&params.desync_profiles, IPPROTO_TCP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->hostname_is_ip, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
ctrack_replay->dp_search_complete = true; ctrack_replay->dp_search_complete = true;
} }
@@ -1338,7 +1388,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");
@@ -1369,11 +1419,15 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim; ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
ttl_fake = (ctrack_replay && ctrack_replay->desync_autottl) ? ctrack_replay->desync_autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig)); ttl_fake = (ctrack_replay && ctrack_replay->desync_autottl) ? ctrack_replay->desync_autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig));
flags_orig = *((uint8_t*)dis->tcp + 13); uint16_t flags_orig = get_tcp_flags(dis->tcp);
scale_factor = tcp_find_scale_factor(dis->tcp); scale_factor = tcp_find_scale_factor(dis->tcp);
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))
@@ -1383,7 +1437,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))
{ {
@@ -1407,11 +1461,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))
@@ -1438,7 +1493,6 @@ 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 = IP4_IP_ID_FIX(dis->ip);
bool bHaveHost = false, bHostIsIp = false; bool bHaveHost = false, bHostIsIp = false;
t_l7proto l7proto = UNKNOWN; t_l7proto l7proto = UNKNOWN;
@@ -1464,7 +1518,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
// we do not reassemble http // we do not reassemble http
reasm_orig_cancel(ctrack); reasm_orig_cancel(ctrack);
forced_wssize_cutoff(ctrack); if (!dp->wssize_no_forced_cutoff) forced_wssize_cutoff(ctrack);
bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host)); bHaveHost = HttpExtractHost(rdata_payload, rlen_payload, host, sizeof(host));
if (!bHaveHost) if (!bHaveHost)
@@ -1522,7 +1576,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
DLOG("req retrans : seq interval %u-%u\n", ctrack->req_seq_start, ctrack->req_seq_end); DLOG("req retrans : seq interval %u-%u\n", ctrack->req_seq_start, ctrack->req_seq_end);
ctrack->req_seq_finalized |= bReqFull; ctrack->req_seq_finalized |= bReqFull;
} }
if (bReqFull || ReasmIsEmpty(&ctrack->reasm_orig)) forced_wssize_cutoff(ctrack); if (!dp->wssize_no_forced_cutoff && (bReqFull || ReasmIsEmpty(&ctrack->reasm_orig))) forced_wssize_cutoff(ctrack);
if (!ReasmIsEmpty(&ctrack->reasm_orig)) if (!ReasmIsEmpty(&ctrack->reasm_orig))
{ {
@@ -1629,6 +1683,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)
{ {
@@ -1646,6 +1701,8 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
goto send_orig; goto send_orig;
} }
} }
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
ttl_fake = (ctrack_replay && ctrack_replay->desync_autottl) ? ctrack_replay->desync_autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig));
} }
} }
else if (ctrack_replay) else if (ctrack_replay)
@@ -1686,7 +1743,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
DLOG("applying tampering to unknown protocol\n"); DLOG("applying tampering to unknown protocol\n");
} }
ttl_fake = (ctrack_replay && ctrack_replay->desync_autottl) ? ctrack_replay->desync_autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig));
if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase || dp->methodeol) && HttpFindHost(&phost, dis->data_payload, dis->len_payload)) if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase || dp->methodeol) && HttpFindHost(&phost, dis->data_payload, dis->len_payload))
{ {
if (dp->hostcase) if (dp->hostcase)
@@ -1889,6 +1945,10 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
seqovl_pos = 0; seqovl_pos = 0;
uint32_t fooling_orig = FOOL_NONE; uint32_t fooling_orig = FOOL_NONE;
uint16_t flags_fake = flags_orig;
rewrite_tcp_flags(&flags_fake, dp->desync_tcp_flags_unset, dp->desync_tcp_flags_set, "desync");
switch (dp->desync_mode) switch (dp->desync_mode)
{ {
case DESYNC_FAKE_KNOWN: case DESYNC_FAKE_KNOWN:
@@ -1929,7 +1989,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
fake_size = fake_item->size - 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, htonl(sequence), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_fake, 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_size, pkt1, &pkt1_len)) fake_data, fake_size, pkt1, &pkt1_len))
@@ -1944,7 +2004,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); ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
if (dp->tcp_mod.seq) sequence += fake_size; if (dp->tcp_mod.seq) sequence += fake_size;
} }
} }
@@ -1968,7 +2028,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); ip_id = IP4_IP_ID_NEXT(ip_id,dp->ip_id_mode);
bFake = true; bFake = true;
break; break;
case DESYNC_HOPBYHOP: case DESYNC_HOPBYHOP:
@@ -2038,7 +2098,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, pos_host, pkt1, &pkt1_len)) seg, pos_host, 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 hostfakesplit before_host part 0-%zu len=%zu : ", pos_host - 1, pos_host); 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"); hexdump_limited_dlog(seg, pos_host, 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))
@@ -2087,20 +2147,20 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
// pkt2: fake_host segment // pkt2: fake_host segment
pkt2_len = sizeof(pkt2); pkt2_len = sizeof(pkt2);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_fake, false, 0,
net32_add(dis->tcp->th_seq, pos_host), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, 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), 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,
fakehost, host_size, pkt2, &pkt2_len)) fakehost, host_size, pkt2, &pkt2_len))
goto send_orig_clean; 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); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
goto send_orig_clean; goto send_orig_clean;
ip_id_after_host = IP4_IP_ID_NEXT(ip_id); 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); 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: after_host segment
pkt3_len = sizeof(pkt3); pkt3_len = sizeof(pkt3);
@@ -2129,6 +2189,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 + pos_host, sz, pkt1, &pkt1_len)) seg + pos_host, sz, pkt1, &pkt1_len))
goto send_orig_clean; 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); 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"); hexdump_limited_dlog(seg + pos_host, sz, PKTDATA_MAXDUMP); DLOG("\n");
@@ -2139,7 +2200,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
{ {
sz = pos_endhost - pos_split_host; sz = pos_endhost - pos_split_host;
pkt1_len = sizeof(pkt1); pkt1_len = sizeof(pkt1);
ip_id = IP4_IP_ID_NEXT(ip_id);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, 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, net32_add(dis->tcp->th_seq, pos_split_host), dis->tcp->th_ack,
dis->tcp->th_win, scale_factor, timestamps, dis->tcp->th_win, scale_factor, timestamps,
@@ -2147,6 +2207,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 + pos_split_host, sz, pkt1, &pkt1_len)) seg + pos_split_host, sz, pkt1, &pkt1_len))
goto send_orig_clean; 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); 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"); hexdump_limited_dlog(seg + pos_split_host, sz, 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))
@@ -2155,11 +2216,21 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (dp->hfs_mod.ordering == 0) 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); 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"); 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)) if (!rawsend_rep(dp->desync_repeats, (struct sockaddr *)&dst, desync_fwmark, ifout, pkt2, pkt2_len))
goto send_orig_clean; 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); 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"); 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)) if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout, pkt3, pkt3_len))
@@ -2168,7 +2239,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
free(fakehost); free(fakehost);
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_after_host); if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_after_host,dp->ip_id_mode);
return VERDICT_DROP; return VERDICT_DROP;
send_orig_clean: send_orig_clean:
@@ -2227,7 +2298,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))
@@ -2266,7 +2337,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (replay && ctrack_replay->ip_id) ip_id = ctrack_replay->ip_id; 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); 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--)
{ {
@@ -2305,7 +2376,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))
@@ -2314,7 +2385,7 @@ 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); if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id_end,dp->ip_id_mode);
return VERDICT_DROP; return VERDICT_DROP;
} }
@@ -2344,7 +2415,6 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n", seqovl_pos, split_pos); DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n", seqovl_pos, split_pos);
else else
seqovl = seqovl_pos; seqovl = seqovl_pos;
ip_id = IP4_IP_ID_NEXT(ip_id);
} }
else else
{ {
@@ -2372,7 +2442,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
} }
fakeseg2_len = sizeof(fakeseg2); fakeseg2_len = sizeof(fakeseg2);
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_fake, 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, fakeseg2, &fakeseg2_len)) pat + split_pos, dis->len_payload - split_pos, fakeseg2, &fakeseg2_len))
@@ -2380,6 +2450,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (order == 0) 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))
@@ -2392,6 +2463,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,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))
@@ -2399,6 +2471,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (order <= 1) if (order <= 1)
{ {
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
{
if (dis->ip) ((struct ip*)fakeseg2)->ip_id = 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))
@@ -2407,14 +2484,13 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (split_pos) if (split_pos)
{ {
ip_id = IP4_IP_ID_PREV(ip_id);
seg_len = sizeof(fakeseg); seg_len = sizeof(fakeseg);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, false, 0, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps, if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_fake, 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;
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))
@@ -2426,6 +2502,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,
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_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))
@@ -2433,6 +2510,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (order <= 2) if (order <= 2)
{ {
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
{
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))
@@ -2440,7 +2522,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
} }
} }
if (replay) ctrack_replay->ip_id = IP4_IP_ID_NEXT(ip_id); if (replay) ctrack_replay->ip_id = ip_id;
return VERDICT_DROP; return VERDICT_DROP;
} }
@@ -2472,7 +2554,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
} }
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_fake, 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, &fakeseg_len)) pat, split_pos, fakeseg, &fakeseg_len))
@@ -2480,6 +2562,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (order == 0) 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))
@@ -2516,7 +2599,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))
@@ -2536,6 +2619,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
#endif #endif
if (order <= 1) if (order <= 1)
{ {
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
{
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 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))
@@ -2545,11 +2633,12 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (split_pos < dis->len_payload) 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_fake, 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;
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))
@@ -2561,7 +2650,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,
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))
@@ -2569,6 +2658,11 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (order <= 2) if (order <= 2)
{ {
if (dp->ip_id_mode!=IPID_SEQ_GROUP)
{
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))
@@ -2581,7 +2675,9 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
return VERDICT_DROP; return VERDICT_DROP;
} }
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);
@@ -2620,6 +2716,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:
@@ -2641,7 +2739,7 @@ unsplitted_part:
{ {
DLOG("changing ip_id of unsplitted part\n"); DLOG("changing ip_id of unsplitted part\n");
dis->ip->ip_id = ctrack_replay->ip_id; dis->ip->ip_id = ctrack_replay->ip_id;
ctrack_replay->ip_id = IP4_IP_ID_NEXT(ctrack_replay->ip_id); ctrack_replay->ip_id = IP4_IP_ID_NEXT(ctrack_replay->ip_id,dp->ip_id_mode);
return VERDICT_MODIFY; return VERDICT_MODIFY;
} }
goto send_orig; goto send_orig;
@@ -2707,12 +2805,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
DLOG("using cached desync profile %d\n", dp->n); DLOG("using cached desync profile %d\n", dp->n);
else if (!ctrack_replay->dp_search_complete) else if (!ctrack_replay->dp_search_complete)
{ {
if (!ctrack_replay->hostname && !bReverse)
{
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &ctrack_replay->hostname_is_ip) && *host)
if (!(ctrack_replay->hostname = strdup(host)))
DLOG_ERR("strdup(host): out of memory\n");
}
dp = ctrack_replay->dp = dp_find(&params.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->hostname_is_ip, ctrack_replay->l7proto, ssid, NULL, NULL, NULL); dp = ctrack_replay->dp = dp_find(&params.desync_profiles, IPPROTO_UDP, (struct sockaddr *)&dst, ctrack_replay->hostname, ctrack_replay->hostname_is_ip, ctrack_replay->l7proto, ssid, NULL, NULL, NULL);
ctrack_replay->dp_search_complete = true; ctrack_replay->dp_search_complete = true;
} }
@@ -2799,14 +2891,16 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
} }
uint32_t desync_fwmark = fwmark | params.desync_fwmark; uint32_t desync_fwmark = fwmark | params.desync_fwmark;
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
DF = ip_has_df(dis->ip); DF = ip_has_df(dis->ip);
if (dis->len_payload) if (dis->len_payload)
{ {
struct blob_collection_head *fake; struct blob_collection_head *fake;
bool bHaveHost = false, bHostIsIp = false; bool bHaveHost = false, bHostIsIp = false;
uint16_t ip_id = IP4_IP_ID_FIX(dis->ip); 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))
{ {
@@ -3055,6 +3149,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)
{ {
@@ -3091,7 +3186,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
if (ctrack_replay->hostname_ah_check) if (ctrack_replay->hostname_ah_check)
{ {
// first request is not retrans // first request is not retrans
if (!bDiscoveredHostname) if (!bDiscoveredHostname && !reasm_offset)
process_retrans_fail(ctrack_replay, IPPROTO_UDP, (struct sockaddr*)&src); process_retrans_fail(ctrack_replay, IPPROTO_UDP, (struct sockaddr*)&src);
} }
} }
@@ -3123,6 +3218,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
break; break;
} }
ttl_orig = dis->ip ? dis->ip->ip_ttl : dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim;
ttl_fake = (ctrack_replay && ctrack_replay->desync_autottl) ? ctrack_replay->desync_autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig)); ttl_fake = (ctrack_replay && ctrack_replay->desync_autottl) ? ctrack_replay->desync_autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig));
uint32_t fooling_orig = FOOL_NONE; uint32_t fooling_orig = FOOL_NONE;
@@ -3170,7 +3266,7 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
hexdump_limited_dlog(fake_data, fake_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;
} }
@@ -3252,8 +3348,6 @@ static uint8_t dpi_desync_udp_packet_play(bool replay, size_t reasm_offset, uint
uint8_t *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);
@@ -3286,6 +3380,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:
+164 -5
View File
@@ -1303,6 +1303,63 @@ static bool parse_strlist(char *opt, struct str_list_head *list)
return true; return true;
} }
static bool parse_tcpflags(char *opt, uint16_t *fl)
{
unsigned int u;
char *e, *p, c;
if (sscanf(optarg, "0x%X", &u)<=0 && sscanf(optarg, "%u", &u)<=0)
{
*fl=0;
for (p = opt; p; )
{
if ((e = strchr(p, ',')))
{
c = *e;
*e = 0;
}
if (!strcasecmp(p, "FIN"))
*fl |= TH_FIN;
else if (!strcasecmp(p, "SYN"))
*fl |= TH_SYN;
else if (!strcasecmp(p, "RST"))
*fl |= TH_RST;
else if (!strcasecmp(p, "PSH") || !strcasecmp(p, "PUSH"))
*fl |= TH_PUSH;
else if (!strcasecmp(p, "ACK"))
*fl |= TH_ACK;
else if (!strcasecmp(p, "URG"))
*fl |= TH_URG;
else if (!strcasecmp(p, "ECE"))
*fl |= 0x40;
else if (!strcasecmp(p, "CWR"))
*fl |= 0x80;
else if (!strcasecmp(p, "AE") || !strcasecmp(p, "AECN") || !strcasecmp(p, "ACCECN"))
*fl |= 0x100;
else if (!strcasecmp(p, "R1"))
*fl |= 0x200;
else if (!strcasecmp(p, "R2"))
*fl |= 0x400;
else if (!strcasecmp(p, "R3"))
*fl |= 0x800;
else
return false;
if (e) *e++ = c;
p = e;
}
return true;
}
else
{
*fl = u & 0xFFF;
return *fl==u;
}
}
static void split_compat(struct desync_profile *dp) static void split_compat(struct desync_profile *dp)
{ {
if (!dp->split_count) if (!dp->split_count)
@@ -1768,11 +1825,14 @@ static void exithelp(void)
" --wsize=<window_size>[:<scale_factor>]\t\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\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\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"
" --wssize-forced-cutoff=0|1\t\t\t\t; 1(default)=auto cutoff wssize on known protocol\n"
" --synack-split=[syn|synack|acksyn]\t\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\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\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\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\t; overrides --orig-autottl for ipv6 only\n" " --orig-autottl6=[<delta>[:<min>[-<max>]]|-]\t\t; overrides --orig-autottl for ipv6 only\n"
" --orig-tcp-flags-set=<int|0xHEX|flaglist>\t\t; set these tcp flags (flags |= value). value can be int, hex or comma separated list : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3\n"
" --orig-tcp-flags-unset=<int|0xHEX|flaglist>\t\t; unset these tcp flags (flags &= ~value)\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-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\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\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"
@@ -1781,10 +1841,13 @@ static void exithelp(void)
" --dup-ttl6=<int>\t\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\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\t; overrides --dup-autottl for ipv6 only\n" " --dup-autottl6=[<delta>[:<min>[-<max>]]|-]\t\t; overrides --dup-autottl for ipv6 only\n"
" --dup-tcp-flags-set=<int|0xHEX|flaglist>\t\t; set these tcp flags (flags |= value). value can be int, hex or comma separated list : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3\n"
" --dup-tcp-flags-unset=<int|0xHEX|flaglist>\t\t; unset these tcp flags (flags &= ~value)\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-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\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\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\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-ip-id=same|zero|seq|rnd\t\t\t\t; ipv4 ip_id mode for dupped packets\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-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\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\t; change Host: => host:\n" " --hostcase\t\t\t\t\t\t; change Host: => host:\n"
@@ -1792,6 +1855,7 @@ static void exithelp(void)
" --hostnospace\t\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\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\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"
" --ip-id=zero|seq|seqgroup|rnd\t\t\t\t; ipv4 ip_id assignment scheme\n"
" --dpi-desync=[<mode0>,]<mode>[,<mode2>]\t\t; try to desync dpi state. modes :\n" " --dpi-desync=[<mode0>,]<mode>[,<mode2>]\t\t; try to desync dpi state. modes :\n"
"\t\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n" "\t\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n"
"\t\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder hostfakesplit ipfrag2 udplen tamper\n" "\t\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder hostfakesplit ipfrag2 udplen tamper\n"
@@ -1804,6 +1868,8 @@ static void exithelp(void)
" --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-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>]]|-]\t; 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>]]|-]\t; 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-tcp-flags-set=<int|0xHEX|flaglist>\t; set these tcp flags (flags |= value). value can be int, hex or comma separated list : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3\n"
" --dpi-desync-tcp-flags-unset=<int|0xHEX|flaglist>\t; unset these tcp flags (flags &= ~value)\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-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\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\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"
@@ -1815,7 +1881,7 @@ static void exithelp(void)
" --dpi-desync-split-seqovl-pattern=[+ofs]@<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=[+ofs]@<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder\n" " --dpi-desync-fakedsplit-pattern=[+ofs]@<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder\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-fakedsplit-mod=mod[,mod]\t\t\t; mods can be none,altorder=0|1|2|3 + 0|8|16\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-hostfakesplit-midhost=marker+N|marker-N\t; additionally split real hostname at specified marker. must be within host..endhost or won't be splitted.\n"
" --dpi-desync-hostfakesplit-mod=mod[,mod]\t\t; mods can be none,host=<hostname>,altorder=0|1\n" " --dpi-desync-hostfakesplit-mod=mod[,mod]\t\t; mods can be none,host=<hostname>,altorder=0|1\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-ipfrag-pos-tcp=<8..%u>\t\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\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-ipfrag-pos-udp=<8..%u>\t\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
@@ -1949,6 +2015,7 @@ enum opt_indices {
IDX_WSIZE, IDX_WSIZE,
IDX_WSSIZE, IDX_WSSIZE,
IDX_WSSIZE_CUTOFF, IDX_WSSIZE_CUTOFF,
IDX_WSSIZE_FORCED_CUTOFF,
IDX_SYNACK_SPLIT, IDX_SYNACK_SPLIT,
IDX_CTRACK_TIMEOUTS, IDX_CTRACK_TIMEOUTS,
IDX_CTRACK_DISABLE, IDX_CTRACK_DISABLE,
@@ -1959,6 +2026,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,
@@ -1970,23 +2038,30 @@ enum opt_indices {
IDX_DUP_TTL6, IDX_DUP_TTL6,
IDX_DUP_AUTOTTL, IDX_DUP_AUTOTTL,
IDX_DUP_AUTOTTL6, IDX_DUP_AUTOTTL6,
IDX_DUP_TCP_FLAGS_SET,
IDX_DUP_TCP_FLAGS_UNSET,
IDX_DUP_FOOLING, IDX_DUP_FOOLING,
IDX_DUP_TS_INCREMENT, IDX_DUP_TS_INCREMENT,
IDX_DUP_BADSEQ_INCREMENT, IDX_DUP_BADSEQ_INCREMENT,
IDX_DUP_BADACK_INCREMENT, IDX_DUP_BADACK_INCREMENT,
IDX_DUP_REPLACE, IDX_DUP_REPLACE,
IDX_DUP_IP_ID,
IDX_DUP_START, IDX_DUP_START,
IDX_DUP_CUTOFF, IDX_DUP_CUTOFF,
IDX_ORIG_TTL, IDX_ORIG_TTL,
IDX_ORIG_TTL6, IDX_ORIG_TTL6,
IDX_ORIG_AUTOTTL, IDX_ORIG_AUTOTTL,
IDX_ORIG_AUTOTTL6, IDX_ORIG_AUTOTTL6,
IDX_ORIG_TCP_FLAGS_SET,
IDX_ORIG_TCP_FLAGS_UNSET,
IDX_ORIG_MOD_START, IDX_ORIG_MOD_START,
IDX_ORIG_MOD_CUTOFF, IDX_ORIG_MOD_CUTOFF,
IDX_DPI_DESYNC_TTL, IDX_DPI_DESYNC_TTL,
IDX_DPI_DESYNC_TTL6, IDX_DPI_DESYNC_TTL6,
IDX_DPI_DESYNC_AUTOTTL, IDX_DPI_DESYNC_AUTOTTL,
IDX_DPI_DESYNC_AUTOTTL6, IDX_DPI_DESYNC_AUTOTTL6,
IDX_DPI_DESYNC_TCP_FLAGS_SET,
IDX_DPI_DESYNC_TCP_FLAGS_UNSET,
IDX_DPI_DESYNC_FOOLING, IDX_DPI_DESYNC_FOOLING,
IDX_DPI_DESYNC_REPEATS, IDX_DPI_DESYNC_REPEATS,
IDX_DPI_DESYNC_SKIP_NOSNI, IDX_DPI_DESYNC_SKIP_NOSNI,
@@ -2081,6 +2156,7 @@ static const struct option long_options[] = {
[IDX_WSIZE] = {"wsize", required_argument, 0, 0}, [IDX_WSIZE] = {"wsize", required_argument, 0, 0},
[IDX_WSSIZE] = {"wssize", required_argument, 0, 0}, [IDX_WSSIZE] = {"wssize", required_argument, 0, 0},
[IDX_WSSIZE_CUTOFF] = {"wssize-cutoff", required_argument, 0, 0}, [IDX_WSSIZE_CUTOFF] = {"wssize-cutoff", required_argument, 0, 0},
[IDX_WSSIZE_FORCED_CUTOFF] = {"wssize-forced-cutoff", required_argument, 0, 0},
[IDX_SYNACK_SPLIT] = {"synack-split", optional_argument, 0, 0}, [IDX_SYNACK_SPLIT] = {"synack-split", optional_argument, 0, 0},
[IDX_CTRACK_TIMEOUTS] = {"ctrack-timeouts", required_argument, 0, 0}, [IDX_CTRACK_TIMEOUTS] = {"ctrack-timeouts", required_argument, 0, 0},
[IDX_CTRACK_DISABLE] = {"ctrack-disable", optional_argument, 0, 0}, [IDX_CTRACK_DISABLE] = {"ctrack-disable", optional_argument, 0, 0},
@@ -2091,6 +2167,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},
@@ -2102,23 +2179,30 @@ static const struct option long_options[] = {
[IDX_DUP_TTL6] = {"dup-ttl6", required_argument, 0, 0}, [IDX_DUP_TTL6] = {"dup-ttl6", required_argument, 0, 0},
[IDX_DUP_AUTOTTL] = {"dup-autottl", optional_argument, 0, 0}, [IDX_DUP_AUTOTTL] = {"dup-autottl", optional_argument, 0, 0},
[IDX_DUP_AUTOTTL6] = {"dup-autottl6", optional_argument, 0, 0}, [IDX_DUP_AUTOTTL6] = {"dup-autottl6", optional_argument, 0, 0},
[IDX_DUP_TCP_FLAGS_SET] = {"dup-tcp-flags-set", optional_argument, 0, 0},
[IDX_DUP_TCP_FLAGS_UNSET] = {"dup-tcp-flags-unset", optional_argument, 0, 0},
[IDX_DUP_FOOLING] = {"dup-fooling", required_argument, 0, 0}, [IDX_DUP_FOOLING] = {"dup-fooling", required_argument, 0, 0},
[IDX_DUP_TS_INCREMENT] = {"dup-ts-increment", required_argument, 0, 0}, [IDX_DUP_TS_INCREMENT] = {"dup-ts-increment", required_argument, 0, 0},
[IDX_DUP_BADSEQ_INCREMENT] = {"dup-badseq-increment", required_argument, 0, 0}, [IDX_DUP_BADSEQ_INCREMENT] = {"dup-badseq-increment", required_argument, 0, 0},
[IDX_DUP_BADACK_INCREMENT] = {"dup-badack-increment", required_argument, 0, 0}, [IDX_DUP_BADACK_INCREMENT] = {"dup-badack-increment", required_argument, 0, 0},
[IDX_DUP_REPLACE] = {"dup-replace", optional_argument, 0, 0}, [IDX_DUP_REPLACE] = {"dup-replace", optional_argument, 0, 0},
[IDX_DUP_IP_ID] = {"dup-ip-id", required_argument, 0, 0},
[IDX_DUP_START] = {"dup-start", required_argument, 0, 0}, [IDX_DUP_START] = {"dup-start", required_argument, 0, 0},
[IDX_DUP_CUTOFF] = {"dup-cutoff", required_argument, 0, 0}, [IDX_DUP_CUTOFF] = {"dup-cutoff", required_argument, 0, 0},
[IDX_ORIG_TTL] = {"orig-ttl", required_argument, 0, 0}, [IDX_ORIG_TTL] = {"orig-ttl", required_argument, 0, 0},
[IDX_ORIG_TTL6] = {"orig-ttl6", required_argument, 0, 0}, [IDX_ORIG_TTL6] = {"orig-ttl6", required_argument, 0, 0},
[IDX_ORIG_AUTOTTL] = {"orig-autottl", optional_argument, 0, 0}, [IDX_ORIG_AUTOTTL] = {"orig-autottl", optional_argument, 0, 0},
[IDX_ORIG_AUTOTTL6] = {"orig-autottl6", optional_argument, 0, 0}, [IDX_ORIG_AUTOTTL6] = {"orig-autottl6", optional_argument, 0, 0},
[IDX_ORIG_TCP_FLAGS_SET] = {"orig-tcp-flags-set", optional_argument, 0, 0},
[IDX_ORIG_TCP_FLAGS_UNSET] = {"orig-tcp-flags-unset", optional_argument, 0, 0},
[IDX_ORIG_MOD_START] = {"orig-mod-start", required_argument, 0, 0}, [IDX_ORIG_MOD_START] = {"orig-mod-start", required_argument, 0, 0},
[IDX_ORIG_MOD_CUTOFF] = {"orig-mod-cutoff", required_argument, 0, 0}, [IDX_ORIG_MOD_CUTOFF] = {"orig-mod-cutoff", required_argument, 0, 0},
[IDX_DPI_DESYNC_TTL] = {"dpi-desync-ttl", required_argument, 0, 0}, [IDX_DPI_DESYNC_TTL] = {"dpi-desync-ttl", required_argument, 0, 0},
[IDX_DPI_DESYNC_TTL6] = {"dpi-desync-ttl6", required_argument, 0, 0}, [IDX_DPI_DESYNC_TTL6] = {"dpi-desync-ttl6", required_argument, 0, 0},
[IDX_DPI_DESYNC_AUTOTTL] = {"dpi-desync-autottl", optional_argument, 0, 0}, [IDX_DPI_DESYNC_AUTOTTL] = {"dpi-desync-autottl", optional_argument, 0, 0},
[IDX_DPI_DESYNC_AUTOTTL6] = {"dpi-desync-autottl6", optional_argument, 0, 0}, [IDX_DPI_DESYNC_AUTOTTL6] = {"dpi-desync-autottl6", optional_argument, 0, 0},
[IDX_DPI_DESYNC_TCP_FLAGS_SET] = {"dpi-desync-tcp-flags-set", optional_argument, 0, 0},
[IDX_DPI_DESYNC_TCP_FLAGS_UNSET] = {"dpi-desync-tcp-flags-unset", optional_argument, 0, 0},
[IDX_DPI_DESYNC_FOOLING] = {"dpi-desync-fooling", required_argument, 0, 0}, [IDX_DPI_DESYNC_FOOLING] = {"dpi-desync-fooling", required_argument, 0, 0},
[IDX_DPI_DESYNC_REPEATS] = {"dpi-desync-repeats", required_argument, 0, 0}, [IDX_DPI_DESYNC_REPEATS] = {"dpi-desync-repeats", required_argument, 0, 0},
[IDX_DPI_DESYNC_SKIP_NOSNI] = {"dpi-desync-skip-nosni", optional_argument, 0, 0}, [IDX_DPI_DESYNC_SKIP_NOSNI] = {"dpi-desync-skip-nosni", optional_argument, 0, 0},
@@ -2420,6 +2504,9 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_WSSIZE_FORCED_CUTOFF:
dp->wssize_no_forced_cutoff = !atoi(optarg);
break;
case IDX_SYNACK_SPLIT: case IDX_SYNACK_SPLIT:
dp->synack_split = SS_SYN; dp->synack_split = SS_SYN;
if (optarg) if (optarg)
@@ -2486,6 +2573,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;
@@ -2576,6 +2678,20 @@ int main(int argc, char **argv)
} }
params.autottl_present = true; params.autottl_present = true;
break; break;
case IDX_DUP_TCP_FLAGS_SET:
if (!parse_tcpflags(optarg, &dp->dup_tcp_flags_set))
{
DLOG_ERR("invalid tcp flags\n");
exit_clean(1);
}
break;
case IDX_DUP_TCP_FLAGS_UNSET:
if (!parse_tcpflags(optarg, &dp->dup_tcp_flags_unset))
{
DLOG_ERR("invalid tcp flags\n");
exit_clean(1);
}
break;
case IDX_DUP_REPLACE: case IDX_DUP_REPLACE:
dp->dup_replace = !optarg || atoi(optarg); dp->dup_replace = !optarg || atoi(optarg);
break; break;
@@ -2621,6 +2737,21 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case IDX_DUP_IP_ID:
if (!strcmp(optarg,"zero"))
dp->dup_ip_id_mode = IPID_ZERO;
else if (!strcmp(optarg,"same"))
dp->dup_ip_id_mode = IPID_SAME;
else if (!strcmp(optarg,"seq"))
dp->dup_ip_id_mode = IPID_SEQ;
else if (!strcmp(optarg,"rnd"))
dp->dup_ip_id_mode = IPID_RND;
else
{
DLOG_ERR("invalid dup ip_id mode : %s\n",optarg);
exit_clean(1);
}
break;
case IDX_ORIG_TTL: case IDX_ORIG_TTL:
dp->orig_mod_ttl = (uint8_t)atoi(optarg); dp->orig_mod_ttl = (uint8_t)atoi(optarg);
@@ -2644,6 +2775,20 @@ int main(int argc, char **argv)
} }
params.autottl_present = true; params.autottl_present = true;
break; break;
case IDX_ORIG_TCP_FLAGS_SET:
if (!parse_tcpflags(optarg, &dp->orig_tcp_flags_set))
{
DLOG_ERR("invalid tcp flags\n");
exit_clean(1);
}
break;
case IDX_ORIG_TCP_FLAGS_UNSET:
if (!parse_tcpflags(optarg, &dp->orig_tcp_flags_unset))
{
DLOG_ERR("invalid tcp flags\n");
exit_clean(1);
}
break;
case IDX_ORIG_MOD_CUTOFF: case IDX_ORIG_MOD_CUTOFF:
if (!parse_cutoff(optarg, &dp->orig_mod_cutoff, &dp->orig_mod_cutoff_mode)) if (!parse_cutoff(optarg, &dp->orig_mod_cutoff, &dp->orig_mod_cutoff_mode))
{ {
@@ -2681,6 +2826,20 @@ int main(int argc, char **argv)
} }
params.autottl_present = true; params.autottl_present = true;
break; break;
case IDX_DPI_DESYNC_TCP_FLAGS_SET:
if (!parse_tcpflags(optarg, &dp->desync_tcp_flags_set))
{
DLOG_ERR("invalid tcp flags\n");
exit_clean(1);
}
break;
case IDX_DPI_DESYNC_TCP_FLAGS_UNSET:
if (!parse_tcpflags(optarg, &dp->desync_tcp_flags_unset))
{
DLOG_ERR("invalid tcp flags\n");
exit_clean(1);
}
break;
case IDX_DPI_DESYNC_FOOLING: case IDX_DPI_DESYNC_FOOLING:
if (!parse_fooling(optarg, &dp->desync_fooling_mode)) if (!parse_fooling(optarg, &dp->desync_fooling_mode))
{ {
@@ -2707,8 +2866,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);
@@ -2758,8 +2917,8 @@ int main(int argc, char **argv)
size_t sz = sizeof(buf); size_t sz = sizeof(buf);
load_file_or_exit(optarg, buf, &sz, NULL); load_file_or_exit(optarg, buf, &sz, NULL);
fill_pattern(dp->seqovl_pattern, sizeof(dp->seqovl_pattern), buf, sz, 0); 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:
{ {
free(dp->fsplit_pattern); free(dp->fsplit_pattern);
@@ -2770,8 +2929,8 @@ int main(int argc, char **argv)
} }
load_file_or_exit(optarg, dp->fsplit_pattern, &dp->fsplit_pattern_size, NULL); load_file_or_exit(optarg, dp->fsplit_pattern, &dp->fsplit_pattern_size, NULL);
dp->fsplit_pattern = realloc(dp->fsplit_pattern, dp->fsplit_pattern_size); dp->fsplit_pattern = realloc(dp->fsplit_pattern, dp->fsplit_pattern_size);
break;
} }
break;
case IDX_DPI_DESYNC_FAKEDSPLIT_MOD: case IDX_DPI_DESYNC_FAKEDSPLIT_MOD:
if (!parse_fakedsplit_mod(optarg, &dp->fs_mod)) if (!parse_fakedsplit_mod(optarg, &dp->fs_mod))
{ {
@@ -3323,7 +3482,7 @@ int main(int argc, char **argv)
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)
{ {
if (dp->fsplit_pattern=calloc(64,1)) if ((dp->fsplit_pattern=calloc(64,1)))
dp->fsplit_pattern_size=64; dp->fsplit_pattern_size=64;
else else
{ {
+4
View File
@@ -219,6 +219,9 @@ void dp_init(struct desync_profile *dp)
LIST_INIT(&dp->ips_collection_exclude); LIST_INIT(&dp->ips_collection_exclude);
LIST_INIT(&dp->pf_tcp); LIST_INIT(&dp->pf_tcp);
LIST_INIT(&dp->pf_udp); LIST_INIT(&dp->pf_udp);
#ifdef HAS_FILTER_SSID
LIST_INIT(&dp->filter_ssid);
#endif
memcpy(dp->hostspell, "host", 4); // default hostspell memcpy(dp->hostspell, "host", 4); // default hostspell
dp->desync_skip_nosni = true; dp->desync_skip_nosni = true;
@@ -237,6 +240,7 @@ void dp_init(struct desync_profile *dp)
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT; dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT; dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
dp->filter_ipv4 = dp->filter_ipv6 = true; dp->filter_ipv4 = dp->filter_ipv6 = true;
dp->dup_ip_id_mode = IPID_SAME;
} }
bool dp_fake_defaults(struct desync_profile *dp) bool dp_fake_defaults(struct desync_profile *dp)
{ {
+9 -1
View File
@@ -97,6 +97,7 @@ struct tcp_mod
}; };
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,IPID_SAME} t_ip_id_mode;
struct desync_profile struct desync_profile
{ {
@@ -105,10 +106,13 @@ struct desync_profile
uint16_t wsize,wssize; uint16_t wsize,wssize;
uint8_t wscale,wsscale; uint8_t wscale,wsscale;
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
bool wssize_no_forced_cutoff;
unsigned int wssize_cutoff; unsigned int wssize_cutoff;
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;
@@ -128,11 +132,14 @@ struct desync_profile
uint32_t dup_fooling_mode; uint32_t dup_fooling_mode;
uint32_t dup_ts_increment, dup_badseq_increment, dup_badseq_ack_increment; uint32_t dup_ts_increment, dup_badseq_increment, dup_badseq_ack_increment;
autottl dup_autottl, dup_autottl6; autottl dup_autottl, dup_autottl6;
uint16_t dup_tcp_flags_set, dup_tcp_flags_unset;
t_ip_id_mode dup_ip_id_mode;
char orig_mod_start_mode, orig_mod_cutoff_mode; // n - packets, d - data packets, s - relative sequence char orig_mod_start_mode, orig_mod_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int orig_mod_start, orig_mod_cutoff; unsigned int orig_mod_start, orig_mod_cutoff;
uint8_t orig_mod_ttl, orig_mod_ttl6; uint8_t orig_mod_ttl, orig_mod_ttl6;
autottl orig_autottl, orig_autottl6; autottl orig_autottl, orig_autottl6;
uint16_t orig_tcp_flags_set, orig_tcp_flags_unset;
char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int desync_start, desync_cutoff; unsigned int desync_start, desync_cutoff;
@@ -140,6 +147,7 @@ struct desync_profile
autottl desync_autottl, desync_autottl6; autottl desync_autottl, desync_autottl6;
uint32_t desync_fooling_mode; uint32_t desync_fooling_mode;
uint32_t desync_ts_increment, desync_badseq_increment, desync_badseq_ack_increment; uint32_t desync_ts_increment, desync_badseq_increment, desync_badseq_ack_increment;
uint16_t desync_tcp_flags_set, desync_tcp_flags_unset;
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],udplen_pattern[FAKE_MAX_UDP]; uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP];
@@ -181,7 +189,7 @@ struct desync_profile
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&(dp)->ips_collection) && !LIST_FIRST(&(dp)->ips_collection_exclude)) #define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&(dp)->ips_collection) && !LIST_FIRST(&(dp)->ips_collection_exclude))
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&(dp)->ips_collection) && ipset_collection_is_empty(&(dp)->ips_collection_exclude)) #define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&(dp)->ips_collection) && ipset_collection_is_empty(&(dp)->ips_collection_exclude))
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&(dp)->hl_collection) && hostlist_collection_is_empty(&(dp)->hl_collection_exclude)) #define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&(dp)->hl_collection) && hostlist_collection_is_empty(&(dp)->hl_collection_exclude))
#define PROFILE_HAS_ORIG_MOD(dp) ((dp)->orig_mod_ttl || (dp)->orig_mod_ttl6) #define PROFILE_HAS_ORIG_MOD(dp) ((dp)->orig_mod_ttl || (dp)->orig_mod_ttl6 || (dp)->orig_tcp_flags_set || (dp)->orig_tcp_flags_unset)
struct desync_profile_list { struct desync_profile_list {
struct desync_profile dp; struct desync_profile dp;
-8
View File
@@ -52,14 +52,6 @@ bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7)
(l7proto==STUN && (filter_l7 & L7_PROTO_STUN)); (l7proto==STUN && (filter_l7 & L7_PROTO_STUN));
} }
#define PM_ABS 0
#define PM_HOST 1
#define PM_HOST_END 2
#define PM_HOST_SLD 3
#define PM_HOST_MIDSLD 4
#define PM_HOST_ENDSLD 5
#define PM_HTTP_METHOD 6
#define PM_SNI_EXT 7
bool IsHostMarker(uint8_t posmarker) bool IsHostMarker(uint8_t posmarker)
{ {
switch(posmarker) switch(posmarker)