91 Commits
v69.8 ... v70.3

Author SHA1 Message Date
bol-van
8ac4fc0af5 fix wrong var 2025-02-26 01:11:07 +03:00
bol-van
af89d03118 nfqws,tpws: fix hostlist-domains file open test 2025-02-25 13:07:38 +03:00
bol-van
d89daaaeac add localhost to zapret-hosts-user-exclude.txt 2025-02-24 13:10:54 +03:00
bol-van
f62b289cb5 nfqws,tpws: --version 2025-02-05 13:04:24 +03:00
bol-van
5f9fa28251 nfqws,tpws: r/o open instead of stat() for list file check 2025-02-04 23:28:18 +03:00
bol-van
bd67b41f32 nfqws,tpws: check accessibility of list files after droproot 2025-02-03 22:37:08 +03:00
bol-van
00619c8dab nfqws,tpws: show hostlist/ipset stat() error 2025-02-02 22:48:23 +03:00
bol-van
58e26c3e9d Merge pull request #1128 from Yoti/patch-1
quick_start: fix spelling
2025-01-30 22:31:37 +03:00
Yoti
eddbc3c3e0 quick_start: fix spelling 2025-01-30 22:20:15 +03:00
bol-van
2cc73de15c readme: move ip2net/mdig chapters 2025-01-30 12:09:34 +03:00
bol-van
9762f2d22b update docs 2025-01-30 12:03:57 +03:00
bol-van
8c9aa188c3 readme: update flow offload info 2025-01-29 14:57:55 +03:00
bol-van
2f151c0943 readme: update flow offload info 2025-01-29 14:55:11 +03:00
bol-van
9498456c4a readme: update flow offload info 2025-01-29 14:47:20 +03:00
bol-van
860607bce2 config.default: remove obsolete comment 2025-01-29 13:42:34 +03:00
bol-van
94f59511f0 update docs 2025-01-28 21:25:44 +03:00
bol-van
b07ce8d8ca nfqws: --dpi-desync-fake-tls-mod=dupsid 2025-01-28 21:22:33 +03:00
bol-van
6fc4e75d89 changes.txt update 2025-01-28 13:28:22 +03:00
bol-van
fb894a8e2c blockcheck: add tlsmod test 2025-01-28 13:26:33 +03:00
bol-van
86352430d4 nfqws: fix slen=0 case 2025-01-28 13:01:47 +03:00
bol-van
e5f20d05f6 nfqws: fix minor clang warning 2025-01-28 12:45:35 +03:00
bol-van
b610f08a9c readme: minor change help text 2025-01-28 12:43:04 +03:00
bol-van
8bbd2d97d5 nfqws: minor change help text 2025-01-28 12:42:31 +03:00
bol-van
972f665d88 update issues 2025-01-28 12:12:36 +03:00
bol-van
a9a497fa77 Update issue templates 2025-01-28 12:09:15 +03:00
bol-van
14a170c9a3 update issue_template 2025-01-28 12:01:04 +03:00
bol-van
d4080b6c6f Merge pull request #1117 from spvkgn/elf-cleaner
github: use termux-elf-cleaner to strip unwanted ELF sections
2025-01-28 11:56:51 +03:00
bol-van
20f1fb2cfd update docs 2025-01-28 11:54:14 +03:00
bol-van
35c3216287 update docs 2025-01-28 11:41:42 +03:00
spvkgn
628f629c49 github: run termux-elf-cleaner 2025-01-28 12:53:44 +05:00
bol-van
33d3059dc8 nfqws: --dpi-desync-fake-tls-mod 2025-01-27 21:08:12 +03:00
bol-van
f5cf7917fb nfqws,tpws: file_mod_signature zero struct if unsuccessful 2025-01-24 20:57:12 +03:00
bol-van
b39508de7f Merge pull request #1056 from chymaboy/patch-4
Update readme.md OpenWrt
2025-01-24 20:52:01 +03:00
bol-van
c69a92f901 update readme 2025-01-24 12:55:16 +03:00
bol-van
aba1fdeb04 tpws,nfqws: track file size in addition to mod time 2025-01-24 12:50:17 +03:00
bol-van
02c76a4fb6 ipset: return HUP reload 2025-01-24 11:39:13 +03:00
bol-van
2ff6ec03aa tpws,nfqws: return lists reload on HUP 2025-01-24 11:12:56 +03:00
bol-van
80a0b38295 install_easy: support dnf packager 2025-01-23 14:34:54 +03:00
bol-van
e0e935c2ae nfqws: apply split+seqovl only to the first reasm fragment 2025-01-19 11:58:31 +03:00
Evgeny
31cf106728 Update readme.md
fix parameter
2025-01-14 13:37:36 +03:00
Evgeny
502e34a96d Update readme.md OpenWrt
change all repeats in text to correct registr
2025-01-14 13:35:03 +03:00
bol-van
29ab747e5b nfqws: weaken wireguard initiation recognition 2025-01-13 18:25:15 +03:00
bol-van
b897ec5d9a Merge pull request #1042 from chymaboy/patch-3
Update readme.md раздел Как это работает
2025-01-11 21:56:09 +03:00
Evgeny
440878cb9f Update readme.md
ё
2025-01-11 21:26:46 +03:00
Evgeny
1935473bd1 Update readme.md раздел Как это работает
пробелы, регистры, дефисы
2025-01-11 19:06:00 +03:00
bol-van
de6cadf8e4 readme.md: minor 2025-01-10 18:39:56 +03:00
bol-van
d509497bb8 Merge pull request #1018 from chymaboy/patch-2
Update readme.md
2025-01-10 18:38:39 +03:00
Evgeny
d7949f70b1 Update readme.md
отмена дифов:
- прежде всего
- embedded устройства
- прикрутка
2025-01-10 18:14:36 +03:00
bol-van
0912b7d104 tpws: remove unneeded header 2025-01-09 19:01:29 +03:00
bol-van
29ff997a3f nfqws,tpws: remove null pointer checks before free() 2025-01-09 18:56:01 +03:00
bol-van
f21bd0c63c update git files 2025-01-05 15:09:47 +03:00
bol-van
41693b1008 blockcheck: minor old shell compat 2025-01-05 12:52:37 +03:00
bol-van
d000345043 blockcheck: SKIP_IPBLOCK, remove hardcoded ports 2025-01-04 18:11:49 +03:00
bol-van
f986da9ae2 blockcheck: wait for child processes on terminate 2025-01-04 09:11:30 +03:00
bol-van
c6e729b237 blockcheck: CURL_MAX_TIME_DOH 2025-01-03 15:11:11 +03:00
bol-van
12a800db97 blockcheck: use defaults if BATCH=1 2025-01-03 14:40:02 +03:00
bol-van
5e84656707 blockcheck: BATCH var 2025-01-03 14:06:21 +03:00
bol-van
e87965cd2f update doc 2025-01-03 13:58:25 +03:00
bol-van
4585cc4656 blockcheck: batch mode, parallel scan 2025-01-03 13:55:32 +03:00
Evgeny
c0a08d3353 Update readme.md
Исправления текста в разделе "Зачем это нужно"
2025-01-02 12:34:14 +03:00
bol-van
77474c9f76 update readme.md 2025-01-02 10:43:15 +03:00
bol-van
15b2ee2d82 Merge pull request #1017 from chymaboy/patch-1
Update readme.md
2025-01-02 10:39:56 +03:00
Evgeny
709279d6cf Update readme.md
Небольшие улучшения текста без изменений логики: исправления опечаток, орфографических и пунктуационных ошибок.
2025-01-02 00:10:20 +03:00
bol-van
35d676406c update docs 2024-12-26 22:04:33 +03:00
bol-van
9aff90b466 nfqws: allow partial TLS for relative markers 2024-12-26 13:46:12 +03:00
bol-van
bc463930aa Merge pull request #989 from Hi-Angel/march=native
Use `-march=native` when building from install_easy.sh
2024-12-24 19:29:10 +03:00
Konstantin Kharlamov
6fe9471077 Use -march=native when building from install_easy.sh
install_easy.sh is used for local installation, which implies that if
it invokes make, the binaries are not being cross-compiled. That
allows us to pass `-march=native` to make sure the binaries are
optimized for the current CPU.

We prepend `-march=native` to CFLAGS to make sure that if a user sets
CFLAGS with a distinct `-march` option, ours will get overwritten.
2024-12-24 18:42:16 +03:00
Konstantin Kharlamov
884213f7ac install_easy.sh: remove trailing whitespaces 2024-12-24 18:40:44 +03:00
bol-van
80bf409615 doc works 2024-12-22 21:01:07 +03:00
bol-van
3fe46ffb82 ipset: do not fail if config is absent 2024-12-22 13:48:36 +03:00
bol-van
42c52014ee ipset: scripts maintenance 2024-12-22 13:38:36 +03:00
bol-van
8aabc8b743 init.d: small optimize 2024-12-22 13:20:06 +03:00
bol-van
5df9b5d109 ipset: script maintenance 2024-12-22 13:10:06 +03:00
bol-van
50616896c8 ipset: scripts maintenance 2024-12-22 12:50:36 +03:00
bol-van
eb1cf7c15a base.sh: fix national decimal separator 2024-12-22 12:31:18 +03:00
bol-van
b878c313f8 init.d: exclude ipban from tpws redirection 2024-12-22 11:33:22 +03:00
bol-van
869e2cd8f9 common: remove readonly 2024-12-21 14:59:47 +03:00
bol-van
8a996b415e update issue_template 2024-12-21 10:54:50 +03:00
bol-van
62d2de904b update issue_template 2024-12-21 10:52:32 +03:00
bol-van
a02be13dd1 base.sh: support randoms in shells with 32-bit math 2024-12-20 16:57:27 +03:00
bol-van
c6058a4ea9 doc works 2024-12-20 13:00:22 +03:00
bol-van
27ffe77243 doc works 2024-12-20 12:59:19 +03:00
bol-van
3eb969cdaf doc works 2024-12-20 12:57:03 +03:00
bol-van
73040bb156 doc works 2024-12-20 12:52:22 +03:00
bol-van
c2bda9388f doc works 2024-12-20 10:37:23 +03:00
bol-van
6cd0de7a0b Merge pull request #967 from Nishimara/initd-sysv-usage
init.d/sysv: set usage helper to show actual path
2024-12-19 23:57:37 +03:00
Nishimara
85d319568c init.d/sysv: set usage helper to show actual path 2024-12-19 23:42:54 +03:00
bol-van
b3fd5c5dc1 Merge pull request #957 from spvkgn/fix-actions
github: minor for lexra
2024-12-18 11:30:01 +03:00
spvkgn
202b7224fb github: set target to RX5281 for lexra 2024-12-18 11:19:40 +05:00
spvkgn
647ee11917 github: optimize 2024-12-18 10:01:08 +05:00
bol-van
63fbf2857c nft.sh remove no more working hardware offload support test 2024-12-16 19:59:50 +03:00
63 changed files with 1336 additions and 717 deletions

2
.gitattributes vendored
View File

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

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

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

19
.github/ISSUE_TEMPLATE/issue-warning.md vendored Normal file
View File

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

View File

