130 Commits
v71.4 ... v72.4

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
bol-van
3c8e4ed15d update docs 2025-10-12 14:35:27 +03:00
bol-van
8c06a6335d update docs 2025-10-12 14:34:49 +03:00
bol-van
f12cae3674 update docs 2025-10-12 14:34:21 +03:00
bol-van
170281bfa6 update docs 2025-10-12 14:33:16 +03:00
bol-van
5d4747458f update docs 2025-10-12 14:30:05 +03:00
bol-van
5774e883d6 update docs 2025-10-12 14:19:04 +03:00
bol-van
80b801c1ca nfqws: fix seqovl>=split_pos message 2025-10-10 17:53:14 +03:00
bol-van
9d8ee398c3 Revert "blockcheck: enable ECN in windows"
This reverts commit 4d35d8d1ec.
2025-10-08 16:32:56 +03:00
bol-van
4d35d8d1ec blockcheck: enable ECN in windows 2025-10-07 10:19:02 +03:00
bol-van
977d117417 nfqws: prevent memleak if multiple fakedsplit pattern options 2025-10-04 20:45:24 +03:00
bol-van
cc8313db51 nfqws: optimize default fakedsplit pattern 2025-10-04 20:18:39 +03:00
bol-van
1e51f90130 nfqws: fix fakedsplit-pattern if not specified 2025-10-04 19:59:19 +03:00
bol-van
da6b89e739 blockcheck: print some OPENWRT_xxx from /etc/os-release 2025-10-04 18:31:48 +03:00
bol-van
90470440a7 blockcheck: print PRETTY_NAME from /etc/os-release 2025-10-04 18:26:07 +03:00
bol-van
a5c9d79417 update docs 2025-10-04 11:58:59 +03:00
bol-van
c003ef2a7b update docs 2025-10-04 11:58:35 +03:00
bol-van
42541fcab8 update docs 2025-10-04 11:57:53 +03:00
bol-van
20b5952978 update docs 2025-10-04 11:56:07 +03:00
bol-van
4b6aa1b5f9 nfqws: help text for more altorders 2025-10-04 11:43:06 +03:00
bol-van
9e141dcefd update docs 2025-10-04 11:30:38 +03:00
bol-van
b1b992eb3f update docs 2025-10-04 11:28:29 +03:00
bol-van
2d061c911a update docs 2025-10-04 11:27:31 +03:00
bol-van
a213084188 update docs 2025-10-04 11:26:42 +03:00
bol-van
1c7ec32b96 update docs 2025-10-04 11:26:00 +03:00
bol-van
dcd9cfbb2b nfqws: ip_id fixes, more altorder support 2025-10-04 11:02:23 +03:00
bol-van
beb0692d28 quick_start: minor change 2025-10-03 10:48:23 +03:00
bol-van
140af2b741 quick_start: remove easy option 2025-10-03 10:47:40 +03:00
bol-van
f8cc109f0b nfqws: remove "file containing" from help text 2025-09-24 16:32:48 +03:00
bol-van
b4a2f44d56 remove -2b fakes 2025-09-24 16:26:39 +03:00
bol-van
14d05d8012 update docs 2025-09-24 16:25:08 +03:00
bol-van
71d5afeaf4 update docs 2025-09-24 16:24:36 +03:00
bol-van
45df8bfb09 update docs 2025-09-24 16:21:59 +03:00
bol-van
784058cf66 nfqws: support +offset@filename fake/pattern loading 2025-09-24 16:08:25 +03:00
bol-van
ce367b1a91 nfqws: optimize ip_id behavior 2025-09-24 10:31:06 +03:00
bol-van
a832c19974 blockcheck: test --dpi-desync-fakedsplit-mod=altorder=1 2025-09-23 14:20:23 +03:00
bol-van
2c14109163 update docs 2025-09-23 14:13:39 +03:00
bol-van
c467e696e3 nfqws: --dpi-desync-fakedsplit-mod=altorder 2025-09-23 14:06:23 +03:00
bol-van
528c27a01a update docs 2025-09-23 13:16:18 +03:00
bol-van
c2f1e708fc blockcheck: test split fake 2025-09-23 12:21:47 +03:00
bol-van
211a4f4673 update docs 2025-09-23 11:54:59 +03:00
bol-van
fd81053d79 nfqws: --dpi-desync-fake-tls=!+offset 2025-09-23 11:52:46 +03:00
bol-van
1bb9f260dd -2b tls fakes 2025-09-23 10:52:38 +03:00
bol-van
26f3cbd06f update docs 2025-09-23 10:52:16 +03:00
bol-van
e384f88931 nfqws: --dpi-desync-fake-tcp-mod=seq 2025-09-23 10:51:49 +03:00
bol-van
59bce0036b update docs 2025-09-22 17:39:00 +03:00
bol-van
0a48c923b8 update docs 2025-09-22 17:37:58 +03:00
bol-van
ed4782887f update docs 2025-09-22 17:37:21 +03:00
bol-van
80b6b75934 blockcheck: test hostfakesplit altorder 2025-09-22 17:18:23 +03:00
bol-van
245ce41550 nfqws: altorder mod for hostfakesplit 2025-09-22 17:06:30 +03:00
bol-van
db5dca28b0 nfqws: fix clang warnings 2025-09-22 15:06:52 +03:00
bol-van
6dad239fe3 blockcheck: fix infinite recursion on mac/bsd 2025-09-22 14:58:51 +03:00
bol-van
aa4982a526 blockcheck: working strategies intersection print for multiple domains 2025-09-22 14:49:33 +03:00
bol-van
61808b37d8 base.sh quote parameters in replace_char 2025-09-22 13:05:35 +03:00
bol-van
4b90ee920c update docs 2025-09-22 10:11:06 +03:00
bol-van
170e9d7ffd nfqws: --dpi-desync-hostfakesplit-mod 2025-09-22 09:51:25 +03:00
bol-van
d8f9ba29c3 update docs 2025-09-21 19:44:31 +03:00
bol-van
4914b813e7 update docs 2025-09-21 19:42:38 +03:00
bol-van
c3fdec9bf0 update docs 2025-09-21 18:54:38 +03:00
bol-van
1cbdf9b891 nfqws: hostfakesplit fix use-after-free 2025-09-21 18:36:49 +03:00
bol-van
706dd7b2d9 nfqws: hostfakesplit send second fake 2025-09-21 18:31:09 +03:00
bol-van
b2468a9095 blockcheck: change nft postnat hook from output to postrouting to fix some issues 2025-09-21 17:53:50 +03:00
bol-van
acfbbc58ac blockcheck: new strategies 2025-09-21 14:54:31 +03:00
bol-van
fd506dfe08 nfqws: print sessionID lengths if dupsid cannot be applied 2025-09-21 13:17:52 +03:00
bol-van
1ee25e01ea nfqws: generate random host with a-z at the first position 2025-09-21 12:51:06 +03:00
bol-van
521c385adb nfqws: --dpi-desync=hostfakesplit 2025-09-21 12:32:53 +03:00
bol-van
17971e87b4 update docs 2025-09-20 15:25:37 +03:00
bol-van
4dc1d035d8 update docs 2025-09-20 15:24:32 +03:00
bol-van
07eee8af25 winws: --wf-raw-part 2025-09-20 13:59:54 +03:00
bol-van
06e7818240 quick_start: traditional linux separate link 2025-09-04 10:12:09 +03:00
bol-van
00b0f3c940 quick_start: typo 2025-09-04 10:09:48 +03:00
bol-van
17df2adbe0 quick_start: curl/wget to stdout info 2025-09-04 10:09:01 +03:00
bol-van
40342745f7 quick_start: curl/wget to stdout info 2025-09-04 10:06:42 +03:00
bol-van
54d4cdb2d5 50-dht4all fix space/tabs 2025-09-03 17:19:35 +03:00
bol-van
b251ea839c custom scripts increase repeats 2025-09-03 12:24:00 +03:00
bol-van
595cf863fc put old kernel ver note for @ih to customs 2025-09-01 22:00:55 +03:00
bol-van
91d5b90ded install_easy: install iptables-mod-u32 2025-09-01 21:29:00 +03:00
bol-van
33a7132920 50-dht4all move from @th to @ih 2025-09-01 21:25:30 +03:00
bol-van
d9b23f14a2 docs works 2025-08-22 19:13:41 +03:00
bol-van
06613b4fd5 docs: windows server note 2025-08-22 19:10:56 +03:00
43 changed files with 3600 additions and 2367 deletions

1
.gitattributes vendored
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

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 }}

View File

