Compare commits

..

No commits in common. "master" and "v69.3" have entirely different histories.

117 changed files with 2345 additions and 6670 deletions

2
.gitattributes vendored
View File

@ -1,3 +1,5 @@
* text=auto eol=lf * text=auto eol=lf
binaries/win64/readme.txt eol=crlf
binaries/win32/readme.txt eol=crlf
*.cmd eol=crlf *.cmd eol=crlf
*.bat eol=crlf *.bat eol=crlf

View File

@ -1 +0,0 @@
blank_issues_enabled: false

View File

@ -1,19 +0,0 @@
---
name: bugs
about: do not write lame questions
title: ''
labels: ''
assignees: ''
---
1. Здесь не место для вопросов, касающихся компьютерной грамотности и навыков использования ОС
2. Здесь не место для вопросов "у меня не работает" без технических подробностей
3. Здесь не место для вопросов "как мне открыть ютуб", "что писать в ...", "перестало открываться".
4. Здесь не место для обсуждения сборок
5. Вирусов здесь нет. У вас либо чья-то сборка, либо ваш антивирус давно пора отправить на покой. Антивирусы в основном жалуются на upx и windivert, которые убраны НЕ будут. upx - это паковщик для сокращения требуемого места на openwrt, windivert - замена iptables для windows, потенциальный инструмент хакера или компонент зловредной программы, но сам по себе вирусом не является. Не согласны - удаляйте софт. За агрессивные наезды "почему автор распространяет вирусы" молча схватите бан.
Все означенное обсуждать в дискуссиях или на форумах.
При нарушении будет закрываться или конвертироваться в дискуссии.
Issue только для обсуждения проблем самого софта. Неработа стратегии или ваше неумение настроить - это ваша проблема, а не проблема софта.
Однокнопочные решения дают только сборщики, поэтому "открытие сайта" не является функцией программы, и нет смысла жаловаться, что он не открывается. Но можно это обсудить в дискуссиях. Не захламляйте issues !

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

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

View File

@ -52,13 +52,6 @@ jobs:
tool: i586-unknown-linux-musl tool: i586-unknown-linux-musl
- arch: x86_64 - arch: x86_64
tool: x86_64-unknown-linux-musl tool: x86_64-unknown-linux-musl
- arch: lexra
tool: mips-linux
dir: rsdk-4.6.4-5281-EB-3.10-0.9.33-m32ub-20141001
env:
CFLAGS: '-march=5281'
LDFLAGS: '-lgcc_eh'
repo: 'bol-van/build'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -67,31 +60,18 @@ jobs:
- name: Set up build tools - name: Set up build tools
env: env:
ARCH: ${{ matrix.arch }} REPO: 'spvkgn/musl-cross'
TOOL: ${{ matrix.tool }} TOOL: ${{ matrix.tool }}
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'spvkgn/musl-cross' }}
DIR: ${{ matrix.arch == 'lexra' && matrix.dir || matrix.tool }}
run: | run: |
if [[ "$ARCH" == lexra ]]; then sudo apt update -qq && sudo apt install -y libcap-dev
sudo dpkg --add-architecture i386
sudo apt update -qq
sudo apt install -y libcap-dev libc6:i386 zlib1g:i386
URL=https://github.com/$REPO/raw/refs/heads/master/$DIR.txz
else
sudo apt update -qq
sudo apt install -y libcap-dev
URL=https://github.com/$REPO/releases/download/latest/$TOOL.tar.xz
fi
mkdir -p $HOME/tools mkdir -p $HOME/tools
wget -qO- $URL | tar -C $HOME/tools -xJ || exit 1 wget -qO- https://github.com/$REPO/releases/download/latest/$TOOL.tar.xz | tar -C $HOME/tools -xJ || exit 1
[[ -d "$HOME/tools/$DIR/bin" ]] && echo "$HOME/tools/$DIR/bin" >> $GITHUB_PATH [ -d "$HOME/tools/$TOOL/bin" ] && echo "$HOME/tools/$TOOL/bin" >> $GITHUB_PATH
- name: Build - name: Build
env: env:
ARCH: ${{ matrix.arch }} ARCH: ${{ matrix.arch }}
TARGET: ${{ matrix.tool }} TARGET: ${{ matrix.tool }}
CFLAGS: ${{ matrix.env.CFLAGS != '' && matrix.env.CFLAGS || null }}
LDFLAGS: ${{ matrix.env.LDFLAGS != '' && matrix.env.LDFLAGS || null }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps DEPS_DIR=$GITHUB_WORKSPACE/deps
@ -101,7 +81,8 @@ jobs:
export NM=$TARGET-nm export NM=$TARGET-nm
export STRIP=$TARGET-strip export STRIP=$TARGET-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
export STAGING_DIR=$RUNNER_TEMP
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
# netfilter libs # netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
@ -111,7 +92,6 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do for i in libmnl libnfnetlink libnetfilter_queue ; do
( (
cd $i-* cd $i-*
CFLAGS="-Os -flto=auto $CFLAGS" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking ./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR make install -j$(nproc) DESTDIR=$DEPS_DIR
) )
@ -123,7 +103,6 @@ jobs:
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
( (
cd zlib-* cd zlib-*
CFLAGS="-Os -flto=auto $CFLAGS" \
./configure --prefix= --static ./configure --prefix= --static
make install -j$(nproc) DESTDIR=$DEPS_DIR make install -j$(nproc) DESTDIR=$DEPS_DIR
) )
@ -134,8 +113,8 @@ jobs:
install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
# zapret # zapret
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include $CFLAGS" \ CFLAGS="$CFLAGS -static-libgcc -static -I$DEPS_DIR/include" \
LDFLAGS="-L$DEPS_DIR/lib $LDFLAGS" \ LDFLAGS="$LDFLAGS -L$DEPS_DIR/lib" \
make -C zapret -j$(nproc) make -C zapret -j$(nproc)
tar -C zapret/binaries/my -cJf zapret-linux-$ARCH.tar.xz . tar -C zapret/binaries/my -cJf zapret-linux-$ARCH.tar.xz .
@ -191,7 +170,7 @@ jobs:
ARCH: ${{ matrix.arch }} ARCH: ${{ matrix.arch }}
run: | run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}" export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
settarget $TARGET-freebsd11 make bsd -j$(nproc) settarget $TARGET-freebsd11 make bsd -j$(nproc) || exit 1
tar -C binaries/my -cJf zapret-freebsd-$ARCH.tar.xz . tar -C binaries/my -cJf zapret-freebsd-$ARCH.tar.xz .
- name: Upload artifacts - name: Upload artifacts
@ -224,9 +203,9 @@ jobs:
- name: Build ip2net, mdig - name: Build ip2net, mdig
shell: msys2 {0} shell: msys2 {0}
run: | run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
mkdir -p output mkdir -p output
cd zapret cd zapret
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
mingw32-make -C ip2net win mingw32-make -C ip2net win
mingw32-make -C mdig win mingw32-make -C mdig win
cp -a {ip2net/ip2net,mdig/mdig}.exe ../output cp -a {ip2net/ip2net,mdig/mdig}.exe ../output
@ -327,12 +306,11 @@ jobs:
- name: Build - name: Build
env: env:
ABI: ${{ matrix.abi }} ABI: ${{ matrix.abi }}
API: 21
TARGET: ${{ matrix.target }} TARGET: ${{ matrix.target }}
GH_TOKEN: ${{ github.token }}
run: | run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps DEPS_DIR=$GITHUB_WORKSPACE/deps
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64 export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
export API=21
export CC="$TOOLCHAIN/bin/clang --target=$TARGET$API" export CC="$TOOLCHAIN/bin/clang --target=$TARGET$API"
export AR=$TOOLCHAIN/bin/llvm-ar export AR=$TOOLCHAIN/bin/llvm-ar
export AS=$CC export AS=$CC
@ -341,6 +319,8 @@ jobs:
export STRIP=$TOOLCHAIN/bin/llvm-strip export STRIP=$TOOLCHAIN/bin/llvm-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
# netfilter libs # netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
wget -qO- https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj wget -qO- https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
@ -350,7 +330,7 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do for i in libmnl libnfnetlink libnetfilter_queue ; do
( (
cd $i-* cd $i-*
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \ CFLAGS="$CFLAGS -Wno-implicit-function-declaration" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking ./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR make install -j$(nproc) DESTDIR=$DEPS_DIR
) )
@ -358,15 +338,8 @@ jobs:
done done
# zapret # zapret
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -I$DEPS_DIR/include" \ CFLAGS="$CFLAGS -I$DEPS_DIR/include" LDFLAGS="$LDFLAGS -L$DEPS_DIR/lib" \
LDFLAGS="-L$DEPS_DIR/lib" \
make -C zapret android -j$(nproc) make -C zapret android -j$(nproc)
# strip unwanted ELF sections to prevent warnings on old Android versions
gh api repos/termux/termux-elf-cleaner/releases/latest --jq '.tag_name' |\
xargs -I{} wget -O elf-cleaner https://github.com/termux/termux-elf-cleaner/releases/download/{}/termux-elf-cleaner
chmod +x elf-cleaner
./elf-cleaner --api-level $API zapret/binaries/my/*
zip zapret-android-$ABI.zip -j zapret/binaries/my/* zip zapret-android-$ABI.zip -j zapret/binaries/my/*
- name: Upload artifacts - name: Upload artifacts
@ -401,7 +374,6 @@ jobs:
uses: crazy-max/ghaction-upx@v3 uses: crazy-max/ghaction-upx@v3
with: with:
install-only: true install-only: true
version: v4.2.4
- name: Prepare binaries - name: Prepare binaries
shell: bash shell: bash
@ -419,7 +391,7 @@ jobs:
if [[ $dir == *-linux-x86_64 ]]; then if [[ $dir == *-linux-x86_64 ]]; then
tar -C $dir -czvf $dir/tpws_wsl.tgz tpws tar -C $dir -czvf $dir/tpws_wsl.tgz tpws
run_upx $dir/* run_upx $dir/*
elif [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then elif [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]]; then
run_upx $dir/* run_upx $dir/*
fi fi
;; ;;
@ -451,7 +423,6 @@ jobs:
*-linux-ppc ) run_dir ppc ;; *-linux-ppc ) run_dir ppc ;;
*-linux-x86 ) run_dir x86 ;; *-linux-x86 ) run_dir x86 ;;
*-linux-x86_64 ) run_dir x86_64 ;; *-linux-x86_64 ) run_dir x86_64 ;;
*-linux-lexra ) run_dir lexra ;;
*-mac-x64 ) run_dir mac64 ;; *-mac-x64 ) run_dir mac64 ;;
*-win-x86 ) run_dir win32 ;; *-win-x86 ) run_dir win32 ;;
*-win-x86_64 ) run_dir win64 ;; *-win-x86_64 ) run_dir win64 ;;
@ -466,12 +437,10 @@ jobs:
find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }} tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }} zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
( rm -rf ${{ env.repo_dir }}/tpws ${{ env.repo_dir }}/nfq ${{ env.repo_dir }}/ip2net ${{ env.repo_dir }}/mdig ${{ env.repo_dir }}/docs ${{ env.repo_dir }}/files/huawei
cd ${{ env.repo_dir }} rm -rf ${{ env.repo_dir }}/init.d/openrc ${{ env.repo_dir }}/init.d/macos ${{ env.repo_dir }}/init.d/pfsense ${{ env.repo_dir }}/init.d/runit ${{ env.repo_dir }}/init.d/s6 ${{ env.repo_dir }}/init.d/systemd
rm -rf binaries/{android*,freebsd*,mac*,win*,x86_64/tpws_wsl.tgz} \ rm -rf ${{ env.repo_dir }}/binaries/android* -rf ${{ env.repo_dir }}/binaries/win* ${{ env.repo_dir }}/binaries/mac* ${{ env.repo_dir }}/binaries/freebsd*
init.d/{openrc,macos,pfsense,runit,s6,systemd} \ rm -f ${{ env.repo_dir }}/Makefile ${{ env.repo_dir }}/binaries/x86_64/tpws_wsl.tgz
tpws nfq ip2net mdig docs files/huawei Makefile
)
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }} tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
- name: Upload release assets - name: Upload release assets

2
.gitignore vendored
View File

@ -4,9 +4,9 @@ mdig/mdig
nfq/dvtws nfq/dvtws
nfq/nfqws nfq/nfqws
nfq/winws.exe nfq/winws.exe
nfq/WinDivert*
tpws/tpws tpws/tpws
binaries/my/ binaries/my/
init.d/**/custom
ipset/zapret-ip*.txt ipset/zapret-ip*.txt
ipset/zapret-ip*.gz ipset/zapret-ip*.gz
ipset/zapret-hosts*.txt ipset/zapret-hosts*.txt

View File

@ -15,19 +15,6 @@ all: clean
done \ done \
done done
systemd: 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" systemd || 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
android: clean android: clean
@mkdir -p "$(TGT)"; \ @mkdir -p "$(TGT)"; \
for dir in $(DIRS); do \ for dir in $(DIRS); do \

View File

