89 Commits

Author SHA1 Message Date
bol-van
4470c73e48 tpws: fix BSD build 2024-11-19 18:04:54 +03:00
bol-van
9812630ef2 doc works 2024-11-19 17:44:53 +03:00
bol-van
818520452e doc works 2024-11-19 17:33:34 +03:00
bol-van
f0cc49c7e3 tpws: minor help text change 2024-11-19 15:14:39 +03:00
bol-van
cc30a90556 tpws: check for kernel version in fixseg 2024-11-19 14:01:24 +03:00
bol-van
e12dd237c2 tpws: check for kernel version in fixseg 2024-11-19 13:59:46 +03:00
bol-van
19e7fca627 readme: more notices about fix-seg 2024-11-19 11:47:14 +03:00
bol-van
a0e1742861 tpws: rate limit fix-seg errors without --debug 2024-11-19 10:12:39 +03:00
bol-van
a93b142dcd tpws: fix-seg wait before send. tune max delay. 2024-11-19 09:51:32 +03:00
bol-van
fc2d511d78 update changes.txt 2024-11-18 23:19:51 +03:00
bol-van
5207104c06 readme: fix-seg info 2024-11-18 23:19:11 +03:00
bol-van
06147836d0 tpws: segmentation failure warning and fix 2024-11-18 23:06:23 +03:00
bol-van
46eb30a897 build docs for unix and windows 2024-11-18 21:00:25 +03:00
bol-van
840617a0c3 install_easy: copy systemd units instead of linking 2024-11-18 20:42:55 +03:00
bol-van
f7ae5eaae5 doc works 2024-11-18 20:33:37 +03:00
bol-van
827a838715 doc works 2024-11-18 20:25:52 +03:00
bol-van
db5c60e19f doc works 2024-11-18 20:24:17 +03:00
bol-van
256c2d7e50 doc works 2024-11-18 16:28:22 +03:00
bol-van
07c8cd3d5d improve compile docs 2024-11-17 20:43:01 +03:00
bol-van
8979384847 ignore dvtws and winws in git 2024-11-17 20:34:28 +03:00
bol-van
2a134b864a delete bad bin 2024-11-17 20:33:46 +03:00
bol-van
765770d2c7 installer: support APK on openwrt 2024-11-17 15:45:28 +03:00
bol-van
ba58892011 compile doc: zlib-dev not reqd notice 2024-11-17 12:27:14 +03:00
bol-van
63f40dd8a4 Merge pull request #800 from spvkgn/actions-android
github: build for Android
2024-11-17 11:38:58 +03:00
spvkgn
30443ed31d github: build for Android 2024-11-17 11:00:06 +05:00
spvkgn
a8432a3caa github: minor changes 2024-11-17 11:00:06 +05:00
bol-van
53546a8d92 update makefiles to build all progs for android 2024-11-16 19:32:58 +03:00
bol-van
97f20a1cb5 improve compile doc 2024-11-16 19:08:02 +03:00
bol-van
2816f93831 makefiles use fixed executable names 2024-11-16 18:35:56 +03:00
bol-van
8624ae1c4a makefiles use fixed executable names 2024-11-16 18:34:55 +03:00
bol-van
ebcec6e79d tpws: support android versions 5+ 2024-11-16 18:25:53 +03:00
bol-van
faa9a3e714 docs: remove wireguard patch info 2024-11-16 16:50:08 +03:00
bol-van
69007b5098 improve compile docs 2024-11-16 16:43:26 +03:00
bol-van
ee44aebcc4 nfqws,tpws: remove @config from android 2024-11-16 15:19:36 +03:00
bol-van
667d32a3e7 blockcheck: summary report all working strategies, tpws limit mss check 2024-11-16 13:19:37 +03:00
bol-van
9a087fc6c9 nfqws: allow seqovl=0 to disable seqovl 2024-11-16 09:46:08 +03:00
bol-van
3ad029efe0 nfqws: message for seqovl pos => seqovl 2024-11-15 21:55:57 +03:00
bol-van
92c27ea7d8 nfqws: allow only absolute positive values in seqovl for multisplit/fakedsplit 2024-11-15 21:53:14 +03:00
bol-van
7b850e2e0e nfqws: allow only absolute positive values in seqovl for multisplit/fakedsplit 2024-11-15 21:51:35 +03:00
bol-van
c48398871c blockcheck: check sniext+4 position 2024-11-15 20:56:51 +03:00
bol-van
8629a29eaa blockcheck: always use additional abs split in seqovl to guarantee packet growth 2024-11-15 20:48:18 +03:00
bol-van
df69ce1991 blockcheck: always use additional abs split in seqovl to guarantee packet growth 2024-11-15 20:33:53 +03:00
bol-van
c56e672600 blockcheck: update for new strategies. nfqws check order reworked. 2024-11-15 18:43:25 +03:00
bol-van
677feecada dvtws: set ip_id field in generated packets 2024-11-15 15:51:59 +03:00
bol-van
5d6c91f7e9 nfqws: add marker support for seqovl pos 2024-11-14 20:20:07 +03:00
bol-van
cde3ca15c2 tpws: debug log data before and after 2nd TLS record 2024-11-14 14:03:37 +03:00
bol-van
fa6f6822a1 nfqws: remove old ESNI notice in help 2024-11-14 12:21:45 +03:00
bol-van
ce33a27c57 nfqws,tpws: set EXEDIR env var to use in @config 2024-11-14 10:57:34 +03:00
bol-van
4d47749e7c tpws: disable simultaneous use of oob and disorder in BSD systems 2024-11-14 10:21:08 +03:00
bol-van
42090daf24 update config.default 2024-11-14 09:18:21 +03:00
bol-van
36cd8ca3b2 update config.default 2024-11-13 23:16:06 +03:00
bol-van
9ec2d685e3 winws: get rid of uuid.lib to reduce exe size 2024-11-13 22:41:58 +03:00
bol-van
46d31003e2 tpws: multisplit 2024-11-13 22:06:45 +03:00
bol-van
ef9f9ae428 nfqws: move code 2024-11-13 19:08:59 +03:00
bol-van
e5bcc5f682 nfqws: fix autohostlist debug chown 2024-11-13 17:35:50 +03:00
bol-van
4961e0d1a5 nfqws: fix snisld compat converter 2024-11-13 15:46:40 +03:00
bol-van
6a20fa27b3 nfqws: chown files after options parse 2024-11-13 14:56:15 +03:00
bol-van
01af779f2a nfqws: chown log files after options parse 2024-11-13 14:48:10 +03:00
bol-van
feb332140a nfqws: chown log files after options parse 2024-11-13 14:47:46 +03:00
bol-van
a85a0f19da init.d: sysv do not hide error messages from daemons. remove start-stop-daemon 2024-11-13 14:23:47 +03:00
bol-van
611292281c nfqws: rewrite default split pos logic 2024-11-13 13:34:34 +03:00
bol-van
14e9fc4d43 nfqws: deprecate single split modes, optimize code 2024-11-13 11:54:40 +03:00
bol-van
8bc74333b8 nfqws: fallback to unknown proto pos if failed to resolve known proto pos 2024-11-12 21:49:01 +03:00
bol-van
28797184e4 nfqws: apply seqovl only to the first multisplit part to prevent server races 2024-11-12 18:35:14 +03:00
bol-van
08238664cd docs compile: move binaries in ipk to /opt/zapret/binaries/my 2024-11-12 17:48:43 +03:00
bol-van
187affb844 nfqws: add seqovl support to multisplit/multidisorder 2024-11-12 16:26:36 +03:00
bol-van
5a82874624 nfqws: new name of split/disorder - fakedsplit/fakeddisorder 2024-11-12 13:02:18 +03:00
bol-van
200cd9caf2 mdig: enlarge dns reply buffer 2024-11-12 10:29:29 +03:00
bol-van
f8b3dca6f5 nfqws: optimize code 2024-11-12 10:23:42 +03:00
bol-van
f973a6f3a6 nfqws: beautify 2024-11-11 21:58:00 +03:00
bol-van
9b3bbb7285 nfqws: minor beautify 2024-11-11 20:35:48 +03:00
bol-van
284f911785 nfqws: move code 2024-11-11 19:48:47 +03:00
bol-van
a17e490851 nfqws: multisplit 2024-11-11 18:41:42 +03:00
bol-van
c1e670be23 quick_start.md: typo 2024-11-11 14:54:27 +03:00
bol-van
918d52c2e6 Revert "quick_start.md: typo"
This reverts commit 1c7080ca68.
2024-11-11 14:53:36 +03:00
bol-van
1c7080ca68 quick_start.md: typo 2024-11-11 14:52:30 +03:00
bol-van
656c549113 quick_start: uninstall 2024-11-11 12:39:33 +03:00
bol-van
41b4c6650b docs works 2024-11-10 17:27:25 +03:00
bol-van
925fdd633a docs works 2024-11-10 17:26:13 +03:00
bol-van
c16b125a55 makefiles: -Os 2024-11-10 14:20:14 +03:00
bol-van
591b246ed6 mdig: fix text mode std io in windows 2024-11-09 23:33:33 +03:00
bol-van
07b8567beb readme: scammers notice 2024-11-09 16:46:23 +03:00
bol-van
f0e68527ba nfqws,tpws: snisld split 2024-11-09 16:02:34 +03:00
bol-van
6514b6f4c3 nfqws: dissect struct 2024-11-09 13:26:20 +03:00
bol-van
d551f2f4ae update license years 2024-11-08 20:05:41 +03:00
bol-van
acb07c9792 install_bin: survive if find is absent but busybox has it 2024-11-08 18:09:22 +03:00
bol-van
da3eedb443 docs: minor corrections 2024-11-08 13:52:06 +03:00
bol-van
d7ce95ed50 remove bins in favour of github-actions 2024-11-08 11:40:07 +03:00
bol-van
c2413e4944 doc works 2024-11-08 11:38:19 +03:00
127 changed files with 4069 additions and 2360 deletions

View File