@@ -41,19 +41,22 @@ CURL_MAX_TIME_QUIC=${CURL_MAX_TIME_QUIC:-$CURL_MAX_TIME}
CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2} CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2}
MIN_TTL=${MIN_TTL:-1} MIN_TTL=${MIN_TTL:-1}
MAX_TTL=${MAX_TTL:-12} MAX_TTL=${MAX_TTL:-12}
MIN_AUTOTTL_DELTA=${MIN_AUTOTTL_DELTA:-1}
MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
USER_AGENT=${USER_AGENT:-Mozilla} USER_AGENT=${USER_AGENT:-Mozilla}
HTTP_PORT=${HTTP_PORT:-80} HTTP_PORT=${HTTP_PORT:-80}
HTTPS_PORT=${HTTPS_PORT:-443} HTTPS_PORT=${HTTPS_PORT:-443}
QUIC_PORT=${QUIC_PORT:-443} QUIC_PORT=${QUIC_PORT:-443}
UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org} UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org}
PARALLEL_OUT=/tmp/zapret_parallel PARALLEL_OUT=/tmp/zapret_parallel
SIM_SUCCESS_RATE=${SIM_SUCCESS_RATE:-10}
HDRTEMP=/tmp/zapret-hdr HDRTEMP=/tmp/zapret-hdr
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
@@ -216,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()
{ {
@@ -244,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}
@@ -275,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
} }
@@ -411,9 +418,16 @@ check_system()
else else
uname -a uname -a
fi fi
[ -f /etc/os-release ] && {
. /etc/os-release
[ -n "$PRETTY_NAME" ] && echo "distro: $PRETTY_NAME"
[ -n "$OPENWRT_RELEASE" ] && echo "openwrt release: $OPENWRT_RELEASE"
[ -n "$OPENWRT_BOARD" ] && echo "openwrt board: $OPENWRT_BOARD"
[ -n "$OPENWRT_ARCH" ] && echo "openwrt arch: $OPENWRT_ARCH"
}
echo firewall type is $FWTYPE echo firewall type is $FWTYPE
echo CURL=$CURL echo CURL=$CURL
$CURL --version "$CURL" --version
} }
zp_already_running() zp_already_running()
@@ -469,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)
@@ -585,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 ]
} }
@@ -598,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 ]
} }
@@ -615,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 ]
} }
@@ -643,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()
{ {
@@ -655,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
@@ -721,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()
{ {
@@ -730,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()
@@ -739,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()
@@ -803,7 +820,7 @@ nft_scheme()
make_comma_list iplist $3 make_comma_list iplist $3
nft add table inet $NFT_TABLE nft add table inet $NFT_TABLE
nft "add chain inet $NFT_TABLE postnat { type filter hook output priority 102; }" nft "add chain inet $NFT_TABLE postnat { type filter hook postrouting priority 102; }"
nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} $1 dport $2 mark and $DESYNC_MARK == 0 ip${ipver} daddr {$iplist} ct mark set ct mark or $DESYNC_MARK queue num $QNUM" nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} $1 dport $2 mark and $DESYNC_MARK == 0 ip${ipver} daddr {$iplist} ct mark set ct mark or $DESYNC_MARK queue num $QNUM"
# for strategies with incoming packets involved (autottl) # for strategies with incoming packets involved (autottl)
nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }" nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }"
@@ -989,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
@@ -1063,6 +1080,17 @@ ws_curl_test()
# $3 - domain # $3 - domain
# $4,$5,$6, ... - ws params # $4,$5,$6, ... - ws params
local code ws_start=$1 testf=$2 dom=$3 local code ws_start=$1 testf=$2 dom=$3
[ "$SIMULATE" = 1 ] && {
n=$(random 0 99)
if [ "$n" -lt "$SIM_SUCCESS_RATE" ]; then
echo "SUCCESS"
return 0
else
echo "FAILED"
return 7
fi
}
shift shift
shift shift
shift shift
@@ -1085,7 +1113,7 @@ tpws_curl_test()
shift; shift; shift; shift;
strategy="$@" strategy="$@"
strategy_append_extra_tpws strategy_append_extra_tpws
report_append "ipv${IPV} $dom $testf : tpws ${WF:+$WF }$strategy" report_append "$dom" "$testf ipv${IPV}" "tpws ${WF:+$WF }$strategy"
} }
return $code return $code
} }
@@ -1104,7 +1132,7 @@ pktws_curl_test()
[ "$code" = 0 ] && { [ "$code" = 0 ] && {
strategy="$@" strategy="$@"
strategy_append_extra_pktws strategy_append_extra_pktws
report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy" report_append "$dom" "$testf ipv${IPV}" "$PKTWSD ${WF:+$WF }$strategy"
} }
return $code return $code
} }
@@ -1144,8 +1172,35 @@ tpws_curl_test_update()
report_append() report_append()
{ {
# $1 - domain
# $2 - test function + ipver
# $3 - value
local hashstr hash hashvar hashcountvar val ct
# save resources if only one domain
[ "$DOMAINS_COUNT" -gt 1 ] && {
hashstr="$2 : $3"
hash="$(echo -n "$hashstr" | md5f)"
hashvar=RESHASH_${hash}
hashcountvar=${hashvar}_COUNTER
NRESHASH=${NRESHASH:-0}
eval val="\$$hashvar"
if [ -n "$val" ]; then
eval ct="\$$hashcountvar"
ct=$(($ct + 1))
eval $hashcountvar="\$ct"
else
eval $hashvar=\"$hashstr\"
eval $hashcountvar=1
eval RES_$NRESHASH="\$hash"
NRESHASH=$(($NRESHASH+1))
fi
}
NREPORT=${NREPORT:-0} NREPORT=${NREPORT:-0}
eval REPORT_${NREPORT}=\"$@\" eval REPORT_${NREPORT}=\"$2 $1 : $3\"
NREPORT=$(($NREPORT+1)) NREPORT=$(($NREPORT+1))
} }
report_print() report_print()
@@ -1158,6 +1213,22 @@ report_print()
n=$(($n+1)) n=$(($n+1))
done done
} }
result_intersection_print()
{
local n=0 hash hashvar hashcountvar ct val
while : ; do
eval hash=\"\$RES_$n\"
[ -n "$hash" ] || break
hashvar=RESHASH_${hash}
hashcountvar=${hashvar}_COUNTER
eval ct=\"\$$hashcountvar\"
[ "$ct" = "$DOMAINS_COUNT" ] && {
eval val=\"\$$hashvar\"
echo "$val"
}
n=$(($n + 1))
done
}
report_strategy() report_strategy()
{ {
# $1 - test function # $1 - test function
@@ -1169,23 +1240,26 @@ report_strategy()
strategy="$(echo "$strategy" | xargs)" strategy="$(echo "$strategy" | xargs)"
echo "!!!!! $1: working strategy found for ipv${IPV} $2 : $3 $strategy !!!!!" echo "!!!!! $1: working strategy found for ipv${IPV} $2 : $3 $strategy !!!!!"
echo echo
# report_append "ipv${IPV} $2 $1 : $3 ${WF:+$WF }$strategy"
return 0 return 0
else else
echo "$1: $3 strategy for ipv${IPV} $2 not found" echo "$1: $3 strategy for ipv${IPV} $2 not found"
echo echo
report_append "ipv${IPV} $2 $1 : $3 not working" report_append "$2" "$1 ipv${IPV}" "$3 not working"
return 1 return 1
fi fi
} }
test_has_split()
{
contains "$1" split || contains "$1" disorder
}
test_has_fakedsplit() test_has_fakedsplit()
{ {
contains "$1" fakedsplit || contains "$1" fakeddisorder contains "$1" fakedsplit || contains "$1" fakeddisorder
} }
test_has_split()
{
contains "$1" multisplit || contains "$1" multidisorder || test_has_fakedsplit "$1"
}
test_has_hostfakesplit()
{
contains "$1" hostfakesplit
}
test_has_fake() test_has_fake()
{ {
[ "$1" = fake ] || starts_with "$1" fake, [ "$1" = fake ] || starts_with "$1" fake,
@@ -1210,7 +1284,7 @@ pktws_curl_test_update_vary()
# $5,$6,... - strategy # $5,$6,... - strategy
local testf=$1 sec=$2 domain=$3 desync=$4 proto splits= pos fake ret=1 local testf=$1 sec=$2 domain=$3 desync=$4 proto splits= pos fake ret=1
local fake1=- fake2=- fake3=- local fake1=- fake2=- fake3=- fake4=-
shift; shift; shift; shift shift; shift; shift; shift
@@ -1219,18 +1293,27 @@ pktws_curl_test_update_vary()
test_has_fake $desync && { test_has_fake $desync && {
fake1="--dpi-desync-fake-$proto=0x00000000" fake1="--dpi-desync-fake-$proto=0x00000000"
[ "$sec" = 0 ] || { [ "$sec" = 0 ] || {
fake2="--dpi-desync-fake-tls=0x00000000 --dpi-desync-fake-tls=! --dpi-desync-fake-tls-mod=rnd,rndsni,dupsid" fake2='--dpi-desync-fake-tls=0x00000000 --dpi-desync-fake-tls=! --dpi-desync-fake-tls-mod=rnd,rndsni,dupsid'
fake3="--dpi-desync-fake-tls-mod=rnd,dupsid,rndsni,padencap" # this splits actual fake to '1603' and modified standard fake from offset 2
fake3='--dpi-desync-fake-tls=0x1603 --dpi-desync-fake-tls=!+2 --dpi-desync-fake-tls-mod=rnd,dupsid,rndsni --dpi-desync-fake-tcp-mod=seq'
fake4='--dpi-desync-fake-tls-mod=rnd,dupsid,rndsni,padencap'
} }
} }
if test_has_fakedsplit $desync ; then if test_has_fakedsplit $desync ; then
splits="method+2 midsld" splits="method+2 midsld"
[ "$sec" = 0 ] || splits="1 midsld" [ "$sec" = 0 ] || splits="1 midsld"
# do not send fake first
fake1='--dpi-desync-fakedsplit-mod=altorder=1'
elif test_has_split $desync ; then elif test_has_split $desync ; then
splits="method+2 midsld" splits="method+2 midsld"
[ "$sec" = 0 ] || splits="1 midsld 1,midsld" [ "$sec" = 0 ] || splits="1 midsld 1,midsld"
fi fi
for fake in '' "$fake1" "$fake2" "$fake3" ; do test_has_hostfakesplit $desync && {
fake1="--dpi-desync-hostfakesplit-mod=altorder=1"
fake2="--dpi-desync-hostfakesplit-midhost=midsld"
fake3="--dpi-desync-hostfakesplit-mod=altorder=1 --dpi-desync-hostfakesplit-midhost=midsld"
}
for fake in '' "$fake1" "$fake2" "$fake3" "$fake4" ; do
[ "$fake" = "-" ] && continue [ "$fake" = "-" ] && continue
if [ -n "$splits" ]; then if [ -n "$splits" ]; then
for pos in $splits ; do for pos in $splits ; do
@@ -1256,8 +1339,8 @@ pktws_check_domain_http_bypass_()
# $2 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk # $2 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
# $3 - domain # $3 - domain
local ok ttls s f f2 e desync pos fooling frag sec="$2" delta orig splits local ok ttls attls s f f2 e desync pos fooling frag sec="$2" delta orig splits
local need_split need_disorder need_fakedsplit need_fakeddisorder need_fake need_wssize local need_split need_disorder need_fakedsplit need_hostfakesplit need_fakeddisorder need_fake need_wssize
local splits_http='method+2 midsld method+2,midsld' local splits_http='method+2 midsld method+2,midsld'
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1' local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
@@ -1268,6 +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=
@@ -1302,25 +1386,33 @@ pktws_check_domain_http_bypass_()
done done
need_fakedsplit=1 need_fakedsplit=1
need_hostfakesplit=1
need_fakeddisorder=1 need_fakeddisorder=1
need_fake=1 need_fake=1
for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit hostfakesplit fake,hostfakesplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do
[ "$need_fake" = 0 ] && test_has_fake "$desync" && continue [ "$need_fake" = 0 ] && test_has_fake "$desync" && continue
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue [ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
[ "$need_hostfakesplit" = 0 ] && contains "$desync" hostfakesplit && continue
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue [ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
ok=0 ok=0
for ttl in $ttls; do for ttl in $ttls; do
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-ttl=$ttl $e && { # orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
[ "$SCANLEVEL" = quick ] && return # missing ACK is transmitted in the first data packet of TLS/HTTP proto
ok=1 for f in '' '--orig-ttl=1 --orig-mod-start=s1 --orig-mod-cutoff=d1'; do
need_wssize=0 pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-ttl=$ttl $f $e && {
break [ "$SCANLEVEL" = quick ] && return
} ok=1
need_wssize=0
[ "$SCANLEVEL" = force ] || break
}
done
[ "$ok" = 1 ] && break
done done
# only skip tests if TTL succeeded. do not skip if TTL failed but fooling succeeded # only skip tests if TTL succeeded. do not skip if TTL failed but fooling succeeded
[ $ok = 1 -a "$SCANLEVEL" != force ] && { [ $ok = 1 -a "$SCANLEVEL" != force ] && {
[ "$desync" = fake ] && need_fake=0 [ "$desync" = fake ] && need_fake=0
[ "$desync" = fakedsplit ] && need_fakedsplit=0 [ "$desync" = fakedsplit ] && need_fakedsplit=0
[ "$desync" = hostfakesplit ] && need_hostfakesplit=0
[ "$desync" = fakeddisorder ] && need_fakeddisorder=0 [ "$desync" = fakeddisorder ] && need_fakeddisorder=0
} }
f= f=
@@ -1329,12 +1421,21 @@ pktws_check_domain_http_bypass_()
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2" [ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
for fooling in $f; do for fooling in $f; do
ok=0 ok=0
f2=
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && { pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && {
warn_fool $fooling $desync warn_fool $fooling $desync
[ "$SCANLEVEL" = quick ] && return [ "$SCANLEVEL" = quick ] && return
need_wssize=0 need_wssize=0
ok=1 ok=1
} }
[ "$fooling" = badseq ] && {
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && continue
# --dpi-desync-badseq-increment=0 leaves modified by default ack increment
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling --dpi-desync-badseq-increment=0 $e && {
[ "$SCANLEVEL" = quick ] && return
need_wssize=0
}
}
[ "$fooling" = md5sig ] && { [ "$fooling" = md5sig ] && {
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && continue [ "$ok" = 1 -a "$SCANLEVEL" != force ] && continue
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling --dup=1 --dup-cutoff=n2 --dup-fooling=md5sig $e && { pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling --dup=1 --dup-cutoff=n2 --dup-fooling=md5sig $e && {
@@ -1399,18 +1500,30 @@ pktws_check_domain_http_bypass_()
need_fakedsplit=1 need_fakedsplit=1
need_fakeddisorder=1 need_fakeddisorder=1
need_hostfakesplit=1
need_fake=1 need_fake=1
for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit hostfakesplit fake,hostfakesplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do
[ "$need_fake" = 0 ] && test_has_fake "$desync" && continue [ "$need_fake" = 0 ] && test_has_fake "$desync" && continue
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue [ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
[ "$need_hostfakesplit" = 0 ] && contains "$desync" hostfakesplit && continue
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue [ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
ok=0 ok=0
for orig in '' 1 2 3; do # orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server.
for delta in 1 2 3 4 5; do # missing ACK is transmitted in the first data packet of TLS/HTTP proto
pktws_curl_test_update_vary $1 $2 $3 $desync ${orig:+--orig-autottl=+$orig} --dpi-desync-ttl=1 --dpi-desync-autottl=-$delta $e && ok=1 for delta in $attls; do
for f in '' '--orig-ttl=1 --orig-mod-start=s1 --orig-mod-cutoff=d1'; do
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-ttl=1 --dpi-desync-autottl=-$delta $f $e && ok=1
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
done done
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
done done
[ "$SCANLEVEL" = force ] && {
for orig in 1 2 3; do
for delta in $attls; do
pktws_curl_test_update_vary $1 $2 $3 $desync ${orig:+--orig-autottl=+$orig} --dpi-desync-ttl=1 --dpi-desync-autottl=-$delta $e && ok=1
done
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
done
}
[ "$ok" = 1 ] && [ "$ok" = 1 ] &&
{ {
echo "WARNING ! although autottl worked it requires testing on multiple domains to find out reliable delta" echo "WARNING ! although autottl worked it requires testing on multiple domains to find out reliable delta"
@@ -1420,6 +1533,7 @@ pktws_check_domain_http_bypass_()
[ "$SCANLEVEL" = force ] || { [ "$SCANLEVEL" = force ] || {
[ "$desync" = fake ] && need_fake=0 [ "$desync" = fake ] && need_fake=0
[ "$desync" = fakedsplit ] && need_fakedsplit=0 [ "$desync" = fakedsplit ] && need_fakedsplit=0
[ "$desync" = hostfakesplit ] && need_hostfakesplit=0
[ "$desync" = fakeddisorder ] && need_fakeddisorder=0 [ "$desync" = fakeddisorder ] && need_fakeddisorder=0
} }
} }
@@ -1592,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
@@ -1601,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
@@ -1628,17 +1742,19 @@ check_domain_prolog()
local code local code
[ "$SIMULATE" = 1 ] && return 0
echo echo
echo \* $1 ipv$IPV $3 echo \* $1 ipv$IPV $3
echo "- checking without DPI bypass" echo "- checking without DPI bypass"
curl_test $1 $3 && { curl_test $1 $3 && {
report_append "ipv${IPV} $3 $1 : working without bypass" report_append "$3" "$1 ipv${IPV}" "working without bypass"
[ "$SCANLEVEL" = force ] || return 1 [ "$SCANLEVEL" = force ] || return 1
} }
code=$? code=$?
curl_has_reason_to_continue $code || { curl_has_reason_to_continue $code || {
report_append "ipv${IPV} $3 $1 : test aborted, no reason to continue. curl code $(curl_translate_code $code)" report_append "$3" "$1 ipv${IPV}" "test aborted, no reason to continue. curl code $(curl_translate_code $code)"
return 1 return 1
} }
return 0 return 0
@@ -1650,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
@@ -1658,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
@@ -1680,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
@@ -1689,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
@@ -1748,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()
@@ -1808,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
} }
@@ -1816,12 +1936,13 @@ 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"
} }
} }
DOMAINS_COUNT="$(echo "$DOMAINS" | wc -w | trim)"
local IPVS_def=4 local IPVS_def=4
[ -n "$IPVS" ] || { [ -n "$IPVS" ] || {
@@ -2158,7 +2279,6 @@ sigsilent()
exit 1 exit 1
} }
fsleep_setup fsleep_setup
fix_sbin_path fix_sbin_path
check_system check_system
@@ -2201,6 +2321,18 @@ cleanup
echo echo
echo \* SUMMARY echo \* SUMMARY
report_print report_print
[ "$DOMAINS_COUNT" -gt 1 ] && {
echo
echo \* COMMON
result_intersection_print
echo
[ "$SCANLEVEL" = force ] || {
echo "blockcheck optimizes test sequence. To save time some strategies can be skipped if their test is considered useless."
echo "That's why COMMON intersection can miss strategies that would work for all domains."
echo "Use \"force\" scan level to test all strategies and generate trustable intersection."
echo "Current scan level was \"$SCANLEVEL\"".
}
}
echo echo
echo "Please note this SUMMARY does not guarantee a magic pill for you to copy/paste and be happy." echo "Please note this SUMMARY does not guarantee a magic pill for you to copy/paste and be happy."
echo "Understanding how strategies work is very desirable." echo "Understanding how strategies work is very desirable."

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()
{ {
@@ -297,10 +313,10 @@ minsleep()
replace_char() replace_char()
{ {
local a=$1 local a="$1"
local b=$2 local b="$2"
shift; shift shift; shift
echo "$@" | tr $a $b echo "$@" | tr "$a" "$b"
} }
replace_str() replace_str()
@@ -318,6 +334,12 @@ setup_md5()
exists $MD5 || MD5=md5 exists $MD5 || MD5=md5
} }
md5f()
{
setup_md5
$MD5 | cut -d ' ' -f1
}
setup_random() setup_random()
{ {
[ -n "$RCUT" ] && return [ -n "$RCUT" ] && return
@@ -330,7 +352,6 @@ random()
{ {
# $1 - min, $2 - max # $1 - min, $2 - max
local r rs local r rs
setup_md5
setup_random setup_random
if [ -c /dev/urandom ]; then if [ -c /dev/urandom ]; then
read rs </dev/urandom read rs </dev/urandom
@@ -338,7 +359,7 @@ random()
rs="$RANDOM$RANDOM$(date)" rs="$RANDOM$RANDOM$(date)"
fi fi
# shells use signed int64 # shells use signed int64
r=1$(echo $rs | $MD5 | sed 's/[^0-9]//g' | $RCUT) r=1$(echo $rs | md5f | sed 's/[^0-9]//g' | $RCUT)
echo $(( ($r % ($2-$1+1)) + $1 )) echo $(( ($r % ($2-$1+1)) + $1 ))
} }

View File

@@ -703,7 +703,7 @@ removable_pkgs_openwrt()
for pkg in $PKGS2; do for pkg in $PKGS2; do
check_package_exists_openwrt $pkg && PKGS="${PKGS:+$PKGS }$pkg" check_package_exists_openwrt $pkg && PKGS="${PKGS:+$PKGS }$pkg"
done done
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS" PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32 ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS"
} }
openwrt_fix_broken_apk_uninstall_scripts() openwrt_fix_broken_apk_uninstall_scripts()
@@ -744,7 +744,7 @@ check_prerequisites_openwrt()
iptables) iptables)
pkg_iptables=iptables pkg_iptables=iptables
check_package_exists_openwrt iptables-zz-legacy && pkg_iptables=iptables-zz-legacy check_package_exists_openwrt iptables-zz-legacy && pkg_iptables=iptables-zz-legacy
PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra" PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32"
check_package_exists_openwrt ip6tables-zz-legacy && pkg_iptables=ip6tables-zz-legacy check_package_exists_openwrt ip6tables-zz-legacy && pkg_iptables=ip6tables-zz-legacy
[ "$DISABLE_IPV6" = 1 ] || PKGS="$PKGS $pkg_iptables ip6tables-mod-nat ip6tables-extra" [ "$DISABLE_IPV6" = 1 ] || PKGS="$PKGS $pkg_iptables ip6tables-mod-nat ip6tables-extra"
;; ;;

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
}

View File

@@ -541,3 +541,38 @@ nfqws,tpws: fix possible crashes or high memory usage if hostlist has duplicate
init.d: custom scripts 50-discord-media, 50-stun4all init.d: custom scripts 50-discord-media, 50-stun4all
init.d: windivert filters for discord media, stun, wireguard init.d: windivert filters for discord media, stun, wireguard
readme: hardware problems description readme: hardware problems description
v72
winws: --wf-raw-part
nfqws: --dpi-desync=hostfakesplit
nfqws: --dpi-desync-fake-tcp-mod=seq
nfqws: --dpi-desync-fake-tls=!+offset , --dpi-desync-fake-xxx=[+offset]@filename
nfqws: --dpi-desync-fakedsplit-mod=altorder for fakedsplit/fakeddisorder
nfqws: --dpi-desync-hostfakesplit-mod=altorder
nfqws: fakedsplit/fakeddisorder normalize fake split pattern offset to reasm offset
nfqws: optimize ipv4 ip_id. apply ip_id on all OS the same way.
blockcheck: print PRETTY_NAME and some OPENWRT_xxx from /etc/os-release
blockcheck: new strategies
blockcheck: curl test simulation : SIMULATE=1
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

View File

@@ -16,7 +16,7 @@
в простыню [readme.md](readme.md). в простыню [readme.md](readme.md).
Обход DPI является хакерской методикой. Под этим словом понимается метод, Обход DPI является хакерской методикой. Под этим словом понимается метод,
которому сопротивляется окружающая среда, которому автоматически не которому оказывается активное противодействие и поэтому автоматически не
гарантирована работоспособность в любых условиях и на любых ресурсах, требуется гарантирована работоспособность в любых условиях и на любых ресурсах, требуется
настройка под специфические условия у вашего провайдера. Условия могут меняться настройка под специфические условия у вашего провайдера. Условия могут меняться
со временем, и методика может начинать или переставать работать, может со временем, и методика может начинать или переставать работать, может
@@ -52,6 +52,18 @@
1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив. 1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив.
Для openwrt и прошивок используйте вариант `openwrt-embedded`. Для openwrt и прошивок используйте вариант `openwrt-embedded`.
Для экономия места в /tmp можно качать через curl в stdout и сразу распаковывать. Для экономия места в /tmp можно качать через curl в stdout и сразу распаковывать.
Пример под openwrt для версии zapret 71.4 (для других URL отличается) :
```
$ curl -Lo - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4-openwrt-embedded.tar.gz | tar -zx
$ wget -O - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4-openwrt-embedded.tar.gz | tar -zx
```
Пример под традиционный linux для версии zapret 71.4 (для других URL отличается) :
```
$ curl -Lo - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4.tar.gz | tar -zx
$ wget -O - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4.tar.gz | tar -zx
```
curl должен быть предварительно установлен. Но он в любом случае понадобится далее.
Вариант с wget будет работать только если установленный wget поддерживает https.
2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и 2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и
сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`. сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`.
@@ -129,10 +141,14 @@
или `tpws` и запомнить найденные стратегии для дальнейшего применения. или `tpws` и запомнить найденные стратегии для дальнейшего применения.
Следует понимать, что скрипт проверяет доступность только конкретного Следует понимать, что скрипт проверяет доступность только конкретного
домена, который вы вводите в начале. Вероятно, все остальные домены домена, который вы вводите в начале, конкретной программой curl.
блокированы подобным образом, **но не факт**. В большинстве случаев можно У разных клиентов есть свой фингерпринт. У броузеров один, у curl другой.
объединить несколько стратегий в одну универсальную, и это **крайне Может применяться или не применяться многопакетный TLS с постквантовой криптографией (kyber).
желательно**. Необходимо понимать как работают стратегии. zapret **не может От этого может зависеть работоспособность стратегий.
Обычно остальные домены блокированы подобным образом, **но не факт**.
Бывают специальные блокировки. Некоторые параметры требуют тюнинга под "общий знаменатель".
В большинстве случаев можно объединить несколько стратегий в одну универсальную, и это **крайне
желательно**, но это требует понимания как работают стратегии. zapret **не может
пробить блокировку по IP адресу**. Для проверки нескольких доменов вводите пробить блокировку по IP адресу**. Для проверки нескольких доменов вводите
их через пробел. их через пробел.
@@ -143,19 +159,7 @@
> направления (IP сервера). скрипт не всегда может выдать вам в итогах > направления (IP сервера). скрипт не всегда может выдать вам в итогах
> оптимальную стратегию, которую надо просто переписать в настройки. В > оптимальную стратегию, которую надо просто переписать в настройки. В
> некоторых случаях надо реально думать что происходит, анализируя результат > некоторых случаях надо реально думать что происходит, анализируя результат
> на разных стратегиях. Если вы применяете большой TTL, чтобы достать до > на разных стратегиях.
> магистрала, то не лишним будет добавить дополнительный ограничитель
> `--dpi-desync-fooling`, чтобы не сломать сайты на более коротких
> дистанциях. `md5sig` наиболее совместим, но работает **только** на linux
> серверах. `badseq` может работать только на https и не работать на http.
> Чтобы выяснить какие дополнительные ограничители работают, смотрите
> результат теста аналогичных стратегий без TTL с каждым из этих
> ограничителей.
>
> При использовании `autottl` следует протестировать как можно больше разных
> доменов. Эта техника может на одних провайдерах работать стабильно, на
> других потребуется выяснить при каких параметрах она стабильна, на третьих
> полный хаос, и проще отказаться.
> >
> Далее, имея понимание что работает на http, https, quic нужно > Далее, имея понимание что работает на http, https, quic нужно
> сконструировать параметры запуска `tpws` и/или `nfqws` с использованием > сконструировать параметры запуска `tpws` и/или `nfqws` с использованием
@@ -202,8 +206,8 @@
> Но здесь совсем "копи-пастный" вариант. Чем больше вы объедините стратегий и > Но здесь совсем "копи-пастный" вариант. Чем больше вы объедините стратегий и
> сократите их общее количество, тем будет лучше. > сократите их общее количество, тем будет лучше.
> >
> Если вам не нужно дурение отдельных протоколов, лучше всего будет их > Если вам не нужно дурение отдельных протоколов, лучше всего будет убрать
> убрать из системы перехвата трафика через параметры `TPWS_PORTS`, > лишние порты из системы перехвата трафика через параметры `TPWS_PORTS`,
> `NFQWS_PORTS_TCP`, `NFQWS_PORTS_UDP` и убрать соответствующие им профили > `NFQWS_PORTS_TCP`, `NFQWS_PORTS_UDP` и убрать соответствующие им профили
> мультистратегии. > мультистратегии.
> >
@@ -230,6 +234,15 @@
> В этом примере `wssize` будет применяться всегда к порту tcp `443` вне > В этом примере `wssize` будет применяться всегда к порту tcp `443` вне
> зависимости от параметра `MODE_FILTER`. Хостлист будет игнорироваться, > зависимости от параметра `MODE_FILTER`. Хостлист будет игнорироваться,
> если таковой имеется. К http применять `wssize` вредно и бессмысленно. > если таковой имеется. К http применять `wssize` вредно и бессмысленно.
>
> Иногда требуется дописать к стратегиям свои собственные параметры.
> Например, нужно изменить количество повторов фейков или задать свой фейк.
> Это делается через шелл-переменные `PKTWS_EXTRA`, `TPWS_EXTRA`.
>
> ```PKTWS_EXTRA="--dpi-desync-repeats=10 --dpi-desync-fake-tls=/tmp/tls.bin" ./blockcheck.sh```
>
> Перебор всех комбинаций может привести к ожиданию неделями, поэтому выбран разумный
> костяк проверки, на который вы можете навешивать свои кустомизации.
7. Запустите скрипт облегченной установки - `install_easy.sh` Выберите `nfqws` 7. Запустите скрипт облегченной установки - `install_easy.sh` Выберите `nfqws`
и/или `tpws`, затем согласитесь на редактирование параметров. Откроется и/или `tpws`, затем согласитесь на редактирование параметров. Откроется

View File

@@ -11,8 +11,8 @@
## Немного разъяснений ## Немного разъяснений
Обход DPI является хакерской методикой. Под этим словом понимается метод, которому сопротивляется окружающая среда, Обход DPI является хакерской методикой. Под этим словом понимается метод, которому оказывается активное противодействие и поэтому
которому автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах, автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах,
требуется настройка под специфические условия у вашего провайдера. Условия могут меняться со временем, требуется настройка под специфические условия у вашего провайдера. Условия могут меняться со временем,
и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации. и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации.
Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать. Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать.
@@ -30,24 +30,7 @@
Будем считать, что у вас есть windows 7 или выше. Задача - обойти блокировки с самой системы. Будем считать, что у вас есть windows 7 или выше. Задача - обойти блокировки с самой системы.
> [!NOTE] ## Я ЧТО-ТО ДЕЛАЛ, НЕ ПОМОГЛО, КАК ТЕПЕРЬ ЭТО УДАЛИТЬ
> Есть решение самое простое, а есть "как положено".
## САМОЕ ПРОСТОЕ РЕШЕНИЕ
_"Совсем ничего не могу, все очень сложно, дайте мне таблетку."_ ©Простой пользователь
1) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.
2) Запустите `zapret-winws/preset_russia.cmd` от имени администратора. Возможно, заведется сразу.
> То же самое с ограничителем по автоматически создаваемому хост-листу `preset_russia_autohostlist.cmd`.
> Что такое `autohostlist` - читайте [readme.md](./readme.md). Проще говоря, мы обходим только то, что долго и упорно не хочет открываться.
> Сначала не будет, но надо пытаться много раз, и тогда сработает, а дальше будет всегда срабатывать.
> Остальное не будет ломаться. Использовать только, если первый вариант тоже работает.
Не помогла _"таблетка"_ ? Это вовсе не значит, что ничего не получится. Но придется делать по нормальному.
## НЕ ПОМОГЛО, КАК ТЕПЕРЬ ЭТО УДАЛИТЬ
Если вы не устанавливали zapret как службу или запланированную задачу (а это требует редактирования cmd файлов), Если вы не устанавливали zapret как службу или запланированную задачу (а это требует редактирования cmd файлов),
достаточно закрыть окно с winws и запустить windivert_delete.cmd. достаточно закрыть окно с winws и запустить windivert_delete.cmd.
@@ -55,14 +38,17 @@ _"Совсем ничего не могу, все очень сложно, да
После чего можно удалить папку с zapret. На этом деинсталляция закончена. После чего можно удалить папку с zapret. На этом деинсталляция закончена.
Если же вы устанавливали zapret как службу, то вы наверняка знаете как ее удалить. Если же вы устанавливали zapret как службу, то вы наверняка знаете как ее удалить.
## РЕШЕНИЕ "КАК ПОЛОЖЕНО" Если вдруг среди того, на что вы нажимали, есть слова "general", "alt", ".bat", "автозапуск", или же есть файлы, которые отсутствуют
в оригинальных репозиториях, то это сборка. Вы не получите ответа как ее удалить от разработчика zapret.
Спрашивайте самих сборщиков. Разработчик не предоставляет простого решения, этим занимаются сборщики, но они и сами отвечают за свои продукты.
1) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip. ## Настройка
2) Если у вас Windows 7 x64, однократно запустите `win7/install_win7.cmd`. Батник заменит файлы windivert на совместимую с Windows 7 версию. 1. Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.
> [!WARNING] 2. Если у вас Windows 7 x64, однократно запустите `win7/install_win7.cmd`. Батник заменит файлы windivert на совместимую с Windows 7 версию.
> Для 32-битных систем Windows нет готового полного варианта.
> Для 32-битных систем Windows нет готового полного варианта.
> На windows 11 arm64 выполните `arm64/install_arm64.cmd` от имени администратора и перезагрузите компьютер. > На windows 11 arm64 выполните `arm64/install_arm64.cmd` от имени администратора и перезагрузите компьютер.
> Читайте [docs/windows.md](./windows.md) > Читайте [docs/windows.md](./windows.md)
@@ -72,15 +58,15 @@ _"Совсем ничего не могу, все очень сложно, да
> более-менее научились с ним дружить. > более-менее научились с ним дружить.
> Если проблема имеет место , используйте исключения. Если не помогает - отключайте антивирус совсем. > Если проблема имеет место , используйте исключения. Если не помогает - отключайте антивирус совсем.
3) Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам zapret. 3. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам zapret.
4) Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. nat не подходит 4. Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. nat не подходит
5) Запустите `blockcheck\blockcheck.cmd`. blockcheck в начале проверяет **DNS**. 5. Запустите `blockcheck\blockcheck.cmd`. blockcheck в начале проверяет **DNS**.
Если выводятся сообщения о подмене адресов, то нужно будет решить проблему с **DNS**. Если выводятся сообщения о подмене адресов, то нужно будет решить проблему с **DNS**.
blockcheck перейдет в этом случае на **DoH** _(DNS over HTTPS)_ и будет пытаться получить и использовать реальные IP адреса. blockcheck перейдет в этом случае на **DoH** _(DNS over HTTPS)_ и будет пытаться получить и использовать реальные IP адреса.
Но если вы не настроите решение этой проблемы, обход будет работать только для тех программ, Но если вы не настроите решение этой проблемы, обход будет работать только для тех программ,
которые сами реализуют механизмы SecureDNS. Для других программ обход работать не будет. которые сами реализуют механизмы SecureDNS. Для других программ обход работать не будет.
> Решение проблемы DNS выходит за рамки проекта. Обычно она решается либо заменой DNS серверов > Решение проблемы DNS выходит за рамки проекта. Обычно она решается либо заменой DNS серверов
> от провайдера на публичные (`1.1.1.1`, `8.8.8.8`), либо в случае перехвата провайдером обращений > от провайдера на публичные (`1.1.1.1`, `8.8.8.8`), либо в случае перехвата провайдером обращений
@@ -92,35 +78,29 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
> >
> Тут все разжевано как и где это включается : https://hackware.ru/?p=13707 > Тут все разжевано как и где это включается : https://hackware.ru/?p=13707
6) blockcheck позволяет выявить рабочую стратегию обхода блокировок. 6. blockcheck позволяет выявить рабочую стратегию обхода блокировок.
Лог скрипта будет сохранен в `blockcheck\blockcheck.log`. Лог скрипта будет сохранен в `blockcheck\blockcheck.log`.
Запомните/перепишите найденные стратегии. Запомните/перепишите найденные стратегии.
> [!WARNING] Следует понимать, что скрипт проверяет доступность только конкретного
> Следует понимать, что blockcheck проверяет доступность только конкретного домена, который вы вводите в начале. домена, который вы вводите в начале, конкретной программой curl.
> Вероятно, все остальные домены блокированы подобным образом, но не факт. У разных клиентов есть свой фингерпринт. У броузеров один, у curl другой.
Может применяться или не применяться многопакетный TLS с постквантовой криптографией (kyber).
От этого может зависеть работоспособность стратегий.
Обычно остальные домены блокированы подобным образом, **но не факт**.
Бывают специальные блокировки. Некоторые параметры требуют тюнинга под "общий знаменатель".
В большинстве случаев можно объединить несколько стратегий в одну универсальную, и это **крайне
желательно**, но это требует понимания как работают стратегии. zapret **не может
пробить блокировку по IP адресу**. Для проверки нескольких доменов вводите их через пробел.
> [!TIP] > Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у
> В большинстве случаев можно обьединить несколько стратегий в одну универсальную, и это крайне желательно. > вас может быть несколько маршрутов с различной длиной по ХОПам, с DPI на
> разных хопах. Приходится преодолевать целый зоопарк DPI, которые еще и
> Необходимо понимать [как работают стратегии](./readme.md/#nfqws). > включаются в работу хаотичным образом или образом, зависящим от
> zapret не может пробить блокировку по IP адресу. Для проверки нескольких доменов вводите их через пробел. > направления (IP сервера). скрипт не всегда может выдать вам в итогах
> > оптимальную стратегию, которую надо просто переписать в настройки. В
> Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов > некоторых случаях надо реально думать что происходит, анализируя результат
> с различной длиной по ХОПам, с DPI на разных хопах. Приходится преодолевать целый зоопарк DPI, > на разных стратегиях.
> которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера).
> blockcheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки.
> В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях.
> Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель
> `--dpi-desync-fooling`, чтобы не сломать сайты на более коротких дистанциях.
> _md5sig_ наиболее совместим, но работатет только на linux серверах.
> badseq может работать только на https и не работать на http.
> Чтобы выяснить какие дополнительные ограничители работают, смотрите результат теста аналогичных стратегий без TTL
> с каждым из этих ограничителей.
>
> При использовании autottl следует протестировать как можно больше разных доменов. Эта техника
> может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах
> она стабильна, на третьих полный хаос, и проще отказаться.
> >
> Далее, имея понимание что работает на http, https, quic, нужно сконструировать параметры запуска winws > Далее, имея понимание что работает на http, https, quic, нужно сконструировать параметры запуска winws
> с использованием мультистратегии. Как работают мультистратегии описано в [readme.md](./readme.md#множественные-стратегии). > с использованием мультистратегии. Как работают мультистратегии описано в [readme.md](./readme.md#множественные-стратегии).
@@ -183,12 +163,21 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
> >
> В этих примерах wssize будет применяться всегда к порту tcp 443, а хостлист будет игнорироваться. > В этих примерах wssize будет применяться всегда к порту tcp 443, а хостлист будет игнорироваться.
> К http применять wssize вредно и бессмысленно. > К http применять wssize вредно и бессмысленно.
>
> Иногда требуется дописать к стратегиям свои собственные параметры.
> Например, нужно изменить количество повторов фейков или задать свой фейк.
> Это делается через шелл-переменные `PKTWS_EXTRA`, `TPWS_EXTRA`. Пользуйтесь шеллом `cygwin/cygwin-admin.cmd`.
>
> ```PKTWS_EXTRA="--dpi-desync-repeats=10 --dpi-desync-fake-tls=/tmp/tls.bin" blockcheck```
>
> Перебор всех комбинаций может привести к ожиданию неделями, поэтому выбран разумный
> костяк проверки, на который вы можете навешивать свои кустомизации.
7) Протестируйте найденные стратегии на winws. Winws следует брать из zapret-winws. 7. Протестируйте найденные стратегии на winws. Winws следует брать из zapret-winws.
Для этого откройте командную строку windows от имени администратора в директории zapret-winws. Для этого откройте командную строку windows от имени администратора в директории zapret-winws.
Проще всего это сделать через `_CMD_ADMIN.cmd`. Он сам поднимет права и зайдет в нужную директорию. Проще всего это сделать через `_CMD_ADMIN.cmd`. Он сам поднимет права и зайдет в нужную директорию.
8) Обеспечьте удобную загрузку обхода блокировок. 8. Обеспечьте удобную загрузку обхода блокировок.
> Есть 2 варианта. Ручной запуск через ярлык или автоматический при старте системы, вне контекста текущего пользователя. > Есть 2 варианта. Ручной запуск через ярлык или автоматический при старте системы, вне контекста текущего пользователя.
> Последний вариант разделяется на запуск через планировщик задач и через службы windows. > Последний вариант разделяется на запуск через планировщик задач и через службы windows.
@@ -203,11 +192,11 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
> >
> Аналогично настраиваются и службы windows. Смотрите `service_*.cmd` > Аналогично настраиваются и службы windows. Смотрите `service_*.cmd`
9) Если ломаются отдельные незаблокированные ресурсы, нужно пользоваться ограничивающим 9. Если ломаются отдельные незаблокированные ресурсы, нужно пользоваться ограничивающим
ipset или хост листом. Читайте основной талмуд [readme.md](./readme.md) ради подробностей. ipset или хост листом. Читайте основной талмуд [readme.md](./readme.md) ради подробностей.
Но еще лучше будет подбирать такие стратегии, которые ломают минимум. Но еще лучше будет подбирать такие стратегии, которые ломают минимум.
Есть стратегии довольно безобидные, а есть сильно ломающие, которые подходят только для точечного пробития отдельных ресурсов, Есть стратегии довольно безобидные, а есть сильно ломающие, которые подходят только для точечного пробития отдельных ресурсов,
когда ничего лучше нет. Хорошая стратегия может сильно ломать из-за плохо подобранных ограничителей для фейков - ttl, fooling. когда ничего лучше нет. Хорошая стратегия может сильно ломать из-за плохо подобранных ограничителей для фейков - ttl, fooling.
> [!CAUTION] > [!CAUTION]
> Это минимальная инструкция, чтобы соориентироваться с чего начать. Однако, это - не панацея. > Это минимальная инструкция, чтобы соориентироваться с чего начать. Однако, это - не панацея.