@ -23,7 +23,6 @@ CURL=${CURL:-curl}
. "$ZAPRET_BASE/common/fwtype.sh" . "$ZAPRET_BASE/common/fwtype.sh"
. "$ZAPRET_BASE/common/virt.sh" . "$ZAPRET_BASE/common/virt.sh"
DOMAINS_DEFAULT=${DOMAINS_DEFAULT:-rutracker.org}
QNUM=${QNUM:-59780} QNUM=${QNUM:-59780}
SOCKS_PORT=${SOCKS_PORT:-1993} SOCKS_PORT=${SOCKS_PORT:-1993}
TPWS_UID=${TPWS_UID:-1} TPWS_UID=${TPWS_UID:-1}
@ -36,9 +35,9 @@ MDIG=${MDIG:-${ZAPRET_BASE}/mdig/mdig}
DESYNC_MARK=0x10000000 DESYNC_MARK=0x10000000
IPFW_RULE_NUM=${IPFW_RULE_NUM:-1} IPFW_RULE_NUM=${IPFW_RULE_NUM:-1}
IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-59780} IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-59780}
DOMAINS=${DOMAINS:-rutracker.org}
CURL_MAX_TIME=${CURL_MAX_TIME:-2} CURL_MAX_TIME=${CURL_MAX_TIME:-2}
CURL_MAX_TIME_QUIC=${CURL_MAX_TIME_QUIC:-$CURL_MAX_TIME} CURL_MAX_TIME_QUIC=${CURL_MAX_TIME_QUIC:-$CURL_MAX_TIME}
CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2}
MIN_TTL=${MIN_TTL:-1} MIN_TTL=${MIN_TTL:-1}
MAX_TTL=${MAX_TTL:-12} MAX_TTL=${MAX_TTL:-12}
USER_AGENT=${USER_AGENT:-Mozilla} USER_AGENT=${USER_AGENT:-Mozilla}
@ -46,9 +45,8 @@ HTTP_PORT=${HTTP_PORT:-80}
HTTPS_PORT=${HTTPS_PORT:-443} HTTPS_PORT=${HTTPS_PORT:-443}
QUIC_PORT=${QUIC_PORT:-443} QUIC_PORT=${QUIC_PORT:-443}
UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org} UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org}
PARALLEL_OUT=/tmp/zapret_parallel
HDRTEMP=/tmp/zapret-hdr HDRTEMP=/tmp/zapret-hdr.txt
NFT_TABLE=blockcheck NFT_TABLE=blockcheck
@ -79,11 +77,9 @@ exitp()
{ {
local A local A
[ "$BATCH" = 1 ] || {
echo echo
echo press enter to continue echo press enter to continue
read A read A
}
exit $1 exit $1
} }
@ -216,7 +212,7 @@ doh_resolve()
# $1 - ip version 4/6 # $1 - ip version 4/6
# $2 - hostname # $2 - hostname
# $3 - doh server URL. use $DOH_SERVER if empty # $3 - doh server URL. use $DOH_SERVER if empty
$MDIG --family=$1 --dns-make-query=$2 | $CURL --max-time $CURL_MAX_TIME_DOH -s --data-binary @- -H "Content-Type: application/dns-message" "${3:-$DOH_SERVER}" | $MDIG --dns-parse-query $MDIG --family=$1 --dns-make-query=$2 | curl -s --data-binary @- -H "Content-Type: application/dns-message" "${3:-$DOH_SERVER}" | $MDIG --dns-parse-query
} }
doh_find_working() doh_find_working()
{ {
@ -341,19 +337,12 @@ netcat_test()
} }
} }
tpws_can_fix_seg()
{
# fix-seg requires kernel 4.6+
"$TPWS" --port 1 --dry-run --fix-seg >/dev/null 2>/dev/null
}
check_system() check_system()
{ {
echo \* checking system echo \* checking system
UNAME=$(uname) UNAME=$(uname)
SUBSYS= SUBSYS=
FIX_SEG=
local s local s
# can be passed FWTYPE=iptables to override default nftables preference # can be passed FWTYPE=iptables to override default nftables preference
@ -361,14 +350,6 @@ check_system()
Linux) Linux)
PKTWS="$NFQWS" PKTWS="$NFQWS"
PKTWSD=nfqws PKTWSD=nfqws
if [ -x "$TPWS" ] ; then
if tpws_can_fix_seg ; then
echo tpws supports --fix-seg on this system
FIX_SEG='--fix-seg'
else
echo tpws does not support --fix-seg on this system
fi
fi
linux_fwtype linux_fwtype
[ "$FWTYPE" = iptables -o "$FWTYPE" = nftables ] || { [ "$FWTYPE" = iptables -o "$FWTYPE" = nftables ] || {
echo firewall type $FWTYPE not supported in $UNAME echo firewall type $FWTYPE not supported in $UNAME
@ -579,7 +560,7 @@ curl_supports_tls13()
[ $? = 2 ] && return 1 [ $? = 2 ] && return 1
# curl can have tlsv1.3 key present but ssl library without TLS 1.3 support # curl can have tlsv1.3 key present but ssl library without TLS 1.3 support
# this is online test because there's no other way to trigger library incompatibility case # this is online test because there's no other way to trigger library incompatibility case
$CURL --tlsv1.3 --max-time 1 -Is -o /dev/null https://iana.org 2>/dev/null $CURL --tlsv1.3 --max-time $CURL_MAX_TIME -Is -o /dev/null https://iana.org 2>/dev/null
r=$? r=$?
[ $r != 4 -a $r != 35 ] [ $r != 4 -a $r != 35 ]
} }
@ -670,28 +651,28 @@ curl_test_http()
# $3 - subst ip # $3 - subst ip
# $4 - "detail" - detail info # $4 - "detail" - detail info
local code loc hdrt="${HDRTEMP}_${!:-$$}.txt" local code loc
curl_probe $1 $2 $HTTP_PORT "$3" -SsD "$hdrt" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || { curl_probe $1 $2 $HTTP_PORT "$3" -SsD "$HDRTEMP" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
code=$? code=$?
rm -f "$hdrt" rm -f "$HDRTEMP"
return $code return $code
} }
if [ "$4" = "detail" ] ; then if [ "$4" = "detail" ] ; then
head -n 1 "$hdrt" head -n 1 "$HDRTEMP"
grep "^[lL]ocation:" "$hdrt" grep "^[lL]ocation:" "$HDRTEMP"
else else
code=$(hdrfile_http_code "$hdrt") code=$(hdrfile_http_code "$HDRTEMP")
[ "$code" = 301 -o "$code" = 302 -o "$code" = 307 -o "$code" = 308 ] && { [ "$code" = 301 -o "$code" = 302 -o "$code" = 307 -o "$code" = 308 ] && {
loc=$(hdrfile_location "$hdrt") loc=$(hdrfile_location "$HDRTEMP")
echo "$loc" | grep -qE "^https?://.*$2(/|$)" || echo "$loc" | grep -qE "^https?://.*$2(/|$)" ||
echo "$loc" | grep -vqE '^https?://' || { echo "$loc" | grep -vqE '^https?://' || {
echo suspicious redirection $code to : $loc echo suspicious redirection $code to : $loc
rm -f "$hdrt" rm -f "$HDRTEMP"
return 254 return 254
} }
} }
fi fi
rm -f "$hdrt" rm -f "$HDRTEMP"
[ "$code" = 400 ] && { [ "$code" = 400 ] && {
# this can often happen if the server receives fake packets it should not receive # this can often happen if the server receives fake packets it should not receive
echo http code $code. likely the server receives fakes. echo http code $code. likely the server receives fakes.
@ -735,11 +716,6 @@ ipt_aux_scheme()
# to avoid possible INVALID state drop # to avoid possible INVALID state drop
[ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn -j ACCEPT [ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn -j ACCEPT
local icmp_filter="-p icmp -m icmp --icmp-type"
[ "$IPV" = 6 ] && icmp_filter="-p icmpv6 -m icmp6 --icmpv6-type"
IPT_ADD_DEL $1 INPUT $icmp_filter time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
# for strategies with incoming packets involved (autottl) # for strategies with incoming packets involved (autottl)
IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID -j ACCEPT IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID -j ACCEPT
if [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ]; then if [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ]; then
@ -771,7 +747,6 @@ ipt_scheme()
$IPTABLES -t mangle -A blockcheck_output -p $1 ! --dport $2 -j RETURN $IPTABLES -t mangle -A blockcheck_output -p $1 ! --dport $2 -j RETURN
for ip in $3; do for ip in $3; do
$IPTABLES -t mangle -A blockcheck_output -d $ip -j CONNMARK --or-mark $DESYNC_MARK
$IPTABLES -t mangle -A blockcheck_output -d $ip -j NFQUEUE --queue-num $QNUM $IPTABLES -t mangle -A blockcheck_output -d $ip -j NFQUEUE --queue-num $QNUM
done done
@ -789,20 +764,12 @@ nft_scheme()
nft add table inet $NFT_TABLE nft add table inet $NFT_TABLE
nft "add chain inet $NFT_TABLE postnat { type filter hook output priority 102; }" nft "add chain inet $NFT_TABLE postnat { type filter hook output priority 102; }"
nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} $1 dport $2 mark and $DESYNC_MARK == 0 ip${ipver} daddr {$iplist} ct mark set ct mark or $DESYNC_MARK queue num $QNUM" nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} $1 dport $2 mark and $DESYNC_MARK != $DESYNC_MARK ip${ipver} daddr {$iplist} queue num $QNUM"
# for strategies with incoming packets involved (autottl) # for strategies with incoming packets involved (autottl)
nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }" nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }"
# enable everything generated by nfqws (works only in OUTPUT, not in FORWARD) # enable everything generated by nfqws (works only in OUTPUT, not in FORWARD)
nft "add chain inet $NFT_TABLE predefrag { type filter hook output priority -402; }" nft "add chain inet $NFT_TABLE predefrag { type filter hook output priority -402; }"
nft "add rule inet $NFT_TABLE predefrag meta nfproto ipv${IPV} mark and $DESYNC_MARK !=0 notrack" nft "add rule inet $NFT_TABLE predefrag meta nfproto ipv${IPV} mark and $DESYNC_MARK !=0 notrack"
[ "$IPV" = 4 ] && {
nft "add rule inet $NFT_TABLE prenat icmp type time-exceeded ct mark and $DESYNC_MARK != 0 drop"
nft "add rule inet $NFT_TABLE prenat icmp type time-exceeded ct state invalid drop"
}
[ "$IPV" = 6 ] && {
nft "add rule inet $NFT_TABLE prenat icmpv6 type time-exceeded ct mark and $DESYNC_MARK != 0 drop"
nft "add rule inet $NFT_TABLE prenat icmpv6 type time-exceeded ct state invalid drop"
}
} }
pktws_ipt_prepare() pktws_ipt_prepare()
@ -997,27 +964,8 @@ curl_test()
# $2 - domain # $2 - domain
# $3 - subst ip # $3 - subst ip
# $4 - param of test function # $4 - param of test function
local code=0 n=0 p pids local code=0 n=0
if [ "$PARALLEL" = 1 ]; then
rm -f "${PARALLEL_OUT}"*
for n in $(seq -s ' ' 1 $REPEATS); do
$1 "$IPV" $2 $3 "$4" >"${PARALLEL_OUT}_$n" &
pids="${pids:+$pids }$!"
done
n=1
for p in $pids; do
[ $REPEATS -gt 1 ] && printf "[attempt $n] "
if wait $p; then
[ $REPEATS -gt 1 ] && echo 'AVAILABLE'
else
code=$?
cat "${PARALLEL_OUT}_$n"
fi
n=$(($n+1))
done
rm -f "${PARALLEL_OUT}"*
else
while [ $n -lt $REPEATS ]; do while [ $n -lt $REPEATS ]; do
n=$(($n+1)) n=$(($n+1))
[ $REPEATS -gt 1 ] && printf "[attempt $n] " [ $REPEATS -gt 1 ] && printf "[attempt $n] "
@ -1028,7 +976,6 @@ curl_test()
[ "$SCANLEVEL" = quick ] && break [ "$SCANLEVEL" = quick ] && break
fi fi
done done
fi
[ "$4" = detail ] || { [ "$4" = detail ] || {
if [ $code = 254 ]; then if [ $code = 254 ]; then
echo "UNAVAILABLE" echo "UNAVAILABLE"
@ -1064,10 +1011,11 @@ tpws_curl_test()
echo - checking tpws $3 $4 $5 $6 $7 $8 $9${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"} echo - checking tpws $3 $4 $5 $6 $7 $8 $9${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
local ALL_PROXY="socks5://127.0.0.1:$SOCKS_PORT" local ALL_PROXY="socks5://127.0.0.1:$SOCKS_PORT"
ws_curl_test tpws_start "$@"${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"} ws_curl_test tpws_start "$@"${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
local testf=$1 dom=$2 strategy code=$? local code=$?
[ "$code" = 0 ] && { [ "$code" = 0 ] && {
local testf=$1 dom=$2
shift; shift; shift; shift;
strategy="$@" local strategy="$@"
strategy_append_extra_tpws strategy_append_extra_tpws
report_append "ipv${IPV} $dom $testf : tpws ${WF:+$WF }$strategy" report_append "ipv${IPV} $dom $testf : tpws ${WF:+$WF }$strategy"
} }
@ -1080,10 +1028,11 @@ pktws_curl_test()
# $3,$4,$5, ... - nfqws/dvtws params # $3,$4,$5, ... - nfqws/dvtws params
echo - checking $PKTWSD ${WF:+$WF }$3 $4 $5 $6 $7 $8 $9${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"} echo - checking $PKTWSD ${WF:+$WF }$3 $4 $5 $6 $7 $8 $9${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
ws_curl_test pktws_start "$@"${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"} ws_curl_test pktws_start "$@"${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
local testf=$1 dom=$2 strategy code=$? local code=$?
[ "$code" = 0 ] && { [ "$code" = 0 ] && {
local testf=$1 dom=$2
shift; shift; shift; shift;
strategy="$@" local strategy="$@"
strategy_append_extra_pktws strategy_append_extra_pktws
report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy" report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy"
} }
@ -1163,10 +1112,6 @@ test_has_split()
{ {
contains "$1" split || contains "$1" disorder contains "$1" split || contains "$1" disorder
} }
test_has_fakedsplit()
{
contains "$1" fakedsplit || contains "$1" fakeddisorder
}
test_has_fake() test_has_fake()
{ {
[ "$1" = fake ] || starts_with "$1" fake, [ "$1" = fake ] || starts_with "$1" fake,
@ -1174,10 +1119,7 @@ test_has_fake()
warn_fool() warn_fool()
{ {
case "$1" in case "$1" in
md5sig) echo 'WARNING ! although md5sig fooling worked it will not work on all sites. it typically works only on linux servers.' md5sig) echo 'WARNING ! although md5sig fooling worked it will not work on all sites. it typically works only on linux servers.' ;;
[ "$2" = "fakedsplit" -o "$2" = "fakeddisorder" ] && \
echo "WARNING ! fakedsplit/fakeddisorder with md5sig fooling and low split position causes MTU overflow with multi-segment TLS (kyber)"
;;
datanoack) echo 'WARNING ! although datanoack fooling worked it may break NAT and may only work with external IP. Additionally it may require nftables to work correctly.' ;; datanoack) echo 'WARNING ! although datanoack fooling worked it may break NAT and may only work with external IP. Additionally it may require nftables to work correctly.' ;;
esac esac
} }
@ -1189,24 +1131,18 @@ pktws_curl_test_update_vary()
# $4 - desync mode # $4 - desync mode
# $5,$6,... - strategy # $5,$6,... - strategy
local testf=$1 sec=$2 domain=$3 desync=$4 proto zerofake= tlsmod= splits= pos fake ret=1 local testf=$1 sec=$2 domain=$3 desync=$4 proto zerofake= splits= pos fake ret=1
shift; shift; shift; shift shift; shift; shift; shift
proto=http proto=http
[ "$sec" = 0 ] || proto=tls [ "$sec" = 0 ] || proto=tls
test_has_fake $desync && { test_has_fake $desync && zerofake="--dpi-desync-fake-$proto=0x00000000"
zerofake="--dpi-desync-fake-$proto=0x00000000" test_has_split $desync && {
[ "$sec" = 0 ] || tlsmod="--dpi-desync-fake-tls-mod=rnd,dupsid,rndsni,padencap"
}
if test_has_fakedsplit $desync ; then
splits="method+2 midsld"
[ "$sec" = 0 ] || splits="1 midsld"
elif test_has_split $desync ; then
splits="method+2 midsld" splits="method+2 midsld"
[ "$sec" = 0 ] || splits="1 midsld 1,midsld" [ "$sec" = 0 ] || splits="1 midsld 1,midsld"
fi }
for fake in '' $zerofake $tlsmod ; do for fake in '' $zerofake ; do
if [ -n "$splits" ]; then if [ -n "$splits" ]; then
for pos in $splits ; do for pos in $splits ; do
pktws_curl_test_update $testf $domain --dpi-desync=$desync "$@" --dpi-desync-split-pos=$pos $fake && { pktws_curl_test_update $testf $domain --dpi-desync=$desync "$@" --dpi-desync-split-pos=$pos $fake && {
@ -1304,7 +1240,7 @@ pktws_check_domain_http_bypass_()
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2" [ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
for fooling in $f; do for fooling in $f; do
pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && { pktws_curl_test_update_vary $1 $2 $3 $desync --dpi-desync-fooling=$fooling $e && {
warn_fool $fooling $desync warn_fool $fooling
[ "$SCANLEVEL" = quick ] && return [ "$SCANLEVEL" = quick ] && return
need_wssize=0 need_wssize=0
} }
@ -1459,11 +1395,6 @@ warn_mss()
[ -n "$1" ] && echo 'WARNING ! although mss worked it may not work on all sites and will likely cause significant slowdown. it may only be required for TLS1.2, not TLS1.3' [ -n "$1" ] && echo 'WARNING ! although mss worked it may not work on all sites and will likely cause significant slowdown. it may only be required for TLS1.2, not TLS1.3'
return 0 return 0
} }
fix_seg()
{
# $1 - split-pos
[ -n "$FIX_SEG" ] && contains "$1" , && echo "$FIX_SEG"
}
tpws_check_domain_http_bypass_() tpws_check_domain_http_bypass_()
{ {
@ -1489,7 +1420,7 @@ tpws_check_domain_http_bypass_()
done done
for s2 in '' '--hostcase' '--oob' '--disorder' ${oobdis:+"$oobdis"}; do for s2 in '' '--hostcase' '--oob' '--disorder' ${oobdis:+"$oobdis"}; do
for s in $splits_http ; do for s in $splits_http ; do
tpws_curl_test_update $1 $3 --split-pos=$s $(fix_seg $s) $s2 && [ "$SCANLEVEL" != force ] && { tpws_curl_test_update $1 $3 --split-pos=$s $s2 && [ "$SCANLEVEL" != force ] && {
[ "$SCANLEVEL" = quick ] && return [ "$SCANLEVEL" = quick ] && return
break break
} }
@ -1504,7 +1435,7 @@ tpws_check_domain_http_bypass_()
s3=${mss:+--mss=$mss} s3=${mss:+--mss=$mss}
for s2 in '' '--oob' '--disorder' ${oobdis:+"$oobdis"}; do for s2 in '' '--oob' '--disorder' ${oobdis:+"$oobdis"}; do
for pos in $splits_tls; do for pos in $splits_tls; do
tpws_curl_test_update $1 $3 --split-pos=$pos $(fix_seg $pos) $s2 $s3 && warn_mss $s3 && [ "$SCANLEVEL" != force ] && { tpws_curl_test_update $1 $3 --split-pos=$pos $s2 $s3 && warn_mss $s3 && [ "$SCANLEVEL" != force ] && {
[ "$SCANLEVEL" = quick ] && return [ "$SCANLEVEL" = quick ] && return
need_mss=0 need_mss=0
break break
@ -1512,7 +1443,7 @@ tpws_check_domain_http_bypass_()
done done
done done
for s in '' '--oob' '--disorder' ${oobdis:+"$oobdis"}; do 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 $FIX_SEG" "--tlsrec=sniext+4 --split-pos=1,midsld $FIX_SEG" ; 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 ] && { tpws_curl_test_update $1 $3 $s2 $s $s3 && warn_mss $s3 && [ "$SCANLEVEL" != force ] && {
[ "$SCANLEVEL" = quick ] && return [ "$SCANLEVEL" = quick ] && return
need_mss=0 need_mss=0
@ -1615,7 +1546,7 @@ check_domain_http_tcp()
check_domain_prolog $1 $2 $4 || return check_domain_prolog $1 $2 $4 || return
[ "$SKIP_IPBLOCK" = 1 ] || check_dpi_ip_block $1 $4 check_dpi_ip_block $1 $4
[ "$SKIP_TPWS" = 1 ] || { [ "$SKIP_TPWS" = 1 ] || {
echo echo
@ -1661,22 +1592,22 @@ check_domain_http_udp()
check_domain_http() check_domain_http()
{ {
# $1 - domain # $1 - domain
check_domain_http_tcp curl_test_http $HTTP_PORT 0 $1 check_domain_http_tcp curl_test_http 80 0 $1
} }
check_domain_https_tls12() check_domain_https_tls12()
{ {
# $1 - domain # $1 - domain
check_domain_http_tcp curl_test_https_tls12 $HTTPS_PORT 1 $1 check_domain_http_tcp curl_test_https_tls12 443 1 $1
} }
check_domain_https_tls13() check_domain_https_tls13()
{ {
# $1 - domain # $1 - domain
check_domain_http_tcp curl_test_https_tls13 $HTTPS_PORT 2 $1 check_domain_http_tcp curl_test_https_tls13 443 2 $1
} }
check_domain_http3() check_domain_http3()
{ {
# $1 - domain # $1 - domain
check_domain_http_udp curl_test_http3 $QUIC_PORT $1 check_domain_http_udp curl_test_http3 443 $1
} }
configure_ip_version() configure_ip_version()
@ -1771,119 +1702,76 @@ ask_params()
exitp 1 exitp 1
} }
local dom
[ -n "$DOMAINS" ] || {
DOMAINS="$DOMAINS_DEFAULT"
[ "$BATCH" = 1 ] || {
echo "specify domain(s) to test. multiple domains are space separated." echo "specify domain(s) to test. multiple domains are space separated."
printf "domain(s) (default: $DOMAINS) : " printf "domain(s) (default: $DOMAINS) : "
local dom
read dom read dom
[ -n "$dom" ] && DOMAINS="$dom" [ -n "$dom" ] && DOMAINS="$dom"
}
}
local IPVS_def=4 local IPVS_def=4
[ -n "$IPVS" ] || {
# yandex public dns # yandex public dns
pingtest 6 2a02:6b8::feed:0ff && IPVS_def=46 pingtest 6 2a02:6b8::feed:0ff && IPVS_def=46
[ "$BATCH" = 1 ] || {
printf "ip protocol version(s) - 4, 6 or 46 for both (default: $IPVS_def) : " printf "ip protocol version(s) - 4, 6 or 46 for both (default: $IPVS_def) : "
read IPVS read IPVS
}
[ -n "$IPVS" ] || IPVS=$IPVS_def [ -n "$IPVS" ] || IPVS=$IPVS_def
[ "$IPVS" = 4 -o "$IPVS" = 6 -o "$IPVS" = 46 ] || { [ "$IPVS" = 4 -o "$IPVS" = 6 -o "$IPVS" = 46 ] || {
echo 'invalid ip version(s). should be 4, 6 or 46.' echo 'invalid ip version(s). should be 4, 6 or 46.'
exitp 1 exitp 1
} }
}
[ "$IPVS" = 46 ] && IPVS="4 6" [ "$IPVS" = 46 ] && IPVS="4 6"
configure_curl_opt configure_curl_opt
[ -n "$ENABLE_HTTP" ] || {
ENABLE_HTTP=1 ENABLE_HTTP=1
[ "$BATCH" = 1 ] || {
echo echo
ask_yes_no_var ENABLE_HTTP "check http" ask_yes_no_var ENABLE_HTTP "check http"
}
}
[ -n "$ENABLE_HTTPS_TLS12" ] || {
ENABLE_HTTPS_TLS12=1 ENABLE_HTTPS_TLS12=1
[ "$BATCH" = 1 ] || {
echo echo
ask_yes_no_var ENABLE_HTTPS_TLS12 "check https tls 1.2" ask_yes_no_var ENABLE_HTTPS_TLS12 "check https tls 1.2"
}
}
[ -n "$ENABLE_HTTPS_TLS13" ] || {
ENABLE_HTTPS_TLS13=0 ENABLE_HTTPS_TLS13=0
if [ -n "$TLS13" ]; then
[ "$BATCH" = 1 ] || {
echo echo
if [ -n "$TLS13" ]; then
echo "TLS 1.3 uses encrypted ServerHello. DPI cannot check domain name in server response." echo "TLS 1.3 uses encrypted ServerHello. DPI cannot check domain name in server response."
echo "This can allow more bypass strategies to work." echo "This can allow more bypass strategies to work."
echo "What works for TLS 1.2 will also work for TLS 1.3 but not vice versa." echo "What works for TLS 1.2 will also work for TLS 1.3 but not vice versa."
echo "Most sites nowadays support TLS 1.3 but not all. If you can't find a strategy for TLS 1.2 use this test." echo "Most sites nowadays support TLS 1.3 but not all. If you can't find a strategy for TLS 1.2 use this test."
echo "TLS 1.3 only strategy is better than nothing." echo "TLS 1.3 only strategy is better than nothing."
ask_yes_no_var ENABLE_HTTPS_TLS13 "check https tls 1.3" ask_yes_no_var ENABLE_HTTPS_TLS13 "check https tls 1.3"
}
else else
echo
echo "installed curl version does not support TLS 1.3 . tests disabled." echo "installed curl version does not support TLS 1.3 . tests disabled."
fi fi
}
[ -n "$ENABLE_HTTP3" ] || {
ENABLE_HTTP3=0 ENABLE_HTTP3=0
echo
if [ -n "$HTTP3" ]; then if [ -n "$HTTP3" ]; then
ENABLE_HTTP3=1
[ "$BATCH" = 1 ] || {
echo
echo "make sure target domain(s) support QUIC or result will be negative in any case" echo "make sure target domain(s) support QUIC or result will be negative in any case"
ENABLE_HTTP3=1
ask_yes_no_var ENABLE_HTTP3 "check http3 QUIC" ask_yes_no_var ENABLE_HTTP3 "check http3 QUIC"
}
else else
echo
echo "installed curl version does not support http3 QUIC. tests disabled." echo "installed curl version does not support http3 QUIC. tests disabled."
fi fi
}
[ -n "$REPEATS" ] || {
[ "$BATCH" = 1 ] || {
echo echo
echo "sometimes ISPs use multiple DPIs or load balancing. bypass strategies may work unstable." echo "sometimes ISPs use multiple DPIs or load balancing. bypass strategies may work unstable."
printf "how many times to repeat each test (default: 1) : " printf "how many times to repeat each test (default: 1) : "
read REPEATS read REPEATS
}
REPEATS=$((0+${REPEATS:-1})) REPEATS=$((0+${REPEATS:-1}))
[ "$REPEATS" = 0 ] && { [ "$REPEATS" = 0 ] && {
echo invalid repeat count echo invalid repeat count
exitp 1 exitp 1
} }
}
[ -z "$PARALLEL" -a $REPEATS -gt 1 ] && {
PARALLEL=0
[ "$BATCH" = 1 ] || {
echo
echo "parallel scan can greatly increase speed but may also trigger DDoS protection and cause false result"
ask_yes_no_var PARALLEL "enable parallel scan"
}
}
PARALLEL=${PARALLEL:-0}
[ -n "$SCANLEVEL" ] || {
SCANLEVEL=standard
[ "$BATCH" = 1 ] || {
echo echo
echo quick - scan as fast as possible to reveal any working strategy echo quick - scan as fast as possible to reveal any working strategy
echo standard - do investigation what works on your DPI echo standard - do investigation what works on your DPI
echo force - scan maximum despite of result echo force - scan maximum despite of result
SCANLEVEL=${SCANLEVEL:-standard}
ask_list SCANLEVEL "quick standard force" "$SCANLEVEL" ask_list SCANLEVEL "quick standard force" "$SCANLEVEL"
# disable tpws checks by default in quick mode # disable tpws checks by default in quick mode
[ "$SCANLEVEL" = quick -a -z "$SKIP_TPWS" -a "$UNAME" != Darwin ] && SKIP_TPWS=1 [ "$SCANLEVEL" = quick -a -z "$SKIP_TPWS" -a "$UNAME" != Darwin ] && SKIP_TPWS=1
}
}
echo echo
@ -2088,15 +1976,14 @@ check_dns()
unprepare_all() unprepare_all()
{ {
# make sure we are not in a middle state that impacts connectivity # make sure we are not in a middle state that impacts connectivity
ws_kill rm -f "$HDRTEMP"
wait
[ -n "$IPV" ] && { [ -n "$IPV" ] && {
pktws_ipt_unprepare_tcp $HTTP_PORT pktws_ipt_unprepare_tcp 80
pktws_ipt_unprepare_tcp $HTTPS_PORT pktws_ipt_unprepare_tcp 443
pktws_ipt_unprepare_udp $QUIC_PORT pktws_ipt_unprepare_udp 443
} }
ws_kill
cleanup cleanup
rm -f "${HDRTEMP}"* "${PARALLEL_OUT}"*
} }
sigint() sigint()
{ {
@ -2142,10 +2029,10 @@ for dom in $DOMAINS; do
for IPV in $IPVS; do for IPV in $IPVS; do
configure_ip_version configure_ip_version
[ "$ENABLE_HTTP" = 1 ] && { [ "$ENABLE_HTTP" = 1 ] && {
[ "$SKIP_IPBLOCK" = 1 ] || check_domain_port_block $dom $HTTP_PORT check_domain_port_block $dom $HTTP_PORT
check_domain_http $dom check_domain_http $dom
} }
[ "$ENABLE_HTTPS_TLS12" = 1 -o "$ENABLE_HTTPS_TLS13" = 1 ] && [ "$SKIP_IPBLOCK" != 1 ] && check_domain_port_block $dom $HTTPS_PORT [ "$ENABLE_HTTPS_TLS12" = 1 -o "$ENABLE_HTTPS_TLS13" = 1 ] && check_domain_port_block $dom $HTTPS_PORT
[ "$ENABLE_HTTPS_TLS12" = 1 ] && check_domain_https_tls12 $dom [ "$ENABLE_HTTPS_TLS12" = 1 ] && check_domain_https_tls12 $dom
[ "$ENABLE_HTTPS_TLS13" = 1 ] && check_domain_https_tls13 $dom [ "$ENABLE_HTTPS_TLS13" = 1 ] && check_domain_https_tls13 $dom
[ "$ENABLE_HTTP3" = 1 ] && check_domain_http3 $dom [ "$ENABLE_HTTP3" = 1 ] && check_domain_http3 $dom

View File

@ -241,7 +241,7 @@ fix_sbin_path()
# it can calculate floating point expr # it can calculate floating point expr
calc() calc()
{ {
LC_ALL=C awk "BEGIN { print $*}"; awk "BEGIN { print $*}";
} }
fsleep_setup() fsleep_setup()
@ -318,27 +318,18 @@ setup_md5()
exists $MD5 || MD5=md5 exists $MD5 || MD5=md5
} }
setup_random()
{
[ -n "$RCUT" ] && return
RCUT="cut -c 1-17"
# some shells can operate with 32 bit signed int
[ $((0x100000000)) = 0 ] && RCUT="cut -c 1-9"
}
random() random()
{ {
# $1 - min, $2 - max # $1 - min, $2 - max
local r rs local r rs
setup_md5 setup_md5
setup_random
if [ -c /dev/urandom ]; then if [ -c /dev/urandom ]; then
read rs </dev/urandom read rs </dev/urandom
else else
rs="$RANDOM$RANDOM$(date)" rs="$RANDOM$RANDOM$(date)"
fi fi
# shells use signed int64 # shells use signed int64
r=1$(echo $rs | $MD5 | sed 's/[^0-9]//g' | $RCUT) r=1$(echo $rs | $MD5 | sed 's/[^0-9]//g' | cut -c 1-17)
echo $(( ($r % ($2-$1+1)) + $1 )) echo $(( ($r % ($2-$1+1)) + $1 ))
} }
@ -405,14 +396,14 @@ std_ports()
has_bad_ws_options() has_bad_ws_options()
{ {
# $1 - nfqws/tpws opts # $1 - nfqws/tpws opts
# ПРИМЕЧАНИЕ ДЛЯ РАСПРОСТРАНИТЕЛЕЙ КОПИПАСТЫ
# kernel or user mode ipset usage should be wise # ЭТОТ КОД СДЕЛАН СПЕЦИАЛЬНО ДЛЯ ВАС, ЧТОБЫ ВЫ НЕ ПОСТИЛИ В СЕТЬ ПЛОХИЕ РЕЦЕПТЫ
# if all traffic is already intercepted it would be OK to use ip-based specialized profiles # ЕСЛИ ВАМ ХОЧЕТСЯ ЕГО УДАЛИТЬ И НАПИСАТЬ ИНСТРУКЦИЮ КАК ЕГО УДАЛЯТЬ, ВЫ ДЕЛАЕТЕ ХРЕНОВУЮ УСЛУГУ. НАПИШИТЕ ЛУЧШЕ custom script.
# but if all traffic is intercepted only to filter a group of ip its BAD. kernel ipset should be used. # custom script - ЭТО ФАЙЛИК, КОТОРЫЙ ДОСТАТОЧНО СКОПИРОВАТЬ В НУЖНУЮ ДИРЕКТОРИЮ, ЧТОБЫ ОН СДЕЛАЛ ТОЖЕ САМОЕ, НО ЭФФЕКТИВНО.
# I cannot insert brain to copy-pasters, I know they will misuse. But it's their problem. # ФИЛЬТРАЦИЯ ПО IPSET В ЯДРЕ НЕСРАВНИМО ЭФФЕКТИВНЕЕ, ЧЕМ ПЕРЕКИДЫВАТЬ ВСЕ ПАКЕТЫ В nfqws И ТАМ ФИЛЬТРОВАТЬ
# zapret is not made for newbies # --ipset СУЩЕСТВУЕТ ТОЛЬКО ДЛЯ ВИНДЫ И LINUX СИСТЕМ БЕЗ ipset (НАПРИМЕР, Android).
#contains "$1" "--ipset" # И ТОЛЬКО ПО ЭТОЙ ПРИЧИНЕ ОНО НЕ ВЫКИНУТО ПОЛНОСТЬЮ ИЗ LINUX ВЕРСИИ
return 1 contains "$1" "--ipset"
} }
check_bad_ws_options() check_bad_ws_options()
{ {

View File

@ -3,8 +3,6 @@ custom_runner()
# $1 - function name # $1 - function name
# $2+ - params # $2+ - params
[ "$DISABLE_CUSTOM" = 1 ] && return 0
local n script FUNC=$1 local n script FUNC=$1
shift shift

View File

@ -1,4 +1,4 @@
GET_LIST_PREFIX=/ipset/get_ readonly GET_LIST_PREFIX=/ipset/get_
SYSTEMD_DIR=/lib/systemd SYSTEMD_DIR=/lib/systemd
[ -d "$SYSTEMD_DIR" ] || SYSTEMD_DIR=/usr/lib/systemd [ -d "$SYSTEMD_DIR" ] || SYSTEMD_DIR=/usr/lib/systemd
@ -140,7 +140,7 @@ echo_var()
eval v="\$$1" eval v="\$$1"
if find_str_in_list $1 "$EDITVAR_NEWLINE_VARS"; then if find_str_in_list $1 "$EDITVAR_NEWLINE_VARS"; then
echo "$1=\"" echo "$1=\""
echo "$v\"" | tr '\n' ' ' | tr -d '\r' | sed -e 's/^ *//' -e 's/ *$//' -e "s/$EDITVAR_NEWLINE_DELIMETER /$EDITVAR_NEWLINE_DELIMETER\n/g" echo "$v\"" | sed "s/$EDITVAR_NEWLINE_DELIMETER /$EDITVAR_NEWLINE_DELIMETER\n/g"
else else
if contains "$v" " "; then if contains "$v" " "; then
echo $1=\"$v\" echo $1=\"$v\"
@ -170,7 +170,6 @@ list_vars()
echo_var $1 echo_var $1
shift shift
done done
echo
} }
openrc_test() openrc_test()
@ -617,17 +616,11 @@ write_config_var()
replace_var_def $1 "$M" "$ZAPRET_CONFIG" replace_var_def $1 "$M" "$ZAPRET_CONFIG"
} }
no_prereq_exit()
{
echo could not install prerequisites
exitp 6
}
check_prerequisites_linux() check_prerequisites_linux()
{ {
echo \* checking prerequisites echo \* checking prerequisites
local s cmd PKGS UTILS req="curl curl" local s cmd PKGS UTILS req="curl curl"
local APTGET DNF YUM PACMAN ZYPPER EOPKG APK
case "$FWTYPE" in case "$FWTYPE" in
iptables) iptables)
req="$req iptables iptables ip6tables iptables ipset ipset" req="$req iptables iptables ip6tables iptables ipset ipset"
@ -656,7 +649,6 @@ check_prerequisites_linux()
echo packages required : $PKGS echo packages required : $PKGS
APTGET=$(whichq apt-get) APTGET=$(whichq apt-get)
DNF=$(whichq dnf)
YUM=$(whichq yum) YUM=$(whichq yum)
PACMAN=$(whichq pacman) PACMAN=$(whichq pacman)
ZYPPER=$(whichq zypper) ZYPPER=$(whichq zypper)
@ -664,23 +656,39 @@ check_prerequisites_linux()
APK=$(whichq apk) APK=$(whichq apk)
if [ -x "$APTGET" ] ; then if [ -x "$APTGET" ] ; then
"$APTGET" update "$APTGET" update
"$APTGET" install -y --no-install-recommends $PKGS dnsutils || no_prereq_exit "$APTGET" install -y --no-install-recommends $PKGS dnsutils || {
elif [ -x "$DNF" ] ; then echo could not install prerequisites
"$DNF" -y install $PKGS || no_prereq_exit exitp 6
}
elif [ -x "$YUM" ] ; then elif [ -x "$YUM" ] ; then
"$YUM" -y install $PKGS || no_prereq_exit "$YUM" -y install $PKGS || {
echo could not install prerequisites
exitp 6
}
elif [ -x "$PACMAN" ] ; then elif [ -x "$PACMAN" ] ; then
"$PACMAN" -Syy "$PACMAN" -Syy
"$PACMAN" --noconfirm -S $PKGS || no_prereq_exit "$PACMAN" --noconfirm -S $PKGS || {
echo could not install prerequisites
exitp 6
}
elif [ -x "$ZYPPER" ] ; then elif [ -x "$ZYPPER" ] ; then
"$ZYPPER" --non-interactive install $PKGS || no_prereq_exit "$ZYPPER" --non-interactive install $PKGS || {
echo could not install prerequisites
exitp 6
}
elif [ -x "$EOPKG" ] ; then elif [ -x "$EOPKG" ] ; then
"$EOPKG" -y install $PKGS || no_prereq_exit "$EOPKG" -y install $PKGS || {
echo could not install prerequisites
exitp 6
}
elif [ -x "$APK" ] ; then elif [ -x "$APK" ] ; then
"$APK" update "$APK" update
# for alpine # for alpine
[ "$FWTYPE" = iptables ] && [ -n "$($APK list ip6tables)" ] && PKGS="$PKGS ip6tables" [ "$FWTYPE" = iptables ] && [ -n "$($APK list ip6tables)" ] && PKGS="$PKGS ip6tables"
"$APK" add $PKGS || no_prereq_exit "$APK" add $PKGS || {
echo could not install prerequisites
exitp 6
}
else else
echo supported package manager not found echo supported package manager not found
echo you must manually install : $UTILS echo you must manually install : $UTILS
@ -829,37 +837,3 @@ select_fwtype()
echo select firewall type : echo select firewall type :
ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE
} }
dry_run_tpws_()
{
local TPWS="$ZAPRET_BASE/tpws/tpws"
echo verifying tpws options
"$TPWS" --dry-run "$@"
}
dry_run_nfqws_()
{
local NFQWS="$ZAPRET_BASE/nfq/nfqws"
echo verifying nfqws options
"$NFQWS" --dry-run "$@"
}
dry_run_tpws()
{
[ "$TPWS_ENABLE" = 1 ] || return 0
local opt="$TPWS_OPT" port=${TPPORT_SOCKS:-988}
filter_apply_hostlist_target opt
dry_run_tpws_ --port=$port $opt
}
dry_run_tpws_socks()
{
[ "$TPWS_SOCKS_ENABLE" = 1 ] || return 0
local opt="$TPWS_SOCKS_OPT" port=${TPPORT:-987}
filter_apply_hostlist_target opt
dry_run_tpws_ --port=$port --socks $opt
}
dry_run_nfqws()
{
[ "$NFQWS_ENABLE" = 1 ] || return 0
local opt="$NFQWS_OPT" qn=${QNUM:-200}
filter_apply_hostlist_target opt
dry_run_nfqws_ --qnum=$qn $opt
}

View File

@ -1,9 +1,5 @@
std_ports std_ports
ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes" readonly ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes"
IPSET_EXCLUDE="-m set ! --match-set nozapret"
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
IPBAN_EXCLUDE="-m set ! --match-set ipban"
IPBAN_EXCLUDE6="-m set ! --match-set ipban6"
ipt() ipt()
{ {
@ -136,7 +132,7 @@ _fw_tpws4()
ipt_print_op $1 "$2" "tpws (port $3)" ipt_print_op $1 "$2" "tpws (port $3)"
rule="$2 $IPSET_EXCLUDE dst $IPBAN_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3" rule="$2 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3"
for i in $4 ; do for i in $4 ; do
ipt_add_del $1 PREROUTING -t nat -i $i $rule ipt_add_del $1 PREROUTING -t nat -i $i $rule
done done
@ -164,7 +160,7 @@ _fw_tpws6()
ipt_print_op $1 "$2" "tpws (port $3)" 6 ipt_print_op $1 "$2" "tpws (port $3)" 6
rule="$2 $IPSET_EXCLUDE6 dst $IPBAN_EXCLUDE6 dst" rule="$2 $IPSET_EXCLUDE6 dst"
for i in $4 ; do for i in $4 ; do
_dnat6_target $i DNAT6 _dnat6_target $i DNAT6
[ -n "$DNAT6" -a "$DNAT6" != "-" ] && ipt6_add_del $1 PREROUTING -t nat -i $i $rule -j DNAT --to [$DNAT6]:$3 [ -n "$DNAT6" -a "$DNAT6" != "-" ] && ipt6_add_del $1 PREROUTING -t nat -i $i $rule -j DNAT --to [$DNAT6]:$3
@ -353,37 +349,27 @@ ipt_do_nfqws_in_out()
} }
} }
zapret_do_firewall_standard_tpws_rules_ipt() zapret_do_firewall_standard_rules_ipt()
{ {
# $1 - 1 - add, 0 - del # $1 - 1 - add, 0 - del
local f4 f6 local f4 f6
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] && { [ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] &&
{
f4="-p tcp -m multiport --dports $TPWS_PORTS_IPT" f4="-p tcp -m multiport --dports $TPWS_PORTS_IPT"
f6=$f4 f6=$f4
filter_apply_ipset_target f4 f6 filter_apply_ipset_target f4 f6
fw_tpws $1 "$f4" "$f6" $TPPORT fw_tpws $1 "$f4" "$f6" $TPPORT
} }
} [ "$NFQWS_ENABLE" = 1 ] &&
zapret_do_firewall_standard_nfqws_rules_ipt()
{ {
# $1 - 1 - add, 0 - del
[ "$NFQWS_ENABLE" = 1 ] && {
ipt_do_nfqws_in_out $1 tcp "$NFQWS_PORTS_TCP_IPT" "$NFQWS_TCP_PKT_OUT" "$NFQWS_TCP_PKT_IN" ipt_do_nfqws_in_out $1 tcp "$NFQWS_PORTS_TCP_IPT" "$NFQWS_TCP_PKT_OUT" "$NFQWS_TCP_PKT_IN"
ipt_do_nfqws_in_out $1 tcp "$NFQWS_PORTS_TCP_KEEPALIVE_IPT" keepalive "$NFQWS_TCP_PKT_IN" ipt_do_nfqws_in_out $1 tcp "$NFQWS_PORTS_TCP_KEEPALIVE_IPT" keepalive "$NFQWS_TCP_PKT_IN"
ipt_do_nfqws_in_out $1 udp "$NFQWS_PORTS_UDP_IPT" "$NFQWS_UDP_PKT_OUT" "$NFQWS_UDP_PKT_IN" ipt_do_nfqws_in_out $1 udp "$NFQWS_PORTS_UDP_IPT" "$NFQWS_UDP_PKT_OUT" "$NFQWS_UDP_PKT_IN"
ipt_do_nfqws_in_out $1 udp "$NFQWS_PORTS_UDP_KEEPALIVE_IPT" keepalive "$NFQWS_UDP_PKT_IN" ipt_do_nfqws_in_out $1 udp "$NFQWS_PORTS_UDP_KEEPALIVE_IPT" keepalive "$NFQWS_UDP_PKT_IN"
} }
} }
zapret_do_firewall_standard_rules_ipt()
{
# $1 - 1 - add, 0 - del
zapret_do_firewall_standard_tpws_rules_ipt $1
zapret_do_firewall_standard_nfqws_rules_ipt $1
}
zapret_do_firewall_rules_ipt() zapret_do_firewall_rules_ipt()
{ {
@ -391,27 +377,6 @@ zapret_do_firewall_rules_ipt()
zapret_do_firewall_standard_rules_ipt $1 zapret_do_firewall_standard_rules_ipt $1
custom_runner zapret_custom_firewall $1 custom_runner zapret_custom_firewall $1
zapret_do_icmp_filter $1
}
zapret_do_icmp_filter()
{
# $1 - 1 - add, 0 - del
local FW_EXTRA_PRE= FW_EXTRA_POST=
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
[ "$DISABLE_IPV4" = 1 ] || {
ipt_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
ipt_add_del $1 INPUT -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
ipt_add_del $1 FORWARD -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
}
[ "$DISABLE_IPV6" = 1 ] || {
ipt6_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
ipt6_add_del $1 INPUT -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
ipt6_add_del $1 FORWARD -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
}
}
} }
zapret_do_firewall_ipt() zapret_do_firewall_ipt()

View File

@ -1,55 +0,0 @@
standard_mode_tpws_socks()
{
# $1 - 1 - run, 0 - stop
local opt
[ "$TPWS_SOCKS_ENABLE" = 1 ] && {
opt="--port=$TPPORT_SOCKS $TPWS_SOCKS_OPT"
filter_apply_hostlist_target opt
do_tpws_socks $1 2 "$opt"
}
}
standard_mode_tpws()
{
# $1 - 1 - run, 0 - stop
local opt
[ "$TPWS_ENABLE" = 1 ] && check_bad_ws_options $1 "$TPWS_OPT" && {
opt="--port=$TPPORT $TPWS_OPT"
filter_apply_hostlist_target opt
do_tpws $1 1 "$opt"
}
}
standard_mode_nfqws()
{
# $1 - 1 - run, 0 - stop
local opt
[ "$NFQWS_ENABLE" = 1 ] && check_bad_ws_options $1 "$NFQWS_OPT" && {
opt="--qnum=$QNUM $NFQWS_OPT"
filter_apply_hostlist_target opt
do_nfqws $1 3 "$opt"
}
}
standard_mode_daemons()
{
# $1 - 1 - run, 0 - stop
standard_mode_tpws_socks $1
standard_mode_tpws $1
standard_mode_nfqws $1
}
zapret_do_daemons()
{
# $1 - 1 - run, 0 - stop
standard_mode_daemons $1
custom_runner zapret_custom_daemons $1
return 0
}
zapret_run_daemons()
{
zapret_do_daemons 1 "$@"
}
zapret_stop_daemons()
{
zapret_do_daemons 0 "$@"
}

View File