@@ -87,15 +87,14 @@ jobs:
export LDFLAGS="-Os"
# netfilter libs
git clone --depth 1 -b libmnl-1.0.5 git://git.netfilter.org/libmnl
git clone --depth 1 -b libnfnetlink-1.0.2 git://git.netfilter.org/libnfnetlink
git clone --depth 1 -b libnetfilter_queue-1.0.5 git://git.netfilter.org/libnetfilter_queue
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/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i
./autogen.sh && \
./configure --prefix= --host=$TARGET --enable-static --disable-shared && \
cd $i-*
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
sed -i "s|^prefix=.*|prefix=$DEPS_DIR|g" $DEPS_DIR/lib/pkgconfig/$i.pc
@@ -106,7 +105,7 @@ jobs:
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
(
cd zlib-*
./configure --prefix= --static && \
./configure --prefix= --static
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -282,9 +281,77 @@ jobs:
path: zapret-*.zip
if-no-files-found: error
build-android:
name: Android ${{ matrix.abi }}
runs-on: ubuntu-latest
strategy:
matrix:
include:
- abi: armeabi-v7a
target: armv7a-linux-androideabi
- abi: arm64-v8a
target: aarch64-linux-android
- abi: x86
target: i686-linux-android
- abi: x86_64
target: x86_64-linux-android
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: zapret
- name: Build
env:
ABI: ${{ matrix.abi }}
TARGET: ${{ matrix.target }}
run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
export API=21
export CC="$TOOLCHAIN/bin/clang --target=$TARGET$API"
export AR=$TOOLCHAIN/bin/llvm-ar
export AS=$CC
export LD=$TOOLCHAIN/bin/ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
# optimize for size
export CFLAGS="-Os -flto=auto"
export LDFLAGS="-Os"
# netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
wget -qO- https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
wget -qO- https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj
patch -p1 -d libnetfilter_queue-* -i ../zapret/.github/workflows/libnetfilter_queue-android.patch
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="$CFLAGS -Wno-implicit-function-declaration" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
sed -i "s|^prefix=.*|prefix=$DEPS_DIR|g" $DEPS_DIR/lib/pkgconfig/$i.pc
done
# zapret
CFLAGS="$CFLAGS -I$DEPS_DIR/include" LDFLAGS="$LDFLAGS -L$DEPS_DIR/lib" \
make -C zapret android -j$(nproc)
zip zapret-android-$ABI.zip -j zapret/binaries/my/*
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: zapret-android-${{ matrix.abi }}
path: zapret-*.zip
if-no-files-found: error
release:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
needs: [ build-linux, build-windows, build-macos, build-freebsd ]
needs: [ build-linux, build-windows, build-macos, build-freebsd, build-android ]
permissions:
contents: write
runs-on: ubuntu-latest
@@ -343,6 +410,10 @@ jobs:
if [ -d $dir ]; then
echo "Processing $dir"
case $dir in
*-android-arm64-v8a ) run_dir android-aarch64 ;;
*-android-armeabi-v7a ) run_dir android-arm ;;
*-android-x86 ) run_dir android-x86 ;;
*-android-x86_64 ) run_dir android-x86_64 ;;
*-freebsd-x86_64 ) run_dir freebsd-x64 ;;
*-linux-arm ) run_dir arm ;;
*-linux-arm64 ) run_dir aarch64 ;;

View File

@@ -0,0 +1,41 @@
--- a/src/extra/pktbuff.c
+++ b/src/extra/pktbuff.c
@@ -14,7 +14,7 @@
#include <string.h> /* for memcpy */
#include <stdbool.h>
-#include <netinet/if_ether.h>
+#include <linux/if_ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
--- a/src/nlmsg.c
+++ b/src/nlmsg.c
@@ -21,7 +21,7 @@
#include <linux/netfilter/nfnetlink_queue.h>
-#include <libnetfilter_queue/libnetfilter_queue.h>
+// #include <libnetfilter_queue/libnetfilter_queue.h>
#include "internal.h"
--- a/src/extra/tcp.c
+++ b/src/extra/tcp.c
@@ -139,12 +139,16 @@ void nfq_tcp_compute_checksum_ipv6(struc
* (union is compatible to any of its members)
* This means this part of the code is -fstrict-aliasing safe now.
*/
+#ifndef __ANDROID__
union tcp_word_hdr {
struct tcphdr hdr;
uint32_t words[5];
};
+#endif
+#ifndef tcp_flag_word
#define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words[3])
+#endif
/**
* nfq_pkt_snprintf_tcp_hdr - print tcp header into one buffer in a humnan

2
.gitignore vendored
View File

@@ -1,7 +1,9 @@
/config
ip2net/ip2net
mdig/mdig
nfq/dvtws
nfq/nfqws
nfq/winws.exe
tpws/tpws
binaries/my/
init.d/**/custom

View File

@@ -15,6 +15,19 @@ all: clean
done \
done
android: clean
@mkdir -p "$(TGT)"; \
for dir in $(DIRS); do \
find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \
$(MAKE) -C "$$dir" android || exit; \
for exe in "$$dir/"*; do \
if [ -f "$$exe" ] && [ -x "$$exe" ]; then \
mv -f "$$exe" "${TGT}" ; \
ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \
fi \
done \
done
bsd: clean
@mkdir -p "$(TGT)"; \
for dir in $(DIRS); do \

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,8 +0,0 @@
From this folder winws can be started only standalone.
To run from cygwin shell delete, rename or move cygwin1.dll.
Cygwin refuses to start winws if a copy of cygwin1.dll is present !
How to get win7 and winws compatible version of cygwin :
curl -O https://www.cygwin.com/setup-x86_64.exe
setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,8 +0,0 @@
From this folder winws can be started only standalone.
To run from cygwin shell delete, rename or move cygwin1.dll.
Cygwin refuses to start winws if a copy of cygwin1.dll is present !
How to get win7 and winws compatible version of cygwin :
curl -O https://www.cygwin.com/setup-x86_64.exe
setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -45,7 +45,6 @@ HTTP_PORT=${HTTP_PORT:-80}
HTTPS_PORT=${HTTPS_PORT:-443}
QUIC_PORT=${QUIC_PORT:-443}
UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org}
[ "$CURL_VERBOSE" = 1 ] && CURL_CMD=1
HDRTEMP=/tmp/zapret-hdr.txt
@@ -792,7 +791,7 @@ pktws_ipt_prepare()
# disable PF to avoid interferences
pf_is_avail && pfctl -qd
for ip in $3; do
IPFW_ADD divert $IPFW_DIVERT_PORT $1 from me to $ip $2 proto ip${IPV} out not diverted not sockarg
IPFW_ADD divert $IPFW_DIVERT_PORT $1 from me to $ip $2 proto ip${IPV} out not diverted
done
;;
opf)
@@ -867,7 +866,7 @@ pktws_ipt_prepare_tcp()
;;
ipfw)
for ip in $2; do
IPFW_ADD divert $IPFW_DIVERT_PORT tcp from $ip $1 to me proto ip${IPV} tcpflags syn,ack in not diverted not sockarg
IPFW_ADD divert $IPFW_DIVERT_PORT tcp from $ip $1 to me proto ip${IPV} tcpflags syn,ack in not diverted
done
;;
esac
@@ -994,7 +993,6 @@ ws_curl_test()
# $2 - test function
# $3 - domain
# $4,$5,$6, ... - ws params
local code ws_start=$1 testf=$2 dom=$3
shift
shift
@@ -1013,6 +1011,15 @@ tpws_curl_test()
echo - checking tpws $3 $4 $5 $6 $7 $8 $9${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
local ALL_PROXY="socks5://127.0.0.1:$SOCKS_PORT"
ws_curl_test tpws_start "$@"${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
local code=$?
[ "$code" = 0 ] && {
local testf=$1 dom=$2
shift; shift;
local strategy="$@"
strategy_append_extra_tpws
report_append "ipv${IPV} $dom $testf : tpws ${WF:+$WF }$strategy"
}
return $code
}
pktws_curl_test()
{
@@ -1021,7 +1028,26 @@ pktws_curl_test()
# $3,$4,$5, ... - nfqws/dvtws params
echo - checking $PKTWSD ${WF:+$WF }$3 $4 $5 $6 $7 $8 $9${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
ws_curl_test pktws_start "$@"${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
local code=$?
[ "$code" = 0 ] && {
local testf=$1 dom=$2
shift; shift;
local strategy="$@"
strategy_append_extra_pktws
report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy"
}
return $code
}
strategy_append_extra_pktws()
{
strategy="${strategy:+$strategy${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"}}"
}
strategy_append_extra_tpws()
{
strategy="${strategy:+$strategy${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"}}"
}
xxxws_curl_test_update()
{
# $1 - xxx_curl_test function
@@ -1073,7 +1099,7 @@ report_strategy()
strategy="$(echo "$strategy" | xargs)"
echo "!!!!! $1: working strategy found for ipv${IPV} $2 : $3 $strategy !!!!!"
echo
report_append "ipv${IPV} $2 $1 : $3 ${WF:+$WF }$strategy"
# report_append "ipv${IPV} $2 $1 : $3 ${WF:+$WF }$strategy"
return 0
else
echo "$1: $3 strategy for ipv${IPV} $2 not found"
@@ -1088,7 +1114,7 @@ test_has_split()
}
test_has_fake()
{
contains "$1" fake
[ "$1" = fake ] || starts_with "$1" fake,
}
warn_fool()
{
@@ -1105,25 +1131,34 @@ pktws_curl_test_update_vary()
# $4 - desync mode
# $5,$6,... - strategy
local testf=$1 sec=$2 domain=$3 desync=$4 zerofake split fake
local testf=$1 sec=$2 domain=$3 desync=$4 proto zerofake= splits= pos fake ret=1
shift; shift; shift; shift
zerofake=http
[ "$sec" = 0 ] || zerofake=tls
zerofake="--dpi-desync-fake-$zerofake=0x00000000"
proto=http
[ "$sec" = 0 ] || proto=tls
test_has_fake $desync && zerofake="--dpi-desync-fake-$proto=0x00000000"
test_has_split $desync && {
splits="method+2 midsld"
[ "$sec" = 0 ] || splits="1 midsld 1,midsld"
}
for fake in '' $zerofake ; do
for split in '' '--dpi-desync-split-pos=1' ; do
pktws_curl_test_update $testf $domain --dpi-desync=$desync "$@" $fake $split && return 0
# split-pos=1 is meaningful for DPIs searching for 16 03 in TLS. no reason to apply to http
[ "$sec" = 1 ] || break
test_has_split $desync || break
if [ -n "$splits" ]; then
for pos in $splits ; do
pktws_curl_test_update $testf $domain --dpi-desync=$desync "$@" --dpi-desync-split-pos=$pos $fake && {
[ "$SCANLEVEL" = force ] || return 0
ret=0
}
done
test_has_fake $desync || break
else
pktws_curl_test_update $testf $domain --dpi-desync=$desync "$@" $fake && {
[ "$SCANLEVEL" = force ] || return 0
ret=0
}
fi
done
return 1
return $ret
}
pktws_check_domain_http_bypass_()
@@ -1132,7 +1167,10 @@ pktws_check_domain_http_bypass_()
# $2 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
# $3 - domain
local tests='fake' ret ok ttls s f e desync pos fooling frag sec="$2" delta hostcase
local ok ttls s f f2 e desync pos fooling frag sec="$2" delta splits
local need_split need_disorder need_fakedsplit need_fakeddisorder need_fake need_wssize
local splits_http='method+2 midsld method+2,midsld'
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
[ "$sec" = 0 ] && {
for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase'; do
@@ -1140,74 +1178,62 @@ pktws_check_domain_http_bypass_()
done
}
s="--dpi-desync=split2"
ok=0
pktws_curl_test_update $1 $3 $s
ret=$?
[ "$ret" = 0 ] && {
[ "$SCANLEVEL" = quick ] && return
ok=1
}
[ "$ret" != 0 -o "$SCANLEVEL" = force ] && {
if [ "$sec" = 0 ]; then
pktws_curl_test_update $1 $3 $s --hostcase && {
[ "$SCANLEVEL" = quick ] && return
ok=1
}
for pos in method host; do
for hostcase in '' '--hostcase'; do
pktws_curl_test_update $1 $3 $s --dpi-desync-split-http-req=$pos $hostcase && {
[ "$SCANLEVEL" = quick ] && return
ok=1
}
done
done
else
for pos in sni sniext; do
pktws_curl_test_update $1 $3 $s --dpi-desync-split-tls=$pos && {
[ "$SCANLEVEL" = quick ] && return
ok=1
}
done
fi
for pos in 1 3 4 5 10 50; do
s="--dpi-desync=split2 --dpi-desync-split-pos=$pos"
if pktws_curl_test_update $1 $3 $s; then
[ "$SCANLEVEL" = quick ] && return
ok=1
[ "$SCANLEVEL" = force ] || break
elif [ "$sec" = 0 ]; then
pktws_curl_test_update $1 $3 $s --hostcase && [ "$SCANLEVEL" = quick ] && return
fi
done
}
[ "$ok" = 1 -a "$SCANLEVEL" != force ] || tests="$tests split fake,split2 fake,split"
pktws_curl_test_update $1 $3 --dpi-desync=disorder2
ret=$?
[ "$ret" = 0 -a "$SCANLEVEL" = quick ] && return
[ "$ret" != 0 -o "$SCANLEVEL" = force ] && {
pktws_curl_test_update $1 $3 --dpi-desync=disorder2 --dpi-desync-split-pos=1
ret=$?
[ "$ret" = 0 -a "$SCANLEVEL" = quick ] && return
}
[ "$ret" != 0 -o "$SCANLEVEL" = force ] && tests="$tests disorder fake,disorder2 fake,disorder"
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
need_wssize=1
for e in '' '--wssize 1:6'; do
need_split=
need_disorder=
[ -n "$e" ] && {
pktws_curl_test_update $1 $3 $e && [ "$SCANLEVEL" = quick ] && return
for desync in split2 disorder2; do
pktws_curl_test_update_vary $1 $2 $3 $desync $e && [ "$SCANLEVEL" = quick ] && return
done
}
for desync in $tests; do
for desync in multisplit multidisorder; do
ok=0
splits="$splits_http"
[ "$sec" = 0 ] || splits="$splits_tls"
for pos in $splits; do
pktws_curl_test_update $1 $3 --dpi-desync=$desync --dpi-desync-split-pos=$pos $e && {
[ "$SCANLEVEL" = quick ] && return
ok=1
need_wssize=0
[ "$SCANLEVEL" = force ] || break
}
done
[ "$ok" = 1 -a "$SCANLEVEL" != force ] || {
case $desync in
multisplit)
need_split=1
;;
multidisorder)
need_disorder=1
;;
esac
}
done
need_fakedsplit=1
need_fakeddisorder=1
need_fake=1
for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do
[ "$need_fake" = 0 ] && test_has_fake "$desync" && continue
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
ok=0
for ttl in $ttls; do
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-ttl=$ttl $e && {
[ "$SCANLEVEL" = quick ] && return
ok=1
need_wssize=0
break
}
done
# only skip tests if TTL succeeded. do not skip if TTL failed but fooling succeeded
[ $ok = 1 -a "$SCANLEVEL" != force ] && {
[ "$desync" = fake ] && need_fake=0
[ "$desync" = fakedsplit ] && need_fakedsplit=0
[ "$desync" = fakeddisorder ] && need_fakeddisorder=0
}
f=
[ "$UNAME" = "OpenBSD" ] || f="badsum"
f="$f badseq datanoack md5sig"
@@ -1216,37 +1242,68 @@ pktws_check_domain_http_bypass_()
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && {
warn_fool $fooling
[ "$SCANLEVEL" = quick ] && return
need_wssize=0
}
done
done
[ "$IPV" = 6 ] && {
f="hopbyhop hopbyhop,split2 hopbyhop,disorder2 destopt destopt,split2 destopt,disorder2"
[ -n "$IP6_DEFRAG_DISABLE" ] && f="$f ipfrag1 ipfrag1,split2 ipfrag1,disorder2"
f="hopbyhop ${need_split:+hopbyhop,multisplit} ${need_disorder:+hopbyhop,multidisorder} destopt ${need_split:+destopt,multisplit} ${need_disorder:+destopt,multidisorder}"
[ -n "$IP6_DEFRAG_DISABLE" ] && f="$f ipfrag1 ${need_split:+ ipfrag1,multisplit} ${need_disorder:+ ipfrag1,multidisorder}"
for desync in $f; do
pktws_curl_test_update_vary $1 $2 $3 $desync $e && [ "$SCANLEVEL" = quick ] && return
pktws_curl_test_update_vary $1 $2 $3 $desync $e && {
[ "$SCANLEVEL" = quick ] && return
need_wssize=0
}
done
}
for desync in split2 disorder2; do
s="--dpi-desync=$desync"
[ "$need_split" = 1 ] && {
# relative markers can be anywhere, even in subsequent packets. first packet can be MTU-full.
# make additional split pos "10" to guarantee enough space for seqovl and likely to be before midsld,sniext,...
# method is always expected in the beginning of the first packet
f="method+2 method+2,midsld"
[ "$sec" = 0 ] || f="10 10,sniext+1 10,sniext+4 10,midsld"
for pos in $f; do
pktws_curl_test_update $1 $3 --dpi-desync=multisplit --dpi-desync-split-pos=$pos --dpi-desync-split-seqovl=1 $e && {
[ "$SCANLEVEL" = quick ] && return
need_wssize=0
}
done
[ "$sec" != 0 ] && pktws_curl_test_update $1 $3 --dpi-desync=multisplit --dpi-desync-split-pos=2 --dpi-desync-split-seqovl=336 --dpi-desync-split-seqovl-pattern="$ZAPRET_BASE/files/fake/tls_clienthello_iana_org.bin" $e && {
[ "$SCANLEVEL" = quick ] && return
need_wssize=0
}
}
[ "$need_disorder" = 1 ] && {
if [ "$sec" = 0 ]; then
for pos in method host; do
pktws_curl_test_update $1 $3 $s --dpi-desync-split-seqovl=1 --dpi-desync-split-http-req=$pos $e && [ "$SCANLEVEL" = quick ] && return
for pos in 'method+1 method+2' 'midsld-1 midsld' 'method+1 method+2,midsld'; do
f="$(extract_arg 1 $pos)"
f2="$(extract_arg 2 $pos)"
pktws_curl_test_update $1 $3 --dpi-desync=multidisorder --dpi-desync-split-pos=$f2 --dpi-desync-split-seqovl=$f $e && {
[ "$SCANLEVEL" = quick ] && return
need_wssize=0
}
done
else
for pos in sni sniext; do
pktws_curl_test_update $1 $3 $s --dpi-desync-split-seqovl=1 --dpi-desync-split-tls=$pos $e && [ "$SCANLEVEL" = quick ] && return
done
fi
for pos in 2 3 4 5 10 50; do
pktws_curl_test_update $1 $3 $s --dpi-desync-split-seqovl=$(($pos - 1)) --dpi-desync-split-pos=$pos $e && [ "$SCANLEVEL" = quick ] && return
done
[ "$sec" != 0 -a $desync = split2 ] && {
pktws_curl_test_update $1 $3 $s --dpi-desync-split-seqovl=336 --dpi-desync-split-seqovl-pattern="$ZAPRET_BASE/files/fake/tls_clienthello_iana_org.bin" $e && [ "$SCANLEVEL" = quick ] && return
for pos in '1 2' 'sniext sniext+1' 'sniext+3 sniext+4' 'midsld-1 midsld' '1 2,midsld'; do
f=$(extract_arg 1 $pos)
f2=$(extract_arg 2 $pos)
pktws_curl_test_update $1 $3 --dpi-desync=multidisorder --dpi-desync-split-pos=$f2 --dpi-desync-split-seqovl=$f $e && {
[ "$SCANLEVEL" = quick ] && return
need_wssize=0
}
done
fi
}
for desync in $tests; do
need_fakedsplit=1
need_fakeddisorder=1
need_fake=1
for desync in fake ${need_split:+fakedsplit fake,multisplit fake,fakedsplit} ${need_disorder:+fakeddisorder fake,multidisorder fake,fakeddisorder}; do
[ "$need_fake" = 0 ] && test_has_fake "$desync" && continue
[ "$need_fakedsplit" = 0 ] && contains "$desync" fakedsplit && continue
[ "$need_fakeddisorder" = 0 ] && contains "$desync" fakeddisorder && continue
ok=0
for delta in 1 2 3 4 5; do
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-ttl=1 --dpi-desync-autottl=$delta $e && ok=1
@@ -1256,18 +1313,25 @@ pktws_check_domain_http_bypass_()
echo "WARNING ! although autottl worked it requires testing on multiple domains to find out reliable delta"
echo "WARNING ! if a reliable delta cannot be found it's a good idea not to use autottl"
[ "$SCANLEVEL" = quick ] && return
need_wssize=0
[ "$SCANLEVEL" = force ] || {
[ "$desync" = fake ] && need_fake=0
[ "$desync" = fakedsplit ] && need_fakedsplit=0
[ "$desync" = fakeddisorder ] && need_fakeddisorder=0
}
}
done
s="http_iana_org.bin"
[ "$sec" = 0 ] || s="tls_clienthello_iana_org.bin"
for desync in syndata syndata,split2 syndata,disorder2 ; do
for desync in syndata ${need_split:+syndata,multisplit} ${need_disorder:+syndata,multidisorder} ; do
pktws_curl_test_update_vary $1 $2 $3 $desync $e && [ "$SCANLEVEL" = quick ] && return
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fake-syndata="$ZAPRET_BASE/files/fake/$s" $e && [ "$SCANLEVEL" = quick ] && return
done
# do not do wssize test for http and TLS 1.3. it's useless
[ "$sec" = 1 ] || break
[ "$SCANLEVEL" = force -o "$need_wssize" = 1 ] || break
done
}
pktws_check_domain_http_bypass()
@@ -1278,7 +1342,7 @@ pktws_check_domain_http_bypass()
local strategy
pktws_check_domain_http_bypass_ "$@"
strategy="${strategy:+$strategy${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"}}"
strategy_append_extra_pktws
report_strategy $1 $3 $PKTWSD
}
@@ -1323,7 +1387,7 @@ pktws_check_domain_http3_bypass()
local strategy
pktws_check_domain_http3_bypass_ "$@"
strategy="${strategy:+$strategy $PKTWS_EXTRA $PKTWS_EXTRA_1 $PKTWS_EXTRA_2 $PKTWS_EXTRA_3 $PKTWS_EXTRA_4 $PKTWS_EXTRA_5 $PKTWS_EXTRA_6 $PKTWS_EXTRA_7 $PKTWS_EXTRA_8 $PKTWS_EXTRA_9}"
strategy_append_extra_pktws
report_strategy $1 $2 $PKTWSD
}
warn_mss()
@@ -1338,50 +1402,58 @@ tpws_check_domain_http_bypass_()
# $2 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
# $3 - domain
local s mss s2 s3 pos sec="$2"
local s mss s2 s3 oobdis pos sec="$2"
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld,endhost-1'
local splits_http='method+2 midsld method+2,midsld'
# simulteneous oob and disorder works properly only in linux. other systems retransmit oob byte without URG tcp flag and poison tcp stream.
[ "$UNAME" = Linux ] && oobdis='--oob --disorder'
if [ "$sec" = 0 ]; then
for s in '--hostcase' '--hostspell=hoSt' '--hostdot' '--hosttab' '--hostnospace' '--domcase' \
'--hostpad=1024' '--hostpad=2048' '--hostpad=4096' '--hostpad=8192' '--hostpad=16384' ; do
for s in '--hostcase' '--hostspell=hoSt' '--hostdot' '--hosttab' '--hostnospace' '--domcase' ; do
tpws_curl_test_update $1 $3 $s && [ "$SCANLEVEL" = quick ] && return
done
for s2 in '' '--oob' '--disorder' '--oob --disorder'; do
for s in '--split-http-req=method' '--split-http-req=method --hostcase' '--split-http-req=host' '--split-http-req=host --hostcase' ; do
tpws_curl_test_update $1 $3 $s $s2 && [ "$SCANLEVEL" = quick ] && return
for s in 1024 2048 4096 8192 16384 ; do
tpws_curl_test_update $1 $3 --hostpad=$s && [ "$SCANLEVEL" != force ] && {
[ "$SCANLEVEL" = quick ] && return
break
}
done
for s2 in '' '--hostcase' '--oob' '--disorder' ${oobdis:+"$oobdis"}; do
for s in $splits_http ; do
tpws_curl_test_update $1 $3 --split-pos=$s $s2 && [ "$SCANLEVEL" != force ] && {
[ "$SCANLEVEL" = quick ] && return
break
}
done
done
for s in '--methodspace' '--unixeol' '--methodeol'; do
tpws_curl_test_update $1 $3 $s && [ "$SCANLEVEL" = quick ] && return
done
else
local need_mss=1
for mss in '' 88; do
s3=${mss:+--mss=$mss}
for s2 in '' '--oob' '--disorder' '--oob --disorder'; do
for pos in sni sniext; do
s="--split-tls=$pos"
tpws_curl_test_update $1 $3 $s $s2 $s3 && warn_mss $s3 && [ "$SCANLEVEL" != force ] && {
[ "$SCANLEVEL" = quick ] && return
break
}
done
for pos in 1 2 3 4 5 10 50; do
s="--split-pos=$pos"
tpws_curl_test_update $1 $3 $s $s2 $s3 && warn_mss $s3 && [ "$SCANLEVEL" != force ] && {
for s2 in '' '--oob' '--disorder' ${oobdis:+"$oobdis"}; do
for pos in $splits_tls; do
tpws_curl_test_update $1 $3 --split-pos=$pos $s2 $s3 && warn_mss $s3 && [ "$SCANLEVEL" != force ] && {
[ "$SCANLEVEL" = quick ] && return
need_mss=0
break
}
done
done
for s2 in '--tlsrec=sni' '--tlsrec=sni --split-tls=sni' '--tlsrec=sni --split-tls=sni --oob' \
'--tlsrec=sni --split-tls=sni --disorder' '--tlsrec=sni --split-tls=sni --oob --disorder' \
'--tlsrec=sni --split-pos=1' '--tlsrec=sni --split-pos=1 --oob' '--tlsrec=sni --split-pos=1 --disorder' \
'--tlsrec=sni --split-pos=1 --oob --disorder'; do
tpws_curl_test_update $1 $3 $s2 $s3 && warn_mss $s3 && [ "$SCANLEVEL" != force ] && {
for s in '' '--oob' '--disorder' ${oobdis:+"$oobdis"}; do
for s2 in '--tlsrec=midsld' '--tlsrec=sniext+1 --split-pos=midsld' '--tlsrec=sniext+4 --split-pos=midsld' '--tlsrec=sniext+1 --split-pos=1,midsld' '--tlsrec=sniext+4 --split-pos=1,midsld' ; do
tpws_curl_test_update $1 $3 $s2 $s $s3 && warn_mss $s3 && [ "$SCANLEVEL" != force ] && {
[ "$SCANLEVEL" = quick ] && return
need_mss=0
break
}
done
done
# only linux supports mss
[ "$UNAME" = Linux -a "$sec" = 1 ] || break
[ "$SCANLEVEL" = force -o "$need_mss" = 1 ] || break
done
fi
}
@@ -1393,7 +1465,7 @@ tpws_check_domain_http_bypass()
local strategy
tpws_check_domain_http_bypass_ "$@"
strategy="${strategy:+$strategy${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"}}"
strategy_append_extra_tpws
report_strategy $1 $3 tpws
}
@@ -1682,17 +1754,6 @@ ask_params()
echo "installed curl version does not support http3 QUIC. tests disabled."
fi
IGNORE_CA=0
CURL_OPT=
[ $ENABLE_HTTPS_TLS13 = 1 -o $ENABLE_HTTPS_TLS12 = 1 ] && {
echo
echo "on limited systems like openwrt CA certificates might not be installed to preserve space"
echo "in such a case curl cannot verify server certificate and you should either install ca-bundle or disable verification"
echo "however disabling verification will break https check if ISP does MitM attack and substitutes server certificate"
ask_yes_no_var IGNORE_CA "do not verify server certificate"
[ "$IGNORE_CA" = 1 ] && CURL_OPT=-k
}
echo
echo "sometimes ISPs use multiple DPIs or load balancing. bypass strategies may work unstable."
printf "how many times to repeat each test (default: 1) : "

