Compare commits

..

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

241 changed files with 8071 additions and 16162 deletions

1
.gitattributes vendored
View File

@ -1,3 +1,4 @@
* text=auto eol=lf
binaries/win64/readme.txt eol=crlf
*.cmd 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 !

View File

@ -1,488 +0,0 @@
name: build
run-name: ${{ startsWith(github.ref, 'refs/tags/v') && format('Release {0}', github.ref_name) || null }}
on:
workflow_dispatch:
push:
tags:
- v[0-9]+*
# branches:
# - master
# paths:
# - 'ip2net/**'
# - 'mdig/**'
# - 'nfq/**'
# - 'tpws/**'
jobs:
build-linux:
name: Linux ${{ matrix.arch }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- arch: arm64
tool: aarch64-unknown-linux-musl
- arch: arm
tool: arm-unknown-linux-musleabi
# - arch: armhf
# tool: arm-unknown-linux-musleabihf
# - arch: armv7
# tool: armv7-unknown-linux-musleabi
# - arch: armv7hf
# tool: armv7-unknown-linux-musleabihf
# - arch: mips64el
# tool: mips64el-unknown-linux-musl
- arch: mips64
tool: mips64-unknown-linux-musl
# - arch: mipsel
# tool: mipsel-unknown-linux-musl
- arch: mipselsf
tool: mipsel-unknown-linux-muslsf
# - arch: mips
# tool: mips-unknown-linux-musl
- arch: mipssf
tool: mips-unknown-linux-muslsf
# - arch: ppc64
# tool: powerpc64-unknown-linux-musl
- arch: ppc
tool: powerpc-unknown-linux-musl
- arch: x86
tool: i586-unknown-linux-musl
- arch: x86_64
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:
- name: Checkout
uses: actions/checkout@v4
with:
path: zapret
- name: Set up build tools
env:
ARCH: ${{ matrix.arch }}
TOOL: ${{ matrix.tool }}
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'spvkgn/musl-cross' }}
DIR: ${{ matrix.arch == 'lexra' && matrix.dir || matrix.tool }}
run: |
if [[ "$ARCH" == lexra ]]; then
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
wget -qO- $URL | tar -C $HOME/tools -xJ || exit 1
[[ -d "$HOME/tools/$DIR/bin" ]] && echo "$HOME/tools/$DIR/bin" >> $GITHUB_PATH
- name: Build
env:
ARCH: ${{ matrix.arch }}
TARGET: ${{ matrix.tool }}
CFLAGS: ${{ matrix.env.CFLAGS != '' && matrix.env.CFLAGS || null }}
LDFLAGS: ${{ matrix.env.LDFLAGS != '' && matrix.env.LDFLAGS || null }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps
export CC="$TARGET-gcc"
export LD=$TARGET-ld
export AR=$TARGET-ar
export NM=$TARGET-nm
export STRIP=$TARGET-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
export STAGING_DIR=$RUNNER_TEMP
# netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
wget -qO- https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
wget -qO- https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="-Os -flto=auto $CFLAGS" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
sed -i "s|^prefix=.*|prefix=$DEPS_DIR|g" $DEPS_DIR/lib/pkgconfig/$i.pc
done
# zlib
gh api repos/madler/zlib/releases/latest --jq '.tag_name' |\
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
(
cd zlib-*
CFLAGS="-Os -flto=auto $CFLAGS" \
./configure --prefix= --static
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
# headers
# wget https://git.alpinelinux.org/aports/plain/main/bsd-compat-headers/queue.h && \
# wget https://git.kernel.org/pub/scm/libs/libcap/libcap.git/plain/libcap/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
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include $CFLAGS" \
LDFLAGS="-L$DEPS_DIR/lib $LDFLAGS" \
make -C zapret -j$(nproc)
tar -C zapret/binaries/my -cJf zapret-linux-$ARCH.tar.xz .
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: zapret-linux-${{ matrix.arch }}
path: zapret-*.tar.xz
if-no-files-found: error
build-macos:
name: macOS
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build zapret
run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
make mac -j$(sysctl -n hw.logicalcpu)
tar -C binaries/my -cJf zapret-mac-x64.tar.xz .
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: zapret-mac-x64
path: zapret-*.tar.xz
if-no-files-found: error
build-freebsd:
name: FreeBSD ${{ matrix.arch }}
runs-on: ubuntu-latest
strategy:
matrix:
include:
- target: x86_64
arch: x86_64
# - target: i386
# arch: x86
container:
image: empterdose/freebsd-cross-build:11.4
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install packages
run: apk add tar xz
- name: Build zapret
env:
TARGET: ${{ matrix.target }}
ARCH: ${{ matrix.arch }}
run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
settarget $TARGET-freebsd11 make bsd -j$(nproc)
tar -C binaries/my -cJf zapret-freebsd-$ARCH.tar.xz .
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: zapret-freebsd-${{ matrix.arch }}
path: zapret-*.tar.xz
if-no-files-found: error
build-windows:
name: Windows ${{ matrix.arch }}
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
arch: [ x86_64, x86 ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: zapret
- name: Set up MinGW
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.arch == 'x86_64' && 'MINGW64' || 'MINGW32' }}
install: >-
${{ matrix.arch == 'x86_64' && 'mingw-w64-x86_64-toolchain' || 'mingw-w64-i686-toolchain' }}
- name: Build ip2net, mdig
shell: msys2 {0}
run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
mkdir -p output
cd zapret
mingw32-make -C ip2net win
mingw32-make -C mdig win
cp -a {ip2net/ip2net,mdig/mdig}.exe ../output
- name: Restore psmisc from cache
id: cache-restore-psmisc
uses: actions/cache/restore@v4
with:
path: ${{ github.workspace }}/psmisc
key: psmisc-${{ matrix.arch }}
- name: Set up Cygwin
env:
PACKAGES: ${{ steps.cache-restore-psmisc.outputs.cache-hit != 'true' && 'cygport gettext-devel libiconv-devel libncurses-devel' || null }}
uses: cygwin/cygwin-install-action@v4
with:
platform: ${{ matrix.arch }}
site: ${{ matrix.arch == 'x86_64' && 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215' || null }}
check-sig: ${{ matrix.arch == 'x86_64' && 'false' || null }}
packages: >-
gcc-core
make
zlib-devel
zip
unzip
wget
${{ env.PACKAGES }}
- name: Build psmisc
if: steps.cache-restore-psmisc.outputs.cache-hit != 'true'
env:
URL: https://mirrors.kernel.org/sourceware/cygwin/x86_64/release/psmisc
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
run: >-
export MAKEFLAGS=-j$(nproc) &&
mkdir -p psmisc && cd psmisc &&
wget -qO- ${URL} | grep -Po 'href=\"\Kpsmisc-(\d+\.)+\d+.+src\.tar\.xz(?=\")' | xargs -I{} wget -O- ${URL}/{} | tar -xJ &&
cd psmisc-*.src &&
echo CYGCONF_ARGS+=\" --disable-dependency-tracking --disable-nls\" >> psmisc.cygport &&
cygport psmisc.cygport prep compile install
- name: Save psmisc to cache
if: steps.cache-restore-psmisc.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: ${{ github.workspace }}/psmisc
key: psmisc-${{ matrix.arch }}
- name: Build winws
env:
TARGET: ${{ matrix.arch == 'x86_64' && 'cygwin' || 'cygwin32' }}
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
run: >-
export MAKEFLAGS=-j$(nproc) &&
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}" &&
cd zapret &&
make -C nfq ${TARGET} &&
cp -a nfq/winws.exe ../output
- name: Create zip
env:
BITS: ${{ matrix.arch == 'x86_64' && '64' || '32' }}
DIR: ${{ matrix.arch == 'x86_64' && 'x64' || 'x86' }}
shell: C:\cygwin\bin\bash.exe -e '{0}'
run: >-
cp -a -t output psmisc/psmisc-*.src/psmisc-*/inst/usr/bin/killall.exe /usr/bin/cygwin1.dll &&
wget -O WinDivert.zip https://github.com/basil00/WinDivert/releases/download/v2.2.2/WinDivert-2.2.2-A.zip &&
unzip -j WinDivert.zip "*/${DIR}/WinDivert.dll" "*/${DIR}/WinDivert${BITS}.sys" -d output &&
zip zapret-win-${{ matrix.arch }}.zip -j output/*
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: zapret-win-${{ matrix.arch }}
path: zapret-*.zip
if-no-files-found: error
build-android:
name: Android ${{ matrix.abi }}
runs-on: ubuntu-latest
strategy:
matrix:
include:
- abi: armeabi-v7a
target: armv7a-linux-androideabi
- abi: arm64-v8a
target: aarch64-linux-android
- abi: x86
target: i686-linux-android
- abi: x86_64
target: x86_64-linux-android
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: zapret
- name: Build
env:
ABI: ${{ matrix.abi }}
API: 21
TARGET: ${{ matrix.target }}
GH_TOKEN: ${{ github.token }}
run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
export CC="$TOOLCHAIN/bin/clang --target=$TARGET$API"
export AR=$TOOLCHAIN/bin/llvm-ar
export AS=$CC
export LD=$TOOLCHAIN/bin/ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
# netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
wget -qO- https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
wget -qO- https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj
patch -p1 -d libnetfilter_queue-* -i ../zapret/.github/workflows/libnetfilter_queue-android.patch
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
sed -i "s|^prefix=.*|prefix=$DEPS_DIR|g" $DEPS_DIR/lib/pkgconfig/$i.pc
done
# zapret
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -I$DEPS_DIR/include" \
LDFLAGS="-L$DEPS_DIR/lib" \
make -C zapret android -j$(nproc)
# 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/*
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: zapret-android-${{ matrix.abi }}
path: zapret-*.zip
if-no-files-found: error
release:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
needs: [ build-linux, build-windows, build-macos, build-freebsd, build-android ]
permissions:
contents: write
runs-on: ubuntu-latest
env:
repo_dir: zapret-${{ github.ref_name }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: ${{ env.repo_dir }}
- name: Download artifacts
uses: actions/download-artifact@v4
id: bins
with:
path: ${{ env.repo_dir }}/binaries
pattern: zapret-*
- name: Install upx
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
version: v4.2.4
- name: Prepare binaries
shell: bash
run: |
cd ${{ steps.bins.outputs.download-path }}
run_upx() {
upx --best --lzma $@ || true
}
run_dir() {
for f in $dir/* ; do
# extract binaries
case $f in
*.tar.xz )
tar -C $dir -xvf $f && rm $f
if [[ $dir == *-linux-x86_64 ]]; then
tar -C $dir -czvf $dir/tpws_wsl.tgz tpws
run_upx $dir/*
elif [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then
run_upx $dir/*
fi
;;
*.zip )
unzip $f -d $dir && rm $f
if [[ $dir =~ win ]]; then
chmod -x $dir/*
run_upx --force $dir/cygwin1.dll
fi
;;
esac
done
mv $dir $1
}
for dir in * ; do
if [ -d $dir ]; then
echo "Processing $dir"
case $dir in
*-android-arm64-v8a ) run_dir android-aarch64 ;;
*-android-armeabi-v7a ) run_dir android-arm ;;
*-android-x86 ) run_dir android-x86 ;;
*-android-x86_64 ) run_dir android-x86_64 ;;
*-freebsd-x86_64 ) run_dir freebsd-x64 ;;
*-linux-arm ) run_dir arm ;;
*-linux-arm64 ) run_dir aarch64 ;;
*-linux-mips64 ) run_dir mips64r2-msb ;;
*-linux-mipselsf ) run_dir mips32r1-lsb ;;
*-linux-mipssf ) run_dir mips32r1-msb ;;
*-linux-ppc ) run_dir ppc ;;
*-linux-x86 ) run_dir x86 ;;
*-linux-x86_64 ) run_dir x86_64 ;;
*-linux-lexra ) run_dir lexra ;;
*-mac-x64 ) run_dir mac64 ;;
*-win-x86 ) run_dir win32 ;;
*-win-x86_64 ) run_dir win64 ;;
esac
fi
done
ls -lhR
- name: Create release bundles
run: |
rm -rf ${{ env.repo_dir }}/.git*
find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
(
cd ${{ env.repo_dir }}
rm -rf binaries/{android*,freebsd*,mac*,win*,x86_64/tpws_wsl.tgz} \
init.d/{openrc,macos,pfsense,runit,s6,systemd} \
tpws nfq ip2net mdig docs files/huawei Makefile
)
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
- name: Upload release assets
uses: softprops/action-gh-release@v2
with:
fail_on_unmatched_files: true
prerelease: false
draft: false
body: |
### zapret ${{ github.ref_name }}
files: |
zapret*.tar.gz
zapret*.zip
sha256sum.txt

View File

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

7
.gitignore vendored
View File

@ -1,12 +1,11 @@
/config
config
ip2net/ip2net
mdig/mdig
nfq/dvtws
nfq/nfqws
nfq/winws.exe
nfq/WinDivert*
tpws/tpws
binaries/my/
binaries/win64/zapret-winws/autohostlist.txt
init.d/**/custom
ipset/zapret-ip*.txt
ipset/zapret-ip*.gz
ipset/zapret-hosts*.txt

View File

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

BIN
binaries/aarch64/ip2net Executable file

Binary file not shown.

BIN
binaries/aarch64/mdig Executable file

Binary file not shown.

BIN
binaries/aarch64/nfqws Executable file

Binary file not shown.

BIN
binaries/aarch64/tpws Executable file

Binary file not shown.

BIN
binaries/arm/ip2net Executable file

Binary file not shown.

BIN
binaries/arm/mdig Executable file

Binary file not shown.

BIN
binaries/arm/nfqws Executable file

Binary file not shown.

BIN
binaries/arm/tpws Executable file

Binary file not shown.

BIN
binaries/freebsd-x64/dvtws Executable file

Binary file not shown.

BIN
binaries/freebsd-x64/ip2net Executable file

Binary file not shown.

BIN
binaries/freebsd-x64/mdig Executable file

Binary file not shown.

BIN
binaries/freebsd-x64/tpws Executable file

Binary file not shown.

BIN
binaries/mac64/ip2net Executable file

Binary file not shown.

BIN
binaries/mac64/mdig Executable file

Binary file not shown.

BIN
binaries/mac64/tpws Executable file

Binary file not shown.

BIN
binaries/mips32r1-lsb/ip2net Executable file

Binary file not shown.

BIN
binaries/mips32r1-lsb/mdig Executable file

Binary file not shown.

BIN
binaries/mips32r1-lsb/nfqws Executable file

Binary file not shown.

BIN
binaries/mips32r1-lsb/tpws Executable file

Binary file not shown.

BIN
binaries/mips32r1-msb/ip2net Executable file

Binary file not shown.

BIN
binaries/mips32r1-msb/mdig Executable file

Binary file not shown.

BIN
binaries/mips32r1-msb/nfqws Executable file

Binary file not shown.

BIN
binaries/mips32r1-msb/tpws Executable file

Binary file not shown.

BIN
binaries/mips64r2-msb/ip2net Executable file

Binary file not shown.

BIN
binaries/mips64r2-msb/mdig Executable file

Binary file not shown.

BIN
binaries/mips64r2-msb/nfqws Executable file

Binary file not shown.

BIN
binaries/mips64r2-msb/tpws Executable file

Binary file not shown.

BIN
binaries/ppc/ip2net Executable file

Binary file not shown.

BIN
binaries/ppc/mdig Executable file

Binary file not shown.

BIN
binaries/ppc/nfqws Executable file

Binary file not shown.

BIN
binaries/ppc/tpws Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
binaries/win64/ip2net.exe Normal file

Binary file not shown.

BIN
binaries/win64/mdig.exe Normal file

Binary file not shown.

View File

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

BIN
binaries/win64/winws.exe Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,3 @@
googlevideo.com
youtubei.googleapis.com
i.ytimg.com

View File

@ -0,0 +1,7 @@
start "zapret: http,https,quic" /min "%~dp0winws.exe" ^
--wf-tcp=80,443 --wf-udp=443 ^
--filter-udp=443 --hostlist="%~dp0list-youtube.txt" --dpi-desync=fake --dpi-desync-repeats=11 --dpi-desync-fake-quic="%~dp0quic_initial_www_google_com.bin" --new ^
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=11 --new ^
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig --new ^
--filter-tcp=443 --hostlist="%~dp0list-youtube.txt" --dpi-desync=fake,split2 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig --dpi-desync-fake-tls="%~dp0tls_clienthello_www_google_com.bin" --new ^
--dpi-desync=fake,disorder2 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig

View File

@ -0,0 +1,7 @@
start "zapret: http,https,quic" /min "%~dp0winws.exe" ^
--wf-tcp=80,443 --wf-udp=443 ^
--filter-udp=443 --hostlist="%~dp0list-youtube.txt" --dpi-desync=fake --dpi-desync-repeats=11 --dpi-desync-fake-quic="%~dp0quic_initial_www_google_com.bin" --new ^
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=11 --new ^
--filter-tcp=80 --dpi-desync=fake,split2 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig --hostlist-auto="%~dp0autohostlist.txt" --new ^
--filter-tcp=443 --hostlist="%~dp0list-youtube.txt" --dpi-desync=fake,split2 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig --dpi-desync-fake-tls="%~dp0tls_clienthello_www_google_com.bin" --new ^
--dpi-desync=fake,disorder2 --dpi-desync-autottl=2 --dpi-desync-fooling=md5sig --hostlist-auto="%~dp0autohostlist.txt"

View File

@ -0,0 +1,12 @@
set ARGS=--wf-l3=ipv4,ipv6 --wf-tcp=80,443 --dpi-desync=fake,split --dpi-desync-ttl=7 --dpi-desync-fooling=md5sig
call :srvinst winws1
rem set ARGS=--wf-l3=ipv4,ipv6 --wf-udp=443 --dpi-desync=fake
rem call :srvinst winws2
goto :eof
:srvinst
net stop %1
sc delete %1
sc create %1 binPath= "\"%~dp0winws.exe\" %ARGS%" DisplayName= "zapret DPI bypass : %1" start= auto
sc description %1 "zapret DPI bypass software"
sc start %1

View File

@ -0,0 +1,7 @@
call :srvdel winws1
rem call :srvdel winws2
goto :eof
:srvdel
net stop %1
sc delete %1

View File

@ -0,0 +1,2 @@
sc start winws1
rem sc start winws2

View File

@ -0,0 +1,2 @@
net stop winws1
rem net stop winws2

View File

@ -0,0 +1,4 @@
set WINWS1=--wf-l3=ipv4,ipv6 --wf-tcp=80,443 --dpi-desync=fake,split --dpi-desync-ttl=7 --dpi-desync-fooling=md5sig
schtasks /Create /F /TN winws1 /NP /RU "" /SC onstart /TR "\"%~dp0winws.exe\" %WINWS1%"
rem set WINWS2=--wf-l3=ipv4,ipv6 --wf-udp=443 --dpi-desync=fake
rem schtasks /Create /F /TN winws2 /NP /RU "" /SC onstart /TR "\"%~dp0winws.exe\" %WINWS2%"

View File

@ -0,0 +1,4 @@
schtasks /End /TN winws1
schtasks /Delete /TN winws1 /F
rem schtasks /End /TN winws2
rem schtasks /Delete /TN winws2 /F

View File

@ -0,0 +1,2 @@
schtasks /Run /TN winws1
rem schtasks /Run /TN winws2

View File

@ -0,0 +1,2 @@
schtasks /End /TN winws1
rem schtasks /End /TN winws2

Binary file not shown.

BIN
binaries/x86/ip2net Executable file

Binary file not shown.

BIN
binaries/x86/mdig Executable file

Binary file not shown.

BIN
binaries/x86/nfqws Executable file

Binary file not shown.

BIN
binaries/x86/tpws Executable file

Binary file not shown.

BIN
binaries/x86_64/ip2net Executable file

Binary file not shown.

BIN
binaries/x86_64/mdig Executable file

Binary file not shown.

BIN
binaries/x86_64/nfqws Executable file

Binary file not shown.

BIN
binaries/x86_64/tpws Executable file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -60,23 +60,8 @@ starts_with()
esac
return 1
}
extract_arg()
{
# $1 - arg number
# $2,$3,... - args
local n=$1
while [ -n "$1" ]; do
shift
[ $n -eq 1 ] && { echo "$1"; return 0; }
n=$(($n-1))
done
return 1
}
find_str_in_list()
{
# $1 - string
# $2 - space separated values
local v
[ -n "$1" ] && {
for v in $2; do
[ "$v" = "$1" ] && return 0
@ -89,19 +74,6 @@ end_with_newline()
local c="$(tail -c 1)"
[ "$c" = "" ]
}
trim()
{
awk '{gsub(/^ +| +$/,"")}1'
}
dir_is_not_empty()
{
# $1 - directory
local n
[ -d "$1" ] || return 1
n=$(ls "$1" | wc -c | xargs)
[ "$n" != 0 ]
}
append_separator_list()
{
@ -241,7 +213,7 @@ fix_sbin_path()
# it can calculate floating point expr
calc()
{
LC_ALL=C awk "BEGIN { print $*}";
awk "BEGIN { print $*}";
}
fsleep_setup()
@ -303,14 +275,6 @@ replace_char()
echo "$@" | tr $a $b
}
replace_str()
{
local a=$(echo "$1" | sed 's/\//\\\//g')
local b=$(echo "$2" | sed 's/\//\\\//g')
shift; shift
echo "$@" | sed "s/$a/$b/g"
}
setup_md5()
{
[ -n "$MD5" ] && return
@ -318,27 +282,18 @@ setup_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()
{
# $1 - min, $2 - max
local r rs
setup_md5
setup_random
if [ -c /dev/urandom ]; then
read rs </dev/urandom
else
rs="$RANDOM$RANDOM$(date)"
fi
# 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 ))
}
@ -374,62 +329,12 @@ win_process_exists()
tasklist /NH /FI "IMAGENAME eq ${1}.exe" | grep -q "^${1}.exe"
}
alloc_num()
{
# $1 - source var name
# $2 - target var name
# $3 - min
# $4 - max
local v
eval v="\$$2"
# do not replace existing value
[ -n "$v" ] && return
eval v="\$$1"
[ -n "$v" ] || v=$3
eval $2="$v"
v=$((v + 1))
[ $v -gt $4 ] && v=$3
eval $1="$v"
}
std_ports()
{
TPWS_PORTS_IPT=$(replace_char - : $TPWS_PORTS)
NFQWS_PORTS_TCP_IPT=$(replace_char - : $NFQWS_PORTS_TCP)
NFQWS_PORTS_TCP_KEEPALIVE_IPT=$(replace_char - : $NFQWS_PORTS_TCP_KEEPALIVE)
NFQWS_PORTS_UDP_IPT=$(replace_char - : $NFQWS_PORTS_UDP)
NFQWS_PORTS_UDP_KEEPALIVE_IPT=$(replace_char - : $NFQWS_PORTS_UDP_KEEPALIVE)
}
has_bad_ws_options()
{
# $1 - nfqws/tpws opts
# ПРИМЕЧАНИЕ ДЛЯ РАСПРОСТРАНИТЕЛЕЙ КОПИПАСТЫ
# ЭТОТ КОД СДЕЛАН СПЕЦИАЛЬНО ДЛЯ ВАС, ЧТОБЫ ВЫ НЕ ПОСТИЛИ В СЕТЬ ПЛОХИЕ РЕЦЕПТЫ
# ЕСЛИ ВАМ ХОЧЕТСЯ ЕГО УДАЛИТЬ И НАПИСАТЬ ИНСТРУКЦИЮ КАК ЕГО УДАЛЯТЬ, ВЫ ДЕЛАЕТЕ ХРЕНОВУЮ УСЛУГУ. НАПИШИТЕ ЛУЧШЕ custom script.
# custom script - ЭТО ФАЙЛИК, КОТОРЫЙ ДОСТАТОЧНО СКОПИРОВАТЬ В НУЖНУЮ ДИРЕКТОРИЮ, ЧТОБЫ ОН СДЕЛАЛ ТОЖЕ САМОЕ, НО ЭФФЕКТИВНО.
# ФИЛЬТРАЦИЯ ПО IPSET В ЯДРЕ НЕСРАВНИМО ЭФФЕКТИВНЕЕ, ЧЕМ ПЕРЕКИДЫВАТЬ ВСЕ ПАКЕТЫ В nfqws И ТАМ ФИЛЬТРОВАТЬ
# --ipset СУЩЕСТВУЕТ ТОЛЬКО ДЛЯ ВИНДЫ И LINUX СИСТЕМ БЕЗ ipset (НАПРИМЕР, Android).
# И ТОЛЬКО ПО ЭТОЙ ПРИЧИНЕ ОНО НЕ ВЫКИНУТО ПОЛНОСТЬЮ ИЗ LINUX ВЕРСИИ
contains "$1" "--ipset"
}
check_bad_ws_options()
{
# $1 - 0 = stop, 1 = start
# $2 - nfqws/tpws options
if [ "$1" = 1 ] && has_bad_ws_options "$2"; then
echo "!!! REFUSING TO USE BAD OPTIONS : $2"
help_bad_ws_options
return 1
else
return 0
fi
}
help_bad_ws_options()
{
echo "WARNING ! you have specified --ipset option"
echo "WARNING ! it would work but on ${UNAME:-$(uname)} it's not the best option"
echo "WARNING ! you should use kernel mode sets. they are much more efficient."
echo "WARNING ! to use ipsets you have to write your own custom script"
HTTP_PORTS=${HTTP_PORTS:-80}
HTTPS_PORTS=${HTTPS_PORTS:-443}
QUIC_PORTS=${QUIC_PORTS:-443}
HTTP_PORTS_IPT=$(replace_char - : $HTTP_PORTS)
HTTPS_PORTS_IPT=$(replace_char - : $HTTPS_PORTS)
QUIC_PORTS_IPT=$(replace_char - : $QUIC_PORTS)
}

View File

@ -3,16 +3,19 @@ custom_runner()
# $1 - function name
# $2+ - params
[ "$DISABLE_CUSTOM" = 1 ] && return 0
local n script FUNC=$1
shift
[ -f "$CUSTOM_DIR/custom" ] && {
unset -f $FUNC
. "$CUSTOM_DIR/custom"
existf $FUNC && $FUNC "$@"
}
[ -d "$CUSTOM_DIR/custom.d" ] && {
dir_is_not_empty "$CUSTOM_DIR/custom.d" && {
n=$(ls "$CUSTOM_DIR/custom.d" | wc -c | xargs)
[ "$n" = 0 ] || {
for script in "$CUSTOM_DIR/custom.d/"*; do
[ -f "$script" ] || continue
unset -f $FUNC
. "$script"
existf $FUNC && $FUNC "$@"
@ -20,20 +23,3 @@ custom_runner()
}
}
}
alloc_tpws_port()
{
# $1 - target var name
alloc_num NUMPOOL_TPWS_PORT $1 910 979
}
alloc_qnum()
{
# $1 - target var name
alloc_num NUMPOOL_QNUM $1 65400 65499
}
alloc_dnum()
{
# alloc daemon number
# $1 - target var name
alloc_num NUMPOOL_DNUM $1 1000 1999
}

View File

@ -1,28 +1,13 @@
require_root()
{
local exe preserve_env
local exe
echo \* checking privileges
[ $(id -u) -ne "0" ] && {
echo root is required
exe="$EXEDIR/$(basename "$0")"
exists sudo && {
echo elevating with sudo
exec sudo -E sh "$exe"
}
exists su && {
echo elevating with su
case "$UNAME" in
Linux)
preserve_env="--preserve-environment"
;;
FreeBSD|OpenBSD|Darwin)
preserve_env="-m"
;;
esac
exec su $preserve_env root -c "sh \"$exe\""
}
exists sudo && exec sudo sh "$exe"
exists su && exec su root -c "sh \"$exe\""
echo su or sudo not found
exitp 2
}
HAVE_ROOT=1
}

