60 Commits

Author SHA1 Message Date
Lorekin
06e364a2ef Merge 92ba6b439e into 8324c04a41 2024-12-04 11:45:15 +03:00
bol-van
8324c04a41 Update windows.md 2024-12-04 10:59:57 +03:00
bol-van
166847ba92 Update windows.en.md 2024-12-04 10:59:22 +03:00
bol-van
1904f01cf4 Update windows.en.md 2024-12-04 10:58:25 +03:00
bol-van
4ae1ad053d Update windows.md 2024-12-04 10:57:09 +03:00
bol-van
7d9946b007 update docs 2024-12-03 18:23:13 +03:00
bol-van
86462f4cee update docs 2024-12-03 18:20:46 +03:00
bol-van
669182c133 install_easy: trim trailing space in editor 2024-12-03 17:33:02 +03:00
bol-van
f81bb51f4a install_easy: validate daemon options 2024-12-03 17:22:16 +03:00
bol-van
d4ff423add tpws: --dry-run 2024-12-03 15:57:21 +03:00
bol-van
b14ff9b647 nfqws: --dry-run 2024-12-03 15:56:37 +03:00
bol-van
277c5f9e00 update docs 2024-12-02 21:06:05 +03:00
bol-van
f016e5a4dc nfqws: customize fakedsplit pattern 2024-12-02 20:03:52 +03:00
bol-van
fc3912b4fe nfqws: improve fakedsplit/fakeddisorder with more fakes 2024-12-02 13:14:01 +03:00
bol-van
c01a764e1f init.d: sysv fix route_localnet with multiple IFACE_LAN 2024-12-01 21:21:08 +03:00
Lorekin
92ba6b439e Add script to get antifilter domains 2024-11-27 23:58:54 +03:00
bol-van
4ecb40e03b Merge pull request #891 from spvkgn/fix-actions
github: minor
2024-11-27 16:28:16 +03:00
spvkgn
be9c300cb3 github: minor 2024-11-27 18:10:56 +05:00
bol-van
839c720f60 Merge pull request #888 from spvkgn/fix-actions
github: fix optimization for size
2024-11-27 14:51:12 +03:00
spvkgn
127bec2f14 github: fix optimization for size 2024-11-27 15:34:46 +05:00
spvkgn
15879c82f6 github: minor 2024-11-27 12:02:13 +05:00
bol-van
9d188840c1 blockcheck: eliminate multipos in fakedsplit and fakeddisorder 2024-11-25 18:16:16 +03:00
bol-van
35a28f4efe blockcheck: old dash compat 2024-11-25 12:39:12 +03:00
bol-van
78ea379e0f quick_start: light release notice 2024-11-24 18:00:01 +03:00
bol-van
007cbe600b update docs 2024-11-24 17:10:01 +03:00
bol-van
d1a8e276b5 update docs 2024-11-24 17:06:23 +03:00
bol-van
eb2f5b5f45 nfqws,tpws: ip->subnet in help text 2024-11-24 17:06:04 +03:00
bol-van
a623cef95d nfqws: fixed lists 2024-11-24 16:48:14 +03:00
bol-van
f00b45a28e tpws: fixed list fixes 2024-11-24 16:47:51 +03:00
bol-van
422faaa29c tpws: fixed ipset and hostlist 2024-11-24 16:03:13 +03:00
bol-van
16a9e3f9c9 github: sha256sum, remove tpws_wsl.tgz in openwrt ver 2024-11-24 13:27:57 +03:00
bol-van
7c5869bc29 display versions 2024-11-24 11:51:49 +03:00
bol-van
feb3dd4d73 issue_template warnings 2024-11-24 10:28:04 +03:00
bol-van
b4204ca2ba github: remote Makefile in light ver 2024-11-23 21:20:03 +03:00
bol-van
89a67e6952 github: tar releases with root owner 2024-11-23 21:17:19 +03:00
bol-van
34199b151c github: separate embedded linux archive 2024-11-23 20:26:58 +03:00
bol-van
c6962f575e install_bin: search win64 and win32 in CYGWIN 2024-11-23 20:07:26 +03:00
bol-van
9c8662b25e nfqws,tpws: fix crash 2024-11-23 14:14:12 +03:00
bol-van
fedb62df66 update docs 2024-11-23 13:28:34 +03:00
bol-van
44c19c1743 blockcheck: --methodeol test for nfqws 2024-11-23 13:20:02 +03:00
bol-van
56aa481226 nfqws: warn if cannot do hostnospace 2024-11-23 13:17:34 +03:00
bol-van
9184317549 nfqws: --methodeol 2024-11-23 13:14:02 +03:00
bol-van
a3048ae120 nfqws: --skip 2024-11-23 12:55:14 +03:00
bol-van
fc44d74f2b fix lto in nfqws makefile 2024-11-23 12:33:15 +03:00
bol-van
1779cfad30 tpws: --skip 2024-11-23 12:17:49 +03:00
bol-van
4856be4ef1 init.d: do not use pgrep for firmwares compatibility 2024-11-23 10:58:46 +03:00
bol-van
033043bdc0 tpws: remote duplicate if 2024-11-22 13:04:06 +03:00
bol-van
46284938ce tpws: fix socks-hostname hostlist checks 2024-11-22 12:42:33 +03:00
bol-van
09378553b9 keenetic script check disable ipv4 2024-11-21 20:35:27 +03:00
bol-van
6b85884cdf update keentic fix script 2024-11-21 20:30:23 +03:00
bol-van
1b14a8210c readme: more precise marker definition 2024-11-21 15:44:18 +03:00
bol-van
182fe850db makefiles: use lto 2024-11-21 15:25:19 +03:00
bol-van
62b081e9fb doc works 2024-11-21 10:47:11 +03:00
bol-van
e3e7449d74 doc works 2024-11-21 10:44:52 +03:00
bol-van
669f1978a3 doc works 2024-11-21 10:02:32 +03:00
bol-van
57c4b1a2b2 fix grep in default_route_interfaces6 2024-11-20 17:21:16 +03:00
bol-van
ac7385391e 10-keenetic-udp-fix: auto discover wan interfaces 2024-11-19 22:09:40 +03:00
bol-van
50a52d79ec default_route_interfaces helpers 2024-11-19 22:08:48 +03:00
bol-van
d77a1c8cd6 init.d: keenetic udp fix script 2024-11-19 19:54:21 +03:00
bol-van
395b9480c5 nfqws: fix wrong printf format 2024-11-19 19:27:36 +03:00
43 changed files with 1528 additions and 684 deletions

10
.github/issue_template.md vendored Normal file
View File

@@ -0,0 +1,10 @@
1. Здесь не место для вопросов, касающихся компьютерной грамотности и навыков использования ОС
2. Здесь не место для вопросов "у меня не работает" без технических подробностей
3. Здесь не место для вопросов "как мне открыть ютуб" или "что писать в ..."
4. Здесь не место для обсуждения сборок
5. Вирусов здесь нет. У вас либо чья-то сборка, либо ваш антивирус давно пора отправить на покой. Не согласны - удаляйте софт.
Все означенное обсуждать в дискуссиях или на форумах.
При нарушении будет закрываться или конвертироваться в дискуссии.
Issue только для обсуждения проблем самого софта. Неработа стратегии или ваше неумение настроить - это ваша проблема, а не проблема софта.

View File