View File

@@ -60,11 +60,22 @@ starts_with()
esac
return 1
}
extract_arg()
{
# $1 - arg number
# $2,$3,... - args
local n=$1
while [ -n "$1" ]; do
shift
[ $n -eq 1 ] && { echo "$1"; return 0; }
n=$(($n-1))
done
return 1
}
find_str_in_list()
{
# $1 - string
# $2 - space separated values
local v
[ -n "$1" ] && {
for v in $2; do

View File

@@ -190,6 +190,7 @@ check_system()
get_fwtype
OPENWRT_FW3=
OPENWRT_FW4=
local info
UNAME=$(uname)
@@ -201,27 +202,35 @@ check_system()
# some distros include systemctl without systemd
if [ -d "$SYSTEMD_DIR" ] && [ -x "$SYSTEMCTL" ] && [ "$INIT" = "systemd" ]; then
SYSTEM=systemd
elif [ -f "/etc/openwrt_release" ] && exists opkg && exists uci && [ "$INIT" = "procd" ] ; then
{
elif [ -f "/etc/openwrt_release" ] && exists opkg || exists apk && exists uci && [ "$INIT" = "procd" ] ; then
SYSTEM=openwrt
OPENWRT_PACKAGER=opkg
OPENWRT_PACKAGER_INSTALL="opkg install"
OPENWRT_PACKAGER_UPDATE="opkg update"
exists apk && {
OPENWRT_PACKAGER=apk
OPENWRT_PACKAGER_INSTALL="apk add"
OPENWRT_PACKAGER_UPDATE=
}
info="package manager $OPENWRT_PACKAGER\n"
if openwrt_fw3 ; then
OPENWRT_FW3=1
info="openwrt firewall uses fw3"
info="${info}firewall fw3"
if is_ipt_flow_offload_avail; then
info="$info. hardware flow offloading requires iptables."
else
info="$info. flow offloading unavailable."
fi
elif openwrt_fw4; then
info="openwrt firewall uses fw4. flow offloading requires nftables."
OPENWRT_FW4=1
info="${info}firewall fw4. flow offloading requires nftables."
fi
}
elif openrc_test; then
SYSTEM=openrc
else
echo system is not either systemd, openrc or openwrt based
echo easy installer can set up config settings but can\'t configure auto start
echo you have to do it manually. check readme.txt for manual setup info.
echo you have to do it manually. check readme.md for manual setup info.
if [ -n "$1" ] || ask_yes_no N "do you want to continue"; then
SYSTEM=linux
else
@@ -232,11 +241,11 @@ check_system()
elif [ "$UNAME" = "Darwin" ]; then
SYSTEM=macos
else
echo easy installer only supports Linux and MacOS. check readme.txt for supported systems and manual setup info.
echo easy installer only supports Linux and MacOS. check readme.md for supported systems and manual setup info.
exitp 5
fi
echo system is based on $SYSTEM
[ -n "$info" ] && echo $info
[ -n "$info" ] && printf "${info}\n"
}
get_free_space_mb()
@@ -420,14 +429,21 @@ check_kmod()
}
check_package_exists_openwrt()
{
[ -n "$(opkg list $1)" ]
[ -n "$($OPENWRT_PACKAGER list $1)" ]
}
check_package_openwrt()
{
case $OPENWRT_PACKAGER in
opkg)
[ -n "$(opkg list-installed $1)" ] && return 0
local what="$(opkg whatprovides $1 | tail -n +2 | head -n 1)"
[ -n "$what" ] || return 1
[ -n "$(opkg list-installed $what)" ]
;;
apk)
apk info -e $1
;;
esac
}
check_packages_openwrt()
{
@@ -516,9 +532,8 @@ restart_openwrt_firewall()
local FW=fw4
[ -n "$OPENWRT_FW3" ] && FW=fw3
$FW -q restart || {
exists $FW && $FW -q restart || {
echo could not restart firewall $FW
exitp 30
}
}
remove_openwrt_firewall()
@@ -684,7 +699,23 @@ check_prerequisites_linux()
removable_pkgs_openwrt()
{
PKGS="iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl"
local pkg PKGS2
[ -n "$OPENWRT_FW4" ] && PKGS2="$PKGS2 iptables-zz-legacy iptables ip6tables-zz-legacy ip6tables"
[ -n "$OPENWRT_FW3" ] && PKGS2="$PKGS2 nftables-json nftables-nojson nftables"
PKGS=
for pkg in $PKGS2; do
check_package_exists_openwrt $pkg && PKGS="${PKGS:+$PKGS }$pkg"
done
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS"
}
openwrt_fix_broken_apk_uninstall_scripts()
{
# at least in early snapshots with apk removing gnu gzip, sort, ... does not restore links to busybox
# system may become unusable
exists sort || { echo fixing missing sort; ln -fs /bin/busybox /usr/bin/sort; }
exists gzip || { echo fixing missing gzip; ln -fs /bin/busybox /bin/gzip; }
exists sleep || { echo fixing missing sleep; ln -fs /bin/busybox /bin/sleep; }
}
remove_extra_pkgs_openwrt()
@@ -693,19 +724,32 @@ remove_extra_pkgs_openwrt()
echo \* remove dependencies
removable_pkgs_openwrt
echo these packages may have been installed by install_easy.sh : $PKGS
ask_yes_no N "do you want to remove them" && opkg remove --autoremove $PKGS
ask_yes_no N "do you want to remove them" && {
case $OPENWRT_PACKAGER in
opkg)
opkg remove --autoremove $PKGS
;;
apk)
apk del $PKGS
openwrt_fix_broken_apk_uninstall_scripts
;;
esac
}
}
check_prerequisites_openwrt()
{
echo \* checking prerequisites
local PKGS="curl" UPD=0
local PKGS="curl" UPD=0 local pkg_iptables
case "$FWTYPE" in
iptables)
PKGS="$PKGS ipset iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra"
[ "$DISABLE_IPV6" != "1" ] && PKGS="$PKGS ip6tables ip6tables-mod-nat ip6tables-extra"
pkg_iptables=iptables
check_package_exists_openwrt iptables-zz-legacy && pkg_iptables=iptables-zz-legacy
PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra"
check_package_exists_openwrt ip6tables-zz-legacy && pkg_iptables=ip6tables-zz-legacy
[ "$DISABLE_IPV6" = 1 ] || PKGS="$PKGS $pkg_iptables ip6tables-mod-nat ip6tables-extra"
;;
nftables)
PKGS="$PKGS nftables kmod-nft-nat kmod-nft-offload kmod-nft-queue"
@@ -717,9 +761,9 @@ check_prerequisites_openwrt()
else
echo \* installing prerequisites
opkg update
$OPENWRT_PACKAGER_UPDATE
UPD=1
opkg install $PKGS || {
$OPENWRT_PACKAGER_INSTALL $PKGS || {
echo could not install prerequisites
exitp 6
}
@@ -732,10 +776,10 @@ check_prerequisites_openwrt()
echo installer can install GNU gzip but it requires about 100 Kb space
if ask_yes_no N "do you want to install GNU gzip"; then
[ "$UPD" = "0" ] && {
opkg update
$OPENWRT_PACKAGER_UPDATE
UPD=1
}
opkg install --force-overwrite gzip
$OPENWRT_PACKAGER_INSTALL --force-overwrite gzip
fi
}
is_linked_to_busybox sort && {
@@ -745,10 +789,10 @@ check_prerequisites_openwrt()
echo installer can install GNU sort but it requires about 100 Kb space
if ask_yes_no N "do you want to install GNU sort"; then
[ "$UPD" = "0" ] && {
opkg update
$OPENWRT_PACKAGER_UPDATE
UPD=1
}
opkg install --force-overwrite coreutils-sort
$OPENWRT_PACKAGER_INSTALL --force-overwrite coreutils-sort
fi
}
[ "$FSLEEP" = 0 ] && is_linked_to_busybox sleep && {
@@ -757,10 +801,10 @@ check_prerequisites_openwrt()
echo if you want to speed up blockcheck install coreutils-sleep. it requires about 40 Kb space
if ask_yes_no N "do you want to install COREUTILS sleep"; then
[ "$UPD" = "0" ] && {
opkg update
$OPENWRT_PACKAGER_UPDATE
UPD=1
}
opkg install --force-overwrite coreutils-sleep
$OPENWRT_PACKAGER_INSTALL --force-overwrite coreutils-sleep
fsleep_setup
fi
}

View File

@@ -55,7 +55,7 @@ TPPORT_SOCKS=987
# <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list
TPWS_SOCKS_OPT="
--filter-tcp=80 --methodeol <HOSTLIST> --new
--filter-tcp=443 --split-tls=sni --disorder <HOSTLIST>
--filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST>
"
TPWS_ENABLE=0
@@ -65,7 +65,7 @@ TPWS_PORTS=80,443
# <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list
TPWS_OPT="
--filter-tcp=80 --methodeol <HOSTLIST> --new
--filter-tcp=443 --split-tls=sni --disorder <HOSTLIST>
--filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST>
"
NFQWS_ENABLE=0
@@ -89,8 +89,8 @@ NFQWS_UDP_PKT_IN=0
# hostlist markers are replaced to empty string if MODE_FILTER does not satisfy
# <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list
NFQWS_OPT="
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
--filter-tcp=443 --dpi-desync=fake,disorder2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
--filter-tcp=80 --dpi-desync=fake,multisplit --dpi-desync-split-pos=method+2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
--filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-fooling=badseq,md5sig <HOSTLIST> --new
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST_NOAUTO>
"

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2016-2021 bol-van
Copyright (c) 2016-2024 bol-van
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -100,7 +100,7 @@ Later you will add ipfw commands to `/etc/rc.firewall.my` to be reapplied after
You can also run zapret daemons from there. Start them with `--daemon` options, for example
```
pkill ^dvtws$
/opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=split2
/opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=multisplit --dpi-desync-split-pos=2
```
To restart firewall and daemons run : `/etc/rc.d/ipfw restart`
@@ -157,7 +157,7 @@ ipfw delete 100
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted not sockarg xmit em0
# required for autottl mode only
ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
Process only table zapret with the exception of table nozapret:
@@ -167,7 +167,7 @@ ipfw add 100 allow tcp from me to table\(nozapret\) 80,443
ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted not sockarg xmit em0
# required for autottl mode only
ipfw add 100 divert 989 tcp from table\(zapret\) 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
Reinjection loop avoidance. FreeBSD artificially ignores sockarg for ipv6 in
@@ -245,7 +245,7 @@ sysctl net.inet6.ip6.pfil.inbound=ipfw,pf
ipfw delete 100
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted not sockarg xmit em0
pkill ^dvtws$
dvtws --daemon --port 989 --dpi-desync=split2
dvtws --daemon --port 989 --dpi-desync=multisplit --dpi-desync-split-pos=2
# required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state
pfctl -d ; pfctl -e
@@ -280,7 +280,7 @@ Autostart `/usr/local/etc/rc.d/zapret.sh`:
```
pfctl -a zapret -f /etc/zapret.anchor
pkill ^tpws$
tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-http-req=method --split-pos=2
tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-pos=2
```
After reboot check that anchor is created and referred from the main ruleset:
@@ -342,7 +342,7 @@ pass out quick on em0 proto tcp to port {80,443} divert-packet port 989
Then:
```
pfctl -f /etc/pf.conf
./dvtws --port=989 --dpi-desync=split2
./dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
`dwtws` only for table zapret with the exception of table nozapret :
@@ -375,7 +375,7 @@ pass out quick on em0 inet6 proto tcp to <zapret6-user> port {80,443} divert-p
Then:
```
pfctl -f /etc/pf.conf
./dvtws --port=989 --dpi-desync=split2
./dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
divert-packet automatically adds the reverse rule. By default also incoming

View File