View File

@@ -1,4 +1,4 @@
# zapret v71.4 # 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)
@@ -136,109 +137,126 @@ For BSD systems there is dvtws. Its built from the same source and has almost th
nfqws takes the following parameters: nfqws takes the following parameters:
``` ```
@<config_file> ; read file for options. must be the only argument. other options are ignored. @<config_file> ; read file for options. must be the only argument. other options are ignored.
--debug=0|1 --debug=0|1
--dry-run ; verify parameters and exit with code 0 if successful --dry-run ; verify parameters and exit with code 0 if successful
--version ; print version and exit --version ; print version and exit
--comment ; any text (ignored) --comment ; any text (ignored)
--qnum=<nfqueue_number> --qnum=<nfqueue_number>
--daemon ; daemonize --daemon ; daemonize
--pidfile=<filename> ; write pid to file --pidfile=<filename> ; write pid to file
--user=<username> ; drop root privs --user=<username> ; drop root privs
--uid=uid[:gid1,gid2,...] ; drop root privs --uid=uid[:gid1,gid2,...] ; drop root privs
--bind-fix4 ; apply outgoing interface selection fix for generated ipv4 packets --bind-fix4 ; apply outgoing interface selection fix for generated ipv4 packets
--bind-fix6 ; apply outgoing interface selection fix for generated ipv6 packets --bind-fix6 ; apply outgoing interface selection fix for generated ipv6 packets
--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
--ctrack-timeouts=S:E:F[:U] ; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default 60:300:60:60 --wssize-forced-cutoff=0|1 ; 1(default)=auto cutoff wssize on known protocol
--ctrack-disable=[0|1] ; 1 or no argument disables conntrack --ctrack-timeouts=S:E:F[:U] ; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default 60:300:60:60
--ipcache-lifetime=<int> ; time in seconds to keep cached hop count and domain name (default 7200). 0 = no expiration --ctrack-disable=[0|1] ; 1 or no argument disables conntrack
--ipcache-hostname=[0|1] ; 1 or no argument enables ip->hostname caching --ipcache-lifetime=<int> ; time in seconds to keep cached hop count and domain name (default 7200). 0 = no expiration
--hostcase ; change Host: => host: --ipcache-hostname=[0|1] ; 1 or no argument enables ip->hostname caching
--hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host" --hostcase ; change Host: => host:
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size --hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host"
--domcase ; mix domain case : Host: TeSt.cOm --hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
--methodeol ; add '\n' before method and remove space after Host: --domcase ; mix domain case : Host: TeSt.cOm
--synack-split=[syn|synack|acksyn] ; perform TCP split handshake : send SYN only, SYN+ACK or ACK+SYN --methodeol ; add '\n' before method and remove space after Host:
--orig-ttl=<int> ; set TTL for original packets --synack-split=[syn|synack|acksyn] ; perform TCP split handshake : send SYN only, SYN+ACK or ACK+SYN
--orig-ttl6=<int> ; set ipv6 hop limit for original packets. by default ttl value is used --orig-ttl=<int> ; set TTL for original packets
--orig-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: +5:3-64. "0:0-0" or "-" disables autottl. --orig-ttl6=<int> ; set ipv6 hop limit for original packets. by default ttl value is used
--orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --orig-autottl for ipv6 only --orig-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: +5:3-64. "0:0-0" or "-" disables autottl.
--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-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --orig-autottl for ipv6 only
--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-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=<int> ; duplicate original packets. send N dups before original. --orig-tcp-flags-unset=<int|0xHEX|flaglist> ; unset these tcp flags (flags &= ~value)
--dup-replace=[0|1] ; 1 or no argument means do not send original, only dups --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
--dup-ttl=<int> ; set TTL for dups --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-ttl6=<int> ; set ipv6 hop limit for dups. by default ttl value is used --dup=<int> ; duplicate original packets. send N dups before original.
--dup-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-64. "0:0-0" or "-" disables autottl. --dup-replace=[0|1] ; 1 or no argument means do not send original, only dups
--dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dup-autottl for ipv6 only --dup-ttl=<int> ; set TTL for dups
--dup-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2 --dup-ttl6=<int> ; set ipv6 hop limit for dups. by default ttl value is used
--dup-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment for dup. default -600000 --dup-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-64. "0:0-0" or "-" disables autottl.
--dup-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment for dup. default -10000 --dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dup-autottl for ipv6 only
--dup-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment for dup. default -66000 --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-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-tcp-flags-unset=<int|0xHEX|flaglist> ; unset these tcp flags (flags &= ~value)
--dup-cutoff=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N --dup-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper --dup-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment for dup. default -600000
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824) --dup-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment for dup. default -10000
--dpi-desync-ttl=<int> ; set ttl for desync packet --dup-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment for dup. default -66000
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used. --dup-ip-id=same|zero|seq|rnd ; ipv4 ip_id mode for dupped packets
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-20. "0:0-0" or "-" disables autottl. --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
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dpi-desync-autottl for ipv6 only --dup-cutoff=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2 --ip-id=zero|seq|seqgroup|rnd ; ipv4 ip_id assignment scheme
--dpi-desync-repeats=<N> ; send every desync packet N times --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-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?) --dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; comma separated list of split positions --dpi-desync-ttl=<int> ; set ttl for desync packet
; markers: method,host,endhost,sld,endsld,midsld,sniext --dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used.
; full list is only used by multisplit and multidisorder --dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-20. "0:0-0" or "-" disables autottl.
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dpi-desync-autottl for ipv6 only
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment --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-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap --dpi-desync-tcp-flags-unset=<int|0xHEX|flaglist> ; unset these tcp flags (flags &= ~value)
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder --dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8. --dpi-desync-repeats=<N> ; send every desync packet N times
--dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32. --dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?)
--dpi-desync-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment. default -600000 --dpi-desync-split-pos=N|-N|marker+N|marker-N ; comma separated list of split positions
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000 ; markers: method,host,endhost,sld,endsld,midsld,sniext
--dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000 ; full list is only used by multisplit and multidisorder
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet ; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
--dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request --dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
--dpi-desync-fake-tls=<filename>|0xHEX|! ; file containing fake TLS ClientHello (for https). '!' = standard fake --dpi-desync-split-seqovl-pattern=[+ofs]@<filename>|0xHEX ; pattern for the fake part of overlap
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap --dpi-desync-fakedsplit-pattern=[+ofs]@<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload --dpi-desync-fakedsplit-mod=mod[,mod] ; mods can be none,altorder=0|1|2|3 + 0|8|16
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload --dpi-desync-hostfakesplit-midhost=marker+N|marker-N ; additionally split real hostname at specified marker. must be within host..endhost or won't be splitted.
--dpi-desync-fake-quic=<filename>|0xHEX ; file containing fake QUIC Initial --dpi-desync-hostfakesplit-mod=mod[,mod] ; can be none, host=<hostname>, altorder=0|1
--dpi-desync-fake-wireguard=<filename>|0xHEX ; file containing fake wireguard handshake initiation --dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8.
--dpi-desync-fake-dht=<filename>|0xHEX ; file containing fake DHT (d1..e) --dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32.
--dpi-desync-fake-discord=<filename>|0xHEX ; file containing fake Discord voice connection initiation packet (IP Discovery) --dpi-desync-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment. default -600000
--dpi-desync-fake-stun=<filename>|0xHEX ; file containing fake STUN message --dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; file containing unknown udp protocol fake payload --dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000
--dpi-desync-udplen-increment=<int> ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length. --dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
--dpi-desync-udplen-pattern=<filename>|0xHEX ; udp tail fill pattern --dpi-desync-fake-tcp-mod=mod[,mod] ; comma separated list of tcp fake mods. available mods : none,seq
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N --dpi-desync-fake-http=[+ofs]@<filename>|0xHEX ; file containing fake http request
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N --dpi-desync-fake-tls=[+ofs]@<filename>|0xHEX|![+offset] ; file containing fake TLS ClientHello (for https). '!' = standard fake
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed) --dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap
--hostlist-domains=<domain_list> ; comma separated fixed domain list --dpi-desync-fake-unknown=[+ofs]@<filename>|0xHEX ; file containing unknown protocol fake payload
--hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed) --dpi-desync-fake-syndata=[+ofs]@<filename>|0xHEX ; file containing SYN data payload
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list --dpi-desync-fake-quic=[+ofs]@<filename>|0xHEX ; file containing fake QUIC Initial
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically --dpi-desync-fake-wireguard=[+ofs]@<filename>|0xHEX ; file containing fake wireguard handshake initiation
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3) --dpi-desync-fake-dht=[+ofs]@<filename>|0xHEX ; file containing fake DHT (d1..e)
--hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60) --dpi-desync-fake-discord=[+ofs]@<filename>|0xHEX ; file containing fake Discord voice connection initiation packet (IP Discovery)
--hostlist-auto-retrans-threshold=<int> ; how many request retransmissions cause attempt to fail (default : 3) --dpi-desync-fake-stun=[+ofs]@<filename>|0xHEX ; file containing fake STUN message
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives --dpi-desync-fake-unknown-udp=[+ofs]@<filename>|0xHEX ; file containing unknown udp protocol fake payload
--new ; begin new strategy (new profile) --dpi-desync-udplen-increment=<int> ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length.
--skip ; do not use this profile --dpi-desync-udplen-pattern=[+ofs]@<filename>|0xHEX ; udp tail fill pattern
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed. --dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list supported. --dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported. --hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed)
--filter-l7=<proto> ; L6-L7 protocol filter. multiple comma separated values allowed. proto: http tls quic wireguard dht discord stun unknown --hostlist-domains=<domain_list> ; comma separated fixed domain list
--filter-ssid=ssid1[,ssid2,ssid3,...] ; per profile wifi SSID filter --hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed)
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed) --hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
--ipset-ip=<ip_list> ; comma separated fixed subnet list --hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed) --hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list --hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
--hostlist-auto-retrans-threshold=<int> ; how many request retransmissions cause attempt to fail (default : 3)
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives
--new ; begin new strategy (new profile)
--skip ; do not use this profile
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list supported.
--filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported.
--filter-l7=<proto> ; L6-L7 protocol filter. multiple comma separated values allowed. proto: http tls quic wireguard dht discord stun unknown
--filter-ssid=ssid1[,ssid2,ssid3,...] ; per profile wifi SSID filter
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-ip=<ip_list> ; comma separated fixed subnet list
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
``` ```
Many parameters dealing with binary data support loading from hex string prefixed by "0x" or from a file.
Filename can be "as is" or prefixed with "@". If there's "+number" prefix before "@" it means offset of data inside the file.
Offset must be less that data size.
### DPI desync attack ### DPI desync attack
The idea is to take original message, modify it, add additional fake information in such a way that the server OS accepts original data only The idea is to take original message, modify it, add additional fake information in such a way that the server OS accepts original data only
@@ -288,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.
@@ -315,6 +337,9 @@ Resulting order would be : `fake1 fake1 fake1 fake2 fake2 fake2 fake3 fake3 fake
### FAKE mods ### FAKE mods
By default all tcp fakes are sent with the same sequence as original packet.
This can be changed by `--dpi-desync-fake-tcp-mod=seq`. In the latter case all fakes are sent as if they would be tcp segments of a single fake.
**nfqws** has built-in TLS fake. It can be customized with `--dpi-desync-fake-tls` option. **nfqws** has built-in TLS fake. It can be customized with `--dpi-desync-fake-tls` option.
Customized fake data can be anything - valid TLS Client Hello or arbitrary data. Customized fake data can be anything - valid TLS Client Hello or arbitrary data.
It's possible to use TLS Client Hello with any fingerprint and any SNI. It's possible to use TLS Client Hello with any fingerprint and any SNI.
@@ -343,8 +368,37 @@ Example : `--dpi-desync-fake-tls=iana_org.bin --dpi-desync-fake-tls-mod=rndsni -
* `multisplit`. split request at specified in `--dpi-desync-split-pos` positions * `multisplit`. split request at specified in `--dpi-desync-split-pos` positions
* `multidisorder`. same as `multisplit` but send in reverse order * `multidisorder`. same as `multisplit` but send in reverse order
* `fakedsplit`. split request into 2 segments adding fakes in the middle of them : fake 1st segment, 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment * `fakedsplit`. sequental one position split with fake mix
* `fakeddisorder`. same as `fakedsplit` but with another order : fake 2nd segment, 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment * `hostfakesplit` (altorder=0). fake host part of the request : before host, random fake host, real host (optionally split this part), random fake host repeat, after host
* `hostfakesplit` (altorder=1). fake host part of the request : before host, random fake host, after host, real host (optionally split this part)
* `fakedsplit`. reverse one position split with fake mix
`--dpi-desync-fakedsplit-mod=altorder=N` specifies number which influence to the presence of individual fakes in `fakedsplit`/`fakeddisorder`.
`fakedsplit` TCP segments of multi-packet messages with split pos :
* `altorder=0`. fake 1st segment, 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
* `altorder=1`. 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
* `altorder=2`. 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
* `altorder=3`. 1st segment, fake 2nd segment, 2nd segment
`fakeddisorder` TCP segments of multi-packet messages with split pos :
* `altorder=0`. fake 2nd segment, 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment
* `altorder=1`. 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment
* `altorder=2`. 2nd segment, fake 1st segment, 1st segment, fake 1st segment
* `altorder=3`. 1st segment, fake 1st segment, 1st segment
`fakedsplit`/`fakeddisorder` TCP segments of multi-packet messages without split pos :
* `altorder=0`. fake, original, fake
* `altorder=8`. original, fake
* `altorder=16`. original
Resulting `altorder=N` is the sum of two `altorder` parts mentioned above.
`--dpi-desync-fakedsplit-pattern` defines data payload of fakes in `fakedsplit`/`fakeddisorder`. By default pattern is simple `0x00`.
Offset of split part + offset of current packet in multi-packet message define offset in the pattern.
Positions are defined by markers. Positions are defined by markers.
@@ -373,6 +427,22 @@ First relative markers are searched. If no suitable found absolute markers are s
For example, `--dpi-desync-split-pos=method+2,midsld,5` means `method+2` for http, `midsld` for TLS and 5 for others. For example, `--dpi-desync-split-pos=method+2,midsld,5` means `method+2` for http, `midsld` for TLS and 5 for others.
`--dpi-desync-fakedsplit-mod=altorder=N` switches `fakedsplit` to alternate segment ordering.
`hostfakesplit` only fakes hostname part of the request making it hard to destinguish between real and fake host names.
It works for tcp protocols with host : TLS and HTTP. Real hostname can be additionally split using `--dpi-desync-hostfakesplit-midhost` marker.
For example, `--dpi-desync-hostfakesplit-midhost=midsld`. Position must be within host range or split won't happen.
Multi-packet queries are supported if hostname part is not already split. If it is fooling is cancelled.
By default fake host names are generated randomly on the fly using `[0-9a-z]` pattern. If host length is >= 7 dot is placed to simulate 3-char TLD and last 3 chars are replaces with a random known 3-char TLD.
It's possible to set fake host template : `--dpi-desync-hostfakesplit-mod=host=<hostname>`.
Template hostname will be expanded to the left to original hostname size with random characters from `[0-9a-z]` pattern : "www.networksolutions.com" -> "h8xmdba4tv7a8.google.com".
If original hostname size is less than template size it will be cut : "habr.com" -> "ogle.com".
If original hostname size is larger than template size by one, dot will be appended to the left : "www.xxx.com" => ".google.com"..
That's why it's a good idea to use short hostnames in template : "ya.ru", "vk.com", "x.com".
`--dpi-desync-hostfakesplit-mod=altorder=1` switches `hostfakesplit` to alternate segment ordering. `altorder=1` sends the whole request with faked host sequentally, then real host segment.
### Sequence numbers overlap ### Sequence numbers overlap
`seqovl` adds to one of the original segment `seqovl` bytes to the beginning and decreases sequence number. For `split` - to the first segment, for `disorder` - to the beginning of the penultimate segment sent (second in the original sequence). `seqovl` adds to one of the original segment `seqovl` bytes to the beginning and decreases sequence number. For `split` - to the first segment, for `disorder` - to the beginning of the penultimate segment sent (second in the original sequence).
@@ -383,6 +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`,
@@ -440,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.
@@ -503,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.
@@ -511,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`.