@ -4,8 +4,6 @@
# PREROUTING - can't DNAT to ::1. can DNAT to link local of -i interface or to any global addr # PREROUTING - can't DNAT to ::1. can DNAT to link local of -i interface or to any global addr
# not a good idea to expose tpws to the world (bind to ::) # not a good idea to expose tpws to the world (bind to ::)
# max wait time for the link local ipv6 on the LAN interface
LINKLOCAL_WAIT_SEC=${LINKLOCAL_WAIT_SEC:-5}
get_ipv6_linklocal() get_ipv6_linklocal()
{ {
@ -111,14 +109,6 @@ unprepare_route_localnet()
set_route_localnet 0 "$@" set_route_localnet 0 "$@"
} }
get_uevent_devtype()
{
local DEVTYPE INTERFACE IFINDEX OF_NAME OF_FULLNAME OF_COMPATIBLE_N
[ -f "/sys/class/net/$1/uevent" ] && {
. "/sys/class/net/$1/uevent"
echo -n $DEVTYPE
}
}
resolve_lower_devices() resolve_lower_devices()
{ {
# $1 - bridge interface name # $1 - bridge interface name

View File

@ -1,5 +1,5 @@
HOSTLIST_MARKER="<HOSTLIST>" readonly HOSTLIST_MARKER="<HOSTLIST>"
HOSTLIST_NOAUTO_MARKER="<HOSTLIST_NOAUTO>" readonly HOSTLIST_NOAUTO_MARKER="<HOSTLIST_NOAUTO>"
find_hostlists() find_hostlists()
{ {

View File

@ -1,5 +1,5 @@
[ -n "$ZAPRET_NFT_TABLE" ] || ZAPRET_NFT_TABLE=zapret [ -n "$ZAPRET_NFT_TABLE" ] || ZAPRET_NFT_TABLE=zapret
nft_connbytes="ct original packets" readonly nft_connbytes="ct original packets"
# required for : nft -f - # required for : nft -f -
create_dev_stdin create_dev_stdin
@ -106,7 +106,7 @@ cat << EOF | nft -f -
flush chain inet $ZAPRET_NFT_TABLE predefrag_nfqws flush chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
add rule inet $ZAPRET_NFT_TABLE predefrag mark and $DESYNC_MARK !=0 jump predefrag_nfqws comment "nfqws generated : avoid drop by INVALID conntrack state" add rule inet $ZAPRET_NFT_TABLE predefrag mark and $DESYNC_MARK !=0 jump predefrag_nfqws comment "nfqws generated : avoid drop by INVALID conntrack state"
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws mark and $DESYNC_MARK_POSTNAT !=0 notrack comment "postnat traffic" add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws mark and $DESYNC_MARK_POSTNAT !=0 notrack comment "postnat traffic"
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws ip frag-off & 0x1fff != 0 notrack comment "ipfrag" add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws ip frag-off != 0 notrack comment "ipfrag"
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws exthdr frag exists notrack comment "ipfrag" add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws exthdr frag exists notrack comment "ipfrag"
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws tcp flags ! syn,rst,ack notrack comment "datanoack" add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws tcp flags ! syn,rst,ack notrack comment "datanoack"
add set inet $ZAPRET_NFT_TABLE lanif { type ifname; } add set inet $ZAPRET_NFT_TABLE lanif { type ifname; }
@ -119,20 +119,6 @@ EOF
nft_flush_chain predefrag_nfqws nft_flush_chain predefrag_nfqws
nft_add_rule predefrag_nfqws notrack comment \"do not track nfqws generated packets to avoid nat tampering and defragmentation\" nft_add_rule predefrag_nfqws notrack comment \"do not track nfqws generated packets to avoid nat tampering and defragmentation\"
} }
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
if is_postnat; then
# can be caused by untracked nfqws-generated packets
nft_add_rule prerouting icmp type time-exceeded ct state invalid drop
else
nft_add_rule postrouting_hook mark and $DESYNC_MARK != 0 ct mark set ct mark or $DESYNC_MARK comment \"nfqws related : prevent ttl expired socket errors\"
fi
[ "$DISABLE_IPV4" = "1" ] || {
nft_add_rule prerouting icmp type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
}
[ "$DISABLE_IPV6" = "1" ] || {
nft_add_rule prerouting icmpv6 type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
}
}
} }
nft_del_chains() nft_del_chains()
{ {
@ -277,6 +263,28 @@ nft_add_flow_offload_exemption()
[ "$DISABLE_IPV6" = "1" -o -z "$2" ] || nft_add_rule flow_offload oifname @wanif6 $2 ip6 daddr != @nozapret6 return comment \"$3\" [ "$DISABLE_IPV6" = "1" -o -z "$2" ] || nft_add_rule flow_offload oifname @wanif6 $2 ip6 daddr != @nozapret6 return comment \"$3\"
} }
nft_hw_offload_supported()
{
# $1,$2,... - interface names
local devices res=1
make_quoted_comma_list devices "$@"
[ -n "$devices" ] && devices="devices={$devices};"
nft add table ${ZAPRET_NFT_TABLE}_test && nft add flowtable ${ZAPRET_NFT_TABLE}_test ft "{ flags offload; $devices }" 2>/dev/null && res=0
nft delete table ${ZAPRET_NFT_TABLE}_test 2>/dev/null
return $res
}
nft_hw_offload_find_supported()
{
# $1,$2,... - interface names
local supported_list
while [ -n "$1" ]; do
nft_hw_offload_supported "$1" && append_separator_list supported_list ' ' '' "$1"
shift
done
echo $supported_list
}
nft_apply_flow_offloading() nft_apply_flow_offloading()
{ {
# ft can be absent # ft can be absent
@ -334,7 +342,7 @@ nft_fill_ifsets()
# $5 - space separated wan physical interface names (optional) # $5 - space separated wan physical interface names (optional)
# $6 - space separated wan6 physical interface names (optional) # $6 - space separated wan6 physical interface names (optional)
local script i j ALLDEVS devs b local script i j ALLDEVS devs
# if large sets exist nft works very ineffectively # if large sets exist nft works very ineffectively
# looks like it analyzes the whole table blob to find required data pieces # looks like it analyzes the whole table blob to find required data pieces
@ -362,18 +370,17 @@ flush set inet $ZAPRET_NFT_TABLE lanif"
nft_create_or_update_flowtable 'offload' 2>/dev/null nft_create_or_update_flowtable 'offload' 2>/dev/null
# then add elements. some of them can cause error because unsupported # then add elements. some of them can cause error because unsupported
for i in $ALLDEVS; do for i in $ALLDEVS; do
if nft_hw_offload_supported $i; then
nft_create_or_update_flowtable 'offload' $i
else
# bridge members must be added instead of the bridge itself # bridge members must be added instead of the bridge itself
# some members may not support hw offload. example : lan1 lan2 lan3 support, wlan0 wlan1 - not # some members may not support hw offload. example : lan1 lan2 lan3 support, wlan0 wlan1 - not
b=
devs=$(resolve_lower_devices $i) devs=$(resolve_lower_devices $i)
for j in $devs; do for j in $devs; do
# do not display error if addition failed # do not display error if addition failed
nft_create_or_update_flowtable 'offload' $j && b=1 2>/dev/null nft_create_or_update_flowtable 'offload' $j 2>/dev/null
done done
[ -n "$b" ] || { fi
# no lower devices added ? try to add interface itself
nft_create_or_update_flowtable 'offload' $i 2>/dev/null
}
done done
;; ;;
esac esac
@ -404,8 +411,8 @@ _nft_fw_tpws4()
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || { [ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
local filter="$1" port="$2" local filter="$1" port="$2"
nft_print_op "$filter" "tpws (port $2)" 4 nft_print_op "$filter" "tpws (port $2)" 4
nft_insert_rule dnat_output skuid != $WS_USER ${3:+oifname @wanif }$filter ip daddr != @nozapret ip daddr != @ipban $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port nft_insert_rule dnat_output skuid != $WS_USER ${3:+oifname @wanif }$filter ip daddr != @nozapret $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
nft_insert_rule dnat_pre iifname @lanif $filter ip daddr != @nozapret ip daddr != @ipban $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port nft_insert_rule dnat_pre iifname @lanif $filter ip daddr != @nozapret $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
prepare_route_localnet prepare_route_localnet
} }
} }
@ -419,9 +426,9 @@ _nft_fw_tpws6()
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || { [ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
local filter="$1" port="$2" DNAT6 i local filter="$1" port="$2" DNAT6 i
nft_print_op "$filter" "tpws (port $port)" 6 nft_print_op "$filter" "tpws (port $port)" 6
nft_insert_rule dnat_output skuid != $WS_USER ${4:+oifname @wanif6 }$filter ip6 daddr != @nozapret6 ip6 daddr != @ipban6 $FW_EXTRA_POST dnat ip6 to [::1]:$port nft_insert_rule dnat_output skuid != $WS_USER ${4:+oifname @wanif6 }$filter ip6 daddr != @nozapret6 $FW_EXTRA_POST dnat ip6 to [::1]:$port
[ -n "$3" ] && { [ -n "$3" ] && {
nft_insert_rule dnat_pre $filter ip6 daddr != @nozapret6 ip6 daddr != @ipban6 $FW_EXTRA_POST dnat ip6 to iifname map @link_local:$port nft_insert_rule dnat_pre $filter ip6 daddr != @nozapret6 $FW_EXTRA_POST dnat ip6 to iifname map @link_local:$port
for i in $3; do for i in $3; do
_dnat6_target $i DNAT6 _dnat6_target $i DNAT6
# can be multiple tpws processes on different ports # can be multiple tpws processes on different ports
@ -470,7 +477,7 @@ _nft_fw_nfqws_post4()
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 4 nft_print_op "$filter" "nfqws postrouting (qnum $port)" 4
rule="${3:+oifname @wanif }$filter ip daddr != @nozapret" rule="${3:+oifname @wanif }$filter ip daddr != @nozapret"
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT" is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass nft_insert_rule $chain $rule $setmark $FW_EXTRA_POST queue num $port bypass
nft_add_nfqws_flow_exempt_rule "$rule" nft_add_nfqws_flow_exempt_rule "$rule"
} }
} }
@ -485,7 +492,7 @@ _nft_fw_nfqws_post6()
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 6 nft_print_op "$filter" "nfqws postrouting (qnum $port)" 6
rule="${3:+oifname @wanif6 }$filter ip6 daddr != @nozapret6" rule="${3:+oifname @wanif6 }$filter ip6 daddr != @nozapret6"
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT" is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass nft_insert_rule $chain $rule $setmark $FW_EXTRA_POST queue num $port bypass
nft_add_nfqws_flow_exempt_rule "$rule" nft_add_nfqws_flow_exempt_rule "$rule"
} }
} }
@ -509,7 +516,7 @@ _nft_fw_nfqws_pre4()
local filter="$1" port="$2" rule local filter="$1" port="$2" rule
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 4 nft_print_op "$filter" "nfqws prerouting (qnum $port)" 4
rule="${3:+iifname @wanif }$filter ip saddr != @nozapret" rule="${3:+iifname @wanif }$filter ip saddr != @nozapret"
nft_insert_rule $(get_prechain) $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass nft_insert_rule $(get_prechain) $rule $FW_EXTRA_POST queue num $port bypass
} }
} }
_nft_fw_nfqws_pre6() _nft_fw_nfqws_pre6()
@ -522,7 +529,7 @@ _nft_fw_nfqws_pre6()
local filter="$1" port="$2" rule local filter="$1" port="$2" rule
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 6 nft_print_op "$filter" "nfqws prerouting (qnum $port)" 6
rule="${3:+iifname @wanif6 }$filter ip6 saddr != @nozapret6" rule="${3:+iifname @wanif6 }$filter ip6 saddr != @nozapret6"
nft_insert_rule $(get_prechain) $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass nft_insert_rule $(get_prechain) $rule $FW_EXTRA_POST queue num $port bypass
} }
} }
nft_fw_nfqws_pre() nft_fw_nfqws_pre()
@ -633,31 +640,25 @@ nft_apply_nfqws_in_out()
} }
} }
zapret_apply_firewall_standard_tpws_rules_nft() zapret_apply_firewall_standard_rules_nft()
{ {
local f4 f6 local f4 f6
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] && { [ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] &&
{
f4="tcp dport {$TPWS_PORTS}" f4="tcp dport {$TPWS_PORTS}"
f6=$f4 f6=$f4
nft_filter_apply_ipset_target f4 f6 nft_filter_apply_ipset_target f4 f6
nft_fw_tpws "$f4" "$f6" $TPPORT nft_fw_tpws "$f4" "$f6" $TPPORT
} }
} [ "$NFQWS_ENABLE" = 1 ] &&
zapret_apply_firewall_standard_nfqws_rules_nft()
{ {
[ "$NFQWS_ENABLE" = 1 ] && {
nft_apply_nfqws_in_out tcp "$NFQWS_PORTS_TCP" "$NFQWS_TCP_PKT_OUT" "$NFQWS_TCP_PKT_IN" nft_apply_nfqws_in_out tcp "$NFQWS_PORTS_TCP" "$NFQWS_TCP_PKT_OUT" "$NFQWS_TCP_PKT_IN"
nft_apply_nfqws_in_out tcp "$NFQWS_PORTS_TCP_KEEPALIVE" keepalive "$NFQWS_TCP_PKT_IN" nft_apply_nfqws_in_out tcp "$NFQWS_PORTS_TCP_KEEPALIVE" keepalive "$NFQWS_TCP_PKT_IN"
nft_apply_nfqws_in_out udp "$NFQWS_PORTS_UDP" "$NFQWS_UDP_PKT_OUT" "$NFQWS_UDP_PKT_IN" nft_apply_nfqws_in_out udp "$NFQWS_PORTS_UDP" "$NFQWS_UDP_PKT_OUT" "$NFQWS_UDP_PKT_IN"
nft_apply_nfqws_in_out udp "$NFQWS_PORTS_UDP_KEEPALIVE" keepalive "$NFQWS_UDP_PKT_IN" nft_apply_nfqws_in_out udp "$NFQWS_PORTS_UDP_KEEPALIVE" keepalive "$NFQWS_UDP_PKT_IN"
} }
} }
zapret_apply_firewall_standard_rules_nft()
{
zapret_apply_firewall_standard_tpws_rules_nft
zapret_apply_firewall_standard_nfqws_rules_nft
}
zapret_apply_firewall_rules_nft() zapret_apply_firewall_rules_nft()
{ {
@ -700,7 +701,3 @@ zapret_do_firewall_nft()
return 0 return 0
} }
# ctmark is not available in POSTNAT mode
CONNMARKER=
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && is_postnat && CONNMARKER="ct mark set ct mark or $DESYNC_MARK"

View File

@ -97,7 +97,7 @@ NFQWS_OPT="
# none,ipset,hostlist,autohostlist # none,ipset,hostlist,autohostlist
MODE_FILTER=none MODE_FILTER=none
# donttouch,none,software,hardware # openwrt only : donttouch,none,software,hardware
FLOWOFFLOAD=donttouch FLOWOFFLOAD=donttouch
# openwrt: specify networks to be treated as LAN. default is "lan" # openwrt: specify networks to be treated as LAN. default is "lan"
@ -129,11 +129,6 @@ INIT_APPLY_FW=1
# do not work with ipv6 # do not work with ipv6
DISABLE_IPV6=1 DISABLE_IPV6=1
# drop icmp time exceeded messages for nfqws tampered connections
# in POSTNAT mode this can interfere with default mtr/traceroute in tcp or udp mode. use source port not redirected to nfqws
# set to 0 if you are not expecting connection breakage due to icmp in response to TCP SYN or UDP
FILTER_TTL_EXPIRED_ICMP=1
# select which init script will be used to get ip or host list # select which init script will be used to get ip or host list
# possible values : get_user.sh get_antizapret.sh get_combined.sh get_reestr.sh get_hostlist.sh # possible values : get_user.sh get_antizapret.sh get_combined.sh get_reestr.sh get_hostlist.sh
# comment if not required # comment if not required

View File

@ -407,93 +407,3 @@ nfqws,tpws: fixed ipsets and hostlists
all progs: version numbers for github, build date/time for self built all progs: version numbers for github, build date/time for self built
repo: light release for openwrt and embedded systems repo: light release for openwrt and embedded systems
repo: sha256sum repo: sha256sum
v69.4
nfqws: fakedsplit/fakeddisorder fakes for both split segments
nfqws: --dpi-desync-fakedsplit-pattern
v69.5
nfqws,tpws: --dry-run
install_easy: check tpws and nfqws options validity
v69.6
nfqws: set NETLINK_NO_ENOBUFS to fix possible nfq recv errors
init.d: unify custom scripts for linux
init.d: new custom scripts : 20-fw-extra, 50-wg4all
v69.7
nfqws,tpws: --comment
nfqws: trash flood warning
winws: exclude empty outgoing ack packets in windivert filter
v69.8
winws: accept empty outgoing RST and FIN packets for conntrack needs
repo: lexra build
v69.9
init.d: exclude ipban from tpws redirection
macos: fix install_easy
macos: fix national decimal separator in sleep
ipset: scripts maintenance
v70
blockcheck: override all dialog questions and enable batch mode
blockcheck: parallel attempts
nfqws: weaken wireguard initiation recognition. use len=148 and data[0]=1 signature
nfqws: apply split+seqovl only to the first reasm fragment
install_easy: dnf packager support
nfqws,tpws: hostlist/ipset track not only file mod time but also file size
nfqws,tpws,ipset: return lists reload on HUP
nfqws,blockcheck: --dpi-desync-fake-tls-mod
v70.1
nfqws: --dpi-desync-fake-tls-mod=dupsid
nfqws,tpws: test accessibility of list files after privs drop
nfqws,tpws: --version
v70.4
nfqws,tpws: ^ prefix in hostlist to disable subdomain matches
nfqws,tpws: optional systemd notify support. compile using 'make systemd'
nfqws,tpws: systemd instance templates for nfqws and tpws
nfqws,tpws: separate droproot from dropcaps
tpws: detect WSL 1 and warn about non-working options
v70.5
nfqws: multiple --dpi-desync-fake-xxx
nfqws: support of inter-packet fragmented QUIC CRYPTO
v70.6
nfqws: detect Discord Voice IP discovery packets
nfqws: detect STUN message packets
nfqws: change SNI to specified value tls mod : --dpi-desync-fake-tls-mod sni=<sni>
nfqws: update default TLS ClientHello fake. firefox 136.0.4 finger, no kyber, SNI=microsoft.com
nfqws: multiple mods for multiple TLS fakes
init.d: remove 50-discord
blockcheck: use tpws --fix-seg on linux for multiple splits
v71
nfqws,tpws: debug tls version, alpn, ech
nfqws: --dpi-desync-fake-tls=! means default tls fake
nfqws: --dup*
nfqws: --orig*
nfqws: ipcache of hop count and host names
nfqws: --ctrack-disable
nfqws: --synack-split
tpws: ipcache of host names
nfqws,tpws: set 1024 repeat limit to fakes and dups
nfqws,tpws: do more before daemonize
nfqws,tpws: accept multiple gids in --gid
init.d: remove --ipset parameter prohibition
init.d, blockcheck: drop time exceeded icmp for nfqws-related connections

View File

@ -12,10 +12,10 @@ Other packages may be required on your distribution. Look for the errors.
examples : 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 -Jxv 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 cd openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64
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 -xv 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 cd openwrt-sdk-x86-64_gcc-13.3.0_musl.Linux-x86_64
3) Install required libs 3) Install required libs
@ -48,7 +48,7 @@ static build : make CFLAGS=-static package/{tpws,nfqws,mdig,ip2net}/compile
executables only : build_dir/target/<progname> executables only : build_dir/target/<progname>
ipk or apk packages : bin/packages/*/base ipk or apk packages : bin/packages/*/base
8) Installing to openwrt to use with zapret 8) Installating to openwrt to use with zapret
zapret with or without binaries should be already installed in /opt/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. Install ipk's or apk's with all compiled progs using opkg or apk.

View File

@ -1,7 +1,7 @@
debian,ubuntu : debian,ubuntu :
apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libsystemd-dev apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev
make -C /opt/zapret systemd make -C /opt/zapret
FreeBSD : FreeBSD :

View File