@@ -143,7 +143,7 @@ $ ipfw -q -f flush
zapret, добавив в параметры `--daemon`. Например так:
```sh
$ pkill ^dvtws$
$ /opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=split2
$ /opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=multisplit --dpi-desync-split-pos=2
```
Для перезапуска фаервола и демонов достаточно будет сделать:
@@ -209,7 +209,7 @@ $ ipfw delete 100
$ ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0
# required for autottl mode only
$ ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diverted recv em0
$ /opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2
$ /opt/zapret/nfq/dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
#### Трафик только на таблицу zapret, за исключением таблицы nozapret
@@ -220,7 +220,7 @@ $ ipfw add 100 allow tcp from me to table\(nozapret\) 80,443
$ ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted not sockarg xmit em0
# required for autottl mode only
$ ipfw add 100 divert 989 tcp from table\(zapret\) 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0
$ /opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2
$ /opt/zapret/nfq/dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
@@ -317,7 +317,7 @@ sysctl net.inet6.ip6.pfil.inbound=ipfw,pf
ipfw delete 100
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0
pkill ^dvtws$
dvtws --daemon --port 989 --dpi-desync=split2
dvtws --daemon --port 989 --dpi-desync=multisplit --dpi-desync-split-pos=2
# required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state
pfctl -d ; pfctl -e
@@ -357,7 +357,7 @@ rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::20c:29ff:5ae3:4821 por
```sh
$ pfctl -a zapret -f /etc/zapret.anchor
$ pkill ^tpws$
$ tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-http-req=method --split-pos=2
$ tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-pos=2
```
4. После перезагрузки проверьте, что правила создались:
@@ -424,7 +424,7 @@ pass out quick on em0 proto tcp to port {80,443} divert-packet port 989 no sta
```sh
$ pfctl -f /etc/pf.conf
$ ./dvtws --port=989 --dpi-desync=split2
$ ./dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
#### Трафик только на таблицу zapret, за исключением таблицы nozapret
@@ -456,7 +456,7 @@ pass out quick on em0 inet6 proto tcp to <zapret6-user> port {80,443} divert-p
```sh
$ pfctl -f /etc/pf.conf
$ ./dvtws --port=989 --dpi-desync=split2
$ ./dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```

View File

@@ -70,7 +70,7 @@ pass in quick on em0 proto tcp from port {80,443} flags SA/SA divert-packet por
pass in quick on em0 proto tcp from port {80,443} no state
pass out quick on em0 proto tcp to port {80,443} divert-packet port 989 no state
pfctl -f /etc/pf.conf
./dvtws --port=989 --dpi-desync=split2
./dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
; dvtws with table limitations : to zapret,zapret6 but not to nozapret,nozapret6
; reload tables : pfctl -f /etc/pf.conf

View File

@@ -358,8 +358,34 @@ blockcheck: do not require root if SKIP_PKTWS=1
v68:
readme.md : move russian version to markdown
docs : move russian version to markdown
nfqws,tpws: use alternate $ sign for $<config_file>
repo: binaries removed from repo. git actions binaries build in releases.
uninstall_easy.sh: offer to remove dependencies in openwrt
install_easy.sh: allow to download lists in autohostlist filter mode
v69:
nfqws, tpws: multisplit/multidisorder support.
nfqws: name change split->fakedsplit, disorder->fakeddisorder. compat : old names are synonyms
nfqws: --dpi-desync-split-http-req, --dpi-desync-split-tls deprecated. compat : these parameters add split point to multisplit.
nfqws: --dpi-desync=split2|disorder2 deprecated. compat: they are now synonyms for multisplit/multidisorder
nfqws: cancel seqovl if MTU is exceeded (linux only). cancel seqovl for disorder if seqovl>=first_part_size.
nfqws: fixed splits in multiple TLS segments.
tpws: --split-http-req,--split-tls deprecated. compat : these parameters add split point to multisplit.
tpws: --tlsrec now takes pos markers. compat : old names are converted to pos markers
tpws: --tlsrec-pos deprecated. compat : sets absolute pos marker
nfqws,tpws: chown autohostlist, autohostlist debug log and debug log files after options parse
nfqws,tpws: set EXEDIR env var to use in @config (won't work for stadalone winws without /bin/sh)
dvtws: set random/increasing ip_id value in generated packets
mdig: fixed parsing of DNS reply in windows (stdin is opened as text, not binary)
tpws: support compile for android NDK api level >= 21 (Android 5.0)
tpws: --fix-seg segmentation fixer
repo: build for android NDK api level 21 (Android 5.0)
install_easy: support for APK package manager in openwrt
blockcheck: removed ignore CA question
blockcheck: removed IGNORE_CA, CURL_VERBOSE
blockcheck: added CURL_OPT
blockcheck: new strategies support
blockcheck: test sequence rework
blockcheck: view all working strategies in summary

View File

@@ -1,21 +1,57 @@
How to compile native programs for use in openwrt
-------------------------------------------------
1) Download latest SDK for your platform from https://downloads.openwrt.org
1) Install required packages to the host system :
debian,ubuntu : apt install build-essential patch libncurses-dev python3-distutils unzip gawk wget git
fedora: dnf install make patch gcc g++ ncurses-devel git perl
Other packages may be required on your distribution. Look for the errors.
2) Download latest SDK for your target platform from https://downloads.openwrt.org
examples :
curl -o - https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz | tar -Jxvf -
cd openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64
2) ./scripts/feeds update -a
./scripts/feeds install -a
curl -o - https://downloads.openwrt.org/snapshots/targets/x86/64/openwrt-sdk-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst | tar --zstd -xvf -
cd openwrt-sdk-x86-64_gcc-13.3.0_musl.Linux-x86_64
3) cp -R /opt/zapret/docs/compile/openwrt/. .
3) Install required libs
./scripts/feeds update base packages
./scripts/feeds install libnetfilter-queue zlib libcap
4) Prepare openwrt package definitions
cp -R /opt/zapret/docs/compile/openwrt/. .
cp -R /opt/zapret/tpws package/zapret/tpws
cp -R /opt/zapret/nfq package/zapret/nfqws
cp -R /opt/zapret/mdig package/zapret/mdig
cp -R /opt/zapret/ip2net package/zapret/ip2net
rm -f package/zapret/tpws/tpws/tpws package/zapret/nfqws/nfq/nfqws package/zapret/mdig/mdig/mdig package/zapret/ip2net/ip2net/ip2net
4) make package/{tpws,nfqws,mdig,ip2net}/compile
5) Prepare .config
5) find bin -name tpws*.ipk
#take your tpws*.ipk , nfqws*.ipk , ip2net*.ipk, mdig*.ipk from there
make defconfig
If you only need bins without packages comment 'CONFIG_AUTOREMOVE=y' line in .config
6) Compile
dynamic build : make package/{tpws,nfqws,mdig,ip2net}/compile
static build : make CFLAGS=-static package/{tpws,nfqws,mdig,ip2net}/compile
7) Get result
executables only : build_dir/target/<progname>
ipk or apk packages : bin/packages/*/base
8) Installating to openwrt to use with zapret
zapret with or without binaries should be already installed in /opt/zapret.
Install ipk's or apk's with all compiled progs using opkg or apk.
Bins are placed to /opt/zapret/binaries/my.
Or copy binaries there manually and set chmod 755 to them.
Run install_bin.sh or install_easy.sh. They will use bins in 'my' folder.

View File

@@ -0,0 +1,16 @@
debian,ubuntu :
apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev
make -C /opt/zapret
FreeBSD :
make -C /opt/zapret
OpenBSD :
make -C /opt/zapret bsd
MacOS :
make -C /opt/zapret mac

View File

@@ -0,0 +1,29 @@
Windows x64
1) Download latest cygwin for windows 7
curl -O https://www.cygwin.com/setup-x86_64.exe
setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215
2) During setup install packages : make gcc-core zlib-devel
3) Run Cygwin.bat
4) cd to %ZAPRET_BASE%/nfq
cd C:/Users/user/Downloads/zapret/nfq
5) Compile
make cygwin64
use winws.exe
6) Take windivert.dll and windivert64.sys here : https://reqrypt.org/download
Choose version 2.2.2 for Windows 10 and 2.2.0 for Windows 7.
7) Copy cygwin1.dll, winws.exe, windivert.dll and windivert64.sys to one folder.
8) Run winws.exe from cmd.exe running as administrator.
winws will not run from cygwin shell with cygwin1.dll copy in it's folder.
winws will not run without cygwin1.dll outside of cygwin shell.

View File

@@ -24,8 +24,8 @@ define Build/Compile
endef
define Package/ip2net/install
$(INSTALL_DIR) $(1)/opt/zapret/ip2net
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret/ip2net
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret/binaries/my
endef
$(eval $(call BuildPackage,ip2net))

View File

@@ -24,8 +24,8 @@ define Build/Compile
endef
define Package/mdig/install
$(INSTALL_DIR) $(1)/opt/zapret/mdig
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret/mdig
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret/binaries/my
endef
$(eval $(call BuildPackage,mdig))

View File

@@ -25,8 +25,8 @@ define Build/Compile
endef
define Package/nfqws/install
$(INSTALL_DIR) $(1)/opt/zapret/nfq
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws $(1)/opt/zapret/nfq
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws $(1)/opt/zapret/binaries/my
endef
$(eval $(call BuildPackage,nfqws))

View File

@@ -25,8 +25,8 @@ define Build/Compile
endef
define Package/tpws/install
$(INSTALL_DIR) $(1)/opt/zapret/tpws
$(INSTALL_BIN) $(PKG_BUILD_DIR)/tpws $(1)/opt/zapret/tpws
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
$(INSTALL_BIN) $(PKG_BUILD_DIR)/tpws $(1)/opt/zapret/binaries/my
endef
$(eval $(call BuildPackage,tpws))

View File

@@ -12,7 +12,7 @@ iptables -t mangle -I POSTROUTING -p udp --dport 443 -m mark ! --mark 0x40000000
# auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by russian DPI
sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1
iptables -t mangle -I POSTROUTING -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:12 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
iptables -t mangle -I PREROUTING -p tcp -m multiport --sports 80,443 -m connbytes --connbytes-dir=reply --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
iptables -t mangle -I PREROUTING -p tcp -m multiport --sports 80,443 -m connbytes --connbytes-dir=reply --connbytes-mode=packets --connbytes 1:3 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
For TPROXY :

View File

@@ -19,8 +19,8 @@ For dpi desync attack :
nft delete table inet ztest
nft create table inet ztest
nft add chain inet ztest post "{type filter hook postrouting priority mangle;}"
nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp dport "{80,443}" ct original packets 1-12 queue num 200 bypass
nft add rule inet ztest post meta mark and 0x40000000 == 0 udp dport 443 ct original packets 1-12 queue num 200 bypass
nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp dport "{80,443}" ct original packets 1-6 queue num 200 bypass
nft add rule inet ztest post meta mark and 0x40000000 == 0 udp dport 443 ct original packets 1-6 queue num 200 bypass
# auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by russian DPI
sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1

View File

@@ -213,7 +213,7 @@
> Если используются методы нулевой фазы десинхронизации (`--mss`,
> `--wssize`, `--dpi-desync=syndata`) и режим фильтрации `hostlist`, то все
> параметры, относящиеся к этим методам, следует помещать в отдельные
> профили мульистратегии, которые получат управление до определения имени
> профили мультистратегии, которые получат управление до определения имени
> хоста. Необходимо понимать алгоритм работы мультистратегий. Самым надежным
> вариантом будет дублирование этих параметров на 2 профиля. Какой-нибудь
> сработает в зависимости от параметра `MODE_FILTER`.
@@ -235,6 +235,13 @@
8. На все остальные вопросы `install_easy.sh` отвечайте согласно выводимой
аннотации.
9. Удалите директорию из /tmp, откуда производилась установка.
## Полное удаление
1. Прогоните `/opt/zapret/uninstall_easy.sh`.
2. Cогласитесь на удаление зависимостей в openwrt.
3. Удалите каталог `/opt/zapret`.
## Итог
Это минимальная инструкция, чтобы быстро сориентироваться с чего начать.

View File

@@ -47,6 +47,14 @@ _"Совсем ничего не могу, все очень сложно, да
Не помогла _"таблетка"_ ? Это вовсе не значит, что ничего не получится. Но придется делать по нормальному.
## НЕ ПОМОГЛО, КАК ТЕПЕРЬ ЭТО УДАЛИТЬ
Если вы не устанавливали zapret как службу или запланированную задачу (а это требует редактирования cmd файлов),
достаточно закрыть окно с winws и запустить windivert_delete.cmd.
Альтернатива - перезагрузить компьютер.
После чего можно удалить папку с zapret. На этом деинсталляция закончена.
Если же вы устанавливали zapret как службу, то вы наверняка знаете как ее удалить.
## РЕШЕНИЕ "КАК ПОЛОЖЕНО"
1) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.

View File

@@ -1,4 +1,9 @@
# zapret v.67
# zapret v.69
# SCAMMER WARNING
This software is free and open source under [MIT license](./LICENSE.txt).
If anyone demands you to download this software only from their webpage, telegram channel, forces you to delete links, videos, makes copyright claims, you are dealing with scammers.
# Multilanguage/Мультиязычный README
___
@@ -10,22 +15,33 @@ ___
- [What is it for](#what-is-it-for)
- [How it works](#how-it-works)
- [How to put this into practice in the linux system](#how-to-put-this-into-practice-in-the-linux-system)
- [ip6tables](#ip6tables)
- [nftables](#nftables)
- [When it will not work](#when-it-will-not-work)
- [nfqws](#nfqws)
- [DPI desync attack](#dpi-desync-attack)
- [DPI desync combos](#dpi-desync-combos)
- [SYNACK mode](#synack-mode)
- [Fakes](#fakes)
- [TCP segmentation](#tcp-segmentation)
- [Sequence numbers overlap](#sequence-numbers-overlap)
- [ipv6 specific modes](#ipv6-specific-modes)
- [Server reply reaction](#server-reply-reaction)
- [SYNDATA mode](#syndata-mode)
- [Virtual Machines](#virtual-machines)
- [DPI desync combos](#dpi-desync-combos)
- [CONNTRACK](#conntrack)
- [Reassemble](#reassemble)
- [UDP support](#udp-support)
- [IP fragmentation](#ip-fragmentation)
- [multiple strategies](#multiple-strategies)
- [Multiple strategies](#multiple-strategies)
- [Virtual machines](#virtual-machines)
- [IPTABLES for nfqws](#iptables-for-nfqws)
- [NFTABLES for nfqws](#nftables-for-nfqws)
- [tpws](#tpws)
- [multiple strategies](#multiple-strategies-1)
- [TCP segmentation in tpws](#tcp-segmentation-in-tpws)
- [TLSREC](#tlsrec)
- [MSS](#mss)
- [Other tamper options](#other-tamper-options)
- [Supplementary options](#supplementary-options)
- [Multiple strategies](#multiple-strategies-1)
- [IPTABLES for tpws](#iptables-for-tpws)
- [NFTABLES for tpws](#nftables-for-tpws)
- [Ways to get a list of blocked IP](#ways-to-get-a-list-of-blocked-ip)
- [Domain name filtering](#domain-name-filtering)
- [**autohostlist** mode](#autohostlist-mode)
@@ -94,94 +110,9 @@ deal with its consequences.
2. Modification of the TCP connection at the stream level. Implemented through a proxy or transparent proxy.
3. Modification of TCP connection at the packet level. Implemented through the NFQUEUE handler and raw sockets.
For options 2 and 3, tpws and nfqws programs are implemented, respectively.
For options 2 and 3, **tpws** and **nfqws** programs are implemented, respectively.
You need to run them with the necessary parameters and redirect certain traffic with iptables or nftables.
To redirect a TCP connection to a transparent proxy, the following commands are used:
forwarded traffic :
`iptables -t nat -I PREROUTING -i <internal_interface> -p tcp --dport 80 -j DNAT --to 127.0.0.127:988`
outgoing traffic :
`iptables -t nat -I OUTPUT -o <external_interface> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.127:988`
DNAT on localhost works in the OUTPUT chain, but does not work in the PREROUTING chain without enabling the route_localnet parameter:
`sysctl -w net.ipv4.conf.<internal_interface>.route_localnet=1`
You can use `-j REDIRECT --to-port 988` instead of DNAT, but in this case the transparent proxy process
should listen on the ip address of the incoming interface or on all addresses. Listen all - not good
in terms of security. Listening one (local) is possible, but automated scripts will have to recognize it,
then dynamically enter it into the command. In any case, additional efforts are required.
Using route_localnet can also introduce some security risks. You make available from internal_interface everything
bound to `127.0.0.0/8`. Services are usually bound to `127.0.0.1`. Its possible to deny input to `127.0.0.1` from all interfaces except lo
or bind tpws to any other IP from `127.0.0.0/8` range, for example to `127.0.0.127`, and allow incomings only to that IP :
```
iptables -A INPUT ! -i lo -d 127.0.0.127 -j ACCEPT
iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j DROP
```
Owner filter is necessary to prevent recursive redirection of connections from tpws itself.
tpws must be started under OS user `tpws`.
NFQUEUE redirection of the outgoing traffic and forwarded traffic going towards the external interface,
can be done with the following commands:
`iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp --dport 80 -j NFQUEUE --queue-num 200 --queue-bypass`
In order not to touch the traffic to unblocked addresses, you can take a list of blocked hosts, resolve it
into IP addresses and put them to ipset 'zapret', then add a filter to the command:
`iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass`
Some DPIs catch only the first http request, ignoring subsequent requests in a keep-alive session.
Then we can reduce CPU load, refusing to process unnecessary packets.
`iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass`
Mark filter does not allow nfqws-generated packets to enter the queue again.
Its necessary to use this filter when also using `connbytes`. Without it packet ordering can be changed breaking the whole idea.
Also if there's huge packet send from nfqws it may deadlock without mark filter.
Some attacks require redirection of incoming packets :
`iptables -t mangle -I PREROUTING -i <external_interface> -p tcp --sport 80 -m connbytes --connbytes-dir=reply --connbytes-mode=packets --connbytes 1:6 -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass`
Incoming packets are filtered by incoming interface, source port and IP. This is opposite to the direct rule.
Some techniques that break NAT are possible only with nftables.
## ip6tables
ip6tables work almost exactly the same way as ipv4, but there are a number of important nuances.
In DNAT, you should take the address --to in square brackets. For example :
`ip6tables -t nat -I OUTPUT -o <external_interface> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to [::1]:988`
The route_localnet parameter does not exist for ipv6.
DNAT to localhost (:: 1) is possible only in the OUTPUT chain.
In the PREROUTING DNAT chain, it is possible to any global address or to the link local address of the same interface
the packet came from.
NFQUEUE works without changes.
## nftables
nftables are fine except one very big problem.
nft requires tons of RAM to load large nf sets (ip lists) with subnets/intervals. Most of the home routers can't afford that.
For example, even a 256 Mb system can't load a 100K ip list. nft process will OOM.
nf sets do not support overlapping intervals and that's why nft process applies very RAM consuming algorithm to merge intervals so they don't overlap.
There're equivalents to iptables for all other functions. Interface and protocol anonymous sets allow not to write multiple similar rules.
Flow offloading is built-in into new linux kernels and nft versions.
nft version `1.0.2` or higher is recommended. But the higher is version the better.
Some techniques can be fully used only with nftables. It's not possible to queue packets after NAT in iptables.
This limits techniques that break NAT.
## When it will not work
* If DNS server returns false responses. ISP can return false IP addresses or not return anything
@@ -215,7 +146,7 @@ nfqws takes the following parameters:
--hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host"
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
--domcase ; mix domain case : Host: TeSt.cOm
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 disorder disorder2 split split2 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-ttl=<int> ; set ttl for desync packet
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used.
@@ -224,10 +155,11 @@ nfqws takes the following parameters:
--dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync-repeats=<N> ; send every desync packet N times
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?)
--dpi-desync-split-pos=<1..9216> ; data payload split position
--dpi-desync-split-http-req=method|host ; split at specified logical part of plain http request
--dpi-desync-split-tls=sni|sniext ; split at specified logical part of TLS ClientHello
--dpi-desync-split-seqovl=<int> ; use sequence overlap before first sent original split segment
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; comma separated list of split positions
; markers: method,host,endhost,sld,endsld,midsld,sniext
; full list is only used by multisplit and multidisorder
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap
--dpi-desync-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.
@@ -262,24 +194,21 @@ nfqws takes the following parameters:
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
```
The manipulation parameters can be combined in any way.
WARNING. `--wsize` parameter is now not used anymore in scripts. TCP split can be achieved using DPI desync attack.
### DPI desync attack
After completion of the tcp 3-way handshake, the first data packet from the client goes.
It usually has `GET / ...` or TLS ClientHello. We drop this packet, replacing with something else.
It can be a fake version with another harmless but valid http or https request (`fake`), tcp reset packet (`rst`,`rstack`),
split into 2 segments original packet with fake segment in the middle (`split`).
`fakeknown` sends fake only in response to known application protocol.
In articles these attack have names **TCB desynchronization** and **TCB teardown**.
Fake packet must reach DPI, but do not reach the destination server.
The following means are available: set a low TTL, send a packet with bad checksum,
add tcp option **MD5 signature**. All of them have their own disadvantages :
The idea is to take original message, modify it, add additional fake information in such a way that the server OS accepts original data only
but DPI cannot recostruct original message or sees what it cannot identify as a prohibited request.
* md5sig does not work on all servers
* badsum doesn't work if your device is behind NAT which does not pass invalid packets.
There's a set of instruments to achieve that goal.
It can be fake packets that reach DPI but do not reach server or get rejected by server, TCP segmentation or IP fragmentation.
There're attacks based on TCP sequence numbers. Methods can be combined in many ways.
### Fakes
Fakes are separate generated by nfqws packets carrying false information for DPI. They must either not reach the server or be rejected by it. Otherwise TCP connection or data stream would be broken. There're multiple ways to solve this task.
* **md5sig** does not work on all servers
* **badsum** doesn't work if your device is behind NAT which does not pass invalid packets.
The most common Linux NAT router configuration does not pass them. Most home routers are Linux based.
The default sysctl configuration `net.netfilter.nf_conntrack_checksum=1` causes contrack to verify tcp and udp checksums
and set INVALID state for packets with invalid checksum.
@@ -294,25 +223,25 @@ add tcp option **MD5 signature**. All of them have their own disadvantages :
This behavior was observed on a Mediatek MT7621 based device.
Tried to modify mediatek ethernet driver with no luck, likely hardware enforced limitation.
However the device allowed to send badsum packets, problem only existed for passthrough traffic from clients.
* badseq packets will be dropped by server, but DPI also can ignore them.
* **badseq** packets will be dropped by server, but DPI also can ignore them.
default badseq increment is set to -10000 because some DPIs drop packets outside of the small tcp window.
But this also can cause troubles when `--dpi-desync-any-protocol` is enabled.
To be 100% sure fake packet cannot fit to server tcp window consider setting badseq increment to 0x80000000
* TTL looks like the best option, but it requires special tuning for each ISP. If DPI is further than local ISP websites
* **TTL** looks like the best option, but it requires special tuning for each ISP. If DPI is further than local ISP websites
you can cut access to them. Manual IP exclude list is required. Its possible to use md5sig with ttl.
This way you cant hurt anything, but good chances it will help to open local ISP websites.
If automatic solution cannot be found then use `zapret-hosts-user-exclude.txt`.
Some router stock firmwares fix outgoing TTL. Without switching this option off TTL fooling will not work.
* `hopbyhop` is ipv6 only. This fooling adds empty extension header `hop-by-hop options` or two headers in case of `hopbyhop2`.
* **hopbyhop** is ipv6 only. This fooling adds empty extension header `hop-by-hop options` or two headers in case of `hopbyhop2`.
Packets with two hop-by-hop headers violate RFC and discarded by all operating systems.
All OS accept packets with one hop-by-hop header.
Some ISPs/operators drop ipv6 packets with hop-by-hop options. Fakes will not be processed by the server either because
ISP drops them or because there are two same headers.
DPIs may still anaylize packets with one or two hop-by-hop headers.
* `datanoack` sends tcp fakes without ACK flag. Servers do not accept this but DPI may accept.
* **datanoack** sends tcp fakes without ACK flag. Servers do not accept this but DPI may accept.
This mode may break NAT and may not work with iptables if masquerade is used, even from the router itself.
Works with nftables properly. Likely requires external IP address (some ISPs pass these packets through their NAT).
* `autottl` tries to automatically guess TTL value that allows DPI to receive fakes and does not allow them to reach the server.
* **autottl** tries to automatically guess TTL value that allows DPI to receive fakes and does not allow them to reach the server.
This tech relies on well known TTL values used by OS : 64,128,255. nfqws takes first incoming packet (YES, you need to redirect it too),
guesses path length and decreases by `delta` value (default 1). If resulting value is outside the range (min,max - default 3,20)
then its normalized to min or max. If the path shorter than the value then autottl fails and falls back to the fixed value.
@@ -322,42 +251,53 @@ add tcp option **MD5 signature**. All of them have their own disadvantages :
`--dpi-desync-fooling` takes multiple comma separated values.
For fake,rst,rstack modes original packet is sent after the fake.
Disorder mode splits original packet and sends packets in the following order :
1. 2nd segment
2. fake 1st segment, data filled with zeroes
3. 1st segment
4. fake 1st segment, data filled with zeroes (2nd copy)
### TCP segmentation
Original packet is always dropped. `--dpi-desync-split-pos` sets split position (default 2).
If position is higher than packet length, pos=1 is used.
This sequence is designed to make reconstruction of critical message as difficult as possible.
Fake segments may not be required to bypass some DPIs, but can potentially help if more sophisticated reconstruction
algorithms are used.
Mode `disorder2` disables sending of fake segments.
* `multisplit`. split request at specified in `--dpi-desync-split-pos` positions
* `multidisorder`. same as `multisplit` but send in reverse order
* `fakedsplit`. split request into 2 segments adding fakes in the middle of them : fake 1st segment, 1st segment, fake 1st segment, 2nd segment
* `fakeddisorder`. same as `fakedsplit` but with another order : 2nd segment, fake 1st segment, 1st segment, fake 1st segment
Split mode is very similar to disorder but without segment reordering :
Positions are defined by markers.
1. fake 1st segment, data filled with zeroes
2. 1st segment
3. fake 1st segment, data filled with zeroes (2nd copy)
4. 2nd segment
* **Absolute positive marker** - numeric offset inside one packet or group of packets starting from the start
* **Absolute negative marker** - numeric offset inside one packet or group of packets starting from the next byte after the end
* **Relative marker** - positive or negative offset relative to a logical position within a packet or group of packets
Mode `split2` disables sending of fake segments. It can be used as a faster alternative to --wsize.
Relative positions :
In `disorder2` and `split2` modes no fake packets are sent, so ttl and fooling options are not required.
* **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.
* **host** - hostname start in a known protocol (http, TLS)
* **endhost** - the byte next to the last hostname's byte
* **sld** - second level domain start in the hostname
* **endsld** - the byte next to the last SLD byte
* **midsld** - middle of SLD
* **sniext** - start of the data field in the SNI TLS extension. Any extension has 2-byte type and length fields followed by data field.
`seqovl` adds to the first sent original segment (1st for split, 2nd for disorder) seqovl bytes to the beginning and decreases
sequence number.
In `split2` mode this creates partially in-window packet. OS receives only in-window part.
In `disorder2` mode OS receives fake and real part of the second segment but does not pass received data to the socket until first
segment is received. First segment overwrites fake part of the second segment. Then OS passes original data to the socket.
Marker list example : `100,midsld,sniext+1,endhost-2,-10`.
When splitting all markers are resolved to absolute offsets. If a relative position is absent in the current protocol its dropped. Then all resolved offsets are normalized to the current packet offset in multi packet group (multi-packet TLS with kyber, for example). Positions outside of the current packet are dropped. Remaining positions are sorted and deduplicated.
In `multisplit`or `multidisorder` case split is cancelled if no position remained.
`fakedsplit` и `fakeddisorder` use only one split position. It's searched from the `--dpi-desync-split-pos` list by a special alorightm.
First relative markers are searched. If no suitable found absolute markers are searched. If nothing found position 1 is used.
For example, `--dpi-desync-split-pos=method+2,midsld,5` means `method+2` for http, `midsld` for TLS and 5 for others.
### Sequence numbers overlap
`seqovl` adds to one of the original segment `seqovl` bytes to the beginning and decreases sequence number. For `split` - to the first segment, for `disorder` - to the beginning of the penultimate segment sent (second in the original sequence).
In `split` mode this creates partially in-window packet. OS receives only in-window part.
In `disorder` mode OS receives fake and real part of the second segment but does not pass received data to the socket until first segment is received. First segment overwrites fake part of the second segment. Then OS passes original data to the socket.
All unix OS except Solaris preserve last received data. This is not the case for Windows servers and `disorder` with `seqovl` will not work.
Disorder requires `seqovl` to be less than `split_pos`. Either statically defined or automatically calculated.
Otherwise desync is not possible and will not happen.
Disorder requires `seqovl` to be less than split position. Otherwise `seqovl` is not possible and will be cancelled.
Method allows to avoid separate fakes. Fakes and real data are mixed.
### ipv6 specific modes
`hopbyhop`, `destopt` and `ipfrag1` desync modes (they're not the same as `hopbyhop` fooling !) are ipv6 only. One `hop-by-hop`,
`destination options` or `fragment` header is added to all desynced packets.
Extra header increases packet size and can't be applied to the maximum size packets.
@@ -365,91 +305,36 @@ If it's not possible to send modified packet original one will be sent.
The idea here is that DPI sees 0 in the next header field of the main ipv6 header and does not
walk through the extension header chain until transport header is found.
`hopbyhop`, `destopt`, `ipfrag1` modes can be used with any second phase mode except `ipfrag1+ipfrag2`.
For example, `hopbyhop,split2` means split original tcp packet into 2 pieces and add hop-by-hop header to both.
For example, `hopbyhop,multisplit` means split original tcp packet into several pieces and add hop-by-hop header to each.
With `hopbyhop,ipfrag2` header sequence will be : `ipv6,hop-by-hop,fragment,tcp/udp`.
`ipfrag1` mode may not always work without special preparations. See "IP Fragmentation" notices.
There are DPIs that analyze responses from the server, particularly the certificate from the ServerHello
that contain domain name(s). The ClientHello delivery confirmation is an ACK packet from the server
with ACK sequence number corresponding to the length of the ClientHello+1.
### Server reply reaction
There are DPIs that analyze responses from the server, particularly the certificate from the ServerHello that contain domain name(s). The ClientHello delivery confirmation is an ACK packet from the server with ACK sequence number corresponding to the length of the ClientHello+1.
In the disorder variant, a selective acknowledgement (SACK) usually arrives first, then a full ACK.
If, instead of ACK or SACK, there is an RST packet with minimal delay, DPI cuts you off at the request stage.
If the RST is after a full ACK after a delay of about ping to the server, then probably DPI acts
on the server response. The DPI may be satisfied with good ClientHello and stop monitoring the TCP session
without checking ServerHello. Then you were lucky. 'fake' option could work.
If it does not stop monitoring and persistently checks the ServerHello, --wssize parameter may help (see CONNTRACK).
If the RST is after a full ACK after a delay of about ping to the server, then probably DPI acts on the server response. The DPI may be satisfied with good ClientHello and stop monitoring the TCP session without checking ServerHello. Then you were lucky. 'fake' option could work.
If it does not stop monitoring and persistently checks the ServerHello, --wssize parameter may help (see [CONNTRACK](#conntrack)).
Otherwise it is hardly possible to overcome this without the help of the server.
The best solution is to enable TLS 1.3 support on the server. TLS 1.3 sends the server certificate in encrypted form.
This is recommendation to all admins of blocked sites. Enable TLS 1.3. You will give more opportunities to overcome DPI.
Hosts are extracted from plain http request Host: header and SNI of ClientHello TLS message.
Subdomains are applied automatically. gzip lists are supported.
iptables for performing the attack on the first packet :
`iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass`
This is good if DPI does not track all requests in http keep-alive session.
If it does, then pass all outgoing packets for http and only first data packet for https :
```
iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
iptables -t mangle -I POSTROUTING -o <external_interface> -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
```
mark is needed to keep away generated packets from NFQUEUE. nfqws sets fwmark when it sends generated packets.
nfqws can internally filter marked packets. but when connbytes filter is used without mark filter
packet ordering can be changed breaking the whole idea of desync attack.
### DPI desync combos
dpi-desync parameter takes up to 3 comma separated arguments.
zero phase means tcp connection establishement (before sending data payload). Mode can be `synack`.
Hostlist filter is not applicable to the zero phase.
Next phases work on packets with data payload.
1st phase mode can be `fake`,`rst`,`rstack`, 2nd phase mode - `disorder`,`disorder2`,`split`,`split2`,`ipfrag2`.
Can be useful for ISPs with more than one DPI.
### SYNACK mode
In geneva docs it's called **TCP turnaround**. Attempt to make the DPI believe the roles of client and server are reversed.
!!! This mode breaks NAT operation and can be used only if there's no NAT between the attacker's device and the DPI !
In linux it's required to remove standard firewall rule dropping INVALID packets in the OUTPUT chain,
for example : `-A OUTPUT -m state --state INVALID -j DROP`
In openwrt it's possible to disable the rule for both FORWARD and OUTPUT chains in /etc/config/firewall :
```
config zone
option name 'wan'
.........
option masq_allow_invalid '1'
```
Unfortunately there's no OUTPUT only switch. It's not desired to remove the rule from the FORWARD chain.
Add the following lines to `/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
```
then `/etc/init.d/firewall restart`
Otherwise raw sending SYN,ACK frame will cause error stopping the further processing.
If you realize you don't need the synack mode it's highly suggested to restore drop INVALID rule.
### SYNDATA mode
Normally SYNs come without data payload. If it's present it's ignored by all major OS if TCP fast open (TFO) is not involved, but may not be ignored by DPI.
Original connections with TFO are not touched because otherwise they would be definitely broken.
Without extra parameter payload is 16 zero bytes.
### Virtual Machines
### DPI desync combos
Most of nfqws packet magic does not work from VMs powered by virtualbox and vmware when network is NATed.
Hypervisor forcibly changes ttl and does not forward fake packets.
Set up bridge networking.
`--dpi-desync` takes up to 3 comma separated modes.
* 0 phase modes work during the connection establishement : `synack`, `syndata` `--wsize`, `--wssize`. [hostlist](((#multiple-strategies))) filters are not applicable.
* In the 1st phase fakes are sent before original data : `fake`, `rst`, `rstack`.
* In the 2nd phase original data is sent in a modified way (for example `fakedsplit` or `ipfrag2`).
Modes must be specified in phase ascending order.
### CONNTRACK
@@ -535,11 +420,7 @@ If nfqws receives a partial ClientHello it begins reassemble session. Packets ar
Then they go through desync using fully reassembled message.
On any error reassemble is cancelled and all delayed packets are sent immediately without desync.
There is special support for all tcp split options for multi segment TLS. Split position is treated
as message-oriented, not packet oriented. For example, if your client sends TLS ClientHello with size 2000
and SNI is at 1700, desync mode is fake,split2, then fake is sent first, then original first segment
and the last splitted segment. 3 segments total.
There is special support for all tcp split options for multi segment TLS. Split position is treated as message-oriented, not packet oriented. For example, if your client sends TLS ClientHello with size 2000 and SNI is at 1700, desync mode is `fake,multisplit`, then fake is sent first, then original first segment and the last splitted segment. 3 segments total.
### UDP support
@@ -619,9 +500,9 @@ nfqws sees packets with internal network source address. If fragmented NAT does
This results in attempt to send packets to internet with internal IP address.
You need to use nftables instead with hook priority 101 or higher.
### multiple strategies
### Multiple strategies
`nfqws` can apply different strategies to different requests. It's done with multiple desync profiles.
**nfqws** can apply different strategies to different requests. It's done with multiple desync profiles.
Profiles are delimited by the `--new` parameter. First profile is created automatically and does not require `--new`.
Each profile has a filter. By default it's empty and profile matches any packet.
Filter can have hard parameters : ip version, ipset and tcp/udp port range.
@@ -637,7 +518,7 @@ Otherwise verification goes to the next profile.
It's possible that before knowing L7 and hostname connection is served by one profile and after
this information is revealed it's switched to another profile.
If you use 0-phase desync methods think carefully what can happen during strategy switch.
Use `--debug` logging to understand better what `nfqws` does.
Use `--debug` logging to understand better what **nfqws** does.
Profiles are numbered from 1 to N. There's last empty profile in the chain numbered 0.
It's used when no filter matched.
@@ -649,6 +530,99 @@ This way you may never unblock all resources and only confuse yourself.
IMPORTANT : user-mode ipset implementation was not designed as a kernel version replacement. Kernel version is much more effective.
It's for the systems that lack ipset support : Windows and Linux without nftables and ipset kernel modules (Android, for example).
### Virtual machines
Most of nfqws packet magic does not work from VMs powered by virtualbox and vmware when network is NATed.
Hypervisor forcibly changes TTL and does not forward fake packets.
Set up bridge networking.
### IPTABLES for nfqws
This is the common way to redirect some traffic to nfqws :
```
iptables -t mangle -I POSTROUTING -o <wan_interface> -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
```
This variant works if DPI is stateful and does not track all packets separately in search for "bad requests". If it's stateless you have to redirect all outgoing plain http packets.
```
iptables -t mangle -I POSTROUTING -o <wan_interface> -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
iptables -t mangle -I POSTROUTING -o <wan_interface> -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
```
mark bit is used to prevent loops. **nfqws** sets this mark in each injected packet.
It's also necessary for correct injected packet ordering and for deadlock prevention.
`autottl` requires incoming `SYN,ACK` packet or first reply packet (it's usually the same).
`autohostlist` needs incoming `RST` and `http redirect`.
It's possible to build tcp flags and u32 based filter but connbytes is easier.
`
iptables -t mangle -I PREROUTING -i <wan_interface> -p tcp -m multiport --sports 80,443 -m connbytes --connbytes-dir=reply --connbytes-mode=packets --connbytes 1:3 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
`
For QUIC :
```
iptables -t mangle -I POSTROUTING -o <wan_interface> -p udp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
```
6 packets cover possible retransmissions of quic initials and feed `autohostlist` mode.
### NFTABLES for nfqws
This is the start configuration :
```
IFACE_WAN=wan
nft create table inet ztest
nft add chain inet ztest post "{type filter hook postrouting priority mangle;}"
nft add rule inet ztest post oifname $IFACE_WAN meta mark and 0x40000000 == 0 tcp dport "{80,443}" ct original packets 1-6 queue num 200 bypass
nft add rule inet ztest post oifname $IFACE_WAN meta mark and 0x40000000 == 0 udp dport 443 ct original packets 1-6 queue num 200 bypass
# auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by russian DPI
sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1
nft add chain inet ztest pre "{type filter hook prerouting priority filter;}"
nft add rule inet ztest pre iifname $IFACE_WAN tcp sport "{80,443}" ct reply packets 1-3 queue num 200 bypass
```
To engage `datanoack` or `ipfrag` for passthrough traffic special POSTNAT configuration is required. Generated packets must be marked as **notrack** in the early stage to avoid being invalidated by linux conntrack.
```
IFACE_WAN=wan
nft create table inet ztest
nft add chain inet ztest postnat "{type filter hook postrouting priority srcnat+1;}"
nft add rule inet ztest postnat oifname $IFACE_WAN meta mark and 0x40000000 == 0 tcp dport "{80,443}" ct original packets 1-6 queue num 200 bypass
nft add rule inet ztest postnat oifname $IFACE_WAN meta mark and 0x40000000 == 0 udp dport 443 ct original packets 1-6 queue num 200 bypass
nft add chain inet ztest predefrag "{type filter hook output priority -401;}"
nft add rule inet ztest predefrag "mark & 0x40000000 != 0x00000000 notrack"
```
Delete nftable :
```
nft delete table inet ztest
```
### Flow offloading
If your device supports flow offloading (hardware acceleration) iptables and nftables may not work. With offloading enabled packets bypass standard netfilter flow. It must be either disabled or selectively controlled.
Newer linux kernels have software flow offloading (SFO). The story is the same with SFO.
In `iptables` flow offloading is controlled by openwrt proprietary extension `FLOWOFFLOAD`. Newer `nftables` implement built-in offloading support.
Flow offloading does not interfere with **tpws** and `OUTPUT` traffic. It only breaks nfqws that fools `FORWARD` traffic.
## tpws
tpws is transparent proxy.
@@ -681,6 +655,7 @@ tpws is transparent proxy.
--skip-nodelay ; do not set TCP_NODELAY for outgoing connections. incompatible with split.
--local-tcp-user-timeout=<seconds> ; set tcp user timeout for local leg (default : 10, 0 = system default)
--remote-tcp-user-timeout=<seconds> ; set tcp user timeout for remote leg (default : 20, 0 = system default)
--fix-seg=<int> ; recover failed TCP segmentation at the cost of slowdown. wait up to N msec.
--no-resolve ; disable socks5 remote dns
--resolver-threads=<int> ; number of resolver worker threads
--maxconn=<max_connections> ; max number of local legs
@@ -702,10 +677,9 @@ tpws is transparent proxy.
--hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives
--split-http-req=method|host ; split http request at specified logical position.
--split-tls=sni|sniext ; split at specified logical part of TLS ClientHello
--split-pos=<numeric_offset> ; split at specified pos. split-http-req takes precedence over split-pos for http reqs.
--split-any-protocol ; split not only http and https
--split-pos=N|-N|marker+N|marker-N ; comma separated list of split positions
; markers: method,host,endhost,sld,endsld,midsld,sniext
--split-any-protocol ; split not only http and TLS
--disorder[=http|tls] ; when splitting simulate sending second fragment first
--oob[=http|tls] ; when splitting send out of band byte. default is HEX 0x00.
--oob-data=<char>|0xHEX ; override default 0x00 OOB byte.
@@ -719,10 +693,9 @@ tpws is transparent proxy.
--methodspace ; add extra space after method
--methodeol ; add end-of-line before method
--unixeol ; replace 0D0A to 0A
--tlsrec=sni|sniext ; make 2 TLS records. split at specified logical part. don't split if SNI is not present.
--tlsrec=N|-N|marker+N|marker-N ; make 2 TLS records. split at specified logical part. don't split if SNI is not present.
--tlsrec-pos=<pos> ; make 2 TLS records. split at specified pos
--mss=<int> ; set client MSS. forces server to split messages but significantly decreases speed !
--mss-pf=[~]port1[-port2] ; MSS port filter. ~ means negation
--tamper-start=[n]<pos> ; start tampering only from specified outbound stream position. byte pos or block number ('n'). default is 0.
--tamper-cutoff=[n]<pos> ; do not tamper anymore after specified outbound stream position. byte pos or block number ('n'). default is unlimited.
--daemon ; daemonize
@@ -731,13 +704,49 @@ tpws is transparent proxy.
--uid=uid[:gid] ; drop root privs
```
The manipulation parameters can be combined in any way.
### TCP segmentation in tpws
`split-http-req` takes precedence over split-pos for http reqs.
**tpws** like **nfqws** supports multiple splits. Split [markers](#tcp-segmentation) are specified in `--split-pos` parameter.
split-pos works by default only on http and TLS ClientHello. use `--split-any-protocol` to act on any packet
On the socket level there's no guaranteed way to force OS to send pieces of data in separate packets. OS has a send buffer for each socket. If `TCP_NODELAY` socket option is enabled and send buffer is empty OS will likely send data immediately. If send buffer is not empty OS will coalesce it with new data and send in one packet if possible.
tpws can bind to multiple interfaces and IP addresses (up to 32).
In practice outside of massive transmissions it's usually enough to enable `TCP_NODELAY` and use separate `send()` calls to force custom TCP segmentation. But if there're too many split segments Linux can combined some pieces and break desired behaviour. BSD and Windows are more predictable in this case. That's why it's not recommended to use too many splits. Tests revealed that 8+ can become problematic.
Since linux kernel 4.6 **tpws** can recognize TCP segmentation failures and warn about them. `--fix-seg` can fix segmentation failures at the cost of some slowdown. It waits for several msec until all previous data is sent. This breaks async processing model and slows down every other connection going through **tpws**. Thus it's not recommended on highly loaded systems. But can be compromise for home systems.
If you're attempting to split massive transmission with `--split-any-protocol` option it will definitely cause massive segmentation failures. Do not do that without `--tamper-start` and `--tamper-cutoff` limiters.
**tpws** works on socket level and receives in one shot long requests (TLS with kyber) that should normally require several TCP packets. It tampers entire received block without knowing how much packets it will take. OS will do additional segmenation to meet MTU.
`--disorder` sends every odd packet with TTL=1. Server receives even packets fastly. Then client OS retransmits odd packets with normal TTL and server receives them. In case of 6 segments server and DPI will see them in this order : `2 4 6 1 3 5`. This way of disorder causes some delays. Default retransmission timeout in Linux is 200 ms.
`--oob` sends one out-of-band byte in the end of the first split segment.
`--oob` and `--disorder` can be combined only in Linux. Others OS do not handle this correctly.
### TLSREC
`--tlsrec` allow to split TLS ClientHello into 2 TLS records in one TCP segment. It accepts single pos marker.
`--tlsrec` breaks significant number of sites. Crypto libraries on servers usually accept fine modified ClientHello but middleboxes such as CDNs and ddos guards - not always. Use of `--tlsrec` without filters is discouraged.
### MSS
`--mss` sets TCP_MAXSEG socket option. Client sets this value in MSS TCP option in the SYN packet.
Server replies with it's own MSS in SYN,ACK packet. Usually servers lower their packet sizes but they still don't fit to supplied MSS. The greater MSS client sets the bigger server's packets will be.
If it's enough to split TLS 1.2 ServerHello, it may fool DPI that checks certificate domain name.
This scheme may significantly lower speed. Hostlist filter is possible only in socks mode if client uses remote resolving (firefox `network.proxy.socks_remote_dns`).
`--mss` is not required for TLS1.3. If TLS1.3 is negotiable then MSS make things only worse. Use only if nothing better is available. Works only in Linux, not BSD or MacOS.
### Other tamper options
`--hostpad=<bytes>` adds padding headers before `Host:` with specified number of bytes. If `<bytes>` is too large headers are split by 2K. Padding more that 64K is not supported and not accepted by http servers.
It's useful against stateful DPI's that reassemble only limited amount of data. Increase padding `<bytes>` until website works. If minimum working `<bytes>` is close to MTU then it's likely DPI is not reassembling packets. Then it's better to use regular split instead of `--hostpad`.
### Supplementary options
**tpws** can bind to multiple interfaces and IP addresses (up to 32).
Port number is always the same.
@@ -773,44 +782,83 @@ To bind to a specific ip when its interface may not be configured yet do : `--bi
It's possible to bind to any nonexistent address in transparent mode but in socks mode address must exist.
In socks proxy mode no additional system privileges are required. Connections to local IPs of the system where tpws runs are prohibited.
In socks proxy mode no additional system privileges are required. Connections to local IPs of the system where **tpws** runs are prohibited.
tpws supports remote dns resolving (curl : `--socks5-hostname` firefox : `socks_remote_dns=true`) , but does it in blocking mode.
tpws uses async sockets for all activities. Domain names are resolved in multi threaded pool.
**tpws** uses async sockets for all activities. Domain names are resolved in multi threaded pool.
Resolving does not freeze other connections. But if there're too many requests resolving delays may increase.
Number of resolver threads is choosen automatically proportinally to `--maxconn` and can be overriden using `--resolver-threads`.
To disable hostname resolve use `--no-resolve` option.
`--disorder` is an additional flag to any split option.
It tries to simulate `--disorder2` option of `nfqws` using standard socket API without the need of additional privileges.
This works fine in Linux and MacOS but unexpectedly in FreeBSD and OpenBSD
(system sends second fragment then the whole packet instead of the first fragment).
### Multiple strategies
`--tlsrec` and `--tlsrec-pos` allow to split TLS ClientHello into 2 TLS records in one TCP segment.
`--tlsrec=sni` splits between 1st and 2nd chars of the hostname. No split occurs if SNI is not present.
`--tlsrec-pos` splits at specified position. If TLS data block size is too small pos=1 is applied.
`--tlsrec` can be combined with `--split-pos` and `--disorder`.
`--tlsrec` breaks significant number of sites. Crypto libraries on end servers usually accept fine modified ClientHello
but middleboxes such as CDNs and ddos guards - not always.
Use of `--tlsrec` without filters is discouraged.
`--mss` sets TCP_MAXSEG socket option. Client sets this value in MSS TCP option in the SYN packet.
Server replies with it's own MSS in SYN,ACK packet. Usually servers lower their packet sizes but they still don't
fit to supplied MSS. The greater MSS client sets the bigger server's packets will be.
If it's enough to split TLS 1.2 ServerHello, it may fool DPI that checks certificate domain name.
This scheme may significantly lower speed. Hostlist filter is possible only in socks mode if client uses remote resolving (firefox `network.proxy.socks_remote_dns`).
`--mss` is not required for TLS1.3. If TLS1.3 is negotiable then MSS make things only worse.
Use only if nothing better is available. Works only in Linux, not BSD or MacOS.
### multiple strategies
`tpws` supports multiple strategies as well. They work mostly like with `nfqws` with minimal differences.
`filter-udp` is absent because `tpws` does not support udp. 0-phase desync methods (`--mss`) can work with hostlist in socks modes with remote hostname resolve.
**tpws** like **nfqws** supports multiple strategies. They work mostly like with **nfqws** with minimal differences.
`filter-udp` is absent because **tpws** does not support udp. 0-phase desync methods (`--mss`) can work with hostlist in socks modes with remote hostname resolve.
This is the point where you have to plan profiles carefully. If you use `--mss` and hostlist filters, behaviour can be different depending on remote resolve feature enabled or not.
Use `--mss` both in hostlist profile and profile without hostlist.
Use `curl --socks5` and `curl --socks5-hostname` to issue two kinds of proxy queries.
See `--debug` output to test your setup.
### IPTABLES for tpws
Use the following rules to redirect TCP connections to 'tpws' :
```
iptables -t nat -I OUTPUT -o <wan_interface> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.127:988
iptables -t nat -I PREROUTING -i <lan_interface> -p tcp --dport 80 -j DNAT --to 127.0.0.127:988
```
First rule redirects outgoing from the same system traffic, second redirects passthrough traffic.
DNAT to localhost works only in the **OUTPUT** chain and does not work in the **PREROUTING** chain without setting this sysctl :
`sysctl -w net.ipv4.conf.<lan_interface>.route_localnet=1`
It's also possible to use `-j REDIRECT --to-port 988` instead of DNAT but in the latter case transparent proxy must listen on all IP addresses or on a LAN interface address. It's not too good to listen on all IP and it's not trivial to get specific IP in a shell script. `route_localnet` has it's own security impact if not protected by additional rules. You open `127.0.0.0/8` subnet to the net.
This is how to open only single `127.0.0.127` address :
```
iptables -A INPUT ! -i lo -d 127.0.0.127 -j ACCEPT
iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j DROP
```
Owner filter is required to avoid redirection loops. **tpws** must be run with `--user tpws` parameter.
ip6tables work almost the same with minor differences. ipv6 addresses should be enclosed in square brackets :
```
ip6tables -t nat -I OUTPUT -o <wan_interface> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to [::1]:988
```
There's no `route_localnet` for ipv6. DNAT to localhost (`::1`) is possible only in **OUTPUT** chain. In **PREROUTING** chain DNAT is possible to any global address or link local address of the interface where packet came from.
### NFTABLES for tpws
Base nftables scheme :
```
IFACE_WAN=wan
IFACE_LAN=br-lan
sysctl -w net.ipv4.conf.$IFACE_LAN.route_localnet=1
nft create table inet ztest
nft create chain inet ztest localnet_protect
nft add rule inet ztest localnet_protect ip daddr 127.0.0.127 return
nft add rule inet ztest localnet_protect ip daddr 127.0.0.0/8 drop
nft create chain inet ztest input "{type filter hook input priority filter - 1;}"
nft add rule inet ztest input iif != "lo" jump localnet_protect
nft create chain inet ztest dnat_output "{type nat hook output priority dstnat;}"
nft add rule inet ztest dnat_output meta skuid != tpws oifname $IFACE_WAN tcp dport { 80, 443 } dnat ip to 127.0.0.127:988
nft create chain inet ztest dnat_pre "{type nat hook prerouting priority dstnat;}"
nft add rule inet ztest dnat_pre meta iifname $IFACE_LAN tcp dport { 80, 443 } dnat ip to 127.0.0.127:988
```
Delete nftable :
```
nft delete table inet ztest
```
## Ways to get a list of blocked IP
nftables can't work with ipsets. Native nf sets require lots of RAM to load large ip lists with subnets and intervals.
@@ -878,8 +926,8 @@ LISTS_RELOAD=- disables reloading ip list backend.
## Domain name filtering
An alternative to ipset is to use tpws or nfqws with a list(s) of domains.
Both `tpws` and `nfqws` take any number of include (`--hostlist`) and exclude (`--hostlist-exclude`) domain lists.
An alternative to ipset is to use **tpws** or **nfqws** with a list(s) of domains.
Both **tpws** and **nfqws** take any number of include (`--hostlist`) and exclude (`--hostlist-exclude`) domain lists.
All lists of the same type are combined internally leaving only 2 lists : include and exclude.
Exclude list is checked first. Fooling is cancelled if domain belongs to exclude list.
@@ -896,13 +944,13 @@ and 1 exclude list
`ipset/zapret-hosts-users-exclude.txt.gz` or `ipset/zapret-hosts-users-exclude.txt`
If `MODE_FILTER=hostlist` all present lists are passed to `nfqws` or `tpws`.
If `MODE_FILTER=hostlist` all present lists are passed to **nfqws** or **tpws**.
If all include lists are empty it works like no include lists exist at all.
If you need "all except" mode you dont have to delete zapret-hosts-users.txt. Just make it empty.
Subdomains auto apply. For example, "ru" in the list affects "*.ru" .
tpws and nfqws automatically reload lists if their modification date is changed.
**tpws** and **nfqws** automatically reload lists if their modification date is changed.
When filtering by domain name, daemons should run without filtering by ipset.
When using large regulator lists estimate the amount of RAM on the router !
@@ -918,7 +966,7 @@ In case of nfqws it's required to redirect both incoming and outgoing traffic to
It's strongly recommended to use connbytes filter or nfqws will process gigabytes of incoming traffic.
For the same reason it's not recommended to use autohostlist mode in BSDs. BSDs do not support connbytes or similar mechanism.
nfqws и tpws detect the folowing situations :
**nfqws** и **tpws** detect the folowing situations :
1) [nfqws] Multiple retransmissions of the first request inside a TCP session having host.
2) [nfqws,tpws] RST in response to the first request.
3) [nfqws,tpws] HTTP redirect in response to the first http request with 2nd level domain diferent from the original.
@@ -964,11 +1012,11 @@ On openwrt by default `nftables` is selected on `firewall4` based systems.
`FWTYPE=iptables`
With `nftables` post-NAT scheme is used by default. It allows more DPI attacks on forwarded traffic.
It's possible to use `iptables`-like pre-NAT scheme. `nfqws` will see client source IPs and display them in logs.
It's possible to use `iptables`-like pre-NAT scheme. **nfqws** will see client source IPs and display them in logs.
`#POSTNAT=0`
There'are 3 standard options configured separately and independently : `tpws-socks`, `tpws`, `nfqws`.
There'are 3 standard options configured separately and independently : `tpws-socks`, **tpws**, **nfqws**.
They can be used alone or combined. Custom scripts in `init.d/{sysv,openwrt,macos}/custom.d` are always applied.
`tpws-socks` requires daemon parameter configuration but does not require traffic interception.
@@ -987,45 +1035,45 @@ Don't use `<HOSTLIST>` in highly specialized profiles. Use your own filter or ho
If any other profile adds something this profile accepts the change automatically.
`tpws` socks proxy mode switch
**tpws** socks proxy mode switch
`TPWS_SOCKS_ENABLE=0`
Listening tcp port for `tpws` proxy mode.
Listening tcp port for **tpws** proxy mode.
`TPPORT_SOCKS=987`
`tpws` socks mode parameters
**tpws** socks mode parameters
```
TPWS_SOCKS_OPT="
--filter-tcp=80 --methodeol <HOSTLIST> --new
--filter-tcp=443 --split-tls=sni --disorder <HOSTLIST>
--filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST>"
"
```
`tpws` transparent mode switch
**tpws** transparent mode switch
`TPWS_ENABLE=0`
`tpws` transparent mode target ports
**tpws** transparent mode target ports
`TPWS_PORTS=80,443`
`tpws` transparent mode parameters
**tpws** transparent mode parameters
```
TPWS_OPT="
--filter-tcp=80 --methodeol <HOSTLIST> --new
--filter-tcp=443 --split-tls=sni --disorder <HOSTLIST>
--filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST>"
"
```
`nfqws` enable switch
**nfqws** enable switch
`NFQWS_ENABLE=0`
`nfqws` port targets for `connbytes`-limited interception. `connbytes` allows to intercept only starting packets from connections.
**nfqws** port targets for `connbytes`-limited interception. `connbytes` allows to intercept only starting packets from connections.
This is more effective kernel-mode alternative to `nfqws --dpi-desync-cutoff=nX`.
```
@@ -1053,12 +1101,12 @@ It's advised also to remove these ports from `connbytes`-limited interception li
#NFQWS_PORTS_UDP_KEEPALIVE=
```
`nfqws` parameters
**nfqws** parameters
```
NFQWS_OPT="
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
--filter-tcp=443 --dpi-desync=fake,disorder2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
--filter-tcp=80 --dpi-desync=fake,multisplit --dpi-desync-split-pos=method+2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
--filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-fooling=badseq,md5sig <HOSTLIST> --new
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST_NOAUTO>
"
```
@@ -1276,33 +1324,29 @@ For low storage openwrt see `init.d/openwrt-minimal`.
### Android
Its not possible to use nfqws and tpws in transparent proxy mode without root privileges.
Without root tpws can run in --socks mode.
Its not possible to use **nfqws** and **tpws** in transparent proxy mode without root privileges. Without root **tpws** can run in `--socks` mode.
Android has NFQUEUE and nfqws should work.
Android has NFQUEUE and **nfqws** should work.
There's no ipset support unless you run custom kernel. In common case task of bringing up ipset
on android is ranging from "not easy" to "almost impossible", unless you find working kernel
image for your device.
There's no `ipset` support unless you run custom kernel. In common case task of bringing up `ipset` on android is ranging from "not easy" to "almost impossible", unless you find working kernel image for your device.
Android does not use /etc/passwd, `tpws --user` won't work. There's replacement.
Use numeric uids in `--uid` option.
Its recommended to use gid 3003 (AID_INET), otherwise tpws will not have inet access.
Although linux binaries work it's recommended to use Android specific ones. They have no problems with user names, local time, DNS, ...
Its recommended to use gid 3003 (AID_INET), otherwise **tpws** will not have inet access.
Example : `--uid 1:3003`
In iptables use : `! --uid-owner 1` instead of `! --uid-owner tpws`.
Nfqws should be executed with `--uid 1`. Otherwise on some devices or firmwares kernel may partially hang. Looks like processes with certain uids can be suspended. With buggy chineese cellular interface driver this can lead to device hang.
**nfqws** should be executed with `--uid 1`. Otherwise on some devices or firmwares kernel may partially hang. Looks like processes with certain uids can be suspended. With buggy chineese cellular interface driver this can lead to device hang.
Write your own shell script with iptables and tpws, run it using your root manager.
Write your own shell script with iptables and **tpws**, run it using your root manager.
Autorun scripts are here :
magisk : `/data/adb/service.d`
supersu : `/system/su.d`
How to run tpws on root-less android.
How to run **tpws** on root-less android.
You can't write to `/system`, `/data`, can't run from sd card.
Selinux prevents running executables in `/data/local/tmp` from apps.
Use adb and adb shell.
@@ -1336,7 +1380,7 @@ You will need :
* root shell access. true sh shell, not microtik-like console
* startup hook
* r/w partition to store binaries and startup script with executable permission (+x)
* tpws can be run almost anywhere but nfqws require kernel support for NFQUEUE. Its missing in most firmwares.
* **tpws** can be run almost anywhere but **nfqws** require kernel support for NFQUEUE. Its missing in most firmwares.
* too old 2.6 kernels are unsupported and can cause errors. newer 2.6 kernels are OK.
If binaries crash with segfault (rare but happens on some kernels) try to unpack upx like this : upx -d tpws.

File diff suppressed because it is too large Load Diff

View File

@@ -1,133 +0,0 @@
Index: WireGuard-0.0.20190123/src/cookie.c
===================================================================
--- WireGuard-0.0.20190123.orig/src/cookie.c
+++ WireGuard-0.0.20190123/src/cookie.c
@@ -193,6 +193,8 @@ void wg_cookie_message_create(struct mes
xchacha20poly1305_encrypt(dst->encrypted_cookie, cookie, COOKIE_LEN,
macs->mac1, COOKIE_LEN, dst->nonce,
checker->cookie_encryption_key);
+ // MOD : randomize trash
+ dst->header.trash = gen_trash();
}
void wg_cookie_message_consume(struct message_handshake_cookie *src,
Index: WireGuard-0.0.20190123/src/messages.h
===================================================================
--- WireGuard-0.0.20190123.orig/src/messages.h
+++ WireGuard-0.0.20190123/src/messages.h
@@ -53,23 +53,41 @@ enum limits {
MAX_QUEUED_PACKETS = 1024 /* TODO: replace this with DQL */
};
+/*
enum message_type {
- MESSAGE_INVALID = 0,
- MESSAGE_HANDSHAKE_INITIATION = 1,
- MESSAGE_HANDSHAKE_RESPONSE = 2,
- MESSAGE_HANDSHAKE_COOKIE = 3,
- MESSAGE_DATA = 4
+ MESSAGE_INVALID = 0,
+ MESSAGE_HANDSHAKE_INITIATION = 1,
+ MESSAGE_HANDSHAKE_RESPONSE = 2,
+ MESSAGE_HANDSHAKE_COOKIE = 3,
+ MESSAGE_DATA = 4
};
+*/
+
+// MOD : message type
+enum message_type {
+ MESSAGE_INVALID = 0xE319CCD0,
+ MESSAGE_HANDSHAKE_INITIATION = 0x48ADE198,
+ MESSAGE_HANDSHAKE_RESPONSE = 0xFCA6A8F3,
+ MESSAGE_HANDSHAKE_COOKIE = 0x64A3BB18,
+ MESSAGE_DATA = 0x391820AA
+};
+
+// MOD : generate fast trash without true RNG
+__le32 gen_trash(void);
struct message_header {
- /* The actual layout of this that we want is:
- * u8 type
- * u8 reserved_zero[3]
- *
- * But it turns out that by encoding this as little endian,
- * we achieve the same thing, and it makes checking faster.
- */
- __le32 type;
+ /* The actual layout of this that we want is:
+ * u8 type
+ * u8 reserved_zero[3]
+ *
+ * But it turns out that by encoding this as little endian,
+ * we achieve the same thing, and it makes checking faster.
+ */
+
+ // MOD : trash field to change message size and add 4 byte offset to all fields
+ __le32 trash;
+
+ __le32 type;
};
struct message_macs {
Index: WireGuard-0.0.20190123/src/noise.c
===================================================================
--- WireGuard-0.0.20190123.orig/src/noise.c
+++ WireGuard-0.0.20190123/src/noise.c
@@ -17,6 +17,24 @@
#include <linux/highmem.h>
#include <crypto/algapi.h>
+
+// MOD : trash generator
+__le32 gtrash = 0;
+__le32 gen_trash(void)
+{
+ if (gtrash)
+ gtrash = gtrash*1103515243 + 12345;
+ else
+ // first value is true random
+ get_random_bytes_wait(&gtrash, sizeof(gtrash));
+ return gtrash;
+}
+
/* This implements Noise_IKpsk2:
*
* <- s
@@ -515,6 +533,10 @@ wg_noise_handshake_create_initiation(str
&handshake->entry);
handshake->state = HANDSHAKE_CREATED_INITIATION;
+
+ // MOD : randomize trash
+ dst->header.trash = gen_trash();
+
ret = true;
out:
@@ -655,6 +677,10 @@ bool wg_noise_handshake_create_response(
&handshake->entry);
handshake->state = HANDSHAKE_CREATED_RESPONSE;
+
+ // MOD : randomize trash
+ dst->header.trash = gen_trash();
+
ret = true;
out:
Index: WireGuard-0.0.20190123/src/send.c
===================================================================
--- WireGuard-0.0.20190123.orig/src/send.c
+++ WireGuard-0.0.20190123/src/send.c
@@ -200,6 +200,10 @@ static bool encrypt_packet(struct sk_buf
header->header.type = cpu_to_le32(MESSAGE_DATA);
header->key_idx = keypair->remote_index;
header->counter = cpu_to_le64(PACKET_CB(skb)->nonce);
+
+ // MOD : randomize trash
+ header->header.trash = gen_trash();
+
pskb_put(skb, trailer, trailer_len);
/* Now we can encrypt the scattergather segments */

View File

@@ -1,250 +0,0 @@
!!! Эта инструкция написана еще до включения wireguard в ядро linux.
!!! Процесс сборки для in-tree модулей отличается.
!!! Цель данного чтива - дать идею для программистов как можно исправить исходники wireguard
!!! для преодоления DPI. Автор не преследует цели поддерживать готовые патчи для актуальных версий.
!!! Вместо патчинга гораздо проще использовать навесное решение ipobfs.
Посвящено возможной блокировке в РФ VPN протоколов через DPI.
Предпосылками являются последние законодательные акты и во всю сочащиеся "секретные" записки.
В РФ разрабатываются и готовятся к применению более продвинутые решения по блокировке трафика.
Вполне вероятно будут резать стандартные VPN протоколы. Нам надо быть к этому готовыми.
Один из возможных и перспективных путей решения данного вопроса - кустомная модификация
исходников VPN с целью незначительного изменения протокола, ломающего стандартные модули обнаружения в DPI.
Это относительно сложно, доступно только для гиков.
Никто не будет разрабатывать специальные модули обнаружения в DPI, если только кто-то не сделает простое и
удобное решение для всех, и его станут широко применять. Но это маловероятно, и даже если и так,
то всегда можно модифицировать протокол чуток по другому. Делать моды для DPI несравненно дольше
и дороже, чем клепать на коленке изменения протокола для wireguard.
ЗАМЕЧЕНИЕ : альтернативой модификации конечного софта для VPN является использование "навесных"
обфускаторов. см : https://github.com/bol-van/ipobfs
Рассмотрю что нам надо пропатчить в wireguard. Модифицированный wireguard проверен на виртуалках
с десктопным linux, он работает, сообщения в wireshark действительно не вписываются в стандартный
протокол и не опознаются.
Wireguard протокол очень простой. Все сообщения описаны в messages.h
Поставим себе целью сделать 2 простые модификации :
1) Добавим в начало всех сообщений немного мусора, чтобы изменить размер сообщений и смещения полей
2) Изменим коды типов сообщений
Этого может быть вполне достаточно для обмана DPI
--messages.h--------------------------
/*
enum message_type {
MESSAGE_INVALID = 0,
MESSAGE_HANDSHAKE_INITIATION = 1,
MESSAGE_HANDSHAKE_RESPONSE = 2,
MESSAGE_HANDSHAKE_COOKIE = 3,
MESSAGE_DATA = 4
};
*/
// MOD : message type
enum message_type {
MESSAGE_INVALID = 0xE319CCD0,
MESSAGE_HANDSHAKE_INITIATION = 0x48ADE198,
MESSAGE_HANDSHAKE_RESPONSE = 0xFCA6A8F3,
MESSAGE_HANDSHAKE_COOKIE = 0x64A3BB18,
MESSAGE_DATA = 0x391820AA
};
// MOD : generate fast trash without true RNG
__le32 gen_trash(void);
struct message_header {
/* The actual layout of this that we want is:
* u8 type
* u8 reserved_zero[3]
*
* But it turns out that by encoding this as little endian,
* we achieve the same thing, and it makes checking faster.
*/
// MOD : trash field to change message size and add 4 byte offset to all fields
__le32 trash;
__le32 type;
};
--------------------------------------
Напишем функцию для генерации trash. Функция должна быть быстрая, важно не замедлить скорость.
Мы не расчитываем, что нас будут специально ловить, иначе бы пришлось делать полноценный обфускатор.
Задача лишь сломать стандартный модуль обнаружения протокола wireguard. Потому истинная рандомность
trash не важна.
Но все же немного "трэша" не повредит. Гонки между тредами так же пофигистичны. Это же трэш.
--noise.c-----------------------------
// MOD : trash generator
__le32 gtrash = 0;
__le32 gen_trash(void)
{
if (gtrash)
gtrash = gtrash*1103515243 + 12345;
else
// first value is true random
get_random_bytes_wait(&gtrash, sizeof(gtrash));
return gtrash;
}
--------------------------------------
Теперь осталось найти все места, где создаются сообщения и внести туда заполнение поля trash.
Сообщений всего 4. Их можно найти по присваиванию полю type одного из значений enum message_type.
2 места в noise.c в функциях wg_noise_handshake_create_initiation и wg_noise_handshake_create_response,
1 место в cookie.c в функции wg_cookie_message_create
Дописываем в конец инициализации структуры сообщения :
--------------------------------------
// MOD : randomize trash
dst->header.trash = gen_trash();
--------------------------------------
и 1 место в send.c в функции encrypt_packet
--------------------------------------
// MOD : randomize trash
header->header.trash = gen_trash();
--------------------------------------
Вот и весь патчинг. Полный patch (версия wireguard 0.0.20190123) лежит в 010-wg-mod.patch.
Патчинг кода - самое простое. Для десктопного linux дальше все просто.
Пересобираем через make, устанавливаем через make install, перегружаем
модуль wireguard, перезапускаем интерфейсы, и все готово.
Настоящий геморой начнется когда вы это попытаетесь засунуть на роутер под openwrt.
Одна из больших проблем linux - отсутствие совместимости драйверов на уровне бинариков.
Поэтому собирать необходимо в точности под вашу версию ядра и в точности под его .config.
Вам придется либо полностью самостоятельно собирать всю прошивку, либо найти SDK в точности
от вашей версии прошивки для вашей архитектуры и собрать модуль с помощью этого SDK.
Последний вариант более легкий.
Для сборки вам понадобится система на linux x86_64. Ее можно установить в виртуалке.
Теоретически можно пользоваться WSL из win10, но на практике там очень медленное I/O,
по крайней мере на старых версиях win10. Безумно медленное. Будете собирать вечность.
Может в новых win10 что-то и улучшили, но я бы сразу расчитывал на полноценный linux.
Находим здесь вашу версию : https://downloads.openwrt.org/
Скачиваем файл openwrt-sdk-*.tar.xz или lede-sdk-*.tar.xz
Например : https://downloads.openwrt.org/releases/18.06.2/targets/ar71xx/generic/openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64.tar.xz
Если ваша версия непонятна или стара, то проще будет найти последнюю прошивку и перешить роутер.
Распаковываем SDK. Следующими командами можно собрать оригинальный вариант wireguard :
# scripts/feeds update -a
# scripts/feeds install -a
# make defconfig
# make -j 4 package/wireguard/compile
Сборка будет довольно долгой. Ведь придется подтащить ядро, собрать его, собрать зависимости.
"-j 4" означает использовать 4 потока. Впишите вместо 4 количество доступных cpu cores.
Получим следующие файлы :
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/bin/targets/ar71xx/generic/packages/kmod-wireguard_4.9.152+0.0.20190123-1_mips_24kc.ipk
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/bin/packages/mips_24kc/base/wireguard-tools_0.0.20190123-1_mips_24kc.ipk
Но это будет оригинальный wireguard. Нам нужен патченый.
Установим quilt и mc для нормального редактора вместо vim :
# sudo apt-get update
# sudo apt-get install quilt mc
# make package/wireguard/clean
# make package/wireguard/prepare V=s QUILT=1
Сорцы приготовлены для сборки в :
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/build_dir/target-mips_24kc_musl/linux-ar71xx_generic/WireGuard-0.0.20190123/src
# cd build_dir/target-mips_24kc_musl/linux-ar71xx_generic/WireGuard-0.0.20190123/src
# quilt push -a
# quilt new 010-wg-mod.patch
# export EDITOR=mcedit
Далее будет открываться редактор mcedit, в который нужно вносить изменения в каждый файл :
# quilt edit messages.h
# quilt edit cookie.c
# quilt edit noise.c
# quilt edit send.c
# quilt diff
# quilt refresh
Получили файл патча в :
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/build_dir/target-mips_24kc_musl/linux-ar71xx_generic/WireGuard-0.0.20190123/patches/010-wg-mod.patch
Выходим в корень SDK.
# make package/wireguard/compile V=99
Если не было ошибок, то получили измененные ipk.
Патч можно зафиксировать в описании пакета :
# make package/wireguard/update
Получим :
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/feeds/base/package/network/services/wireguard/patches/010-wg-mod.patch
При последующей очистке и пересборке он будет автоматом применяться.
АЛЬТЕРНАТИВА : можно не возиться с quilt.
сделайте
# make package/wireguard/clean
# make package/wireguard/prepare
и напрямую модифицируйте или копируйте файлы в
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/build_dir/target-mips_24kc_musl/linux-ar71xx_generic/WireGuard-0.0.20190123/src
затем
# make package/wireguard/compile
Если нужно поменять версию wireguard, то идите в
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/feeds/base/package/network/services/wireguard/Makefile
поменяйте там версию в PKG_VERSION на последнюю из : https://git.zx2c4.com/WireGuard
скачайте tar.xz с этой версией , вычислите его sha256sum, впишите в PKG_HASH
1 раз где-нибудь пропатчите файлы последней версии wireguard в текстовом редакторе, скопируйте в build_dir,
сделайте версию для openwrt. эти же файлы скопируйте на ваш сервер с десктопным linux, сделайте там make / make install
Но имейте в виду, что build_dir - локация для временных файлов.
make clean оттуда все снесет, включая ваши модификации. Модифицированные файлы лучше сохранить отдельно,
чтобы потом было легко скопировать обратно.
Полученные ipk копируем на роутер в /tmp, устанавливаем через
# cd /tmp
# rm -r /tmp/opkg-lists
# opkg install *.ipk
Если требует зависимостей, то
# opkg update
# opkg install .... <зависимости>
# rm -r /tmp/opkg-lists
# opkg install *.ipk
В /tmp/opkg-lists opkg хранит кэш списка пакетов. Если попытаться установить файл ipk, и такой же пакет
найдется в репозитории, opkg будет устанавливать из репозитория. А нам это не надо.
# rmmod wireguard
# kmodloader
# dmesg | tail
должны увидеть что-то вроде :
[8985.415490] wireguard: WireGuard 0.0.20190123 loaded. See www.wireguard.com for information.
[8985.424178] wireguard: Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
значит модуль загрузился
Могут понадобиться ключи opkg --force-reinstall, --force-depends.
--force-depends поможет при несоответствии hash версии ядра. То есть версия x.x.x та же самая, но hash конфигурации разный.
При несоответствии x.x.x вы что-то делаете не так, работать это не будет.
Например : 4.14.56-1-b1186491495127cc6ff81d29c00a91fc, 4.14.56-1-3f8a21a63974cfb7ee67e41f2d4b805d
Это свидетельствует о несоответствии .config ядра при сборке прошивки и в SDK.
Если несоответствие легкое, то может все прокатить, но при более серьезной разнице в .config модуль может не загрузиться
или вызвать стабильные или хаотические падения ядра и перезагрузки (включая вариант беонечной перезагрузки - bootloop).
Так что перед --force-depends убедитесь, что знаете как лечится такая ситуация, и не стоит это делать при отсутствии физического
доступа к девайсу.
Когда поднимите линк, и вдруг ничего не будет работать, то посмотрите в wireshark udp пакеты
на порт endpoint. Они не должны начинаться с 0,1,2,3,4. В первых 4 байтах должен быть рандом,
в следующих 4 байтах - значения из измененного enum message_type. Если пакет все еще начинается с 0..4,
значит модуль wireguard оригинальный, что-то не собралось, не скопировалось, не перезапустилось.
В противном случае должен подняться линк, пинги ходить. Значит вы победили, поздравляю.
Регулятору будет намного сложнее поймать ваш VPN.

View File

@@ -236,7 +236,7 @@ config rule
--- Подготовка zapret ---
Выполните install_easy.sh. Он настроит режим обхода DPI. Если обход DPI не нужен - выберите MODE=filter.
Выполните install_easy.sh. Он настроит режим обхода DPI. Если обход DPI не нужен - не включайте tpws и nfqws.
Так же инсталятор заресолвит домены из ipset/zapret-hosts-user-ipban.txt и внесет крон-джоб для периодического обновления ip.
Если вы используете в своих правилах ipset zapret, то он ресолвится и обновляется только, если выбран режим фильтрации обхода DPI по ipset.

View File

@@ -169,13 +169,10 @@ run_daemon()
local DAEMONBASE="$(basename "$2")"
local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
echo "Starting daemon $1: $2 $3"
if exists start-stop-daemon ; then
start-stop-daemon -S -p "$PIDFILE" -m -b -x "$2" -- $3
else
if [ -f "$PIDFILE" ] && pgrep -F "$PIDFILE" "$DAEMONBASE" >/dev/null; then
echo already running
else
"$2" $3 >/dev/null 2>/dev/null &
"$2" $3 >/dev/null &
PID=$!
if [ -n "$PID" ]; then
echo $PID >$PIDFILE
@@ -184,7 +181,6 @@ run_daemon()
false
fi
fi
fi
}
stop_daemon()
{

View File

@@ -25,7 +25,11 @@ check_dir()
# find does not use its own shell exec
# it uses execvp(). in musl libc it does not call shell, in glibc it DOES call /bin/sh
# that's why prefer bash or zsh if present. otherwise it's our last chance
out=$(echo 0.0.0.0 | find "$dir" -maxdepth 1 -name ip2net -exec {} \; 2>/dev/null)
local FIND=find
if ! exists find && exists busybox; then
FIND="busybox find"
fi
out=$(echo 0.0.0.0 | $FIND "$dir" -maxdepth 1 -name ip2net -exec {} \; 2>/dev/null)
fi
[ -n "$out" ]
else

View File

@@ -549,7 +549,7 @@ service_install_systemd()
if [ -w "$SYSTEMD_SYSTEM_DIR" ] ; then
rm -f "$INIT_SCRIPT"
ln -fs "$EXEDIR/init.d/systemd/zapret.service" "$SYSTEMD_SYSTEM_DIR"
cp -f "$EXEDIR/init.d/systemd/zapret.service" "$SYSTEMD_SYSTEM_DIR"
"$SYSTEMCTL" daemon-reload
"$SYSTEMCTL" enable zapret || {
echo could not enable systemd service
@@ -567,8 +567,8 @@ timer_install_systemd()
if [ -w "$SYSTEMD_SYSTEM_DIR" ] ; then
"$SYSTEMCTL" disable zapret-list-update.timer
"$SYSTEMCTL" stop zapret-list-update.timer
ln -fs "$EXEDIR/init.d/systemd/zapret-list-update.service" "$SYSTEMD_SYSTEM_DIR"
ln -fs "$EXEDIR/init.d/systemd/zapret-list-update.timer" "$SYSTEMD_SYSTEM_DIR"
cp -f "$EXEDIR/init.d/systemd/zapret-list-update.service" "$SYSTEMD_SYSTEM_DIR"
cp -f "$EXEDIR/init.d/systemd/zapret-list-update.timer" "$SYSTEMD_SYSTEM_DIR"
"$SYSTEMCTL" daemon-reload
"$SYSTEMCTL" enable zapret-list-update.timer || {
echo could not enable zapret-list-update.timer

View File

@@ -1,5 +1,5 @@
CC ?= gcc
CFLAGS += -std=gnu99 -O3
CFLAGS += -std=gnu99 -Os
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_WIN = -static
LIBS =
@@ -9,7 +9,9 @@ SRC_FILES = ip2net.c qsort.c
all: ip2net
ip2net: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o $@ $(SRC_FILES) $(LDFLAGS) $(LIBS)
$(CC) -s $(CFLAGS) -o ip2net $(SRC_FILES) $(LDFLAGS) $(LIBS)
android: ip2net
bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o ip2net $(SRC_FILES) $(LDFLAGS) $(LIBS)

View File

@@ -1,15 +1,19 @@
CC ?= gcc
CFLAGS += -std=gnu99 -O3
CFLAGS += -std=gnu99 -Os
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_WIN = -static
LIBS = -lpthread
LIBS_ANDROID =
LIBS_WIN = -lws2_32
SRC_FILES = *.c
all: mdig
mdig: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o $@ $(SRC_FILES) $(LDFLAGS) $(LIBS)
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS)
android: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS_ANDROID)
bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS)

View File

@@ -12,7 +12,6 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <pthread.h>
#include <getopt.h>
#ifdef _WIN32
@@ -21,7 +20,9 @@
#include <winsock2.h>
#include <ws2ipdef.h>
#include <ws2tcpip.h>
#include <fcntl.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
@@ -364,6 +365,9 @@ int dns_make_query(const char *dom, char family)
fprintf(stderr, "could not make DNS query\n");
return 1;
}
#ifdef _WIN32
_setmode(_fileno(stdout), _O_BINARY);
#endif
if (fwrite(q,l,1,stdout)!=1)
{
fprintf(stderr, "could not write DNS query blob to stdout\n");
@@ -420,8 +424,11 @@ bool dns_parse_print(const uint8_t *a, size_t len)
}
int dns_parse_query()
{
uint8_t a[1500];
uint8_t a[8192];
size_t l;
#ifdef _WIN32
_setmode(_fileno(stdin), _O_BINARY);
#endif
l = fread(a,1,sizeof(a),stdin);
if (!l || !feof(stdin))
{

View File

@@ -1,12 +1,12 @@
CC ?= cc
CFLAGS += -std=gnu99 -s -O3 -Wno-address-of-packed-member
CFLAGS += -std=gnu99 -s -Os -Wno-address-of-packed-member
LIBS = -lz
SRC_FILES = *.c crypto/*.c
all: dvtws
dvtws: $(SRC_FILES)
$(CC) $(CFLAGS) -o $@ $(SRC_FILES) $(LDFLAGS) $(LIBS)
$(CC) $(CFLAGS) -o dvtws $(SRC_FILES) $(LDFLAGS) $(LIBS)
clean:
rm -f dvtws

View File

@@ -1,11 +1,11 @@
CC ?= gcc
CFLAGS += -std=gnu99 -O3
CFLAGS += -std=gnu99 -Os
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_MAC = -mmacosx-version-min=10.8
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
LIBS_BSD = -lz
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32 -luuid
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32
LIBS_CYGWIN32 = -lwindivert32
LIBS_CYGWIN64 = -lwindivert64
RES_CYGWIN32 = windows/res/32/winmanifest.o windows/res/32/winicon.o
@@ -15,7 +15,9 @@ SRC_FILES = *.c crypto/*.c
all: nfqws
nfqws: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o $@ $(SRC_FILES) $(LDFLAGS) $(LIBS_LINUX)
$(CC) -s $(CFLAGS) -o nfqws $(SRC_FILES) $(LDFLAGS) $(LIBS_LINUX)
android: nfqws
bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o dvtws $(SRC_FILES) $(LDFLAGS) $(LIBS_BSD)

View File

@@ -12,29 +12,6 @@ static void ut_oom_recover(void *elem)
oom = true;
}
const char *l7proto_str(t_l7proto l7)
{
switch(l7)
{
case HTTP: return "http";
case TLS: return "tls";
case QUIC: return "quic";
case WIREGUARD: return "wireguard";
case DHT: return "dht";
default: return "unknown";
}
}
bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7)
{
return (l7proto==UNKNOWN && (filter_l7 & L7_PROTO_UNKNOWN)) ||
(l7proto==HTTP && (filter_l7 & L7_PROTO_HTTP)) ||
(l7proto==TLS && (filter_l7 & L7_PROTO_TLS)) ||
(l7proto==QUIC && (filter_l7 & L7_PROTO_QUIC)) ||
(l7proto==WIREGUARD && (filter_l7 & L7_PROTO_WIREGUARD)) ||
(l7proto==DHT && (filter_l7 & L7_PROTO_DHT));
}
static const char *connstate_s[]={"SYN","ESTABLISHED","FIN"};
static void connswap(const t_conn *c, t_conn *c2)

View File

@@ -4,8 +4,6 @@
// this conntrack is not bullet-proof
// its designed to satisfy dpi desync needs only
#include "packet_queue.h"
#include <stdbool.h>
#include <stdint.h>
#include <ctype.h>
@@ -19,6 +17,8 @@
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include "packet_queue.h"
#include "protocol.h"
//#define HASH_BLOOM 20
#define HASH_NONFATAL_OOM 1
@@ -53,16 +53,6 @@ typedef struct {
// FIN - FIN or RST received
typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
typedef enum {UNKNOWN=0, HTTP, TLS, QUIC, WIREGUARD, DHT} t_l7proto;
#define L7_PROTO_HTTP 0x00000001
#define L7_PROTO_TLS 0x00000002
#define L7_PROTO_QUIC 0x00000004
#define L7_PROTO_WIREGUARD 0x00000008
#define L7_PROTO_DHT 0x00000010
#define L7_PROTO_UNKNOWN 0x80000000
const char *l7proto_str(t_l7proto l7);
bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7);
typedef struct
{
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache

View File

@@ -163,7 +163,7 @@ static void fill_udphdr(struct udphdr *udp, uint16_t nsport, uint16_t ndport, ui
udp->uh_sum = 0;
}
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, uint8_t ttl, uint8_t tos)
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, uint8_t ttl, uint8_t tos, uint16_t ip_id)
{
ip->ip_tos = tos;
ip->ip_sum = 0;
@@ -171,7 +171,7 @@ static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in
ip->ip_v = 4;
ip->ip_hl = 5;
ip->ip_len = htons(pktlen);
ip->ip_id = 0;
ip->ip_id = ip_id;
ip->ip_ttl = ttl;
ip->ip_p = proto;
ip->ip_src = *src;
@@ -196,6 +196,7 @@ bool prepare_tcp_segment4(
uint32_t *timestamps,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@@ -211,7 +212,7 @@ bool prepare_tcp_segment4(
struct tcphdr *tcp = (struct tcphdr*)(ip+1);
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, ttl, tos);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, ttl, tos, ip_id);
fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len);
@@ -314,7 +315,9 @@ bool prepare_tcp_segment(
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t tos, uint32_t flow_label,
uint8_t tos,
uint16_t ip_id,
uint32_t flow_label,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@@ -322,7 +325,7 @@ bool prepare_tcp_segment(
uint8_t *buf, size_t *buflen)
{
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,tos,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
false;
@@ -334,6 +337,7 @@ bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,
@@ -357,7 +361,7 @@ bool prepare_udp_segment4(
uint8_t *payload = (uint8_t*)(udp+1);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl, tos);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl, tos, ip_id);
fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
memcpy(payload,data,len);
@@ -463,7 +467,9 @@ bool prepare_udp_segment6(
bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
uint8_t ttl,
uint8_t tos, uint32_t flow_label,
uint8_t tos,
uint16_t ip_id,
uint32_t flow_label,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,
@@ -471,7 +477,7 @@ bool prepare_udp_segment(
uint8_t *buf, size_t *buflen)
{
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,tos,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
false;
@@ -869,60 +875,49 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
// we have garbage
}
void proto_dissect_l3l4(
uint8_t *data, size_t len,
struct ip **ip, struct ip6_hdr **ip6,
uint8_t *proto,
struct tcphdr **tcp,
struct udphdr **udp,
size_t *transport_len,
uint8_t **data_payload, size_t *len_payload)
void proto_dissect_l3l4(uint8_t *data, size_t len,struct dissect *dis)
{
*ip = NULL;
*ip6 = NULL;
*proto = 0;
*tcp = NULL;
*transport_len = 0;
*udp = NULL;
*data_payload = NULL;
*len_payload = 0;
memset(dis,0,sizeof(*dis));
dis->data_pkt = data;
dis->len_pkt = len;
if (proto_check_ipv4(data, len))
{
*ip = (struct ip *) data;
*proto = (*ip)->ip_p;
dis->ip = (struct ip *) data;
dis->proto = dis->ip->ip_p;
proto_skip_ipv4(&data, &len);
}
else if (proto_check_ipv6(data, len))
{
*ip6 = (struct ip6_hdr *) data;
proto_skip_ipv6(&data, &len, proto, NULL);
dis->ip6 = (struct ip6_hdr *) data;
proto_skip_ipv6(&data, &len, &dis->proto, NULL);
}
else
{
return;
}
if (*proto==IPPROTO_TCP && proto_check_tcp(data, len))
if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len))
{
*tcp = (struct tcphdr *) data;
*transport_len = len;
dis->tcp = (struct tcphdr *) data;
dis->transport_len = len;
proto_skip_tcp(&data, &len);
*data_payload = data;
*len_payload = len;
dis->data_payload = data;
dis->len_payload = len;
}
else if (*proto==IPPROTO_UDP && proto_check_udp(data, len))
else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len))
{
*udp = (struct udphdr *) data;
*transport_len = len;
dis->udp = (struct udphdr *) data;
dis->transport_len = len;
proto_skip_udp(&data, &len);
*data_payload = data;
*len_payload = len;
dis->data_payload = data;
dis->len_payload = len;
}
}
@@ -1882,3 +1877,34 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
}
}
void dbgprint_socket_buffers(int fd)
{
if (params.debug)
{
int v;
socklen_t sz;
sz = sizeof(int);
if (!getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &v, &sz))
DLOG("fd=%d SO_RCVBUF=%d\n", fd, v);
sz = sizeof(int);
if (!getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &v, &sz))
DLOG("fd=%d SO_SNDBUF=%d\n", fd, v);
}
}
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf)
{
DLOG("set_socket_buffers fd=%d rcvbuf=%d sndbuf=%d\n", fd, rcvbuf, sndbuf);
if (rcvbuf && setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0)
{
DLOG_PERROR("setsockopt (SO_RCVBUF)");
return false;
}
if (sndbuf && setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0)
{
DLOG_PERROR("setsockopt (SO_SNDBUF)");
return false;
}
dbgprint_socket_buffers(fd);
return true;
}

View File

@@ -22,6 +22,7 @@
#endif
#ifdef __CYGWIN__
#define INITGUID
#include "windivert/windivert.h"
#endif
@@ -60,6 +61,7 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
#define VERDICT_NOCSUM 4
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0)
#define IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0)
#define IP6_FLOW(ip6_header) (ip6_header ? ip6_header->ip6_ctlun.ip6_un1.ip6_un1_flow : 0)
// seq and wsize have network byte order
@@ -72,6 +74,7 @@ bool prepare_tcp_segment4(
uint32_t *timestamps,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@@ -99,7 +102,9 @@ bool prepare_tcp_segment(
uint8_t scale_factor,
uint32_t *timestamps,
uint8_t ttl,
uint8_t tos, uint32_t flow_label,
uint8_t tos,
uint16_t ip_id,
uint32_t flow_label,
uint32_t fooling,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
@@ -111,6 +116,7 @@ bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,
@@ -128,7 +134,9 @@ bool prepare_udp_segment6(
bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
uint8_t ttl,
uint8_t tos, uint32_t flow_label,
uint8_t tos,
uint16_t ip_id,
uint32_t flow_label,
uint32_t fooling,
const uint8_t *padding, size_t padding_size,
int padlen,
@@ -210,14 +218,20 @@ bool proto_check_tcp(const uint8_t *data, size_t len);
void proto_skip_tcp(uint8_t **data, size_t *len);
bool proto_check_udp(const uint8_t *data, size_t len);
void proto_skip_udp(uint8_t **data, size_t *len);
void proto_dissect_l3l4(
uint8_t *data, size_t len,
struct ip **ip, struct ip6_hdr **ip6,
uint8_t *proto,
struct tcphdr **tcp,
struct udphdr **udp,
size_t *transport_len,
uint8_t **data_payload, size_t *len_payload);
struct dissect
{
uint8_t *data_pkt;
size_t len_pkt;
struct ip *ip;
struct ip6_hdr *ip6;
uint8_t proto;
struct tcphdr *tcp;
struct udphdr *udp;
size_t transport_len;
uint8_t *data_payload;
size_t len_payload;
};
void proto_dissect_l3l4(uint8_t *data, size_t len,struct dissect *dis);
bool tcp_synack_segment(const struct tcphdr *tcphdr);
bool tcp_syn_segment(const struct tcphdr *tcphdr);
@@ -241,3 +255,6 @@ void do_nat(bool bOutbound, struct ip *ip, struct ip6_hdr *ip6, struct tcphdr *t
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);
void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);
void dbgprint_socket_buffers(int fd);
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf);

File diff suppressed because it is too large Load Diff

View File

@@ -28,10 +28,10 @@ enum dpi_desync_mode {
DESYNC_RSTACK,
DESYNC_SYNACK,
DESYNC_SYNDATA,
DESYNC_DISORDER,
DESYNC_DISORDER2,
DESYNC_SPLIT,
DESYNC_SPLIT2,
DESYNC_FAKEDSPLIT,
DESYNC_FAKEDDISORDER,
DESYNC_MULTISPLIT,
DESYNC_MULTIDISORDER,
DESYNC_IPFRAG2,
DESYNC_HOPBYHOP,
DESYNC_DESTOPT,

View File

@@ -5,11 +5,31 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/stat.h>
#include <libgen.h>
#include "params.h"
int unique_size_t(size_t *pu, int ct)
{
int i, j, u;
for (i = j = 0; j < ct; i++)
{
u = pu[j++];
for (; j < ct && pu[j] == u; j++);
pu[i] = u;
}
return i;
}
static int cmp_size_t(const void * a, const void * b)
{
return *(size_t*)a < *(size_t*)b ? -1 : *(size_t*)a > *(size_t*)b;
}
void qsort_size_t(size_t *array,size_t ct)
{
qsort(array,ct,sizeof(*array),cmp_size_t);
}
void rtrim(char *s)
{
@@ -43,22 +63,6 @@ char *strncasestr(const char *s, const char *find, size_t slen)
return (char *)s;
}
void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
{
size_t k;
bool bcut = false;
if (size > limit)
{
size = limit;
bcut = true;
}
if (!size) return;
for (k = 0; k < size; k++) DLOG("%02X ", data[k]);
DLOG(bcut ? "... : " : ": ");
for (k = 0; k < size; k++) DLOG("%c", data[k] >= 0x20 && data[k] <= 0x7F ? (char)data[k] : '.');
if (bcut) DLOG(" ...");
}
bool load_file(const char *filename, void *buffer, size_t *buffer_size)
{
@@ -199,38 +203,6 @@ uint16_t saport(const struct sockaddr *sa)
sa->sa_family==AF_INET6 ? ((struct sockaddr_in6*)sa)->sin6_port : 0);
}
void dbgprint_socket_buffers(int fd)
{
if (params.debug)
{
int v;
socklen_t sz;
sz = sizeof(int);
if (!getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &v, &sz))
DLOG("fd=%d SO_RCVBUF=%d\n", fd, v);
sz = sizeof(int);
if (!getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &v, &sz))
DLOG("fd=%d SO_SNDBUF=%d\n", fd, v);
}
}
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf)
{
DLOG("set_socket_buffers fd=%d rcvbuf=%d sndbuf=%d\n", fd, rcvbuf, sndbuf);
if (rcvbuf && setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(int)) < 0)
{
DLOG_PERROR("setsockopt (SO_RCVBUF)");
close(fd);
return false;
}
if (sndbuf && setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(int)) < 0)
{
DLOG_PERROR("setsockopt (SO_SNDBUF)");
close(fd);
return false;
}
dbgprint_socket_buffers(fd);
return true;
}
uint64_t pntoh64(const void *p)
{
@@ -395,14 +367,14 @@ void fill_random_az09(uint8_t *p,size_t sz)
}
}
bool cd_to_exe_dir(const char *argv0)
bool set_env_exedir(const char *argv0)
{
char *s,*d;
bool bOK=false;
if ((s = strdup(argv0)))
{
if ((d = dirname(s)))
bOK = !chdir(d);
setenv("EXEDIR",s,1);
free(s);
}
return bOK;

View File

@@ -17,11 +17,13 @@ typedef union
char _align[32]; // force 16-byte alignment for ip6_and int128 ops
} sockaddr_in46;
int unique_size_t(size_t *pu, int ct);
void qsort_size_t(size_t *array,size_t ct);
void rtrim(char *s);
void replace_char(char *s, char from, char to);
char *strncasestr(const char *s,const char *find, size_t slen);
void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit);
bool load_file(const char *filename,void *buffer,size_t *buffer_size);
bool load_file_nonempty(const char *filename,void *buffer,size_t *buffer_size);
bool save_file(const char *filename, const void *buffer, size_t buffer_size);
@@ -37,9 +39,6 @@ uint16_t saport(const struct sockaddr *sa);
bool seq_within(uint32_t s, uint32_t s1, uint32_t s2);
void dbgprint_socket_buffers(int fd);
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf);
uint64_t pntoh64(const void *p);
void phton64(uint8_t *p, uint64_t v);
@@ -76,7 +75,7 @@ void fill_random_bytes(uint8_t *p,size_t sz);
void fill_random_az(uint8_t *p,size_t sz);
void fill_random_az09(uint8_t *p,size_t sz);
bool cd_to_exe_dir(const char *argv0);
bool set_env_exedir(const char *argv0);
struct cidr4

Some files were not shown because too many files have changed in this diff Show More