@@ -82,10 +82,6 @@ jobs:
export STRIP=$TARGET-strip export STRIP=$TARGET-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
# optimize for size
export CFLAGS="-Os -flto=auto"
export LDFLAGS="-Os"
# netfilter libs # 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/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 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 for i in libmnl libnfnetlink libnetfilter_queue ; do
( (
cd $i-* cd $i-*
CFLAGS="-Os -flto=auto" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking ./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR 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 xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
( (
cd zlib-* cd zlib-*
CFLAGS="-Os -flto=auto" \
./configure --prefix= --static ./configure --prefix= --static
make install -j$(nproc) DESTDIR=$DEPS_DIR 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 install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
# zapret # zapret
CFLAGS="$CFLAGS -static-libgcc -static -I$DEPS_DIR/include" \ CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include" \
LDFLAGS="$LDFLAGS -L$DEPS_DIR/lib" \ LDFLAGS="-L$DEPS_DIR/lib" \
make -C zapret -j$(nproc) make -C zapret -j$(nproc)
tar -C zapret/binaries/my -cJf zapret-linux-$ARCH.tar.xz . tar -C zapret/binaries/my -cJf zapret-linux-$ARCH.tar.xz .
@@ -136,6 +134,7 @@ jobs:
- name: Build zapret - name: Build zapret
run: | run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
make mac -j$(sysctl -n hw.logicalcpu) make mac -j$(sysctl -n hw.logicalcpu)
tar -C binaries/my -cJf zapret-mac-x64.tar.xz . tar -C binaries/my -cJf zapret-mac-x64.tar.xz .
@@ -170,7 +169,8 @@ jobs:
TARGET: ${{ matrix.target }} TARGET: ${{ matrix.target }}
ARCH: ${{ matrix.arch }} ARCH: ${{ matrix.arch }}
run: | 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 . tar -C binaries/my -cJf zapret-freebsd-$ARCH.tar.xz .
- name: Upload artifacts - name: Upload artifacts
@@ -203,6 +203,7 @@ jobs:
- name: Build ip2net, mdig - name: Build ip2net, mdig
shell: msys2 {0} shell: msys2 {0}
run: | run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
mkdir -p output mkdir -p output
cd zapret cd zapret
mingw32-make -C ip2net win mingw32-make -C ip2net win
@@ -259,6 +260,7 @@ jobs:
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}' shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
run: >- run: >-
export MAKEFLAGS=-j$(nproc) && export MAKEFLAGS=-j$(nproc) &&
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}" &&
cd zapret && cd zapret &&
make -C nfq ${TARGET} && make -C nfq ${TARGET} &&
cp -a nfq/winws.exe ../output cp -a nfq/winws.exe ../output
@@ -317,10 +319,6 @@ jobs:
export STRIP=$TOOLCHAIN/bin/llvm-strip export STRIP=$TOOLCHAIN/bin/llvm-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
# optimize for size
export CFLAGS="-Os -flto=auto"
export LDFLAGS="-Os"
# netfilter libs # 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/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 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 for i in libmnl libnfnetlink libnetfilter_queue ; do
( (
cd $i-* 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 ./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR make install -j$(nproc) DESTDIR=$DEPS_DIR
) )
@@ -338,7 +336,8 @@ jobs:
done done
# zapret # 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) make -C zapret android -j$(nproc)
zip zapret-android-$ABI.zip -j zapret/binaries/my/* zip zapret-android-$ABI.zip -j zapret/binaries/my/*
@@ -434,8 +433,16 @@ jobs:
- name: Create release bundles - name: Create release bundles
run: | run: |
rm -rf ${{ env.repo_dir }}/.git* 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 }} 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 - name: Upload release assets
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
@@ -448,3 +455,4 @@ jobs:
files: | files: |
zapret*.tar.gz zapret*.tar.gz
zapret*.zip zapret*.zip
sha256sum.txt

View File

@@ -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"} 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" 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"} 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 ] && { [ "$code" = 0 ] && {
local testf=$1 dom=$2
shift; shift; shift; shift;
local strategy="$@" strategy="$@"
strategy_append_extra_tpws strategy_append_extra_tpws
report_append "ipv${IPV} $dom $testf : tpws ${WF:+$WF }$strategy" report_append "ipv${IPV} $dom $testf : tpws ${WF:+$WF }$strategy"
} }
@@ -1028,11 +1027,10 @@ pktws_curl_test()
# $3,$4,$5, ... - nfqws/dvtws params # $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"} 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"} 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 ] && { [ "$code" = 0 ] && {
local testf=$1 dom=$2
shift; shift; shift; shift;
local strategy="$@" strategy="$@"
strategy_append_extra_pktws strategy_append_extra_pktws
report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy" report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy"
} }
@@ -1112,6 +1110,10 @@ test_has_split()
{ {
contains "$1" split || contains "$1" disorder contains "$1" split || contains "$1" disorder
} }
test_has_fakedsplit()
{
contains "$1" fakedsplit || contains "$1" fakeddisorder
}
test_has_fake() test_has_fake()
{ {
[ "$1" = fake ] || starts_with "$1" fake, [ "$1" = fake ] || starts_with "$1" fake,
@@ -1138,10 +1140,13 @@ pktws_curl_test_update_vary()
proto=http proto=http
[ "$sec" = 0 ] || proto=tls [ "$sec" = 0 ] || proto=tls
test_has_fake $desync && zerofake="--dpi-desync-fake-$proto=0x00000000" 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" splits="method+2 midsld"
[ "$sec" = 0 ] || splits="1 midsld 1,midsld" [ "$sec" = 0 ] || splits="1 midsld 1,midsld"
} fi
for fake in '' $zerofake ; do for fake in '' $zerofake ; do
if [ -n "$splits" ]; then if [ -n "$splits" ]; then
for pos in $splits ; do 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' 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 ] && { [ "$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 pktws_curl_test_update $1 $3 $s
done done
} }

View File

@@ -140,7 +140,7 @@ echo_var()
eval v="\$$1" eval v="\$$1"
if find_str_in_list $1 "$EDITVAR_NEWLINE_VARS"; then if find_str_in_list $1 "$EDITVAR_NEWLINE_VARS"; then
echo "$1=\"" 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 else
if contains "$v" " "; then if contains "$v" " "; then
echo $1=\"$v\" echo $1=\"$v\"
@@ -170,6 +170,7 @@ list_vars()
echo_var $1 echo_var $1
shift shift
done done
echo
} }
openrc_test() openrc_test()
@@ -837,3 +838,37 @@ select_fwtype()
echo select firewall type : echo select firewall type :
ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE 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
}

View File

@@ -125,3 +125,13 @@ resolve_lower_devices()
} }
} }
} }
default_route_interfaces6()
{
sed -nre 's/^00000000000000000000000000000000 00 [0-9a-f]{32} [0-9a-f]{2} [0-9a-f]{32} [0-9a-f]{8} [0-9a-f]{8} [0-9a-f]{8} [0-9a-f]{8} +(.*)$/\1/p' /proc/net/ipv6_route | grep -v '^lo$' | sort -u | xargs
}
default_route_interfaces4()
{
sed -nre 's/^([^\t]+)\t00000000\t[0-9A-F]{8}\t[0-9A-F]{4}\t[0-9]+\t[0-9]+\t[0-9]+\t00000000.*$/\1/p' /proc/net/route | sort -u | xargs
}

View File

@@ -389,3 +389,31 @@ blockcheck: added CURL_OPT
blockcheck: new strategies support blockcheck: new strategies support
blockcheck: test sequence rework blockcheck: test sequence rework
blockcheck: view all working strategies in summary 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

View File

@@ -50,6 +50,8 @@
> образ `squashfs` с помощью `image builder` и перешить этим вариантом роутер. > образ `squashfs` с помощью `image builder` и перешить этим вариантом роутер.
1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив. 1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив.
Для openwrt и прошивок используйте вариант `openwrt-embedded`.
Для экономия места в /tmp можно качать через curl в stdout и сразу распаковывать.
2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и 2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и
сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`. сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`.

View File

@@ -1,4 +1,4 @@
# zapret v.69 # zapret v69.5
# SCAMMER WARNING # 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. @<config_file> ; read file for options. must be the only argument. other options are ignored.
--debug=0|1 --debug=0|1
--dry-run ; verify parameters and exit with code 0 if successful
--qnum=<nfqueue_number> --qnum=<nfqueue_number>
--daemon ; daemonize --daemon ; daemonize
--pidfile=<filename> ; write pid to file --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" --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 --hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
--domcase ; mix domain case : Host: TeSt.cOm --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=[<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-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
--dpi-desync-ttl=<int> ; set ttl for desync packet --dpi-desync-ttl=<int> ; set ttl for desync packet
@@ -161,6 +163,7 @@ nfqws takes the following parameters:
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise ; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment --dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap --dpi-desync-split-seqovl-pattern=<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-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8.
--dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32. --dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32.
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000 --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-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N --dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) --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=<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=<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-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-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-retrans-threshold=<int> ; how many request retransmissions cause attempt to fail (default : 3)
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives --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-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-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-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. --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=<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=<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 ### 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 * `multisplit`. split request at specified in `--dpi-desync-split-pos` positions
* `multidisorder`. same as `multisplit` but send in reverse order * `multidisorder`. same as `multisplit` but send in reverse order
* `fakedsplit`. split request into 2 segments adding fakes in the middle of them : fake 1st segment, 1st segment, fake 1st segment, 2nd 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 : 2nd segment, fake 1st segment, 1st segment, fake 1st 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. Positions are defined by markers.
@@ -267,7 +275,7 @@ Positions are defined by markers.
Relative positions : 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) * **host** - hostname start in a known protocol (http, TLS)
* **endhost** - the byte next to the last hostname's byte * **endhost** - the byte next to the last hostname's byte
* **sld** - second level domain start in the hostname * **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=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> --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-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-iface4=<interface_name> ; bind to the first ipv4 addr of interface
--bind-iface6=<interface_name> ; bind to the first ipv6 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 ; 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 --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-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-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. --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=<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=<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=<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=<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=<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-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-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
@@ -701,7 +715,7 @@ tpws is transparent proxy.
--daemon ; daemonize --daemon ; daemonize
--pidfile=<filename> ; write pid to file --pidfile=<filename> ; write pid to file
--user=<username> ; drop root privs --user=<username> ; drop root privs
--uid=uid[:gid] ; drop root privs --uid=uid[:gid] ; drop root privs
``` ```
### TCP segmentation in tpws ### TCP segmentation in tpws

View File

@@ -1,4 +1,4 @@
# zapret v.69 # zapret v69.5
# ВНИМАНИЕ, остерегайтесь мошенников # ВНИМАНИЕ, остерегайтесь мошенников
@@ -159,70 +159,78 @@ DPI. Все больше становится внереестровых бло
dvtws, собираемый из тех же исходников (см. [документация BSD](./bsd.md)). dvtws, собираемый из тех же исходников (см. [документация BSD](./bsd.md)).
``` ```
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются. @<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
--debug=0|1 ; 1=выводить отладочные сообщения --debug=0|1 ; 1=выводить отладочные сообщения
--daemon ; демонизировать прогу --dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
--pidfile=<file> ; сохранить PID в файл --daemon ; демонизировать прогу
--user=<username> ; менять uid процесса --pidfile=<file> ; сохранить PID в файл
--uid=uid[:gid] ; менять uid процесса --user=<username> ; менять uid процесса
--qnum=N ; номер очереди N --uid=uid[:gid] ; менять uid процесса
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов --qnum=N ; номер очереди N
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов --bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !) --bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !) --wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
--wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !)
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60 --wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". --ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета --hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase --hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
--domcase ; домен после Host: сделать таким : TeSt.cOm --methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com"
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper --hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000 --domcase ; домен после Host: сделать таким : TeSt.cOm
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов --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-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl --dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию. --dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; переопределение предыдущего параметра для ipv6 --dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2 --dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию.
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты) --dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; переопределение предыдущего параметра для ipv6
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI --dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder --dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число. --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-split-seqovl-pattern=<filename>|0xHEX ; чем заполнять фейковую часть overlap
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000 --dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; чем заполнять фейки в fakedsplit/fakeddisorder
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000 --dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных --dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org --dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному --dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт --dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata --dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial --dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт --dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт --dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
--dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen --dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули --dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N --dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N --dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются. --dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
; в файле должен быть хост на каждой строке. --hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска. ; в файле должен быть хост на каждой строке.
; при изменении времени модификации файла он перечитывается автоматически по необходимости ; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
; список может быть запакован в gzip. формат автоматически распознается и разжимается ; при изменении времени модификации файла он перечитывается автоматически по необходимости
; списков может быть множество. пустой общий лист = его отсутствие ; список может быть запакован в gzip. формат автоматически распознается и разжимается
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello. ; списков может быть множество. пустой общий лист = его отсутствие
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам. ; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика) --hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3) --hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) --hostlist-exclude-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3) --hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты. --hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
--new ; начало новой стратегии (новый профиль) --hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии --hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3)
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую. --hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую. --new ; начало новой стратегии (новый профиль)
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую. --skip ; не использовать этот профиль . полезно для временной деактивации профиля без удаления параметров.
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая. --filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая. --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 или в файл. Может быть важен порядок следования `--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. Может быть важен порядок следования
@@ -312,8 +320,13 @@ dvtws, собираемый из тех же исходников (см. [док
* `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях. * `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях.
* `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке. * `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке.
* `fakedsplit`. нарезаем запрос на 2 части, обрамляя его фейками : фейк 1-й части, 1 часть, фейк 1-й части, 2 часть * `fakedsplit`. нарезаем запрос на 2 части, обрамляя каждую часть фейками : фейк 1-й части, 1 часть, фейк 1-й части, фейк 2-й части, 2 часть, фейк 2-й части
* `fakeddisorder`. нарезаем запрос на 2 части, обрамляя его фейками : 2 часть, фейк 1-й части, 1 часть, фейк 1 части. * `fakeddisorder`. аналогично `fakedsplit`, только в обратном порядке : фейк 2-й части, 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1 части.
Содержимое фейков в `fakedsplit`/`fakeddisorder` определяется параметром `--dpi-desync-fakedsplit-pattern` (по умолчанию 0x00).
Данные фейков берутся из паттерна со смещением, соответствующим смещению отсылаемых частей.
Размеры фейков соответствуют длинам отсылаемых частей.
Цель этих режимов - максимально усложнить выявление оригинальных данных среди фейков.
Для определения позиций нарезки используются маркеры. Для определения позиций нарезки используются маркеры.
@@ -323,11 +336,11 @@ dvtws, собираемый из тех же исходников (см. [док
Относительные позиции : Относительные позиции :
* **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но поддерживается и нахождение метода после дурение методом `--methodeol` от tpws. Тогда позиция может стать 1 или 2. * **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но может сместиться из-за `--methodeol`. Тогда позиция может стать 1 или 2.
* **host** - начало имени хоста в известном протоколе (http, TLS) * **host** - начало имени хоста в известном протоколе (http, TLS)
* **endhost** - конец имени хоста * **endhost** - байт, следующий за последним байтом имени хоста
* **sld** - начало домена 2 уровня в имени хоста * **sld** - начало домена 2 уровня в имени хоста
* **endsld** - конец домена 2 уровня в имени хоста * **endsld** - байт, следующий за последним байтом домена 2 уровня в имени хоста
* **midsld** - середина домена 2 уровня в имени хоста * **midsld** - середина домена 2 уровня в имени хоста
* **sniext** - начало поля данных SNI extension в TLS. Любой extension состоит из 2-байтовых полей type и length, за ними идет поле данных. * **sniext** - начало поля данных SNI extension в TLS. Любой extension состоит из 2-байтовых полей type и length, за ними идет поле данных.
@@ -381,7 +394,7 @@ Windows оставляет старые данные, поэтому disorder с
### СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6 ### СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6
Режимы десинхронизации `hopbyhop`, `destopt` и `ipfrag1` (не путать с fooling !) относятся только к `ipv6` и заключается Режимы десинхронизации `hopbyhop`, `destopt` и `ipfrag1` (не путать с fooling !) относятся только к ipv6 и заключается
в добавлении хедера `hop-by-hop options`, `destination options` или `fragment` во все пакеты, попадающие под десинхронизацию. в добавлении хедера `hop-by-hop options`, `destination options` или `fragment` во все пакеты, попадающие под десинхронизацию.
Здесь надо обязательно понимать, что добавление хедера увеличивает размер пакета, потому не может быть применено Здесь надо обязательно понимать, что добавление хедера увеличивает размер пакета, потому не может быть применено
к пакетам максимального размера. Это имеет место при передаче больших сообщений. к пакетам максимального размера. Это имеет место при передаче больших сообщений.
@@ -398,7 +411,7 @@ extension хедерам в поисках транспортного хедер
В параметре dpi-desync можно указать до 3 режимов через запятую. В параметре dpi-desync можно указать до 3 режимов через запятую.
* 0 фаза - предполагает работу на этапе установления соединения : `synack`, `syndata` `--wsize`, `--wssize`. На эту фазу не действуют фильтры по [hostlist](((#множественные-стратегии))). * 0 фаза - предполагает работу на этапе установления соединения : `synack`, `syndata`, `--wsize`, `--wssize`. На эту фазу не действуют фильтры по [hostlist](#множественные-стратегии).
* 1 фаза - отсылка чего-либо до оригинального пакета данных : `fake`, `rst`, `rstack`. * 1 фаза - отсылка чего-либо до оригинального пакета данных : `fake`, `rst`, `rstack`.
* 2 фаза - отсылка в модифицированном виде оригинального пакета данных (например, `fakedsplit` или `ipfrag2`). * 2 фаза - отсылка в модифицированном виде оригинального пакета данных (например, `fakedsplit` или `ipfrag2`).
@@ -424,29 +437,10 @@ DPI может отстать от потока, если ClientHello его у
В документации по geneva это называется "TCB turnaround". Попытка ввести DPI в заблуждение относительно В документации по geneva это называется "TCB turnaround". Попытка ввести DPI в заблуждение относительно
ролей клиента и сервера. ролей клиента и сервера.
!!! Поскольку режим нарушает работу NAT, техника может сработать только если между атакующим устройством
Поскольку режим нарушает работу NAT, техника может сработать только если между атакующим устройством
и DPI нет NAT. Атака не сработает через NAT роутер, но может сработать с него. и DPI нет NAT. Атака не сработает через NAT роутер, но может сработать с него.
Для реализации атаки в linux обязательно требуется отключить стандартное правило firewall, Для реализации атаки на проходящий трафик требуются nftables и схема [POSTNAT](#nftables-для-nfqws).
дропающее инвалидные пакеты в цепочке OUTPUT. Например : `-A OUTPUT -m state --state INVALID -j DROP`
В openwrt можно отключить drop INVALID в OUTPUT и FORWARD через опцию в /etc/config/firewall:
```
config zone
option name 'wan'
.........
option masq_allow_invalid '1'
```
К сожалению, отключить только в OUTPUT таким образом нельзя. Но можно сделать иначе. Вписать в `/etc/firewall.user`:
```
iptables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT
ip6tables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT
```
Лучше делать так, потому что отсутствие дропа INVALID в FORWARD может привести к нежелательным утечкам пакетов из LAN.
Если не принять эти меры, отсылка SYN,ACK сегмента вызовет ошибку и операция будет прервана.
Остальные режимы тоже не сработают. Если поймете, что вам synack не нужен, обязательно верните правило дропа INVALID.
### РЕЖИМ SYNDATA ### РЕЖИМ SYNDATA
@@ -480,7 +474,7 @@ conntrack - простенький, он не писался с учетом в
`--wssize` позволяет изменить с клиента размер tcp window для сервера, чтобы он послал следующие ответы разбитыми на части. `--wssize` позволяет изменить с клиента размер tcp window для сервера, чтобы он послал следующие ответы разбитыми на части.
Чтобы это подействовало на все серверные ОС, необходимо менять window size в каждом исходящем с клиента пакете до отсылки сообщения, Чтобы это подействовало на все серверные ОС, необходимо менять window size в каждом исходящем с клиента пакете до отсылки сообщения,
ответ на который должен быть разбит (например, TLS ClientHello). Именно поэтому и необходим conntrack, чтобы ответ на которое должен быть разбит (например, TLS ClientHello). Именно поэтому и необходим conntrack, чтобы
знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически. знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически.
В linux это может быть купировано через connbytes, но в BSD системах такой возможности нет. В linux это может быть купировано через connbytes, но в BSD системах такой возможности нет.
В случае http(s) останавливаемся сразу после отсылки первого http запроса или TLS ClientHello. В случае http(s) останавливаемся сразу после отсылки первого http запроса или TLS ClientHello.
@@ -521,7 +515,7 @@ nfqws поддерживает реассемблинг некоторых ви
На текущий момент это TLS и QUIC ClientHello. Они бывает длинными, если в chrome включить пост-квантовую На текущий момент это TLS и QUIC ClientHello. Они бывает длинными, если в chrome включить пост-квантовую
криптографию tls-kyber, и занимают как правило 2 или 3 пакета. kyber включен по умолчанию, начиная с chromium 124. криптографию tls-kyber, и занимают как правило 2 или 3 пакета. kyber включен по умолчанию, начиная с chromium 124.
chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть
попасть любой пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом попасть в любой пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом
принимает решение о блокировке. принимает решение о блокировке.
В случае получения TLS или QUIC пакета с частичным ClientHello начинается процесс сборки, а пакеты В случае получения TLS или QUIC пакета с частичным ClientHello начинается процесс сборки, а пакеты
задерживаются и не отсылаются до ее окончания. По окончании сборки пакеты проходит через десинхронизацию задерживаются и не отсылаются до ее окончания. По окончании сборки пакеты проходит через десинхронизацию
@@ -761,95 +755,101 @@ iptables target `FLOWOFFLOAD` - это проприетарное изобрет
tpws - это transparent proxy. 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=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename> --debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
--daemon ; демонизировать прогу --dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
--pidfile=<file> ; сохранить PID в файл
--user=<username> ; менять uid процесса --daemon ; демонизировать прогу
--uid=uid[:gid] ; менять uid процесса --pidfile=<file> ; сохранить PID в файл
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес --user=<username> ; менять uid процесса
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan --uid=uid[:gid] ; менять uid процесса
--bind-linklocal=no|unwanted|prefer|force --bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес
; no : биндаться только на global ipv6 ; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
; unwanted (default) : предпочтительно global, если нет - LL --bind-linklocal=no|unwanted|prefer|force ; no : биндаться только на global ipv6
; prefer : предпочтительно LL, если нет - global ; unwanted (default) : предпочтительно global, если нет - LL
; force : биндаться только на LL ; prefer : предпочтительно LL, если нет - global
--bind-iface4=<iface> ; слушать на первом ipv4 интерфейса iface ; force : биндаться только на LL
--bind-iface6=<iface> ; слушать на первом ipv6 интерфейса iface --bind-iface4=<iface> ; слушать на первом ipv4 интерфейса iface
--bind-wait-ifup=<sec ; ждать до N секунд появления и поднятия интерфейса --bind-iface6=<iface> ; слушать на первом ipv6 интерфейса iface
--bind-wait-ip=<sec> ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса) --bind-wait-ifup=<sec> ; ждать до N секунд появления и поднятия интерфейса
--bind-wait-ip=<sec> ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса)
--bind-wait-ip-linklocal=<sec> --bind-wait-ip-linklocal=<sec>
; имеет смысл только при задании --bind-wait-ip ; имеет смысл только при задании --bind-wait-ip
; --bind-linklocal=unwanted : согласиться на LL после N секунд ; --bind-linklocal=unwanted : согласиться на LL после N секунд
; --bind-linklocal=prefer : согласиться на global address после N секунд ; --bind-linklocal=prefer : согласиться на global address после N секунд
--bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0. --bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0.
--connect-bind-addr ; с какого адреса подключаться во внешнюю сеть. может быть ipv4 или ipv6 адрес --connect-bind-addr ; с какого адреса подключаться во внешнюю сеть. может быть ipv4 или ipv6 адрес
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan ; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
; опция может повторяться для v4 и v6 адресов ; опция может повторяться для v4 и v6 адресов
; опция не отменяет правил маршрутизации ! выбор интерфейса определяется лишь правилами маршрутизации, кроме случая v6 link local. ; опция не отменяет правил маршрутизации ! выбор интерфейса определяется лишь правилами маршрутизации, кроме случая v6 link local.
--socks ; вместо прозрачного прокси реализовать socks4/5 proxy --socks ; вместо прозрачного прокси реализовать socks4/5 proxy
--no-resolve ; запретить ресолвинг имен через socks5 --no-resolve ; запретить ресолвинг имен через socks5
--resolve-threads ; количество потоков ресолвера --resolve-threads ; количество потоков ресолвера
--port=<port> ; на каком порту слушать --port=<port> ; на каком порту слушать
--maxconn=<max_connections> ; максимальное количество соединений от клиентов к прокси --maxconn=<max_connections> ; максимальное количество соединений от клиентов к прокси
--maxfiles=<max_open_files> ; макс количество файловых дескрипторов (setrlimit). мин требование (X*connections+16), где X=6 в tcp proxy mode, X=4 в режиме тамперинга. --maxfiles=<max_open_files> ; макс количество файловых дескрипторов (setrlimit). мин требование (X*connections+16), где X=6 в tcp proxy mode, X=4 в режиме тамперинга.
; стоит сделать запас с коэффициентом как минимум 1.5. по умолчанию maxfiles (X*connections)*1.5+16 ; стоит сделать запас с коэффициентом как минимум 1.5. по умолчанию maxfiles (X*connections)*1.5+16
--max-orphan-time=<sec> ; если вы запускаете через tpws торрент-клиент с множеством раздач, он пытается установить очень много исходящих соединений, --max-orphan-time=<sec> ; если вы запускаете через tpws торрент-клиент с множеством раздач, он пытается установить очень много исходящих соединений,
; большая часть из которых отваливается по таймауту (юзера сидят за NAT, firewall, ...) ; большая часть из которых отваливается по таймауту (юзера сидят за NAT, firewall, ...)
; установление соединения в linux может длиться очень долго. локальный конец отвалился, перед этим послав блок данных, ; установление соединения в linux может длиться очень долго. локальный конец отвалился, перед этим послав блок данных,
; tpws ждет подключения удаленного конца, чтобы отослать ему этот блок, и зависает надолго. ; tpws ждет подключения удаленного конца, чтобы отослать ему этот блок, и зависает надолго.
; настройка позволяет сбрасывать такие подключения через N секунд, теряя блок данных. по умолчанию 5 сек. 0 означает отключить функцию ; настройка позволяет сбрасывать такие подключения через N секунд, теряя блок данных. по умолчанию 5 сек. 0 означает отключить функцию
; эта функция не действует на успешно подключенные ранее соединения ; эта функция не действует на успешно подключенные ранее соединения
--local-rcvbuf=<bytes> ; SO_RCVBUF для соединений client-proxy --local-rcvbuf=<bytes> ; SO_RCVBUF для соединений client-proxy
--local-sndbuf=<bytes> ; SO_SNDBUF для соединений client-proxy --local-sndbuf=<bytes> ; SO_SNDBUF для соединений client-proxy
--remote-rcvbuf=<bytes> ; SO_RCVBUF для соединений proxy-target --remote-rcvbuf=<bytes> ; SO_RCVBUF для соединений proxy-target
--remote-sndbuf=<bytes> ; SO_SNDBUF для соединений proxy-target --remote-sndbuf=<bytes> ; SO_SNDBUF для соединений proxy-target
--nosplice ; не использовать splice на linux системах --nosplice ; не использовать splice на linux системах
--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split. --skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение) --local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение) --remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
--fix-seg=<int> ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс. --fix-seg=<int> ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс.
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации --split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS) --split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
--disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса --disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса
--oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита --oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита
--oob-data=<char>|0xHEX ; переопределить байт OOB. по умолчанию 0x00. --oob-data=<char>|0xHEX ; переопределить байт OOB. по умолчанию 0x00.
--hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:". --hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:".
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase --hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
--hostdot ; добавление точки после имени хоста : "Host: kinozal.tv." --hostdot ; добавление точки после имени хоста : "Host: kinozal.tv."
--hosttab ; добавление табуляции после имени хоста : "Host: kinozal.tv\t" --hosttab ; добавление табуляции после имени хоста : "Host: kinozal.tv\t"
--hostnospace ; убрать пробел после "Host:" --hostnospace ; убрать пробел после "Host:"
--hostpad=<bytes> ; добавить паддинг-хедеров общей длиной <bytes> перед Host: --hostpad=<bytes> ; добавить паддинг-хедеров общей длиной <bytes> перед Host:
--domcase ; домен после Host: сделать таким : TeSt.cOm --domcase ; домен после Host: сделать таким : TeSt.cOm
--methodspace ; добавить пробел после метода : "GET /" => "GET /" --methodspace ; добавить пробел после метода : "GET /" => "GET /"
--methodeol ; добавить перевод строки перед методом : "GET /" => "\r\nGET /" --methodeol ; добавить перевод строки перед методом : "GET /" => "\r\nGET /"
--unixeol ; конвертировать 0D0A в 0A и использовать везде 0A --unixeol ; конвертировать 0D0A в 0A и использовать везде 0A
--tlsrec=N|-N|marker+N|marker-N ; разбивка TLS ClientHello на 2 TLS records на указанной позиции. Минимальное смещение - 6. --tlsrec=N|-N|marker+N|marker-N ; разбивка TLS ClientHello на 2 TLS records на указанной позиции. Минимальное смещение - 6.
--mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость --mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость
--tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока) --tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока)
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока) --tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются. --hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
; в файле должен быть хост на каждой строке. ; в файле должен быть хост на каждой строке.
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска. ; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
; при изменении времени модификации файла он перечитывается автоматически по необходимости ; при изменении времени модификации файла он перечитывается автоматически по необходимости
; список может быть запакован в gzip. формат автоматически распознается и разжимается ; список может быть запакован в gzip. формат автоматически распознается и разжимается
; списков может быть множество. пустой общий лист = его отсутствие ; списков может быть множество. пустой общий лист = его отсутствие
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello. ; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам. --hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика) --hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3) --hostlist-exclude-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) --hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты. --hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
--new ; начало новой стратегии (новый профиль) --hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии --hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую. --new ; начало новой стратегии (новый профиль)
--skip ; не использовать этот профиль . полезно для временной деактивации профиля без удаления параметров.
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую.
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую. --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая. --ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-exclude=<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 ### TCP СЕГМЕНТАЦИЯ В TPWS

View File

@@ -101,10 +101,11 @@ There are several options :
Replace these 2 files in every location they are present. Replace these 2 files in every location they are present.
In `zapret-win-bundle` they are in `zapret-winws` и `blockcheck/zapret/nfq` folders. 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. 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. If you are in Russia or Belarus temporary change region in Control Panel.
### blockcheck ### blockcheck

View File

@@ -159,6 +159,7 @@ _windivert 2.2.2-A_, который идет в поставке zapret.
и заменить эти 2 файла. и заменить эти 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). В [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] > [!NOTE]
> Этот вариант проверен и должен работать. Тем не менее патч 10 летней давности, который включает SHA256 сигнатуры, все еще необходим. > Этот вариант проверен и должен работать. Тем не менее патч 10 летней давности, который включает SHA256 сигнатуры, все еще необходим.

View File

@@ -0,0 +1,22 @@
# This script fixes keenetic issue with nfqws generated udp packets
# Keenetic uses proprietary ndmmark and does not masquerade without this mark
# If not masqueraded packets go to WAN with LAN IP and get dropped by ISP
# It's advised to set IFACE_WAN in config
zapret_custom_firewall()
{
# $1 - 1 - add, 0 - stop
local wan wanif rule
[ "$DISABLE_IPV4" = "1" ] || {
# use IFACE_WAN if defined. if not - search for interfaces with default route.
wanif=${IFACE_WAN:-$(sed -nre 's/^([^\t]+)\t00000000\t[0-9A-F]{8}\t[0-9A-F]{4}\t[0-9]+\t[0-9]+\t[0-9]+\t00000000.*$/\1/p' /proc/net/route | sort -u | xargs)}
for wan in $wanif; do
rule="-o $wan -p udp -m mark --mark $DESYNC_MARK/$DESYNC_MARK"
ipt_print_op $1 "$rule" "keenetic udp fix"
ipt_add_del $1 POSTROUTING -t nat $rule -j MASQUERADE
done
}
}

View File

@@ -102,7 +102,7 @@ dnat6_target()
} }
set_route_localnet() set_route_localnet()
{ {
_set_route_localnet $1 "$IFACE_LAN" _set_route_localnet $1 $IFACE_LAN
} }
fw_nfqws_post4() fw_nfqws_post4()
@@ -167,9 +167,15 @@ run_daemon()
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile # use $PIDDIR/$DAEMONBASE$1.pid as pidfile
local DAEMONBASE="$(basename "$2")" local DAEMONBASE="$(basename "$2")"
local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid local PID= PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
echo "Starting daemon $1: $2 $3" 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 echo already running
else else
"$2" $3 >/dev/null & "$2" $3 >/dev/null &
@@ -188,18 +194,14 @@ stop_daemon()
# $2 - daemon # $2 - daemon
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile # use $PIDDIR/$DAEMONBASE$1.pid as pidfile
local DAEMONBASE="$(basename "$2")" local DAEMONBASE="$(basename "$2")"
local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid local PID PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
echo "Stopping daemon $1: $2" echo "Stopping daemon $1: $2"
if exists start-stop-daemon ; then if [ -f "$PIDFILE" ]; then
start-stop-daemon -K -p "$PIDFILE" -x "$2" read PID <"$PIDFILE"
kill $PID
rm -f "$PIDFILE"
else else
if [ -f "$PIDFILE" ]; then echo no pidfile : $PIDFILE
read PID <"$PIDFILE"
kill $PID
rm -f "$PIDFILE"
else
echo no pidfile : $PIDFILE
fi
fi fi
} }
do_daemon() do_daemon()

View File

@@ -68,7 +68,7 @@ case $UNAME in
;; ;;
CYGWIN*) CYGWIN*)
UNAME=CYGWIN UNAME=CYGWIN
ARCHLIST="win64" ARCHLIST="win64 win32"
PKTWS=winws PKTWS=winws
;; ;;
*) *)

View File

@@ -26,6 +26,7 @@ IPSET_DIR="$ZAPRET_BASE/ipset"
. "$ZAPRET_BASE/common/ipt.sh" . "$ZAPRET_BASE/common/ipt.sh"
. "$ZAPRET_BASE/common/installer.sh" . "$ZAPRET_BASE/common/installer.sh"
. "$ZAPRET_BASE/common/virt.sh" . "$ZAPRET_BASE/common/virt.sh"
. "$ZAPRET_BASE/common/list.sh"
GET_LIST="$IPSET_DIR/get_config.sh" GET_LIST="$IPSET_DIR/get_config.sh"
@@ -115,6 +116,30 @@ ws_opt_validate()
} }
return 0 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() select_mode_group()
{ {
@@ -162,18 +187,17 @@ select_mode_group()
select_mode_tpws_socks() select_mode_tpws_socks()
{ {
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_SOCKS_OPT" 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" tpws_socks_opt_validate TPWS_SOCKS_OPT
select_mode_group TPWS_SOCKS_ENABLE "enable tpws socks mode on port $TPPORT_SOCKS ?" "TPPORT_SOCKS TPWS_SOCKS_OPT"
} }
select_mode_tpws() select_mode_tpws()
{ {
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_OPT" 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() select_mode_nfqws()
{ {
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="NFQWS_OPT" 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() select_mode_mode()

View File

@@ -1,5 +1,5 @@
CC ?= gcc CC ?= gcc
CFLAGS += -std=gnu99 -Os CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_BSD = -Wno-address-of-packed-member CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_WIN = -static CFLAGS_WIN = -static
LIBS = LIBS =

View File

@@ -192,7 +192,7 @@ static void ip6_and(const struct in6_addr * restrict a, const struct in6_addr *
static void rtrim(char *s) static void rtrim(char *s)
{ {
if (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); 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[]) static void parse_params(int argc, char *argv[])
{ {
int option_index = 0; int option_index = 0;
@@ -245,6 +253,7 @@ static void parse_params(int argc, char *argv[])
{ {
case 0: case 0:
case 1: case 1:
PRINT_VER;
exithelp(); exithelp();
break; break;
case 2: case 2:

View 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

View File

@@ -35,7 +35,7 @@
static void trimstr(char *s) static void trimstr(char *s)
{ {
char *p; 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) static const char* eai_str(int r)
@@ -458,6 +458,15 @@ static void exithelp(void)
); );
exit(1); 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 main(int argc, char **argv)
{ {
int r, v, option_index = 0; int r, v, option_index = 0;
@@ -487,6 +496,7 @@ int main(int argc, char **argv)
switch (option_index) switch (option_index)
{ {
case 0: /* help */ case 0: /* help */
PRINT_VER;
exithelp(); exithelp();
break; break;
case 1: /* threads */ case 1: /* threads */

View File

@@ -1,5 +1,5 @@
CC ?= cc CC ?= cc
CFLAGS += -std=gnu99 -s -Os -Wno-address-of-packed-member CFLAGS += -std=gnu99 -s -Os -Wno-address-of-packed-member -flto=auto
LIBS = -lz LIBS = -lz
SRC_FILES = *.c crypto/*.c SRC_FILES = *.c crypto/*.c

View File

@@ -1,7 +1,6 @@
CC ?= gcc CC ?= gcc
CFLAGS += -std=gnu99 -Os CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_BSD = -Wno-address-of-packed-member CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_MAC = -mmacosx-version-min=10.8
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
LIBS_BSD = -lz LIBS_BSD = -lz

View File

@@ -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)); 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) 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; verdict=VERDICT_MODIFY;
} }
uint8_t *pua; uint8_t *pua;
if (dp->hostnospace && 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)))
{ {
DLOG("removing space after Host: and adding it to User-Agent:\n"); if ((pua = (uint8_t*)memmem(dis->data_payload, dis->len_payload, "\r\nUser-Agent: ", 14)) &&
if (pua > phost) (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); DLOG("removing space after Host: and adding it to User-Agent:\n");
pua[-1]=' '; 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 else
{ DLOG("cannot do hostnospace because valid User-Agent: not found\n");
memmove(pua + 1, pua, phost - pua + 5);
*pua = ' ';
}
verdict=VERDICT_MODIFY;
} }
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) if (dp->desync_mode==DESYNC_NONE)
@@ -1395,7 +1412,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (i==0) if (i==0)
{ {
if (seqovl_pos>=from) if (seqovl_pos>=from)
DLOG("seqovl>=split_pos (%u>=%zu). cancelling seqovl for part %d.\n",seqovl,from,i+2); DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl for part %d.\n",seqovl,from,i+2);
else else
{ {
seqovl = seqovl_pos; seqovl = seqovl_pos;
@@ -1432,15 +1449,22 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_FAKEDDISORDER: case DESYNC_FAKEDDISORDER:
if (split_pos) if (split_pos)
{ {
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg; uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100], fakeseg2[DPI_DESYNC_MAX_FAKE_LEN+100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg;
size_t seg_len; size_t seg_len,fakeseg2_len;
unsigned int seqovl; 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); ip_id = IP4_IP_ID_FIX(dis->ip);
if (seqovl_pos>=split_pos) if (seqovl_pos>=split_pos)
{ {
DLOG("seqovl>=split_pos (%u>=%zu). cancelling seqovl.\n",seqovl_pos,split_pos); DLOG("seqovl>=split_pos (%zu>=%zu). cancelling seqovl.\n",seqovl_pos,split_pos);
seqovl = 0; seqovl = 0;
} }
else else
@@ -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 = dis->data_payload+split_pos;
seg_len = dis->len_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); 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, 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), 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)) if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
return verdict; 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); 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, 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), 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, 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; return verdict;
ip_id=IP4_IP_ID_PREV(ip_id); ip_id=IP4_IP_ID_PREV(ip_id);
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
hexdump_limited_dlog(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)) if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len))
return verdict; 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; 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); 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)) if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len))
return verdict; return verdict;
@@ -1511,20 +1556,27 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_FAKEDSPLIT: case DESYNC_FAKEDSPLIT:
if (split_pos) 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; 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); ip_id = IP4_IP_ID_FIX(dis->ip);
fakeseg_len = sizeof(fakeseg); 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, 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), 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, 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; return verdict;
ip_id=IP4_IP_ID_NEXT(ip_id); ip_id=IP4_IP_ID_NEXT(ip_id);
DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
hexdump_limited_dlog(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)) if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
return verdict; 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; if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
ip_id=IP4_IP_ID_NEXT(ip_id); ip_id=IP4_IP_ID_NEXT(ip_id);
DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos); DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
hexdump_limited_dlog(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)) if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
return verdict; 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, fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
dis->data_payload+split_pos, dis->len_payload-split_pos, pkt1, &pkt1_len)) dis->data_payload+split_pos, dis->len_payload-split_pos, pkt1, &pkt1_len))
return verdict; 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); DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
hexdump_limited_dlog(dis->data_payload+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n"); hexdump_limited_dlog(dis->data_payload+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len)) if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
return verdict; 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; return VERDICT_DROP;
} }
break; break;

View File

@@ -24,7 +24,7 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
*hostlist = NULL; *hostlist = NULL;
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
// advance to the next line // advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++); 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; return true;
} }
bool AppendHostlistItem(strpool **hostlist, char *s)
{
return addpool(hostlist,&s,s+strlen(s),NULL);
}
bool AppendHostList(strpool **hostlist, const char *filename) bool AppendHostList(strpool **hostlist, const char *filename)
{ {
char *p, *e, s[256], *zbuf; char *p, *e, s[256], *zbuf;
@@ -98,21 +103,24 @@ bool AppendHostList(strpool **hostlist, const char *filename)
static bool LoadHostList(struct hostlist_file *hfile) static bool LoadHostList(struct hostlist_file *hfile)
{ {
time_t t = file_mod_time(hfile->filename); if (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))
{ {
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); 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; return true;
} }
static bool LoadHostLists(struct hostlist_files_head *list) 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) 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 (SearchHostList(item->hfile->hostlist, host))
{ {
if (excluded) *excluded = true; if (excluded) *excluded = true;
@@ -214,7 +222,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
{ {
LIST_FOREACH(item, hostlists, next) 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)) if (SearchHostList(item->hfile->hostlist, host))
return true; 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) static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
{ {
struct hostlist_file *hfile; 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; return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile)) if (!hostlist_collection_add(hl_collection, hfile))
return NULL; return NULL;
}
return hfile; return hfile;
} }
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename) 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); DLOG_ERR("cannot access hostlist file '%s'\n",filename);
return NULL; return NULL;
@@ -265,15 +285,30 @@ void HostlistsDebug()
struct hostlist_item *hl_item; struct hostlist_item *hl_item;
LIST_FOREACH(hfile, &params.hostlists, next) LIST_FOREACH(hfile, &params.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, &params.desync_profiles, next) LIST_FOREACH(dpl, &params.desync_profiles, next)
{ {
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next) LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
if (hl_item->hfile!=dpl->dp.hostlist_auto) 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) 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) 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)"); DLOG("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
} }

View File

@@ -4,6 +4,7 @@
#include "pools.h" #include "pools.h"
#include "params.h" #include "params.h"
bool AppendHostlistItem(strpool **hostlist, char *s);
bool AppendHostList(strpool **hostlist, const char *filename); bool AppendHostList(strpool **hostlist, const char *filename);
bool LoadAllHostLists(); bool LoadAllHostLists();
bool NonEmptyHostlist(strpool **hostlist); bool NonEmptyHostlist(strpool **hostlist);

View File

@@ -31,7 +31,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips); ipsetDestroy(ips);
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
else if (parse_cidr6(cidr,&c6)) else if (parse_cidr6(cidr,&c6))
{ {
@@ -40,7 +40,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips); ipsetDestroy(ips);
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
else else
DLOG_ERR("bad ip or subnet : %s\n",cidr); 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) static bool AppendIpset(ipset *ips, const char *filename)
{ {
char *p, *e, s[256], *zbuf; 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) static bool LoadIpset(struct ipset_file *hfile)
{ {
time_t t = file_mod_time(hfile->filename); if (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))
{ {
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); 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; return true;
} }
static bool LoadIpsets(struct ipset_files_head *list) 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) 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)) if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return false; return false;
} }
@@ -214,7 +222,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
{ {
LIST_FOREACH(item, ips, next) 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)) if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return true; 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) static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
{ {
struct ipset_file *hfile; struct ipset_file *hfile;
if (!(hfile=ipset_files_search(ipsets, filename))) if (filename)
if (!(hfile=ipset_files_add(ipsets, 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; return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile)) if (!ipset_collection_add(ips_collection, hfile))
return NULL; return NULL;
}
return hfile; return hfile;
} }
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename) 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); DLOG_ERR("cannot access ipset file '%s'\n",filename);
return NULL; return NULL;
@@ -277,13 +295,24 @@ void IpsetsDebug()
struct ipset_item *ips_item; struct ipset_item *ips_item;
LIST_FOREACH(hfile, &params.ipsets, next) LIST_FOREACH(hfile, &params.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, &params.desync_profiles, next) LIST_FOREACH(dpl, &params.desync_profiles, next)
{ {
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, 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) 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));
} }
} }

View File

@@ -9,3 +9,4 @@ bool LoadAllIpsets();
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6); 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); struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
void IpsetsDebug(); void IpsetsDebug();
bool AppendIpsetItem(ipset *ips, char *ip);

View File

@@ -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 if (p) return false; // too much splits
return true; 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) static void split_compat(struct desync_profile *dp)
{ {
if (!dp->split_count) 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" " @<config_file>|$<config_file>\t\t\t; read file for options. must be the only argument. other options are ignored.\n\n"
#endif #endif
" --debug=0|1|syslog|@<filename>\n" " --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__ #ifdef __linux__
" --qnum=<nfqueue_number>\n" " --qnum=<nfqueue_number>\n"
#elif defined(BSD) #elif defined(BSD)
@@ -1020,15 +1062,20 @@ static void exithelp(void)
#endif #endif
"\nMULTI-STRATEGY:\n" "\nMULTI-STRATEGY:\n"
" --new\t\t\t\t\t\t; begin new strategy\n" " --new\t\t\t\t\t\t; 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-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-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-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" " --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=<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=<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" "\nHOSTLIST FILTER:\n"
" --hostlist=<filename>\t\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n" " --hostlist=<filename>\t\t\t\t; 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=<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=<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-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" " --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" " --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" " --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" " --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" " --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; synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1\n"
"\t\t\t\t\t\t; multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper\n" "\t\t\t\t\t\t; 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" "\t\t\t\t\t\t; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise\n"
" --dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment\n" " --dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment\n"
" --dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap\n" " --dpi-desync-split-seqovl-pattern=<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-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-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" " --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 #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) int main(int argc, char **argv)
{ {
set_env_exedir(argv[0]); set_env_exedir(argv[0]);
@@ -1139,8 +1196,10 @@ int main(int argc, char **argv)
#endif #endif
int result, v; int result, v;
int option_index = 0; int option_index = 0;
bool daemon = false; bool daemon = false, bSkip = false, bDry = false;
char pidfile[256]; 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__ #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]; 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; bool wf_ipv4=true, wf_ipv6=true;
@@ -1152,6 +1211,8 @@ int main(int argc, char **argv)
srandom(time(NULL)); srandom(time(NULL));
mask_from_preflen6_prepare(); mask_from_preflen6_prepare();
PRINT_VER;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
*pidfile = 0; *pidfile = 0;
@@ -1203,101 +1264,113 @@ int main(int argc, char **argv)
const struct option long_options[] = { const struct option long_options[] = {
{"debug",optional_argument,0,0}, // optidx=0 {"debug",optional_argument,0,0}, // optidx=0
{"dry-run",no_argument,0,0}, // optidx=1
#ifdef __linux__ #ifdef __linux__
{"qnum",required_argument,0,0}, // optidx=1 {"qnum",required_argument,0,0}, // optidx=2
#elif defined(BSD) #elif defined(BSD)
{"port",required_argument,0,0}, // optidx=1 {"port",required_argument,0,0}, // optidx=2
#else #else
{"disabled_argument_1",no_argument,0,0},// optidx=1 {"disabled_argument_1",no_argument,0,0},// optidx=2
#endif #endif
{"daemon",no_argument,0,0}, // optidx=2 {"daemon",no_argument,0,0}, // optidx=3
{"pidfile",required_argument,0,0}, // optidx=3 {"pidfile",required_argument,0,0}, // optidx=4
#ifndef __CYGWIN__ #ifndef __CYGWIN__
{"user",required_argument,0,0 }, // optidx=4 {"user",required_argument,0,0 }, // optidx=5
{"uid",required_argument,0,0 }, // optidx=5 {"uid",required_argument,0,0 }, // optidx=6
#else #else
{"disabled_argument_2",no_argument,0,0}, // optidx=4 {"disabled_argument_2",no_argument,0,0}, // optidx=5
{"disabled_argument_3",no_argument,0,0}, // optidx=5 {"disabled_argument_3",no_argument,0,0}, // optidx=6
#endif #endif
{"wsize",required_argument,0,0}, // optidx=6 {"wsize",required_argument,0,0}, // optidx=7
{"wssize",required_argument,0,0}, // optidx=7 {"wssize",required_argument,0,0}, // optidx=8
{"wssize-cutoff",required_argument,0,0},// optidx=8 {"wssize-cutoff",required_argument,0,0},// optidx=9
{"ctrack-timeouts",required_argument,0,0},// optidx=9 {"ctrack-timeouts",required_argument,0,0},// optidx=10
{"hostcase",no_argument,0,0}, // optidx=10 {"hostcase",no_argument,0,0}, // optidx=11
{"hostspell",required_argument,0,0}, // optidx=11 {"hostspell",required_argument,0,0}, // optidx=12
{"hostnospace",no_argument,0,0}, // optidx=12 {"hostnospace",no_argument,0,0}, // optidx=13
{"domcase",no_argument,0,0 }, // optidx=13 {"domcase",no_argument,0,0 }, // optidx=14
{"dpi-desync",required_argument,0,0}, // optidx=14 {"methodeol",no_argument,0,0 }, // optidx=15
{"dpi-desync",required_argument,0,0}, // optidx=17
#ifdef __linux__ #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) #elif defined(SO_USER_COOKIE)
{"dpi-desync-sockarg",required_argument,0,0}, // optidx=15 {"dpi-desync-sockarg",required_argument,0,0}, // optidx=17
#else #else
{"disabled_argument_4",no_argument,0,0}, // optidx=15 {"disabled_argument_4",no_argument,0,0}, // optidx=17
#endif #endif
{"dpi-desync-ttl",required_argument,0,0}, // optidx=16 {"dpi-desync-ttl",required_argument,0,0}, // optidx=18
{"dpi-desync-ttl6",required_argument,0,0}, // optidx=17 {"dpi-desync-ttl6",required_argument,0,0}, // optidx=19
{"dpi-desync-autottl",optional_argument,0,0}, // optidx=18 {"dpi-desync-autottl",optional_argument,0,0}, // optidx=20
{"dpi-desync-autottl6",optional_argument,0,0}, // optidx=19 {"dpi-desync-autottl6",optional_argument,0,0}, // optidx=21
{"dpi-desync-fooling",required_argument,0,0}, // optidx=20 {"dpi-desync-fooling",required_argument,0,0}, // optidx=22
{"dpi-desync-repeats",required_argument,0,0}, // optidx=21 {"dpi-desync-repeats",required_argument,0,0}, // optidx=23
{"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=22 {"dpi-desync-skip-nosni",optional_argument,0,0},// optidx=24
{"dpi-desync-split-pos",required_argument,0,0},// optidx=23 {"dpi-desync-split-pos",required_argument,0,0},// optidx=25
{"dpi-desync-split-http-req",required_argument,0,0 },// optidx=24 {"dpi-desync-split-http-req",required_argument,0,0 },// optidx=26
{"dpi-desync-split-tls",required_argument,0,0 },// optidx=25 {"dpi-desync-split-tls",required_argument,0,0 },// optidx=27
{"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=26 {"dpi-desync-split-seqovl",required_argument,0,0 },// optidx=28
{"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=27 {"dpi-desync-split-seqovl-pattern",required_argument,0,0 },// optidx=29
{"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=28 {"dpi-desync-fakedsplit-pattern",required_argument,0,0 },// optidx=30
{"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=29 {"dpi-desync-ipfrag-pos-tcp",required_argument,0,0},// optidx=31
{"dpi-desync-badseq-increment",required_argument,0,0},// optidx=30 {"dpi-desync-ipfrag-pos-udp",required_argument,0,0},// optidx=32
{"dpi-desync-badack-increment",required_argument,0,0},// optidx=31 {"dpi-desync-badseq-increment",required_argument,0,0},// optidx=33
{"dpi-desync-any-protocol",optional_argument,0,0},// optidx=32 {"dpi-desync-badack-increment",required_argument,0,0},// optidx=34
{"dpi-desync-fake-http",required_argument,0,0},// optidx=33 {"dpi-desync-any-protocol",optional_argument,0,0},// optidx=35
{"dpi-desync-fake-tls",required_argument,0,0},// optidx=34 {"dpi-desync-fake-http",required_argument,0,0},// optidx=36
{"dpi-desync-fake-unknown",required_argument,0,0},// optidx=35 {"dpi-desync-fake-tls",required_argument,0,0},// optidx=37
{"dpi-desync-fake-syndata",required_argument,0,0},// optidx=36 {"dpi-desync-fake-unknown",required_argument,0,0},// optidx=38
{"dpi-desync-fake-quic",required_argument,0,0},// optidx=37 {"dpi-desync-fake-syndata",required_argument,0,0},// optidx=39
{"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=38 {"dpi-desync-fake-quic",required_argument,0,0},// optidx=40
{"dpi-desync-fake-dht",required_argument,0,0},// optidx=39 {"dpi-desync-fake-wireguard",required_argument,0,0},// optidx=41
{"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=40 {"dpi-desync-fake-dht",required_argument,0,0},// optidx=42
{"dpi-desync-udplen-increment",required_argument,0,0},// optidx=41 {"dpi-desync-fake-unknown-udp",required_argument,0,0},// optidx=43
{"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=42 {"dpi-desync-udplen-increment",required_argument,0,0},// optidx=44
{"dpi-desync-cutoff",required_argument,0,0},// optidx=43 {"dpi-desync-udplen-pattern",required_argument,0,0},// optidx=45
{"dpi-desync-start",required_argument,0,0},// optidx=43 {"dpi-desync-cutoff",required_argument,0,0},// optidx=46
{"hostlist",required_argument,0,0}, // optidx=44 {"dpi-desync-start",required_argument,0,0},// optidx=47
{"hostlist-exclude",required_argument,0,0}, // optidx=45 {"hostlist",required_argument,0,0}, // optidx=48
{"hostlist-auto",required_argument,0,0}, // optidx=46 {"hostlist-domains",required_argument,0,0},// optidx=49
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=48 {"hostlist-exclude",required_argument,0,0}, // optidx=50
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=49 {"hostlist-exclude-domains",required_argument,0,0},// optidx=51
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=50 {"hostlist-auto",required_argument,0,0}, // optidx=52
{"hostlist-auto-debug",required_argument,0,0}, // optidx=51 {"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=53
{"new",no_argument,0,0}, // optidx=52 {"hostlist-auto-fail-time",required_argument,0,0}, // optidx=54
{"filter-l3",required_argument,0,0}, // optidx=53 {"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=55
{"filter-tcp",required_argument,0,0}, // optidx=54 {"hostlist-auto-debug",required_argument,0,0}, // optidx=56
{"filter-udp",required_argument,0,0}, // optidx=55 {"new",no_argument,0,0}, // optidx=57
{"filter-l7",required_argument,0,0}, // optidx=56 {"skip",no_argument,0,0}, // optidx=58
{"ipset",required_argument,0,0}, // optidx=57 {"filter-l3",required_argument,0,0}, // optidx=59
{"ipset-exclude",required_argument,0,0},// optidx=58 {"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__ #ifdef __linux__
{"bind-fix4",no_argument,0,0}, // optidx=59 {"bind-fix4",no_argument,0,0}, // optidx=67
{"bind-fix6",no_argument,0,0}, // optidx=60 {"bind-fix6",no_argument,0,0}, // optidx=68
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
{"wf-iface",required_argument,0,0}, // optidx=59 {"wf-iface",required_argument,0,0}, // optidx=67
{"wf-l3",required_argument,0,0}, // optidx=60 {"wf-l3",required_argument,0,0}, // optidx=68
{"wf-tcp",required_argument,0,0}, // optidx=61 {"wf-tcp",required_argument,0,0}, // optidx=69
{"wf-udp",required_argument,0,0}, // optidx=62 {"wf-udp",required_argument,0,0}, // optidx=70
{"wf-raw",required_argument,0,0}, // optidx=63 {"wf-raw",required_argument,0,0}, // optidx=71
{"wf-save",required_argument,0,0}, // optidx=64 {"wf-save",required_argument,0,0}, // optidx=72
{"ssid-filter",required_argument,0,0}, // optidx=65 {"ssid-filter",required_argument,0,0}, // optidx=73
{"nlm-filter",required_argument,0,0}, // optidx=66 {"nlm-filter",required_argument,0,0}, // optidx=74
{"nlm-list",optional_argument,0,0}, // optidx=67 {"nlm-list",optional_argument,0,0}, // optidx=75
#endif #endif
{NULL,0,NULL,0} {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) 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) switch (option_index)
{ {
case 0: /* debug */ case 0: /* debug */
@@ -1335,7 +1408,10 @@ int main(int argc, char **argv)
} }
break; break;
#ifndef __CYGWIN__ #ifndef __CYGWIN__
case 1: /* qnum or port */ case 1: /* dry-run */
bDry=true;
break;
case 2: /* qnum or port */
#ifdef __linux__ #ifdef __linux__
params.qnum = atoi(optarg); params.qnum = atoi(optarg);
if (params.qnum < 0 || params.qnum>65535) if (params.qnum < 0 || params.qnum>65535)
@@ -1356,15 +1432,15 @@ int main(int argc, char **argv)
#endif #endif
break; break;
#endif #endif
case 2: /* daemon */ case 3: /* daemon */
daemon = true; daemon = true;
break; break;
case 3: /* pidfile */ case 4: /* pidfile */
strncpy(pidfile, optarg, sizeof(pidfile)); strncpy(pidfile, optarg, sizeof(pidfile));
pidfile[sizeof(pidfile) - 1] = '\0'; pidfile[sizeof(pidfile) - 1] = '\0';
break; break;
#ifndef __CYGWIN__ #ifndef __CYGWIN__
case 4: /* user */ case 5: /* user */
{ {
struct passwd *pwd = getpwnam(optarg); struct passwd *pwd = getpwnam(optarg);
if (!pwd) if (!pwd)
@@ -1377,7 +1453,7 @@ int main(int argc, char **argv)
params.droproot = true; params.droproot = true;
break; break;
} }
case 5: /* uid */ case 6: /* uid */
params.gid = 0x7FFFFFFF; // default gid. drop gid=0 params.gid = 0x7FFFFFFF; // default gid. drop gid=0
params.droproot = true; params.droproot = true;
if (sscanf(optarg, "%u:%u", &params.uid, &params.gid)<1) if (sscanf(optarg, "%u:%u", &params.uid, &params.gid)<1)
@@ -1387,32 +1463,32 @@ int main(int argc, char **argv)
} }
break; break;
#endif #endif
case 6: /* wsize */ case 7: /* wsize */
if (!parse_ws_scale_factor(optarg,&dp->wsize,&dp->wscale)) if (!parse_ws_scale_factor(optarg,&dp->wsize,&dp->wscale))
exit_clean(1); exit_clean(1);
break; break;
case 7: /* wssize */ case 8: /* wssize */
if (!parse_ws_scale_factor(optarg,&dp->wssize,&dp->wsscale)) if (!parse_ws_scale_factor(optarg,&dp->wssize,&dp->wsscale))
exit_clean(1); exit_clean(1);
break; break;
case 8: /* wssize-cutoff */ case 9: /* wssize-cutoff */
if (!parse_cutoff(optarg, &dp->wssize_cutoff, &dp->wssize_cutoff_mode)) if (!parse_cutoff(optarg, &dp->wssize_cutoff, &dp->wssize_cutoff_mode))
{ {
DLOG_ERR("invalid wssize-cutoff value\n"); DLOG_ERR("invalid wssize-cutoff value\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 9: /* ctrack-timeouts */ case 10: /* ctrack-timeouts */
if (sscanf(optarg, "%u:%u:%u:%u", &params.ctrack_t_syn, &params.ctrack_t_est, &params.ctrack_t_fin, &params.ctrack_t_udp)<3) if (sscanf(optarg, "%u:%u:%u:%u", &params.ctrack_t_syn, &params.ctrack_t_est, &params.ctrack_t_fin, &params.ctrack_t_udp)<3)
{ {
DLOG_ERR("invalid ctrack-timeouts value\n"); DLOG_ERR("invalid ctrack-timeouts value\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 10: /* hostcase */ case 11: /* hostcase */
dp->hostcase = true; dp->hostcase = true;
break; break;
case 11: /* hostspell */ case 12: /* hostspell */
if (strlen(optarg) != 4) if (strlen(optarg) != 4)
{ {
DLOG_ERR("hostspell must be exactly 4 chars long\n"); DLOG_ERR("hostspell must be exactly 4 chars long\n");
@@ -1421,13 +1497,26 @@ int main(int argc, char **argv)
dp->hostcase = true; dp->hostcase = true;
memcpy(dp->hostspell, optarg, 4); memcpy(dp->hostspell, optarg, 4);
break; break;
case 12: /* hostnospace */ case 13: /* hostnospace */
if (dp->methodeol)
{
DLOG_ERR("--hostnospace and --methodeol are incompatible\n");
exit_clean(1);
}
dp->hostnospace = true; dp->hostnospace = true;
break; break;
case 13: /* domcase */ case 14: /* domcase */
dp->domcase = true; dp->domcase = true;
break; 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; char *mode=optarg,*mode2,*mode3;
mode2 = mode ? strchr(mode,',') : NULL; mode2 = mode ? strchr(mode,',') : NULL;
@@ -1473,7 +1562,7 @@ int main(int argc, char **argv)
} }
break; break;
#ifndef __CYGWIN__ #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) #if defined(__linux__) || defined(SO_USER_COOKIE)
params.desync_fwmark = 0; params.desync_fwmark = 0;
if (sscanf(optarg, "0x%X", &params.desync_fwmark)<=0) sscanf(optarg, "%u", &params.desync_fwmark); if (sscanf(optarg, "0x%X", &params.desync_fwmark)<=0) sscanf(optarg, "%u", &params.desync_fwmark);
@@ -1488,27 +1577,27 @@ int main(int argc, char **argv)
#endif #endif
break; break;
#endif #endif
case 16: /* dpi-desync-ttl */ case 18: /* dpi-desync-ttl */
dp->desync_ttl = (uint8_t)atoi(optarg); dp->desync_ttl = (uint8_t)atoi(optarg);
break; break;
case 17: /* dpi-desync-ttl6 */ case 19: /* dpi-desync-ttl6 */
dp->desync_ttl6 = (uint8_t)atoi(optarg); dp->desync_ttl6 = (uint8_t)atoi(optarg);
break; break;
case 18: /* dpi-desync-autottl */ case 20: /* dpi-desync-autottl */
if (!parse_autottl(optarg, &dp->desync_autottl)) if (!parse_autottl(optarg, &dp->desync_autottl))
{ {
DLOG_ERR("dpi-desync-autottl value error\n"); DLOG_ERR("dpi-desync-autottl value error\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 19: /* dpi-desync-autottl6 */ case 21: /* dpi-desync-autottl6 */
if (!parse_autottl(optarg, &dp->desync_autottl6)) if (!parse_autottl(optarg, &dp->desync_autottl6))
{ {
DLOG_ERR("dpi-desync-autottl6 value error\n"); DLOG_ERR("dpi-desync-autottl6 value error\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 20: /* dpi-desync-fooling */ case 22: /* dpi-desync-fooling */
{ {
char *e,*p = optarg; char *e,*p = optarg;
while (p) while (p)
@@ -1543,17 +1632,17 @@ int main(int argc, char **argv)
} }
} }
break; 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) 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"); DLOG_ERR("dpi-desync-repeats must be within 1..20\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 22: /* dpi-desync-skip-nosni */ case 24: /* dpi-desync-skip-nosni */
dp->desync_skip_nosni = !optarg || atoi(optarg); dp->desync_skip_nosni = !optarg || atoi(optarg);
break; break;
case 23: /* dpi-desync-split-pos */ case 25: /* dpi-desync-split-pos */
{ {
int ct; int ct;
if (!parse_split_pos_list(optarg,dp->splits+dp->split_count,MAX_SPLITS-dp->split_count,&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; dp->split_count += ct;
} }
break; break;
case 24: /* dpi-desync-split-http-req */ case 26: /* dpi-desync-split-http-req */
// obsolete arg // obsolete arg
DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS); DLOG_CONDUP("WARNING ! --dpi-desync-split-http-req is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS);
if (dp->split_count>=MAX_SPLITS) if (dp->split_count>=MAX_SPLITS)
@@ -1579,7 +1668,7 @@ int main(int argc, char **argv)
} }
dp->split_count++; dp->split_count++;
break; break;
case 25: /* dpi-desync-split-tls */ case 27: /* dpi-desync-split-tls */
// obsolete arg // obsolete arg
DLOG_CONDUP("WARNING ! --dpi-desync-split-tls is deprecated. use --dpi-desync-split-pos with markers.\n",MAX_SPLITS); 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) if (dp->split_count>=MAX_SPLITS)
@@ -1594,7 +1683,7 @@ int main(int argc, char **argv)
} }
dp->split_count++; dp->split_count++;
break; break;
case 26: /* dpi-desync-split-seqovl */ case 28: /* dpi-desync-split-seqovl */
if (!strcmp(optarg,"0")) if (!strcmp(optarg,"0"))
{ {
// allow zero = disable seqovl // allow zero = disable seqovl
@@ -1607,7 +1696,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 27: /* dpi-desync-split-seqovl-pattern */ case 29: /* dpi-desync-split-seqovl-pattern */
{ {
char buf[sizeof(dp->seqovl_pattern)]; char buf[sizeof(dp->seqovl_pattern)];
size_t sz=sizeof(buf); 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); fill_pattern(dp->seqovl_pattern,sizeof(dp->seqovl_pattern),buf,sz);
} }
break; 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) 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); 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); exit_clean(1);
} }
break; 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) 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); 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); exit_clean(1);
} }
break; break;
case 30: /* dpi-desync-badseq-increments */ case 33: /* dpi-desync-badseq-increments */
if (!parse_badseq_increment(optarg,&dp->desync_badseq_increment)) if (!parse_badseq_increment(optarg,&dp->desync_badseq_increment))
{ {
DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n"); DLOG_ERR("dpi-desync-badseq-increment should be signed decimal or signed 0xHEX\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 31: /* dpi-desync-badack-increment */ case 34: /* dpi-desync-badack-increment */
if (!parse_badseq_increment(optarg,&dp->desync_badseq_ack_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"); DLOG_ERR("dpi-desync-badack-increment should be signed decimal or signed 0xHEX\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 32: /* dpi-desync-any-protocol */ case 35: /* dpi-desync-any-protocol */
dp->desync_any_proto = !optarg || atoi(optarg); dp->desync_any_proto = !optarg || atoi(optarg);
break; break;
case 33: /* dpi-desync-fake-http */ case 36: /* dpi-desync-fake-http */
dp->fake_http_size = sizeof(dp->fake_http); dp->fake_http_size = sizeof(dp->fake_http);
load_file_or_exit(optarg,dp->fake_http,&dp->fake_http_size); load_file_or_exit(optarg,dp->fake_http,&dp->fake_http_size);
break; break;
case 34: /* dpi-desync-fake-tls */ case 37: /* dpi-desync-fake-tls */
dp->fake_tls_size = sizeof(dp->fake_tls); dp->fake_tls_size = sizeof(dp->fake_tls);
load_file_or_exit(optarg,dp->fake_tls,&dp->fake_tls_size); load_file_or_exit(optarg,dp->fake_tls,&dp->fake_tls_size);
break; break;
case 35: /* dpi-desync-fake-unknown */ case 38: /* dpi-desync-fake-unknown */
dp->fake_unknown_size = sizeof(dp->fake_unknown); dp->fake_unknown_size = sizeof(dp->fake_unknown);
load_file_or_exit(optarg,dp->fake_unknown,&dp->fake_unknown_size); load_file_or_exit(optarg,dp->fake_unknown,&dp->fake_unknown_size);
break; break;
case 36: /* dpi-desync-fake-syndata */ case 39: /* dpi-desync-fake-syndata */
dp->fake_syndata_size = sizeof(dp->fake_syndata); dp->fake_syndata_size = sizeof(dp->fake_syndata);
load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size); load_file_or_exit(optarg,dp->fake_syndata,&dp->fake_syndata_size);
break; break;
case 37: /* dpi-desync-fake-quic */ case 40: /* dpi-desync-fake-quic */
dp->fake_quic_size = sizeof(dp->fake_quic); dp->fake_quic_size = sizeof(dp->fake_quic);
load_file_or_exit(optarg,dp->fake_quic,&dp->fake_quic_size); load_file_or_exit(optarg,dp->fake_quic,&dp->fake_quic_size);
break; break;
case 38: /* dpi-desync-fake-wireguard */ case 41: /* dpi-desync-fake-wireguard */
dp->fake_wg_size = sizeof(dp->fake_wg); dp->fake_wg_size = sizeof(dp->fake_wg);
load_file_or_exit(optarg,dp->fake_wg,&dp->fake_wg_size); load_file_or_exit(optarg,dp->fake_wg,&dp->fake_wg_size);
break; break;
case 39: /* dpi-desync-fake-dht */ case 42: /* dpi-desync-fake-dht */
dp->fake_dht_size = sizeof(dp->fake_dht); dp->fake_dht_size = sizeof(dp->fake_dht);
load_file_or_exit(optarg,dp->fake_dht,&dp->fake_dht_size); load_file_or_exit(optarg,dp->fake_dht,&dp->fake_dht_size);
break; 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); dp->fake_unknown_udp_size = sizeof(dp->fake_unknown_udp);
load_file_or_exit(optarg,dp->fake_unknown_udp,&dp->fake_unknown_udp_size); load_file_or_exit(optarg,dp->fake_unknown_udp,&dp->fake_unknown_udp_size);
break; 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) 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"); DLOG_ERR("dpi-desync-udplen-increment must be integer within -32768..32767 range\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 42: /* dpi-desync-udplen-pattern */ case 45: /* dpi-desync-udplen-pattern */
{ {
char buf[sizeof(dp->udplen_pattern)]; char buf[sizeof(dp->udplen_pattern)];
size_t sz=sizeof(buf); 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); fill_pattern(dp->udplen_pattern,sizeof(dp->udplen_pattern),buf,sz);
} }
break; break;
case 43: /* desync-cutoff */ case 46: /* desync-cutoff */
if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode)) if (!parse_cutoff(optarg, &dp->desync_cutoff, &dp->desync_cutoff_mode))
{ {
DLOG_ERR("invalid desync-cutoff value\n"); DLOG_ERR("invalid desync-cutoff value\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 44: /* desync-start */ case 47: /* desync-start */
if (!parse_cutoff(optarg, &dp->desync_start, &dp->desync_start_mode)) if (!parse_cutoff(optarg, &dp->desync_start, &dp->desync_start_mode))
{ {
DLOG_ERR("invalid desync-start value\n"); DLOG_ERR("invalid desync-start value\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 45: /* hostlist */ case 48: /* hostlist */
if (bSkip) break;
if (!RegisterHostlist(dp, false, optarg)) if (!RegisterHostlist(dp, false, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; 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)) if (!RegisterHostlist(dp, true, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; 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) if (dp->hostlist_auto)
{ {
DLOG_ERR("only one auto hostlist per profile is supported\n"); DLOG_ERR("only one auto hostlist per profile is supported\n");
@@ -1758,7 +1884,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 48: /* hostlist-auto-fail-threshold */ case 53: /* hostlist-auto-fail-threshold */
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20) 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); exit_clean(1);
} }
break; break;
case 49: /* hostlist-auto-fail-time */ case 54: /* hostlist-auto-fail-time */
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_time<1) if (dp->hostlist_auto_fail_time<1)
{ {
@@ -1774,7 +1900,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 50: /* hostlist-auto-retrans-threshold */ case 55: /* hostlist-auto-retrans-threshold */
dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg); dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10) 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); exit_clean(1);
} }
break; break;
case 51: /* hostlist-auto-debug */ case 56: /* hostlist-auto-debug */
{ {
FILE *F = fopen(optarg,"a+t"); FILE *F = fopen(optarg,"a+t");
if (!F) if (!F)
@@ -1796,23 +1922,39 @@ int main(int argc, char **argv)
} }
break; break;
case 52: /* new */ case 57: /* new */
if (!(dpl = dp_list_add(&params.desync_profiles))) if (bSkip)
{ {
DLOG_ERR("desync_profile_add: out of memory\n"); dp_clear(dp);
exit_clean(1); dp_init(dp);
dp->n = desync_profile_count;
bSkip = false;
} }
dp = &dpl->dp; else
dp->n = ++desync_profile_count; {
if (!(dpl = dp_list_add(&params.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; 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)) if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{ {
DLOG_ERR("bad value for --filter-l3\n"); DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 54: /* filter-tcp */ case 60: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp)) if (!parse_pf_list(optarg,&dp->pf_tcp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); 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)) if (!port_filters_deny_if_empty(&dp->pf_udp))
exit_clean(1); exit_clean(1);
break; break;
case 55: /* filter-udp */ case 61: /* filter-udp */
if (!parse_pf_list(optarg,&dp->pf_udp)) if (!parse_pf_list(optarg,&dp->pf_udp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); 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)) if (!port_filters_deny_if_empty(&dp->pf_tcp))
exit_clean(1); exit_clean(1);
break; break;
case 56: /* filter-l7 */ case 62: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7)) if (!parse_l7_list(optarg,&dp->filter_l7))
{ {
DLOG_ERR("Invalid l7 filter : %s\n",optarg); DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 57: /* ipset */ case 63: /* ipset */
if (bSkip) break;
if (!RegisterIpset(dp, false, optarg)) if (!RegisterIpset(dp, false, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; 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)) if (!RegisterIpset(dp, true, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; 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__ #ifdef __linux__
case 59: /* bind-fix4 */ case 67: /* bind-fix4 */
params.bind_fix4 = true; params.bind_fix4 = true;
break; break;
case 60: /* bind-fix6 */ case 68: /* bind-fix6 */
params.bind_fix6 = true; params.bind_fix6 = true;
break; break;
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
case 59: /* wf-iface */ case 67: /* wf-iface */
if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx)) if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx))
{ {
DLOG_ERR("bad value for --wf-iface\n"); DLOG_ERR("bad value for --wf-iface\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 60: /* wf-l3 */ case 68: /* wf-l3 */
if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6)) if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6))
{ {
DLOG_ERR("bad value for --wf-l3\n"); DLOG_ERR("bad value for --wf-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 61: /* wf-tcp */ case 69: /* wf-tcp */
hash_wf_tcp=hash_jen(optarg,strlen(optarg)); hash_wf_tcp=hash_jen(optarg,strlen(optarg));
if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) || 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))) !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); exit_clean(1);
} }
break; break;
case 62: /* wf-udp */ case 70: /* wf-udp */
hash_wf_udp=hash_jen(optarg,strlen(optarg)); hash_wf_udp=hash_jen(optarg,strlen(optarg));
if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) || 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))) !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); exit_clean(1);
} }
break; break;
case 63: /* wf-raw */ case 71: /* wf-raw */
hash_wf_raw=hash_jen(optarg,strlen(optarg)); hash_wf_raw=hash_jen(optarg,strlen(optarg));
if (optarg[0]=='@') if (optarg[0]=='@')
{ {
@@ -1910,11 +2079,11 @@ int main(int argc, char **argv)
windivert_filter[sizeof(windivert_filter) - 1] = '\0'; windivert_filter[sizeof(windivert_filter) - 1] = '\0';
} }
break; break;
case 64: /* wf-save */ case 72: /* wf-save */
strncpy(wf_save_file, optarg, sizeof(wf_save_file)); strncpy(wf_save_file, optarg, sizeof(wf_save_file));
wf_save_file[sizeof(wf_save_file) - 1] = '\0'; wf_save_file[sizeof(wf_save_file) - 1] = '\0';
break; break;
case 65: /* ssid-filter */ case 73: /* ssid-filter */
hash_ssid_filter=hash_jen(optarg,strlen(optarg)); hash_ssid_filter=hash_jen(optarg,strlen(optarg));
{ {
char *e,*p = optarg; char *e,*p = optarg;
@@ -1932,7 +2101,7 @@ int main(int argc, char **argv)
} }
} }
break; break;
case 66: /* nlm-filter */ case 74: /* nlm-filter */
hash_nlm_filter=hash_jen(optarg,strlen(optarg)); hash_nlm_filter=hash_jen(optarg,strlen(optarg));
{ {
char *e,*p = optarg; char *e,*p = optarg;
@@ -1950,7 +2119,7 @@ int main(int argc, char **argv)
} }
} }
break; break;
case 67: /* nlm-list */ case 75: /* nlm-list */
if (!nlm_list(optarg && !strcmp(optarg,"all"))) if (!nlm_list(optarg && !strcmp(optarg,"all")))
{ {
DLOG_ERR("could not get list of NLM networks\n"); DLOG_ERR("could not get list of NLM networks\n");
@@ -1961,6 +2130,12 @@ int main(int argc, char **argv)
#endif #endif
} }
} }
if (bSkip)
{
LIST_REMOVE(dpl,next);
dp_entry_destroy(dpl);
desync_profile_count--;
}
// do not need args from file anymore // do not need args from file anymore
#if !defined( __OpenBSD__) && !defined(__ANDROID__) #if !defined( __OpenBSD__) && !defined(__ANDROID__)
@@ -2076,6 +2251,12 @@ int main(int argc, char **argv)
SplitDebug(); SplitDebug();
DLOG("\n"); DLOG("\n");
if (bDry)
{
DLOG_CONDUP("command line parameters verified\n");
exit_clean(0);
}
if (daemon) daemonize(); if (daemon) daemonize();
if (*pidfile && !writepid(pidfile)) if (*pidfile && !writepid(pidfile))