View File

@ -15,99 +15,13 @@ exitp()
exit $1
}
extract_var_def()
{
# $1 - var name
# this sed script parses single or multi line shell var assignments with optional ' or " enclosure
sed -n \
"/^$1=\"/ {
:s1
/\".*\"/ {
p
b
}
N
t c1
b s1
:c1
}
/^$1='/ {
:s2
/'.*'/ {
p
b
}
N
t c2
b s2
:c2
}
/^$1=/p
"
}
replace_var_def()
{
# $1 - var name
# $2 - new val
# $3 - conf file
# this sed script replaces single or multi line shell var assignments with optional ' or " enclosure
local repl
if [ -z "$2" ]; then
repl="#$1="
elif contains "$2" " "; then
repl="$1=\"$2\""
else
repl="$1=$2"
fi
local script=\
"/^#*[[:space:]]*$1=\"/ {
:s1
/\".*\"/ {
c\\
$repl
b
}
N
t c1
b s1
:c1
}
/^#*[[:space:]]*$1='/ {
:s2
/'.*'/ {
c\\
$repl
b
}
N
t c2
b s2
:c2
}
/^#*[[:space:]]*$1=/c\\
$repl"
# there's incompatibility with -i option on MacOS/BSD and busybox/GNU
if [ "$UNAME" = "Linux" ]; then
sed -i -e "$script" "$3"
else
sed -i '' -e "$script" "$3"
fi
}
parse_var_checked()
{
# $1 - file name
# $2 - var name
local tmp="/tmp/zvar-pid-$$.sh"
local v
cat "$1" | extract_var_def "$2" >"$tmp"
. "$tmp"
rm -f "$tmp"
eval v="\$$2"
# trim
v="$(echo "$v" | trim)"
eval $2=\""$v"\"
local sed="sed -nre s/^[[:space:]]*$2=[\\\"|\']?([^\\\"|\']*)[\\\"|\']?/\1/p"
local v="$($sed <"$1" | tail -n 1)"
eval $2=\"$v\"
}
parse_vars_checked()
{
@ -134,45 +48,22 @@ edit_file()
}
[ -n "$ed" ] && "$ed" "$1"
}
echo_var()
{
local v
eval v="\$$1"
if find_str_in_list $1 "$EDITVAR_NEWLINE_VARS"; then
echo "$1=\""
echo "$v\"" | tr '\n' ' ' | tr -d '\r' | sed -e 's/^ *//' -e 's/ *$//' -e "s/$EDITVAR_NEWLINE_DELIMETER /$EDITVAR_NEWLINE_DELIMETER\n/g"
else
if contains "$v" " "; then
echo $1=\"$v\"
else
echo $1=$v
fi
fi
}
edit_vars()
{
# $1,$2,... - var names
local n=1 var tmp="/tmp/zvars-pid-$$.txt"
local n=1 var v tmp="/tmp/zvars"
rm -f "$tmp"
while : ; do
while [ 1=1 ]; do
eval var="\${$n}"
[ -n "$var" ] || break
echo_var $var >> "$tmp"
eval v="\$$var"
echo $var=\"$v\" >>"$tmp"
n=$(($n+1))
done
edit_file "$tmp" && parse_vars_checked "$tmp" "$@"
rm -f "$tmp"
}
list_vars()
{
while [ -n "$1" ] ; do
echo_var $1
shift
done
echo
}
openrc_test()
{
exists rc-update || return 1
@ -191,7 +82,6 @@ check_system()
get_fwtype
OPENWRT_FW3=
OPENWRT_FW4=
local info
UNAME=$(uname)
@ -203,35 +93,27 @@ check_system()
# some distros include systemctl without systemd
if [ -d "$SYSTEMD_DIR" ] && [ -x "$SYSTEMCTL" ] && [ "$INIT" = "systemd" ]; then
SYSTEM=systemd
elif [ -f "/etc/openwrt_release" ] && exists opkg || exists apk && exists uci && [ "$INIT" = "procd" ] ; then
elif [ -f "/etc/openwrt_release" ] && exists opkg && exists uci && [ "$INIT" = "procd" ] ; then
{
SYSTEM=openwrt
OPENWRT_PACKAGER=opkg
OPENWRT_PACKAGER_INSTALL="opkg install"
OPENWRT_PACKAGER_UPDATE="opkg update"
exists apk && {
OPENWRT_PACKAGER=apk
OPENWRT_PACKAGER_INSTALL="apk add"
OPENWRT_PACKAGER_UPDATE=
}
info="package manager $OPENWRT_PACKAGER\n"
if openwrt_fw3 ; then
OPENWRT_FW3=1
info="${info}firewall fw3"
info="openwrt firewall uses fw3"
if is_ipt_flow_offload_avail; then
info="$info. hardware flow offloading requires iptables."
else
info="$info. flow offloading unavailable."
fi
elif openwrt_fw4; then
OPENWRT_FW4=1
info="${info}firewall fw4. flow offloading requires nftables."
info="openwrt firewall uses fw4. flow offloading requires nftables."
fi
}
elif openrc_test; then
SYSTEM=openrc
else
echo system is not either systemd, openrc or openwrt based
echo easy installer can set up config settings but can\'t configure auto start
echo you have to do it manually. check readme.md for manual setup info.
echo you have to do it manually. check readme.txt for manual setup info.
if [ -n "$1" ] || ask_yes_no N "do you want to continue"; then
SYSTEM=linux
else
@ -242,11 +124,11 @@ check_system()
elif [ "$UNAME" = "Darwin" ]; then
SYSTEM=macos
else
echo easy installer only supports Linux and MacOS. check readme.md for supported systems and manual setup info.
echo easy installer only supports Linux and MacOS. check readme.txt for supported systems and manual setup info.
exitp 5
fi
echo system is based on $SYSTEM
[ -n "$info" ] && printf "${info}\n"
[ -n "$info" ] && echo $info
}
get_free_space_mb()
@ -430,21 +312,14 @@ check_kmod()
}
check_package_exists_openwrt()
{
[ -n "$($OPENWRT_PACKAGER list $1)" ]
[ -n "$(opkg list $1)" ]
}
check_package_openwrt()
{
case $OPENWRT_PACKAGER in
opkg)
[ -n "$(opkg list-installed $1)" ] && return 0
local what="$(opkg whatprovides $1 | tail -n +2 | head -n 1)"
[ -n "$what" ] || return 1
[ -n "$(opkg list-installed $what)" ]
;;
apk)
apk info -e $1
;;
esac
[ -n "$(opkg list-installed $1)" ] && return 0
local what="$(opkg whatprovides $1 | tail -n +2 | head -n 1)"
[ -n "$what" ] || return 1
[ -n "$(opkg list-installed $what)" ]
}
check_packages_openwrt()
{
@ -533,8 +408,9 @@ restart_openwrt_firewall()
local FW=fw4
[ -n "$OPENWRT_FW3" ] && FW=fw3
exists $FW && $FW -q restart || {
$FW -q restart || {
echo could not restart firewall $FW
exitp 30
}
}
remove_openwrt_firewall()
@ -607,27 +483,37 @@ write_config_var()
# $1 - mode var
local M
eval M="\$$1"
# replace / => \/
#M=${M//\//\\\/}
M=$(echo $M | sed 's/\//\\\//g' | trim)
grep -q "^[[:space:]]*$1=\|^#*[[:space:]]*$1=" "$ZAPRET_CONFIG" || {
if grep -q "^$1=\|^#$1=" "$ZAPRET_CONFIG"; then
# replace / => \/
#M=${M//\//\\\/}
M=$(echo $M | sed 's/\//\\\//g')
if [ -n "$M" ]; then
if contains "$M" " "; then
sedi -Ee "s/^#?$1=.*$/$1=\"$M\"/" "$ZAPRET_CONFIG"
else
sedi -Ee "s/^#?$1=.*$/$1=$M/" "$ZAPRET_CONFIG"
fi
else
# write with comment at the beginning
sedi -Ee "s/^#?$1=.*$/#$1=/" "$ZAPRET_CONFIG"
fi
else
# var does not exist in config. add it
echo $1= >>"$ZAPRET_CONFIG"
}
replace_var_def $1 "$M" "$ZAPRET_CONFIG"
contains "$M" " " && M="\"$M\""
if [ -n "$M" ]; then
echo "$1=$M" >>"$ZAPRET_CONFIG"
else
echo "#$1=$M" >>"$ZAPRET_CONFIG"
fi
fi
}
no_prereq_exit()
{
echo could not install prerequisites
exitp 6
}
check_prerequisites_linux()
{
echo \* checking prerequisites
local s cmd PKGS UTILS req="curl curl"
local APTGET DNF YUM PACMAN ZYPPER EOPKG APK
case "$FWTYPE" in
iptables)
req="$req iptables iptables ip6tables iptables ipset ipset"
@ -656,7 +542,6 @@ check_prerequisites_linux()
echo packages required : $PKGS
APTGET=$(whichq apt-get)
DNF=$(whichq dnf)
YUM=$(whichq yum)
PACMAN=$(whichq pacman)
ZYPPER=$(whichq zypper)
@ -664,23 +549,39 @@ check_prerequisites_linux()
APK=$(whichq apk)
if [ -x "$APTGET" ] ; then
"$APTGET" update
"$APTGET" install -y --no-install-recommends $PKGS dnsutils || no_prereq_exit
elif [ -x "$DNF" ] ; then
"$DNF" -y install $PKGS || no_prereq_exit
"$APTGET" install -y --no-install-recommends $PKGS dnsutils || {
echo could not install prerequisites
exitp 6
}
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
"$PACMAN" -Syy
"$PACMAN" --noconfirm -S $PKGS || no_prereq_exit
"$PACMAN" --noconfirm -S $PKGS || {
echo could not install prerequisites
exitp 6
}
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
"$EOPKG" -y install $PKGS || no_prereq_exit
"$EOPKG" -y install $PKGS || {
echo could not install prerequisites
exitp 6
}
elif [ -x "$APK" ] ; then
"$APK" update
# for alpine
[ "$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
echo supported package manager not found
echo you must manually install : $UTILS
@ -689,59 +590,16 @@ check_prerequisites_linux()
fi
}
removable_pkgs_openwrt()
{
local pkg PKGS2
[ -n "$OPENWRT_FW4" ] && PKGS2="$PKGS2 iptables-zz-legacy iptables ip6tables-zz-legacy ip6tables"
[ -n "$OPENWRT_FW3" ] && PKGS2="$PKGS2 nftables-json nftables-nojson nftables"
PKGS=
for pkg in $PKGS2; do
check_package_exists_openwrt $pkg && PKGS="${PKGS:+$PKGS }$pkg"
done
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS"
}
openwrt_fix_broken_apk_uninstall_scripts()
{
# at least in early snapshots with apk removing gnu gzip, sort, ... does not restore links to busybox
# system may become unusable
exists sort || { echo fixing missing sort; ln -fs /bin/busybox /usr/bin/sort; }
exists gzip || { echo fixing missing gzip; ln -fs /bin/busybox /bin/gzip; }
exists sleep || { echo fixing missing sleep; ln -fs /bin/busybox /bin/sleep; }
}
remove_extra_pkgs_openwrt()
{
local PKGS
echo \* remove dependencies
removable_pkgs_openwrt
echo these packages may have been installed by install_easy.sh : $PKGS
ask_yes_no N "do you want to remove them" && {
case $OPENWRT_PACKAGER in
opkg)
opkg remove --autoremove $PKGS
;;
apk)
apk del $PKGS
openwrt_fix_broken_apk_uninstall_scripts
;;
esac
}
}
check_prerequisites_openwrt()
{
echo \* checking prerequisites
local PKGS="curl" UPD=0 local pkg_iptables
local PKGS="curl" UPD=0
case "$FWTYPE" in
iptables)
pkg_iptables=iptables
check_package_exists_openwrt iptables-zz-legacy && pkg_iptables=iptables-zz-legacy
PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra"
check_package_exists_openwrt ip6tables-zz-legacy && pkg_iptables=ip6tables-zz-legacy
[ "$DISABLE_IPV6" = 1 ] || PKGS="$PKGS $pkg_iptables ip6tables-mod-nat ip6tables-extra"
PKGS="$PKGS ipset iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra"
[ "$DISABLE_IPV6" != "1" ] && PKGS="$PKGS ip6tables ip6tables-mod-nat ip6tables-extra"
;;
nftables)
PKGS="$PKGS nftables kmod-nft-nat kmod-nft-offload kmod-nft-queue"
@ -753,9 +611,9 @@ check_prerequisites_openwrt()
else
echo \* installing prerequisites
$OPENWRT_PACKAGER_UPDATE
opkg update
UPD=1
$OPENWRT_PACKAGER_INSTALL $PKGS || {
opkg install $PKGS || {
echo could not install prerequisites
exitp 6
}
@ -768,10 +626,10 @@ check_prerequisites_openwrt()
echo installer can install GNU gzip but it requires about 100 Kb space
if ask_yes_no N "do you want to install GNU gzip"; then
[ "$UPD" = "0" ] && {
$OPENWRT_PACKAGER_UPDATE
opkg update
UPD=1
}
$OPENWRT_PACKAGER_INSTALL --force-overwrite gzip
opkg install --force-overwrite gzip
fi
}
is_linked_to_busybox sort && {
@ -781,10 +639,10 @@ check_prerequisites_openwrt()
echo installer can install GNU sort but it requires about 100 Kb space
if ask_yes_no N "do you want to install GNU sort"; then
[ "$UPD" = "0" ] && {
$OPENWRT_PACKAGER_UPDATE
opkg update
UPD=1
}
$OPENWRT_PACKAGER_INSTALL --force-overwrite coreutils-sort
opkg install --force-overwrite coreutils-sort
fi
}
[ "$FSLEEP" = 0 ] && is_linked_to_busybox sleep && {
@ -793,10 +651,10 @@ check_prerequisites_openwrt()
echo if you want to speed up blockcheck install coreutils-sleep. it requires about 40 Kb space
if ask_yes_no N "do you want to install COREUTILS sleep"; then
[ "$UPD" = "0" ] && {
$OPENWRT_PACKAGER_UPDATE
opkg update
UPD=1
}
$OPENWRT_PACKAGER_INSTALL --force-overwrite coreutils-sleep
opkg install --force-overwrite coreutils-sleep
fsleep_setup
fi
}
@ -829,37 +687,3 @@ select_fwtype()
echo select firewall type :
ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE
}
dry_run_tpws_()
{
local TPWS="$ZAPRET_BASE/tpws/tpws"
echo verifying tpws options
"$TPWS" --dry-run "$@"
}
dry_run_nfqws_()
{
local NFQWS="$ZAPRET_BASE/nfq/nfqws"
echo verifying nfqws options
"$NFQWS" --dry-run "$@"
}
dry_run_tpws()
{
[ "$TPWS_ENABLE" = 1 ] || return 0
local opt="$TPWS_OPT" port=${TPPORT_SOCKS:-988}
filter_apply_hostlist_target opt
dry_run_tpws_ --port=$port $opt
}
dry_run_tpws_socks()
{
[ "$TPWS_SOCKS_ENABLE" = 1 ] || return 0
local opt="$TPWS_SOCKS_OPT" port=${TPPORT:-987}
filter_apply_hostlist_target opt
dry_run_tpws_ --port=$port --socks $opt
}
dry_run_nfqws()
{
[ "$NFQWS_ENABLE" = 1 ] || return 0
local opt="$NFQWS_OPT" qn=${QNUM:-200}
filter_apply_hostlist_target opt
dry_run_nfqws_ --qnum=$qn $opt
}

