165 Commits
v69.1 ... v70

Author SHA1 Message Date
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
bol-van
9c8636081c update docs 2024-12-15 16:23:44 +03:00
bol-van
578d6d6db8 github: lexra 2024-12-15 16:22:15 +03:00
bol-van
9ab9aef32b install_bin: lexra 2024-12-15 16:22:05 +03:00
bol-van
d4a72df111 makefiles: LDFLAGS after LIBS 2024-12-15 13:50:48 +03:00
bol-van
ead91ae4f7 dvtws: openbsd build fix 2024-12-15 13:50:16 +03:00
bol-van
49385b6e57 tpws: more compats 2024-12-15 12:59:04 +03:00
bol-van
499f9824ab tpws: more compats 2024-12-14 20:36:56 +03:00
bol-van
2be5f1221a tpws: simplify tcp_info compat code 2024-12-14 17:00:26 +03:00
bol-van
fef64e8849 nfqws: unify profile debug messages 2024-12-14 14:35:04 +03:00
bol-van
675a8e52b6 tpws: old headers compat, increase default fix seg to 50 ms 2024-12-14 13:13:41 +03:00
bol-van
d9a24b4105 winws: process outgoing tcp fin and rst 2024-12-14 10:20:48 +03:00
bol-van
594e613fcb update docs 2024-12-13 18:59:43 +03:00
bol-van
7b7a6dd154 winws: --wf-tcp filter out empty ack 2024-12-13 18:49:45 +03:00
bol-van
dcf78a76e5 nfqws: trash flood check 2024-12-13 15:59:58 +03:00
bol-van
fc42f6e20e nfqws: remove obsolete code 2024-12-12 14:41:11 +03:00
bol-van
45b93f3a45 blockcheck: use instead of curl in mdig test 2024-12-12 09:14:38 +03:00
bol-van
1476cd2149 dvtws: fix build 2024-12-10 16:58:24 +03:00
bol-van
4ec6e5fa9f tpws,nfqws: --comment 2024-12-10 11:27:35 +03:00
bol-van
9d8398628c nfqws: fix bionic bad syscall on exit 2024-12-09 16:44:13 +03:00
bol-van
fe98c9d972 nfqws: remove unneeded ifdefs 2024-12-09 14:54:09 +03:00
bol-van
720c2fad86 nfqws: nfq_main error logic cleanup 2024-12-09 14:34:49 +03:00
bol-van
7b057491af update docs 2024-12-09 13:23:44 +03:00
bol-van
8e7b694076 init.d: 20-fw-extra 2024-12-09 13:20:05 +03:00
bol-van
e8395eea56 nfqws: pfsense split2->multisplit 2024-12-09 12:13:48 +03:00
bol-van
6e619eba1a nfqws: fix crash 2024-12-09 12:06:49 +03:00
bol-van
f8bd218e67 custom.d: DISABLE_CUSTOM switch 2024-12-09 11:04:13 +03:00
bol-van
207a6faf33 init.d: unify standard_mode_daemons 2024-12-09 10:49:43 +03:00
bol-van
991e3534a6 install_easy: copy custom.d.examples.linux in openwrt 2024-12-09 09:51:17 +03:00
bol-van
ebb22dfa3f init.d: unitfy custom scripts for linux 2024-12-09 09:28:25 +03:00
bol-van
9bd65e0c1d init.d: remove NFQWS_OPT_BASE from sysv custom scripts 2024-12-08 20:07:06 +03:00
bol-van
5b337b6015 50-wg4all: remove desync any protocol 2024-12-08 19:36:43 +03:00
bol-van
4189803693 init.d: custom script 50-wg4all 2024-12-08 19:31:29 +03:00
bol-van
1175b171ba nfqws: NETLINK_NO_ENOBUFS 2024-12-08 09:58:30 +03:00
bol-van
bea643c967 nfqws: more error checking fixing 2024-12-08 09:40:45 +03:00
bol-van
addc813956 tpws: fix dangling else 2024-12-08 08:38:17 +03:00
bol-van
0f1721d2c4 nfqws: dangling else fix 2024-12-07 22:41:55 +03:00
bol-van
abdc8d9449 nfqws: fix return value type 2024-12-07 22:05:26 +03:00
bol-van
9e9136cffd nfqws: static func 2024-12-07 20:54:22 +03:00
bol-van
c802069a11 nfqws: fix nfq recv result and error handling 2024-12-07 20:51:51 +03:00
bol-van
4e5caf4087 quick_start: improve link 2024-12-06 11:41:06 +03:00
bol-van
de63ee7321 quick_start_windows: improve link 2024-12-06 11:26:50 +03:00
bol-van
d6688b935d winws: fix non-working --dry-run 2024-12-05 21:55:48 +03:00
bol-van
21e08ca55e tpws,nfqws: fix recognition of CONNECT and OPTIONS http methods 2024-12-05 19:23:39 +03:00
bol-van
c4f53549b1 quick_start_windows: simplify win7 2024-12-05 18:05:02 +03:00
bol-van
08645997f8 50-tpws-ipset: fix var names 2024-12-04 16:23:44 +03:00
bol-van
e42a545ebc init.d: 50-tpws-ipset custom script example 2024-12-04 16:18:31 +03:00
bol-van
8324c04a41 Update windows.md 2024-12-04 10:59:57 +03:00
bol-van
166847ba92 Update windows.en.md 2024-12-04 10:59:22 +03:00
bol-van
1904f01cf4 Update windows.en.md 2024-12-04 10:58:25 +03:00
bol-van
4ae1ad053d Update windows.md 2024-12-04 10:57:09 +03:00
bol-van
7d9946b007 update docs 2024-12-03 18:23:13 +03:00
bol-van
86462f4cee update docs 2024-12-03 18:20:46 +03:00
bol-van
669182c133 install_easy: trim trailing space in editor 2024-12-03 17:33:02 +03:00
bol-van
f81bb51f4a install_easy: validate daemon options 2024-12-03 17:22:16 +03:00
bol-van
d4ff423add tpws: --dry-run 2024-12-03 15:57:21 +03:00
bol-van
b14ff9b647 nfqws: --dry-run 2024-12-03 15:56:37 +03:00
bol-van
277c5f9e00 update docs 2024-12-02 21:06:05 +03:00
bol-van
f016e5a4dc nfqws: customize fakedsplit pattern 2024-12-02 20:03:52 +03:00
bol-van
fc3912b4fe nfqws: improve fakedsplit/fakeddisorder with more fakes 2024-12-02 13:14:01 +03:00
bol-van
c01a764e1f init.d: sysv fix route_localnet with multiple IFACE_LAN 2024-12-01 21:21:08 +03:00
bol-van
4ecb40e03b Merge pull request #891 from spvkgn/fix-actions
github: minor
2024-11-27 16:28:16 +03:00
spvkgn
be9c300cb3 github: minor 2024-11-27 18:10:56 +05:00
bol-van
839c720f60 Merge pull request #888 from spvkgn/fix-actions
github: fix optimization for size
2024-11-27 14:51:12 +03:00
spvkgn
127bec2f14 github: fix optimization for size 2024-11-27 15:34:46 +05:00
spvkgn
15879c82f6 github: minor 2024-11-27 12:02:13 +05:00
bol-van
9d188840c1 blockcheck: eliminate multipos in fakedsplit and fakeddisorder 2024-11-25 18:16:16 +03:00
bol-van
35a28f4efe blockcheck: old dash compat 2024-11-25 12:39:12 +03:00
bol-van
78ea379e0f quick_start: light release notice 2024-11-24 18:00:01 +03:00
bol-van
007cbe600b update docs 2024-11-24 17:10:01 +03:00
bol-van
d1a8e276b5 update docs 2024-11-24 17:06:23 +03:00
bol-van
eb2f5b5f45 nfqws,tpws: ip->subnet in help text 2024-11-24 17:06:04 +03:00
bol-van
a623cef95d nfqws: fixed lists 2024-11-24 16:48:14 +03:00
bol-van
f00b45a28e tpws: fixed list fixes 2024-11-24 16:47:51 +03:00
bol-van
422faaa29c tpws: fixed ipset and hostlist 2024-11-24 16:03:13 +03:00
bol-van
16a9e3f9c9 github: sha256sum, remove tpws_wsl.tgz in openwrt ver 2024-11-24 13:27:57 +03:00
bol-van
7c5869bc29 display versions 2024-11-24 11:51:49 +03:00
bol-van
feb3dd4d73 issue_template warnings 2024-11-24 10:28:04 +03:00
bol-van
b4204ca2ba github: remote Makefile in light ver 2024-11-23 21:20:03 +03:00
bol-van
89a67e6952 github: tar releases with root owner 2024-11-23 21:17:19 +03:00
bol-van
34199b151c github: separate embedded linux archive 2024-11-23 20:26:58 +03:00
bol-van
c6962f575e install_bin: search win64 and win32 in CYGWIN 2024-11-23 20:07:26 +03:00
bol-van
9c8662b25e nfqws,tpws: fix crash 2024-11-23 14:14:12 +03:00
bol-van
fedb62df66 update docs 2024-11-23 13:28:34 +03:00
bol-van
44c19c1743 blockcheck: --methodeol test for nfqws 2024-11-23 13:20:02 +03:00
bol-van
56aa481226 nfqws: warn if cannot do hostnospace 2024-11-23 13:17:34 +03:00
bol-van
9184317549 nfqws: --methodeol 2024-11-23 13:14:02 +03:00
bol-van
a3048ae120 nfqws: --skip 2024-11-23 12:55:14 +03:00
bol-van
fc44d74f2b fix lto in nfqws makefile 2024-11-23 12:33:15 +03:00
bol-van
1779cfad30 tpws: --skip 2024-11-23 12:17:49 +03:00
bol-van
4856be4ef1 init.d: do not use pgrep for firmwares compatibility 2024-11-23 10:58:46 +03:00
bol-van
033043bdc0 tpws: remote duplicate if 2024-11-22 13:04:06 +03:00
91 changed files with 2846 additions and 1318 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