@ -2,8 +2,8 @@
> [!CAUTION] > [!CAUTION]
> Не пишите в issue вопросы типа "как скопировать файл", "как скачать", "как > Не пишите в issue вопросы типа "как скопировать файл", "как скачать", "как
> запустить" и т.п. То есть все, что касается базовых навыков обращения с ОС > запустить", ... То есть все , что касается базовых навыков обращения с ОС
> Linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы > linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы
> возникают, рекомендую не использовать данный софт или искать помощь где-то в > возникают, рекомендую не использовать данный софт или искать помощь где-то в
> другом месте. То же самое могу сказать тем, кто хочет нажать 1 кнопку, чтобы > другом месте. То же самое могу сказать тем, кто хочет нажать 1 кнопку, чтобы
> все заработало, и совсем не хочет читать и изучать. Увы, такое не подвезли и > все заработало, и совсем не хочет читать и изучать. Увы, такое не подвезли и
@ -50,8 +50,6 @@
> образ `squashfs` с помощью `image builder` и перешить этим вариантом роутер. > образ `squashfs` с помощью `image builder` и перешить этим вариантом роутер.
1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив. 1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив.
Для openwrt и прошивок используйте вариант `openwrt-embedded`.
Для экономия места в /tmp можно качать через curl в stdout и сразу распаковывать.
2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и 2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и
сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`. сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`.
@ -89,8 +87,7 @@
> >
> Проверить работает ли этот вариант можно так: > Проверить работает ли этот вариант можно так:
> ```sh > ```sh
> $ dig -p 53 @77.88.8.88 rutracker.org > $ dig -p 53 @77.88.8.88 rutracker.org dig -p 1253 @77.88.8.88 rutracker.org
> $ dig -p 1253 @77.88.8.88 rutracker.org
> ``` > ```
> >
> Если DNS действительно подменяется, и ответ на эти 2 команды разный, > Если DNS действительно подменяется, и ответ на эти 2 команды разный,
@ -159,12 +156,12 @@
> >
> Далее, имея понимание что работает на http, https, quic нужно > Далее, имея понимание что работает на http, https, quic нужно
> сконструировать параметры запуска `tpws` и/или `nfqws` с использованием > сконструировать параметры запуска `tpws` и/или `nfqws` с использованием
> мультистратегии. Как работают мультистратегии описано в [readme.md](./readme.md#множественные-стратегии). > мультистратегии. Как работают мультистратегии описано в readme.txt.
> >
> Если кратко, то обычно параметры конструируются так: > Если кратко, то обычно параметры конструируются так:
> ```sh > ```sh
> "--filter-udp=443 'параметры для quic' <HOSTLIST_NOAUTO> --new > "--filter-udp=443 'параметры для quic' <HOSTLIST_NOAUTO> --new
> --filter-tcp=80,443 'объединенные параметры для http и https' <HOSTLIST>" > --filter-tcp=80,443 'обьединенные параметры для http и https' <HOSTLIST>"
> ``` > ```
> >
> Или так: > Или так:
@ -194,7 +191,7 @@
> "--filter-l3=ipv4 --filter-udp=443 lпараметры для quic ipv4' <HOSTLIST_NOAUTO> --new > "--filter-l3=ipv4 --filter-udp=443 lпараметры для quic ipv4' <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv4 --filter-tcp=80 'параметры для http ipv4' <HOSTLIST> --new > --filter-l3=ipv4 --filter-tcp=80 'параметры для http ipv4' <HOSTLIST> --new
> --filter-l3=ipv4 --filter-tcp=443 'параметры для https ipv4' <HOSTLIST> --new > --filter-l3=ipv4 --filter-tcp=443 'параметры для https ipv4' <HOSTLIST> --new
> --filter-l3=ipv6 --filter-udp=443 'параметры для quic ipv6' <HOSTLIST_NOAUTO> --new > --filter-l3=ipv6 --filter-udp=443 "параметры для quic ipv6" <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv6 --filter-tcp=80 'параметры для http ipv6' <HOSTLIST> --new > --filter-l3=ipv6 --filter-tcp=80 'параметры для http ipv6' <HOSTLIST> --new
> --filter-l3=ipv6 --filter-tcp=443 'параметры для https ipv6' <HOSTLIST>" > --filter-l3=ipv6 --filter-tcp=443 'параметры для https ipv6' <HOSTLIST>"
> ``` > ```

View File

@ -59,7 +59,7 @@ _"Совсем ничего не могу, все очень сложно, да
1) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip. 1) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.
2) Если у вас Windows 7 x64, однократно запустите `win7/install_win7.cmd`. Батник заменит файлы windivert на совместимую с Windows 7 версию. 2) Если у вас Windows 7 x64, читайте [docs/windows.md](./windows.md). Без описанной там подготовки может не работать.
> [!WARNING] > [!WARNING]
> Для 32-битных систем Windows нет готового полного варианта. > Для 32-битных систем Windows нет готового полного варианта.
@ -123,7 +123,7 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
> она стабильна, на третьих полный хаос, и проще отказаться. > она стабильна, на третьих полный хаос, и проще отказаться.
> >
> Далее, имея понимание что работает на http, https, quic, нужно сконструировать параметры запуска winws > Далее, имея понимание что работает на http, https, quic, нужно сконструировать параметры запуска winws
> с использованием мультистратегии. Как работают мультистратегии описано в [readme.md](./readme.md#множественные-стратегии). > с использованием мультистратегии. Как работают мультистратегии описано в [readme.md](./readme.md).
> >
> Прежде всего вам нужно собрать фильтр перехватываемого трафика. Это делается через параметры > Прежде всего вам нужно собрать фильтр перехватываемого трафика. Это делается через параметры
> `--wf-l3`, `--wf-tcp`, `--wf-udp`. > `--wf-l3`, `--wf-tcp`, `--wf-udp`.

View File

@ -1,4 +1,4 @@
# zapret v70.7 # zapret v69.3
# SCAMMER WARNING # SCAMMER WARNING
@ -19,7 +19,6 @@ ___
- [nfqws](#nfqws) - [nfqws](#nfqws)
- [DPI desync attack](#dpi-desync-attack) - [DPI desync attack](#dpi-desync-attack)
- [Fakes](#fakes) - [Fakes](#fakes)
- [Fake mods](#fake-mods)
- [TCP segmentation](#tcp-segmentation) - [TCP segmentation](#tcp-segmentation)
- [Sequence numbers overlap](#sequence-numbers-overlap) - [Sequence numbers overlap](#sequence-numbers-overlap)
- [ipv6 specific modes](#ipv6-specific-modes) - [ipv6 specific modes](#ipv6-specific-modes)
@ -120,7 +119,7 @@ You need to run them with the necessary parameters and redirect certain traffic
when blocked domains are queried. If this is the case change DNS to public ones, such as 8.8.8.8 or 1.1.1.1.Sometimes ISP hijacks queries to any DNS server. Dnscrypt or dns-over-tls help. when blocked domains are queried. If this is the case change DNS to public ones, such as 8.8.8.8 or 1.1.1.1.Sometimes ISP hijacks queries to any DNS server. Dnscrypt or dns-over-tls help.
* If blocking is done by IP. * If blocking is done by IP.
* If a connection passes through a filter capable of reconstructing a TCP connection, and which * If a connection passes through a filter capable of reconstructing a TCP connection, and which
follows all standards. For example, we are routed to squid. Connection goes through the full OS tcpip stack. This project targets DPI only, not full OS stack and not server applications. follows all standards. For example, we are routed to squid. Connection goes through the full OS tcpip stack, fragmentation disappears immediately as a means of circumvention. Squid is correct, it will find everything as it should, it is useless to deceive him. BUT. Only small providers can afford using squid, since it is very resource intensive. Large companies usually use DPI, which is designed for much greater bandwidth.
## nfqws ## nfqws
@ -132,9 +131,6 @@ nfqws takes the following parameters:
@<config_file> ; read file for options. must be the only argument. other options are ignored. @<config_file> ; read file for options. must be the only argument. other options are ignored.
--debug=0|1 --debug=0|1
--dry-run ; verify parameters and exit with code 0 if successful
--version ; print version and exit
--comment ; any text (ignored)
--qnum=<nfqueue_number> --qnum=<nfqueue_number>
--daemon ; daemonize --daemon ; daemonize
--pidfile=<filename> ; write pid to file --pidfile=<filename> ; write pid to file
@ -166,30 +162,26 @@ nfqws takes the following parameters:
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise ; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment --dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap --dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder
--dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8. --dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8.
--dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32. --dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32.
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000 --dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000
--dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000 --dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet --dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
--dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request --dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request
--dpi-desync-fake-tls=<filename>|0xHEX|! ; file containing fake TLS ClientHello (for https). '!' = standard fake --dpi-desync-fake-tls=<filename>|0xHEX ; file containing fake TLS ClientHello (for https)
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload --dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload --dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload
--dpi-desync-fake-quic=<filename>|0xHEX ; file containing fake QUIC Initial --dpi-desync-fake-quic=<filename>|0xHEX ; file containing fake QUIC Initial
--dpi-desync-fake-wireguard=<filename>|0xHEX ; file containing fake wireguard handshake initiation --dpi-desync-fake-wireguard=<filename>|0xHEX ; file containing fake wireguard handshake initiation
--dpi-desync-fake-dht=<filename>|0xHEX ; file containing fake DHT (d1..e) --dpi-desync-fake-dht=<filename>|0xHEX ; file containing fake DHT (d1..e)
--dpi-desync-fake-discord=<filename>|0xHEX ; file containing fake Discord voice connection initiation packet (IP Discovery)
--dpi-desync-fake-stun=<filename>|0xHEX ; file containing fake STUN message
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; file containing unknown udp protocol fake payload --dpi-desync-fake-unknown-udp=<filename>|0xHEX ; file containing unknown udp protocol fake payload
--dpi-desync-udplen-increment=<int> ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length. --dpi-desync-udplen-increment=<int> ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length.
--dpi-desync-udplen-pattern=<filename>|0xHEX ; udp tail fill pattern --dpi-desync-udplen-pattern=<filename>|0xHEX ; udp tail fill pattern
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N --dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N --dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed) --hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-domains=<domain_list> ; comma separated fixed domain list --hostlist-domains=<domain_list> ; comma separated fixed domain list
--hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed) --hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list --hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically --hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3) --hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
@ -201,7 +193,7 @@ nfqws takes the following parameters:
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed. --filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list supported. --filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list supported.
--filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported. --filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported.
--filter-l7=<proto> ; L6-L7 protocol filter. multiple comma separated values allowed. proto: http tls quic wireguard dht discord stun unknown --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed) --ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-ip=<ip_list> ; comma separated fixed subnet list --ipset-ip=<ip_list> ; comma separated fixed subnet list
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed) --ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
@ -221,9 +213,7 @@ There're attacks based on TCP sequence numbers. Methods can be combined in many
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. 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. It typically works only on Linux servers. MD5 tcp option requires additional space in TCP header * **md5sig** does not work on all servers
and can cause MTU overflow during fakedsplit/fakeddisorder on low positions when multisegment query (TLS kyber) is transmitted.
`nfqws` cannot redistribute data between original TCP segments. The error displayed is 'message too long'.
* **badsum** doesn't work if your device is behind NAT which does not pass invalid packets. * **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 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 The default sysctl configuration `net.netfilter.nf_conntrack_checksum=1` causes contrack to verify tcp and udp checksums
@ -268,43 +258,12 @@ Fakes are separate generated by nfqws packets carrying false information for DPI
`--dpi-desync-fooling` takes multiple comma separated values. `--dpi-desync-fooling` takes multiple comma separated values.
Multiple parameters `--dpi-desync-fake-???` are supported except for the `--dpi-desync-fake-syndata`.
Fakes are sent in the specified order. `--dpi-desync-repeats` resends each fake.
Resulting order would be : `fake1 fake1 fake1 fake2 fake2 fake2 fake3 fake3 fake3 .....`
### FAKE mods
**nfqws** has built-in TLS fake. It can be customized with `--dpi-desync-fake-tls` option.
Customized fake data can be anything - valid TLS Client Hello or arbitrary data.
It's possible to use TLS Client Hello with any fingerprint and any SNI.
**nfqws** can do some modifications of valid TLS Client Hello fakes in runtime with `--dpi-desync-fake-tls-mod` option.
* `none`. Do not do any mods.
* `rnd`. Randomize `random` and `session id` fields. Applied on every request.
* `rndsni`. Randomize SNI. If SNI >=7 symbols random SLD is applied with known TLD. Otherwise filled with random symbols. Applied only once at startup.
* `dupsid`. Copy `session ID` from original TLS Client Hello. Takes precedence over `rnd`. Applied on every request.
* `sni=<sni>`. Set specified SNI value. Changes TLS fake length, fixes lengths in TLS structure. Applied once at startup before `rndsni`.
* `padencap`. Padding extension is extended by original TLS Client Hello size (including multi packet variation with kyber). Padding extension is added to the end if not present, otherwise it must be the last extension. All lengths are increased. Fake size is not changed. Can be useful if DPI does not analyze sequence numbers properly. Applied on every request.
By default if custom fake is not defined `rnd,rndsni,dupsid` mods are applied. If defined - `none`.
This behaviour is compatible with previous versions with addition of `dupsid`.
If multiple TLS fakes are present each one takes the last mod.
If a mod is specified after fake it replaces previous mod.
This way it's possible to use different mods for every TLS fake.
If a mod is set to non-TLS fake it causes error. Use `--dpi-desync-fake-tls-mod=none'.
Example : `--dpi-desync-fake-tls=iana_org.bin --dpi-desync-fake-tls-mod=rndsni --dpi-desync-fake-tls=0xaabbccdd --dpi-desync-fake-tls-mod=none'
### TCP segmentation ### TCP segmentation
* `multisplit`. split request at specified in `--dpi-desync-split-pos` positions * `multisplit`. split request at specified in `--dpi-desync-split-pos` positions
* `multidisorder`. same as `multisplit` but send in reverse order * `multidisorder`. same as `multisplit` but send in reverse order
* `fakedsplit`. split request into 2 segments adding fakes in the middle of them : fake 1st segment, 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment * `fakedsplit`. 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 : fake 2nd segment, 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment * `fakeddisorder`. same as `fakedsplit` but with another order : 2nd segment, fake 1st segment, 1st segment, fake 1st segment
Positions are defined by markers. Positions are defined by markers.
@ -481,7 +440,7 @@ This option can resist DPIs that track outgoing UDP packet sizes.
Requires that application protocol does not depend on udp payload size. Requires that application protocol does not depend on udp payload size.
QUIC initial packets are recognized. Decryption and hostname extraction is supported so `--hostlist` parameter will work. QUIC initial packets are recognized. Decryption and hostname extraction is supported so `--hostlist` parameter will work.
Wireguard handshake initiation, DHT, STUN and [Discord Voice IP Discovery](https://discord.com/developers/docs/topics/voice-connections#ip-discovery) packets are also recognized. Wireguard handshake initiation and DHT packets are also recognized.
For other protocols desync use `--dpi-desync-any-protocol`. For other protocols desync use `--dpi-desync-any-protocol`.
Conntrack supports udp. `--dpi-desync-cutoff` will work. UDP conntrack timeout can be set in the 4th parameter of `--ctrack-timeouts`. Conntrack supports udp. `--dpi-desync-cutoff` will work. UDP conntrack timeout can be set in the 4th parameter of `--ctrack-timeouts`.
@ -679,8 +638,6 @@ tpws is transparent proxy.
--debug=0|1|2|syslog|@<filename> ; 1 and 2 means log to console and set debug level. for other targets use --debug-level. --debug=0|1|2|syslog|@<filename> ; 1 and 2 means log to console and set debug level. for other targets use --debug-level.
--debug-level=0|1|2 ; specify debug level for syslog and @<filename> --debug-level=0|1|2 ; specify debug level for syslog and @<filename>
--dry-run ; verify parameters and exit with code 0 if successful
--version ; print version and exit
--bind-addr=<v4_addr>|<v6_addr> ; for v6 link locals append %interface_name : fe80::1%br-lan --bind-addr=<v4_addr>|<v6_addr> ; for v6 link locals append %interface_name : fe80::1%br-lan
--bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface --bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface
--bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface --bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface
@ -722,9 +679,9 @@ tpws is transparent proxy.
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed) --ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list --ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply if not prefixed with '^', gzip supported, multiple hostlists allowed) --hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-domains=<domain_list> ; comma separated fixed domain list --hostlist-domains=<domain_list> ; comma separated fixed domain list
--hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply if not prefixed with '^', gzip supported, multiple hostlists allowed) --hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list --hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically --hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3) --hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
@ -1003,10 +960,8 @@ 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. 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" . Subdomains auto apply. For example, "ru" in the list affects "*.ru" .
`^` prefix symbol disables subdomain match.
**tpws** and **nfqws** automatically reload lists if their modification time or file size is changed. **tpws** and **nfqws** automatically reload lists if their modification date is changed.
HUP signal forcibly reloads all lists.
When filtering by domain name, daemons should run without filtering by ipset. 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 ! When using large regulator lists estimate the amount of RAM on the router !
@ -1451,8 +1406,12 @@ If this is the case then run another script in background and add some delay the
Are welcome here : Are welcome here :
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E` <img src=https://cdn-icons-png.flaticon.com/16/14446/14446252.png alt="USDT" style="vertical-align: middle;"/> USDT
```
0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E
```
BTC `bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve` <img src=https://cdn-icons-png.flaticon.com/16/5968/5968260.png alt="USDT" style="vertical-align: middle;"/> BTC
```
ETH `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E` bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve
```

File diff suppressed because it is too large Load Diff

View File

@ -101,11 +101,10 @@ There are several options :
Replace these 2 files in every location they are present. Replace these 2 files in every location they are present.
In `zapret-win-bundle` they are in `zapret-winws` и `blockcheck/zapret/nfq` folders. In `zapret-win-bundle` they are in `zapret-winws` и `blockcheck/zapret/nfq` folders.
However this option still requires 10+ year old patch that enables SHA256 signatures. However this option still requires 10+ year old patch that enables SHA256 signatures.
If you're using win bundle you can simply run `win7\install_win7.cmd`
3. [Hack ESU](https://hackandpwn.com/windows-7-esu-patching) 2. [Hack ESU](https://hackandpwn.com/windows-7-esu-patching)
4. Use `UpdatePack7R2` from simplix : https://blog.simplix.info 3. Use `UpdatePack7R2` from simplix : https://blog.simplix.info
If you are in Russia or Belarus temporary change region in Control Panel. If you are in Russia or Belarus temporary change region in Control Panel.
### blockcheck ### blockcheck

View File

@ -159,7 +159,6 @@ _windivert 2.2.2-A_, который идет в поставке zapret.
и заменить эти 2 файла. и заменить эти 2 файла.
В [zapret-win-bundle](https://github.com/bol-van/zapret-win-bundle) есть отдельных 2 места, где находится **winws** : [_zapret-winws_](https://github.com/bol-van/zapret-win-bundle/tree/master/zapret-winws) и [_blockcheck/zapret/nfq_](https://github.com/bol-van/zapret-win-bundle/tree/master/blockcheck). В [zapret-win-bundle](https://github.com/bol-van/zapret-win-bundle) есть отдельных 2 места, где находится **winws** : [_zapret-winws_](https://github.com/bol-van/zapret-win-bundle/tree/master/zapret-winws) и [_blockcheck/zapret/nfq_](https://github.com/bol-van/zapret-win-bundle/tree/master/blockcheck).
Надо менять в обоих местах. Надо менять в обоих местах.
Альтернативный вариант при использовании win bundle - запустить `win7\install_win7.cmd`
> [!NOTE] > [!NOTE]
> Этот вариант проверен и должен работать. Тем не менее патч 10 летней давности, который включает SHA256 сигнатуры, все еще необходим. > Этот вариант проверен и должен работать. Тем не менее патч 10 летней давности, который включает SHA256 сигнатуры, все еще необходим.

Binary file not shown.

View File

@ -1,66 +0,0 @@
# this custom script runs standard mode with extra firewall rules
# config: use TPWS_ENABLE_OVERRIDE, NFQWS_ENABLE_OVERRIDE to enable standard mode daemons
# standard and override switches cannot be enabled simultaneously !
TPWS_ENABLE_OVERRIDE=${TPWS_ENABLE_OVERRIDE:-0}
NFQWS_ENABLE_OVERRIDE=${NFQWS_ENABLE_OVERRIDE:-0}
# config: some if these values must be set in config. not setting any of these makes this script meaningless.
# pre vars put ipt/nft code to the rule beginning
#FW_EXTRA_PRE_TPWS_IPT=
#FW_EXTRA_PRE_TPWS_NFT=
#FW_EXTRA_PRE_NFQWS_IPT="-m mark --mark 0x10000000/0x10000000"
#FW_EXTRA_PRE_NFQWS_NFT="mark and 0x10000000 != 0"
# post vars put ipt/nft code to the rule end
#FW_EXTRA_POST_TPWS_IPT=
#FW_EXTRA_POST_TPWS_NFT=
#FW_EXTRA_POST_NFQWS_IPT=
#FW_EXTRA_POST_NFQWS_NFT=
check_std_intersect()
{
[ "$TPWS_ENABLE_OVERRIDE" = 1 -a "$TPWS_ENABLE" = 1 ] && {
echo "ERROR ! both TPWS_ENABLE_OVERRIDE and TPWS_ENABLE are enabled"
return 1
}
[ "$NFQWS_ENABLE_OVERRIDE" = 1 -a "$NFQWS_ENABLE" = 1 ] && {
echo "ERROR ! both NFQWS_ENABLE_OVERRIDE and NFQWS_ENABLE are enabled"
return 1
}
return 0
}
zapret_custom_daemons()
{
# $1 - 1 - add, 0 - stop
check_std_intersect || return
local TPWS_SOCKS_ENABLE=0 TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE
standard_mode_daemons "$1"
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
check_std_intersect || return
local FW_EXTRA_PRE FW_EXTRA_POST TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE
FW_EXTRA_PRE="$FW_EXTRA_PRE_TPWS_IPT" FW_EXTRA_POST="$FW_EXTRA_POST_TPWS_IPT"
zapret_do_firewall_standard_tpws_rules_ipt $1
FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS_IPT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS_IPT"
zapret_do_firewall_standard_nfqws_rules_ipt $1
}
zapret_custom_firewall_nft()
{
# stop logic is not required
check_std_intersect || return
local FW_EXTRA_PRE FW_EXTRA_POST TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE
FW_EXTRA_PRE="$FW_EXTRA_PRE_TPWS_NFT" FW_EXTRA_POST="$FW_EXTRA_POST_TPWS_NFT"
zapret_apply_firewall_standard_tpws_rules_nft
FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS_NFT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS_NFT"
zapret_apply_firewall_standard_nfqws_rules_nft
}

View File

@ -1,144 +0,0 @@
# this custom script demonstrates how to launch extra nfqws instance limited by ipset
# can override in config :
NFQWS_MY1_OPT="${NFQWS_MY1_OPT:---filter-udp=* --dpi-desync=fake --dpi-desync-repeats=6 --dpi-desync-any-protocol --new --filter-tcp=* --dpi-desync=multisplit}"
NFQWS_MY1_SUBNETS4="${NFQWS_MY1_SUBNETS4:-173.194.0.0/16 108.177.0.0/17 74.125.0.0/16 64.233.160.0/19 172.217.0.0/16}"
NFQWS_MY1_SUBNETS6="${NFQWS_MY1_SUBNETS6:-2a00:1450::/29}"
NFQWS_MY1_PORTS_TCP=${NFQWS_MY1_PORTS_TCP:-$NFQWS_PORTS_TCP}
NFQWS_MY1_PORTS_UDP=${NFQWS_MY1_PORTS_UDP:-$NFQWS_PORTS_UDP}
NFQWS_MY1_TCP_PKT_OUT=${NFQWS_MY1_TCP_PKT_OUT:-$NFQWS_TCP_PKT_OUT}
NFQWS_MY1_UDP_PKT_OUT=${NFQWS_MY1_UDP_PKT_OUT:-$NFQWS_UDP_PKT_OUT}
NFQWS_MY1_TCP_PKT_IN=${NFQWS_MY1_TCP_PKT_IN:-$NFQWS_TCP_PKT_IN}
NFQWS_MY1_UDP_PKT_IN=${NFQWS_MY1_UDP_PKT_IN:-$NFQWS_UDP_PKT_IN}
NFQWS_MY1_IPSET_SIZE=${NFQWS_MY1_IPSET_SIZE:-4096}
NFQWS_MY1_IPSET_OPT="${NFQWS_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS_MY1_IPSET_SIZE}"
alloc_dnum DNUM_NFQWS_MY1
alloc_qnum QNUM_NFQWS_MY1
NFQWS_MY1_NAME4=my1nfqws4
NFQWS_MY1_NAME6=my1nfqws6
zapret_custom_daemons()
{
# $1 - 1 - run, 0 - stop
local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_MY1_OPT"
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local f4 f6 subnet
local NFQWS_MY1_PORTS_TCP=$(replace_char - : $NFQWS_MY1_PORTS_TCP)
local NFQWS_MY1_PORTS_UDP=$(replace_char - : $NFQWS_MY1_PORTS_UDP)
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
ipset create $NFQWS_MY1_NAME4 $NFQWS_MY1_IPSET_OPT family inet 2>/dev/null
ipset flush $NFQWS_MY1_NAME4
for subnet in $NFQWS_MY1_SUBNETS4; do
echo add $NFQWS_MY1_NAME4 $subnet
done | ipset -! restore
}
[ "$1" = 1 -a "$DISABLE_IPV6" != 1 ] && {
ipset create $NFQWS_MY1_NAME6 $NFQWS_MY1_IPSET_OPT family inet6 2>/dev/null
ipset flush $NFQWS_MY1_NAME6
for subnet in $NFQWS_MY1_SUBNETS6; do
echo add $NFQWS_MY1_NAME6 $subnet
done | ipset -! restore
}
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
f4="-p tcp -m multiport --dports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_OUT -m set --match-set"
f6="$f4 $NFQWS_MY1_NAME6 dst"
f4="$f4 $NFQWS_MY1_NAME4 dst"
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
f4="-p tcp -m multiport --sports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_IN -m set --match-set"
f6="$f4 $NFQWS_MY1_NAME6 src"
f4="$f4 $NFQWS_MY1_NAME4 src"
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
}
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
f4="-p udp -m multiport --dports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_OUT -m set --match-set"
f6="$f4 $NFQWS_MY1_NAME6 dst"
f4="$f4 $NFQWS_MY1_NAME4 dst"
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
f4="-p udp -m multiport --sports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_IN -m set --match-set"
f6="$f4 $NFQWS_MY1_NAME6 src"
f4="$f4 $NFQWS_MY1_NAME4 src"
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
}
[ "$1" = 1 ] || {
ipset destroy $NFQWS_MY1_NAME4 2>/dev/null
ipset destroy $NFQWS_MY1_NAME6 2>/dev/null
}
}
zapret_custom_firewall_nft()
{
local f4 f6 subnets
local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT"
[ "$DISABLE_IPV4" != 1 ] && {
make_comma_list subnets $NFQWS_MY1_SUBNETS4
nft_create_set $NFQWS_MY1_NAME4 "type ipv4_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
nft_flush_set $NFQWS_MY1_NAME4
nft_add_set_element $NFQWS_MY1_NAME4 "$subnets"
}
[ "$DISABLE_IPV6" != 1 ] && {
make_comma_list subnets $NFQWS_MY1_SUBNETS6
nft_create_set $NFQWS_MY1_NAME6 "type ipv6_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
nft_flush_set $NFQWS_MY1_NAME6
nft_add_set_element $NFQWS_MY1_NAME6 "$subnets"
}
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
f4="tcp dport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_OUT)"
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
f4="tcp sport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_IN)"
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
}
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
f4="udp dport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_OUT)"
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
f4="udp sport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_IN)"
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
}
}
}
zapret_custom_firewall_nft_flush()
{
# this function is called after all nft fw rules are deleted
# however sets are not deleted. it's desired to clear sets here.
nft_del_set $NFQWS_MY1_NAME4 2>/dev/null
nft_del_set $NFQWS_MY1_NAME6 2>/dev/null
}

View File

@ -1,88 +0,0 @@
# this custom script demonstrates how to launch extra tpws instance limited by ipset
# can override in config :
TPWS_MY1_OPT="${TPWS_MY1_OPT:---oob --split-pos=midsld}"
TPWS_MY1_PORTS=${TPWS_MY1_PORTS:-$TPWS_PORTS}
TPWS_MY1_SUBNETS4="${TPWS_MY1_SUBNETS4:-142.250.0.0/15 64.233.160.0/19 172.217.0.0/16 173.194.0.0/16 108.177.0.0/17 74.125.0.0/16 209.85.128.0/17 216.58.192.0/19}"
TPWS_MY1_SUBNETS6="${TPWS_MY1_SUBNETS6:-2607:F8B0::/32 2a00:1450:4000::/37}"
TPWS_MY1_IPSET_SIZE=${TPWS_MY1_IPSET_SIZE:-4096}
TPWS_MY1_IPSET_OPT="${TPWS_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $TPWS_MY1_IPSET_SIZE}"
alloc_dnum DNUM_TPWS_MY1
alloc_tpws_port PORT_TPWS_MY1
TPWS_MY1_NAME4=my1tpws4
TPWS_MY1_NAME6=my1tpws6
zapret_custom_daemons()
{
# $1 - 1 - run, 0 - stop
local opt="--port=$PORT_TPWS_MY1 $TPWS_MY1_OPT"
do_tpws $1 $DNUM_TPWS_MY1 "$opt"
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local f4 f6 subnet
local PORTS_IPT=$(replace_char - : $TPWS_MY1_PORTS)
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
ipset create $TPWS_MY1_NAME4 $TPWS_MY1_IPSET_OPT family inet 2>/dev/null
ipset flush $TPWS_MY1_NAME4
for subnet in $TPWS_MY1_SUBNETS4; do
echo add $TPWS_MY1_NAME4 $subnet
done | ipset -! restore
}
[ "$1" = 1 -a "$DISABLE_IPV6" != 1 ] && {
ipset create $TPWS_MY1_NAME6 $TPWS_MY1_IPSET_OPT family inet6 2>/dev/null
ipset flush $TPWS_MY1_NAME6
for subnet in $TPWS_MY1_SUBNETS6; do
echo add $TPWS_MY1_NAME6 $subnet
done | ipset -! restore
}
f4="-p tcp -m multiport --dports $PORTS_IPT -m set --match-set"
f6="$f4 $TPWS_MY1_NAME6 dst"
f4="$f4 $TPWS_MY1_NAME4 dst"
fw_tpws $1 "$f4" "$f6" $PORT_TPWS_MY1
[ "$1" = 1 ] || {
ipset destroy $TPWS_MY1_NAME4 2>/dev/null
ipset destroy $TPWS_MY1_NAME6 2>/dev/null
}
}
zapret_custom_firewall_nft()
{
local f4 f6 subnets
[ "$DISABLE_IPV4" != 1 ] && {
make_comma_list subnets $TPWS_MY1_SUBNETS4
nft_create_set $TPWS_MY1_NAME4 "type ipv4_addr; size $TPWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
nft_flush_set $TPWS_MY1_NAME4
nft_add_set_element $TPWS_MY1_NAME4 "$subnets"
}
[ "$DISABLE_IPV6" != 1 ] && {
make_comma_list subnets $TPWS_MY1_SUBNETS6
nft_create_set $TPWS_MY1_NAME6 "type ipv6_addr; size $TPWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
nft_flush_set $TPWS_MY1_NAME6
nft_add_set_element $TPWS_MY1_NAME6 "$subnets"
}
f4="tcp dport {$TPWS_MY1_PORTS}"
f6="$f4 ip6 daddr @$TPWS_MY1_NAME6"
f4="$f4 ip daddr @$TPWS_MY1_NAME4"
nft_fw_tpws "$f4" "$f6" $PORT_TPWS_MY1
}
zapret_custom_firewall_nft_flush()
{
# this function is called after all nft fw rules are deleted
# however sets are not deleted. it's desired to clear sets here.
nft_del_set $TPWS_MY1_NAME4 2>/dev/null
nft_del_set $TPWS_MY1_NAME6 2>/dev/null
}

View File

@ -1,30 +0,0 @@
# this custom script runs desync to all wireguard handshake initiation packets
# can override in config :
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---dpi-desync=fake}"
alloc_dnum DNUM_WG4ALL
alloc_qnum QNUM_WG4ALL
zapret_custom_daemons()
{
# $1 - 1 - add, 0 - stop
local opt="--qnum=$QNUM_WG4ALL $NFQWS_OPT_DESYNC_WG"
do_nfqws $1 $DNUM_WG4ALL "$opt"
}
# size = 156 (8 udp header + 148 payload) && payload starts with 0x01000000
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local f='-p udp -m u32 --u32'
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x9c&&0>>22&0x3C@8=0x01000000" "$f 44>>16=0x9c&&48=0x01000000" $QNUM_WG4ALL
}
zapret_custom_firewall_nft()
{
# stop logic is not required
local f="udp length 156 @th,64,32 0x01000000"
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
}

View File

@ -0,0 +1,38 @@
# this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering
# can override in config :
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---dpi-desync=tamper}"
alloc_dnum DNUM_DHT4ALL
alloc_qnum QNUM_DHT4ALL
zapret_custom_daemons()
{
# stop logic is managed by procd
local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_DHT"
run_daemon $DNUM_DHT4ALL $NFQWS "$opt"
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local f uf4 uf6
local first_packet_only="$ipt_connbytes 1:1"
f='-p udp -m length --length 109:407 -m u32 --u32'
uf4='0>>22&0x3C@8>>16=0x6431'
uf6='48>>16=0x6431'
fw_nfqws_post $1 "$f $uf4 $first_packet_only" "$f $uf6 $first_packet_only" $QNUM_DHT4ALL
}
zapret_custom_firewall_nft()
{
# stop logic is not required
local f
local first_packet_only="$nft_connbytes 1"
f="meta length 109-407 meta l4proto udp @th,64,16 0x6431"
nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL
}

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,6 @@ ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
. "$ZAPRET_BASE/common/ipt.sh" . "$ZAPRET_BASE/common/ipt.sh"
. "$ZAPRET_BASE/common/nft.sh" . "$ZAPRET_BASE/common/nft.sh"
. "$ZAPRET_BASE/common/linux_fw.sh" . "$ZAPRET_BASE/common/linux_fw.sh"
. "$ZAPRET_BASE/common/linux_daemons.sh"
. "$ZAPRET_BASE/common/list.sh" . "$ZAPRET_BASE/common/list.sh"
. "$ZAPRET_BASE/common/custom.sh" . "$ZAPRET_BASE/common/custom.sh"
CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt" CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt"
@ -25,8 +24,15 @@ CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt"
TPWS_LOCALHOST4=127.0.0.127 TPWS_LOCALHOST4=127.0.0.127
# max wait time for the link local ipv6 on the LAN interface
LINKLOCAL_WAIT_SEC=5
IPSET_CR="$ZAPRET_BASE/ipset/create_ipset.sh" IPSET_CR="$ZAPRET_BASE/ipset/create_ipset.sh"
IPSET_EXCLUDE="-m set ! --match-set nozapret"
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
# can be multiple ipv6 outgoing interfaces # can be multiple ipv6 outgoing interfaces
# uplink from isp, tunnelbroker, vpn, ... # uplink from isp, tunnelbroker, vpn, ...
# want them all. who knows what's the real one that blocks sites # want them all. who knows what's the real one that blocks sites

View File

@ -81,10 +81,6 @@ run_tpws()
} }
run_daemon $1 "$TPWS" "$OPT $2" run_daemon $1 "$TPWS" "$OPT $2"
} }
do_tpws()
{
[ "$1" = 0 ] || { shift; run_tpws "$@"; }
}
run_tpws_socks() run_tpws_socks()
{ {
[ "$DISABLE_IPV4" = "1" ] && [ "$DISABLE_IPV6" = "1" ] && return 0 [ "$DISABLE_IPV4" = "1" ] && [ "$DISABLE_IPV6" = "1" ] && return 0
@ -94,10 +90,13 @@ run_tpws_socks()
tpws_apply_socks_binds opt tpws_apply_socks_binds opt
run_daemon $1 "$TPWS" "$opt $2" run_daemon $1 "$TPWS" "$opt $2"
} }
do_tpws_socks()
stop_tpws()
{ {
[ "$1" = 0 ] || { shift; run_tpws_socks "$@"; } stop_daemon $1 "$TPWS"
} }
tpws_apply_socks_binds() tpws_apply_socks_binds()
{ {
local o local o
@ -114,19 +113,31 @@ tpws_apply_socks_binds()
eval $1="\"\$$1 $o\"" eval $1="\"\$$1 $o\""
} }
run_nfqws()
standard_mode_daemons()
{ {
run_daemon $1 "$NFQWS" "$NFQWS_OPT_BASE $2" local opt
[ "$TPWS_ENABLE" = 1 ] && check_bad_ws_options 1 "$TPWS_OPT" && {
opt="--port=$TPPORT $TPWS_OPT"
filter_apply_hostlist_target opt
run_tpws 1 "$opt"
}
[ "$TPWS_SOCKS_ENABLE" = 1 ] && {
opt="--port=$TPPORT_SOCKS $TPWS_SOCKS_OPT"
filter_apply_hostlist_target opt
run_tpws_socks 2 "$opt"
}
[ "$NFQWS_ENABLE" = 1 ] && check_bad_ws_options 1 "$NFQWS_OPT" && {
opt="--qnum=$QNUM $NFQWS_OPT_BASE $NFQWS_OPT"
filter_apply_hostlist_target opt
run_daemon 3 "$NFQWS" "$opt"
} }
do_nfqws()
{
[ "$1" = 0 ] || { shift; run_nfqws "$@"; }
} }
start_daemons_procd() start_daemons_procd()
{ {
standard_mode_daemons 1 standard_mode_daemons
custom_runner zapret_custom_daemons 1 custom_runner zapret_custom_daemons
return 0 return 0
} }

View File

@ -21,4 +21,4 @@ pfctl -d ; pfctl -e
ipfw delete 100 ipfw delete 100
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted not sockarg ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted not sockarg
pkill ^dvtws$ pkill ^dvtws$
dvtws --daemon --port 989 --dpi-desync=multisplit dvtws --daemon --port 989 --dpi-desync=split2

View File

@ -1,65 +0,0 @@
# Example systemd service unit for nfqws. Adjust for your installation.
# WARNING ! This unit requires to compile nfqws using `make systemd`
# WARNING ! This makefile target enables special systemd notify support.
# PREPARE
# install build depends
# make -C /opt/zapret systemd
# cp nfqws@service /lib/systemd/system
# systemctl daemon-reload
# MANAGE INSTANCE
# prepare /etc/zapret/nfqws1.conf with nfqws parameters
# systemctl start nfqws@nfqws1
# systemctl status nfqws@nfqws1
# systemctl restart nfqws@nfqws1
# systemctl enable nfqws@nfqws1
# systemctl disable nfqws@nfqws1
# systemctl stop nfqws@nfqws1
# DELETE
# rm /lib/systemd/system/nfqws@.service
# systemctl daemon-reload
[Unit]
After=network.target
[Service]
Type=notify
Restart=on-failure
ExecSearchPath=/opt/zapret/binaries/my
ExecStart=nfqws @${CONFIG_DIR}/${INSTANCE}.conf
Environment=CONFIG_DIR=/etc/zapret
Environment=INSTANCE=%i
RestrictAddressFamilies=AF_NETLINK AF_UNIX AF_INET6 AF_INET
LockPersonality=true
MemoryDenyWriteExecute=true
PrivateDevices=true
PrivateMounts=true
PrivateTmp=true
ProcSubset=pid
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectProc=invisible
ProtectSystem=full
RemoveIPC=true
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@resources
UMask=0077
[Install]
WantedBy=multi-user.target

View File

@ -1,63 +0,0 @@
# Example systemd service unit for tpws. Adjust for your installation.
# WARNING ! This unit requires to compile tpws using `make systemd`
# WARNING ! This makefile target enables special systemd notify support.
# PREPARE
# install build depends
# make -C /opt/zapret systemd
# cp tpws@service /lib/systemd/system
# systemctl daemon-reload
# MANAGE INSTANCE
# prepare /etc/zapret/tpws1.conf with tpws parameters
# systemctl start tpws@tpws1
# systemctl status tpws@tpws1
# systemctl restart tpws@tpws1
# systemctl enable tpws@tpws1
# systemctl disable tpws@tpws1
# systemctl stop tpws@tpws1
# DELETE
# rm /lib/systemd/system/tpws@.service
# systemctl daemon-reload
[Unit]
After=network.target
[Service]
Type=notify
Restart=on-failure
ExecSearchPath=/opt/zapret/binaries/my
ExecStart=tpws @${CONFIG_DIR}/${INSTANCE}.conf
Environment=CONFIG_DIR=/etc/zapret
Environment=INSTANCE=%i
RestrictAddressFamilies=AF_NETLINK AF_UNIX AF_INET6 AF_INET
LockPersonality=true
MemoryDenyWriteExecute=true
PrivateDevices=true
PrivateMounts=true
PrivateTmp=true
ProcSubset=pid
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectProc=invisible
ProtectSystem=full
RemoveIPC=true
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SystemCallArchitectures=native
SystemCallFilter=@system-service
UMask=0077
[Install]
WantedBy=multi-user.target

View File

@ -8,9 +8,9 @@ alloc_qnum QNUM_DHT4ALL
zapret_custom_daemons() zapret_custom_daemons()
{ {
# $1 - 1 - add, 0 - stop # stop logic is managed by procd
local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_DESYNC_DHT" local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_DHT"
do_nfqws $1 $DNUM_DHT4ALL "$opt" do_nfqws $1 $DNUM_DHT4ALL "$opt"
} }
zapret_custom_firewall() zapret_custom_firewall()

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,6 @@ ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
. "$ZAPRET_BASE/common/ipt.sh" . "$ZAPRET_BASE/common/ipt.sh"
. "$ZAPRET_BASE/common/nft.sh" . "$ZAPRET_BASE/common/nft.sh"
. "$ZAPRET_BASE/common/linux_fw.sh" . "$ZAPRET_BASE/common/linux_fw.sh"
. "$ZAPRET_BASE/common/linux_daemons.sh"
. "$ZAPRET_BASE/common/list.sh" . "$ZAPRET_BASE/common/list.sh"
. "$ZAPRET_BASE/common/custom.sh" . "$ZAPRET_BASE/common/custom.sh"
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv" CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
@ -90,13 +89,20 @@ TPWS_WAIT_SOCKS6="$TPWS_WAIT --bind-wait-ip-linklocal=30"
# first wait for lan to ifup, then wait for bind-wait-ip-linklocal seconds for link local address and bind-wait-ip for any ipv6 as the worst case # first wait for lan to ifup, then wait for bind-wait-ip-linklocal seconds for link local address and bind-wait-ip for any ipv6 as the worst case
TPWS_OPT_BASE6_PRE="--bind-linklocal=prefer $TPWS_WAIT --bind-wait-ip-linklocal=3" TPWS_OPT_BASE6_PRE="--bind-linklocal=prefer $TPWS_WAIT --bind-wait-ip-linklocal=3"
# max wait time for the link local ipv6 on the LAN interface
LINKLOCAL_WAIT_SEC=5
IPSET_EXCLUDE="-m set ! --match-set nozapret"
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
dnat6_target() dnat6_target()
{ {
_dnat6_target "$@" _dnat6_target "$@"
} }
set_route_localnet() set_route_localnet()
{ {
_set_route_localnet $1 $IFACE_LAN _set_route_localnet $1 "$IFACE_LAN"
} }
fw_nfqws_post4() fw_nfqws_post4()
@ -269,3 +275,45 @@ create_ipset()
echo "Creating ip list table (firewall type $FWTYPE)" echo "Creating ip list table (firewall type $FWTYPE)"
"$IPSET_CR" "$@" "$IPSET_CR" "$@"
} }
standard_mode_daemons()
{
# $1 - 1 - run, 0 - stop
local opt
[ "$TPWS_ENABLE" = 1 ] && check_bad_ws_options $1 "$TPWS_OPT" && {
opt="--port=$TPPORT $TPWS_OPT"
filter_apply_hostlist_target opt
do_tpws $1 1 "$opt"
}
[ "$TPWS_SOCKS_ENABLE" = 1 ] && {
opt="--port=$TPPORT_SOCKS $TPWS_SOCKS_OPT"
filter_apply_hostlist_target opt
do_tpws_socks $1 2 "$opt"
}
[ "$NFQWS_ENABLE" = 1 ] && check_bad_ws_options $1 "$NFQWS_OPT" && {
opt="--qnum=$QNUM $NFQWS_OPT"
filter_apply_hostlist_target opt
do_nfqws $1 3 "$opt"
}
}
zapret_do_daemons()
{
# $1 - 1 - run, 0 - stop
standard_mode_daemons $1
custom_runner zapret_custom_daemons $1
return 0
}
zapret_run_daemons()
{
zapret_do_daemons 1 "$@"
}
zapret_stop_daemons()
{
zapret_do_daemons 0 "$@"
}

View File

@ -74,7 +74,8 @@ case "$1" in
;; ;;
*) *)
echo "Usage: $SCRIPT {start|stop|restart|start-fw|stop-fw|restart-fw|start-daemons|stop-daemons|restart-daemons|reload-ifsets|list-ifsets|list-table}" >&2 N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|start-fw|stop-fw|restart-fw|start-daemons|stop-daemons|restart-daemons|reload-ifsets|list-ifsets|list-table}" >&2
exit 1 exit 1
;; ;;
esac esac

View File

@ -56,7 +56,7 @@ UNAME=$(uname)
unset PKTWS unset PKTWS
case $UNAME in case $UNAME in
Linux) Linux)
ARCHLIST="my x86_64 x86 aarch64 arm mips64r2-msb mips32r1-lsb mips32r1-msb lexra ppc" ARCHLIST="my x86_64 x86 aarch64 arm mips64r2-msb mips32r1-lsb mips32r1-msb ppc"
PKTWS=nfqws PKTWS=nfqws
;; ;;
Darwin) Darwin)

View File

@ -26,7 +26,6 @@ IPSET_DIR="$ZAPRET_BASE/ipset"
. "$ZAPRET_BASE/common/ipt.sh" . "$ZAPRET_BASE/common/ipt.sh"
. "$ZAPRET_BASE/common/installer.sh" . "$ZAPRET_BASE/common/installer.sh"
. "$ZAPRET_BASE/common/virt.sh" . "$ZAPRET_BASE/common/virt.sh"
. "$ZAPRET_BASE/common/list.sh"
GET_LIST="$IPSET_DIR/get_config.sh" GET_LIST="$IPSET_DIR/get_config.sh"
@ -69,15 +68,8 @@ check_bins()
echo found architecture "\"$arch\"" echo found architecture "\"$arch\""
elif [ -f "$EXEDIR/Makefile" ] && exists make; then elif [ -f "$EXEDIR/Makefile" ] && exists make; then
echo trying to compile echo trying to compile
case $SYSTEM in [ "$SYSTEM" = "macos" ] && make_target=mac
macos) make -C "$EXEDIR" $make_target || {
make_target=mac
;;
systemd)
make_target=systemd
;;
esac
CFLAGS="-march=native ${CFLAGS}" make -C "$EXEDIR" $make_target || {
echo could not compile echo could not compile
make -C "$EXEDIR" clean make -C "$EXEDIR" clean
exitp 8 exitp 8
@ -123,30 +115,6 @@ ws_opt_validate()
} }
return 0 return 0
} }
tpws_opt_validate()
{
ws_opt_validate "$1" || return 1
dry_run_tpws || {
echo invalid tpws options
return 1
}
}
tpws_socks_opt_validate()
{
# --ipset allowed here
dry_run_tpws_socks || {
echo invalid tpws options
return 1
}
}
nfqws_opt_validate()
{
ws_opt_validate "$1" || return 1
dry_run_nfqws || {
echo invalid nfqws options
return 1
}
}
select_mode_group() select_mode_group()
{ {
@ -194,17 +162,18 @@ select_mode_group()
select_mode_tpws_socks() select_mode_tpws_socks()
{ {
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_SOCKS_OPT" local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_SOCKS_OPT"
select_mode_group TPWS_SOCKS_ENABLE "enable tpws socks mode on port $TPPORT_SOCKS ?" "TPPORT_SOCKS TPWS_SOCKS_OPT" tpws_socks_opt_validate TPWS_SOCKS_OPT # --ipset allowed here
select_mode_group TPWS_SOCKS_ENABLE "enable tpws socks mode on port $TPPORT_SOCKS ?" "TPPORT_SOCKS TPWS_SOCKS_OPT"
} }
select_mode_tpws() select_mode_tpws()
{ {
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_OPT" local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_OPT"
select_mode_group TPWS_ENABLE "enable tpws transparent mode ?" "TPWS_PORTS TPWS_OPT" tpws_opt_validate TPWS_OPT select_mode_group TPWS_ENABLE "enable tpws transparent mode ?" "TPWS_PORTS TPWS_OPT" ws_opt_validate TPWS_OPT
} }
select_mode_nfqws() select_mode_nfqws()
{ {
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="NFQWS_OPT" local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="NFQWS_OPT"
select_mode_group NFQWS_ENABLE "enable nfqws ?" "NFQWS_PORTS_TCP NFQWS_PORTS_UDP NFQWS_TCP_PKT_OUT NFQWS_TCP_PKT_IN NFQWS_UDP_PKT_OUT NFQWS_UDP_PKT_IN NFQWS_PORTS_TCP_KEEPALIVE NFQWS_PORTS_UDP_KEEPALIVE NFQWS_OPT" nfqws_opt_validate NFQWS_OPT select_mode_group NFQWS_ENABLE "enable nfqws ?" "NFQWS_PORTS_TCP NFQWS_PORTS_UDP NFQWS_TCP_PKT_OUT NFQWS_TCP_PKT_IN NFQWS_UDP_PKT_OUT NFQWS_UDP_PKT_IN NFQWS_PORTS_TCP_KEEPALIVE NFQWS_PORTS_UDP_KEEPALIVE NFQWS_OPT" ws_opt_validate NFQWS_OPT
} }
select_mode_mode() select_mode_mode()
@ -401,7 +370,7 @@ copy_openwrt()
mkdir "$2/tpws" "$2/nfq" "$2/ip2net" "$2/mdig" "$2/binaries" "$2/binaries/$ARCH" "$2/init.d" "$2/tmp" "$2/files" mkdir "$2/tpws" "$2/nfq" "$2/ip2net" "$2/mdig" "$2/binaries" "$2/binaries/$ARCH" "$2/init.d" "$2/tmp" "$2/files"
cp -R "$1/files/fake" "$2/files" cp -R "$1/files/fake" "$2/files"
cp -R "$1/common" "$1/ipset" "$2" cp -R "$1/common" "$1/ipset" "$2"
cp -R "$1/init.d/openwrt" "$1/init.d/custom.d.examples.linux" "$2/init.d" cp -R "$1/init.d/openwrt" "$2/init.d"
cp "$1/config" "$1/config.default" "$1/install_easy.sh" "$1/uninstall_easy.sh" "$1/install_bin.sh" "$1/install_prereq.sh" "$1/blockcheck.sh" "$2" cp "$1/config" "$1/config.default" "$1/install_easy.sh" "$1/uninstall_easy.sh" "$1/install_bin.sh" "$1/install_prereq.sh" "$1/blockcheck.sh" "$2"
cp "$BINDIR/tpws" "$BINDIR/nfqws" "$BINDIR/ip2net" "$BINDIR/mdig" "$2/binaries/$ARCH" cp "$BINDIR/tpws" "$BINDIR/nfqws" "$BINDIR/ip2net" "$BINDIR/mdig" "$2/binaries/$ARCH"
} }
@ -779,6 +748,7 @@ deoffload_openwrt_firewall()
else else
echo system wide software flow offloading disabled. ok echo system wide software flow offloading disabled. ok
fi fi
} }

View File

@ -9,24 +9,22 @@ SRC_FILES = ip2net.c qsort.c
all: ip2net all: ip2net
ip2net: $(SRC_FILES) ip2net: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o ip2net $(SRC_FILES) $(LIBS) $(LDFLAGS) $(CC) -s $(CFLAGS) -o ip2net $(SRC_FILES) $(LDFLAGS) $(LIBS)
systemd: ip2net
android: ip2net android: ip2net
bsd: $(SRC_FILES) bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o ip2net $(SRC_FILES) $(LIBS) $(LDFLAGS) $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o ip2net $(SRC_FILES) $(LDFLAGS) $(LIBS)
mac: $(SRC_FILES) mac: $(SRC_FILES)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -o ip2neta $(SRC_FILES) -target arm64-apple-macos10.8 $(LIBS) $(LDFLAGS) $(CC) $(CFLAGS) $(CFLAGS_BSD) -o ip2neta $(SRC_FILES) $(LDFLAGS) -target arm64-apple-macos10.8 $(LIBS)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -o ip2netx $(SRC_FILES) -target x86_64-apple-macos10.8 $(LIBS) $(LDFLAGS) $(CC) $(CFLAGS) $(CFLAGS_BSD) -o ip2netx $(SRC_FILES) $(LDFLAGS) -target x86_64-apple-macos10.8 $(LIBS)
strip ip2neta ip2netx strip ip2neta ip2netx
lipo -create -output ip2net ip2netx ip2neta lipo -create -output ip2net ip2netx ip2neta
rm -f ip2netx ip2neta rm -f ip2netx ip2neta
win: $(SRC_FILES) win: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o ip2net $(SRC_FILES) $(LIBS_WIN) $(LDFLAGS) $(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o ip2net $(SRC_FILES) $(LDFLAGS) $(LIBS_WIN)
clean: clean:
rm -f ip2net *.o rm -f ip2net *.o

View File

@ -225,28 +225,6 @@ static void exithelp(void)
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__) #define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif #endif
enum opt_indices {
IDX_HELP,
IDX_H,
IDX_4,
IDX_6,
IDX_PREFIX_LENGTH,
IDX_V4_THRESHOLD,
IDX_V6_THRESHOLD,
IDX_LAST,
};
static const struct option long_options[] = {
[IDX_HELP] = {"help", no_argument, 0, 0},
[IDX_H] = {"h", no_argument, 0, 0},
[IDX_4] = {"4", no_argument, 0, 0},
[IDX_6] = {"6", no_argument, 0, 0},
[IDX_PREFIX_LENGTH] = {"prefix-length", required_argument, 0, 0},
[IDX_V4_THRESHOLD] = {"v4-threshold", required_argument, 0, 0},
[IDX_V6_THRESHOLD] = {"v6-threshold", required_argument, 0, 0},
[IDX_LAST] = {NULL, 0, NULL, 0},
};
static void parse_params(int argc, char *argv[]) static void parse_params(int argc, char *argv[])
{ {
int option_index = 0; int option_index = 0;
@ -258,23 +236,33 @@ static void parse_params(int argc, char *argv[])
params.pctdiv = DEFAULT_PCTDIV; params.pctdiv = DEFAULT_PCTDIV;
params.v6_threshold = DEFAULT_V6_THRESHOLD; params.v6_threshold = DEFAULT_V6_THRESHOLD;
const struct option long_options[] = {
{ "help",no_argument,0,0 },// optidx=0
{ "h",no_argument,0,0 },// optidx=1
{ "4",no_argument,0,0 },// optidx=2
{ "6",no_argument,0,0 },// optidx=3
{ "prefix-length",required_argument,0,0 },// optidx=4
{ "v4-threshold",required_argument,0,0 },// optidx=5
{ "v6-threshold",required_argument,0,0 },// optidx=6
{ NULL,0,NULL,0 }
};
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{ {
if (v) exithelp(); if (v) exithelp();
switch (option_index) switch (option_index)
{ {
case IDX_HELP: case 0:
case IDX_H: case 1:
PRINT_VER; PRINT_VER;
exithelp(); exithelp();
break; break;
case IDX_4: case 2:
params.ipv6 = false; params.ipv6 = false;
break; break;
case IDX_6: case 3:
params.ipv6 = true; params.ipv6 = true;
break; break;
case IDX_PREFIX_LENGTH: case 4:
i = sscanf(optarg,"%u-%u",&plen1,&plen2); i = sscanf(optarg,"%u-%u",&plen1,&plen2);
if (i == 1) plen2 = plen1; if (i == 1) plen2 = plen1;
if (i<=0 || plen2<plen1 || !plen1 || !plen2) if (i<=0 || plen2<plen1 || !plen1 || !plen2)
@ -283,7 +271,7 @@ static void parse_params(int argc, char *argv[])
exit(1); exit(1);
} }
break; break;
case IDX_V4_THRESHOLD: case 5:
i = sscanf(optarg, "%u/%u", &params.pctmult, &params.pctdiv); i = sscanf(optarg, "%u/%u", &params.pctmult, &params.pctdiv);
if (i!=2 || params.pctdiv<2 || params.pctmult<1 || params.pctmult>=params.pctdiv) if (i!=2 || params.pctdiv<2 || params.pctmult<1 || params.pctmult>=params.pctdiv)
{ {
@ -291,7 +279,7 @@ static void parse_params(int argc, char *argv[])
exit(1); exit(1);
} }
break; break;
case IDX_V6_THRESHOLD: case 6:
i = sscanf(optarg, "%u", &params.v6_threshold); i = sscanf(optarg, "%u", &params.v6_threshold);
if (i != 1 || params.v6_threshold<1) if (i != 1 || params.v6_threshold<1)
{ {

View File

@ -7,7 +7,7 @@ get_antifilter()
[ "$DISABLE_IPV4" != "1" ] && { [ "$DISABLE_IPV4" != "1" ] && {
curl --fail --max-time 150 --connect-timeout 20 --max-filesize 41943040 -k -L "$1" | cut_local >"$ZIPLISTTMP" && curl --fail --max-time 150 --connect-timeout 20 --max-filesize 41943040 -k -L "$1" | cut_local >"$ZIPLISTTMP" &&
{ {
dlsize=$(LC_ALL=C LANG=C wc -c "$ZIPLISTTMP" | xargs | cut -f 1 -d ' ') dlsize=$(LANG=C wc -c "$ZIPLISTTMP" | xargs | cut -f 1 -d ' ')
if [ $dlsize -lt 102400 ]; then if [ $dlsize -lt 102400 ]; then
echo list file is too small. can be bad. echo list file is too small. can be bad.
exit 2 exit 2

View File

@ -5,7 +5,7 @@ ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"} ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
IPSET_RW_DIR="$ZAPRET_RW/ipset" IPSET_RW_DIR="$ZAPRET_RW/ipset"
[ -f "$ZAPRET_CONFIG" ] && . "$ZAPRET_CONFIG" . "$ZAPRET_CONFIG"
. "$ZAPRET_BASE/common/base.sh" . "$ZAPRET_BASE/common/base.sh"
[ -z "$TMPDIR" ] && TMPDIR=/tmp [ -z "$TMPDIR" ] && TMPDIR=/tmp
@ -141,18 +141,6 @@ zzsize()
printf 0 printf 0
fi fi
} }
zzcopy()
{
local is_gz=0
zztest "$1" && is_gz=1
if [ "$GZIP_LISTS" = 1 -a $is_gz = 1 ]; then
cp "$1" "${2}.gz"
elif [ "$GZIP_LISTS" != 1 -a $is_gz != 1 ]; then
cp "$1" "$2"
else
zzcat "$1" | zz "$2"
fi
}
digger() digger()
{ {
@ -267,17 +255,3 @@ getipban()
_get_ipban _get_ipban
return 0 return 0
} }
hup_zapret_daemons()
{
echo forcing zapret daemons to reload their hostlist
if exists killall; then
killall -HUP tpws nfqws dvtws 2>/dev/null
elif exists pkill; then
pkill -HUP ^tpws$
pkill -HUP ^nfqws$
pkill -HUP ^dvtws$
else
echo no mass killer available ! cant HUP zapret daemons
fi
}

View File

@ -21,7 +21,7 @@ curl -H "Accept-Encoding: gzip" -k --fail --max-time 600 --connect-timeout 5 --r
exit 2 exit 2
} }
dlsize=$(LC_ALL=C LANG=C wc -c "$ZDOM" | xargs | cut -f 1 -d ' ') dlsize=$(LANG=C wc -c "$ZDOM" | xargs | cut -f 1 -d ' ')
if test $dlsize -lt 102400; then if test $dlsize -lt 102400; then
echo list file is too small. can be bad. echo list file is too small. can be bad.
exit 2 exit 2
@ -31,6 +31,4 @@ sort -u "$ZDOM" | zz "$ZHOSTLIST"
rm -f "$ZDOM" rm -f "$ZDOM"
hup_zapret_daemons
exit 0 exit 0

View File

@ -4,7 +4,7 @@
IPSET_DIR="$(dirname "$0")" IPSET_DIR="$(dirname "$0")"
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
[ -f "$IPSET_DIR/../config" ] && . "$IPSET_DIR/../config" . "$IPSET_DIR/../config"
[ -z "$GETLIST" ] && GETLIST=get_ipban.sh [ -z "$GETLIST" ] && GETLIST=get_ipban.sh
[ -x "$IPSET_DIR/$GETLIST" ] && exec "$IPSET_DIR/$GETLIST" [ -x "$IPSET_DIR/$GETLIST" ] && exec "$IPSET_DIR/$GETLIST"

View File

@ -5,9 +5,9 @@ IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
. "$IPSET_DIR/def.sh" . "$IPSET_DIR/def.sh"
ZREESTR="$TMPDIR/zapret.txt.gz" ZREESTR="$TMPDIR/zapret.txt"
IPB="$TMPDIR/ipb.txt" IPB="$TMPDIR/ipb.txt"
ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv.gz ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv
dl_checked() dl_checked()
{ {
@ -21,7 +21,7 @@ dl_checked()
echo list download failed : $1 echo list download failed : $1
return 2 return 2
} }
dlsize=$(LC_ALL=C LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ') dlsize=$(LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ')
if test $dlsize -lt $3; then if test $dlsize -lt $3; then
echo list is too small : $dlsize bytes. can be bad. echo list is too small : $dlsize bytes. can be bad.
return 2 return 2
@ -31,11 +31,11 @@ dl_checked()
reestr_list() reestr_list()
{ {
LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }' LANG=C cut -s -f2 -d';' "$ZREESTR" | LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }'
} }
reestr_extract_ip() reestr_extract_ip()
{ {
LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}' LANG=C nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' "$ZREESTR" | LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}'
} }
ipban_fin() ipban_fin()
@ -58,8 +58,6 @@ rm -f "$ZREESTR"
[ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6" [ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6"
rm -f "$IPB" rm -f "$IPB"
hup_zapret_daemons
ipban_fin ipban_fin
exit 0 exit 0

View File

@ -24,12 +24,12 @@ dl()
echo list download failed : $1 echo list download failed : $1
exit 2 exit 2
} }
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') dlsize=$(LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
if test $dlsize -lt $3; then if test $dlsize -lt $3; then
echo list is too small : $dlsize bytes. can be bad. echo list is too small : $dlsize bytes. can be bad.
exit 2 exit 2
fi fi
zzcopy "$TMPLIST" "$2" zzcat "$TMPLIST" | zz "$2"
rm -f "$TMPLIST" rm -f "$TMPLIST"
} }

View File

@ -24,12 +24,12 @@ dl()
echo list download failed : $1 echo list download failed : $1
exit 2 exit 2
} }
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') dlsize=$(LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
if test $dlsize -lt $3; then if test $dlsize -lt $3; then
echo list is too small : $dlsize bytes. can be bad. echo list is too small : $dlsize bytes. can be bad.
exit 2 exit 2
fi fi
zzcopy "$TMPLIST" "$2" zzcat "$TMPLIST" | zz "$2"
rm -f "$TMPLIST" rm -f "$TMPLIST"
} }

View File

@ -23,19 +23,17 @@ dl()
echo list download failed : $1 echo list download failed : $1
exit 2 exit 2
} }
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') dlsize=$(LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
if test $dlsize -lt $3; then if test $dlsize -lt $3; then
echo list is too small : $dlsize bytes. can be bad. echo list is too small : $dlsize bytes. can be bad.
exit 2 exit 2
fi fi
zzcopy "$TMPLIST" "$2" zzcat "$TMPLIST" | zz "$2"
rm -f "$TMPLIST" rm -f "$TMPLIST"
} }
dl "$URL" "$ZHOSTLIST" 65536 67108864 dl "$URL" "$ZHOSTLIST" 65536 67108864
hup_zapret_daemons
[ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576 [ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
[ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576 [ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576

View File

@ -5,12 +5,12 @@ IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
. "$IPSET_DIR/def.sh" . "$IPSET_DIR/def.sh"
ZREESTR="$TMPDIR/zapret.txt.gz" ZREESTR="$TMPDIR/zapret.txt"
ZDIG="$TMPDIR/zapret-dig.txt" ZDIG="$TMPDIR/zapret-dig.txt"
IPB="$TMPDIR/ipb.txt" IPB="$TMPDIR/ipb.txt"
ZIPLISTTMP="$TMPDIR/zapret-ip.txt" ZIPLISTTMP="$TMPDIR/zapret-ip.txt"
#ZURL=https://reestr.rublacklist.net/api/current #ZURL=https://reestr.rublacklist.net/api/current
ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv.gz ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv
dl_checked() dl_checked()
{ {
@ -24,7 +24,7 @@ dl_checked()
echo list download failed : $1 echo list download failed : $1
return 2 return 2
} }
dlsize=$(LC_ALL=C LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ') dlsize=$(LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ')
if test $dlsize -lt $3; then if test $dlsize -lt $3; then
echo list is too small : $dlsize bytes. can be bad. echo list is too small : $dlsize bytes. can be bad.
return 2 return 2
@ -34,11 +34,11 @@ dl_checked()
reestr_list() reestr_list()
{ {
LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }' LANG=C cut -s -f2 -d';' "$ZREESTR" | LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p'
} }
reestr_extract_ip() reestr_extract_ip()
{ {
LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}' LANG=C nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' "$ZREESTR" | LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}'
} }
getuser && { getuser && {

View File

@ -20,12 +20,12 @@ dl()
echo list download failed : $1 echo list download failed : $1
exit 2 exit 2
} }
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') dlsize=$(LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
if test $dlsize -lt $3; then if test $dlsize -lt $3; then
echo list is too small : $dlsize bytes. can be bad. echo list is too small : $dlsize bytes. can be bad.
exit 2 exit 2
fi fi
zzcopy "$TMPLIST" "$2" zzcat "$TMPLIST" | tr -d '\015' | zz "$2"
rm -f "$TMPLIST" rm -f "$TMPLIST"
} }
@ -37,6 +37,4 @@ getipban || FAIL=1
dl "$URL" "$ZHOSTLIST" 32768 4194304 dl "$URL" "$ZHOSTLIST" 32768 4194304
hup_zapret_daemons
exit 0 exit 0

View File

@ -20,12 +20,13 @@ dl()
echo list download failed : $1 echo list download failed : $1
exit 2 exit 2
} }
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') dlsize=$(LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
if test $dlsize -lt $3; then if test $dlsize -lt $3; then
echo list is too small : $dlsize bytes. can be bad. echo list is too small : $dlsize bytes. can be bad.
exit 2 exit 2
fi fi
zzcopy "$TMPLIST" "$2" # remove DOS EOL \r
zzcat "$TMPLIST" | tr -d '\015' | zz "$2"
rm -f "$TMPLIST" rm -f "$TMPLIST"
} }

View File

@ -1,8 +1,6 @@
127.0.0.0/8
10.0.0.0/8 10.0.0.0/8
172.16.0.0/12 172.16.0.0/12
192.168.0.0/16 192.168.0.0/16
169.254.0.0/16 169.254.0.0/16
::1
fc00::/7 fc00::/7
fe80::/10 fe80::/10

View File

@ -10,25 +10,23 @@ SRC_FILES = *.c
all: mdig all: mdig
mdig: $(SRC_FILES) mdig: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS) $(LDFLAGS) $(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS)
systemd: mdig
android: $(SRC_FILES) android: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS_ANDROID) $(LDFLAGS) $(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS_ANDROID)
bsd: $(SRC_FILES) bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o mdig $(SRC_FILES) $(LIBS) $(LDFLAGS) $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS)
mac: $(SRC_FILES) mac: $(SRC_FILES)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -o mdiga $(SRC_FILES) -target arm64-apple-macos10.8 $(LIBS_BSD) $(LDFLAGS) $(CC) $(CFLAGS) $(CFLAGS_BSD) -o mdiga $(SRC_FILES) $(LDFLAGS) -target arm64-apple-macos10.8 $(LIBS_BSD)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -o mdigx $(SRC_FILES) -target x86_64-apple-macos10.8 $(LIBS_BSD) $(LDFLAGS) $(CC) $(CFLAGS) $(CFLAGS_BSD) -o mdigx $(SRC_FILES) $(LDFLAGS) -target x86_64-apple-macos10.8 $(LIBS_BSD)
strip mdiga mdigx strip mdiga mdigx
lipo -create -output mdig mdigx mdiga lipo -create -output mdig mdigx mdiga
rm -f mdigx mdiga rm -f mdigx mdiga
win: $(SRC_FILES) win: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o mdig $(SRC_FILES) $(LIBS_WIN) $(LDFLAGS) $(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS_WIN)
clean: clean:
rm -f mdig *.o rm -f mdig *.o

View File

@ -467,38 +467,25 @@ static void exithelp(void)
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__) #define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif #endif
enum opt_indices {
IDX_HELP,
IDX_THREADS,
IDX_FAMILY,
IDX_VERBOSE,
IDX_STATS,
IDX_LOG_RESOLVED,
IDX_LOG_FAILED,
IDX_DNS_MAKE_QUERY,
IDX_DNS_PARSE_QUERY,
IDX_LAST,
};
static const struct option long_options[] = {
[IDX_HELP] = {"help", no_argument, 0, 0},
[IDX_THREADS] = {"threads", required_argument, 0, 0},
[IDX_FAMILY] = {"family", required_argument, 0, 0},
[IDX_VERBOSE] = {"verbose", no_argument, 0, 0},
[IDX_STATS] = {"stats", required_argument, 0, 0},
[IDX_LOG_RESOLVED] = {"log-resolved", required_argument, 0, 0},
[IDX_LOG_FAILED] = {"log-failed", required_argument, 0, 0},
[IDX_DNS_MAKE_QUERY] = {"dns-make-query", required_argument, 0, 0},
[IDX_DNS_PARSE_QUERY] = {"dns-parse-query", no_argument, 0, 0},
[IDX_LAST] = {NULL, 0, NULL, 0},
};
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int r, v, option_index = 0; int r, v, option_index = 0;
char fn1[256],fn2[256]; char fn1[256],fn2[256];
char dom[256]; char dom[256];
static const struct option long_options[] = {
{"help",no_argument,0,0}, // optidx=0
{"threads",required_argument,0,0}, // optidx=1
{"family",required_argument,0,0}, // optidx=2
{"verbose",no_argument,0,0}, // optidx=3
{"stats",required_argument,0,0}, // optidx=4
{"log-resolved",required_argument,0,0}, // optidx=5
{"log-failed",required_argument,0,0}, // optidx=6
{"dns-make-query",required_argument,0,0}, // optidx=7
{"dns-parse-query",no_argument,0,0}, // optidx=8
{NULL,0,NULL,0}
};
memset(&glob, 0, sizeof(glob)); memset(&glob, 0, sizeof(glob));
*fn1 = *fn2 = *dom = 0; *fn1 = *fn2 = *dom = 0;
glob.family = FAMILY4; glob.family = FAMILY4;
@ -508,11 +495,11 @@ int main(int argc, char **argv)
if (v) exithelp(); if (v) exithelp();
switch (option_index) switch (option_index)
{ {
case IDX_HELP: case 0: /* help */
PRINT_VER; PRINT_VER;
exithelp(); exithelp();
break; break;
case IDX_THREADS: case 1: /* threads */
glob.threads = optarg ? atoi(optarg) : 0; glob.threads = optarg ? atoi(optarg) : 0;
if (glob.threads <= 0 || glob.threads > 100) if (glob.threads <= 0 || glob.threads > 100)
{ {
@ -520,7 +507,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
break; break;
case IDX_FAMILY: case 2: /* family */
if (!strcmp(optarg, "4")) if (!strcmp(optarg, "4"))
glob.family = FAMILY4; glob.family = FAMILY4;
else if (!strcmp(optarg, "6")) else if (!strcmp(optarg, "6"))
@ -533,25 +520,25 @@ int main(int argc, char **argv)
return 1; return 1;
} }
break; break;
case IDX_VERBOSE: case 3: /* verbose */
glob.verbose = '\1'; glob.verbose = '\1';
break; break;
case IDX_STATS: case 4: /* stats */
glob.stats_every = optarg ? atoi(optarg) : 0; glob.stats_every = optarg ? atoi(optarg) : 0;
break; break;
case IDX_LOG_RESOLVED: case 5: /* log-resolved */
strncpy(fn1,optarg,sizeof(fn1)); strncpy(fn1,optarg,sizeof(fn1));
fn1[sizeof(fn1)-1] = 0; fn1[sizeof(fn1)-1] = 0;
break; break;
case IDX_LOG_FAILED: case 6: /* log-failed */
strncpy(fn2,optarg,sizeof(fn2)); strncpy(fn2,optarg,sizeof(fn2));
fn2[sizeof(fn2)-1] = 0; fn2[sizeof(fn2)-1] = 0;
break; break;
case IDX_DNS_MAKE_QUERY: case 7: /* dns-make-query */
strncpy(dom,optarg,sizeof(dom)); strncpy(dom,optarg,sizeof(dom));
dom[sizeof(dom)-1] = 0; dom[sizeof(dom)-1] = 0;
break; break;
case IDX_DNS_PARSE_QUERY: case 8: /* dns-parse-query */
return dns_parse_query(); return dns_parse_query();
} }
} }

View File

@ -6,7 +6,7 @@ SRC_FILES = *.c crypto/*.c
all: dvtws all: dvtws
dvtws: $(SRC_FILES) dvtws: $(SRC_FILES)
$(CC) $(CFLAGS) -o dvtws $(SRC_FILES) $(LIBS) $(LDFLAGS) $(CC) $(CFLAGS) -o dvtws $(SRC_FILES) $(LDFLAGS) $(LIBS)
clean: clean:
rm -f dvtws rm -f dvtws

View File

@ -1,10 +1,8 @@
CC ?= gcc CC ?= gcc
CFLAGS += -std=gnu99 -Os -flto=auto CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
CFLAGS_BSD = -Wno-address-of-packed-member CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
LIBS_SYSTEMD = -lsystemd
LIBS_BSD = -lz LIBS_BSD = -lz
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32 LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32
LIBS_CYGWIN32 = -lwindivert32 LIBS_CYGWIN32 = -lwindivert32
@ -16,27 +14,24 @@ SRC_FILES = *.c crypto/*.c
all: nfqws all: nfqws
nfqws: $(SRC_FILES) nfqws: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LDFLAGS) $(CC) -s $(CFLAGS) -o nfqws $(SRC_FILES) $(LDFLAGS) $(LIBS_LINUX)
systemd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_SYSTEMD) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
android: nfqws android: nfqws
bsd: $(SRC_FILES) bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o dvtws $(SRC_FILES) $(LIBS_BSD) $(LDFLAGS) $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o dvtws $(SRC_FILES) $(LDFLAGS) $(LIBS_BSD)
mac: $(SRC_FILES) mac: $(SRC_FILES)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -o dvtwsa $(SRC_FILES) -target arm64-apple-macos10.8 $(LIBS_BSD) $(LDFLAGS) $(CC) $(CFLAGS) $(CFLAGS_BSD) -o dvtwsa $(SRC_FILES) $(LDFLAGS) -target arm64-apple-macos10.8 $(LIBS_BSD)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -o dvtwsx $(SRC_FILES) -target x86_64-apple-macos10.8 $(LIBS_BSD) $(LDFLAGS) $(CC) $(CFLAGS) $(CFLAGS_BSD) -o dvtwsx $(SRC_FILES) $(LDFLAGS) -target x86_64-apple-macos10.8 $(LIBS_BSD)
strip dvtwsa dvtwsx strip dvtwsa dvtwsx
lipo -create -output dvtws dvtwsx dvtwsa lipo -create -output dvtws dvtwsx dvtwsa
rm -f dvtwsx dvtwsa rm -f dvtwsx dvtwsa
cygwin64: cygwin64:
$(CC) -s $(CFLAGS) $(CFLAGS_CYGWIN) -o winws $(SRC_FILES) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(RES_CYGWIN64) $(LDFLAGS) $(CC) -s $(CFLAGS) $(CFLAGS_CYGWIN) -o winws $(SRC_FILES) $(LDFLAGS) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(RES_CYGWIN64)
cygwin32: cygwin32:
$(CC) -s $(CFLAGS) $(CFLAGS_CYGWIN) -o winws $(SRC_FILES) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(RES_CYGWIN32) $(LDFLAGS) $(CC) -s $(CFLAGS) $(CFLAGS_CYGWIN) -o winws $(SRC_FILES) $(LDFLAGS) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(RES_CYGWIN32)
cygwin: cygwin64 cygwin: cygwin64
clean: clean:

View File

@ -26,10 +26,13 @@ static void connswap(const t_conn *c, t_conn *c2)
} }
void ConntrackClearHostname(t_ctrack *track) void ConntrackClearHostname(t_ctrack *track)
{
if (track->hostname)
{ {
free(track->hostname); free(track->hostname);
track->hostname = NULL; track->hostname = NULL;
} }
}
static void ConntrackClearTrack(t_ctrack *track) static void ConntrackClearTrack(t_ctrack *track)
{ {
ConntrackClearHostname(track); ConntrackClearHostname(track);
@ -143,11 +146,8 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
} }
else if (tcp_synack_segment(tcphdr)) else if (tcp_synack_segment(tcphdr))
{ {
// ignore SA dups if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
uint32_t seq0 = ntohl(tcphdr->th_ack)-1; if (!t->seq0) t->seq0 = ntohl(tcphdr->th_ack)-1;
if (t->state!=SYN && t->seq0!=seq0)
ConntrackReInitTrack(t); // erase current entry
if (!t->seq0) t->seq0 = seq0;
t->ack0 = ntohl(tcphdr->th_seq); t->ack0 = ntohl(tcphdr->th_seq);
} }
else if (tcphdr->th_flags & (TH_FIN|TH_RST)) else if (tcphdr->th_flags & (TH_FIN|TH_RST))
@ -341,16 +341,19 @@ void ConntrackPoolDump(const t_conntrack *p)
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u", printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
t->track.seq_last, t->track.pos_orig, t->track.seq_last, t->track.pos_orig,
t->track.ack_last, t->track.pos_reply); t->track.ack_last, t->track.pos_reply);
printf(" req_retrans=%u cutoff=%u wss_cutoff=%u desync_cutoff=%u dup_cutoff=%u orig_cutoff=%u hostname=%s l7proto=%s\n", printf(" req_retrans=%u cutoff=%u wss_cutoff=%u d_cutoff=%u hostname=%s l7proto=%s\n",
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff, t->track.b_dup_cutoff, t->track.b_orig_mod_cutoff, t->track.hostname, l7proto_str(t->track.l7proto)); t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
}; };
} }
void ReasmClear(t_reassemble *reasm) void ReasmClear(t_reassemble *reasm)
{
if (reasm->packet)
{ {
free(reasm->packet); free(reasm->packet);
reasm->packet = NULL; reasm->packet = NULL;
}
reasm->size = reasm->size_present = 0; reasm->size = reasm->size_present = 0;
} }
bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start) bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start)

View File

@ -77,16 +77,14 @@ typedef struct
bool req_seq_present,req_seq_finalized,req_seq_abandoned; bool req_seq_present,req_seq_finalized,req_seq_abandoned;
uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions) uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions)
uint8_t incoming_ttl, desync_autottl, orig_autottl, dup_autottl; uint8_t incoming_ttl, autottl;
bool b_autottl_discovered;
bool b_cutoff; // mark for deletion bool b_cutoff; // mark for deletion
bool b_wssize_cutoff, b_desync_cutoff, b_dup_cutoff, b_orig_mod_cutoff; bool b_wssize_cutoff, b_desync_cutoff;
t_l7proto l7proto; t_l7proto l7proto;
bool l7proto_discovered; bool l7proto_discovered;
char *hostname; char *hostname;
bool hostname_discovered;
bool hostname_ah_check; // should perform autohostlist checks bool hostname_ah_check; // should perform autohostlist checks
t_reassemble reasm_orig; t_reassemble reasm_orig;

View File

@ -38,11 +38,6 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
return htons(ntohs(netorder_value)+cpuorder_increment); return htons(ntohs(netorder_value)+cpuorder_increment);
} }
bool ip_has_df(const struct ip *ip)
{
return ip && !!(ntohs(ip->ip_off) & IP_DF);
}
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind) uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind)
{ {
uint8_t *t = (uint8_t*)(tcp+1); uint8_t *t = (uint8_t*)(tcp+1);
@ -88,22 +83,10 @@ bool tcp_has_fastopen(const struct tcphdr *tcp)
opt = tcp_find_option((struct tcphdr*)tcp, 254); opt = tcp_find_option((struct tcphdr*)tcp, 254);
return opt && opt[1]>=4 && opt[2]==0xF9 && opt[3]==0x89; return opt && opt[1]>=4 && opt[2]==0xF9 && opt[3]==0x89;
} }
uint16_t tcp_find_mss(struct tcphdr *tcp)
{
uint8_t *t = tcp_find_option(tcp,2);
return (t && t[1]==4) ? *(uint16_t*)(t+2) : 0;
}
bool tcp_has_sack(struct tcphdr *tcp)
{
uint8_t *t = tcp_find_option(tcp,4);
return !!t;
}
// n prefix (nsport, nwsize) means network byte order // n prefix (nsport, nwsize) means network byte order
static void fill_tcphdr( static void fill_tcphdr(
struct tcphdr *tcp, uint32_t fooling, uint8_t tcp_flags, struct tcphdr *tcp, uint32_t fooling, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nsport, uint16_t ndport, uint16_t nsport, uint16_t ndport,
uint16_t nwsize, uint8_t scale_factor, uint16_t nwsize, uint8_t scale_factor,
@ -133,27 +116,15 @@ static void fill_tcphdr(
tcp_flags &= ~TH_ACK; tcp_flags &= ~TH_ACK;
*((uint8_t*)tcp+13)= tcp_flags; *((uint8_t*)tcp+13)= tcp_flags;
tcp->th_win = nwsize; tcp->th_win = nwsize;
if (nmss)
{
tcpopt[t++] = 2; // kind
tcpopt[t++] = 4; // len
*(uint16_t*)(tcpopt+t) = nmss;
t+=2;
}
if (sack)
{
tcpopt[t++] = 4; // kind
tcpopt[t++] = 2; // len
}
if (fooling & FOOL_MD5SIG) if (fooling & FOOL_MD5SIG)
{ {
tcpopt[t] = 19; // kind tcpopt[0] = 19; // kind
tcpopt[t+1] = 18; // len tcpopt[1] = 18; // len
*(uint32_t*)(tcpopt+t+2)=random(); *(uint32_t*)(tcpopt+2)=random();
*(uint32_t*)(tcpopt+t+6)=random(); *(uint32_t*)(tcpopt+6)=random();
*(uint32_t*)(tcpopt+t+10)=random(); *(uint32_t*)(tcpopt+10)=random();
*(uint32_t*)(tcpopt+t+14)=random(); *(uint32_t*)(tcpopt+14)=random();
t+=18; t=18;
} }
if (timestamps || (fooling & FOOL_TS)) if (timestamps || (fooling & FOOL_TS))
{ {
@ -174,12 +145,10 @@ static void fill_tcphdr(
tcp->th_off += t>>2; tcp->th_off += t>>2;
tcp->th_sum = 0; tcp->th_sum = 0;
} }
static uint16_t tcpopt_len(bool sack, bool mss, uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor) static uint16_t tcpopt_len(uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor)
{ {
uint16_t t=0; uint16_t t=0;
if (sack) t+=2; if (fooling & FOOL_MD5SIG) t=18;
if (mss) t+=4;
if (fooling & FOOL_MD5SIG) t+=18;
if ((fooling & FOOL_TS) || timestamps) t+=10; if ((fooling & FOOL_TS) || timestamps) t+=10;
if (scale_factor!=SCALE_NONE) t+=3; if (scale_factor!=SCALE_NONE) t+=3;
return (t+3)&~3; return (t+3)&~3;
@ -194,11 +163,11 @@ static void fill_udphdr(struct udphdr *udp, uint16_t nsport, uint16_t ndport, ui
udp->uh_sum = 0; 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, bool DF, uint8_t ttl, uint8_t tos, uint16_t ip_id) 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_tos = tos;
ip->ip_sum = 0; ip->ip_sum = 0;
ip->ip_off = DF ? htons(IP_DF) : 0; ip->ip_off = 0;
ip->ip_v = 4; ip->ip_v = 4;
ip->ip_hl = 5; ip->ip_hl = 5;
ip->ip_len = htons(pktlen); ip->ip_len = htons(pktlen);
@ -221,13 +190,10 @@ static void fill_ip6hdr(struct ip6_hdr *ip6, const struct in6_addr *src, const s
bool prepare_tcp_segment4( bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -237,7 +203,7 @@ bool prepare_tcp_segment4(
const void *data, uint16_t len, const void *data, uint16_t len,
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,fooling,timestamps,scale_factor); uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
uint16_t ip_payload_len = sizeof(struct tcphdr) + tcpoptlen + len; uint16_t ip_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
uint16_t pktlen = sizeof(struct ip) + ip_payload_len; uint16_t pktlen = sizeof(struct ip) + ip_payload_len;
if (pktlen>*buflen) return false; if (pktlen>*buflen) return false;
@ -246,12 +212,12 @@ bool prepare_tcp_segment4(
struct tcphdr *tcp = (struct tcphdr*)(ip+1); struct tcphdr *tcp = (struct tcphdr*)(ip+1);
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen; uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, DF, ttl, tos, ip_id); fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, ttl, tos, ip_id);
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len); 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); memcpy(payload,data,len);
tcp4_fix_checksum(tcp,ip_payload_len,&ip->ip_src,&ip->ip_dst); tcp4_fix_checksum(tcp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
if (fooling & FOOL_BADSUM) tcp->th_sum^=(uint16_t)(1+random()%0xFFFF); if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
*buflen = pktlen; *buflen = pktlen;
return true; return true;
@ -260,8 +226,6 @@ bool prepare_tcp_segment4(
bool prepare_tcp_segment6( bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst, const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
@ -274,7 +238,7 @@ bool prepare_tcp_segment6(
const void *data, uint16_t len, const void *data, uint16_t len,
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,fooling,timestamps,scale_factor); uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
uint16_t transport_payload_len = sizeof(struct tcphdr) + tcpoptlen + len; uint16_t transport_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
uint16_t ip_payload_len = transport_payload_len + uint16_t ip_payload_len = transport_payload_len +
8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) + 8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) +
@ -333,11 +297,11 @@ bool prepare_tcp_segment6(
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen; uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl, flow_label); fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl, flow_label);
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len); fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len); memcpy(payload,data,len);
tcp6_fix_checksum(tcp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); tcp6_fix_checksum(tcp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
if (fooling & FOOL_BADSUM) tcp->th_sum^=(1+random()%0xFFFF); if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
*buflen = pktlen; *buflen = pktlen;
return true; return true;
@ -346,13 +310,10 @@ bool prepare_tcp_segment6(
bool prepare_tcp_segment( bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -364,9 +325,9 @@ bool prepare_tcp_segment(
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ? return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,DF,ttl,tos,ip_id,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) ? (src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) : 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; false;
} }
@ -374,7 +335,6 @@ bool prepare_tcp_segment(
// padlen<0 means payload shrinking // padlen<0 means payload shrinking
bool prepare_udp_segment4( bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -401,7 +361,7 @@ bool prepare_udp_segment4(
uint8_t *payload = (uint8_t*)(udp+1); uint8_t *payload = (uint8_t*)(udp+1);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, DF, ttl, tos, ip_id); 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); fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
memcpy(payload,data,len); memcpy(payload,data,len);
@ -410,7 +370,7 @@ bool prepare_udp_segment4(
else else
memset(payload+len,0,padlen); memset(payload+len,0,padlen);
udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst); udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF); if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
*buflen = pktlen; *buflen = pktlen;
return true; return true;
@ -499,14 +459,13 @@ bool prepare_udp_segment6(
else else
memset(payload+len,0,padlen); memset(payload+len,0,padlen);
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst); udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF); if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
*buflen = pktlen; *buflen = pktlen;
return true; return true;
} }
bool prepare_udp_segment( bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -518,7 +477,7 @@ bool prepare_udp_segment(
uint8_t *buf, size_t *buflen) uint8_t *buf, size_t *buflen)
{ {
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ? return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,DF,ttl,tos,ip_id,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) ? (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) : prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
false; false;
@ -642,29 +601,10 @@ bool ip_frag(
return false; return false;
} }
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl) void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
{ {
if (ttl) if (ip) ip->ip_ttl = ttl;
{ if (ip6) ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
if (ip)
{
if (ip->ip_ttl!=ttl)
{
ip->ip_ttl = ttl;
ip4_fix_checksum(ip);
return true;
}
}
else if (ip6)
{
if (ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim!=ttl)
{
ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
return true;
}
}
}
return false;
} }
@ -1807,9 +1747,7 @@ nofix:
bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen); bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen);
if (bytes==-1) if (bytes==-1)
{ {
char s[40]; DLOG_PERROR("rawsend: sendto");
snprintf(s,sizeof(s),"rawsend: sendto (%zu)",len);
DLOG_PERROR(s);
return false; return false;
} }
return true; return true;
@ -1832,15 +1770,16 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
} }
uint8_t hop_count_guess(uint8_t ttl) // return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
// ttl = TTL of incoming packet
uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
{ {
uint8_t orig, path, fake;
// 18.65.168.125 ( cloudfront ) 255 // 18.65.168.125 ( cloudfront ) 255
// 157.254.246.178 128 // 157.254.246.178 128
// 1.1.1.1 64 // 1.1.1.1 64
// guess original ttl. consider path lengths less than 32 hops // guess original ttl. consider path lengths less than 32 hops
uint8_t orig;
if (ttl>223) if (ttl>223)
orig=255; orig=255;
else if (ttl<128 && ttl>96) else if (ttl<128 && ttl>96)
@ -1850,21 +1789,13 @@ uint8_t hop_count_guess(uint8_t ttl)
else else
return 0; return 0;
return orig - ttl; path = orig - ttl;
}
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
uint8_t autottl_eval(uint8_t hop_count, const autottl *attl)
{
uint8_t fake;
int d;
d = (int)hop_count + attl->delta; fake = path > attl->delta ? path - attl->delta : attl->min;
if (d<attl->min) fake=attl->min; if (fake<attl->min) fake=attl->min;
else if (d>attl->max) fake=attl->max; else if (fake>attl->max) fake=attl->max;
else fake=(uint8_t)d;
if (attl->delta<0 && fake>=hop_count || attl->delta>=0 && fake<hop_count) if (fake>=path) return 0;
return 0;
return fake; return fake;
} }
@ -1916,15 +1847,15 @@ void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transpo
{ {
if (!(verdict & VERDICT_NOCSUM)) if (!(verdict & VERDICT_NOCSUM))
{ {
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad // always fix csum for windivert. original can be partial or bad
if ((verdict & VERDICT_MASK)!=VERDICT_DROP) #ifndef __CYGWIN__
#elif defined(__FreeBSD__) #ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum // FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else #else
// if original packet was tampered earlier it needs checksum fixed // if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif #endif
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr); tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
} }
@ -1933,15 +1864,15 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
{ {
if (!(verdict & VERDICT_NOCSUM)) if (!(verdict & VERDICT_NOCSUM))
{ {
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad // always fix csum for windivert. original can be partial or bad
if ((verdict & VERDICT_MASK)!=VERDICT_DROP) #ifndef __CYGWIN__
#elif defined(__FreeBSD__) #ifdef __FreeBSD__
// FreeBSD tend to pass ipv6 frames with wrong checksum // FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else #else
// if original packet was tampered earlier it needs checksum fixed // if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY) if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif #endif
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr); udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
} }

View File

@ -59,7 +59,6 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
#define VERDICT_DROP 2 #define VERDICT_DROP 2
#define VERDICT_MASK 3 #define VERDICT_MASK 3
#define VERDICT_NOCSUM 4 #define VERDICT_NOCSUM 4
#define VERDICT_GARBAGE 8
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0) #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 IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0)
@ -69,13 +68,10 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
bool prepare_tcp_segment4( bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -87,8 +83,6 @@ bool prepare_tcp_segment4(
bool prepare_tcp_segment6( bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst, const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
@ -103,13 +97,10 @@ bool prepare_tcp_segment6(
bool prepare_tcp_segment( bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags, uint8_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq, uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize, uint16_t nwsize,
uint8_t scale_factor, uint8_t scale_factor,
uint32_t *timestamps, uint32_t *timestamps,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -123,7 +114,6 @@ bool prepare_tcp_segment(
bool prepare_udp_segment4( bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst, const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -143,7 +133,6 @@ bool prepare_udp_segment6(
uint8_t *buf, size_t *buflen); uint8_t *buf, size_t *buflen);
bool prepare_udp_segment( bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst, const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl, uint8_t ttl,
uint8_t tos, uint8_t tos,
uint16_t ip_id, uint16_t ip_id,
@ -173,20 +162,15 @@ bool ip_frag(
uint8_t *pkt1, size_t *pkt1_size, uint8_t *pkt1, size_t *pkt1_size,
uint8_t *pkt2, size_t *pkt2_size); uint8_t *pkt2, size_t *pkt2_size);
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl); void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl);
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport); void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport);
void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst); void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind); uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind);
uint32_t *tcp_find_timestamps(struct tcphdr *tcp); uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp); uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
uint16_t tcp_find_mss(struct tcphdr *tcp);
bool tcp_has_sack(struct tcphdr *tcp);
bool tcp_has_fastopen(const struct tcphdr *tcp); bool tcp_has_fastopen(const struct tcphdr *tcp);
bool ip_has_df(const struct ip *ip);
#ifdef __CYGWIN__ #ifdef __CYGWIN__
extern uint32_t w_win32_error; extern uint32_t w_win32_error;
@ -258,13 +242,15 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
typedef struct typedef struct
{ {
int8_t delta; uint8_t delta, min, max;
uint8_t min, max;
} autottl; } autottl;
#define AUTOTTL_DEFAULT_DELTA 1
#define AUTOTTL_DEFAULT_MIN 3
#define AUTOTTL_DEFAULT_MAX 20
#define AUTOTTL_ENABLED(a) (!!(a).delta) #define AUTOTTL_ENABLED(a) (!!(a).delta)
#define AUTOTTL_SET_DEFAULT(a) {(a).delta=AUTOTTL_DEFAULT_DELTA; (a).min=AUTOTTL_DEFAULT_MIN; (a).max=AUTOTTL_DEFAULT_MAX;}
uint8_t hop_count_guess(uint8_t ttl); uint8_t autottl_guess(uint8_t ttl, const autottl *attl);
uint8_t autottl_eval(uint8_t hop_count, const autottl *attl);
void do_nat(bool bOutbound, struct ip *ip, struct ip6_hdr *ip6, struct tcphdr *tcphdr, struct udphdr *udphdr, const struct sockaddr_in *target4, const struct sockaddr_in6 *target6); void do_nat(bool bOutbound, struct ip *ip, struct ip6_hdr *ip6, struct tcphdr *tcphdr, struct udphdr *udphdr, const struct sockaddr_in *target4, const struct sockaddr_in6 *target6);
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr); void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);

File diff suppressed because it is too large Load Diff

View File

@ -41,7 +41,7 @@ enum dpi_desync_mode {
}; };
extern const char *fake_http_request_default; extern const char *fake_http_request_default;
extern const uint8_t fake_tls_clienthello_default[680]; extern const uint8_t fake_tls_clienthello_default[648];
void randomize_default_tls_payload(uint8_t *p); void randomize_default_tls_payload(uint8_t *p);
enum dpi_desync_mode desync_mode_from_string(const char *s); enum dpi_desync_mode desync_mode_from_string(const char *s);
@ -52,4 +52,5 @@ bool desync_valid_second_stage(enum dpi_desync_mode mode);
bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode); bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode);
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode); bool desync_valid_second_stage_udp(enum dpi_desync_mode mode);
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, uint8_t *data_pkt, size_t *len_pkt); void desync_init(void);
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt);

View File

@ -65,8 +65,11 @@ int z_readfile(FILE *F, char **buf, size_t *size)
zerr: zerr:
inflateEnd(&zs); inflateEnd(&zs);
if (*buf)
{
free(*buf); free(*buf);
*buf = NULL; *buf = NULL;
}
return r; return r;
} }

View File

@ -9,7 +9,6 @@
#include <ctype.h> #include <ctype.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <libgen.h> #include <libgen.h>
#include <fcntl.h>
int unique_size_t(size_t *pu, int ct) int unique_size_t(size_t *pu, int ct)
{ {
@ -301,29 +300,6 @@ time_t file_mod_time(const char *filename)
struct stat st; struct stat st;
return stat(filename,&st)==-1 ? 0 : st.st_mtime; return stat(filename,&st)==-1 ? 0 : st.st_mtime;
} }
bool file_mod_signature(const char *filename, file_mod_sig *ms)
{
struct stat st;
if (stat(filename,&st)==-1)
{
FILE_MOD_RESET(ms);
return false;
}
ms->mod_time=st.st_mtime;
ms->size=st.st_size;
return true;
}
bool file_open_test(const char *filename, int flags)
{
int fd = open(filename,flags);
if (fd>=0)
{
close(fd);
return true;
}
return false;
}
bool pf_in_range(uint16_t port, const port_filter *pf) bool pf_in_range(uint16_t port, const port_filter *pf)
{ {
@ -391,12 +367,6 @@ void fill_random_az09(uint8_t *p,size_t sz)
} }
} }
void set_console_io_buffering(void)
{
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
}
bool set_env_exedir(const char *argv0) bool set_env_exedir(const char *argv0)
{ {
char *s,*d; char *s,*d;

View File

@ -9,8 +9,6 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#define UNARY_PLUS(v) (v>0 ? "+" : "")
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes. // this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
typedef union typedef union
{ {
@ -53,14 +51,6 @@ static inline void phton16(uint8_t *p, uint16_t v) {
p[0] = (uint8_t)(v >> 8); p[0] = (uint8_t)(v >> 8);
p[1] = v & 0xFF; p[1] = v & 0xFF;
} }
static inline uint32_t pntoh24(const uint8_t *p) {
return ((uint32_t)p[0] << 16) | ((uint32_t)p[1] << 8) | (uint32_t)p[2];
}
static inline void phton24(uint8_t *p, uint32_t v) {
p[0] = (uint8_t)(v>>16);
p[1] = (uint8_t)(v>>8);
p[2] = (uint8_t)v;
}
static inline uint32_t pntoh32(const uint8_t *p) { static inline uint32_t pntoh32(const uint8_t *p) {
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3]; return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
} }
@ -70,16 +60,7 @@ void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize
int fprint_localtime(FILE *F); int fprint_localtime(FILE *F);
typedef struct
{
time_t mod_time;
off_t size;
} file_mod_sig;
#define FILE_MOD_COMPARE(ms1,ms2) (((ms1)->mod_time==(ms2)->mod_time) && ((ms1)->size==(ms2)->size))
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
bool file_mod_signature(const char *filename, file_mod_sig *ms);
time_t file_mod_time(const char *filename); time_t file_mod_time(const char *filename);
bool file_open_test(const char *filename, int flags);
typedef struct typedef struct
{ {
@ -94,7 +75,6 @@ void fill_random_bytes(uint8_t *p,size_t sz);
void fill_random_az(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); void fill_random_az09(uint8_t *p,size_t sz);
void set_console_io_buffering(void);
bool set_env_exedir(const char *argv0); bool set_env_exedir(const char *argv0);

View File

@ -4,7 +4,7 @@
#include "helpers.h" #include "helpers.h"
// inplace tolower() and add to pool // inplace tolower() and add to pool
static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct) static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
{ {
char *p=*s; char *p=*s;
@ -17,16 +17,10 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
else else
{ {
// advance until eol lowering all chars // advance until eol lowering all chars
uint32_t flags = 0;
if (*p=='^')
{
p = ++(*s);
flags |= HOSTLIST_POOL_FLAG_STRICT_MATCH;
}
for (; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p); for (; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
if (!HostlistPoolAddStrLen(hostlist, *s, p-*s, flags)) if (!StrPoolAddStrLen(hostlist, *s, p-*s))
{ {
HostlistPoolDestroy(hostlist); StrPoolDestroy(hostlist);
*hostlist = NULL; *hostlist = NULL;
return false; return false;
} }
@ -38,12 +32,12 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
return true; return true;
} }
bool AppendHostlistItem(hostlist_pool **hostlist, char *s) bool AppendHostlistItem(strpool **hostlist, char *s)
{ {
return addpool(hostlist,&s,s+strlen(s),NULL); return addpool(hostlist,&s,s+strlen(s),NULL);
} }
bool AppendHostList(hostlist_pool **hostlist, const char *filename) bool AppendHostList(strpool **hostlist, const char *filename)
{ {
char *p, *e, s[256], *zbuf; char *p, *e, s[256], *zbuf;
size_t zsize; size_t zsize;
@ -111,22 +105,21 @@ static bool LoadHostList(struct hostlist_file *hfile)
{ {
if (hfile->filename) if (hfile->filename)
{ {
file_mod_sig fsig; time_t t = file_mod_time(hfile->filename);
if (!file_mod_signature(hfile->filename, &fsig)) if (!t)
{ {
// stat() error // stat() error
DLOG_PERROR("file_mod_signature");
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename); DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true; return true;
} }
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date if (t==hfile->mod_time) return true; // up to date
HostlistPoolDestroy(&hfile->hostlist); StrPoolDestroy(&hfile->hostlist);
if (!AppendHostList(&hfile->hostlist, hfile->filename)) if (!AppendHostList(&hfile->hostlist, hfile->filename))
{ {
HostlistPoolDestroy(&hfile->hostlist); StrPoolDestroy(&hfile->hostlist);
return false; return false;
} }
hfile->mod_sig=fsig; hfile->mod_time=t;
} }
return true; return true;
} }
@ -144,10 +137,10 @@ static bool LoadHostLists(struct hostlist_files_head *list)
return bres; return bres;
} }
bool NonEmptyHostlist(hostlist_pool **hostlist) bool NonEmptyHostlist(strpool **hostlist)
{ {
// add impossible hostname if the list is empty // add impossible hostname if the list is empty
return *hostlist ? true : HostlistPoolAddStrLen(hostlist, "@&()", 4, 0); return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4);
} }
static void MakeAutolistsNonEmpty() static void MakeAutolistsNonEmpty()
@ -170,34 +163,19 @@ bool LoadAllHostLists()
static bool SearchHostList(hostlist_pool *hostlist, const char *host) static bool SearchHostList(strpool *hostlist, const char *host)
{ {
if (hostlist) if (hostlist)
{ {
const char *p = host; const char *p = host;
const struct hostlist_pool *hp; bool bInHostList;
bool bHostFull=true;
while (p) while (p)
{ {
DLOG("hostlist check for %s : ", p); bInHostList = StrPoolCheckStr(hostlist, p);
hp = HostlistPoolGetStr(hostlist, p); DLOG("hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative");
if (hp) if (bInHostList) return true;
{
if ((hp->flags & HOSTLIST_POOL_FLAG_STRICT_MATCH) && !bHostFull)
{
DLOG("negative : strict_mismatch : %s != %s\n", p, host);
}
else
{
DLOG("positive\n");
return true;
}
}
else
DLOG("negative\n");
p = strchr(p, '.'); p = strchr(p, '.');
if (p) p++; if (p) p++;
bHostFull = false;
} }
} }
return false; return false;
@ -287,13 +265,11 @@ static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostl
} }
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename) struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
{ {
/*
if (filename && !file_mod_time(filename)) if (filename && !file_mod_time(filename))
{ {
DLOG_ERR("cannot access hostlist file '%s'\n",filename); DLOG_ERR("cannot access hostlist file '%s'\n",filename);
return NULL; return NULL;
} }
*/
return RegisterHostlist_( return RegisterHostlist_(
&params.hostlists, &params.hostlists,
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection, bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,

View File

@ -4,14 +4,12 @@
#include "pools.h" #include "pools.h"
#include "params.h" #include "params.h"
bool AppendHostlistItem(hostlist_pool **hostlist, char *s); bool AppendHostlistItem(strpool **hostlist, char *s);
bool AppendHostList(hostlist_pool **hostlist, const char *filename); bool AppendHostList(strpool **hostlist, const char *filename);
bool LoadAllHostLists(); bool LoadAllHostLists();
bool NonEmptyHostlist(hostlist_pool **hostlist); bool NonEmptyHostlist(strpool **hostlist);
// return : true = apply fooling, false = do not apply // return : true = apply fooling, false = do not apply
bool HostlistCheck(const struct desync_profile *dp,const char *host, bool *excluded, bool bSkipReloadCheck); bool HostlistCheck(const struct desync_profile *dp,const char *host, bool *excluded, bool bSkipReloadCheck);
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename); struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename);
bool HostlistsReloadCheckForProfile(const struct desync_profile *dp); bool HostlistsReloadCheckForProfile(const struct desync_profile *dp);
void HostlistsDebug(); void HostlistsDebug();
#define ResetAllHostlistsModTime() hostlist_files_reset_modtime(&params.hostlists)

View File

@ -126,22 +126,21 @@ static bool LoadIpset(struct ipset_file *hfile)
{ {
if (hfile->filename) if (hfile->filename)
{ {
file_mod_sig fsig; time_t t = file_mod_time(hfile->filename);
if (!file_mod_signature(hfile->filename, &fsig)) if (!t)
{ {
// stat() error // stat() error
DLOG_PERROR("file_mod_signature");
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename); DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true; return true;
} }
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date if (t==hfile->mod_time) return true; // up to date
ipsetDestroy(&hfile->ipset); ipsetDestroy(&hfile->ipset);
if (!AppendIpset(&hfile->ipset, hfile->filename)) if (!AppendIpset(&hfile->ipset, hfile->filename))
{ {
ipsetDestroy(&hfile->ipset); ipsetDestroy(&hfile->ipset);
return false; return false;
} }
hfile->mod_sig=fsig; hfile->mod_time=t;
} }
return true; return true;
} }

View File

@ -10,5 +10,3 @@ bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, con
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename); struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
void IpsetsDebug(); void IpsetsDebug();
bool AppendIpsetItem(ipset *ips, char *ip); bool AppendIpsetItem(ipset *ips, char *ip);
#define ResetAllIpsetModTime() ipset_files_reset_modtime(&params.ipsets)

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include "packet_queue.h" #include "packet_queue.h"
@ -26,7 +25,7 @@ void rawpacket_queue_destroy(struct rawpacket_tailhead *q)
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp); while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
} }
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload) struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len,size_t len_payload)
{ {
struct rawpacket *rp = malloc(sizeof(struct rawpacket)); struct rawpacket *rp = malloc(sizeof(struct rawpacket));
if (!rp) return NULL; if (!rp) return NULL;
@ -40,14 +39,13 @@ struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sock
rp->dst = *dst; rp->dst = *dst;
rp->fwmark = fwmark; rp->fwmark = fwmark;
if (ifin)
snprintf(rp->ifin,sizeof(rp->ifin),"%s",ifin);
else
*rp->ifin = 0;
if (ifout) if (ifout)
snprintf(rp->ifout,sizeof(rp->ifout),"%s",ifout); {
strncpy(rp->ifout,ifout,sizeof(rp->ifout));
rp->ifout[sizeof(rp->ifout)-1]=0;
}
else else
*rp->ifout = 0; rp->ifout[0]=0;
memcpy(rp->packet,data,len); memcpy(rp->packet,data,len);
rp->len=len; rp->len=len;
rp->len_payload=len_payload; rp->len_payload=len_payload;

View File

@ -9,7 +9,7 @@
struct rawpacket struct rawpacket
{ {
struct sockaddr_storage dst; struct sockaddr_storage dst;
char ifin[IFNAMSIZ], ifout[IFNAMSIZ]; char ifout[IFNAMSIZ+1];
uint32_t fwmark; uint32_t fwmark;
size_t len, len_payload; size_t len, len_payload;
uint8_t *packet; uint8_t *packet;
@ -21,6 +21,6 @@ void rawpacket_queue_init(struct rawpacket_tailhead *q);
void rawpacket_queue_destroy(struct rawpacket_tailhead *q); void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q); bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q); unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload); struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len,size_t len_payload);
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q); struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
void rawpacket_free(struct rawpacket *rp); void rawpacket_free(struct rawpacket *rp);

View File

@ -65,7 +65,6 @@ static int DLOG_VA(const char *format, int syslog_priority, bool condup, va_list
{ {
va_copy(args2,args); va_copy(args2,args);
DLOG_CON(format,syslog_priority,args2); DLOG_CON(format,syslog_priority,args2);
va_end(args2);
} }
if (params.debug) if (params.debug)
{ {
@ -185,57 +184,29 @@ void dp_init(struct desync_profile *dp)
dp->desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT; dp->desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT;
dp->desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT; dp->desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT;
dp->desync_repeats = 1; dp->desync_repeats = 1;
dp->fake_tls_size = sizeof(fake_tls_clienthello_default);
memcpy(dp->fake_tls,fake_tls_clienthello_default,dp->fake_tls_size);
randomize_default_tls_payload(dp->fake_tls);
dp->fake_http_size = strlen(fake_http_request_default);
memcpy(dp->fake_http,fake_http_request_default,dp->fake_http_size);
dp->fake_quic_size = 620; // must be 601+ for TSPU hack
dp->fake_quic[0] = 0x40; // russian TSPU QUIC short header fake
dp->fake_wg_size = 64;
dp->fake_dht_size = 64;
dp->fake_unknown_size = 256;
dp->fake_syndata_size = 16; dp->fake_syndata_size = 16;
dp->fake_unknown_udp_size = 64;
dp->wscale=-1; // default - dont change scale factor (client) dp->wscale=-1; // default - dont change scale factor (client)
dp->desync_ttl6 = dp->dup_ttl6 = dp->orig_mod_ttl6 = 0xFF; // unused dp->desync_ttl6 = 0xFF; // unused
dp->desync_badseq_increment = dp->dup_badseq_increment = BADSEQ_INCREMENT_DEFAULT; dp->desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
dp->desync_badseq_ack_increment = dp->dup_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT; dp->desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = dp->dup_start_mode = dp->dup_cutoff_mode = dp->orig_mod_start_mode = dp->orig_mod_cutoff_mode = 'n'; // packet number by default dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = 'n'; // packet number by default
dp->udplen_increment = UDPLEN_INCREMENT_DEFAULT; dp->udplen_increment = UDPLEN_INCREMENT_DEFAULT;
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT; dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT; dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT; dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
dp->filter_ipv4 = dp->filter_ipv6 = true; dp->filter_ipv4 = dp->filter_ipv6 = true;
} }
bool dp_fake_defaults(struct desync_profile *dp)
{
struct blob_item *item;
if (blob_collection_empty(&dp->fake_http))
if (!blob_collection_add_blob(&dp->fake_http,fake_http_request_default,strlen(fake_http_request_default),0))
return false;
if (blob_collection_empty(&dp->fake_tls))
{
if (!(item=blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(((struct fake_tls_mod*)0)->sni))))
return false;
if (!(item->extra2 = malloc(sizeof(struct fake_tls_mod))))
return false;
*(struct fake_tls_mod*)item->extra2 = dp->tls_mod_last;
}
if (blob_collection_empty(&dp->fake_unknown))
{
if (!(item=blob_collection_add_blob(&dp->fake_unknown,NULL,256,0)))
return false;
memset(item->data,0,item->size);
}
if (blob_collection_empty(&dp->fake_quic))
{
if (!(item=blob_collection_add_blob(&dp->fake_quic,NULL,620,0)))
return false;
memset(item->data,0,item->size);
item->data[0] = 0x40;
}
struct blob_collection_head **fake,*fakes_z64[] = {&dp->fake_wg, &dp->fake_dht, &dp->fake_discord, &dp->fake_stun, &dp->fake_unknown_udp,NULL};
for(fake=fakes_z64;*fake;fake++)
{
if (blob_collection_empty(*fake))
{
if (!(item=blob_collection_add_blob(*fake,NULL,64,0)))
return false;
memset(item->data,0,item->size);
}
}
return true;
}
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head) struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
{ {
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list)); struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
@ -264,8 +235,6 @@ static void dp_clear_dynamic(struct desync_profile *dp)
port_filters_destroy(&dp->pf_tcp); port_filters_destroy(&dp->pf_tcp);
port_filters_destroy(&dp->pf_udp); port_filters_destroy(&dp->pf_udp);
HostFailPoolDestroy(&dp->hostlist_auto_fail_counters); HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
struct blob_collection_head **fake,*fakes[] = {&dp->fake_http, &dp->fake_tls, &dp->fake_unknown, &dp->fake_unknown_udp, &dp->fake_quic, &dp->fake_wg, &dp->fake_dht, &dp->fake_discord, &dp->fake_stun, NULL};
for(fake=fakes;*fake;fake++) blob_collection_destroy(*fake);
} }
void dp_clear(struct desync_profile *dp) void dp_clear(struct desync_profile *dp)
{ {
@ -294,12 +263,3 @@ bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
return true; return true;
return false; return false;
} }
// check if we need empty outgoing ACK
bool dp_list_need_all_out(struct desync_profile_list_head *head)
{
struct desync_profile_list *dpl;
LIST_FOREACH(dpl, head, next)
if (dpl->dp.dup_repeats || PROFILE_HAS_ORIG_MOD(&dpl->dp))
return true;
return false;
}

View File

@ -20,6 +20,8 @@
#define TLS_PARTIALS_ENABLE true #define TLS_PARTIALS_ENABLE true
#define Q_RCVBUF (128*1024) // in bytes
#define Q_SNDBUF (64*1024) // in bytes
#define RAW_SNDBUF (64*1024) // in bytes #define RAW_SNDBUF (64*1024) // in bytes
#define Q_MAXLEN 1024 // in packets #define Q_MAXLEN 1024 // in packets
@ -36,49 +38,10 @@
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60 #define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
#define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3 #define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3
#define IPCACHE_LIFETIME 7200
#define AUTOTTL_DEFAULT_DESYNC_DELTA -1
#define AUTOTTL_DEFAULT_DESYNC_MIN 3
#define AUTOTTL_DEFAULT_DESYNC_MAX 20
#define AUTOTTL_DEFAULT_ORIG_DELTA +5
#define AUTOTTL_DEFAULT_ORIG_MIN 3
#define AUTOTTL_DEFAULT_ORIG_MAX 64
#define AUTOTTL_DEFAULT_DUP_DELTA -1
#define AUTOTTL_DEFAULT_DUP_MIN 3
#define AUTOTTL_DEFAULT_DUP_MAX 64
#define MAX_SPLITS 64 #define MAX_SPLITS 64
#define FAKE_TLS_MOD_SAVE_MASK 0x0F
#define FAKE_TLS_MOD_SET 0x01
#define FAKE_TLS_MOD_CUSTOM_FAKE 0x02
#define FAKE_TLS_MOD_RND 0x10
#define FAKE_TLS_MOD_DUP_SID 0x20
#define FAKE_TLS_MOD_RND_SNI 0x40
#define FAKE_TLS_MOD_SNI 0x80
#define FAKE_TLS_MOD_PADENCAP 0x100
#define FAKE_MAX_TCP 1460
#define FAKE_MAX_UDP 1472
#define MAX_GIDS 64
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG }; enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
struct fake_tls_mod_cache
{
size_t extlen_offset, padlen_offset;
};
struct fake_tls_mod
{
char sni[64];
uint32_t mod;
};
typedef enum {SS_NONE=0,SS_SYN,SS_SYNACK,SS_ACKSYN} t_synack_split;
struct desync_profile struct desync_profile
{ {
int n; // number of the profile int n; // number of the profile
@ -88,8 +51,6 @@ struct desync_profile
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int wssize_cutoff; unsigned int wssize_cutoff;
t_synack_split synack_split;
bool hostcase, hostnospace, domcase, methodeol; bool hostcase, hostnospace, domcase, methodeol;
char hostspell[4]; char hostspell[4];
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2; enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
@ -101,34 +62,15 @@ struct desync_profile
int split_count; int split_count;
struct proto_pos seqovl; struct proto_pos seqovl;
char dup_start_mode, dup_cutoff_mode; // n - packets, d - data packets, s - relative sequence
bool dup_replace;
unsigned int dup_start, dup_cutoff;
unsigned int dup_repeats;
uint8_t dup_ttl, dup_ttl6;
uint32_t dup_fooling_mode;
uint32_t dup_badseq_increment, dup_badseq_ack_increment;
autottl dup_autottl, dup_autottl6;
char orig_mod_start_mode, orig_mod_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int orig_mod_start, orig_mod_cutoff;
uint8_t orig_mod_ttl, orig_mod_ttl6;
autottl orig_autottl, orig_autottl6;
char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int desync_start, desync_cutoff; unsigned int desync_start, desync_cutoff;
uint8_t desync_ttl, desync_ttl6; uint8_t desync_ttl, desync_ttl6;
autottl desync_autottl, desync_autottl6; autottl desync_autottl, desync_autottl6;
uint32_t desync_fooling_mode; uint32_t desync_fooling_mode;
uint32_t desync_badseq_increment, desync_badseq_ack_increment; uint32_t desync_badseq_increment, desync_badseq_ack_increment;
uint8_t fake_http[1460],fake_tls[1460],fake_unknown[1460],fake_syndata[1460],seqovl_pattern[1460];
struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht,fake_discord,fake_stun; uint8_t fake_unknown_udp[1472],udplen_pattern[1472],fake_quic[1472],fake_wg[1472],fake_dht[1472];
uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],fsplit_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP]; size_t fake_http_size,fake_tls_size,fake_quic_size,fake_wg_size,fake_dht_size,fake_unknown_size,fake_syndata_size,fake_unknown_udp_size;
size_t fake_syndata_size;
struct fake_tls_mod tls_mod_last;
struct blob_item *tls_fake_last;
int udplen_increment; int udplen_increment;
bool filter_ipv4,filter_ipv6; bool filter_ipv4,filter_ipv6;
@ -147,10 +89,9 @@ struct desync_profile
hostfail_pool *hostlist_auto_fail_counters; hostfail_pool *hostlist_auto_fail_counters;
}; };
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&(dp)->ips_collection) && !LIST_FIRST(&(dp)->ips_collection_exclude)) #define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&dp->ips_collection) && !LIST_FIRST(&dp->ips_collection_exclude))
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&(dp)->ips_collection) && ipset_collection_is_empty(&(dp)->ips_collection_exclude)) #define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&dp->ips_collection) && ipset_collection_is_empty(&dp->ips_collection_exclude))
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&(dp)->hl_collection) && hostlist_collection_is_empty(&(dp)->hl_collection_exclude)) #define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&dp->hl_collection) && hostlist_collection_is_empty(&dp->hl_collection_exclude))
#define PROFILE_HAS_ORIG_MOD(dp) ((dp)->orig_mod_ttl || (dp)->orig_mod_ttl6)
struct desync_profile_list { struct desync_profile_list {
struct desync_profile dp; struct desync_profile dp;
@ -161,9 +102,7 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
void dp_entry_destroy(struct desync_profile_list *entry); void dp_entry_destroy(struct desync_profile_list *entry);
void dp_list_destroy(struct desync_profile_list_head *head); void dp_list_destroy(struct desync_profile_list_head *head);
bool dp_list_have_autohostlist(struct desync_profile_list_head *head); bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
bool dp_list_need_all_out(struct desync_profile_list_head *head);
void dp_init(struct desync_profile *dp); void dp_init(struct desync_profile *dp);
bool dp_fake_defaults(struct desync_profile *dp);
void dp_clear(struct desync_profile *dp); void dp_clear(struct desync_profile *dp);
struct params_s struct params_s
@ -176,8 +115,6 @@ struct params_s
char debug_logfile[PATH_MAX]; char debug_logfile[PATH_MAX];
bool debug; bool debug;
bool daemon;
#ifdef __linux__ #ifdef __linux__
int qnum; int qnum;
#elif defined(BSD) #elif defined(BSD)
@ -193,10 +130,8 @@ struct params_s
#else #else
bool droproot; bool droproot;
uid_t uid; uid_t uid;
gid_t gid[MAX_GIDS]; gid_t gid;
int gid_count;
#endif #endif
char pidfile[PATH_MAX];
char hostlist_auto_debuglog[PATH_MAX]; char hostlist_auto_debuglog[PATH_MAX];
@ -207,11 +142,6 @@ struct params_s
unsigned int ctrack_t_syn, ctrack_t_est, ctrack_t_fin, ctrack_t_udp; unsigned int ctrack_t_syn, ctrack_t_est, ctrack_t_fin, ctrack_t_udp;
t_conntrack conntrack; t_conntrack conntrack;
bool ctrack_disable;
bool autottl_present,cache_hostname;
unsigned int ipcache_lifetime;
ip_cache ipcache;
}; };
extern struct params_s params; extern struct params_s params;

View File

@ -3,7 +3,6 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <arpa/inet.h>
#define DESTROY_STR_POOL(etype, ppool) \ #define DESTROY_STR_POOL(etype, ppool) \
etype *elem, *tmp; \ etype *elem, *tmp; \
@ -32,9 +31,6 @@
free(elem); \ free(elem); \
return false; \ return false; \
} }
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
elem->flags = flg;
#undef uthash_nonfatal_oom #undef uthash_nonfatal_oom
@ -46,31 +42,27 @@ static void ut_oom_recover(void *elem)
} }
// for not zero terminated strings // for not zero terminated strings
bool HostlistPoolAddStrLen(hostlist_pool **pp, const char *s, size_t slen, uint32_t flags) bool StrPoolAddStrLen(strpool **pp, const char *s, size_t slen)
{ {
ADD_HOSTLIST_POOL(hostlist_pool, pp, s, slen, flags) ADD_STR_POOL(strpool, pp, s, slen)
return true; return true;
} }
// for zero terminated strings // for zero terminated strings
bool HostlistPoolAddStr(hostlist_pool **pp, const char *s, uint32_t flags) bool StrPoolAddStr(strpool **pp, const char *s)
{ {
return HostlistPoolAddStrLen(pp, s, strlen(s), flags); return StrPoolAddStrLen(pp, s, strlen(s));
} }
hostlist_pool *HostlistPoolGetStr(hostlist_pool *p, const char *s) bool StrPoolCheckStr(strpool *p, const char *s)
{ {
hostlist_pool *elem; strpool *elem;
HASH_FIND_STR(p, s, elem); HASH_FIND_STR(p, s, elem);
return elem; return elem != NULL;
}
bool HostlistPoolCheckStr(hostlist_pool *p, const char *s)
{
return !!HostlistPoolGetStr(p,s);
} }
void HostlistPoolDestroy(hostlist_pool **pp) void StrPoolDestroy(strpool **pp)
{ {
DESTROY_STR_POOL(hostlist_pool, pp) DESTROY_STR_POOL(strpool, pp)
} }
@ -147,7 +139,7 @@ bool strlist_add(struct str_list_head *head, const char *filename)
} }
static void strlist_entry_destroy(struct str_list *entry) static void strlist_entry_destroy(struct str_list *entry)
{ {
free(entry->str); if (entry->str) free(entry->str);
free(entry); free(entry);
} }
void strlist_destroy(struct str_list_head *head) void strlist_destroy(struct str_list_head *head)
@ -162,6 +154,7 @@ void strlist_destroy(struct str_list_head *head)
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename) struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename)
{ {
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file)); struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
@ -177,7 +170,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
} }
else else
entry->filename = NULL; entry->filename = NULL;
FILE_MOD_RESET(&entry->mod_sig); entry->mod_time = 0;
entry->hostlist = NULL; entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next); LIST_INSERT_HEAD(head, entry, next);
} }
@ -185,8 +178,8 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
} }
static void hostlist_files_entry_destroy(struct hostlist_file *entry) static void hostlist_files_entry_destroy(struct hostlist_file *entry)
{ {
free(entry->filename); if (entry->filename) free(entry->filename);
HostlistPoolDestroy(&entry->hostlist); StrPoolDestroy(&entry->hostlist);
free(entry); free(entry);
} }
void hostlist_files_destroy(struct hostlist_files_head *head) void hostlist_files_destroy(struct hostlist_files_head *head)
@ -209,13 +202,6 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
} }
return NULL; return NULL;
} }
void hostlist_files_reset_modtime(struct hostlist_files_head *list)
{
struct hostlist_file *hfile;
LIST_FOREACH(hfile, list, next)
FILE_MOD_RESET(&hfile->mod_sig);
}
struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile) struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile)
{ {
@ -398,7 +384,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
} }
else else
entry->filename = NULL; entry->filename = NULL;
FILE_MOD_RESET(&entry->mod_sig); entry->mod_time = 0;
memset(&entry->ipset,0,sizeof(entry->ipset)); memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next); LIST_INSERT_HEAD(head, entry, next);
} }
@ -406,7 +392,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
} }
static void ipset_files_entry_destroy(struct ipset_file *entry) static void ipset_files_entry_destroy(struct ipset_file *entry)
{ {
free(entry->filename); if (entry->filename) free(entry->filename);
ipsetDestroy(&entry->ipset); ipsetDestroy(&entry->ipset);
free(entry); free(entry);
} }
@ -430,13 +416,6 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
} }
return NULL; return NULL;
} }
void ipset_files_reset_modtime(struct ipset_files_head *list)
{
struct ipset_file *hfile;
LIST_FOREACH(hfile, list, next)
FILE_MOD_RESET(&hfile->mod_sig);
}
struct ipset_item *ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile) struct ipset_item *ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile)
{ {
@ -518,281 +497,3 @@ bool port_filters_deny_if_empty(struct port_filters_head *head)
if (LIST_FIRST(head)) return true; if (LIST_FIRST(head)) return true;
return pf_parse("0",&pf) && port_filter_add(head,&pf); return pf_parse("0",&pf) && port_filter_add(head,&pf);
} }
struct blob_item *blob_collection_add(struct blob_collection_head *head)
{
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
if (entry)
{
// insert to the end
struct blob_item *itemc,*iteml=LIST_FIRST(head);
if (iteml)
{
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
LIST_INSERT_AFTER(iteml, entry, next);
}
else
LIST_INSERT_HEAD(head, entry, next);
}
return entry;
}
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve)
{
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
if (!entry) return NULL;
if (!(entry->data = malloc(size+size_reserve)))
{
free(entry);
return NULL;
}
if (data) memcpy(entry->data,data,size);
entry->size = size;
entry->size_buf = size+size_reserve;
// insert to the end
struct blob_item *itemc,*iteml=LIST_FIRST(head);
if (iteml)
{
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
LIST_INSERT_AFTER(iteml, entry, next);
}
else
LIST_INSERT_HEAD(head, entry, next);
return entry;
}
void blob_collection_destroy(struct blob_collection_head *head)
{
struct blob_item *entry;
while ((entry = LIST_FIRST(head)))
{
LIST_REMOVE(entry, next);
free(entry->extra);
free(entry->extra2);
free(entry->data);
free(entry);
}
}
bool blob_collection_empty(const struct blob_collection_head *head)
{
return !LIST_FIRST(head);
}
static void ipcache_item_touch(ip_cache_item *item)
{
time(&item->last);
}
static void ipcache_item_init(ip_cache_item *item)
{
ipcache_item_touch(item);
item->hostname = NULL;
item->hops = 0;
}
static void ipcache_item_destroy(ip_cache_item *item)
{
free(item->hostname);
}
static void ipcache4Destroy(ip_cache4 **ipcache)
{
ip_cache4 *elem, *tmp;
HASH_ITER(hh, *ipcache, elem, tmp)
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
static void ipcache4Key(ip4if *key, const struct in_addr *a, const char *iface)
{
memset(key,0,sizeof(*key)); // make sure everything is zero
key->addr = *a;
if (iface) snprintf(key->iface,sizeof(key->iface),"%s",iface);
}
static ip_cache4 *ipcache4Find(ip_cache4 *ipcache, const struct in_addr *a, const char *iface)
{
ip_cache4 *entry;
struct ip4if key;
ipcache4Key(&key,a,iface);
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
return entry;
}
static ip_cache4 *ipcache4Add(ip_cache4 **ipcache, const struct in_addr *a, const char *iface)
{
// avoid dups
ip_cache4 *entry = ipcache4Find(*ipcache,a,iface);
if (entry) return entry; // already included
entry = malloc(sizeof(ip_cache4));
if (!entry) return NULL;
ipcache4Key(&entry->key,a,iface);
oom = false;
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
if (oom) { free(entry); return NULL; }
ipcache_item_init(&entry->data);
return entry;
}
static void ipcache4Print(ip_cache4 *ipcache)
{
char s_ip[16];
time_t now;
ip_cache4 *ipc, *tmp;
time(&now);
HASH_ITER(hh, ipcache , ipc, tmp)
{
*s_ip=0;
inet_ntop(AF_INET, &ipc->key.addr, s_ip, sizeof(s_ip));
printf("%s iface=%s : hops %u hostname=%s now=last+%llu\n", s_ip, ipc->key.iface, ipc->data.hops, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
}
}
static void ipcache6Destroy(ip_cache6 **ipcache)
{
ip_cache6 *elem, *tmp;
HASH_ITER(hh, *ipcache, elem, tmp)
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
static void ipcache6Key(ip6if *key, const struct in6_addr *a, const char *iface)
{
memset(key,0,sizeof(*key)); // make sure everything is zero
key->addr = *a;
if (iface) snprintf(key->iface,sizeof(key->iface),"%s",iface);
}
static ip_cache6 *ipcache6Find(ip_cache6 *ipcache, const struct in6_addr *a, const char *iface)
{
ip_cache6 *entry;
ip6if key;
ipcache6Key(&key,a,iface);
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
return entry;
}
static ip_cache6 *ipcache6Add(ip_cache6 **ipcache, const struct in6_addr *a, const char *iface)
{
// avoid dups
ip_cache6 *entry = ipcache6Find(*ipcache,a,iface);
if (entry) return entry; // already included
entry = malloc(sizeof(ip_cache6));
if (!entry) return NULL;
ipcache6Key(&entry->key,a,iface);
oom = false;
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
if (oom) { free(entry); return NULL; }
ipcache_item_init(&entry->data);
return entry;
}
static void ipcache6Print(ip_cache6 *ipcache)
{
char s_ip[40];
time_t now;
ip_cache6 *ipc, *tmp;
time(&now);
HASH_ITER(hh, ipcache , ipc, tmp)
{
*s_ip=0;
inet_ntop(AF_INET6, &ipc->key.addr, s_ip, sizeof(s_ip));
printf("%s iface=%s : hops %u hostname=%s now=last+%llu\n", s_ip, ipc->key.iface, ipc->data.hops, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
}
}
void ipcacheDestroy(ip_cache *ipcache)
{
ipcache4Destroy(&ipcache->ipcache4);
ipcache6Destroy(&ipcache->ipcache6);
}
void ipcachePrint(ip_cache *ipcache)
{
ipcache4Print(ipcache->ipcache4);
ipcache6Print(ipcache->ipcache6);
}
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
{
ip_cache4 *ipcache4;
ip_cache6 *ipcache6;
if (a4)
{
if ((ipcache4 = ipcache4Add(&ipcache->ipcache4,a4,iface)))
{
ipcache_item_touch(&ipcache4->data);
return &ipcache4->data;
}
}
else if (a6)
{
if ((ipcache6 = ipcache6Add(&ipcache->ipcache6,a6,iface)))
{
ipcache_item_touch(&ipcache6->data);
return &ipcache6->data;
}
}
return NULL;
}
static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
{
ip_cache4 *elem, *tmp;
time_t now = time(NULL);
HASH_ITER(hh, *ipcache, elem, tmp)
{
if (now >= (elem->data.last + lifetime))
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
}
static void ipcache6_purge(ip_cache6 **ipcache, time_t lifetime)
{
ip_cache6 *elem, *tmp;
time_t now = time(NULL);
HASH_ITER(hh, *ipcache, elem, tmp)
{
if (now >= (elem->data.last + lifetime))
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
}
static void ipcache_purge(ip_cache *ipcache, time_t lifetime)
{
if (lifetime) // 0 = no expire
{
ipcache4_purge(&ipcache->ipcache4, lifetime);
ipcache6_purge(&ipcache->ipcache6, lifetime);
}
}
static time_t ipcache_purge_prev=0;
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime)
{
time_t now = time(NULL);
// do not purge too often to save resources
if (ipcache_purge_prev != now)
{
ipcache_purge(ipcache, lifetime);
ipcache_purge_prev = now;
}
}

View File

@ -3,7 +3,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <ctype.h> #include <ctype.h>
#include <sys/queue.h> #include <sys/queue.h>
#include <net/if.h>
#include <time.h> #include <time.h>
#include "helpers.h" #include "helpers.h"
@ -13,18 +12,15 @@
#define HASH_FUNCTION HASH_BER #define HASH_FUNCTION HASH_BER
#include "uthash.h" #include "uthash.h"
#define HOSTLIST_POOL_FLAG_STRICT_MATCH 1 typedef struct strpool {
typedef struct hostlist_pool {
char *str; /* key */ char *str; /* key */
uint32_t flags; /* custom data */
UT_hash_handle hh; /* makes this structure hashable */ UT_hash_handle hh; /* makes this structure hashable */
} hostlist_pool; } strpool;
void HostlistPoolDestroy(hostlist_pool **pp); void StrPoolDestroy(strpool **pp);
bool HostlistPoolAddStr(hostlist_pool **pp, const char *s, uint32_t flags); bool StrPoolAddStr(strpool **pp,const char *s);
bool HostlistPoolAddStrLen(hostlist_pool **pp, const char *s, size_t slen, uint32_t flags); bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen);
hostlist_pool *HostlistPoolGetStr(hostlist_pool *p, const char *s); bool StrPoolCheckStr(strpool *p,const char *s);
struct str_list { struct str_list {
char *str; char *str;
@ -54,8 +50,8 @@ void strlist_destroy(struct str_list_head *head);
struct hostlist_file { struct hostlist_file {
char *filename; char *filename;
file_mod_sig mod_sig; time_t mod_time;
hostlist_pool *hostlist; strpool *hostlist;
LIST_ENTRY(hostlist_file) next; LIST_ENTRY(hostlist_file) next;
}; };
LIST_HEAD(hostlist_files_head, hostlist_file); LIST_HEAD(hostlist_files_head, hostlist_file);
@ -63,7 +59,6 @@ LIST_HEAD(hostlist_files_head, hostlist_file);
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename); struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename);
void hostlist_files_destroy(struct hostlist_files_head *head); void hostlist_files_destroy(struct hostlist_files_head *head);
struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, const char *filename); struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, const char *filename);
void hostlist_files_reset_modtime(struct hostlist_files_head *list);
struct hostlist_item { struct hostlist_item {
struct hostlist_file *hfile; struct hostlist_file *hfile;
@ -116,7 +111,7 @@ void ipsetPrint(ipset *ipset);
struct ipset_file { struct ipset_file {
char *filename; char *filename;
file_mod_sig mod_sig; time_t mod_time;
ipset ipset; ipset ipset;
LIST_ENTRY(ipset_file) next; LIST_ENTRY(ipset_file) next;
}; };
@ -125,7 +120,6 @@ LIST_HEAD(ipset_files_head, ipset_file);
struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *filename); struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *filename);
void ipset_files_destroy(struct ipset_files_head *head); void ipset_files_destroy(struct ipset_files_head *head);
struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char *filename); struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char *filename);
void ipset_files_reset_modtime(struct ipset_files_head *list);
struct ipset_item { struct ipset_item {
struct ipset_file *hfile; struct ipset_file *hfile;
@ -147,58 +141,3 @@ bool port_filter_add(struct port_filters_head *head, const port_filter *pf);
void port_filters_destroy(struct port_filters_head *head); void port_filters_destroy(struct port_filters_head *head);
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port); bool port_filters_in_range(const struct port_filters_head *head, uint16_t port);
bool port_filters_deny_if_empty(struct port_filters_head *head); bool port_filters_deny_if_empty(struct port_filters_head *head);
struct blob_item {
uint8_t *data; // main data blob
size_t size; // main data blob size
size_t size_buf;// main data blob allocated size
void *extra; // any data without size
void *extra2; // any data without size
LIST_ENTRY(blob_item) next;
};
LIST_HEAD(blob_collection_head, blob_item);
struct blob_item *blob_collection_add(struct blob_collection_head *head);
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve);
void blob_collection_destroy(struct blob_collection_head *head);
bool blob_collection_empty(const struct blob_collection_head *head);
typedef struct ip4if
{
char iface[IFNAMSIZ];
struct in_addr addr;
} ip4if;
typedef struct ip6if
{
char iface[IFNAMSIZ];
struct in6_addr addr;
} ip6if;
typedef struct ip_cache_item
{
time_t last;
char *hostname;
uint8_t hops;
} ip_cache_item;
typedef struct ip_cache4
{
ip4if key;
ip_cache_item data;
UT_hash_handle hh; /* makes this structure hashable */
} ip_cache4;
typedef struct ip_cache6
{
ip6if key;
ip_cache_item data;
UT_hash_handle hh; /* makes this structure hashable */
} ip_cache6;
typedef struct ip_cache
{
ip_cache4 *ipcache4;
ip_cache6 *ipcache6;
} ip_cache;
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface);
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime);
void ipcacheDestroy(ip_cache *ipcache);
void ipcachePrint(ip_cache *ipcache);

View File

@ -2,8 +2,6 @@
#include "protocol.h" #include "protocol.h"
#include "helpers.h" #include "helpers.h"
#include "params.h"
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <arpa/inet.h> #include <arpa/inet.h>
@ -35,8 +33,6 @@ const char *l7proto_str(t_l7proto l7)
case QUIC: return "quic"; case QUIC: return "quic";
case WIREGUARD: return "wireguard"; case WIREGUARD: return "wireguard";
case DHT: return "dht"; case DHT: return "dht";
case DISCORD: return "discord";
case STUN: return "stun";
default: return "unknown"; default: return "unknown";
} }
} }
@ -47,9 +43,7 @@ bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7)
(l7proto==TLS && (filter_l7 & L7_PROTO_TLS)) || (l7proto==TLS && (filter_l7 & L7_PROTO_TLS)) ||
(l7proto==QUIC && (filter_l7 & L7_PROTO_QUIC)) || (l7proto==QUIC && (filter_l7 & L7_PROTO_QUIC)) ||
(l7proto==WIREGUARD && (filter_l7 & L7_PROTO_WIREGUARD)) || (l7proto==WIREGUARD && (filter_l7 & L7_PROTO_WIREGUARD)) ||
(l7proto==DHT && (filter_l7 & L7_PROTO_DHT)) || (l7proto==DHT && (filter_l7 & L7_PROTO_DHT));
(l7proto==DISCORD && (filter_l7 & L7_PROTO_DISCORD)) ||
(l7proto==STUN && (filter_l7 & L7_PROTO_STUN));
} }
#define PM_ABS 0 #define PM_ABS 0
@ -157,7 +151,7 @@ void ResolveMultiPos(const uint8_t *data, size_t sz, t_l7proto l7proto, const st
} }
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS ","PUT /","DELETE /","CONNECT ","TRACE /",NULL }; const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL };
const char *HttpMethod(const uint8_t *data, size_t len) const char *HttpMethod(const uint8_t *data, size_t len)
{ {
const char **method; const char **method;
@ -345,19 +339,6 @@ size_t HttpPos(uint8_t posmarker, int16_t pos, const uint8_t *data, size_t sz)
} }
const char *TLSVersionStr(uint16_t tlsver)
{
switch(tlsver)
{
case 0x0301: return "TLS 1.0";
case 0x0302: return "TLS 1.1";
case 0x0303: return "TLS 1.2";
case 0x0304: return "TLS 1.3";
default:
// 0x0a0a, 0x1a1a, ..., 0xfafa
return (((tlsver & 0x0F0F) == 0x0A0A) && ((tlsver>>12)==((tlsver>>4)&0xF))) ? "GREASE" : "UNKNOWN";
}
}
uint16_t TLSRecordDataLen(const uint8_t *data) uint16_t TLSRecordDataLen(const uint8_t *data)
{ {
@ -390,46 +371,6 @@ bool IsTLSHandshakeFull(const uint8_t *data, size_t len)
} }
bool TLSFindExtLenOffsetInHandshake(const uint8_t *data, size_t len, size_t *off)
{
// +0
// u8 HandshakeType: ClientHello
// u24 Length
// u16 Version
// c[32] random
// u8 SessionIDLength
// <SessionID>
// u16 CipherSuitesLength
// <CipherSuites>
// u8 CompressionMethodsLength
// <CompressionMethods>
// u16 ExtensionsLength
size_t l;
l = 1 + 3 + 2 + 32;
// SessionIDLength
if (len < (l + 1)) return false;
l += data[l] + 1;
// CipherSuitesLength
if (len < (l + 2)) return false;
l += pntoh16(data + l) + 2;
// CompressionMethodsLength
if (len < (l + 1)) return false;
l += data[l] + 1;
// ExtensionsLength
if (len < (l + 2)) return false;
*off = l;
return true;
}
bool TLSFindExtLen(const uint8_t *data, size_t len, size_t *off)
{
if (!TLSFindExtLenOffsetInHandshake(data+5,len-5,off))
return false;
*off+=5;
return true;
}
// bPartialIsOK=true - accept partial packets not containing the whole TLS message // bPartialIsOK=true - accept partial packets not containing the whole TLS message
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK) bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK)
{ {
@ -450,7 +391,18 @@ bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const
if (!bPartialIsOK && !IsTLSHandshakeFull(data,len)) return false; if (!bPartialIsOK && !IsTLSHandshakeFull(data,len)) return false;
if (!TLSFindExtLenOffsetInHandshake(data,len,&l)) return false; l = 1 + 3 + 2 + 32;
// SessionIDLength
if (len < (l + 1)) return false;
l += data[l] + 1;
// CipherSuitesLength
if (len < (l + 2)) return false;
l += pntoh16(data + l) + 2;
// CompressionMethodsLength
if (len < (l + 1)) return false;
l += data[l] + 1;
// ExtensionsLength
if (len < (l + 2)) return false;
data += l; len -= l; data += l; len -= l;
l = pntoh16(data); l = pntoh16(data);
@ -497,7 +449,7 @@ bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **
if (reclen<len) len=reclen; // correct len if it has more data than the first tls record has if (reclen<len) len=reclen; // correct len if it has more data than the first tls record has
return TLSFindExtInHandshake(data + 5, len - 5, type, ext, len_ext, bPartialIsOK); return TLSFindExtInHandshake(data + 5, len - 5, type, ext, len_ext, bPartialIsOK);
} }
bool TLSAdvanceToHostInSNI(const uint8_t **ext, size_t *elen, size_t *slen) static bool TLSAdvanceToHostInSNI(const uint8_t **ext, size_t *elen, size_t *slen)
{ {
// u16 data+0 - name list length // u16 data+0 - name list length
// u8 data+2 - server name type. 0=host_name // u8 data+2 - server name type. 0=host_name
@ -555,7 +507,7 @@ size_t TLSPos(uint8_t posmarker, int16_t pos, const uint8_t *data, size_t sz)
case PM_HOST_MIDSLD: case PM_HOST_MIDSLD:
case PM_HOST_ENDSLD: case PM_HOST_ENDSLD:
case PM_SNI_EXT: case PM_SNI_EXT:
if (TLSFindExt(data,sz,0,&ext,&elen,TLS_PARTIALS_ENABLE)) if (TLSFindExt(data,sz,0,&ext,&elen,false))
{ {
if (posmarker==PM_SNI_EXT) if (posmarker==PM_SNI_EXT)
{ {
@ -861,16 +813,7 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
return !memcmp(data + pn_offset + pkn_len + cryptlen, atag, 16); return !memcmp(data + pn_offset + pkn_len + cryptlen, atag, 16);
} }
struct range64 bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,size_t *defrag_len)
{
uint64_t offset,len;
};
#define MAX_DEFRAG_PIECES 128
static int cmp_range64(const void * a, const void * b)
{
return (((struct range64*)a)->offset < ((struct range64*)b)->offset) ? -1 : (((struct range64*)a)->offset > ((struct range64*)b)->offset) ? 1 : 0;
}
bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,size_t *defrag_len, bool *bFull)
{ {
// Crypto frame can be split into multiple chunks // Crypto frame can be split into multiple chunks
// chromium randomly splits it and pads with zero/one bytes to force support the standard // chromium randomly splits it and pads with zero/one bytes to force support the standard
@ -879,15 +822,13 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
if (*defrag_len<10) return false; if (*defrag_len<10) return false;
uint8_t *defrag_data = defrag+10; uint8_t *defrag_data = defrag+10;
size_t defrag_data_len = *defrag_len-10; size_t defrag_data_len = *defrag_len-10;
uint8_t ft; uint8_t ft;
uint64_t offset,sz,szmax=0,zeropos=0,pos=0; uint64_t offset,sz,szmax=0,zeropos=0,pos=0;
bool found=false; bool found=false;
struct range64 ranges[MAX_DEFRAG_PIECES];
int i,range=0;
while(pos<clean_len) while(pos<clean_len)
{ {
// frame type
ft = clean[pos]; ft = clean[pos];
pos++; pos++;
if (ft>1) // 00 - padding, 01 - ping if (ft>1) // 00 - padding, 01 - ping
@ -895,7 +836,6 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
if (ft!=6) return false; // dont want to know all possible frame type formats if (ft!=6) return false; // dont want to know all possible frame type formats
if (pos>=clean_len) return false; if (pos>=clean_len) return false;
if (range>=MAX_DEFRAG_PIECES) return false;
if ((pos+tvb_get_size(clean[pos])>=clean_len)) return false; if ((pos+tvb_get_size(clean[pos])>=clean_len)) return false;
pos += tvb_get_varint(clean+pos, &offset); pos += tvb_get_varint(clean+pos, &offset);
@ -904,7 +844,7 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
pos += tvb_get_varint(clean+pos, &sz); pos += tvb_get_varint(clean+pos, &sz);
if ((pos+sz)>clean_len) return false; if ((pos+sz)>clean_len) return false;
if ((offset+sz)>defrag_data_len) return false; // defrag buf overflow if ((offset+sz)>defrag_data_len) return false;
if (zeropos < offset) if (zeropos < offset)
// make sure no uninitialized gaps exist in case of not full fragment coverage // make sure no uninitialized gaps exist in case of not full fragment coverage
memset(defrag_data+zeropos,0,offset-zeropos); memset(defrag_data+zeropos,0,offset-zeropos);
@ -915,10 +855,6 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
found=true; found=true;
pos+=sz; pos+=sz;
ranges[range].offset = offset;
ranges[range].len = sz;
range++;
} }
} }
if (found) if (found)
@ -930,23 +866,6 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
phton64(defrag+2,szmax); phton64(defrag+2,szmax);
defrag[2] |= 0xC0; // 64 bit value defrag[2] |= 0xC0; // 64 bit value
*defrag_len = (size_t)(szmax+10); *defrag_len = (size_t)(szmax+10);
qsort(ranges, range, sizeof(*ranges), cmp_range64);
//for(i=0 ; i<range ; i++)
// printf("RANGE %zu len %zu\n",ranges[i].offset,ranges[i].len);
for(i=0,offset=0,*bFull=true ; i<range ; i++)
{
if (ranges[i].offset!=offset)
{
*bFull = false;
break;
}
offset += ranges[i].len;
}
//printf("bFull=%u\n",*bFull);
} }
return found; return found;
} }
@ -1017,25 +936,9 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len) bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len)
{ {
return len==148 && data[0]==1; return len==148 && data[0]==1 && data[1]==0 && data[2]==0 && data[3]==0;
} }
bool IsDhtD1(const uint8_t *data, size_t len) bool IsDhtD1(const uint8_t *data, size_t len)
{ {
return len>=7 && data[0]=='d' && data[1]=='1' && data[len-1]=='e'; return len>=7 && data[0]=='d' && data[1]=='1' && data[len-1]=='e';
} }
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len)
{
return len==74 &&
data[0]==0 && data[1]==1 &&
data[2]==0 && data[3]==70 &&
!memcmp(data+8,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",64);
// address is not set in request
}
bool IsStunMessage(const uint8_t *data, size_t len)
{
return len>=20 && // header size
(data[0]&0xC0)==0 && // 2 most significant bits must be zeroes
(data[3]&0b11)==0 && // length must be a multiple of 4
ntohl(*(uint32_t*)(&data[4]))==0x2112A442 && // magic cookie
ntohs(*(uint16_t*)(&data[2]))==len-20;
}

View File

@ -7,14 +7,12 @@
#include "crypto/aes-gcm.h" #include "crypto/aes-gcm.h"
#include "helpers.h" #include "helpers.h"
typedef enum {UNKNOWN=0, HTTP, TLS, QUIC, WIREGUARD, DHT, DISCORD, STUN} t_l7proto; typedef enum {UNKNOWN=0, HTTP, TLS, QUIC, WIREGUARD, DHT} t_l7proto;
#define L7_PROTO_HTTP 0x00000001 #define L7_PROTO_HTTP 0x00000001
#define L7_PROTO_TLS 0x00000002 #define L7_PROTO_TLS 0x00000002
#define L7_PROTO_QUIC 0x00000004 #define L7_PROTO_QUIC 0x00000004
#define L7_PROTO_WIREGUARD 0x00000008 #define L7_PROTO_WIREGUARD 0x00000008
#define L7_PROTO_DHT 0x00000010 #define L7_PROTO_DHT 0x00000010
#define L7_PROTO_DISCORD 0x00000020
#define L7_PROTO_STUN 0x00000040
#define L7_PROTO_UNKNOWN 0x80000000 #define L7_PROTO_UNKNOWN 0x80000000
const char *l7proto_str(t_l7proto l7); const char *l7proto_str(t_l7proto l7);
bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7); bool l7_proto_match(t_l7proto l7proto, uint32_t filter_l7);
@ -57,7 +55,6 @@ int HttpReplyCode(const uint8_t *data, size_t len);
// must be pre-checked by IsHttpReply // must be pre-checked by IsHttpReply
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host); bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
const char *TLSVersionStr(uint16_t tlsver);
uint16_t TLSRecordDataLen(const uint8_t *data); uint16_t TLSRecordDataLen(const uint8_t *data);
size_t TLSRecordLen(const uint8_t *data); size_t TLSRecordLen(const uint8_t *data);
bool IsTLSRecordFull(const uint8_t *data, size_t len); bool IsTLSRecordFull(const uint8_t *data, size_t len);
@ -65,9 +62,6 @@ bool IsTLSClientHello(const uint8_t *data, size_t len, bool bPartialIsOK);
size_t TLSHandshakeLen(const uint8_t *data); size_t TLSHandshakeLen(const uint8_t *data);
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len); bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len);
bool IsTLSHandshakeFull(const uint8_t *data, size_t len); bool IsTLSHandshakeFull(const uint8_t *data, size_t len);
bool TLSAdvanceToHostInSNI(const uint8_t **ext, size_t *elen, size_t *slen);
bool TLSFindExtLen(const uint8_t *data, size_t len, size_t *off);
bool TLSFindExtLenOffsetInHandshake(const uint8_t *data, size_t len, size_t *off);
bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK); bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK); bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK); bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
@ -75,8 +69,6 @@ bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *hos
bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len); bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len);
bool IsDhtD1(const uint8_t *data, size_t len); bool IsDhtD1(const uint8_t *data, size_t len);
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len);
bool IsStunMessage(const uint8_t *data, size_t len);
#define QUIC_MAX_CID_LENGTH 20 #define QUIC_MAX_CID_LENGTH 20
typedef struct quic_cid { typedef struct quic_cid {
@ -92,6 +84,5 @@ uint8_t QUICDraftVersion(uint32_t version);
bool QUICExtractDCID(const uint8_t *data, size_t len, quic_cid_t *cid); bool QUICExtractDCID(const uint8_t *data, size_t len, quic_cid_t *cid);
bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, size_t *clean_len); bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, size_t *clean_len);
// returns true if crypto frames were found . bFull = true if crypto frame fragments have full coverage bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,size_t *defrag_len);
bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,size_t *defrag_len, bool *bFull);
//bool QUICExtractHostFromInitial(const uint8_t *data, size_t data_len, char *host, size_t len_host, bool *bDecryptOK, bool *bIsCryptoHello); //bool QUICExtractHostFromInitial(const uint8_t *data, size_t data_len, char *host, size_t len_host, bool *bDecryptOK, bool *bIsCryptoHello);

View File

@ -88,6 +88,10 @@ SYS_symlinkat,
SYS_link, SYS_link,
#endif #endif
SYS_linkat, SYS_linkat,
#ifdef SYS_pkey_mprotect
SYS_pkey_mprotect,
#endif
SYS_mprotect,
SYS_truncate, SYS_truncate,
#ifdef SYS_truncate64 #ifdef SYS_truncate64
SYS_truncate64, SYS_truncate64,
@ -192,21 +196,20 @@ static bool set_seccomp(void)
bool sec_harden(void) bool sec_harden(void)
{ {
bool bRes = true;
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
{ {
DLOG_PERROR("PR_SET_NO_NEW_PRIVS(prctl)"); DLOG_PERROR("PR_SET_NO_NEW_PRIVS(prctl)");
bRes = false; return false;
} }
#if ARCH_NR!=0 #if ARCH_NR!=0
if (!set_seccomp()) if (!set_seccomp())
{ {
DLOG_PERROR("seccomp"); DLOG_PERROR("seccomp");
if (errno==EINVAL) DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n"); if (errno==EINVAL) DLOG_ERR("seccomp: this can be safely ignored if kernel does not support seccomp\n");
bRes = false; return false;
} }
#endif #endif
return bRes; return true;
} }
@ -288,20 +291,15 @@ bool can_drop_root(void)
{ {
#ifdef __linux__ #ifdef __linux__
// has some caps // has some caps
return checkpcap((1<<CAP_SETUID)|(1<<CAP_SETGID)); return checkpcap((1<<CAP_SETUID)|(1<<CAP_SETGID)|(1<<CAP_SETPCAP));
#else #else
// effective root // effective root
return !geteuid(); return !geteuid();
#endif #endif
} }
bool droproot(uid_t uid, gid_t *gid, int gid_count) bool droproot(uid_t uid, gid_t gid)
{ {
if (gid_count<1)
{
DLOG_ERR("droproot: no groups specified");
return false;
}
#ifdef __linux__ #ifdef __linux__
if (prctl(PR_SET_KEEPCAPS, 1L)) if (prctl(PR_SET_KEEPCAPS, 1L))
{ {
@ -310,12 +308,12 @@ bool droproot(uid_t uid, gid_t *gid, int gid_count)
} }
#endif #endif
// drop all SGIDs // drop all SGIDs
if (setgroups(gid_count,gid)) if (setgroups(0,NULL))
{ {
DLOG_PERROR("setgroups"); DLOG_PERROR("setgroups");
return false; return false;
} }
if (setgid(gid[0])) if (setgid(gid))
{ {
DLOG_PERROR("setgid"); DLOG_PERROR("setgid");
return false; return false;
@ -325,7 +323,11 @@ bool droproot(uid_t uid, gid_t *gid, int gid_count)
DLOG_PERROR("setuid"); DLOG_PERROR("setuid");
return false; return false;
} }
#ifdef __linux__
return dropcaps();
#else
return true; return true;
#endif
} }
void print_id(void) void print_id(void)
@ -348,13 +350,9 @@ void print_id(void)
#endif #endif
void daemonize(void) void daemonize(void)
{ {
int pid; int pid;
#ifdef __CYGWIN__
char *cwd = get_current_dir_name();
#endif
pid = fork(); pid = fork();
if (pid == -1) if (pid == -1)
@ -365,10 +363,6 @@ void daemonize(void)
else if (pid != 0) else if (pid != 0)
exit(0); exit(0);
#ifdef __CYGWIN__
chdir(get_current_dir_name());
#endif
if (setsid() == -1) if (setsid() == -1)
exit(2); exit(2);
if (chdir("/") == -1) if (chdir("/") == -1)

View File

@ -84,7 +84,7 @@ bool dropcaps(void);
#ifndef __CYGWIN__ #ifndef __CYGWIN__
bool sec_harden(void); bool sec_harden(void);
bool can_drop_root(void); bool can_drop_root(void);
bool droproot(uid_t uid, gid_t *gid, int gid_count); bool droproot(uid_t uid, gid_t gid);
void print_id(void); void print_id(void);
#endif #endif

View File

@ -6,7 +6,7 @@ SRC_FILES = *.c
all: tpws all: tpws
tpws: $(SRC_FILES) tpws: $(SRC_FILES)
$(CC) $(CFLAGS) -Iepoll-shim/include -o tpws $(SRC_FILES) epoll-shim/src/*.c $(LIBS) $(LDFLAGS) $(CC) $(CFLAGS) -Iepoll-shim/include -o tpws $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS)
clean: clean:
rm -f tpws *.o rm -f tpws *.o

View File

@ -1,9 +1,7 @@
CC ?= gcc CC ?= gcc
CFLAGS += -std=gnu99 -Os -flto=auto CFLAGS += -std=gnu99 -Os -flto=auto
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
CFLAGS_BSD = -Wno-address-of-packed-member CFLAGS_BSD = -Wno-address-of-packed-member
LIBS = -lz -lpthread LIBS = -lz -lpthread
LIBS_SYSTEMD = -lsystemd
LIBS_ANDROID = -lz LIBS_ANDROID = -lz
SRC_FILES = *.c SRC_FILES = *.c
SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c
@ -11,20 +9,17 @@ SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c
all: tpws all: tpws
tpws: $(SRC_FILES) tpws: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES) $(LIBS) $(LDFLAGS) $(CC) -s $(CFLAGS) -o tpws $(SRC_FILES) $(LDFLAGS) $(LIBS)
systemd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_SYSTEMD) -o tpws $(SRC_FILES) $(LIBS) $(LIBS_SYSTEMD) $(LDFLAGS)
android: $(SRC_FILES) android: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES_ANDROID) $(LIBS_ANDROID) $(LDFLAGS) $(CC) -s $(CFLAGS) -o tpws $(SRC_FILES_ANDROID) $(LDFLAGS) $(LIBS_ANDROID)
bsd: $(SRC_FILES) bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -o tpws $(SRC_FILES) epoll-shim/src/*.c $(LIBS) $(LDFLAGS) $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -o tpws $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS)
mac: $(SRC_FILES) mac: $(SRC_FILES)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsa -target arm64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LIBS) $(LDFLAGS) $(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsa -target arm64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsx -target x86_64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LIBS) $(LDFLAGS) $(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsx -target x86_64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS)
strip tpwsa tpwsx strip tpwsa tpwsx
lipo -create -output tpws tpwsx tpwsa lipo -create -output tpws tpwsx tpwsa
rm -f tpwsx tpwsa rm -f tpwsx tpwsa

View File

@ -65,8 +65,11 @@ int z_readfile(FILE *F, char **buf, size_t *size)
zerr: zerr:
inflateEnd(&zs); inflateEnd(&zs);
if (*buf)
{
free(*buf); free(*buf);
*buf = NULL; *buf = NULL;
}
return r; return r;
} }

View File

@ -11,7 +11,10 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <libgen.h> #include <libgen.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h>
#ifdef __linux__
#include <linux/tcp.h>
#endif
#ifdef __ANDROID__ #ifdef __ANDROID__
#include "andr/ifaddrs.h" #include "andr/ifaddrs.h"
@ -20,10 +23,6 @@
#endif #endif
#include "helpers.h" #include "helpers.h"
#ifdef __linux__
#include <linux/tcp.h>
#endif
#include "linux_compat.h"
int unique_size_t(size_t *pu, int ct) int unique_size_t(size_t *pu, int ct)
{ {
@ -78,13 +77,6 @@ char *strncasestr(const char *s, const char *find, size_t slen)
return (char *)s; return (char *)s;
} }
bool str_ends_with(const char *s, const char *suffix)
{
size_t slen = strlen(s);
size_t suffix_len = strlen(suffix);
return suffix_len <= slen && !strcmp(s + slen - suffix_len, suffix);
}
bool load_file(const char *filename, void *buffer, size_t *buffer_size) bool load_file(const char *filename, void *buffer, size_t *buffer_size)
{ {
FILE *F; FILE *F;
@ -322,29 +314,6 @@ time_t file_mod_time(const char *filename)
struct stat st; struct stat st;
return stat(filename, &st) == -1 ? 0 : st.st_mtime; return stat(filename, &st) == -1 ? 0 : st.st_mtime;
} }
bool file_mod_signature(const char *filename, file_mod_sig *ms)
{
struct stat st;
if (stat(filename,&st)==-1)
{
FILE_MOD_RESET(ms);
return false;
}
ms->mod_time=st.st_mtime;
ms->size=st.st_size;
return true;
}
bool file_open_test(const char *filename, int flags)
{
int fd = open(filename,flags);
if (fd>=0)
{
close(fd);
return true;
}
return false;
}
bool pf_in_range(uint16_t port, const port_filter *pf) bool pf_in_range(uint16_t port, const port_filter *pf)
{ {
@ -390,11 +359,6 @@ bool pf_is_empty(const port_filter *pf)
return !pf->neg && !pf->from && !pf->to; return !pf->neg && !pf->from && !pf->to;
} }
void set_console_io_buffering(void)
{
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
}
bool set_env_exedir(const char *argv0) bool set_env_exedir(const char *argv0)
{ {
@ -517,7 +481,7 @@ void msleep(unsigned int ms)
bool socket_supports_notsent() bool socket_supports_notsent()
{ {
int sfd; int sfd;
struct tcp_info_new tcpi; struct tcp_info tcpi;
sfd = socket(AF_INET,SOCK_STREAM,0); sfd = socket(AF_INET,SOCK_STREAM,0);
if (sfd<0) return false; if (sfd<0) return false;
@ -530,11 +494,11 @@ bool socket_supports_notsent()
} }
close(sfd); close(sfd);
return ts>=((char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi + sizeof(tcpi.tcpi_notsent_bytes)); return ts>=((char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi.tcpi_state + sizeof(tcpi.tcpi_notsent_bytes));
} }
bool socket_has_notsent(int sfd) bool socket_has_notsent(int sfd)
{ {
struct tcp_info_new tcpi; struct tcp_info tcpi;
socklen_t ts = sizeof(tcpi); socklen_t ts = sizeof(tcpi);
if (getsockopt(sfd, IPPROTO_TCP, TCP_INFO, (char *)&tcpi, &ts) < 0) if (getsockopt(sfd, IPPROTO_TCP, TCP_INFO, (char *)&tcpi, &ts) < 0)
@ -572,20 +536,4 @@ bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms
} }
return false; return false;
} }
int is_wsl(void)
{
struct utsname buf;
if (uname(&buf) != 0)
return -1;
if (strcmp(buf.sysname, "Linux") != 0)
return 0;
if (str_ends_with(buf.release, "microsoft-standard-WSL2"))
return 2;
if (str_ends_with(buf.release, "-Microsoft"))
return 1;
return 0;
}
#endif #endif

View File

@ -7,12 +7,10 @@
#include <netdb.h> #include <netdb.h>
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <sys/utsname.h>
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes. // this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
typedef union typedef union
{ {
sa_family_t sa_family;
struct sockaddr_in sa4; // size 16 struct sockaddr_in sa4; // size 16
struct sockaddr_in6 sa6; // size 28 struct sockaddr_in6 sa6; // size 28
} sockaddr_in46; } sockaddr_in46;
@ -24,8 +22,6 @@ void rtrim(char *s);
void replace_char(char *s, char from, char to); void replace_char(char *s, char from, char to);
char *strncasestr(const char *s,const char *find, size_t slen); char *strncasestr(const char *s,const char *find, size_t slen);
bool str_ends_with(const char *s, const char *suffix);
bool load_file(const char *filename,void *buffer,size_t *buffer_size); bool load_file(const char *filename,void *buffer,size_t *buffer_size);
bool append_to_list_file(const char *filename, const char *s); bool append_to_list_file(const char *filename, const char *s);
@ -66,16 +62,7 @@ static inline void phton16(uint8_t *p, uint16_t v) {
int fprint_localtime(FILE *F); int fprint_localtime(FILE *F);
typedef struct
{
time_t mod_time;
off_t size;
} file_mod_sig;
#define FILE_MOD_COMPARE(ms1,ms2) (((ms1)->mod_time==(ms2)->mod_time) && ((ms1)->size==(ms2)->size))
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
bool file_mod_signature(const char *filename, file_mod_sig *ms);
time_t file_mod_time(const char *filename); time_t file_mod_time(const char *filename);
bool file_open_test(const char *filename, int flags);
typedef struct typedef struct
{ {
@ -86,7 +73,6 @@ bool pf_in_range(uint16_t port, const port_filter *pf);
bool pf_parse(const char *s, port_filter *pf); bool pf_parse(const char *s, port_filter *pf);
bool pf_is_empty(const port_filter *pf); bool pf_is_empty(const port_filter *pf);
void set_console_io_buffering(void);
bool set_env_exedir(const char *argv0); bool set_env_exedir(const char *argv0);
#ifndef IN_LOOPBACK #ifndef IN_LOOPBACK
@ -137,6 +123,4 @@ void msleep(unsigned int ms);
bool socket_supports_notsent(); bool socket_supports_notsent();
bool socket_has_notsent(int sfd); bool socket_has_notsent(int sfd);
bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms); bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms);
int is_wsl();
#endif #endif

View File

@ -4,7 +4,7 @@
#include "helpers.h" #include "helpers.h"
// inplace tolower() and add to pool // inplace tolower() and add to pool
static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct) static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
{ {
char *p=*s; char *p=*s;
@ -17,16 +17,10 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
else else
{ {
// advance until eol lowering all chars // advance until eol lowering all chars
uint32_t flags = 0;
if (*p=='^')
{
p = ++(*s);
flags |= HOSTLIST_POOL_FLAG_STRICT_MATCH;
}
for (; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p); for (; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
if (!HostlistPoolAddStrLen(hostlist, *s, p-*s, flags)) if (!StrPoolAddStrLen(hostlist, *s, p-*s))
{ {
HostlistPoolDestroy(hostlist); StrPoolDestroy(hostlist);
*hostlist = NULL; *hostlist = NULL;
return false; return false;
} }
@ -38,12 +32,12 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
return true; return true;
} }
bool AppendHostlistItem(hostlist_pool **hostlist, char *s) bool AppendHostlistItem(strpool **hostlist, char *s)
{ {
return addpool(hostlist,&s,s+strlen(s),NULL); return addpool(hostlist,&s,s+strlen(s),NULL);
} }
bool AppendHostList(hostlist_pool **hostlist, const char *filename) bool AppendHostList(strpool **hostlist, const char *filename)
{ {
char *p, *e, s[256], *zbuf; char *p, *e, s[256], *zbuf;
size_t zsize; size_t zsize;
@ -111,22 +105,21 @@ static bool LoadHostList(struct hostlist_file *hfile)
{ {
if (hfile->filename) if (hfile->filename)
{ {
file_mod_sig fsig; time_t t = file_mod_time(hfile->filename);
if (!file_mod_signature(hfile->filename, &fsig)) if (!t)
{ {
// stat() error // stat() error
DLOG_PERROR("file_mod_signature");
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename); DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true; return true;
} }
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date if (t==hfile->mod_time) return true; // up to date
HostlistPoolDestroy(&hfile->hostlist); StrPoolDestroy(&hfile->hostlist);
if (!AppendHostList(&hfile->hostlist, hfile->filename)) if (!AppendHostList(&hfile->hostlist, hfile->filename))
{ {
HostlistPoolDestroy(&hfile->hostlist); StrPoolDestroy(&hfile->hostlist);
return false; return false;
} }
hfile->mod_sig=fsig; hfile->mod_time=t;
} }
return true; return true;
} }
@ -144,10 +137,10 @@ static bool LoadHostLists(struct hostlist_files_head *list)
return bres; return bres;
} }
bool NonEmptyHostlist(hostlist_pool **hostlist) bool NonEmptyHostlist(strpool **hostlist)
{ {
// add impossible hostname if the list is empty // add impossible hostname if the list is empty
return *hostlist ? true : HostlistPoolAddStrLen(hostlist, "@&()", 4, 0); return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4);
} }
static void MakeAutolistsNonEmpty() static void MakeAutolistsNonEmpty()
@ -170,34 +163,19 @@ bool LoadAllHostLists()
static bool SearchHostList(hostlist_pool *hostlist, const char *host) static bool SearchHostList(strpool *hostlist, const char *host)
{ {
if (hostlist) if (hostlist)
{ {
const char *p = host; const char *p = host;
const struct hostlist_pool *hp; bool bInHostList;
bool bHostFull=true;
while (p) while (p)
{ {
VPRINT("hostlist check for %s : ", p); bInHostList = StrPoolCheckStr(hostlist, p);
hp = HostlistPoolGetStr(hostlist, p); VPRINT("hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative");
if (hp) if (bInHostList) return true;
{
if ((hp->flags & HOSTLIST_POOL_FLAG_STRICT_MATCH) && !bHostFull)
{
VPRINT("negative : strict_mismatch : %s != %s\n", p, host);
}
else
{
VPRINT("positive\n");
return true;
}
}
else
VPRINT("negative\n");
p = strchr(p, '.'); p = strchr(p, '.');
if (p) p++; if (p) p++;
bHostFull = false;
} }
} }
return false; return false;
@ -287,13 +265,11 @@ static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostl
} }
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename) struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
{ {
/*
if (filename && !file_mod_time(filename)) if (filename && !file_mod_time(filename))
{ {
DLOG_ERR("cannot access hostlist file '%s'\n",filename); DLOG_ERR("cannot access hostlist file '%s'\n",filename);
return NULL; return NULL;
} }
*/
return RegisterHostlist_( return RegisterHostlist_(
&params.hostlists, &params.hostlists,
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection, bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,

View File

@ -4,14 +4,12 @@
#include "pools.h" #include "pools.h"
#include "params.h" #include "params.h"
bool AppendHostlistItem(hostlist_pool **hostlist, char *s); bool AppendHostlistItem(strpool **hostlist, char *s);
bool AppendHostList(hostlist_pool **hostlist, const char *filename); bool AppendHostList(strpool **hostlist, const char *filename);
bool LoadAllHostLists(); bool LoadAllHostLists();
bool NonEmptyHostlist(hostlist_pool **hostlist); bool NonEmptyHostlist(strpool **hostlist);
// return : true = apply fooling, false = do not apply // return : true = apply fooling, false = do not apply
bool HostlistCheck(const struct desync_profile *dp,const char *host, bool *excluded, bool bSkipReloadCheck); bool HostlistCheck(const struct desync_profile *dp,const char *host, bool *excluded, bool bSkipReloadCheck);
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename); struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename);
bool HostlistsReloadCheckForProfile(const struct desync_profile *dp); bool HostlistsReloadCheckForProfile(const struct desync_profile *dp);
void HostlistsDebug(); void HostlistsDebug();
#define ResetAllHostlistsModTime() hostlist_files_reset_modtime(&params.hostlists)

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