View File

@ -1,21 +1,17 @@
std_ports
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"
readonly ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes"
ipt()
{
iptables $FW_EXTRA_PRE -C "$@" $FW_EXTRA_POST >/dev/null 2>/dev/null || iptables $FW_EXTRA_PRE -I "$@" $FW_EXTRA_POST
iptables -C "$@" >/dev/null 2>/dev/null || iptables -I "$@"
}
ipta()
{
iptables $FW_EXTRA_PRE -C "$@" $FW_EXTRA_POST >/dev/null 2>/dev/null || iptables $FW_EXTRA_PRE -A "$@" $FW_EXTRA_POST
iptables -C "$@" >/dev/null 2>/dev/null || iptables -A "$@"
}
ipt_del()
{
iptables $FW_EXTRA_PRE -C "$@" $FW_EXTRA_POST >/dev/null 2>/dev/null && iptables $FW_EXTRA_PRE -D "$@" $FW_EXTRA_POST
iptables -C "$@" >/dev/null 2>/dev/null && iptables -D "$@"
}
ipt_add_del()
{
@ -52,6 +48,28 @@ is_ipt_flow_offload_avail()
grep -q FLOWOFFLOAD 2>/dev/null /proc/net/ip$1_tables_targets
}
filter_apply_port_target()
{
# $1 - var name of iptables filter
local f
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then
f="-p tcp -m multiport --dports $HTTP_PORTS_IPT,$HTTPS_PORTS_IPT"
elif [ "$MODE_HTTPS" = "1" ]; then
f="-p tcp -m multiport --dports $HTTPS_PORTS_IPT"
elif [ "$MODE_HTTP" = "1" ]; then
f="-p tcp -m multiport --dports $HTTP_PORTS_IPT"
else
echo WARNING !!! HTTP and HTTPS are both disabled
fi
eval $1="\"\$$1 $f\""
}
filter_apply_port_target_quic()
{
# $1 - var name of nftables filter
local f
f="-p udp -m multiport --dports $QUIC_PORTS_IPT"
eval $1="\"\$$1 $f\""
}
filter_apply_ipset_target4()
{
# $1 - var name of ipv4 iptables filter
@ -116,7 +134,7 @@ unprepare_tpws_fw()
ipt_print_op()
{
if [ "$1" = "1" ]; then
echo "Inserting ip$4tables rule for $3 : $2"
echo "Adding ip$4tables rule for $3 : $2"
else
echo "Deleting ip$4tables rule for $3 : $2"
fi
@ -136,7 +154,7 @@ _fw_tpws4()
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
ipt_add_del $1 PREROUTING -t nat -i $i $rule
done
@ -164,7 +182,7 @@ _fw_tpws6()
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
_dnat6_target $i DNAT6
[ -n "$DNAT6" -a "$DNAT6" != "-" ] && ipt6_add_del $1 PREROUTING -t nat -i $i $rule -j DNAT --to [$DNAT6]:$3
@ -202,7 +220,7 @@ _fw_nfqws_post4()
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)"
rule="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass"
rule="$2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass"
if [ -n "$4" ] ; then
for i in $4; do
ipt_add_del $1 POSTROUTING -t mangle -o $i $rule
@ -223,7 +241,7 @@ _fw_nfqws_post6()
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)" 6
rule="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass"
rule="$2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass"
if [ -n "$4" ] ; then
for i in $4; do
ipt6_add_del $1 POSTROUTING -t mangle -o $i $rule
@ -302,13 +320,27 @@ fw_nfqws_pre()
}
produce_reverse_nfqws_rule()
{
local rule="$1"
if contains "$rule" "$ipt_connbytes"; then
# autohostlist - need several incoming packets
# autottl - need only one incoming packet
[ "$MODE_FILTER" = autohostlist ] || rule=$(echo "$rule" | sed -re "s/$ipt_connbytes [0-9]+:[0-9]+/$ipt_connbytes 1:1/")
else
local n=1
[ "$MODE_FILTER" = autohostlist ] && n=$(first_packets_for_mode)
rule="$ipt_connbytes 1:$n $rule"
fi
echo "$rule" | reverse_nfqws_rule_stream
}
fw_reverse_nfqws_rule4()
{
fw_nfqws_pre4 $1 "$(reverse_nfqws_rule "$2")" $3
fw_nfqws_pre4 $1 "$(produce_reverse_nfqws_rule "$2")" $3
}
fw_reverse_nfqws_rule6()
{
fw_nfqws_pre6 $1 "$(reverse_nfqws_rule "$2")" $3
fw_nfqws_pre6 $1 "$(produce_reverse_nfqws_rule "$2")" $3
}
fw_reverse_nfqws_rule()
{
@ -321,76 +353,93 @@ fw_reverse_nfqws_rule()
fw_reverse_nfqws_rule6 $1 "$3" $4
}
ipt_first_packets()
{
# $1 - packet count
[ -n "$1" -a "$1" != keepalive ] && [ "$1" -ge 1 ] && echo "$ipt_connbytes 1:$1"
}
ipt_do_nfqws_in_out()
{
# $1 - 1 - add, 0 - del
# $2 - tcp,udp
# $3 - ports
# $4 - PKT_OUT. special value : 'keepalive'
# $5 - PKT_IN
local f4 f6 first_packets_only
[ -n "$3" ] || return
[ -n "$4" -a "$4" != 0 ] &&
{
first_packets_only="$(ipt_first_packets $4)"
f4="-p $2 -m multiport --dports $3 $first_packets_only"
f6=$f4
filter_apply_ipset_target f4 f6
fw_nfqws_post $1 "$f4" "$f6" $QNUM
}
[ -n "$5" -a "$5" != 0 ] &&
{
first_packets_only="$(ipt_first_packets $5)"
f4="-p $2 -m multiport --dports $3 $first_packets_only"
f6=$f4
filter_apply_ipset_target f4 f6
fw_reverse_nfqws_rule $1 "$f4" "$f6" $QNUM
}
}
zapret_do_firewall_standard_tpws_rules_ipt()
{
# $1 - 1 - add, 0 - del
local f4 f6
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] && {
f4="-p tcp -m multiport --dports $TPWS_PORTS_IPT"
f6=$f4
filter_apply_ipset_target f4 f6
fw_tpws $1 "$f4" "$f6" $TPPORT
}
}
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_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_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()
{
# $1 - 1 - add, 0 - del
local mode="${MODE_OVERRIDE:-$MODE}"
zapret_do_firewall_standard_rules_ipt $1
custom_runner zapret_custom_firewall $1
local first_packet_only="$ipt_connbytes 1:$(first_packets_for_mode)"
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
local n f4 f6 qn qns qn6 qns6
case "$mode" in
tpws)
if [ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ]; then
echo both http and https are disabled. not applying redirection.
else
filter_apply_port_target f4
f6=$f4
filter_apply_ipset_target f4 f6
fw_tpws $1 "$f4" "$f6" $TPPORT
fi
;;
nfqws)
# quite complex but we need to minimize nfqws processes to save RAM
get_nfqws_qnums qn qns qn6 qns6
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn" ] && [ "$qn" = "$qns" ]; then
filter_apply_port_target f4
f4="$f4 $first_packet_only"
filter_apply_ipset_target4 f4
fw_nfqws_post4 $1 "$f4 $desync" $qn
fw_reverse_nfqws_rule4 $1 "$f4" $qn
else
if [ -n "$qn" ]; then
f4="-p tcp -m multiport --dports $HTTP_PORTS_IPT"
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f4="$f4 $first_packet_only"
filter_apply_ipset_target4 f4
fw_nfqws_post4 $1 "$f4 $desync" $qn
fw_reverse_nfqws_rule4 $1 "$f4" $qn
fi
if [ -n "$qns" ]; then
f4="-p tcp -m multiport --dports $HTTPS_PORTS_IPT $first_packet_only"
filter_apply_ipset_target4 f4
fw_nfqws_post4 $1 "$f4 $desync" $qns
fw_reverse_nfqws_rule4 $1 "$f4" $qns
fi
fi
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn6" ] && [ "$qn6" = "$qns6" ]; then
filter_apply_port_target f6
f6="$f6 $first_packet_only"
filter_apply_ipset_target6 f6
fw_nfqws_post6 $1 "$f6 $desync" $qn6
fw_reverse_nfqws_rule6 $1 "$f6" $qn6
else
if [ -n "$qn6" ]; then
f6="-p tcp -m multiport --dports $HTTP_PORTS_IPT"
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f6="$f6 $first_packet_only"
filter_apply_ipset_target6 f6
fw_nfqws_post6 $1 "$f6 $desync" $qn6
fw_reverse_nfqws_rule6 $1 "$f6" $qn6
fi
if [ -n "$qns6" ]; then
f6="-p tcp -m multiport --dports $HTTPS_PORTS_IPT $first_packet_only"
filter_apply_ipset_target6 f6
fw_nfqws_post6 $1 "$f6 $desync" $qns6
fw_reverse_nfqws_rule6 $1 "$f6" $qns6
fi
fi
get_nfqws_qnums_quic qn qn6
if [ -n "$qn" ]; then
f4=
filter_apply_port_target_quic f4
f4="$f4 $first_packet_only"
filter_apply_ipset_target4 f4
fw_nfqws_post4 $1 "$f4 $desync" $qn
fi
if [ -n "$qn6" ]; then
f6=
filter_apply_port_target_quic f6
f6="$f6 $first_packet_only"
filter_apply_ipset_target6 f6
fw_nfqws_post6 $1 "$f6 $desync" $qn6
fi
;;
custom)
custom_runner zapret_custom_firewall $1
;;
esac
}
zapret_do_firewall_ipt()
@ -403,6 +452,10 @@ zapret_do_firewall_ipt()
echo Clearing iptables
fi
local mode="${MODE_OVERRIDE:-$MODE}"
[ "$mode" = "tpws-socks" ] && return 0
# always create ipsets. ip_exclude ipset is required
[ "$1" = 1 ] && create_ipset no-update

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

@ -23,7 +23,7 @@ zapret_do_firewall()
# switch on liberal mode on zapret firewall start and switch off on zapret firewall stop
# this is only required for processing incoming bad RSTs. incoming rules are only applied in autohostlist mode
# calling this after firewall because conntrack module can be not loaded before applying conntrack firewall rules
[ "$MODE_FILTER" = "autohostlist" ] && set_conntrack_liberal_mode $1
[ "$MODE_FILTER" = "autohostlist" -a "$MODE" != tpws -a "$MODE" != tpws-socks ] && set_conntrack_liberal_mode $1
[ "$1" = 1 -a -n "$INIT_FW_POST_UP_HOOK" ] && $INIT_FW_POST_UP_HOOK
[ "$1" = 0 -a -n "$INIT_FW_POST_DOWN_HOOK" ] && $INIT_FW_POST_DOWN_HOOK
@ -38,3 +38,16 @@ zapret_unapply_firewall()
{
zapret_do_firewall 0 "$@"
}
first_packets_for_mode()
{
# autohostlist and autottl modes requires incoming traffic sample
# always use conntrack packet limiter or nfqws will deal with gigabytes
local n
if [ "$MODE_FILTER" = "autohostlist" ]; then
n=$((6+${AUTOHOSTLIST_RETRANS_THRESHOLD:-3}))
else
n=6
fi
echo $n
}

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