@@ -52,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
@@ -60,18 +67,31 @@ jobs:
- name: Set up build tools
env:
REPO: 'spvkgn/musl-cross'
ARCH: ${{ matrix.arch }}
TOOL: ${{ matrix.tool }}
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'spvkgn/musl-cross' }}
DIR: ${{ matrix.arch == 'lexra' && matrix.dir || matrix.tool }}
run: |
sudo apt update -qq && sudo apt install -y libcap-dev
if [[ "$ARCH" == lexra ]]; then
sudo dpkg --add-architecture i386
sudo apt update -qq
sudo apt install -y libcap-dev libc6:i386 zlib1g:i386
URL=https://github.com/$REPO/raw/refs/heads/master/$DIR.txz
else
sudo apt update -qq
sudo apt install -y libcap-dev
URL=https://github.com/$REPO/releases/download/latest/$TOOL.tar.xz
fi
mkdir -p $HOME/tools
wget -qO- https://github.com/$REPO/releases/download/latest/$TOOL.tar.xz | tar -C $HOME/tools -xJ || exit 1
[ -d "$HOME/tools/$TOOL/bin" ] && echo "$HOME/tools/$TOOL/bin" >> $GITHUB_PATH
wget -qO- $URL | tar -C $HOME/tools -xJ || exit 1
[[ -d "$HOME/tools/$DIR/bin" ]] && echo "$HOME/tools/$DIR/bin" >> $GITHUB_PATH
- name: Build
env:
ARCH: ${{ matrix.arch }}
TARGET: ${{ matrix.tool }}
CFLAGS: ${{ matrix.env.CFLAGS != '' && matrix.env.CFLAGS || null }}
LDFLAGS: ${{ matrix.env.LDFLAGS != '' && matrix.env.LDFLAGS || null }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps
@@ -81,10 +101,7 @@ jobs:
export NM=$TARGET-nm
export STRIP=$TARGET-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
# optimize for size
export CFLAGS="-Os -flto=auto"
export LDFLAGS="-Os"
export STAGING_DIR=$RUNNER_TEMP
# netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
@@ -94,6 +111,7 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="-Os -flto=auto $CFLAGS" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -105,6 +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" \
./configure --prefix= --static
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -115,8 +134,8 @@ jobs:
install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
# zapret
CFLAGS="$CFLAGS -static-libgcc -static -I$DEPS_DIR/include" \
LDFLAGS="$LDFLAGS -L$DEPS_DIR/lib" \
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 .
@@ -136,6 +155,7 @@ jobs:
- name: Build zapret
run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
make mac -j$(sysctl -n hw.logicalcpu)
tar -C binaries/my -cJf zapret-mac-x64.tar.xz .
@@ -170,7 +190,8 @@ jobs:
TARGET: ${{ matrix.target }}
ARCH: ${{ matrix.arch }}
run: |
settarget $TARGET-freebsd11 make bsd -j$(nproc) || exit 1
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
settarget $TARGET-freebsd11 make bsd -j$(nproc)
tar -C binaries/my -cJf zapret-freebsd-$ARCH.tar.xz .
- name: Upload artifacts
@@ -203,6 +224,7 @@ jobs:
- name: Build ip2net, mdig
shell: msys2 {0}
run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
mkdir -p output
cd zapret
mingw32-make -C ip2net win
@@ -259,6 +281,7 @@ jobs:
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
run: >-
export MAKEFLAGS=-j$(nproc) &&
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}" &&
cd zapret &&
make -C nfq ${TARGET} &&
cp -a nfq/winws.exe ../output
@@ -304,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
@@ -317,10 +341,6 @@ jobs:
export STRIP=$TOOLCHAIN/bin/llvm-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
# optimize for size
export CFLAGS="-Os -flto=auto"
export LDFLAGS="-Os"
# netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
wget -qO- https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
@@ -330,7 +350,7 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="$CFLAGS -Wno-implicit-function-declaration" \
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -338,8 +358,15 @@ jobs:
done
# zapret
CFLAGS="$CFLAGS -I$DEPS_DIR/include" LDFLAGS="$LDFLAGS -L$DEPS_DIR/lib" \
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -I$DEPS_DIR/include" \
LDFLAGS="-L$DEPS_DIR/lib" \
make -C zapret android -j$(nproc)
# 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
@@ -391,7 +418,7 @@ jobs:
if [[ $dir == *-linux-x86_64 ]]; then
tar -C $dir -czvf $dir/tpws_wsl.tgz tpws
run_upx $dir/*
elif [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]]; then
elif [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then
run_upx $dir/*
fi
;;
@@ -423,6 +450,7 @@ jobs:
*-linux-ppc ) run_dir ppc ;;
*-linux-x86 ) run_dir x86 ;;
*-linux-x86_64 ) run_dir x86_64 ;;
*-linux-lexra ) run_dir lexra ;;
*-mac-x64 ) run_dir mac64 ;;
*-win-x86 ) run_dir win32 ;;
*-win-x86_64 ) run_dir win64 ;;
@@ -434,8 +462,16 @@ jobs:
- name: Create release bundles
run: |
rm -rf ${{ env.repo_dir }}/.git*
tar -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
(
cd ${{ env.repo_dir }}
rm -rf binaries/{android*,freebsd*,mac*,win*,x86_64/tpws_wsl.tgz} \
init.d/{openrc,macos,pfsense,runit,s6,systemd} \
tpws nfq ip2net mdig docs files/huawei Makefile
)
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
- name: Upload release assets
uses: softprops/action-gh-release@v2
@@ -448,3 +484,4 @@ jobs:
files: |
zapret*.tar.gz
zapret*.zip
sha256sum.txt

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"
@@ -1011,11 +1035,10 @@ tpws_curl_test()
echo - checking tpws $3 $4 $5 $6 $7 $8 $9${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
local ALL_PROXY="socks5://127.0.0.1:$SOCKS_PORT"
ws_curl_test tpws_start "$@"${TPWS_EXTRA:+ $TPWS_EXTRA}${TPWS_EXTRA_1:+ "$TPWS_EXTRA_1"}${TPWS_EXTRA_2:+ "$TPWS_EXTRA_2"}${TPWS_EXTRA_3:+ "$TPWS_EXTRA_3"}${TPWS_EXTRA_4:+ "$TPWS_EXTRA_4"}${TPWS_EXTRA_5:+ "$TPWS_EXTRA_5"}${TPWS_EXTRA_6:+ "$TPWS_EXTRA_6"}${TPWS_EXTRA_7:+ "$TPWS_EXTRA_7"}${TPWS_EXTRA_8:+ "$TPWS_EXTRA_8"}${TPWS_EXTRA_9:+ "$TPWS_EXTRA_9"}
local code=$?
local testf=$1 dom=$2 strategy code=$?
[ "$code" = 0 ] && {
local testf=$1 dom=$2
shift; shift;
local strategy="$@"
strategy="$@"
strategy_append_extra_tpws
report_append "ipv${IPV} $dom $testf : tpws ${WF:+$WF }$strategy"
}
@@ -1028,11 +1051,10 @@ pktws_curl_test()
# $3,$4,$5, ... - nfqws/dvtws params
echo - checking $PKTWSD ${WF:+$WF }$3 $4 $5 $6 $7 $8 $9${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
ws_curl_test pktws_start "$@"${PKTWS_EXTRA:+ $PKTWS_EXTRA}${PKTWS_EXTRA_1:+ "$PKTWS_EXTRA_1"}${PKTWS_EXTRA_2:+ "$PKTWS_EXTRA_2"}${PKTWS_EXTRA_3:+ "$PKTWS_EXTRA_3"}${PKTWS_EXTRA_4:+ "$PKTWS_EXTRA_4"}${PKTWS_EXTRA_5:+ "$PKTWS_EXTRA_5"}${PKTWS_EXTRA_6:+ "$PKTWS_EXTRA_6"}${PKTWS_EXTRA_7:+ "$PKTWS_EXTRA_7"}${PKTWS_EXTRA_8:+ "$PKTWS_EXTRA_8"}${PKTWS_EXTRA_9:+ "$PKTWS_EXTRA_9"}
local code=$?
local testf=$1 dom=$2 strategy code=$?
[ "$code" = 0 ] && {
local testf=$1 dom=$2
shift; shift;
local strategy="$@"
strategy="$@"
strategy_append_extra_pktws
report_append "ipv${IPV} $dom $testf : $PKTWSD ${WF:+$WF }$strategy"
}
@@ -1112,6 +1134,10 @@ test_has_split()
{
contains "$1" split || contains "$1" disorder
}
test_has_fakedsplit()
{
contains "$1" fakedsplit || contains "$1" fakeddisorder
}
test_has_fake()
{
[ "$1" = fake ] || starts_with "$1" fake,
@@ -1131,18 +1157,24 @@ 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_split $desync && {
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"
elif test_has_split $desync ; then
splits="method+2 midsld"
[ "$sec" = 0 ] || splits="1 midsld 1,midsld"
}
for fake in '' $zerofake ; do
fi
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 && {
@@ -1173,7 +1205,7 @@ pktws_check_domain_http_bypass_()
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
[ "$sec" = 0 ] && {
for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase'; do
for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase' '--methodeol'; do
pktws_curl_test_update $1 $3 $s
done
}
@@ -1546,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
@@ -1592,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()
@@ -1702,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
@@ -1976,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()
{
@@ -2029,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

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

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
@@ -140,7 +140,7 @@ echo_var()
eval v="\$$1"
if find_str_in_list $1 "$EDITVAR_NEWLINE_VARS"; then
echo "$1=\""
echo "$v\"" | sed "s/$EDITVAR_NEWLINE_DELIMETER /$EDITVAR_NEWLINE_DELIMETER\n/g"
echo "$v\"" | tr '\n' ' ' | tr -d '\r' | sed -e 's/^ *//' -e 's/ *$//' -e "s/$EDITVAR_NEWLINE_DELIMETER /$EDITVAR_NEWLINE_DELIMETER\n/g"
else
if contains "$v" " "; then
echo $1=\"$v\"
@@ -170,6 +170,7 @@ list_vars()
echo_var $1
shift
done
echo
}
openrc_test()
@@ -616,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"
@@ -649,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)
@@ -656,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
@@ -837,3 +829,37 @@ select_fwtype()
echo select firewall type :
ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE
}
dry_run_tpws_()
{
local TPWS="$ZAPRET_BASE/tpws/tpws"
echo verifying tpws options
"$TPWS" --dry-run "$@"
}
dry_run_nfqws_()
{
local NFQWS="$ZAPRET_BASE/nfq/nfqws"
echo verifying nfqws options
"$NFQWS" --dry-run "$@"
}
dry_run_tpws()
{
[ "$TPWS_ENABLE" = 1 ] || return 0
local opt="$TPWS_OPT" port=${TPPORT_SOCKS:-988}
filter_apply_hostlist_target opt
dry_run_tpws_ --port=$port $opt
}
dry_run_tpws_socks()
{
[ "$TPWS_SOCKS_ENABLE" = 1 ] || return 0
local opt="$TPWS_SOCKS_OPT" port=${TPPORT:-987}
filter_apply_hostlist_target opt
dry_run_tpws_ --port=$port --socks $opt
}
dry_run_nfqws()
{
[ "$NFQWS_ENABLE" = 1 ] || return 0
local opt="$NFQWS_OPT" qn=${QNUM:-200}
filter_apply_hostlist_target opt
dry_run_nfqws_ --qnum=$qn $opt
}

View File