View File

@@ -170,45 +170,49 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
if (bcut) DLOG(" ..."); 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 *dp_list_add(struct desync_profile_list_head *head)
{ {
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list)); struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
if (!entry) return NULL; if (!entry) return NULL;
LIST_INIT(&entry->dp.hl_collection); dp_init(&entry->dp);
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;
// add to the tail // add to the tail
struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles); struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles);
@@ -222,15 +226,24 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
return entry; 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(&dp->hl_collection);
hostlist_collection_destroy(&entry->dp.hl_collection_exclude); hostlist_collection_destroy(&dp->hl_collection_exclude);
ipset_collection_destroy(&entry->dp.ips_collection); ipset_collection_destroy(&dp->ips_collection);
ipset_collection_destroy(&entry->dp.ips_collection_exclude); ipset_collection_destroy(&dp->ips_collection_exclude);
port_filters_destroy(&entry->dp.pf_tcp); port_filters_destroy(&dp->pf_tcp);
port_filters_destroy(&entry->dp.pf_udp); port_filters_destroy(&dp->pf_udp);
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters); 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); free(entry);
} }
void dp_list_destroy(struct desync_profile_list_head *head) void dp_list_destroy(struct desync_profile_list_head *head)

View File

@@ -51,7 +51,7 @@ struct desync_profile
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int wssize_cutoff; unsigned int wssize_cutoff;
bool hostcase, hostnospace, domcase; bool hostcase, hostnospace, domcase, methodeol;
char hostspell[4]; char hostspell[4];
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2; enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
bool desync_retrans,desync_skip_nosni,desync_any_proto; bool desync_retrans,desync_skip_nosni,desync_any_proto;
@@ -68,7 +68,7 @@ struct desync_profile
autottl desync_autottl, desync_autottl6; autottl desync_autottl, desync_autottl6;
uint32_t desync_fooling_mode; uint32_t desync_fooling_mode;
uint32_t desync_badseq_increment, desync_badseq_ack_increment; 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]; 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; 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; int udplen_increment;
@@ -99,8 +99,11 @@ struct desync_profile_list {
}; };
LIST_HEAD(desync_profile_list_head, 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); 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_list_destroy(struct desync_profile_list_head *head);
bool dp_list_have_autohostlist(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 struct params_s
{ {

View File

@@ -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)); struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
if (entry) if (entry)
{ {
if (!(entry->filename = strdup(filename))) if (filename)
{ {
free(entry); if (!(entry->filename = strdup(filename)))
return false; {
free(entry);
return false;
}
} }
entry->mod_time=0; else
entry->filename = NULL;
entry->mod_time = 0;
entry->hostlist = NULL; entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next); 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) LIST_FOREACH(hfile, head, next)
{ {
if (!strcmp(hfile->filename,filename)) if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile; return hfile;
} }
return NULL; return NULL;
@@ -223,7 +228,7 @@ struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head
LIST_FOREACH(item, head, next) LIST_FOREACH(item, head, next)
{ {
if (!strcmp(item->hfile->filename,filename)) if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item; return item;
} }
return NULL; 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)); struct ipset_file *entry = malloc(sizeof(struct ipset_file));
if (entry) if (entry)
{ {
if (!(entry->filename = strdup(filename))) if (filename)
{ {
free(entry); if (!(entry->filename = strdup(filename)))
return false; {
free(entry);
return false;
}
} }
entry->mod_time=0; else
entry->filename = NULL;
entry->mod_time = 0;
memset(&entry->ipset,0,sizeof(entry->ipset)); memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next); 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) LIST_FOREACH(hfile, head, next)
{ {
if (!strcmp(hfile->filename,filename)) if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile; return hfile;
} }
return NULL; return NULL;
@@ -432,7 +442,7 @@ struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, c
LIST_FOREACH(item, head, next) LIST_FOREACH(item, head, next)
{ {
if (!strcmp(item->hfile->filename,filename)) if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item; return item;
} }
return NULL; return NULL;