View File

@ -1,6 +1,3 @@
HOSTLIST_MARKER="<HOSTLIST>"
HOSTLIST_NOAUTO_MARKER="<HOSTLIST_NOAUTO>"
find_hostlists()
{
[ -n "$HOSTLIST_BASE" ] || HOSTLIST_BASE="$ZAPRET_BASE/ipset"
@ -21,35 +18,38 @@ find_hostlists()
HOSTLIST_AUTO_DEBUGLOG="$HOSTLIST_BASE/zapret-hosts-auto-debug.log"
}
filter_apply_autohostlist_target()
{
# $1 - var name of tpws or nfqws params
local parm1="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}"
local parm2="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
local parm3 parm4
[ "$MODE" = "tpws" -o "$MODE" = "tpws-socks" ] || parm3="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
[ "$AUTOHOSTLIST_DEBUGLOG" = 1 ] && parm4="--hostlist-auto-debug=$HOSTLIST_AUTO_DEBUGLOG"
eval $1="\"\$$1 --hostlist-auto=$HOSTLIST_AUTO $parm1 $parm2 $parm3 $parm4\""
}
filter_apply_hostlist_target()
{
# $1 - var name of tpws or nfqws params
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parmNA
eval v="\$$1"
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
{
find_hostlists
parm1="${HOSTLIST_USER:+--hostlist=$HOSTLIST_USER}"
parm2="${HOSTLIST:+--hostlist=$HOSTLIST}"
parm3="${HOSTLIST_EXCLUDE:+--hostlist-exclude=$HOSTLIST_EXCLUDE}"
[ "$MODE_FILTER" = autohostlist ] &&
{
parm4="--hostlist-auto=$HOSTLIST_AUTO"
parm5="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}"
parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
parm8="--hostlist=$HOSTLIST_AUTO"
}
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}"
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm8:+ $parm8}"
}
v="$(replace_str $HOSTLIST_NOAUTO_MARKER "$parmNA" "$v")"
v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")"
[ "$MODE_FILTER" = autohostlist -a "$AUTOHOSTLIST_DEBUGLOG" = 1 ] && {
v="$v --hostlist-auto-debug=$HOSTLIST_AUTO_DEBUGLOG"
}
eval $1=\""$v"\"
fi
[ "$MODE_FILTER" = "hostlist" -o "$MODE_FILTER" = "autohostlist" ] || return
local HOSTLIST_BASE HOSTLIST HOSTLIST_USER HOSTLIST_EXCLUDE
find_hostlists
[ -n "$HOSTLIST" ] && eval $1="\"\$$1 --hostlist=$HOSTLIST\""
[ -n "$HOSTLIST_USER" ] && eval $1="\"\$$1 --hostlist=$HOSTLIST_USER\""
[ -n "$HOSTLIST_EXCLUDE" ] && eval $1="\"\$$1 --hostlist-exclude=$HOSTLIST_EXCLUDE\""
[ "$MODE_FILTER" = "autohostlist" ] && filter_apply_autohostlist_target $1
}
filter_apply_suffix()
{
# $1 - var name of tpws or nfqws params
# $2 - suffix value
local v="${2:+ --new $2}"
eval $1="\"\$$1$v\""
}

View File

@ -1,5 +1,5 @@
[ -n "$ZAPRET_NFT_TABLE" ] || ZAPRET_NFT_TABLE=zapret
nft_connbytes="ct original packets"
readonly nft_connbytes="ct original packets"
# required for : nft -f -
create_dev_stdin
@ -86,16 +86,10 @@ cat << EOF | nft -f -
add rule inet $ZAPRET_NFT_TABLE localnet_protect ip daddr $TPWS_LOCALHOST4 return comment "route_localnet allow access to tpws"
add rule inet $ZAPRET_NFT_TABLE localnet_protect ip daddr 127.0.0.0/8 drop comment "route_localnet remote access protection"
add rule inet $ZAPRET_NFT_TABLE input iif != lo jump localnet_protect
add chain inet $ZAPRET_NFT_TABLE postrouting
add chain inet $ZAPRET_NFT_TABLE postrouting { type filter hook postrouting priority 99; }
flush chain inet $ZAPRET_NFT_TABLE postrouting
add chain inet $ZAPRET_NFT_TABLE postrouting_hook { type filter hook postrouting priority 99; }
flush chain inet $ZAPRET_NFT_TABLE postrouting_hook
add rule inet $ZAPRET_NFT_TABLE postrouting_hook mark and $DESYNC_MARK == 0 jump postrouting
add chain inet $ZAPRET_NFT_TABLE postnat
add chain inet $ZAPRET_NFT_TABLE postnat { type filter hook postrouting priority 101; }
flush chain inet $ZAPRET_NFT_TABLE postnat
add chain inet $ZAPRET_NFT_TABLE postnat_hook { type filter hook postrouting priority 101; }
flush chain inet $ZAPRET_NFT_TABLE postnat_hook
add rule inet $ZAPRET_NFT_TABLE postnat_hook mark and $DESYNC_MARK == 0 jump postnat
add chain inet $ZAPRET_NFT_TABLE prerouting { type filter hook prerouting priority -99; }
flush chain inet $ZAPRET_NFT_TABLE prerouting
add chain inet $ZAPRET_NFT_TABLE prenat { type filter hook prerouting priority -101; }
@ -113,7 +107,6 @@ cat << EOF | nft -f -
add set inet $ZAPRET_NFT_TABLE wanif { type ifname; }
add set inet $ZAPRET_NFT_TABLE wanif6 { type ifname; }
add map inet $ZAPRET_NFT_TABLE link_local { type ifname : ipv6_addr; }
EOF
[ -n "$POSTNAT_ALL" ] && {
nft_flush_chain predefrag_nfqws
@ -125,12 +118,6 @@ nft_del_chains()
# do not delete all chains because of additional user hooks
# they must be inside zapret table to use nfsets
# these chains are newer. do not fail all because chains are not present
cat << EOF | nft -f - 2>/dev/null
delete chain inet $ZAPRET_NFT_TABLE postrouting_hook
delete chain inet $ZAPRET_NFT_TABLE postnat_hook
EOF
cat << EOF | nft -f - 2>/dev/null
delete chain inet $ZAPRET_NFT_TABLE dnat_output
delete chain inet $ZAPRET_NFT_TABLE dnat_pre
@ -212,15 +199,7 @@ nft_add_rule()
# $2,$3,... - rule(s)
local chain="$1"
shift
nft add rule inet $ZAPRET_NFT_TABLE $chain $FW_EXTRA_PRE "$@"
}
nft_insert_rule()
{
# $1 - chain
# $2,$3,... - rule(s)
local chain="$1"
shift
nft insert rule inet $ZAPRET_NFT_TABLE $chain $FW_EXTRA_PRE "$@"
nft add rule inet $ZAPRET_NFT_TABLE $chain "$@"
}
nft_add_set_element()
{
@ -248,7 +227,6 @@ nft_clean_nfqws_rule()
nft_add_nfqws_flow_exempt_rule()
{
# $1 - rule (must be all filters in one var)
local FW_EXTRA_POST= FW_EXTRA_PRE=
nft_add_rule flow_offload $(nft_clean_nfqws_rule $1) return comment \"direct flow offloading exemption\"
# do not need this because of oifname @wanif/@wanif6 filter in forward chain
#nft_add_rule flow_offload $(nft_reverse_nfqws_rule $1) return comment \"reverse flow offloading exemption\"
@ -258,11 +236,32 @@ nft_add_flow_offload_exemption()
# "$1" - rule for ipv4
# "$2" - rule for ipv6
# "$3" - comment
local FW_EXTRA_POST= FW_EXTRA_PRE=
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || nft_add_rule flow_offload oifname @wanif $1 ip daddr != @nozapret 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()
{
# ft can be absent
@ -276,6 +275,28 @@ nft_apply_flow_offloading()
nft_filter_apply_port_target()
{
# $1 - var name of nftables filter
local f
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then
f="tcp dport {$HTTP_PORTS,$HTTPS_PORTS}"
elif [ "$MODE_HTTPS" = "1" ]; then
f="tcp dport {$HTTPS_PORTS}"
elif [ "$MODE_HTTP" = "1" ]; then
f="tcp dport {$HTTP_PORTS}"
else
echo WARNING !!! HTTP and HTTPS are both disabled
fi
eval $1="\"\$$1 $f\""
}
nft_filter_apply_port_target_quic()
{
# $1 - var name of nftables filter
local f
f="udp dport {$QUIC_PORTS}"
eval $1="\"\$$1 $f\""
}
nft_filter_apply_ipset_target4()
{
# $1 - var name of ipv4 nftables filter
@ -348,15 +369,17 @@ flush set inet $ZAPRET_NFT_TABLE lanif"
nft_create_or_update_flowtable 'offload' 2>/dev/null
# then add elements. some of them can cause error because unsupported
for i in $ALLDEVS; do
# first try to add interface itself
nft_create_or_update_flowtable 'offload' $i 2>/dev/null
# 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
devs=$(resolve_lower_devices $i)
for j in $devs; do
# do not display error if addition failed
nft_create_or_update_flowtable 'offload' $j 2>/dev/null
done
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
# some members may not support hw offload. example : lan1 lan2 lan3 support, wlan0 wlan1 - not
devs=$(resolve_lower_devices $i)
for j in $devs; do
# do not display error if addition failed
nft_create_or_update_flowtable 'offload' $j 2>/dev/null
done
fi
done
;;
esac
@ -376,7 +399,7 @@ nft_only()
nft_print_op()
{
echo "Inserting nftables ipv$3 rule for $2 : $1"
echo "Adding nftables ipv$3 rule for $2 : $1"
}
_nft_fw_tpws4()
{
@ -387,8 +410,8 @@ _nft_fw_tpws4()
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
local filter="$1" port="$2"
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_pre iifname @lanif $filter ip daddr != @nozapret ip daddr != @ipban $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
nft_add_rule dnat_output skuid != $WS_USER ${3:+oifname @wanif }$filter ip daddr != @nozapret dnat ip to $TPWS_LOCALHOST4:$port
nft_add_rule dnat_pre iifname @lanif $filter ip daddr != @nozapret dnat ip to $TPWS_LOCALHOST4:$port
prepare_route_localnet
}
}
@ -402,9 +425,9 @@ _nft_fw_tpws6()
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
local filter="$1" port="$2" DNAT6 i
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_add_rule dnat_output skuid != $WS_USER ${4:+oifname @wanif6 }$filter ip6 daddr != @nozapret6 dnat ip6 to [::1]:$port
[ -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_add_rule dnat_pre $filter ip6 daddr != @nozapret6 dnat ip6 to iifname map @link_local:$port
for i in $3; do
_dnat6_target $i DNAT6
# can be multiple tpws processes on different ports
@ -453,7 +476,7 @@ _nft_fw_nfqws_post4()
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 4
rule="${3:+oifname @wanif }$filter ip daddr != @nozapret"
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
nft_insert_rule $chain $rule $setmark $FW_EXTRA_POST queue num $port bypass
nft_add_rule $chain $rule $setmark queue num $port bypass
nft_add_nfqws_flow_exempt_rule "$rule"
}
}
@ -468,7 +491,7 @@ _nft_fw_nfqws_post6()
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 6
rule="${3:+oifname @wanif6 }$filter ip6 daddr != @nozapret6"
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
nft_insert_rule $chain $rule $setmark $FW_EXTRA_POST queue num $port bypass
nft_add_rule $chain $rule $setmark queue num $port bypass
nft_add_nfqws_flow_exempt_rule "$rule"
}
}
@ -492,7 +515,7 @@ _nft_fw_nfqws_pre4()
local filter="$1" port="$2" rule
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 4
rule="${3:+iifname @wanif }$filter ip saddr != @nozapret"
nft_insert_rule $(get_prechain) $rule $FW_EXTRA_POST queue num $port bypass
nft_add_rule $(get_prechain) $rule queue num $port bypass
}
}
_nft_fw_nfqws_pre6()
@ -505,7 +528,7 @@ _nft_fw_nfqws_pre6()
local filter="$1" port="$2" rule
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 6
rule="${3:+iifname @wanif6 }$filter ip6 saddr != @nozapret6"
nft_insert_rule $(get_prechain) $rule $FW_EXTRA_POST queue num $port bypass
nft_add_rule $(get_prechain) $rule queue num $port bypass
}
}
nft_fw_nfqws_pre()
@ -559,13 +582,29 @@ zapret_list_table()
nft_produce_reverse_nfqws_rule()
{
local rule="$1"
if contains "$rule" "$nft_connbytes "; then
# autohostlist - need several incoming packets
# autottl - need only one incoming packet
[ "$MODE_FILTER" = autohostlist ] || rule=$(echo "$rule" | sed -re "s/$nft_connbytes [0-9]+-[0-9]+/$nft_connbytes 1/")
else
# old nft does not swallow 1-1
local range=1
[ "$MODE_FILTER" = autohostlist ] && range=$(first_packets_for_mode)
[ "$range" = 1 ] || range="1-$range"
rule="$nft_connbytes $range $rule"
fi
nft_reverse_nfqws_rule $rule
}
nft_fw_reverse_nfqws_rule4()
{
nft_fw_nfqws_pre4 "$(nft_reverse_nfqws_rule "$1")" $2
nft_fw_nfqws_pre4 "$(nft_produce_reverse_nfqws_rule "$1")" $2
}
nft_fw_reverse_nfqws_rule6()
{
nft_fw_nfqws_pre6 "$(nft_reverse_nfqws_rule "$1")" $2
nft_fw_nfqws_pre6 "$(nft_produce_reverse_nfqws_rule "$1")" $2
}
nft_fw_reverse_nfqws_rule()
{
@ -577,81 +616,108 @@ nft_fw_reverse_nfqws_rule()
nft_fw_reverse_nfqws_rule6 "$2" $3
}
nft_first_packets()
{
# $1 - packet count
[ -n "$1" -a "$1" != keepalive ] && [ "$1" -ge 1 ] &&
{
if [ "$1" = 1 ] ; then
echo "$nft_connbytes 1"
else
echo "$nft_connbytes 1-$1"
fi
}
}
nft_apply_nfqws_in_out()
{
# $1 - tcp,udp
# $2 - ports
# $3 - PKT_OUT. special value : 'keepalive'
# $4 - PKT_IN
local f4 f6 first_packets_only
[ -n "$2" ] || return
[ -n "$3" -a "$3" != 0 ] &&
{
first_packets_only="$(nft_first_packets $3)"
f4="$1 dport {$2} $first_packets_only"
f6=$f4
nft_filter_apply_ipset_target f4 f6
nft_fw_nfqws_post "$f4" "$f6" $QNUM
}
[ -n "$4" -a "$4" != 0 ] &&
{
first_packets_only="$(nft_first_packets $4)"
f4="$1 dport {$2} $first_packets_only"
f6=$f4
nft_filter_apply_ipset_target f4 f6
nft_fw_reverse_nfqws_rule "$f4" "$f6" $QNUM
}
}
zapret_apply_firewall_standard_tpws_rules_nft()
{
local f4 f6
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] && {
f4="tcp dport {$TPWS_PORTS}"
f6=$f4
nft_filter_apply_ipset_target f4 f6
nft_fw_tpws "$f4" "$f6" $TPPORT
}
}
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_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_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_standard_rules_nft
custom_runner zapret_custom_firewall_nft
local mode="${MODE_OVERRIDE:-$MODE}"
local first_packets_only
local desync="mark and $DESYNC_MARK == 0"
local f4 f6 qn qns qn6 qns6
first_packets_only="$nft_connbytes 1-$(first_packets_for_mode)"
case "$mode" in
tpws)
if [ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ]; then
echo both http and https are disabled. not applying redirection.
else
nft_filter_apply_port_target f4
f6=$f4
nft_filter_apply_ipset_target f4 f6
nft_fw_tpws "$f4" "$f6" $TPPORT
fi
;;
nfqws)
local POSTNAT_SAVE=$POSTNAT
POSTNAT=1
# quite complex but we need to minimize nfqws processes to save RAM
get_nfqws_qnums qn qns qn6 qns6
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn" ] && [ "$qn" = "$qns" ]; then
nft_filter_apply_port_target f4
f4="$f4 $first_packets_only"
nft_filter_apply_ipset_target4 f4
nft_fw_nfqws_post4 "$f4 $desync" $qn
nft_fw_reverse_nfqws_rule4 "$f4" $qn
else
if [ -n "$qn" ]; then
f4="tcp dport {$HTTP_PORTS}"
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f4="$f4 $first_packets_only"
nft_filter_apply_ipset_target4 f4
nft_fw_nfqws_post4 "$f4 $desync" $qn
nft_fw_reverse_nfqws_rule4 "$f4" $qn
fi
if [ -n "$qns" ]; then
f4="tcp dport {$HTTPS_PORTS} $first_packets_only"
nft_filter_apply_ipset_target4 f4
nft_fw_nfqws_post4 "$f4 $desync" $qns
nft_fw_reverse_nfqws_rule4 "$f4" $qns
fi
fi
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn6" ] && [ "$qn6" = "$qns6" ]; then
nft_filter_apply_port_target f6
f6="$f6 $first_packets_only"
nft_filter_apply_ipset_target6 f6
nft_fw_nfqws_post6 "$f6 $desync" $qn6
nft_fw_reverse_nfqws_rule6 "$f6" $qn6
else
if [ -n "$qn6" ]; then
f6="tcp dport {$HTTP_PORTS}"
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f6="$f6 $first_packets_only"
nft_filter_apply_ipset_target6 f6
nft_fw_nfqws_post6 "$f6 $desync" $qn6
nft_fw_reverse_nfqws_rule6 "$f6" $qn6
fi
if [ -n "$qns6" ]; then
f6="tcp dport {$HTTPS_PORTS} $first_packets_only"
nft_filter_apply_ipset_target6 f6
nft_fw_nfqws_post6 "$f6 $desync" $qns6
nft_fw_reverse_nfqws_rule6 "$f6" $qns6
fi
fi
get_nfqws_qnums_quic qn qn6
if [ -n "$qn" ]; then
f4=
nft_filter_apply_port_target_quic f4
f4="$f4 $first_packets_only"
nft_filter_apply_ipset_target4 f4
nft_fw_nfqws_post4 "$f4 $desync" $qn
fi
if [ -n "$qn6" ]; then
f6=
nft_filter_apply_port_target_quic f6
f6="$f6 $first_packets_only"
nft_filter_apply_ipset_target6 f6
nft_fw_nfqws_post6 "$f6 $desync" $qn6
fi
POSTNAT=$POSTNAT_SAVE
;;
custom)
custom_runner zapret_custom_firewall_nft
;;
esac
}
zapret_apply_firewall_nft()
{
echo Applying nftables
local mode="${MODE_OVERRIDE:-$MODE}"
[ "$mode" = "tpws-socks" ] && return 0
create_ipset no-update
nft_create_firewall
nft_fill_ifsets_overload
@ -668,7 +734,6 @@ zapret_unapply_firewall_nft()
unprepare_route_localnet
nft_del_firewall
custom_runner zapret_custom_firewall_nft_flush
return 0
}
zapret_do_firewall_nft()