@@ -1,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
@@ -349,27 +353,37 @@ ipt_do_nfqws_in_out()
}
}
zapret_do_firewall_standard_rules_ipt()
zapret_do_firewall_standard_tpws_rules_ipt()
{
# $1 - 1 - add, 0 - del
local f4 f6
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] &&
{
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] && {
f4="-p tcp -m multiport --dports $TPWS_PORTS_IPT"
f6=$f4
filter_apply_ipset_target f4 f6
fw_tpws $1 "$f4" "$f6" $TPPORT
}
[ "$NFQWS_ENABLE" = 1 ] &&
{
}
zapret_do_firewall_standard_nfqws_rules_ipt()
{
# $1 - 1 - add, 0 - del
[ "$NFQWS_ENABLE" = 1 ] && {
ipt_do_nfqws_in_out $1 tcp "$NFQWS_PORTS_TCP_IPT" "$NFQWS_TCP_PKT_OUT" "$NFQWS_TCP_PKT_IN"
ipt_do_nfqws_in_out $1 tcp "$NFQWS_PORTS_TCP_KEEPALIVE_IPT" keepalive "$NFQWS_TCP_PKT_IN"
ipt_do_nfqws_in_out $1 udp "$NFQWS_PORTS_UDP_IPT" "$NFQWS_UDP_PKT_OUT" "$NFQWS_UDP_PKT_IN"
ipt_do_nfqws_in_out $1 udp "$NFQWS_PORTS_UDP_KEEPALIVE_IPT" keepalive "$NFQWS_UDP_PKT_IN"
}
}
zapret_do_firewall_standard_rules_ipt()
{
# $1 - 1 - add, 0 - del
zapret_do_firewall_standard_tpws_rules_ipt $1
zapret_do_firewall_standard_nfqws_rules_ipt $1
}
zapret_do_firewall_rules_ipt()
{

55
common/linux_daemons.sh Normal file
View File

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

View File

@@ -4,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
@@ -640,25 +616,31 @@ nft_apply_nfqws_in_out()
}
}
zapret_apply_firewall_standard_rules_nft()
zapret_apply_firewall_standard_tpws_rules_nft()
{
local f4 f6
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] &&
{
[ "$TPWS_ENABLE" = 1 -a -n "$TPWS_PORTS" ] && {
f4="tcp dport {$TPWS_PORTS}"
f6=$f4
nft_filter_apply_ipset_target f4 f6
nft_fw_tpws "$f4" "$f6" $TPPORT
}
[ "$NFQWS_ENABLE" = 1 ] &&
{
}
zapret_apply_firewall_standard_nfqws_rules_nft()
{
[ "$NFQWS_ENABLE" = 1 ] && {
nft_apply_nfqws_in_out tcp "$NFQWS_PORTS_TCP" "$NFQWS_TCP_PKT_OUT" "$NFQWS_TCP_PKT_IN"
nft_apply_nfqws_in_out tcp "$NFQWS_PORTS_TCP_KEEPALIVE" keepalive "$NFQWS_TCP_PKT_IN"
nft_apply_nfqws_in_out udp "$NFQWS_PORTS_UDP" "$NFQWS_UDP_PKT_OUT" "$NFQWS_UDP_PKT_IN"
nft_apply_nfqws_in_out udp "$NFQWS_PORTS_UDP_KEEPALIVE" keepalive "$NFQWS_UDP_PKT_IN"
}
}
zapret_apply_firewall_standard_rules_nft()
{
zapret_apply_firewall_standard_tpws_rules_nft
zapret_apply_firewall_standard_nfqws_rules_nft
}
zapret_apply_firewall_rules_nft()
{

View File

@@ -389,3 +389,66 @@ blockcheck: added CURL_OPT
blockcheck: new strategies support
blockcheck: test sequence rework
blockcheck: view all working strategies in summary
v69.1:
init.d: keenetic udp fix custom
tpws: fixed incorrect hostlist checks
v69.2:
nfqws,tpws: --skip
nfqws: --methodeol
init.d: do not use pgrep in sysv for busybox compat
v69.3
nfqws,tpws: fixed ipsets and hostlists
all progs: version numbers for github, build date/time for self built
repo: light release for openwrt and embedded systems
repo: sha256sum
v69.4
nfqws: fakedsplit/fakeddisorder fakes for both split segments
nfqws: --dpi-desync-fakedsplit-pattern
v69.5
nfqws,tpws: --dry-run
install_easy: check tpws and nfqws options validity
v69.6
nfqws: set NETLINK_NO_ENOBUFS to fix possible nfq recv errors
init.d: unify custom scripts for linux
init.d: new custom scripts : 20-fw-extra, 50-wg4all
v69.7
nfqws,tpws: --comment
nfqws: trash flood warning
winws: exclude empty outgoing ack packets in windivert filter
v69.8
winws: accept empty outgoing RST and FIN packets for conntrack needs
repo: lexra build
v69.9
init.d: exclude ipban from tpws redirection
macos: fix install_easy
macos: fix national decimal separator in sleep
ipset: scripts maintenance
v70
blockcheck: override all dialog questions and enable batch mode
blockcheck: parallel attempts
nfqws: weaken wireguard initiation recognition. use len=148 and data[0]=1 signature
nfqws: apply split+seqovl only to the first reasm fragment
install_easy: dnf packager support
nfqws,tpws: hostlist/ipset track not only file mod time but also file size
nfqws,tpws,ipset: return lists reload on HUP
nfqws,blockcheck: --dpi-desync-fake-tls-mod

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
# zapret v.69
# zapret v70
# 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
@@ -131,6 +132,8 @@ nfqws takes the following parameters:
@<config_file> ; read file for options. must be the only argument. other options are ignored.
--debug=0|1
--dry-run ; verify parameters and exit with code 0 if successful
--comment ; any text (ignored)
--qnum=<nfqueue_number>
--daemon ; daemonize
--pidfile=<filename> ; write pid to file
@@ -146,6 +149,7 @@ nfqws takes the following parameters:
--hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host"
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
--domcase ; mix domain case : Host: TeSt.cOm
--methodeol ; add '\n' before method and remove space after Host:
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
--dpi-desync-ttl=<int> ; set ttl for desync packet
@@ -161,6 +165,7 @@ nfqws takes the following parameters:
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder
--dpi-desync-ipfrag-pos-tcp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 8.
--dpi-desync-ipfrag-pos-udp=<8..9216> ; ip frag position starting from the transport header. multiple of 8, default 32.
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000
@@ -168,6 +173,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,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
@@ -179,19 +185,24 @@ nfqws takes the following parameters:
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-domains=<domain_list> ; comma separated fixed domain list
--hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
--hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
--hostlist-auto-retrans-threshold=<int> ; how many request retransmissions cause attempt to fail (default : 3)
--hostlist-auto-debug=<logfile> ; debug auto hostlist positives
--new ; begin new strategy
--new ; begin new strategy (new profile)
--skip ; do not use this profile
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list supported.
--filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported.
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-ip=<ip_list> ; comma separated fixed subnet list
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
```
### DPI desync attack
@@ -251,13 +262,28 @@ 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.
* `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` mods are applied. If defined - `none`.
This behaviour is compatible with previous versions.
### TCP segmentation
* `multisplit`. split request at specified in `--dpi-desync-split-pos` positions
* `multidisorder`. same as `multisplit` but send in reverse order
* `fakedsplit`. split request into 2 segments adding fakes in the middle of them : fake 1st segment, 1st segment, fake 1st segment, 2nd segment
* `fakeddisorder`. same as `fakedsplit` but with another order : 2nd segment, fake 1st segment, 1st segment, fake 1st segment
* `fakedsplit`. split request into 2 segments adding fakes in the middle of them : fake 1st segment, 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
* `fakeddisorder`. same as `fakedsplit` but with another order : fake 2nd segment, 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment
Positions are defined by markers.
@@ -267,7 +293,7 @@ Positions are defined by markers.
Relative positions :
* **method** - HTTP method start ('GET', 'POST', 'HEAD', ...). Method is usually always at position 0 but also supported `--methodeol` fooling by **tpws**. If fooled position can become 1 or 2.
* **method** - HTTP method start ('GET', 'POST', 'HEAD', ...). Method is usually always at position 0 but can shift because of `--methodeol` fooling. If fooled position can become 1 or 2.
* **host** - hostname start in a known protocol (http, TLS)
* **endhost** - the byte next to the last hostname's byte
* **sld** - second level domain start in the hostname
@@ -632,6 +658,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
--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
@@ -663,15 +690,20 @@ tpws is transparent proxy.
; its worth to make a reserve with 1.5 multiplier. by default maxfiles is (X*connections)*1.5+16
--max-orphan-time=<sec> ; if local leg sends something and closes and remote leg is still connecting then cancel connection attempt after N seconds
--new ; begin new strategy
--new ; begin new strategy (new profile)
--skip ; do not use this profile
--filter-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. comma separated list supported.
--filter-l7=[http|tls|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-ip=<ip_list> ; comma separated fixed subnet list
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-domains=<domain_list> ; comma separated fixed domain list
--hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
--hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
@@ -701,7 +733,7 @@ tpws is transparent proxy.
--daemon ; daemonize
--pidfile=<filename> ; write pid to file
--user=<username> ; drop root privs
--uid=uid[:gid] ; drop root privs
--uid=uid[:gid] ; drop root privs
```
### TCP segmentation in tpws
@@ -950,7 +982,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 v.69
# zapret v70
# ВНИМАНИЕ, остерегайтесь мошенников
@@ -21,6 +21,7 @@ zapret является свободным и open source.
- [nfqws](#nfqws)
- [АТАКА ДЕСИНХРОНИЗАЦИИ DPI](#атака-десинхронизации-dpi)
- [ФЕЙКИ](#фейки)
- [МОДИФИКАЦИЯ ФЕЙКОВ](#модификация-фейков)
- [TCP СЕГМЕНТАЦИЯ](#tcp-сегментация)
- [ПЕРЕКРЫТИЕ SEQUENCE NUMBERS](#перекрытие-sequence-numbers)
- [СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6](#специфические-режимы-ipv6)
@@ -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
@@ -159,70 +155,80 @@ DPI. Все больше становится внереестровых бло
dvtws, собираемый из тех же исходников (см. [документация BSD](./bsd.md)).
```
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
--debug=0|1 ; 1=выводить отладочные сообщения
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
--user=<username> ; менять uid процесса
--uid=uid[:gid] ; менять uid процесса
--qnum=N ; номер очереди N
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !)
--wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
--domcase ; домен после Host: сделать таким : TeSt.cOm
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию.
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; переопределение предыдущего параметра для ipv6
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
--debug=0|1 ; 1=выводить отладочные сообщения
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
--comment ; любой текст (игнорируется)
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
--user=<username> ; менять uid процесса
--uid=uid[:gid] ; менять uid процесса
--qnum=N ; номер очереди N
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !)
--wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
--methodeol ; добавить перевод строки в unix стиле ('\n') перед методом и убрать пробел из Host: : "GET / ... Host: domain.com" => "\nGET / ... Host:domain.com"
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
--domcase ; домен после Host: сделать таким : TeSt.cOm
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию.
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; переопределение предыдущего параметра для ipv6
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; чем заполнять фейковую часть overlap
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
--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-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
--dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
; в файле должен быть хост на каждой строке.
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
; при изменении времени модификации файла он перечитывается автоматически по необходимости
; список может быть запакован в gzip. формат автоматически распознается и разжимается
; списков может быть множество. пустой общий лист = его отсутствие
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
--hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3)
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
--new ; начало новой стратегии (новый профиль)
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую.
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую.
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--dpi-desync-fakedsplit-pattern=<filename>|0xHEX ; чем заполнять фейки в fakedsplit/fakeddisorder
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
--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,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
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
--dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
; в файле должен быть хост на каждой строке.
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
; при изменении времени модификации файла он перечитывается автоматически по необходимости
; список может быть запакован в gzip. формат автоматически распознается и разжимается
; списков может быть множество. пустой общий лист = его отсутствие
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
--hostlist-exclude-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
--hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3)
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
--new ; начало новой стратегии (новый профиль)
--skip ; не использовать этот профиль . полезно для временной деактивации профиля без удаления параметров.
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую.
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую.
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-exclude-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
```
`--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. Может быть важен порядок следования
@@ -259,7 +265,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 вы ничего
@@ -308,12 +314,35 @@ 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`. Выполняется на каждый запрос.
* `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`. Если фейк задан, используется `none`.
Это соответствует поведению программы более старых версий.
### TCP СЕГМЕНТАЦИЯ
* `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях.
* `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке.
* `fakedsplit`. нарезаем запрос на 2 части, обрамляя его фейками : фейк 1-й части, 1 часть, фейк 1-й части, 2 часть
* `fakeddisorder`. нарезаем запрос на 2 части, обрамляя его фейками : 2 часть, фейк 1-й части, 1 часть, фейк 1 части.
* `fakedsplit`. нарезаем запрос на 2 части, обрамляя каждую часть фейками : фейк 1-й части, 1 часть, фейк 1-й части, фейк 2-й части, 2 часть, фейк 2-й части
* `fakeddisorder`. аналогично `fakedsplit`, только в обратном порядке : фейк 2-й части, 2 часть, фейк 2-й части, фейк 1-й части, 1 часть, фейк 1 части.
Содержимое фейков в `fakedsplit`/`fakeddisorder` определяется параметром `--dpi-desync-fakedsplit-pattern` (по умолчанию 0x00).
Данные фейков берутся из паттерна со смещением, соответствующим смещению отсылаемых частей.
Размеры фейков соответствуют длинам отсылаемых частей.
Цель этих режимов - максимально усложнить выявление оригинальных данных среди фейков.
Для определения позиций нарезки используются маркеры.
@@ -323,7 +352,7 @@ dvtws, собираемый из тех же исходников (см. [док
Относительные позиции :
* **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но поддерживается и нахождение метода после дурение методом `--methodeol` от tpws. Тогда позиция может стать 1 или 2.
* **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но может сместиться из-за `--methodeol`. Тогда позиция может стать 1 или 2.
* **host** - начало имени хоста в известном протоколе (http, TLS)
* **endhost** - байт, следующий за последним байтом имени хоста
* **sld** - начало домена 2 уровня в имени хоста
@@ -557,7 +586,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` с содержимым :
```
@@ -731,10 +760,10 @@ iptables могут не работать. При включенном offloadin
DNAT/REDIRECT (tpws). Эти соединения исключаются из offloading. Однако, остальные соединения идут через SFO, потому
NFQUEUE будет срабатывать только до помещения соединения в flowtable. Практически это означает, что почти весь функционал nfqws работать не будет.
Offload включается через специальный target в iptables `FLOWOFFLOAD`. Не обязательно пропускать весь трафик через offload. Можно исключить из
offload соединения, которые должны попасть на tpws или nfqws. openwrt не предусматривает выборочного управления offload.
Поэтому скрипты zapret поддерживают свою систему выборочного управления offload в openwrt.
offload соединения, которые должны попасть на tpws или nfqws. OpenWrt не предусматривает выборочного управления offload.
Поэтому скрипты zapret поддерживают свою систему выборочного управления offload в OpenWrt.
iptables target `FLOWOFFLOAD` - это проприетарное изобретение openwrt.
iptables target `FLOWOFFLOAD` - это проприетарное изобретение OpenWrt.
Управление offload в nftables реализовано в базовом ядре linux без патчей.
@@ -742,95 +771,101 @@ iptables target `FLOWOFFLOAD` - это проприетарное изобрет
tpws - это transparent proxy.
```
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
--debug=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
--user=<username> ; менять uid процесса
--uid=uid[:gid] ; менять uid процесса
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
--bind-linklocal=no|unwanted|prefer|force
; no : биндаться только на global ipv6
; unwanted (default) : предпочтительно global, если нет - LL
; prefer : предпочтительно LL, если нет - global
; force : биндаться только на LL
--bind-iface4=<iface> ; слушать на первом ipv4 интерфейса iface
--bind-iface6=<iface> ; слушать на первом ipv6 интерфейса iface
--bind-wait-ifup=<sec ; ждать до N секунд появления и поднятия интерфейса
--bind-wait-ip=<sec> ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса)
--debug=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
--dry-run ; проверить опции командной строки и выйти. код 0 - успешная проверка.
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
--user=<username> ; менять uid процесса
--uid=uid[:gid] ; менять uid процесса
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
--bind-linklocal=no|unwanted|prefer|force ; no : биндаться только на global ipv6
; unwanted (default) : предпочтительно global, если нет - LL
; prefer : предпочтительно LL, если нет - global
; force : биндаться только на LL
--bind-iface4=<iface> ; слушать на первом ipv4 интерфейса iface
--bind-iface6=<iface> ; слушать на первом ipv6 интерфейса iface
--bind-wait-ifup=<sec> ; ждать до N секунд появления и поднятия интерфейса
--bind-wait-ip=<sec> ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса)
--bind-wait-ip-linklocal=<sec>
; имеет смысл только при задании --bind-wait-ip
; --bind-linklocal=unwanted : согласиться на LL после N секунд
; --bind-linklocal=prefer : согласиться на global address после N секунд
--bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0.
--connect-bind-addr ; с какого адреса подключаться во внешнюю сеть. может быть ipv4 или ipv6 адрес
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
; опция может повторяться для v4 и v6 адресов
; опция не отменяет правил маршрутизации ! выбор интерфейса определяется лишь правилами маршрутизации, кроме случая v6 link local.
--socks ; вместо прозрачного прокси реализовать socks4/5 proxy
--no-resolve ; запретить ресолвинг имен через socks5
--resolve-threads ; количество потоков ресолвера
--port=<port> ; на каком порту слушать
--maxconn=<max_connections> ; максимальное количество соединений от клиентов к прокси
--maxfiles=<max_open_files> ; макс количество файловых дескрипторов (setrlimit). мин требование (X*connections+16), где X=6 в tcp proxy mode, X=4 в режиме тамперинга.
; стоит сделать запас с коэффициентом как минимум 1.5. по умолчанию maxfiles (X*connections)*1.5+16
--max-orphan-time=<sec> ; если вы запускаете через tpws торрент-клиент с множеством раздач, он пытается установить очень много исходящих соединений,
; большая часть из которых отваливается по таймауту (юзера сидят за NAT, firewall, ...)
; установление соединения в linux может длиться очень долго. локальный конец отвалился, перед этим послав блок данных,
; tpws ждет подключения удаленного конца, чтобы отослать ему этот блок, и зависает надолго.
; настройка позволяет сбрасывать такие подключения через N секунд, теряя блок данных. по умолчанию 5 сек. 0 означает отключить функцию
; эта функция не действует на успешно подключенные ранее соединения
; имеет смысл только при задании --bind-wait-ip
; --bind-linklocal=unwanted : согласиться на LL после N секунд
; --bind-linklocal=prefer : согласиться на global address после N секунд
--bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0.
--connect-bind-addr ; с какого адреса подключаться во внешнюю сеть. может быть ipv4 или ipv6 адрес
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
; опция может повторяться для v4 и v6 адресов
; опция не отменяет правил маршрутизации ! выбор интерфейса определяется лишь правилами маршрутизации, кроме случая v6 link local.
--socks ; вместо прозрачного прокси реализовать socks4/5 proxy
--no-resolve ; запретить ресолвинг имен через socks5
--resolve-threads ; количество потоков ресолвера
--port=<port> ; на каком порту слушать
--maxconn=<max_connections> ; максимальное количество соединений от клиентов к прокси
--maxfiles=<max_open_files> ; макс количество файловых дескрипторов (setrlimit). мин требование (X*connections+16), где X=6 в tcp proxy mode, X=4 в режиме тамперинга.
; стоит сделать запас с коэффициентом как минимум 1.5. по умолчанию maxfiles (X*connections)*1.5+16
--max-orphan-time=<sec> ; если вы запускаете через tpws торрент-клиент с множеством раздач, он пытается установить очень много исходящих соединений,
; большая часть из которых отваливается по таймауту (юзера сидят за NAT, firewall, ...)
; установление соединения в linux может длиться очень долго. локальный конец отвалился, перед этим послав блок данных,
; tpws ждет подключения удаленного конца, чтобы отослать ему этот блок, и зависает надолго.
; настройка позволяет сбрасывать такие подключения через N секунд, теряя блок данных. по умолчанию 5 сек. 0 означает отключить функцию
; эта функция не действует на успешно подключенные ранее соединения
--local-rcvbuf=<bytes> ; SO_RCVBUF для соединений client-proxy
--local-sndbuf=<bytes> ; SO_SNDBUF для соединений client-proxy
--remote-rcvbuf=<bytes> ; SO_RCVBUF для соединений proxy-target
--remote-sndbuf=<bytes> ; SO_SNDBUF для соединений proxy-target
--nosplice ; не использовать splice на linux системах
--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
--fix-seg=<int> ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс.
--local-rcvbuf=<bytes> ; SO_RCVBUF для соединений client-proxy
--local-sndbuf=<bytes> ; SO_SNDBUF для соединений client-proxy
--remote-rcvbuf=<bytes> ; SO_RCVBUF для соединений proxy-target
--remote-sndbuf=<bytes> ; SO_SNDBUF для соединений proxy-target
--nosplice ; не использовать splice на linux системах
--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
--fix-seg=<int> ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс.
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
--disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса
--oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита
--oob-data=<char>|0xHEX ; переопределить байт OOB. по умолчанию 0x00.
--hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:".
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
--hostdot ; добавление точки после имени хоста : "Host: kinozal.tv."
--hosttab ; добавление табуляции после имени хоста : "Host: kinozal.tv\t"
--hostnospace ; убрать пробел после "Host:"
--hostpad=<bytes> ; добавить паддинг-хедеров общей длиной <bytes> перед Host:
--domcase ; домен после Host: сделать таким : TeSt.cOm
--methodspace ; добавить пробел после метода : "GET /" => "GET /"
--methodeol ; добавить перевод строки перед методом : "GET /" => "\r\nGET /"
--unixeol ; конвертировать 0D0A в 0A и использовать везде 0A
--tlsrec=N|-N|marker+N|marker-N ; разбивка TLS ClientHello на 2 TLS records на указанной позиции. Минимальное смещение - 6.
--mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость
--tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока)
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
; в файле должен быть хост на каждой строке.
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
; при изменении времени модификации файла он перечитывается автоматически по необходимости
; список может быть запакован в gzip. формат автоматически распознается и разжимается
; списков может быть множество. пустой общий лист = его отсутствие
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
--new ; начало новой стратегии (новый профиль)
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую.
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
--disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса
--oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита
--oob-data=<char>|0xHEX ; переопределить байт OOB. по умолчанию 0x00.
--hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:".
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
--hostdot ; добавление точки после имени хоста : "Host: kinozal.tv."
--hosttab ; добавление табуляции после имени хоста : "Host: kinozal.tv\t"
--hostnospace ; убрать пробел после "Host:"
--hostpad=<bytes> ; добавить паддинг-хедеров общей длиной <bytes> перед Host:
--domcase ; домен после Host: сделать таким : TeSt.cOm
--methodspace ; добавить пробел после метода : "GET /" => "GET /"
--methodeol ; добавить перевод строки перед методом : "GET /" => "\r\nGET /"
--unixeol ; конвертировать 0D0A в 0A и использовать везде 0A
--tlsrec=N|-N|marker+N|marker-N ; разбивка TLS ClientHello на 2 TLS records на указанной позиции. Минимальное смещение - 6.
--mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость
--tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока)
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
; в файле должен быть хост на каждой строке.
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
; при изменении времени модификации файла он перечитывается автоматически по необходимости
; список может быть запакован в gzip. формат автоматически распознается и разжимается
; списков может быть множество. пустой общий лист = его отсутствие
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
--hostlist-exclude-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
--new ; начало новой стратегии (новый профиль)
--skip ; не использовать этот профиль . полезно для временной деактивации профиля без удаления параметров.
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую.
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-exclude-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
```
### TCP СЕГМЕНТАЦИЯ В TPWS
@@ -1288,7 +1323,8 @@ ipset/get_refilter_domains.sh
```
Он кладется в `ipset/zapret-hosts.txt.gz`.
При изменении времени модификации файлов списки перечитываются автоматически.
При изменении времени модификации или размера файлов списки перечитываются автоматически.
После неатомарных операций изменения можно послать tpws/nfqws сигнал HUP для принудительной перечитки всех листов.
При фильтрации по именам доменов демон должен запускаться без фильтрации по ipset.
tpws и nfqws решают нужно ли применять дурение в зависимости от хоста, полученного из протокола прикладного уровня (http, tls, quic).
@@ -1412,11 +1448,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
@@ -1424,13 +1471,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-ы недостаточно подробно информируют о причинах ошибки.
@@ -1537,7 +1585,7 @@ curl: (28) Connection timed out after 2002 milliseconds
На linux системах можно выбрать использовать `iptables` или `nftables`.
По умолчанию на традиционных linux выбирается `nftables`, если установлен nft.
На openwrt по умолчанию выбирается `nftables` на новых версиях с firewall4.
На OpenWrt по умолчанию выбирается `nftables` на новых версиях с firewall4.
`FWTYPE=iptables`
@@ -1686,7 +1734,7 @@ DISABLE_IPV6=1
```
Количество потоков для многопоточного DNS ресолвера mdig (1..100).
Чем их больше, тем быстрее, но не обидится ли на долбежку ваш DNS сервер?\
Чем их больше, тем быстрее, но не обидется ли на долбежку ваш DNS сервер?\
`MDIG_THREADS=30`
Место для хранения временных файлов. При скачивании огромных реестров в `/tmp` места может не хватить.
@@ -1748,11 +1796,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"
@@ -1762,7 +1810,7 @@ OPENWRT_WAN6="wan6 vpn6"
Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables.\
При иных значениях или если параметр закомментирован, правила применены не будут.\
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.\
На openwrt неприменимо при использовании firewall3+iptables.
На OpenWrt неприменимо при использовании firewall3+iptables.
***Следующие настройки не актуальны для openwrt:***
@@ -1816,7 +1864,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`
@@ -1847,8 +1895,9 @@ custom скрипты - это маленькие shell программы, уп
/opt/zapret/init.d/macos/custom.d
```
Директория будет просканирована в алфавитном порядке, и каждый скрипт будет применен.
Рядом имеется `custom.d.examples`. Это готовые скрипты, которые можно копировать в `custom.d`.
Их можно взять за основу для написания собственных.
В `init.d` имеется `custom.d.examples.linux`, в `init.d/macos` - `custom.d.examples`.
Это готовые скрипты, которые можно копировать в `custom.d`. Их можно взять за основу для написания собственных.
***Для linux пишется код в функции***
```
@@ -1866,9 +1915,9 @@ zapret_custom_firewall_v6
```
zapret_custom_daemons поднимает демоны **nfqws**/**tpws** в нужном вам количестве и с нужными вам параметрами.
Для систем традиционного linux (sysv) и MacOS в первом параметре передается код операции: 1 = запуск, 0 = останов.
Для openwrt логика останова отсутствует за ненадобностью.
Схема запуска демонов в openwrt отличается - используется procd.
В первом параметре передается код операции: 1 = запуск, 0 = останов.
Схема запуска демонов в OpenWrt отличается - используется procd.
Поэтому логика останова отсутствует за ненадобностью, останов никогда не вызывается.
zapret_custom_firewall поднимает и убирает правила `iptables`.
В первом параметре передается код операции: 1 = запуск, 0 = останов.
@@ -1894,8 +1943,8 @@ zapret_custom_firewall_nft поднимает правила nftables.
В macos firewall-функции ничего сами никуда не заносят. Их задача - лишь выдать текст в stdout,
содержащий правила для pf-якоря. Остальное сделает обертка.
Особо обратите внимание на номер демона в функциях `run_daemon` и `do_daemon`, номера портов **tpws**
и очередей `nfqueue`.
Особо обратите внимание на номер демона в функциях `run_daemon` , `do_daemon`, `do_tpws`, `do_tpws_socks`, `do_nfqws` ,
номера портов **tpws** и очередей **nfqueue**.
Они должны быть уникальными во всех скриптах. При накладке будет ошибка.
Поэтому используйте функции динамического получения этих значений из пула.
@@ -1909,7 +1958,7 @@ zapret_custom_firewall_nft поднимает правила nftables.
## Простая установка
`install_easy.sh` автоматизирует ручные варианты процедур установки.
Он поддерживает OpenWRT, linux системы на базе systemd или openrc и MacOS.
Он поддерживает OpenWrt, linux системы на базе systemd или openrc и MacOS.
Для более гибкой настройки перед запуском инсталлятора следует выполнить раздел "Выбор параметров".
@@ -1926,7 +1975,7 @@ zapret_custom_firewall_nft поднимает правила nftables.
`install_easy.sh make`
Под openwrt все уже сразу готово для использования системы в качестве роутера.
Под OpenWrt все уже сразу готово для использования системы в качестве роутера.
Имена интерфейсов WAN и LAN известны из настроек системы.
Под другими системами роутер вы настраиваете самостоятельно. Инсталлятор в это не вмешивается.
инсталлятор в зависимости от выбранного режима может спросить LAN и WAN интерфейсы.
@@ -2051,17 +2100,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
@@ -2202,10 +2252,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 корня системы сильно кастрированы. они не имеют
возможности доустановки ПО из репозитория без специальных вывертов и заточены в основном
@@ -2226,45 +2276,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

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

View File

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

View File

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

View File

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

View File

@@ -14,7 +14,7 @@ zapret_custom_daemons()
{
# $1 - 1 - run, 0 - stop
local opt="--qnum=$QNUM_DISCORD $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_DISCORD"
local opt="--qnum=$QNUM_DISCORD $NFQWS_OPT_DESYNC_DISCORD"
do_nfqws $1 $DNUM_DISCORD "$opt"
}

View File

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

View File

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

View File

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

File diff suppressed because one or more lines are too long

View File

@@ -10,6 +10,7 @@ ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
. "$ZAPRET_BASE/common/ipt.sh"
. "$ZAPRET_BASE/common/nft.sh"
. "$ZAPRET_BASE/common/linux_fw.sh"
. "$ZAPRET_BASE/common/linux_daemons.sh"
. "$ZAPRET_BASE/common/list.sh"
. "$ZAPRET_BASE/common/custom.sh"
CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt"
@@ -24,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

@@ -81,6 +81,10 @@ run_tpws()
}
run_daemon $1 "$TPWS" "$OPT $2"
}
do_tpws()
{
[ "$1" = 0 ] || { shift; run_tpws "$@"; }
}
run_tpws_socks()
{
[ "$DISABLE_IPV4" = "1" ] && [ "$DISABLE_IPV6" = "1" ] && return 0
@@ -90,13 +94,10 @@ run_tpws_socks()
tpws_apply_socks_binds opt
run_daemon $1 "$TPWS" "$opt $2"
}
stop_tpws()
do_tpws_socks()
{
stop_daemon $1 "$TPWS"
[ "$1" = 0 ] || { shift; run_tpws_socks "$@"; }
}
tpws_apply_socks_binds()
{
local o
@@ -105,39 +106,27 @@ tpws_apply_socks_binds()
[ "$DISABLE_IPV6" = "1" ] || o="$o --bind-addr=::1"
for lan in $OPENWRT_LAN; do
network_get_device DEVICE $lan
[ -n "$DEVICE" ] || continue
[ "$DISABLE_IPV4" = "1" ] || o="$o --bind-iface4=$DEVICE $TPWS_WAIT"
[ "$DISABLE_IPV6" = "1" ] || o="$o --bind-iface6=$DEVICE --bind-linklocal=unwanted $TPWS_WAIT_SOCKS6"
network_get_device DEVICE $lan
[ -n "$DEVICE" ] || continue
[ "$DISABLE_IPV4" = "1" ] || o="$o --bind-iface4=$DEVICE $TPWS_WAIT"
[ "$DISABLE_IPV6" = "1" ] || o="$o --bind-iface6=$DEVICE --bind-linklocal=unwanted $TPWS_WAIT_SOCKS6"
done
eval $1="\"\$$1 $o\""
}
standard_mode_daemons()
run_nfqws()
{
local opt
[ "$TPWS_ENABLE" = 1 ] && check_bad_ws_options 1 "$TPWS_OPT" && {
opt="--port=$TPPORT $TPWS_OPT"
filter_apply_hostlist_target opt
run_tpws 1 "$opt"
}
[ "$TPWS_SOCKS_ENABLE" = 1 ] && {
opt="--port=$TPPORT_SOCKS $TPWS_SOCKS_OPT"
filter_apply_hostlist_target opt
run_tpws_socks 2 "$opt"
}
[ "$NFQWS_ENABLE" = 1 ] && check_bad_ws_options 1 "$NFQWS_OPT" && {
opt="--qnum=$QNUM $NFQWS_OPT_BASE $NFQWS_OPT"
filter_apply_hostlist_target opt
run_daemon 3 "$NFQWS" "$opt"
}
run_daemon $1 "$NFQWS" "$NFQWS_OPT_BASE $2"
}
do_nfqws()
{
[ "$1" = 0 ] || { shift; run_nfqws "$@"; }
}
start_daemons_procd()
{
standard_mode_daemons
custom_runner zapret_custom_daemons
standard_mode_daemons 1
custom_runner zapret_custom_daemons 1
return 0
}

View File

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

View File

@@ -10,6 +10,7 @@ ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
. "$ZAPRET_BASE/common/ipt.sh"
. "$ZAPRET_BASE/common/nft.sh"
. "$ZAPRET_BASE/common/linux_fw.sh"
. "$ZAPRET_BASE/common/linux_daemons.sh"
. "$ZAPRET_BASE/common/list.sh"
. "$ZAPRET_BASE/common/custom.sh"
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
@@ -89,20 +90,13 @@ 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 "$@"
}
set_route_localnet()
{
_set_route_localnet $1 "$IFACE_LAN"
_set_route_localnet $1 $IFACE_LAN
}
fw_nfqws_post4()
@@ -167,9 +161,15 @@ run_daemon()
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
local DAEMONBASE="$(basename "$2")"
local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
local PID= PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
echo "Starting daemon $1: $2 $3"
if [ -f "$PIDFILE" ] && pgrep -F "$PIDFILE" "$DAEMONBASE" >/dev/null; then
[ -f "$PIDFILE" ] && {
read PID <"$PIDFILE"
[ -d "/proc/$PID" ] || PID=
}
if [ -n "$PID" ]; then
echo already running
else
"$2" $3 >/dev/null &
@@ -188,18 +188,14 @@ stop_daemon()
# $2 - daemon
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
local DAEMONBASE="$(basename "$2")"
local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
local PID PIDFILE=$PIDDIR/$DAEMONBASE$1.pid
echo "Stopping daemon $1: $2"
if exists start-stop-daemon ; then
start-stop-daemon -K -p "$PIDFILE" -x "$2"
if [ -f "$PIDFILE" ]; then
read PID <"$PIDFILE"
kill $PID
rm -f "$PIDFILE"
else
if [ -f "$PIDFILE" ]; then
read PID <"$PIDFILE"
kill $PID
rm -f "$PIDFILE"
else
echo no pidfile : $PIDFILE
fi
echo no pidfile : $PIDFILE
fi
}
do_daemon()
@@ -273,45 +269,3 @@ create_ipset()
echo "Creating ip list table (firewall type $FWTYPE)"
"$IPSET_CR" "$@"
}
standard_mode_daemons()
{
# $1 - 1 - run, 0 - stop
local opt
[ "$TPWS_ENABLE" = 1 ] && check_bad_ws_options $1 "$TPWS_OPT" && {
opt="--port=$TPPORT $TPWS_OPT"
filter_apply_hostlist_target opt
do_tpws $1 1 "$opt"
}
[ "$TPWS_SOCKS_ENABLE" = 1 ] && {
opt="--port=$TPPORT_SOCKS $TPWS_SOCKS_OPT"
filter_apply_hostlist_target opt
do_tpws_socks $1 2 "$opt"
}
[ "$NFQWS_ENABLE" = 1 ] && check_bad_ws_options $1 "$NFQWS_OPT" && {
opt="--qnum=$QNUM $NFQWS_OPT"
filter_apply_hostlist_target opt
do_nfqws $1 3 "$opt"
}
}
zapret_do_daemons()
{
# $1 - 1 - run, 0 - stop
standard_mode_daemons $1
custom_runner zapret_custom_daemons $1
return 0
}
zapret_run_daemons()
{
zapret_do_daemons 1 "$@"
}
zapret_stop_daemons()
{
zapret_do_daemons 0 "$@"
}

View File

@@ -74,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

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

View File

@@ -26,6 +26,7 @@ IPSET_DIR="$ZAPRET_BASE/ipset"
. "$ZAPRET_BASE/common/ipt.sh"
. "$ZAPRET_BASE/common/installer.sh"
. "$ZAPRET_BASE/common/virt.sh"
. "$ZAPRET_BASE/common/list.sh"
GET_LIST="$IPSET_DIR/get_config.sh"
@@ -69,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
@@ -115,6 +116,30 @@ ws_opt_validate()
}
return 0
}
tpws_opt_validate()
{
ws_opt_validate "$1" || return 1
dry_run_tpws || {
echo invalid tpws options
return 1
}
}
tpws_socks_opt_validate()
{
# --ipset allowed here
dry_run_tpws_socks || {
echo invalid tpws options
return 1
}
}
nfqws_opt_validate()
{
ws_opt_validate "$1" || return 1
dry_run_nfqws || {
echo invalid nfqws options
return 1
}
}
select_mode_group()
{
@@ -162,18 +187,17 @@ select_mode_group()
select_mode_tpws_socks()
{
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_SOCKS_OPT"
# --ipset allowed here
select_mode_group TPWS_SOCKS_ENABLE "enable tpws socks mode on port $TPPORT_SOCKS ?" "TPPORT_SOCKS TPWS_SOCKS_OPT"
select_mode_group TPWS_SOCKS_ENABLE "enable tpws socks mode on port $TPPORT_SOCKS ?" "TPPORT_SOCKS TPWS_SOCKS_OPT" tpws_socks_opt_validate TPWS_SOCKS_OPT
}
select_mode_tpws()
{
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="TPWS_OPT"
select_mode_group TPWS_ENABLE "enable tpws transparent mode ?" "TPWS_PORTS TPWS_OPT" ws_opt_validate TPWS_OPT
select_mode_group TPWS_ENABLE "enable tpws transparent mode ?" "TPWS_PORTS TPWS_OPT" tpws_opt_validate TPWS_OPT
}
select_mode_nfqws()
{
local EDITVAR_NEWLINE_DELIMETER="--new" EDITVAR_NEWLINE_VARS="NFQWS_OPT"
select_mode_group NFQWS_ENABLE "enable nfqws ?" "NFQWS_PORTS_TCP NFQWS_PORTS_UDP NFQWS_TCP_PKT_OUT NFQWS_TCP_PKT_IN NFQWS_UDP_PKT_OUT NFQWS_UDP_PKT_IN NFQWS_PORTS_TCP_KEEPALIVE NFQWS_PORTS_UDP_KEEPALIVE NFQWS_OPT" ws_opt_validate NFQWS_OPT
select_mode_group NFQWS_ENABLE "enable nfqws ?" "NFQWS_PORTS_TCP NFQWS_PORTS_UDP NFQWS_TCP_PKT_OUT NFQWS_TCP_PKT_IN NFQWS_UDP_PKT_OUT NFQWS_UDP_PKT_IN NFQWS_PORTS_TCP_KEEPALIVE NFQWS_PORTS_UDP_KEEPALIVE NFQWS_OPT" nfqws_opt_validate NFQWS_OPT
}
select_mode_mode()
@@ -268,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=
@@ -364,13 +388,13 @@ 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"
cp -R "$1/files/fake" "$2/files"
cp -R "$1/common" "$1/ipset" "$2"
cp -R "$1/init.d/openwrt" "$2/init.d"
cp -R "$1/init.d/openwrt" "$1/init.d/custom.d.examples.linux" "$2/init.d"
cp "$1/config" "$1/config.default" "$1/install_easy.sh" "$1/uninstall_easy.sh" "$1/install_bin.sh" "$1/install_prereq.sh" "$1/blockcheck.sh" "$2"
cp "$BINDIR/tpws" "$BINDIR/nfqws" "$BINDIR/ip2net" "$BINDIR/mdig" "$2/binaries/$ARCH"
}
@@ -458,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"
@@ -700,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
@@ -748,7 +772,6 @@ deoffload_openwrt_firewall()
else
echo system wide software flow offloading disabled. ok
fi
}

View File

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

View File

@@ -192,7 +192,7 @@ static void ip6_and(const struct in6_addr * restrict a, const struct in6_addr *
static void rtrim(char *s)
{
if (s)
for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0';
for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'); p--) *p = '\0';
}
@@ -217,6 +217,14 @@ static void exithelp(void)
exit(1);
}
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
#else
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif
static void parse_params(int argc, char *argv[])
{
int option_index = 0;
@@ -245,6 +253,7 @@ static void parse_params(int argc, char *argv[])
{
case 0:
case 1:
PRINT_VER;
exithelp();
break;
case 2:

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

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

View File

@@ -35,7 +35,7 @@
static void trimstr(char *s)
{
char *p;
for (p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0';
for (p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'); p--) *p = '\0';
}
static const char* eai_str(int r)
@@ -458,6 +458,15 @@ static void exithelp(void)
);
exit(1);
}
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
#else
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif
int main(int argc, char **argv)
{
int r, v, option_index = 0;
@@ -487,6 +496,7 @@ int main(int argc, char **argv)
switch (option_index)
{
case 0: /* help */
PRINT_VER;
exithelp();
break;
case 1: /* threads */

View File

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

View File

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

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,26 +63,9 @@ 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
static uint8_t zeropkt[DPI_DESYNC_MAX_FAKE_LEN];
void desync_init(void)
{
memset(zeropkt, 0, sizeof(zeropkt));
}
bool desync_valid_zero_stage(enum dpi_desync_mode mode)
{
return mode==DESYNC_SYNACK || mode==DESYNC_SYNDATA;
@@ -374,7 +357,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
{
@@ -619,6 +603,40 @@ 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, size_t encap_len, uint8_t *fake_mod)
{
bool b=false;
if (dp->fake_tls_mod & FAKE_TLS_MOD_PADENCAP)
{
size_t sz_rec = pntoh16(dp->fake_tls+3) + encap_len;
size_t sz_handshake = pntoh24(dp->fake_tls+6) + encap_len;
size_t sz_ext = pntoh16(dp->fake_tls+dp->fake_tls_extlen_offset) + encap_len;
size_t sz_pad = pntoh16(dp->fake_tls+dp->fake_tls_padlen_offset) + encap_len;
if ((sz_rec & ~0xFFFF) || (sz_handshake & ~0xFFFFFF) || (sz_ext & ~0xFFFF) || (sz_pad & ~0xFFFF))
DLOG("cannot apply 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;
}
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;
@@ -862,6 +880,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)
{
@@ -1082,7 +1101,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
}
ttl_fake = (ctrack_replay && ctrack_replay->autottl) ? ctrack_replay->autottl : (dis->ip6 ? (dp->desync_ttl6 ? dp->desync_ttl6 : ttl_orig) : (dp->desync_ttl ? dp->desync_ttl : ttl_orig));
if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase) && HttpFindHost(&phost,dis->data_payload,dis->len_payload))
if ((l7proto == HTTP) && (dp->hostcase || dp->hostnospace || dp->domcase || dp->methodeol) && HttpFindHost(&phost,dis->data_payload,dis->len_payload))
{
if (dp->hostcase)
{
@@ -1098,23 +1117,40 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
verdict=VERDICT_MODIFY;
}
uint8_t *pua;
if (dp->hostnospace &&
(pua = (uint8_t*)memmem(dis->data_payload, dis->len_payload, "\r\nUser-Agent: ", 14)) &&
(pua = (uint8_t*)memmem(pua + 1, dis->len_payload - (pua - dis->data_payload) - 1, "\r\n", 2)))
if (dp->hostnospace)
{
DLOG("removing space after Host: and adding it to User-Agent:\n");
if (pua > phost)
if ((pua = (uint8_t*)memmem(dis->data_payload, dis->len_payload, "\r\nUser-Agent: ", 14)) &&
(pua = (uint8_t*)memmem(pua + 1, dis->len_payload - (pua - dis->data_payload) - 1, "\r\n", 2)))
{
memmove(phost + 5, phost + 6, pua - phost - 6);
pua[-1]=' ';
DLOG("removing space after Host: and adding it to User-Agent:\n");
if (pua > phost)
{
memmove(phost + 5, phost + 6, pua - phost - 6);
pua[-1]=' ';
}
else
{
memmove(pua + 1, pua, phost - pua + 5);
*pua = ' ';
}
verdict=VERDICT_MODIFY;
}
else
{
memmove(pua + 1, pua, phost - pua + 5);
*pua = ' ';
}
verdict=VERDICT_MODIFY;
DLOG("cannot do hostnospace because valid User-Agent: not found\n");
}
else if (dp->methodeol)
{
if (phost[5]==' ' || phost[5]=='\t')
{
DLOG("removing space after Host: and adding '\\n' before method\n");
memmove(dis->data_payload+1,dis->data_payload,phost-dis->data_payload+5);
dis->data_payload[0]='\n';
verdict=VERDICT_MODIFY;
}
else
DLOG("cannot do methodeol because there's no space or tab after Host:\n");
}
}
if (dp->desync_mode==DESYNC_NONE)
@@ -1138,7 +1174,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,rlen_payload,fake_mod) ? fake_mod : dp->fake_tls;
fake_size = dp->fake_tls_size;
break;
default:
@@ -1317,7 +1353,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)
@@ -1432,10 +1468,17 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_FAKEDDISORDER:
if (split_pos)
{
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg;
size_t seg_len;
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100], fakeseg2[DPI_DESYNC_MAX_FAKE_LEN+100], pat[DPI_DESYNC_MAX_FAKE_LEN], *seg;
size_t seg_len,fakeseg2_len;
unsigned int seqovl;
if (dis->len_payload > sizeof(pat))
{
DLOG("packet is too large\n");
return verdict;
}
fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern));
ip_id = IP4_IP_ID_FIX(dis->ip);
if (seqovl_pos>=split_pos)
@@ -1463,6 +1506,19 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
seg = dis->data_payload+split_pos;
seg_len = dis->len_payload-split_pos;
}
fakeseg2_len = sizeof(fakeseg2);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
pat+split_pos, dis->len_payload-split_pos, fakeseg2, &fakeseg2_len))
return verdict;
ip_id=IP4_IP_ID_PREV(ip_id);
DLOG("sending fake(1) 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg2, fakeseg2_len))
return verdict;
pkt1_len = sizeof(pkt1);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq , split_pos - seqovl), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
ttl_orig,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
@@ -1475,15 +1531,23 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
return verdict;
if (dis->ip) ((struct ip*)fakeseg2)->ip_id = ip_id;
ip_id=IP4_IP_ID_PREV(ip_id);
DLOG("sending fake(2) 2nd out-of-order tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg2, fakeseg2_len))
return verdict;
seg_len = sizeof(fakeseg);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
zeropkt, split_pos, fakeseg, &seg_len))
pat, split_pos, fakeseg, &seg_len))
return verdict;
ip_id=IP4_IP_ID_PREV(ip_id);
DLOG("sending fake(1) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len))
return verdict;
@@ -1501,7 +1565,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
DLOG("sending fake(2) 1st out-of-order tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, seg_len))
return verdict;
@@ -1511,24 +1575,31 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
case DESYNC_FAKEDSPLIT:
if (split_pos)
{
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100],ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100], *seg;
uint8_t fakeseg[DPI_DESYNC_MAX_FAKE_LEN+100],ovlseg[DPI_DESYNC_MAX_FAKE_LEN+100],pat[DPI_DESYNC_MAX_FAKE_LEN], *seg;
size_t fakeseg_len,seg_len;
if (dis->len_payload > sizeof(pat))
{
DLOG("packet is too large\n");
return verdict;
}
fill_pattern(pat,dis->len_payload,dp->fsplit_pattern,sizeof(dp->fsplit_pattern));
ip_id = IP4_IP_ID_FIX(dis->ip);
fakeseg_len = sizeof(fakeseg);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, dis->tcp->th_seq, dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
zeropkt, split_pos, fakeseg, &fakeseg_len))
pat, split_pos, fakeseg, &fakeseg_len))
return verdict;
ip_id=IP4_IP_ID_NEXT(ip_id);
DLOG("sending fake(1) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
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)
@@ -1579,7 +1650,19 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
ip_id=IP4_IP_ID_NEXT(ip_id);
DLOG("sending fake(2) 1st tcp segment 0-%zu len=%zu : ",split_pos-1, split_pos);
hexdump_limited_dlog(zeropkt,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
hexdump_limited_dlog(pat,split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
return verdict;
fakeseg_len = sizeof(fakeseg);
if (!prepare_tcp_segment((struct sockaddr *)&src, (struct sockaddr *)&dst, flags_orig, net32_add(dis->tcp->th_seq,split_pos), dis->tcp->th_ack, dis->tcp->th_win, scale_factor, timestamps,
ttl_fake,IP4_TOS(dis->ip),ip_id,IP6_FLOW(dis->ip6),
dp->desync_fooling_mode,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
pat+split_pos, dis->len_payload-split_pos, fakeseg, &fakeseg_len))
return verdict;
ip_id=IP4_IP_ID_NEXT(ip_id);
DLOG("sending fake(1) 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
return verdict;
@@ -1589,11 +1672,19 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
fooling_orig,dp->desync_badseq_increment,dp->desync_badseq_ack_increment,
dis->data_payload+split_pos, dis->len_payload-split_pos, pkt1, &pkt1_len))
return verdict;
ip_id=IP4_IP_ID_NEXT(ip_id);
DLOG("sending 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
hexdump_limited_dlog(dis->data_payload+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend((struct sockaddr *)&dst, desync_fwmark, ifout , pkt1, pkt1_len))
return verdict;
if (dis->ip) ((struct ip*)fakeseg)->ip_id = ip_id;
DLOG("sending fake(2) 2nd tcp segment %zu-%zu len=%zu : ",split_pos,dis->len_payload-1, dis->len_payload-split_pos);
hexdump_limited_dlog(pat+split_pos,dis->len_payload-split_pos,PKTDATA_MAXDUMP); DLOG("\n");
if (!rawsend_rep(dp->desync_repeats,(struct sockaddr *)&dst, desync_fwmark, ifout , fakeseg, fakeseg_len))
return verdict;
return VERDICT_DROP;
}
break;

View File

@@ -52,5 +52,4 @@ bool desync_valid_second_stage(enum dpi_desync_mode mode);
bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode);
bool desync_valid_second_stage_udp(enum dpi_desync_mode mode);
void desync_init(void);
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt);