View File

@@ -1,5 +1,5 @@
CC ?= cc CC ?= cc
CFLAGS += -std=gnu99 -s -Os CFLAGS += -std=gnu99 -s -Os -flto=auto
LIBS = -lz -lpthread LIBS = -lz -lpthread
SRC_FILES = *.c SRC_FILES = *.c

View File

@@ -1,5 +1,5 @@
CC ?= gcc CC ?= gcc
CFLAGS += -std=gnu99 -Os CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_BSD = -Wno-address-of-packed-member CFLAGS_BSD = -Wno-address-of-packed-member
LIBS = -lz -lpthread LIBS = -lz -lpthread
LIBS_ANDROID = -lz LIBS_ANDROID = -lz

View File

@@ -24,7 +24,7 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
*hostlist = NULL; *hostlist = NULL;
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
// advance to the next line // advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++); 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; return true;
} }
bool AppendHostlistItem(strpool **hostlist, char *s)
{
return addpool(hostlist,&s,s+strlen(s),NULL);
}
bool AppendHostList(strpool **hostlist, const char *filename) bool AppendHostList(strpool **hostlist, const char *filename)
{ {
char *p, *e, s[256], *zbuf; char *p, *e, s[256], *zbuf;
@@ -98,21 +103,24 @@ bool AppendHostList(strpool **hostlist, const char *filename)
static bool LoadHostList(struct hostlist_file *hfile) static bool LoadHostList(struct hostlist_file *hfile)
{ {
time_t t = file_mod_time(hfile->filename); if (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))
{ {
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); 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; return true;
} }
static bool LoadHostLists(struct hostlist_files_head *list) 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) 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 (SearchHostList(item->hfile->hostlist, host))
{ {
if (excluded) *excluded = true; if (excluded) *excluded = true;
@@ -214,7 +222,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
{ {
LIST_FOREACH(item, hostlists, next) 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)) if (SearchHostList(item->hfile->hostlist, host))
return true; 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) static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
{ {
struct hostlist_file *hfile; 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; return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile)) if (!hostlist_collection_add(hl_collection, hfile))
return NULL; return NULL;
}
return hfile; return hfile;
} }
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename) 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); DLOG_ERR("cannot access hostlist file '%s'\n",filename);
return NULL; return NULL;
@@ -265,15 +285,30 @@ void HostlistsDebug()
struct hostlist_item *hl_item; struct hostlist_item *hl_item;
LIST_FOREACH(hfile, &params.hostlists, next) LIST_FOREACH(hfile, &params.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, &params.desync_profiles, next) LIST_FOREACH(dpl, &params.desync_profiles, next)
{ {
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next) LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
if (hl_item->hfile!=dpl->dp.hostlist_auto) 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) 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) 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)"); VPRINT("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
} }