View File

@ -1,5 +1,5 @@
PF_MAIN="/etc/pf.conf"
PF_ANCHOR_DIR="/etc/pf.anchors"
PF_ANCHOR_DIR=/etc/pf.anchors
PF_ANCHOR_ZAPRET="$PF_ANCHOR_DIR/zapret"
PF_ANCHOR_ZAPRET_V4="$PF_ANCHOR_DIR/zapret-v4"
PF_ANCHOR_ZAPRET_V6="$PF_ANCHOR_DIR/zapret-v6"
@ -108,17 +108,33 @@ pf_anchor_zapret_tables()
}
pf_nat_reorder_rules()
{
# this is dirty hack to move rdr above route-to
# use only first word as a key and preserve order within a single key
sort -srfk 1,1
# this is dirty hack to move rdr above route-to and remove route-to dups
sort -rfu
}
pf_anchor_port_target()
{
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then
echo "{$HTTP_PORTS_IPT,$HTTPS_PORTS_IPT}"
elif [ "$MODE_HTTPS" = "1" ]; then
echo "{$HTTPS_PORTS_IPT}"
elif [ "$MODE_HTTP" = "1" ]; then
echo "{$HTTP_PORTS_IPT}"
fi
}
pf_anchor_zapret_v4_tpws()
{
# $1 - tpws listen port
# $2 - rdr ports
# $2 - rdr ports. defaults are used if empty
local rule port
if [ -n "$2" ]; then
port="{$2}"
else
port=$(pf_anchor_port_target)
fi
local rule port="{$2}"
for lan in $IFACE_LAN; do
for t in $tbl; do
echo "rdr on $lan inet proto tcp from any to $t port $port -> 127.0.0.1 port $1"
@ -141,19 +157,31 @@ pf_anchor_zapret_v4()
{
local tbl port
[ "$DISABLE_IPV4" = "1" ] || {
{
pf_anchor_zapret_tables tbl zapret-user "$ZIPLIST_USER" zapret "$ZIPLIST"
custom_runner zapret_custom_firewall_v4
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] && pf_anchor_zapret_v4_tpws $TPPORT "$TPWS_PORTS_IPT"
} | pf_nat_reorder_rules
case "${MODE_OVERRIDE:-$MODE}" in
tpws)
[ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ] && return
pf_anchor_zapret_tables tbl zapret-user "$ZIPLIST_USER" zapret "$ZIPLIST"
pf_anchor_zapret_v4_tpws $TPPORT
;;
custom)
pf_anchor_zapret_tables tbl zapret-user "$ZIPLIST_USER" zapret "$ZIPLIST"
custom_runner zapret_custom_firewall_v4 | pf_nat_reorder_rules
;;
esac
}
}
pf_anchor_zapret_v6_tpws()
{
# $1 - tpws listen port
# $2 - rdr ports
# $2 - rdr ports. defaults are used if empty
local rule LL_LAN port="{$2}"
local rule LL_LAN port
if [ -n "$2" ]; then
port="{$2}"
else
port=$(pf_anchor_port_target)
fi
# LAN link local is only for router
for lan in $IFACE_LAN; do
@ -179,12 +207,19 @@ pf_anchor_zapret_v6_tpws()
pf_anchor_zapret_v6()
{
local tbl port
[ "$DISABLE_IPV6" = "1" ] || {
{
pf_anchor_zapret_tables tbl zapret-user "$ZIPLIST_USER" zapret "$ZIPLIST"
custom_runner zapret_custom_firewall_v6
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS_IPT" ] && pf_anchor_zapret_v6_tpws $TPPORT "$TPWS_PORTS_IPT"
} | pf_nat_reorder_rules
case "${MODE_OVERRIDE:-$MODE}" in
tpws)
[ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ] && return
pf_anchor_zapret_tables tbl zapret6-user "$ZIPLIST_USER6" zapret6 "$ZIPLIST6"
pf_anchor_zapret_v6_tpws $TPPORT
;;
custom)
pf_anchor_zapret_tables tbl zapret6-user "$ZIPLIST_USER6" zapret6 "$ZIPLIST6"
custom_runner zapret_custom_firewall_v6 | pf_nat_reorder_rules
;;
esac
}
}

View File

@ -9,9 +9,6 @@
# override firewall type : iptables,nftables,ipfw
#FWTYPE=iptables
# nftables only : set this to 0 to use pre-nat mode. default is post-nat.
# pre-nat mode disables some bypass techniques for forwarded traffic but allows to see client IP addresses in debug log
#POSTNAT=0
# options for ipsets
# maximum number of elements in sets. also used for nft sets
@ -43,61 +40,55 @@ GZIP_LISTS=1
# set to "-" to disable reload
#LISTS_RELOAD="pfctl -f /etc/pf.conf"
# mark bit used by nfqws to prevent loop
DESYNC_MARK=0x40000000
DESYNC_MARK_POSTNAT=0x20000000
TPWS_SOCKS_ENABLE=0
# tpws socks listens on this port on localhost and LAN interfaces
TPPORT_SOCKS=987
# use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir
# hostlist markers are replaced to empty string if MODE_FILTER does not satisfy
# <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list
TPWS_SOCKS_OPT="
--filter-tcp=80 --methodeol <HOSTLIST> --new
--filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST>
"
TPWS_ENABLE=0
TPWS_PORTS=80,443
# use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir
# hostlist markers are replaced to empty string if MODE_FILTER does not satisfy
# <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list
TPWS_OPT="
--filter-tcp=80 --methodeol <HOSTLIST> --new
--filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST>
"
NFQWS_ENABLE=0
# redirect outgoing traffic with connbytes limiter applied in both directions.
NFQWS_PORTS_TCP=80,443
NFQWS_PORTS_UDP=443
# PKT_OUT means connbytes dir original
# PKT_IN means connbytes dir reply
# this is --dpi-desync-cutoff=nX kernel mode implementation for linux. it saves a lot of CPU.
NFQWS_TCP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
NFQWS_TCP_PKT_IN=3
NFQWS_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
NFQWS_UDP_PKT_IN=0
# redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter
# normally it's needed only for stateless DPI that matches every packet in a single TCP session
# typical example are plain HTTP keep alives
# this mode can be very CPU consuming. enable with care !
#NFQWS_PORTS_TCP_KEEPALIVE=80
#NFQWS_PORTS_UDP_KEEPALIVE=
# use <HOSTLIST> and <HOSTLIST_NOAUTO> placeholders to engage standard hostlists and autohostlist in ipset dir
# hostlist markers are replaced to empty string if MODE_FILTER does not satisfy
# <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list
NFQWS_OPT="
--filter-tcp=80 --dpi-desync=fake,multisplit --dpi-desync-split-pos=method+2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
--filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-fooling=badseq,md5sig <HOSTLIST> --new
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST_NOAUTO>
"
# override ports
#HTTP_PORTS=80-81,85
#HTTPS_PORTS=443,500-501
#QUIC_PORTS=443,444
# CHOOSE OPERATION MODE
# MODE : nfqws,tpws,tpws-socks,filter,custom
# nfqws : nfqws for dpi desync
# tpws : tpws transparent mode
# tpws-socks : tpws socks mode
# filter : no daemon, just create ipset or download hostlist
# custom : custom mode. should modify custom init script and add your own code
MODE=tpws
# apply fooling to http
MODE_HTTP=1
# for nfqws only. support http keep alives. enable only if DPI checks for http request in any outgoing packet
MODE_HTTP_KEEPALIVE=0
# apply fooling to https
MODE_HTTPS=1
# apply fooling to quic
MODE_QUIC=0
# none,ipset,hostlist,autohostlist
MODE_FILTER=none
# donttouch,none,software,hardware
# CHOOSE NFQWS DAEMON OPTIONS for DPI desync mode. run "nfq/nfqws --help" for option list
# SUFFIX VARS define additional lower priority desync profile. it's required if MODE_FILTER=hostlist and strategy has hostlist-incompatible 0-phase desync methods (syndata,wssize)
DESYNC_MARK=0x40000000
DESYNC_MARK_POSTNAT=0x20000000
NFQWS_OPT_DESYNC="--dpi-desync=fake --dpi-desync-ttl=0 --dpi-desync-ttl6=0 --dpi-desync-fooling=badsum"
#NFQWS_OPT_DESYNC_SUFFIX="--dpi-desync=syndata"
#NFQWS_OPT_DESYNC_HTTP=""
#NFQWS_OPT_DESYNC_HTTP_SUFFIX="--dpi-desync=syndata"
#NFQWS_OPT_DESYNC_HTTPS=""
#NFQWS_OPT_DESYNC_HTTPS_SUFFIX="--wssize 1:6"
#NFQWS_OPT_DESYNC_HTTP6=""
#NFQWS_OPT_DESYNC_HTTP6_SUFFIX="--dpi-desync=syndata"
#NFQWS_OPT_DESYNC_HTTPS6=""
#NFQWS_OPT_DESYNC_HTTPS6_SUFFIX="--wssize 1:6"
NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake --dpi-desync-repeats=6"
#NFQWS_OPT_DESYNC_QUIC_SUFFIX=""
#NFQWS_OPT_DESYNC_QUIC6="--dpi-desync=hopbyhop"
#NFQWS_OPT_DESYNC_QUIC6_SUFFIX=""
# CHOOSE TPWS DAEMON OPTIONS. run "tpws/tpws --help" for option list
# SUFFIX VARS define additional lower priority desync profile. it's required if MODE_FILTER=hostlist and strategy has hostlist-incompatible 0-phase desync methods (mss)
TPWS_OPT="--hostspell=HOST --split-http-req=method --split-pos=3 --oob"
#TPWS_OPT_SUFFIX="--mss 88"
# openwrt only : donttouch,none,software,hardware
FLOWOFFLOAD=donttouch
# openwrt: specify networks to be treated as LAN. default is "lan"
@ -132,4 +123,4 @@ DISABLE_IPV6=1
# 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
# comment if not required
#GETLIST=
GETLIST=get_antifilter_ipsmart.sh

View File

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

View File