View File

@@ -65,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

@@ -300,6 +300,18 @@ 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 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,6 +68,14 @@ 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);
typedef struct

View File

@@ -24,7 +24,7 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
*hostlist = NULL;
return false;
}
(*ct)++;
if (ct) (*ct)++;
}
// advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
@@ -32,6 +32,11 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
return true;
}
bool AppendHostlistItem(strpool **hostlist, char *s)
{
return addpool(hostlist,&s,s+strlen(s),NULL);
}
bool AppendHostList(strpool **hostlist, const char *filename)
{
char *p, *e, s[256], *zbuf;
@@ -98,21 +103,24 @@ bool AppendHostList(strpool **hostlist, const char *filename)
static bool LoadHostList(struct hostlist_file *hfile)
{
time_t t = file_mod_time(hfile->filename);
if (!t)
{
// stat() error
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
StrPoolDestroy(&hfile->hostlist);
if (!AppendHostList(&hfile->hostlist, hfile->filename))
if (hfile->filename)
{
file_mod_sig fsig;
if (!file_mod_signature(hfile->filename, &fsig))
{
// stat() error
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
StrPoolDestroy(&hfile->hostlist);
return false;
if (!AppendHostList(&hfile->hostlist, hfile->filename))
{
StrPoolDestroy(&hfile->hostlist);
return false;
}
hfile->mod_sig=fsig;
}
hfile->mod_time=t;
return true;
}
static bool LoadHostLists(struct hostlist_files_head *list)
@@ -202,7 +210,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
LIST_FOREACH(item, hostlists_exclude, next)
{
DLOG("[%s] exclude ", item->hfile->filename);
DLOG("[%s] exclude ", item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchHostList(item->hfile->hostlist, host))
{
if (excluded) *excluded = true;
@@ -214,7 +222,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
{
LIST_FOREACH(item, hostlists, next)
{
DLOG("[%s] include ", item->hfile->filename);
DLOG("[%s] include ", item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchHostList(item->hfile->hostlist, host))
return true;
}
@@ -235,17 +243,29 @@ bool HostlistCheck(const struct desync_profile *dp, const char *host, bool *excl
static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
{
struct hostlist_file *hfile;
if (!(hfile=hostlist_files_search(hostlists, filename)))
if (!(hfile=hostlist_files_add(hostlists, filename)))
if (filename)
{
if (!(hfile=hostlist_files_search(hostlists, filename)))
if (!(hfile=hostlist_files_add(hostlists, filename)))
return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile))
return NULL;
}
else
{
if (!(hfile=hostlist_files_add(hostlists, NULL)))
return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile))
return NULL;
}
return hfile;
}
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
{
if (!file_mod_time(filename))
if (filename && !file_mod_time(filename))
{
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
return NULL;
@@ -265,15 +285,30 @@ void HostlistsDebug()
struct hostlist_item *hl_item;
LIST_FOREACH(hfile, &params.hostlists, next)
DLOG("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
{
if (hfile->filename)
DLOG("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
else
DLOG("hostlist fixed%s\n",hfile->hostlist ? "" : " (empty)");
}
LIST_FOREACH(dpl, &params.desync_profiles, next)
{
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
if (hl_item->hfile!=dpl->dp.hostlist_auto)
DLOG("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
{
if (hl_item->hfile->filename)
DLOG("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
else
DLOG("profile %d include fixed hostlist%s\n",dpl->dp.n, hl_item->hfile->hostlist ? "" : " (empty)");
}
LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next)
DLOG("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
{
if (hl_item->hfile->filename)
DLOG("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
else
DLOG("profile %d exclude fixed hostlist%s\n",dpl->dp.n,hl_item->hfile->hostlist ? "" : " (empty)");
}
if (dpl->dp.hostlist_auto)
DLOG("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
}

View File

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

@@ -31,7 +31,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips);
return false;
}
(*ct)++;
if (ct) (*ct)++;
}
else if (parse_cidr6(cidr,&c6))
{
@@ -40,7 +40,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips);
return false;
}
(*ct)++;
if (ct) (*ct)++;
}
else
DLOG_ERR("bad ip or subnet : %s\n",cidr);
@@ -53,6 +53,11 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
}
bool AppendIpsetItem(ipset *ips, char *ip)
{
return addpool(ips,&ip,ip+strlen(ip),NULL);
}
static bool AppendIpset(ipset *ips, const char *filename)
{
char *p, *e, s[256], *zbuf;
@@ -119,21 +124,24 @@ static bool AppendIpset(ipset *ips, const char *filename)
static bool LoadIpset(struct ipset_file *hfile)
{
time_t t = file_mod_time(hfile->filename);
if (!t)
{
// stat() error
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
ipsetDestroy(&hfile->ipset);
if (!AppendIpset(&hfile->ipset, hfile->filename))
if (hfile->filename)
{
file_mod_sig fsig;
if (!file_mod_signature(hfile->filename, &fsig))
{
// stat() error
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
ipsetDestroy(&hfile->ipset);
return false;
if (!AppendIpset(&hfile->ipset, hfile->filename))
{
ipsetDestroy(&hfile->ipset);
return false;
}
hfile->mod_sig=fsig;
}
hfile->mod_time=t;
return true;
}
static bool LoadIpsets(struct ipset_files_head *list)
@@ -205,7 +213,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
LIST_FOREACH(item, ips_exclude, next)
{
DLOG("[%s] exclude ",item->hfile->filename);
DLOG("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return false;
}
@@ -214,7 +222,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
{
LIST_FOREACH(item, ips, next)
{
DLOG("[%s] include ",item->hfile->filename);
DLOG("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return true;
}
@@ -234,17 +242,27 @@ bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, con
static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
{
struct ipset_file *hfile;
if (!(hfile=ipset_files_search(ipsets, filename)))
if (!(hfile=ipset_files_add(ipsets, filename)))
if (filename)
{
if (!(hfile=ipset_files_search(ipsets, filename)))
if (!(hfile=ipset_files_add(ipsets, filename)))
return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile))
return NULL;
}
else
{
if (!(hfile=ipset_files_add(ipsets, NULL)))
return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile))
return NULL;
}
return hfile;
}
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename)
{
if (!file_mod_time(filename))
if (filename && !file_mod_time(filename))
{
DLOG_ERR("cannot access ipset file '%s'\n",filename);
return NULL;
@@ -277,13 +295,24 @@ void IpsetsDebug()
struct ipset_item *ips_item;
LIST_FOREACH(hfile, &params.ipsets, next)
DLOG("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
{
if (hfile->filename)
DLOG("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
else
DLOG("ipset fixed (%s)\n",dbg_ipset_fill(&hfile->ipset));
}
LIST_FOREACH(dpl, &params.desync_profiles, next)
{
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next)
DLOG("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
if (ips_item->hfile->filename)
DLOG("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
else
DLOG("profile %d include fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next)
DLOG("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
if (ips_item->hfile->filename)
DLOG("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
else
DLOG("profile %d exclude fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
}
}

View File

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

@@ -170,45 +170,49 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
if (bcut) DLOG(" ...");
}
void dp_init(struct desync_profile *dp)
{
LIST_INIT(&dp->hl_collection);
LIST_INIT(&dp->hl_collection_exclude);
LIST_INIT(&dp->ips_collection);
LIST_INIT(&dp->ips_collection_exclude);
LIST_INIT(&dp->pf_tcp);
LIST_INIT(&dp->pf_udp);
memcpy(dp->hostspell, "host", 4); // default hostspell
dp->desync_skip_nosni = true;
dp->desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT;
dp->desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT;
dp->desync_repeats = 1;
dp->fake_tls_size = sizeof(fake_tls_clienthello_default);
memcpy(dp->fake_tls,fake_tls_clienthello_default,dp->fake_tls_size);
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
dp->fake_quic[0] = 0x40; // russian TSPU QUIC short header fake
dp->fake_wg_size = 64;
dp->fake_dht_size = 64;
dp->fake_unknown_size = 256;
dp->fake_syndata_size = 16;
dp->fake_unknown_udp_size = 64;
dp->wscale=-1; // default - dont change scale factor (client)
dp->desync_ttl6 = 0xFF; // unused
dp->desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
dp->desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = 'n'; // packet number by default
dp->udplen_increment = UDPLEN_INCREMENT_DEFAULT;
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
dp->filter_ipv4 = dp->filter_ipv6 = true;
}
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
{
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
if (!entry) return NULL;
LIST_INIT(&entry->dp.hl_collection);
LIST_INIT(&entry->dp.hl_collection_exclude);
LIST_INIT(&entry->dp.ips_collection);
LIST_INIT(&entry->dp.ips_collection_exclude);
LIST_INIT(&entry->dp.pf_tcp);
LIST_INIT(&entry->dp.pf_udp);
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
entry->dp.desync_skip_nosni = true;
entry->dp.desync_ipfrag_pos_udp = IPFRAG_UDP_DEFAULT;
entry->dp.desync_ipfrag_pos_tcp = IPFRAG_TCP_DEFAULT;
entry->dp.desync_repeats = 1;
entry->dp.fake_tls_size = sizeof(fake_tls_clienthello_default);
memcpy(entry->dp.fake_tls,fake_tls_clienthello_default,entry->dp.fake_tls_size);
randomize_default_tls_payload(entry->dp.fake_tls);
entry->dp.fake_http_size = strlen(fake_http_request_default);
memcpy(entry->dp.fake_http,fake_http_request_default,entry->dp.fake_http_size);
entry->dp.fake_quic_size = 620; // must be 601+ for TSPU hack
entry->dp.fake_quic[0] = 0x40; // russian TSPU QUIC short header fake
entry->dp.fake_wg_size = 64;
entry->dp.fake_dht_size = 64;
entry->dp.fake_unknown_size = 256;
entry->dp.fake_syndata_size = 16;
entry->dp.fake_unknown_udp_size = 64;
entry->dp.wscale=-1; // default - dont change scale factor (client)
entry->dp.desync_ttl6 = 0xFF; // unused
entry->dp.desync_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
entry->dp.desync_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
entry->dp.wssize_cutoff_mode = entry->dp.desync_start_mode = entry->dp.desync_cutoff_mode = 'n'; // packet number by default
entry->dp.udplen_increment = UDPLEN_INCREMENT_DEFAULT;
entry->dp.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
entry->dp.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
entry->dp.hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
entry->dp.filter_ipv4 = entry->dp.filter_ipv6 = true;
dp_init(&entry->dp);
// add to the tail
struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles);
@@ -222,15 +226,24 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
return entry;
}
static void dp_entry_destroy(struct desync_profile_list *entry)
static void dp_clear_dynamic(struct desync_profile *dp)
{
hostlist_collection_destroy(&entry->dp.hl_collection);
hostlist_collection_destroy(&entry->dp.hl_collection_exclude);
ipset_collection_destroy(&entry->dp.ips_collection);
ipset_collection_destroy(&entry->dp.ips_collection_exclude);
port_filters_destroy(&entry->dp.pf_tcp);
port_filters_destroy(&entry->dp.pf_udp);
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters);
hostlist_collection_destroy(&dp->hl_collection);
hostlist_collection_destroy(&dp->hl_collection_exclude);
ipset_collection_destroy(&dp->ips_collection);
ipset_collection_destroy(&dp->ips_collection_exclude);
port_filters_destroy(&dp->pf_tcp);
port_filters_destroy(&dp->pf_udp);
HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
}
void dp_clear(struct desync_profile *dp)
{
dp_clear_dynamic(dp);
memset(dp,0,sizeof(*dp));
}
void dp_entry_destroy(struct desync_profile_list *entry)
{
dp_clear_dynamic(&entry->dp);
free(entry);
}
void dp_list_destroy(struct desync_profile_list_head *head)

View File

@@ -20,8 +20,6 @@
#define TLS_PARTIALS_ENABLE true
#define Q_RCVBUF (128*1024) // in bytes
#define Q_SNDBUF (64*1024) // in bytes
#define RAW_SNDBUF (64*1024) // in bytes
#define Q_MAXLEN 1024 // in packets
@@ -40,6 +38,13 @@
#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_RND_SNI 0x20
#define FAKE_TLS_MOD_PADENCAP 0x40
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
struct desync_profile
@@ -51,7 +56,7 @@ struct desync_profile
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int wssize_cutoff;
bool hostcase, hostnospace, domcase;
bool hostcase, hostnospace, domcase, methodeol;
char hostspell[4];
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
bool desync_retrans,desync_skip_nosni,desync_any_proto;
@@ -68,9 +73,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];
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;
@@ -99,8 +108,11 @@ struct desync_profile_list {
};
LIST_HEAD(desync_profile_list_head, desync_profile_list);
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
void dp_entry_destroy(struct desync_profile_list *entry);
void dp_list_destroy(struct desync_profile_list_head *head);
bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
void dp_init(struct desync_profile *dp);
void dp_clear(struct desync_profile *dp);
struct params_s
{

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,18 +154,22 @@ void strlist_destroy(struct str_list_head *head)
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename)
{
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
if (entry)
{
if (!(entry->filename = strdup(filename)))
if (filename)
{
free(entry);
return false;
if (!(entry->filename = strdup(filename)))
{
free(entry);
return false;
}
}
entry->mod_time=0;
else
entry->filename = NULL;
FILE_MOD_RESET(&entry->mod_sig);
entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next);
}
@@ -173,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);
}
@@ -192,11 +196,18 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
LIST_FOREACH(hfile, head, next)
{
if (!strcmp(hfile->filename,filename))
if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile;
}
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)
{
@@ -223,7 +234,7 @@ struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head
LIST_FOREACH(item, head, next)
{
if (!strcmp(item->hfile->filename,filename))
if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item;
}
return NULL;
@@ -369,12 +380,17 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
struct ipset_file *entry = malloc(sizeof(struct ipset_file));
if (entry)
{
if (!(entry->filename = strdup(filename)))
if (filename)
{
free(entry);
return false;
if (!(entry->filename = strdup(filename)))
{
free(entry);
return false;
}
}
entry->mod_time=0;
else
entry->filename = NULL;
FILE_MOD_RESET(&entry->mod_sig);
memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next);
}
@@ -382,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);
}
@@ -401,11 +417,18 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
LIST_FOREACH(hfile, head, next)
{
if (!strcmp(hfile->filename,filename))
if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile;
}
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)
{
@@ -432,7 +455,7 @@ struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, c
LIST_FOREACH(item, head, next)
{
if (!strcmp(item->hfile->filename,filename))
if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item;
}
return NULL;

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>
@@ -151,7 +153,7 @@ void ResolveMultiPos(const uint8_t *data, size_t sz, t_l7proto l7proto, const st
}
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL };
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS ","PUT /","DELETE /","CONNECT ","TRACE /",NULL };
const char *HttpMethod(const uint8_t *data, size_t len)
{
const char **method;
@@ -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

@@ -88,10 +88,6 @@ SYS_symlinkat,
SYS_link,
#endif
SYS_linkat,
#ifdef SYS_pkey_mprotect
SYS_pkey_mprotect,
#endif
SYS_mprotect,
SYS_truncate,
#ifdef SYS_truncate64
SYS_truncate64,

View File

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

View File

@@ -9,17 +9,17 @@ SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c
all: tpws
tpws: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES) $(LDFLAGS) $(LIBS)
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES) $(LIBS) $(LDFLAGS)
android: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES_ANDROID) $(LDFLAGS) $(LIBS_ANDROID)
$(CC) -s $(CFLAGS) -o tpws $(SRC_FILES_ANDROID) $(LIBS_ANDROID) $(LDFLAGS)
bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -o tpws $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -o tpws $(SRC_FILES) epoll-shim/src/*.c $(LIBS) $(LDFLAGS)
mac: $(SRC_FILES)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsa -target arm64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsx -target x86_64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsa -target arm64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LIBS) $(LDFLAGS)
$(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsx -target x86_64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LIBS) $(LDFLAGS)
strip tpwsa tpwsx
lipo -create -output tpws tpwsx tpwsa
rm -f tpwsx tpwsa

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

@@ -12,10 +12,6 @@
#include <libgen.h>
#include <unistd.h>
#ifdef __linux__
#include <linux/tcp.h>
#endif
#ifdef __ANDROID__
#include "andr/ifaddrs.h"
#else
@@ -23,6 +19,10 @@
#endif
#include "helpers.h"
#ifdef __linux__
#include <linux/tcp.h>
#endif
#include "linux_compat.h"
int unique_size_t(size_t *pu, int ct)
{
@@ -314,6 +314,18 @@ 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 pf_in_range(uint16_t port, const port_filter *pf)
{
@@ -481,7 +493,7 @@ void msleep(unsigned int ms)
bool socket_supports_notsent()
{
int sfd;
struct tcp_info tcpi;
struct tcp_info_new tcpi;
sfd = socket(AF_INET,SOCK_STREAM,0);
if (sfd<0) return false;
@@ -494,11 +506,11 @@ bool socket_supports_notsent()
}
close(sfd);
return ts>=((char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi.tcpi_state + sizeof(tcpi.tcpi_notsent_bytes));
return ts>=((char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi + sizeof(tcpi.tcpi_notsent_bytes));
}
bool socket_has_notsent(int sfd)
{
struct tcp_info tcpi;
struct tcp_info_new tcpi;
socklen_t ts = sizeof(tcpi);
if (getsockopt(sfd, IPPROTO_TCP, TCP_INFO, (char *)&tcpi, &ts) < 0)

View File

@@ -62,6 +62,14 @@ 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);
typedef struct

View File

@@ -24,7 +24,7 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
*hostlist = NULL;
return false;
}
(*ct)++;
if (ct) (*ct)++;
}
// advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
@@ -32,6 +32,11 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
return true;
}
bool AppendHostlistItem(strpool **hostlist, char *s)
{
return addpool(hostlist,&s,s+strlen(s),NULL);
}
bool AppendHostList(strpool **hostlist, const char *filename)
{
char *p, *e, s[256], *zbuf;
@@ -98,21 +103,24 @@ bool AppendHostList(strpool **hostlist, const char *filename)
static bool LoadHostList(struct hostlist_file *hfile)
{
time_t t = file_mod_time(hfile->filename);
if (!t)
{
// stat() error
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
StrPoolDestroy(&hfile->hostlist);
if (!AppendHostList(&hfile->hostlist, hfile->filename))
if (hfile->filename)
{
file_mod_sig fsig;
if (!file_mod_signature(hfile->filename, &fsig))
{
// stat() error
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
StrPoolDestroy(&hfile->hostlist);
return false;
if (!AppendHostList(&hfile->hostlist, hfile->filename))
{
StrPoolDestroy(&hfile->hostlist);
return false;
}
hfile->mod_sig=fsig;
}
hfile->mod_time=t;
return true;
}
static bool LoadHostLists(struct hostlist_files_head *list)
@@ -202,7 +210,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
LIST_FOREACH(item, hostlists_exclude, next)
{
VPRINT("[%s] exclude ", item->hfile->filename);
VPRINT("[%s] exclude ", item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchHostList(item->hfile->hostlist, host))
{
if (excluded) *excluded = true;
@@ -214,7 +222,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
{
LIST_FOREACH(item, hostlists, next)
{
VPRINT("[%s] include ", item->hfile->filename);
VPRINT("[%s] include ", item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchHostList(item->hfile->hostlist, host))
return true;
}
@@ -235,17 +243,29 @@ bool HostlistCheck(const struct desync_profile *dp, const char *host, bool *excl
static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
{
struct hostlist_file *hfile;
if (!(hfile=hostlist_files_search(hostlists, filename)))
if (!(hfile=hostlist_files_add(hostlists, filename)))
if (filename)
{
if (!(hfile=hostlist_files_search(hostlists, filename)))
if (!(hfile=hostlist_files_add(hostlists, filename)))
return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile))
return NULL;
}
else
{
if (!(hfile=hostlist_files_add(hostlists, NULL)))
return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile))
return NULL;
}
return hfile;
}
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
{
if (!file_mod_time(filename))
if (filename && !file_mod_time(filename))
{
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
return NULL;
@@ -265,15 +285,30 @@ void HostlistsDebug()
struct hostlist_item *hl_item;
LIST_FOREACH(hfile, &params.hostlists, next)
VPRINT("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
{
if (hfile->filename)
VPRINT("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
else
VPRINT("hostlist fixed%s\n",hfile->hostlist ? "" : " (empty)");
}
LIST_FOREACH(dpl, &params.desync_profiles, next)
{
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
if (hl_item->hfile!=dpl->dp.hostlist_auto)
VPRINT("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
{
if (hl_item->hfile->filename)
VPRINT("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
else
VPRINT("profile %d include fixed hostlist%s\n",dpl->dp.n, hl_item->hfile->hostlist ? "" : " (empty)");
}
LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next)
VPRINT("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
{
if (hl_item->hfile->filename)
VPRINT("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
else
VPRINT("profile %d exclude fixed hostlist%s\n",dpl->dp.n,hl_item->hfile->hostlist ? "" : " (empty)");
}
if (dpl->dp.hostlist_auto)
VPRINT("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
}

View File

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

@@ -31,7 +31,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips);
return false;
}
(*ct)++;
if (ct) (*ct)++;
}
else if (parse_cidr6(cidr,&c6))
{
@@ -40,7 +40,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips);
return false;
}
(*ct)++;
if (ct) (*ct)++;
}
else
DLOG_ERR("bad ip or subnet : %s\n",cidr);
@@ -53,6 +53,11 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
}
bool AppendIpsetItem(ipset *ips, char *ip)
{
return addpool(ips,&ip,ip+strlen(ip),NULL);
}
static bool AppendIpset(ipset *ips, const char *filename)
{
char *p, *e, s[256], *zbuf;
@@ -119,21 +124,24 @@ static bool AppendIpset(ipset *ips, const char *filename)
static bool LoadIpset(struct ipset_file *hfile)
{
time_t t = file_mod_time(hfile->filename);
if (!t)
{
// stat() error
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
ipsetDestroy(&hfile->ipset);
if (!AppendIpset(&hfile->ipset, hfile->filename))
if (hfile->filename)
{
file_mod_sig fsig;
if (!file_mod_signature(hfile->filename, &fsig))
{
// stat() error
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (FILE_MOD_COMPARE(&hfile->mod_sig,&fsig)) return true; // up to date
ipsetDestroy(&hfile->ipset);
return false;
if (!AppendIpset(&hfile->ipset, hfile->filename))
{
ipsetDestroy(&hfile->ipset);
return false;
}
hfile->mod_sig=fsig;
}
hfile->mod_time=t;
return true;
}
static bool LoadIpsets(struct ipset_files_head *list)
@@ -205,7 +213,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
LIST_FOREACH(item, ips_exclude, next)
{
VPRINT("[%s] exclude ",item->hfile->filename);
VPRINT("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return false;
}
@@ -214,7 +222,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
{
LIST_FOREACH(item, ips, next)
{
VPRINT("[%s] include ",item->hfile->filename);
VPRINT("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return true;
}
@@ -234,17 +242,27 @@ bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, con
static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
{
struct ipset_file *hfile;
if (!(hfile=ipset_files_search(ipsets, filename)))
if (!(hfile=ipset_files_add(ipsets, filename)))
if (filename)
{
if (!(hfile=ipset_files_search(ipsets, filename)))
if (!(hfile=ipset_files_add(ipsets, filename)))
return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile))
return NULL;
}
else
{
if (!(hfile=ipset_files_add(ipsets, NULL)))
return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile))
return NULL;
}
return hfile;
}
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename)
{
if (!file_mod_time(filename))
if (filename && !file_mod_time(filename))
{
DLOG_ERR("cannot access ipset file '%s'\n",filename);
return NULL;
@@ -277,13 +295,24 @@ void IpsetsDebug()
struct ipset_item *ips_item;
LIST_FOREACH(hfile, &params.ipsets, next)
VPRINT("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
{
if (hfile->filename)
VPRINT("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
else
VPRINT("ipset fixed (%s)\n",dbg_ipset_fill(&hfile->ipset));
}
LIST_FOREACH(dpl, &params.desync_profiles, next)
{
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next)
VPRINT("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
if (ips_item->hfile->filename)
VPRINT("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
else
VPRINT("profile %d include fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next)
VPRINT("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
if (ips_item->hfile->filename)
VPRINT("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
else
VPRINT("profile %d exclude fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
}
}

View File

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

111
tpws/linux_compat.h Normal file
View File

@@ -0,0 +1,111 @@
#ifdef __linux__
#include <linux/types.h>
#ifndef TCP_USER_TIMEOUT
#define TCP_USER_TIMEOUT 18
#endif
#ifndef IP6T_SO_ORIGINAL_DST
#define IP6T_SO_ORIGINAL_DST 80
#endif
#ifndef PR_SET_NO_NEW_PRIVS
#define PR_SET_NO_NEW_PRIVS 38
#endif
// workaround for old headers
struct tcp_info_new {
__u8 tcpi_state;
__u8 tcpi_ca_state;
__u8 tcpi_retransmits;
__u8 tcpi_probes;
__u8 tcpi_backoff;
__u8 tcpi_options;
__u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4;
__u8 tcpi_delivery_rate_app_limited : 1, tcpi_fastopen_client_fail : 2;
__u32 tcpi_rto;
__u32 tcpi_ato;
__u32 tcpi_snd_mss;
__u32 tcpi_rcv_mss;
__u32 tcpi_unacked;
__u32 tcpi_sacked;
__u32 tcpi_lost;
__u32 tcpi_retrans;
__u32 tcpi_fackets;
/* Times. */
__u32 tcpi_last_data_sent;
__u32 tcpi_last_ack_sent; /* Not remembered, sorry. */
__u32 tcpi_last_data_recv;
__u32 tcpi_last_ack_recv;
/* Metrics. */
__u32 tcpi_pmtu;
__u32 tcpi_rcv_ssthresh;
__u32 tcpi_rtt;
__u32 tcpi_rttvar;
__u32 tcpi_snd_ssthresh;
__u32 tcpi_snd_cwnd;
__u32 tcpi_advmss;
__u32 tcpi_reordering;
__u32 tcpi_rcv_rtt;
__u32 tcpi_rcv_space;
__u32 tcpi_total_retrans;
__u64 tcpi_pacing_rate;
__u64 tcpi_max_pacing_rate;
__u64 tcpi_bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked */
__u64 tcpi_bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived */
__u32 tcpi_segs_out; /* RFC4898 tcpEStatsPerfSegsOut */
__u32 tcpi_segs_in; /* RFC4898 tcpEStatsPerfSegsIn */
__u32 tcpi_notsent_bytes;
__u32 tcpi_min_rtt;
__u32 tcpi_data_segs_in; /* RFC4898 tcpEStatsDataSegsIn */
__u32 tcpi_data_segs_out; /* RFC4898 tcpEStatsDataSegsOut */
__u64 tcpi_delivery_rate;
__u64 tcpi_busy_time; /* Time (usec) busy sending data */
__u64 tcpi_rwnd_limited; /* Time (usec) limited by receive window */
__u64 tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */
__u32 tcpi_delivered;
__u32 tcpi_delivered_ce;
__u64 tcpi_bytes_sent; /* RFC4898 tcpEStatsPerfHCDataOctetsOut */
__u64 tcpi_bytes_retrans; /* RFC4898 tcpEStatsPerfOctetsRetrans */
__u32 tcpi_dsack_dups; /* RFC4898 tcpEStatsStackDSACKDups */
__u32 tcpi_reord_seen; /* reordering events seen */
__u32 tcpi_rcv_ooopack; /* Out-of-order packets received */
__u32 tcpi_snd_wnd; /* peer's advertised receive window after
* scaling (bytes)
*/
__u32 tcpi_rcv_wnd; /* local advertised receive window after
* scaling (bytes)
*/
__u32 tcpi_rehash; /* PLB or timeout triggered rehash attempts */
__u16 tcpi_total_rto; /* Total number of RTO timeouts, including
* SYN/SYN-ACK and recurring timeouts.
*/
__u16 tcpi_total_rto_recoveries; /* Total number of RTO
* recoveries, including any
* unfinished recovery.
*/
__u32 tcpi_total_rto_time; /* Total time spent in RTO recoveries
* in milliseconds, including any
* unfinished recovery.
*/
};
#endif

View File

@@ -155,22 +155,26 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
if (bcut) VPRINT(" ...");
}
void dp_init(struct desync_profile *dp)
{
LIST_INIT(&dp->hl_collection);
LIST_INIT(&dp->hl_collection_exclude);
LIST_INIT(&dp->ips_collection);
LIST_INIT(&dp->ips_collection_exclude);
LIST_INIT(&dp->pf_tcp);
dp->filter_ipv4 = dp->filter_ipv6 = true;
memcpy(dp->hostspell, "host", 4); // default hostspell
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
}
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
{
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
if (!entry) return NULL;
LIST_INIT(&entry->dp.hl_collection);
LIST_INIT(&entry->dp.hl_collection_exclude);
LIST_INIT(&entry->dp.ips_collection);
LIST_INIT(&entry->dp.ips_collection_exclude);
LIST_INIT(&entry->dp.pf_tcp);
entry->dp.filter_ipv4 = entry->dp.filter_ipv6 = true;
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
entry->dp.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
entry->dp.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
dp_init(&entry->dp);
// add to the tail
struct desync_profile_list *dpn,*dpl=LIST_FIRST(&params.desync_profiles);
@@ -184,14 +188,23 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
return entry;
}
static void dp_entry_destroy(struct desync_profile_list *entry)
static void dp_clear_dynamic(struct desync_profile *dp)
{
hostlist_collection_destroy(&entry->dp.hl_collection);
hostlist_collection_destroy(&entry->dp.hl_collection_exclude);
ipset_collection_destroy(&entry->dp.ips_collection);
ipset_collection_destroy(&entry->dp.ips_collection_exclude);
port_filters_destroy(&entry->dp.pf_tcp);
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters);
hostlist_collection_destroy(&dp->hl_collection);
hostlist_collection_destroy(&dp->hl_collection_exclude);
ipset_collection_destroy(&dp->ips_collection);
ipset_collection_destroy(&dp->ips_collection_exclude);
port_filters_destroy(&dp->pf_tcp);
HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
}
void dp_clear(struct desync_profile *dp)
{
dp_clear_dynamic(dp);
memset(dp,0,sizeof(*dp));
}
void dp_entry_destroy(struct desync_profile_list *entry)
{
dp_clear_dynamic(&entry->dp);
free(entry);
}
void dp_list_destroy(struct desync_profile_list_head *head)

