mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
Compare commits
47 Commits
v69.1
...
06e364a2ef
Author | SHA1 | Date | |
---|---|---|---|
|
06e364a2ef | ||
|
8324c04a41 | ||
|
166847ba92 | ||
|
1904f01cf4 | ||
|
4ae1ad053d | ||
|
7d9946b007 | ||
|
86462f4cee | ||
|
669182c133 | ||
|
f81bb51f4a | ||
|
d4ff423add | ||
|
b14ff9b647 | ||
|
277c5f9e00 | ||
|
f016e5a4dc | ||
|
fc3912b4fe | ||
|
c01a764e1f | ||
|
92ba6b439e | ||
|
4ecb40e03b | ||
|
be9c300cb3 | ||
|
839c720f60 | ||
|
127bec2f14 | ||
|
15879c82f6 | ||
|
9d188840c1 | ||
|
35a28f4efe | ||
|
78ea379e0f | ||
|
007cbe600b | ||
|
d1a8e276b5 | ||
|
eb2f5b5f45 | ||
|
a623cef95d | ||
|
f00b45a28e | ||
|
422faaa29c | ||
|
16a9e3f9c9 | ||
|
7c5869bc29 | ||
|
feb3dd4d73 | ||
|
b4204ca2ba | ||
|
89a67e6952 | ||
|
34199b151c | ||
|
c6962f575e | ||
|
9c8662b25e | ||
|
fedb62df66 | ||
|
44c19c1743 | ||
|
56aa481226 | ||
|
9184317549 | ||
|
a3048ae120 | ||
|
fc44d74f2b | ||
|
1779cfad30 | ||
|
4856be4ef1 | ||
|
033043bdc0 |
10
.github/issue_template.md
vendored
Normal file
10
.github/issue_template.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
1. Здесь не место для вопросов, касающихся компьютерной грамотности и навыков использования ОС
|
||||
2. Здесь не место для вопросов "у меня не работает" без технических подробностей
|
||||
3. Здесь не место для вопросов "как мне открыть ютуб" или "что писать в ..."
|
||||
4. Здесь не место для обсуждения сборок
|
||||
5. Вирусов здесь нет. У вас либо чья-то сборка, либо ваш антивирус давно пора отправить на покой. Не согласны - удаляйте софт.
|
||||
|
||||
Все означенное обсуждать в дискуссиях или на форумах.
|
||||
При нарушении будет закрываться или конвертироваться в дискуссии.
|
||||
Issue только для обсуждения проблем самого софта. Неработа стратегии или ваше неумение настроить - это ваша проблема, а не проблема софта.
|
||||
|
36
.github/workflows/build.yml
vendored
36
.github/workflows/build.yml
vendored
@@ -82,10 +82,6 @@ jobs:
|
||||
export STRIP=$TARGET-strip
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
|
||||
# optimize for size
|
||||
export CFLAGS="-Os -flto=auto"
|
||||
export LDFLAGS="-Os"
|
||||
|
||||
# netfilter libs
|
||||
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
|
||||
wget -qO- https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
|
||||
@@ -94,6 +90,7 @@ jobs:
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
CFLAGS="-Os -flto=auto" \
|
||||
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -105,6 +102,7 @@ jobs:
|
||||
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
|
||||
(
|
||||
cd zlib-*
|
||||
CFLAGS="-Os -flto=auto" \
|
||||
./configure --prefix= --static
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -115,8 +113,8 @@ jobs:
|
||||
install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
|
||||
|
||||
# zapret
|
||||
CFLAGS="$CFLAGS -static-libgcc -static -I$DEPS_DIR/include" \
|
||||
LDFLAGS="$LDFLAGS -L$DEPS_DIR/lib" \
|
||||
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include" \
|
||||
LDFLAGS="-L$DEPS_DIR/lib" \
|
||||
make -C zapret -j$(nproc)
|
||||
tar -C zapret/binaries/my -cJf zapret-linux-$ARCH.tar.xz .
|
||||
|
||||
@@ -136,6 +134,7 @@ jobs:
|
||||
|
||||
- name: Build zapret
|
||||
run: |
|
||||
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
|
||||
make mac -j$(sysctl -n hw.logicalcpu)
|
||||
tar -C binaries/my -cJf zapret-mac-x64.tar.xz .
|
||||
|
||||
@@ -170,7 +169,8 @@ jobs:
|
||||
TARGET: ${{ matrix.target }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: |
|
||||
settarget $TARGET-freebsd11 make bsd -j$(nproc) || exit 1
|
||||
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
|
||||
settarget $TARGET-freebsd11 make bsd -j$(nproc)
|
||||
tar -C binaries/my -cJf zapret-freebsd-$ARCH.tar.xz .
|
||||
|
||||
- name: Upload artifacts
|
||||
@@ -203,6 +203,7 @@ jobs:
|
||||
- name: Build ip2net, mdig
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
|
||||
mkdir -p output
|
||||
cd zapret
|
||||
mingw32-make -C ip2net win
|
||||
@@ -259,6 +260,7 @@ jobs:
|
||||
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
|
||||
run: >-
|
||||
export MAKEFLAGS=-j$(nproc) &&
|
||||
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}" &&
|
||||
cd zapret &&
|
||||
make -C nfq ${TARGET} &&
|
||||
cp -a nfq/winws.exe ../output
|
||||
@@ -317,10 +319,6 @@ jobs:
|
||||
export STRIP=$TOOLCHAIN/bin/llvm-strip
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
|
||||
# optimize for size
|
||||
export CFLAGS="-Os -flto=auto"
|
||||
export LDFLAGS="-Os"
|
||||
|
||||
# netfilter libs
|
||||
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
|
||||
wget -qO- https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
|
||||
@@ -330,7 +328,7 @@ jobs:
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
CFLAGS="$CFLAGS -Wno-implicit-function-declaration" \
|
||||
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \
|
||||
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -338,7 +336,8 @@ jobs:
|
||||
done
|
||||
|
||||
# zapret
|
||||
CFLAGS="$CFLAGS -I$DEPS_DIR/include" LDFLAGS="$LDFLAGS -L$DEPS_DIR/lib" \
|
||||
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -I$DEPS_DIR/include" \
|
||||
LDFLAGS="-L$DEPS_DIR/lib" \
|
||||
make -C zapret android -j$(nproc)
|
||||
zip zapret-android-$ABI.zip -j zapret/binaries/my/*
|
||||
|
||||
@@ -434,8 +433,16 @@ jobs:
|
||||
- name: Create release bundles
|
||||
run: |
|
||||
rm -rf ${{ env.repo_dir }}/.git*
|
||||
tar -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
|
||||
find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
|
||||
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
|
||||
(
|
||||
cd ${{ env.repo_dir }}
|
||||
rm -rf binaries/{android*,freebsd*,mac*,win*,x86_64/tpws_wsl.tgz} \
|
||||
init.d/{openrc,macos,pfsense,runit,s6,systemd} \
|
||||
tpws nfq ip2net mdig docs files/huawei Makefile
|
||||
)
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
|
||||
|
||||
- name: Upload release assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
@@ -448,3 +455,4 @@ jobs:
|
||||
files: |
|
||||
zapret*.tar.gz
|
||||
zapret*.zip
|
||||
sha256sum.txt
|
||||
|
@@ -1011,11 +1011,10 @@ tpws_curl_test()
|
||||
echo - checking tpws $3 $4 $5 $6 $7 $8 $9${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
|
||||
local ALL_PROXY="socks5://127.0.0.1:$SOCKS_PORT"
|
||||
ws_curl_test tpws_start "$@"${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
|
||||
local code=$?
|
||||
local testf=$1 dom=$2 strategy code=$?
|
||||
[ "$code" = 0 ] && {
|
||||
local testf=$1 dom=$2
|
||||
shift; shift;
|
||||
local strategy="$@"
|
||||
strategy="$@"
|
||||
strategy_append_extra_tpws
|
||||
report_append "ipv${IPV} $dom $testf : tpws ${WF:+$WF }$strategy"
|
||||
}
|
||||
@@ -1028,11 +1027,10 @@ pktws_curl_test()
|
||||
# $3,$4,$5, ... - nfqws/dvtws params
|
||||
echo - checking $PKTWSD ${WF:+$WF }$3 $4 $5 $6 $7 $8 $9${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
|
||||
ws_curl_test pktws_start "$@"${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
|
||||
local code=$?
|
||||
local testf=$1 dom=$2 strategy code=$?
|
||||
[ "$code" = 0 ] && {
|
||||
local testf=$1 dom=$2
|
||||
shift; shift;
|
||||
local strategy="$@"
|
||||
strategy="$@"
|
||||
strategy_append_extra_pktws
|
||||
report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy"
|
||||
}
|
||||
@@ -1112,6 +1110,10 @@ test_has_split()
|
||||
{
|
||||
contains "$1" split || contains "$1" disorder
|
||||
}
|
||||
test_has_fakedsplit()
|
||||
{
|
||||
contains "$1" fakedsplit || contains "$1" fakeddisorder
|
||||
}
|
||||
test_has_fake()
|
||||
{
|
||||
[ "$1" = fake ] || starts_with "$1" fake,
|
||||
@@ -1138,10 +1140,13 @@ pktws_curl_test_update_vary()
|
||||
proto=http
|
||||
[ "$sec" = 0 ] || proto=tls
|
||||
test_has_fake $desync && zerofake="--dpi-desync-fake-$proto=0x00000000"
|
||||
test_has_split $desync && {
|
||||
if test_has_fakedsplit $desync ; then
|
||||
splits="method+2 midsld"
|
||||
[ "$sec" = 0 ] || splits="1 midsld"
|
||||
elif test_has_split $desync ; then
|
||||
splits="method+2 midsld"
|
||||
[ "$sec" = 0 ] || splits="1 midsld 1,midsld"
|
||||
}
|
||||
fi
|
||||
for fake in '' $zerofake ; do
|
||||
if [ -n "$splits" ]; then
|
||||
for pos in $splits ; do
|
||||
@@ -1173,7 +1178,7 @@ pktws_check_domain_http_bypass_()
|
||||
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'
|
||||
|
||||
[ "$sec" = 0 ] && {
|
||||
for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase'; do
|
||||
for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase' '--methodeol'; do
|
||||
pktws_curl_test_update $1 $3 $s
|
||||
done
|
||||
}
|
||||
|
@@ -140,7 +140,7 @@ echo_var()
|
||||
eval v="\$$1"
|
||||
if find_str_in_list $1 "$EDITVAR_NEWLINE_VARS"; then
|
||||
echo "$1=\""
|
||||
echo "$v\"" | sed "s/$EDITVAR_NEWLINE_DELIMETER /$EDITVAR_NEWLINE_DELIMETER\n/g"
|
||||
echo "$v\"" | tr '\n' ' ' | tr -d '\r' | sed -e 's/^ *//' -e 's/ *$//' -e "s/$EDITVAR_NEWLINE_DELIMETER /$EDITVAR_NEWLINE_DELIMETER\n/g"
|
||||
else
|
||||
if contains "$v" " "; then
|
||||
echo $1=\"$v\"
|
||||
@@ -170,6 +170,7 @@ list_vars()
|
||||
echo_var $1
|
||||
shift
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
openrc_test()
|
||||
@@ -837,3 +838,37 @@ select_fwtype()
|
||||
echo select firewall type :
|
||||
ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE
|
||||
}
|
||||
|
||||
dry_run_tpws_()
|
||||
{
|
||||
local TPWS="$ZAPRET_BASE/tpws/tpws"
|
||||
echo verifying tpws options
|
||||
"$TPWS" --dry-run "$@"
|
||||
}
|
||||
dry_run_nfqws_()
|
||||
{
|
||||
local NFQWS="$ZAPRET_BASE/nfq/nfqws"
|
||||
echo verifying nfqws options
|
||||
"$NFQWS" --dry-run "$@"
|
||||
}
|
||||
dry_run_tpws()
|
||||
{
|
||||
[ "$TPWS_ENABLE" = 1 ] || return 0
|
||||
local opt="$TPWS_OPT" port=${TPPORT_SOCKS:-988}
|
||||
filter_apply_hostlist_target opt
|
||||
dry_run_tpws_ --port=$port $opt
|
||||
}
|
||||
dry_run_tpws_socks()
|
||||
{
|
||||
[ "$TPWS_SOCKS_ENABLE" = 1 ] || return 0
|
||||
local opt="$TPWS_SOCKS_OPT" port=${TPPORT:-987}
|
||||
filter_apply_hostlist_target opt
|
||||
dry_run_tpws_ --port=$port --socks $opt
|
||||
}
|
||||
dry_run_nfqws()
|
||||
{
|
||||
[ "$NFQWS_ENABLE" = 1 ] || return 0
|
||||
local opt="$NFQWS_OPT" qn=${QNUM:-200}
|
||||
filter_apply_hostlist_target opt
|
||||
dry_run_nfqws_ --qnum=$qn $opt
|
||||
}
|
||||
|
@@ -389,3 +389,31 @@ blockcheck: added CURL_OPT
|
||||
blockcheck: new strategies support
|
||||
blockcheck: test sequence rework
|
||||
blockcheck: view all working strategies in summary
|
||||
|
||||
v69.1:
|
||||
|
||||
init.d: keenetic udp fix custom
|
||||
tpws: fixed incorrect hostlist checks
|
||||
|
||||
v69.2:
|
||||
|
||||
nfqws,tpws: --skip
|
||||
nfqws: --methodeol
|
||||
init.d: do not use pgrep in sysv for busybox compat
|
||||
|
||||
v69.3
|
||||
|
||||
nfqws,tpws: fixed ipsets and hostlists
|
||||
all progs: version numbers for github, build date/time for self built
|
||||
repo: light release for openwrt and embedded systems
|
||||
repo: sha256sum
|
||||
|
||||
v69.4
|
||||
|
||||
nfqws: fakedsplit/fakeddisorder fakes for both split segments
|
||||
nfqws: --dpi-desync-fakedsplit-pattern
|
||||
|
||||
v69.5
|
||||
|
||||
nfqws,tpws: --dry-run
|
||||
install_easy: check tpws and nfqws options validity
|
||||
|
@@ -50,6 +50,8 @@
|
||||
> образ `squashfs` с помощью `image builder` и перешить этим вариантом роутер.
|
||||
|
||||
1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив.
|
||||
Для openwrt и прошивок используйте вариант `openwrt-embedded`.
|
||||
Для экономия места в /tmp можно качать через curl в stdout и сразу распаковывать.
|
||||
|
||||
2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и
|
||||
сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`.
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# zapret v.69
|
||||
# zapret v69.5
|
||||
|
||||
# SCAMMER WARNING
|
||||
|
||||
@@ -131,6 +131,7 @@ nfqws takes the following parameters:
|
||||
@<config_file> ; read file for options. must be the only argument. other options are ignored.
|
||||
|
||||
--debug=0|1
|
||||
--dry-run ; verify parameters and exit with code 0 if successful
|
||||
--qnum=<nfqueue_number>
|
||||
--daemon ; daemonize
|
||||
--pidfile=<filename> ; write pid to file
|
||||
@@ -146,6 +147,7 @@ nfqws takes the following parameters:
|
||||
--hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host"
|
||||
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
|
||||
--domcase ; mix domain case : Host: TeSt.cOm
|
||||
--methodeol ; add '\n' before method and remove space after Host:
|
||||
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
||||
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
|
||||
--dpi-desync-ttl=<int> ; set ttl for desync packet
|
||||
@@ -161,6 +163,7 @@ nfqws takes the following parameters:
|
||||
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
|
||||
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
|
||||
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap
|
||||
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder
|
||||
--dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8.
|
||||
--dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32.
|
||||
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000
|
||||
@@ -179,19 +182,24 @@ nfqws takes the following parameters:
|
||||
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
|
||||
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
|
||||
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
|
||||
--hostlist-domains=<domain_list> ; comma separated fixed domain list
|
||||
--hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
|
||||
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
|
||||
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
|
||||
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
|
||||
--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 ; 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=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
|
||||
--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
|
||||
```
|
||||
|
||||
### DPI desync attack
|
||||
@@ -256,8 +264,8 @@ Fakes are separate generated by nfqws packets carrying false information for DPI
|
||||
|
||||
* `multisplit`. split request at specified in `--dpi-desync-split-pos` positions
|
||||
* `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, 2nd segment
|
||||
* `fakeddisorder`. same as `fakedsplit` but with another order : 2nd segment, fake 1st segment, 1st segment, fake 1st segment
|
||||
* `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
|
||||
* `fakeddisorder`. same as `fakedsplit` but with another order : fake 2nd segment, 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment
|
||||
|
||||
Positions are defined by markers.
|
||||
|
||||
@@ -267,7 +275,7 @@ Positions are defined by markers.
|
||||
|
||||
Relative positions :
|
||||
|
||||
* **method** - HTTP method start ('GET', 'POST', 'HEAD', ...). Method is usually always at position 0 but also supported `--methodeol` fooling by **tpws**. If fooled position can become 1 or 2.
|
||||
* **method** - HTTP method start ('GET', 'POST', 'HEAD', ...). Method is usually always at position 0 but can shift because of `--methodeol` fooling. If fooled position can become 1 or 2.
|
||||
* **host** - hostname start in a known protocol (http, TLS)
|
||||
* **endhost** - the byte next to the last hostname's byte
|
||||
* **sld** - second level domain start in the hostname
|
||||
@@ -632,6 +640,7 @@ tpws is transparent proxy.
|
||||
|
||||
--debug=0|1|2|syslog|@<filename> ; 1 and 2 means log to console and set debug level. for other targets use --debug-level.
|
||||
--debug-level=0|1|2 ; specify debug level for syslog and @<filename>
|
||||
--dry-run ; verify parameters and exit with code 0 if successful
|
||||
--bind-addr=<v4_addr>|<v6_addr> ; for v6 link locals append %interface_name : fe80::1%br-lan
|
||||
--bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface
|
||||
--bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface
|
||||
@@ -663,15 +672,20 @@ tpws is transparent proxy.
|
||||
; its worth to make a reserve with 1.5 multiplier. by default maxfiles is (X*connections)*1.5+16
|
||||
--max-orphan-time=<sec> ; if local leg sends something and closes and remote leg is still connecting then cancel connection attempt after N seconds
|
||||
|
||||
--new ; begin new strategy
|
||||
--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. comma separated list supported.
|
||||
--filter-l7=[http|tls|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
|
||||
--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
|
||||
|
||||
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
|
||||
--hostlist-domains=<domain_list> ; comma separated fixed domain list
|
||||
--hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
|
||||
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
|
||||
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
|
||||
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
|
||||
--hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
|
||||
@@ -701,7 +715,7 @@ tpws is transparent proxy.
|
||||
--daemon ; daemonize
|
||||
--pidfile=<filename> ; write pid to file
|
||||
--user=<username> ; drop root privs
|
||||
--uid=uid[:gid] ; drop root privs
|
||||
--uid=uid[:gid] ; drop root privs
|
||||
```
|
||||
|
||||
### TCP segmentation in tpws
|
||||
|
319
docs/readme.md
319
docs/readme.md
@@ -1,4 +1,4 @@
|
||||
# zapret v.69
|
||||
# zapret v69.5
|
||||
|
||||
# ВНИМАНИЕ, остерегайтесь мошенников
|
||||
|
||||
@@ -159,70 +159,78 @@ DPI. Все больше становится внереестровых бло
|
||||
dvtws, собираемый из тех же исходников (см. [документация BSD](./bsd.md)).
|
||||
|
||||
```
|
||||
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
|
||||
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
|
||||
|
||||
--debug=0|1 ; 1=выводить отладочные сообщения
|
||||
--daemon ; демонизировать прогу
|
||||
--pidfile=<file> ; сохранить PID в файл
|
||||
--user=<username> ; менять uid процесса
|
||||
--uid=uid[:gid] ; менять uid процесса
|
||||
--qnum=N ; номер очереди N
|
||||
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
|
||||
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
|
||||
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
|
||||
--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
|
||||
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
|
||||
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
|
||||
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
|
||||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||||
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
||||
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
||||
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
|
||||
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
|
||||
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
|
||||
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию.
|
||||
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; переопределение предыдущего параметра для ipv6
|
||||
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
|
||||
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
|
||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
||||
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
|
||||
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
|
||||
--debug=0|1 ; 1=выводить отладочные сообщения
|
||||
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
|
||||
--daemon ; демонизировать прогу
|
||||
--pidfile=<file> ; сохранить PID в файл
|
||||
--user=<username> ; менять uid процесса
|
||||
--uid=uid[:gid] ; менять uid процесса
|
||||
--qnum=N ; номер очереди N
|
||||
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
|
||||
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
|
||||
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
|
||||
--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
|
||||
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
|
||||
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
|
||||
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
|
||||
--methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com"
|
||||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||||
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
||||
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
||||
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
|
||||
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
|
||||
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
|
||||
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию.
|
||||
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; переопределение предыдущего параметра для ipv6
|
||||
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
|
||||
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
|
||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
||||
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
|
||||
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
|
||||
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; чем заполнять фейковую часть overlap
|
||||
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
|
||||
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
|
||||
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
||||
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
||||
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
|
||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
||||
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
|
||||
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||
--dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen
|
||||
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
|
||||
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
|
||||
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
||||
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
||||
; в файле должен быть хост на каждой строке.
|
||||
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||||
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||||
; список может быть запакован в gzip. формат автоматически распознается и разжимается
|
||||
; списков может быть множество. пустой общий лист = его отсутствие
|
||||
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
||||
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
|
||||
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
||||
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
||||
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
|
||||
--hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3)
|
||||
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
|
||||
--new ; начало новой стратегии (новый профиль)
|
||||
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
||||
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую.
|
||||
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую.
|
||||
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
||||
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; чем заполнять фейки в fakedsplit/fakeddisorder
|
||||
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
|
||||
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
|
||||
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
||||
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
||||
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
|
||||
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
||||
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
||||
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
|
||||
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||||
--dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen
|
||||
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
|
||||
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
|
||||
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
||||
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
||||
; в файле должен быть хост на каждой строке.
|
||||
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||||
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||||
; список может быть запакован в gzip. формат автоматически распознается и разжимается
|
||||
; списков может быть множество. пустой общий лист = его отсутствие
|
||||
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
||||
--hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
|
||||
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
|
||||
--hostlist-exclude-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
|
||||
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
||||
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
||||
--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=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
||||
--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 или в файл. Может быть важен порядок следования
|
||||
@@ -312,8 +320,13 @@ dvtws, собираемый из тех же исходников (см. [док
|
||||
|
||||
* `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях.
|
||||
* `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке.
|
||||
* `fakedsplit`. нарезаем запрос на 2 части, обрамляя его фейками : фейк 1-й части, 1 часть, фейк 1-й части, 2 часть
|
||||
* `fakeddisorder`. нарезаем запрос на 2 части, обрамляя его фейками : 2 часть, фейк 1-й части, 1 часть, фейк 1 части.
|
||||
* `fakedsplit`. нарезаем запрос на 2 части, обрамляя каждую часть фейками : фейк 1-й части, 1 часть, фейк 1-й части, фейк 2-й части, 2 часть, фейк 2-й части
|
||||
* `fakeddisorder`. аналогично `fakedsplit`, только в обратном порядке : фейк 2-й части, 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1 части.
|
||||
|
||||
Содержимое фейков в `fakedsplit`/`fakeddisorder` определяется параметром `--dpi-desync-fakedsplit-pattern` (по умолчанию 0x00).
|
||||
Данные фейков берутся из паттерна со смещением, соответствующим смещению отсылаемых частей.
|
||||
Размеры фейков соответствуют длинам отсылаемых частей.
|
||||
Цель этих режимов - максимально усложнить выявление оригинальных данных среди фейков.
|
||||
|
||||
Для определения позиций нарезки используются маркеры.
|
||||
|
||||
@@ -323,7 +336,7 @@ dvtws, собираемый из тех же исходников (см. [док
|
||||
|
||||
Относительные позиции :
|
||||
|
||||
* **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но поддерживается и нахождение метода после дурение методом `--methodeol` от tpws. Тогда позиция может стать 1 или 2.
|
||||
* **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но может сместиться из-за `--methodeol`. Тогда позиция может стать 1 или 2.
|
||||
* **host** - начало имени хоста в известном протоколе (http, TLS)
|
||||
* **endhost** - байт, следующий за последним байтом имени хоста
|
||||
* **sld** - начало домена 2 уровня в имени хоста
|
||||
@@ -742,95 +755,101 @@ iptables target `FLOWOFFLOAD` - это проприетарное изобрет
|
||||
|
||||
tpws - это transparent proxy.
|
||||
```
|
||||
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
|
||||
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
|
||||
|
||||
--debug=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
|
||||
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
|
||||
--daemon ; демонизировать прогу
|
||||
--pidfile=<file> ; сохранить PID в файл
|
||||
--user=<username> ; менять uid процесса
|
||||
--uid=uid[:gid] ; менять uid процесса
|
||||
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес
|
||||
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
|
||||
--bind-linklocal=no|unwanted|prefer|force
|
||||
; no : биндаться только на global ipv6
|
||||
; unwanted (default) : предпочтительно global, если нет - LL
|
||||
; prefer : предпочтительно LL, если нет - global
|
||||
; force : биндаться только на LL
|
||||
--bind-iface4=<iface> ; слушать на первом ipv4 интерфейса iface
|
||||
--bind-iface6=<iface> ; слушать на первом ipv6 интерфейса iface
|
||||
--bind-wait-ifup=<sec ; ждать до N секунд появления и поднятия интерфейса
|
||||
--bind-wait-ip=<sec> ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса)
|
||||
--debug=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
|
||||
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
|
||||
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
|
||||
|
||||
--daemon ; демонизировать прогу
|
||||
--pidfile=<file> ; сохранить PID в файл
|
||||
--user=<username> ; менять uid процесса
|
||||
--uid=uid[:gid] ; менять uid процесса
|
||||
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес
|
||||
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
|
||||
--bind-linklocal=no|unwanted|prefer|force ; no : биндаться только на global ipv6
|
||||
; unwanted (default) : предпочтительно global, если нет - LL
|
||||
; prefer : предпочтительно LL, если нет - global
|
||||
; force : биндаться только на LL
|
||||
--bind-iface4=<iface> ; слушать на первом ipv4 интерфейса iface
|
||||
--bind-iface6=<iface> ; слушать на первом ipv6 интерфейса iface
|
||||
--bind-wait-ifup=<sec> ; ждать до N секунд появления и поднятия интерфейса
|
||||
--bind-wait-ip=<sec> ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса)
|
||||
--bind-wait-ip-linklocal=<sec>
|
||||
; имеет смысл только при задании --bind-wait-ip
|
||||
; --bind-linklocal=unwanted : согласиться на LL после N секунд
|
||||
; --bind-linklocal=prefer : согласиться на global address после N секунд
|
||||
--bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0.
|
||||
--connect-bind-addr ; с какого адреса подключаться во внешнюю сеть. может быть ipv4 или ipv6 адрес
|
||||
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
|
||||
; опция может повторяться для v4 и v6 адресов
|
||||
; опция не отменяет правил маршрутизации ! выбор интерфейса определяется лишь правилами маршрутизации, кроме случая v6 link local.
|
||||
--socks ; вместо прозрачного прокси реализовать socks4/5 proxy
|
||||
--no-resolve ; запретить ресолвинг имен через socks5
|
||||
--resolve-threads ; количество потоков ресолвера
|
||||
--port=<port> ; на каком порту слушать
|
||||
--maxconn=<max_connections> ; максимальное количество соединений от клиентов к прокси
|
||||
--maxfiles=<max_open_files> ; макс количество файловых дескрипторов (setrlimit). мин требование (X*connections+16), где X=6 в tcp proxy mode, X=4 в режиме тамперинга.
|
||||
; стоит сделать запас с коэффициентом как минимум 1.5. по умолчанию maxfiles (X*connections)*1.5+16
|
||||
--max-orphan-time=<sec> ; если вы запускаете через tpws торрент-клиент с множеством раздач, он пытается установить очень много исходящих соединений,
|
||||
; большая часть из которых отваливается по таймауту (юзера сидят за NAT, firewall, ...)
|
||||
; установление соединения в linux может длиться очень долго. локальный конец отвалился, перед этим послав блок данных,
|
||||
; tpws ждет подключения удаленного конца, чтобы отослать ему этот блок, и зависает надолго.
|
||||
; настройка позволяет сбрасывать такие подключения через N секунд, теряя блок данных. по умолчанию 5 сек. 0 означает отключить функцию
|
||||
; эта функция не действует на успешно подключенные ранее соединения
|
||||
; имеет смысл только при задании --bind-wait-ip
|
||||
; --bind-linklocal=unwanted : согласиться на LL после N секунд
|
||||
; --bind-linklocal=prefer : согласиться на global address после N секунд
|
||||
--bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0.
|
||||
--connect-bind-addr ; с какого адреса подключаться во внешнюю сеть. может быть ipv4 или ipv6 адрес
|
||||
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
|
||||
; опция может повторяться для v4 и v6 адресов
|
||||
; опция не отменяет правил маршрутизации ! выбор интерфейса определяется лишь правилами маршрутизации, кроме случая v6 link local.
|
||||
--socks ; вместо прозрачного прокси реализовать socks4/5 proxy
|
||||
--no-resolve ; запретить ресолвинг имен через socks5
|
||||
--resolve-threads ; количество потоков ресолвера
|
||||
--port=<port> ; на каком порту слушать
|
||||
--maxconn=<max_connections> ; максимальное количество соединений от клиентов к прокси
|
||||
--maxfiles=<max_open_files> ; макс количество файловых дескрипторов (setrlimit). мин требование (X*connections+16), где X=6 в tcp proxy mode, X=4 в режиме тамперинга.
|
||||
; стоит сделать запас с коэффициентом как минимум 1.5. по умолчанию maxfiles (X*connections)*1.5+16
|
||||
--max-orphan-time=<sec> ; если вы запускаете через tpws торрент-клиент с множеством раздач, он пытается установить очень много исходящих соединений,
|
||||
; большая часть из которых отваливается по таймауту (юзера сидят за NAT, firewall, ...)
|
||||
; установление соединения в linux может длиться очень долго. локальный конец отвалился, перед этим послав блок данных,
|
||||
; tpws ждет подключения удаленного конца, чтобы отослать ему этот блок, и зависает надолго.
|
||||
; настройка позволяет сбрасывать такие подключения через N секунд, теряя блок данных. по умолчанию 5 сек. 0 означает отключить функцию
|
||||
; эта функция не действует на успешно подключенные ранее соединения
|
||||
|
||||
--local-rcvbuf=<bytes> ; SO_RCVBUF для соединений client-proxy
|
||||
--local-sndbuf=<bytes> ; SO_SNDBUF для соединений client-proxy
|
||||
--remote-rcvbuf=<bytes> ; SO_RCVBUF для соединений proxy-target
|
||||
--remote-sndbuf=<bytes> ; SO_SNDBUF для соединений proxy-target
|
||||
--nosplice ; не использовать splice на linux системах
|
||||
--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.
|
||||
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
|
||||
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
|
||||
--fix-seg=<int> ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс.
|
||||
--local-rcvbuf=<bytes> ; SO_RCVBUF для соединений client-proxy
|
||||
--local-sndbuf=<bytes> ; SO_SNDBUF для соединений client-proxy
|
||||
--remote-rcvbuf=<bytes> ; SO_RCVBUF для соединений proxy-target
|
||||
--remote-sndbuf=<bytes> ; SO_SNDBUF для соединений proxy-target
|
||||
--nosplice ; не использовать splice на linux системах
|
||||
--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.
|
||||
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
|
||||
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
|
||||
--fix-seg=<int> ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс.
|
||||
|
||||
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
|
||||
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
|
||||
--disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса
|
||||
--oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита
|
||||
--oob-data=<char>|0xHEX ; переопределить байт OOB. по умолчанию 0x00.
|
||||
--hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:".
|
||||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||||
--hostdot ; добавление точки после имени хоста : "Host: kinozal.tv."
|
||||
--hosttab ; добавление табуляции после имени хоста : "Host: kinozal.tv\t"
|
||||
--hostnospace ; убрать пробел после "Host:"
|
||||
--hostpad=<bytes> ; добавить паддинг-хедеров общей длиной <bytes> перед Host:
|
||||
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
||||
--methodspace ; добавить пробел после метода : "GET /" => "GET /"
|
||||
--methodeol ; добавить перевод строки перед методом : "GET /" => "\r\nGET /"
|
||||
--unixeol ; конвертировать 0D0A в 0A и использовать везде 0A
|
||||
--tlsrec=N|-N|marker+N|marker-N ; разбивка TLS ClientHello на 2 TLS records на указанной позиции. Минимальное смещение - 6.
|
||||
--mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость
|
||||
--tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока)
|
||||
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
|
||||
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
||||
; в файле должен быть хост на каждой строке.
|
||||
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||||
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||||
; список может быть запакован в gzip. формат автоматически распознается и разжимается
|
||||
; списков может быть множество. пустой общий лист = его отсутствие
|
||||
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
||||
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
|
||||
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
||||
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
||||
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
|
||||
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
|
||||
--new ; начало новой стратегии (новый профиль)
|
||||
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
||||
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую.
|
||||
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
|
||||
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
|
||||
--disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса
|
||||
--oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита
|
||||
--oob-data=<char>|0xHEX ; переопределить байт OOB. по умолчанию 0x00.
|
||||
--hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:".
|
||||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||||
--hostdot ; добавление точки после имени хоста : "Host: kinozal.tv."
|
||||
--hosttab ; добавление табуляции после имени хоста : "Host: kinozal.tv\t"
|
||||
--hostnospace ; убрать пробел после "Host:"
|
||||
--hostpad=<bytes> ; добавить паддинг-хедеров общей длиной <bytes> перед Host:
|
||||
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
||||
--methodspace ; добавить пробел после метода : "GET /" => "GET /"
|
||||
--methodeol ; добавить перевод строки перед методом : "GET /" => "\r\nGET /"
|
||||
--unixeol ; конвертировать 0D0A в 0A и использовать везде 0A
|
||||
--tlsrec=N|-N|marker+N|marker-N ; разбивка TLS ClientHello на 2 TLS records на указанной позиции. Минимальное смещение - 6.
|
||||
--mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость
|
||||
--tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока)
|
||||
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
|
||||
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
||||
; в файле должен быть хост на каждой строке.
|
||||
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||||
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||||
; список может быть запакован в gzip. формат автоматически распознается и разжимается
|
||||
; списков может быть множество. пустой общий лист = его отсутствие
|
||||
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
||||
--hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
|
||||
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
|
||||
--hostlist-exclude-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
|
||||
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
||||
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
||||
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
|
||||
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
|
||||
--new ; начало новой стратегии (новый профиль)
|
||||
--skip ; не использовать этот профиль . полезно для временной деактивации профиля без удаления параметров.
|
||||
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
||||
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую.
|
||||
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
||||
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||||
--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> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
|
||||
```
|
||||
|
||||
### TCP СЕГМЕНТАЦИЯ В TPWS
|
||||
|
@@ -101,10 +101,11 @@ There are several options :
|
||||
Replace these 2 files in every location they are present.
|
||||
In `zapret-win-bundle` they are in `zapret-winws` и `blockcheck/zapret/nfq` folders.
|
||||
However this option still requires 10+ year old patch that enables SHA256 signatures.
|
||||
If you're using win bundle you can simply run `win7\install_win7.cmd`
|
||||
|
||||
2. [Hack ESU](https://hackandpwn.com/windows-7-esu-patching)
|
||||
3. [Hack ESU](https://hackandpwn.com/windows-7-esu-patching)
|
||||
|
||||
3. Use `UpdatePack7R2` from simplix : https://blog.simplix.info
|
||||
4. Use `UpdatePack7R2` from simplix : https://blog.simplix.info
|
||||
If you are in Russia or Belarus temporary change region in Control Panel.
|
||||
|
||||
### blockcheck
|
||||
|
@@ -159,6 +159,7 @@ _windivert 2.2.2-A_, который идет в поставке zapret.
|
||||
и заменить эти 2 файла.
|
||||
В [zapret-win-bundle](https://github.com/bol-van/zapret-win-bundle) есть отдельных 2 места, где находится **winws** : [_zapret-winws_](https://github.com/bol-van/zapret-win-bundle/tree/master/zapret-winws) и [_blockcheck/zapret/nfq_](https://github.com/bol-van/zapret-win-bundle/tree/master/blockcheck).
|
||||
Надо менять в обоих местах.
|
||||
Альтернативный вариант при использовании win bundle - запустить `win7\install_win7.cmd`
|
||||
|
||||
> [!NOTE]
|
||||
> Этот вариант проверен и должен работать. Тем не менее патч 10 летней давности, который включает SHA256 сигнатуры, все еще необходим.
|
||||
|
@@ -102,7 +102,7 @@ dnat6_target()
|
||||
}
|
||||
set_route_localnet()
|
||||
{
|
||||
_set_route_localnet $1 "$IFACE_LAN"
|
||||
_set_route_localnet $1 $IFACE_LAN
|
||||
}
|
||||
|
||||
fw_nfqws_post4()
|
||||
@@ -167,9 +167,15 @@ run_daemon()
|
||||
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
|
||||
|
||||
local DAEMONBASE="$(basename "$2")"
|
||||
local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
|
||||
local PID= PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
|
||||
echo "Starting daemon $1: $2 $3"
|
||||
if [ -f "$PIDFILE" ] && pgrep -F "$PIDFILE" "$DAEMONBASE" >/dev/null; then
|
||||
|
||||
[ -f "$PIDFILE" ] && {
|
||||
read PID <"$PIDFILE"
|
||||
[ -d "/proc/$PID" ] || PID=
|
||||
}
|
||||
|
||||
if [ -n "$PID" ]; then
|
||||
echo already running
|
||||
else
|
||||
"$2" $3 >/dev/null &
|
||||
@@ -188,18 +194,14 @@ stop_daemon()
|
||||
# $2 - daemon
|
||||
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
|
||||
local DAEMONBASE="$(basename "$2")"
|
||||
local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
|
||||
local PID PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
|
||||
echo "Stopping daemon $1: $2"
|
||||
if exists start-stop-daemon ; then
|
||||
start-stop-daemon -K -p "$PIDFILE" -x "$2"
|
||||
if [ -f "$PIDFILE" ]; then
|
||||
read PID <"$PIDFILE"
|
||||
kill $PID
|
||||
rm -f "$PIDFILE"
|
||||
else
|
||||
if [ -f "$PIDFILE" ]; then
|
||||
read PID <"$PIDFILE"
|
||||
kill $PID
|
||||
rm -f "$PIDFILE"
|
||||
else
|
||||
echo no pidfile : $PIDFILE
|
||||
fi
|
||||
echo no pidfile : $PIDFILE
|
||||
fi
|
||||
}
|
||||
do_daemon()
|
||||
|
@@ -68,7 +68,7 @@ case $UNAME in
|
||||
;;
|
||||
CYGWIN*)
|
||||
UNAME=CYGWIN
|
||||
ARCHLIST="win64"
|
||||
ARCHLIST="win64 win32"
|
||||
PKTWS=winws
|
||||
;;
|
||||
*)
|
||||
|
@@ -26,6 +26,7 @@ IPSET_DIR="$ZAPRET_BASE/ipset"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
. "$ZAPRET_BASE/common/installer.sh"
|
||||
. "$ZAPRET_BASE/common/virt.sh"
|
||||
. "$ZAPRET_BASE/common/list.sh"
|
||||
|
||||
GET_LIST="$IPSET_DIR/get_config.sh"
|
||||
|
||||
@@ -115,6 +116,30 @@ ws_opt_validate()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
tpws_opt_validate()
|
||||
{
|
||||
ws_opt_validate "$1" || return 1
|
||||
dry_run_tpws || {
|
||||
echo invalid tpws options
|
||||
return 1
|
||||
}
|
||||
}
|
||||
tpws_socks_opt_validate()
|
||||
{
|
||||
# --ipset allowed here
|
||||
dry_run_tpws_socks || {
|
||||
echo invalid tpws options
|
||||
return 1
|
||||
}
|
||||
}
|
||||
nfqws_opt_validate()
|
||||
{
|
||||
ws_opt_validate "$1" || return 1
|
||||
dry_run_nfqws || {
|
||||
echo invalid nfqws options
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
select_mode_group()
|
||||
{
|
||||
@@ -162,18 +187,17 @@ select_mode_group()
|
||||
select_mode_tpws_socks()
|
||||
{
|
||||
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_SOCKS_OPT"
|
||||
# --ipset allowed here
|
||||
select_mode_group TPWS_SOCKS_ENABLE "enable tpws socks mode on port $TPPORT_SOCKS ?" "TPPORT_SOCKS TPWS_SOCKS_OPT"
|
||||
select_mode_group TPWS_SOCKS_ENABLE "enable tpws socks mode on port $TPPORT_SOCKS ?" "TPPORT_SOCKS TPWS_SOCKS_OPT" tpws_socks_opt_validate TPWS_SOCKS_OPT
|
||||
}
|
||||
select_mode_tpws()
|
||||
{
|
||||
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_OPT"
|
||||
select_mode_group TPWS_ENABLE "enable tpws transparent mode ?" "TPWS_PORTS TPWS_OPT" ws_opt_validate TPWS_OPT
|
||||
select_mode_group TPWS_ENABLE "enable tpws transparent mode ?" "TPWS_PORTS TPWS_OPT" tpws_opt_validate TPWS_OPT
|
||||
}
|
||||
select_mode_nfqws()
|
||||
{
|
||||
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="NFQWS_OPT"
|
||||
select_mode_group NFQWS_ENABLE "enable nfqws ?" "NFQWS_PORTS_TCP NFQWS_PORTS_UDP NFQWS_TCP_PKT_OUT NFQWS_TCP_PKT_IN NFQWS_UDP_PKT_OUT NFQWS_UDP_PKT_IN NFQWS_PORTS_TCP_KEEPALIVE NFQWS_PORTS_UDP_KEEPALIVE NFQWS_OPT" ws_opt_validate NFQWS_OPT
|
||||
select_mode_group NFQWS_ENABLE "enable nfqws ?" "NFQWS_PORTS_TCP NFQWS_PORTS_UDP NFQWS_TCP_PKT_OUT NFQWS_TCP_PKT_IN NFQWS_UDP_PKT_OUT NFQWS_UDP_PKT_IN NFQWS_PORTS_TCP_KEEPALIVE NFQWS_PORTS_UDP_KEEPALIVE NFQWS_OPT" nfqws_opt_validate NFQWS_OPT
|
||||
}
|
||||
|
||||
select_mode_mode()
|
||||
|
@@ -192,7 +192,7 @@ static void ip6_and(const struct in6_addr * restrict a, const struct in6_addr *
|
||||
static void rtrim(char *s)
|
||||
{
|
||||
if (s)
|
||||
for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0';
|
||||
for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'); p--) *p = '\0';
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +217,14 @@ static void exithelp(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
|
||||
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
|
||||
#else
|
||||
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
|
||||
#endif
|
||||
|
||||
static void parse_params(int argc, char *argv[])
|
||||
{
|
||||
int option_index = 0;
|
||||
@@ -245,6 +253,7 @@ static void parse_params(int argc, char *argv[])
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
PRINT_VER;
|
||||
exithelp();
|
||||
break;
|
||||
case 2:
|
||||
|
40
ipset/get_antifilter_domains.sh
Normal file
40
ipset/get_antifilter_domains.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
TMPLIST="$TMPDIR/list.txt"
|
||||
|
||||
URL="https://antifilter.download/list/domains.lst"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -L -H "Accept-Encoding: gzip" -k --fail --max-time 60 --connect-timeout 10 --retry 4 --max-filesize 251658240 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcat "$TMPLIST" | tr -d '\015' | zz "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
# useful in case ipban set is used in custom scripts
|
||||
FAIL=
|
||||
getipban || FAIL=1
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
[ -n "$FAIL" ] && exit
|
||||
|
||||
dl "$URL" "$ZHOSTLIST" 32768 4194304
|
||||
|
||||
exit 0
|
12
mdig/mdig.c
12
mdig/mdig.c
@@ -35,7 +35,7 @@
|
||||
static void trimstr(char *s)
|
||||
{
|
||||
char *p;
|
||||
for (p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0';
|
||||
for (p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'); p--) *p = '\0';
|
||||
}
|
||||
|
||||
static const char* eai_str(int r)
|
||||
@@ -458,6 +458,15 @@ static void exithelp(void)
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
|
||||
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
|
||||
#else
|
||||
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int r, v, option_index = 0;
|
||||
@@ -487,6 +496,7 @@ int main(int argc, char **argv)
|
||||
switch (option_index)
|
||||
{
|
||||
case 0: /* help */
|
||||
PRINT_VER;
|
||||
exithelp();
|
||||
break;
|
||||
case 1: /* threads */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
CC ?= gcc
|
||||
CFLAGS += -std=gnu99 -Os
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member -flto=auto
|
||||
CFLAGS += -std=gnu99 -Os -flto=auto
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
|
||||
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
|
||||
LIBS_BSD = -lz
|
||||
|
116
nfq/desync.c
116
nfq/desync.c
@@ -1082,7 +1082,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
}
|
||||
|
||||
ttl_fake = (ctrack_replay && ctrack_replay->autottl) ? ctrack_replay->autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig));
|
||||
if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase) && HttpFindHost(&phost,dis->data_payload,dis->len_payload))
|
||||
if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase || dp->methodeol) && HttpFindHost(&phost,dis->data_payload,dis->len_payload))
|
||||
{
|
||||
if (dp->hostcase)
|
||||
{
|
||||
@@ -1098,23 +1098,40 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
verdict=VERDICT_MODIFY;
|
||||
}
|
||||
uint8_t *pua;
|
||||
if (dp->hostnospace &&
|
||||
(pua = (uint8_t*)memmem(dis->data_payload, dis->len_payload, "\r\nUser-Agent: ", 14)) &&
|
||||
(pua = (uint8_t*)memmem(pua + 1, dis->len_payload - (pua - dis->data_payload) - 1, "\r\n", 2)))
|
||||
if (dp->hostnospace)
|
||||
{
|
||||
DLOG("removing space after Host: and adding it to User-Agent:\n");
|
||||
if (pua > phost)
|
||||
if ((pua = (uint8_t*)memmem(dis->data_payload, dis->len_payload, "\r\nUser-Agent: ", 14)) &&
|
||||
(pua = (uint8_t*)memmem(pua + 1, dis->len_payload - (pua - dis->data_payload) - 1, "\r\n", 2)))
|
||||
{
|
||||
memmove(phost + 5, phost + 6, pua - phost - 6);
|
||||
pua[-1]=' ';
|
||||
DLOG("removing space after Host: and adding it to User-Agent:\n");
|
||||
if (pua > phost)
|
||||
{
|
||||
memmove(phost + 5, phost + 6, pua - phost - 6);
|
||||
pua[-1]=' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(pua + 1, pua, phost - pua + 5);
|
||||
*pua = ' ';
|
||||
}
|
||||
verdict=VERDICT_MODIFY;
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(pua + 1, pua, phost - pua + 5);
|
||||
*pua = ' ';
|
||||
}
|
||||
verdict=VERDICT_MODIFY;
|
||||
DLOG("cannot do hostnospace because valid User-Agent: not found\n");
|
||||
}
|
||||
else if (dp->methodeol)
|
||||
{
|
||||
if (phost[5]==' ' || phost[5]=='\t')
|
||||
{
|
||||
DLOG("removing space after Host: and adding '\\n' before method\n");
|
||||
memmove(dis->data_payload+1,dis->data_payload,phost-dis->data_payload+5);
|
||||
dis->data_payload[0]='\n';
|
||||
verdict=VERDICT_MODIFY;
|
||||
}
|
||||
else
|
||||
DLOG("cannot do methodeol because there's no space or tab after Host:\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (dp->desync_mode==DESYNC_NONE)
|
||||
@@ -1432,10 +1449,17 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
case DESYNC_FAKEDDISORDER:
|
||||
if (split_pos)
|
||||
{
|
||||
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg;
|
||||
size_t seg_len;
|
||||
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100], fakeseg2[DPI_DESYNC_MAX_FAKE_LEN+100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg;
|
||||
size_t seg_len,fakeseg2_len;
|
||||
unsigned int seqovl;
|
||||
|
||||
if (dis->len_payload > sizeof(pat))
|
||||
{
|
||||
DLOG("packet is too large\n");
|
||||
return verdict;
|
||||
}
|
||||
fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern));
|
||||
|
||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
||||
|
||||
if (seqovl_pos>=split_pos)
|
||||
@@ -1463,6 +1487,19 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
seg = dis->data_payload+split_pos;
|
||||
seg_len = dis->len_payload-split_pos;
|
||||
}
|
||||
|
||||
fakeseg2_len = sizeof(fakeseg2);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
pat+split_pos, dis->len_payload-split_pos, fakeseg2, &fakeseg2_len))
|
||||
return verdict;
|
||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
||||
DLOG("sending fake(1) 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
|
||||
hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg2, fakeseg2_len))
|
||||
return verdict;
|
||||
|
||||
pkt1_len = sizeof(pkt1);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq , split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
@@ -1475,15 +1512,23 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return verdict;
|
||||
|
||||
if (dis->ip) ((struct ip*)fakeseg2)->ip_id = ip_id;
|
||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
||||
|
||||
DLOG("sending fake(2) 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
|
||||
hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg2, fakeseg2_len))
|
||||
return verdict;
|
||||
|
||||
seg_len = sizeof(fakeseg);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
zeropkt, split_pos, fakeseg, &seg_len))
|
||||
pat, split_pos, fakeseg, &seg_len))
|
||||
return verdict;
|
||||
ip_id=IP4_IP_ID_PREV(ip_id);
|
||||
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len))
|
||||
return verdict;
|
||||
|
||||
@@ -1501,7 +1546,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
|
||||
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
||||
DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len))
|
||||
return verdict;
|
||||
|
||||
@@ -1511,20 +1556,27 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
case DESYNC_FAKEDSPLIT:
|
||||
if (split_pos)
|
||||
{
|
||||
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100],ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg;
|
||||
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100],ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100],pat[DPI_DESYNC_MAX_FAKE_LEN], *seg;
|
||||
size_t fakeseg_len,seg_len;
|
||||
|
||||
if (dis->len_payload > sizeof(pat))
|
||||
{
|
||||
DLOG("packet is too large\n");
|
||||
return verdict;
|
||||
}
|
||||
fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern));
|
||||
|
||||
ip_id = IP4_IP_ID_FIX(dis->ip);
|
||||
|
||||
fakeseg_len = sizeof(fakeseg);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
zeropkt, split_pos, fakeseg, &fakeseg_len))
|
||||
pat, split_pos, fakeseg, &fakeseg_len))
|
||||
return verdict;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
|
||||
return verdict;
|
||||
|
||||
@@ -1579,7 +1631,19 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
|
||||
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
|
||||
return verdict;
|
||||
|
||||
fakeseg_len = sizeof(fakeseg);
|
||||
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
|
||||
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
|
||||
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
pat+split_pos, dis->len_payload-split_pos, fakeseg, &fakeseg_len))
|
||||
return verdict;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
DLOG("sending fake(1) 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
|
||||
hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
|
||||
return verdict;
|
||||
|
||||
@@ -1589,11 +1653,19 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
|
||||
dis->data_payload+split_pos, dis->len_payload-split_pos, pkt1, &pkt1_len))
|
||||
return verdict;
|
||||
ip_id=IP4_IP_ID_NEXT(ip_id);
|
||||
DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
|
||||
hexdump_limited_dlog(dis->data_payload+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
|
||||
return verdict;
|
||||
|
||||
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
|
||||
|
||||
DLOG("sending fake(2) 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
|
||||
hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
|
||||
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
|
||||
return verdict;
|
||||
|
||||
return VERDICT_DROP;
|
||||
}
|
||||
break;
|
||||
|
@@ -24,7 +24,7 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
||||
*hostlist = NULL;
|
||||
return false;
|
||||
}
|
||||
(*ct)++;
|
||||
if (ct) (*ct)++;
|
||||
}
|
||||
// advance to the next line
|
||||
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
|
||||
@@ -32,6 +32,11 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AppendHostlistItem(strpool **hostlist, char *s)
|
||||
{
|
||||
return addpool(hostlist,&s,s+strlen(s),NULL);
|
||||
}
|
||||
|
||||
bool AppendHostList(strpool **hostlist, const char *filename)
|
||||
{
|
||||
char *p, *e, s[256], *zbuf;
|
||||
@@ -98,21 +103,24 @@ bool AppendHostList(strpool **hostlist, const char *filename)
|
||||
|
||||
static bool LoadHostList(struct hostlist_file *hfile)
|
||||
{
|
||||
time_t t = file_mod_time(hfile->filename);
|
||||
if (!t)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
if (t==hfile->mod_time) return true; // up to date
|
||||
StrPoolDestroy(&hfile->hostlist);
|
||||
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
||||
if (hfile->filename)
|
||||
{
|
||||
time_t t = file_mod_time(hfile->filename);
|
||||
if (!t)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
if (t==hfile->mod_time) return true; // up to date
|
||||
StrPoolDestroy(&hfile->hostlist);
|
||||
return false;
|
||||
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
||||
{
|
||||
StrPoolDestroy(&hfile->hostlist);
|
||||
return false;
|
||||
}
|
||||
hfile->mod_time=t;
|
||||
}
|
||||
hfile->mod_time=t;
|
||||
return true;
|
||||
}
|
||||
static bool LoadHostLists(struct hostlist_files_head *list)
|
||||
@@ -202,7 +210,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
|
||||
LIST_FOREACH(item, hostlists_exclude, next)
|
||||
{
|
||||
DLOG("[%s] exclude ", item->hfile->filename);
|
||||
DLOG("[%s] exclude ", item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchHostList(item->hfile->hostlist, host))
|
||||
{
|
||||
if (excluded) *excluded = true;
|
||||
@@ -214,7 +222,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
{
|
||||
LIST_FOREACH(item, hostlists, next)
|
||||
{
|
||||
DLOG("[%s] include ", item->hfile->filename);
|
||||
DLOG("[%s] include ", item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchHostList(item->hfile->hostlist, host))
|
||||
return true;
|
||||
}
|
||||
@@ -235,17 +243,29 @@ bool HostlistCheck(const struct desync_profile *dp, const char *host, bool *excl
|
||||
static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
|
||||
{
|
||||
struct hostlist_file *hfile;
|
||||
if (!(hfile=hostlist_files_search(hostlists, filename)))
|
||||
if (!(hfile=hostlist_files_add(hostlists, filename)))
|
||||
|
||||
if (filename)
|
||||
{
|
||||
if (!(hfile=hostlist_files_search(hostlists, filename)))
|
||||
if (!(hfile=hostlist_files_add(hostlists, filename)))
|
||||
return NULL;
|
||||
if (!hostlist_collection_search(hl_collection, filename))
|
||||
if (!hostlist_collection_add(hl_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(hfile=hostlist_files_add(hostlists, NULL)))
|
||||
return NULL;
|
||||
if (!hostlist_collection_search(hl_collection, filename))
|
||||
if (!hostlist_collection_add(hl_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hfile;
|
||||
}
|
||||
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
|
||||
{
|
||||
if (!file_mod_time(filename))
|
||||
if (filename && !file_mod_time(filename))
|
||||
{
|
||||
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
|
||||
return NULL;
|
||||
@@ -265,15 +285,30 @@ void HostlistsDebug()
|
||||
struct hostlist_item *hl_item;
|
||||
|
||||
LIST_FOREACH(hfile, ¶ms.hostlists, next)
|
||||
DLOG("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
|
||||
{
|
||||
if (hfile->filename)
|
||||
DLOG("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("hostlist fixed%s\n",hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
|
||||
if (hl_item->hfile!=dpl->dp.hostlist_auto)
|
||||
DLOG("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("profile %d include fixed hostlist%s\n",dpl->dp.n, hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next)
|
||||
DLOG("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("profile %d exclude fixed hostlist%s\n",dpl->dp.n,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
if (dpl->dp.hostlist_auto)
|
||||
DLOG("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include "pools.h"
|
||||
#include "params.h"
|
||||
|
||||
bool AppendHostlistItem(strpool **hostlist, char *s);
|
||||
bool AppendHostList(strpool **hostlist, const char *filename);
|
||||
bool LoadAllHostLists();
|
||||
bool NonEmptyHostlist(strpool **hostlist);
|
||||
|
75
nfq/ipset.c
75
nfq/ipset.c
@@ -31,7 +31,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
||||
ipsetDestroy(ips);
|
||||
return false;
|
||||
}
|
||||
(*ct)++;
|
||||
if (ct) (*ct)++;
|
||||
}
|
||||
else if (parse_cidr6(cidr,&c6))
|
||||
{
|
||||
@@ -40,7 +40,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
||||
ipsetDestroy(ips);
|
||||
return false;
|
||||
}
|
||||
(*ct)++;
|
||||
if (ct) (*ct)++;
|
||||
}
|
||||
else
|
||||
DLOG_ERR("bad ip or subnet : %s\n",cidr);
|
||||
@@ -53,6 +53,11 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
||||
|
||||
}
|
||||
|
||||
bool AppendIpsetItem(ipset *ips, char *ip)
|
||||
{
|
||||
return addpool(ips,&ip,ip+strlen(ip),NULL);
|
||||
}
|
||||
|
||||
static bool AppendIpset(ipset *ips, const char *filename)
|
||||
{
|
||||
char *p, *e, s[256], *zbuf;
|
||||
@@ -119,21 +124,24 @@ static bool AppendIpset(ipset *ips, const char *filename)
|
||||
|
||||
static bool LoadIpset(struct ipset_file *hfile)
|
||||
{
|
||||
time_t t = file_mod_time(hfile->filename);
|
||||
if (!t)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
if (t==hfile->mod_time) return true; // up to date
|
||||
ipsetDestroy(&hfile->ipset);
|
||||
if (!AppendIpset(&hfile->ipset, hfile->filename))
|
||||
if (hfile->filename)
|
||||
{
|
||||
time_t t = file_mod_time(hfile->filename);
|
||||
if (!t)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
if (t==hfile->mod_time) return true; // up to date
|
||||
ipsetDestroy(&hfile->ipset);
|
||||
return false;
|
||||
if (!AppendIpset(&hfile->ipset, hfile->filename))
|
||||
{
|
||||
ipsetDestroy(&hfile->ipset);
|
||||
return false;
|
||||
}
|
||||
hfile->mod_time=t;
|
||||
}
|
||||
hfile->mod_time=t;
|
||||
return true;
|
||||
}
|
||||
static bool LoadIpsets(struct ipset_files_head *list)
|
||||
@@ -205,7 +213,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
|
||||
|
||||
LIST_FOREACH(item, ips_exclude, next)
|
||||
{
|
||||
DLOG("[%s] exclude ",item->hfile->filename);
|
||||
DLOG("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
|
||||
return false;
|
||||
}
|
||||
@@ -214,7 +222,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
|
||||
{
|
||||
LIST_FOREACH(item, ips, next)
|
||||
{
|
||||
DLOG("[%s] include ",item->hfile->filename);
|
||||
DLOG("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
|
||||
return true;
|
||||
}
|
||||
@@ -234,17 +242,27 @@ bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, con
|
||||
static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
|
||||
{
|
||||
struct ipset_file *hfile;
|
||||
if (!(hfile=ipset_files_search(ipsets, filename)))
|
||||
if (!(hfile=ipset_files_add(ipsets, filename)))
|
||||
if (filename)
|
||||
{
|
||||
if (!(hfile=ipset_files_search(ipsets, filename)))
|
||||
if (!(hfile=ipset_files_add(ipsets, filename)))
|
||||
return NULL;
|
||||
if (!ipset_collection_search(ips_collection, filename))
|
||||
if (!ipset_collection_add(ips_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(hfile=ipset_files_add(ipsets, NULL)))
|
||||
return NULL;
|
||||
if (!ipset_collection_search(ips_collection, filename))
|
||||
if (!ipset_collection_add(ips_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
return hfile;
|
||||
}
|
||||
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename)
|
||||
{
|
||||
if (!file_mod_time(filename))
|
||||
if (filename && !file_mod_time(filename))
|
||||
{
|
||||
DLOG_ERR("cannot access ipset file '%s'\n",filename);
|
||||
return NULL;
|
||||
@@ -277,13 +295,24 @@ void IpsetsDebug()
|
||||
struct ipset_item *ips_item;
|
||||
|
||||
LIST_FOREACH(hfile, ¶ms.ipsets, next)
|
||||
DLOG("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
|
||||
{
|
||||
if (hfile->filename)
|
||||
DLOG("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
|
||||
else
|
||||
DLOG("ipset fixed (%s)\n",dbg_ipset_fill(&hfile->ipset));
|
||||
}
|
||||
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next)
|
||||
DLOG("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
if (ips_item->hfile->filename)
|
||||
DLOG("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
else
|
||||
DLOG("profile %d include fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next)
|
||||
DLOG("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
if (ips_item->hfile->filename)
|
||||
DLOG("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
else
|
||||
DLOG("profile %d exclude fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
}
|
||||
}
|
||||
|
@@ -9,3 +9,4 @@ bool LoadAllIpsets();
|
||||
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6);
|
||||
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
|
||||
void IpsetsDebug();
|
||||
bool AppendIpsetItem(ipset *ips, char *ip);
|
||||
|
487
nfq/nfqws.c
487
nfq/nfqws.c
@@ -836,6 +836,47 @@ static bool parse_split_pos_list(char *opt, struct proto_pos *splits, int splits
|
||||
if (p) return false; // too much splits
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_domain_list(char *opt, strpool **pp)
|
||||
{
|
||||
char *e,*p,c;
|
||||
|
||||
for (p=opt ; p ; )
|
||||
{
|
||||
if ((e = strchr(p,',')))
|
||||
{
|
||||
c=*e;
|
||||
*e=0;
|
||||
}
|
||||
|
||||
if (*p && !AppendHostlistItem(pp,p)) return false;
|
||||
|
||||
if (e) *e++=c;
|
||||
p = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_ip_list(char *opt, ipset *pp)
|
||||
{
|
||||
char *e,*p,c;
|
||||
|
||||
for (p=opt ; p ; )
|
||||
{
|
||||
if ((e = strchr(p,',')))
|
||||
{
|
||||
c=*e;
|
||||
*e=0;
|
||||
}
|
||||
|
||||
if (*p && !AppendIpsetItem(pp,p)) return false;
|
||||
|
||||
if (e) *e++=c;
|
||||
p = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void split_compat(struct desync_profile *dp)
|
||||
{
|
||||
if (!dp->split_count)
|
||||
@@ -989,6 +1030,7 @@ static void exithelp(void)
|
||||
" @<config_file>|$<config_file>\t\t\t; read file for options. must be the only argument. other options are ignored.\n\n"
|
||||
#endif
|
||||
" --debug=0|1|syslog|@<filename>\n"
|
||||
" --dry-run\t\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
||||
#ifdef __linux__
|
||||
" --qnum=<nfqueue_number>\n"
|
||||
#elif defined(BSD)
|
||||
@@ -1020,15 +1062,20 @@ static void exithelp(void)
|
||||
#endif
|
||||
"\nMULTI-STRATEGY:\n"
|
||||
" --new\t\t\t\t\t\t; begin new strategy\n"
|
||||
" --skip\t\t\t\t\t\t; do not use this strategy\n"
|
||||
" --filter-l3=ipv4|ipv6\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --filter-tcp=[~]port1[-port2]|*\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n"
|
||||
" --filter-udp=[~]port1[-port2]|*\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
|
||||
" --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --ipset=<filename>\t\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||
" --ipset-ip=<ip_list>\t\t\t\t; comma separated fixed subnet list\n"
|
||||
" --ipset-exclude=<filename>\t\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||
" --ipset-exclude-ip=<ip_list>\t\t\t; comma separated fixed subnet list\n"
|
||||
"\nHOSTLIST FILTER:\n"
|
||||
" --hostlist=<filename>\t\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-domains=<domain_list>\t\t; comma separated fixed domain list\n"
|
||||
" --hostlist-exclude=<filename>\t\t\t; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-exclude-domains=<domain_list>\t; comma separated fixed domain list\n"
|
||||
" --hostlist-auto=<filename>\t\t\t; detect DPI blocks and build hostlist automatically\n"
|
||||
" --hostlist-auto-fail-threshold=<int>\t\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
|
||||
" --hostlist-auto-fail-time=<int>\t\t; all failed attemps must be within these seconds (default : %d)\n"
|
||||
@@ -1042,6 +1089,7 @@ static void exithelp(void)
|
||||
" --hostspell\t\t\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
|
||||
" --hostnospace\t\t\t\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
|
||||
" --domcase\t\t\t\t\t; mix domain case : Host: TeSt.cOm\n"
|
||||
" --methodeol\t\t\t\t\t; add '\\n' before method and remove space from Host:\n"
|
||||
" --dpi-desync=[<mode0>,]<mode>[,<mode2>]\t; try to desync dpi state. modes :\n"
|
||||
"\t\t\t\t\t\t; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n"
|
||||
"\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper\n"
|
||||
@@ -1063,6 +1111,7 @@ static void exithelp(void)
|
||||
"\t\t\t\t\t\t; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise\n"
|
||||
" --dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment\n"
|
||||
" --dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap\n"
|
||||
" --dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder\n"
|
||||
" --dpi-desync-ipfrag-pos-tcp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
||||
" --dpi-desync-ipfrag-pos-udp=<8..%u>\t\t; ip frag position starting from the transport header. multiple of 8, default %u.\n"
|
||||
" --dpi-desync-badseq-increment=<int|0xHEX>\t; badseq fooling seq signed increment. default %d\n"
|
||||
@@ -1126,6 +1175,14 @@ void config_from_file(const char *filename)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
|
||||
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
|
||||
#else
|
||||
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
set_env_exedir(argv[0]);
|
||||
@@ -1139,8 +1196,10 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
int result, v;
|
||||
int option_index = 0;
|
||||
bool daemon = false;
|
||||
bool daemon = false, bSkip = false, bDry = false;
|
||||
char pidfile[256];
|
||||
struct hostlist_file *anon_hl = NULL, *anon_hl_exclude = NULL;
|
||||
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
|
||||
#ifdef __CYGWIN__
|
||||
char windivert_filter[8192], wf_pf_tcp_src[256], wf_pf_tcp_dst[256], wf_pf_udp_src[256], wf_pf_udp_dst[256], wf_save_file[256];
|
||||
bool wf_ipv4=true, wf_ipv6=true;
|
||||
@@ -1152,6 +1211,8 @@ int main(int argc, char **argv)
|
||||
srandom(time(NULL));
|
||||
mask_from_preflen6_prepare();
|
||||
|
||||
PRINT_VER;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
*pidfile = 0;
|
||||
|
||||
@@ -1203,101 +1264,113 @@ int main(int argc, char **argv)
|
||||
|
||||
const struct option long_options[] = {
|
||||
{"debug",optional_argument,0,0}, // optidx=0
|
||||
{"dry-run",no_argument,0,0}, // optidx=1
|
||||
#ifdef __linux__
|
||||
{"qnum",required_argument,0,0}, // optidx=1
|
||||
{"qnum",required_argument,0,0}, // optidx=2
|
||||
#elif defined(BSD)
|
||||
{"port",required_argument,0,0}, // optidx=1
|
||||
{"port",required_argument,0,0}, // optidx=2
|
||||
#else
|
||||
{"disabled_argument_1",no_argument,0,0},// optidx=1
|
||||
{"disabled_argument_1",no_argument,0,0},// optidx=2
|
||||
#endif
|
||||
{"daemon",no_argument,0,0}, // optidx=2
|
||||
{"pidfile",required_argument,0,0}, // optidx=3
|
||||
{"daemon",no_argument,0,0}, // optidx=3
|
||||
{"pidfile",required_argument,0,0}, // optidx=4
|
||||
#ifndef __CYGWIN__
|
||||
{"user",required_argument,0,0 }, // optidx=4
|
||||
{"uid",required_argument,0,0 }, // optidx=5
|
||||
{"user",required_argument,0,0 }, // optidx=5
|
||||
{"uid",required_argument,0,0 }, // optidx=6
|
||||
#else
|
||||
{"disabled_argument_2",no_argument,0,0}, // optidx=4
|
||||
{"disabled_argument_3",no_argument,0,0}, // optidx=5
|
||||
{"disabled_argument_2",no_argument,0,0}, // optidx=5
|
||||
{"disabled_argument_3",no_argument,0,0}, // optidx=6
|
||||
#endif
|
||||
{"wsize",required_argument,0,0}, // optidx=6
|
||||
{"wssize",required_argument,0,0}, // optidx=7
|
||||
{"wssize-cutoff",required_argument,0,0},// optidx=8
|
||||
{"ctrack-timeouts",required_argument,0,0},// optidx=9
|
||||
{"hostcase",no_argument,0,0}, // optidx=10
|
||||
{"hostspell",required_argument,0,0}, // optidx=11
|
||||
{"hostnospace",no_argument,0,0}, // optidx=12
|
||||
{"domcase",no_argument,0,0 }, // optidx=13
|
||||
{"dpi-desync",required_argument,0,0}, // optidx=14
|
||||
{"wsize",required_argument,0,0}, // optidx=7
|
||||
{"wssize",required_argument,0,0}, // optidx=8
|
||||
{"wssize-cutoff",required_argument,0,0},// optidx=9
|
||||
{"ctrack-timeouts",required_argument,0,0},// optidx=10
|
||||
{"hostcase",no_argument,0,0}, // optidx=11
|
||||
{"hostspell",required_argument,0,0}, // optidx=12
|
||||
{"hostnospace",no_argument,0,0}, // optidx=13
|
||||
{"domcase",no_argument,0,0 }, // optidx=14
|
||||
{"methodeol",no_argument,0,0 }, // optidx=15
|
||||
{"dpi-desync",required_argument,0,0}, // optidx=17
|
||||
#ifdef __linux__
|
||||
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=15
|
||||
{"dpi-desync-fwmark",required_argument,0,0}, // optidx=17
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=15
|
||||
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=17
|
||||
#else
|
||||
{"disabled_argument_4",no_argument,0,0}, // optidx=15
|
||||
{"disabled_argument_4",no_argument,0,0}, // optidx=17
|
||||
#endif
|
||||
{"dpi-desync-ttl",required_argument,0,0}, // optidx=16
|
||||
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=17
|
||||
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=18
|
||||
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=19
|
||||
{"dpi-desync-fooling",required_argument,0,0}, // optidx=20
|
||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=21
|
||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=22
|
||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=23
|
||||
{"dpi-desync-split-http-req",required_argument,0,0 },// optidx=24
|
||||
{"dpi-desync-split-tls",required_argument,0,0 },// optidx=25
|
||||
{"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=26
|
||||
{"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=27
|
||||
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=28
|
||||
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=29
|
||||
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=30
|
||||
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=31
|
||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=32
|
||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=33
|
||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=34
|
||||
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=35
|
||||
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=36
|
||||
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=37
|
||||
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=38
|
||||
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=39
|
||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=40
|
||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=41
|
||||
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=42
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=43
|
||||
{"dpi-desync-start",required_argument,0,0},// optidx=43
|
||||
{"hostlist",required_argument,0,0}, // optidx=44
|
||||
{"hostlist-exclude",required_argument,0,0}, // optidx=45
|
||||
{"hostlist-auto",required_argument,0,0}, // optidx=46
|
||||
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=48
|
||||
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=49
|
||||
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=50
|
||||
{"hostlist-auto-debug",required_argument,0,0}, // optidx=51
|
||||
{"new",no_argument,0,0}, // optidx=52
|
||||
{"filter-l3",required_argument,0,0}, // optidx=53
|
||||
{"filter-tcp",required_argument,0,0}, // optidx=54
|
||||
{"filter-udp",required_argument,0,0}, // optidx=55
|
||||
{"filter-l7",required_argument,0,0}, // optidx=56
|
||||
{"ipset",required_argument,0,0}, // optidx=57
|
||||
{"ipset-exclude",required_argument,0,0},// optidx=58
|
||||
{"dpi-desync-ttl",required_argument,0,0}, // optidx=18
|
||||
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=19
|
||||
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=20
|
||||
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=21
|
||||
{"dpi-desync-fooling",required_argument,0,0}, // optidx=22
|
||||
{"dpi-desync-repeats",required_argument,0,0}, // optidx=23
|
||||
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=24
|
||||
{"dpi-desync-split-pos",required_argument,0,0},// optidx=25
|
||||
{"dpi-desync-split-http-req",required_argument,0,0 },// optidx=26
|
||||
{"dpi-desync-split-tls",required_argument,0,0 },// optidx=27
|
||||
{"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=28
|
||||
{"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=29
|
||||
{"dpi-desync-fakedsplit-pattern",required_argument,0,0 },// optidx=30
|
||||
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=31
|
||||
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=32
|
||||
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=33
|
||||
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=34
|
||||
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=35
|
||||
{"dpi-desync-fake-http",required_argument,0,0},// optidx=36
|
||||
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=37
|
||||
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=38
|
||||
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=39
|
||||
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=40
|
||||
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=41
|
||||
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=42
|
||||
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=43
|
||||
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=44
|
||||
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=45
|
||||
{"dpi-desync-cutoff",required_argument,0,0},// optidx=46
|
||||
{"dpi-desync-start",required_argument,0,0},// optidx=47
|
||||
{"hostlist",required_argument,0,0}, // optidx=48
|
||||
{"hostlist-domains",required_argument,0,0},// optidx=49
|
||||
{"hostlist-exclude",required_argument,0,0}, // optidx=50
|
||||
{"hostlist-exclude-domains",required_argument,0,0},// optidx=51
|
||||
{"hostlist-auto",required_argument,0,0}, // optidx=52
|
||||
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=53
|
||||
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=54
|
||||
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=55
|
||||
{"hostlist-auto-debug",required_argument,0,0}, // optidx=56
|
||||
{"new",no_argument,0,0}, // optidx=57
|
||||
{"skip",no_argument,0,0}, // optidx=58
|
||||
{"filter-l3",required_argument,0,0}, // optidx=59
|
||||
{"filter-tcp",required_argument,0,0}, // optidx=60
|
||||
{"filter-udp",required_argument,0,0}, // optidx=61
|
||||
{"filter-l7",required_argument,0,0}, // optidx=62
|
||||
{"ipset",required_argument,0,0}, // optidx=63
|
||||
{"ipset-ip",required_argument,0,0}, // optidx=64
|
||||
{"ipset-exclude",required_argument,0,0},// optidx=65
|
||||
{"ipset-exclude-ip",required_argument,0,0}, // optidx=66
|
||||
#ifdef __linux__
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=59
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=60
|
||||
{"bind-fix4",no_argument,0,0}, // optidx=67
|
||||
{"bind-fix6",no_argument,0,0}, // optidx=68
|
||||
#elif defined(__CYGWIN__)
|
||||
{"wf-iface",required_argument,0,0}, // optidx=59
|
||||
{"wf-l3",required_argument,0,0}, // optidx=60
|
||||
{"wf-tcp",required_argument,0,0}, // optidx=61
|
||||
{"wf-udp",required_argument,0,0}, // optidx=62
|
||||
{"wf-raw",required_argument,0,0}, // optidx=63
|
||||
{"wf-save",required_argument,0,0}, // optidx=64
|
||||
{"ssid-filter",required_argument,0,0}, // optidx=65
|
||||
{"nlm-filter",required_argument,0,0}, // optidx=66
|
||||
{"nlm-list",optional_argument,0,0}, // optidx=67
|
||||
{"wf-iface",required_argument,0,0}, // optidx=67
|
||||
{"wf-l3",required_argument,0,0}, // optidx=68
|
||||
{"wf-tcp",required_argument,0,0}, // optidx=69
|
||||
{"wf-udp",required_argument,0,0}, // optidx=70
|
||||
{"wf-raw",required_argument,0,0}, // optidx=71
|
||||
{"wf-save",required_argument,0,0}, // optidx=72
|
||||
{"ssid-filter",required_argument,0,0}, // optidx=73
|
||||
{"nlm-filter",required_argument,0,0}, // optidx=74
|
||||
{"nlm-list",optional_argument,0,0}, // optidx=75
|
||||
#endif
|
||||
{NULL,0,NULL,0}
|
||||
};
|
||||
if (argc < 2) exithelp();
|
||||
if (argc < 2) exithelp_clean();
|
||||
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
|
||||
{
|
||||
if (v) exithelp();
|
||||
if (v)
|
||||
if (bDry)
|
||||
exit_clean(1);
|
||||
else
|
||||
exithelp_clean();
|
||||
switch (option_index)
|
||||
{
|
||||
case 0: /* debug */
|
||||
@@ -1335,7 +1408,10 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
#ifndef __CYGWIN__
|
||||
case 1: /* qnum or port */
|
||||
case 1: /* dry-run */
|
||||
bDry=true;
|
||||
break;
|
||||
case 2: /* qnum or port */
|
||||
#ifdef __linux__
|
||||
params.qnum = atoi(optarg);
|
||||
if (params.qnum < 0 || params.qnum>65535)
|
||||
@@ -1356,15 +1432,15 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
case 2: /* daemon */
|
||||
case 3: /* daemon */
|
||||
daemon = true;
|
||||
break;
|
||||
case 3: /* pidfile */
|
||||
case 4: /* pidfile */
|
||||
strncpy(pidfile, optarg, sizeof(pidfile));
|
||||
pidfile[sizeof(pidfile) - 1] = '\0';
|
||||
break;
|
||||
#ifndef __CYGWIN__
|
||||
case 4: /* user */
|
||||
case 5: /* user */
|
||||
{
|
||||
struct passwd *pwd = getpwnam(optarg);
|
||||
if (!pwd)
|
||||
@@ -1377,7 +1453,7 @@ int main(int argc, char **argv)
|
||||
params.droproot = true;
|
||||
break;
|
||||
}
|
||||
case 5: /* uid */
|
||||
case 6: /* uid */
|
||||
params.gid = 0x7FFFFFFF; // default gid. drop gid=0
|
||||
params.droproot = true;
|
||||
if (sscanf(optarg, "%u:%u", ¶ms.uid, ¶ms.gid)<1)
|
||||
@@ -1387,32 +1463,32 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 6: /* wsize */
|
||||
case 7: /* wsize */
|
||||
if (!parse_ws_scale_factor(optarg,&dp->wsize,&dp->wscale))
|
||||
exit_clean(1);
|
||||
break;
|
||||
case 7: /* wssize */
|
||||
case 8: /* wssize */
|
||||
if (!parse_ws_scale_factor(optarg,&dp->wssize,&dp->wsscale))
|
||||
exit_clean(1);
|
||||
break;
|
||||
case 8: /* wssize-cutoff */
|
||||
case 9: /* wssize-cutoff */
|
||||
if (!parse_cutoff(optarg, &dp->wssize_cutoff, &dp->wssize_cutoff_mode))
|
||||
{
|
||||
DLOG_ERR("invalid wssize-cutoff value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 9: /* ctrack-timeouts */
|
||||
case 10: /* ctrack-timeouts */
|
||||
if (sscanf(optarg, "%u:%u:%u:%u", ¶ms.ctrack_t_syn, ¶ms.ctrack_t_est, ¶ms.ctrack_t_fin, ¶ms.ctrack_t_udp)<3)
|
||||
{
|
||||
DLOG_ERR("invalid ctrack-timeouts value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 10: /* hostcase */
|
||||
case 11: /* hostcase */
|
||||
dp->hostcase = true;
|
||||
break;
|
||||
case 11: /* hostspell */
|
||||
case 12: /* hostspell */
|
||||
if (strlen(optarg) != 4)
|
||||
{
|
||||
DLOG_ERR("hostspell must be exactly 4 chars long\n");
|
||||
@@ -1421,13 +1497,26 @@ int main(int argc, char **argv)
|
||||
dp->hostcase = true;
|
||||
memcpy(dp->hostspell, optarg, 4);
|
||||
break;
|
||||
case 12: /* hostnospace */
|
||||
case 13: /* hostnospace */
|
||||
if (dp->methodeol)
|
||||
{
|
||||
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp->hostnospace = true;
|
||||
break;
|
||||
case 13: /* domcase */
|
||||
case 14: /* domcase */
|
||||
dp->domcase = true;
|
||||
break;
|
||||
case 14: /* dpi-desync */
|
||||
case 15: /* methodeol */
|
||||
if (dp->hostnospace)
|
||||
{
|
||||
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp->methodeol = true;
|
||||
break;
|
||||
case 16: /* dpi-desync */
|
||||
{
|
||||
char *mode=optarg,*mode2,*mode3;
|
||||
mode2 = mode ? strchr(mode,',') : NULL;
|
||||
@@ -1473,7 +1562,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
#ifndef __CYGWIN__
|
||||
case 15: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
||||
case 17: /* dpi-desync-fwmark/dpi-desync-sockarg */
|
||||
#if defined(__linux__) || defined(SO_USER_COOKIE)
|
||||
params.desync_fwmark = 0;
|
||||
if (sscanf(optarg, "0x%X", ¶ms.desync_fwmark)<=0) sscanf(optarg, "%u", ¶ms.desync_fwmark);
|
||||
@@ -1488,27 +1577,27 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
case 16: /* dpi-desync-ttl */
|
||||
case 18: /* dpi-desync-ttl */
|
||||
dp->desync_ttl = (uint8_t)atoi(optarg);
|
||||
break;
|
||||
case 17: /* dpi-desync-ttl6 */
|
||||
case 19: /* dpi-desync-ttl6 */
|
||||
dp->desync_ttl6 = (uint8_t)atoi(optarg);
|
||||
break;
|
||||
case 18: /* dpi-desync-autottl */
|
||||
case 20: /* dpi-desync-autottl */
|
||||
if (!parse_autottl(optarg, &dp->desync_autottl))
|
||||
{
|
||||
DLOG_ERR("dpi-desync-autottl value error\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 19: /* dpi-desync-autottl6 */
|
||||
case 21: /* dpi-desync-autottl6 */
|
||||
if (!parse_autottl(optarg, &dp->desync_autottl6))
|
||||
{
|
||||
DLOG_ERR("dpi-desync-autottl6 value error\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 20: /* dpi-desync-fooling */
|
||||
case 22: /* dpi-desync-fooling */
|
||||
{
|
||||
char *e,*p = optarg;
|
||||
while (p)
|
||||
@@ -1543,17 +1632,17 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 21: /* dpi-desync-repeats */
|
||||
case 23: /* dpi-desync-repeats */
|
||||
if (sscanf(optarg,"%u",&dp->desync_repeats)<1 || !dp->desync_repeats || dp->desync_repeats>20)
|
||||
{
|
||||
DLOG_ERR("dpi-desync-repeats must be within 1..20\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 22: /* dpi-desync-skip-nosni */
|
||||
case 24: /* dpi-desync-skip-nosni */
|
||||
dp->desync_skip_nosni = !optarg || atoi(optarg);
|
||||
break;
|
||||
case 23: /* dpi-desync-split-pos */
|
||||
case 25: /* dpi-desync-split-pos */
|
||||
{
|
||||
int ct;
|
||||
if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&ct))
|
||||
@@ -1564,7 +1653,7 @@ int main(int argc, char **argv)
|
||||
dp->split_count += ct;
|
||||
}
|
||||
break;
|
||||
case 24: /* dpi-desync-split-http-req */
|
||||
case 26: /* dpi-desync-split-http-req */
|
||||
// obsolete arg
|
||||
DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS);
|
||||
if (dp->split_count>=MAX_SPLITS)
|
||||
@@ -1579,7 +1668,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
dp->split_count++;
|
||||
break;
|
||||
case 25: /* dpi-desync-split-tls */
|
||||
case 27: /* dpi-desync-split-tls */
|
||||
// obsolete arg
|
||||
DLOG_CONDUP("WARNING ! --dpi-desync-split-tls is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS);
|
||||
if (dp->split_count>=MAX_SPLITS)
|
||||
@@ -1594,7 +1683,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
dp->split_count++;
|
||||
break;
|
||||
case 26: /* dpi-desync-split-seqovl */
|
||||
case 28: /* dpi-desync-split-seqovl */
|
||||
if (!strcmp(optarg,"0"))
|
||||
{
|
||||
// allow zero = disable seqovl
|
||||
@@ -1607,7 +1696,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 27: /* dpi-desync-split-seqovl-pattern */
|
||||
case 29: /* dpi-desync-split-seqovl-pattern */
|
||||
{
|
||||
char buf[sizeof(dp->seqovl_pattern)];
|
||||
size_t sz=sizeof(buf);
|
||||
@@ -1615,7 +1704,15 @@ int main(int argc, char **argv)
|
||||
fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz);
|
||||
}
|
||||
break;
|
||||
case 28: /* dpi-desync-ipfrag-pos-tcp */
|
||||
case 30: /* dpi-desync-fakedsplit-pattern */
|
||||
{
|
||||
char buf[sizeof(dp->fsplit_pattern)];
|
||||
size_t sz=sizeof(buf);
|
||||
load_file_or_exit(optarg,buf,&sz);
|
||||
fill_pattern(dp->fsplit_pattern,sizeof(dp->fsplit_pattern),buf,sz);
|
||||
}
|
||||
break;
|
||||
case 31: /* dpi-desync-ipfrag-pos-tcp */
|
||||
if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_tcp)<1 || dp->desync_ipfrag_pos_tcp<1 || dp->desync_ipfrag_pos_tcp>DPI_DESYNC_MAX_FAKE_LEN)
|
||||
{
|
||||
DLOG_ERR("dpi-desync-ipfrag-pos-tcp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||
@@ -1627,7 +1724,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 29: /* dpi-desync-ipfrag-pos-udp */
|
||||
case 32: /* dpi-desync-ipfrag-pos-udp */
|
||||
if (sscanf(optarg,"%u",&dp->desync_ipfrag_pos_udp)<1 || dp->desync_ipfrag_pos_udp<1 || dp->desync_ipfrag_pos_udp>DPI_DESYNC_MAX_FAKE_LEN)
|
||||
{
|
||||
DLOG_ERR("dpi-desync-ipfrag-pos-udp must be within 1..%u range\n",DPI_DESYNC_MAX_FAKE_LEN);
|
||||
@@ -1639,63 +1736,63 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 30: /* dpi-desync-badseq-increments */
|
||||
case 33: /* dpi-desync-badseq-increments */
|
||||
if (!parse_badseq_increment(optarg,&dp->desync_badseq_increment))
|
||||
{
|
||||
DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 31: /* dpi-desync-badack-increment */
|
||||
case 34: /* dpi-desync-badack-increment */
|
||||
if (!parse_badseq_increment(optarg,&dp->desync_badseq_ack_increment))
|
||||
{
|
||||
DLOG_ERR("dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 32: /* dpi-desync-any-protocol */
|
||||
case 35: /* dpi-desync-any-protocol */
|
||||
dp->desync_any_proto = !optarg || atoi(optarg);
|
||||
break;
|
||||
case 33: /* dpi-desync-fake-http */
|
||||
case 36: /* dpi-desync-fake-http */
|
||||
dp->fake_http_size = sizeof(dp->fake_http);
|
||||
load_file_or_exit(optarg,dp->fake_http,&dp->fake_http_size);
|
||||
break;
|
||||
case 34: /* dpi-desync-fake-tls */
|
||||
case 37: /* dpi-desync-fake-tls */
|
||||
dp->fake_tls_size = sizeof(dp->fake_tls);
|
||||
load_file_or_exit(optarg,dp->fake_tls,&dp->fake_tls_size);
|
||||
break;
|
||||
case 35: /* dpi-desync-fake-unknown */
|
||||
case 38: /* dpi-desync-fake-unknown */
|
||||
dp->fake_unknown_size = sizeof(dp->fake_unknown);
|
||||
load_file_or_exit(optarg,dp->fake_unknown,&dp->fake_unknown_size);
|
||||
break;
|
||||
case 36: /* dpi-desync-fake-syndata */
|
||||
case 39: /* dpi-desync-fake-syndata */
|
||||
dp->fake_syndata_size = sizeof(dp->fake_syndata);
|
||||
load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size);
|
||||
break;
|
||||
case 37: /* dpi-desync-fake-quic */
|
||||
case 40: /* dpi-desync-fake-quic */
|
||||
dp->fake_quic_size = sizeof(dp->fake_quic);
|
||||
load_file_or_exit(optarg,dp->fake_quic,&dp->fake_quic_size);
|
||||
break;
|
||||
case 38: /* dpi-desync-fake-wireguard */
|
||||
case 41: /* dpi-desync-fake-wireguard */
|
||||
dp->fake_wg_size = sizeof(dp->fake_wg);
|
||||
load_file_or_exit(optarg,dp->fake_wg,&dp->fake_wg_size);
|
||||
break;
|
||||
case 39: /* dpi-desync-fake-dht */
|
||||
case 42: /* dpi-desync-fake-dht */
|
||||
dp->fake_dht_size = sizeof(dp->fake_dht);
|
||||
load_file_or_exit(optarg,dp->fake_dht,&dp->fake_dht_size);
|
||||
break;
|
||||
case 40: /* dpi-desync-fake-unknown-udp */
|
||||
case 43: /* dpi-desync-fake-unknown-udp */
|
||||
dp->fake_unknown_udp_size = sizeof(dp->fake_unknown_udp);
|
||||
load_file_or_exit(optarg,dp->fake_unknown_udp,&dp->fake_unknown_udp_size);
|
||||
break;
|
||||
case 41: /* dpi-desync-udplen-increment */
|
||||
case 44: /* dpi-desync-udplen-increment */
|
||||
if (sscanf(optarg,"%d",&dp->udplen_increment)<1 || dp->udplen_increment>0x7FFF || dp->udplen_increment<-0x8000)
|
||||
{
|
||||
DLOG_ERR("dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 42: /* dpi-desync-udplen-pattern */
|
||||
case 45: /* dpi-desync-udplen-pattern */
|
||||
{
|
||||
char buf[sizeof(dp->udplen_pattern)];
|
||||
size_t sz=sizeof(buf);
|
||||
@@ -1703,35 +1800,64 @@ int main(int argc, char **argv)
|
||||
fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz);
|
||||
}
|
||||
break;
|
||||
case 43: /* desync-cutoff */
|
||||
case 46: /* desync-cutoff */
|
||||
if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode))
|
||||
{
|
||||
DLOG_ERR("invalid desync-cutoff value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 44: /* desync-start */
|
||||
case 47: /* desync-start */
|
||||
if (!parse_cutoff(optarg, &dp->desync_start, &dp->desync_start_mode))
|
||||
{
|
||||
DLOG_ERR("invalid desync-start value\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 45: /* hostlist */
|
||||
case 48: /* hostlist */
|
||||
if (bSkip) break;
|
||||
if (!RegisterHostlist(dp, false, optarg))
|
||||
{
|
||||
DLOG_ERR("failed to register hostlist '%s'\n", optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 46: /* hostlist-exclude */
|
||||
case 49: /* hostlist-domains */
|
||||
if (bSkip) break;
|
||||
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
|
||||
{
|
||||
DLOG_ERR("failed to register anonymous hostlist\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!parse_domain_list(optarg, &anon_hl->hostlist))
|
||||
{
|
||||
DLOG_ERR("failed to add domains to anonymous hostlist\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 50: /* hostlist-exclude */
|
||||
if (bSkip) break;
|
||||
if (!RegisterHostlist(dp, true, optarg))
|
||||
{
|
||||
DLOG_ERR("failed to register hostlist '%s'\n", optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 47: /* hostlist-auto */
|
||||
case 51: /* hostlist-exclude-domains */
|
||||
if (bSkip) break;
|
||||
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
|
||||
{
|
||||
DLOG_ERR("failed to register anonymous hostlist\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!parse_domain_list(optarg, &anon_hl_exclude->hostlist))
|
||||
{
|
||||
DLOG_ERR("failed to add domains to anonymous hostlist\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 52: /* hostlist-auto */
|
||||
if (bSkip) break;
|
||||
if (dp->hostlist_auto)
|
||||
{
|
||||
DLOG_ERR("only one auto hostlist per profile is supported\n");
|
||||
@@ -1758,7 +1884,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 48: /* hostlist-auto-fail-threshold */
|
||||
case 53: /* hostlist-auto-fail-threshold */
|
||||
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
|
||||
{
|
||||
@@ -1766,7 +1892,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 49: /* hostlist-auto-fail-time */
|
||||
case 54: /* hostlist-auto-fail-time */
|
||||
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_time<1)
|
||||
{
|
||||
@@ -1774,7 +1900,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 50: /* hostlist-auto-retrans-threshold */
|
||||
case 55: /* hostlist-auto-retrans-threshold */
|
||||
dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10)
|
||||
{
|
||||
@@ -1782,7 +1908,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 51: /* hostlist-auto-debug */
|
||||
case 56: /* hostlist-auto-debug */
|
||||
{
|
||||
FILE *F = fopen(optarg,"a+t");
|
||||
if (!F)
|
||||
@@ -1796,23 +1922,39 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
|
||||
case 52: /* new */
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
case 57: /* new */
|
||||
if (bSkip)
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
exit_clean(1);
|
||||
dp_clear(dp);
|
||||
dp_init(dp);
|
||||
dp->n = desync_profile_count;
|
||||
bSkip = false;
|
||||
}
|
||||
dp = &dpl->dp;
|
||||
dp->n = ++desync_profile_count;
|
||||
else
|
||||
{
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp = &dpl->dp;
|
||||
dp->n = ++desync_profile_count;
|
||||
}
|
||||
anon_hl = anon_hl_exclude = NULL;
|
||||
anon_ips = anon_ips_exclude = NULL;
|
||||
break;
|
||||
case 53: /* filter-l3 */
|
||||
case 58: /* skip */
|
||||
bSkip = true;
|
||||
break;
|
||||
|
||||
case 59: /* filter-l3 */
|
||||
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
||||
{
|
||||
DLOG_ERR("bad value for --filter-l3\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 54: /* filter-tcp */
|
||||
case 60: /* filter-tcp */
|
||||
if (!parse_pf_list(optarg,&dp->pf_tcp))
|
||||
{
|
||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||
@@ -1822,7 +1964,7 @@ int main(int argc, char **argv)
|
||||
if (!port_filters_deny_if_empty(&dp->pf_udp))
|
||||
exit_clean(1);
|
||||
break;
|
||||
case 55: /* filter-udp */
|
||||
case 61: /* filter-udp */
|
||||
if (!parse_pf_list(optarg,&dp->pf_udp))
|
||||
{
|
||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||
@@ -1832,53 +1974,80 @@ int main(int argc, char **argv)
|
||||
if (!port_filters_deny_if_empty(&dp->pf_tcp))
|
||||
exit_clean(1);
|
||||
break;
|
||||
case 56: /* filter-l7 */
|
||||
case 62: /* filter-l7 */
|
||||
if (!parse_l7_list(optarg,&dp->filter_l7))
|
||||
{
|
||||
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 57: /* ipset */
|
||||
case 63: /* ipset */
|
||||
if (bSkip) break;
|
||||
if (!RegisterIpset(dp, false, optarg))
|
||||
{
|
||||
DLOG_ERR("failed to register ipset '%s'\n", optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 58: /* ipset-exclude */
|
||||
case 64: /* ipset-ip */
|
||||
if (bSkip) break;
|
||||
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
|
||||
{
|
||||
DLOG_ERR("failed to register anonymous ipset\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!parse_ip_list(optarg, &anon_ips->ipset))
|
||||
{
|
||||
DLOG_ERR("failed to add subnets to anonymous ipset\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 65: /* ipset-exclude */
|
||||
if (bSkip) break;
|
||||
if (!RegisterIpset(dp, true, optarg))
|
||||
{
|
||||
DLOG_ERR("failed to register ipset '%s'\n", optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 66: /* ipset-exclude-ip */
|
||||
if (bSkip) break;
|
||||
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
|
||||
{
|
||||
DLOG_ERR("failed to register anonymous ipset\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!parse_ip_list(optarg, &anon_ips_exclude->ipset))
|
||||
{
|
||||
DLOG_ERR("failed to add subnets to anonymous ipset\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
case 59: /* bind-fix4 */
|
||||
case 67: /* bind-fix4 */
|
||||
params.bind_fix4 = true;
|
||||
break;
|
||||
case 60: /* bind-fix6 */
|
||||
case 68: /* bind-fix6 */
|
||||
params.bind_fix6 = true;
|
||||
break;
|
||||
#elif defined(__CYGWIN__)
|
||||
case 59: /* wf-iface */
|
||||
case 67: /* wf-iface */
|
||||
if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx))
|
||||
{
|
||||
DLOG_ERR("bad value for --wf-iface\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 60: /* wf-l3 */
|
||||
case 68: /* wf-l3 */
|
||||
if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6))
|
||||
{
|
||||
DLOG_ERR("bad value for --wf-l3\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 61: /* wf-tcp */
|
||||
case 69: /* wf-tcp */
|
||||
hash_wf_tcp=hash_jen(optarg,strlen(optarg));
|
||||
if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) ||
|
||||
!wf_make_pf(optarg,"tcp","DstPort",wf_pf_tcp_dst,sizeof(wf_pf_tcp_dst)))
|
||||
@@ -1887,7 +2056,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 62: /* wf-udp */
|
||||
case 70: /* wf-udp */
|
||||
hash_wf_udp=hash_jen(optarg,strlen(optarg));
|
||||
if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) ||
|
||||
!wf_make_pf(optarg,"udp","DstPort",wf_pf_udp_dst,sizeof(wf_pf_udp_dst)))
|
||||
@@ -1896,7 +2065,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 63: /* wf-raw */
|
||||
case 71: /* wf-raw */
|
||||
hash_wf_raw=hash_jen(optarg,strlen(optarg));
|
||||
if (optarg[0]=='@')
|
||||
{
|
||||
@@ -1910,11 +2079,11 @@ int main(int argc, char **argv)
|
||||
windivert_filter[sizeof(windivert_filter) - 1] = '\0';
|
||||
}
|
||||
break;
|
||||
case 64: /* wf-save */
|
||||
case 72: /* wf-save */
|
||||
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
|
||||
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
|
||||
break;
|
||||
case 65: /* ssid-filter */
|
||||
case 73: /* ssid-filter */
|
||||
hash_ssid_filter=hash_jen(optarg,strlen(optarg));
|
||||
{
|
||||
char *e,*p = optarg;
|
||||
@@ -1932,7 +2101,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 66: /* nlm-filter */
|
||||
case 74: /* nlm-filter */
|
||||
hash_nlm_filter=hash_jen(optarg,strlen(optarg));
|
||||
{
|
||||
char *e,*p = optarg;
|
||||
@@ -1950,7 +2119,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 67: /* nlm-list */
|
||||
case 75: /* nlm-list */
|
||||
if (!nlm_list(optarg && !strcmp(optarg,"all")))
|
||||
{
|
||||
DLOG_ERR("could not get list of NLM networks\n");
|
||||
@@ -1961,6 +2130,12 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (bSkip)
|
||||
{
|
||||
LIST_REMOVE(dpl,next);
|
||||
dp_entry_destroy(dpl);
|
||||
desync_profile_count--;
|
||||
}
|
||||
|
||||
// do not need args from file anymore
|
||||
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
||||
@@ -2076,6 +2251,12 @@ int main(int argc, char **argv)
|
||||
SplitDebug();
|
||||
DLOG("\n");
|
||||
|
||||
if (bDry)
|
||||
{
|
||||
DLOG_CONDUP("command line parameters verified\n");
|
||||
exit_clean(0);
|
||||
}
|
||||
|
||||
if (daemon) daemonize();
|
||||
|
||||
if (*pidfile && !writepid(pidfile))
|
||||
|
97
nfq/params.c
97
nfq/params.c
@@ -170,45 +170,49 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
|
||||
if (bcut) DLOG(" ...");
|
||||
}
|
||||
|
||||
void dp_init(struct desync_profile *dp)
|
||||
{
|
||||
LIST_INIT(&dp->hl_collection);
|
||||
LIST_INIT(&dp->hl_collection_exclude);
|
||||
LIST_INIT(&dp->ips_collection);
|
||||
LIST_INIT(&dp->ips_collection_exclude);
|
||||
LIST_INIT(&dp->pf_tcp);
|
||||
LIST_INIT(&dp->pf_udp);
|
||||
|
||||
memcpy(dp->hostspell, "host", 4); // default hostspell
|
||||
dp->desync_skip_nosni = true;
|
||||
dp->desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT;
|
||||
dp->desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT;
|
||||
dp->desync_repeats = 1;
|
||||
dp->fake_tls_size = sizeof(fake_tls_clienthello_default);
|
||||
memcpy(dp->fake_tls,fake_tls_clienthello_default,dp->fake_tls_size);
|
||||
randomize_default_tls_payload(dp->fake_tls);
|
||||
dp->fake_http_size = strlen(fake_http_request_default);
|
||||
memcpy(dp->fake_http,fake_http_request_default,dp->fake_http_size);
|
||||
dp->fake_quic_size = 620; // must be 601+ for TSPU hack
|
||||
dp->fake_quic[0] = 0x40; // russian TSPU QUIC short header fake
|
||||
dp->fake_wg_size = 64;
|
||||
dp->fake_dht_size = 64;
|
||||
dp->fake_unknown_size = 256;
|
||||
dp->fake_syndata_size = 16;
|
||||
dp->fake_unknown_udp_size = 64;
|
||||
dp->wscale=-1; // default - dont change scale factor (client)
|
||||
dp->desync_ttl6 = 0xFF; // unused
|
||||
dp->desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
|
||||
dp->desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
|
||||
dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = 'n'; // packet number by default
|
||||
dp->udplen_increment = UDPLEN_INCREMENT_DEFAULT;
|
||||
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
||||
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
|
||||
dp->filter_ipv4 = dp->filter_ipv6 = true;
|
||||
}
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
||||
{
|
||||
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
|
||||
if (!entry) return NULL;
|
||||
|
||||
LIST_INIT(&entry->dp.hl_collection);
|
||||
LIST_INIT(&entry->dp.hl_collection_exclude);
|
||||
LIST_INIT(&entry->dp.ips_collection);
|
||||
LIST_INIT(&entry->dp.ips_collection_exclude);
|
||||
LIST_INIT(&entry->dp.pf_tcp);
|
||||
LIST_INIT(&entry->dp.pf_udp);
|
||||
|
||||
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
|
||||
entry->dp.desync_skip_nosni = true;
|
||||
entry->dp.desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT;
|
||||
entry->dp.desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT;
|
||||
entry->dp.desync_repeats = 1;
|
||||
entry->dp.fake_tls_size = sizeof(fake_tls_clienthello_default);
|
||||
memcpy(entry->dp.fake_tls,fake_tls_clienthello_default,entry->dp.fake_tls_size);
|
||||
randomize_default_tls_payload(entry->dp.fake_tls);
|
||||
entry->dp.fake_http_size = strlen(fake_http_request_default);
|
||||
memcpy(entry->dp.fake_http,fake_http_request_default,entry->dp.fake_http_size);
|
||||
entry->dp.fake_quic_size = 620; // must be 601+ for TSPU hack
|
||||
entry->dp.fake_quic[0] = 0x40; // russian TSPU QUIC short header fake
|
||||
entry->dp.fake_wg_size = 64;
|
||||
entry->dp.fake_dht_size = 64;
|
||||
entry->dp.fake_unknown_size = 256;
|
||||
entry->dp.fake_syndata_size = 16;
|
||||
entry->dp.fake_unknown_udp_size = 64;
|
||||
entry->dp.wscale=-1; // default - dont change scale factor (client)
|
||||
entry->dp.desync_ttl6 = 0xFF; // unused
|
||||
entry->dp.desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
|
||||
entry->dp.desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
|
||||
entry->dp.wssize_cutoff_mode = entry->dp.desync_start_mode = entry->dp.desync_cutoff_mode = 'n'; // packet number by default
|
||||
entry->dp.udplen_increment = UDPLEN_INCREMENT_DEFAULT;
|
||||
entry->dp.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
||||
entry->dp.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
entry->dp.hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
|
||||
entry->dp.filter_ipv4 = entry->dp.filter_ipv6 = true;
|
||||
dp_init(&entry->dp);
|
||||
|
||||
// add to the tail
|
||||
struct desync_profile_list *dpn,*dpl=LIST_FIRST(¶ms.desync_profiles);
|
||||
@@ -222,15 +226,24 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
||||
|
||||
return entry;
|
||||
}
|
||||
static void dp_entry_destroy(struct desync_profile_list *entry)
|
||||
static void dp_clear_dynamic(struct desync_profile *dp)
|
||||
{
|
||||
hostlist_collection_destroy(&entry->dp.hl_collection);
|
||||
hostlist_collection_destroy(&entry->dp.hl_collection_exclude);
|
||||
ipset_collection_destroy(&entry->dp.ips_collection);
|
||||
ipset_collection_destroy(&entry->dp.ips_collection_exclude);
|
||||
port_filters_destroy(&entry->dp.pf_tcp);
|
||||
port_filters_destroy(&entry->dp.pf_udp);
|
||||
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters);
|
||||
hostlist_collection_destroy(&dp->hl_collection);
|
||||
hostlist_collection_destroy(&dp->hl_collection_exclude);
|
||||
ipset_collection_destroy(&dp->ips_collection);
|
||||
ipset_collection_destroy(&dp->ips_collection_exclude);
|
||||
port_filters_destroy(&dp->pf_tcp);
|
||||
port_filters_destroy(&dp->pf_udp);
|
||||
HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
|
||||
}
|
||||
void dp_clear(struct desync_profile *dp)
|
||||
{
|
||||
dp_clear_dynamic(dp);
|
||||
memset(dp,0,sizeof(*dp));
|
||||
}
|
||||
void dp_entry_destroy(struct desync_profile_list *entry)
|
||||
{
|
||||
dp_clear_dynamic(&entry->dp);
|
||||
free(entry);
|
||||
}
|
||||
void dp_list_destroy(struct desync_profile_list_head *head)
|
||||
|
@@ -51,7 +51,7 @@ struct desync_profile
|
||||
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
|
||||
unsigned int wssize_cutoff;
|
||||
|
||||
bool hostcase, hostnospace, domcase;
|
||||
bool hostcase, hostnospace, domcase, methodeol;
|
||||
char hostspell[4];
|
||||
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
|
||||
bool desync_retrans,desync_skip_nosni,desync_any_proto;
|
||||
@@ -68,7 +68,7 @@ struct desync_profile
|
||||
autottl desync_autottl, desync_autottl6;
|
||||
uint32_t desync_fooling_mode;
|
||||
uint32_t desync_badseq_increment, desync_badseq_ack_increment;
|
||||
uint8_t fake_http[1460],fake_tls[1460],fake_unknown[1460],fake_syndata[1460],seqovl_pattern[1460];
|
||||
uint8_t fake_http[1460],fake_tls[1460],fake_unknown[1460],fake_syndata[1460],seqovl_pattern[1460],fsplit_pattern[1460];
|
||||
uint8_t fake_unknown_udp[1472],udplen_pattern[1472],fake_quic[1472],fake_wg[1472],fake_dht[1472];
|
||||
size_t fake_http_size,fake_tls_size,fake_quic_size,fake_wg_size,fake_dht_size,fake_unknown_size,fake_syndata_size,fake_unknown_udp_size;
|
||||
int udplen_increment;
|
||||
@@ -99,8 +99,11 @@ struct desync_profile_list {
|
||||
};
|
||||
LIST_HEAD(desync_profile_list_head, desync_profile_list);
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
||||
void dp_entry_destroy(struct desync_profile_list *entry);
|
||||
void dp_list_destroy(struct desync_profile_list_head *head);
|
||||
bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
|
||||
void dp_init(struct desync_profile *dp);
|
||||
void dp_clear(struct desync_profile *dp);
|
||||
|
||||
struct params_s
|
||||
{
|
||||
|
34
nfq/pools.c
34
nfq/pools.c
@@ -160,12 +160,17 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
|
||||
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
|
||||
if (entry)
|
||||
{
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
if (filename)
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
entry->mod_time=0;
|
||||
else
|
||||
entry->filename = NULL;
|
||||
entry->mod_time = 0;
|
||||
entry->hostlist = NULL;
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
}
|
||||
@@ -192,7 +197,7 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
|
||||
|
||||
LIST_FOREACH(hfile, head, next)
|
||||
{
|
||||
if (!strcmp(hfile->filename,filename))
|
||||
if (hfile->filename && !strcmp(hfile->filename,filename))
|
||||
return hfile;
|
||||
}
|
||||
return NULL;
|
||||
@@ -223,7 +228,7 @@ struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head
|
||||
|
||||
LIST_FOREACH(item, head, next)
|
||||
{
|
||||
if (!strcmp(item->hfile->filename,filename))
|
||||
if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
|
||||
return item;
|
||||
}
|
||||
return NULL;
|
||||
@@ -369,12 +374,17 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
|
||||
struct ipset_file *entry = malloc(sizeof(struct ipset_file));
|
||||
if (entry)
|
||||
{
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
if (filename)
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
entry->mod_time=0;
|
||||
else
|
||||
entry->filename = NULL;
|
||||
entry->mod_time = 0;
|
||||
memset(&entry->ipset,0,sizeof(entry->ipset));
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
}
|
||||
@@ -401,7 +411,7 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
|
||||
|
||||
LIST_FOREACH(hfile, head, next)
|
||||
{
|
||||
if (!strcmp(hfile->filename,filename))
|
||||
if (hfile->filename && !strcmp(hfile->filename,filename))
|
||||
return hfile;
|
||||
}
|
||||
return NULL;
|
||||
@@ -432,7 +442,7 @@ struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, c
|
||||
|
||||
LIST_FOREACH(item, head, next)
|
||||
{
|
||||
if (!strcmp(item->hfile->filename,filename))
|
||||
if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
|
||||
return item;
|
||||
}
|
||||
return NULL;
|
||||
|
@@ -24,7 +24,7 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
||||
*hostlist = NULL;
|
||||
return false;
|
||||
}
|
||||
(*ct)++;
|
||||
if (ct) (*ct)++;
|
||||
}
|
||||
// advance to the next line
|
||||
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
|
||||
@@ -32,6 +32,11 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AppendHostlistItem(strpool **hostlist, char *s)
|
||||
{
|
||||
return addpool(hostlist,&s,s+strlen(s),NULL);
|
||||
}
|
||||
|
||||
bool AppendHostList(strpool **hostlist, const char *filename)
|
||||
{
|
||||
char *p, *e, s[256], *zbuf;
|
||||
@@ -98,21 +103,24 @@ bool AppendHostList(strpool **hostlist, const char *filename)
|
||||
|
||||
static bool LoadHostList(struct hostlist_file *hfile)
|
||||
{
|
||||
time_t t = file_mod_time(hfile->filename);
|
||||
if (!t)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
if (t==hfile->mod_time) return true; // up to date
|
||||
StrPoolDestroy(&hfile->hostlist);
|
||||
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
||||
if (hfile->filename)
|
||||
{
|
||||
time_t t = file_mod_time(hfile->filename);
|
||||
if (!t)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
if (t==hfile->mod_time) return true; // up to date
|
||||
StrPoolDestroy(&hfile->hostlist);
|
||||
return false;
|
||||
if (!AppendHostList(&hfile->hostlist, hfile->filename))
|
||||
{
|
||||
StrPoolDestroy(&hfile->hostlist);
|
||||
return false;
|
||||
}
|
||||
hfile->mod_time=t;
|
||||
}
|
||||
hfile->mod_time=t;
|
||||
return true;
|
||||
}
|
||||
static bool LoadHostLists(struct hostlist_files_head *list)
|
||||
@@ -202,7 +210,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
|
||||
LIST_FOREACH(item, hostlists_exclude, next)
|
||||
{
|
||||
VPRINT("[%s] exclude ", item->hfile->filename);
|
||||
VPRINT("[%s] exclude ", item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchHostList(item->hfile->hostlist, host))
|
||||
{
|
||||
if (excluded) *excluded = true;
|
||||
@@ -214,7 +222,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
{
|
||||
LIST_FOREACH(item, hostlists, next)
|
||||
{
|
||||
VPRINT("[%s] include ", item->hfile->filename);
|
||||
VPRINT("[%s] include ", item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchHostList(item->hfile->hostlist, host))
|
||||
return true;
|
||||
}
|
||||
@@ -235,17 +243,29 @@ bool HostlistCheck(const struct desync_profile *dp, const char *host, bool *excl
|
||||
static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
|
||||
{
|
||||
struct hostlist_file *hfile;
|
||||
if (!(hfile=hostlist_files_search(hostlists, filename)))
|
||||
if (!(hfile=hostlist_files_add(hostlists, filename)))
|
||||
|
||||
if (filename)
|
||||
{
|
||||
if (!(hfile=hostlist_files_search(hostlists, filename)))
|
||||
if (!(hfile=hostlist_files_add(hostlists, filename)))
|
||||
return NULL;
|
||||
if (!hostlist_collection_search(hl_collection, filename))
|
||||
if (!hostlist_collection_add(hl_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(hfile=hostlist_files_add(hostlists, NULL)))
|
||||
return NULL;
|
||||
if (!hostlist_collection_search(hl_collection, filename))
|
||||
if (!hostlist_collection_add(hl_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hfile;
|
||||
}
|
||||
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
|
||||
{
|
||||
if (!file_mod_time(filename))
|
||||
if (filename && !file_mod_time(filename))
|
||||
{
|
||||
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
|
||||
return NULL;
|
||||
@@ -265,15 +285,30 @@ void HostlistsDebug()
|
||||
struct hostlist_item *hl_item;
|
||||
|
||||
LIST_FOREACH(hfile, ¶ms.hostlists, next)
|
||||
VPRINT("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
|
||||
{
|
||||
if (hfile->filename)
|
||||
VPRINT("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
VPRINT("hostlist fixed%s\n",hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
|
||||
if (hl_item->hfile!=dpl->dp.hostlist_auto)
|
||||
VPRINT("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
VPRINT("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
VPRINT("profile %d include fixed hostlist%s\n",dpl->dp.n, hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next)
|
||||
VPRINT("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
VPRINT("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
VPRINT("profile %d exclude fixed hostlist%s\n",dpl->dp.n,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
if (dpl->dp.hostlist_auto)
|
||||
VPRINT("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include "pools.h"
|
||||
#include "params.h"
|
||||
|
||||
bool AppendHostlistItem(strpool **hostlist, char *s);
|
||||
bool AppendHostList(strpool **hostlist, const char *filename);
|
||||
bool LoadAllHostLists();
|
||||
bool NonEmptyHostlist(strpool **hostlist);
|
||||
|
75
tpws/ipset.c
75
tpws/ipset.c
@@ -31,7 +31,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
||||
ipsetDestroy(ips);
|
||||
return false;
|
||||
}
|
||||
(*ct)++;
|
||||
if (ct) (*ct)++;
|
||||
}
|
||||
else if (parse_cidr6(cidr,&c6))
|
||||
{
|
||||
@@ -40,7 +40,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
||||
ipsetDestroy(ips);
|
||||
return false;
|
||||
}
|
||||
(*ct)++;
|
||||
if (ct) (*ct)++;
|
||||
}
|
||||
else
|
||||
DLOG_ERR("bad ip or subnet : %s\n",cidr);
|
||||
@@ -53,6 +53,11 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
||||
|
||||
}
|
||||
|
||||
bool AppendIpsetItem(ipset *ips, char *ip)
|
||||
{
|
||||
return addpool(ips,&ip,ip+strlen(ip),NULL);
|
||||
}
|
||||
|
||||
static bool AppendIpset(ipset *ips, const char *filename)
|
||||
{
|
||||
char *p, *e, s[256], *zbuf;
|
||||
@@ -119,21 +124,24 @@ static bool AppendIpset(ipset *ips, const char *filename)
|
||||
|
||||
static bool LoadIpset(struct ipset_file *hfile)
|
||||
{
|
||||
time_t t = file_mod_time(hfile->filename);
|
||||
if (!t)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
if (t==hfile->mod_time) return true; // up to date
|
||||
ipsetDestroy(&hfile->ipset);
|
||||
if (!AppendIpset(&hfile->ipset, hfile->filename))
|
||||
if (hfile->filename)
|
||||
{
|
||||
time_t t = file_mod_time(hfile->filename);
|
||||
if (!t)
|
||||
{
|
||||
// stat() error
|
||||
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
|
||||
return true;
|
||||
}
|
||||
if (t==hfile->mod_time) return true; // up to date
|
||||
ipsetDestroy(&hfile->ipset);
|
||||
return false;
|
||||
if (!AppendIpset(&hfile->ipset, hfile->filename))
|
||||
{
|
||||
ipsetDestroy(&hfile->ipset);
|
||||
return false;
|
||||
}
|
||||
hfile->mod_time=t;
|
||||
}
|
||||
hfile->mod_time=t;
|
||||
return true;
|
||||
}
|
||||
static bool LoadIpsets(struct ipset_files_head *list)
|
||||
@@ -205,7 +213,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
|
||||
|
||||
LIST_FOREACH(item, ips_exclude, next)
|
||||
{
|
||||
VPRINT("[%s] exclude ",item->hfile->filename);
|
||||
VPRINT("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
|
||||
return false;
|
||||
}
|
||||
@@ -214,7 +222,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
|
||||
{
|
||||
LIST_FOREACH(item, ips, next)
|
||||
{
|
||||
VPRINT("[%s] include ",item->hfile->filename);
|
||||
VPRINT("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
|
||||
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
|
||||
return true;
|
||||
}
|
||||
@@ -234,17 +242,27 @@ bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, con
|
||||
static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
|
||||
{
|
||||
struct ipset_file *hfile;
|
||||
if (!(hfile=ipset_files_search(ipsets, filename)))
|
||||
if (!(hfile=ipset_files_add(ipsets, filename)))
|
||||
if (filename)
|
||||
{
|
||||
if (!(hfile=ipset_files_search(ipsets, filename)))
|
||||
if (!(hfile=ipset_files_add(ipsets, filename)))
|
||||
return NULL;
|
||||
if (!ipset_collection_search(ips_collection, filename))
|
||||
if (!ipset_collection_add(ips_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(hfile=ipset_files_add(ipsets, NULL)))
|
||||
return NULL;
|
||||
if (!ipset_collection_search(ips_collection, filename))
|
||||
if (!ipset_collection_add(ips_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
return hfile;
|
||||
}
|
||||
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename)
|
||||
{
|
||||
if (!file_mod_time(filename))
|
||||
if (filename && !file_mod_time(filename))
|
||||
{
|
||||
DLOG_ERR("cannot access ipset file '%s'\n",filename);
|
||||
return NULL;
|
||||
@@ -277,13 +295,24 @@ void IpsetsDebug()
|
||||
struct ipset_item *ips_item;
|
||||
|
||||
LIST_FOREACH(hfile, ¶ms.ipsets, next)
|
||||
VPRINT("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
|
||||
{
|
||||
if (hfile->filename)
|
||||
VPRINT("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
|
||||
else
|
||||
VPRINT("ipset fixed (%s)\n",dbg_ipset_fill(&hfile->ipset));
|
||||
}
|
||||
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next)
|
||||
VPRINT("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
if (ips_item->hfile->filename)
|
||||
VPRINT("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
else
|
||||
VPRINT("profile %d include fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next)
|
||||
VPRINT("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
if (ips_item->hfile->filename)
|
||||
VPRINT("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
else
|
||||
VPRINT("profile %d exclude fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
}
|
||||
}
|
||||
|
@@ -9,3 +9,4 @@ bool LoadAllIpsets();
|
||||
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6);
|
||||
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
|
||||
void IpsetsDebug();
|
||||
bool AppendIpsetItem(ipset *ips, char *ip);
|
||||
|
@@ -155,22 +155,26 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
|
||||
if (bcut) VPRINT(" ...");
|
||||
}
|
||||
|
||||
void dp_init(struct desync_profile *dp)
|
||||
{
|
||||
LIST_INIT(&dp->hl_collection);
|
||||
LIST_INIT(&dp->hl_collection_exclude);
|
||||
LIST_INIT(&dp->ips_collection);
|
||||
LIST_INIT(&dp->ips_collection_exclude);
|
||||
LIST_INIT(&dp->pf_tcp);
|
||||
|
||||
dp->filter_ipv4 = dp->filter_ipv6 = true;
|
||||
memcpy(dp->hostspell, "host", 4); // default hostspell
|
||||
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
||||
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
}
|
||||
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
||||
{
|
||||
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
|
||||
if (!entry) return NULL;
|
||||
|
||||
LIST_INIT(&entry->dp.hl_collection);
|
||||
LIST_INIT(&entry->dp.hl_collection_exclude);
|
||||
LIST_INIT(&entry->dp.ips_collection);
|
||||
LIST_INIT(&entry->dp.ips_collection_exclude);
|
||||
LIST_INIT(&entry->dp.pf_tcp);
|
||||
|
||||
entry->dp.filter_ipv4 = entry->dp.filter_ipv6 = true;
|
||||
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
|
||||
entry->dp.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
||||
entry->dp.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
dp_init(&entry->dp);
|
||||
|
||||
// add to the tail
|
||||
struct desync_profile_list *dpn,*dpl=LIST_FIRST(¶ms.desync_profiles);
|
||||
@@ -184,14 +188,23 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
||||
|
||||
return entry;
|
||||
}
|
||||
static void dp_entry_destroy(struct desync_profile_list *entry)
|
||||
static void dp_clear_dynamic(struct desync_profile *dp)
|
||||
{
|
||||
hostlist_collection_destroy(&entry->dp.hl_collection);
|
||||
hostlist_collection_destroy(&entry->dp.hl_collection_exclude);
|
||||
ipset_collection_destroy(&entry->dp.ips_collection);
|
||||
ipset_collection_destroy(&entry->dp.ips_collection_exclude);
|
||||
port_filters_destroy(&entry->dp.pf_tcp);
|
||||
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters);
|
||||
hostlist_collection_destroy(&dp->hl_collection);
|
||||
hostlist_collection_destroy(&dp->hl_collection_exclude);
|
||||
ipset_collection_destroy(&dp->ips_collection);
|
||||
ipset_collection_destroy(&dp->ips_collection_exclude);
|
||||
port_filters_destroy(&dp->pf_tcp);
|
||||
HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
|
||||
}
|
||||
void dp_clear(struct desync_profile *dp)
|
||||
{
|
||||
dp_clear_dynamic(dp);
|
||||
memset(dp,0,sizeof(*dp));
|
||||
}
|
||||
void dp_entry_destroy(struct desync_profile_list *entry)
|
||||
{
|
||||
dp_clear_dynamic(&entry->dp);
|
||||
free(entry);
|
||||
}
|
||||
void dp_list_destroy(struct desync_profile_list_head *head)
|
||||
|
@@ -83,7 +83,10 @@ struct desync_profile_list {
|
||||
};
|
||||
LIST_HEAD(desync_profile_list_head, desync_profile_list);
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
||||
void dp_entry_destroy(struct desync_profile_list *entry);
|
||||
void dp_list_destroy(struct desync_profile_list_head *head);
|
||||
void dp_init(struct desync_profile *dp);
|
||||
void dp_clear(struct desync_profile *dp);
|
||||
|
||||
struct params_s
|
||||
{
|
||||
|
35
tpws/pools.c
35
tpws/pools.c
@@ -154,18 +154,22 @@ void strlist_destroy(struct str_list_head *head)
|
||||
|
||||
|
||||
|
||||
|
||||
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename)
|
||||
{
|
||||
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
|
||||
if (entry)
|
||||
{
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
if (filename)
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
entry->mod_time=0;
|
||||
else
|
||||
entry->filename = NULL;
|
||||
entry->mod_time = 0;
|
||||
entry->hostlist = NULL;
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
}
|
||||
@@ -192,7 +196,7 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
|
||||
|
||||
LIST_FOREACH(hfile, head, next)
|
||||
{
|
||||
if (!strcmp(hfile->filename,filename))
|
||||
if (hfile->filename && !strcmp(hfile->filename,filename))
|
||||
return hfile;
|
||||
}
|
||||
return NULL;
|
||||
@@ -223,7 +227,7 @@ struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head
|
||||
|
||||
LIST_FOREACH(item, head, next)
|
||||
{
|
||||
if (!strcmp(item->hfile->filename,filename))
|
||||
if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
|
||||
return item;
|
||||
}
|
||||
return NULL;
|
||||
@@ -369,12 +373,17 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
|
||||
struct ipset_file *entry = malloc(sizeof(struct ipset_file));
|
||||
if (entry)
|
||||
{
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
if (filename)
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
if (!(entry->filename = strdup(filename)))
|
||||
{
|
||||
free(entry);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
entry->mod_time=0;
|
||||
else
|
||||
entry->filename = NULL;
|
||||
entry->mod_time = 0;
|
||||
memset(&entry->ipset,0,sizeof(entry->ipset));
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
}
|
||||
@@ -401,7 +410,7 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
|
||||
|
||||
LIST_FOREACH(hfile, head, next)
|
||||
{
|
||||
if (!strcmp(hfile->filename,filename))
|
||||
if (hfile->filename && !strcmp(hfile->filename,filename))
|
||||
return hfile;
|
||||
}
|
||||
return NULL;
|
||||
@@ -432,7 +441,7 @@ struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, c
|
||||
|
||||
LIST_FOREACH(item, head, next)
|
||||
{
|
||||
if (!strcmp(item->hfile->filename,filename))
|
||||
if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
|
||||
return item;
|
||||
}
|
||||
return NULL;
|
||||
|
301
tpws/tpws.c
301
tpws/tpws.c
@@ -175,16 +175,22 @@ static void exithelp(void)
|
||||
#endif
|
||||
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
|
||||
" --debug-level=0|1|2\t\t\t; specify debug level\n"
|
||||
" --dry-run\t\t\t\t; verify parameters and exit with code 0 if successful\n"
|
||||
"\nMULTI-STRATEGY:\n"
|
||||
" --new\t\t\t\t\t; begin new strategy\n"
|
||||
" --skip\t\t\t\t\t; do not use this strategy\n"
|
||||
" --filter-l3=ipv4|ipv6\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --filter-tcp=[~]port1[-port2]|*\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n"
|
||||
" --filter-l7=[http|tls|unknown]\t\t; L6-L7 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --ipset=<filename>\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||
" --ipset-ip=<ip_list>\t\t\t; comma separated fixed subnet list\n"
|
||||
" --ipset-exclude=<filename>\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
|
||||
" --ipset-exclude-ip=<ip_list>\t\t; comma separated fixed subnet list\n"
|
||||
"\nHOSTLIST FILTER:\n"
|
||||
" --hostlist=<filename>\t\t\t; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-domains=<domain_list>\t; comma separated fixed domain list\n"
|
||||
" --hostlist-exclude=<filename>\t\t; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list\n"
|
||||
" --hostlist-auto=<filename>\t\t; detect DPI blocks and build hostlist automatically\n"
|
||||
" --hostlist-auto-fail-threshold=<int>\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
|
||||
" --hostlist-auto-fail-time=<int>\t; all failed attemps must be within these seconds (default : %d)\n"
|
||||
@@ -483,6 +489,46 @@ static bool parse_pf_list(char *opt, struct port_filters_head *pfl)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_domain_list(char *opt, strpool **pp)
|
||||
{
|
||||
char *e,*p,c;
|
||||
|
||||
for (p=opt ; p ; )
|
||||
{
|
||||
if ((e = strchr(p,',')))
|
||||
{
|
||||
c=*e;
|
||||
*e=0;
|
||||
}
|
||||
|
||||
if (*p && !AppendHostlistItem(pp,p)) return false;
|
||||
|
||||
if (e) *e++=c;
|
||||
p = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_ip_list(char *opt, ipset *pp)
|
||||
{
|
||||
char *e,*p,c;
|
||||
|
||||
for (p=opt ; p ; )
|
||||
{
|
||||
if ((e = strchr(p,',')))
|
||||
{
|
||||
c=*e;
|
||||
*e=0;
|
||||
}
|
||||
|
||||
if (*p && !AppendIpsetItem(pp,p)) return false;
|
||||
|
||||
if (e) *e++=c;
|
||||
p = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
||||
// no static to not allow optimizer to inline this func (save stack)
|
||||
void config_from_file(const char *filename)
|
||||
@@ -524,6 +570,9 @@ void parse_params(int argc, char *argv[])
|
||||
{
|
||||
int option_index = 0;
|
||||
int v, i;
|
||||
bool bSkip=false, bDry=false;
|
||||
struct hostlist_file *anon_hl = NULL, *anon_hl_exclude = NULL;
|
||||
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.maxconn = DEFAULT_MAX_CONN;
|
||||
@@ -609,45 +658,51 @@ void parse_params(int argc, char *argv[])
|
||||
{ "tlsrec",required_argument,0,0 },// optidx=34
|
||||
{ "tlsrec-pos",required_argument,0,0 },// optidx=35
|
||||
{ "hostlist",required_argument,0,0 },// optidx=36
|
||||
{ "hostlist-exclude",required_argument,0,0 },// optidx=37
|
||||
{ "hostlist-auto",required_argument,0,0}, // optidx=38
|
||||
{ "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=39
|
||||
{ "hostlist-auto-fail-time",required_argument,0,0}, // optidx=40
|
||||
{ "hostlist-auto-debug",required_argument,0,0}, // optidx=41
|
||||
{ "pidfile",required_argument,0,0 },// optidx=42
|
||||
{ "debug",optional_argument,0,0 },// optidx=43
|
||||
{ "debug-level",required_argument,0,0 },// optidx=44
|
||||
{ "local-rcvbuf",required_argument,0,0 },// optidx=45
|
||||
{ "local-sndbuf",required_argument,0,0 },// optidx=46
|
||||
{ "remote-rcvbuf",required_argument,0,0 },// optidx=47
|
||||
{ "remote-sndbuf",required_argument,0,0 },// optidx=48
|
||||
{ "socks",no_argument,0,0 },// optidx=40
|
||||
{ "no-resolve",no_argument,0,0 },// optidx=50
|
||||
{ "resolver-threads",required_argument,0,0 },// optidx=51
|
||||
{ "skip-nodelay",no_argument,0,0 },// optidx=52
|
||||
{ "tamper-start",required_argument,0,0 },// optidx=53
|
||||
{ "tamper-cutoff",required_argument,0,0 },// optidx=54
|
||||
{ "connect-bind-addr",required_argument,0,0 },// optidx=55
|
||||
{ "hostlist-domains",required_argument,0,0 },// optidx=37
|
||||
{ "hostlist-exclude",required_argument,0,0 },// optidx=38
|
||||
{ "hostlist-exclude-domains",required_argument,0,0 },// optidx=39
|
||||
{ "hostlist-auto",required_argument,0,0}, // optidx=40
|
||||
{ "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=41
|
||||
{ "hostlist-auto-fail-time",required_argument,0,0}, // optidx=42
|
||||
{ "hostlist-auto-debug",required_argument,0,0}, // optidx=43
|
||||
{ "pidfile",required_argument,0,0 },// optidx=44
|
||||
{ "debug",optional_argument,0,0 },// optidx=45
|
||||
{ "debug-level",required_argument,0,0 },// optidx=46
|
||||
{ "dry-run",no_argument,0,0 },// optidx=47
|
||||
{ "local-rcvbuf",required_argument,0,0 },// optidx=48
|
||||
{ "local-sndbuf",required_argument,0,0 },// optidx=49
|
||||
{ "remote-rcvbuf",required_argument,0,0 },// optidx=50
|
||||
{ "remote-sndbuf",required_argument,0,0 },// optidx=51
|
||||
{ "socks",no_argument,0,0 },// optidx=52
|
||||
{ "no-resolve",no_argument,0,0 },// optidx=53
|
||||
{ "resolver-threads",required_argument,0,0 },// optidx=54
|
||||
{ "skip-nodelay",no_argument,0,0 },// optidx=55
|
||||
{ "tamper-start",required_argument,0,0 },// optidx=56
|
||||
{ "tamper-cutoff",required_argument,0,0 },// optidx=57
|
||||
{ "connect-bind-addr",required_argument,0,0 },// optidx=58
|
||||
|
||||
{ "new",no_argument,0,0 }, // optidx=56
|
||||
{ "filter-l3",required_argument,0,0 }, // optidx=57
|
||||
{ "filter-tcp",required_argument,0,0 }, // optidx=58
|
||||
{ "filter-l7",required_argument,0,0 }, // optidx=59
|
||||
{ "ipset",required_argument,0,0 }, // optidx=60
|
||||
{ "ipset-exclude",required_argument,0,0 }, // optidx=61
|
||||
{ "new",no_argument,0,0 }, // optidx=59
|
||||
{ "skip",no_argument,0,0 }, // optidx=60
|
||||
{ "filter-l3",required_argument,0,0 }, // optidx=61
|
||||
{ "filter-tcp",required_argument,0,0 }, // optidx=63
|
||||
{ "filter-l7",required_argument,0,0 }, // optidx=64
|
||||
{ "ipset",required_argument,0,0 }, // optidx=65
|
||||
{ "ipset-ip",required_argument,0,0 }, // optidx=66
|
||||
{ "ipset-exclude",required_argument,0,0 }, // optidx=67
|
||||
{ "ipset-exclude-ip",required_argument,0,0 }, // optidx=68
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
{ "enable-pf",no_argument,0,0 },// optidx=62
|
||||
{ "enable-pf",no_argument,0,0 },// optidx=68
|
||||
#elif defined(__APPLE__)
|
||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62
|
||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63
|
||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=68
|
||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=69
|
||||
#elif defined(__linux__)
|
||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62
|
||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63
|
||||
{ "mss",required_argument,0,0 }, // optidx=64
|
||||
{ "fix-seg",optional_argument,0,0 }, // optidx=65
|
||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=68
|
||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=69
|
||||
{ "mss",required_argument,0,0 }, // optidx=70
|
||||
{ "fix-seg",optional_argument,0,0 }, // optidx=71
|
||||
#ifdef SPLICE_PRESENT
|
||||
{ "nosplice",no_argument,0,0 }, // optidx=66
|
||||
{ "nosplice",no_argument,0,0 }, // optidx=72
|
||||
#endif
|
||||
#endif
|
||||
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
|
||||
@@ -655,7 +710,11 @@ void parse_params(int argc, char *argv[])
|
||||
};
|
||||
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
|
||||
{
|
||||
if (v) exithelp_clean();
|
||||
if (v)
|
||||
if (bDry)
|
||||
exit_clean(1);
|
||||
else
|
||||
exithelp_clean();
|
||||
switch (option_index)
|
||||
{
|
||||
case 0:
|
||||
@@ -945,6 +1004,7 @@ void parse_params(int argc, char *argv[])
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 36: /* hostlist */
|
||||
if (bSkip) break;
|
||||
if (!RegisterHostlist(dp, false, optarg))
|
||||
{
|
||||
DLOG_ERR("failed to register hostlist '%s'\n", optarg);
|
||||
@@ -952,7 +1012,22 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 37: /* hostlist-exclude */
|
||||
case 37: /* hostlist-domains */
|
||||
if (bSkip) break;
|
||||
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
|
||||
{
|
||||
DLOG_ERR("failed to register anonymous hostlist\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!parse_domain_list(optarg, &anon_hl->hostlist))
|
||||
{
|
||||
DLOG_ERR("failed to add domains to anonymous hostlist\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 38: /* hostlist-exclude */
|
||||
if (bSkip) break;
|
||||
if (!RegisterHostlist(dp, true, optarg))
|
||||
{
|
||||
DLOG_ERR("failed to register hostlist '%s'\n", optarg);
|
||||
@@ -960,7 +1035,22 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 38: /* hostlist-auto */
|
||||
case 39: /* hostlist-exclude-domains */
|
||||
if (bSkip) break;
|
||||
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
|
||||
{
|
||||
DLOG_ERR("failed to register anonymous hostlist\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!parse_domain_list(optarg, &anon_hl_exclude->hostlist))
|
||||
{
|
||||
DLOG_ERR("failed to add domains to anonymous hostlist\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 40: /* hostlist-auto */
|
||||
if (bSkip) break;
|
||||
if (dp->hostlist_auto)
|
||||
{
|
||||
DLOG_ERR("only one auto hostlist per profile is supported\n");
|
||||
@@ -988,7 +1078,7 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
|
||||
break;
|
||||
case 39: /* hostlist-auto-fail-threshold */
|
||||
case 41: /* hostlist-auto-fail-threshold */
|
||||
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
|
||||
{
|
||||
@@ -996,7 +1086,7 @@ void parse_params(int argc, char *argv[])
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 40: /* hostlist-auto-fail-time */
|
||||
case 42: /* hostlist-auto-fail-time */
|
||||
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_time<1)
|
||||
{
|
||||
@@ -1004,7 +1094,7 @@ void parse_params(int argc, char *argv[])
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 41: /* hostlist-auto-debug */
|
||||
case 43: /* hostlist-auto-debug */
|
||||
{
|
||||
FILE *F = fopen(optarg,"a+t");
|
||||
if (!F)
|
||||
@@ -1017,11 +1107,11 @@ void parse_params(int argc, char *argv[])
|
||||
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
|
||||
}
|
||||
break;
|
||||
case 42: /* pidfile */
|
||||
case 44: /* pidfile */
|
||||
strncpy(params.pidfile,optarg,sizeof(params.pidfile));
|
||||
params.pidfile[sizeof(params.pidfile)-1]='\0';
|
||||
break;
|
||||
case 43: /* debug */
|
||||
case 45: /* debug */
|
||||
if (optarg)
|
||||
{
|
||||
if (*optarg=='@')
|
||||
@@ -1055,44 +1145,47 @@ void parse_params(int argc, char *argv[])
|
||||
params.debug_target = LOG_TARGET_CONSOLE;
|
||||
}
|
||||
break;
|
||||
case 44: /* debug-level */
|
||||
case 46: /* debug-level */
|
||||
params.debug = atoi(optarg);
|
||||
break;
|
||||
case 45: /* local-rcvbuf */
|
||||
case 47: /* dry-run */
|
||||
bDry = true;
|
||||
break;
|
||||
case 48: /* local-rcvbuf */
|
||||
#ifdef __linux__
|
||||
params.local_rcvbuf = atoi(optarg)/2;
|
||||
#else
|
||||
params.local_rcvbuf = atoi(optarg);
|
||||
#endif
|
||||
break;
|
||||
case 46: /* local-sndbuf */
|
||||
case 49: /* local-sndbuf */
|
||||
#ifdef __linux__
|
||||
params.local_sndbuf = atoi(optarg)/2;
|
||||
#else
|
||||
params.local_sndbuf = atoi(optarg);
|
||||
#endif
|
||||
break;
|
||||
case 47: /* remote-rcvbuf */
|
||||
case 50: /* remote-rcvbuf */
|
||||
#ifdef __linux__
|
||||
params.remote_rcvbuf = atoi(optarg)/2;
|
||||
#else
|
||||
params.remote_rcvbuf = atoi(optarg);
|
||||
#endif
|
||||
break;
|
||||
case 48: /* remote-sndbuf */
|
||||
case 51: /* remote-sndbuf */
|
||||
#ifdef __linux__
|
||||
params.remote_sndbuf = atoi(optarg)/2;
|
||||
#else
|
||||
params.remote_sndbuf = atoi(optarg);
|
||||
#endif
|
||||
break;
|
||||
case 49: /* socks */
|
||||
case 52: /* socks */
|
||||
params.proxy_type = CONN_TYPE_SOCKS;
|
||||
break;
|
||||
case 50: /* no-resolve */
|
||||
case 53: /* no-resolve */
|
||||
params.no_resolve = true;
|
||||
break;
|
||||
case 51: /* resolver-threads */
|
||||
case 54: /* resolver-threads */
|
||||
params.resolver_threads = atoi(optarg);
|
||||
if (params.resolver_threads<1 || params.resolver_threads>300)
|
||||
{
|
||||
@@ -1100,10 +1193,10 @@ void parse_params(int argc, char *argv[])
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 52: /* skip-nodelay */
|
||||
case 55: /* skip-nodelay */
|
||||
params.skip_nodelay = true;
|
||||
break;
|
||||
case 53: /* tamper-start */
|
||||
case 56: /* tamper-start */
|
||||
{
|
||||
const char *p=optarg;
|
||||
if (*p=='n')
|
||||
@@ -1117,7 +1210,7 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper_lim = true;
|
||||
break;
|
||||
case 54: /* tamper-cutoff */
|
||||
case 57: /* tamper-cutoff */
|
||||
{
|
||||
const char *p=optarg;
|
||||
if (*p=='n')
|
||||
@@ -1131,7 +1224,7 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper_lim = true;
|
||||
break;
|
||||
case 55: /* connect-bind-addr */
|
||||
case 58: /* connect-bind-addr */
|
||||
{
|
||||
char *p = strchr(optarg,'%');
|
||||
if (p) *p++=0;
|
||||
@@ -1159,37 +1252,53 @@ void parse_params(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
|
||||
case 56: /* new */
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
case 59: /* new */
|
||||
if (bSkip)
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
exit_clean(1);
|
||||
dp_clear(dp);
|
||||
dp_init(dp);
|
||||
dp->n = desync_profile_count;
|
||||
bSkip = false;
|
||||
}
|
||||
dp = &dpl->dp;
|
||||
dp->n = ++desync_profile_count;
|
||||
else
|
||||
{
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp = &dpl->dp;
|
||||
dp->n = ++desync_profile_count;
|
||||
}
|
||||
anon_hl = anon_hl_exclude = NULL;
|
||||
anon_ips = anon_ips_exclude = NULL;
|
||||
break;
|
||||
case 57: /* filter-l3 */
|
||||
case 60: /* skip */
|
||||
bSkip = true;
|
||||
break;
|
||||
case 61: /* filter-l3 */
|
||||
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
||||
{
|
||||
DLOG_ERR("bad value for --filter-l3\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 58: /* filter-tcp */
|
||||
case 62: /* filter-tcp */
|
||||
if (!parse_pf_list(optarg,&dp->pf_tcp))
|
||||
{
|
||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 59: /* filter-l7 */
|
||||
case 63: /* filter-l7 */
|
||||
if (!parse_l7_list(optarg,&dp->filter_l7))
|
||||
{
|
||||
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 60: /* ipset */
|
||||
case 64: /* ipset */
|
||||
if (bSkip) break;
|
||||
if (!RegisterIpset(dp, false, optarg))
|
||||
{
|
||||
DLOG_ERR("failed to register ipset '%s'\n", optarg);
|
||||
@@ -1197,7 +1306,22 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 61: /* ipset-exclude */
|
||||
case 65: /* ipset-ip */
|
||||
if (bSkip) break;
|
||||
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
|
||||
{
|
||||
DLOG_ERR("failed to register anonymous ipset\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!parse_ip_list(optarg, &anon_ips->ipset))
|
||||
{
|
||||
DLOG_ERR("failed to add subnets to anonymous ipset\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 66: /* ipset-exclude */
|
||||
if (bSkip) break;
|
||||
if (!RegisterIpset(dp, true, optarg))
|
||||
{
|
||||
DLOG_ERR("failed to register ipset '%s'\n", optarg);
|
||||
@@ -1205,13 +1329,27 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 67: /* ipset-exclude-ip */
|
||||
if (bSkip) break;
|
||||
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
|
||||
{
|
||||
DLOG_ERR("failed to register anonymous ipset\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!parse_ip_list(optarg, &anon_ips_exclude->ipset))
|
||||
{
|
||||
DLOG_ERR("failed to add subnets to anonymous ipset\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
case 62: /* enable-pf */
|
||||
case 68: /* enable-pf */
|
||||
params.pf_enable = true;
|
||||
break;
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
case 62: /* local-tcp-user-timeout */
|
||||
case 68: /* local-tcp-user-timeout */
|
||||
params.tcp_user_timeout_local = atoi(optarg);
|
||||
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
|
||||
{
|
||||
@@ -1219,7 +1357,7 @@ void parse_params(int argc, char *argv[])
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 63: /* remote-tcp-user-timeout */
|
||||
case 69: /* remote-tcp-user-timeout */
|
||||
params.tcp_user_timeout_remote = atoi(optarg);
|
||||
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
|
||||
{
|
||||
@@ -1230,7 +1368,7 @@ void parse_params(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
case 64: /* mss */
|
||||
case 70: /* mss */
|
||||
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing
|
||||
dp->mss = atoi(optarg);
|
||||
if (dp->mss<88 || dp->mss>32767)
|
||||
@@ -1239,7 +1377,7 @@ void parse_params(int argc, char *argv[])
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 65: /* fix-seg */
|
||||
case 71: /* fix-seg */
|
||||
if (!params.fix_seg_avail)
|
||||
{
|
||||
DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
|
||||
@@ -1259,13 +1397,20 @@ void parse_params(int argc, char *argv[])
|
||||
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
|
||||
break;
|
||||
#ifdef SPLICE_PRESENT
|
||||
case 66: /* nosplice */
|
||||
case 72: /* nosplice */
|
||||
params.nosplice = true;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (bSkip)
|
||||
{
|
||||
LIST_REMOVE(dpl,next);
|
||||
dp_entry_destroy(dpl);
|
||||
desync_profile_count--;
|
||||
}
|
||||
|
||||
if (!params.bind_wait_only && !params.port)
|
||||
{
|
||||
DLOG_ERR("Need port number\n");
|
||||
@@ -1327,6 +1472,11 @@ void parse_params(int argc, char *argv[])
|
||||
// do not need args from file anymore
|
||||
cleanup_args();
|
||||
#endif
|
||||
if (bDry)
|
||||
{
|
||||
DLOG_CONDUP("command line parameters verified\n");
|
||||
exit_clean(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1476,6 +1626,15 @@ struct salisten_s
|
||||
int bind_wait_ip_left; // how much seconds left from bind_wait_ip
|
||||
};
|
||||
static const char *bindll_s[] = { "unwanted","no","prefer","force" };
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
|
||||
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
|
||||
#else
|
||||
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, listen_fd[MAX_BINDS], yes = 1, retval = 0, if_index, exit_v=EXIT_FAILURE;
|
||||
@@ -1486,6 +1645,8 @@ int main(int argc, char *argv[])
|
||||
srand(time(NULL));
|
||||
mask_from_preflen6_prepare();
|
||||
|
||||
PRINT_VER;
|
||||
|
||||
parse_params(argc, argv);
|
||||
argv=NULL; argc=0;
|
||||
|
||||
|
@@ -485,7 +485,7 @@ static bool connect_remote_conn(tproxy_conn_t *conn)
|
||||
|
||||
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
|
||||
|
||||
if (conn->track.dp)
|
||||
if (conn->track.dp && conn->track.dp->mss)
|
||||
{
|
||||
mss = conn->track.dp->mss;
|
||||
if (conn->track.dp->hostlist_auto)
|
||||
@@ -495,8 +495,11 @@ static bool connect_remote_conn(tproxy_conn_t *conn)
|
||||
bool bHostExcluded;
|
||||
conn->track.b_host_matches = HostlistCheck(conn->track.dp, conn->track.hostname, &bHostExcluded, false);
|
||||
conn->track.b_host_checked = true;
|
||||
if (!conn->track.b_host_matches) conn->track.b_ah_check = !bHostExcluded;
|
||||
if (!conn->track.b_host_matches) mss = 0;
|
||||
if (!conn->track.b_host_matches)
|
||||
{
|
||||
conn->track.b_ah_check = !bHostExcluded;
|
||||
mss = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -833,7 +836,6 @@ static bool proxy_mode_connect_remote(tproxy_conn_t *conn, struct tailhead *conn
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!(conn->partner = new_conn(remote_fd, true)))
|
||||
{
|
||||
close(remote_fd);
|
||||
@@ -1676,7 +1678,6 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
DBGPRINT("conn fd=%d has no unsent\n", conn->fd);
|
||||
conn->bFlowIn = false;
|
||||
epoll_update_flow(conn);
|
||||
|
Reference in New Issue
Block a user