@ -100,7 +100,7 @@ Later you will add ipfw commands to `/etc/rc.firewall.my` to be reapplied after
You can also run zapret daemons from there. Start them with `--daemon` options, for example
```
pkill ^dvtws$
/opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=multisplit --dpi-desync-split-pos=2
/opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=split2
```
To restart firewall and daemons run : `/etc/rc.d/ipfw restart`
@ -157,7 +157,7 @@ ipfw delete 100
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted not sockarg xmit em0
# required for autottl mode only
ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2
```
Process only table zapret with the exception of table nozapret:
@ -167,7 +167,7 @@ ipfw add 100 allow tcp from me to table\(nozapret\) 80,443
ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted not sockarg xmit em0
# required for autottl mode only
ipfw add 100 divert 989 tcp from table\(zapret\) 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2
```
Reinjection loop avoidance. FreeBSD artificially ignores sockarg for ipv6 in
@ -217,9 +217,8 @@ ipfrag2 desync mode.
There's autostart script example in `init.d/pfsense`. It should be placed to
`/usr/local/etc/rc.d` and edited. Write your ipfw rules and daemon start
commands.
curl is present by default. You can use it to download `tar.gz` release directly from github.
Or you can copy files using sftp.
commands. Because git is absent the most convinient way to copy files is ssh.
curl is present by default.
Copy zip with zapret files to `/opt` and unpack there as it's done in other
systems. In this case run `dvtws` as `/opt/zapret/nfq/dvtws`. Or just copy
@ -228,6 +227,9 @@ present. It's possible to renew lists.
If you dont like poverty of default repos its possible to enable FreeBSD repo.
Change `no` to `yes` in `/usr/local/etc/pkg/repos/FreeBSD.conf` and `/usr/local/etc/pkg/repos/pfSense.conf`.
Then it becomes possible to install all the required software including git to download
zapret from github directly.
`/usr/local/etc/rc.d/zapret.sh` (chmod 755)
```
@ -245,7 +247,7 @@ sysctl net.inet6.ip6.pfil.inbound=ipfw,pf
ipfw delete 100
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted not sockarg xmit em0
pkill ^dvtws$
dvtws --daemon --port 989 --dpi-desync=multisplit --dpi-desync-split-pos=2
dvtws --daemon --port 989 --dpi-desync=split2
# required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state
pfctl -d ; pfctl -e
@ -280,7 +282,7 @@ Autostart `/usr/local/etc/rc.d/zapret.sh`:
```
pfctl -a zapret -f /etc/zapret.anchor
pkill ^tpws$
tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-pos=2
tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-http-req=method --split-pos=2
```
After reboot check that anchor is created and referred from the main ruleset:
@ -342,7 +344,7 @@ pass out quick on em0 proto tcp to port {80,443} divert-packet port 989
Then:
```
pfctl -f /etc/pf.conf
./dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
./dvtws --port=989 --dpi-desync=split2
```
`dwtws` only for table zapret with the exception of table nozapret :
@ -375,7 +377,7 @@ pass out quick on em0 inet6 proto tcp to <zapret6-user> port {80,443} divert-p
Then:
```
pfctl -f /etc/pf.conf
./dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
./dvtws --port=989 --dpi-desync=split2
```
divert-packet automatically adds the reverse rule. By default also incoming

View File

@ -1,725 +0,0 @@
# Настройка BSD-подобных систем
* [Поддерживаемые версии](#поддерживаемые-версии)
* [Особенности BSD систем](#особенности-bsd-систем)
* [Отсутствие nfqueue](#отсутствие-nfqueue)
* [Типы Firewall](#типы-firewall)
* [Сборка](#сборка)
* [Divert сокеты](#divert-сокеты)
* [Lookup Tables](#lookup-tables)
* [Загрузка ip таблиц из файла](#загрузка-ip-таблиц-из-файла)
* [Отсутствие splice](#отсутствие-splice)
* [mdig и ip2net](#mdig-и-ip2net)
* [FreeBSD](#freebsd)
* [Подгрузка ipdivert](#подгрузка-ipdivert)
* [Авто-восстановление правил ipfw и работа в фоне](#авто-восстановление-правил-ipfw-и-работа-в-фоне)
* [tpws в прозрачном режиме](#tpws-в-прозрачном-режиме)
* [Запуск dvtws](#запуск-dvtws)
* [PF в FreeBSD](#pf-в-freebsd)
* [pfsense](#pfsense)
* [OpenBSD](#openbsd)
* [tpws bind на ipv4](#tpws-bind-на-ipv4)
* [tpws для проходящего трафика](#tpws-для-проходящего-трафика)
* [Запуск dvtws](#запуск-dvtws)
* [Проблемы с badsum](#проблемы-с-badsum)
* [Особенность отправки fake пакетов](#особенность-отправки-fake-пакетов)
* [Перезагрузка PF таблиц](#перезагрузка-pf-таблиц)
* [MacOS](#macos)
* [Введение](#введение)
* [dvtws бесполезен](#dvtws-бесполезен)
* [tpws](#tpws)
* [Проблема link-local адреса](#проблема-link-local-адреса)
* [Сборка](#сборка)
* [Простая установка](#простая-установка)
* [Вариант Custom](#вариант-custom)
## Поддерживаемые версии
**FreeBSD** 11.x+ , **OpenBSD** 6.x+, частично **MacOS Sierra** +
> [!CAUTION]
> На более старых может собираться, может не собираться, может работать или не
> работать. На **FreeBSD** 10 собирается и работает `dvtws`. С `tpws` есть
> проблемы из-за слишком старой версии компилятора clang. Вероятно, будет
> работать, если обновить компилятор. Возможна прикрутка к последним версиям
> pfsense без веб интерфейса в ручном режиме через консоль.
## Особенности BSD систем
### Отсутствие nfqueue
В **BSD** нет `nfqueue`. Похожий механизм - divert sockets. Из каталога
[`nfq/`](../nfq/) под **BSD** собирается `dvtws` вместо `nfqws`. Он разделяет с
`nfqws` большую часть кода и почти совпадает по параметрам командной строки.
### Типы Firewall
**FreeBSD** содержит 3 фаервола : **IPFilter**, **ipfw** и **Packet Filter (PF
в дальнейшем)**. **OpenBSD** содержит только **PF**.
### Сборка
Под **FreeBSD** `tpws` и `dvtws` собираются через `make`.
Под **OpenBSD**:
```sh
make bsd
```
Под **MacOS**:
```sh
make mac
```
**FreeBSD** make распознает BSDmakefile, **OpenBSD** и **MacOS** - нет. Поэтому
там используется отдельный target в Makefile. Сборка всех исходников:
```sh
make -C /opt/zapret
```
### Divert сокеты
Divert сокет это внутренний тип сокета ядра **BSD**. Он не привязывается ни к
какому сетевому адресу, не участвует в обмене данными через сеть и
идентифицируется по номеру порта `1..65535`. Аналогия с номером очереди
`NFQUEUE`. На divert сокеты заворачивается трафик посредством правил ipfw или
PF. Если в фаерволе есть правило divert, но на divert порту никто не слушает,
то пакеты дропаются. Это поведение аналогично правилам `NFQUEUE` без параметра
`--queue-bypass`. На **FreeBSD** divert сокеты могут быть только ipv4, хотя на
них принимаются и ipv4, и ipv6 фреймы. На **OpenBSD** divert сокеты создаются
отдельно для ipv4 и ipv6 и работают только с одной версией `ip` каждый. На
**MacOS** похоже, что divert сокеты из ядра вырезаны. См подробнее раздел про
**MacOS**. Отсылка в divert сокет работает аналогично отсылке через raw socket
на linux. Передается полностью IP фрейм, начиная с ip загловка. Эти особенности
учитываются в `dvtws`.
### Lookup Tables
Скрипты [`ipset/*.sh`](../ipset/) при наличии ipfw работают с ipfw lookup
tables. Это прямой аналог ipset. lookup tables не разделены на v4 и v6. Они
могут содержать v4 и v6 адреса и подсети одновременно. Если ipfw отсутствует,
то действие зависит от переменной `LISTS_RELOAD` в config. Если она задана, то
выполняется команда из `LISTS_RELOAD`. В противном случае не делается ничего.
Если `LISTS_RELOAD=-`, то заполнение таблиц отключается даже при наличии ipfw.
### Загрузка ip таблиц из файла
PF может загружать ip таблицы из файла. Чтобы использовать эту возможность
следует отключить сжатие gzip для листов через параметр файла config:
`GZIP_LISTS=0`.
### Отсутствие splice
**BSD** не содержит системного вызова splice. `tpws` работает через переброску
данных в user mode в оба конца. Это медленнее, но не критически. Управление
асинхронными сокетами в `tpws` основано на linux-specific механизме epoll. В
**BSD** для его эмуляции используется epoll-shim - прослойка для эмуляции epoll
на базе kqueue.
### mdig и ip2net
mdig и ip2net полностью работоспособны в **BSD**. В них нет ничего
системо-зависимого.
## FreeBSD
### Подгрузка ipdivert
Divert сокеты требуют специального модуля ядра - `ipdivert`.
- Поместите следующие строки в `/boot/loader.conf` (создать, если отсутствует):
```
ipdivert_load="YES"
net.inet.ip.fw.default_to_accept=1
```
`/etc/rc.conf`:
```
firewall_enable="YES"
firewall_script="/etc/rc.firewall.my"
```
`/etc/rc.firewall.my`:
```sh
$ ipfw -q -f flush
```
### Авто-восстановление правил ipfw и работа в фоне
В `/etc/rc.firewall.my` можно дописывать правила ipfw, чтобы они
восстанавливались после перезагрузки. Оттуда же можно запускать и демоны
zapret, добавив в параметры `--daemon`. Например так:
```sh
$ pkill ^dvtws$
$ /opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=multisplit --dpi-desync-split-pos=2
```
Для перезапуска фаервола и демонов достаточно будет сделать:
```sh
$ /etc/rc.d/ipfw restart
```
### tpws в прозрачном режиме
Краткая инструкция по запуску `tpws` в прозрачном режиме.
> [!NOTE]
> Предполагается, что интерфейс LAN называется `em1`, WAN - `em0`.
#### Весь трафик
```sh
$ ipfw delete 100
$ ipfw add 100 fwd 127.0.0.1,988 tcp from me to any 80,443 proto ip4 xmit em0 not uid daemon
$ ipfw add 100 fwd ::1,988 tcp from me to any 80,443 proto ip6 xmit em0 not uid daemon
$ ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1
$ ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1
$ /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
```
#### Трафик только на таблицу zapret, за исключением таблицы nozapret
```sh
$ ipfw delete 100
$ ipfw add 100 allow tcp from me to table\(nozapret\) 80,443
$ ipfw add 100 fwd 127.0.0.1,988 tcp from me to table\(zapret\) 80,443 proto ip4 xmit em0 not uid daemon
$ ipfw add 100 fwd ::1,988 tcp from me to table\(zapret\) 80,443 proto ip6 xmit em0 not uid daemon
$ ipfw add 100 allow tcp from any to table\(nozapret\) 80,443 recv em1
$ ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1
$ ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1
$ /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
```
> [!NOTE]
> Таблицы zapret, nozapret, ipban создаются скриптами из ipset по аналогии с
> Linux. Обновление скриптов можно забить в cron под root:
> ```sh
> $ crontab -e
> ```
>
> ```
> <...>
> 0 12 */2 * * /opt/zapret/ipset/get_config.sh
> ```
> [!CAUTION]
> При использовании ipfw `tpws` не требует повышенных привилегий для реализации
> прозрачного режима. Однако, без рута невозможен bind на порты `< 1024` и
> смена UID/GID. Без смены UID будет рекурсия, поэтому правила ipfw нужно
> создавать с учетом UID, под которым работает `tpws`. Переадресация на порты
> `>= 1024` может создать угрозу перехвата трафика непривилегированным
> процессом, если вдруг `tpws` не запущен.
### Запуск dvtws
#### Весь трафик
```sh
$ ipfw delete 100
$ ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0
# required for autottl mode only
$ ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diverted recv em0
$ /opt/zapret/nfq/dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
#### Трафик только на таблицу zapret, за исключением таблицы nozapret
```sh
$ ipfw delete 100
$ ipfw add 100 allow tcp from me to table\(nozapret\) 80,443
$ ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted not sockarg xmit em0
# required for autottl mode only
$ ipfw add 100 divert 989 tcp from table\(zapret\) 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0
$ /opt/zapret/nfq/dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
### PF в FreeBSD
Настройка аналогична **OpenBSD**, но есть важные нюансы.
- В **FreeBSD** поддержка PF в `tpws` отключена по умолчанию. Чтобы ее
включить, нужно использовать параметр `--enable-pf`.
- Нельзя сделать ipv6 rdr на `::1`. Нужно делать на link-local адрес входящего
интерфейса. Смотрите через `ifconfig` адрес `fe80:...` и добавляете в правило.
- Синтаксис `pf.conf` немного отличается. Более новая версия PF.
- Лимит на количество элементов таблиц задается так:
```sh
$ sysctl net.pf.request_maxcount=2000000
```
- Сломан divert-to. Он работает, но не работает механизм предотвращения
зацикливаний. Кто-то уже написал патч, но в `14-RELEASE` проблема все еще
есть. Следовательно, на данный момент работа `dvtws` через PF невозможна.
`/etc/pf.conf`:
```
rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::31c:29ff:dee2:1c4d port 988
rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988
```
```sh
$ /opt/zapret/tpws/tpws --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force
```
> [!NOTE]
> В PF не выходит делать rdr-to с той же системы, где работает proxy.
> Вариант с route-to не сохраняет мета информацию. Адрес назначения теряется.
> Поэтому этот вариант годится для squid, берущего адрес из протокола прикладного уровня, но не годится для tpws, полагающегося на метаданные ОС.
> Поддержка rdr-to реализована через `/dev/pf`, поэтому прозрачный режим **требует root**.
### pfsense
#### Описание
pfsense основан на **FreeBSD** и использует фаервол PF, имеющий проблемы с
divert. К счастью, модули ipfw и ipdivert присутствуют в поставке последних
версий pfsense. Их можно подгрузить через `kldload`.
В некоторых более старых версиях pfsense требуется изменить порядок фаерволов
через `sysctl`, сделав ipfw первым. В более новых эти параметры `sysctl`
отсутствуют, но система работает как надо и без них. В некоторых случаях
фаервол PF может ограничивать возможности `dvtws`, в частности в области
фрагментации ip.
Присутствуют по умолчанию правила scrub для реассемблинга фрагментов.
Бинарики из [`binaries/freebsd-x64`](../binaries/freebsd-x64) собраны под
**FreeBSD 11**. Они должны работать и на последующих версиях **FreeBSD**,
включая pfsense. Можно пользоваться `install_bin.sh`.
#### Автозапуск
Пример скрипта автозапуска лежит в [`init.d/pfsense`](../init.d/pfsense). Его
следует поместить в `/usr/local/etc/rc.d` и отредактировать на предмет правил
ipfw и запуска демонов. Есть встроенный редактор `edit` как более приемлемая
альтернатива `vi`.
> [!NOTE]
> Поскольку `git` отсутствует, копировать файлы удобнее всего через `ssh`.
> `curl` присутствует по умолчанию. Можно скопировать zip с файлами zapret и
> распаковать в `/opt`, как это делается на других системах. Тогда `dvtws`
> нужно запускать как `/opt/zapret/nfq/dvtws`. Либо скопировать только `dvtws`
> в `/usr/local/sbin`. Как вам больше нравится.
> [!NOTE]
> Скрипты ipset работают, крон есть. Можно сделать автообновление листов.
> [!NOTE]
> Если вас напрягает бедность имеющегося репозитория, можно включить
> репозиторий от **FreeBSD**, который по умолчанию выключен.
>
> Поменяйте `no` на `yes` в `/usr/local/etc/pkg/repos/FreeBSD.conf`
>
> Можно установить весь привычный софт, включая `git`, чтобы напрямую скачивать
> zapret с github.
`/usr/local/etc/rc.d/zapret.sh` (chmod `755`):
```sh
#!/bin/sh
kldload ipfw
kldload ipdivert
# for older pfsense versions. newer do not have these sysctls
sysctl net.inet.ip.pfil.outbound=ipfw,pf
sysctl net.inet.ip.pfil.inbound=ipfw,pf
sysctl net.inet6.ip6.pfil.outbound=ipfw,pf
sysctl net.inet6.ip6.pfil.inbound=ipfw,pf
ipfw delete 100
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0
pkill ^dvtws$
dvtws --daemon --port 989 --dpi-desync=multisplit --dpi-desync-split-pos=2
# required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state
pfctl -d ; pfctl -e
```
#### Проблемы tpws
Что касается `tpws`, то видимо имеется некоторый конфликт двух фаерволов, и
правила fwd в ipfw не работают. Работает перенаправление средствами PF как
описано в разделе по **FreeBSD**. В PF можно изменять правила только целыми
блоками - якорями (anchors). Нельзя просто так добавить или удалить что-то. Но
чтобы какой-то anchor был обработан, на него должна быть ссылка из основного
набора правил. Его трогать нельзя, иначе порушится весь фаервол. Поэтому
придется править код скриптов pfsense.
1. Поправьте `/etc/inc/filter.inc` следующим образом:
```
<...>
/* MOD */
$natrules .= "# ZAPRET redirection\n";
$natrules .= "rdr-anchor \"zapret\"\n";
$natrules .= "# TFTP proxy\n";
$natrules .= "rdr-anchor \"tftp-proxy/*\"\n";
<...>
```
2. Напишите файл с содержимым anchor-а (например, `/etc/zapret.anchor`):
```
rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988
rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::20c:29ff:5ae3:4821 port 988
```
`fe80::20c:29ff:5ae3:4821` замените на ваш link local адрес LAN интерфейса,
либо уберите строчку, если ipv6 не нужен.
3. Добавьте в автозапуск `/usr/local/etc/rc.d/zapret.sh`:
```sh
$ pfctl -a zapret -f /etc/zapret.anchor
$ pkill ^tpws$
$ tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-pos=2
```
4. После перезагрузки проверьте, что правила создались:
```sh
$ pfctl -s nat
no nat proto carp all
nat-anchor "natearly/*" all
nat-anchor "natrules/*" all
<...>
no rdr proto carp all
rdr-anchor "zapret" all
rdr-anchor "tftp-proxy/*" all
rdr-anchor "miniupnpd" all
$ pfctl -s nat -a zapret
rdr pass on em1 inet proto tcp from any to any port = http -> 127.0.0.1 port 988
rdr pass on em1 inet proto tcp from any to any port = https -> 127.0.0.1 port 988
rdr pass on em1 inet6 proto tcp from any to any port = http -> fe80::20c:29ff:5ae3:4821 port 988
rdr pass on em1 inet6 proto tcp from any to any port = https -> fe80::20c:29ff:5ae3:4821 port 988
```
> [!NOTE]
> Так же есть более элегантный способ запуска `tpws` через @reboot в cron и
> правило перенаправления в UI. Это позволит не редактировать код pfsense.
## OpenBSD
### tpws bind на ipv4
В `tpws` bind по умолчанию только на ipv6. Для bind на ipv4 нужно указать `--bind-addr=0.0.0.0`.
Используйте `--bind-addr=0.0.0.0 --bind-addr=::` для достижения того же результата, как в других ОС по умолчанию.
Но лучше все же так не делать, а сажать на определенные внутренние адреса или интерфейсы.
### tpws для проходящего трафика
`/etc/pf.conf`:
```
pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988
pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988
```
```sh
$ pfctl -f /etc/pf.conf
$ tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
```
> [!NOTE]
> В PF не выходит делать rdr-to с той же системы, где работает proxy.
> Вариант с route-to не сохраняет мета информацию. Адрес назначения теряется.
> Поэтому этот вариант годится для squid, берущего адрес из протокола прикладного уровня, но не годится для tpws, полагающегося на метаданные ОС.
> Поддержка rdr-to реализована через `/dev/pf`, поэтому прозрачный режим **требует root**.
### Запуск dvtws
#### Весь трафик
`/etc/pf.conf`:
```
pass in quick on em0 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 proto tcp from port {80,443} no state
pass out quick on em0 proto tcp to port {80,443} divert-packet port 989 no state
```
```sh
$ pfctl -f /etc/pf.conf
$ ./dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
#### Трафик только на таблицу zapret, за исключением таблицы nozapret
`/etc/pf.conf`:
```
set limit table-entries 2000000
table <zapret> file "/opt/zapret/ipset/zapret-ip.txt"
table <zapret-user> file "/opt/zapret/ipset/zapret-ip-user.txt"
table <nozapret> file "/opt/zapret/ipset/zapret-ip-exclude.txt"
pass out quick on em0 inet proto tcp to <nozapret> port {80,443}
pass in quick on em0 inet proto tcp from <zapret> port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 inet proto tcp from <zapret> port {80,443} no state
pass out quick on em0 inet proto tcp to <zapret> port {80,443} divert-packet port 989 no state
pass in quick on em0 inet proto tcp from <zapret-user> port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 inet proto tcp from <zapret-user> port {80,443} no state
pass out quick on em0 inet proto tcp to <zapret-user> port {80,443} divert-packet port 989 no state
table <zapret6> file "/opt/zapret/ipset/zapret-ip6.txt"
table <zapret6-user> file "/opt/zapret/ipset/zapret-ip-user6.txt"
table <nozapret6> file "/opt/zapret/ipset/zapret-ip-exclude6.txt"
pass out quick on em0 inet6 proto tcp to <nozapret6> port {80,443}
pass in quick on em0 inet6 proto tcp from <zapret6> port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 inet6 proto tcp from <zapret6> port {80,443} no state
pass out quick on em0 inet6 proto tcp to <zapret6> port {80,443} divert-packet port 989 no state
pass in quick on em0 inet6 proto tcp from <zapret6-user> port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 inet6 proto tcp from <zapret6-user> port {80,443} no state
pass out quick on em0 inet6 proto tcp to <zapret6-user> port {80,443} divert-packet port 989 no state
```
```sh
$ pfctl -f /etc/pf.conf
$ ./dvtws --port=989 --dpi-desync=multisplit --dpi-desync-split-pos=2
```
### Проблемы с badsum
**OpenBSD** принудительно пересчитывает tcp checksum после divert, поэтому
скорее всего `dpi-desync-fooling=badsum` у вас не заработает. При использовании
этого параметра `dvtws` предупредит о возможной проблеме.
### Особенность отправки fake пакетов
В **OpenBSD** `dvtws` все фейки отсылает через divert socket, поскольку эта
возможность через raw sockets заблокирована. Видимо PF автоматически
предотвращает повторный заворот diverted фреймов, поэтому проблемы зацикливания
нет.
divert-packet автоматически вносит обратное правило для перенаправления. Трюк с
no state и in правилом позволяет обойти эту проблему, чтобы напрасно не гнать
массивный трафик через `dvtws`.
### Перезагрузка PF таблиц
Скрипты из ipset не перезагружают таблицы в PF по умолчанию.
Чтобы они это делали, добавьте параметр в `/opt/zapret/config`:
```
LISTS_RELOAD="pfctl -f /etc/pf.conf"
```
Более новые версии `pfctl` понимают команду перезагрузить только таблицы. Но это не относится к **OpenBSD**. В новых **FreeBSD** есть.
```sh
$ pfctl -Tl -f /etc/pf.conf
```
> [!IMPORTANT]
> Не забудьте выключить сжатие gzip: `GZIP_LISTS=0`
> [!IMPORTANT]
> Если в вашей конфигурации какого-то файла листа нет, то его необходимо
> исключить из правил PF. Если вдруг листа нет, и он задан в pf.conf, будет
> ошибка перезагрузки фаервола.
> [!NOTE]
> После настройки обновление листов можно поместить в cron:
> ```sh
> $ crontab -e
> ```
>
> ```
> <...>
> 0 12 */2 * * /opt/zapret/ipset/get_config.sh
> ```
## MacOS
### Введение
Иначально ядро этой ОС "darwin" основывалось на **BSD**, потому в ней много
похожего на другие версии **BSD**. Однако, как и в других массовых коммерческих
проектах, приоритеты смещаются в сторону от оригинала. Яблочники что хотят, то
и творят.
### dvtws бесполезен
Раньше был ipfw, потом его убрали, заменили на PF. Есть сомнения, что divert
сокеты в ядре остались. Попытка создать divert socket не выдает ошибок, но
полученный сокет ведет себя точно так же, как raw, со всеми его унаследованными
косяками + еще яблочно специфическими. В PF divert-packet не работает. Простой
grep бинарика `pfctl` показывает, что там нет слова "divert", а в других
версиях **BSD** оно есть. `dvtws` собирается, но совершенно бесполезен.
### tpws
`tpws` удалось адаптировать, он работоспособен. Получение адреса назначения для
прозрачного прокси в PF (`DIOCNATLOOK`) убрали из заголовков в новых SDK,
сделав фактически недокументированным.
В `tpws` перенесены некоторые определения из более старых версий яблочных SDK.
С ними удалось завести прозрачный режим. Однако, что будет в следующих версиях
угадать сложно. Гарантий нет. Еще одной особенностью PF в **MacOS** является
проверка на рута в момент обращения к `/dev/pf`, чего нет в остальных **BSD**.
`tpws` по умолчанию сбрасывает рутовые привилегии. Необходимо явно указать
параметр `--user=root`. В остальном PF себя ведет похоже на **FreeBSD**.
Синтаксис `pf.conf` тот же.
> [!IMPORTANT]
> На **MacOS** работает редирект как с проходящего трафика, так и с локальной
> системы через route-to. Поскольку `tpws` вынужден работать под root, для
> исключения рекурсии приходится пускать исходящий от root трафик напрямую.
> Отсюда имеем недостаток - **обход DPI для рута работать НЕ будет**.
#### Работа в прозрачном режиме только для исходящих запросов
`/etc/pf.conf`:
```
rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988
rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988
pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root }
pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root }
```
```sh
$ pfctl -ef /etc/pf.conf
$ /opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force
```
#### Работа в прозрачном режиме
> [!NOTE]
> Предполагается, что имя LAN интерфейса - `en1`
```sh
$ ifconfig en1 | grep fe80
inet6 fe80::bbbb:bbbb:bbbb:bbbb%en1 prefixlen 64 scopeid 0x8
```
`/etc/pf.conf`:
```
rdr pass on en1 inet proto tcp from any to any port {80,443} -> 127.0.0.1 port 988
rdr pass on en1 inet6 proto tcp from any to any port {80,443} -> fe80::bbbb:bbbb:bbbb:bbbb port 988
rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988
rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988
pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root }
pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root }
```
```sh
$ pfctl -ef /etc/pf.conf
$ /opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force --bind-iface6=en1 --bind-linklocal=force
```
### Проблема link-local адреса
Если вы пользуетесь **MaсOS** в качестве ipv6 роутера, то нужно будет
решить вопрос с регулярно изменяемым link-local адресом. С некоторых версий
**MacOS** использует по умолчанию постоянные "secured" ipv6 адреса вместо
генерируемых на базе MAC адреса.
Все замечательно, но есть одна проблема. Постоянными остаются только global
scope адреса. Link locals периодически меняются. Смена завязана на системное
время. Перезагрузки адрес не меняют, Но если перевести время на день вперед и
перезагрузиться - link local станет другим (по крайней мере в vmware это так).
Информации по вопросу крайне мало, но тянет на баг. Не должен меняться link
local. Скрывать link local не имеет смысла, а динамический link local нельзя
использовать в качестве адреса шлюза. Проще всего отказаться от "secured"
адресов. Для этого поместите строчку `net.inet6.send.opmode=0` в
`/etc/sysctl.conf` и перезагрузите систему.
Все равно для исходящих соединений будут использоваться temporary адреса, как и
в других системах. Или вам идея не по вкусу, можно прописать дополнительный
статический ipv6 из диапазона маски `fc00::/7` - выберите любой с длиной
префикса `128`. Это можно сделать в системных настройках, создав дополнительный
адаптер на базе того же сетевого интерфейса, отключить в нем ipv4 и вписать
статический ipv6. Он добавится к автоматически настраеваемым.
### Сборка
```sh
$ make -C /opt/zapret mac
```
### Простая установка
В **MacOS** поддерживается `install_easy.sh`
В комплекте идут бинарики, собраные под 64-bit с опцией
`-mmacosx-version-min=10.8`. Они должны работать на всех поддерживаемых версиях
**MacOS**. Если вдруг не работают - можно собрать свои. Developer tools
ставятся автоматом при запуске `make`.
> [!WARNING]
> Internet sharing средствами системы **не поддерживается**!
>
> Поддерживается только роутер, настроенный своими силами через PF. Если вы
> вдруг включили шаринг, а потом выключили, то доступ к сайтам может пропасть
> совсем.
>
> Лечение:
> ```sh
> $ pfctl -f /etc/pf.conf
> ```
>
> Если вам нужен шаринг интернета, лучше отказаться от прозрачного режима и
> использовать socks прокси.
Для автостарта используется launchd (`/Library/LaunchDaemons/zapret.plist`)
Управляющий скрипт : `/opt/zapret/init.d/macos/zapret`
Следующие команды работают с `tpws` и фаерволом одновременно (если
`INIT_APPLY_FW=1` в config)
```sh
$ /opt/zapret/init.d/macos/zapret start
$ /opt/zapret/init.d/macos/zapret stop
$ /opt/zapret/init.d/macos/zapret restart
```
Работа только с tpws:
```sh
$ /opt/zapret/init.d/macos/zapret start-daemons
$ /opt/zapret/init.d/macos/zapret stop-daemons
$ /opt/zapret/init.d/macos/zapret restart-daemons
```
Работа только с PF:
```sh
$ /opt/zapret/init.d/macos/zapret start-fw
$ /opt/zapret/init.d/macos/zapret stop-fw
$ /opt/zapret/init.d/macos/zapret restart-fw
```
Перезагрузка всех IP таблиц из файлов:
```sh
$ /opt/zapret/init.d/macos/zapret reload-fw-tables
```
> [!NOTE]
> Инсталятор настраивает `LISTS_RELOAD` в config, так что скрипты
> [`ipset/*.sh`](../ipset/) автоматически перезагружают IP таблицы в PF.
> [!NOTE]
> Автоматически создается cron job на
> [`ipset/get_config.sh`](../ipset/get_config.sh), по аналогии с openwrt.
При start-fw скрипт автоматически модицифирует `/etc/pf.conf`, вставляя туда
anchors "zapret". Модификация расчитана на `pf.conf`, в котором сохранены
дефолтные anchors от apple. Если у вас измененный `pf.conf` и модификация не
удалась, об этом будет предупреждение. Не игнорируйте его. В этом случае вам
нужно вставить в свой `pf.conf` (в соответствии с порядком типов правил):
```
rdr-anchor "zapret"
anchor "zapret"
```
> [!NOTE]
> При деинсталяции через `uninstall_easy.sh` модификации `pf.conf` убираются.
> [!NOTE]
> start-fw создает 3 файла anchors в `/etc/pf.anchors`: `zapret`, `zapret-v4`,
> `zapret-v6`. Последние 2 подключаются из anchor "zapret".
> [!NOTE]
> Таблицы `nozapret` и `nozapret6` принадлежат anchor "zapret".
>
> Таблицы `zapret` и `zapret-user` в anchor "zapret-v4".
>
> Таблицы `zapret6` и `zapret6-user` в anchor "zapret-v6".
>
> Если какая-то версия протокола отключена - соответствующий anchor пустой и не
> упоминается в anchor "zapret". Таблицы и правила создаются только на те
> листы, которые фактически есть в директории ipset.
### Вариант Custom
Так же как и в других системах, поддерживаемых в простом инсталяторе, можно
создавать свои custom скрипты.
Расположение: `/opt/zapret/init.d/macos/custom`
`zapret_custom_daemons()` получает в `$1`: `0` или `1`. `0` = stop, `1` = start
custom firewall отличается от linux варианта. Вместо заполнения `iptables` вам
нужно сгенерировать правила для `zapret-v4` и `zapret-v6` anchors и выдать их в
stdout. Это делается в функциях `zapret_custom_firewall_v4()` и
`zapret_custom_firewall_v6()`. Определения таблиц заполняются основным скриптом
\- вам это делать не нужно. Можно ссылаться на таблицы `zapret` и `zapret-user`
в v4, `zapret6` и `zapret6-user`.
Cм. пример [в файле](../init.d/macos/custom.d.examples/50-extra-tpws).