View File

@@ -18,7 +18,7 @@
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
#define FIX_SEG_DEFAULT_MAX_WAIT 30
#define FIX_SEG_DEFAULT_MAX_WAIT 50
enum bindll { unwanted=0, no, prefer, force };
@@ -83,7 +83,10 @@ struct desync_profile_list {
};
LIST_HEAD(desync_profile_list_head, desync_profile_list);
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
void dp_entry_destroy(struct desync_profile_list *entry);
void dp_list_destroy(struct desync_profile_list_head *head);
void dp_init(struct desync_profile *dp);
void dp_clear(struct desync_profile *dp);
struct params_s
{

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,18 +154,22 @@ void strlist_destroy(struct str_list_head *head)
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename)
{
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
if (entry)
{
if (!(entry->filename = strdup(filename)))
if (filename)
{
free(entry);
return false;
if (!(entry->filename = strdup(filename)))
{
free(entry);
return false;
}
}
entry->mod_time=0;
else
entry->filename = NULL;
FILE_MOD_RESET(&entry->mod_sig);
entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next);
}
@@ -173,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);
}
@@ -192,11 +196,18 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
LIST_FOREACH(hfile, head, next)
{
if (!strcmp(hfile->filename,filename))
if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile;
}
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)
{
@@ -223,7 +234,7 @@ struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head
LIST_FOREACH(item, head, next)
{
if (!strcmp(item->hfile->filename,filename))
if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item;
}
return NULL;
@@ -369,12 +380,17 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
struct ipset_file *entry = malloc(sizeof(struct ipset_file));
if (entry)
{
if (!(entry->filename = strdup(filename)))
if (filename)
{
free(entry);
return false;
if (!(entry->filename = strdup(filename)))
{
free(entry);
return false;
}
}
entry->mod_time=0;
else
entry->filename = NULL;
FILE_MOD_RESET(&entry->mod_sig);
memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next);
}
@@ -382,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);
}
@@ -401,11 +417,18 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
LIST_FOREACH(hfile, head, next)
{
if (!strcmp(hfile->filename,filename))
if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile;
}
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)
{
@@ -432,7 +455,7 @@ struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, c
LIST_FOREACH(item, head, next)
{
if (!strcmp(item->hfile->filename,filename))
if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item;
}
return NULL;

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

@@ -151,7 +151,7 @@ void ResolveMultiPos(const uint8_t *data, size_t sz, t_l7proto l7proto, const st
}
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL };
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS ","PUT /","DELETE /","CONNECT ","TRACE /",NULL };
const char *HttpMethod(const uint8_t *data, size_t len)
{
const char **method;

View File

@@ -9,12 +9,10 @@
#include "params.h"
#include "helpers.h"
#include "linux_compat.h"
#ifdef __linux__
#include <linux/netfilter_ipv4.h>
#ifndef IP6T_SO_ORIGINAL_DST
#define IP6T_SO_ORIGINAL_DST 80
#endif
#endif

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)
@@ -175,16 +196,23 @@ static void exithelp(void)
#endif
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
" --debug-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"
" --comment=any_text\n"
"\nMULTI-STRATEGY:\n"
" --new\t\t\t\t\t; begin new strategy\n"
" --skip\t\t\t\t\t; do not use this strategy\n"
" --filter-l3=ipv4|ipv6\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
" --filter-tcp=[~]port1[-port2]|*\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n"
" --filter-l7=[http|tls|unknown]\t\t; L6-L7 protocol filter. multiple comma separated values allowed.\n"
" --ipset=<filename>\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
" --ipset-ip=<ip_list>\t\t\t; comma separated fixed subnet list\n"
" --ipset-exclude=<filename>\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
" --ipset-exclude-ip=<ip_list>\t\t; comma separated fixed subnet list\n"
"\nHOSTLIST FILTER:\n"
" --hostlist=<filename>\t\t\t; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
" --hostlist-domains=<domain_list>\t; comma separated fixed domain list\n"
" --hostlist-exclude=<filename>\t\t; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
" --hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list\n"
" --hostlist-auto=<filename>\t\t; detect DPI blocks and build hostlist automatically\n"
" --hostlist-auto-fail-threshold=<int>\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
" --hostlist-auto-fail-time=<int>\t; all failed attemps must be within these seconds (default : %d)\n"
@@ -483,6 +511,46 @@ static bool parse_pf_list(char *opt, struct port_filters_head *pfl)
return true;
}
static bool parse_domain_list(char *opt, strpool **pp)
{
char *e,*p,c;
for (p=opt ; p ; )
{
if ((e = strchr(p,',')))
{
c=*e;
*e=0;
}
if (*p && !AppendHostlistItem(pp,p)) return false;
if (e) *e++=c;
p = e;
}
return true;
}
static bool parse_ip_list(char *opt, ipset *pp)
{
char *e,*p,c;
for (p=opt ; p ; )
{
if ((e = strchr(p,',')))
{
c=*e;
*e=0;
}
if (*p && !AppendIpsetItem(pp,p)) return false;
if (e) *e++=c;
p = e;
}
return true;
}
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
// no static to not allow optimizer to inline this func (save stack)
void config_from_file(const char *filename)
@@ -524,6 +592,9 @@ void parse_params(int argc, char *argv[])
{
int option_index = 0;
int v, i;
bool bSkip=false, bDry=false;
struct hostlist_file *anon_hl = NULL, *anon_hl_exclude = NULL;
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
memset(&params, 0, sizeof(params));
params.maxconn = DEFAULT_MAX_CONN;
@@ -609,45 +680,52 @@ void parse_params(int argc, char *argv[])
{ "tlsrec",required_argument,0,0 },// optidx=34
{ "tlsrec-pos",required_argument,0,0 },// optidx=35
{ "hostlist",required_argument,0,0 },// optidx=36
{ "hostlist-exclude",required_argument,0,0 },// optidx=37
{ "hostlist-auto",required_argument,0,0}, // optidx=38
{ "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=39
{ "hostlist-auto-fail-time",required_argument,0,0}, // optidx=40
{ "hostlist-auto-debug",required_argument,0,0}, // optidx=41
{ "pidfile",required_argument,0,0 },// optidx=42
{ "debug",optional_argument,0,0 },// optidx=43
{ "debug-level",required_argument,0,0 },// optidx=44
{ "local-rcvbuf",required_argument,0,0 },// optidx=45
{ "local-sndbuf",required_argument,0,0 },// optidx=46
{ "remote-rcvbuf",required_argument,0,0 },// optidx=47
{ "remote-sndbuf",required_argument,0,0 },// optidx=48
{ "socks",no_argument,0,0 },// optidx=40
{ "no-resolve",no_argument,0,0 },// optidx=50
{ "resolver-threads",required_argument,0,0 },// optidx=51
{ "skip-nodelay",no_argument,0,0 },// optidx=52
{ "tamper-start",required_argument,0,0 },// optidx=53
{ "tamper-cutoff",required_argument,0,0 },// optidx=54
{ "connect-bind-addr",required_argument,0,0 },// optidx=55
{ "hostlist-domains",required_argument,0,0 },// optidx=37
{ "hostlist-exclude",required_argument,0,0 },// optidx=38
{ "hostlist-exclude-domains",required_argument,0,0 },// optidx=39
{ "hostlist-auto",required_argument,0,0}, // optidx=40
{ "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=41
{ "hostlist-auto-fail-time",required_argument,0,0}, // optidx=42
{ "hostlist-auto-debug",required_argument,0,0}, // optidx=43
{ "pidfile",required_argument,0,0 },// optidx=44
{ "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
{ "new",no_argument,0,0 }, // optidx=56
{ "filter-l3",required_argument,0,0 }, // optidx=57
{ "filter-tcp",required_argument,0,0 }, // optidx=58
{ "filter-l7",required_argument,0,0 }, // optidx=59
{ "ipset",required_argument,0,0 }, // optidx=60
{ "ipset-exclude",required_argument,0,0 }, // optidx=61
{ "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
#if defined(__FreeBSD__)
{ "enable-pf",no_argument,0,0 },// optidx=62
{ "enable-pf",no_argument,0,0 },// optidx=69
#elif defined(__APPLE__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=69
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=70
#elif defined(__linux__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63
{ "mss",required_argument,0,0 }, // optidx=64
{ "fix-seg",optional_argument,0,0 }, // optidx=65
{ "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
#ifdef SPLICE_PRESENT
{ "nosplice",no_argument,0,0 }, // optidx=66
{ "nosplice",no_argument,0,0 }, // optidx=73
#endif
#endif
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
@@ -655,7 +733,13 @@ void parse_params(int argc, char *argv[])
};
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp_clean();
if (v)
{
if (bDry)
exit_clean(1);
else
exithelp_clean();
}
switch (option_index)
{
case 0:
@@ -945,6 +1029,7 @@ void parse_params(int argc, char *argv[])
params.tamper = true;
break;
case 36: /* hostlist */
if (bSkip) break;
if (!RegisterHostlist(dp, false, optarg))
{
DLOG_ERR("failed to register hostlist '%s'\n", optarg);
@@ -952,7 +1037,22 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 37: /* hostlist-exclude */
case 37: /* hostlist-domains */
if (bSkip) break;
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
{
DLOG_ERR("failed to register anonymous hostlist\n");
exit_clean(1);
}
if (!parse_domain_list(optarg, &anon_hl->hostlist))
{
DLOG_ERR("failed to add domains to anonymous hostlist\n");
exit_clean(1);
}
params.tamper = true;
break;
case 38: /* hostlist-exclude */
if (bSkip) break;
if (!RegisterHostlist(dp, true, optarg))
{
DLOG_ERR("failed to register hostlist '%s'\n", optarg);
@@ -960,7 +1060,22 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 38: /* hostlist-auto */
case 39: /* hostlist-exclude-domains */
if (bSkip) break;
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
{
DLOG_ERR("failed to register anonymous hostlist\n");
exit_clean(1);
}
if (!parse_domain_list(optarg, &anon_hl_exclude->hostlist))
{
DLOG_ERR("failed to add domains to anonymous hostlist\n");
exit_clean(1);
}
params.tamper = true;
break;
case 40: /* hostlist-auto */
if (bSkip) break;
if (dp->hostlist_auto)
{
DLOG_ERR("only one auto hostlist per profile is supported\n");
@@ -988,7 +1103,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
break;
case 39: /* hostlist-auto-fail-threshold */
case 41: /* hostlist-auto-fail-threshold */
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
{
@@ -996,7 +1111,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 40: /* hostlist-auto-fail-time */
case 42: /* hostlist-auto-fail-time */
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_time<1)
{
@@ -1004,7 +1119,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 41: /* hostlist-auto-debug */
case 43: /* hostlist-auto-debug */
{
FILE *F = fopen(optarg,"a+t");
if (!F)
@@ -1017,11 +1132,11 @@ void parse_params(int argc, char *argv[])
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
}
break;
case 42: /* pidfile */
case 44: /* pidfile */
strncpy(params.pidfile,optarg,sizeof(params.pidfile));
params.pidfile[sizeof(params.pidfile)-1]='\0';
break;
case 43: /* debug */
case 45: /* debug */
if (optarg)
{
if (*optarg=='@')
@@ -1055,44 +1170,49 @@ void parse_params(int argc, char *argv[])
params.debug_target = LOG_TARGET_CONSOLE;
}
break;
case 44: /* debug-level */
case 46: /* debug-level */
params.debug = atoi(optarg);
break;
case 45: /* local-rcvbuf */
case 47: /* dry-run */
bDry = true;
break;
case 48: /* comment */
break;
case 49: /* local-rcvbuf */
#ifdef __linux__
params.local_rcvbuf = atoi(optarg)/2;
#else
params.local_rcvbuf = atoi(optarg);
#endif
break;
case 46: /* local-sndbuf */
case 50: /* local-sndbuf */
#ifdef __linux__
params.local_sndbuf = atoi(optarg)/2;
#else
params.local_sndbuf = atoi(optarg);
#endif
break;
case 47: /* remote-rcvbuf */
case 51: /* remote-rcvbuf */
#ifdef __linux__
params.remote_rcvbuf = atoi(optarg)/2;
#else
params.remote_rcvbuf = atoi(optarg);
#endif
break;
case 48: /* remote-sndbuf */
case 52: /* remote-sndbuf */
#ifdef __linux__
params.remote_sndbuf = atoi(optarg)/2;
#else
params.remote_sndbuf = atoi(optarg);
#endif
break;
case 49: /* socks */
case 53: /* socks */
params.proxy_type = CONN_TYPE_SOCKS;
break;
case 50: /* no-resolve */
case 54: /* no-resolve */
params.no_resolve = true;
break;
case 51: /* resolver-threads */
case 55: /* resolver-threads */
params.resolver_threads = atoi(optarg);
if (params.resolver_threads<1 || params.resolver_threads>300)
{
@@ -1100,10 +1220,10 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 52: /* skip-nodelay */
case 56: /* skip-nodelay */
params.skip_nodelay = true;
break;
case 53: /* tamper-start */
case 57: /* tamper-start */
{
const char *p=optarg;
if (*p=='n')
@@ -1117,7 +1237,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper_lim = true;
break;
case 54: /* tamper-cutoff */
case 58: /* tamper-cutoff */
{
const char *p=optarg;
if (*p=='n')
@@ -1131,7 +1251,7 @@ void parse_params(int argc, char *argv[])
}
params.tamper_lim = true;
break;
case 55: /* connect-bind-addr */
case 59: /* connect-bind-addr */
{
char *p = strchr(optarg,'%');
if (p) *p++=0;
@@ -1159,37 +1279,53 @@ void parse_params(int argc, char *argv[])
break;
case 56: /* new */
if (!(dpl = dp_list_add(&params.desync_profiles)))
case 60: /* new */
if (bSkip)
{
DLOG_ERR("desync_profile_add: out of memory\n");
exit_clean(1);
dp_clear(dp);
dp_init(dp);
dp->n = desync_profile_count;
bSkip = false;
}
dp = &dpl->dp;
dp->n = ++desync_profile_count;
else
{
if (!(dpl = dp_list_add(&params.desync_profiles)))
{
DLOG_ERR("desync_profile_add: out of memory\n");
exit_clean(1);
}
dp = &dpl->dp;
dp->n = ++desync_profile_count;
}
anon_hl = anon_hl_exclude = NULL;
anon_ips = anon_ips_exclude = NULL;
break;
case 57: /* filter-l3 */
case 61: /* skip */
bSkip = true;
break;
case 62: /* 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 58: /* filter-tcp */
case 63: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp))
{
DLOG_ERR("Invalid port filter : %s\n",optarg);
exit_clean(1);
}
break;
case 59: /* filter-l7 */
case 64: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7))
{
DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1);
}
break;
case 60: /* ipset */
case 65: /* ipset */
if (bSkip) break;
if (!RegisterIpset(dp, false, optarg))
{
DLOG_ERR("failed to register ipset '%s'\n", optarg);
@@ -1197,7 +1333,22 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 61: /* ipset-exclude */
case 66: /* ipset-ip */
if (bSkip) break;
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
{
DLOG_ERR("failed to register anonymous ipset\n");
exit_clean(1);
}
if (!parse_ip_list(optarg, &anon_ips->ipset))
{
DLOG_ERR("failed to add subnets to anonymous ipset\n");
exit_clean(1);
}
params.tamper = true;
break;
case 67: /* ipset-exclude */
if (bSkip) break;
if (!RegisterIpset(dp, true, optarg))
{
DLOG_ERR("failed to register ipset '%s'\n", optarg);
@@ -1205,13 +1356,27 @@ void parse_params(int argc, char *argv[])
}
params.tamper = true;
break;
case 68: /* ipset-exclude-ip */
if (bSkip) break;
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
{
DLOG_ERR("failed to register anonymous ipset\n");
exit_clean(1);
}
if (!parse_ip_list(optarg, &anon_ips_exclude->ipset))
{
DLOG_ERR("failed to add subnets to anonymous ipset\n");
exit_clean(1);
}
params.tamper = true;
break;
#if defined(__FreeBSD__)
case 62: /* enable-pf */
case 69: /* enable-pf */
params.pf_enable = true;
break;
#elif defined(__linux__) || defined(__APPLE__)
case 62: /* local-tcp-user-timeout */
case 69: /* local-tcp-user-timeout */
params.tcp_user_timeout_local = atoi(optarg);
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
{
@@ -1219,7 +1384,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 63: /* remote-tcp-user-timeout */
case 70: /* remote-tcp-user-timeout */
params.tcp_user_timeout_remote = atoi(optarg);
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
{
@@ -1230,7 +1395,7 @@ void parse_params(int argc, char *argv[])
#endif
#if defined(__linux__)
case 64: /* mss */
case 71: /* 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)
@@ -1239,7 +1404,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1);
}
break;
case 65: /* fix-seg */
case 72: /* fix-seg */
if (!params.fix_seg_avail)
{
DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
@@ -1259,13 +1424,20 @@ void parse_params(int argc, char *argv[])
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
break;
#ifdef SPLICE_PRESENT
case 66: /* nosplice */
case 73: /* nosplice */
params.nosplice = true;
break;
#endif
#endif
}
}
if (bSkip)
{
LIST_REMOVE(dpl,next);
dp_entry_destroy(dpl);
desync_profile_count--;
}
if (!params.bind_wait_only && !params.port)
{
DLOG_ERR("Need port number\n");
@@ -1327,6 +1499,11 @@ void parse_params(int argc, char *argv[])
// do not need args from file anymore
cleanup_args();
#endif
if (bDry)
{
DLOG_CONDUP("command line parameters verified\n");
exit_clean(0);
}
}
@@ -1476,6 +1653,15 @@ struct salisten_s
int bind_wait_ip_left; // how much seconds left from bind_wait_ip
};
static const char *bindll_s[] = { "unwanted","no","prefer","force" };
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
#else
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif
int main(int argc, char *argv[])
{
int i, listen_fd[MAX_BINDS], yes = 1, retval = 0, if_index, exit_v=EXIT_FAILURE;
@@ -1486,6 +1672,8 @@ int main(int argc, char *argv[])
srand(time(NULL));
mask_from_preflen6_prepare();
PRINT_VER;
parse_params(argc, argv);
argv=NULL; argc=0;

View File

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

View File

@@ -23,6 +23,7 @@
#include "socks.h"
#include "helpers.h"
#include "hostlist.h"
#include "linux_compat.h"
// keep separate legs counter. counting every time thousands of legs can consume cpu
static int legs_local, legs_remote;
@@ -168,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)
{
@@ -485,7 +483,7 @@ static bool connect_remote_conn(tproxy_conn_t *conn)
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
if (conn->track.dp)
if (conn->track.dp && conn->track.dp->mss)
{
mss = conn->track.dp->mss;
if (conn->track.dp->hostlist_auto)
@@ -495,8 +493,11 @@ static bool connect_remote_conn(tproxy_conn_t *conn)
bool bHostExcluded;
conn->track.b_host_matches = HostlistCheck(conn->track.dp, conn->track.hostname, &bHostExcluded, false);
conn->track.b_host_checked = true;
if (!conn->track.b_host_matches) conn->track.b_ah_check = !bHostExcluded;
if (!conn->track.b_host_matches) mss = 0;
if (!conn->track.b_host_matches)
{
conn->track.b_ah_check = !bHostExcluded;
mss = 0;
}
}
}
}
@@ -516,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);
}
@@ -833,7 +834,6 @@ static bool proxy_mode_connect_remote(tproxy_conn_t *conn, struct tailhead *conn
return false;
}
if (!(conn->partner = new_conn(remote_fd, true)))
{
close(remote_fd);
@@ -1544,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)
@@ -1676,7 +1678,6 @@ int event_loop(const int *listen_fd, size_t listen_fd_ct)
}
else
{
DBGPRINT("conn fd=%d has no unsent\n", conn->fd);
conn->bFlowIn = false;
epoll_update_flow(conn);
@@ -1760,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]);