View File

@@ -4,6 +4,7 @@
#include "pools.h" #include "pools.h"
#include "params.h" #include "params.h"
bool AppendHostlistItem(strpool **hostlist, char *s);
bool AppendHostList(strpool **hostlist, const char *filename); bool AppendHostList(strpool **hostlist, const char *filename);
bool LoadAllHostLists(); bool LoadAllHostLists();
bool NonEmptyHostlist(strpool **hostlist); bool NonEmptyHostlist(strpool **hostlist);

View File

@@ -31,7 +31,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips); ipsetDestroy(ips);
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
else if (parse_cidr6(cidr,&c6)) else if (parse_cidr6(cidr,&c6))
{ {
@@ -40,7 +40,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips); ipsetDestroy(ips);
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
else else
DLOG_ERR("bad ip or subnet : %s\n",cidr); 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) static bool AppendIpset(ipset *ips, const char *filename)
{ {
char *p, *e, s[256], *zbuf; 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) static bool LoadIpset(struct ipset_file *hfile)
{ {
time_t t = file_mod_time(hfile->filename); if (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))
{ {
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); 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; return true;
} }
static bool LoadIpsets(struct ipset_files_head *list) 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) 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)) if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return false; return false;
} }
@@ -214,7 +222,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
{ {
LIST_FOREACH(item, ips, next) 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)) if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return true; 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) static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
{ {
struct ipset_file *hfile; struct ipset_file *hfile;
if (!(hfile=ipset_files_search(ipsets, filename))) if (filename)
if (!(hfile=ipset_files_add(ipsets, 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; return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile)) if (!ipset_collection_add(ips_collection, hfile))
return NULL; return NULL;
}
return hfile; return hfile;
} }
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename) 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); DLOG_ERR("cannot access ipset file '%s'\n",filename);
return NULL; return NULL;
@@ -277,13 +295,24 @@ void IpsetsDebug()
struct ipset_item *ips_item; struct ipset_item *ips_item;
LIST_FOREACH(hfile, &params.ipsets, next) LIST_FOREACH(hfile, &params.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, &params.desync_profiles, next) LIST_FOREACH(dpl, &params.desync_profiles, next)
{ {
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, 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) 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));
} }
} }