476
docs/bsd.txt Normal file
View File

@ -0,0 +1,476 @@
Поддерживаемые версии
---------------------
FreeBSD 11.x+ , OpenBSD 6.x+, частично MacOS Sierra+
На более старых может собираться, может не собираться, может работать или не работать.
На FreeBSD 10 собирается и работает dvtws. С tpws есть проблемы из-за слишком старой версии компилятора clang.
Вероятно, будет работать, если обновить компилятор.
Возможна прикрутка к последним версиям pfsense без веб интерфейса в ручном режиме через консоль.
Особенности BSD систем
----------------------
В BSD нет nfqueue. Похожий механизм - divert sockets.
Из каталога "nfq" под BSD собирается dvtws вместо nfqws.
Он разделяет с nfqws большую часть кода и почти совпадает по параметрам командной строки.
FreeBSD содержит 3 фаервола : IPFilter, ipfw и Packet Filter (PF). OpenBSD содержит только PF.
Под FreeBSD tpws и dvtws собираются через "make", под OpenBSD - "make bsd", под MacOS - "make mac".
FreeBSD make распознает BSDmakefile , OpenBSD и MacOS - нет. Поэтому там используется отдельный target в Makefile.
Сборка всех исходников : make -C /opt/zapret
divert сокет - внутренний тип сокета ядра BSD. Он не привязывается ни к какому сетевому адресу, не участвует
в обмене данными через сеть и идентифицируется по номеру порта 1..65535. Аналогия с номером очереди NFQUEUE.
На divert сокеты заворачивается трафик посредством правил ipfw или PF.
Если в фаерволе есть правило divert, но на divert порту никто не слушает, то пакеты дропаются.
Это поведение аналогично правилам NFQUEUE без параметра --queue-bypass.
На FreeBSD divert сокеты могут быть только ipv4, хотя на них принимаются и ipv4, и ipv6 фреймы.
На OpenBSD divert сокеты создаются отдельно для ipv4 и ipv6 и работают только с одной версией ip каждый.
На MacOS похоже, что divert сокеты из ядра вырезаны. См подробнее раздел про MacOS.
Отсылка в divert сокет работает аналогично отсылке через raw socket на linux. Передается полностью IP фрейм, начиная
с ip загловка . Эти особенности учитываются в dvtws.
Скрипты ipset/*.sh при наличии ipfw работают с ipfw lookup tables.
Это прямой аналог ipset. lookup tables не разделены на v4 и v6. Они могут содержать v4 и v6 адреса и подсети одновременно.
Если ipfw отсутствует, то действие зависит от переменной LISTS_RELOAD в config.
Если она задана, то выполняется команда из LISTS_RELOAD. В противном случае не делается ничего.
Если LISTS_RELOAD=-, то заполнение таблиц отключается даже при наличии ipfw.
PF может загружать ip таблицы из файла. Чтобы использовать эту возможность следует отключить сжатие gzip для листов
через параметр файла config "GZIP_LISTS=0".
BSD не содержит системного вызова splice. tpws работает через переброску данных в user mode в оба конца.
Это медленнее, но не критически.
Управление асинхронными сокетами в tpws основано на linux-specific механизме epoll.
В BSD для его эмуляции используется epoll-shim - прослойка для эмуляции epoll на базе kqueue.
mdig и ip2net полностью работоспособны в BSD. В них нет ничего системо-зависимого.
FreeBSD
-------
divert сокеты требуют специального модуля ядра ipdivert.
Поместите следующие строки в /boot/loader.conf (создать, если отсутствует) :
-----------
ipdivert_load="YES"
net.inet.ip.fw.default_to_accept=1
-----------
В /etc/rc.conf :
-----------
firewall_enable="YES"
firewall_script="/etc/rc.firewall.my"
-----------
/etc/rc.firewall.my :
-----------
ipfw -q -f flush
-----------
В /etc/rc.firewall.my можно дописывать правила ipfw, чтобы они восстанавливались после перезагрузки.
Оттуда же можно запускать и демоны zapret, добавив в параметры "--daemon". Например так :
-----------
pkill ^dvtws$
/opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=split2
-----------
Для перезапуска фаервола и демонов достаточно будет сделать : /etc/rc.d/ipfw restart
Краткая инструкция по запуску tpws в прозрачном режиме.
Предполагается, что интерфейс LAN называется em1, WAN - em0.
Для всего трафика :
ipfw delete 100
ipfw add 100 fwd 127.0.0.1,988 tcp from me to any 80,443 proto ip4 xmit em0 not uid daemon
ipfw add 100 fwd ::1,988 tcp from me to any 80,443 proto ip6 xmit em0 not uid daemon
ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1
ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1
/opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
Для трафика только на таблицу zapret, за исключением таблицы nozapret :
ipfw delete 100
ipfw add 100 allow tcp from me to table\(nozapret\) 80,443
ipfw add 100 fwd 127.0.0.1,988 tcp from me to table\(zapret\) 80,443 proto ip4 xmit em0 not uid daemon
ipfw add 100 fwd ::1,988 tcp from me to table\(zapret\) 80,443 proto ip6 xmit em0 not uid daemon
ipfw add 100 allow tcp from any to table\(nozapret\) 80,443 recv em1
ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1
ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1
/opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
Таблицы zapret, nozapret, ipban создаются скриптами из ipset по аналогии с Linux.
Обновление скриптов можно забить в cron под root :
crontab -e
Создать строчку "0 12 */2 * * /opt/zapret/ipset/get_config.sh"
При использовании ipfw tpws не требует повышенных привилегий для реализации прозрачного режима.
Однако, без рута невозможен бинд на порты <1024 и смена UID/GID. Без смены UID будет рекурсия,
поэтому правила ipfw нужно создавать с учетом UID, под которым работает tpws.
Переадресация на порты >=1024 может создать угрозу перехвата трафика непривилегированным
процессом, если вдруг tpws не запущен.
Краткая инструкция по запуску dvtws.
Для всего трафика :
ipfw delete 100
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0
# required for autottl mode only
ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diverted recv em0
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2
Для трафика только на таблицу zapret, за исключением таблицы nozapret :
ipfw delete 100
ipfw add 100 allow tcp from me to table\(nozapret\) 80,443
ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted not sockarg xmit em0
# required for autottl mode only
ipfw add 100 divert 989 tcp from table\(zapret\) 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2
PF в FreeBSD:
Настройка аналогична OpenBSD, но есть важные нюансы.
1) В FreeBSD поддержка PF в tpws отключена по умолчанию. Чтобы ее включить, нужно использовать параметр --enable-pf.
2) Нельзя сделать ipv6 rdr на ::1. Нужно делать на link-local адрес входящего интерфейса.
Смотрите через ifconfig адрес fe80:... и добавляете в правило
3) Синтаксис pf.conf немного отличается. Более новая версия PF.
4) Лимит на количество элементов таблиц задается так : sysctl net.pf.request_maxcount=2000000
5) divert-to сломан. Он работает, но не работает механизм предотвращения зацикливаний.
Кто-то уже написал патч, но в 14-RELEASE проблема все еще есть.
Следовательно, на данный момент работа dvtws через pf невозможна.
/etc/pf.conf
-----------
rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::31c:29ff:dee2:1c4d port 988
rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988
-----------
/opt/zapret/tpws/tpws --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force
В PF непонятно как делать rdr-to с той же системы, где работает proxy. Вариант с route-to у меня не заработал.
pfsense
-------
pfsense основано на FreeBSD.
pfsense использует фаервол pf, а он имеет проблемы с divert.
К счастью, модули ipfw и ipdivert присутствуют в поставке последних версий pfsense.
Их можно подгрузить через kldload.
В некоторых более старых версиях pfsense требуется изменить порядок фаерволов через sysctl, сделав ipfw первым.
В более новых эти параметры sysctl отсутствуют, но система работает как надо и без них.
В некоторых случаях фаервол pf может ограничивать возможности dvtws, в частности в области фрагментации ip.
Присутствуют по умолчанию правила scrub для реассемблинга фрагментов.
Бинарики из binaries/freebsd-x64 собраны под FreeBSD 11. Они должны работать и на последующих версиях FreeBSD,
включая pfsense. Можно пользоваться install_bin.sh.
Пример скрипта автозапуска лежит в init.d/pfsense. Его следует поместить в /usr/local/etc/rc.d и отредактировать
на предмет правил ipfw и запуска демонов. Есть встроенный редактор edit как более приемлемая альтернатива vi.
Поскольку git отсутствует, копировать файлы удобнее всего через ssh. curl присутствует по умолчанию.
Можно скопировать zip с файлами zapret и распаковать в /opt, как это делается на других системах.
Тогда dvtws нужно запускать как /opt/zapret/nfq/dvtws. Либо скопировать только dvtws в /usr/local/sbin.
Как вам больше нравится.
ipset скрипты работают, крон есть. Можно сделать автообновление листов.
Если вас напрягает бедность имеющегося репозитория, можно включить репозиторий от FreeBSD, который по умолчанию выключен.
Поменяйте no на yes в /usr/local/etc/pkg/repos/FreeBSD.conf
Можно установить весь привычный soft, включая git, чтобы напрямую скачивать zapret с github.
/usr/local/etc/rc.d/zapret.sh (chmod 755)
-----------
#!/bin/sh
kldload ipfw
kldload ipdivert
# for older pfsense versions. newer do not have these sysctls
sysctl net.inet.ip.pfil.outbound=ipfw,pf
sysctl net.inet.ip.pfil.inbound=ipfw,pf
sysctl net.inet6.ip6.pfil.outbound=ipfw,pf
sysctl net.inet6.ip6.pfil.inbound=ipfw,pf
ipfw delete 100
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0
pkill ^dvtws$
dvtws --daemon --port 989 --dpi-desync=split2
# required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state
pfctl -d ; pfctl -e
-----------
Что касается tpws, то видимо имеется некоторый конфликт двух фаерволов, и правила fwd в ipfw не работают.
Работает перенаправление средствами pf как описано в разделе по FreeBSD.
В pf можно изменять правила только целыми блоками - якорями (anchors). Нельзя просто так добавить или удалить что-то.
Но чтобы какой-то anchor был обработан, на него должна быть ссылка из основного набора правил.
Его трогать нельзя, иначе порушится весь фаервол.
Поэтому придется править код скриптов pfsense. Поправьте /etc/inc/filter.inc следующим образом :
-----------
.................
/* MOD */
$natrules .= "# ZAPRET redirection\n";
$natrules .= "rdr-anchor \"zapret\"\n";
$natrules .= "# TFTP proxy\n";
$natrules .= "rdr-anchor \"tftp-proxy/*\"\n";
.................
-----------
Напишите файл с содержимым anchor-а (например, /etc/zapret.anchor):
-----------
rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988
rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::20c:29ff:5ae3:4821 port 988
-----------
fe80::20c:29ff:5ae3:4821 замените на ваш link local адрес LAN интерфейса, либо уберите строчку, если ipv6 не нужен.
Добавьте в автозапуск /usr/local/etc/rc.d/zapret.sh :
-----------
pfctl -a zapret -f /etc/zapret.anchor
pkill ^tpws$
tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-http-req=method --split-pos=2
-----------
После перезагрузки проверьте, что правила создались :
-----------
[root@pfSense /]# pfctl -s nat
no nat proto carp all
nat-anchor "natearly/*" all
nat-anchor "natrules/*" all
...................
no rdr proto carp all
rdr-anchor "zapret" all
rdr-anchor "tftp-proxy/*" all
rdr-anchor "miniupnpd" all
[root@pfSense /]# pfctl -s nat -a zapret
rdr pass on em1 inet proto tcp from any to any port = http -> 127.0.0.1 port 988
rdr pass on em1 inet proto tcp from any to any port = https -> 127.0.0.1 port 988
rdr pass on em1 inet6 proto tcp from any to any port = http -> fe80::20c:29ff:5ae3:4821 port 988
rdr pass on em1 inet6 proto tcp from any to any port = https -> fe80::20c:29ff:5ae3:4821 port 988
-----------
Так же есть более элегантный способ запуска tpws через @reboot в cron и правило перенаправления в UI.
Это позволит не редактировать код pfsense.
OpenBSD
-------
В tpws бинд по умолчанию только на ipv6. для бинда на ipv4 указать "--bind-addr=0.0.0.0"
Используйте --bind-addr=0.0.0.0 --bind-addr=:: для достижения того же результата, как в других ОС по умолчанию.
(лучше все же так не делать, а сажать на определенные внутренние адреса или интерфейсы)
tpws для проходящего трафика :
/etc/pf.conf
------------
pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988
pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988
------------
pfctl -f /etc/pf.conf
tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
В PF непонятно как делать rdr-to с той же системы, где работает proxy. Вариант с route-to у меня не заработал.
Поддержка rdr-to реализована через /dev/pf, поэтому прозрачный режим требует root.
dvtws для всего трафика :
/etc/pf.conf
------------
pass in quick on em0 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 proto tcp from port {80,443} no state
pass out quick on em0 proto tcp to port {80,443} divert-packet port 989 no state
------------
pfctl -f /etc/pf.conf
./dvtws --port=989 --dpi-desync=split2
dvtws для трафика только на таблицу zapret, за исключением таблицы nozapret :
/etc/pf.conf
------------
set limit table-entries 2000000
table <zapret> file "/opt/zapret/ipset/zapret-ip.txt"
table <zapret-user> file "/opt/zapret/ipset/zapret-ip-user.txt"
table <nozapret> file "/opt/zapret/ipset/zapret-ip-exclude.txt"
pass out quick on em0 inet proto tcp to <nozapret> port {80,443}
pass in quick on em0 inet proto tcp from <zapret> port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 inet proto tcp from <zapret> port {80,443} no state
pass out quick on em0 inet proto tcp to <zapret> port {80,443} divert-packet port 989 no state
pass in quick on em0 inet proto tcp from <zapret-user> port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 inet proto tcp from <zapret-user> port {80,443} no state
pass out quick on em0 inet proto tcp to <zapret-user> port {80,443} divert-packet port 989 no state
table <zapret6> file "/opt/zapret/ipset/zapret-ip6.txt"
table <zapret6-user> file "/opt/zapret/ipset/zapret-ip-user6.txt"
table <nozapret6> file "/opt/zapret/ipset/zapret-ip-exclude6.txt"
pass out quick on em0 inet6 proto tcp to <nozapret6> port {80,443}
pass in quick on em0 inet6 proto tcp from <zapret6> port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 inet6 proto tcp from <zapret6> port {80,443} no state
pass out quick on em0 inet6 proto tcp to <zapret6> port {80,443} divert-packet port 989 no state
pass in quick on em0 inet6 proto tcp from <zapret6-user> port {80,443} flags SA/SA divert-packet port 989 no state
pass in quick on em0 inet6 proto tcp from <zapret6-user> port {80,443} no state
pass out quick on em0 inet6 proto tcp to <zapret6-user> port {80,443} divert-packet port 989 no state
------------
pfctl -f /etc/pf.conf
./dvtws --port=989 --dpi-desync=split2
divert-packet автоматически вносит обратное правило для перенаправления.
Трюк с no state и in правилом позволяет обойти эту проблему, чтобы напрасно не гнать массивный трафик через dvtws.
В OpenBSD dvtws все фейки отсылает через divert socket, поскольку эта возможность через raw sockets заблокирована.
Видимо pf автоматически предотвращает повторный заворот diverted фреймов, поэтому проблемы зацикливания нет.
OpenBSD принудительно пересчитывает tcp checksum после divert, поэтому скорее всего
dpi-desync-fooling=badsum у вас не заработает. При использовании этого параметра
dvtws предупредит о возможной проблеме.
Скрипты из ipset не перезагружают таблицы в PF по умолчанию.
Чтобы они это делали, добавьте параметр в /opt/zapret/config :
LISTS_RELOAD="pfctl -f /etc/pf.conf"
Более новые версии pfctl понимают команду перезагрузить только таблицы : pfctl -Tl -f /etc/pf.conf
Но это не относится к OpenBSD 6.8. В новых FreeBSD есть.
Не забудьте выключить сжатие gzip :
GZIP_LISTS=0
Если в вашей конфигурации какого-то файла листа нет, то его необходимо исключить из правил PF.
Если вдруг листа нет, и он задан в pf.conf, будет ошибка перезагрузки фаервола.
После настройки обновление листов можно поместить в cron :
crontab -e
дописать строчку : 0 12 */2 * * /opt/zapret/ipset/get_config.sh
MacOS
-----
Иначально ядро этой ОС "darwin" основывалось на BSD, потому в ней много похожего на другие версии BSD.
Однако, как и в других массовых коммерческих проектах, приоритеты смещаются в сторону от оригинала.
Яблочники что хотят, то и творят.
Раньше был ipfw, потом его убрали, заменили на PF.
Есть сомнения, что divert сокеты в ядре остались. Попытка создать divert socket не выдает ошибок,
но полученный сокет ведет себя точно так же, как raw, со всеми его унаследованными косяками + еще яблочно специфическими.
В PF divert-packet не работает. Простой grep бинарика pfctl показывает, что там нет слова "divert",
а в других версиях BSD оно есть. dvtws собирается, но совершенно бесполезен.
tpws удалось адаптировать, он работоспособен. Получение адреса назначения для прозрачного прокси в PF (DIOCNATLOOK)
убрали из заголовков в новых SDK, сделав фактически недокументированным.
В tpws перенесены некоторые определения из более старых версий яблочных SDK. С ними удалось завести прозрачный режим.
Однако, что будет в следующих версиях угадать сложно. Гарантий нет.
Еще одной особенностью PF в MacOS является проверка на рута в момент обращения к /dev/pf, чего нет в остальных BSD.
tpws по умолчанию сбрасывает рутовые привилегии. Необходимо явно указать параметр --user=root.
В остальном PF себя ведет похоже на FreeBSD. Синтаксис pf.conf тот же.
На MacOS работает редирект как с проходящего трафика, так и с локальной системы через route-to.
Поскольку tpws вынужден работать под root, для исключения рекурсии приходится пускать исходящий от root трафик напрямую.
Отсюда имеем недостаток : обход DPI для рута работать не будет.
Если вы пользуетесь MaсOS в качестве ipv6 роутера, то нужно будет решить вопрос с регулярно изменяемым link-local адресом.
С некоторых версий MacOS использует по умолчанию постоянные "secured" ipv6 адреса вместо генерируемых на базе MAC адреса.
Все замечательно, но есть одна проблема. Постоянными остаются только global scope адреса.
Link locals периодически меняются. Смена завязана на системное время. Перезагрузки адрес не меняют,
Но если перевести время на день вперед и перезагрузиться - link local станет другим. (по крайней мере в vmware это так)
Информации по вопросу крайне мало, но тянет на баг. Не должен меняться link local. Скрывать link local не имеет смысла,
а динамический link local нельзя использовать в качестве адреса шлюза.
Проще всего отказаться от "secured" адресов.
Поместите строчку "net.inet6.send.opmode=0" в /etc/sysctl.conf. Затем перезагрузите систему.
Все равно для исходящих соединений будут использоваться temporary адреса, как и в других системах.
Или вам идея не по вкусу, можно прописать дополнительный статический ipv6 из диапазона fc00::/7 -
выберите любой с длиной префикса 128. Это можно сделать в системных настройках, создав дополнительный адаптер на базе
того же сетевого интерфейса, отключить в нем ipv4 и вписать статический ipv6. Он добавится к автоматически настраеваемым.
Настройка tpws на macos в прозрачном режиме только для исходящих запросов :
/etc/pf.conf
------------
rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988
rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988
pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root }
pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root }
------------
pfctl -ef /etc/pf.conf
/opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force
Настройка tpws на macos роутере в прозрачном режиме, где en1 - LAN.
ifconfig en1 | grep fe80
inet6 fe80::bbbb:bbbb:bbbb:bbbb%en1 prefixlen 64 scopeid 0x8
/etc/pf.conf
------------
rdr pass on en1 inet proto tcp from any to any port {80,443} -> 127.0.0.1 port 988
rdr pass on en1 inet6 proto tcp from any to any port {80,443} -> fe80::bbbb:bbbb:bbbb:bbbb port 988
rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988
rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988
pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root }
pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root }
------------
pfctl -ef /etc/pf.conf
/opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force --bind-iface6=en1 --bind-linklocal=force
Сборка : make -C /opt/zapret mac
Скрипты получения листов ipset/*.sh работают.
Если будете пользоваться ipset/get_combined.sh, нужно установить gnu grep через brew.
Имеющийся очень старый и безумно медленный с оцией -f.
MacOS простая установка
-----------------------
В MacOS поддерживается install_easy.sh
В комплекте идут бинарики, собраные под 64-bit с опцией -mmacosx-version-min=10.8.
Они должны работать на всех поддерживаемых версиях macos.
Если вдруг не работают - можно собрать свои. Developer tools ставятся автоматом при запуске make.
!! Internet sharing средствами системы НЕ ПОДДЕРЖИВАЕТСЯ !!
Поддерживается только роутер, настроенный своими силами через PF.
Если вы вдруг включили шаринг, а потом выключили, то доступ к сайтам может пропасть совсем.
Лечение : pfctl -f /etc/pf.conf
Если вам нужен шаринг интернета, лучше отказаться от прозрачного режима и использовать socks.
Для автостарта используется launchd (/Library/LaunchDaemons/zapret.plist)
Управляющий скрипт : /opt/zapret/init.d/macos/zapret
Следующие команды работают с tpws и фаерволом одновременно (если INIT_APPLY_FW=1 в config)
/opt/zapret/init.d/macos/zapret start
/opt/zapret/init.d/macos/zapret stop
/opt/zapret/init.d/macos/zapret restart
Работа только с tpws :
/opt/zapret/init.d/macos/zapret start-daemons
/opt/zapret/init.d/macos/zapret stop-daemons
/opt/zapret/init.d/macos/zapret restart-daemons
Работа только с PF :
/opt/zapret/init.d/macos/zapret start-fw
/opt/zapret/init.d/macos/zapret stop-fw
/opt/zapret/init.d/macos/zapret restart-fw
Перезагрузка всех IP таблиц из файлов :
/opt/zapret/init.d/macos/zapret reload-fw-tables
Инсталятор настраивает LISTS_RELOAD в config, так что скрипты ipset/*.sh автоматически перезагружают IP таблицы в PF.
Автоматически создается cron job на ipset/get_config.sh, по аналогии с openwrt.
При start-fw скрипт автоматически модицифирует /etc/pf.conf, вставляя туда anchors "zapret".
Модификация расчитана на pf.conf, в котором сохранены дефолтные anchors от apple.
Если у вас измененный pf.conf и модификация не удалась, об этом будет предупреждение. Не игнорируйте его.
В этом случае вам нужно вставить в свой pf.conf (в соответствии с порядком типов правил) :
rdr-anchor "zapret"
anchor "zapret"
При деинсталяции через uninstall_easy.sh модификации pf.conf убираются.
start-fw создает 3 файла anchors в /etc/pf.anchors : zapret,zapret-v4,zapret-v6.
Последние 2 подключаются из anchor "zapret".
Таблицы nozapret,nozapret6 принадлежат anchor "zapret".
Таблицы zapret,zapret-user - в anchor "zapret-v4".
Таблицы zapret6,zapret6-user - в anchor "zapret-v6".
Если какая-то версия протокола отключена - соответствующий anchor пустой и не упоминается в anchor "zapret".
Таблицы и правила создаются только на те листы, которые фактически есть в директории ipset.
MacOS вариант custom
--------------------
Так же как и в других системах, поддерживаемых в простом инсталяторе, можно создавать свои custom скрипты.
Расположение : /opt/zapret/init.d/macos/custom
zapret_custom_daemons() получает в $1 "0" или "1". "0" - stop, "1" - start
custom firewall отличается от linux варианта.
Вместо заполнения iptables вам нужно сгенерировать правила для zapret-v4 и zapret-v6 anchors и выдать их в stdout.
Это делается в функциях zapret_custom_firewall_v4() и zapret_custom_firewall_v6().
Определения таблиц заполняются основным скриптом - вам это делать не нужно.
Можно ссылаться на таблицы zapret и zapret-user в v4, zapret6 и zapret6-user.
Cм. пример в файле custom-tpws

View File

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

View File

@ -323,165 +323,3 @@ v64:
blockcheck: warn if dpi bypass software is already running
blockcheck: TPWS_EXTRA, NFQWS_EXTRA
init.d: multiple custom scripts
v65:
init.d: dynamic number allocation for dnum,tpws_port,qnum
init.d: FW_EXTRA_PRE, FW_EXTRA_POST
init.d: zapret_custom_firewall_nft_flush
nfqws,tpws: l7proto and client ip:port info in autohostlist debug log
nfqws,tpws: user mode ipset filter support
nfqws,tpws: l7proto filter support
tpws: fixed MSS apply in transparent mode
nfqws: fixed autottl apply if desync profile changed
tpws,nfqws: fixed 100% cpu hang on gzipped list with comments
ipset: get_refilter_ipsum.sh , get_refilter_domain.sh
v66:
init.d: rewrite traffic interception and daemon launch parameters in config file. this break compatibility with old versions.
init.d: openwrt-minimal : tpws launch for low storage openwrt devices
v67:
mdig: --dns-make-query, --dns-parse-query for side-channel resolving (DoH)
blockcheck: use DoH resolvers if DNS spoof is detected
blockcheck: restring fooling to testing domain's IPs
nfqws,tpws: internal hostlist deduplication to save RAM
nfqws,tpws: hostlist/ipset auto reload on file change. no more HUP.
nfqws,tpws: --filter-tcp, --filter-udp take comma separated port range list
nfqws,tpws: @<config_file> - read config from a file
config: <HOSTLIST_NOAUTO> marker
binaries: remove zapret-winws. add win32.
blockcheck, install_easy.sh: preserve user environment variables during elevation
blockcheck: do not require root if SKIP_PKTWS=1
v68:
docs : move russian version to markdown
nfqws,tpws: use alternate $ sign for $<config_file>
repo: binaries removed from repo. git actions binaries build in releases.
uninstall_easy.sh: offer to remove dependencies in openwrt
install_easy.sh: allow to download lists in autohostlist filter mode
v69:
nfqws, tpws: multisplit/multidisorder support.
nfqws: name change split->fakedsplit, disorder->fakeddisorder. compat : old names are synonyms
nfqws: --dpi-desync-split-http-req, --dpi-desync-split-tls deprecated. compat : these parameters add split point to multisplit.
nfqws: --dpi-desync=split2|disorder2 deprecated. compat: they are now synonyms for multisplit/multidisorder
nfqws: cancel seqovl if MTU is exceeded (linux only). cancel seqovl for disorder if seqovl>=first_part_size.
nfqws: fixed splits in multiple TLS segments.
tpws: --split-http-req,--split-tls deprecated. compat : these parameters add split point to multisplit.
tpws: --tlsrec now takes pos markers. compat : old names are converted to pos markers
tpws: --tlsrec-pos deprecated. compat : sets absolute pos marker
nfqws,tpws: chown autohostlist, autohostlist debug log and debug log files after options parse
nfqws,tpws: set EXEDIR env var to use in @config (won't work for stadalone winws without /bin/sh)
dvtws: set random/increasing ip_id value in generated packets
mdig: fixed parsing of DNS reply in windows (stdin is opened as text, not binary)
tpws: support compile for android NDK api level >= 21 (Android 5.0)
tpws: --fix-seg segmentation fixer
repo: build for android NDK api level 21 (Android 5.0)
install_easy: support for APK package manager in openwrt
blockcheck: removed ignore CA question
blockcheck: removed IGNORE_CA, CURL_VERBOSE
blockcheck: added CURL_OPT
blockcheck: new strategies support
blockcheck: test sequence rework
blockcheck: view all working strategies in summary
v69.1:
init.d: keenetic udp fix custom
tpws: fixed incorrect hostlist checks
v69.2:
nfqws,tpws: --skip
nfqws: --methodeol
init.d: do not use pgrep in sysv for busybox compat
v69.3
nfqws,tpws: fixed ipsets and hostlists
all progs: version numbers for github, build date/time for self built
repo: light release for openwrt and embedded systems
repo: sha256sum
v69.4
nfqws: fakedsplit/fakeddisorder fakes for both split segments
nfqws: --dpi-desync-fakedsplit-pattern
v69.5
nfqws,tpws: --dry-run
install_easy: check tpws and nfqws options validity
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
v70.7
nfqws,tpws: debug tls version, alpn, ech

View File

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

View File

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

View File

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

View File

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

View File

@ -1 +1 @@
Copy "ip2net" folder here !
Copy "ip2net" folder here !

View File

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

View File

@ -1 +1 @@
Copy "mdig" folder here !
Copy "mdig" folder here !

View File

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

View File

@ -1 +1 @@
Copy "nfq" folder here !
Copy "nfq" folder here !

View File

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

View File

@ -1 +1 @@
Copy "tpws" folder here !
Copy "tpws" folder here !

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