View File

@@ -1,4 +1,4 @@
# zapret v71.4 # 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)
- [МОДИФИКАЦИЯ ОРИГИНАЛА](#модификация-оригинала) - [МОДИФИКАЦИЯ ОРИГИНАЛА](#модификация-оригинала)
- [ДУБЛИКАТЫ](#дубликаты) - [ДУБЛИКАТЫ](#дубликаты)
@@ -163,108 +164,121 @@ DPI. Все больше становится внереестровых бло
dvtws, собираемый из тех же исходников (см. [документация BSD](./bsd.md)). dvtws, собираемый из тех же исходников (см. [документация BSD](./bsd.md)).
``` ```
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются. @<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
--debug=0|1 ; 1=выводить отладочные сообщения --debug=0|1 ; 1=выводить отладочные сообщения
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка. --dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
--version ; вывести версию и выйти --version ; вывести версию и выйти
--comment ; любой текст (игнорируется) --comment ; любой текст (игнорируется)
--daemon ; демонизировать прогу --daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл --pidfile=<file> ; сохранить PID в файл
--user=<username> ; менять uid процесса --user=<username> ; менять uid процесса
--uid=uid[:gid] ; менять uid процесса --uid=uid[:gid] ; менять uid процесса
--qnum=N ; номер очереди N --qnum=N ; номер очереди N
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов --bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов --bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60 --ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
--ctrack-disable=[0|1] ; 1 или остутствие аргумента отключает conntrack --ctrack-disable=[0|1] ; 1 или остутствие аргумента отключает conntrack
--ipcache-lifetime=<int> ; время жизни записей кэша IP в секундах. 0 - без ограничений. --ipcache-lifetime=<int> ; время жизни записей кэша IP в секундах. 0 - без ограничений.
--ipcache-hostname=[0|1] ; 1 или отсутствие аргумента включают кэширование имен хостов для применения в стратегиях нулевой фазы --ipcache-hostname=[0|1] ; 1 или отсутствие аргумента включают кэширование имен хостов для применения в стратегиях нулевой фазы
--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
--synack-split=[syn|synack|acksyn] ; выполнить tcp split handshake. вместо SYN,ACK отсылать только SYN, SYN+ACK или ACK+SYN --wssize-forced-cutoff=0|1 ; 1(default)=автоматически отключать wssize в случае обнаружения известного протокола
--orig-ttl=<int> ; модифицировать TTL оригинального пакета --synack-split=[syn|synack|acksyn] ; выполнить tcp split handshake. вместо SYN,ACK отсылать только SYN, SYN+ACK или ACK+SYN
--orig-ttl6=<int> ; модифицировать ipv6 hop limit оригинальных пакетов. если не указано, используется значение --orig-ttl --orig-ttl=<int> ; модифицировать TTL оригинального пакета
--orig-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +5:3-64. "0:0-0" или "-" отключает функцию --orig-ttl6=<int> ; модифицировать ipv6 hop limit оригинальных пакетов. если не указано, используется значение --orig-ttl
--orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6 --orig-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +5:3-64. "0:0-0" или "-" отключает функцию
--orig-mod-start=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N --orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
--orig-mod-cutoff=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --orig-tcp-flags-set=<int|0xHEX|flaglist> ; устанавливать указанные tcp флаги (flags |= value). число , либо список через запятую : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--dup=<int> ; высылать N дубликатов до оригинала --orig-tcp-flags-unset=<int|0xHEX|flaglist> ; удалять указанные tcp флаги (flags &= ~value)
--dup-replace=[0|1] ; 1 или отсутствие аргумента блокирует отправку оригинала. отправляются только дубликаты. --orig-mod-start=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
--dup-ttl=<int> ; модифицировать TTL дубликатов --orig-mod-cutoff=[n|d|s]N ; применять orig-mod только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--dup-ttl6=<int> ; модифицировать ipv6 hop limit дубликатов. если не указано, используется значение --dup-ttl --dup=<int> ; высылать N дубликатов до оригинала
--dup-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +1:3-64. "0:0-0" или "-" отключает функцию --dup-replace=[0|1] ; 1 или отсутствие аргумента блокирует отправку оригинала. отправляются только дубликаты.
--dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6 --dup-ttl=<int> ; модифицировать TTL дубликатов
--dup-fooling=<fooling> ; дополнительные методики как сделать, чтобы дубликат не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2 --dup-ttl6=<int> ; модифицировать ipv6 hop limit дубликатов. если не указано, используется значение --dup-ttl
--dup-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000 --dup-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: +1:3-64. "0:0-0" или "-" отключает функцию
--dup-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000 --dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
--dup-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000 --dup-tcp-flags-set=<int|0xHEX|flaglist> ; устанавливать указанные tcp флаги (flags |= value). число , либо список через запятую : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--dup-start=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N --dup-tcp-flags-unset=<int|0xHEX|flaglist> ; удалять указанные tcp флаги (flags &= ~value)
--dup-cutoff=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --dup-fooling=<fooling> ; дополнительные методики как сделать, чтобы дубликат не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". --dup-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета --dup-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
--methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com" --dup-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase --dup-ip-id=same|zero|seq|rnd ; режим назначения ip_id для пакетов dup
--domcase ; домен после Host: сделать таким : TeSt.cOm --dup-start=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper --dup-cutoff=[n|d|s]N ; применять dup только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000 --hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов --hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение --dpi-desync-ttl --methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com"
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. "0:0-0" или "-" отключает функцию --hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6 --domcase ; домен после Host: сделать таким : TeSt.cOm
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2 --ip-id=seq|seqgroup|rnd|zero ; режим назначения ip_id для генерированных пакетов
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты) --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-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI --dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder --dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число. --dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение --dpi-desync-ttl
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; чем заполнять фейковую часть overlap --dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. "0:0-0" или "-" отключает функцию
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; чем заполнять фейки в fakedsplit/fakeddisorder --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; переопределение предыдущего параметра для ipv6
--dpi-desync-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000 --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-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000 --dpi-desync-tcp-flags-unset=<int|0xHEX|flaglist> ; удалять указанные tcp флаги (flags &= ~value)
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000 --dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack ts hopbyhop hopbyhop2
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных --dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org --dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
--dpi-desync-fake-tls=<filename>|0xHEX|! ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному. '!' = стандартный фейк --dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,sni=<sni>,dupsid,padencap --dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт --dpi-desync-split-seqovl-pattern=[+ofs]@<filename>|0xHEX ; чем заполнять фейковую часть overlap
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata --dpi-desync-fakedsplit-pattern=[+ofs]@<filename>|0xHEX ; чем заполнять фейки в fakedsplit/fakeddisorder
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial --dpi-desync-fakedsplit-mod=mod[,mod] ; может быть none, altorder=0|1|2|3 + 0|8|16
--dpi-desync-fake-wireguard=<filename>|0xHEX ; файл, содержащий фейковый wireguard handshake initiation --dpi-desync-hostfakesplit-midhost=marker+N|marker-N ; маркер дополнительного разреза сегмента с оригинальным хостом. должен попадать в пределы хоста.
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт --dpi-desync-hostfakesplit-mod=mod[,mod] ; может быть none, host=<hostname>, altorder=0|1
--dpi-desync-fake-discord=<filename>|0xHEX ; файл, содержащий фейковый пейлоад Discord протокола нахождения IP адреса для голосовых чатов для dpi-desync=fake, на замену стандартным нулям 64 байт --dpi-desync-ts-increment=<int|0xHEX> ; инкремент TSval для ts. по умолчанию -600000
--dpi-desync-fake-stun=<filename>|0xHEX ; файл, содержащий фейковый пейлоад STUN протокола для dpi-desync=fake, на замену стандартным нулям 64 байт --dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт --dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
--dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen --dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули --dpi-desync-fake-tcp-mod=mod[,mod] ; список через запятую режимов runtime модификации tcp фейков (любых) : none, seq
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N --dpi-desync-fake-http=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --dpi-desync-fake-tls=[+ofs]@<filename>|0xHEX|![+offset] ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному. '!' = стандартный фейк
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются, если хост не начинается с '^'. --dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,sni=<sni>,dupsid,padencap
; в файле должен быть хост на каждой строке. --dpi-desync-fake-unknown=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска. --dpi-desync-fake-syndata=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
; при изменении времени модификации файла он перечитывается автоматически по необходимости --dpi-desync-fake-quic=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
; список может быть запакован в gzip. формат автоматически распознается и разжимается --dpi-desync-fake-wireguard=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый wireguard handshake initiation
; списков может быть множество. пустой общий лист = его отсутствие --dpi-desync-fake-dht=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello. --dpi-desync-fake-discord=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад Discord протокола нахождения IP адреса для голосовых чатов для dpi-desync=fake, на замену стандартным нулям 64 байт
--hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов. --dpi-desync-fake-stun=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад STUN протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам. --dpi-desync-fake-unknown-udp=[+ofs]@<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
--hostlist-exclude-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов. --dpi-desync-udplen-increment=<int> ; на сколько увеличивать длину udp пейлоада в режиме udplen
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика) --dpi-desync-udplen-pattern=[+ofs]@<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3) --dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) --dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3) --hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются, если хост не начинается с '^'.
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты. ; в файле должен быть хост на каждой строке.
--new ; начало новой стратегии (новый профиль) ; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
--skip ; не использовать этот профиль . полезно для временной деактивации профиля без удаления параметров. ; при изменении времени модификации файла он перечитывается автоматически по необходимости
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии ; список может быть запакован в gzip. формат автоматически распознается и разжимается
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую. ; списков может быть множество. пустой общий лист = его отсутствие
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую. ; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--filter-l7=<proto> ; фильтр протокола L6-L7. поддерживается несколько значений через запятую. proto : http tls quic wireguard dht discord stun unknown --hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--filter-ssid=ssid1[,ssid2,ssid3,...] ; фильтр по имени wifi сети (только для linux) --hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая. --hostlist-exclude-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--ipset-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей. --hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая. --hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
--ipset-exclude-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей. --hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
--hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3)
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
--new ; начало новой стратегии (новый профиль)
--skip ; не использовать этот профиль . полезно для временной деактивации профиля без удаления параметров.
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую.
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую.
--filter-l7=<proto> ; фильтр протокола L6-L7. поддерживается несколько значений через запятую. proto : http tls quic wireguard dht discord stun unknown
--filter-ssid=ssid1[,ssid2,ssid3,...] ; фильтр по имени wifi сети (только для linux)
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-exclude-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
``` ```
`--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. Может быть важен порядок следования `--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. Может быть важен порядок следования
@@ -276,6 +290,13 @@ dvtws, собираемый из тех же исходников (см. [док
невозможна. Если вы потом удалите файл, и у процесса не будет прав на создание файла в его директории, лог больше не невозможна. Если вы потом удалите файл, и у процесса не будет прав на создание файла в его директории, лог больше не
будет вестись. Вместо удаления лучше использовать truncate. В шелле это можно сделать через команду ": >filename" будет вестись. Вместо удаления лучше использовать truncate. В шелле это можно сделать через команду ": >filename"
Многие параметры, загружающие двоичные данные из файлов, поддерживают загрузку из hex-строки или из файла.
hex строка начинается с "0x". Имя файла можно писать как есть или использовать префикс "@".
Если перед префиксом "@" указано "+<число>", то это означает смещение полезных данных внутри файла.
Файл может загружаться целиком с нулевой позиции, к нему могут применяться модификации, требующие полного файла (TLS),
но передача пойдет с позиции offset. offset должен быть меньше длины файла. Если к блоку данных применяется мод,
который уменьшает размер данных, и offset окажется не меньше новой длины данных, будет ошибка.
### АТАКА ДЕСИНХРОНИЗАЦИИ DPI ### АТАКА ДЕСИНХРОНИЗАЦИИ DPI
Суть ее в следующем. Берется оригинальный запрос, модифицируется, добавляется поддельная информация (фейки) Суть ее в следующем. Берется оригинальный запрос, модифицируется, добавляется поддельная информация (фейки)
@@ -342,6 +363,10 @@ dvtws, собираемый из тех же исходников (см. [док
выяснено, что многие провайдерские 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 выключены по умолчанию.
@@ -371,6 +396,10 @@ dvtws, собираемый из тех же исходников (см. [док
### МОДИФИКАЦИЯ ФЕЙКОВ ### МОДИФИКАЦИЯ ФЕЙКОВ
Любые tcp фейки отправляются с исходным sequence по умолчанию, даже если их несколько.
Если задать `--dpi-desync-fake-tcp-mod=seq`, то несколько фейков будут отправлены с увеличением sequence number таким образом,
как будто они являются tcp сегментами одного фейка.
В nfqws зашит базовый вариант фейка для TLS. Его можно переопределить опцией `--dpi-desync-fake-tls`. В nfqws зашит базовый вариант фейка для TLS. Его можно переопределить опцией `--dpi-desync-fake-tls`.
Переопределение фейков дает возможность использовать любые данные в качестве фейка для TLS. Переопределение фейков дает возможность использовать любые данные в качестве фейка для TLS.
Можно использовать фейковый Client Hello с любым фингерпринтом и с любым SNI. Можно использовать фейковый Client Hello с любым фингерпринтом и с любым SNI.
@@ -403,17 +432,61 @@ dvtws, собираемый из тех же исходников (см. [док
* `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях. * `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях.
* `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке. * `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке.
* `fakedsplit`. нарезаем запрос на 2 части, обрамляя каждую часть фейками : фейк 1-й части, 1 часть, фейк 1-й части, фейк 2-й части, 2 часть, фейк 2-й части * `fakedsplit`. различные варианты замешивания фейков и оригиналов в прямом порядке
* `fakeddisorder`. различные варианты замешивания фейков и оригиналов в обратном порядке
* `hostfakesplit` (altorder=0). фейкование части запроса с хостом : оригинал до хоста, фейк хоста, оригинал хоста (+ опционально нарезка маркером midhost), фейк хоста, оригинал после хоста
* `hostfakesplit` (altorder=1). фейкование части запроса с хостом : оригинал до хоста, фейк хоста, оригинал после хоста, оригинал хоста (+опционально нарезка маркером midhost)
* `fakeddisorder`. аналогично `fakedsplit`, только в обратном порядке : фейк 2-й части, 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1 части. * `fakeddisorder`. аналогично `fakedsplit`, только в обратном порядке : фейк 2-й части, 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1 части.
Для `fakedsplit` и `fakeddisorder` предусмотрены вариации порядка следования сегментов.
Параметр `--dpi-desync-fakedsplit-mod=altorder=N` задает число, влияющее на наличие отдельных фейков :
Режимы altorder для `fakedsplit` для части многопакетного запроса, где есть сплит-позиция :
* `altorder=0`. фейк 1-й части, 1 часть, фейк 1-й части, фейк 2-й части, 2 часть, фейк 2-й части
* `altorder=1`. 1 часть, фейк 1-й части, фейк 2-й части, 2 часть, фейк 2-й части
* `altorder=2`. 1 часть, фейк 2-й части, 2 часть, фейк 2-й части
* `altorder=3`. 1 часть, фейк 2-й части, 2 часть
Режимы altorder для `fakeddisorder` для части многопакетного запроса, где есть сплит-позиция :
* `altorder=0`. фейк 2-й части, 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1-й части
* `altorder=1`. 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1-й части
* `altorder=2`. 2 часть, фейк 1-й части, 1 часть, фейк 1-й части
* `altorder=3`. 2 часть, фейк 1-й части, 1 часть
Режимы altorder для `fakedsplit` и `fakeddisorder` для части многопакетного запроса, где нет сплит-позиции :
* `altorder=0`. фейк, оригинал, фейк
* `altorder=8`. оригинал, фейк
* `altorder=16`. оригинал
Итоговое число `altorder=N` вычисляется как сумма чисел из этих двух групп. По умолчанию `altorder=0`.
Содержимое фейков в `fakedsplit`/`fakeddisorder` определяется параметром `--dpi-desync-fakedsplit-pattern` (по умолчанию 0x00). Содержимое фейков в `fakedsplit`/`fakeddisorder` определяется параметром `--dpi-desync-fakedsplit-pattern` (по умолчанию 0x00).
Данные фейков берутся из паттерна со смещением, соответствующим смещению отсылаемых частей. Данные фейков берутся из паттерна со смещением, соответствующим смещению отсылаемых частей, учитывая смещения пакетов в многопакетных запросах.
Размеры фейков соответствуют длинам отсылаемых частей. Размеры фейков соответствуют длинам отсылаемых частей.
Цель этих режимов - максимально усложнить выявление оригинальных данных среди фейков. Цель этих режимов - максимально усложнить выявление оригинальных данных среди фейков.
Использование `fakedsplit` или `fakeddisorder` на TLS kyber с md5sig fooling может привести к ошибкам "message too long", если позиция сплита мала, Использование `fakedsplit` или `fakeddisorder` на TLS kyber с md5sig fooling может привести к ошибкам "message too long", если позиция сплита мала,
поскольку будет превышение MTU из-за md5 tcp option. поскольку будет превышение MTU из-за md5 tcp option.
Режим 'hostfakesplit' имеет задачу минимального вмешательства фейком - как раз по той части запроса, на основании которой DPI принимает решение о блокировке. Конкретно - имени хоста.
По умолчанию фейк хоста генерируется каждый раз случайно из набора `[a-z0-9]`. При длине более 7 символов за 3 символа до конца ставится точка, имитируя TLD, а последние 3 символа заполняются одним из нескольких известных TLD.
Можно переопределить шаблон генерации с помощью `--dpi-desync-hostfakesplit-mod=host=<hostname>`. В последнем случае справа всегда будет указанный hostname.
Слева он будет дополнен до размера оригинального хоста как поддомен со случайными символами. Пример : "www.networksolutions.com" -> "h8xmdba4tv7a8.google.com".
Если размер оригинального хоста меньше шаблона, шаблон будет порезан : "habr.com" -> "ogle.com".
Если размер оригинального хоста больше шаблона на 1, получится инвалидный пустой поддомен : "www.xxx.com" => ".google.com".
Поэтому стоит использовать максимально короткие хосты из разрешенных : "ya.ru", "vk.com".
`--dpi-desync-hostfakesplit-mod=altorder=1` позволяет сменить порядок следования частей на альтернативный вариант.
`altorder=1` шлет фрагменты в таком порядке, чтобы при последовательной сборке сегментов на DPI он получил полностью собранный оригинал запроса с подмененным хостом.
Реальный хост идет отдельным сегментом уже после. То есть в этом варианте применяется разновидность disorder. Сервер принимает фрагменты с нарушенным порядком sequence.
Опционально можно разрезать оригинальный хост. Например, `--dpi-desync-hostfakesplit-midhost=midsld`. Позиция нарезки должна попадать внутрь хоста.
Многопакетные запросы поддерживаются только, если исходная нарезка пакетов не включает позиции имени хоста. В последнем случае дурение отменяется.
Вариант `fakedsplit` имеет несколько альтернативных порядков нарезки - от 0 до 3. Режим задается в параметре `--dpi-desync-fakedsplit-mod=altorder=N`.
Каждый следующий altorder убирает часть фейков.
Для определения позиций нарезки используются маркеры. Для определения позиций нарезки используются маркеры.
* **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала. * **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала.
@@ -478,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 и заключается
@@ -567,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.
@@ -620,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,
@@ -783,7 +878,7 @@ L7 протокол становится известен обычно посл
> [!IMPORTANT] > [!IMPORTANT]
> user-mode реализация ipset создавалась не как удобная замена *nix версии, реализованной в ядре. > user-mode реализация ipset создавалась не как удобная замена *nix версии, реализованной в ядре.
> Вариант в ядре работает гораздо эффективнее. Это создавалось для систем без подд3ержки ipset в ядре. > Вариант в ядре работает гораздо эффективнее. Это создавалось для систем без поддержки ipset в ядре.
> Конкретно - Windows и ядра Linux, собранные без nftables и ipset модулей ядра. Например, в android нет ipset. > Конкретно - Windows и ядра Linux, собранные без nftables и ipset модулей ядра. Например, в android нет ipset.
### ФИЛЬТРАЦИЯ ПО WIFI ### ФИЛЬТРАЦИЯ ПО WIFI
@@ -1570,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`
@@ -1721,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
@@ -1744,6 +1840,10 @@ SECURE_DNS=0|1 - принудительно выключить или включ
DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера
DOH_SERVER - конкретный DoH URL, отказ от поиска DOH_SERVER - конкретный DoH URL, отказ от поиска
UNBLOCKED_DOM - незаблокированный домен, который используется для тестов IP block UNBLOCKED_DOM - незаблокированный домен, который используется для тестов IP block
MIN_TTL,MAX_TTL - пределы тестов с TTL. MAX_TTL=0 отключает тесты.
MIN_AUTOTTL_DELTA,MAX_AUTOTTL_DELTA - пределы тестов с autottl по дельте. MAX_AUTOTTL_DELTA=0 отключает тесты.
SIMULATE=1 - включить режим симуляции для отладки логики скрипта. отключаются реальные запросы через curl, заменяются рандомным результатом.
SIM_SUCCESS_RATE=<percent> - вероятность успеха симуляции в процентах
``` ```
Пример запуска с переменными:\ Пример запуска с переменными:\

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.
@@ -47,7 +47,9 @@ Task of `iptables` is done inside `winws` through `windivert` filters. `Windiver
--wf-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed. --wf-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
--wf-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation. multiple comma separated values allowed. --wf-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation. multiple comma separated values allowed.
--wf-udp=[~]port1[-port2] ; UDP port filter. ~ means negation. multiple comma separated values allowed. --wf-udp=[~]port1[-port2] ; UDP port filter. ~ means negation. multiple comma separated values allowed.
--wf-raw=<filter>|@<filename> ; raw windivert filter string or filename --wf-raw-part=<filter>|@<filename> ; partial raw windivert filter string or filename
--wf-filter-lan=0|1 ; add excluding filter for non-global IP (default : 1)
--wf-raw=<filter>|@<filename> ; full raw windivert filter string or filename. replaces --wf-tcp,--wf-udp,--wf-raw-part
--wf-save=<filename> ; save windivert filter string to a file and exit --wf-save=<filename> ; save windivert filter string to a file and exit
--ssid-filter=ssid1[,ssid2,ssid3,...] ; enable winws only if any of specified wifi SSIDs connected --ssid-filter=ssid1[,ssid2,ssid3,...] ; enable winws only if any of specified wifi SSIDs connected
--nlm-filter=net1[,net2,net3,...] ; enable winws only if any of specified NLM network is connected. names and GUIDs are accepted. --nlm-filter=net1[,net2,net3,...] ; enable winws only if any of specified NLM network is connected. names and GUIDs are accepted.
@@ -60,6 +62,12 @@ Interface indexes can be discovered using this command : `netsh int ip show int`
If you can't find index this way use `winws --debug` to see index there. Subinterface index is almost always 0 and you can omit it. If you can't find index this way use `winws --debug` to see index there. Subinterface index is almost always 0 and you can omit it.
`--wf-raw-part` specifies partial windivert filter. Multiple filter parts are supported. They can also be combined with `--wf-tcp`,`--wf-udp`.
`--wf-raw` specifies full windivert filter that replaces `--wf-tcp`,`--wf-udp`,`--wf-raw-part`.
Kernel filtering with windivert language is much more effective than passing massive amount of traffic to winws. Use it if possible to save CPU resources.
Multiple `winws` processes are allowed. However, it's discouraged to intersect their filters. Multiple `winws` processes are allowed. However, it's discouraged to intersect their filters.
`--ssid-filter` allows to enable `winws` only if specified wifi networks are connected. `winws` auto detects SSID appearance and disappearance. `--ssid-filter` allows to enable `winws` only if specified wifi networks are connected. `winws` auto detects SSID appearance and disappearance.
@@ -165,3 +173,9 @@ clone the code in all cmd files to support multiple tasks `winws1,winws2,winws3,
Tasks can also be controlled from GUI `taskschd.msc`. Tasks can also be controlled from GUI `taskschd.msc`.
Also you can use windows services the same way with `service_*.cmd`. Also you can use windows services the same way with `service_*.cmd`.
### Windows Server
winws is linked against wlanapi.dll which is absent by default.
To solve this problem run power shell as administrator and execute command `Install-WindowsFeature -Name Wireless-Networking`.
Then reboot the system.

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.
@@ -44,7 +48,7 @@ tpws в режиме socks можно запускать под более-ме
Это вариант пакетного фильтра nfqws для Windows, построенный на базе windivert. Это вариант пакетного фильтра nfqws для Windows, построенный на базе windivert.
Все функции работоспособны, однако функционал ipset в ядре отсутствует. Он реализован в user mode. Фильтры по большому количеству IP адресов невозможны. Все функции работоспособны, однако функционал ipset в ядре отсутствует. Он реализован в user mode. Фильтры по большому количеству IP адресов невозможны.
Работа с проходящим трафиком, например в случае "расшаривания" соединения, не проверялась и не гарантируется. Работа с проходящим трафиком, например в случае "расшаривания" соединения, невозможна.
Для работы с windivert требуются права администратора. Для работы с windivert требуются права администратора.
Специфические для unix параметры, такие как `--uid`, `--user` и тд, исключены. Все остальные параметры аналогичны nfqws и dvtws. Специфические для unix параметры, такие как `--uid`, `--user` и тд, исключены. Все остальные параметры аналогичны nfqws и dvtws.
@@ -63,15 +67,17 @@ secure boot могут быть проблемы из-за подписи дра
Чтобы не писать сложные фильтры вручную, предусмотрены различные упрощенные варианты автоматического построения фильтров. Чтобы не писать сложные фильтры вручную, предусмотрены различные упрощенные варианты автоматического построения фильтров.
``` ```
--wf-iface=<int>[.<int>] ; числовые индексы интерфейса и суб-интерфейса --wf-iface=<int>[.<int>] ; числовые индексы интерфейса и суб-интерфейса
--wf-l3=ipv4|ipv6 ; фильтр L3 протоколов. по умолчанию включены ipv4 и ipv6. --wf-l3=ipv4|ipv6 ; фильтр L3 протоколов. по умолчанию включены ipv4 и ipv6.
--wf-tcp=[~]port1[-port2] ; фильтр портов для tcp. ~ означает отрицание --wf-tcp=[~]port1[-port2] ; фильтр портов для tcp. ~ означает отрицание
--wf-udp=[~]port1[-port2] ; фильтр портов для udp. ~ означает отрицание --wf-udp=[~]port1[-port2] ; фильтр портов для udp. ~ означает отрицание
--wf-raw=<filter>|@<filename> ; задать напрямую фильтр windivert из параметра или из файла. имени файла предшествует символ @. --wf-raw-part=<filter>|@<filename> ; частичный windivert фильтр из параметра или из файла. имени файла предшествует символ @. может быть множество частей. сочетается с --wf-tcp,--wf-udp.
--wf-save=<filename> ; сохранить сконструированный фильтр windivert в файл для последующей правки вручную --wf-filter-lan=0|1 ; отфильтровывать адреса назначения, не являющиеся глобальными inet адресами ipv4 или ipv6. по умолчанию - 1.
--wf-raw=<filter>|@<filename> ; полный windivert фильтр из параметра или из файла. имени файла предшествует символ @. замещает --wf-raw-part,--wf-tcp,--wf-udp.
--wf-save=<filename> ; сохранить сконструированный фильтр windivert в файл для последующей правки вручную
--ssid-filter=ssid1[,ssid2,ssid3,...] ; включать winws только когда подключена любая из указанных wifi сетей --ssid-filter=ssid1[,ssid2,ssid3,...] ; включать winws только когда подключена любая из указанных wifi сетей
--nlm-filter=net1[,net2,net3,...] ; включать winws только когда подключена любая из указанных сетей NLM --nlm-filter=net1[,net2,net3,...] ; включать winws только когда подключена любая из указанных сетей NLM
--nlm-list[=all] ; вывести список сетей NLM. по умолчанию только подключенных, all - всех. --nlm-list[=all] ; вывести список сетей NLM. по умолчанию только подключенных, all - всех.
``` ```
Параметры `--wf-l3`, `--wf-tcp`, `--wf-udp` могут брать несколько значений через запятую. Параметры `--wf-l3`, `--wf-tcp`, `--wf-udp` могут брать несколько значений через запятую.
@@ -80,11 +86,19 @@ secure boot могут быть проблемы из-за подписи дра
Некоторых типы соединений там не увидеть. В этом случае запускайте **winws** с параметром `--debug` и смотрите IfIdx там. Некоторых типы соединений там не увидеть. В этом случае запускайте **winws** с параметром `--debug` и смотрите IfIdx там.
SubInterface используется windivert, но практически всегда **0**, его можно не указывать. Вероятно, он нужен в редких случаях. SubInterface используется windivert, но практически всегда **0**, его можно не указывать. Вероятно, он нужен в редких случаях.
Конструктор фильтров автоматически включает входящие tcp пакеты с tcp synack и tcp rst для корректной работы функций Конструктор стандартных фильтров автоматически включает входящие tcp пакеты с tcp synack и tcp rst для корректной работы функций
autottl и autohostlist. При включении autohostlist так же перенаправляются пакеты данных с http redirect с кодами 302 и 307. autottl и autohostlist. При включении autohostlist так же перенаправляются пакеты данных с http redirect с кодами 302 и 307.
Всегда добавляется фильтр на исключение не-интернет адресов ipv4 и ipv6. Если не указаное иное, добавляется фильтр на исключение не-интернет адресов ipv4 и ipv6.
Для сложных нестандартных сценариев могут потребоваться свои фильтры. Логично будет начать со стандартного шаблона, Для сложных нестандартных сценариев могут потребоваться свои фильтры. Полный фильтр --wf-raw замещает все остальное.
сохраненного через `--wf-save`. Нужно править файл и подсовывать его в параметре `--wf-raw`. Максимальный размер фильтра - **16 Kb**. Частичные фильтры `--wf-raw-part` совместимы друг с другом и `--wf-tcp` и `--wf-udp`. Они позволяют исключить написание
громоздких полных фильтров, сосредоточившись лишь на добавлении какого-то особенного пейлоада.
`--wf-save` позволяет записать итоговый windivert фильтр в файл. Максимальный размер фильтра - **16 Kb**.
Фильтрация windivert производится в ядре. Это несравнимо легче по ресурсам, чем перенаправлять пакеты в пространство user mode,
чтобы winws принимал решение. Поэтому пользуйтесь по максимуму возможностями windivert.
Например, если вам нужно дурить wireguard на все порты, вам придется перенаправить все порты на winws. Или же написать windivert фильтр, который отсечет wireguard по содержимому пакета.
Разница в нагрузке на процессор колоссальна. В первом случае - до 100% одного ядра cpu в зависимости от обьема исходящего udp трафика (привет, торрент и uTP), во втором - близко к 0.
Кроме нагрузки на процессор еще можете порезать себе скорость, тк одно ядро не будет справляться с обработкой вашего гигабитного интернета. А на старых ноутах еще и получите самолетный вой системы охлаждения, приводящий к ее износу.
Можно запускать несколько процессов **winws** с разными стратегиями. Однако, не следует делать пересекающиеся фильтры. Можно запускать несколько процессов **winws** с разными стратегиями. Однако, не следует делать пересекающиеся фильтры.
@@ -257,3 +271,9 @@ _zapret-winws_ - это отдельный комплект для повсед
Все батники требуется запускать от имени администратора. Все батники требуется запускать от имени администратора.
Управлять задачами можно так же из графической программы управления планировщиком `taskschd.msc` Управлять задачами можно так же из графической программы управления планировщиком `taskschd.msc`
## Особенности Windows Server
winws слинкован с wlanapi.dll, который по умолчанию не установлен в windows server.
Для решения этой проблемы запустите power shell под администратором и выполните команду `Install-WindowsFeature -Name Wireless-Networking`.
После чего перезагрузите систему.

View File

@@ -1,4 +1,5 @@
# this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering # this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config : # can override in config :
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---dpi-desync=tamper}" NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---dpi-desync=tamper}"
@@ -10,20 +11,20 @@ zapret_custom_daemons()
{ {
# $1 - 1 - add, 0 - stop # $1 - 1 - add, 0 - stop
local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_DESYNC_DHT" local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_DESYNC_DHT"
do_nfqws $1 $DNUM_DHT4ALL "$opt" do_nfqws $1 $DNUM_DHT4ALL "$opt"
} }
zapret_custom_firewall() zapret_custom_firewall()
{ {
# $1 - 1 - run, 0 - stop # $1 - 1 - run, 0 - stop
local f uf4 uf6 local f uf4 uf6
local first_packet_only="$ipt_connbytes 1:1" local first_packet_only="$ipt_connbytes 1:1"
f='-p udp -m length --length 109:407 -m u32 --u32' f='-p udp -m length --length 109:407 -m u32 --u32'
uf4='0>>22&0x3C@8>>16=0x6431' uf4='0>>22&0x3C@8>>16=0x6431'
uf6='48>>16=0x6431' uf6='48>>16=0x6431'
fw_nfqws_post $1 "$f $uf4 $first_packet_only" "$f $uf6 $first_packet_only" $QNUM_DHT4ALL fw_nfqws_post $1 "$f $uf4 $first_packet_only" "$f $uf6 $first_packet_only" $QNUM_DHT4ALL
} }
zapret_custom_firewall_nft() zapret_custom_firewall_nft()
{ {
@@ -32,6 +33,6 @@ zapret_custom_firewall_nft()
local f local f
local first_packet_only="$nft_connbytes 1" local first_packet_only="$nft_connbytes 1"
f="meta length 109-407 meta l4proto udp @th,64,16 0x6431" f="meta length 109-407 meta l4proto udp @ih,0,16 0x6431"
nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL
} }

View File

@@ -1,7 +1,8 @@
# this custom script runs desync to all discord media packets # this custom script runs desync to all discord media packets
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config : # can override in config :
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---dpi-desync=fake}" NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---dpi-desync=fake --dpi-desync-repeats=2}"
DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}" DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}"
alloc_dnum DNUM_DISCORD_MEDIA alloc_dnum DNUM_DISCORD_MEDIA
@@ -14,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

View File

@@ -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
}

View File

@@ -1,7 +1,8 @@
# this custom script runs desync to all stun packets # this custom script runs desync to all stun packets
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config : # can override in config :
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---dpi-desync=fake}" NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---dpi-desync=fake --dpi-desync-repeats=2}"
alloc_dnum DNUM_STUN4ALL alloc_dnum DNUM_STUN4ALL
alloc_qnum QNUM_STUN4ALL alloc_qnum QNUM_STUN4ALL
@@ -13,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

View File

@@ -1,8 +1,9 @@
# this custom script runs desync to all wireguard handshake initiation packets # this custom script runs desync to all wireguard handshake initiation packets
# NOTE : this works for original wireguard and may not work for 3rd party implementations such as xray # NOTE: this works for original wireguard and may not work for 3rd party implementations such as xray
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config : # can override in config :
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---dpi-desync=fake}" NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---dpi-desync=fake --dpi-desync-repeats=2}"
alloc_dnum DNUM_WG4ALL alloc_dnum DNUM_WG4ALL
alloc_qnum QNUM_WG4ALL alloc_qnum QNUM_WG4ALL

View File

@@ -1,14 +1,14 @@
Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws. Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws.
Задействуются через `winws --wf-raw=@filename`. Задействуются через `winws --wf-raw-part=@filename`. Может быть несколько частичных фильтров. Они могут сочетаться с --wf-tcp и --wf-udp.
Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики. Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики.
Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку. Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку.
Дофильтрация производится силами winws. Дофильтрация производится силами winws.
Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language
Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw=@windivert.discord_media+stun.txt --filter-l7=stun,discord --dpi-desync=fake` Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw-part=@windivert_part.discord_media.txt --wf-raw-part=@windivert_part.stun.txt --filter-l7=stun,discord --dpi-desync=fake`
These filters are invoked using `winws --wf-raw=@filename`. These filters are invoked using `winws --wf-raw-part=@filename`. Multiple filter parts are supported. They can be combined with --wf-tcp and --wf-udp.
Filters are kernel mode and save great amount of CPU. Filters are kernel mode and save great amount of CPU.
However windivert cannot filter by bit fields, lacks shift and bitwise logic operations. However windivert cannot filter by bit fields, lacks shift and bitwise logic operations.
Filters are relaxed and can pass wrong payloads. Finer filtering is done by winws. Filters are relaxed and can pass wrong payloads. Finer filtering is done by winws.

View File

@@ -1,29 +0,0 @@
!impostor and !loopback and
(outbound and
((ip and
udp.DstPort>=50000 and udp.DstPort<=50099 and
udp.PayloadLength=74 and
udp.Payload32[0]=0x00010046 and
udp.Payload32[2]=0 and
udp.Payload32[3]=0 and
udp.Payload32[4]=0 and
udp.Payload32[5]=0 and
udp.Payload32[6]=0 and
udp.Payload32[7]=0 and
udp.Payload32[8]=0 and
udp.Payload32[9]=0 and
udp.Payload32[10]=0 and
udp.Payload32[11]=0 and
udp.Payload32[12]=0 and
udp.Payload32[13]=0 and
udp.Payload32[14]=0 and
udp.Payload32[15]=0 and
udp.Payload32[16]=0 and
udp.Payload32[17]=0)
or
(udp.PayloadLength>=20 and
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40)) and
( ((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or
((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))
)
)

View File

@@ -1,8 +0,0 @@
!impostor and !loopback and
(outbound and
udp.PayloadLength>=20 and
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40 and
( ((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or
((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))
)
)

View File

@@ -1,8 +0,0 @@
!impostor and !loopback and
(outbound and
udp.PayloadLength=148 and
udp.Payload[0]=0x01 and
( ((ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)) or
((ipv6.DstAddr > ::1) and (ipv6.DstAddr < 2001::0 or ipv6.DstAddr >= 2001:1::0) and (ipv6.DstAddr < fc00::0 or ipv6.DstAddr >= fe00::0) and (ipv6.DstAddr < fe80::0 or ipv6.DstAddr >= fec0::0) and (ipv6.DstAddr < ff00::0 or ipv6.DstAddr >= ffff::0))
)
)

View File

@@ -1,5 +1,4 @@
!impostor and !loopback and outbound and ip and
(outbound and
udp.DstPort>=50000 and udp.DstPort<=50099 and udp.DstPort>=50000 and udp.DstPort<=50099 and
udp.PayloadLength=74 and udp.PayloadLength=74 and
udp.Payload32[0]=0x00010046 and udp.Payload32[0]=0x00010046 and
@@ -18,6 +17,4 @@
udp.Payload32[14]=0 and udp.Payload32[14]=0 and
udp.Payload32[15]=0 and udp.Payload32[15]=0 and
udp.Payload32[16]=0 and udp.Payload32[16]=0 and
udp.Payload32[17]=0 and udp.Payload32[17]=0
(ip.DstAddr < 127.0.0.1 or ip.DstAddr > 127.255.255.255) and (ip.DstAddr < 10.0.0.0 or ip.DstAddr > 10.255.255.255) and (ip.DstAddr < 192.168.0.0 or ip.DstAddr > 192.168.255.255) and (ip.DstAddr < 172.16.0.0 or ip.DstAddr > 172.31.255.255) and (ip.DstAddr < 169.254.0.0 or ip.DstAddr > 169.254.255.255)
)

View File

@@ -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

View File

@@ -0,0 +1,3 @@
outbound and
udp.PayloadLength>=20 and
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40

View File

@@ -0,0 +1,3 @@
outbound and
udp.PayloadLength=148 and
udp.Payload[0]=0x01

View File

@@ -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

View File

@@ -83,13 +83,15 @@ typedef struct
bool b_cutoff; // mark for deletion bool b_cutoff; // mark for deletion
bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff; bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff;
uint16_t ip_id;
t_l7proto l7proto; t_l7proto l7proto;
bool l7proto_discovered; bool l7proto_discovered;
char *hostname; char *hostname;
bool hostname_is_ip; bool hostname_is_ip;
bool hostname_discovered; bool hostname_discovered;
bool hostname_ah_check; // should perform autohostlist checks bool hostname_ah_check; // should perform autohostlist checks
t_reassemble reasm_orig; t_reassemble reasm_orig;
struct rawpacket_tailhead delayed; struct rawpacket_tailhead delayed;
} t_ctrack; } t_ctrack;

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;
} }

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--)
{ {

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

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,
@@ -420,7 +421,7 @@ bool prepare_udp_segment4(
memcpy(payload,data,len); memcpy(payload,data,len);
if (padding) if (padding)
fill_pattern(payload+len,padlen,padding,padding_size); fill_pattern(payload+len,padlen,padding,padding_size,0);
else else
memset(payload+len,0,padlen); memset(payload+len,0,padlen);
udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst); udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
@@ -509,7 +510,7 @@ bool prepare_udp_segment6(
memcpy(payload,data,len); memcpy(payload,data,len);
if (padding) if (padding)
fill_pattern(payload+len,padlen,padding,padding_size); fill_pattern(payload+len,padlen,padding,padding_size,0);
else else
memset(payload+len,0,padlen); memset(payload+len,0,padlen);
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
@@ -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:

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);

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,7 @@ enum dpi_desync_mode {
DESYNC_FAKEDDISORDER, DESYNC_FAKEDDISORDER,
DESYNC_MULTISPLIT, DESYNC_MULTISPLIT,
DESYNC_MULTIDISORDER, DESYNC_MULTIDISORDER,
DESYNC_HOSTFAKESPLIT,
DESYNC_IPFRAG2, DESYNC_IPFRAG2,
DESYNC_HOPBYHOP, DESYNC_HOPBYHOP,
DESYNC_DESTOPT, DESYNC_DESTOPT,

View File

@@ -338,10 +338,18 @@ bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size)
return true; return true;
} }
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize) void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset)
{ {
size_t size; size_t size;
if (offset%=patsize)
{
size = patsize-offset;
size = bufsize>size ? size : bufsize;
memcpy(buf,pattern+offset,size);
buf += size;
bufsize -= size;
}
while (bufsize) while (bufsize)
{ {
size = bufsize>patsize ? patsize : bufsize; size = bufsize>patsize ? patsize : bufsize;

View File

@@ -70,7 +70,7 @@ static inline uint32_t pntoh32(const uint8_t *p) {
} }
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size); bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size);
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize); void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset);
int fprint_localtime(FILE *F); int fprint_localtime(FILE *F);

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,7 @@ const char *progname = "nfqws";
#error UNKNOWN_SYSTEM_TIME #error UNKNOWN_SYSTEM_TIME
#endif #endif
const char * tld[6] = { "com","org","net","edu","gov","biz" };
int DLOG_FILE(FILE *F, const char *format, va_list args) int DLOG_FILE(FILE *F, const char *format, va_list args)
{ {
@@ -218,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;
@@ -236,16 +240,17 @@ 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)
{ {
struct blob_item *item; struct blob_item *item;
if (blob_collection_empty(&dp->fake_http)) if (blob_collection_empty(&dp->fake_http))
if (!blob_collection_add_blob(&dp->fake_http,fake_http_request_default,strlen(fake_http_request_default),0)) if (!blob_collection_add_blob(&dp->fake_http,fake_http_request_default,strlen(fake_http_request_default),0,0))
return false; return false;
if (blob_collection_empty(&dp->fake_tls)) if (blob_collection_empty(&dp->fake_tls))
{ {
if (!(item=blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(((struct fake_tls_mod*)0)->sni)))) if (!(item=blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(((struct fake_tls_mod*)0)->sni),0)))
return false; return false;
if (!(item->extra2 = malloc(sizeof(struct fake_tls_mod)))) if (!(item->extra2 = malloc(sizeof(struct fake_tls_mod))))
return false; return false;
@@ -253,13 +258,13 @@ bool dp_fake_defaults(struct desync_profile *dp)
} }
if (blob_collection_empty(&dp->fake_unknown)) if (blob_collection_empty(&dp->fake_unknown))
{ {
if (!(item=blob_collection_add_blob(&dp->fake_unknown,NULL,256,0))) if (!(item=blob_collection_add_blob(&dp->fake_unknown,NULL,256,0,0)))
return false; return false;
memset(item->data,0,item->size); memset(item->data,0,item->size);
} }
if (blob_collection_empty(&dp->fake_quic)) if (blob_collection_empty(&dp->fake_quic))
{ {
if (!(item=blob_collection_add_blob(&dp->fake_quic,NULL,620,0))) if (!(item=blob_collection_add_blob(&dp->fake_quic,NULL,620,0,0)))
return false; return false;
memset(item->data,0,item->size); memset(item->data,0,item->size);
item->data[0] = 0x40; item->data[0] = 0x40;
@@ -269,7 +274,7 @@ bool dp_fake_defaults(struct desync_profile *dp)
{ {
if (blob_collection_empty(*fake)) if (blob_collection_empty(*fake))
{ {
if (!(item=blob_collection_add_blob(*fake,NULL,64,0))) if (!(item=blob_collection_add_blob(*fake,NULL,64,0,0)))
return false; return false;
memset(item->data,0,item->size); memset(item->data,0,item->size);
} }
@@ -297,6 +302,8 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
} }
static void dp_clear_dynamic(struct desync_profile *dp) static void dp_clear_dynamic(struct desync_profile *dp)
{ {
free(dp->fsplit_pattern);
hostlist_collection_destroy(&dp->hl_collection); hostlist_collection_destroy(&dp->hl_collection);
hostlist_collection_destroy(&dp->hl_collection_exclude); hostlist_collection_destroy(&dp->hl_collection_exclude);
ipset_collection_destroy(&dp->ips_collection); ipset_collection_destroy(&dp->ips_collection);
@@ -371,6 +378,7 @@ void cleanup_params(struct params_s *params)
#ifdef __CYGWIN__ #ifdef __CYGWIN__
strlist_destroy(&params->ssid_filter); strlist_destroy(&params->ssid_filter);
strlist_destroy(&params->nlm_filter); strlist_destroy(&params->nlm_filter);
strlist_destroy(&params->wf_raw_part);
#else #else
free(params->user); params->user=NULL; free(params->user); params->user=NULL;
#endif #endif

View File

@@ -68,6 +68,8 @@
#define MAX_GIDS 64 #define MAX_GIDS 64
extern const char * tld[6];
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG, LOG_TARGET_ANDROID }; enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG, LOG_TARGET_ANDROID };
struct fake_tls_mod_cache struct fake_tls_mod_cache
@@ -76,11 +78,26 @@ struct fake_tls_mod_cache
}; };
struct fake_tls_mod struct fake_tls_mod
{ {
char sni[64]; char sni[128];
uint32_t mod; uint32_t mod;
}; };
struct hostfakesplit_mod
{
char host[128];
size_t host_size;
int ordering;
};
struct fakedsplit_mod
{
int ordering;
};
struct tcp_mod
{
bool seq;
};
typedef enum {SS_NONE=0,SS_SYN,SS_SYNACK,SS_ACKSYN} t_synack_split; typedef enum {SS_NONE=0,SS_SYN,SS_SYNACK,SS_ACKSYN} t_synack_split;
typedef enum {IPID_SEQ=0,IPID_SEQ_GROUP,IPID_RND,IPID_ZERO,IPID_SAME} t_ip_id_mode;
struct desync_profile struct desync_profile
{ {
@@ -89,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;
@@ -102,7 +122,7 @@ struct desync_profile
// multisplit // multisplit
struct proto_pos splits[MAX_SPLITS]; struct proto_pos splits[MAX_SPLITS];
int split_count; int split_count;
struct proto_pos seqovl; struct proto_pos seqovl,hostfakesplit_midhost;
char dup_start_mode, dup_cutoff_mode; // n - packets, d - data packets, s - relative sequence char dup_start_mode, dup_cutoff_mode; // n - packets, d - data packets, s - relative sequence
bool dup_replace; bool dup_replace;
@@ -112,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;
@@ -124,14 +147,20 @@ 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],fsplit_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP]; uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP];
size_t fake_syndata_size; uint8_t *fsplit_pattern;
size_t fake_syndata_size, fsplit_pattern_size;
struct fake_tls_mod tls_mod_last; struct fake_tls_mod tls_mod_last;
struct blob_item *tls_fake_last; struct blob_item *tls_fake_last;
struct hostfakesplit_mod hfs_mod;
struct fakedsplit_mod fs_mod;
struct tcp_mod tcp_mod;
int udplen_increment; int udplen_increment;
bool filter_ipv4,filter_ipv6; bool filter_ipv4,filter_ipv6;
@@ -160,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;
@@ -200,6 +229,7 @@ struct params_s
#ifdef __CYGWIN__ #ifdef __CYGWIN__
struct str_list_head ssid_filter,nlm_filter; struct str_list_head ssid_filter,nlm_filter;
struct str_list_head wf_raw_part;
#else #else
bool droproot; bool droproot;
char *user; char *user;

View File

@@ -579,8 +579,9 @@ struct blob_item *blob_collection_add(struct blob_collection_head *head)
} }
return entry; return entry;
} }
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve) struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve, size_t offset)
{ {
if (offset>=size) return NULL;
struct blob_item *entry = calloc(1,sizeof(struct blob_item)); struct blob_item *entry = calloc(1,sizeof(struct blob_item));
if (!entry) return NULL; if (!entry) return NULL;
if (!(entry->data = malloc(size+size_reserve))) if (!(entry->data = malloc(size+size_reserve)))
@@ -591,6 +592,7 @@ struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, co
if (data) memcpy(entry->data,data,size); if (data) memcpy(entry->data,data,size);
entry->size = size; entry->size = size;
entry->size_buf = size+size_reserve; entry->size_buf = size+size_reserve;
entry->offset = offset;
// insert to the end // insert to the end
struct blob_item *itemc,*iteml=LIST_FIRST(head); struct blob_item *itemc,*iteml=LIST_FIRST(head);

View File

@@ -157,13 +157,14 @@ struct blob_item {
uint8_t *data; // main data blob uint8_t *data; // main data blob
size_t size; // main data blob size size_t size; // main data blob size
size_t size_buf;// main data blob allocated size size_t size_buf;// main data blob allocated size
size_t offset; // optional offset to useful data
void *extra; // any data without size void *extra; // any data without size
void *extra2; // any data without size void *extra2; // any data without size
LIST_ENTRY(blob_item) next; LIST_ENTRY(blob_item) next;
}; };
LIST_HEAD(blob_collection_head, blob_item); LIST_HEAD(blob_collection_head, blob_item);
struct blob_item *blob_collection_add(struct blob_collection_head *head); struct blob_item *blob_collection_add(struct blob_collection_head *head);
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve); struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve, size_t offset);
void blob_collection_destroy(struct blob_collection_head *head); void blob_collection_destroy(struct blob_collection_head *head);
bool blob_collection_empty(const struct blob_collection_head *head); bool blob_collection_empty(const struct blob_collection_head *head);

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)