View File

@@ -9,3 +9,4 @@ bool LoadAllIpsets();
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6); 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); struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
void IpsetsDebug(); void IpsetsDebug();
bool AppendIpsetItem(ipset *ips, char *ip);

View File

@@ -155,22 +155,26 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
if (bcut) VPRINT(" ..."); 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 *dp_list_add(struct desync_profile_list_head *head)
{ {
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list)); struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
if (!entry) return NULL; if (!entry) return NULL;
LIST_INIT(&entry->dp.hl_collection); dp_init(&entry->dp);
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;
// add to the tail // add to the tail
struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles); struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles);
@@ -184,14 +188,23 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
return entry; 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(&dp->hl_collection);
hostlist_collection_destroy(&entry->dp.hl_collection_exclude); hostlist_collection_destroy(&dp->hl_collection_exclude);
ipset_collection_destroy(&entry->dp.ips_collection); ipset_collection_destroy(&dp->ips_collection);
ipset_collection_destroy(&entry->dp.ips_collection_exclude); ipset_collection_destroy(&dp->ips_collection_exclude);
port_filters_destroy(&entry->dp.pf_tcp); port_filters_destroy(&dp->pf_tcp);
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters); 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); free(entry);
} }
void dp_list_destroy(struct desync_profile_list_head *head) void dp_list_destroy(struct desync_profile_list_head *head)