@@ -22,9 +22,6 @@ jobs:
fail-fast: false
matrix:
include:
- arch: lexra
tool: mips-linux
dir: rsdk-4.6.4-5281-EB-3.10-0.9.33-m32ub-20141001
- arch: arm64
tool: aarch64-unknown-linux-musl
- arch: arm
@@ -55,6 +52,13 @@ jobs:
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
@@ -63,27 +67,31 @@ jobs:
- name: Set up build tools
env:
REPO: 'spvkgn/musl-cross'
REPO_LEXRA: 'bol-van/build'
ARCH: ${{ matrix.arch }}
TOOL: ${{ matrix.tool }}
DIR: ${{ matrix.dir }}
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'spvkgn/musl-cross' }}
DIR: ${{ matrix.arch == 'lexra' && matrix.dir || matrix.tool }}
run: |
DIR=${DIR:-$TOOL}
[ "$ARCH" = lexra ] && sudo dpkg --add-architecture i386
sudo apt update -qq
sudo apt install -y libcap-dev
[ "$ARCH" = lexra ] && sudo apt install -y libc6:i386 zlib1g:i386
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
URL=https://github.com/$REPO/releases/download/latest/$DIR.tar.xz
[ "$ARCH" = lexra ] && URL=https://github.com/$REPO_LEXRA/raw/refs/heads/master/$DIR.txz
wget -qO- $URL | tar -C $HOME/tools -xJ || exit 1
[ -d "$HOME/tools/$DIR/bin" ] && echo "$HOME/tools/$DIR/bin" >> $GITHUB_PATH
[[ -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
@@ -93,10 +101,7 @@ jobs:
export NM=$TARGET-nm
export STRIP=$TARGET-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
export STAGING_DIR=/tmp
LDFLAGS=
[ "$ARCH" = lexra ] && LDFLAGS=-lgcc_eh
export LDFLAGS
export STAGING_DIR=$RUNNER_TEMP
# netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
@@ -106,7 +111,7 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="-Os -flto=auto" \
CFLAGS="-Os -flto=auto $CFLAGS" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -118,7 +123,7 @@ jobs:
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
(
cd zlib-*
CFLAGS="-Os -flto=auto" \
CFLAGS="-Os -flto=auto $CFLAGS" \
./configure --prefix= --static
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -129,7 +134,7 @@ jobs:
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="-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 .
@@ -322,11 +327,12 @@ jobs:
- 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 API=21
export CC="$TOOLCHAIN/bin/clang --target=$TARGET$API"
export AR=$TOOLCHAIN/bin/llvm-ar
export AS=$CC
@@ -355,6 +361,12 @@ jobs:
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

1
.gitignore vendored
View File

@@ -6,7 +6,6 @@ nfq/nfqws
nfq/winws.exe
tpws/tpws
binaries/my/
init.d/**/custom
ipset/zapret-ip*.txt
ipset/zapret-ip*.gz
ipset/zapret-hosts*.txt

View File

@@ -23,6 +23,7 @@ CURL=${CURL:-curl}
. "$ZAPRET_BASE/common/fwtype.sh"
. "$ZAPRET_BASE/common/virt.sh"
DOMAINS_DEFAULT=${DOMAINS_DEFAULT:-rutracker.org}
QNUM=${QNUM:-59780}
SOCKS_PORT=${SOCKS_PORT:-1993}
TPWS_UID=${TPWS_UID:-1}
@@ -35,9 +36,9 @@ MDIG=${MDIG:-${ZAPRET_BASE}/mdig/mdig}
DESYNC_MARK=0x10000000
IPFW_RULE_NUM=${IPFW_RULE_NUM:-1}
IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-59780}
DOMAINS=${DOMAINS:-rutracker.org}
CURL_MAX_TIME=${CURL_MAX_TIME:-2}
CURL_MAX_TIME_QUIC=${CURL_MAX_TIME_QUIC:-$CURL_MAX_TIME}
CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2}
MIN_TTL=${MIN_TTL:-1}
MAX_TTL=${MAX_TTL:-12}
USER_AGENT=${USER_AGENT:-Mozilla}
@@ -45,8 +46,9 @@ HTTP_PORT=${HTTP_PORT:-80}
HTTPS_PORT=${HTTPS_PORT:-443}
QUIC_PORT=${QUIC_PORT:-443}
UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org}
PARALLEL_OUT=/tmp/zapret_parallel
HDRTEMP=/tmp/zapret-hdr.txt
HDRTEMP=/tmp/zapret-hdr
NFT_TABLE=blockcheck
@@ -77,9 +79,11 @@ exitp()
{
local A
echo
echo press enter to continue
read A
[ "$BATCH" = 1 ] || {
echo
echo press enter to continue
read A
}
exit $1
}
@@ -212,7 +216,7 @@ doh_resolve()
# $1 - ip version 4/6
# $2 - hostname
# $3 - doh server URL. use $DOH_SERVER if empty
$MDIG --family=$1 --dns-make-query=$2 | $CURL -s --data-binary @- -H "Content-Type: application/dns-message" "${3:-$DOH_SERVER}" | $MDIG --dns-parse-query
$MDIG --family=$1 --dns-make-query=$2 | $CURL --max-time $CURL_MAX_TIME_DOH -s --data-binary @- -H "Content-Type: application/dns-message" "${3:-$DOH_SERVER}" | $MDIG --dns-parse-query
}
doh_find_working()
{
@@ -560,7 +564,7 @@ curl_supports_tls13()
[ $? = 2 ] && return 1
# curl can have tlsv1.3 key present but ssl library without TLS 1.3 support
# this is online test because there's no other way to trigger library incompatibility case
$CURL --tlsv1.3 --max-time $CURL_MAX_TIME -Is -o /dev/null https://iana.org 2>/dev/null
$CURL --tlsv1.3 --max-time 1 -Is -o /dev/null https://iana.org 2>/dev/null
r=$?
[ $r != 4 -a $r != 35 ]
}
@@ -651,28 +655,28 @@ curl_test_http()
# $3 - subst ip
# $4 - "detail" - detail info
local code loc
curl_probe $1 $2 $HTTP_PORT "$3" -SsD "$HDRTEMP" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
local code loc hdrt="${HDRTEMP}_${!:-$$}.txt"
curl_probe $1 $2 $HTTP_PORT "$3" -SsD "$hdrt" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
code=$?
rm -f "$HDRTEMP"
rm -f "$hdrt"
return $code
}
if [ "$4" = "detail" ] ; then
head -n 1 "$HDRTEMP"
grep "^[lL]ocation:" "$HDRTEMP"
head -n 1 "$hdrt"
grep "^[lL]ocation:" "$hdrt"
else
code=$(hdrfile_http_code "$HDRTEMP")
code=$(hdrfile_http_code "$hdrt")
[ "$code" = 301 -o "$code" = 302 -o "$code" = 307 -o "$code" = 308 ] && {
loc=$(hdrfile_location "$HDRTEMP")
loc=$(hdrfile_location "$hdrt")
echo "$loc" | grep -qE "^https?://.*$2(/|$)" ||
echo "$loc" | grep -vqE '^https?://' || {
echo suspicious redirection $code to : $loc
rm -f "$HDRTEMP"
rm -f "$hdrt"
return 254
}
}
fi
rm -f "$HDRTEMP"
rm -f "$hdrt"
[ "$code" = 400 ] && {
# this can often happen if the server receives fake packets it should not receive
echo http code $code. likely the server receives fakes.
@@ -964,18 +968,38 @@ curl_test()
# $2 - domain
# $3 - subst ip
# $4 - param of test function
local code=0 n=0
local code=0 n=0 p pids
while [ $n -lt $REPEATS ]; do
n=$(($n+1))
[ $REPEATS -gt 1 ] && printf "[attempt $n] "
if $1 "$IPV" $2 $3 "$4" ; then
[ $REPEATS -gt 1 ] && echo 'AVAILABLE'
else
code=$?
[ "$SCANLEVEL" = quick ] && break
fi
done
if [ "$PARALLEL" = 1 ]; then
rm -f "${PARALLEL_OUT}"*
for n in $(seq -s ' ' 1 $REPEATS); do
$1 "$IPV" $2 $3 "$4" >"${PARALLEL_OUT}_$n" &
pids="${pids:+$pids }$!"
done
n=1
for p in $pids; do
[ $REPEATS -gt 1 ] && printf "[attempt $n] "
if wait $p; then
[ $REPEATS -gt 1 ] && echo 'AVAILABLE'
else
code=$?
cat "${PARALLEL_OUT}_$n"
fi
n=$(($n+1))
done
rm -f "${PARALLEL_OUT}"*
else
while [ $n -lt $REPEATS ]; do
n=$(($n+1))
[ $REPEATS -gt 1 ] && printf "[attempt $n] "
if $1 "$IPV" $2 $3 "$4" ; then
[ $REPEATS -gt 1 ] && echo 'AVAILABLE'
else
code=$?
[ "$SCANLEVEL" = quick ] && break
fi
done
fi
[ "$4" = detail ] || {
if [ $code = 254 ]; then
echo "UNAVAILABLE"
@@ -1133,13 +1157,16 @@ pktws_curl_test_update_vary()
# $4 - desync mode
# $5,$6,... - strategy
local testf=$1 sec=$2 domain=$3 desync=$4 proto zerofake= splits= pos fake ret=1
local testf=$1 sec=$2 domain=$3 desync=$4 proto zerofake= tlsmod= splits= pos fake ret=1
shift; shift; shift; shift
proto=http
[ "$sec" = 0 ] || proto=tls
test_has_fake $desync && zerofake="--dpi-desync-fake-$proto=0x00000000"
test_has_fake $desync && {
zerofake="--dpi-desync-fake-$proto=0x00000000"
[ "$sec" = 0 ] || tlsmod="--dpi-desync-fake-tls-mod=rnd,rndsni,padencap"
}
if test_has_fakedsplit $desync ; then
splits="method+2 midsld"
[ "$sec" = 0 ] || splits="1 midsld"
@@ -1147,7 +1174,7 @@ pktws_curl_test_update_vary()
splits="method+2 midsld"
[ "$sec" = 0 ] || splits="1 midsld 1,midsld"
fi
for fake in '' $zerofake ; do
for fake in '' $zerofake $tlsmod ; do
if [ -n "$splits" ]; then
for pos in $splits ; do
pktws_curl_test_update $testf $domain --dpi-desync=$desync "$@" --dpi-desync-split-pos=$pos $fake && {
@@ -1551,7 +1578,7 @@ check_domain_http_tcp()
check_domain_prolog $1 $2 $4 || return
check_dpi_ip_block $1 $4
[ "$SKIP_IPBLOCK" = 1 ] || check_dpi_ip_block $1 $4
[ "$SKIP_TPWS" = 1 ] || {
echo
@@ -1597,22 +1624,22 @@ check_domain_http_udp()
check_domain_http()
{
# $1 - domain
check_domain_http_tcp curl_test_http 80 0 $1
check_domain_http_tcp curl_test_http $HTTP_PORT 0 $1
}
check_domain_https_tls12()
{
# $1 - domain
check_domain_http_tcp curl_test_https_tls12 443 1 $1
check_domain_http_tcp curl_test_https_tls12 $HTTPS_PORT 1 $1
}
check_domain_https_tls13()
{
# $1 - domain
check_domain_http_tcp curl_test_https_tls13 443 2 $1
check_domain_http_tcp curl_test_https_tls13 $HTTPS_PORT 2 $1
}
check_domain_http3()
{
# $1 - domain
check_domain_http_udp curl_test_http3 443 $1
check_domain_http_udp curl_test_http3 $QUIC_PORT $1
}
configure_ip_version()
@@ -1707,76 +1734,119 @@ ask_params()
exitp 1
}
echo "specify domain(s) to test. multiple domains are space separated."
printf "domain(s) (default: $DOMAINS) : "
local dom
read dom
[ -n "$dom" ] && DOMAINS="$dom"
[ -n "$DOMAINS" ] || {
DOMAINS="$DOMAINS_DEFAULT"
[ "$BATCH" = 1 ] || {
echo "specify domain(s) to test. multiple domains are space separated."
printf "domain(s) (default: $DOMAINS) : "
read dom
[ -n "$dom" ] && DOMAINS="$dom"
}
}
local IPVS_def=4
# yandex public dns
pingtest 6 2a02:6b8::feed:0ff && IPVS_def=46
printf "ip protocol version(s) - 4, 6 or 46 for both (default: $IPVS_def) : "
read IPVS
[ -n "$IPVS" ] || IPVS=$IPVS_def
[ "$IPVS" = 4 -o "$IPVS" = 6 -o "$IPVS" = 46 ] || {
echo 'invalid ip version(s). should be 4, 6 or 46.'
exitp 1
[ -n "$IPVS" ] || {
# yandex public dns
pingtest 6 2a02:6b8::feed:0ff && IPVS_def=46
[ "$BATCH" = 1 ] || {
printf "ip protocol version(s) - 4, 6 or 46 for both (default: $IPVS_def) : "
read IPVS
}
[ -n "$IPVS" ] || IPVS=$IPVS_def
[ "$IPVS" = 4 -o "$IPVS" = 6 -o "$IPVS" = 46 ] || {
echo 'invalid ip version(s). should be 4, 6 or 46.'
exitp 1
}
}
[ "$IPVS" = 46 ] && IPVS="4 6"
configure_curl_opt
ENABLE_HTTP=1
echo
ask_yes_no_var ENABLE_HTTP "check http"
ENABLE_HTTPS_TLS12=1
echo
ask_yes_no_var ENABLE_HTTPS_TLS12 "check https tls 1.2"
ENABLE_HTTPS_TLS13=0
echo
if [ -n "$TLS13" ]; then
echo "TLS 1.3 uses encrypted ServerHello. DPI cannot check domain name in server response."
echo "This can allow more bypass strategies to work."
echo "What works for TLS 1.2 will also work for TLS 1.3 but not vice versa."
echo "Most sites nowadays support TLS 1.3 but not all. If you can't find a strategy for TLS 1.2 use this test."
echo "TLS 1.3 only strategy is better than nothing."
ask_yes_no_var ENABLE_HTTPS_TLS13 "check https tls 1.3"
else
echo "installed curl version does not support TLS 1.3 . tests disabled."
fi
ENABLE_HTTP3=0
echo
if [ -n "$HTTP3" ]; then
echo "make sure target domain(s) support QUIC or result will be negative in any case"
ENABLE_HTTP3=1
ask_yes_no_var ENABLE_HTTP3 "check http3 QUIC"
else
echo "installed curl version does not support http3 QUIC. tests disabled."
fi
echo
echo "sometimes ISPs use multiple DPIs or load balancing. bypass strategies may work unstable."
printf "how many times to repeat each test (default: 1) : "
read REPEATS
REPEATS=$((0+${REPEATS:-1}))
[ "$REPEATS" = 0 ] && {
echo invalid repeat count
exitp 1
[ -n "$ENABLE_HTTP" ] || {
ENABLE_HTTP=1
[ "$BATCH" = 1 ] || {
echo
ask_yes_no_var ENABLE_HTTP "check http"
}
}
echo
echo quick - scan as fast as possible to reveal any working strategy
echo standard - do investigation what works on your DPI
echo force - scan maximum despite of result
SCANLEVEL=${SCANLEVEL:-standard}
ask_list SCANLEVEL "quick standard force" "$SCANLEVEL"
# disable tpws checks by default in quick mode
[ "$SCANLEVEL" = quick -a -z "$SKIP_TPWS" -a "$UNAME" != Darwin ] && SKIP_TPWS=1
[ -n "$ENABLE_HTTPS_TLS12" ] || {
ENABLE_HTTPS_TLS12=1
[ "$BATCH" = 1 ] || {
echo
ask_yes_no_var ENABLE_HTTPS_TLS12 "check https tls 1.2"
}
}
[ -n "$ENABLE_HTTPS_TLS13" ] || {
ENABLE_HTTPS_TLS13=0
if [ -n "$TLS13" ]; then
[ "$BATCH" = 1 ] || {
echo
echo "TLS 1.3 uses encrypted ServerHello. DPI cannot check domain name in server response."
echo "This can allow more bypass strategies to work."
echo "What works for TLS 1.2 will also work for TLS 1.3 but not vice versa."
echo "Most sites nowadays support TLS 1.3 but not all. If you can't find a strategy for TLS 1.2 use this test."
echo "TLS 1.3 only strategy is better than nothing."
ask_yes_no_var ENABLE_HTTPS_TLS13 "check https tls 1.3"
}
else
echo
echo "installed curl version does not support TLS 1.3 . tests disabled."
fi
}
[ -n "$ENABLE_HTTP3" ] || {
ENABLE_HTTP3=0
if [ -n "$HTTP3" ]; then
ENABLE_HTTP3=1
[ "$BATCH" = 1 ] || {
echo
echo "make sure target domain(s) support QUIC or result will be negative in any case"
ask_yes_no_var ENABLE_HTTP3 "check http3 QUIC"
}
else
echo
echo "installed curl version does not support http3 QUIC. tests disabled."
fi
}
[ -n "$REPEATS" ] || {
[ "$BATCH" = 1 ] || {
echo
echo "sometimes ISPs use multiple DPIs or load balancing. bypass strategies may work unstable."
printf "how many times to repeat each test (default: 1) : "
read REPEATS
}
REPEATS=$((0+${REPEATS:-1}))
[ "$REPEATS" = 0 ] && {
echo invalid repeat count
exitp 1
}
}
[ -z "$PARALLEL" -a $REPEATS -gt 1 ] && {
PARALLEL=0
[ "$BATCH" = 1 ] || {
echo
echo "parallel scan can greatly increase speed but may also trigger DDoS protection and cause false result"
ask_yes_no_var PARALLEL "enable parallel scan"
}
}
PARALLEL=${PARALLEL:-0}
[ -n "$SCANLEVEL" ] || {
SCANLEVEL=standard
[ "$BATCH" = 1 ] || {
echo
echo quick - scan as fast as possible to reveal any working strategy
echo standard - do investigation what works on your DPI
echo force - scan maximum despite of result
ask_list SCANLEVEL "quick standard force" "$SCANLEVEL"
# disable tpws checks by default in quick mode
[ "$SCANLEVEL" = quick -a -z "$SKIP_TPWS" -a "$UNAME" != Darwin ] && SKIP_TPWS=1
}
}
echo
@@ -1981,14 +2051,15 @@ check_dns()
unprepare_all()
{
# make sure we are not in a middle state that impacts connectivity
rm -f "$HDRTEMP"
[ -n "$IPV" ] && {
pktws_ipt_unprepare_tcp 80
pktws_ipt_unprepare_tcp 443
pktws_ipt_unprepare_udp 443
}
ws_kill
wait
[ -n "$IPV" ] && {
pktws_ipt_unprepare_tcp $HTTP_PORT
pktws_ipt_unprepare_tcp $HTTPS_PORT
pktws_ipt_unprepare_udp $QUIC_PORT
}
cleanup
rm -f "${HDRTEMP}"* "${PARALLEL_OUT}"*
}
sigint()
{
@@ -2034,10 +2105,10 @@ for dom in $DOMAINS; do
for IPV in $IPVS; do
configure_ip_version
[ "$ENABLE_HTTP" = 1 ] && {
check_domain_port_block $dom $HTTP_PORT
[ "$SKIP_IPBLOCK" = 1 ] || check_domain_port_block $dom $HTTP_PORT
check_domain_http $dom
}
[ "$ENABLE_HTTPS_TLS12" = 1 -o "$ENABLE_HTTPS_TLS13" = 1 ] && check_domain_port_block $dom $HTTPS_PORT
[ "$ENABLE_HTTPS_TLS12" = 1 -o "$ENABLE_HTTPS_TLS13" = 1 ] && [ "$SKIP_IPBLOCK" != 1 ] && check_domain_port_block $dom $HTTPS_PORT
[ "$ENABLE_HTTPS_TLS12" = 1 ] && check_domain_https_tls12 $dom
[ "$ENABLE_HTTPS_TLS13" = 1 ] && check_domain_https_tls13 $dom
[ "$ENABLE_HTTP3" = 1 ] && check_domain_http3 $dom

View File

@@ -241,7 +241,7 @@ fix_sbin_path()
# it can calculate floating point expr
calc()
{
awk "BEGIN { print $*}";
LC_ALL=C awk "BEGIN { print $*}";
}
fsleep_setup()
@@ -318,18 +318,27 @@ 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' | cut -c 1-17)
r=1$(echo $rs | $MD5 | sed 's/[^0-9]//g' | $RCUT)
echo $(( ($r % ($2-$1+1)) + $1 ))
}

View File

@@ -1,4 +1,4 @@
readonly GET_LIST_PREFIX=/ipset/get_
GET_LIST_PREFIX=/ipset/get_
SYSTEMD_DIR=/lib/systemd
[ -d "$SYSTEMD_DIR" ] || SYSTEMD_DIR=/usr/lib/systemd
@@ -617,11 +617,17 @@ write_config_var()
replace_var_def $1 "$M" "$ZAPRET_CONFIG"
}
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"
@@ -650,6 +656,7 @@ check_prerequisites_linux()
echo packages required : $PKGS
APTGET=$(whichq apt-get)
DNF=$(whichq dnf)
YUM=$(whichq yum)
PACMAN=$(whichq pacman)
ZYPPER=$(whichq zypper)
@@ -657,39 +664,23 @@ check_prerequisites_linux()
APK=$(whichq apk)
if [ -x "$APTGET" ] ; then
"$APTGET" update
"$APTGET" install -y --no-install-recommends $PKGS dnsutils || {
echo could not install prerequisites
exitp 6
}
"$APTGET" install -y --no-install-recommends $PKGS dnsutils || no_prereq_exit
elif [ -x "$DNF" ] ; then
"$DNF" -y install $PKGS || no_prereq_exit
elif [ -x "$YUM" ] ; then
"$YUM" -y install $PKGS || {
echo could not install prerequisites
exitp 6
}
"$YUM" -y install $PKGS || no_prereq_exit
elif [ -x "$PACMAN" ] ; then
"$PACMAN" -Syy
"$PACMAN" --noconfirm -S $PKGS || {
echo could not install prerequisites
exitp 6
}
"$PACMAN" --noconfirm -S $PKGS || no_prereq_exit
elif [ -x "$ZYPPER" ] ; then
"$ZYPPER" --non-interactive install $PKGS || {
echo could not install prerequisites
exitp 6
}
"$ZYPPER" --non-interactive install $PKGS || no_prereq_exit
elif [ -x "$EOPKG" ] ; then
"$EOPKG" -y install $PKGS || {
echo could not install prerequisites
exitp 6
}
"$EOPKG" -y install $PKGS || no_prereq_exit
elif [ -x "$APK" ] ; then
"$APK" update
# for alpine
[ "$FWTYPE" = iptables ] && [ -n "$($APK list ip6tables)" ] && PKGS="$PKGS ip6tables"
"$APK" add $PKGS || {
echo could not install prerequisites
exitp 6
}
"$APK" add $PKGS || no_prereq_exit
else
echo supported package manager not found
echo you must manually install : $UTILS

View File

@@ -1,5 +1,9 @@
std_ports
readonly ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes"
ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes"
IPSET_EXCLUDE="-m set ! --match-set nozapret"
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
IPBAN_EXCLUDE="-m set ! --match-set ipban"
IPBAN_EXCLUDE6="-m set ! --match-set ipban6"
ipt()
{
@@ -132,7 +136,7 @@ _fw_tpws4()
ipt_print_op $1 "$2" "tpws (port $3)"
rule="$2 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3"
rule="$2 $IPSET_EXCLUDE dst $IPBAN_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3"
for i in $4 ; do
ipt_add_del $1 PREROUTING -t nat -i $i $rule
done
@@ -160,7 +164,7 @@ _fw_tpws6()
ipt_print_op $1 "$2" "tpws (port $3)" 6
rule="$2 $IPSET_EXCLUDE6 dst"
rule="$2 $IPSET_EXCLUDE6 dst $IPBAN_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

View File

@@ -4,6 +4,8 @@
# 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()
{

View File

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

View File

@@ -1,5 +1,5 @@
[ -n "$ZAPRET_NFT_TABLE" ] || ZAPRET_NFT_TABLE=zapret
readonly nft_connbytes="ct original packets"
nft_connbytes="ct original packets"
# required for : nft -f -
create_dev_stdin
@@ -263,28 +263,6 @@ nft_add_flow_offload_exemption()
[ "$DISABLE_IPV6" = "1" -o -z "$2" ] || nft_add_rule flow_offload oifname @wanif6 $2 ip6 daddr != @nozapret6 return comment \"$3\"
}
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
@@ -370,17 +348,15 @@ 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
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
# 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
done
;;
esac
@@ -411,8 +387,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 $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
nft_insert_rule dnat_pre iifname @lanif $filter ip daddr != @nozapret $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
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
prepare_route_localnet
}
}
@@ -426,9 +402,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 $FW_EXTRA_POST dnat ip6 to [::1]:$port
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
[ -n "$3" ] && {
nft_insert_rule dnat_pre $filter ip6 daddr != @nozapret6 $FW_EXTRA_POST dnat ip6 to iifname map @link_local:$port
nft_insert_rule dnat_pre $filter ip6 daddr != @nozapret6 ip6 daddr != @ipban6 $FW_EXTRA_POST 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

View File

@@ -97,7 +97,7 @@ NFQWS_OPT="
# none,ipset,hostlist,autohostlist
MODE_FILTER=none
# openwrt only : donttouch,none,software,hardware
# donttouch,none,software,hardware
FLOWOFFLOAD=donttouch
# openwrt: specify networks to be treated as LAN. default is "lan"

View File

@@ -434,3 +434,27 @@ 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.3
nfqws: --dpi-desync-fake-tls-mod=dupsid
nfqws,tpws: test accessibility of list files after privs drop
nfqws,tpws: --version

View File

@@ -2,8 +2,8 @@
> [!CAUTION]
> Не пишите в issue вопросы типа "как скопировать файл", "как скачать", "как
> запустить", ... То есть все , что касается базовых навыков обращения с ОС
> linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы
> запустить" и т.п. То есть все, что касается базовых навыков обращения с ОС
> Linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы
> возникают, рекомендую не использовать данный софт или искать помощь где-то в
> другом месте. То же самое могу сказать тем, кто хочет нажать 1 кнопку, чтобы
> все заработало, и совсем не хочет читать и изучать. Увы, такое не подвезли и
@@ -89,14 +89,15 @@
>
> Проверить работает ли этот вариант можно так:
> ```sh
> $ dig -p 53 @77.88.8.88 rutracker.org dig -p 1253 @77.88.8.88 rutracker.org
> $ dig -p 53 @77.88.8.88 rutracker.org
> $ dig -p 1253 @77.88.8.88 rutracker.org
> ```
>
> Если DNS действительно подменяется, и ответ на эти 2 команды разный,
> значит метод вероятно работает.
>
> В openwrt DNS на нестандартном порту можно прописать в `/etc/config/dhcp`
> таким способом :
> таким способом:
>
> ```
> config dnsmasq
@@ -163,7 +164,7 @@
> Если кратко, то обычно параметры конструируются так:
> ```sh
> "--filter-udp=443 'параметры для quic' <HOSTLIST_NOAUTO> --new
> --filter-tcp=80,443 'обьединенные параметры для http и https' <HOSTLIST>"
> --filter-tcp=80,443 'объединенные параметры для http и https' <HOSTLIST>"
> ```
>
> Или так:
@@ -193,7 +194,7 @@
> "--filter-l3=ipv4 --filter-udp=443 lпараметры для quic ipv4' <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv4 --filter-tcp=80 'параметры для http ipv4' <HOSTLIST> --new
> --filter-l3=ipv4 --filter-tcp=443 'параметры для https ipv4' <HOSTLIST> --new
> --filter-l3=ipv6 --filter-udp=443 "параметры для quic ipv6" <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv6 --filter-udp=443 'параметры для quic ipv6' <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv6 --filter-tcp=80 'параметры для http ipv6' <HOSTLIST> --new
> --filter-l3=ipv6 --filter-tcp=443 'параметры для https ipv6' <HOSTLIST>"
> ```

View File

@@ -1,4 +1,4 @@
# zapret v69.8
# zapret v70.1
# SCAMMER WARNING
@@ -19,6 +19,7 @@ ___
- [nfqws](#nfqws)
- [DPI desync attack](#dpi-desync-attack)
- [Fakes](#fakes)
- [Fake mods](#fake-mods)
- [TCP segmentation](#tcp-segmentation)
- [Sequence numbers overlap](#sequence-numbers-overlap)
- [ipv6 specific modes](#ipv6-specific-modes)
@@ -119,7 +120,7 @@ You need to run them with the necessary parameters and redirect certain traffic
when blocked domains are queried. If this is the case change DNS to public ones, such as 8.8.8.8 or 1.1.1.1.Sometimes ISP hijacks queries to any DNS server. Dnscrypt or dns-over-tls help.
* If blocking is done by IP.
* If a connection passes through a filter capable of reconstructing a TCP connection, and which
follows all standards. For example, we are routed to squid. Connection goes through the full OS tcpip stack, fragmentation disappears immediately as a means of circumvention. Squid is correct, it will find everything as it should, it is useless to deceive him. BUT. Only small providers can afford using squid, since it is very resource intensive. Large companies usually use DPI, which is designed for much greater bandwidth.
follows all standards. For example, we are routed to squid. Connection goes through the full OS tcpip stack. This project targets DPI only, not full OS stack and not server applications.
## nfqws
@@ -132,6 +133,7 @@ nfqws takes the following parameters:
--debug=0|1
--dry-run ; verify parameters and exit with code 0 if successful
--version ; print version and exit
--comment ; any text (ignored)
--qnum=<nfqueue_number>
--daemon ; daemonize
@@ -172,6 +174,7 @@ nfqws takes the following parameters:
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
--dpi-desync-fake-http=<filename>|0xHEX ; file containing fake http request
--dpi-desync-fake-tls=<filename>|0xHEX ; file containing fake TLS ClientHello (for https)
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,dupsid,padencap
--dpi-desync-fake-unknown=<filename>|0xHEX ; file containing unknown protocol fake payload
--dpi-desync-fake-syndata=<filename>|0xHEX ; file containing SYN data payload
--dpi-desync-fake-quic=<filename>|0xHEX ; file containing fake QUIC Initial
@@ -260,6 +263,22 @@ Fakes are separate generated by nfqws packets carrying false information for DPI
`--dpi-desync-fooling` takes multiple comma separated values.
### FAKE mods
**nfqws** has built-in TLS fake. It can be customized with `--dpi-desync-fake-tls` option.
Customized fake data can be anything - valid TLS Client Hello or arbitrary data.
It's possible to use TLS Client Hello with any fingerprint and any SNI.
**nfqws** can do some modifications of valid TLS Client Hello fakes in runtime with `--dpi-desync-fake-tls-mod` option.
* `none`. Do not do any mods.
* `rnd`. Randomize `random` and `session id` fields. Applied on every request.
* `rndsni`. Randomize SNI. If SNI >=7 symbols random SLD is applied with known TLD. Otherwise filled with random symbols. Applied only once at startup.
* `dupsid`. Copy `session ID` from original TLS Client Hello. Takes precedence over `rnd`. Applied on every request.
* `padencap`. Padding extension is extended by original TLS Client Hello size (including multi packet variation with kyber). Padding extension is added to the end if not present, otherwise it must be the last extension. All lengths are increased. Fake size is not changed. Can be useful if DPI does not analyze sequence numbers properly. Applied on every request.
By default if custom fake is not defined `rnd,rndsni,dupsid` mods are applied. If defined - `none`.
This behaviour is compatible with previous versions with addition of `dupsid`.
### TCP segmentation
@@ -642,6 +661,7 @@ tpws is transparent proxy.
--debug=0|1|2|syslog|@<filename> ; 1 and 2 means log to console and set debug level. for other targets use --debug-level.
--debug-level=0|1|2 ; specify debug level for syslog and @<filename>
--dry-run ; verify parameters and exit with code 0 if successful
--version ; print version and exit
--bind-addr=<v4_addr>|<v6_addr> ; for v6 link locals append %interface_name : fe80::1%br-lan
--bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface
--bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface
@@ -965,7 +985,8 @@ If you need "all except" mode you dont have to delete zapret-hosts-users.txt. Ju
Subdomains auto apply. For example, "ru" in the list affects "*.ru" .
**tpws** and **nfqws** automatically reload lists if their modification date is changed.
**tpws** and **nfqws** automatically reload lists if their modification time or file size is changed.
HUP signal forcibly reloads all lists.
When filtering by domain name, daemons should run without filtering by ipset.
When using large regulator lists estimate the amount of RAM on the router !

View File

@@ -1,4 +1,4 @@
# zapret v69.8
# zapret v70.1
# ВНИМАНИЕ, остерегайтесь мошенников
@@ -21,6 +21,7 @@ zapret является свободным и open source.
- [nfqws](#nfqws)
- [АТАКА ДЕСИНХРОНИЗАЦИИ DPI](#атака-десинхронизации-dpi)
- [ФЕЙКИ](#фейки)
- [МОДИФИКАЦИЯ ФЕЙКОВ](#модификация-фейков)
- [TCP СЕГМЕНТАЦИЯ](#tcp-сегментация)
- [ПЕРЕКРЫТИЕ SEQUENCE NUMBERS](#перекрытие-sequence-numbers)
- [СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6](#специфические-режимы-ipv6)
@@ -46,9 +47,9 @@ zapret является свободным и open source.
- [СЛУЖЕБНЫЕ ПАРАМЕТРЫ](#служебные-параметры)
- [IPTABLES ДЛЯ TPWS](#iptables-для-tpws)
- [NFTABLES ДЛЯ TPWS](#nftables-для-tpws)
- [Способы получения списка заблокированных IP](#способы-получения-списка-заблокированных-ip)
- [ip2net](#ip2net)
- [mdig](#mdig)
- [Способы получения списка заблокированных IP](#способы-получения-списка-заблокированных-ip)
- [Фильтрация по именам доменов](#фильтрация-по-именам-доменов)
- [Режим фильтрации autohostlist](#режим-фильтрации-autohostlist)
- [Проверка провайдера](#проверка-провайдера)
@@ -71,14 +72,14 @@ zapret является свободным и open source.
## Зачем это нужно
Автономное средство противодействия DPI, которое не требует подключения каких-либо сторонних серверов. Может помочь
обойти блокировки или замедление сайтов http(s), сигнатурный анализ tcp и udp протоколов, например с целью блокировки
обойти блокировки или замедление сайтов HTTP(S), сигнатурный анализ TCP и UDP протоколов, например, с целью блокировки
VPN.
Проект нацелен прежде всего на маломощные embedded устройства - роутеры, работающие под openwrt. Поддерживаются
традиционные Linux системы, FreeBSD, OpenBSD, частично MacOS. В некоторых случаях возможна самостоятельная прикрутка
Проект нацелен прежде всего на маломощные embedded устройства - роутеры, работающие под OpenWrt. Поддерживаются
традиционные Linux-системы, FreeBSD, OpenBSD, частично macOS. В некоторых случаях возможна самостоятельная прикрутка
решения к различным прошивкам.
Большая часть функционала работает на windows.
Большая часть функционала работает на Windows.
## Быстрый старт
@@ -89,25 +90,25 @@ VPN.
В самом простейшем случае вы имеете дело с пассивным DPI. Пассивный DPI может читать трафик из потока, может инжектить
свои пакеты, но не может блокировать проходящие пакеты. Если запрос "плохой", пассивный DPI инжектит пакет RST,
опционально дополняя его пакетом http redirect. Если фейк пакет инжектится только для клиента, в этом случае можно
обойтись командами iptables для дропа RST и/или редиректа на заглушку по определенным условиям, которые нужно подбирать
опционально дополняя его пакетом HTTP redirect. Если фейк пакет инжектится только для клиента, в этом случае можно
обойтись командами iptables для дропа RST и/или редиректа на заглушку по определённым условиям, которые нужно подбирать
для каждого провайдера индивидуально. Так мы обходим последствия срабатывания триггера запрета. Если пассивный DPI
направляет пакет RST в том числе и серверу, то вы ничего с этим не сможете сделать. Ваша задача - не допустить
срабатывания триггера запрета. Одними iptables уже не обойдетесь. Этот проект нацелен именно на предотвращение
направляет пакет RST в том числе и серверу, то вы ничего с этим не сможете сделать. Ваша задача не допустить
срабатывания триггера запрета. Одними iptables уже не обойтись. Этот проект нацелен именно на предотвращение
срабатывания запрета, а не ликвидацию его последствий.
Активный DPI ставится в разрез провода и может дропать пакеты по любым критериям, в том числе распознавать TCP потоки и
Активный DPI ставится в разрез провода и может дропать пакеты по любым критериям, в том числе распознавать TCP-потоки и
блокировать любые пакеты, принадлежащие потоку.
Как не допустить срабатывания триггера запрета ? Послать то, на что DPI не рассчитывает и что ломает ему алгоритм
Как не допустить срабатывания триггера запрета? Послать то, на что DPI не рассчитывает и что ломает ему алгоритм
распознавания запросов и их блокировки.
Некоторые DPI не могут распознать http запрос, если он разделен на TCP сегменты. Например, запрос
Некоторые DPI не могут распознать HTTP-запрос, если он разделен на TCP-сегменты. Например, запрос
вида `GET / HTTP/1.1\r\nHost: kinozal.tv......`
мы посылаем 2 частями : сначала идет `GET`, затем `/ HTTP/1.1\r\nHost: kinozal.tv.....`. Другие DPI спотыкаются, когда
заголовок `Host:` пишется в другом регистре : например,`host:`. Кое-где работает добавление дополнительного пробела
после метода : `GET /` => `GET /`
или добавление точки в конце имени хоста : `Host: kinozal.tv.`
мы посылаем двумя частями: сначала идет `GET`, затем `/ HTTP/1.1\r\nHost: kinozal.tv.....`. Другие DPI спотыкаются, когда
заголовок `Host:` пишется в другом регистре: например, `host:`. Кое-где работает добавление дополнительного пробела
после метода: `GET /` `GET /`
или добавление точки в конце имени хоста: `Host: kinozal.tv.`
Существует и более продвинутая магия, направленная на преодоление DPI на пакетном уровне.
@@ -144,14 +145,9 @@ DPI. Все больше становится внереестровых бло
* Если подменяется DNS. С этой проблемой легко справиться.
* Если блокировка осуществляется по IP.
* Если соединение проходит через фильтр, способный реконструировать TCP соединение, и который следует всем стандартам.
Например, нас заворачивают на squid. Соединение идет через полноценный стек tcpip операционной системы, фрагментация
отпадает сразу как средство обхода. Squid правильный, он все найдет как надо, обманывать его бесполезно. НО.
Заворачивать на squid могут позволить себе лишь небольшие провайдеры, поскольку это очень ресурсоемко. Большие
компании обычно используют DPI, который рассчитан на гораздо большую пропускную способность. Может применяться
комбинированный подход, когда на DPI заворачивают только IP из "плохого" списка, и дальше уже DPI решает пропускать
или нет. Так можно снизить нагрузку на DPI в десятки, если не сотни раз, а следовательно не покупать очень дорогие
решения, обойдясь чем-то существенно более дешевым. Мелкие провайдеры могут покупать услугу фильтрации у вышестоящих,
чтобы самим не морочиться, и они уже будут применять DPI.
Например, нас заворачивают на squid. Соединение идет через полноценный стек tcpip операционной системы.
Проект нацелен на обман DPI, который всилу ограниченности ресурсов и большого трафика вынужден интерпретировать его лишь ограниченно.
Обмануть полноценный стек ОС и полноценные серверные приложения не получится.
## nfqws
@@ -163,6 +159,7 @@ dvtws, собираемый из тех же исходников (см. [док
--debug=0|1 ; 1=выводить отладочные сообщения
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
--version ; вывести версию и выйти
--comment ; любой текст (игнорируется)
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
@@ -198,6 +195,7 @@ dvtws, собираемый из тех же исходников (см. [док
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
--dpi-desync-fake-tls-mod=mod[,mod] ; список через запятую режимов runtime модификации фейков : none,rnd,rndsni,dupsid,padencap
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
@@ -268,7 +266,7 @@ dvtws, собираемый из тех же исходников (см. [док
`net.netfilter.nf_conntrack_checksum=1` заставляет conntrack проверять tcp и udp чексуммы входящих пакетов и
выставлять state INVALID для пакетов с инвалидной суммой. Обычно в правилах iptables вставляется правило для дропа
пакетов с состоянием INVALID в цепочке FORWARD. Совместное сочетание этих факторов приводит к непрохождению badsum
через такой роутер. В openwrt из коробки `net.netfilter.nf_conntrack_checksum=0`, в других роутерах часто нет, и не
через такой роутер. В OpenWrt из коробки `net.netfilter.nf_conntrack_checksum=0`, в других роутерах часто нет, и не
всегда это можно изменить. Чтобы nfqws мог работать через роутер, нужно на нем выставить указанное значение sysctl в 0.
nfqws на самом роутере будет работать и без этой настройки, потому что чексумма локально созданных пакетов не
проверяется никогда. Если роутер за другим NAT, например провайдерским, и он не пропускает invalid packets вы ничего
@@ -317,6 +315,25 @@ dvtws, собираемый из тех же исходников (см. [док
Режимы дурения могут сочетаться в любых комбинациях. `--dpi-desync-fooling` берет множество значений через запятую.
### МОДИФИКАЦИЯ ФЕЙКОВ
В nfqws зашит базовый вариант фейка для TLS. Его можно переопределить опцией `--dpi-desync-fake-tls`.
Переопределение фейков дает возможность использовать любые данные в качестве фейка для TLS.
Можно использовать фейковый Client Hello с любым фингерпринтом и с любым SNI.
Некоторые модификации можно делать в процессе выполнения с помощью `--dpi-desync-fake-tls-mod`.
Часть из них работает при обработке каждого TLS Client Hello и может подстраиваться под отправляемые данные.
Модификации требуют наличия полного валидного TLS Client Hello в качестве фейка, они не работают с произвольными данными.
* `none`. Не применять никакие модификации.
* `rnd`. Рандомизировать поля `random` и `session id`. Выполняется на каждый запрос.
* `dupsid`. Копировать `session ID` из передаваемого TLS Client Hello. Имеет приоритет над `rnd`. Выполняется на каждый запрос.
* `rndsni`. Рандомизировать SNI. Если SNI >=7 символов, применяется случайный домен 2 уровня с известным TLD, иначе заполняется случайными символами без точки. Выполняется один раз при старте.
* `padencap`. Расширяется padding extension на размер передаваемого TLS Client Hello (включая многопакетный вариант с kyber). Если padding отсутствует, он добавляется в конец. Если присутствует - требуется, чтобы padding шел последним extension. Правятся все длины, чтобы создать видимость включения передаваемого TLS Client Hello в padding extension. Размер фейка не изменяется. Расчет идет на DPI, который не анализирует sequence numbers должным образом. Выполняется на каждый запрос.
По умолчанию если не задан собственный фейк для TLS используются модификации `rnd,rndsni,dupsid`. Если фейк задан, используется `none`.
Это соответствует поведению программы более старых версий с добавлением функции `dupsid`.
### TCP СЕГМЕНТАЦИЯ
* `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях.
@@ -571,7 +588,7 @@ ipv6 : Нет способа для приложения гарантирова
Чтобы не загромождать описание, смотрите пример решения этой проблемы в `blockcheck.sh`.
Иногда требуется подгружать модуль `ip6table_raw` с параметром `raw_before_defrag=1`.
В openwrt параметры модулей указываются через пробел после их названий в файлах `/etc/modules.d`.
В OpenWrt параметры модулей указываются через пробел после их названий в файлах `/etc/modules.d`.
В традиционных системах посмотрите используется ли `iptables-legacy` или `iptables-nft`. Если legacy, то нужно создать файл
`/etc/modprobe.d/ip6table_raw.conf` с содержимым :
```
@@ -744,12 +761,21 @@ iptables могут не работать. При включенном offloadin
Пакеты, проходящие через SFO, так же проходят мимо большей части механизмов iptables. При включенном SFO работает
DNAT/REDIRECT (tpws). Эти соединения исключаются из offloading. Однако, остальные соединения идут через SFO, потому
NFQUEUE будет срабатывать только до помещения соединения в flowtable. Практически это означает, что почти весь функционал nfqws работать не будет.
Offload включается через специальный target в iptables `FLOWOFFLOAD`. Не обязательно пропускать весь трафик через offload. Можно исключить из
offload соединения, которые должны попасть на tpws или nfqws. openwrt не предусматривает выборочного управления offload.
Поэтому скрипты zapret поддерживают свою систему выборочного управления offload в openwrt.
Offload включается через специальный target в iptables `FLOWOFFLOAD` или через flowtable в nftables.
iptables target `FLOWOFFLOAD` - это проприетарное изобретение openwrt.
Не обязательно пропускать весь трафик через offload.
tpws и так обходит offload "by design", а для отработки nfqws достаточно первых нескольких пакетов в tcp соединении или udp сеансе.
Пока сеанс не направлен на offload, он процессится обычным образом через полноценный netfilter.
Как только срабатывает правило offload по любому входящему или исходящему пакету, весь сеанс окончательно уходит из netfilter в offload.
Поэтому скрипты zapret берут правила для NFQUEUE, что они создали, и из них создают exemption правила, которые не дают раньше времени попасть сеансу в offload, а потом его "отпускают".
При этом входящим пакетам не дают начать offload, триггером выступают только исходящие пакеты.
Эта схема обеспечивает практически нулевой негативный эффект на скорость, одновременно покрывая нужды nfqws и упрощая правила таблиц.
OpenWrt не предусматривает выборочного управления offload, поэтому скрипты zapret поддерживают свою систему выборочного управления.
iptables target `FLOWOFFLOAD` - это проприетарное изобретение OpenWrt.
Управление offload в nftables реализовано в базовом ядре linux без патчей.
nftables - единственный способ включения offload на классическом Linux.
## tpws
@@ -761,6 +787,7 @@ tpws - это transparent proxy.
--debug=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
--version ; вывести версию и выйти
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
@@ -878,13 +905,15 @@ tpws, как и nfqws, поддерживает множественную се
указанным сплит позициям. Другие ОС в этом вопросе ведут себя более предсказуемо. Спонтанного обьединения замечено не было.
Поэтому не стоит злоупотреблять сплитами и в особенности мелкими соседними пакетами.
Как показывается практика, проблемы могут начаться , если количество сплит позиций превышает 8.
Как показывается практика, проблемы могут начаться , если количество сплитов более одного.
На каких-то системах наблюдался стабильный результат до 8 сплитов, на других проблемы уже начинались после 2 сплитов.
Один сплит работает стабильно, если не является частью массивной потоковой передачи.
При неудаче сегментации будет выводиться сообщение `WARNING ! segmentation failed`.
Если вы его видите, это повод снизить количество сплит позиций.
Если это не вариант, для ядер Linux >=4.6 есть параметр `--fix-seg`. Он позволяет подождать завершение отсылки перед отправкой следующей части.
Но этот вариант ломает модель асинхронной обработки событий. Пока идет ожидание, все остальные соединения не обрабатываются
и кратковременно подвисают. На практике это может быть совсем небольшое ожидание - менее 10 мс.
И производится оно только , если происходит split, и в ожидании есть реальная необходимость.
Выполняется оно только , если происходит split, и в ожидании есть реальная необходимость.
В высоконагруженных системах данный вариант не рекомендуется. Но для домашнего использования может подойти, и вы эти задержки даже не заметите.
Если вы пытаетесь сплитнуть массивную передачу с `--split-any-protocol`, когда информация поступает быстрее отсылки,
@@ -1100,6 +1129,78 @@ nft add rule inet ztest dnat_pre meta iifname $IFACE_LAN tcp dport { 80, 443 } d
nft delete table inet ztest
```
## ip2net
Утилита ip2net предназначена для преобразования ipv4 или ipv6 списка ip в список подсетей
с целью сокращения размера списка. Входные данные берутся из stdin, выходные выдаются в `stdout`.
```
-4 ; лист - ipv4 (по умолчанию)
-6 ; лист - ipv6
--prefix-length=min[-max] ; диапазон рассматриваемых длин префиксов. например : 22-30 (ipv4), 56-64 (ipv6)
--v4-threshold=mul/div ; ipv4 : включать подсети, в которых заполнено по крайней мере mul/div адресов. например : 3/4
--v6-threshold=N ; ipv6 : минимальное количество ip для создания подсети
```
В списке могут присутствовать записи вида ip/prefix и ip1-ip2. Такие записи выкидываются в stdout без изменений.
Они принимаются командой ipset. ipset умеет для листов hash:net из ip1-ip2 делать оптимальное покрытие ip/prefix.
ipfw из FreeBSD понимает ip/prefix, но не понимает ip1-ip2.
ip2net фильтрует входные данные, выкидывая неправильные IP адреса.
Выбирается подсеть, в которой присутствует указанный минимум адресов.
Для ipv4 минимум задается как процент от размера подсети (mul/div. например, 3/4), для ipv6 минимум задается напрямую.
Размер подсети выбирается следующим алгоритмом:
Сначала в указанном диапазоне длин префиксов ищутся подсети, в которых количество адресов - максимально.
Если таких сетей найдено несколько, берется наименьшая сеть (префикс больше).
Например, заданы параметры v6_threshold=2 prefix_length=32-64, имеются следующие ipv6 :
```
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
Результат будет :
1234:5678:aaa8::/45
```
Эти адреса так же входят в подсеть /32. Однако, нет смысла проходиться ковровой бомбардировкой,
когда те же самые адреса вполне влезают в /45 и их ровно столько же.
Если изменить v6_threshold=4, то результат будет:
```
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
```
То есть ip не объединятся в подсеть, потому что их слишком мало.
Если изменить `prefix_length=56-64`, результат будет:
```
1234:5678:aaaa::/64
1234:5678:aaac::5
```
Требуемое процессорное время для вычислений сильно зависит от ширины диапазона длин префиксов, размера искомых подсетей и длины листа.
Если ip2net думает слишком долго, не используйте слишком большие подсети и уменьшите диапазон длин префиксов.
Учтите, что арифметика mul/div - целочисленная. При превышении разрядной сетки 32 bit результат непредсказуем.
Не надо делать такое: 5000000/10000000. 1/2 - гораздо лучше.
## mdig
Программа предназначена для многопоточного ресолвинга больших листов через системный DNS.
Она берет из stdin список доменов и выводит в stdout результат ресолвинга. Ошибки выводятся в stderr.
```
--threads=<threads_number> ; количество потоков. по умолчанию 1.
--family=<4|6|46> ; выбор семейства IP адресов : ipv4, ipv6, ipv4+ipv6
--verbose ; дебаг-лог на консоль
--stats=N ; выводить статистику каждые N доменов
--log-resolved=<file> ; сохранять успешно отресолвленные домены в файл
--log-failed=<file> ; сохранять неудачно отресолвленные домены в файл
--dns-make-query=<domain> ; вывести в stdout бинарный DNS запрос по домену. если --family=6, запрос будет AAAA, иначе A.
--dns-parse-query ; распарсить бинарный DNS ответ и выдать все ivp4 и ipv6 адреса из него в stdout
```
Параметры `--dns-make-query` и `--dns-parse-query` позволяют провести ресолвинг одного домена через произвольный канал.
Например, следующим образом можно выполнить DoH запрос, используя лишь mdig и curl :
```
mdig --family=6 --dns-make-query=rutracker.org | curl --data-binary @- -H "Content-Type: application/dns-message" https://cloudflare-dns.com/dns-query | mdig --dns-parse-query
```
## Способы получения списка заблокированных IP
@@ -1198,79 +1299,6 @@ ipfw таблицы в отличие от ipset могут содержать
Это особенно полезно на BSD системах с PF.
LISTS_RELOAD=- отключает перезагрузку листов.
## ip2net
Утилита ip2net предназначена для преобразования ipv4 или ipv6 списка ip в список подсетей
с целью сокращения размера списка. Входные данные берутся из stdin, выходные выдаются в `stdout`.
```
-4 ; лист - ipv4 (по умолчанию)
-6 ; лист - ipv6
--prefix-length=min[-max] ; диапазон рассматриваемых длин префиксов. например : 22-30 (ipv4), 56-64 (ipv6)
--v4-threshold=mul/div ; ipv4 : включать подсети, в которых заполнено по крайней мере mul/div адресов. например : 3/4
--v6-threshold=N ; ipv6 : минимальное количество ip для создания подсети
```
В списке могут присутствовать записи вида ip/prefix и ip1-ip2. Такие записи выкидываются в stdout без изменений.
Они принимаются командой ipset. ipset умеет для листов hash:net из ip1-ip2 делать оптимальное покрытие ip/prefix.
ipfw из FreeBSD понимает ip/prefix, но не понимает ip1-ip2.
ip2net фильтрует входные данные, выкидывая неправильные IP адреса.
Выбирается подсеть, в которой присутствует указанный минимум адресов.
Для ipv4 минимум задается как процент от размера подсети (mul/div. например, 3/4), для ipv6 минимум задается напрямую.
Размер подсети выбирается следующим алгоритмом:
Сначала в указанном диапазоне длин префиксов ищутся подсети, в которых количество адресов - максимально.
Если таких сетей найдено несколько, берется наименьшая сеть (префикс больше).
Например, заданы параметры v6_threshold=2 prefix_length=32-64, имеются следующие ipv6 :
```
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
Результат будет :
1234:5678:aaa8::/45
```
Эти адреса так же входят в подсеть /32. Однако, нет смысла проходиться ковровой бомбардировкой,
когда те же самые адреса вполне влезают в /45 и их ровно столько же.
Если изменить v6_threshold=4, то результат будет:
```
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
```
То есть ip не объединятся в подсеть, потому что их слишком мало.
Если изменить `prefix_length=56-64`, результат будет:
```
1234:5678:aaaa::/64
1234:5678:aaac::5
```
Требуемое процессорное время для вычислений сильно зависит от ширины диапазона длин префиксов, размера искомых подсетей и длины листа.
Если ip2net думает слишком долго, не используйте слишком большие подсети и уменьшите диапазон длин префиксов.
Учтите, что арифметика mul/div - целочисленная. При превышении разрядной сетки 32 bit результат непредсказуем.
Не надо делать такое: 5000000/10000000. 1/2 - гораздо лучше.
## mdig
Программа предназначена для многопоточного ресолвинга больших листов через системный DNS.
Она берет из stdin список доменов и выводит в stdout результат ресолвинга. Ошибки выводятся в stderr.
```
--threads=<threads_number> ; количество потоков. по умолчанию 1.
--family=<4|6|46> ; выбор семейства IP адресов : ipv4, ipv6, ipv4+ipv6
--verbose ; дебаг-лог на консоль
--stats=N ; выводить статистику каждые N доменов
--log-resolved=<file> ; сохранять успешно отресолвленные домены в файл
--log-failed=<file> ; сохранять неудачно отресолвленные домены в файл
--dns-make-query=<domain> ; вывести в stdout бинарный DNS запрос по домену. если --family=6, запрос будет AAAA, иначе A.
--dns-parse-query ; распарсить бинарный DNS ответ и выдать все ivp4 и ipv6 адреса из него в stdout
```
Параметры `--dns-make-query` и `--dns-parse-query` позволяют провести ресолвинг одного домена через произвольный канал.
Например, следующим образом можно выполнить DoH запрос, используя лишь mdig и curl :
```
mdig --family=6 --dns-make-query=rutracker.org | curl --data-binary @- -H "Content-Type: application/dns-message" https://cloudflare-dns.com/dns-query | mdig --dns-parse-query
```
## Фильтрация по именам доменов
Альтернативой ipset является использование tpws или nfqws со списком доменов.
@@ -1308,7 +1336,8 @@ ipset/get_refilter_domains.sh
```
Он кладется в `ipset/zapret-hosts.txt.gz`.
При изменении времени модификации файлов списки перечитываются автоматически.
При изменении времени модификации или размера файлов списки перечитываются автоматически.
После неатомарных операций изменения можно послать tpws/nfqws сигнал HUP для принудительной перечитки всех листов.
При фильтрации по именам доменов демон должен запускаться без фильтрации по ipset.
tpws и nfqws решают нужно ли применять дурение в зависимости от хоста, полученного из протокола прикладного уровня (http, tls, quic).
@@ -1432,11 +1461,22 @@ linux, но через раз приобретает статус INVALID в con
CURL - замена программы curl
CURL_MAX_TIME - время таймаута curl в секундах
CURL_MAX_TIME_QUIC - время таймаута curl для quic. если не задано, используется значение CURL_MAX_TIME
CURL_MAX_TIME_DOH - время таймаута curl для DoH серверов
CURL_CMD=1 - показывать команды curl
CURL_OPT - дополнительные параметры curl. `-k` - игнор сертификатов. `-v` - подробный вывод протокола
DOMAINS - список тестируемых доменов через пробел
IPVS=4|6|46 - тестируемые версии ip протокола
ENABLE_HTTP=0|1 - включить тест plain http
ENABLE_HTTPS_TLS12=0|1 - включить тест https TLS 1.2
ENABLE_HTTPS_TLS13=0|1 - включить тест https TLS 1.3
ENABLE_HTTP3=0|1 - включить тест QUIC
REPEATS - количество попыток тестирования
PARALLEL=0|1 - включить параллельные попытки. может обидеть сайт из-за долбежки и привести к неверному результату
SCANLEVEL=quick|standard|force - уровень сканирования
BATCH=1 - пакетный режим без вопросов и ожидания ввода в консоли
HTTP_PORT, HTTPS_PORT, QUIC_PORT - номера портов для соответствующих протоколов
SKIP_DNSCHECK=1 - отказ от проверки DNS
SKIP_IPBLOCK=1 - отказ от тестов блокировки по порту или IP
SKIP_TPWS=1 - отказ от тестов tpws
SKIP_PKTWS=1 - отказ от тестов nfqws/dvtws/winws
PKTWS_EXTRA, TPWS_EXTRA - дополнительные параметры nfqws/dvtws/winws и tpws
@@ -1444,13 +1484,14 @@ PKTWS_EXTRA_1 .. PKTWS_EXTRA_9, TPWS_EXTRA_1 .. TPWS_EXTRA_9 - отдельно
SECURE_DNS=0|1 - принудительно выключить или включить DoH
DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера
DOH_SERVER - конкретный DoH URL, отказ от поиска
UNBLOCKED_DOM - незаблокированный домен, который используется для тестов IP block
```
Пример запуска с переменными:\
`SECURE_DNS=1 SKIP_TPWS=1 CURL_MAX_TIME=1 CURL=/tmp/curl ./blockcheck.sh`
**СКАН ПОРТОВ**\
Если в системе присутствует совместимый `netcat` (ncat от nmap или openbsd ncat. в openwrt по умолчанию нет),
Если в системе присутствует совместимый `netcat` (ncat от nmap или openbsd ncat. в OpenWrt по умолчанию нет),
то выполняется сканирование портов http или https всех IP адресов домена.
Если ни один IP не отвечает, то результат очевиден. Можно останавливать сканирование.
Автоматически оно не остановится, потому что netcat-ы недостаточно подробно информируют о причинах ошибки.
@@ -1557,7 +1598,7 @@ curl: (28) Connection timed out after 2002 milliseconds
На linux системах можно выбрать использовать `iptables` или `nftables`.
По умолчанию на традиционных linux выбирается `nftables`, если установлен nft.
На openwrt по умолчанию выбирается `nftables` на новых версиях с firewall4.
На OpenWrt по умолчанию выбирается `nftables` на новых версиях с firewall4.
`FWTYPE=iptables`
@@ -1706,7 +1747,7 @@ DISABLE_IPV6=1
```
Количество потоков для многопоточного DNS ресолвера mdig (1..100).
Чем их больше, тем быстрее, но не обидится ли на долбежку ваш DNS сервер?\
Чем их больше, тем быстрее, но не обидется ли на долбежку ваш DNS сервер?\
`MDIG_THREADS=30`
Место для хранения временных файлов. При скачивании огромных реестров в `/tmp` места может не хватить.
@@ -1768,11 +1809,11 @@ LISTS_RELOAD="pfctl -f /etc/pf.conf"
LISTS_RELOAD=-
```
В openwrt существует сеть по умолчанию 'lan'. Только трафик с этой сети будет перенаправлен на tpws.
В OpenWrt существует сеть по умолчанию 'lan'. Только трафик с этой сети будет перенаправлен на tpws.
Но возможно задать другие сети или список сетей:\
`OPENWRT_LAN="lan lan2 lan3"`
В openwrt в качестве wan берутся интерфейсы, имеющие default route. Отдельно для ipv4 и ipv6.
В OpenWrt в качестве wan берутся интерфейсы, имеющие default route. Отдельно для ipv4 и ipv6.
Это можно переопределить:
```
OPENWRT_WAN4="wan4 vpn"
@@ -1782,7 +1823,7 @@ OPENWRT_WAN6="wan6 vpn6"
Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables.\
При иных значениях или если параметр закомментирован, правила применены не будут.\
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.\
На openwrt неприменимо при использовании firewall3+iptables.
На OpenWrt неприменимо при использовании firewall3+iptables.
***Следующие настройки не актуальны для openwrt:***
@@ -1836,7 +1877,7 @@ _Для `nftables` предусмотрено несколько дополни
Обновить set-ы интерфейсов, относящихся к lan, wan и wan6.
Для традиционных linux список интерфейсов берется из переменных конфига IFACE_LAN, IFACE_WAN.
Для openwrt определяется автоматически. Множество lanif может быть расширено параметром OPENWRT_LAN.
Для OpenWrt определяется автоматически. Множество lanif может быть расширено параметром OPENWRT_LAN.
Все интерфейсы lan и wan так же добавляются в ingress hook от flow table.\
`/opt/zapret/init.d/sysv/zapret reload_ifsets`
@@ -1888,7 +1929,7 @@ zapret_custom_firewall_v6
zapret_custom_daemons поднимает демоны **nfqws**/**tpws** в нужном вам количестве и с нужными вам параметрами.
В первом параметре передается код операции: 1 = запуск, 0 = останов.
Схема запуска демонов в openwrt отличается - используется procd.
Схема запуска демонов в OpenWrt отличается - используется procd.
Поэтому логика останова отсутствует за ненадобностью, останов никогда не вызывается.
zapret_custom_firewall поднимает и убирает правила `iptables`.
@@ -1930,7 +1971,7 @@ zapret_custom_firewall_nft поднимает правила nftables.
## Простая установка
`install_easy.sh` автоматизирует ручные варианты процедур установки.
Он поддерживает OpenWRT, linux системы на базе systemd или openrc и MacOS.
Он поддерживает OpenWrt, linux системы на базе systemd или openrc и MacOS.
Для более гибкой настройки перед запуском инсталлятора следует выполнить раздел "Выбор параметров".
@@ -1947,7 +1988,7 @@ zapret_custom_firewall_nft поднимает правила nftables.
`install_easy.sh make`
Под openwrt все уже сразу готово для использования системы в качестве роутера.
Под OpenWrt все уже сразу готово для использования системы в качестве роутера.
Имена интерфейсов WAN и LAN известны из настроек системы.
Под другими системами роутер вы настраиваете самостоятельно. Инсталлятор в это не вмешивается.
инсталлятор в зависимости от выбранного режима может спросить LAN и WAN интерфейсы.
@@ -2072,17 +2113,18 @@ adb push tpws /data/local/tmp/zapret
chmod 755 /data/local/tmp/zapret /data/local/tmp/zapret/tpws
chcon u:object_r:system_file:s0 /data/local/tmp/zapret/tpws
```
Как найти стратегию обхода сотового оператора: проще всего раздать инет на комп с linux.
Можно записать live image linux на флэшку и загрузиться с нее или запустить виртуалку с linux
и пробросить в нее usb устройство от режима модема с телефона.
На компе с linux прогнать стандартную процедуру blockcheck. При переносе правил на телефон уменьшить TTL на 1,
если правила с TTL присутствуют в стратегии.
Можно развернуть rootfs какого-нибудь дистрибутива linux прямо на телефоне, имея рута.
Как найти стратегию обхода сотового оператора: проще всего раздать инет на комп.
Для этого подойдет любая поддерживаемая ОС. Подключите android через USB кабель к компу и включите режим модема.
Прогоните стандартную процедуру blockcheck. При переносе правил на телефон уменьшить TTL на 1,
если правила с TTL присутствуют в стратегии. Если проверялось на windows, убрать параметры `--wf-*`.
Работа blockcheck в android shell не поддерживается, но имея рута можно развернуть rootfs какого-нибудь дистрибутива linux.
Это лучше всего делать с компа через adb shell.
Если компа нет, то это единственный вариант, хотя и неудобный.
Подойдет что-то легковесное, например, alpine или даже openwrt.
Если компа нет, то развертка chroot - единственный вариант, хотя и неудобный.
Подойдет что-то легковесное, например, alpine или даже OpenWrt.
Если это не эмулятор android, то универсальная архитектура - arm (любой вариант).
Если вы точно знаете, что ОС у вас 64-разрядная, то лучше вместо arm - aarch64.
Выяснить архитектуру можно командой `uname -a`.
```
mount --bind /dev /data/linux/dev
@@ -2223,10 +2265,10 @@ entware содержит репозиторий user-mode компонент, к
одробное описание настроек для других прошивок выходит за рамки данного проекта._
Openwrt является одной из немногих относительно полноценных linux систем для embedded devices.
OpenWrt является одной из немногих относительно полноценных linux систем для embedded devices.
Она характеризуется следующими вещами, которые и послужили основой выбора именно этой прошивк:
* полный root доступ к девайсу через shell. на заводских прошивках чаще всего отсутствует, на многих альтернативных есть
* корень r/w. это практически уникальная особенность openwrt. заводские и большинство альтернативных прошивок
* корень r/w. это практически уникальная особенность OpenWrt. заводские и большинство альтернативных прошивок
построены на базе squashfs root (r/o), а конфигурация хранится в специально отформатированной области
встроенной памяти, называемой nvram. не имеющие r/w корня системы сильно кастрированы. они не имеют
возможности доустановки ПО из репозитория без специальных вывертов и заточены в основном
@@ -2247,45 +2289,45 @@ Openwrt является одной из немногих относительн
Если не работает автономный обход, приходится перенаправлять трафик через сторонний хост.
Предлагается использовать прозрачный редирект через socks5 посредством `iptables+redsocks`, либо `iptables+iproute+vpn`.
Настройка варианта с redsocks на openwrt описана в [redsocks.txt](./redsocks.txt).
Настройка варианта с redsocks на OpenWrt описана в [redsocks.txt](./redsocks.txt).
Настройка варианта с `iproute+wireguard` - в [wireguard_iproute_openwrt.txt](./wireguard_iproute_openwrt.txt).
## Почему стоит вложиться в покупку VPS
VPS - это виртуальный сервер. Существует огромное множество датацентров, предлагающих данную услугу.
На VPS могут выполняться какие угодно задачи. От простого веб сайта до навороченной системы собственной разработки.
Можно использовать VPS и для поднятия собственного vpn или прокси.
Сама широта возможных способов применения, распространенность услуги сводят к минимуму возможности
VPS это виртуальный сервер. Существует огромное множество датацентров, предлагающих данную услугу.
На VPS могут выполняться какие угодно задачи. От простого веб-сайта до навороченной системы собственной разработки.
Можно использовать VPS и для поднятия собственного VPN или прокси.
Сама широта возможных способов применения и распространенность услуги сводят к минимуму возможности
регуляторов по бану сервисов такого типа. Да, если введут белые списки, то решение загнется, но это будет уже другая
реальность, в которой придется изобретать иные решения.
Пока этого не сделали, никто не будет банить хостинги просто потому, что они предоставляют хостинг услуги.
Вы как индивидуум скорее всего никому не нужны. Подумайте чем вы отличаетесь от известного VPN провайдера.
VPN провайдер предоставляет _простую_ и оступную_ услугу по обходу блокировок для масс.
Вы, как индивидуум, скорее всего, никому не нужны. Подумайте чем вы отличаетесь от известного VPN провайдера.
VPN-провайдер предоставляет _простую_ и оступную_ услугу по обходу блокировок для масс.
Этот факт делает его первоочередной целью блокировки. РКН направит уведомление, после отказа сотрудничать
заблокирует VPN. Предоплаченная сумма пропадет.
У регуляторов нет и никогда не будет ресурсов для тотальной проверки каждого сервера в сети.
Возможен китайский расклад, при котором DPI выявляет vpn протоколы и динамически банит IP серверов,
Возможен китайский расклад, при котором DPI выявляет VPN-протоколы и динамически банит IP серверов,
предоставляющих нелицензированный VPN. Но имея знания, голову, вы всегда можете обфусцировать
vpn трафик или применить другие типы VPN, более устойчивые к анализу на DPI или просто менее широкоизвестные,
VPN трафик или применить другие типы VPN, более устойчивые к анализу на DPI, или просто менее широкоизвестные,
а следовательно с меньшей вероятностью обнаруживаемые регулятором.
У вас есть свобода делать на вашем VPS все что вы захотите, адаптируясь к новым условиям.
Да, это потребует знаний. Вам выбирать учиться и держать ситуацию под контролем, когда вам ничего запретить
не могут, или покориться системе.
VPS можно прибрести в множестве мест. Существуют специализированные на поиске предложений VPS порталы.\
VPS можно приобрести в множестве мест. Существуют специализированные на поиске предложений VPS порталы.\
Например, [вот этот](https://vps.today).
Для персонального VPN сервера обычно достаточно самой минимальной конфигурации, но с безлимитным трафиком или
с большим лимитом по трафику (терабайты). Важен и тип VPS. Openvz подойдет для openvpn, но
вы не поднимете на нем wireguard, ipsec, то есть все, что требует kernel mode.
с большим лимитом по трафику (терабайты). Важен и тип VPS. OpenVZ подойдёт для OpenVPN, но
вы не поднимете на нем WireGuard, IPsec, то есть все, что требует kernel mode.
Для kernel mode требуется тип виртуализации, предполагающий запуск полноценного экземпляра ОС linux
вместе с ядром. Подойдут kvm, xen, hyper-v, vmware.
вместе с ядром. Подойдут KVM, Xen, Hyper-V, VMware.
По цене можно найти предложения, которые будут дешевле готовой VPN услуги, но при этом вы сам хозяин в своей лавке
и не рискуете попасть под бан регулятора, разве что "заодно" под ковровую бомбардировку с баном миллионов IP.
и не рискуете попасть под бан регулятора, разве что «заодно» — под ковровую бомбардировку с баном миллионов IP.
Кроме того, если вам совсем все кажется сложным, прочитанное вызывает ступор и вы точно знаете, что ничего
из описанного сделать не сможете, то вы сможете хотя бы использовать динамическое перенаправление портов ssh
для получения шифрованного socks proxy и прописать его в броузер. Знания linux не нужны совсем.
из описанного сделать не сможете, то вы сможете хотя бы использовать динамическое перенаправление портов SSH
для получения шифрованного SOCKS-прокси и прописать его в браузер. Знания linux не нужны совсем.
Это вариант наименее напряжный для чайников, хотя и не самый удобный в использовании.
## Поддержать разработчика

View File

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

View File

@@ -90,13 +90,6 @@ TPWS_WAIT_SOCKS6="$TPWS_WAIT --bind-wait-ip-linklocal=30"
# first wait for lan to ifup, then wait for bind-wait-ip-linklocal seconds for link local address and bind-wait-ip for any ipv6 as the worst case
TPWS_OPT_BASE6_PRE="--bind-linklocal=prefer $TPWS_WAIT --bind-wait-ip-linklocal=3"
# max wait time for the link local ipv6 on the LAN interface
LINKLOCAL_WAIT_SEC=5
IPSET_EXCLUDE="-m set ! --match-set nozapret"
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
dnat6_target()
{
_dnat6_target "$@"

View File

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

View File

@@ -70,7 +70,7 @@ check_bins()
elif [ -f "$EXEDIR/Makefile" ] && exists make; then
echo trying to compile
[ "$SYSTEM" = "macos" ] && make_target=mac
make -C "$EXEDIR" $make_target || {
CFLAGS="-march=native ${CFLAGS}" make -C "$EXEDIR" $make_target || {
echo could not compile
make -C "$EXEDIR" clean
exitp 8
@@ -292,7 +292,7 @@ ask_config_tmpdir()
echo default tmpfs has size of 50% RAM
echo "RAM : $(get_ram_mb) Mb"
echo "DISK : $(get_free_space_mb) Mb"
echo select temp file location
echo select temp file location
[ -z "$TMPDIR" ] && TMPDIR=/tmp
ask_list TMPDIR "/tmp $EXEDIR/tmp" && {
[ "$TMPDIR" = "/tmp" ] && TMPDIR=
@@ -388,7 +388,7 @@ copy_openwrt()
local ARCH="$(get_bin_arch)"
local BINDIR="$1/binaries/$ARCH"
local file
[ -d "$2" ] || mkdir -p "$2"
mkdir "$2/tpws" "$2/nfq" "$2/ip2net" "$2/mdig" "$2/binaries" "$2/binaries/$ARCH" "$2/init.d" "$2/tmp" "$2/files"
@@ -482,7 +482,7 @@ _restore_settings()
[ -z "$f" -o "$f" = "/" ] && continue
[ -f "/tmp/zapret-bkp-$i" ] && {
mv -f "/tmp/zapret-bkp-$i" "$ZAPRET_TARGET/$f" || rm -f "/tmp/zapret-bkp-$i"
mv -f "/tmp/zapret-bkp-$i" "$ZAPRET_TARGET/$f" || rm -f "/tmp/zapret-bkp-$i"
}
[ -d "/tmp/zapret-bkp-$i" ] && {
[ -d "$ZAPRET_TARGET/$f" ] && rm -r "$ZAPRET_TARGET/$f"
@@ -724,7 +724,7 @@ install_linux()
crontab_del_quiet
# desktop system. more likely up at daytime
crontab_add 10 22
echo
echo '!!! WARNING. YOUR SETUP IS INCOMPLETE !!!'
echo you must manually add to auto start : $INIT_SCRIPT_SRC start
@@ -772,7 +772,6 @@ deoffload_openwrt_firewall()
else
echo system wide software flow offloading disabled. ok
fi
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,11 +27,8 @@ static void connswap(const t_conn *c, t_conn *c2)
void ConntrackClearHostname(t_ctrack *track)
{
if (track->hostname)
{
free(track->hostname);
track->hostname = NULL;
}
free(track->hostname);
track->hostname = NULL;
}
static void ConntrackClearTrack(t_ctrack *track)
{
@@ -349,11 +346,8 @@ void ConntrackPoolDump(const t_conntrack *p)
void ReasmClear(t_reassemble *reasm)
{
if (reasm->packet)
{
free(reasm->packet);
reasm->packet = NULL;
}
free(reasm->packet);
reasm->packet = NULL;
reasm->size = reasm->size_present = 0;
}
bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start)

View File

@@ -63,16 +63,6 @@ const uint8_t fake_tls_clienthello_default[648] = {
0x84,0x66,0x6b,0xec,0xc7,0xed,0xbc,0xe4
};
static const char * tld[]={"com","org","net","edu","gov","biz"};
void randomize_default_tls_payload(uint8_t *p)
{
fill_random_bytes(p+11,32);
fill_random_bytes(p+44,32);
fill_random_az(p+125,1);
fill_random_az09(p+126,5);
memcpy(p+132,tld[random()%(sizeof(tld)/sizeof(*tld))],3);
}
#define PKTDATA_MAXDUMP 32
#define IP_MAXDUMP 80
@@ -364,10 +354,11 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
}
if (!append_to_list_file(dp->hostlist_auto->filename, hostname))
{
DLOG_PERROR("write to auto hostlist:");
DLOG_PERROR("write to auto hostlist");
return;
}
dp->hostlist_auto->mod_time = file_mod_time(dp->hostlist_auto->filename);
if (!file_mod_signature(dp->hostlist_auto->filename, &dp->hostlist_auto->mod_sig))
DLOG_PERROR("file_mod_signature");
}
else
{
@@ -612,6 +603,53 @@ static uint16_t IP4_IP_ID_FIX(const struct ip *ip)
#endif
// fake_mod buffer must at least sizeof(desync_profile->fake_tls)
// size does not change
// return : true - altered, false - not altered
static bool runtime_tls_mod(const struct desync_profile *dp, uint8_t *fake_mod, const uint8_t *payload, size_t payload_len)
{
bool b=false;
if (dp->fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
{
size_t sz_rec = pntoh16(dp->fake_tls+3) + payload_len;
size_t sz_handshake = pntoh24(dp->fake_tls+6) + payload_len;
size_t sz_ext = pntoh16(dp->fake_tls+dp->fake_tls_extlen_offset) + payload_len;
size_t sz_pad = pntoh16(dp->fake_tls+dp->fake_tls_padlen_offset) + payload_len;
if ((sz_rec & ~0xFFFF) || (sz_handshake & ~0xFFFFFF) || (sz_ext & ~0xFFFF) || (sz_pad & ~0xFFFF))
DLOG("cannot apply padencap tls mod. length overflow.\n");
else
{
memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size);
phton16(fake_mod+3,(uint16_t)sz_rec);
phton24(fake_mod+6,(uint32_t)sz_handshake);
phton16(fake_mod+dp->fake_tls_extlen_offset,(uint16_t)sz_ext);
phton16(fake_mod+dp->fake_tls_padlen_offset,(uint16_t)sz_pad);
b=true;
}
}
if (dp->fake_tls_mod & FAKE_TLS_MOD_RND)
{
if (!b) memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size);
fill_random_bytes(fake_mod+11,32); // random
fill_random_bytes(fake_mod+44,fake_mod[43]); // session id
b=true;
}
if (dp->fake_tls_mod & FAKE_TLS_MOD_DUP_SID)
{
if (dp->fake_tls[43]!=payload[43])
DLOG("cannot apply dupsid tls mod. fake and orig session id length mismatch.\n");
else if (payload_len<(44+payload[43]))
DLOG("cannot apply dupsid tls mod. data payload is not valid.\n");
else
{
if (!b) memcpy(fake_mod,dp->fake_tls,dp->fake_tls_size);
memcpy(fake_mod+44,payload+44,fake_mod[43]); // session id
b=true;
}
}
return b;
}
static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint32_t fwmark, const char *ifout, struct dissect *dis)
{
uint8_t verdict=VERDICT_PASS;
@@ -855,6 +893,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
int i;
uint16_t ip_id;
t_l7proto l7proto = UNKNOWN;
uint8_t fake_mod[sizeof(dp->fake_tls)];
if (replay)
{
@@ -1148,7 +1187,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
fake_size = dp->fake_http_size;
break;
case TLS:
fake = dp->fake_tls;
fake = runtime_tls_mod(dp,fake_mod,rdata_payload,rlen_payload) ? fake_mod : dp->fake_tls;
fake_size = dp->fake_tls_size;
break;
default:
@@ -1327,7 +1366,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
// do seqovl only to the first packet
// otherwise it's prone to race condition on server side
// what happens first : server pushes socket buffer to process or another packet with seqovl arrives
seqovl = i==0 ? seqovl_pos : 0;
seqovl = (i==0 && reasm_offset==0) ? seqovl_pos : 0;
#ifdef __linux__
// only linux return error if MTU is exceeded
for(;;seqovl=0)
@@ -1573,7 +1612,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
return verdict;
unsigned int seqovl = seqovl_pos;
unsigned int seqovl = reasm_offset ? 0 : seqovl_pos;
#ifdef __linux__
// only linux return error if MTU is exceeded
for(;;seqovl=0)

View File

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

View File

@@ -9,6 +9,7 @@
#include <ctype.h>
#include <sys/stat.h>
#include <libgen.h>
#include <fcntl.h>
int unique_size_t(size_t *pu, int ct)
{
@@ -300,6 +301,29 @@ time_t file_mod_time(const char *filename)
struct stat st;
return stat(filename,&st)==-1 ? 0 : st.st_mtime;
}
bool file_mod_signature(const char *filename, file_mod_sig *ms)
{
struct stat st;
if (stat(filename,&st)==-1)
{
FILE_MOD_RESET(ms);
return false;
}
ms->mod_time=st.st_mtime;
ms->size=st.st_size;
return true;
}
bool file_open_test(const char *filename, int flags)
{
int fd = open(filename,flags);
if (fd>=0)
{
close(fd);
return true;
}
return false;
}
bool pf_in_range(uint16_t port, const port_filter *pf)
{

View File

@@ -51,6 +51,14 @@ static inline void phton16(uint8_t *p, uint16_t v) {
p[0] = (uint8_t)(v >> 8);
p[1] = v & 0xFF;
}
static inline uint32_t pntoh24(const uint8_t *p) {
return ((uint32_t)p[0] << 16) | ((uint32_t)p[1] << 8) | (uint32_t)p[2];
}
static inline void phton24(uint8_t *p, uint32_t v) {
p[0] = (uint8_t)(v>>16);
p[1] = (uint8_t)(v>>8);
p[2] = (uint8_t)v;
}
static inline uint32_t pntoh32(const uint8_t *p) {
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
}
@@ -60,7 +68,16 @@ void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize
int fprint_localtime(FILE *F);
typedef struct
{
time_t mod_time;
off_t size;
} file_mod_sig;
#define FILE_MOD_COMPARE(ms1,ms2) (((ms1)->mod_time==(ms2)->mod_time) && ((ms1)->size==(ms2)->size))
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
bool file_mod_signature(const char *filename, file_mod_sig *ms);
time_t file_mod_time(const char *filename);
bool file_open_test(const char *filename, int flags);
typedef struct
{

View File

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

View File

@@ -13,3 +13,5 @@ bool HostlistCheck(const struct desync_profile *dp,const char *host, bool *exclu
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename);
bool HostlistsReloadCheckForProfile(const struct desync_profile *dp);
void HostlistsDebug();
#define ResetAllHostlistsModTime() hostlist_files_reset_modtime(&params.hostlists)

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -186,7 +186,7 @@ void dp_init(struct desync_profile *dp)
dp->desync_repeats = 1;
dp->fake_tls_size = sizeof(fake_tls_clienthello_default);
memcpy(dp->fake_tls,fake_tls_clienthello_default,dp->fake_tls_size);
randomize_default_tls_payload(dp->fake_tls);
dp->fake_tls_mod = 0;
dp->fake_http_size = strlen(fake_http_request_default);
memcpy(dp->fake_http,fake_http_request_default,dp->fake_http_size);
dp->fake_quic_size = 620; // must be 601+ for TSPU hack

View File

@@ -38,6 +38,14 @@
#define MAX_SPLITS 64
#define FAKE_TLS_MOD_SAVE_MASK 0x0F
#define FAKE_TLS_MOD_SET 0x01
#define FAKE_TLS_MOD_CUSTOM_FAKE 0x02
#define FAKE_TLS_MOD_RND 0x10
#define FAKE_TLS_MOD_DUP_SID 0x20
#define FAKE_TLS_MOD_RND_SNI 0x40
#define FAKE_TLS_MOD_PADENCAP 0x80
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
struct desync_profile
@@ -66,9 +74,13 @@ struct desync_profile
autottl desync_autottl, desync_autottl6;
uint32_t desync_fooling_mode;
uint32_t desync_badseq_increment, desync_badseq_ack_increment;
uint8_t fake_http[1460],fake_tls[1460],fake_unknown[1460],fake_syndata[1460],seqovl_pattern[1460],fsplit_pattern[1460];
uint8_t fake_http[1460],fake_unknown[1460],fake_syndata[1460],seqovl_pattern[1460],fsplit_pattern[1460];
uint8_t fake_unknown_udp[1472],udplen_pattern[1472],fake_quic[1472],fake_wg[1472],fake_dht[1472];
size_t fake_http_size,fake_tls_size,fake_quic_size,fake_wg_size,fake_dht_size,fake_unknown_size,fake_syndata_size,fake_unknown_udp_size;
size_t fake_http_size,fake_quic_size,fake_wg_size,fake_dht_size,fake_unknown_size,fake_syndata_size,fake_unknown_udp_size;
uint8_t fake_tls[1460],fake_tls_mod;
size_t fake_tls_size, fake_tls_extlen_offset, fake_tls_padlen_offset;
int udplen_increment;
bool filter_ipv4,filter_ipv6;

View File

@@ -139,7 +139,7 @@ bool strlist_add(struct str_list_head *head, const char *filename)
}
static void strlist_entry_destroy(struct str_list *entry)
{
if (entry->str) free(entry->str);
free(entry->str);
free(entry);
}
void strlist_destroy(struct str_list_head *head)
@@ -154,7 +154,6 @@ void strlist_destroy(struct str_list_head *head)
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename)
{
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
@@ -170,7 +169,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
}
else
entry->filename = NULL;
entry->mod_time = 0;
FILE_MOD_RESET(&entry->mod_sig);
entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next);
}
@@ -178,7 +177,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
}
static void hostlist_files_entry_destroy(struct hostlist_file *entry)
{
if (entry->filename) free(entry->filename);
free(entry->filename);
StrPoolDestroy(&entry->hostlist);
free(entry);
}
@@ -202,6 +201,13 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
}
return NULL;
}
void hostlist_files_reset_modtime(struct hostlist_files_head *list)
{
struct hostlist_file *hfile;
LIST_FOREACH(hfile, list, next)
FILE_MOD_RESET(&hfile->mod_sig);
}
struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile)
{
@@ -384,7 +390,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
}
else
entry->filename = NULL;
entry->mod_time = 0;
FILE_MOD_RESET(&entry->mod_sig);
memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next);
}
@@ -392,7 +398,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
}
static void ipset_files_entry_destroy(struct ipset_file *entry)
{
if (entry->filename) free(entry->filename);
free(entry->filename);
ipsetDestroy(&entry->ipset);
free(entry);
}
@@ -416,6 +422,13 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
}
return NULL;
}
void ipset_files_reset_modtime(struct ipset_files_head *list)
{
struct ipset_file *hfile;
LIST_FOREACH(hfile, list, next)
FILE_MOD_RESET(&hfile->mod_sig);
}
struct ipset_item *ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile)
{

View File

@@ -50,7 +50,7 @@ void strlist_destroy(struct str_list_head *head);
struct hostlist_file {
char *filename;
time_t mod_time;
file_mod_sig mod_sig;
strpool *hostlist;
LIST_ENTRY(hostlist_file) next;
};
@@ -59,6 +59,7 @@ LIST_HEAD(hostlist_files_head, hostlist_file);
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename);
void hostlist_files_destroy(struct hostlist_files_head *head);
struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, const char *filename);
void hostlist_files_reset_modtime(struct hostlist_files_head *list);
struct hostlist_item {
struct hostlist_file *hfile;
@@ -111,7 +112,7 @@ void ipsetPrint(ipset *ipset);
struct ipset_file {
char *filename;
time_t mod_time;
file_mod_sig mod_sig;
ipset ipset;
LIST_ENTRY(ipset_file) next;
};
@@ -120,6 +121,7 @@ LIST_HEAD(ipset_files_head, ipset_file);
struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *filename);
void ipset_files_destroy(struct ipset_files_head *head);
struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char *filename);
void ipset_files_reset_modtime(struct ipset_files_head *list);
struct ipset_item {
struct ipset_file *hfile;

View File

@@ -2,6 +2,8 @@
#include "protocol.h"
#include "helpers.h"
#include "params.h"
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
@@ -371,6 +373,46 @@ bool IsTLSHandshakeFull(const uint8_t *data, size_t len)
}
bool TLSFindExtLenOffsetInHandshake(const uint8_t *data, size_t len, size_t *off)
{
// +0
// u8 HandshakeType: ClientHello
// u24 Length
// u16 Version
// c[32] random
// u8 SessionIDLength
// <SessionID>
// u16 CipherSuitesLength
// <CipherSuites>
// u8 CompressionMethodsLength
// <CompressionMethods>
// u16 ExtensionsLength
size_t l;
l = 1 + 3 + 2 + 32;
// SessionIDLength
if (len < (l + 1)) return false;
l += data[l] + 1;
// CipherSuitesLength
if (len < (l + 2)) return false;
l += pntoh16(data + l) + 2;
// CompressionMethodsLength
if (len < (l + 1)) return false;
l += data[l] + 1;
// ExtensionsLength
if (len < (l + 2)) return false;
*off = l;
return true;
}
bool TLSFindExtLen(const uint8_t *data, size_t len, size_t *off)
{
if (!TLSFindExtLenOffsetInHandshake(data+5,len-5,off))
return false;
*off+=5;
return true;
}
// bPartialIsOK=true - accept partial packets not containing the whole TLS message
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK)
{
@@ -391,18 +433,7 @@ bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const
if (!bPartialIsOK && !IsTLSHandshakeFull(data,len)) return false;
l = 1 + 3 + 2 + 32;
// SessionIDLength
if (len < (l + 1)) return false;
l += data[l] + 1;
// CipherSuitesLength
if (len < (l + 2)) return false;
l += pntoh16(data + l) + 2;
// CompressionMethodsLength
if (len < (l + 1)) return false;
l += data[l] + 1;
// ExtensionsLength
if (len < (l + 2)) return false;
if (!TLSFindExtLenOffsetInHandshake(data,len,&l)) return false;
data += l; len -= l;
l = pntoh16(data);
@@ -449,7 +480,7 @@ bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **
if (reclen<len) len=reclen; // correct len if it has more data than the first tls record has
return TLSFindExtInHandshake(data + 5, len - 5, type, ext, len_ext, bPartialIsOK);
}
static bool TLSAdvanceToHostInSNI(const uint8_t **ext, size_t *elen, size_t *slen)
bool TLSAdvanceToHostInSNI(const uint8_t **ext, size_t *elen, size_t *slen)
{
// u16 data+0 - name list length
// u8 data+2 - server name type. 0=host_name
@@ -507,7 +538,7 @@ size_t TLSPos(uint8_t posmarker, int16_t pos, const uint8_t *data, size_t sz)
case PM_HOST_MIDSLD:
case PM_HOST_ENDSLD:
case PM_SNI_EXT:
if (TLSFindExt(data,sz,0,&ext,&elen,false))
if (TLSFindExt(data,sz,0,&ext,&elen,TLS_PARTIALS_ENABLE))
{
if (posmarker==PM_SNI_EXT)
{
@@ -936,7 +967,7 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len)
{
return len==148 && data[0]==1 && data[1]==0 && data[2]==0 && data[3]==0;
return len==148 && data[0]==1;
}
bool IsDhtD1(const uint8_t *data, size_t len)
{

View File

@@ -62,6 +62,9 @@ bool IsTLSClientHello(const uint8_t *data, size_t len, bool bPartialIsOK);
size_t TLSHandshakeLen(const uint8_t *data);
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len);
bool IsTLSHandshakeFull(const uint8_t *data, size_t len);
bool TLSAdvanceToHostInSNI(const uint8_t **ext, size_t *elen, size_t *slen);
bool TLSFindExtLen(const uint8_t *data, size_t len, size_t *off);
bool TLSFindExtLenOffsetInHandshake(const uint8_t *data, size_t len, size_t *off);
bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);

View File

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

View File

@@ -11,6 +11,7 @@
#include <sys/stat.h>
#include <libgen.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef __ANDROID__
#include "andr/ifaddrs.h"
@@ -314,6 +315,29 @@ time_t file_mod_time(const char *filename)
struct stat st;
return stat(filename, &st) == -1 ? 0 : st.st_mtime;
}
bool file_mod_signature(const char *filename, file_mod_sig *ms)
{
struct stat st;
if (stat(filename,&st)==-1)
{
FILE_MOD_RESET(ms);
return false;
}
ms->mod_time=st.st_mtime;
ms->size=st.st_size;
return true;
}
bool file_open_test(const char *filename, int flags)
{
int fd = open(filename,flags);
if (fd>=0)
{
close(fd);
return true;
}
return false;
}
bool pf_in_range(uint16_t port, const port_filter *pf)
{

View File

@@ -62,7 +62,16 @@ static inline void phton16(uint8_t *p, uint16_t v) {
int fprint_localtime(FILE *F);
typedef struct
{
time_t mod_time;
off_t size;
} file_mod_sig;
#define FILE_MOD_COMPARE(ms1,ms2) (((ms1)->mod_time==(ms2)->mod_time) && ((ms1)->size==(ms2)->size))
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
bool file_mod_signature(const char *filename, file_mod_sig *ms);
time_t file_mod_time(const char *filename);
bool file_open_test(const char *filename, int flags);
typedef struct
{

View File

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

View File

@@ -13,3 +13,5 @@ bool HostlistCheck(const struct desync_profile *dp,const char *host, bool *exclu
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename);
bool HostlistsReloadCheckForProfile(const struct desync_profile *dp);
void HostlistsDebug();
#define ResetAllHostlistsModTime() hostlist_files_reset_modtime(&params.hostlists)

View File

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

View File

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

View File

@@ -139,7 +139,7 @@ bool strlist_add(struct str_list_head *head, const char *filename)
}
static void strlist_entry_destroy(struct str_list *entry)
{
if (entry->str) free(entry->str);
free(entry->str);
free(entry);
}
void strlist_destroy(struct str_list_head *head)
@@ -169,7 +169,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
}
else
entry->filename = NULL;
entry->mod_time = 0;
FILE_MOD_RESET(&entry->mod_sig);
entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next);
}
@@ -177,7 +177,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
}
static void hostlist_files_entry_destroy(struct hostlist_file *entry)
{
if (entry->filename) free(entry->filename);
free(entry->filename);
StrPoolDestroy(&entry->hostlist);
free(entry);
}
@@ -201,6 +201,13 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
}
return NULL;
}
void hostlist_files_reset_modtime(struct hostlist_files_head *list)
{
struct hostlist_file *hfile;
LIST_FOREACH(hfile, list, next)
FILE_MOD_RESET(&hfile->mod_sig);
}
struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile)
{
@@ -383,7 +390,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
}
else
entry->filename = NULL;
entry->mod_time = 0;
FILE_MOD_RESET(&entry->mod_sig);
memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next);
}
@@ -391,7 +398,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
}
static void ipset_files_entry_destroy(struct ipset_file *entry)
{
if (entry->filename) free(entry->filename);
free(entry->filename);
ipsetDestroy(&entry->ipset);
free(entry);
}
@@ -415,6 +422,13 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
}
return NULL;
}
void ipset_files_reset_modtime(struct ipset_files_head *list)
{
struct ipset_file *hfile;
LIST_FOREACH(hfile, list, next)
FILE_MOD_RESET(&hfile->mod_sig);
}
struct ipset_item *ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile)
{

View File

@@ -50,7 +50,7 @@ void strlist_destroy(struct str_list_head *head);
struct hostlist_file {
char *filename;
time_t mod_time;
file_mod_sig mod_sig;
strpool *hostlist;
LIST_ENTRY(hostlist_file) next;
};
@@ -59,6 +59,7 @@ LIST_HEAD(hostlist_files_head, hostlist_file);
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename);
void hostlist_files_destroy(struct hostlist_files_head *head);
struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, const char *filename);
void hostlist_files_reset_modtime(struct hostlist_files_head *list);
struct hostlist_item {
struct hostlist_file *hfile;
@@ -111,7 +112,7 @@ void ipsetPrint(ipset *ipset);
struct ipset_file {
char *filename;
time_t mod_time;
file_mod_sig mod_sig;
ipset ipset;
LIST_ENTRY(ipset_file) next;
};
@@ -120,6 +121,7 @@ LIST_HEAD(ipset_files_head, ipset_file);
struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *filename);
void ipset_files_destroy(struct ipset_files_head *head);
struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char *filename);
void ipset_files_reset_modtime(struct ipset_files_head *list);
struct ipset_item {
struct ipset_file *hfile;

View File

@@ -443,7 +443,8 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
DLOG_PERROR("write to auto hostlist:");
return;
}
dp->hostlist_auto->mod_time = file_mod_time(dp->hostlist_auto->filename);
if (!file_mod_signature(dp->hostlist_auto->filename, &dp->hostlist_auto->mod_sig))
DLOG_PERROR("file_mod_signature");
}
else
{

View File

@@ -50,10 +50,31 @@
#define MAX_CONFIG_FILE_SIZE 16384
struct params_s params;
static bool bReload=false;
static void onhup(int sig)
{
printf("HUP received !\n");
printf("HUP received ! Lists will be reloaded.\n");
bReload=true;
}
void ReloadCheck()
{
if (bReload)
{
ResetAllHostlistsModTime();
if (!LoadAllHostLists())
{
DLOG_ERR("hostlists load failed. this is fatal.\n");
exit(1);
}
ResetAllIpsetModTime();
if (!LoadAllIpsets())
{
DLOG_ERR("ipset load failed. this is fatal.\n");
exit(1);
}
bReload=false;
}
}
static void onusr2(int sig)
@@ -95,6 +116,29 @@ static int8_t block_sigpipe(void)
return 0;
}
static bool test_list_files()
{
struct hostlist_file *hfile;
struct ipset_file *ifile;
printf("1\n");
LIST_FOREACH(hfile, &params.hostlists, next)
if (hfile->filename && !file_open_test(hfile->filename, O_RDONLY))
{
DLOG_PERROR("file_open_test");
DLOG_ERR("cannot access hostlist file '%s'\n",hfile->filename);
return false;
}
LIST_FOREACH(ifile, &params.ipsets, next)
if (ifile->filename && !file_open_test(ifile->filename, O_RDONLY))
{
DLOG_PERROR("file_open_test");
DLOG_ERR("cannot access ipset file '%s'\n",ifile->filename);
return false;
}
printf("2\n");
return true;
}
static bool is_interface_online(const char *ifname)
{
@@ -176,6 +220,7 @@ static void exithelp(void)
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
" --debug-level=0|1|2\t\t\t; specify debug level\n"
" --dry-run\t\t\t\t; verify parameters and exit with code 0 if successful\n"
" --version\t\t\t\t; print version and exit\n"
" --comment=any_text\n"
"\nMULTI-STRATEGY:\n"
" --new\t\t\t\t\t; begin new strategy\n"
@@ -670,41 +715,42 @@ void parse_params(int argc, char *argv[])
{ "debug",optional_argument,0,0 },// optidx=45
{ "debug-level",required_argument,0,0 },// optidx=46
{ "dry-run",no_argument,0,0 },// optidx=47
{ "comment",optional_argument,0,0 },// optidx=48
{ "local-rcvbuf",required_argument,0,0 },// optidx=49
{ "local-sndbuf",required_argument,0,0 },// optidx=50
{ "remote-rcvbuf",required_argument,0,0 },// optidx=51
{ "remote-sndbuf",required_argument,0,0 },// optidx=52
{ "socks",no_argument,0,0 },// optidx=53
{ "no-resolve",no_argument,0,0 },// optidx=54
{ "resolver-threads",required_argument,0,0 },// optidx=55
{ "skip-nodelay",no_argument,0,0 },// optidx=56
{ "tamper-start",required_argument,0,0 },// optidx=57
{ "tamper-cutoff",required_argument,0,0 },// optidx=58
{ "connect-bind-addr",required_argument,0,0 },// optidx=59
{ "version",no_argument,0,0 },// optidx=48
{ "comment",optional_argument,0,0 },// optidx=49
{ "local-rcvbuf",required_argument,0,0 },// optidx=50
{ "local-sndbuf",required_argument,0,0 },// optidx=51
{ "remote-rcvbuf",required_argument,0,0 },// optidx=52
{ "remote-sndbuf",required_argument,0,0 },// optidx=53
{ "socks",no_argument,0,0 },// optidx=54
{ "no-resolve",no_argument,0,0 },// optidx=55
{ "resolver-threads",required_argument,0,0 },// optidx=56
{ "skip-nodelay",no_argument,0,0 },// optidx=57
{ "tamper-start",required_argument,0,0 },// optidx=58
{ "tamper-cutoff",required_argument,0,0 },// optidx=59
{ "connect-bind-addr",required_argument,0,0 },// optidx=60
{ "new",no_argument,0,0 }, // optidx=60
{ "skip",no_argument,0,0 }, // optidx=61
{ "filter-l3",required_argument,0,0 }, // optidx=62
{ "filter-tcp",required_argument,0,0 }, // optidx=63
{ "filter-l7",required_argument,0,0 }, // optidx=64
{ "ipset",required_argument,0,0 }, // optidx=65
{ "ipset-ip",required_argument,0,0 }, // optidx=66
{ "ipset-exclude",required_argument,0,0 }, // optidx=67
{ "ipset-exclude-ip",required_argument,0,0 }, // optidx=68
{ "new",no_argument,0,0 }, // optidx=61
{ "skip",no_argument,0,0 }, // optidx=62
{ "filter-l3",required_argument,0,0 }, // optidx=63
{ "filter-tcp",required_argument,0,0 }, // optidx=64
{ "filter-l7",required_argument,0,0 }, // optidx=65
{ "ipset",required_argument,0,0 }, // optidx=66
{ "ipset-ip",required_argument,0,0 }, // optidx=67
{ "ipset-exclude",required_argument,0,0 }, // optidx=68
{ "ipset-exclude-ip",required_argument,0,0 }, // optidx=69
#if defined(__FreeBSD__)
{ "enable-pf",no_argument,0,0 },// optidx=69
#elif defined(__APPLE__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=69
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=70
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=79
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=71
#elif defined(__linux__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=69
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=70
{ "mss",required_argument,0,0 }, // optidx=71
{ "fix-seg",optional_argument,0,0 }, // optidx=72
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=70
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=71
{ "mss",required_argument,0,0 }, // optidx=72
{ "fix-seg",optional_argument,0,0 }, // optidx=73
#ifdef SPLICE_PRESENT
{ "nosplice",no_argument,0,0 }, // optidx=73
{ "nosplice",no_argument,0,0 }, // optidx=74
#endif
#endif
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
@@ -1155,43 +1201,46 @@ void parse_params(int argc, char *argv[])
case 47: /* dry-run */
bDry = true;
break;
case 48: /* comment */
case 48: /* version */
exit_clean(0);
break;
case 49: /* local-rcvbuf */
case 49: /* comment */
break;
case 50: /* local-rcvbuf */
#ifdef __linux__
params.local_rcvbuf = atoi(optarg)/2;
#else
params.local_rcvbuf = atoi(optarg);
#endif
break;
case 50: /* local-sndbuf */
case 51: /* local-sndbuf */
#ifdef __linux__
params.local_sndbuf = atoi(optarg)/2;
#else
params.local_sndbuf = atoi(optarg);
#endif
break;
case 51: /* remote-rcvbuf */
case 52: /* remote-rcvbuf */
#ifdef __linux__
params.remote_rcvbuf = atoi(optarg)/2;
#else
params.remote_rcvbuf = atoi(optarg);
#endif
break;
case 52: /* remote-sndbuf */
case 53: /* remote-sndbuf */
#ifdef __linux__
params.remote_sndbuf = atoi(optarg)/2;
#else
params.remote_sndbuf = atoi(optarg);
#endif
break;
case 53: /* socks */
case 54: /* socks */
params.proxy_type = CONN_TYPE_SOCKS;
break;
case 54: /* no-resolve */
case 55: /* no-resolve */
params.no_resolve = true;
break;
case 55: /* resolver-threads */
case 56: /* resolver-threads */
params.resolver_threads = atoi(optarg);
if (params.resolver_threads<1 || params.resolver_threads>300)
{
@@ -1199,10 +1248,10 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 56: /* skip-nodelay */
case 57: /* skip-nodelay */
params.skip_nodelay = true;
break;
case 57: /* tamper-start */
case 58: /* tamper-start */
{
const char *p=optarg;
if (*p=='n')
@@ -1216,7 +1265,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper_lim = true;
break;
case 58: /* tamper-cutoff */
case 59: /* tamper-cutoff */
{
const char *p=optarg;
if (*p=='n')
@@ -1230,7 +1279,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper_lim = true;
break;
case 59: /* connect-bind-addr */
case 60: /* connect-bind-addr */
{
char *p = strchr(optarg,'%');
if (p) *p++=0;
@@ -1258,7 +1307,7 @@ void parse_params(int argc, char *argv[])
break;
case 60: /* new */
case 61: /* new */
if (bSkip)
{
dp_clear(dp);
@@ -1279,31 +1328,31 @@ void parse_params(int argc, char *argv[])
anon_hl = anon_hl_exclude = NULL;
anon_ips = anon_ips_exclude = NULL;
break;
case 61: /* skip */
case 62: /* skip */
bSkip = true;
break;
case 62: /* filter-l3 */
case 63: /* filter-l3 */
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{
DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1);
}
break;
case 63: /* filter-tcp */
case 64: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp))
{
DLOG_ERR("Invalid port filter : %s\n",optarg);
exit_clean(1);
}
break;
case 64: /* filter-l7 */
case 65: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7))
{
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1);
}
break;
case 65: /* ipset */
case 66: /* ipset */
if (bSkip) break;
if (!RegisterIpset(dp, false, optarg))
{
@@ -1312,7 +1361,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 66: /* ipset-ip */
case 67: /* ipset-ip */
if (bSkip) break;
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
{
@@ -1326,7 +1375,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 67: /* ipset-exclude */
case 68: /* ipset-exclude */
if (bSkip) break;
if (!RegisterIpset(dp, true, optarg))
{
@@ -1335,7 +1384,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 68: /* ipset-exclude-ip */
case 69: /* ipset-exclude-ip */
if (bSkip) break;
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
{
@@ -1351,11 +1400,11 @@ void parse_params(int argc, char *argv[])
break;
#if defined(__FreeBSD__)
case 69: /* enable-pf */
case 70: /* enable-pf */
params.pf_enable = true;
break;
#elif defined(__linux__) || defined(__APPLE__)
case 69: /* local-tcp-user-timeout */
case 70: /* local-tcp-user-timeout */
params.tcp_user_timeout_local = atoi(optarg);
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
{
@@ -1363,7 +1412,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 70: /* remote-tcp-user-timeout */
case 71: /* remote-tcp-user-timeout */
params.tcp_user_timeout_remote = atoi(optarg);
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
{
@@ -1374,7 +1423,7 @@ void parse_params(int argc, char *argv[])
#endif
#if defined(__linux__)
case 71: /* mss */
case 72: /* mss */
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing
dp->mss = atoi(optarg);
if (dp->mss<88 || dp->mss>32767)
@@ -1383,7 +1432,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 72: /* fix-seg */
case 73: /* fix-seg */
if (!params.fix_seg_avail)
{
DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
@@ -1403,7 +1452,7 @@ void parse_params(int argc, char *argv[])
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
break;
#ifdef SPLICE_PRESENT
case 73: /* nosplice */
case 74: /* nosplice */
params.nosplice = true;
break;
#endif
@@ -1897,10 +1946,12 @@ int main(int argc, char *argv[])
set_ulimit();
sec_harden();
if (params.droproot && !droproot(params.uid,params.gid))
goto exiterr;
print_id();
if (params.droproot && !test_list_files())
goto exiterr;
//splice() causes the process to receive the SIGPIPE-signal if one part (for
//example a socket) is closed during splice(). I would rather have splice()
//fail and return -1, so blocking SIGPIPE.

View File

@@ -6,4 +6,4 @@
#include <sys/param.h>
void dohup(void);
void ReloadCheck();

View File

@@ -169,11 +169,8 @@ static bool send_buffer_realloc(send_buffer_t *sb, size_t extra_bytes)
static void send_buffer_free(send_buffer_t *sb)
{
if (sb->data)
{
free(sb->data);
sb->data = NULL;
}
free(sb->data);
sb->data = NULL;
}
static void send_buffers_free(send_buffer_t *sb_array, int count)
{
@@ -520,7 +517,7 @@ static void free_conn(tproxy_conn_t *conn)
}
conn_free_buffers(conn);
if (conn->partner) conn->partner->partner=NULL;
if (conn->track.hostname) free(conn->track.hostname);
free(conn->track.hostname);
if (conn->socks_ri) conn->socks_ri->ptr = NULL; // detach conn
free(conn);
}
@@ -1547,6 +1544,8 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
for(;;)
{
ReloadCheck();
DBGPRINT("epoll_wait\n");
if ((num_events = epoll_wait(efd, events, MAX_EPOLL_EVENTS, -1)) == -1)
@@ -1762,7 +1761,7 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
ex:
if (efd) close(efd);
if (listen_conn) free(listen_conn);
free(listen_conn);
resolver_deinit();
if (resolve_pipe[0]) close(resolve_pipe[0]);
if (resolve_pipe[1]) close(resolve_pipe[1]);