View File

@@ -83,7 +83,10 @@ struct desync_profile_list {
}; };
LIST_HEAD(desync_profile_list_head, 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); 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_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 struct params_s
{ {

View File

@@ -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 *hostlist_files_add(struct hostlist_files_head *head, const char *filename)
{ {
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file)); struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
if (entry) if (entry)
{ {
if (!(entry->filename = strdup(filename))) if (filename)
{ {
free(entry); if (!(entry->filename = strdup(filename)))
return false; {
free(entry);
return false;
}
} }
entry->mod_time=0; else
entry->filename = NULL;
entry->mod_time = 0;
entry->hostlist = NULL; entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next); 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) LIST_FOREACH(hfile, head, next)
{ {
if (!strcmp(hfile->filename,filename)) if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile; return hfile;
} }
return NULL; return NULL;
@@ -223,7 +227,7 @@ struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head
LIST_FOREACH(item, head, next) LIST_FOREACH(item, head, next)
{ {
if (!strcmp(item->hfile->filename,filename)) if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item; return item;
} }
return NULL; 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)); struct ipset_file *entry = malloc(sizeof(struct ipset_file));
if (entry) if (entry)
{ {
if (!(entry->filename = strdup(filename))) if (filename)
{ {
free(entry); if (!(entry->filename = strdup(filename)))
return false; {
free(entry);
return false;
}
} }
entry->mod_time=0; else
entry->filename = NULL;
entry->mod_time = 0;
memset(&entry->ipset,0,sizeof(entry->ipset)); memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next); 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) LIST_FOREACH(hfile, head, next)
{ {
if (!strcmp(hfile->filename,filename)) if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile; return hfile;
} }
return NULL; return NULL;
@@ -432,7 +441,7 @@ struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, c
LIST_FOREACH(item, head, next) LIST_FOREACH(item, head, next)
{ {
if (!strcmp(item->hfile->filename,filename)) if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item; return item;
} }
return NULL; return NULL;

View File

@@ -140,11 +140,6 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
if (bHaveHost) if (bHaveHost)
VPRINT("request hostname: %s\n", Host); VPRINT("request hostname: %s\n", Host);
if (ctrack->b_not_act)
{
VPRINT("Not acting on this request\n");
return;
}
bool bDiscoveredL7 = ctrack->l7proto==UNKNOWN && l7proto!=UNKNOWN; bool bDiscoveredL7 = ctrack->l7proto==UNKNOWN && l7proto!=UNKNOWN;
if (bDiscoveredL7) if (bDiscoveredL7)
@@ -169,17 +164,25 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
struct desync_profile *dp_prev = ctrack->dp; struct desync_profile *dp_prev = ctrack->dp;
apply_desync_profile(ctrack, dest); apply_desync_profile(ctrack, dest);
if (ctrack->dp!=dp_prev) if (ctrack->dp!=dp_prev)
{
VPRINT("desync profile changed by revealed l7 protocol or hostname !\n"); VPRINT("desync profile changed by revealed l7 protocol or hostname !\n");
ctrack->b_host_checked = ctrack->b_ah_check = false;
}
} }
if (bDiscoveredHostname && ctrack->dp->hostlist_auto) if (l7proto!=UNKNOWN && ctrack->dp->hostlist_auto)
{ {
bool bHostExcluded; if (bHaveHost && !ctrack->b_host_checked)
if (!HostlistCheck(ctrack->dp, Host, &bHostExcluded, false)) {
bool bHostExcluded;
ctrack->b_host_matches = HostlistCheck(ctrack->dp, Host, &bHostExcluded, false);
ctrack->b_host_checked = true;
if (!ctrack->b_host_matches)
ctrack->b_ah_check = !bHostExcluded;
}
if (!ctrack->b_host_matches)
{ {
ctrack->b_ah_check = !bHostExcluded;
VPRINT("Not acting on this request\n"); VPRINT("Not acting on this request\n");
ctrack->b_not_act = true;
return; return;
} }
} }

View File

@@ -14,8 +14,7 @@ typedef struct
// common state // common state
t_l7proto l7proto; t_l7proto l7proto;
bool bTamperInCutoff; bool bTamperInCutoff;
bool b_ah_check; bool b_host_checked,b_host_matches,b_ah_check;
bool b_not_act;
char *hostname; char *hostname;
struct desync_profile *dp; // desync profile cache struct desync_profile *dp; // desync profile cache
} t_ctrack; } t_ctrack;

View File

@@ -175,16 +175,22 @@ static void exithelp(void)
#endif #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=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" " --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" "\nMULTI-STRATEGY:\n"
" --new\t\t\t\t\t; begin new 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-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-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" " --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=<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=<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" "\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=<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=<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=<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-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" " --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; 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__) #if !defined( __OpenBSD__) && !defined(__ANDROID__)
// no static to not allow optimizer to inline this func (save stack) // no static to not allow optimizer to inline this func (save stack)
void config_from_file(const char *filename) void config_from_file(const char *filename)
@@ -524,6 +570,9 @@ void parse_params(int argc, char *argv[])
{ {
int option_index = 0; int option_index = 0;
int v, i; 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(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
params.maxconn = DEFAULT_MAX_CONN; params.maxconn = DEFAULT_MAX_CONN;
@@ -609,45 +658,51 @@ void parse_params(int argc, char *argv[])
{ "tlsrec",required_argument,0,0 },// optidx=34 { "tlsrec",required_argument,0,0 },// optidx=34
{ "tlsrec-pos",required_argument,0,0 },// optidx=35 { "tlsrec-pos",required_argument,0,0 },// optidx=35
{ "hostlist",required_argument,0,0 },// optidx=36 { "hostlist",required_argument,0,0 },// optidx=36
{ "hostlist-exclude",required_argument,0,0 },// optidx=37 { "hostlist-domains",required_argument,0,0 },// optidx=37
{ "hostlist-auto",required_argument,0,0}, // optidx=38 { "hostlist-exclude",required_argument,0,0 },// optidx=38
{ "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=39 { "hostlist-exclude-domains",required_argument,0,0 },// optidx=39
{ "hostlist-auto-fail-time",required_argument,0,0}, // optidx=40 { "hostlist-auto",required_argument,0,0}, // optidx=40
{ "hostlist-auto-debug",required_argument,0,0}, // optidx=41 { "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=41
{ "pidfile",required_argument,0,0 },// optidx=42 { "hostlist-auto-fail-time",required_argument,0,0}, // optidx=42
{ "debug",optional_argument,0,0 },// optidx=43 { "hostlist-auto-debug",required_argument,0,0}, // optidx=43
{ "debug-level",required_argument,0,0 },// optidx=44 { "pidfile",required_argument,0,0 },// optidx=44
{ "local-rcvbuf",required_argument,0,0 },// optidx=45 { "debug",optional_argument,0,0 },// optidx=45
{ "local-sndbuf",required_argument,0,0 },// optidx=46 { "debug-level",required_argument,0,0 },// optidx=46
{ "remote-rcvbuf",required_argument,0,0 },// optidx=47 { "dry-run",no_argument,0,0 },// optidx=47
{ "remote-sndbuf",required_argument,0,0 },// optidx=48 { "local-rcvbuf",required_argument,0,0 },// optidx=48
{ "socks",no_argument,0,0 },// optidx=40 { "local-sndbuf",required_argument,0,0 },// optidx=49
{ "no-resolve",no_argument,0,0 },// optidx=50 { "remote-rcvbuf",required_argument,0,0 },// optidx=50
{ "resolver-threads",required_argument,0,0 },// optidx=51 { "remote-sndbuf",required_argument,0,0 },// optidx=51
{ "skip-nodelay",no_argument,0,0 },// optidx=52 { "socks",no_argument,0,0 },// optidx=52
{ "tamper-start",required_argument,0,0 },// optidx=53 { "no-resolve",no_argument,0,0 },// optidx=53
{ "tamper-cutoff",required_argument,0,0 },// optidx=54 { "resolver-threads",required_argument,0,0 },// optidx=54
{ "connect-bind-addr",required_argument,0,0 },// optidx=55 { "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 { "new",no_argument,0,0 }, // optidx=59
{ "filter-l3",required_argument,0,0 }, // optidx=57 { "skip",no_argument,0,0 }, // optidx=60
{ "filter-tcp",required_argument,0,0 }, // optidx=58 { "filter-l3",required_argument,0,0 }, // optidx=61
{ "filter-l7",required_argument,0,0 }, // optidx=59 { "filter-tcp",required_argument,0,0 }, // optidx=63
{ "ipset",required_argument,0,0 }, // optidx=60 { "filter-l7",required_argument,0,0 }, // optidx=64
{ "ipset-exclude",required_argument,0,0 }, // optidx=61 { "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__) #if defined(__FreeBSD__)
{ "enable-pf",no_argument,0,0 },// optidx=62 { "enable-pf",no_argument,0,0 },// optidx=68
#elif defined(__APPLE__) #elif defined(__APPLE__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62 { "local-tcp-user-timeout",required_argument,0,0 }, // optidx=68
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63 { "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=69
#elif defined(__linux__) #elif defined(__linux__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62 { "local-tcp-user-timeout",required_argument,0,0 }, // optidx=68
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63 { "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=69
{ "mss",required_argument,0,0 }, // optidx=64 { "mss",required_argument,0,0 }, // optidx=70
{ "fix-seg",optional_argument,0,0 }, // optidx=65 { "fix-seg",optional_argument,0,0 }, // optidx=71
#ifdef SPLICE_PRESENT #ifdef SPLICE_PRESENT
{ "nosplice",no_argument,0,0 }, // optidx=66 { "nosplice",no_argument,0,0 }, // optidx=72
#endif #endif
#endif #endif
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility { "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) 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) switch (option_index)
{ {
case 0: case 0:
@@ -945,6 +1004,7 @@ void parse_params(int argc, char *argv[])
params.tamper = true; params.tamper = true;
break; break;
case 36: /* hostlist */ case 36: /* hostlist */
if (bSkip) break;
if (!RegisterHostlist(dp, false, optarg)) if (!RegisterHostlist(dp, false, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
@@ -952,7 +1012,22 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; 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)) if (!RegisterHostlist(dp, true, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
@@ -960,7 +1035,22 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; 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) if (dp->hostlist_auto)
{ {
DLOG_ERR("only one auto hostlist per profile is supported\n"); 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. params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
break; break;
case 39: /* hostlist-auto-fail-threshold */ case 41: /* hostlist-auto-fail-threshold */
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20) 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); exit_clean(1);
} }
break; break;
case 40: /* hostlist-auto-fail-time */ case 42: /* hostlist-auto-fail-time */
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_time<1) if (dp->hostlist_auto_fail_time<1)
{ {
@@ -1004,7 +1094,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 41: /* hostlist-auto-debug */ case 43: /* hostlist-auto-debug */
{ {
FILE *F = fopen(optarg,"a+t"); FILE *F = fopen(optarg,"a+t");
if (!F) if (!F)
@@ -1017,11 +1107,11 @@ void parse_params(int argc, char *argv[])
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0'; params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
} }
break; break;
case 42: /* pidfile */ case 44: /* pidfile */
strncpy(params.pidfile,optarg,sizeof(params.pidfile)); strncpy(params.pidfile,optarg,sizeof(params.pidfile));
params.pidfile[sizeof(params.pidfile)-1]='\0'; params.pidfile[sizeof(params.pidfile)-1]='\0';
break; break;
case 43: /* debug */ case 45: /* debug */
if (optarg) if (optarg)
{ {
if (*optarg=='@') if (*optarg=='@')
@@ -1055,44 +1145,47 @@ void parse_params(int argc, char *argv[])
params.debug_target = LOG_TARGET_CONSOLE; params.debug_target = LOG_TARGET_CONSOLE;
} }
break; break;
case 44: /* debug-level */ case 46: /* debug-level */
params.debug = atoi(optarg); params.debug = atoi(optarg);
break; break;
case 45: /* local-rcvbuf */ case 47: /* dry-run */
bDry = true;
break;
case 48: /* local-rcvbuf */
#ifdef __linux__ #ifdef __linux__
params.local_rcvbuf = atoi(optarg)/2; params.local_rcvbuf = atoi(optarg)/2;
#else #else
params.local_rcvbuf = atoi(optarg); params.local_rcvbuf = atoi(optarg);
#endif #endif
break; break;
case 46: /* local-sndbuf */ case 49: /* local-sndbuf */
#ifdef __linux__ #ifdef __linux__
params.local_sndbuf = atoi(optarg)/2; params.local_sndbuf = atoi(optarg)/2;
#else #else
params.local_sndbuf = atoi(optarg); params.local_sndbuf = atoi(optarg);
#endif #endif
break; break;
case 47: /* remote-rcvbuf */ case 50: /* remote-rcvbuf */
#ifdef __linux__ #ifdef __linux__
params.remote_rcvbuf = atoi(optarg)/2; params.remote_rcvbuf = atoi(optarg)/2;
#else #else
params.remote_rcvbuf = atoi(optarg); params.remote_rcvbuf = atoi(optarg);
#endif #endif
break; break;
case 48: /* remote-sndbuf */ case 51: /* remote-sndbuf */
#ifdef __linux__ #ifdef __linux__
params.remote_sndbuf = atoi(optarg)/2; params.remote_sndbuf = atoi(optarg)/2;
#else #else
params.remote_sndbuf = atoi(optarg); params.remote_sndbuf = atoi(optarg);
#endif #endif
break; break;
case 49: /* socks */ case 52: /* socks */
params.proxy_type = CONN_TYPE_SOCKS; params.proxy_type = CONN_TYPE_SOCKS;
break; break;
case 50: /* no-resolve */ case 53: /* no-resolve */
params.no_resolve = true; params.no_resolve = true;
break; break;
case 51: /* resolver-threads */ case 54: /* resolver-threads */
params.resolver_threads = atoi(optarg); params.resolver_threads = atoi(optarg);
if (params.resolver_threads<1 || params.resolver_threads>300) if (params.resolver_threads<1 || params.resolver_threads>300)
{ {
@@ -1100,10 +1193,10 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 52: /* skip-nodelay */ case 55: /* skip-nodelay */
params.skip_nodelay = true; params.skip_nodelay = true;
break; break;
case 53: /* tamper-start */ case 56: /* tamper-start */
{ {
const char *p=optarg; const char *p=optarg;
if (*p=='n') if (*p=='n')
@@ -1117,7 +1210,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper_lim = true; params.tamper_lim = true;
break; break;
case 54: /* tamper-cutoff */ case 57: /* tamper-cutoff */
{ {
const char *p=optarg; const char *p=optarg;
if (*p=='n') if (*p=='n')
@@ -1131,7 +1224,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper_lim = true; params.tamper_lim = true;
break; break;
case 55: /* connect-bind-addr */ case 58: /* connect-bind-addr */
{ {
char *p = strchr(optarg,'%'); char *p = strchr(optarg,'%');
if (p) *p++=0; if (p) *p++=0;
@@ -1159,37 +1252,53 @@ void parse_params(int argc, char *argv[])
break; break;
case 56: /* new */ case 59: /* new */
if (!(dpl = dp_list_add(&params.desync_profiles))) if (bSkip)
{ {
DLOG_ERR("desync_profile_add: out of memory\n"); dp_clear(dp);
exit_clean(1); dp_init(dp);
dp->n = desync_profile_count;
bSkip = false;
} }
dp = &dpl->dp; else
dp->n = ++desync_profile_count; {
if (!(dpl = dp_list_add(&params.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; 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)) if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{ {
DLOG_ERR("bad value for --filter-l3\n"); DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 58: /* filter-tcp */ case 62: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp)) if (!parse_pf_list(optarg,&dp->pf_tcp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); DLOG_ERR("Invalid port filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 59: /* filter-l7 */ case 63: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7)) if (!parse_l7_list(optarg,&dp->filter_l7))
{ {
DLOG_ERR("Invalid l7 filter : %s\n",optarg); DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 60: /* ipset */ case 64: /* ipset */
if (bSkip) break;
if (!RegisterIpset(dp, false, optarg)) if (!RegisterIpset(dp, false, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
@@ -1197,7 +1306,22 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; 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)) if (!RegisterIpset(dp, true, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
@@ -1205,13 +1329,27 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; 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__) #if defined(__FreeBSD__)
case 62: /* enable-pf */ case 68: /* enable-pf */
params.pf_enable = true; params.pf_enable = true;
break; break;
#elif defined(__linux__) || defined(__APPLE__) #elif defined(__linux__) || defined(__APPLE__)
case 62: /* local-tcp-user-timeout */ case 68: /* local-tcp-user-timeout */
params.tcp_user_timeout_local = atoi(optarg); params.tcp_user_timeout_local = atoi(optarg);
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400) 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); exit_clean(1);
} }
break; break;
case 63: /* remote-tcp-user-timeout */ case 69: /* remote-tcp-user-timeout */
params.tcp_user_timeout_remote = atoi(optarg); params.tcp_user_timeout_remote = atoi(optarg);
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400) 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 #endif
#if defined(__linux__) #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 // this option does not work in any BSD and MacOS. OS may accept but it changes nothing
dp->mss = atoi(optarg); dp->mss = atoi(optarg);
if (dp->mss<88 || dp->mss>32767) if (dp->mss<88 || dp->mss>32767)
@@ -1239,7 +1377,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 65: /* fix-seg */ case 71: /* fix-seg */
if (!params.fix_seg_avail) if (!params.fix_seg_avail)
{ {
DLOG_ERR("--fix-seg is supported since kernel 4.6\n"); 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; params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
break; break;
#ifdef SPLICE_PRESENT #ifdef SPLICE_PRESENT
case 66: /* nosplice */ case 72: /* nosplice */
params.nosplice = true; params.nosplice = true;
break; break;
#endif #endif
#endif #endif
} }
} }
if (bSkip)
{
LIST_REMOVE(dpl,next);
dp_entry_destroy(dpl);
desync_profile_count--;
}
if (!params.bind_wait_only && !params.port) if (!params.bind_wait_only && !params.port)
{ {
DLOG_ERR("Need port number\n"); DLOG_ERR("Need port number\n");
@@ -1327,6 +1472,11 @@ void parse_params(int argc, char *argv[])
// do not need args from file anymore // do not need args from file anymore
cleanup_args(); cleanup_args();
#endif #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 int bind_wait_ip_left; // how much seconds left from bind_wait_ip
}; };
static const char *bindll_s[] = { "unwanted","no","prefer","force" }; 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 main(int argc, char *argv[])
{ {
int i, listen_fd[MAX_BINDS], yes = 1, retval = 0, if_index, exit_v=EXIT_FAILURE; 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)); srand(time(NULL));
mask_from_preflen6_prepare(); mask_from_preflen6_prepare();
PRINT_VER;
parse_params(argc, argv); parse_params(argc, argv);
argv=NULL; argc=0; argv=NULL; argc=0;

View File

@@ -479,6 +479,33 @@ static int connect_remote(const struct sockaddr *remote_addr, int mss)
return remote_fd; return remote_fd;
} }
static bool connect_remote_conn(tproxy_conn_t *conn)
{
int mss=0;
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
if (conn->track.dp && conn->track.dp->mss)
{
mss = conn->track.dp->mss;
if (conn->track.dp->hostlist_auto)
{
if (conn->track.hostname)
{
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;
mss = 0;
}
}
}
}
return (conn->partner->fd = connect_remote((struct sockaddr *)&conn->dest, mss))>=0;
}
//Free resources occupied by this connection //Free resources occupied by this connection
static void free_conn(tproxy_conn_t *conn) static void free_conn(tproxy_conn_t *conn)
@@ -636,9 +663,7 @@ static tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list,int
conn->partner->client = conn->client; conn->partner->client = conn->client;
conn->partner->dest = conn->dest; conn->partner->dest = conn->dest;
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest); if (!connect_remote_conn(conn))
if ((conn->partner->fd = connect_remote((struct sockaddr *)&orig_dst, conn->track.dp ? conn->track.dp->mss : 0)) < 0)
{ {
DLOG_ERR("Failed to connect\n"); DLOG_ERR("Failed to connect\n");
free_conn(conn->partner); free_conn(conn->partner);
@@ -811,14 +836,6 @@ static bool proxy_mode_connect_remote(tproxy_conn_t *conn, struct tailhead *conn
return false; return false;
} }
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
if ((remote_fd = connect_remote((struct sockaddr *)&conn->dest, conn->track.dp ? conn->track.dp->mss : 0)) < 0)
{
DLOG_ERR("socks failed to connect (1) errno=%d\n", errno);
socks_send_rep_errno(conn->socks_ver, conn->fd, errno);
return false;
}
if (!(conn->partner = new_conn(remote_fd, true))) if (!(conn->partner = new_conn(remote_fd, true)))
{ {
close(remote_fd); close(remote_fd);
@@ -830,6 +847,15 @@ static bool proxy_mode_connect_remote(tproxy_conn_t *conn, struct tailhead *conn
conn->partner->efd = conn->efd; conn->partner->efd = conn->efd;
conn->partner->client = conn->client; conn->partner->client = conn->client;
conn->partner->dest = conn->dest; conn->partner->dest = conn->dest;
if (!connect_remote_conn(conn))
{
free_conn(conn->partner); conn->partner = NULL;
DLOG_ERR("socks failed to connect (1) errno=%d\n", errno);
socks_send_rep_errno(conn->socks_ver, conn->fd, errno);
return false;
}
if (!epoll_set(conn->partner, EPOLLOUT)) if (!epoll_set(conn->partner, EPOLLOUT))
{ {
DLOG_ERR("socks epoll_set error %d\n", errno); DLOG_ERR("socks epoll_set error %d\n", errno);
@@ -1652,7 +1678,6 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
} }
else else
{ {
DBGPRINT("conn fd=%d has no unsent\n", conn->fd); DBGPRINT("conn fd=%d has no unsent\n", conn->fd);
conn->bFlowIn = false; conn->bFlowIn = false;
epoll_update_flow(conn); epoll_update_flow(conn);